First part of fix for bug 8310 - toupper_ascii() is broken on big-endian systems
[Samba.git] / source3 / smbd / reply.c
blobc594a6b7aea1961f369da6b01a8eb42bd5f74bc4
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
27 #include "includes.h"
28 #include "system/filesys.h"
29 #include "printing.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/cli_spoolss.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_server/rpc_ncacn_np.h"
38 #include "libcli/security/security.h"
39 #include "libsmb/nmblib.h"
40 #include "auth.h"
41 #include "smbprofile.h"
43 /****************************************************************************
44 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
45 path or anything including wildcards.
46 We're assuming here that '/' is not the second byte in any multibyte char
47 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
48 set.
49 ****************************************************************************/
51 /* Custom version for processing POSIX paths. */
52 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
54 static NTSTATUS check_path_syntax_internal(char *path,
55 bool posix_path,
56 bool *p_last_component_contains_wcard)
58 char *d = path;
59 const char *s = path;
60 NTSTATUS ret = NT_STATUS_OK;
61 bool start_of_name_component = True;
62 bool stream_started = false;
64 *p_last_component_contains_wcard = False;
66 while (*s) {
67 if (stream_started) {
68 switch (*s) {
69 case '/':
70 case '\\':
71 return NT_STATUS_OBJECT_NAME_INVALID;
72 case ':':
73 if (s[1] == '\0') {
74 return NT_STATUS_OBJECT_NAME_INVALID;
76 if (strchr_m(&s[1], ':')) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 break;
83 if ((*s == ':') && !posix_path && !stream_started) {
84 if (*p_last_component_contains_wcard) {
85 return NT_STATUS_OBJECT_NAME_INVALID;
87 /* Stream names allow more characters than file names.
88 We're overloading posix_path here to allow a wider
89 range of characters. If stream_started is true this
90 is still a Windows path even if posix_path is true.
91 JRA.
93 stream_started = true;
94 start_of_name_component = false;
95 posix_path = true;
97 if (s[1] == '\0') {
98 return NT_STATUS_OBJECT_NAME_INVALID;
102 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
104 * Safe to assume is not the second part of a mb char
105 * as this is handled below.
107 /* Eat multiple '/' or '\\' */
108 while (IS_PATH_SEP(*s,posix_path)) {
109 s++;
111 if ((d != path) && (*s != '\0')) {
112 /* We only care about non-leading or trailing '/' or '\\' */
113 *d++ = '/';
116 start_of_name_component = True;
117 /* New component. */
118 *p_last_component_contains_wcard = False;
119 continue;
122 if (start_of_name_component) {
123 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
124 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
127 * No mb char starts with '.' so we're safe checking the directory separator here.
130 /* If we just added a '/' - delete it */
131 if ((d > path) && (*(d-1) == '/')) {
132 *(d-1) = '\0';
133 d--;
136 /* Are we at the start ? Can't go back further if so. */
137 if (d <= path) {
138 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
139 break;
141 /* Go back one level... */
142 /* We know this is safe as '/' cannot be part of a mb sequence. */
143 /* NOTE - if this assumption is invalid we are not in good shape... */
144 /* Decrement d first as d points to the *next* char to write into. */
145 for (d--; d > path; d--) {
146 if (*d == '/')
147 break;
149 s += 2; /* Else go past the .. */
150 /* We're still at the start of a name component, just the previous one. */
151 continue;
153 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
154 if (posix_path) {
155 /* Eat the '.' */
156 s++;
157 continue;
163 if (!(*s & 0x80)) {
164 if (!posix_path) {
165 if (*s <= 0x1f || *s == '|') {
166 return NT_STATUS_OBJECT_NAME_INVALID;
168 switch (*s) {
169 case '*':
170 case '?':
171 case '<':
172 case '>':
173 case '"':
174 *p_last_component_contains_wcard = True;
175 break;
176 default:
177 break;
180 *d++ = *s++;
181 } else {
182 size_t siz;
183 /* Get the size of the next MB character. */
184 next_codepoint(s,&siz);
185 switch(siz) {
186 case 5:
187 *d++ = *s++;
188 /*fall through*/
189 case 4:
190 *d++ = *s++;
191 /*fall through*/
192 case 3:
193 *d++ = *s++;
194 /*fall through*/
195 case 2:
196 *d++ = *s++;
197 /*fall through*/
198 case 1:
199 *d++ = *s++;
200 break;
201 default:
202 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
203 *d = '\0';
204 return NT_STATUS_INVALID_PARAMETER;
207 start_of_name_component = False;
210 *d = '\0';
212 return ret;
215 /****************************************************************************
216 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
217 No wildcards allowed.
218 ****************************************************************************/
220 NTSTATUS check_path_syntax(char *path)
222 bool ignore;
223 return check_path_syntax_internal(path, False, &ignore);
226 /****************************************************************************
227 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
228 Wildcards allowed - p_contains_wcard returns true if the last component contained
229 a wildcard.
230 ****************************************************************************/
232 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
234 return check_path_syntax_internal(path, False, p_contains_wcard);
237 /****************************************************************************
238 Check the path for a POSIX client.
239 We're assuming here that '/' is not the second byte in any multibyte char
240 set (a safe assumption).
241 ****************************************************************************/
243 NTSTATUS check_path_syntax_posix(char *path)
245 bool ignore;
246 return check_path_syntax_internal(path, True, &ignore);
249 /****************************************************************************
250 Pull a string and check the path allowing a wilcard - provide for error return.
251 ****************************************************************************/
253 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
254 const char *base_ptr,
255 uint16 smb_flags2,
256 char **pp_dest,
257 const char *src,
258 size_t src_len,
259 int flags,
260 NTSTATUS *err,
261 bool *contains_wcard)
263 size_t ret;
265 *pp_dest = NULL;
267 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
268 src_len, flags);
270 if (!*pp_dest) {
271 *err = NT_STATUS_INVALID_PARAMETER;
272 return ret;
275 *contains_wcard = False;
277 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
279 * For a DFS path the function parse_dfs_path()
280 * will do the path processing, just make a copy.
282 *err = NT_STATUS_OK;
283 return ret;
286 if (lp_posix_pathnames()) {
287 *err = check_path_syntax_posix(*pp_dest);
288 } else {
289 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
292 return ret;
295 /****************************************************************************
296 Pull a string and check the path - provide for error return.
297 ****************************************************************************/
299 size_t srvstr_get_path(TALLOC_CTX *ctx,
300 const char *base_ptr,
301 uint16 smb_flags2,
302 char **pp_dest,
303 const char *src,
304 size_t src_len,
305 int flags,
306 NTSTATUS *err)
308 bool ignore;
309 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
310 src_len, flags, err, &ignore);
313 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
314 char **pp_dest, const char *src, int flags,
315 NTSTATUS *err, bool *contains_wcard)
317 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
318 pp_dest, src, smbreq_bufrem(req, src),
319 flags, err, contains_wcard);
322 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
323 char **pp_dest, const char *src, int flags,
324 NTSTATUS *err)
326 bool ignore;
327 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
328 flags, err, &ignore);
331 /****************************************************************************
332 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
333 ****************************************************************************/
335 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
336 files_struct *fsp)
338 if ((fsp == NULL) || (conn == NULL)) {
339 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
340 return False;
342 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
343 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
344 return False;
346 return True;
349 /****************************************************************************
350 Check if we have a correct fsp pointing to a file.
351 ****************************************************************************/
353 bool check_fsp(connection_struct *conn, struct smb_request *req,
354 files_struct *fsp)
356 if (!check_fsp_open(conn, req, fsp)) {
357 return False;
359 if (fsp->is_directory) {
360 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
361 return False;
363 if (fsp->fh->fd == -1) {
364 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
365 return False;
367 fsp->num_smb_operations++;
368 return True;
371 /****************************************************************************
372 Check if we have a correct fsp pointing to a quota fake file. Replacement for
373 the CHECK_NTQUOTA_HANDLE_OK macro.
374 ****************************************************************************/
376 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
377 files_struct *fsp)
379 if (!check_fsp_open(conn, req, fsp)) {
380 return false;
383 if (fsp->is_directory) {
384 return false;
387 if (fsp->fake_file_handle == NULL) {
388 return false;
391 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
392 return false;
395 if (fsp->fake_file_handle->private_data == NULL) {
396 return false;
399 return true;
402 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
403 const char *name, int name_type)
405 char *trim_name;
406 char *trim_name_type;
407 const char *retarget_parm;
408 char *retarget;
409 char *p;
410 int retarget_type = 0x20;
411 int retarget_port = 139;
412 struct sockaddr_storage retarget_addr;
413 struct sockaddr_in *in_addr;
414 bool ret = false;
415 uint8_t outbuf[10];
417 if (get_socket_port(sconn->sock) != 139) {
418 return false;
421 trim_name = talloc_strdup(talloc_tos(), name);
422 if (trim_name == NULL) {
423 goto fail;
425 trim_char(trim_name, ' ', ' ');
427 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
428 name_type);
429 if (trim_name_type == NULL) {
430 goto fail;
433 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
434 trim_name_type, NULL);
435 if (retarget_parm == NULL) {
436 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
437 trim_name, NULL);
439 if (retarget_parm == NULL) {
440 goto fail;
443 retarget = talloc_strdup(trim_name, retarget_parm);
444 if (retarget == NULL) {
445 goto fail;
448 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
450 p = strchr(retarget, ':');
451 if (p != NULL) {
452 *p++ = '\0';
453 retarget_port = atoi(p);
456 p = strchr_m(retarget, '#');
457 if (p != NULL) {
458 *p++ = '\0';
459 if (sscanf(p, "%x", &retarget_type) != 1) {
460 goto fail;
464 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
465 if (!ret) {
466 DEBUG(10, ("could not resolve %s\n", retarget));
467 goto fail;
470 if (retarget_addr.ss_family != AF_INET) {
471 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
472 goto fail;
475 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
477 _smb_setlen(outbuf, 6);
478 SCVAL(outbuf, 0, 0x84);
479 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
480 *(uint16_t *)(outbuf+8) = htons(retarget_port);
482 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
483 NULL)) {
484 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
485 "failed.");
488 ret = true;
489 fail:
490 TALLOC_FREE(trim_name);
491 return ret;
494 /****************************************************************************
495 Reply to a (netbios-level) special message.
496 ****************************************************************************/
498 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
500 int msg_type = CVAL(inbuf,0);
501 int msg_flags = CVAL(inbuf,1);
503 * We only really use 4 bytes of the outbuf, but for the smb_setlen
504 * calculation & friends (srv_send_smb uses that) we need the full smb
505 * header.
507 char outbuf[smb_size];
509 memset(outbuf, '\0', sizeof(outbuf));
511 smb_setlen(outbuf,0);
513 switch (msg_type) {
514 case 0x81: /* session request */
516 /* inbuf_size is guarenteed to be at least 4. */
517 fstring name1,name2;
518 int name_type1, name_type2;
519 int name_len1, name_len2;
521 *name1 = *name2 = 0;
523 if (sconn->nbt.got_session) {
524 exit_server_cleanly("multiple session request not permitted");
527 SCVAL(outbuf,0,0x82);
528 SCVAL(outbuf,3,0);
530 /* inbuf_size is guaranteed to be at least 4. */
531 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
532 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
533 DEBUG(0,("Invalid name length in session request\n"));
534 break;
536 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
537 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
538 DEBUG(0,("Invalid name length in session request\n"));
539 break;
542 name_type1 = name_extract((unsigned char *)inbuf,
543 inbuf_size,(unsigned int)4,name1);
544 name_type2 = name_extract((unsigned char *)inbuf,
545 inbuf_size,(unsigned int)(4 + name_len1),name2);
547 if (name_type1 == -1 || name_type2 == -1) {
548 DEBUG(0,("Invalid name type in session request\n"));
549 break;
552 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
553 name1, name_type1, name2, name_type2));
555 if (netbios_session_retarget(sconn, name1, name_type1)) {
556 exit_server_cleanly("retargeted client");
560 * Windows NT/2k uses "*SMBSERVER" and XP uses
561 * "*SMBSERV" arrggg!!!
563 if (strequal(name1, "*SMBSERVER ")
564 || strequal(name1, "*SMBSERV ")) {
565 fstrcpy(name1, sconn->client_id.addr);
568 set_local_machine_name(name1, True);
569 set_remote_machine_name(name2, True);
571 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
572 get_local_machine_name(), get_remote_machine_name(),
573 name_type2));
575 if (name_type2 == 'R') {
576 /* We are being asked for a pathworks session ---
577 no thanks! */
578 SCVAL(outbuf, 0,0x83);
579 break;
582 /* only add the client's machine name to the list
583 of possibly valid usernames if we are operating
584 in share mode security */
585 if (lp_security() == SEC_SHARE) {
586 add_session_user(sconn, get_remote_machine_name());
589 reload_services(sconn->msg_ctx, sconn->sock, True);
590 reopen_logs();
592 sconn->nbt.got_session = true;
593 break;
596 case 0x89: /* session keepalive request
597 (some old clients produce this?) */
598 SCVAL(outbuf,0,SMBkeepalive);
599 SCVAL(outbuf,3,0);
600 break;
602 case 0x82: /* positive session response */
603 case 0x83: /* negative session response */
604 case 0x84: /* retarget session response */
605 DEBUG(0,("Unexpected session response\n"));
606 break;
608 case SMBkeepalive: /* session keepalive */
609 default:
610 return;
613 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
614 msg_type, msg_flags));
616 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
617 return;
620 /****************************************************************************
621 Reply to a tcon.
622 conn POINTER CAN BE NULL HERE !
623 ****************************************************************************/
625 void reply_tcon(struct smb_request *req)
627 connection_struct *conn = req->conn;
628 const char *service;
629 char *service_buf = NULL;
630 char *password = NULL;
631 char *dev = NULL;
632 int pwlen=0;
633 NTSTATUS nt_status;
634 const char *p;
635 DATA_BLOB password_blob;
636 TALLOC_CTX *ctx = talloc_tos();
637 struct smbd_server_connection *sconn = req->sconn;
639 START_PROFILE(SMBtcon);
641 if (req->buflen < 4) {
642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
643 END_PROFILE(SMBtcon);
644 return;
647 p = (const char *)req->buf + 1;
648 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
649 p += 1;
650 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
651 p += pwlen+1;
652 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
653 p += 1;
655 if (service_buf == NULL || password == NULL || dev == NULL) {
656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
657 END_PROFILE(SMBtcon);
658 return;
660 p = strrchr_m(service_buf,'\\');
661 if (p) {
662 service = p+1;
663 } else {
664 service = service_buf;
667 password_blob = data_blob(password, pwlen+1);
669 conn = make_connection(sconn,service,password_blob,dev,
670 req->vuid,&nt_status);
671 req->conn = conn;
673 data_blob_clear_free(&password_blob);
675 if (!conn) {
676 reply_nterror(req, nt_status);
677 END_PROFILE(SMBtcon);
678 return;
681 reply_outbuf(req, 2, 0);
682 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
683 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
684 SSVAL(req->outbuf,smb_tid,conn->cnum);
686 DEBUG(3,("tcon service=%s cnum=%d\n",
687 service, conn->cnum));
689 END_PROFILE(SMBtcon);
690 return;
693 /****************************************************************************
694 Reply to a tcon and X.
695 conn POINTER CAN BE NULL HERE !
696 ****************************************************************************/
698 void reply_tcon_and_X(struct smb_request *req)
700 connection_struct *conn = req->conn;
701 const char *service = NULL;
702 DATA_BLOB password;
703 TALLOC_CTX *ctx = talloc_tos();
704 /* what the cleint thinks the device is */
705 char *client_devicetype = NULL;
706 /* what the server tells the client the share represents */
707 const char *server_devicetype;
708 NTSTATUS nt_status;
709 int passlen;
710 char *path = NULL;
711 const char *p, *q;
712 uint16 tcon_flags;
713 struct smbd_server_connection *sconn = req->sconn;
715 START_PROFILE(SMBtconX);
717 if (req->wct < 4) {
718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
719 END_PROFILE(SMBtconX);
720 return;
723 passlen = SVAL(req->vwv+3, 0);
724 tcon_flags = SVAL(req->vwv+2, 0);
726 /* we might have to close an old one */
727 if ((tcon_flags & 0x1) && conn) {
728 close_cnum(conn,req->vuid);
729 req->conn = NULL;
730 conn = NULL;
733 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
734 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
735 END_PROFILE(SMBtconX);
736 return;
739 if (sconn->smb1.negprot.encrypted_passwords) {
740 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
741 if (lp_security() == SEC_SHARE) {
743 * Security = share always has a pad byte
744 * after the password.
746 p = (const char *)req->buf + passlen + 1;
747 } else {
748 p = (const char *)req->buf + passlen;
750 } else {
751 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
752 /* Ensure correct termination */
753 password.data[passlen]=0;
754 p = (const char *)req->buf + passlen + 1;
757 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
759 if (path == NULL) {
760 data_blob_clear_free(&password);
761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
762 END_PROFILE(SMBtconX);
763 return;
767 * the service name can be either: \\server\share
768 * or share directly like on the DELL PowerVault 705
770 if (*path=='\\') {
771 q = strchr_m(path+2,'\\');
772 if (!q) {
773 data_blob_clear_free(&password);
774 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
775 END_PROFILE(SMBtconX);
776 return;
778 service = q+1;
779 } else {
780 service = path;
783 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
784 &client_devicetype, p,
785 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
787 if (client_devicetype == NULL) {
788 data_blob_clear_free(&password);
789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
790 END_PROFILE(SMBtconX);
791 return;
794 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
796 conn = make_connection(sconn, service, password, client_devicetype,
797 req->vuid, &nt_status);
798 req->conn =conn;
800 data_blob_clear_free(&password);
802 if (!conn) {
803 reply_nterror(req, nt_status);
804 END_PROFILE(SMBtconX);
805 return;
808 if ( IS_IPC(conn) )
809 server_devicetype = "IPC";
810 else if ( IS_PRINT(conn) )
811 server_devicetype = "LPT1:";
812 else
813 server_devicetype = "A:";
815 if (get_Protocol() < PROTOCOL_NT1) {
816 reply_outbuf(req, 2, 0);
817 if (message_push_string(&req->outbuf, server_devicetype,
818 STR_TERMINATE|STR_ASCII) == -1) {
819 reply_nterror(req, NT_STATUS_NO_MEMORY);
820 END_PROFILE(SMBtconX);
821 return;
823 } else {
824 /* NT sets the fstype of IPC$ to the null string */
825 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
827 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
828 /* Return permissions. */
829 uint32 perm1 = 0;
830 uint32 perm2 = 0;
832 reply_outbuf(req, 7, 0);
834 if (IS_IPC(conn)) {
835 perm1 = FILE_ALL_ACCESS;
836 perm2 = FILE_ALL_ACCESS;
837 } else {
838 perm1 = conn->share_access;
841 SIVAL(req->outbuf, smb_vwv3, perm1);
842 SIVAL(req->outbuf, smb_vwv5, perm2);
843 } else {
844 reply_outbuf(req, 3, 0);
847 if ((message_push_string(&req->outbuf, server_devicetype,
848 STR_TERMINATE|STR_ASCII) == -1)
849 || (message_push_string(&req->outbuf, fstype,
850 STR_TERMINATE) == -1)) {
851 reply_nterror(req, NT_STATUS_NO_MEMORY);
852 END_PROFILE(SMBtconX);
853 return;
856 /* what does setting this bit do? It is set by NT4 and
857 may affect the ability to autorun mounted cdroms */
858 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
859 (lp_csc_policy(SNUM(conn)) << 2));
861 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
862 DEBUG(2,("Serving %s as a Dfs root\n",
863 lp_servicename(SNUM(conn)) ));
864 SSVAL(req->outbuf, smb_vwv2,
865 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
870 DEBUG(3,("tconX service=%s \n",
871 service));
873 /* set the incoming and outgoing tid to the just created one */
874 SSVAL(req->inbuf,smb_tid,conn->cnum);
875 SSVAL(req->outbuf,smb_tid,conn->cnum);
877 END_PROFILE(SMBtconX);
879 req->tid = conn->cnum;
880 chain_reply(req);
881 return;
884 /****************************************************************************
885 Reply to an unknown type.
886 ****************************************************************************/
888 void reply_unknown_new(struct smb_request *req, uint8 type)
890 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
891 smb_fn_name(type), type, type));
892 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
893 return;
896 /****************************************************************************
897 Reply to an ioctl.
898 conn POINTER CAN BE NULL HERE !
899 ****************************************************************************/
901 void reply_ioctl(struct smb_request *req)
903 connection_struct *conn = req->conn;
904 uint16 device;
905 uint16 function;
906 uint32 ioctl_code;
907 int replysize;
908 char *p;
910 START_PROFILE(SMBioctl);
912 if (req->wct < 3) {
913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
914 END_PROFILE(SMBioctl);
915 return;
918 device = SVAL(req->vwv+1, 0);
919 function = SVAL(req->vwv+2, 0);
920 ioctl_code = (device << 16) + function;
922 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
924 switch (ioctl_code) {
925 case IOCTL_QUERY_JOB_INFO:
926 replysize = 32;
927 break;
928 default:
929 reply_force_doserror(req, ERRSRV, ERRnosupport);
930 END_PROFILE(SMBioctl);
931 return;
934 reply_outbuf(req, 8, replysize+1);
935 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
936 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
937 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
938 p = smb_buf(req->outbuf);
939 memset(p, '\0', replysize+1); /* valgrind-safe. */
940 p += 1; /* Allow for alignment */
942 switch (ioctl_code) {
943 case IOCTL_QUERY_JOB_INFO:
945 files_struct *fsp = file_fsp(
946 req, SVAL(req->vwv+0, 0));
947 if (!fsp) {
948 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
949 END_PROFILE(SMBioctl);
950 return;
952 /* Job number */
953 if (fsp->print_file) {
954 SSVAL(p, 0, fsp->print_file->rap_jobid);
955 } else {
956 SSVAL(p, 0, 0);
958 srvstr_push((char *)req->outbuf, req->flags2, p+2,
959 global_myname(), 15,
960 STR_TERMINATE|STR_ASCII);
961 if (conn) {
962 srvstr_push((char *)req->outbuf, req->flags2,
963 p+18, lp_servicename(SNUM(conn)),
964 13, STR_TERMINATE|STR_ASCII);
965 } else {
966 memset(p+18, 0, 13);
968 break;
972 END_PROFILE(SMBioctl);
973 return;
976 /****************************************************************************
977 Strange checkpath NTSTATUS mapping.
978 ****************************************************************************/
980 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
982 /* Strange DOS error code semantics only for checkpath... */
983 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
984 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
985 /* We need to map to ERRbadpath */
986 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
989 return status;
992 /****************************************************************************
993 Reply to a checkpath.
994 ****************************************************************************/
996 void reply_checkpath(struct smb_request *req)
998 connection_struct *conn = req->conn;
999 struct smb_filename *smb_fname = NULL;
1000 char *name = NULL;
1001 NTSTATUS status;
1002 TALLOC_CTX *ctx = talloc_tos();
1004 START_PROFILE(SMBcheckpath);
1006 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1007 STR_TERMINATE, &status);
1009 if (!NT_STATUS_IS_OK(status)) {
1010 status = map_checkpath_error(req->flags2, status);
1011 reply_nterror(req, status);
1012 END_PROFILE(SMBcheckpath);
1013 return;
1016 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1018 status = filename_convert(ctx,
1019 conn,
1020 req->flags2 & FLAGS2_DFS_PATHNAMES,
1021 name,
1023 NULL,
1024 &smb_fname);
1026 if (!NT_STATUS_IS_OK(status)) {
1027 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1028 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1029 ERRSRV, ERRbadpath);
1030 END_PROFILE(SMBcheckpath);
1031 return;
1033 goto path_err;
1036 if (!VALID_STAT(smb_fname->st) &&
1037 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1038 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1039 smb_fname_str_dbg(smb_fname), strerror(errno)));
1040 status = map_nt_error_from_unix(errno);
1041 goto path_err;
1044 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1045 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1046 ERRDOS, ERRbadpath);
1047 goto out;
1050 reply_outbuf(req, 0, 0);
1052 path_err:
1053 /* We special case this - as when a Windows machine
1054 is parsing a path is steps through the components
1055 one at a time - if a component fails it expects
1056 ERRbadpath, not ERRbadfile.
1058 status = map_checkpath_error(req->flags2, status);
1059 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1061 * Windows returns different error codes if
1062 * the parent directory is valid but not the
1063 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1064 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1065 * if the path is invalid.
1067 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1068 ERRDOS, ERRbadpath);
1069 goto out;
1072 reply_nterror(req, status);
1074 out:
1075 TALLOC_FREE(smb_fname);
1076 END_PROFILE(SMBcheckpath);
1077 return;
1080 /****************************************************************************
1081 Reply to a getatr.
1082 ****************************************************************************/
1084 void reply_getatr(struct smb_request *req)
1086 connection_struct *conn = req->conn;
1087 struct smb_filename *smb_fname = NULL;
1088 char *fname = NULL;
1089 int mode=0;
1090 SMB_OFF_T size=0;
1091 time_t mtime=0;
1092 const char *p;
1093 NTSTATUS status;
1094 TALLOC_CTX *ctx = talloc_tos();
1095 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1097 START_PROFILE(SMBgetatr);
1099 p = (const char *)req->buf + 1;
1100 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1101 if (!NT_STATUS_IS_OK(status)) {
1102 reply_nterror(req, status);
1103 goto out;
1106 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1107 under WfWg - weird! */
1108 if (*fname == '\0') {
1109 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1110 if (!CAN_WRITE(conn)) {
1111 mode |= FILE_ATTRIBUTE_READONLY;
1113 size = 0;
1114 mtime = 0;
1115 } else {
1116 status = filename_convert(ctx,
1117 conn,
1118 req->flags2 & FLAGS2_DFS_PATHNAMES,
1119 fname,
1121 NULL,
1122 &smb_fname);
1123 if (!NT_STATUS_IS_OK(status)) {
1124 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1125 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1126 ERRSRV, ERRbadpath);
1127 goto out;
1129 reply_nterror(req, status);
1130 goto out;
1132 if (!VALID_STAT(smb_fname->st) &&
1133 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1134 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1135 smb_fname_str_dbg(smb_fname),
1136 strerror(errno)));
1137 reply_nterror(req, map_nt_error_from_unix(errno));
1138 goto out;
1141 mode = dos_mode(conn, smb_fname);
1142 size = smb_fname->st.st_ex_size;
1144 if (ask_sharemode) {
1145 struct timespec write_time_ts;
1146 struct file_id fileid;
1148 ZERO_STRUCT(write_time_ts);
1149 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1150 get_file_infos(fileid, 0, NULL, &write_time_ts);
1151 if (!null_timespec(write_time_ts)) {
1152 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1156 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1157 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1158 size = 0;
1162 reply_outbuf(req, 10, 0);
1164 SSVAL(req->outbuf,smb_vwv0,mode);
1165 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1166 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1167 } else {
1168 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1170 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1172 if (get_Protocol() >= PROTOCOL_NT1) {
1173 SSVAL(req->outbuf, smb_flg2,
1174 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1177 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1178 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1180 out:
1181 TALLOC_FREE(smb_fname);
1182 TALLOC_FREE(fname);
1183 END_PROFILE(SMBgetatr);
1184 return;
1187 /****************************************************************************
1188 Reply to a setatr.
1189 ****************************************************************************/
1191 void reply_setatr(struct smb_request *req)
1193 struct smb_file_time ft;
1194 connection_struct *conn = req->conn;
1195 struct smb_filename *smb_fname = NULL;
1196 char *fname = NULL;
1197 int mode;
1198 time_t mtime;
1199 const char *p;
1200 NTSTATUS status;
1201 TALLOC_CTX *ctx = talloc_tos();
1203 START_PROFILE(SMBsetatr);
1205 ZERO_STRUCT(ft);
1207 if (req->wct < 2) {
1208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1209 goto out;
1212 p = (const char *)req->buf + 1;
1213 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1214 if (!NT_STATUS_IS_OK(status)) {
1215 reply_nterror(req, status);
1216 goto out;
1219 status = filename_convert(ctx,
1220 conn,
1221 req->flags2 & FLAGS2_DFS_PATHNAMES,
1222 fname,
1224 NULL,
1225 &smb_fname);
1226 if (!NT_STATUS_IS_OK(status)) {
1227 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1228 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1229 ERRSRV, ERRbadpath);
1230 goto out;
1232 reply_nterror(req, status);
1233 goto out;
1236 if (smb_fname->base_name[0] == '.' &&
1237 smb_fname->base_name[1] == '\0') {
1239 * Not sure here is the right place to catch this
1240 * condition. Might be moved to somewhere else later -- vl
1242 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1243 goto out;
1246 mode = SVAL(req->vwv+0, 0);
1247 mtime = srv_make_unix_date3(req->vwv+1);
1249 ft.mtime = convert_time_t_to_timespec(mtime);
1250 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 reply_nterror(req, status);
1253 goto out;
1256 if (mode != FILE_ATTRIBUTE_NORMAL) {
1257 if (VALID_STAT_OF_DIR(smb_fname->st))
1258 mode |= FILE_ATTRIBUTE_DIRECTORY;
1259 else
1260 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1262 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1263 false) != 0) {
1264 reply_nterror(req, map_nt_error_from_unix(errno));
1265 goto out;
1269 reply_outbuf(req, 0, 0);
1271 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1272 mode));
1273 out:
1274 TALLOC_FREE(smb_fname);
1275 END_PROFILE(SMBsetatr);
1276 return;
1279 /****************************************************************************
1280 Reply to a dskattr.
1281 ****************************************************************************/
1283 void reply_dskattr(struct smb_request *req)
1285 connection_struct *conn = req->conn;
1286 uint64_t dfree,dsize,bsize;
1287 START_PROFILE(SMBdskattr);
1289 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1290 reply_nterror(req, map_nt_error_from_unix(errno));
1291 END_PROFILE(SMBdskattr);
1292 return;
1295 reply_outbuf(req, 5, 0);
1297 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1298 double total_space, free_space;
1299 /* we need to scale this to a number that DOS6 can handle. We
1300 use floating point so we can handle large drives on systems
1301 that don't have 64 bit integers
1303 we end up displaying a maximum of 2G to DOS systems
1305 total_space = dsize * (double)bsize;
1306 free_space = dfree * (double)bsize;
1308 dsize = (uint64_t)((total_space+63*512) / (64*512));
1309 dfree = (uint64_t)((free_space+63*512) / (64*512));
1311 if (dsize > 0xFFFF) dsize = 0xFFFF;
1312 if (dfree > 0xFFFF) dfree = 0xFFFF;
1314 SSVAL(req->outbuf,smb_vwv0,dsize);
1315 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1316 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1317 SSVAL(req->outbuf,smb_vwv3,dfree);
1318 } else {
1319 SSVAL(req->outbuf,smb_vwv0,dsize);
1320 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1321 SSVAL(req->outbuf,smb_vwv2,512);
1322 SSVAL(req->outbuf,smb_vwv3,dfree);
1325 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1327 END_PROFILE(SMBdskattr);
1328 return;
1332 * Utility function to split the filename from the directory.
1334 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1335 char **fname_dir_out,
1336 char **fname_mask_out)
1338 const char *p = NULL;
1339 char *fname_dir = NULL;
1340 char *fname_mask = NULL;
1342 p = strrchr_m(fname_in, '/');
1343 if (!p) {
1344 fname_dir = talloc_strdup(ctx, ".");
1345 fname_mask = talloc_strdup(ctx, fname_in);
1346 } else {
1347 fname_dir = talloc_strndup(ctx, fname_in,
1348 PTR_DIFF(p, fname_in));
1349 fname_mask = talloc_strdup(ctx, p+1);
1352 if (!fname_dir || !fname_mask) {
1353 TALLOC_FREE(fname_dir);
1354 TALLOC_FREE(fname_mask);
1355 return NT_STATUS_NO_MEMORY;
1358 *fname_dir_out = fname_dir;
1359 *fname_mask_out = fname_mask;
1360 return NT_STATUS_OK;
1363 /****************************************************************************
1364 Reply to a search.
1365 Can be called from SMBsearch, SMBffirst or SMBfunique.
1366 ****************************************************************************/
1368 void reply_search(struct smb_request *req)
1370 connection_struct *conn = req->conn;
1371 char *path = NULL;
1372 const char *mask = NULL;
1373 char *directory = NULL;
1374 struct smb_filename *smb_fname = NULL;
1375 char *fname = NULL;
1376 SMB_OFF_T size;
1377 uint32 mode;
1378 struct timespec date;
1379 uint32 dirtype;
1380 unsigned int numentries = 0;
1381 unsigned int maxentries = 0;
1382 bool finished = False;
1383 const char *p;
1384 int status_len;
1385 char status[21];
1386 int dptr_num= -1;
1387 bool check_descend = False;
1388 bool expect_close = False;
1389 NTSTATUS nt_status;
1390 bool mask_contains_wcard = False;
1391 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1392 TALLOC_CTX *ctx = talloc_tos();
1393 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1394 struct dptr_struct *dirptr = NULL;
1395 struct smbd_server_connection *sconn = req->sconn;
1397 START_PROFILE(SMBsearch);
1399 if (req->wct < 2) {
1400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1401 goto out;
1404 if (lp_posix_pathnames()) {
1405 reply_unknown_new(req, req->cmd);
1406 goto out;
1409 /* If we were called as SMBffirst then we must expect close. */
1410 if(req->cmd == SMBffirst) {
1411 expect_close = True;
1414 reply_outbuf(req, 1, 3);
1415 maxentries = SVAL(req->vwv+0, 0);
1416 dirtype = SVAL(req->vwv+1, 0);
1417 p = (const char *)req->buf + 1;
1418 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1419 &nt_status, &mask_contains_wcard);
1420 if (!NT_STATUS_IS_OK(nt_status)) {
1421 reply_nterror(req, nt_status);
1422 goto out;
1425 p++;
1426 status_len = SVAL(p, 0);
1427 p += 2;
1429 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1431 if (status_len == 0) {
1432 nt_status = filename_convert(ctx, conn,
1433 req->flags2 & FLAGS2_DFS_PATHNAMES,
1434 path,
1435 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1436 &mask_contains_wcard,
1437 &smb_fname);
1438 if (!NT_STATUS_IS_OK(nt_status)) {
1439 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1440 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1441 ERRSRV, ERRbadpath);
1442 goto out;
1444 reply_nterror(req, nt_status);
1445 goto out;
1448 directory = smb_fname->base_name;
1450 p = strrchr_m(directory,'/');
1451 if ((p != NULL) && (*directory != '/')) {
1452 mask = p + 1;
1453 directory = talloc_strndup(ctx, directory,
1454 PTR_DIFF(p, directory));
1455 } else {
1456 mask = directory;
1457 directory = talloc_strdup(ctx,".");
1460 if (!directory) {
1461 reply_nterror(req, NT_STATUS_NO_MEMORY);
1462 goto out;
1465 memset((char *)status,'\0',21);
1466 SCVAL(status,0,(dirtype & 0x1F));
1468 nt_status = dptr_create(conn,
1469 NULL, /* fsp */
1470 directory,
1471 True,
1472 expect_close,
1473 req->smbpid,
1474 mask,
1475 mask_contains_wcard,
1476 dirtype,
1477 &dirptr);
1478 if (!NT_STATUS_IS_OK(nt_status)) {
1479 reply_nterror(req, nt_status);
1480 goto out;
1482 dptr_num = dptr_dnum(dirptr);
1483 } else {
1484 int status_dirtype;
1485 const char *dirpath;
1487 memcpy(status,p,21);
1488 status_dirtype = CVAL(status,0) & 0x1F;
1489 if (status_dirtype != (dirtype & 0x1F)) {
1490 dirtype = status_dirtype;
1493 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1494 if (!dirptr) {
1495 goto SearchEmpty;
1497 dirpath = dptr_path(sconn, dptr_num);
1498 directory = talloc_strdup(ctx, dirpath);
1499 if (!directory) {
1500 reply_nterror(req, NT_STATUS_NO_MEMORY);
1501 goto out;
1504 mask = dptr_wcard(sconn, dptr_num);
1505 if (!mask) {
1506 goto SearchEmpty;
1509 * For a 'continue' search we have no string. So
1510 * check from the initial saved string.
1512 mask_contains_wcard = ms_has_wild(mask);
1513 dirtype = dptr_attr(sconn, dptr_num);
1516 DEBUG(4,("dptr_num is %d\n",dptr_num));
1518 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1519 dptr_init_search_op(dirptr);
1521 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1522 char buf[DIR_STRUCT_SIZE];
1523 memcpy(buf,status,21);
1524 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1525 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1526 reply_nterror(req, NT_STATUS_NO_MEMORY);
1527 goto out;
1529 dptr_fill(sconn, buf+12,dptr_num);
1530 if (dptr_zero(buf+12) && (status_len==0)) {
1531 numentries = 1;
1532 } else {
1533 numentries = 0;
1535 if (message_push_blob(&req->outbuf,
1536 data_blob_const(buf, sizeof(buf)))
1537 == -1) {
1538 reply_nterror(req, NT_STATUS_NO_MEMORY);
1539 goto out;
1541 } else {
1542 unsigned int i;
1543 maxentries = MIN(
1544 maxentries,
1545 ((BUFFER_SIZE -
1546 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1547 /DIR_STRUCT_SIZE));
1549 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1550 directory,lp_dontdescend(SNUM(conn))));
1551 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1552 check_descend = True;
1555 for (i=numentries;(i<maxentries) && !finished;i++) {
1556 finished = !get_dir_entry(ctx,
1557 dirptr,
1558 mask,
1559 dirtype,
1560 &fname,
1561 &size,
1562 &mode,
1563 &date,
1564 check_descend,
1565 ask_sharemode);
1566 if (!finished) {
1567 char buf[DIR_STRUCT_SIZE];
1568 memcpy(buf,status,21);
1569 if (!make_dir_struct(ctx,
1570 buf,
1571 mask,
1572 fname,
1573 size,
1574 mode,
1575 convert_timespec_to_time_t(date),
1576 !allow_long_path_components)) {
1577 reply_nterror(req, NT_STATUS_NO_MEMORY);
1578 goto out;
1580 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1581 break;
1583 if (message_push_blob(&req->outbuf,
1584 data_blob_const(buf, sizeof(buf)))
1585 == -1) {
1586 reply_nterror(req, NT_STATUS_NO_MEMORY);
1587 goto out;
1589 numentries++;
1594 SearchEmpty:
1596 /* If we were called as SMBffirst with smb_search_id == NULL
1597 and no entries were found then return error and close dirptr
1598 (X/Open spec) */
1600 if (numentries == 0) {
1601 dptr_close(sconn, &dptr_num);
1602 } else if(expect_close && status_len == 0) {
1603 /* Close the dptr - we know it's gone */
1604 dptr_close(sconn, &dptr_num);
1607 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1608 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1609 dptr_close(sconn, &dptr_num);
1612 if ((numentries == 0) && !mask_contains_wcard) {
1613 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1614 goto out;
1617 SSVAL(req->outbuf,smb_vwv0,numentries);
1618 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1619 SCVAL(smb_buf(req->outbuf),0,5);
1620 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1622 /* The replies here are never long name. */
1623 SSVAL(req->outbuf, smb_flg2,
1624 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1625 if (!allow_long_path_components) {
1626 SSVAL(req->outbuf, smb_flg2,
1627 SVAL(req->outbuf, smb_flg2)
1628 & (~FLAGS2_LONG_PATH_COMPONENTS));
1631 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1632 SSVAL(req->outbuf, smb_flg2,
1633 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1635 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1636 smb_fn_name(req->cmd),
1637 mask,
1638 directory,
1639 dirtype,
1640 numentries,
1641 maxentries ));
1642 out:
1643 TALLOC_FREE(directory);
1644 TALLOC_FREE(smb_fname);
1645 END_PROFILE(SMBsearch);
1646 return;
1649 /****************************************************************************
1650 Reply to a fclose (stop directory search).
1651 ****************************************************************************/
1653 void reply_fclose(struct smb_request *req)
1655 int status_len;
1656 char status[21];
1657 int dptr_num= -2;
1658 const char *p;
1659 char *path = NULL;
1660 NTSTATUS err;
1661 bool path_contains_wcard = False;
1662 TALLOC_CTX *ctx = talloc_tos();
1663 struct smbd_server_connection *sconn = req->sconn;
1665 START_PROFILE(SMBfclose);
1667 if (lp_posix_pathnames()) {
1668 reply_unknown_new(req, req->cmd);
1669 END_PROFILE(SMBfclose);
1670 return;
1673 p = (const char *)req->buf + 1;
1674 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1675 &err, &path_contains_wcard);
1676 if (!NT_STATUS_IS_OK(err)) {
1677 reply_nterror(req, err);
1678 END_PROFILE(SMBfclose);
1679 return;
1681 p++;
1682 status_len = SVAL(p,0);
1683 p += 2;
1685 if (status_len == 0) {
1686 reply_force_doserror(req, ERRSRV, ERRsrverror);
1687 END_PROFILE(SMBfclose);
1688 return;
1691 memcpy(status,p,21);
1693 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1694 /* Close the dptr - we know it's gone */
1695 dptr_close(sconn, &dptr_num);
1698 reply_outbuf(req, 1, 0);
1699 SSVAL(req->outbuf,smb_vwv0,0);
1701 DEBUG(3,("search close\n"));
1703 END_PROFILE(SMBfclose);
1704 return;
1707 /****************************************************************************
1708 Reply to an open.
1709 ****************************************************************************/
1711 void reply_open(struct smb_request *req)
1713 connection_struct *conn = req->conn;
1714 struct smb_filename *smb_fname = NULL;
1715 char *fname = NULL;
1716 uint32 fattr=0;
1717 SMB_OFF_T size = 0;
1718 time_t mtime=0;
1719 int info;
1720 files_struct *fsp;
1721 int oplock_request;
1722 int deny_mode;
1723 uint32 dos_attr;
1724 uint32 access_mask;
1725 uint32 share_mode;
1726 uint32 create_disposition;
1727 uint32 create_options = 0;
1728 uint32_t private_flags = 0;
1729 NTSTATUS status;
1730 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1731 TALLOC_CTX *ctx = talloc_tos();
1733 START_PROFILE(SMBopen);
1735 if (req->wct < 2) {
1736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1737 goto out;
1740 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1741 deny_mode = SVAL(req->vwv+0, 0);
1742 dos_attr = SVAL(req->vwv+1, 0);
1744 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1745 STR_TERMINATE, &status);
1746 if (!NT_STATUS_IS_OK(status)) {
1747 reply_nterror(req, status);
1748 goto out;
1751 status = filename_convert(ctx,
1752 conn,
1753 req->flags2 & FLAGS2_DFS_PATHNAMES,
1754 fname,
1756 NULL,
1757 &smb_fname);
1758 if (!NT_STATUS_IS_OK(status)) {
1759 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1760 reply_botherror(req,
1761 NT_STATUS_PATH_NOT_COVERED,
1762 ERRSRV, ERRbadpath);
1763 goto out;
1765 reply_nterror(req, status);
1766 goto out;
1769 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1770 OPENX_FILE_EXISTS_OPEN, &access_mask,
1771 &share_mode, &create_disposition,
1772 &create_options, &private_flags)) {
1773 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1774 goto out;
1777 status = SMB_VFS_CREATE_FILE(
1778 conn, /* conn */
1779 req, /* req */
1780 0, /* root_dir_fid */
1781 smb_fname, /* fname */
1782 access_mask, /* access_mask */
1783 share_mode, /* share_access */
1784 create_disposition, /* create_disposition*/
1785 create_options, /* create_options */
1786 dos_attr, /* file_attributes */
1787 oplock_request, /* oplock_request */
1788 0, /* allocation_size */
1789 private_flags,
1790 NULL, /* sd */
1791 NULL, /* ea_list */
1792 &fsp, /* result */
1793 &info); /* pinfo */
1795 if (!NT_STATUS_IS_OK(status)) {
1796 if (open_was_deferred(req->mid)) {
1797 /* We have re-scheduled this call. */
1798 goto out;
1800 reply_openerror(req, status);
1801 goto out;
1804 size = smb_fname->st.st_ex_size;
1805 fattr = dos_mode(conn, smb_fname);
1807 /* Deal with other possible opens having a modified
1808 write time. JRA. */
1809 if (ask_sharemode) {
1810 struct timespec write_time_ts;
1812 ZERO_STRUCT(write_time_ts);
1813 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1814 if (!null_timespec(write_time_ts)) {
1815 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1819 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1821 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1822 DEBUG(3,("attempt to open a directory %s\n",
1823 fsp_str_dbg(fsp)));
1824 close_file(req, fsp, ERROR_CLOSE);
1825 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1826 ERRDOS, ERRnoaccess);
1827 goto out;
1830 reply_outbuf(req, 7, 0);
1831 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1832 SSVAL(req->outbuf,smb_vwv1,fattr);
1833 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1834 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1835 } else {
1836 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1838 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1839 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1841 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1842 SCVAL(req->outbuf,smb_flg,
1843 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1846 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1847 SCVAL(req->outbuf,smb_flg,
1848 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1850 out:
1851 TALLOC_FREE(smb_fname);
1852 END_PROFILE(SMBopen);
1853 return;
1856 /****************************************************************************
1857 Reply to an open and X.
1858 ****************************************************************************/
1860 void reply_open_and_X(struct smb_request *req)
1862 connection_struct *conn = req->conn;
1863 struct smb_filename *smb_fname = NULL;
1864 char *fname = NULL;
1865 uint16 open_flags;
1866 int deny_mode;
1867 uint32 smb_attr;
1868 /* Breakout the oplock request bits so we can set the
1869 reply bits separately. */
1870 int ex_oplock_request;
1871 int core_oplock_request;
1872 int oplock_request;
1873 #if 0
1874 int smb_sattr = SVAL(req->vwv+4, 0);
1875 uint32 smb_time = make_unix_date3(req->vwv+6);
1876 #endif
1877 int smb_ofun;
1878 uint32 fattr=0;
1879 int mtime=0;
1880 int smb_action = 0;
1881 files_struct *fsp;
1882 NTSTATUS status;
1883 uint64_t allocation_size;
1884 ssize_t retval = -1;
1885 uint32 access_mask;
1886 uint32 share_mode;
1887 uint32 create_disposition;
1888 uint32 create_options = 0;
1889 uint32_t private_flags = 0;
1890 TALLOC_CTX *ctx = talloc_tos();
1892 START_PROFILE(SMBopenX);
1894 if (req->wct < 15) {
1895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1896 goto out;
1899 open_flags = SVAL(req->vwv+2, 0);
1900 deny_mode = SVAL(req->vwv+3, 0);
1901 smb_attr = SVAL(req->vwv+5, 0);
1902 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1903 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1904 oplock_request = ex_oplock_request | core_oplock_request;
1905 smb_ofun = SVAL(req->vwv+8, 0);
1906 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1908 /* If it's an IPC, pass off the pipe handler. */
1909 if (IS_IPC(conn)) {
1910 if (lp_nt_pipe_support()) {
1911 reply_open_pipe_and_X(conn, req);
1912 } else {
1913 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1915 goto out;
1918 /* XXXX we need to handle passed times, sattr and flags */
1919 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1920 STR_TERMINATE, &status);
1921 if (!NT_STATUS_IS_OK(status)) {
1922 reply_nterror(req, status);
1923 goto out;
1926 status = filename_convert(ctx,
1927 conn,
1928 req->flags2 & FLAGS2_DFS_PATHNAMES,
1929 fname,
1931 NULL,
1932 &smb_fname);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1935 reply_botherror(req,
1936 NT_STATUS_PATH_NOT_COVERED,
1937 ERRSRV, ERRbadpath);
1938 goto out;
1940 reply_nterror(req, status);
1941 goto out;
1944 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1945 &access_mask, &share_mode,
1946 &create_disposition,
1947 &create_options,
1948 &private_flags)) {
1949 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1950 goto out;
1953 status = SMB_VFS_CREATE_FILE(
1954 conn, /* conn */
1955 req, /* req */
1956 0, /* root_dir_fid */
1957 smb_fname, /* fname */
1958 access_mask, /* access_mask */
1959 share_mode, /* share_access */
1960 create_disposition, /* create_disposition*/
1961 create_options, /* create_options */
1962 smb_attr, /* file_attributes */
1963 oplock_request, /* oplock_request */
1964 0, /* allocation_size */
1965 private_flags,
1966 NULL, /* sd */
1967 NULL, /* ea_list */
1968 &fsp, /* result */
1969 &smb_action); /* pinfo */
1971 if (!NT_STATUS_IS_OK(status)) {
1972 if (open_was_deferred(req->mid)) {
1973 /* We have re-scheduled this call. */
1974 goto out;
1976 reply_openerror(req, status);
1977 goto out;
1980 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1981 if the file is truncated or created. */
1982 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1983 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1984 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1985 close_file(req, fsp, ERROR_CLOSE);
1986 reply_nterror(req, NT_STATUS_DISK_FULL);
1987 goto out;
1989 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1990 if (retval < 0) {
1991 close_file(req, fsp, ERROR_CLOSE);
1992 reply_nterror(req, NT_STATUS_DISK_FULL);
1993 goto out;
1995 status = vfs_stat_fsp(fsp);
1996 if (!NT_STATUS_IS_OK(status)) {
1997 close_file(req, fsp, ERROR_CLOSE);
1998 reply_nterror(req, status);
1999 goto out;
2003 fattr = dos_mode(conn, fsp->fsp_name);
2004 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2005 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2006 close_file(req, fsp, ERROR_CLOSE);
2007 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2008 goto out;
2011 /* If the caller set the extended oplock request bit
2012 and we granted one (by whatever means) - set the
2013 correct bit for extended oplock reply.
2016 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2017 smb_action |= EXTENDED_OPLOCK_GRANTED;
2020 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2021 smb_action |= EXTENDED_OPLOCK_GRANTED;
2024 /* If the caller set the core oplock request bit
2025 and we granted one (by whatever means) - set the
2026 correct bit for core oplock reply.
2029 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2030 reply_outbuf(req, 19, 0);
2031 } else {
2032 reply_outbuf(req, 15, 0);
2035 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2036 SCVAL(req->outbuf, smb_flg,
2037 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2040 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2041 SCVAL(req->outbuf, smb_flg,
2042 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2045 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2046 SSVAL(req->outbuf,smb_vwv3,fattr);
2047 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2048 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2049 } else {
2050 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2052 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2053 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2054 SSVAL(req->outbuf,smb_vwv11,smb_action);
2056 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2057 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2060 chain_reply(req);
2061 out:
2062 TALLOC_FREE(smb_fname);
2063 END_PROFILE(SMBopenX);
2064 return;
2067 /****************************************************************************
2068 Reply to a SMBulogoffX.
2069 ****************************************************************************/
2071 void reply_ulogoffX(struct smb_request *req)
2073 struct smbd_server_connection *sconn = req->sconn;
2074 user_struct *vuser;
2076 START_PROFILE(SMBulogoffX);
2078 vuser = get_valid_user_struct(sconn, req->vuid);
2080 if(vuser == NULL) {
2081 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2082 req->vuid));
2085 /* in user level security we are supposed to close any files
2086 open by this user */
2087 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2088 file_close_user(sconn, req->vuid);
2091 invalidate_vuid(sconn, req->vuid);
2093 reply_outbuf(req, 2, 0);
2095 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2097 END_PROFILE(SMBulogoffX);
2098 req->vuid = UID_FIELD_INVALID;
2099 chain_reply(req);
2102 /****************************************************************************
2103 Reply to a mknew or a create.
2104 ****************************************************************************/
2106 void reply_mknew(struct smb_request *req)
2108 connection_struct *conn = req->conn;
2109 struct smb_filename *smb_fname = NULL;
2110 char *fname = NULL;
2111 uint32 fattr = 0;
2112 struct smb_file_time ft;
2113 files_struct *fsp;
2114 int oplock_request = 0;
2115 NTSTATUS status;
2116 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2117 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2118 uint32 create_disposition;
2119 uint32 create_options = 0;
2120 TALLOC_CTX *ctx = talloc_tos();
2122 START_PROFILE(SMBcreate);
2123 ZERO_STRUCT(ft);
2125 if (req->wct < 3) {
2126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2127 goto out;
2130 fattr = SVAL(req->vwv+0, 0);
2131 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2133 /* mtime. */
2134 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2136 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2137 STR_TERMINATE, &status);
2138 if (!NT_STATUS_IS_OK(status)) {
2139 reply_nterror(req, status);
2140 goto out;
2143 status = filename_convert(ctx,
2144 conn,
2145 req->flags2 & FLAGS2_DFS_PATHNAMES,
2146 fname,
2148 NULL,
2149 &smb_fname);
2150 if (!NT_STATUS_IS_OK(status)) {
2151 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2152 reply_botherror(req,
2153 NT_STATUS_PATH_NOT_COVERED,
2154 ERRSRV, ERRbadpath);
2155 goto out;
2157 reply_nterror(req, status);
2158 goto out;
2161 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2162 DEBUG(0,("Attempt to create file (%s) with volid set - "
2163 "please report this\n",
2164 smb_fname_str_dbg(smb_fname)));
2167 if(req->cmd == SMBmknew) {
2168 /* We should fail if file exists. */
2169 create_disposition = FILE_CREATE;
2170 } else {
2171 /* Create if file doesn't exist, truncate if it does. */
2172 create_disposition = FILE_OVERWRITE_IF;
2175 status = SMB_VFS_CREATE_FILE(
2176 conn, /* conn */
2177 req, /* req */
2178 0, /* root_dir_fid */
2179 smb_fname, /* fname */
2180 access_mask, /* access_mask */
2181 share_mode, /* share_access */
2182 create_disposition, /* create_disposition*/
2183 create_options, /* create_options */
2184 fattr, /* file_attributes */
2185 oplock_request, /* oplock_request */
2186 0, /* allocation_size */
2187 0, /* private_flags */
2188 NULL, /* sd */
2189 NULL, /* ea_list */
2190 &fsp, /* result */
2191 NULL); /* pinfo */
2193 if (!NT_STATUS_IS_OK(status)) {
2194 if (open_was_deferred(req->mid)) {
2195 /* We have re-scheduled this call. */
2196 goto out;
2198 reply_openerror(req, status);
2199 goto out;
2202 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2203 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2204 if (!NT_STATUS_IS_OK(status)) {
2205 END_PROFILE(SMBcreate);
2206 goto out;
2209 reply_outbuf(req, 1, 0);
2210 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2212 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2213 SCVAL(req->outbuf,smb_flg,
2214 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2217 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2218 SCVAL(req->outbuf,smb_flg,
2219 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2222 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2223 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2224 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2225 (unsigned int)fattr));
2227 out:
2228 TALLOC_FREE(smb_fname);
2229 END_PROFILE(SMBcreate);
2230 return;
2233 /****************************************************************************
2234 Reply to a create temporary file.
2235 ****************************************************************************/
2237 void reply_ctemp(struct smb_request *req)
2239 connection_struct *conn = req->conn;
2240 struct smb_filename *smb_fname = NULL;
2241 char *fname = NULL;
2242 uint32 fattr;
2243 files_struct *fsp;
2244 int oplock_request;
2245 int tmpfd;
2246 char *s;
2247 NTSTATUS status;
2248 TALLOC_CTX *ctx = talloc_tos();
2250 START_PROFILE(SMBctemp);
2252 if (req->wct < 3) {
2253 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2254 goto out;
2257 fattr = SVAL(req->vwv+0, 0);
2258 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2260 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2261 STR_TERMINATE, &status);
2262 if (!NT_STATUS_IS_OK(status)) {
2263 reply_nterror(req, status);
2264 goto out;
2266 if (*fname) {
2267 fname = talloc_asprintf(ctx,
2268 "%s/TMXXXXXX",
2269 fname);
2270 } else {
2271 fname = talloc_strdup(ctx, "TMXXXXXX");
2274 if (!fname) {
2275 reply_nterror(req, NT_STATUS_NO_MEMORY);
2276 goto out;
2279 status = filename_convert(ctx, conn,
2280 req->flags2 & FLAGS2_DFS_PATHNAMES,
2281 fname,
2283 NULL,
2284 &smb_fname);
2285 if (!NT_STATUS_IS_OK(status)) {
2286 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2287 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2288 ERRSRV, ERRbadpath);
2289 goto out;
2291 reply_nterror(req, status);
2292 goto out;
2295 tmpfd = mkstemp(smb_fname->base_name);
2296 if (tmpfd == -1) {
2297 reply_nterror(req, map_nt_error_from_unix(errno));
2298 goto out;
2301 SMB_VFS_STAT(conn, smb_fname);
2303 /* We should fail if file does not exist. */
2304 status = SMB_VFS_CREATE_FILE(
2305 conn, /* conn */
2306 req, /* req */
2307 0, /* root_dir_fid */
2308 smb_fname, /* fname */
2309 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2310 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2311 FILE_OPEN, /* create_disposition*/
2312 0, /* create_options */
2313 fattr, /* file_attributes */
2314 oplock_request, /* oplock_request */
2315 0, /* allocation_size */
2316 0, /* private_flags */
2317 NULL, /* sd */
2318 NULL, /* ea_list */
2319 &fsp, /* result */
2320 NULL); /* pinfo */
2322 /* close fd from mkstemp() */
2323 close(tmpfd);
2325 if (!NT_STATUS_IS_OK(status)) {
2326 if (open_was_deferred(req->mid)) {
2327 /* We have re-scheduled this call. */
2328 goto out;
2330 reply_openerror(req, status);
2331 goto out;
2334 reply_outbuf(req, 1, 0);
2335 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2337 /* the returned filename is relative to the directory */
2338 s = strrchr_m(fsp->fsp_name->base_name, '/');
2339 if (!s) {
2340 s = fsp->fsp_name->base_name;
2341 } else {
2342 s++;
2345 #if 0
2346 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2347 thing in the byte section. JRA */
2348 SSVALS(p, 0, -1); /* what is this? not in spec */
2349 #endif
2350 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2351 == -1) {
2352 reply_nterror(req, NT_STATUS_NO_MEMORY);
2353 goto out;
2356 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2357 SCVAL(req->outbuf, smb_flg,
2358 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2361 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2362 SCVAL(req->outbuf, smb_flg,
2363 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2366 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2367 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2368 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2369 out:
2370 TALLOC_FREE(smb_fname);
2371 END_PROFILE(SMBctemp);
2372 return;
2375 /*******************************************************************
2376 Check if a user is allowed to rename a file.
2377 ********************************************************************/
2379 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2380 uint16 dirtype)
2382 if (!CAN_WRITE(conn)) {
2383 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2386 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2387 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2388 /* Only bother to read the DOS attribute if we might deny the
2389 rename on the grounds of attribute missmatch. */
2390 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2391 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2392 return NT_STATUS_NO_SUCH_FILE;
2396 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2397 if (fsp->posix_open) {
2398 return NT_STATUS_OK;
2401 /* If no pathnames are open below this
2402 directory, allow the rename. */
2404 if (file_find_subpath(fsp)) {
2405 return NT_STATUS_ACCESS_DENIED;
2407 return NT_STATUS_OK;
2410 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2411 return NT_STATUS_OK;
2414 return NT_STATUS_ACCESS_DENIED;
2417 /*******************************************************************
2418 * unlink a file with all relevant access checks
2419 *******************************************************************/
2421 static NTSTATUS do_unlink(connection_struct *conn,
2422 struct smb_request *req,
2423 struct smb_filename *smb_fname,
2424 uint32 dirtype)
2426 uint32 fattr;
2427 files_struct *fsp;
2428 uint32 dirtype_orig = dirtype;
2429 NTSTATUS status;
2430 int ret;
2431 bool posix_paths = lp_posix_pathnames();
2433 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2434 smb_fname_str_dbg(smb_fname),
2435 dirtype));
2437 if (!CAN_WRITE(conn)) {
2438 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2441 if (posix_paths) {
2442 ret = SMB_VFS_LSTAT(conn, smb_fname);
2443 } else {
2444 ret = SMB_VFS_STAT(conn, smb_fname);
2446 if (ret != 0) {
2447 return map_nt_error_from_unix(errno);
2450 fattr = dos_mode(conn, smb_fname);
2452 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2453 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2456 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2457 if (!dirtype) {
2458 return NT_STATUS_NO_SUCH_FILE;
2461 if (!dir_check_ftype(conn, fattr, dirtype)) {
2462 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2463 return NT_STATUS_FILE_IS_A_DIRECTORY;
2465 return NT_STATUS_NO_SUCH_FILE;
2468 if (dirtype_orig & 0x8000) {
2469 /* These will never be set for POSIX. */
2470 return NT_STATUS_NO_SUCH_FILE;
2473 #if 0
2474 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2475 return NT_STATUS_FILE_IS_A_DIRECTORY;
2478 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2479 return NT_STATUS_NO_SUCH_FILE;
2482 if (dirtype & 0xFF00) {
2483 /* These will never be set for POSIX. */
2484 return NT_STATUS_NO_SUCH_FILE;
2487 dirtype &= 0xFF;
2488 if (!dirtype) {
2489 return NT_STATUS_NO_SUCH_FILE;
2492 /* Can't delete a directory. */
2493 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2494 return NT_STATUS_FILE_IS_A_DIRECTORY;
2496 #endif
2498 #if 0 /* JRATEST */
2499 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2500 return NT_STATUS_OBJECT_NAME_INVALID;
2501 #endif /* JRATEST */
2503 /* On open checks the open itself will check the share mode, so
2504 don't do it here as we'll get it wrong. */
2506 status = SMB_VFS_CREATE_FILE
2507 (conn, /* conn */
2508 req, /* req */
2509 0, /* root_dir_fid */
2510 smb_fname, /* fname */
2511 DELETE_ACCESS, /* access_mask */
2512 FILE_SHARE_NONE, /* share_access */
2513 FILE_OPEN, /* create_disposition*/
2514 FILE_NON_DIRECTORY_FILE, /* create_options */
2515 /* file_attributes */
2516 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2517 FILE_ATTRIBUTE_NORMAL,
2518 0, /* oplock_request */
2519 0, /* allocation_size */
2520 0, /* private_flags */
2521 NULL, /* sd */
2522 NULL, /* ea_list */
2523 &fsp, /* result */
2524 NULL); /* pinfo */
2526 if (!NT_STATUS_IS_OK(status)) {
2527 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2528 nt_errstr(status)));
2529 return status;
2532 status = can_set_delete_on_close(fsp, fattr);
2533 if (!NT_STATUS_IS_OK(status)) {
2534 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2535 "(%s)\n",
2536 smb_fname_str_dbg(smb_fname),
2537 nt_errstr(status)));
2538 close_file(req, fsp, NORMAL_CLOSE);
2539 return status;
2542 /* The set is across all open files on this dev/inode pair. */
2543 if (!set_delete_on_close(fsp, True, &conn->session_info->utok)) {
2544 close_file(req, fsp, NORMAL_CLOSE);
2545 return NT_STATUS_ACCESS_DENIED;
2548 return close_file(req, fsp, NORMAL_CLOSE);
2551 /****************************************************************************
2552 The guts of the unlink command, split out so it may be called by the NT SMB
2553 code.
2554 ****************************************************************************/
2556 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2557 uint32 dirtype, struct smb_filename *smb_fname,
2558 bool has_wild)
2560 char *fname_dir = NULL;
2561 char *fname_mask = NULL;
2562 int count=0;
2563 NTSTATUS status = NT_STATUS_OK;
2564 TALLOC_CTX *ctx = talloc_tos();
2566 /* Split up the directory from the filename/mask. */
2567 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2568 &fname_dir, &fname_mask);
2569 if (!NT_STATUS_IS_OK(status)) {
2570 goto out;
2574 * We should only check the mangled cache
2575 * here if unix_convert failed. This means
2576 * that the path in 'mask' doesn't exist
2577 * on the file system and so we need to look
2578 * for a possible mangle. This patch from
2579 * Tine Smukavec <valentin.smukavec@hermes.si>.
2582 if (!VALID_STAT(smb_fname->st) &&
2583 mangle_is_mangled(fname_mask, conn->params)) {
2584 char *new_mask = NULL;
2585 mangle_lookup_name_from_8_3(ctx, fname_mask,
2586 &new_mask, conn->params);
2587 if (new_mask) {
2588 TALLOC_FREE(fname_mask);
2589 fname_mask = new_mask;
2593 if (!has_wild) {
2596 * Only one file needs to be unlinked. Append the mask back
2597 * onto the directory.
2599 TALLOC_FREE(smb_fname->base_name);
2600 if (ISDOT(fname_dir)) {
2601 /* Ensure we use canonical names on open. */
2602 smb_fname->base_name = talloc_asprintf(smb_fname,
2603 "%s",
2604 fname_mask);
2605 } else {
2606 smb_fname->base_name = talloc_asprintf(smb_fname,
2607 "%s/%s",
2608 fname_dir,
2609 fname_mask);
2611 if (!smb_fname->base_name) {
2612 status = NT_STATUS_NO_MEMORY;
2613 goto out;
2615 if (dirtype == 0) {
2616 dirtype = FILE_ATTRIBUTE_NORMAL;
2619 status = check_name(conn, smb_fname->base_name);
2620 if (!NT_STATUS_IS_OK(status)) {
2621 goto out;
2624 status = do_unlink(conn, req, smb_fname, dirtype);
2625 if (!NT_STATUS_IS_OK(status)) {
2626 goto out;
2629 count++;
2630 } else {
2631 struct smb_Dir *dir_hnd = NULL;
2632 long offset = 0;
2633 const char *dname = NULL;
2634 char *talloced = NULL;
2636 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2637 status = NT_STATUS_OBJECT_NAME_INVALID;
2638 goto out;
2641 if (strequal(fname_mask,"????????.???")) {
2642 TALLOC_FREE(fname_mask);
2643 fname_mask = talloc_strdup(ctx, "*");
2644 if (!fname_mask) {
2645 status = NT_STATUS_NO_MEMORY;
2646 goto out;
2650 status = check_name(conn, fname_dir);
2651 if (!NT_STATUS_IS_OK(status)) {
2652 goto out;
2655 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2656 dirtype);
2657 if (dir_hnd == NULL) {
2658 status = map_nt_error_from_unix(errno);
2659 goto out;
2662 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2663 the pattern matches against the long name, otherwise the short name
2664 We don't implement this yet XXXX
2667 status = NT_STATUS_NO_SUCH_FILE;
2669 while ((dname = ReadDirName(dir_hnd, &offset,
2670 &smb_fname->st, &talloced))) {
2671 TALLOC_CTX *frame = talloc_stackframe();
2673 if (!is_visible_file(conn, fname_dir, dname,
2674 &smb_fname->st, true)) {
2675 TALLOC_FREE(frame);
2676 TALLOC_FREE(talloced);
2677 continue;
2680 /* Quick check for "." and ".." */
2681 if (ISDOT(dname) || ISDOTDOT(dname)) {
2682 TALLOC_FREE(frame);
2683 TALLOC_FREE(talloced);
2684 continue;
2687 if(!mask_match(dname, fname_mask,
2688 conn->case_sensitive)) {
2689 TALLOC_FREE(frame);
2690 TALLOC_FREE(talloced);
2691 continue;
2694 TALLOC_FREE(smb_fname->base_name);
2695 if (ISDOT(fname_dir)) {
2696 /* Ensure we use canonical names on open. */
2697 smb_fname->base_name =
2698 talloc_asprintf(smb_fname, "%s",
2699 dname);
2700 } else {
2701 smb_fname->base_name =
2702 talloc_asprintf(smb_fname, "%s/%s",
2703 fname_dir, dname);
2706 if (!smb_fname->base_name) {
2707 TALLOC_FREE(dir_hnd);
2708 status = NT_STATUS_NO_MEMORY;
2709 TALLOC_FREE(frame);
2710 TALLOC_FREE(talloced);
2711 goto out;
2714 status = check_name(conn, smb_fname->base_name);
2715 if (!NT_STATUS_IS_OK(status)) {
2716 TALLOC_FREE(dir_hnd);
2717 TALLOC_FREE(frame);
2718 TALLOC_FREE(talloced);
2719 goto out;
2722 status = do_unlink(conn, req, smb_fname, dirtype);
2723 if (!NT_STATUS_IS_OK(status)) {
2724 TALLOC_FREE(frame);
2725 TALLOC_FREE(talloced);
2726 continue;
2729 count++;
2730 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2731 smb_fname->base_name));
2733 TALLOC_FREE(frame);
2734 TALLOC_FREE(talloced);
2736 TALLOC_FREE(dir_hnd);
2739 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2740 status = map_nt_error_from_unix(errno);
2743 out:
2744 TALLOC_FREE(fname_dir);
2745 TALLOC_FREE(fname_mask);
2746 return status;
2749 /****************************************************************************
2750 Reply to a unlink
2751 ****************************************************************************/
2753 void reply_unlink(struct smb_request *req)
2755 connection_struct *conn = req->conn;
2756 char *name = NULL;
2757 struct smb_filename *smb_fname = NULL;
2758 uint32 dirtype;
2759 NTSTATUS status;
2760 bool path_contains_wcard = False;
2761 TALLOC_CTX *ctx = talloc_tos();
2763 START_PROFILE(SMBunlink);
2765 if (req->wct < 1) {
2766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2767 goto out;
2770 dirtype = SVAL(req->vwv+0, 0);
2772 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2773 STR_TERMINATE, &status,
2774 &path_contains_wcard);
2775 if (!NT_STATUS_IS_OK(status)) {
2776 reply_nterror(req, status);
2777 goto out;
2780 status = filename_convert(ctx, conn,
2781 req->flags2 & FLAGS2_DFS_PATHNAMES,
2782 name,
2783 UCF_COND_ALLOW_WCARD_LCOMP,
2784 &path_contains_wcard,
2785 &smb_fname);
2786 if (!NT_STATUS_IS_OK(status)) {
2787 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2788 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2789 ERRSRV, ERRbadpath);
2790 goto out;
2792 reply_nterror(req, status);
2793 goto out;
2796 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2798 status = unlink_internals(conn, req, dirtype, smb_fname,
2799 path_contains_wcard);
2800 if (!NT_STATUS_IS_OK(status)) {
2801 if (open_was_deferred(req->mid)) {
2802 /* We have re-scheduled this call. */
2803 goto out;
2805 reply_nterror(req, status);
2806 goto out;
2809 reply_outbuf(req, 0, 0);
2810 out:
2811 TALLOC_FREE(smb_fname);
2812 END_PROFILE(SMBunlink);
2813 return;
2816 /****************************************************************************
2817 Fail for readbraw.
2818 ****************************************************************************/
2820 static void fail_readraw(void)
2822 const char *errstr = talloc_asprintf(talloc_tos(),
2823 "FAIL ! reply_readbraw: socket write fail (%s)",
2824 strerror(errno));
2825 if (!errstr) {
2826 errstr = "";
2828 exit_server_cleanly(errstr);
2831 /****************************************************************************
2832 Fake (read/write) sendfile. Returns -1 on read or write fail.
2833 ****************************************************************************/
2835 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2837 size_t bufsize;
2838 size_t tosend = nread;
2839 char *buf;
2841 if (nread == 0) {
2842 return 0;
2845 bufsize = MIN(nread, 65536);
2847 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2848 return -1;
2851 while (tosend > 0) {
2852 ssize_t ret;
2853 size_t cur_read;
2855 if (tosend > bufsize) {
2856 cur_read = bufsize;
2857 } else {
2858 cur_read = tosend;
2860 ret = read_file(fsp,buf,startpos,cur_read);
2861 if (ret == -1) {
2862 SAFE_FREE(buf);
2863 return -1;
2866 /* If we had a short read, fill with zeros. */
2867 if (ret < cur_read) {
2868 memset(buf + ret, '\0', cur_read - ret);
2871 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2872 != cur_read) {
2873 char addr[INET6_ADDRSTRLEN];
2875 * Try and give an error message saying what
2876 * client failed.
2878 DEBUG(0, ("write_data failed for client %s. "
2879 "Error %s\n",
2880 get_peer_addr(fsp->conn->sconn->sock, addr,
2881 sizeof(addr)),
2882 strerror(errno)));
2883 SAFE_FREE(buf);
2884 return -1;
2886 tosend -= cur_read;
2887 startpos += cur_read;
2890 SAFE_FREE(buf);
2891 return (ssize_t)nread;
2894 /****************************************************************************
2895 Deal with the case of sendfile reading less bytes from the file than
2896 requested. Fill with zeros (all we can do).
2897 ****************************************************************************/
2899 void sendfile_short_send(files_struct *fsp,
2900 ssize_t nread,
2901 size_t headersize,
2902 size_t smb_maxcnt)
2904 #define SHORT_SEND_BUFSIZE 1024
2905 if (nread < headersize) {
2906 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2907 "header for file %s (%s). Terminating\n",
2908 fsp_str_dbg(fsp), strerror(errno)));
2909 exit_server_cleanly("sendfile_short_send failed");
2912 nread -= headersize;
2914 if (nread < smb_maxcnt) {
2915 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2916 if (!buf) {
2917 exit_server_cleanly("sendfile_short_send: "
2918 "malloc failed");
2921 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2922 "with zeros !\n", fsp_str_dbg(fsp)));
2924 while (nread < smb_maxcnt) {
2926 * We asked for the real file size and told sendfile
2927 * to not go beyond the end of the file. But it can
2928 * happen that in between our fstat call and the
2929 * sendfile call the file was truncated. This is very
2930 * bad because we have already announced the larger
2931 * number of bytes to the client.
2933 * The best we can do now is to send 0-bytes, just as
2934 * a read from a hole in a sparse file would do.
2936 * This should happen rarely enough that I don't care
2937 * about efficiency here :-)
2939 size_t to_write;
2941 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2942 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2943 != to_write) {
2944 char addr[INET6_ADDRSTRLEN];
2946 * Try and give an error message saying what
2947 * client failed.
2949 DEBUG(0, ("write_data failed for client %s. "
2950 "Error %s\n",
2951 get_peer_addr(
2952 fsp->conn->sconn->sock, addr,
2953 sizeof(addr)),
2954 strerror(errno)));
2955 exit_server_cleanly("sendfile_short_send: "
2956 "write_data failed");
2958 nread += to_write;
2960 SAFE_FREE(buf);
2964 /****************************************************************************
2965 Return a readbraw error (4 bytes of zero).
2966 ****************************************************************************/
2968 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2970 char header[4];
2972 SIVAL(header,0,0);
2974 smbd_lock_socket(sconn);
2975 if (write_data(sconn->sock,header,4) != 4) {
2976 char addr[INET6_ADDRSTRLEN];
2978 * Try and give an error message saying what
2979 * client failed.
2981 DEBUG(0, ("write_data failed for client %s. "
2982 "Error %s\n",
2983 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2984 strerror(errno)));
2986 fail_readraw();
2988 smbd_unlock_socket(sconn);
2991 /****************************************************************************
2992 Use sendfile in readbraw.
2993 ****************************************************************************/
2995 static void send_file_readbraw(connection_struct *conn,
2996 struct smb_request *req,
2997 files_struct *fsp,
2998 SMB_OFF_T startpos,
2999 size_t nread,
3000 ssize_t mincount)
3002 struct smbd_server_connection *sconn = req->sconn;
3003 char *outbuf = NULL;
3004 ssize_t ret=0;
3007 * We can only use sendfile on a non-chained packet
3008 * but we can use on a non-oplocked file. tridge proved this
3009 * on a train in Germany :-). JRA.
3010 * reply_readbraw has already checked the length.
3013 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3014 (fsp->wcp == NULL) &&
3015 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3016 ssize_t sendfile_read = -1;
3017 char header[4];
3018 DATA_BLOB header_blob;
3020 _smb_setlen(header,nread);
3021 header_blob = data_blob_const(header, 4);
3023 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3024 &header_blob, startpos,
3025 nread);
3026 if (sendfile_read == -1) {
3027 /* Returning ENOSYS means no data at all was sent.
3028 * Do this as a normal read. */
3029 if (errno == ENOSYS) {
3030 goto normal_readbraw;
3034 * Special hack for broken Linux with no working sendfile. If we
3035 * return EINTR we sent the header but not the rest of the data.
3036 * Fake this up by doing read/write calls.
3038 if (errno == EINTR) {
3039 /* Ensure we don't do this again. */
3040 set_use_sendfile(SNUM(conn), False);
3041 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3043 if (fake_sendfile(fsp, startpos, nread) == -1) {
3044 DEBUG(0,("send_file_readbraw: "
3045 "fake_sendfile failed for "
3046 "file %s (%s).\n",
3047 fsp_str_dbg(fsp),
3048 strerror(errno)));
3049 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3051 return;
3054 DEBUG(0,("send_file_readbraw: sendfile failed for "
3055 "file %s (%s). Terminating\n",
3056 fsp_str_dbg(fsp), strerror(errno)));
3057 exit_server_cleanly("send_file_readbraw sendfile failed");
3058 } else if (sendfile_read == 0) {
3060 * Some sendfile implementations return 0 to indicate
3061 * that there was a short read, but nothing was
3062 * actually written to the socket. In this case,
3063 * fallback to the normal read path so the header gets
3064 * the correct byte count.
3066 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3067 "bytes falling back to the normal read: "
3068 "%s\n", fsp_str_dbg(fsp)));
3069 goto normal_readbraw;
3072 /* Deal with possible short send. */
3073 if (sendfile_read != 4+nread) {
3074 sendfile_short_send(fsp, sendfile_read, 4, nread);
3076 return;
3079 normal_readbraw:
3081 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3082 if (!outbuf) {
3083 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3084 (unsigned)(nread+4)));
3085 reply_readbraw_error(sconn);
3086 return;
3089 if (nread > 0) {
3090 ret = read_file(fsp,outbuf+4,startpos,nread);
3091 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3092 if (ret < mincount)
3093 ret = 0;
3094 #else
3095 if (ret < nread)
3096 ret = 0;
3097 #endif
3100 _smb_setlen(outbuf,ret);
3101 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3102 char addr[INET6_ADDRSTRLEN];
3104 * Try and give an error message saying what
3105 * client failed.
3107 DEBUG(0, ("write_data failed for client %s. "
3108 "Error %s\n",
3109 get_peer_addr(fsp->conn->sconn->sock, addr,
3110 sizeof(addr)),
3111 strerror(errno)));
3113 fail_readraw();
3116 TALLOC_FREE(outbuf);
3119 /****************************************************************************
3120 Reply to a readbraw (core+ protocol).
3121 ****************************************************************************/
3123 void reply_readbraw(struct smb_request *req)
3125 connection_struct *conn = req->conn;
3126 struct smbd_server_connection *sconn = req->sconn;
3127 ssize_t maxcount,mincount;
3128 size_t nread = 0;
3129 SMB_OFF_T startpos;
3130 files_struct *fsp;
3131 struct lock_struct lock;
3132 SMB_OFF_T size = 0;
3134 START_PROFILE(SMBreadbraw);
3136 if (srv_is_signing_active(sconn) ||
3137 is_encrypted_packet(req->inbuf)) {
3138 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3139 "raw reads/writes are disallowed.");
3142 if (req->wct < 8) {
3143 reply_readbraw_error(sconn);
3144 END_PROFILE(SMBreadbraw);
3145 return;
3148 if (sconn->smb1.echo_handler.trusted_fde) {
3149 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3150 "'async smb echo handler = yes'\n"));
3151 reply_readbraw_error(sconn);
3152 END_PROFILE(SMBreadbraw);
3153 return;
3157 * Special check if an oplock break has been issued
3158 * and the readraw request croses on the wire, we must
3159 * return a zero length response here.
3162 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3165 * We have to do a check_fsp by hand here, as
3166 * we must always return 4 zero bytes on error,
3167 * not a NTSTATUS.
3170 if (!fsp || !conn || conn != fsp->conn ||
3171 req->vuid != fsp->vuid ||
3172 fsp->is_directory || fsp->fh->fd == -1) {
3174 * fsp could be NULL here so use the value from the packet. JRA.
3176 DEBUG(3,("reply_readbraw: fnum %d not valid "
3177 "- cache prime?\n",
3178 (int)SVAL(req->vwv+0, 0)));
3179 reply_readbraw_error(sconn);
3180 END_PROFILE(SMBreadbraw);
3181 return;
3184 /* Do a "by hand" version of CHECK_READ. */
3185 if (!(fsp->can_read ||
3186 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3187 (fsp->access_mask & FILE_EXECUTE)))) {
3188 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3189 (int)SVAL(req->vwv+0, 0)));
3190 reply_readbraw_error(sconn);
3191 END_PROFILE(SMBreadbraw);
3192 return;
3195 flush_write_cache(fsp, READRAW_FLUSH);
3197 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3198 if(req->wct == 10) {
3200 * This is a large offset (64 bit) read.
3202 #ifdef LARGE_SMB_OFF_T
3204 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3206 #else /* !LARGE_SMB_OFF_T */
3209 * Ensure we haven't been sent a >32 bit offset.
3212 if(IVAL(req->vwv+8, 0) != 0) {
3213 DEBUG(0,("reply_readbraw: large offset "
3214 "(%x << 32) used and we don't support "
3215 "64 bit offsets.\n",
3216 (unsigned int)IVAL(req->vwv+8, 0) ));
3217 reply_readbraw_error(sconn);
3218 END_PROFILE(SMBreadbraw);
3219 return;
3222 #endif /* LARGE_SMB_OFF_T */
3224 if(startpos < 0) {
3225 DEBUG(0,("reply_readbraw: negative 64 bit "
3226 "readraw offset (%.0f) !\n",
3227 (double)startpos ));
3228 reply_readbraw_error(sconn);
3229 END_PROFILE(SMBreadbraw);
3230 return;
3234 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3235 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3237 /* ensure we don't overrun the packet size */
3238 maxcount = MIN(65535,maxcount);
3240 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3241 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3242 &lock);
3244 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3245 reply_readbraw_error(sconn);
3246 END_PROFILE(SMBreadbraw);
3247 return;
3250 if (fsp_stat(fsp) == 0) {
3251 size = fsp->fsp_name->st.st_ex_size;
3254 if (startpos >= size) {
3255 nread = 0;
3256 } else {
3257 nread = MIN(maxcount,(size - startpos));
3260 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3261 if (nread < mincount)
3262 nread = 0;
3263 #endif
3265 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3266 "min=%lu nread=%lu\n",
3267 fsp->fnum, (double)startpos,
3268 (unsigned long)maxcount,
3269 (unsigned long)mincount,
3270 (unsigned long)nread ) );
3272 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3274 DEBUG(5,("reply_readbraw finished\n"));
3276 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3278 END_PROFILE(SMBreadbraw);
3279 return;
3282 #undef DBGC_CLASS
3283 #define DBGC_CLASS DBGC_LOCKING
3285 /****************************************************************************
3286 Reply to a lockread (core+ protocol).
3287 ****************************************************************************/
3289 void reply_lockread(struct smb_request *req)
3291 connection_struct *conn = req->conn;
3292 ssize_t nread = -1;
3293 char *data;
3294 SMB_OFF_T startpos;
3295 size_t numtoread;
3296 NTSTATUS status;
3297 files_struct *fsp;
3298 struct byte_range_lock *br_lck = NULL;
3299 char *p = NULL;
3300 struct smbd_server_connection *sconn = req->sconn;
3302 START_PROFILE(SMBlockread);
3304 if (req->wct < 5) {
3305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3306 END_PROFILE(SMBlockread);
3307 return;
3310 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3312 if (!check_fsp(conn, req, fsp)) {
3313 END_PROFILE(SMBlockread);
3314 return;
3317 if (!CHECK_READ(fsp,req)) {
3318 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3319 END_PROFILE(SMBlockread);
3320 return;
3323 numtoread = SVAL(req->vwv+1, 0);
3324 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3326 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3328 reply_outbuf(req, 5, numtoread + 3);
3330 data = smb_buf(req->outbuf) + 3;
3333 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3334 * protocol request that predates the read/write lock concept.
3335 * Thus instead of asking for a read lock here we need to ask
3336 * for a write lock. JRA.
3337 * Note that the requested lock size is unaffected by max_recv.
3340 br_lck = do_lock(req->sconn->msg_ctx,
3341 fsp,
3342 (uint64_t)req->smbpid,
3343 (uint64_t)numtoread,
3344 (uint64_t)startpos,
3345 WRITE_LOCK,
3346 WINDOWS_LOCK,
3347 False, /* Non-blocking lock. */
3348 &status,
3349 NULL,
3350 NULL);
3351 TALLOC_FREE(br_lck);
3353 if (NT_STATUS_V(status)) {
3354 reply_nterror(req, status);
3355 END_PROFILE(SMBlockread);
3356 return;
3360 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3363 if (numtoread > sconn->smb1.negprot.max_recv) {
3364 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3365 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3366 (unsigned int)numtoread,
3367 (unsigned int)sconn->smb1.negprot.max_recv));
3368 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3370 nread = read_file(fsp,data,startpos,numtoread);
3372 if (nread < 0) {
3373 reply_nterror(req, map_nt_error_from_unix(errno));
3374 END_PROFILE(SMBlockread);
3375 return;
3378 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3380 SSVAL(req->outbuf,smb_vwv0,nread);
3381 SSVAL(req->outbuf,smb_vwv5,nread+3);
3382 p = smb_buf(req->outbuf);
3383 SCVAL(p,0,0); /* pad byte. */
3384 SSVAL(p,1,nread);
3386 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3387 fsp->fnum, (int)numtoread, (int)nread));
3389 END_PROFILE(SMBlockread);
3390 return;
3393 #undef DBGC_CLASS
3394 #define DBGC_CLASS DBGC_ALL
3396 /****************************************************************************
3397 Reply to a read.
3398 ****************************************************************************/
3400 void reply_read(struct smb_request *req)
3402 connection_struct *conn = req->conn;
3403 size_t numtoread;
3404 ssize_t nread = 0;
3405 char *data;
3406 SMB_OFF_T startpos;
3407 int outsize = 0;
3408 files_struct *fsp;
3409 struct lock_struct lock;
3410 struct smbd_server_connection *sconn = req->sconn;
3412 START_PROFILE(SMBread);
3414 if (req->wct < 3) {
3415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3416 END_PROFILE(SMBread);
3417 return;
3420 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3422 if (!check_fsp(conn, req, fsp)) {
3423 END_PROFILE(SMBread);
3424 return;
3427 if (!CHECK_READ(fsp,req)) {
3428 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3429 END_PROFILE(SMBread);
3430 return;
3433 numtoread = SVAL(req->vwv+1, 0);
3434 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3436 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3439 * The requested read size cannot be greater than max_recv. JRA.
3441 if (numtoread > sconn->smb1.negprot.max_recv) {
3442 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3443 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3444 (unsigned int)numtoread,
3445 (unsigned int)sconn->smb1.negprot.max_recv));
3446 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3449 reply_outbuf(req, 5, numtoread+3);
3451 data = smb_buf(req->outbuf) + 3;
3453 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3454 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3455 &lock);
3457 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3458 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3459 END_PROFILE(SMBread);
3460 return;
3463 if (numtoread > 0)
3464 nread = read_file(fsp,data,startpos,numtoread);
3466 if (nread < 0) {
3467 reply_nterror(req, map_nt_error_from_unix(errno));
3468 goto strict_unlock;
3471 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3473 SSVAL(req->outbuf,smb_vwv0,nread);
3474 SSVAL(req->outbuf,smb_vwv5,nread+3);
3475 SCVAL(smb_buf(req->outbuf),0,1);
3476 SSVAL(smb_buf(req->outbuf),1,nread);
3478 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3479 fsp->fnum, (int)numtoread, (int)nread ) );
3481 strict_unlock:
3482 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3484 END_PROFILE(SMBread);
3485 return;
3488 /****************************************************************************
3489 Setup readX header.
3490 ****************************************************************************/
3492 static int setup_readX_header(struct smb_request *req, char *outbuf,
3493 size_t smb_maxcnt)
3495 int outsize;
3496 char *data;
3498 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3499 data = smb_buf(outbuf);
3501 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3503 SCVAL(outbuf,smb_vwv0,0xFF);
3504 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3505 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3506 SSVAL(outbuf,smb_vwv6,
3507 req_wct_ofs(req)
3508 + 1 /* the wct field */
3509 + 12 * sizeof(uint16_t) /* vwv */
3510 + 2); /* the buflen field */
3511 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3512 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3513 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3514 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3515 return outsize;
3518 /****************************************************************************
3519 Reply to a read and X - possibly using sendfile.
3520 ****************************************************************************/
3522 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3523 files_struct *fsp, SMB_OFF_T startpos,
3524 size_t smb_maxcnt)
3526 ssize_t nread = -1;
3527 struct lock_struct lock;
3528 int saved_errno = 0;
3530 if(fsp_stat(fsp) == -1) {
3531 reply_nterror(req, map_nt_error_from_unix(errno));
3532 return;
3535 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3536 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3537 &lock);
3539 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3540 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3541 return;
3544 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3545 (startpos > fsp->fsp_name->st.st_ex_size)
3546 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3548 * We already know that we would do a short read, so don't
3549 * try the sendfile() path.
3551 goto nosendfile_read;
3555 * We can only use sendfile on a non-chained packet
3556 * but we can use on a non-oplocked file. tridge proved this
3557 * on a train in Germany :-). JRA.
3560 if (!req_is_in_chain(req) &&
3561 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3562 (fsp->wcp == NULL) &&
3563 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3564 uint8 headerbuf[smb_size + 12 * 2];
3565 DATA_BLOB header;
3568 * Set up the packet header before send. We
3569 * assume here the sendfile will work (get the
3570 * correct amount of data).
3573 header = data_blob_const(headerbuf, sizeof(headerbuf));
3575 construct_reply_common_req(req, (char *)headerbuf);
3576 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3578 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3579 startpos, smb_maxcnt);
3580 if (nread == -1) {
3581 /* Returning ENOSYS means no data at all was sent.
3582 Do this as a normal read. */
3583 if (errno == ENOSYS) {
3584 goto normal_read;
3588 * Special hack for broken Linux with no working sendfile. If we
3589 * return EINTR we sent the header but not the rest of the data.
3590 * Fake this up by doing read/write calls.
3593 if (errno == EINTR) {
3594 /* Ensure we don't do this again. */
3595 set_use_sendfile(SNUM(conn), False);
3596 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3597 nread = fake_sendfile(fsp, startpos,
3598 smb_maxcnt);
3599 if (nread == -1) {
3600 DEBUG(0,("send_file_readX: "
3601 "fake_sendfile failed for "
3602 "file %s (%s).\n",
3603 fsp_str_dbg(fsp),
3604 strerror(errno)));
3605 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3607 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3608 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3609 /* No outbuf here means successful sendfile. */
3610 goto strict_unlock;
3613 DEBUG(0,("send_file_readX: sendfile failed for file "
3614 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3615 strerror(errno)));
3616 exit_server_cleanly("send_file_readX sendfile failed");
3617 } else if (nread == 0) {
3619 * Some sendfile implementations return 0 to indicate
3620 * that there was a short read, but nothing was
3621 * actually written to the socket. In this case,
3622 * fallback to the normal read path so the header gets
3623 * the correct byte count.
3625 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3626 "falling back to the normal read: %s\n",
3627 fsp_str_dbg(fsp)));
3628 goto normal_read;
3631 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3632 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3634 /* Deal with possible short send. */
3635 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3636 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3638 /* No outbuf here means successful sendfile. */
3639 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3640 SMB_PERFCOUNT_END(&req->pcd);
3641 goto strict_unlock;
3644 normal_read:
3646 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3647 uint8 headerbuf[smb_size + 2*12];
3649 construct_reply_common_req(req, (char *)headerbuf);
3650 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3652 /* Send out the header. */
3653 if (write_data(req->sconn->sock, (char *)headerbuf,
3654 sizeof(headerbuf)) != sizeof(headerbuf)) {
3656 char addr[INET6_ADDRSTRLEN];
3658 * Try and give an error message saying what
3659 * client failed.
3661 DEBUG(0, ("write_data failed for client %s. "
3662 "Error %s\n",
3663 get_peer_addr(req->sconn->sock, addr,
3664 sizeof(addr)),
3665 strerror(errno)));
3667 DEBUG(0,("send_file_readX: write_data failed for file "
3668 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3669 strerror(errno)));
3670 exit_server_cleanly("send_file_readX sendfile failed");
3672 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3673 if (nread == -1) {
3674 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3675 "file %s (%s).\n", fsp_str_dbg(fsp),
3676 strerror(errno)));
3677 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3679 goto strict_unlock;
3682 nosendfile_read:
3684 reply_outbuf(req, 12, smb_maxcnt);
3686 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3687 saved_errno = errno;
3689 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3691 if (nread < 0) {
3692 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3693 return;
3696 setup_readX_header(req, (char *)req->outbuf, nread);
3698 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3699 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3701 chain_reply(req);
3702 return;
3704 strict_unlock:
3705 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3706 TALLOC_FREE(req->outbuf);
3707 return;
3710 /****************************************************************************
3711 Reply to a read and X.
3712 ****************************************************************************/
3714 void reply_read_and_X(struct smb_request *req)
3716 connection_struct *conn = req->conn;
3717 files_struct *fsp;
3718 SMB_OFF_T startpos;
3719 size_t smb_maxcnt;
3720 bool big_readX = False;
3721 #if 0
3722 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3723 #endif
3725 START_PROFILE(SMBreadX);
3727 if ((req->wct != 10) && (req->wct != 12)) {
3728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3729 return;
3732 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3733 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3734 smb_maxcnt = SVAL(req->vwv+5, 0);
3736 /* If it's an IPC, pass off the pipe handler. */
3737 if (IS_IPC(conn)) {
3738 reply_pipe_read_and_X(req);
3739 END_PROFILE(SMBreadX);
3740 return;
3743 if (!check_fsp(conn, req, fsp)) {
3744 END_PROFILE(SMBreadX);
3745 return;
3748 if (!CHECK_READ(fsp,req)) {
3749 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3750 END_PROFILE(SMBreadX);
3751 return;
3754 if (global_client_caps & CAP_LARGE_READX) {
3755 size_t upper_size = SVAL(req->vwv+7, 0);
3756 smb_maxcnt |= (upper_size<<16);
3757 if (upper_size > 1) {
3758 /* Can't do this on a chained packet. */
3759 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3760 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3761 END_PROFILE(SMBreadX);
3762 return;
3764 /* We currently don't do this on signed or sealed data. */
3765 if (srv_is_signing_active(req->sconn) ||
3766 is_encrypted_packet(req->inbuf)) {
3767 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3768 END_PROFILE(SMBreadX);
3769 return;
3771 /* Is there room in the reply for this data ? */
3772 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3773 reply_nterror(req,
3774 NT_STATUS_INVALID_PARAMETER);
3775 END_PROFILE(SMBreadX);
3776 return;
3778 big_readX = True;
3782 if (req->wct == 12) {
3783 #ifdef LARGE_SMB_OFF_T
3785 * This is a large offset (64 bit) read.
3787 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3789 #else /* !LARGE_SMB_OFF_T */
3792 * Ensure we haven't been sent a >32 bit offset.
3795 if(IVAL(req->vwv+10, 0) != 0) {
3796 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3797 "used and we don't support 64 bit offsets.\n",
3798 (unsigned int)IVAL(req->vwv+10, 0) ));
3799 END_PROFILE(SMBreadX);
3800 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3801 return;
3804 #endif /* LARGE_SMB_OFF_T */
3808 if (!big_readX) {
3809 NTSTATUS status = schedule_aio_read_and_X(conn,
3810 req,
3811 fsp,
3812 startpos,
3813 smb_maxcnt);
3814 if (NT_STATUS_IS_OK(status)) {
3815 /* Read scheduled - we're done. */
3816 goto out;
3818 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3819 /* Real error - report to client. */
3820 END_PROFILE(SMBreadX);
3821 reply_nterror(req, status);
3822 return;
3824 /* NT_STATUS_RETRY - fall back to sync read. */
3827 smbd_lock_socket(req->sconn);
3828 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3829 smbd_unlock_socket(req->sconn);
3831 out:
3832 END_PROFILE(SMBreadX);
3833 return;
3836 /****************************************************************************
3837 Error replies to writebraw must have smb_wct == 1. Fix this up.
3838 ****************************************************************************/
3840 void error_to_writebrawerr(struct smb_request *req)
3842 uint8 *old_outbuf = req->outbuf;
3844 reply_outbuf(req, 1, 0);
3846 memcpy(req->outbuf, old_outbuf, smb_size);
3847 TALLOC_FREE(old_outbuf);
3850 /****************************************************************************
3851 Read 4 bytes of a smb packet and return the smb length of the packet.
3852 Store the result in the buffer. This version of the function will
3853 never return a session keepalive (length of zero).
3854 Timeout is in milliseconds.
3855 ****************************************************************************/
3857 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3858 size_t *len)
3860 uint8_t msgtype = SMBkeepalive;
3862 while (msgtype == SMBkeepalive) {
3863 NTSTATUS status;
3865 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3866 len);
3867 if (!NT_STATUS_IS_OK(status)) {
3868 char addr[INET6_ADDRSTRLEN];
3869 /* Try and give an error message
3870 * saying what client failed. */
3871 DEBUG(0, ("read_fd_with_timeout failed for "
3872 "client %s read error = %s.\n",
3873 get_peer_addr(fd,addr,sizeof(addr)),
3874 nt_errstr(status)));
3875 return status;
3878 msgtype = CVAL(inbuf, 0);
3881 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3882 (unsigned long)len));
3884 return NT_STATUS_OK;
3887 /****************************************************************************
3888 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3889 ****************************************************************************/
3891 void reply_writebraw(struct smb_request *req)
3893 connection_struct *conn = req->conn;
3894 char *buf = NULL;
3895 ssize_t nwritten=0;
3896 ssize_t total_written=0;
3897 size_t numtowrite=0;
3898 size_t tcount;
3899 SMB_OFF_T startpos;
3900 char *data=NULL;
3901 bool write_through;
3902 files_struct *fsp;
3903 struct lock_struct lock;
3904 NTSTATUS status;
3906 START_PROFILE(SMBwritebraw);
3909 * If we ever reply with an error, it must have the SMB command
3910 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3911 * we're finished.
3913 SCVAL(req->inbuf,smb_com,SMBwritec);
3915 if (srv_is_signing_active(req->sconn)) {
3916 END_PROFILE(SMBwritebraw);
3917 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3918 "raw reads/writes are disallowed.");
3921 if (req->wct < 12) {
3922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3923 error_to_writebrawerr(req);
3924 END_PROFILE(SMBwritebraw);
3925 return;
3928 if (req->sconn->smb1.echo_handler.trusted_fde) {
3929 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3930 "'async smb echo handler = yes'\n"));
3931 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3932 error_to_writebrawerr(req);
3933 END_PROFILE(SMBwritebraw);
3934 return;
3937 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3938 if (!check_fsp(conn, req, fsp)) {
3939 error_to_writebrawerr(req);
3940 END_PROFILE(SMBwritebraw);
3941 return;
3944 if (!CHECK_WRITE(fsp)) {
3945 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3946 error_to_writebrawerr(req);
3947 END_PROFILE(SMBwritebraw);
3948 return;
3951 tcount = IVAL(req->vwv+1, 0);
3952 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3953 write_through = BITSETW(req->vwv+7,0);
3955 /* We have to deal with slightly different formats depending
3956 on whether we are using the core+ or lanman1.0 protocol */
3958 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3959 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3960 data = smb_buf(req->inbuf);
3961 } else {
3962 numtowrite = SVAL(req->vwv+10, 0);
3963 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3966 /* Ensure we don't write bytes past the end of this packet. */
3967 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3969 error_to_writebrawerr(req);
3970 END_PROFILE(SMBwritebraw);
3971 return;
3974 if (!fsp->print_file) {
3975 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3976 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3977 &lock);
3979 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3980 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3981 error_to_writebrawerr(req);
3982 END_PROFILE(SMBwritebraw);
3983 return;
3987 if (numtowrite>0) {
3988 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3991 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3992 "wrote=%d sync=%d\n",
3993 fsp->fnum, (double)startpos, (int)numtowrite,
3994 (int)nwritten, (int)write_through));
3996 if (nwritten < (ssize_t)numtowrite) {
3997 reply_nterror(req, NT_STATUS_DISK_FULL);
3998 error_to_writebrawerr(req);
3999 goto strict_unlock;
4002 total_written = nwritten;
4004 /* Allocate a buffer of 64k + length. */
4005 buf = TALLOC_ARRAY(NULL, char, 65540);
4006 if (!buf) {
4007 reply_nterror(req, NT_STATUS_NO_MEMORY);
4008 error_to_writebrawerr(req);
4009 goto strict_unlock;
4012 /* Return a SMBwritebraw message to the redirector to tell
4013 * it to send more bytes */
4015 memcpy(buf, req->inbuf, smb_size);
4016 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4017 SCVAL(buf,smb_com,SMBwritebraw);
4018 SSVALS(buf,smb_vwv0,0xFFFF);
4019 show_msg(buf);
4020 if (!srv_send_smb(req->sconn,
4021 buf,
4022 false, 0, /* no signing */
4023 IS_CONN_ENCRYPTED(conn),
4024 &req->pcd)) {
4025 exit_server_cleanly("reply_writebraw: srv_send_smb "
4026 "failed.");
4029 /* Now read the raw data into the buffer and write it */
4030 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4031 &numtowrite);
4032 if (!NT_STATUS_IS_OK(status)) {
4033 exit_server_cleanly("secondary writebraw failed");
4036 /* Set up outbuf to return the correct size */
4037 reply_outbuf(req, 1, 0);
4039 if (numtowrite != 0) {
4041 if (numtowrite > 0xFFFF) {
4042 DEBUG(0,("reply_writebraw: Oversize secondary write "
4043 "raw requested (%u). Terminating\n",
4044 (unsigned int)numtowrite ));
4045 exit_server_cleanly("secondary writebraw failed");
4048 if (tcount > nwritten+numtowrite) {
4049 DEBUG(3,("reply_writebraw: Client overestimated the "
4050 "write %d %d %d\n",
4051 (int)tcount,(int)nwritten,(int)numtowrite));
4054 status = read_data(req->sconn->sock, buf+4, numtowrite);
4056 if (!NT_STATUS_IS_OK(status)) {
4057 char addr[INET6_ADDRSTRLEN];
4058 /* Try and give an error message
4059 * saying what client failed. */
4060 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4061 "raw read failed (%s) for client %s. "
4062 "Terminating\n", nt_errstr(status),
4063 get_peer_addr(req->sconn->sock, addr,
4064 sizeof(addr))));
4065 exit_server_cleanly("secondary writebraw failed");
4068 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4069 if (nwritten == -1) {
4070 TALLOC_FREE(buf);
4071 reply_nterror(req, map_nt_error_from_unix(errno));
4072 error_to_writebrawerr(req);
4073 goto strict_unlock;
4076 if (nwritten < (ssize_t)numtowrite) {
4077 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4078 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4081 if (nwritten > 0) {
4082 total_written += nwritten;
4086 TALLOC_FREE(buf);
4087 SSVAL(req->outbuf,smb_vwv0,total_written);
4089 status = sync_file(conn, fsp, write_through);
4090 if (!NT_STATUS_IS_OK(status)) {
4091 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4092 fsp_str_dbg(fsp), nt_errstr(status)));
4093 reply_nterror(req, status);
4094 error_to_writebrawerr(req);
4095 goto strict_unlock;
4098 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4099 "wrote=%d\n",
4100 fsp->fnum, (double)startpos, (int)numtowrite,
4101 (int)total_written));
4103 if (!fsp->print_file) {
4104 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4107 /* We won't return a status if write through is not selected - this
4108 * follows what WfWg does */
4109 END_PROFILE(SMBwritebraw);
4111 if (!write_through && total_written==tcount) {
4113 #if RABBIT_PELLET_FIX
4115 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4116 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4117 * JRA.
4119 if (!send_keepalive(req->sconn->sock)) {
4120 exit_server_cleanly("reply_writebraw: send of "
4121 "keepalive failed");
4123 #endif
4124 TALLOC_FREE(req->outbuf);
4126 return;
4128 strict_unlock:
4129 if (!fsp->print_file) {
4130 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4133 END_PROFILE(SMBwritebraw);
4134 return;
4137 #undef DBGC_CLASS
4138 #define DBGC_CLASS DBGC_LOCKING
4140 /****************************************************************************
4141 Reply to a writeunlock (core+).
4142 ****************************************************************************/
4144 void reply_writeunlock(struct smb_request *req)
4146 connection_struct *conn = req->conn;
4147 ssize_t nwritten = -1;
4148 size_t numtowrite;
4149 SMB_OFF_T startpos;
4150 const char *data;
4151 NTSTATUS status = NT_STATUS_OK;
4152 files_struct *fsp;
4153 struct lock_struct lock;
4154 int saved_errno = 0;
4156 START_PROFILE(SMBwriteunlock);
4158 if (req->wct < 5) {
4159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4160 END_PROFILE(SMBwriteunlock);
4161 return;
4164 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4166 if (!check_fsp(conn, req, fsp)) {
4167 END_PROFILE(SMBwriteunlock);
4168 return;
4171 if (!CHECK_WRITE(fsp)) {
4172 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4173 END_PROFILE(SMBwriteunlock);
4174 return;
4177 numtowrite = SVAL(req->vwv+1, 0);
4178 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4179 data = (const char *)req->buf + 3;
4181 if (!fsp->print_file && numtowrite > 0) {
4182 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4183 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4184 &lock);
4186 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4187 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4188 END_PROFILE(SMBwriteunlock);
4189 return;
4193 /* The special X/Open SMB protocol handling of
4194 zero length writes is *NOT* done for
4195 this call */
4196 if(numtowrite == 0) {
4197 nwritten = 0;
4198 } else {
4199 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4200 saved_errno = errno;
4203 status = sync_file(conn, fsp, False /* write through */);
4204 if (!NT_STATUS_IS_OK(status)) {
4205 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4206 fsp_str_dbg(fsp), nt_errstr(status)));
4207 reply_nterror(req, status);
4208 goto strict_unlock;
4211 if(nwritten < 0) {
4212 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4213 goto strict_unlock;
4216 if((nwritten < numtowrite) && (numtowrite != 0)) {
4217 reply_nterror(req, NT_STATUS_DISK_FULL);
4218 goto strict_unlock;
4221 if (numtowrite && !fsp->print_file) {
4222 status = do_unlock(req->sconn->msg_ctx,
4223 fsp,
4224 (uint64_t)req->smbpid,
4225 (uint64_t)numtowrite,
4226 (uint64_t)startpos,
4227 WINDOWS_LOCK);
4229 if (NT_STATUS_V(status)) {
4230 reply_nterror(req, status);
4231 goto strict_unlock;
4235 reply_outbuf(req, 1, 0);
4237 SSVAL(req->outbuf,smb_vwv0,nwritten);
4239 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4240 fsp->fnum, (int)numtowrite, (int)nwritten));
4242 strict_unlock:
4243 if (numtowrite && !fsp->print_file) {
4244 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4247 END_PROFILE(SMBwriteunlock);
4248 return;
4251 #undef DBGC_CLASS
4252 #define DBGC_CLASS DBGC_ALL
4254 /****************************************************************************
4255 Reply to a write.
4256 ****************************************************************************/
4258 void reply_write(struct smb_request *req)
4260 connection_struct *conn = req->conn;
4261 size_t numtowrite;
4262 ssize_t nwritten = -1;
4263 SMB_OFF_T startpos;
4264 const char *data;
4265 files_struct *fsp;
4266 struct lock_struct lock;
4267 NTSTATUS status;
4268 int saved_errno = 0;
4270 START_PROFILE(SMBwrite);
4272 if (req->wct < 5) {
4273 END_PROFILE(SMBwrite);
4274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4275 return;
4278 /* If it's an IPC, pass off the pipe handler. */
4279 if (IS_IPC(conn)) {
4280 reply_pipe_write(req);
4281 END_PROFILE(SMBwrite);
4282 return;
4285 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4287 if (!check_fsp(conn, req, fsp)) {
4288 END_PROFILE(SMBwrite);
4289 return;
4292 if (!CHECK_WRITE(fsp)) {
4293 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4294 END_PROFILE(SMBwrite);
4295 return;
4298 numtowrite = SVAL(req->vwv+1, 0);
4299 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4300 data = (const char *)req->buf + 3;
4302 if (!fsp->print_file) {
4303 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4304 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4305 &lock);
4307 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4308 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4309 END_PROFILE(SMBwrite);
4310 return;
4315 * X/Open SMB protocol says that if smb_vwv1 is
4316 * zero then the file size should be extended or
4317 * truncated to the size given in smb_vwv[2-3].
4320 if(numtowrite == 0) {
4322 * This is actually an allocate call, and set EOF. JRA.
4324 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4325 if (nwritten < 0) {
4326 reply_nterror(req, NT_STATUS_DISK_FULL);
4327 goto strict_unlock;
4329 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4330 if (nwritten < 0) {
4331 reply_nterror(req, NT_STATUS_DISK_FULL);
4332 goto strict_unlock;
4334 trigger_write_time_update_immediate(fsp);
4335 } else {
4336 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4339 status = sync_file(conn, fsp, False);
4340 if (!NT_STATUS_IS_OK(status)) {
4341 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4342 fsp_str_dbg(fsp), nt_errstr(status)));
4343 reply_nterror(req, status);
4344 goto strict_unlock;
4347 if(nwritten < 0) {
4348 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4349 goto strict_unlock;
4352 if((nwritten == 0) && (numtowrite != 0)) {
4353 reply_nterror(req, NT_STATUS_DISK_FULL);
4354 goto strict_unlock;
4357 reply_outbuf(req, 1, 0);
4359 SSVAL(req->outbuf,smb_vwv0,nwritten);
4361 if (nwritten < (ssize_t)numtowrite) {
4362 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4363 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4366 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4368 strict_unlock:
4369 if (!fsp->print_file) {
4370 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4373 END_PROFILE(SMBwrite);
4374 return;
4377 /****************************************************************************
4378 Ensure a buffer is a valid writeX for recvfile purposes.
4379 ****************************************************************************/
4381 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4382 (2*14) + /* word count (including bcc) */ \
4383 1 /* pad byte */)
4385 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4386 const uint8_t *inbuf)
4388 size_t numtowrite;
4389 connection_struct *conn = NULL;
4390 unsigned int doff = 0;
4391 size_t len = smb_len_large(inbuf);
4393 if (is_encrypted_packet(inbuf)) {
4394 /* Can't do this on encrypted
4395 * connections. */
4396 return false;
4399 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4400 return false;
4403 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4404 CVAL(inbuf,smb_wct) != 14) {
4405 DEBUG(10,("is_valid_writeX_buffer: chained or "
4406 "invalid word length.\n"));
4407 return false;
4410 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4411 if (conn == NULL) {
4412 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4413 return false;
4415 if (IS_IPC(conn)) {
4416 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4417 return false;
4419 if (IS_PRINT(conn)) {
4420 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4421 return false;
4423 doff = SVAL(inbuf,smb_vwv11);
4425 numtowrite = SVAL(inbuf,smb_vwv10);
4427 if (len > doff && len - doff > 0xFFFF) {
4428 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4431 if (numtowrite == 0) {
4432 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4433 return false;
4436 /* Ensure the sizes match up. */
4437 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4438 /* no pad byte...old smbclient :-( */
4439 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4440 (unsigned int)doff,
4441 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4442 return false;
4445 if (len - doff != numtowrite) {
4446 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4447 "len = %u, doff = %u, numtowrite = %u\n",
4448 (unsigned int)len,
4449 (unsigned int)doff,
4450 (unsigned int)numtowrite ));
4451 return false;
4454 DEBUG(10,("is_valid_writeX_buffer: true "
4455 "len = %u, doff = %u, numtowrite = %u\n",
4456 (unsigned int)len,
4457 (unsigned int)doff,
4458 (unsigned int)numtowrite ));
4460 return true;
4463 /****************************************************************************
4464 Reply to a write and X.
4465 ****************************************************************************/
4467 void reply_write_and_X(struct smb_request *req)
4469 connection_struct *conn = req->conn;
4470 files_struct *fsp;
4471 struct lock_struct lock;
4472 SMB_OFF_T startpos;
4473 size_t numtowrite;
4474 bool write_through;
4475 ssize_t nwritten;
4476 unsigned int smb_doff;
4477 unsigned int smblen;
4478 char *data;
4479 NTSTATUS status;
4480 int saved_errno = 0;
4482 START_PROFILE(SMBwriteX);
4484 if ((req->wct != 12) && (req->wct != 14)) {
4485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4486 END_PROFILE(SMBwriteX);
4487 return;
4490 numtowrite = SVAL(req->vwv+10, 0);
4491 smb_doff = SVAL(req->vwv+11, 0);
4492 smblen = smb_len(req->inbuf);
4494 if (req->unread_bytes > 0xFFFF ||
4495 (smblen > smb_doff &&
4496 smblen - smb_doff > 0xFFFF)) {
4497 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4500 if (req->unread_bytes) {
4501 /* Can't do a recvfile write on IPC$ */
4502 if (IS_IPC(conn)) {
4503 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4504 END_PROFILE(SMBwriteX);
4505 return;
4507 if (numtowrite != req->unread_bytes) {
4508 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4509 END_PROFILE(SMBwriteX);
4510 return;
4512 } else {
4513 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4514 smb_doff + numtowrite > smblen) {
4515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4516 END_PROFILE(SMBwriteX);
4517 return;
4521 /* If it's an IPC, pass off the pipe handler. */
4522 if (IS_IPC(conn)) {
4523 if (req->unread_bytes) {
4524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4525 END_PROFILE(SMBwriteX);
4526 return;
4528 reply_pipe_write_and_X(req);
4529 END_PROFILE(SMBwriteX);
4530 return;
4533 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4534 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4535 write_through = BITSETW(req->vwv+7,0);
4537 if (!check_fsp(conn, req, fsp)) {
4538 END_PROFILE(SMBwriteX);
4539 return;
4542 if (!CHECK_WRITE(fsp)) {
4543 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4544 END_PROFILE(SMBwriteX);
4545 return;
4548 data = smb_base(req->inbuf) + smb_doff;
4550 if(req->wct == 14) {
4551 #ifdef LARGE_SMB_OFF_T
4553 * This is a large offset (64 bit) write.
4555 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4557 #else /* !LARGE_SMB_OFF_T */
4560 * Ensure we haven't been sent a >32 bit offset.
4563 if(IVAL(req->vwv+12, 0) != 0) {
4564 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4565 "used and we don't support 64 bit offsets.\n",
4566 (unsigned int)IVAL(req->vwv+12, 0) ));
4567 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4568 END_PROFILE(SMBwriteX);
4569 return;
4572 #endif /* LARGE_SMB_OFF_T */
4575 /* X/Open SMB protocol says that, unlike SMBwrite
4576 if the length is zero then NO truncation is
4577 done, just a write of zero. To truncate a file,
4578 use SMBwrite. */
4580 if(numtowrite == 0) {
4581 nwritten = 0;
4582 } else {
4583 if (req->unread_bytes == 0) {
4584 status = schedule_aio_write_and_X(conn,
4585 req,
4586 fsp,
4587 data,
4588 startpos,
4589 numtowrite);
4591 if (NT_STATUS_IS_OK(status)) {
4592 /* write scheduled - we're done. */
4593 goto out;
4595 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4596 /* Real error - report to client. */
4597 reply_nterror(req, status);
4598 goto out;
4600 /* NT_STATUS_RETRY - fall through to sync write. */
4603 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4604 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4605 &lock);
4607 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4608 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4609 goto out;
4612 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4613 saved_errno = errno;
4615 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4618 if(nwritten < 0) {
4619 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4620 goto out;
4623 if((nwritten == 0) && (numtowrite != 0)) {
4624 reply_nterror(req, NT_STATUS_DISK_FULL);
4625 goto out;
4628 reply_outbuf(req, 6, 0);
4629 SSVAL(req->outbuf,smb_vwv2,nwritten);
4630 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4632 if (nwritten < (ssize_t)numtowrite) {
4633 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4634 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4637 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4638 fsp->fnum, (int)numtowrite, (int)nwritten));
4640 status = sync_file(conn, fsp, write_through);
4641 if (!NT_STATUS_IS_OK(status)) {
4642 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4643 fsp_str_dbg(fsp), nt_errstr(status)));
4644 reply_nterror(req, status);
4645 goto out;
4648 END_PROFILE(SMBwriteX);
4649 chain_reply(req);
4650 return;
4652 out:
4653 END_PROFILE(SMBwriteX);
4654 return;
4657 /****************************************************************************
4658 Reply to a lseek.
4659 ****************************************************************************/
4661 void reply_lseek(struct smb_request *req)
4663 connection_struct *conn = req->conn;
4664 SMB_OFF_T startpos;
4665 SMB_OFF_T res= -1;
4666 int mode,umode;
4667 files_struct *fsp;
4669 START_PROFILE(SMBlseek);
4671 if (req->wct < 4) {
4672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4673 END_PROFILE(SMBlseek);
4674 return;
4677 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4679 if (!check_fsp(conn, req, fsp)) {
4680 return;
4683 flush_write_cache(fsp, SEEK_FLUSH);
4685 mode = SVAL(req->vwv+1, 0) & 3;
4686 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4687 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4689 switch (mode) {
4690 case 0:
4691 umode = SEEK_SET;
4692 res = startpos;
4693 break;
4694 case 1:
4695 umode = SEEK_CUR;
4696 res = fsp->fh->pos + startpos;
4697 break;
4698 case 2:
4699 umode = SEEK_END;
4700 break;
4701 default:
4702 umode = SEEK_SET;
4703 res = startpos;
4704 break;
4707 if (umode == SEEK_END) {
4708 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4709 if(errno == EINVAL) {
4710 SMB_OFF_T current_pos = startpos;
4712 if(fsp_stat(fsp) == -1) {
4713 reply_nterror(req,
4714 map_nt_error_from_unix(errno));
4715 END_PROFILE(SMBlseek);
4716 return;
4719 current_pos += fsp->fsp_name->st.st_ex_size;
4720 if(current_pos < 0)
4721 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4725 if(res == -1) {
4726 reply_nterror(req, map_nt_error_from_unix(errno));
4727 END_PROFILE(SMBlseek);
4728 return;
4732 fsp->fh->pos = res;
4734 reply_outbuf(req, 2, 0);
4735 SIVAL(req->outbuf,smb_vwv0,res);
4737 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4738 fsp->fnum, (double)startpos, (double)res, mode));
4740 END_PROFILE(SMBlseek);
4741 return;
4744 /****************************************************************************
4745 Reply to a flush.
4746 ****************************************************************************/
4748 void reply_flush(struct smb_request *req)
4750 connection_struct *conn = req->conn;
4751 uint16 fnum;
4752 files_struct *fsp;
4754 START_PROFILE(SMBflush);
4756 if (req->wct < 1) {
4757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4758 return;
4761 fnum = SVAL(req->vwv+0, 0);
4762 fsp = file_fsp(req, fnum);
4764 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4765 return;
4768 if (!fsp) {
4769 file_sync_all(conn);
4770 } else {
4771 NTSTATUS status = sync_file(conn, fsp, True);
4772 if (!NT_STATUS_IS_OK(status)) {
4773 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4774 fsp_str_dbg(fsp), nt_errstr(status)));
4775 reply_nterror(req, status);
4776 END_PROFILE(SMBflush);
4777 return;
4781 reply_outbuf(req, 0, 0);
4783 DEBUG(3,("flush\n"));
4784 END_PROFILE(SMBflush);
4785 return;
4788 /****************************************************************************
4789 Reply to a exit.
4790 conn POINTER CAN BE NULL HERE !
4791 ****************************************************************************/
4793 void reply_exit(struct smb_request *req)
4795 START_PROFILE(SMBexit);
4797 file_close_pid(req->sconn, req->smbpid, req->vuid);
4799 reply_outbuf(req, 0, 0);
4801 DEBUG(3,("exit\n"));
4803 END_PROFILE(SMBexit);
4804 return;
4807 /****************************************************************************
4808 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4809 ****************************************************************************/
4811 void reply_close(struct smb_request *req)
4813 connection_struct *conn = req->conn;
4814 NTSTATUS status = NT_STATUS_OK;
4815 files_struct *fsp = NULL;
4816 START_PROFILE(SMBclose);
4818 if (req->wct < 3) {
4819 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4820 END_PROFILE(SMBclose);
4821 return;
4824 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4827 * We can only use check_fsp if we know it's not a directory.
4830 if (!check_fsp_open(conn, req, fsp)) {
4831 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4832 END_PROFILE(SMBclose);
4833 return;
4836 if(fsp->is_directory) {
4838 * Special case - close NT SMB directory handle.
4840 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4841 status = close_file(req, fsp, NORMAL_CLOSE);
4842 } else {
4843 time_t t;
4845 * Close ordinary file.
4848 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4849 fsp->fh->fd, fsp->fnum,
4850 conn->num_files_open));
4853 * Take care of any time sent in the close.
4856 t = srv_make_unix_date3(req->vwv+1);
4857 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4860 * close_file() returns the unix errno if an error
4861 * was detected on close - normally this is due to
4862 * a disk full error. If not then it was probably an I/O error.
4865 status = close_file(req, fsp, NORMAL_CLOSE);
4868 if (!NT_STATUS_IS_OK(status)) {
4869 reply_nterror(req, status);
4870 END_PROFILE(SMBclose);
4871 return;
4874 reply_outbuf(req, 0, 0);
4875 END_PROFILE(SMBclose);
4876 return;
4879 /****************************************************************************
4880 Reply to a writeclose (Core+ protocol).
4881 ****************************************************************************/
4883 void reply_writeclose(struct smb_request *req)
4885 connection_struct *conn = req->conn;
4886 size_t numtowrite;
4887 ssize_t nwritten = -1;
4888 NTSTATUS close_status = NT_STATUS_OK;
4889 SMB_OFF_T startpos;
4890 const char *data;
4891 struct timespec mtime;
4892 files_struct *fsp;
4893 struct lock_struct lock;
4895 START_PROFILE(SMBwriteclose);
4897 if (req->wct < 6) {
4898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4899 END_PROFILE(SMBwriteclose);
4900 return;
4903 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4905 if (!check_fsp(conn, req, fsp)) {
4906 END_PROFILE(SMBwriteclose);
4907 return;
4909 if (!CHECK_WRITE(fsp)) {
4910 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4911 END_PROFILE(SMBwriteclose);
4912 return;
4915 numtowrite = SVAL(req->vwv+1, 0);
4916 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4917 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4918 data = (const char *)req->buf + 1;
4920 if (!fsp->print_file) {
4921 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4922 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4923 &lock);
4925 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4926 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4927 END_PROFILE(SMBwriteclose);
4928 return;
4932 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4934 set_close_write_time(fsp, mtime);
4937 * More insanity. W2K only closes the file if writelen > 0.
4938 * JRA.
4941 if (numtowrite) {
4942 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4943 "file %s\n", fsp_str_dbg(fsp)));
4944 close_status = close_file(req, fsp, NORMAL_CLOSE);
4947 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4948 fsp->fnum, (int)numtowrite, (int)nwritten,
4949 conn->num_files_open));
4951 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4952 reply_nterror(req, NT_STATUS_DISK_FULL);
4953 goto strict_unlock;
4956 if(!NT_STATUS_IS_OK(close_status)) {
4957 reply_nterror(req, close_status);
4958 goto strict_unlock;
4961 reply_outbuf(req, 1, 0);
4963 SSVAL(req->outbuf,smb_vwv0,nwritten);
4965 strict_unlock:
4966 if (numtowrite && !fsp->print_file) {
4967 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4970 END_PROFILE(SMBwriteclose);
4971 return;
4974 #undef DBGC_CLASS
4975 #define DBGC_CLASS DBGC_LOCKING
4977 /****************************************************************************
4978 Reply to a lock.
4979 ****************************************************************************/
4981 void reply_lock(struct smb_request *req)
4983 connection_struct *conn = req->conn;
4984 uint64_t count,offset;
4985 NTSTATUS status;
4986 files_struct *fsp;
4987 struct byte_range_lock *br_lck = NULL;
4989 START_PROFILE(SMBlock);
4991 if (req->wct < 5) {
4992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4993 END_PROFILE(SMBlock);
4994 return;
4997 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4999 if (!check_fsp(conn, req, fsp)) {
5000 END_PROFILE(SMBlock);
5001 return;
5004 count = (uint64_t)IVAL(req->vwv+1, 0);
5005 offset = (uint64_t)IVAL(req->vwv+3, 0);
5007 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5008 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5010 br_lck = do_lock(req->sconn->msg_ctx,
5011 fsp,
5012 (uint64_t)req->smbpid,
5013 count,
5014 offset,
5015 WRITE_LOCK,
5016 WINDOWS_LOCK,
5017 False, /* Non-blocking lock. */
5018 &status,
5019 NULL,
5020 NULL);
5022 TALLOC_FREE(br_lck);
5024 if (NT_STATUS_V(status)) {
5025 reply_nterror(req, status);
5026 END_PROFILE(SMBlock);
5027 return;
5030 reply_outbuf(req, 0, 0);
5032 END_PROFILE(SMBlock);
5033 return;
5036 /****************************************************************************
5037 Reply to a unlock.
5038 ****************************************************************************/
5040 void reply_unlock(struct smb_request *req)
5042 connection_struct *conn = req->conn;
5043 uint64_t count,offset;
5044 NTSTATUS status;
5045 files_struct *fsp;
5047 START_PROFILE(SMBunlock);
5049 if (req->wct < 5) {
5050 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5051 END_PROFILE(SMBunlock);
5052 return;
5055 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5057 if (!check_fsp(conn, req, fsp)) {
5058 END_PROFILE(SMBunlock);
5059 return;
5062 count = (uint64_t)IVAL(req->vwv+1, 0);
5063 offset = (uint64_t)IVAL(req->vwv+3, 0);
5065 status = do_unlock(req->sconn->msg_ctx,
5066 fsp,
5067 (uint64_t)req->smbpid,
5068 count,
5069 offset,
5070 WINDOWS_LOCK);
5072 if (NT_STATUS_V(status)) {
5073 reply_nterror(req, status);
5074 END_PROFILE(SMBunlock);
5075 return;
5078 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5079 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5081 reply_outbuf(req, 0, 0);
5083 END_PROFILE(SMBunlock);
5084 return;
5087 #undef DBGC_CLASS
5088 #define DBGC_CLASS DBGC_ALL
5090 /****************************************************************************
5091 Reply to a tdis.
5092 conn POINTER CAN BE NULL HERE !
5093 ****************************************************************************/
5095 void reply_tdis(struct smb_request *req)
5097 connection_struct *conn = req->conn;
5098 START_PROFILE(SMBtdis);
5100 if (!conn) {
5101 DEBUG(4,("Invalid connection in tdis\n"));
5102 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5103 END_PROFILE(SMBtdis);
5104 return;
5107 conn->used = False;
5109 close_cnum(conn,req->vuid);
5110 req->conn = NULL;
5112 reply_outbuf(req, 0, 0);
5113 END_PROFILE(SMBtdis);
5114 return;
5117 /****************************************************************************
5118 Reply to a echo.
5119 conn POINTER CAN BE NULL HERE !
5120 ****************************************************************************/
5122 void reply_echo(struct smb_request *req)
5124 connection_struct *conn = req->conn;
5125 struct smb_perfcount_data local_pcd;
5126 struct smb_perfcount_data *cur_pcd;
5127 int smb_reverb;
5128 int seq_num;
5130 START_PROFILE(SMBecho);
5132 smb_init_perfcount_data(&local_pcd);
5134 if (req->wct < 1) {
5135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5136 END_PROFILE(SMBecho);
5137 return;
5140 smb_reverb = SVAL(req->vwv+0, 0);
5142 reply_outbuf(req, 1, req->buflen);
5144 /* copy any incoming data back out */
5145 if (req->buflen > 0) {
5146 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5149 if (smb_reverb > 100) {
5150 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5151 smb_reverb = 100;
5154 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5156 /* this makes sure we catch the request pcd */
5157 if (seq_num == smb_reverb) {
5158 cur_pcd = &req->pcd;
5159 } else {
5160 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5161 cur_pcd = &local_pcd;
5164 SSVAL(req->outbuf,smb_vwv0,seq_num);
5166 show_msg((char *)req->outbuf);
5167 if (!srv_send_smb(req->sconn,
5168 (char *)req->outbuf,
5169 true, req->seqnum+1,
5170 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5171 cur_pcd))
5172 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5175 DEBUG(3,("echo %d times\n", smb_reverb));
5177 TALLOC_FREE(req->outbuf);
5179 END_PROFILE(SMBecho);
5180 return;
5183 /****************************************************************************
5184 Reply to a printopen.
5185 ****************************************************************************/
5187 void reply_printopen(struct smb_request *req)
5189 connection_struct *conn = req->conn;
5190 files_struct *fsp;
5191 NTSTATUS status;
5193 START_PROFILE(SMBsplopen);
5195 if (req->wct < 2) {
5196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5197 END_PROFILE(SMBsplopen);
5198 return;
5201 if (!CAN_PRINT(conn)) {
5202 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5203 END_PROFILE(SMBsplopen);
5204 return;
5207 status = file_new(req, conn, &fsp);
5208 if(!NT_STATUS_IS_OK(status)) {
5209 reply_nterror(req, status);
5210 END_PROFILE(SMBsplopen);
5211 return;
5214 /* Open for exclusive use, write only. */
5215 status = print_spool_open(fsp, NULL, req->vuid);
5217 if (!NT_STATUS_IS_OK(status)) {
5218 file_free(req, fsp);
5219 reply_nterror(req, status);
5220 END_PROFILE(SMBsplopen);
5221 return;
5224 reply_outbuf(req, 1, 0);
5225 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5227 DEBUG(3,("openprint fd=%d fnum=%d\n",
5228 fsp->fh->fd, fsp->fnum));
5230 END_PROFILE(SMBsplopen);
5231 return;
5234 /****************************************************************************
5235 Reply to a printclose.
5236 ****************************************************************************/
5238 void reply_printclose(struct smb_request *req)
5240 connection_struct *conn = req->conn;
5241 files_struct *fsp;
5242 NTSTATUS status;
5244 START_PROFILE(SMBsplclose);
5246 if (req->wct < 1) {
5247 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5248 END_PROFILE(SMBsplclose);
5249 return;
5252 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5254 if (!check_fsp(conn, req, fsp)) {
5255 END_PROFILE(SMBsplclose);
5256 return;
5259 if (!CAN_PRINT(conn)) {
5260 reply_force_doserror(req, ERRSRV, ERRerror);
5261 END_PROFILE(SMBsplclose);
5262 return;
5265 DEBUG(3,("printclose fd=%d fnum=%d\n",
5266 fsp->fh->fd,fsp->fnum));
5268 status = close_file(req, fsp, NORMAL_CLOSE);
5270 if(!NT_STATUS_IS_OK(status)) {
5271 reply_nterror(req, status);
5272 END_PROFILE(SMBsplclose);
5273 return;
5276 reply_outbuf(req, 0, 0);
5278 END_PROFILE(SMBsplclose);
5279 return;
5282 /****************************************************************************
5283 Reply to a printqueue.
5284 ****************************************************************************/
5286 void reply_printqueue(struct smb_request *req)
5288 connection_struct *conn = req->conn;
5289 int max_count;
5290 int start_index;
5292 START_PROFILE(SMBsplretq);
5294 if (req->wct < 2) {
5295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5296 END_PROFILE(SMBsplretq);
5297 return;
5300 max_count = SVAL(req->vwv+0, 0);
5301 start_index = SVAL(req->vwv+1, 0);
5303 /* we used to allow the client to get the cnum wrong, but that
5304 is really quite gross and only worked when there was only
5305 one printer - I think we should now only accept it if they
5306 get it right (tridge) */
5307 if (!CAN_PRINT(conn)) {
5308 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5309 END_PROFILE(SMBsplretq);
5310 return;
5313 reply_outbuf(req, 2, 3);
5314 SSVAL(req->outbuf,smb_vwv0,0);
5315 SSVAL(req->outbuf,smb_vwv1,0);
5316 SCVAL(smb_buf(req->outbuf),0,1);
5317 SSVAL(smb_buf(req->outbuf),1,0);
5319 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5320 start_index, max_count));
5323 TALLOC_CTX *mem_ctx = talloc_tos();
5324 NTSTATUS status;
5325 WERROR werr;
5326 const char *sharename = lp_servicename(SNUM(conn));
5327 struct rpc_pipe_client *cli = NULL;
5328 struct dcerpc_binding_handle *b = NULL;
5329 struct policy_handle handle;
5330 struct spoolss_DevmodeContainer devmode_ctr;
5331 union spoolss_JobInfo *info;
5332 uint32_t count;
5333 uint32_t num_to_get;
5334 uint32_t first;
5335 uint32_t i;
5337 ZERO_STRUCT(handle);
5339 status = rpc_pipe_open_interface(conn,
5340 &ndr_table_spoolss.syntax_id,
5341 conn->session_info,
5342 &conn->sconn->client_id,
5343 conn->sconn->msg_ctx,
5344 &cli);
5345 if (!NT_STATUS_IS_OK(status)) {
5346 DEBUG(0, ("reply_printqueue: "
5347 "could not connect to spoolss: %s\n",
5348 nt_errstr(status)));
5349 reply_nterror(req, status);
5350 goto out;
5352 b = cli->binding_handle;
5354 ZERO_STRUCT(devmode_ctr);
5356 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5357 sharename,
5358 NULL, devmode_ctr,
5359 SEC_FLAG_MAXIMUM_ALLOWED,
5360 &handle,
5361 &werr);
5362 if (!NT_STATUS_IS_OK(status)) {
5363 reply_nterror(req, status);
5364 goto out;
5366 if (!W_ERROR_IS_OK(werr)) {
5367 reply_nterror(req, werror_to_ntstatus(werr));
5368 goto out;
5371 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5372 &handle,
5373 0, /* firstjob */
5374 0xff, /* numjobs */
5375 2, /* level */
5376 0, /* offered */
5377 &count,
5378 &info);
5379 if (!W_ERROR_IS_OK(werr)) {
5380 reply_nterror(req, werror_to_ntstatus(werr));
5381 goto out;
5384 if (max_count > 0) {
5385 first = start_index;
5386 } else {
5387 first = start_index + max_count + 1;
5390 if (first >= count) {
5391 num_to_get = first;
5392 } else {
5393 num_to_get = first + MIN(ABS(max_count), count - first);
5396 for (i = first; i < num_to_get; i++) {
5397 char blob[28];
5398 char *p = blob;
5399 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5400 int qstatus;
5401 uint16_t qrapjobid = pjobid_to_rap(sharename,
5402 info[i].info2.job_id);
5404 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5405 qstatus = 2;
5406 } else {
5407 qstatus = 3;
5410 srv_put_dos_date2(p, 0, qtime);
5411 SCVAL(p, 4, qstatus);
5412 SSVAL(p, 5, qrapjobid);
5413 SIVAL(p, 7, info[i].info2.size);
5414 SCVAL(p, 11, 0);
5415 srvstr_push(blob, req->flags2, p+12,
5416 info[i].info2.notify_name, 16, STR_ASCII);
5418 if (message_push_blob(
5419 &req->outbuf,
5420 data_blob_const(
5421 blob, sizeof(blob))) == -1) {
5422 reply_nterror(req, NT_STATUS_NO_MEMORY);
5423 goto out;
5427 if (count > 0) {
5428 SSVAL(req->outbuf,smb_vwv0,count);
5429 SSVAL(req->outbuf,smb_vwv1,
5430 (max_count>0?first+count:first-1));
5431 SCVAL(smb_buf(req->outbuf),0,1);
5432 SSVAL(smb_buf(req->outbuf),1,28*count);
5436 DEBUG(3, ("%u entries returned in queue\n",
5437 (unsigned)count));
5439 out:
5440 if (b && is_valid_policy_hnd(&handle)) {
5441 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5446 END_PROFILE(SMBsplretq);
5447 return;
5450 /****************************************************************************
5451 Reply to a printwrite.
5452 ****************************************************************************/
5454 void reply_printwrite(struct smb_request *req)
5456 connection_struct *conn = req->conn;
5457 int numtowrite;
5458 const char *data;
5459 files_struct *fsp;
5461 START_PROFILE(SMBsplwr);
5463 if (req->wct < 1) {
5464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5465 END_PROFILE(SMBsplwr);
5466 return;
5469 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5471 if (!check_fsp(conn, req, fsp)) {
5472 END_PROFILE(SMBsplwr);
5473 return;
5476 if (!fsp->print_file) {
5477 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5478 END_PROFILE(SMBsplwr);
5479 return;
5482 if (!CHECK_WRITE(fsp)) {
5483 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5484 END_PROFILE(SMBsplwr);
5485 return;
5488 numtowrite = SVAL(req->buf, 1);
5490 if (req->buflen < numtowrite + 3) {
5491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5492 END_PROFILE(SMBsplwr);
5493 return;
5496 data = (const char *)req->buf + 3;
5498 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5499 reply_nterror(req, map_nt_error_from_unix(errno));
5500 END_PROFILE(SMBsplwr);
5501 return;
5504 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5506 END_PROFILE(SMBsplwr);
5507 return;
5510 /****************************************************************************
5511 Reply to a mkdir.
5512 ****************************************************************************/
5514 void reply_mkdir(struct smb_request *req)
5516 connection_struct *conn = req->conn;
5517 struct smb_filename *smb_dname = NULL;
5518 char *directory = NULL;
5519 NTSTATUS status;
5520 TALLOC_CTX *ctx = talloc_tos();
5522 START_PROFILE(SMBmkdir);
5524 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5525 STR_TERMINATE, &status);
5526 if (!NT_STATUS_IS_OK(status)) {
5527 reply_nterror(req, status);
5528 goto out;
5531 status = filename_convert(ctx, conn,
5532 req->flags2 & FLAGS2_DFS_PATHNAMES,
5533 directory,
5535 NULL,
5536 &smb_dname);
5537 if (!NT_STATUS_IS_OK(status)) {
5538 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5539 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5540 ERRSRV, ERRbadpath);
5541 goto out;
5543 reply_nterror(req, status);
5544 goto out;
5547 status = create_directory(conn, req, smb_dname);
5549 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5551 if (!NT_STATUS_IS_OK(status)) {
5553 if (!use_nt_status()
5554 && NT_STATUS_EQUAL(status,
5555 NT_STATUS_OBJECT_NAME_COLLISION)) {
5557 * Yes, in the DOS error code case we get a
5558 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5559 * samba4 torture test.
5561 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5564 reply_nterror(req, status);
5565 goto out;
5568 reply_outbuf(req, 0, 0);
5570 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5571 out:
5572 TALLOC_FREE(smb_dname);
5573 END_PROFILE(SMBmkdir);
5574 return;
5577 /****************************************************************************
5578 Reply to a rmdir.
5579 ****************************************************************************/
5581 void reply_rmdir(struct smb_request *req)
5583 connection_struct *conn = req->conn;
5584 struct smb_filename *smb_dname = NULL;
5585 char *directory = NULL;
5586 NTSTATUS status;
5587 TALLOC_CTX *ctx = talloc_tos();
5588 files_struct *fsp = NULL;
5589 int info = 0;
5590 struct smbd_server_connection *sconn = req->sconn;
5592 START_PROFILE(SMBrmdir);
5594 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5595 STR_TERMINATE, &status);
5596 if (!NT_STATUS_IS_OK(status)) {
5597 reply_nterror(req, status);
5598 goto out;
5601 status = filename_convert(ctx, conn,
5602 req->flags2 & FLAGS2_DFS_PATHNAMES,
5603 directory,
5605 NULL,
5606 &smb_dname);
5607 if (!NT_STATUS_IS_OK(status)) {
5608 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5609 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5610 ERRSRV, ERRbadpath);
5611 goto out;
5613 reply_nterror(req, status);
5614 goto out;
5617 if (is_ntfs_stream_smb_fname(smb_dname)) {
5618 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5619 goto out;
5622 status = SMB_VFS_CREATE_FILE(
5623 conn, /* conn */
5624 req, /* req */
5625 0, /* root_dir_fid */
5626 smb_dname, /* fname */
5627 DELETE_ACCESS, /* access_mask */
5628 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5629 FILE_SHARE_DELETE),
5630 FILE_OPEN, /* create_disposition*/
5631 FILE_DIRECTORY_FILE, /* create_options */
5632 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5633 0, /* oplock_request */
5634 0, /* allocation_size */
5635 0, /* private_flags */
5636 NULL, /* sd */
5637 NULL, /* ea_list */
5638 &fsp, /* result */
5639 &info); /* pinfo */
5641 if (!NT_STATUS_IS_OK(status)) {
5642 if (open_was_deferred(req->mid)) {
5643 /* We have re-scheduled this call. */
5644 goto out;
5646 reply_nterror(req, status);
5647 goto out;
5650 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5651 if (!NT_STATUS_IS_OK(status)) {
5652 close_file(req, fsp, ERROR_CLOSE);
5653 reply_nterror(req, status);
5654 goto out;
5657 if (!set_delete_on_close(fsp, true, &conn->session_info->utok)) {
5658 close_file(req, fsp, ERROR_CLOSE);
5659 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5660 goto out;
5663 status = close_file(req, fsp, NORMAL_CLOSE);
5664 if (!NT_STATUS_IS_OK(status)) {
5665 reply_nterror(req, status);
5666 } else {
5667 reply_outbuf(req, 0, 0);
5670 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5672 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5673 out:
5674 TALLOC_FREE(smb_dname);
5675 END_PROFILE(SMBrmdir);
5676 return;
5679 /*******************************************************************
5680 Resolve wildcards in a filename rename.
5681 ********************************************************************/
5683 static bool resolve_wildcards(TALLOC_CTX *ctx,
5684 const char *name1,
5685 const char *name2,
5686 char **pp_newname)
5688 char *name2_copy = NULL;
5689 char *root1 = NULL;
5690 char *root2 = NULL;
5691 char *ext1 = NULL;
5692 char *ext2 = NULL;
5693 char *p,*p2, *pname1, *pname2;
5695 name2_copy = talloc_strdup(ctx, name2);
5696 if (!name2_copy) {
5697 return False;
5700 pname1 = strrchr_m(name1,'/');
5701 pname2 = strrchr_m(name2_copy,'/');
5703 if (!pname1 || !pname2) {
5704 return False;
5707 /* Truncate the copy of name2 at the last '/' */
5708 *pname2 = '\0';
5710 /* Now go past the '/' */
5711 pname1++;
5712 pname2++;
5714 root1 = talloc_strdup(ctx, pname1);
5715 root2 = talloc_strdup(ctx, pname2);
5717 if (!root1 || !root2) {
5718 return False;
5721 p = strrchr_m(root1,'.');
5722 if (p) {
5723 *p = 0;
5724 ext1 = talloc_strdup(ctx, p+1);
5725 } else {
5726 ext1 = talloc_strdup(ctx, "");
5728 p = strrchr_m(root2,'.');
5729 if (p) {
5730 *p = 0;
5731 ext2 = talloc_strdup(ctx, p+1);
5732 } else {
5733 ext2 = talloc_strdup(ctx, "");
5736 if (!ext1 || !ext2) {
5737 return False;
5740 p = root1;
5741 p2 = root2;
5742 while (*p2) {
5743 if (*p2 == '?') {
5744 /* Hmmm. Should this be mb-aware ? */
5745 *p2 = *p;
5746 p2++;
5747 } else if (*p2 == '*') {
5748 *p2 = '\0';
5749 root2 = talloc_asprintf(ctx, "%s%s",
5750 root2,
5752 if (!root2) {
5753 return False;
5755 break;
5756 } else {
5757 p2++;
5759 if (*p) {
5760 p++;
5764 p = ext1;
5765 p2 = ext2;
5766 while (*p2) {
5767 if (*p2 == '?') {
5768 /* Hmmm. Should this be mb-aware ? */
5769 *p2 = *p;
5770 p2++;
5771 } else if (*p2 == '*') {
5772 *p2 = '\0';
5773 ext2 = talloc_asprintf(ctx, "%s%s",
5774 ext2,
5776 if (!ext2) {
5777 return False;
5779 break;
5780 } else {
5781 p2++;
5783 if (*p) {
5784 p++;
5788 if (*ext2) {
5789 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5790 name2_copy,
5791 root2,
5792 ext2);
5793 } else {
5794 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5795 name2_copy,
5796 root2);
5799 if (!*pp_newname) {
5800 return False;
5803 return True;
5806 /****************************************************************************
5807 Ensure open files have their names updated. Updated to notify other smbd's
5808 asynchronously.
5809 ****************************************************************************/
5811 static void rename_open_files(connection_struct *conn,
5812 struct share_mode_lock *lck,
5813 uint32_t orig_name_hash,
5814 const struct smb_filename *smb_fname_dst)
5816 files_struct *fsp;
5817 bool did_rename = False;
5818 NTSTATUS status;
5819 uint32_t new_name_hash;
5821 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5822 fsp = file_find_di_next(fsp)) {
5823 /* fsp_name is a relative path under the fsp. To change this for other
5824 sharepaths we need to manipulate relative paths. */
5825 /* TODO - create the absolute path and manipulate the newname
5826 relative to the sharepath. */
5827 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5828 continue;
5830 if (fsp->name_hash != orig_name_hash) {
5831 continue;
5833 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5834 "(file_id %s) from %s -> %s\n", fsp->fnum,
5835 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5836 smb_fname_str_dbg(smb_fname_dst)));
5838 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5839 if (NT_STATUS_IS_OK(status)) {
5840 did_rename = True;
5841 new_name_hash = fsp->name_hash;
5845 if (!did_rename) {
5846 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5847 "for %s\n", file_id_string_tos(&lck->id),
5848 smb_fname_str_dbg(smb_fname_dst)));
5851 /* Send messages to all smbd's (not ourself) that the name has changed. */
5852 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5853 orig_name_hash, new_name_hash,
5854 smb_fname_dst);
5858 /****************************************************************************
5859 We need to check if the source path is a parent directory of the destination
5860 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5861 refuse the rename with a sharing violation. Under UNIX the above call can
5862 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5863 probably need to check that the client is a Windows one before disallowing
5864 this as a UNIX client (one with UNIX extensions) can know the source is a
5865 symlink and make this decision intelligently. Found by an excellent bug
5866 report from <AndyLiebman@aol.com>.
5867 ****************************************************************************/
5869 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5870 const struct smb_filename *smb_fname_dst)
5872 const char *psrc = smb_fname_src->base_name;
5873 const char *pdst = smb_fname_dst->base_name;
5874 size_t slen;
5876 if (psrc[0] == '.' && psrc[1] == '/') {
5877 psrc += 2;
5879 if (pdst[0] == '.' && pdst[1] == '/') {
5880 pdst += 2;
5882 if ((slen = strlen(psrc)) > strlen(pdst)) {
5883 return False;
5885 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5889 * Do the notify calls from a rename
5892 static void notify_rename(connection_struct *conn, bool is_dir,
5893 const struct smb_filename *smb_fname_src,
5894 const struct smb_filename *smb_fname_dst)
5896 char *parent_dir_src = NULL;
5897 char *parent_dir_dst = NULL;
5898 uint32 mask;
5900 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5901 : FILE_NOTIFY_CHANGE_FILE_NAME;
5903 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5904 &parent_dir_src, NULL) ||
5905 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5906 &parent_dir_dst, NULL)) {
5907 goto out;
5910 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5911 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5912 smb_fname_src->base_name);
5913 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5914 smb_fname_dst->base_name);
5916 else {
5917 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5918 smb_fname_src->base_name);
5919 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5920 smb_fname_dst->base_name);
5923 /* this is a strange one. w2k3 gives an additional event for
5924 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5925 files, but not directories */
5926 if (!is_dir) {
5927 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5928 FILE_NOTIFY_CHANGE_ATTRIBUTES
5929 |FILE_NOTIFY_CHANGE_CREATION,
5930 smb_fname_dst->base_name);
5932 out:
5933 TALLOC_FREE(parent_dir_src);
5934 TALLOC_FREE(parent_dir_dst);
5937 /****************************************************************************
5938 Rename an open file - given an fsp.
5939 ****************************************************************************/
5941 NTSTATUS rename_internals_fsp(connection_struct *conn,
5942 files_struct *fsp,
5943 const struct smb_filename *smb_fname_dst_in,
5944 uint32 attrs,
5945 bool replace_if_exists)
5947 TALLOC_CTX *ctx = talloc_tos();
5948 struct smb_filename *smb_fname_dst = NULL;
5949 NTSTATUS status = NT_STATUS_OK;
5950 struct share_mode_lock *lck = NULL;
5951 bool dst_exists, old_is_stream, new_is_stream;
5953 status = check_name(conn, smb_fname_dst_in->base_name);
5954 if (!NT_STATUS_IS_OK(status)) {
5955 return status;
5958 /* Make a copy of the dst smb_fname structs */
5960 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5961 if (!NT_STATUS_IS_OK(status)) {
5962 goto out;
5966 * Check for special case with case preserving and not
5967 * case sensitive. If the old last component differs from the original
5968 * last component only by case, then we should allow
5969 * the rename (user is trying to change the case of the
5970 * filename).
5972 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5973 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5974 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5975 char *last_slash;
5976 char *fname_dst_lcomp_base_mod = NULL;
5977 struct smb_filename *smb_fname_orig_lcomp = NULL;
5980 * Get the last component of the destination name.
5982 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5983 if (last_slash) {
5984 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5985 } else {
5986 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
5988 if (!fname_dst_lcomp_base_mod) {
5989 status = NT_STATUS_NO_MEMORY;
5990 goto out;
5994 * Create an smb_filename struct using the original last
5995 * component of the destination.
5997 status = create_synthetic_smb_fname_split(ctx,
5998 smb_fname_dst->original_lcomp, NULL,
5999 &smb_fname_orig_lcomp);
6000 if (!NT_STATUS_IS_OK(status)) {
6001 TALLOC_FREE(fname_dst_lcomp_base_mod);
6002 goto out;
6005 /* If the base names only differ by case, use original. */
6006 if(!strcsequal(fname_dst_lcomp_base_mod,
6007 smb_fname_orig_lcomp->base_name)) {
6008 char *tmp;
6010 * Replace the modified last component with the
6011 * original.
6013 if (last_slash) {
6014 *last_slash = '\0'; /* Truncate at the '/' */
6015 tmp = talloc_asprintf(smb_fname_dst,
6016 "%s/%s",
6017 smb_fname_dst->base_name,
6018 smb_fname_orig_lcomp->base_name);
6019 } else {
6020 tmp = talloc_asprintf(smb_fname_dst,
6021 "%s",
6022 smb_fname_orig_lcomp->base_name);
6024 if (tmp == NULL) {
6025 status = NT_STATUS_NO_MEMORY;
6026 TALLOC_FREE(fname_dst_lcomp_base_mod);
6027 TALLOC_FREE(smb_fname_orig_lcomp);
6028 goto out;
6030 TALLOC_FREE(smb_fname_dst->base_name);
6031 smb_fname_dst->base_name = tmp;
6034 /* If the stream_names only differ by case, use original. */
6035 if(!strcsequal(smb_fname_dst->stream_name,
6036 smb_fname_orig_lcomp->stream_name)) {
6037 char *tmp = NULL;
6038 /* Use the original stream. */
6039 tmp = talloc_strdup(smb_fname_dst,
6040 smb_fname_orig_lcomp->stream_name);
6041 if (tmp == NULL) {
6042 status = NT_STATUS_NO_MEMORY;
6043 TALLOC_FREE(fname_dst_lcomp_base_mod);
6044 TALLOC_FREE(smb_fname_orig_lcomp);
6045 goto out;
6047 TALLOC_FREE(smb_fname_dst->stream_name);
6048 smb_fname_dst->stream_name = tmp;
6050 TALLOC_FREE(fname_dst_lcomp_base_mod);
6051 TALLOC_FREE(smb_fname_orig_lcomp);
6055 * If the src and dest names are identical - including case,
6056 * don't do the rename, just return success.
6059 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6060 strcsequal(fsp->fsp_name->stream_name,
6061 smb_fname_dst->stream_name)) {
6062 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6063 "- returning success\n",
6064 smb_fname_str_dbg(smb_fname_dst)));
6065 status = NT_STATUS_OK;
6066 goto out;
6069 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6070 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6072 /* Return the correct error code if both names aren't streams. */
6073 if (!old_is_stream && new_is_stream) {
6074 status = NT_STATUS_OBJECT_NAME_INVALID;
6075 goto out;
6078 if (old_is_stream && !new_is_stream) {
6079 status = NT_STATUS_INVALID_PARAMETER;
6080 goto out;
6083 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6085 if(!replace_if_exists && dst_exists) {
6086 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6087 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6088 smb_fname_str_dbg(smb_fname_dst)));
6089 status = NT_STATUS_OBJECT_NAME_COLLISION;
6090 goto out;
6093 if (dst_exists) {
6094 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6095 &smb_fname_dst->st);
6096 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6097 fileid);
6098 /* The file can be open when renaming a stream */
6099 if (dst_fsp && !new_is_stream) {
6100 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6101 status = NT_STATUS_ACCESS_DENIED;
6102 goto out;
6106 /* Ensure we have a valid stat struct for the source. */
6107 status = vfs_stat_fsp(fsp);
6108 if (!NT_STATUS_IS_OK(status)) {
6109 goto out;
6112 status = can_rename(conn, fsp, attrs);
6114 if (!NT_STATUS_IS_OK(status)) {
6115 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6116 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6117 smb_fname_str_dbg(smb_fname_dst)));
6118 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6119 status = NT_STATUS_ACCESS_DENIED;
6120 goto out;
6123 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6124 status = NT_STATUS_ACCESS_DENIED;
6127 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6128 NULL);
6131 * We have the file open ourselves, so not being able to get the
6132 * corresponding share mode lock is a fatal error.
6135 SMB_ASSERT(lck != NULL);
6137 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6138 uint32 create_options = fsp->fh->private_options;
6140 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6141 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6142 smb_fname_str_dbg(smb_fname_dst)));
6144 if (!lp_posix_pathnames() &&
6145 (lp_map_archive(SNUM(conn)) ||
6146 lp_store_dos_attributes(SNUM(conn)))) {
6147 /* We must set the archive bit on the newly
6148 renamed file. */
6149 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6150 uint32_t old_dosmode = dos_mode(conn,
6151 smb_fname_dst);
6152 file_set_dosmode(conn,
6153 smb_fname_dst,
6154 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6155 NULL,
6156 true);
6160 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6161 smb_fname_dst);
6163 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6166 * A rename acts as a new file create w.r.t. allowing an initial delete
6167 * on close, probably because in Windows there is a new handle to the
6168 * new file. If initial delete on close was requested but not
6169 * originally set, we need to set it here. This is probably not 100% correct,
6170 * but will work for the CIFSFS client which in non-posix mode
6171 * depends on these semantics. JRA.
6174 if (create_options & FILE_DELETE_ON_CLOSE) {
6175 status = can_set_delete_on_close(fsp, 0);
6177 if (NT_STATUS_IS_OK(status)) {
6178 /* Note that here we set the *inital* delete on close flag,
6179 * not the regular one. The magic gets handled in close. */
6180 fsp->initial_delete_on_close = True;
6183 TALLOC_FREE(lck);
6184 status = NT_STATUS_OK;
6185 goto out;
6188 TALLOC_FREE(lck);
6190 if (errno == ENOTDIR || errno == EISDIR) {
6191 status = NT_STATUS_OBJECT_NAME_COLLISION;
6192 } else {
6193 status = map_nt_error_from_unix(errno);
6196 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6197 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6198 smb_fname_str_dbg(smb_fname_dst)));
6200 out:
6201 TALLOC_FREE(smb_fname_dst);
6203 return status;
6206 /****************************************************************************
6207 The guts of the rename command, split out so it may be called by the NT SMB
6208 code.
6209 ****************************************************************************/
6211 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6212 connection_struct *conn,
6213 struct smb_request *req,
6214 struct smb_filename *smb_fname_src,
6215 struct smb_filename *smb_fname_dst,
6216 uint32 attrs,
6217 bool replace_if_exists,
6218 bool src_has_wild,
6219 bool dest_has_wild,
6220 uint32_t access_mask)
6222 char *fname_src_dir = NULL;
6223 char *fname_src_mask = NULL;
6224 int count=0;
6225 NTSTATUS status = NT_STATUS_OK;
6226 struct smb_Dir *dir_hnd = NULL;
6227 const char *dname = NULL;
6228 char *talloced = NULL;
6229 long offset = 0;
6230 int create_options = 0;
6231 bool posix_pathnames = lp_posix_pathnames();
6234 * Split the old name into directory and last component
6235 * strings. Note that unix_convert may have stripped off a
6236 * leading ./ from both name and newname if the rename is
6237 * at the root of the share. We need to make sure either both
6238 * name and newname contain a / character or neither of them do
6239 * as this is checked in resolve_wildcards().
6242 /* Split up the directory from the filename/mask. */
6243 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6244 &fname_src_dir, &fname_src_mask);
6245 if (!NT_STATUS_IS_OK(status)) {
6246 status = NT_STATUS_NO_MEMORY;
6247 goto out;
6251 * We should only check the mangled cache
6252 * here if unix_convert failed. This means
6253 * that the path in 'mask' doesn't exist
6254 * on the file system and so we need to look
6255 * for a possible mangle. This patch from
6256 * Tine Smukavec <valentin.smukavec@hermes.si>.
6259 if (!VALID_STAT(smb_fname_src->st) &&
6260 mangle_is_mangled(fname_src_mask, conn->params)) {
6261 char *new_mask = NULL;
6262 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6263 conn->params);
6264 if (new_mask) {
6265 TALLOC_FREE(fname_src_mask);
6266 fname_src_mask = new_mask;
6270 if (!src_has_wild) {
6271 files_struct *fsp;
6274 * Only one file needs to be renamed. Append the mask back
6275 * onto the directory.
6277 TALLOC_FREE(smb_fname_src->base_name);
6278 if (ISDOT(fname_src_dir)) {
6279 /* Ensure we use canonical names on open. */
6280 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6281 "%s",
6282 fname_src_mask);
6283 } else {
6284 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6285 "%s/%s",
6286 fname_src_dir,
6287 fname_src_mask);
6289 if (!smb_fname_src->base_name) {
6290 status = NT_STATUS_NO_MEMORY;
6291 goto out;
6294 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6295 "case_preserve = %d, short case preserve = %d, "
6296 "directory = %s, newname = %s, "
6297 "last_component_dest = %s\n",
6298 conn->case_sensitive, conn->case_preserve,
6299 conn->short_case_preserve,
6300 smb_fname_str_dbg(smb_fname_src),
6301 smb_fname_str_dbg(smb_fname_dst),
6302 smb_fname_dst->original_lcomp));
6304 /* The dest name still may have wildcards. */
6305 if (dest_has_wild) {
6306 char *fname_dst_mod = NULL;
6307 if (!resolve_wildcards(smb_fname_dst,
6308 smb_fname_src->base_name,
6309 smb_fname_dst->base_name,
6310 &fname_dst_mod)) {
6311 DEBUG(6, ("rename_internals: resolve_wildcards "
6312 "%s %s failed\n",
6313 smb_fname_src->base_name,
6314 smb_fname_dst->base_name));
6315 status = NT_STATUS_NO_MEMORY;
6316 goto out;
6318 TALLOC_FREE(smb_fname_dst->base_name);
6319 smb_fname_dst->base_name = fname_dst_mod;
6322 ZERO_STRUCT(smb_fname_src->st);
6323 if (posix_pathnames) {
6324 SMB_VFS_LSTAT(conn, smb_fname_src);
6325 } else {
6326 SMB_VFS_STAT(conn, smb_fname_src);
6329 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6330 create_options |= FILE_DIRECTORY_FILE;
6333 status = SMB_VFS_CREATE_FILE(
6334 conn, /* conn */
6335 req, /* req */
6336 0, /* root_dir_fid */
6337 smb_fname_src, /* fname */
6338 access_mask, /* access_mask */
6339 (FILE_SHARE_READ | /* share_access */
6340 FILE_SHARE_WRITE),
6341 FILE_OPEN, /* create_disposition*/
6342 create_options, /* create_options */
6343 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6344 0, /* oplock_request */
6345 0, /* allocation_size */
6346 0, /* private_flags */
6347 NULL, /* sd */
6348 NULL, /* ea_list */
6349 &fsp, /* result */
6350 NULL); /* pinfo */
6352 if (!NT_STATUS_IS_OK(status)) {
6353 DEBUG(3, ("Could not open rename source %s: %s\n",
6354 smb_fname_str_dbg(smb_fname_src),
6355 nt_errstr(status)));
6356 goto out;
6359 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6360 attrs, replace_if_exists);
6362 close_file(req, fsp, NORMAL_CLOSE);
6364 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6365 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6366 smb_fname_str_dbg(smb_fname_dst)));
6368 goto out;
6372 * Wildcards - process each file that matches.
6374 if (strequal(fname_src_mask, "????????.???")) {
6375 TALLOC_FREE(fname_src_mask);
6376 fname_src_mask = talloc_strdup(ctx, "*");
6377 if (!fname_src_mask) {
6378 status = NT_STATUS_NO_MEMORY;
6379 goto out;
6383 status = check_name(conn, fname_src_dir);
6384 if (!NT_STATUS_IS_OK(status)) {
6385 goto out;
6388 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6389 attrs);
6390 if (dir_hnd == NULL) {
6391 status = map_nt_error_from_unix(errno);
6392 goto out;
6395 status = NT_STATUS_NO_SUCH_FILE;
6397 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6398 * - gentest fix. JRA
6401 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6402 &talloced))) {
6403 files_struct *fsp = NULL;
6404 char *destname = NULL;
6405 bool sysdir_entry = False;
6407 /* Quick check for "." and ".." */
6408 if (ISDOT(dname) || ISDOTDOT(dname)) {
6409 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6410 sysdir_entry = True;
6411 } else {
6412 TALLOC_FREE(talloced);
6413 continue;
6417 if (!is_visible_file(conn, fname_src_dir, dname,
6418 &smb_fname_src->st, false)) {
6419 TALLOC_FREE(talloced);
6420 continue;
6423 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6424 TALLOC_FREE(talloced);
6425 continue;
6428 if (sysdir_entry) {
6429 status = NT_STATUS_OBJECT_NAME_INVALID;
6430 break;
6433 TALLOC_FREE(smb_fname_src->base_name);
6434 if (ISDOT(fname_src_dir)) {
6435 /* Ensure we use canonical names on open. */
6436 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6437 "%s",
6438 dname);
6439 } else {
6440 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6441 "%s/%s",
6442 fname_src_dir,
6443 dname);
6445 if (!smb_fname_src->base_name) {
6446 status = NT_STATUS_NO_MEMORY;
6447 goto out;
6450 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6451 smb_fname_dst->base_name,
6452 &destname)) {
6453 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6454 smb_fname_src->base_name, destname));
6455 TALLOC_FREE(talloced);
6456 continue;
6458 if (!destname) {
6459 status = NT_STATUS_NO_MEMORY;
6460 goto out;
6463 TALLOC_FREE(smb_fname_dst->base_name);
6464 smb_fname_dst->base_name = destname;
6466 ZERO_STRUCT(smb_fname_src->st);
6467 if (posix_pathnames) {
6468 SMB_VFS_LSTAT(conn, smb_fname_src);
6469 } else {
6470 SMB_VFS_STAT(conn, smb_fname_src);
6473 create_options = 0;
6475 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6476 create_options |= FILE_DIRECTORY_FILE;
6479 status = SMB_VFS_CREATE_FILE(
6480 conn, /* conn */
6481 req, /* req */
6482 0, /* root_dir_fid */
6483 smb_fname_src, /* fname */
6484 access_mask, /* access_mask */
6485 (FILE_SHARE_READ | /* share_access */
6486 FILE_SHARE_WRITE),
6487 FILE_OPEN, /* create_disposition*/
6488 create_options, /* create_options */
6489 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6490 0, /* oplock_request */
6491 0, /* allocation_size */
6492 0, /* private_flags */
6493 NULL, /* sd */
6494 NULL, /* ea_list */
6495 &fsp, /* result */
6496 NULL); /* pinfo */
6498 if (!NT_STATUS_IS_OK(status)) {
6499 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6500 "returned %s rename %s -> %s\n",
6501 nt_errstr(status),
6502 smb_fname_str_dbg(smb_fname_src),
6503 smb_fname_str_dbg(smb_fname_dst)));
6504 break;
6507 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6508 dname);
6509 if (!smb_fname_dst->original_lcomp) {
6510 status = NT_STATUS_NO_MEMORY;
6511 goto out;
6514 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6515 attrs, replace_if_exists);
6517 close_file(req, fsp, NORMAL_CLOSE);
6519 if (!NT_STATUS_IS_OK(status)) {
6520 DEBUG(3, ("rename_internals_fsp returned %s for "
6521 "rename %s -> %s\n", nt_errstr(status),
6522 smb_fname_str_dbg(smb_fname_src),
6523 smb_fname_str_dbg(smb_fname_dst)));
6524 break;
6527 count++;
6529 DEBUG(3,("rename_internals: doing rename on %s -> "
6530 "%s\n", smb_fname_str_dbg(smb_fname_src),
6531 smb_fname_str_dbg(smb_fname_src)));
6532 TALLOC_FREE(talloced);
6534 TALLOC_FREE(dir_hnd);
6536 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6537 status = map_nt_error_from_unix(errno);
6540 out:
6541 TALLOC_FREE(talloced);
6542 TALLOC_FREE(fname_src_dir);
6543 TALLOC_FREE(fname_src_mask);
6544 return status;
6547 /****************************************************************************
6548 Reply to a mv.
6549 ****************************************************************************/
6551 void reply_mv(struct smb_request *req)
6553 connection_struct *conn = req->conn;
6554 char *name = NULL;
6555 char *newname = NULL;
6556 const char *p;
6557 uint32 attrs;
6558 NTSTATUS status;
6559 bool src_has_wcard = False;
6560 bool dest_has_wcard = False;
6561 TALLOC_CTX *ctx = talloc_tos();
6562 struct smb_filename *smb_fname_src = NULL;
6563 struct smb_filename *smb_fname_dst = NULL;
6564 bool stream_rename = false;
6566 START_PROFILE(SMBmv);
6568 if (req->wct < 1) {
6569 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6570 goto out;
6573 attrs = SVAL(req->vwv+0, 0);
6575 p = (const char *)req->buf + 1;
6576 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6577 &status, &src_has_wcard);
6578 if (!NT_STATUS_IS_OK(status)) {
6579 reply_nterror(req, status);
6580 goto out;
6582 p++;
6583 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6584 &status, &dest_has_wcard);
6585 if (!NT_STATUS_IS_OK(status)) {
6586 reply_nterror(req, status);
6587 goto out;
6590 if (!lp_posix_pathnames()) {
6591 /* The newname must begin with a ':' if the
6592 name contains a ':'. */
6593 if (strchr_m(name, ':')) {
6594 if (newname[0] != ':') {
6595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6596 goto out;
6598 stream_rename = true;
6602 status = filename_convert(ctx,
6603 conn,
6604 req->flags2 & FLAGS2_DFS_PATHNAMES,
6605 name,
6606 UCF_COND_ALLOW_WCARD_LCOMP,
6607 &src_has_wcard,
6608 &smb_fname_src);
6610 if (!NT_STATUS_IS_OK(status)) {
6611 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6612 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6613 ERRSRV, ERRbadpath);
6614 goto out;
6616 reply_nterror(req, status);
6617 goto out;
6620 status = filename_convert(ctx,
6621 conn,
6622 req->flags2 & FLAGS2_DFS_PATHNAMES,
6623 newname,
6624 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6625 &dest_has_wcard,
6626 &smb_fname_dst);
6628 if (!NT_STATUS_IS_OK(status)) {
6629 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6630 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6631 ERRSRV, ERRbadpath);
6632 goto out;
6634 reply_nterror(req, status);
6635 goto out;
6638 if (stream_rename) {
6639 /* smb_fname_dst->base_name must be the same as
6640 smb_fname_src->base_name. */
6641 TALLOC_FREE(smb_fname_dst->base_name);
6642 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6643 smb_fname_src->base_name);
6644 if (!smb_fname_dst->base_name) {
6645 reply_nterror(req, NT_STATUS_NO_MEMORY);
6646 goto out;
6650 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6651 smb_fname_str_dbg(smb_fname_dst)));
6653 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6654 attrs, False, src_has_wcard, dest_has_wcard,
6655 DELETE_ACCESS);
6656 if (!NT_STATUS_IS_OK(status)) {
6657 if (open_was_deferred(req->mid)) {
6658 /* We have re-scheduled this call. */
6659 goto out;
6661 reply_nterror(req, status);
6662 goto out;
6665 reply_outbuf(req, 0, 0);
6666 out:
6667 TALLOC_FREE(smb_fname_src);
6668 TALLOC_FREE(smb_fname_dst);
6669 END_PROFILE(SMBmv);
6670 return;
6673 /*******************************************************************
6674 Copy a file as part of a reply_copy.
6675 ******************************************************************/
6678 * TODO: check error codes on all callers
6681 NTSTATUS copy_file(TALLOC_CTX *ctx,
6682 connection_struct *conn,
6683 struct smb_filename *smb_fname_src,
6684 struct smb_filename *smb_fname_dst,
6685 int ofun,
6686 int count,
6687 bool target_is_directory)
6689 struct smb_filename *smb_fname_dst_tmp = NULL;
6690 SMB_OFF_T ret=-1;
6691 files_struct *fsp1,*fsp2;
6692 uint32 dosattrs;
6693 uint32 new_create_disposition;
6694 NTSTATUS status;
6697 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6698 if (!NT_STATUS_IS_OK(status)) {
6699 return status;
6703 * If the target is a directory, extract the last component from the
6704 * src filename and append it to the dst filename
6706 if (target_is_directory) {
6707 const char *p;
6709 /* dest/target can't be a stream if it's a directory. */
6710 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6712 p = strrchr_m(smb_fname_src->base_name,'/');
6713 if (p) {
6714 p++;
6715 } else {
6716 p = smb_fname_src->base_name;
6718 smb_fname_dst_tmp->base_name =
6719 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6721 if (!smb_fname_dst_tmp->base_name) {
6722 status = NT_STATUS_NO_MEMORY;
6723 goto out;
6727 status = vfs_file_exist(conn, smb_fname_src);
6728 if (!NT_STATUS_IS_OK(status)) {
6729 goto out;
6732 if (!target_is_directory && count) {
6733 new_create_disposition = FILE_OPEN;
6734 } else {
6735 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6736 NULL, NULL,
6737 &new_create_disposition,
6738 NULL,
6739 NULL)) {
6740 status = NT_STATUS_INVALID_PARAMETER;
6741 goto out;
6745 /* Open the src file for reading. */
6746 status = SMB_VFS_CREATE_FILE(
6747 conn, /* conn */
6748 NULL, /* req */
6749 0, /* root_dir_fid */
6750 smb_fname_src, /* fname */
6751 FILE_GENERIC_READ, /* access_mask */
6752 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6753 FILE_OPEN, /* create_disposition*/
6754 0, /* create_options */
6755 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6756 INTERNAL_OPEN_ONLY, /* oplock_request */
6757 0, /* allocation_size */
6758 0, /* private_flags */
6759 NULL, /* sd */
6760 NULL, /* ea_list */
6761 &fsp1, /* result */
6762 NULL); /* psbuf */
6764 if (!NT_STATUS_IS_OK(status)) {
6765 goto out;
6768 dosattrs = dos_mode(conn, smb_fname_src);
6770 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6771 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6774 /* Open the dst file for writing. */
6775 status = SMB_VFS_CREATE_FILE(
6776 conn, /* conn */
6777 NULL, /* req */
6778 0, /* root_dir_fid */
6779 smb_fname_dst, /* fname */
6780 FILE_GENERIC_WRITE, /* access_mask */
6781 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6782 new_create_disposition, /* create_disposition*/
6783 0, /* create_options */
6784 dosattrs, /* file_attributes */
6785 INTERNAL_OPEN_ONLY, /* oplock_request */
6786 0, /* allocation_size */
6787 0, /* private_flags */
6788 NULL, /* sd */
6789 NULL, /* ea_list */
6790 &fsp2, /* result */
6791 NULL); /* psbuf */
6793 if (!NT_STATUS_IS_OK(status)) {
6794 close_file(NULL, fsp1, ERROR_CLOSE);
6795 goto out;
6798 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6799 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6800 if (ret == -1) {
6801 DEBUG(0, ("error - vfs lseek returned error %s\n",
6802 strerror(errno)));
6803 status = map_nt_error_from_unix(errno);
6804 close_file(NULL, fsp1, ERROR_CLOSE);
6805 close_file(NULL, fsp2, ERROR_CLOSE);
6806 goto out;
6810 /* Do the actual copy. */
6811 if (smb_fname_src->st.st_ex_size) {
6812 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6813 } else {
6814 ret = 0;
6817 close_file(NULL, fsp1, NORMAL_CLOSE);
6819 /* Ensure the modtime is set correctly on the destination file. */
6820 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6823 * As we are opening fsp1 read-only we only expect
6824 * an error on close on fsp2 if we are out of space.
6825 * Thus we don't look at the error return from the
6826 * close of fsp1.
6828 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6830 if (!NT_STATUS_IS_OK(status)) {
6831 goto out;
6834 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6835 status = NT_STATUS_DISK_FULL;
6836 goto out;
6839 status = NT_STATUS_OK;
6841 out:
6842 TALLOC_FREE(smb_fname_dst_tmp);
6843 return status;
6846 /****************************************************************************
6847 Reply to a file copy.
6848 ****************************************************************************/
6850 void reply_copy(struct smb_request *req)
6852 connection_struct *conn = req->conn;
6853 struct smb_filename *smb_fname_src = NULL;
6854 struct smb_filename *smb_fname_dst = NULL;
6855 char *fname_src = NULL;
6856 char *fname_dst = NULL;
6857 char *fname_src_mask = NULL;
6858 char *fname_src_dir = NULL;
6859 const char *p;
6860 int count=0;
6861 int error = ERRnoaccess;
6862 int tid2;
6863 int ofun;
6864 int flags;
6865 bool target_is_directory=False;
6866 bool source_has_wild = False;
6867 bool dest_has_wild = False;
6868 NTSTATUS status;
6869 TALLOC_CTX *ctx = talloc_tos();
6871 START_PROFILE(SMBcopy);
6873 if (req->wct < 3) {
6874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6875 goto out;
6878 tid2 = SVAL(req->vwv+0, 0);
6879 ofun = SVAL(req->vwv+1, 0);
6880 flags = SVAL(req->vwv+2, 0);
6882 p = (const char *)req->buf;
6883 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6884 &status, &source_has_wild);
6885 if (!NT_STATUS_IS_OK(status)) {
6886 reply_nterror(req, status);
6887 goto out;
6889 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6890 &status, &dest_has_wild);
6891 if (!NT_STATUS_IS_OK(status)) {
6892 reply_nterror(req, status);
6893 goto out;
6896 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6898 if (tid2 != conn->cnum) {
6899 /* can't currently handle inter share copies XXXX */
6900 DEBUG(3,("Rejecting inter-share copy\n"));
6901 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6902 goto out;
6905 status = filename_convert(ctx, conn,
6906 req->flags2 & FLAGS2_DFS_PATHNAMES,
6907 fname_src,
6908 UCF_COND_ALLOW_WCARD_LCOMP,
6909 &source_has_wild,
6910 &smb_fname_src);
6911 if (!NT_STATUS_IS_OK(status)) {
6912 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6913 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6914 ERRSRV, ERRbadpath);
6915 goto out;
6917 reply_nterror(req, status);
6918 goto out;
6921 status = filename_convert(ctx, conn,
6922 req->flags2 & FLAGS2_DFS_PATHNAMES,
6923 fname_dst,
6924 UCF_COND_ALLOW_WCARD_LCOMP,
6925 &dest_has_wild,
6926 &smb_fname_dst);
6927 if (!NT_STATUS_IS_OK(status)) {
6928 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6929 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6930 ERRSRV, ERRbadpath);
6931 goto out;
6933 reply_nterror(req, status);
6934 goto out;
6937 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6939 if ((flags&1) && target_is_directory) {
6940 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6941 goto out;
6944 if ((flags&2) && !target_is_directory) {
6945 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6946 goto out;
6949 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6950 /* wants a tree copy! XXXX */
6951 DEBUG(3,("Rejecting tree copy\n"));
6952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6953 goto out;
6956 /* Split up the directory from the filename/mask. */
6957 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6958 &fname_src_dir, &fname_src_mask);
6959 if (!NT_STATUS_IS_OK(status)) {
6960 reply_nterror(req, NT_STATUS_NO_MEMORY);
6961 goto out;
6965 * We should only check the mangled cache
6966 * here if unix_convert failed. This means
6967 * that the path in 'mask' doesn't exist
6968 * on the file system and so we need to look
6969 * for a possible mangle. This patch from
6970 * Tine Smukavec <valentin.smukavec@hermes.si>.
6972 if (!VALID_STAT(smb_fname_src->st) &&
6973 mangle_is_mangled(fname_src_mask, conn->params)) {
6974 char *new_mask = NULL;
6975 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6976 &new_mask, conn->params);
6978 /* Use demangled name if one was successfully found. */
6979 if (new_mask) {
6980 TALLOC_FREE(fname_src_mask);
6981 fname_src_mask = new_mask;
6985 if (!source_has_wild) {
6988 * Only one file needs to be copied. Append the mask back onto
6989 * the directory.
6991 TALLOC_FREE(smb_fname_src->base_name);
6992 if (ISDOT(fname_src_dir)) {
6993 /* Ensure we use canonical names on open. */
6994 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6995 "%s",
6996 fname_src_mask);
6997 } else {
6998 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6999 "%s/%s",
7000 fname_src_dir,
7001 fname_src_mask);
7003 if (!smb_fname_src->base_name) {
7004 reply_nterror(req, NT_STATUS_NO_MEMORY);
7005 goto out;
7008 if (dest_has_wild) {
7009 char *fname_dst_mod = NULL;
7010 if (!resolve_wildcards(smb_fname_dst,
7011 smb_fname_src->base_name,
7012 smb_fname_dst->base_name,
7013 &fname_dst_mod)) {
7014 reply_nterror(req, NT_STATUS_NO_MEMORY);
7015 goto out;
7017 TALLOC_FREE(smb_fname_dst->base_name);
7018 smb_fname_dst->base_name = fname_dst_mod;
7021 status = check_name(conn, smb_fname_src->base_name);
7022 if (!NT_STATUS_IS_OK(status)) {
7023 reply_nterror(req, status);
7024 goto out;
7027 status = check_name(conn, smb_fname_dst->base_name);
7028 if (!NT_STATUS_IS_OK(status)) {
7029 reply_nterror(req, status);
7030 goto out;
7033 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7034 ofun, count, target_is_directory);
7036 if(!NT_STATUS_IS_OK(status)) {
7037 reply_nterror(req, status);
7038 goto out;
7039 } else {
7040 count++;
7042 } else {
7043 struct smb_Dir *dir_hnd = NULL;
7044 const char *dname = NULL;
7045 char *talloced = NULL;
7046 long offset = 0;
7049 * There is a wildcard that requires us to actually read the
7050 * src dir and copy each file matching the mask to the dst.
7051 * Right now streams won't be copied, but this could
7052 * presumably be added with a nested loop for reach dir entry.
7054 SMB_ASSERT(!smb_fname_src->stream_name);
7055 SMB_ASSERT(!smb_fname_dst->stream_name);
7057 smb_fname_src->stream_name = NULL;
7058 smb_fname_dst->stream_name = NULL;
7060 if (strequal(fname_src_mask,"????????.???")) {
7061 TALLOC_FREE(fname_src_mask);
7062 fname_src_mask = talloc_strdup(ctx, "*");
7063 if (!fname_src_mask) {
7064 reply_nterror(req, NT_STATUS_NO_MEMORY);
7065 goto out;
7069 status = check_name(conn, fname_src_dir);
7070 if (!NT_STATUS_IS_OK(status)) {
7071 reply_nterror(req, status);
7072 goto out;
7075 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7076 if (dir_hnd == NULL) {
7077 status = map_nt_error_from_unix(errno);
7078 reply_nterror(req, status);
7079 goto out;
7082 error = ERRbadfile;
7084 /* Iterate over the src dir copying each entry to the dst. */
7085 while ((dname = ReadDirName(dir_hnd, &offset,
7086 &smb_fname_src->st, &talloced))) {
7087 char *destname = NULL;
7089 if (ISDOT(dname) || ISDOTDOT(dname)) {
7090 TALLOC_FREE(talloced);
7091 continue;
7094 if (!is_visible_file(conn, fname_src_dir, dname,
7095 &smb_fname_src->st, false)) {
7096 TALLOC_FREE(talloced);
7097 continue;
7100 if(!mask_match(dname, fname_src_mask,
7101 conn->case_sensitive)) {
7102 TALLOC_FREE(talloced);
7103 continue;
7106 error = ERRnoaccess;
7108 /* Get the src smb_fname struct setup. */
7109 TALLOC_FREE(smb_fname_src->base_name);
7110 if (ISDOT(fname_src_dir)) {
7111 /* Ensure we use canonical names on open. */
7112 smb_fname_src->base_name =
7113 talloc_asprintf(smb_fname_src, "%s",
7114 dname);
7115 } else {
7116 smb_fname_src->base_name =
7117 talloc_asprintf(smb_fname_src, "%s/%s",
7118 fname_src_dir, dname);
7121 if (!smb_fname_src->base_name) {
7122 TALLOC_FREE(dir_hnd);
7123 TALLOC_FREE(talloced);
7124 reply_nterror(req, NT_STATUS_NO_MEMORY);
7125 goto out;
7128 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7129 smb_fname_dst->base_name,
7130 &destname)) {
7131 TALLOC_FREE(talloced);
7132 continue;
7134 if (!destname) {
7135 TALLOC_FREE(dir_hnd);
7136 TALLOC_FREE(talloced);
7137 reply_nterror(req, NT_STATUS_NO_MEMORY);
7138 goto out;
7141 TALLOC_FREE(smb_fname_dst->base_name);
7142 smb_fname_dst->base_name = destname;
7144 status = check_name(conn, smb_fname_src->base_name);
7145 if (!NT_STATUS_IS_OK(status)) {
7146 TALLOC_FREE(dir_hnd);
7147 TALLOC_FREE(talloced);
7148 reply_nterror(req, status);
7149 goto out;
7152 status = check_name(conn, smb_fname_dst->base_name);
7153 if (!NT_STATUS_IS_OK(status)) {
7154 TALLOC_FREE(dir_hnd);
7155 TALLOC_FREE(talloced);
7156 reply_nterror(req, status);
7157 goto out;
7160 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7161 smb_fname_src->base_name,
7162 smb_fname_dst->base_name));
7164 status = copy_file(ctx, conn, smb_fname_src,
7165 smb_fname_dst, ofun, count,
7166 target_is_directory);
7167 if (NT_STATUS_IS_OK(status)) {
7168 count++;
7171 TALLOC_FREE(talloced);
7173 TALLOC_FREE(dir_hnd);
7176 if (count == 0) {
7177 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7178 goto out;
7181 reply_outbuf(req, 1, 0);
7182 SSVAL(req->outbuf,smb_vwv0,count);
7183 out:
7184 TALLOC_FREE(smb_fname_src);
7185 TALLOC_FREE(smb_fname_dst);
7186 TALLOC_FREE(fname_src);
7187 TALLOC_FREE(fname_dst);
7188 TALLOC_FREE(fname_src_mask);
7189 TALLOC_FREE(fname_src_dir);
7191 END_PROFILE(SMBcopy);
7192 return;
7195 #undef DBGC_CLASS
7196 #define DBGC_CLASS DBGC_LOCKING
7198 /****************************************************************************
7199 Get a lock pid, dealing with large count requests.
7200 ****************************************************************************/
7202 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7203 bool large_file_format)
7205 if(!large_file_format)
7206 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7207 else
7208 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7211 /****************************************************************************
7212 Get a lock count, dealing with large count requests.
7213 ****************************************************************************/
7215 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7216 bool large_file_format)
7218 uint64_t count = 0;
7220 if(!large_file_format) {
7221 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7222 } else {
7224 #if defined(HAVE_LONGLONG)
7225 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7226 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7227 #else /* HAVE_LONGLONG */
7230 * NT4.x seems to be broken in that it sends large file (64 bit)
7231 * lockingX calls even if the CAP_LARGE_FILES was *not*
7232 * negotiated. For boxes without large unsigned ints truncate the
7233 * lock count by dropping the top 32 bits.
7236 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7237 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7238 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7239 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7240 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7243 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7244 #endif /* HAVE_LONGLONG */
7247 return count;
7250 #if !defined(HAVE_LONGLONG)
7251 /****************************************************************************
7252 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7253 ****************************************************************************/
7255 static uint32 map_lock_offset(uint32 high, uint32 low)
7257 unsigned int i;
7258 uint32 mask = 0;
7259 uint32 highcopy = high;
7262 * Try and find out how many significant bits there are in high.
7265 for(i = 0; highcopy; i++)
7266 highcopy >>= 1;
7269 * We use 31 bits not 32 here as POSIX
7270 * lock offsets may not be negative.
7273 mask = (~0) << (31 - i);
7275 if(low & mask)
7276 return 0; /* Fail. */
7278 high <<= (31 - i);
7280 return (high|low);
7282 #endif /* !defined(HAVE_LONGLONG) */
7284 /****************************************************************************
7285 Get a lock offset, dealing with large offset requests.
7286 ****************************************************************************/
7288 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7289 bool large_file_format, bool *err)
7291 uint64_t offset = 0;
7293 *err = False;
7295 if(!large_file_format) {
7296 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7297 } else {
7299 #if defined(HAVE_LONGLONG)
7300 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7301 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7302 #else /* HAVE_LONGLONG */
7305 * NT4.x seems to be broken in that it sends large file (64 bit)
7306 * lockingX calls even if the CAP_LARGE_FILES was *not*
7307 * negotiated. For boxes without large unsigned ints mangle the
7308 * lock offset by mapping the top 32 bits onto the lower 32.
7311 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7312 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7313 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7314 uint32 new_low = 0;
7316 if((new_low = map_lock_offset(high, low)) == 0) {
7317 *err = True;
7318 return (uint64_t)-1;
7321 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7322 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7323 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7324 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7327 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7328 #endif /* HAVE_LONGLONG */
7331 return offset;
7334 NTSTATUS smbd_do_locking(struct smb_request *req,
7335 files_struct *fsp,
7336 uint8_t type,
7337 int32_t timeout,
7338 uint16_t num_ulocks,
7339 struct smbd_lock_element *ulocks,
7340 uint16_t num_locks,
7341 struct smbd_lock_element *locks,
7342 bool *async)
7344 connection_struct *conn = req->conn;
7345 int i;
7346 NTSTATUS status = NT_STATUS_OK;
7348 *async = false;
7350 /* Data now points at the beginning of the list
7351 of smb_unlkrng structs */
7352 for(i = 0; i < (int)num_ulocks; i++) {
7353 struct smbd_lock_element *e = &ulocks[i];
7355 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7356 "pid %u, file %s\n",
7357 (double)e->offset,
7358 (double)e->count,
7359 (unsigned int)e->smblctx,
7360 fsp_str_dbg(fsp)));
7362 if (e->brltype != UNLOCK_LOCK) {
7363 /* this can only happen with SMB2 */
7364 return NT_STATUS_INVALID_PARAMETER;
7367 status = do_unlock(req->sconn->msg_ctx,
7368 fsp,
7369 e->smblctx,
7370 e->count,
7371 e->offset,
7372 WINDOWS_LOCK);
7374 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7375 nt_errstr(status)));
7377 if (!NT_STATUS_IS_OK(status)) {
7378 return status;
7382 /* Setup the timeout in seconds. */
7384 if (!lp_blocking_locks(SNUM(conn))) {
7385 timeout = 0;
7388 /* Data now points at the beginning of the list
7389 of smb_lkrng structs */
7391 for(i = 0; i < (int)num_locks; i++) {
7392 struct smbd_lock_element *e = &locks[i];
7394 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7395 "%llu, file %s timeout = %d\n",
7396 (double)e->offset,
7397 (double)e->count,
7398 (unsigned long long)e->smblctx,
7399 fsp_str_dbg(fsp),
7400 (int)timeout));
7402 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7403 struct blocking_lock_record *blr = NULL;
7405 if (num_locks > 1) {
7407 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7408 * if the lock vector contains one entry. When given mutliple cancel
7409 * requests in a single PDU we expect the server to return an
7410 * error. Windows servers seem to accept the request but only
7411 * cancel the first lock.
7412 * JRA - Do what Windows does (tm) :-).
7415 #if 0
7416 /* MS-CIFS (2.2.4.32.1) behavior. */
7417 return NT_STATUS_DOS(ERRDOS,
7418 ERRcancelviolation);
7419 #else
7420 /* Windows behavior. */
7421 if (i != 0) {
7422 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7423 "cancel request\n"));
7424 continue;
7426 #endif
7429 if (lp_blocking_locks(SNUM(conn))) {
7431 /* Schedule a message to ourselves to
7432 remove the blocking lock record and
7433 return the right error. */
7435 blr = blocking_lock_cancel_smb1(fsp,
7436 e->smblctx,
7437 e->offset,
7438 e->count,
7439 WINDOWS_LOCK,
7440 type,
7441 NT_STATUS_FILE_LOCK_CONFLICT);
7442 if (blr == NULL) {
7443 return NT_STATUS_DOS(
7444 ERRDOS,
7445 ERRcancelviolation);
7448 /* Remove a matching pending lock. */
7449 status = do_lock_cancel(fsp,
7450 e->smblctx,
7451 e->count,
7452 e->offset,
7453 WINDOWS_LOCK,
7454 blr);
7455 } else {
7456 bool blocking_lock = timeout ? true : false;
7457 bool defer_lock = false;
7458 struct byte_range_lock *br_lck;
7459 uint64_t block_smblctx;
7461 br_lck = do_lock(req->sconn->msg_ctx,
7462 fsp,
7463 e->smblctx,
7464 e->count,
7465 e->offset,
7466 e->brltype,
7467 WINDOWS_LOCK,
7468 blocking_lock,
7469 &status,
7470 &block_smblctx,
7471 NULL);
7473 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7474 /* Windows internal resolution for blocking locks seems
7475 to be about 200ms... Don't wait for less than that. JRA. */
7476 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7477 timeout = lp_lock_spin_time();
7479 defer_lock = true;
7482 /* If a lock sent with timeout of zero would fail, and
7483 * this lock has been requested multiple times,
7484 * according to brl_lock_failed() we convert this
7485 * request to a blocking lock with a timeout of between
7486 * 150 - 300 milliseconds.
7488 * If lp_lock_spin_time() has been set to 0, we skip
7489 * this blocking retry and fail immediately.
7491 * Replacement for do_lock_spin(). JRA. */
7493 if (!req->sconn->using_smb2 &&
7494 br_lck && lp_blocking_locks(SNUM(conn)) &&
7495 lp_lock_spin_time() && !blocking_lock &&
7496 NT_STATUS_EQUAL((status),
7497 NT_STATUS_FILE_LOCK_CONFLICT))
7499 defer_lock = true;
7500 timeout = lp_lock_spin_time();
7503 if (br_lck && defer_lock) {
7505 * A blocking lock was requested. Package up
7506 * this smb into a queued request and push it
7507 * onto the blocking lock queue.
7509 if(push_blocking_lock_request(br_lck,
7510 req,
7511 fsp,
7512 timeout,
7514 e->smblctx,
7515 e->brltype,
7516 WINDOWS_LOCK,
7517 e->offset,
7518 e->count,
7519 block_smblctx)) {
7520 TALLOC_FREE(br_lck);
7521 *async = true;
7522 return NT_STATUS_OK;
7526 TALLOC_FREE(br_lck);
7529 if (!NT_STATUS_IS_OK(status)) {
7530 break;
7534 /* If any of the above locks failed, then we must unlock
7535 all of the previous locks (X/Open spec). */
7537 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7539 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7540 i = -1; /* we want to skip the for loop */
7544 * Ensure we don't do a remove on the lock that just failed,
7545 * as under POSIX rules, if we have a lock already there, we
7546 * will delete it (and we shouldn't) .....
7548 for(i--; i >= 0; i--) {
7549 struct smbd_lock_element *e = &locks[i];
7551 do_unlock(req->sconn->msg_ctx,
7552 fsp,
7553 e->smblctx,
7554 e->count,
7555 e->offset,
7556 WINDOWS_LOCK);
7558 return status;
7561 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7562 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7564 return NT_STATUS_OK;
7567 /****************************************************************************
7568 Reply to a lockingX request.
7569 ****************************************************************************/
7571 void reply_lockingX(struct smb_request *req)
7573 connection_struct *conn = req->conn;
7574 files_struct *fsp;
7575 unsigned char locktype;
7576 unsigned char oplocklevel;
7577 uint16 num_ulocks;
7578 uint16 num_locks;
7579 int32 lock_timeout;
7580 int i;
7581 const uint8_t *data;
7582 bool large_file_format;
7583 bool err;
7584 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7585 struct smbd_lock_element *ulocks;
7586 struct smbd_lock_element *locks;
7587 bool async = false;
7589 START_PROFILE(SMBlockingX);
7591 if (req->wct < 8) {
7592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7593 END_PROFILE(SMBlockingX);
7594 return;
7597 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7598 locktype = CVAL(req->vwv+3, 0);
7599 oplocklevel = CVAL(req->vwv+3, 1);
7600 num_ulocks = SVAL(req->vwv+6, 0);
7601 num_locks = SVAL(req->vwv+7, 0);
7602 lock_timeout = IVAL(req->vwv+4, 0);
7603 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7605 if (!check_fsp(conn, req, fsp)) {
7606 END_PROFILE(SMBlockingX);
7607 return;
7610 data = req->buf;
7612 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7613 /* we don't support these - and CANCEL_LOCK makes w2k
7614 and XP reboot so I don't really want to be
7615 compatible! (tridge) */
7616 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7617 END_PROFILE(SMBlockingX);
7618 return;
7621 /* Check if this is an oplock break on a file
7622 we have granted an oplock on.
7624 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7625 /* Client can insist on breaking to none. */
7626 bool break_to_none = (oplocklevel == 0);
7627 bool result;
7629 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7630 "for fnum = %d\n", (unsigned int)oplocklevel,
7631 fsp->fnum ));
7634 * Make sure we have granted an exclusive or batch oplock on
7635 * this file.
7638 if (fsp->oplock_type == 0) {
7640 /* The Samba4 nbench simulator doesn't understand
7641 the difference between break to level2 and break
7642 to none from level2 - it sends oplock break
7643 replies in both cases. Don't keep logging an error
7644 message here - just ignore it. JRA. */
7646 DEBUG(5,("reply_lockingX: Error : oplock break from "
7647 "client for fnum = %d (oplock=%d) and no "
7648 "oplock granted on this file (%s).\n",
7649 fsp->fnum, fsp->oplock_type,
7650 fsp_str_dbg(fsp)));
7652 /* if this is a pure oplock break request then don't
7653 * send a reply */
7654 if (num_locks == 0 && num_ulocks == 0) {
7655 END_PROFILE(SMBlockingX);
7656 return;
7657 } else {
7658 END_PROFILE(SMBlockingX);
7659 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7660 return;
7664 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7665 (break_to_none)) {
7666 result = remove_oplock(fsp);
7667 } else {
7668 result = downgrade_oplock(fsp);
7671 if (!result) {
7672 DEBUG(0, ("reply_lockingX: error in removing "
7673 "oplock on file %s\n", fsp_str_dbg(fsp)));
7674 /* Hmmm. Is this panic justified? */
7675 smb_panic("internal tdb error");
7678 reply_to_oplock_break_requests(fsp);
7680 /* if this is a pure oplock break request then don't send a
7681 * reply */
7682 if (num_locks == 0 && num_ulocks == 0) {
7683 /* Sanity check - ensure a pure oplock break is not a
7684 chained request. */
7685 if(CVAL(req->vwv+0, 0) != 0xff)
7686 DEBUG(0,("reply_lockingX: Error : pure oplock "
7687 "break is a chained %d request !\n",
7688 (unsigned int)CVAL(req->vwv+0, 0)));
7689 END_PROFILE(SMBlockingX);
7690 return;
7694 if (req->buflen <
7695 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7697 END_PROFILE(SMBlockingX);
7698 return;
7701 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7702 if (ulocks == NULL) {
7703 reply_nterror(req, NT_STATUS_NO_MEMORY);
7704 END_PROFILE(SMBlockingX);
7705 return;
7708 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7709 if (locks == NULL) {
7710 reply_nterror(req, NT_STATUS_NO_MEMORY);
7711 END_PROFILE(SMBlockingX);
7712 return;
7715 /* Data now points at the beginning of the list
7716 of smb_unlkrng structs */
7717 for(i = 0; i < (int)num_ulocks; i++) {
7718 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7719 ulocks[i].count = get_lock_count(data, i, large_file_format);
7720 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7721 ulocks[i].brltype = UNLOCK_LOCK;
7724 * There is no error code marked "stupid client bug".... :-).
7726 if(err) {
7727 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7728 END_PROFILE(SMBlockingX);
7729 return;
7733 /* Now do any requested locks */
7734 data += ((large_file_format ? 20 : 10)*num_ulocks);
7736 /* Data now points at the beginning of the list
7737 of smb_lkrng structs */
7739 for(i = 0; i < (int)num_locks; i++) {
7740 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7741 locks[i].count = get_lock_count(data, i, large_file_format);
7742 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7744 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7745 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7746 locks[i].brltype = PENDING_READ_LOCK;
7747 } else {
7748 locks[i].brltype = READ_LOCK;
7750 } else {
7751 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7752 locks[i].brltype = PENDING_WRITE_LOCK;
7753 } else {
7754 locks[i].brltype = WRITE_LOCK;
7759 * There is no error code marked "stupid client bug".... :-).
7761 if(err) {
7762 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7763 END_PROFILE(SMBlockingX);
7764 return;
7768 status = smbd_do_locking(req, fsp,
7769 locktype, lock_timeout,
7770 num_ulocks, ulocks,
7771 num_locks, locks,
7772 &async);
7773 if (!NT_STATUS_IS_OK(status)) {
7774 END_PROFILE(SMBlockingX);
7775 reply_nterror(req, status);
7776 return;
7778 if (async) {
7779 END_PROFILE(SMBlockingX);
7780 return;
7783 reply_outbuf(req, 2, 0);
7785 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7786 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7788 END_PROFILE(SMBlockingX);
7789 chain_reply(req);
7792 #undef DBGC_CLASS
7793 #define DBGC_CLASS DBGC_ALL
7795 /****************************************************************************
7796 Reply to a SMBreadbmpx (read block multiplex) request.
7797 Always reply with an error, if someone has a platform really needs this,
7798 please contact vl@samba.org
7799 ****************************************************************************/
7801 void reply_readbmpx(struct smb_request *req)
7803 START_PROFILE(SMBreadBmpx);
7804 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7805 END_PROFILE(SMBreadBmpx);
7806 return;
7809 /****************************************************************************
7810 Reply to a SMBreadbs (read block multiplex secondary) request.
7811 Always reply with an error, if someone has a platform really needs this,
7812 please contact vl@samba.org
7813 ****************************************************************************/
7815 void reply_readbs(struct smb_request *req)
7817 START_PROFILE(SMBreadBs);
7818 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7819 END_PROFILE(SMBreadBs);
7820 return;
7823 /****************************************************************************
7824 Reply to a SMBsetattrE.
7825 ****************************************************************************/
7827 void reply_setattrE(struct smb_request *req)
7829 connection_struct *conn = req->conn;
7830 struct smb_file_time ft;
7831 files_struct *fsp;
7832 NTSTATUS status;
7834 START_PROFILE(SMBsetattrE);
7835 ZERO_STRUCT(ft);
7837 if (req->wct < 7) {
7838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7839 goto out;
7842 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7844 if(!fsp || (fsp->conn != conn)) {
7845 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7846 goto out;
7850 * Convert the DOS times into unix times.
7853 ft.atime = convert_time_t_to_timespec(
7854 srv_make_unix_date2(req->vwv+3));
7855 ft.mtime = convert_time_t_to_timespec(
7856 srv_make_unix_date2(req->vwv+5));
7857 ft.create_time = convert_time_t_to_timespec(
7858 srv_make_unix_date2(req->vwv+1));
7860 reply_outbuf(req, 0, 0);
7863 * Patch from Ray Frush <frush@engr.colostate.edu>
7864 * Sometimes times are sent as zero - ignore them.
7867 /* Ensure we have a valid stat struct for the source. */
7868 status = vfs_stat_fsp(fsp);
7869 if (!NT_STATUS_IS_OK(status)) {
7870 reply_nterror(req, status);
7871 goto out;
7874 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7875 if (!NT_STATUS_IS_OK(status)) {
7876 reply_nterror(req, status);
7877 goto out;
7880 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7881 " createtime=%u\n",
7882 fsp->fnum,
7883 (unsigned int)ft.atime.tv_sec,
7884 (unsigned int)ft.mtime.tv_sec,
7885 (unsigned int)ft.create_time.tv_sec
7887 out:
7888 END_PROFILE(SMBsetattrE);
7889 return;
7893 /* Back from the dead for OS/2..... JRA. */
7895 /****************************************************************************
7896 Reply to a SMBwritebmpx (write block multiplex primary) request.
7897 Always reply with an error, if someone has a platform really needs this,
7898 please contact vl@samba.org
7899 ****************************************************************************/
7901 void reply_writebmpx(struct smb_request *req)
7903 START_PROFILE(SMBwriteBmpx);
7904 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7905 END_PROFILE(SMBwriteBmpx);
7906 return;
7909 /****************************************************************************
7910 Reply to a SMBwritebs (write block multiplex secondary) request.
7911 Always reply with an error, if someone has a platform really needs this,
7912 please contact vl@samba.org
7913 ****************************************************************************/
7915 void reply_writebs(struct smb_request *req)
7917 START_PROFILE(SMBwriteBs);
7918 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7919 END_PROFILE(SMBwriteBs);
7920 return;
7923 /****************************************************************************
7924 Reply to a SMBgetattrE.
7925 ****************************************************************************/
7927 void reply_getattrE(struct smb_request *req)
7929 connection_struct *conn = req->conn;
7930 int mode;
7931 files_struct *fsp;
7932 struct timespec create_ts;
7934 START_PROFILE(SMBgetattrE);
7936 if (req->wct < 1) {
7937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7938 END_PROFILE(SMBgetattrE);
7939 return;
7942 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7944 if(!fsp || (fsp->conn != conn)) {
7945 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7946 END_PROFILE(SMBgetattrE);
7947 return;
7950 /* Do an fstat on this file */
7951 if(fsp_stat(fsp)) {
7952 reply_nterror(req, map_nt_error_from_unix(errno));
7953 END_PROFILE(SMBgetattrE);
7954 return;
7957 mode = dos_mode(conn, fsp->fsp_name);
7960 * Convert the times into dos times. Set create
7961 * date to be last modify date as UNIX doesn't save
7962 * this.
7965 reply_outbuf(req, 11, 0);
7967 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7968 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7969 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7970 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7971 /* Should we check pending modtime here ? JRA */
7972 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7973 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7975 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7976 SIVAL(req->outbuf, smb_vwv6, 0);
7977 SIVAL(req->outbuf, smb_vwv8, 0);
7978 } else {
7979 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7980 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7981 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7983 SSVAL(req->outbuf,smb_vwv10, mode);
7985 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7987 END_PROFILE(SMBgetattrE);
7988 return;