Fix more use of VFS_STAT when posix pathnames selected.
[Samba.git] / source3 / smbd / reply.c
bloba3280cb9d4ae36910098cdbae9cdce41bfc09588
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 "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
37 set.
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS check_path_syntax_internal(char *path,
44 bool posix_path,
45 bool *p_last_component_contains_wcard)
47 char *d = path;
48 const char *s = path;
49 NTSTATUS ret = NT_STATUS_OK;
50 bool start_of_name_component = True;
51 bool stream_started = false;
53 *p_last_component_contains_wcard = False;
55 while (*s) {
56 if (stream_started) {
57 switch (*s) {
58 case '/':
59 case '\\':
60 return NT_STATUS_OBJECT_NAME_INVALID;
61 case ':':
62 if (s[1] == '\0') {
63 return NT_STATUS_OBJECT_NAME_INVALID;
65 if (strchr_m(&s[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID;
68 break;
72 if (!posix_path && !stream_started && *s == ':') {
73 if (*p_last_component_contains_wcard) {
74 return NT_STATUS_OBJECT_NAME_INVALID;
76 /* Stream names allow more characters than file names.
77 We're overloading posix_path here to allow a wider
78 range of characters. If stream_started is true this
79 is still a Windows path even if posix_path is true.
80 JRA.
82 stream_started = true;
83 start_of_name_component = false;
84 posix_path = true;
86 if (s[1] == '\0') {
87 return NT_STATUS_OBJECT_NAME_INVALID;
91 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
93 * Safe to assume is not the second part of a mb char
94 * as this is handled below.
96 /* Eat multiple '/' or '\\' */
97 while (IS_PATH_SEP(*s,posix_path)) {
98 s++;
100 if ((d != path) && (*s != '\0')) {
101 /* We only care about non-leading or trailing '/' or '\\' */
102 *d++ = '/';
105 start_of_name_component = True;
106 /* New component. */
107 *p_last_component_contains_wcard = False;
108 continue;
111 if (start_of_name_component) {
112 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
113 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
116 * No mb char starts with '.' so we're safe checking the directory separator here.
119 /* If we just added a '/' - delete it */
120 if ((d > path) && (*(d-1) == '/')) {
121 *(d-1) = '\0';
122 d--;
125 /* Are we at the start ? Can't go back further if so. */
126 if (d <= path) {
127 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
128 break;
130 /* Go back one level... */
131 /* We know this is safe as '/' cannot be part of a mb sequence. */
132 /* NOTE - if this assumption is invalid we are not in good shape... */
133 /* Decrement d first as d points to the *next* char to write into. */
134 for (d--; d > path; d--) {
135 if (*d == '/')
136 break;
138 s += 2; /* Else go past the .. */
139 /* We're still at the start of a name component, just the previous one. */
140 continue;
142 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
143 if (posix_path) {
144 /* Eat the '.' */
145 s++;
146 continue;
152 if (!(*s & 0x80)) {
153 if (!posix_path) {
154 if (*s <= 0x1f || *s == '|') {
155 return NT_STATUS_OBJECT_NAME_INVALID;
157 switch (*s) {
158 case '*':
159 case '?':
160 case '<':
161 case '>':
162 case '"':
163 *p_last_component_contains_wcard = True;
164 break;
165 default:
166 break;
169 *d++ = *s++;
170 } else {
171 size_t siz;
172 /* Get the size of the next MB character. */
173 next_codepoint(s,&siz);
174 switch(siz) {
175 case 5:
176 *d++ = *s++;
177 /*fall through*/
178 case 4:
179 *d++ = *s++;
180 /*fall through*/
181 case 3:
182 *d++ = *s++;
183 /*fall through*/
184 case 2:
185 *d++ = *s++;
186 /*fall through*/
187 case 1:
188 *d++ = *s++;
189 break;
190 default:
191 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
192 *d = '\0';
193 return NT_STATUS_INVALID_PARAMETER;
196 start_of_name_component = False;
199 *d = '\0';
201 return ret;
204 /****************************************************************************
205 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
206 No wildcards allowed.
207 ****************************************************************************/
209 NTSTATUS check_path_syntax(char *path)
211 bool ignore;
212 return check_path_syntax_internal(path, False, &ignore);
215 /****************************************************************************
216 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
217 Wildcards allowed - p_contains_wcard returns true if the last component contained
218 a wildcard.
219 ****************************************************************************/
221 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
223 return check_path_syntax_internal(path, False, p_contains_wcard);
226 /****************************************************************************
227 Check the path for a POSIX client.
228 We're assuming here that '/' is not the second byte in any multibyte char
229 set (a safe assumption).
230 ****************************************************************************/
232 NTSTATUS check_path_syntax_posix(char *path)
234 bool ignore;
235 return check_path_syntax_internal(path, True, &ignore);
238 /****************************************************************************
239 Pull a string and check the path allowing a wilcard - provide for error return.
240 ****************************************************************************/
242 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
243 const char *base_ptr,
244 uint16 smb_flags2,
245 char **pp_dest,
246 const char *src,
247 size_t src_len,
248 int flags,
249 NTSTATUS *err,
250 bool *contains_wcard)
252 size_t ret;
254 *pp_dest = NULL;
256 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
257 src_len, flags);
259 if (!*pp_dest) {
260 *err = NT_STATUS_INVALID_PARAMETER;
261 return ret;
264 *contains_wcard = False;
266 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
268 * For a DFS path the function parse_dfs_path()
269 * will do the path processing, just make a copy.
271 *err = NT_STATUS_OK;
272 return ret;
275 if (lp_posix_pathnames()) {
276 *err = check_path_syntax_posix(*pp_dest);
277 } else {
278 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
281 return ret;
284 /****************************************************************************
285 Pull a string and check the path - provide for error return.
286 ****************************************************************************/
288 size_t srvstr_get_path(TALLOC_CTX *ctx,
289 const char *base_ptr,
290 uint16 smb_flags2,
291 char **pp_dest,
292 const char *src,
293 size_t src_len,
294 int flags,
295 NTSTATUS *err)
297 bool ignore;
298 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
299 src_len, flags, err, &ignore);
302 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
303 char **pp_dest, const char *src, int flags,
304 NTSTATUS *err, bool *contains_wcard)
306 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
307 pp_dest, src, smbreq_bufrem(req, src),
308 flags, err, contains_wcard);
311 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
312 char **pp_dest, const char *src, int flags,
313 NTSTATUS *err)
315 bool ignore;
316 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
317 flags, err, &ignore);
320 /****************************************************************************
321 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
322 ****************************************************************************/
324 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
325 files_struct *fsp)
327 if (!(fsp) || !(conn)) {
328 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
329 return False;
331 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
332 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
333 return False;
335 return True;
338 /****************************************************************************
339 Check if we have a correct fsp pointing to a file.
340 ****************************************************************************/
342 bool check_fsp(connection_struct *conn, struct smb_request *req,
343 files_struct *fsp)
345 if (!check_fsp_open(conn, req, fsp)) {
346 return False;
348 if ((fsp)->is_directory) {
349 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
350 return False;
352 if ((fsp)->fh->fd == -1) {
353 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
354 return False;
356 (fsp)->num_smb_operations++;
357 return True;
360 /****************************************************************************
361 Check if we have a correct fsp pointing to a quota fake file. Replacement for
362 the CHECK_NTQUOTA_HANDLE_OK macro.
363 ****************************************************************************/
365 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
366 files_struct *fsp)
368 if (!check_fsp_open(conn, req, fsp)) {
369 return false;
372 if (fsp->is_directory) {
373 return false;
376 if (fsp->fake_file_handle == NULL) {
377 return false;
380 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
381 return false;
384 if (fsp->fake_file_handle->private_data == NULL) {
385 return false;
388 return true;
391 /****************************************************************************
392 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
393 ****************************************************************************/
395 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
396 files_struct *fsp)
398 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
399 && (req->vuid == (fsp)->vuid)) {
400 return True;
403 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
404 return False;
407 static bool netbios_session_retarget(const char *name, int name_type)
409 char *trim_name;
410 char *trim_name_type;
411 const char *retarget_parm;
412 char *retarget;
413 char *p;
414 int retarget_type = 0x20;
415 int retarget_port = 139;
416 struct sockaddr_storage retarget_addr;
417 struct sockaddr_in *in_addr;
418 bool ret = false;
419 uint8_t outbuf[10];
421 if (get_socket_port(smbd_server_fd()) != 139) {
422 return false;
425 trim_name = talloc_strdup(talloc_tos(), name);
426 if (trim_name == NULL) {
427 goto fail;
429 trim_char(trim_name, ' ', ' ');
431 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
432 name_type);
433 if (trim_name_type == NULL) {
434 goto fail;
437 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
438 trim_name_type, NULL);
439 if (retarget_parm == NULL) {
440 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 trim_name, NULL);
443 if (retarget_parm == NULL) {
444 goto fail;
447 retarget = talloc_strdup(trim_name, retarget_parm);
448 if (retarget == NULL) {
449 goto fail;
452 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
454 p = strchr(retarget, ':');
455 if (p != NULL) {
456 *p++ = '\0';
457 retarget_port = atoi(p);
460 p = strchr_m(retarget, '#');
461 if (p != NULL) {
462 *p++ = '\0';
463 sscanf(p, "%x", &retarget_type);
466 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
467 if (!ret) {
468 DEBUG(10, ("could not resolve %s\n", retarget));
469 goto fail;
472 if (retarget_addr.ss_family != AF_INET) {
473 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
474 goto fail;
477 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
479 _smb_setlen(outbuf, 6);
480 SCVAL(outbuf, 0, 0x84);
481 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
482 *(uint16_t *)(outbuf+8) = htons(retarget_port);
484 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
485 NULL)) {
486 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
487 "failed.");
490 ret = true;
491 fail:
492 TALLOC_FREE(trim_name);
493 return ret;
496 /****************************************************************************
497 Reply to a (netbios-level) special message.
498 ****************************************************************************/
500 void reply_special(char *inbuf)
502 int msg_type = CVAL(inbuf,0);
503 int msg_flags = CVAL(inbuf,1);
504 fstring name1,name2;
505 char name_type1, name_type2;
506 struct smbd_server_connection *sconn = smbd_server_conn;
509 * We only really use 4 bytes of the outbuf, but for the smb_setlen
510 * calculation & friends (srv_send_smb uses that) we need the full smb
511 * header.
513 char outbuf[smb_size];
515 *name1 = *name2 = 0;
517 memset(outbuf, '\0', sizeof(outbuf));
519 smb_setlen(outbuf,0);
521 switch (msg_type) {
522 case 0x81: /* session request */
524 if (sconn->nbt.got_session) {
525 exit_server_cleanly("multiple session request not permitted");
528 SCVAL(outbuf,0,0x82);
529 SCVAL(outbuf,3,0);
530 if (name_len(inbuf+4) > 50 ||
531 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
532 DEBUG(0,("Invalid name length in session request\n"));
533 return;
535 name_type1 = name_extract(inbuf,4,name1);
536 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
537 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
538 name1, name_type1, name2, name_type2));
540 if (netbios_session_retarget(name1, name_type1)) {
541 exit_server_cleanly("retargeted client");
544 set_local_machine_name(name1, True);
545 set_remote_machine_name(name2, True);
547 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
548 get_local_machine_name(), get_remote_machine_name(),
549 name_type2));
551 if (name_type2 == 'R') {
552 /* We are being asked for a pathworks session ---
553 no thanks! */
554 SCVAL(outbuf, 0,0x83);
555 break;
558 /* only add the client's machine name to the list
559 of possibly valid usernames if we are operating
560 in share mode security */
561 if (lp_security() == SEC_SHARE) {
562 add_session_user(sconn, get_remote_machine_name());
565 reload_services(True);
566 reopen_logs();
568 sconn->nbt.got_session = true;
569 break;
571 case 0x89: /* session keepalive request
572 (some old clients produce this?) */
573 SCVAL(outbuf,0,SMBkeepalive);
574 SCVAL(outbuf,3,0);
575 break;
577 case 0x82: /* positive session response */
578 case 0x83: /* negative session response */
579 case 0x84: /* retarget session response */
580 DEBUG(0,("Unexpected session response\n"));
581 break;
583 case SMBkeepalive: /* session keepalive */
584 default:
585 return;
588 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
589 msg_type, msg_flags));
591 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
592 return;
595 /****************************************************************************
596 Reply to a tcon.
597 conn POINTER CAN BE NULL HERE !
598 ****************************************************************************/
600 void reply_tcon(struct smb_request *req)
602 connection_struct *conn = req->conn;
603 const char *service;
604 char *service_buf = NULL;
605 char *password = NULL;
606 char *dev = NULL;
607 int pwlen=0;
608 NTSTATUS nt_status;
609 const char *p;
610 DATA_BLOB password_blob;
611 TALLOC_CTX *ctx = talloc_tos();
612 struct smbd_server_connection *sconn = smbd_server_conn;
614 START_PROFILE(SMBtcon);
616 if (req->buflen < 4) {
617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
618 END_PROFILE(SMBtcon);
619 return;
622 p = (const char *)req->buf + 1;
623 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
624 p += 1;
625 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
626 p += pwlen+1;
627 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
628 p += 1;
630 if (service_buf == NULL || password == NULL || dev == NULL) {
631 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
632 END_PROFILE(SMBtcon);
633 return;
635 p = strrchr_m(service_buf,'\\');
636 if (p) {
637 service = p+1;
638 } else {
639 service = service_buf;
642 password_blob = data_blob(password, pwlen+1);
644 conn = make_connection(sconn,service,password_blob,dev,
645 req->vuid,&nt_status);
646 req->conn = conn;
648 data_blob_clear_free(&password_blob);
650 if (!conn) {
651 reply_nterror(req, nt_status);
652 END_PROFILE(SMBtcon);
653 return;
656 reply_outbuf(req, 2, 0);
657 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
658 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
659 SSVAL(req->outbuf,smb_tid,conn->cnum);
661 DEBUG(3,("tcon service=%s cnum=%d\n",
662 service, conn->cnum));
664 END_PROFILE(SMBtcon);
665 return;
668 /****************************************************************************
669 Reply to a tcon and X.
670 conn POINTER CAN BE NULL HERE !
671 ****************************************************************************/
673 void reply_tcon_and_X(struct smb_request *req)
675 connection_struct *conn = req->conn;
676 const char *service = NULL;
677 DATA_BLOB password;
678 TALLOC_CTX *ctx = talloc_tos();
679 /* what the cleint thinks the device is */
680 char *client_devicetype = NULL;
681 /* what the server tells the client the share represents */
682 const char *server_devicetype;
683 NTSTATUS nt_status;
684 int passlen;
685 char *path = NULL;
686 const char *p, *q;
687 uint16 tcon_flags;
688 struct smbd_server_connection *sconn = smbd_server_conn;
690 START_PROFILE(SMBtconX);
692 if (req->wct < 4) {
693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
694 END_PROFILE(SMBtconX);
695 return;
698 passlen = SVAL(req->vwv+3, 0);
699 tcon_flags = SVAL(req->vwv+2, 0);
701 /* we might have to close an old one */
702 if ((tcon_flags & 0x1) && conn) {
703 close_cnum(conn,req->vuid);
704 req->conn = NULL;
705 conn = NULL;
708 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
709 reply_doserror(req, ERRDOS, ERRbuftoosmall);
710 END_PROFILE(SMBtconX);
711 return;
714 if (sconn->smb1.negprot.encrypted_passwords) {
715 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
716 if (lp_security() == SEC_SHARE) {
718 * Security = share always has a pad byte
719 * after the password.
721 p = (const char *)req->buf + passlen + 1;
722 } else {
723 p = (const char *)req->buf + passlen;
725 } else {
726 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
727 /* Ensure correct termination */
728 password.data[passlen]=0;
729 p = (const char *)req->buf + passlen + 1;
732 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
734 if (path == NULL) {
735 data_blob_clear_free(&password);
736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
737 END_PROFILE(SMBtconX);
738 return;
742 * the service name can be either: \\server\share
743 * or share directly like on the DELL PowerVault 705
745 if (*path=='\\') {
746 q = strchr_m(path+2,'\\');
747 if (!q) {
748 data_blob_clear_free(&password);
749 reply_doserror(req, ERRDOS, ERRnosuchshare);
750 END_PROFILE(SMBtconX);
751 return;
753 service = q+1;
754 } else {
755 service = path;
758 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
759 &client_devicetype, p,
760 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
762 if (client_devicetype == NULL) {
763 data_blob_clear_free(&password);
764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
765 END_PROFILE(SMBtconX);
766 return;
769 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
771 conn = make_connection(sconn, service, password, client_devicetype,
772 req->vuid, &nt_status);
773 req->conn =conn;
775 data_blob_clear_free(&password);
777 if (!conn) {
778 reply_nterror(req, nt_status);
779 END_PROFILE(SMBtconX);
780 return;
783 if ( IS_IPC(conn) )
784 server_devicetype = "IPC";
785 else if ( IS_PRINT(conn) )
786 server_devicetype = "LPT1:";
787 else
788 server_devicetype = "A:";
790 if (Protocol < PROTOCOL_NT1) {
791 reply_outbuf(req, 2, 0);
792 if (message_push_string(&req->outbuf, server_devicetype,
793 STR_TERMINATE|STR_ASCII) == -1) {
794 reply_nterror(req, NT_STATUS_NO_MEMORY);
795 END_PROFILE(SMBtconX);
796 return;
798 } else {
799 /* NT sets the fstype of IPC$ to the null string */
800 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
802 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
803 /* Return permissions. */
804 uint32 perm1 = 0;
805 uint32 perm2 = 0;
807 reply_outbuf(req, 7, 0);
809 if (IS_IPC(conn)) {
810 perm1 = FILE_ALL_ACCESS;
811 perm2 = FILE_ALL_ACCESS;
812 } else {
813 perm1 = CAN_WRITE(conn) ?
814 SHARE_ALL_ACCESS :
815 SHARE_READ_ONLY;
818 SIVAL(req->outbuf, smb_vwv3, perm1);
819 SIVAL(req->outbuf, smb_vwv5, perm2);
820 } else {
821 reply_outbuf(req, 3, 0);
824 if ((message_push_string(&req->outbuf, server_devicetype,
825 STR_TERMINATE|STR_ASCII) == -1)
826 || (message_push_string(&req->outbuf, fstype,
827 STR_TERMINATE) == -1)) {
828 reply_nterror(req, NT_STATUS_NO_MEMORY);
829 END_PROFILE(SMBtconX);
830 return;
833 /* what does setting this bit do? It is set by NT4 and
834 may affect the ability to autorun mounted cdroms */
835 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
836 (lp_csc_policy(SNUM(conn)) << 2));
838 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
839 DEBUG(2,("Serving %s as a Dfs root\n",
840 lp_servicename(SNUM(conn)) ));
841 SSVAL(req->outbuf, smb_vwv2,
842 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
847 DEBUG(3,("tconX service=%s \n",
848 service));
850 /* set the incoming and outgoing tid to the just created one */
851 SSVAL(req->inbuf,smb_tid,conn->cnum);
852 SSVAL(req->outbuf,smb_tid,conn->cnum);
854 END_PROFILE(SMBtconX);
856 req->tid = conn->cnum;
857 chain_reply(req);
858 return;
861 /****************************************************************************
862 Reply to an unknown type.
863 ****************************************************************************/
865 void reply_unknown_new(struct smb_request *req, uint8 type)
867 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
868 smb_fn_name(type), type, type));
869 reply_doserror(req, ERRSRV, ERRunknownsmb);
870 return;
873 /****************************************************************************
874 Reply to an ioctl.
875 conn POINTER CAN BE NULL HERE !
876 ****************************************************************************/
878 void reply_ioctl(struct smb_request *req)
880 connection_struct *conn = req->conn;
881 uint16 device;
882 uint16 function;
883 uint32 ioctl_code;
884 int replysize;
885 char *p;
887 START_PROFILE(SMBioctl);
889 if (req->wct < 3) {
890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
891 END_PROFILE(SMBioctl);
892 return;
895 device = SVAL(req->vwv+1, 0);
896 function = SVAL(req->vwv+2, 0);
897 ioctl_code = (device << 16) + function;
899 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
901 switch (ioctl_code) {
902 case IOCTL_QUERY_JOB_INFO:
903 replysize = 32;
904 break;
905 default:
906 reply_doserror(req, ERRSRV, ERRnosupport);
907 END_PROFILE(SMBioctl);
908 return;
911 reply_outbuf(req, 8, replysize+1);
912 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
913 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
914 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
915 p = smb_buf(req->outbuf);
916 memset(p, '\0', replysize+1); /* valgrind-safe. */
917 p += 1; /* Allow for alignment */
919 switch (ioctl_code) {
920 case IOCTL_QUERY_JOB_INFO:
922 files_struct *fsp = file_fsp(
923 req, SVAL(req->vwv+0, 0));
924 if (!fsp) {
925 reply_doserror(req, ERRDOS, ERRbadfid);
926 END_PROFILE(SMBioctl);
927 return;
929 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
930 srvstr_push((char *)req->outbuf, req->flags2, p+2,
931 global_myname(), 15,
932 STR_TERMINATE|STR_ASCII);
933 if (conn) {
934 srvstr_push((char *)req->outbuf, req->flags2,
935 p+18, lp_servicename(SNUM(conn)),
936 13, STR_TERMINATE|STR_ASCII);
937 } else {
938 memset(p+18, 0, 13);
940 break;
944 END_PROFILE(SMBioctl);
945 return;
948 /****************************************************************************
949 Strange checkpath NTSTATUS mapping.
950 ****************************************************************************/
952 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
954 /* Strange DOS error code semantics only for checkpath... */
955 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
956 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
957 /* We need to map to ERRbadpath */
958 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
961 return status;
964 /****************************************************************************
965 Reply to a checkpath.
966 ****************************************************************************/
968 void reply_checkpath(struct smb_request *req)
970 connection_struct *conn = req->conn;
971 struct smb_filename *smb_fname = NULL;
972 char *name = NULL;
973 NTSTATUS status;
974 TALLOC_CTX *ctx = talloc_tos();
976 START_PROFILE(SMBcheckpath);
978 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
979 STR_TERMINATE, &status);
981 if (!NT_STATUS_IS_OK(status)) {
982 status = map_checkpath_error(req->flags2, status);
983 reply_nterror(req, status);
984 END_PROFILE(SMBcheckpath);
985 return;
988 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
990 status = filename_convert(ctx,
991 conn,
992 req->flags2 & FLAGS2_DFS_PATHNAMES,
993 name,
995 NULL,
996 &smb_fname);
998 if (!NT_STATUS_IS_OK(status)) {
999 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1000 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1001 ERRSRV, ERRbadpath);
1002 END_PROFILE(SMBcheckpath);
1003 return;
1005 goto path_err;
1008 if (!VALID_STAT(smb_fname->st) &&
1009 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1010 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1011 smb_fname_str_dbg(smb_fname), strerror(errno)));
1012 status = map_nt_error_from_unix(errno);
1013 goto path_err;
1016 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1017 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1018 ERRDOS, ERRbadpath);
1019 goto out;
1022 reply_outbuf(req, 0, 0);
1024 path_err:
1025 /* We special case this - as when a Windows machine
1026 is parsing a path is steps through the components
1027 one at a time - if a component fails it expects
1028 ERRbadpath, not ERRbadfile.
1030 status = map_checkpath_error(req->flags2, status);
1031 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1033 * Windows returns different error codes if
1034 * the parent directory is valid but not the
1035 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1036 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1037 * if the path is invalid.
1039 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1040 ERRDOS, ERRbadpath);
1041 goto out;
1044 reply_nterror(req, status);
1046 out:
1047 TALLOC_FREE(smb_fname);
1048 END_PROFILE(SMBcheckpath);
1049 return;
1052 /****************************************************************************
1053 Reply to a getatr.
1054 ****************************************************************************/
1056 void reply_getatr(struct smb_request *req)
1058 connection_struct *conn = req->conn;
1059 struct smb_filename *smb_fname = NULL;
1060 char *fname = NULL;
1061 int mode=0;
1062 SMB_OFF_T size=0;
1063 time_t mtime=0;
1064 const char *p;
1065 NTSTATUS status;
1066 TALLOC_CTX *ctx = talloc_tos();
1067 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1069 START_PROFILE(SMBgetatr);
1071 p = (const char *)req->buf + 1;
1072 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1073 if (!NT_STATUS_IS_OK(status)) {
1074 reply_nterror(req, status);
1075 goto out;
1078 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1079 under WfWg - weird! */
1080 if (*fname == '\0') {
1081 mode = aHIDDEN | aDIR;
1082 if (!CAN_WRITE(conn)) {
1083 mode |= aRONLY;
1085 size = 0;
1086 mtime = 0;
1087 } else {
1088 status = filename_convert(ctx,
1089 conn,
1090 req->flags2 & FLAGS2_DFS_PATHNAMES,
1091 fname,
1093 NULL,
1094 &smb_fname);
1095 if (!NT_STATUS_IS_OK(status)) {
1096 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1097 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1098 ERRSRV, ERRbadpath);
1099 goto out;
1101 reply_nterror(req, status);
1102 goto out;
1104 if (!VALID_STAT(smb_fname->st) &&
1105 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1106 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1107 smb_fname_str_dbg(smb_fname),
1108 strerror(errno)));
1109 reply_nterror(req, map_nt_error_from_unix(errno));
1110 goto out;
1113 mode = dos_mode(conn, smb_fname);
1114 size = smb_fname->st.st_ex_size;
1116 if (ask_sharemode) {
1117 struct timespec write_time_ts;
1118 struct file_id fileid;
1120 ZERO_STRUCT(write_time_ts);
1121 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1122 get_file_infos(fileid, NULL, &write_time_ts);
1123 if (!null_timespec(write_time_ts)) {
1124 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1128 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1129 if (mode & aDIR) {
1130 size = 0;
1134 reply_outbuf(req, 10, 0);
1136 SSVAL(req->outbuf,smb_vwv0,mode);
1137 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1138 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1139 } else {
1140 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1142 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1144 if (Protocol >= PROTOCOL_NT1) {
1145 SSVAL(req->outbuf, smb_flg2,
1146 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1149 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1150 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1152 out:
1153 TALLOC_FREE(smb_fname);
1154 TALLOC_FREE(fname);
1155 END_PROFILE(SMBgetatr);
1156 return;
1159 /****************************************************************************
1160 Reply to a setatr.
1161 ****************************************************************************/
1163 void reply_setatr(struct smb_request *req)
1165 struct smb_file_time ft;
1166 connection_struct *conn = req->conn;
1167 struct smb_filename *smb_fname = NULL;
1168 char *fname = NULL;
1169 int mode;
1170 time_t mtime;
1171 const char *p;
1172 NTSTATUS status;
1173 TALLOC_CTX *ctx = talloc_tos();
1175 START_PROFILE(SMBsetatr);
1177 ZERO_STRUCT(ft);
1179 if (req->wct < 2) {
1180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1181 goto out;
1184 p = (const char *)req->buf + 1;
1185 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1186 if (!NT_STATUS_IS_OK(status)) {
1187 reply_nterror(req, status);
1188 goto out;
1191 status = filename_convert(ctx,
1192 conn,
1193 req->flags2 & FLAGS2_DFS_PATHNAMES,
1194 fname,
1196 NULL,
1197 &smb_fname);
1198 if (!NT_STATUS_IS_OK(status)) {
1199 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1200 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1201 ERRSRV, ERRbadpath);
1202 goto out;
1204 reply_nterror(req, status);
1205 goto out;
1208 if (smb_fname->base_name[0] == '.' &&
1209 smb_fname->base_name[1] == '\0') {
1211 * Not sure here is the right place to catch this
1212 * condition. Might be moved to somewhere else later -- vl
1214 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1215 goto out;
1218 mode = SVAL(req->vwv+0, 0);
1219 mtime = srv_make_unix_date3(req->vwv+1);
1221 ft.mtime = convert_time_t_to_timespec(mtime);
1222 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1223 if (!NT_STATUS_IS_OK(status)) {
1224 reply_nterror(req, status);
1225 goto out;
1228 if (mode != FILE_ATTRIBUTE_NORMAL) {
1229 if (VALID_STAT_OF_DIR(smb_fname->st))
1230 mode |= aDIR;
1231 else
1232 mode &= ~aDIR;
1234 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1235 false) != 0) {
1236 reply_nterror(req, map_nt_error_from_unix(errno));
1237 goto out;
1241 reply_outbuf(req, 0, 0);
1243 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1244 mode));
1245 out:
1246 TALLOC_FREE(smb_fname);
1247 END_PROFILE(SMBsetatr);
1248 return;
1251 /****************************************************************************
1252 Reply to a dskattr.
1253 ****************************************************************************/
1255 void reply_dskattr(struct smb_request *req)
1257 connection_struct *conn = req->conn;
1258 uint64_t dfree,dsize,bsize;
1259 START_PROFILE(SMBdskattr);
1261 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1262 reply_nterror(req, map_nt_error_from_unix(errno));
1263 END_PROFILE(SMBdskattr);
1264 return;
1267 reply_outbuf(req, 5, 0);
1269 if (Protocol <= PROTOCOL_LANMAN2) {
1270 double total_space, free_space;
1271 /* we need to scale this to a number that DOS6 can handle. We
1272 use floating point so we can handle large drives on systems
1273 that don't have 64 bit integers
1275 we end up displaying a maximum of 2G to DOS systems
1277 total_space = dsize * (double)bsize;
1278 free_space = dfree * (double)bsize;
1280 dsize = (uint64_t)((total_space+63*512) / (64*512));
1281 dfree = (uint64_t)((free_space+63*512) / (64*512));
1283 if (dsize > 0xFFFF) dsize = 0xFFFF;
1284 if (dfree > 0xFFFF) dfree = 0xFFFF;
1286 SSVAL(req->outbuf,smb_vwv0,dsize);
1287 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1288 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1289 SSVAL(req->outbuf,smb_vwv3,dfree);
1290 } else {
1291 SSVAL(req->outbuf,smb_vwv0,dsize);
1292 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1293 SSVAL(req->outbuf,smb_vwv2,512);
1294 SSVAL(req->outbuf,smb_vwv3,dfree);
1297 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1299 END_PROFILE(SMBdskattr);
1300 return;
1304 * Utility function to split the filename from the directory.
1306 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1307 char **fname_dir_out,
1308 char **fname_mask_out)
1310 const char *p = NULL;
1311 char *fname_dir = NULL;
1312 char *fname_mask = NULL;
1314 p = strrchr_m(fname_in, '/');
1315 if (!p) {
1316 fname_dir = talloc_strdup(ctx, ".");
1317 fname_mask = talloc_strdup(ctx, fname_in);
1318 } else {
1319 fname_dir = talloc_strndup(ctx, fname_in,
1320 PTR_DIFF(p, fname_in));
1321 fname_mask = talloc_strdup(ctx, p+1);
1324 if (!fname_dir || !fname_mask) {
1325 TALLOC_FREE(fname_dir);
1326 TALLOC_FREE(fname_mask);
1327 return NT_STATUS_NO_MEMORY;
1330 *fname_dir_out = fname_dir;
1331 *fname_mask_out = fname_mask;
1332 return NT_STATUS_OK;
1335 /****************************************************************************
1336 Reply to a search.
1337 Can be called from SMBsearch, SMBffirst or SMBfunique.
1338 ****************************************************************************/
1340 void reply_search(struct smb_request *req)
1342 connection_struct *conn = req->conn;
1343 char *path = NULL;
1344 const char *mask = NULL;
1345 char *directory = NULL;
1346 struct smb_filename *smb_fname = NULL;
1347 char *fname = NULL;
1348 SMB_OFF_T size;
1349 uint32 mode;
1350 struct timespec date;
1351 uint32 dirtype;
1352 unsigned int numentries = 0;
1353 unsigned int maxentries = 0;
1354 bool finished = False;
1355 const char *p;
1356 int status_len;
1357 char status[21];
1358 int dptr_num= -1;
1359 bool check_descend = False;
1360 bool expect_close = False;
1361 NTSTATUS nt_status;
1362 bool mask_contains_wcard = False;
1363 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1364 TALLOC_CTX *ctx = talloc_tos();
1365 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1366 struct dptr_struct *dirptr = NULL;
1367 struct smbd_server_connection *sconn = smbd_server_conn;
1369 START_PROFILE(SMBsearch);
1371 if (req->wct < 2) {
1372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1373 goto out;
1376 if (lp_posix_pathnames()) {
1377 reply_unknown_new(req, req->cmd);
1378 goto out;
1381 /* If we were called as SMBffirst then we must expect close. */
1382 if(req->cmd == SMBffirst) {
1383 expect_close = True;
1386 reply_outbuf(req, 1, 3);
1387 maxentries = SVAL(req->vwv+0, 0);
1388 dirtype = SVAL(req->vwv+1, 0);
1389 p = (const char *)req->buf + 1;
1390 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1391 &nt_status, &mask_contains_wcard);
1392 if (!NT_STATUS_IS_OK(nt_status)) {
1393 reply_nterror(req, nt_status);
1394 goto out;
1397 p++;
1398 status_len = SVAL(p, 0);
1399 p += 2;
1401 /* dirtype &= ~aDIR; */
1403 if (status_len == 0) {
1404 nt_status = filename_convert(ctx, conn,
1405 req->flags2 & FLAGS2_DFS_PATHNAMES,
1406 path,
1407 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1408 &mask_contains_wcard,
1409 &smb_fname);
1410 if (!NT_STATUS_IS_OK(nt_status)) {
1411 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1412 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1413 ERRSRV, ERRbadpath);
1414 goto out;
1416 reply_nterror(req, nt_status);
1417 goto out;
1420 directory = smb_fname->base_name;
1422 p = strrchr_m(directory,'/');
1423 if ((p != NULL) && (*directory != '/')) {
1424 mask = p + 1;
1425 directory = talloc_strndup(ctx, directory,
1426 PTR_DIFF(p, directory));
1427 } else {
1428 mask = directory;
1429 directory = talloc_strdup(ctx,".");
1432 if (!directory) {
1433 reply_nterror(req, NT_STATUS_NO_MEMORY);
1434 goto out;
1437 memset((char *)status,'\0',21);
1438 SCVAL(status,0,(dirtype & 0x1F));
1440 nt_status = dptr_create(conn,
1441 directory,
1442 True,
1443 expect_close,
1444 req->smbpid,
1445 mask,
1446 mask_contains_wcard,
1447 dirtype,
1448 &dirptr);
1449 if (!NT_STATUS_IS_OK(nt_status)) {
1450 reply_nterror(req, nt_status);
1451 goto out;
1453 dptr_num = dptr_dnum(dirptr);
1454 } else {
1455 int status_dirtype;
1456 const char *dirpath;
1458 memcpy(status,p,21);
1459 status_dirtype = CVAL(status,0) & 0x1F;
1460 if (status_dirtype != (dirtype & 0x1F)) {
1461 dirtype = status_dirtype;
1464 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1465 if (!dirptr) {
1466 goto SearchEmpty;
1468 dirpath = dptr_path(sconn, dptr_num);
1469 directory = talloc_strdup(ctx, dirpath);
1470 if (!directory) {
1471 reply_nterror(req, NT_STATUS_NO_MEMORY);
1472 goto out;
1475 mask = dptr_wcard(sconn, dptr_num);
1476 if (!mask) {
1477 goto SearchEmpty;
1480 * For a 'continue' search we have no string. So
1481 * check from the initial saved string.
1483 mask_contains_wcard = ms_has_wild(mask);
1484 dirtype = dptr_attr(sconn, dptr_num);
1487 DEBUG(4,("dptr_num is %d\n",dptr_num));
1489 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1490 dptr_init_search_op(dirptr);
1492 if ((dirtype&0x1F) == aVOLID) {
1493 char buf[DIR_STRUCT_SIZE];
1494 memcpy(buf,status,21);
1495 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1496 0,aVOLID,0,!allow_long_path_components)) {
1497 reply_nterror(req, NT_STATUS_NO_MEMORY);
1498 goto out;
1500 dptr_fill(sconn, buf+12,dptr_num);
1501 if (dptr_zero(buf+12) && (status_len==0)) {
1502 numentries = 1;
1503 } else {
1504 numentries = 0;
1506 if (message_push_blob(&req->outbuf,
1507 data_blob_const(buf, sizeof(buf)))
1508 == -1) {
1509 reply_nterror(req, NT_STATUS_NO_MEMORY);
1510 goto out;
1512 } else {
1513 unsigned int i;
1514 maxentries = MIN(
1515 maxentries,
1516 ((BUFFER_SIZE -
1517 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1518 /DIR_STRUCT_SIZE));
1520 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1521 directory,lp_dontdescend(SNUM(conn))));
1522 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1523 check_descend = True;
1526 for (i=numentries;(i<maxentries) && !finished;i++) {
1527 finished = !get_dir_entry(ctx,
1528 dirptr,
1529 mask,
1530 dirtype,
1531 &fname,
1532 &size,
1533 &mode,
1534 &date,
1535 check_descend,
1536 ask_sharemode);
1537 if (!finished) {
1538 char buf[DIR_STRUCT_SIZE];
1539 memcpy(buf,status,21);
1540 if (!make_dir_struct(ctx,
1541 buf,
1542 mask,
1543 fname,
1544 size,
1545 mode,
1546 convert_timespec_to_time_t(date),
1547 !allow_long_path_components)) {
1548 reply_nterror(req, NT_STATUS_NO_MEMORY);
1549 goto out;
1551 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1552 break;
1554 if (message_push_blob(&req->outbuf,
1555 data_blob_const(buf, sizeof(buf)))
1556 == -1) {
1557 reply_nterror(req, NT_STATUS_NO_MEMORY);
1558 goto out;
1560 numentries++;
1565 SearchEmpty:
1567 /* If we were called as SMBffirst with smb_search_id == NULL
1568 and no entries were found then return error and close dirptr
1569 (X/Open spec) */
1571 if (numentries == 0) {
1572 dptr_close(sconn, &dptr_num);
1573 } else if(expect_close && status_len == 0) {
1574 /* Close the dptr - we know it's gone */
1575 dptr_close(sconn, &dptr_num);
1578 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1579 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1580 dptr_close(sconn, &dptr_num);
1583 if ((numentries == 0) && !mask_contains_wcard) {
1584 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1585 goto out;
1588 SSVAL(req->outbuf,smb_vwv0,numentries);
1589 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1590 SCVAL(smb_buf(req->outbuf),0,5);
1591 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1593 /* The replies here are never long name. */
1594 SSVAL(req->outbuf, smb_flg2,
1595 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1596 if (!allow_long_path_components) {
1597 SSVAL(req->outbuf, smb_flg2,
1598 SVAL(req->outbuf, smb_flg2)
1599 & (~FLAGS2_LONG_PATH_COMPONENTS));
1602 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1603 SSVAL(req->outbuf, smb_flg2,
1604 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1606 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1607 smb_fn_name(req->cmd),
1608 mask,
1609 directory,
1610 dirtype,
1611 numentries,
1612 maxentries ));
1613 out:
1614 TALLOC_FREE(directory);
1615 TALLOC_FREE(smb_fname);
1616 END_PROFILE(SMBsearch);
1617 return;
1620 /****************************************************************************
1621 Reply to a fclose (stop directory search).
1622 ****************************************************************************/
1624 void reply_fclose(struct smb_request *req)
1626 int status_len;
1627 char status[21];
1628 int dptr_num= -2;
1629 const char *p;
1630 char *path = NULL;
1631 NTSTATUS err;
1632 bool path_contains_wcard = False;
1633 TALLOC_CTX *ctx = talloc_tos();
1634 struct smbd_server_connection *sconn = smbd_server_conn;
1636 START_PROFILE(SMBfclose);
1638 if (lp_posix_pathnames()) {
1639 reply_unknown_new(req, req->cmd);
1640 END_PROFILE(SMBfclose);
1641 return;
1644 p = (const char *)req->buf + 1;
1645 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1646 &err, &path_contains_wcard);
1647 if (!NT_STATUS_IS_OK(err)) {
1648 reply_nterror(req, err);
1649 END_PROFILE(SMBfclose);
1650 return;
1652 p++;
1653 status_len = SVAL(p,0);
1654 p += 2;
1656 if (status_len == 0) {
1657 reply_doserror(req, ERRSRV, ERRsrverror);
1658 END_PROFILE(SMBfclose);
1659 return;
1662 memcpy(status,p,21);
1664 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1665 /* Close the dptr - we know it's gone */
1666 dptr_close(sconn, &dptr_num);
1669 reply_outbuf(req, 1, 0);
1670 SSVAL(req->outbuf,smb_vwv0,0);
1672 DEBUG(3,("search close\n"));
1674 END_PROFILE(SMBfclose);
1675 return;
1678 /****************************************************************************
1679 Reply to an open.
1680 ****************************************************************************/
1682 void reply_open(struct smb_request *req)
1684 connection_struct *conn = req->conn;
1685 struct smb_filename *smb_fname = NULL;
1686 char *fname = NULL;
1687 uint32 fattr=0;
1688 SMB_OFF_T size = 0;
1689 time_t mtime=0;
1690 int info;
1691 files_struct *fsp;
1692 int oplock_request;
1693 int deny_mode;
1694 uint32 dos_attr;
1695 uint32 access_mask;
1696 uint32 share_mode;
1697 uint32 create_disposition;
1698 uint32 create_options = 0;
1699 NTSTATUS status;
1700 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1701 TALLOC_CTX *ctx = talloc_tos();
1703 START_PROFILE(SMBopen);
1705 if (req->wct < 2) {
1706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1707 goto out;
1710 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1711 deny_mode = SVAL(req->vwv+0, 0);
1712 dos_attr = SVAL(req->vwv+1, 0);
1714 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1715 STR_TERMINATE, &status);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 reply_nterror(req, status);
1718 goto out;
1721 status = filename_convert(ctx,
1722 conn,
1723 req->flags2 & FLAGS2_DFS_PATHNAMES,
1724 fname,
1726 NULL,
1727 &smb_fname);
1728 if (!NT_STATUS_IS_OK(status)) {
1729 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1730 reply_botherror(req,
1731 NT_STATUS_PATH_NOT_COVERED,
1732 ERRSRV, ERRbadpath);
1733 goto out;
1735 reply_nterror(req, status);
1736 goto out;
1739 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1740 OPENX_FILE_EXISTS_OPEN, &access_mask,
1741 &share_mode, &create_disposition,
1742 &create_options)) {
1743 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1744 goto out;
1747 status = SMB_VFS_CREATE_FILE(
1748 conn, /* conn */
1749 req, /* req */
1750 0, /* root_dir_fid */
1751 smb_fname, /* fname */
1752 access_mask, /* access_mask */
1753 share_mode, /* share_access */
1754 create_disposition, /* create_disposition*/
1755 create_options, /* create_options */
1756 dos_attr, /* file_attributes */
1757 oplock_request, /* oplock_request */
1758 0, /* allocation_size */
1759 NULL, /* sd */
1760 NULL, /* ea_list */
1761 &fsp, /* result */
1762 &info); /* pinfo */
1764 if (!NT_STATUS_IS_OK(status)) {
1765 if (open_was_deferred(req->mid)) {
1766 /* We have re-scheduled this call. */
1767 goto out;
1769 reply_openerror(req, status);
1770 goto out;
1773 size = smb_fname->st.st_ex_size;
1774 fattr = dos_mode(conn, smb_fname);
1776 /* Deal with other possible opens having a modified
1777 write time. JRA. */
1778 if (ask_sharemode) {
1779 struct timespec write_time_ts;
1781 ZERO_STRUCT(write_time_ts);
1782 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1783 if (!null_timespec(write_time_ts)) {
1784 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1788 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1790 if (fattr & aDIR) {
1791 DEBUG(3,("attempt to open a directory %s\n",
1792 fsp_str_dbg(fsp)));
1793 close_file(req, fsp, ERROR_CLOSE);
1794 reply_doserror(req, ERRDOS,ERRnoaccess);
1795 goto out;
1798 reply_outbuf(req, 7, 0);
1799 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1800 SSVAL(req->outbuf,smb_vwv1,fattr);
1801 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1802 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1803 } else {
1804 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1806 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1807 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1809 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1810 SCVAL(req->outbuf,smb_flg,
1811 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1814 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1815 SCVAL(req->outbuf,smb_flg,
1816 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1818 out:
1819 TALLOC_FREE(smb_fname);
1820 END_PROFILE(SMBopen);
1821 return;
1824 /****************************************************************************
1825 Reply to an open and X.
1826 ****************************************************************************/
1828 void reply_open_and_X(struct smb_request *req)
1830 connection_struct *conn = req->conn;
1831 struct smb_filename *smb_fname = NULL;
1832 char *fname = NULL;
1833 uint16 open_flags;
1834 int deny_mode;
1835 uint32 smb_attr;
1836 /* Breakout the oplock request bits so we can set the
1837 reply bits separately. */
1838 int ex_oplock_request;
1839 int core_oplock_request;
1840 int oplock_request;
1841 #if 0
1842 int smb_sattr = SVAL(req->vwv+4, 0);
1843 uint32 smb_time = make_unix_date3(req->vwv+6);
1844 #endif
1845 int smb_ofun;
1846 uint32 fattr=0;
1847 int mtime=0;
1848 int smb_action = 0;
1849 files_struct *fsp;
1850 NTSTATUS status;
1851 uint64_t allocation_size;
1852 ssize_t retval = -1;
1853 uint32 access_mask;
1854 uint32 share_mode;
1855 uint32 create_disposition;
1856 uint32 create_options = 0;
1857 TALLOC_CTX *ctx = talloc_tos();
1859 START_PROFILE(SMBopenX);
1861 if (req->wct < 15) {
1862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1863 goto out;
1866 open_flags = SVAL(req->vwv+2, 0);
1867 deny_mode = SVAL(req->vwv+3, 0);
1868 smb_attr = SVAL(req->vwv+5, 0);
1869 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1870 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1871 oplock_request = ex_oplock_request | core_oplock_request;
1872 smb_ofun = SVAL(req->vwv+8, 0);
1873 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1875 /* If it's an IPC, pass off the pipe handler. */
1876 if (IS_IPC(conn)) {
1877 if (lp_nt_pipe_support()) {
1878 reply_open_pipe_and_X(conn, req);
1879 } else {
1880 reply_doserror(req, ERRSRV, ERRaccess);
1882 goto out;
1885 /* XXXX we need to handle passed times, sattr and flags */
1886 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1887 STR_TERMINATE, &status);
1888 if (!NT_STATUS_IS_OK(status)) {
1889 reply_nterror(req, status);
1890 goto out;
1893 status = filename_convert(ctx,
1894 conn,
1895 req->flags2 & FLAGS2_DFS_PATHNAMES,
1896 fname,
1898 NULL,
1899 &smb_fname);
1900 if (!NT_STATUS_IS_OK(status)) {
1901 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1902 reply_botherror(req,
1903 NT_STATUS_PATH_NOT_COVERED,
1904 ERRSRV, ERRbadpath);
1905 goto out;
1907 reply_nterror(req, status);
1908 goto out;
1911 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1912 &access_mask, &share_mode,
1913 &create_disposition,
1914 &create_options)) {
1915 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1916 goto out;
1919 status = SMB_VFS_CREATE_FILE(
1920 conn, /* conn */
1921 req, /* req */
1922 0, /* root_dir_fid */
1923 smb_fname, /* fname */
1924 access_mask, /* access_mask */
1925 share_mode, /* share_access */
1926 create_disposition, /* create_disposition*/
1927 create_options, /* create_options */
1928 smb_attr, /* file_attributes */
1929 oplock_request, /* oplock_request */
1930 0, /* allocation_size */
1931 NULL, /* sd */
1932 NULL, /* ea_list */
1933 &fsp, /* result */
1934 &smb_action); /* pinfo */
1936 if (!NT_STATUS_IS_OK(status)) {
1937 if (open_was_deferred(req->mid)) {
1938 /* We have re-scheduled this call. */
1939 goto out;
1941 reply_openerror(req, status);
1942 goto out;
1945 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1946 if the file is truncated or created. */
1947 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1948 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1949 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1950 close_file(req, fsp, ERROR_CLOSE);
1951 reply_nterror(req, NT_STATUS_DISK_FULL);
1952 goto out;
1954 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1955 if (retval < 0) {
1956 close_file(req, fsp, ERROR_CLOSE);
1957 reply_nterror(req, NT_STATUS_DISK_FULL);
1958 goto out;
1960 smb_fname->st.st_ex_size =
1961 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1964 fattr = dos_mode(conn, smb_fname);
1965 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1966 if (fattr & aDIR) {
1967 close_file(req, fsp, ERROR_CLOSE);
1968 reply_doserror(req, ERRDOS, ERRnoaccess);
1969 goto out;
1972 /* If the caller set the extended oplock request bit
1973 and we granted one (by whatever means) - set the
1974 correct bit for extended oplock reply.
1977 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1978 smb_action |= EXTENDED_OPLOCK_GRANTED;
1981 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1982 smb_action |= EXTENDED_OPLOCK_GRANTED;
1985 /* If the caller set the core oplock request bit
1986 and we granted one (by whatever means) - set the
1987 correct bit for core oplock reply.
1990 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1991 reply_outbuf(req, 19, 0);
1992 } else {
1993 reply_outbuf(req, 15, 0);
1996 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1997 SCVAL(req->outbuf, smb_flg,
1998 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2001 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2002 SCVAL(req->outbuf, smb_flg,
2003 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2006 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2007 SSVAL(req->outbuf,smb_vwv3,fattr);
2008 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2009 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2010 } else {
2011 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2013 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2014 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2015 SSVAL(req->outbuf,smb_vwv11,smb_action);
2017 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2018 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2021 chain_reply(req);
2022 out:
2023 TALLOC_FREE(smb_fname);
2024 END_PROFILE(SMBopenX);
2025 return;
2028 /****************************************************************************
2029 Reply to a SMBulogoffX.
2030 ****************************************************************************/
2032 void reply_ulogoffX(struct smb_request *req)
2034 struct smbd_server_connection *sconn = smbd_server_conn;
2035 user_struct *vuser;
2037 START_PROFILE(SMBulogoffX);
2039 vuser = get_valid_user_struct(sconn, req->vuid);
2041 if(vuser == NULL) {
2042 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2043 req->vuid));
2046 /* in user level security we are supposed to close any files
2047 open by this user */
2048 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2049 file_close_user(req->vuid);
2052 invalidate_vuid(sconn, req->vuid);
2054 reply_outbuf(req, 2, 0);
2056 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2058 END_PROFILE(SMBulogoffX);
2059 req->vuid = UID_FIELD_INVALID;
2060 chain_reply(req);
2063 /****************************************************************************
2064 Reply to a mknew or a create.
2065 ****************************************************************************/
2067 void reply_mknew(struct smb_request *req)
2069 connection_struct *conn = req->conn;
2070 struct smb_filename *smb_fname = NULL;
2071 char *fname = NULL;
2072 uint32 fattr = 0;
2073 struct smb_file_time ft;
2074 files_struct *fsp;
2075 int oplock_request = 0;
2076 NTSTATUS status;
2077 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2078 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2079 uint32 create_disposition;
2080 uint32 create_options = 0;
2081 TALLOC_CTX *ctx = talloc_tos();
2083 START_PROFILE(SMBcreate);
2084 ZERO_STRUCT(ft);
2086 if (req->wct < 3) {
2087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2088 goto out;
2091 fattr = SVAL(req->vwv+0, 0);
2092 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2094 /* mtime. */
2095 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2097 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2098 STR_TERMINATE, &status);
2099 if (!NT_STATUS_IS_OK(status)) {
2100 reply_nterror(req, status);
2101 goto out;
2104 status = filename_convert(ctx,
2105 conn,
2106 req->flags2 & FLAGS2_DFS_PATHNAMES,
2107 fname,
2109 NULL,
2110 &smb_fname);
2111 if (!NT_STATUS_IS_OK(status)) {
2112 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2113 reply_botherror(req,
2114 NT_STATUS_PATH_NOT_COVERED,
2115 ERRSRV, ERRbadpath);
2116 goto out;
2118 reply_nterror(req, status);
2119 goto out;
2122 if (fattr & aVOLID) {
2123 DEBUG(0,("Attempt to create file (%s) with volid set - "
2124 "please report this\n",
2125 smb_fname_str_dbg(smb_fname)));
2128 if(req->cmd == SMBmknew) {
2129 /* We should fail if file exists. */
2130 create_disposition = FILE_CREATE;
2131 } else {
2132 /* Create if file doesn't exist, truncate if it does. */
2133 create_disposition = FILE_OVERWRITE_IF;
2136 status = SMB_VFS_CREATE_FILE(
2137 conn, /* conn */
2138 req, /* req */
2139 0, /* root_dir_fid */
2140 smb_fname, /* fname */
2141 access_mask, /* access_mask */
2142 share_mode, /* share_access */
2143 create_disposition, /* create_disposition*/
2144 create_options, /* create_options */
2145 fattr, /* file_attributes */
2146 oplock_request, /* oplock_request */
2147 0, /* allocation_size */
2148 NULL, /* sd */
2149 NULL, /* ea_list */
2150 &fsp, /* result */
2151 NULL); /* pinfo */
2153 if (!NT_STATUS_IS_OK(status)) {
2154 if (open_was_deferred(req->mid)) {
2155 /* We have re-scheduled this call. */
2156 goto out;
2158 reply_openerror(req, status);
2159 goto out;
2162 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2163 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2164 if (!NT_STATUS_IS_OK(status)) {
2165 END_PROFILE(SMBcreate);
2166 goto out;
2169 reply_outbuf(req, 1, 0);
2170 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2172 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2173 SCVAL(req->outbuf,smb_flg,
2174 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2177 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2178 SCVAL(req->outbuf,smb_flg,
2179 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2182 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2183 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2184 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2185 (unsigned int)fattr));
2187 out:
2188 TALLOC_FREE(smb_fname);
2189 END_PROFILE(SMBcreate);
2190 return;
2193 /****************************************************************************
2194 Reply to a create temporary file.
2195 ****************************************************************************/
2197 void reply_ctemp(struct smb_request *req)
2199 connection_struct *conn = req->conn;
2200 struct smb_filename *smb_fname = NULL;
2201 char *fname = NULL;
2202 uint32 fattr;
2203 files_struct *fsp;
2204 int oplock_request;
2205 int tmpfd;
2206 char *s;
2207 NTSTATUS status;
2208 TALLOC_CTX *ctx = talloc_tos();
2210 START_PROFILE(SMBctemp);
2212 if (req->wct < 3) {
2213 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2214 goto out;
2217 fattr = SVAL(req->vwv+0, 0);
2218 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2220 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2221 STR_TERMINATE, &status);
2222 if (!NT_STATUS_IS_OK(status)) {
2223 reply_nterror(req, status);
2224 goto out;
2226 if (*fname) {
2227 fname = talloc_asprintf(ctx,
2228 "%s/TMXXXXXX",
2229 fname);
2230 } else {
2231 fname = talloc_strdup(ctx, "TMXXXXXX");
2234 if (!fname) {
2235 reply_nterror(req, NT_STATUS_NO_MEMORY);
2236 goto out;
2239 status = filename_convert(ctx, conn,
2240 req->flags2 & FLAGS2_DFS_PATHNAMES,
2241 fname,
2243 NULL,
2244 &smb_fname);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2247 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2248 ERRSRV, ERRbadpath);
2249 goto out;
2251 reply_nterror(req, status);
2252 goto out;
2255 tmpfd = mkstemp(smb_fname->base_name);
2256 if (tmpfd == -1) {
2257 reply_nterror(req, map_nt_error_from_unix(errno));
2258 goto out;
2261 SMB_VFS_STAT(conn, smb_fname);
2263 /* We should fail if file does not exist. */
2264 status = SMB_VFS_CREATE_FILE(
2265 conn, /* conn */
2266 req, /* req */
2267 0, /* root_dir_fid */
2268 smb_fname, /* fname */
2269 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2270 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2271 FILE_OPEN, /* create_disposition*/
2272 0, /* create_options */
2273 fattr, /* file_attributes */
2274 oplock_request, /* oplock_request */
2275 0, /* allocation_size */
2276 NULL, /* sd */
2277 NULL, /* ea_list */
2278 &fsp, /* result */
2279 NULL); /* pinfo */
2281 /* close fd from mkstemp() */
2282 close(tmpfd);
2284 if (!NT_STATUS_IS_OK(status)) {
2285 if (open_was_deferred(req->mid)) {
2286 /* We have re-scheduled this call. */
2287 goto out;
2289 reply_openerror(req, status);
2290 goto out;
2293 reply_outbuf(req, 1, 0);
2294 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2296 /* the returned filename is relative to the directory */
2297 s = strrchr_m(fsp->fsp_name->base_name, '/');
2298 if (!s) {
2299 s = fsp->fsp_name->base_name;
2300 } else {
2301 s++;
2304 #if 0
2305 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2306 thing in the byte section. JRA */
2307 SSVALS(p, 0, -1); /* what is this? not in spec */
2308 #endif
2309 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2310 == -1) {
2311 reply_nterror(req, NT_STATUS_NO_MEMORY);
2312 goto out;
2315 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2316 SCVAL(req->outbuf, smb_flg,
2317 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2320 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2321 SCVAL(req->outbuf, smb_flg,
2322 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2325 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2326 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2327 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2328 out:
2329 TALLOC_FREE(smb_fname);
2330 END_PROFILE(SMBctemp);
2331 return;
2334 /*******************************************************************
2335 Check if a user is allowed to rename a file.
2336 ********************************************************************/
2338 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2339 uint16 dirtype, SMB_STRUCT_STAT *pst)
2341 uint32 fmode;
2343 if (!CAN_WRITE(conn)) {
2344 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2347 fmode = dos_mode(conn, fsp->fsp_name);
2348 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2349 return NT_STATUS_NO_SUCH_FILE;
2352 if (S_ISDIR(pst->st_ex_mode)) {
2353 if (fsp->posix_open) {
2354 return NT_STATUS_OK;
2357 /* If no pathnames are open below this
2358 directory, allow the rename. */
2360 if (file_find_subpath(fsp)) {
2361 return NT_STATUS_ACCESS_DENIED;
2363 return NT_STATUS_OK;
2366 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2367 return NT_STATUS_OK;
2370 return NT_STATUS_ACCESS_DENIED;
2373 /*******************************************************************
2374 * unlink a file with all relevant access checks
2375 *******************************************************************/
2377 static NTSTATUS do_unlink(connection_struct *conn,
2378 struct smb_request *req,
2379 struct smb_filename *smb_fname,
2380 uint32 dirtype)
2382 uint32 fattr;
2383 files_struct *fsp;
2384 uint32 dirtype_orig = dirtype;
2385 NTSTATUS status;
2387 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2388 smb_fname_str_dbg(smb_fname),
2389 dirtype));
2391 if (!CAN_WRITE(conn)) {
2392 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2395 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
2396 return map_nt_error_from_unix(errno);
2399 fattr = dos_mode(conn, smb_fname);
2401 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2402 dirtype = aDIR|aARCH|aRONLY;
2405 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2406 if (!dirtype) {
2407 return NT_STATUS_NO_SUCH_FILE;
2410 if (!dir_check_ftype(conn, fattr, dirtype)) {
2411 if (fattr & aDIR) {
2412 return NT_STATUS_FILE_IS_A_DIRECTORY;
2414 return NT_STATUS_NO_SUCH_FILE;
2417 if (dirtype_orig & 0x8000) {
2418 /* These will never be set for POSIX. */
2419 return NT_STATUS_NO_SUCH_FILE;
2422 #if 0
2423 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2424 return NT_STATUS_FILE_IS_A_DIRECTORY;
2427 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2428 return NT_STATUS_NO_SUCH_FILE;
2431 if (dirtype & 0xFF00) {
2432 /* These will never be set for POSIX. */
2433 return NT_STATUS_NO_SUCH_FILE;
2436 dirtype &= 0xFF;
2437 if (!dirtype) {
2438 return NT_STATUS_NO_SUCH_FILE;
2441 /* Can't delete a directory. */
2442 if (fattr & aDIR) {
2443 return NT_STATUS_FILE_IS_A_DIRECTORY;
2445 #endif
2447 #if 0 /* JRATEST */
2448 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2449 return NT_STATUS_OBJECT_NAME_INVALID;
2450 #endif /* JRATEST */
2452 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2454 On a Windows share, a file with read-only dosmode can be opened with
2455 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2456 fails with NT_STATUS_CANNOT_DELETE error.
2458 This semantic causes a problem that a user can not
2459 rename a file with read-only dosmode on a Samba share
2460 from a Windows command prompt (i.e. cmd.exe, but can rename
2461 from Windows Explorer).
2464 if (!lp_delete_readonly(SNUM(conn))) {
2465 if (fattr & aRONLY) {
2466 return NT_STATUS_CANNOT_DELETE;
2470 /* On open checks the open itself will check the share mode, so
2471 don't do it here as we'll get it wrong. */
2473 status = SMB_VFS_CREATE_FILE
2474 (conn, /* conn */
2475 req, /* req */
2476 0, /* root_dir_fid */
2477 smb_fname, /* fname */
2478 DELETE_ACCESS, /* access_mask */
2479 FILE_SHARE_NONE, /* share_access */
2480 FILE_OPEN, /* create_disposition*/
2481 FILE_NON_DIRECTORY_FILE, /* create_options */
2482 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2483 0, /* oplock_request */
2484 0, /* allocation_size */
2485 NULL, /* sd */
2486 NULL, /* ea_list */
2487 &fsp, /* result */
2488 NULL); /* pinfo */
2490 if (!NT_STATUS_IS_OK(status)) {
2491 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2492 nt_errstr(status)));
2493 return status;
2496 /* The set is across all open files on this dev/inode pair. */
2497 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2498 close_file(req, fsp, NORMAL_CLOSE);
2499 return NT_STATUS_ACCESS_DENIED;
2502 return close_file(req, fsp, NORMAL_CLOSE);
2505 /****************************************************************************
2506 The guts of the unlink command, split out so it may be called by the NT SMB
2507 code.
2508 ****************************************************************************/
2510 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2511 uint32 dirtype, struct smb_filename *smb_fname,
2512 bool has_wild)
2514 char *fname_dir = NULL;
2515 char *fname_mask = NULL;
2516 int count=0;
2517 NTSTATUS status = NT_STATUS_OK;
2518 TALLOC_CTX *ctx = talloc_tos();
2520 /* Split up the directory from the filename/mask. */
2521 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2522 &fname_dir, &fname_mask);
2523 if (!NT_STATUS_IS_OK(status)) {
2524 goto out;
2528 * We should only check the mangled cache
2529 * here if unix_convert failed. This means
2530 * that the path in 'mask' doesn't exist
2531 * on the file system and so we need to look
2532 * for a possible mangle. This patch from
2533 * Tine Smukavec <valentin.smukavec@hermes.si>.
2536 if (!VALID_STAT(smb_fname->st) &&
2537 mangle_is_mangled(fname_mask, conn->params)) {
2538 char *new_mask = NULL;
2539 mangle_lookup_name_from_8_3(ctx, fname_mask,
2540 &new_mask, conn->params);
2541 if (new_mask) {
2542 TALLOC_FREE(fname_mask);
2543 fname_mask = new_mask;
2547 if (!has_wild) {
2550 * Only one file needs to be unlinked. Append the mask back
2551 * onto the directory.
2553 TALLOC_FREE(smb_fname->base_name);
2554 smb_fname->base_name = talloc_asprintf(smb_fname,
2555 "%s/%s",
2556 fname_dir,
2557 fname_mask);
2558 if (!smb_fname->base_name) {
2559 status = NT_STATUS_NO_MEMORY;
2560 goto out;
2562 if (dirtype == 0) {
2563 dirtype = FILE_ATTRIBUTE_NORMAL;
2566 status = check_name(conn, smb_fname->base_name);
2567 if (!NT_STATUS_IS_OK(status)) {
2568 goto out;
2571 status = do_unlink(conn, req, smb_fname, dirtype);
2572 if (!NT_STATUS_IS_OK(status)) {
2573 goto out;
2576 count++;
2577 } else {
2578 struct smb_Dir *dir_hnd = NULL;
2579 long offset = 0;
2580 char *dname = NULL;
2582 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2583 status = NT_STATUS_OBJECT_NAME_INVALID;
2584 goto out;
2587 if (strequal(fname_mask,"????????.???")) {
2588 TALLOC_FREE(fname_mask);
2589 fname_mask = talloc_strdup(ctx, "*");
2590 if (!fname_mask) {
2591 status = NT_STATUS_NO_MEMORY;
2592 goto out;
2596 status = check_name(conn, fname_dir);
2597 if (!NT_STATUS_IS_OK(status)) {
2598 goto out;
2601 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2602 dirtype);
2603 if (dir_hnd == NULL) {
2604 status = map_nt_error_from_unix(errno);
2605 goto out;
2608 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2609 the pattern matches against the long name, otherwise the short name
2610 We don't implement this yet XXXX
2613 status = NT_STATUS_NO_SUCH_FILE;
2615 while ((dname = ReadDirName(dir_hnd, &offset,
2616 &smb_fname->st))) {
2617 TALLOC_CTX *frame = talloc_stackframe();
2619 if (!is_visible_file(conn, fname_dir, dname,
2620 &smb_fname->st, true)) {
2621 TALLOC_FREE(frame);
2622 TALLOC_FREE(dname);
2623 continue;
2626 /* Quick check for "." and ".." */
2627 if (ISDOT(dname) || ISDOTDOT(dname)) {
2628 TALLOC_FREE(frame);
2629 TALLOC_FREE(dname);
2630 continue;
2633 if(!mask_match(dname, fname_mask,
2634 conn->case_sensitive)) {
2635 TALLOC_FREE(frame);
2636 TALLOC_FREE(dname);
2637 continue;
2640 TALLOC_FREE(smb_fname->base_name);
2641 smb_fname->base_name =
2642 talloc_asprintf(smb_fname, "%s/%s",
2643 fname_dir, dname);
2645 if (!smb_fname->base_name) {
2646 TALLOC_FREE(dir_hnd);
2647 status = NT_STATUS_NO_MEMORY;
2648 TALLOC_FREE(frame);
2649 TALLOC_FREE(dname);
2650 goto out;
2653 status = check_name(conn, smb_fname->base_name);
2654 if (!NT_STATUS_IS_OK(status)) {
2655 TALLOC_FREE(dir_hnd);
2656 TALLOC_FREE(frame);
2657 TALLOC_FREE(dname);
2658 goto out;
2661 status = do_unlink(conn, req, smb_fname, dirtype);
2662 if (!NT_STATUS_IS_OK(status)) {
2663 TALLOC_FREE(frame);
2664 TALLOC_FREE(dname);
2665 continue;
2668 count++;
2669 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2670 smb_fname->base_name));
2672 TALLOC_FREE(frame);
2673 TALLOC_FREE(dname);
2675 TALLOC_FREE(dir_hnd);
2678 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2679 status = map_nt_error_from_unix(errno);
2682 out:
2683 TALLOC_FREE(fname_dir);
2684 TALLOC_FREE(fname_mask);
2685 return status;
2688 /****************************************************************************
2689 Reply to a unlink
2690 ****************************************************************************/
2692 void reply_unlink(struct smb_request *req)
2694 connection_struct *conn = req->conn;
2695 char *name = NULL;
2696 struct smb_filename *smb_fname = NULL;
2697 uint32 dirtype;
2698 NTSTATUS status;
2699 bool path_contains_wcard = False;
2700 TALLOC_CTX *ctx = talloc_tos();
2702 START_PROFILE(SMBunlink);
2704 if (req->wct < 1) {
2705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2706 goto out;
2709 dirtype = SVAL(req->vwv+0, 0);
2711 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2712 STR_TERMINATE, &status,
2713 &path_contains_wcard);
2714 if (!NT_STATUS_IS_OK(status)) {
2715 reply_nterror(req, status);
2716 goto out;
2719 status = filename_convert(ctx, conn,
2720 req->flags2 & FLAGS2_DFS_PATHNAMES,
2721 name,
2722 UCF_COND_ALLOW_WCARD_LCOMP,
2723 &path_contains_wcard,
2724 &smb_fname);
2725 if (!NT_STATUS_IS_OK(status)) {
2726 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2727 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2728 ERRSRV, ERRbadpath);
2729 goto out;
2731 reply_nterror(req, status);
2732 goto out;
2735 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2737 status = unlink_internals(conn, req, dirtype, smb_fname,
2738 path_contains_wcard);
2739 if (!NT_STATUS_IS_OK(status)) {
2740 if (open_was_deferred(req->mid)) {
2741 /* We have re-scheduled this call. */
2742 goto out;
2744 reply_nterror(req, status);
2745 goto out;
2748 reply_outbuf(req, 0, 0);
2749 out:
2750 TALLOC_FREE(smb_fname);
2751 END_PROFILE(SMBunlink);
2752 return;
2755 /****************************************************************************
2756 Fail for readbraw.
2757 ****************************************************************************/
2759 static void fail_readraw(void)
2761 const char *errstr = talloc_asprintf(talloc_tos(),
2762 "FAIL ! reply_readbraw: socket write fail (%s)",
2763 strerror(errno));
2764 if (!errstr) {
2765 errstr = "";
2767 exit_server_cleanly(errstr);
2770 /****************************************************************************
2771 Fake (read/write) sendfile. Returns -1 on read or write fail.
2772 ****************************************************************************/
2774 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2775 size_t nread)
2777 size_t bufsize;
2778 size_t tosend = nread;
2779 char *buf;
2781 if (nread == 0) {
2782 return 0;
2785 bufsize = MIN(nread, 65536);
2787 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2788 return -1;
2791 while (tosend > 0) {
2792 ssize_t ret;
2793 size_t cur_read;
2795 if (tosend > bufsize) {
2796 cur_read = bufsize;
2797 } else {
2798 cur_read = tosend;
2800 ret = read_file(fsp,buf,startpos,cur_read);
2801 if (ret == -1) {
2802 SAFE_FREE(buf);
2803 return -1;
2806 /* If we had a short read, fill with zeros. */
2807 if (ret < cur_read) {
2808 memset(buf + ret, '\0', cur_read - ret);
2811 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2812 SAFE_FREE(buf);
2813 return -1;
2815 tosend -= cur_read;
2816 startpos += cur_read;
2819 SAFE_FREE(buf);
2820 return (ssize_t)nread;
2823 #if defined(WITH_SENDFILE)
2824 /****************************************************************************
2825 Deal with the case of sendfile reading less bytes from the file than
2826 requested. Fill with zeros (all we can do).
2827 ****************************************************************************/
2829 static void sendfile_short_send(files_struct *fsp,
2830 ssize_t nread,
2831 size_t headersize,
2832 size_t smb_maxcnt)
2834 #define SHORT_SEND_BUFSIZE 1024
2835 if (nread < headersize) {
2836 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2837 "header for file %s (%s). Terminating\n",
2838 fsp_str_dbg(fsp), strerror(errno)));
2839 exit_server_cleanly("sendfile_short_send failed");
2842 nread -= headersize;
2844 if (nread < smb_maxcnt) {
2845 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2846 if (!buf) {
2847 exit_server_cleanly("sendfile_short_send: "
2848 "malloc failed");
2851 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2852 "with zeros !\n", fsp_str_dbg(fsp)));
2854 while (nread < smb_maxcnt) {
2856 * We asked for the real file size and told sendfile
2857 * to not go beyond the end of the file. But it can
2858 * happen that in between our fstat call and the
2859 * sendfile call the file was truncated. This is very
2860 * bad because we have already announced the larger
2861 * number of bytes to the client.
2863 * The best we can do now is to send 0-bytes, just as
2864 * a read from a hole in a sparse file would do.
2866 * This should happen rarely enough that I don't care
2867 * about efficiency here :-)
2869 size_t to_write;
2871 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2872 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2873 exit_server_cleanly("sendfile_short_send: "
2874 "write_data failed");
2876 nread += to_write;
2878 SAFE_FREE(buf);
2881 #endif /* defined WITH_SENDFILE */
2883 /****************************************************************************
2884 Return a readbraw error (4 bytes of zero).
2885 ****************************************************************************/
2887 static void reply_readbraw_error(void)
2889 char header[4];
2890 SIVAL(header,0,0);
2891 if (write_data(smbd_server_fd(),header,4) != 4) {
2892 fail_readraw();
2896 /****************************************************************************
2897 Use sendfile in readbraw.
2898 ****************************************************************************/
2900 static void send_file_readbraw(connection_struct *conn,
2901 struct smb_request *req,
2902 files_struct *fsp,
2903 SMB_OFF_T startpos,
2904 size_t nread,
2905 ssize_t mincount)
2907 char *outbuf = NULL;
2908 ssize_t ret=0;
2910 #if defined(WITH_SENDFILE)
2912 * We can only use sendfile on a non-chained packet
2913 * but we can use on a non-oplocked file. tridge proved this
2914 * on a train in Germany :-). JRA.
2915 * reply_readbraw has already checked the length.
2918 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2919 (fsp->wcp == NULL) &&
2920 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2921 ssize_t sendfile_read = -1;
2922 char header[4];
2923 DATA_BLOB header_blob;
2925 _smb_setlen(header,nread);
2926 header_blob = data_blob_const(header, 4);
2928 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2929 &header_blob, startpos, nread)) == -1) {
2930 /* Returning ENOSYS means no data at all was sent.
2931 * Do this as a normal read. */
2932 if (errno == ENOSYS) {
2933 goto normal_readbraw;
2937 * Special hack for broken Linux with no working sendfile. If we
2938 * return EINTR we sent the header but not the rest of the data.
2939 * Fake this up by doing read/write calls.
2941 if (errno == EINTR) {
2942 /* Ensure we don't do this again. */
2943 set_use_sendfile(SNUM(conn), False);
2944 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2946 if (fake_sendfile(fsp, startpos, nread) == -1) {
2947 DEBUG(0,("send_file_readbraw: "
2948 "fake_sendfile failed for "
2949 "file %s (%s).\n",
2950 fsp_str_dbg(fsp),
2951 strerror(errno)));
2952 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2954 return;
2957 DEBUG(0,("send_file_readbraw: sendfile failed for "
2958 "file %s (%s). Terminating\n",
2959 fsp_str_dbg(fsp), strerror(errno)));
2960 exit_server_cleanly("send_file_readbraw sendfile failed");
2961 } else if (sendfile_read == 0) {
2963 * Some sendfile implementations return 0 to indicate
2964 * that there was a short read, but nothing was
2965 * actually written to the socket. In this case,
2966 * fallback to the normal read path so the header gets
2967 * the correct byte count.
2969 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2970 "bytes falling back to the normal read: "
2971 "%s\n", fsp_str_dbg(fsp)));
2972 goto normal_readbraw;
2975 /* Deal with possible short send. */
2976 if (sendfile_read != 4+nread) {
2977 sendfile_short_send(fsp, sendfile_read, 4, nread);
2979 return;
2982 normal_readbraw:
2983 #endif
2985 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2986 if (!outbuf) {
2987 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2988 (unsigned)(nread+4)));
2989 reply_readbraw_error();
2990 return;
2993 if (nread > 0) {
2994 ret = read_file(fsp,outbuf+4,startpos,nread);
2995 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2996 if (ret < mincount)
2997 ret = 0;
2998 #else
2999 if (ret < nread)
3000 ret = 0;
3001 #endif
3004 _smb_setlen(outbuf,ret);
3005 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3006 fail_readraw();
3008 TALLOC_FREE(outbuf);
3011 /****************************************************************************
3012 Reply to a readbraw (core+ protocol).
3013 ****************************************************************************/
3015 void reply_readbraw(struct smb_request *req)
3017 connection_struct *conn = req->conn;
3018 ssize_t maxcount,mincount;
3019 size_t nread = 0;
3020 SMB_OFF_T startpos;
3021 files_struct *fsp;
3022 struct lock_struct lock;
3023 SMB_STRUCT_STAT st;
3024 SMB_OFF_T size = 0;
3026 START_PROFILE(SMBreadbraw);
3028 if (srv_is_signing_active(smbd_server_conn) ||
3029 is_encrypted_packet(req->inbuf)) {
3030 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3031 "raw reads/writes are disallowed.");
3034 if (req->wct < 8) {
3035 reply_readbraw_error();
3036 END_PROFILE(SMBreadbraw);
3037 return;
3041 * Special check if an oplock break has been issued
3042 * and the readraw request croses on the wire, we must
3043 * return a zero length response here.
3046 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3049 * We have to do a check_fsp by hand here, as
3050 * we must always return 4 zero bytes on error,
3051 * not a NTSTATUS.
3054 if (!fsp || !conn || conn != fsp->conn ||
3055 req->vuid != fsp->vuid ||
3056 fsp->is_directory || fsp->fh->fd == -1) {
3058 * fsp could be NULL here so use the value from the packet. JRA.
3060 DEBUG(3,("reply_readbraw: fnum %d not valid "
3061 "- cache prime?\n",
3062 (int)SVAL(req->vwv+0, 0)));
3063 reply_readbraw_error();
3064 END_PROFILE(SMBreadbraw);
3065 return;
3068 /* Do a "by hand" version of CHECK_READ. */
3069 if (!(fsp->can_read ||
3070 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3071 (fsp->access_mask & FILE_EXECUTE)))) {
3072 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3073 (int)SVAL(req->vwv+0, 0)));
3074 reply_readbraw_error();
3075 END_PROFILE(SMBreadbraw);
3076 return;
3079 flush_write_cache(fsp, READRAW_FLUSH);
3081 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3082 if(req->wct == 10) {
3084 * This is a large offset (64 bit) read.
3086 #ifdef LARGE_SMB_OFF_T
3088 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3090 #else /* !LARGE_SMB_OFF_T */
3093 * Ensure we haven't been sent a >32 bit offset.
3096 if(IVAL(req->vwv+8, 0) != 0) {
3097 DEBUG(0,("reply_readbraw: large offset "
3098 "(%x << 32) used and we don't support "
3099 "64 bit offsets.\n",
3100 (unsigned int)IVAL(req->vwv+8, 0) ));
3101 reply_readbraw_error();
3102 END_PROFILE(SMBreadbraw);
3103 return;
3106 #endif /* LARGE_SMB_OFF_T */
3108 if(startpos < 0) {
3109 DEBUG(0,("reply_readbraw: negative 64 bit "
3110 "readraw offset (%.0f) !\n",
3111 (double)startpos ));
3112 reply_readbraw_error();
3113 END_PROFILE(SMBreadbraw);
3114 return;
3118 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3119 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3121 /* ensure we don't overrun the packet size */
3122 maxcount = MIN(65535,maxcount);
3124 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3125 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3126 &lock);
3128 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3129 reply_readbraw_error();
3130 END_PROFILE(SMBreadbraw);
3131 return;
3134 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3135 size = st.st_ex_size;
3138 if (startpos >= size) {
3139 nread = 0;
3140 } else {
3141 nread = MIN(maxcount,(size - startpos));
3144 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3145 if (nread < mincount)
3146 nread = 0;
3147 #endif
3149 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3150 "min=%lu nread=%lu\n",
3151 fsp->fnum, (double)startpos,
3152 (unsigned long)maxcount,
3153 (unsigned long)mincount,
3154 (unsigned long)nread ) );
3156 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3158 DEBUG(5,("reply_readbraw finished\n"));
3160 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3162 END_PROFILE(SMBreadbraw);
3163 return;
3166 #undef DBGC_CLASS
3167 #define DBGC_CLASS DBGC_LOCKING
3169 /****************************************************************************
3170 Reply to a lockread (core+ protocol).
3171 ****************************************************************************/
3173 void reply_lockread(struct smb_request *req)
3175 connection_struct *conn = req->conn;
3176 ssize_t nread = -1;
3177 char *data;
3178 SMB_OFF_T startpos;
3179 size_t numtoread;
3180 NTSTATUS status;
3181 files_struct *fsp;
3182 struct byte_range_lock *br_lck = NULL;
3183 char *p = NULL;
3184 struct smbd_server_connection *sconn = smbd_server_conn;
3186 START_PROFILE(SMBlockread);
3188 if (req->wct < 5) {
3189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3190 END_PROFILE(SMBlockread);
3191 return;
3194 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3196 if (!check_fsp(conn, req, fsp)) {
3197 END_PROFILE(SMBlockread);
3198 return;
3201 if (!CHECK_READ(fsp,req)) {
3202 reply_doserror(req, ERRDOS, ERRbadaccess);
3203 END_PROFILE(SMBlockread);
3204 return;
3207 numtoread = SVAL(req->vwv+1, 0);
3208 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3210 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3212 reply_outbuf(req, 5, numtoread + 3);
3214 data = smb_buf(req->outbuf) + 3;
3217 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3218 * protocol request that predates the read/write lock concept.
3219 * Thus instead of asking for a read lock here we need to ask
3220 * for a write lock. JRA.
3221 * Note that the requested lock size is unaffected by max_recv.
3224 br_lck = do_lock(smbd_messaging_context(),
3225 fsp,
3226 req->smbpid,
3227 (uint64_t)numtoread,
3228 (uint64_t)startpos,
3229 WRITE_LOCK,
3230 WINDOWS_LOCK,
3231 False, /* Non-blocking lock. */
3232 &status,
3233 NULL,
3234 NULL);
3235 TALLOC_FREE(br_lck);
3237 if (NT_STATUS_V(status)) {
3238 reply_nterror(req, status);
3239 END_PROFILE(SMBlockread);
3240 return;
3244 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3247 if (numtoread > sconn->smb1.negprot.max_recv) {
3248 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3249 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3250 (unsigned int)numtoread,
3251 (unsigned int)sconn->smb1.negprot.max_recv));
3252 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3254 nread = read_file(fsp,data,startpos,numtoread);
3256 if (nread < 0) {
3257 reply_nterror(req, map_nt_error_from_unix(errno));
3258 END_PROFILE(SMBlockread);
3259 return;
3262 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3264 SSVAL(req->outbuf,smb_vwv0,nread);
3265 SSVAL(req->outbuf,smb_vwv5,nread+3);
3266 p = smb_buf(req->outbuf);
3267 SCVAL(p,0,0); /* pad byte. */
3268 SSVAL(p,1,nread);
3270 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3271 fsp->fnum, (int)numtoread, (int)nread));
3273 END_PROFILE(SMBlockread);
3274 return;
3277 #undef DBGC_CLASS
3278 #define DBGC_CLASS DBGC_ALL
3280 /****************************************************************************
3281 Reply to a read.
3282 ****************************************************************************/
3284 void reply_read(struct smb_request *req)
3286 connection_struct *conn = req->conn;
3287 size_t numtoread;
3288 ssize_t nread = 0;
3289 char *data;
3290 SMB_OFF_T startpos;
3291 int outsize = 0;
3292 files_struct *fsp;
3293 struct lock_struct lock;
3294 struct smbd_server_connection *sconn = smbd_server_conn;
3296 START_PROFILE(SMBread);
3298 if (req->wct < 3) {
3299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3300 END_PROFILE(SMBread);
3301 return;
3304 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3306 if (!check_fsp(conn, req, fsp)) {
3307 END_PROFILE(SMBread);
3308 return;
3311 if (!CHECK_READ(fsp,req)) {
3312 reply_doserror(req, ERRDOS, ERRbadaccess);
3313 END_PROFILE(SMBread);
3314 return;
3317 numtoread = SVAL(req->vwv+1, 0);
3318 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3320 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3323 * The requested read size cannot be greater than max_recv. JRA.
3325 if (numtoread > sconn->smb1.negprot.max_recv) {
3326 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3327 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3328 (unsigned int)numtoread,
3329 (unsigned int)sconn->smb1.negprot.max_recv));
3330 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3333 reply_outbuf(req, 5, numtoread+3);
3335 data = smb_buf(req->outbuf) + 3;
3337 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3338 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3339 &lock);
3341 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3342 reply_doserror(req, ERRDOS,ERRlock);
3343 END_PROFILE(SMBread);
3344 return;
3347 if (numtoread > 0)
3348 nread = read_file(fsp,data,startpos,numtoread);
3350 if (nread < 0) {
3351 reply_nterror(req, map_nt_error_from_unix(errno));
3352 goto strict_unlock;
3355 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3357 SSVAL(req->outbuf,smb_vwv0,nread);
3358 SSVAL(req->outbuf,smb_vwv5,nread+3);
3359 SCVAL(smb_buf(req->outbuf),0,1);
3360 SSVAL(smb_buf(req->outbuf),1,nread);
3362 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3363 fsp->fnum, (int)numtoread, (int)nread ) );
3365 strict_unlock:
3366 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3368 END_PROFILE(SMBread);
3369 return;
3372 /****************************************************************************
3373 Setup readX header.
3374 ****************************************************************************/
3376 static int setup_readX_header(struct smb_request *req, char *outbuf,
3377 size_t smb_maxcnt)
3379 int outsize;
3380 char *data;
3382 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3383 data = smb_buf(outbuf);
3385 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3387 SCVAL(outbuf,smb_vwv0,0xFF);
3388 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3389 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3390 SSVAL(outbuf,smb_vwv6,
3391 req_wct_ofs(req)
3392 + 1 /* the wct field */
3393 + 12 * sizeof(uint16_t) /* vwv */
3394 + 2); /* the buflen field */
3395 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3396 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3397 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3398 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3399 return outsize;
3402 /****************************************************************************
3403 Reply to a read and X - possibly using sendfile.
3404 ****************************************************************************/
3406 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3407 files_struct *fsp, SMB_OFF_T startpos,
3408 size_t smb_maxcnt)
3410 SMB_STRUCT_STAT sbuf;
3411 ssize_t nread = -1;
3412 struct lock_struct lock;
3413 int saved_errno = 0;
3415 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3416 reply_nterror(req, map_nt_error_from_unix(errno));
3417 return;
3420 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3421 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3422 &lock);
3424 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3425 reply_doserror(req, ERRDOS, ERRlock);
3426 return;
3429 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3430 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3432 * We already know that we would do a short read, so don't
3433 * try the sendfile() path.
3435 goto nosendfile_read;
3438 #if defined(WITH_SENDFILE)
3440 * We can only use sendfile on a non-chained packet
3441 * but we can use on a non-oplocked file. tridge proved this
3442 * on a train in Germany :-). JRA.
3445 if (!req_is_in_chain(req) &&
3446 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3447 (fsp->wcp == NULL) &&
3448 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3449 uint8 headerbuf[smb_size + 12 * 2];
3450 DATA_BLOB header;
3453 * Set up the packet header before send. We
3454 * assume here the sendfile will work (get the
3455 * correct amount of data).
3458 header = data_blob_const(headerbuf, sizeof(headerbuf));
3460 construct_reply_common_req(req, (char *)headerbuf);
3461 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3463 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3464 /* Returning ENOSYS means no data at all was sent.
3465 Do this as a normal read. */
3466 if (errno == ENOSYS) {
3467 goto normal_read;
3471 * Special hack for broken Linux with no working sendfile. If we
3472 * return EINTR we sent the header but not the rest of the data.
3473 * Fake this up by doing read/write calls.
3476 if (errno == EINTR) {
3477 /* Ensure we don't do this again. */
3478 set_use_sendfile(SNUM(conn), False);
3479 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3480 nread = fake_sendfile(fsp, startpos,
3481 smb_maxcnt);
3482 if (nread == -1) {
3483 DEBUG(0,("send_file_readX: "
3484 "fake_sendfile failed for "
3485 "file %s (%s).\n",
3486 fsp_str_dbg(fsp),
3487 strerror(errno)));
3488 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3490 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3491 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3492 /* No outbuf here means successful sendfile. */
3493 goto strict_unlock;
3496 DEBUG(0,("send_file_readX: sendfile failed for file "
3497 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3498 strerror(errno)));
3499 exit_server_cleanly("send_file_readX sendfile failed");
3500 } else if (nread == 0) {
3502 * Some sendfile implementations return 0 to indicate
3503 * that there was a short read, but nothing was
3504 * actually written to the socket. In this case,
3505 * fallback to the normal read path so the header gets
3506 * the correct byte count.
3508 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3509 "falling back to the normal read: %s\n",
3510 fsp_str_dbg(fsp)));
3511 goto normal_read;
3514 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3515 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3517 /* Deal with possible short send. */
3518 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3519 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3521 /* No outbuf here means successful sendfile. */
3522 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3523 SMB_PERFCOUNT_END(&req->pcd);
3524 goto strict_unlock;
3527 normal_read:
3529 #endif
3531 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3532 uint8 headerbuf[smb_size + 2*12];
3534 construct_reply_common_req(req, (char *)headerbuf);
3535 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3537 /* Send out the header. */
3538 if (write_data(smbd_server_fd(), (char *)headerbuf,
3539 sizeof(headerbuf)) != sizeof(headerbuf)) {
3540 DEBUG(0,("send_file_readX: write_data failed for file "
3541 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3542 strerror(errno)));
3543 exit_server_cleanly("send_file_readX sendfile failed");
3545 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3546 if (nread == -1) {
3547 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3548 "file %s (%s).\n", fsp_str_dbg(fsp),
3549 strerror(errno)));
3550 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3552 goto strict_unlock;
3555 nosendfile_read:
3557 reply_outbuf(req, 12, smb_maxcnt);
3559 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3560 saved_errno = errno;
3562 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3564 if (nread < 0) {
3565 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3566 return;
3569 setup_readX_header(req, (char *)req->outbuf, nread);
3571 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3572 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3574 chain_reply(req);
3575 return;
3577 strict_unlock:
3578 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3579 TALLOC_FREE(req->outbuf);
3580 return;
3583 /****************************************************************************
3584 Reply to a read and X.
3585 ****************************************************************************/
3587 void reply_read_and_X(struct smb_request *req)
3589 connection_struct *conn = req->conn;
3590 files_struct *fsp;
3591 SMB_OFF_T startpos;
3592 size_t smb_maxcnt;
3593 bool big_readX = False;
3594 #if 0
3595 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3596 #endif
3598 START_PROFILE(SMBreadX);
3600 if ((req->wct != 10) && (req->wct != 12)) {
3601 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3602 return;
3605 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3606 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3607 smb_maxcnt = SVAL(req->vwv+5, 0);
3609 /* If it's an IPC, pass off the pipe handler. */
3610 if (IS_IPC(conn)) {
3611 reply_pipe_read_and_X(req);
3612 END_PROFILE(SMBreadX);
3613 return;
3616 if (!check_fsp(conn, req, fsp)) {
3617 END_PROFILE(SMBreadX);
3618 return;
3621 if (!CHECK_READ(fsp,req)) {
3622 reply_doserror(req, ERRDOS,ERRbadaccess);
3623 END_PROFILE(SMBreadX);
3624 return;
3627 if (global_client_caps & CAP_LARGE_READX) {
3628 size_t upper_size = SVAL(req->vwv+7, 0);
3629 smb_maxcnt |= (upper_size<<16);
3630 if (upper_size > 1) {
3631 /* Can't do this on a chained packet. */
3632 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3633 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3634 END_PROFILE(SMBreadX);
3635 return;
3637 /* We currently don't do this on signed or sealed data. */
3638 if (srv_is_signing_active(smbd_server_conn) ||
3639 is_encrypted_packet(req->inbuf)) {
3640 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3641 END_PROFILE(SMBreadX);
3642 return;
3644 /* Is there room in the reply for this data ? */
3645 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3646 reply_nterror(req,
3647 NT_STATUS_INVALID_PARAMETER);
3648 END_PROFILE(SMBreadX);
3649 return;
3651 big_readX = True;
3655 if (req->wct == 12) {
3656 #ifdef LARGE_SMB_OFF_T
3658 * This is a large offset (64 bit) read.
3660 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3662 #else /* !LARGE_SMB_OFF_T */
3665 * Ensure we haven't been sent a >32 bit offset.
3668 if(IVAL(req->vwv+10, 0) != 0) {
3669 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3670 "used and we don't support 64 bit offsets.\n",
3671 (unsigned int)IVAL(req->vwv+10, 0) ));
3672 END_PROFILE(SMBreadX);
3673 reply_doserror(req, ERRDOS, ERRbadaccess);
3674 return;
3677 #endif /* LARGE_SMB_OFF_T */
3681 if (!big_readX &&
3682 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3683 goto out;
3686 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3688 out:
3689 END_PROFILE(SMBreadX);
3690 return;
3693 /****************************************************************************
3694 Error replies to writebraw must have smb_wct == 1. Fix this up.
3695 ****************************************************************************/
3697 void error_to_writebrawerr(struct smb_request *req)
3699 uint8 *old_outbuf = req->outbuf;
3701 reply_outbuf(req, 1, 0);
3703 memcpy(req->outbuf, old_outbuf, smb_size);
3704 TALLOC_FREE(old_outbuf);
3707 /****************************************************************************
3708 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3709 ****************************************************************************/
3711 void reply_writebraw(struct smb_request *req)
3713 connection_struct *conn = req->conn;
3714 char *buf = NULL;
3715 ssize_t nwritten=0;
3716 ssize_t total_written=0;
3717 size_t numtowrite=0;
3718 size_t tcount;
3719 SMB_OFF_T startpos;
3720 char *data=NULL;
3721 bool write_through;
3722 files_struct *fsp;
3723 struct lock_struct lock;
3724 NTSTATUS status;
3726 START_PROFILE(SMBwritebraw);
3729 * If we ever reply with an error, it must have the SMB command
3730 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3731 * we're finished.
3733 SCVAL(req->inbuf,smb_com,SMBwritec);
3735 if (srv_is_signing_active(smbd_server_conn)) {
3736 END_PROFILE(SMBwritebraw);
3737 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3738 "raw reads/writes are disallowed.");
3741 if (req->wct < 12) {
3742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3743 error_to_writebrawerr(req);
3744 END_PROFILE(SMBwritebraw);
3745 return;
3748 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3749 if (!check_fsp(conn, req, fsp)) {
3750 error_to_writebrawerr(req);
3751 END_PROFILE(SMBwritebraw);
3752 return;
3755 if (!CHECK_WRITE(fsp)) {
3756 reply_doserror(req, ERRDOS, ERRbadaccess);
3757 error_to_writebrawerr(req);
3758 END_PROFILE(SMBwritebraw);
3759 return;
3762 tcount = IVAL(req->vwv+1, 0);
3763 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3764 write_through = BITSETW(req->vwv+7,0);
3766 /* We have to deal with slightly different formats depending
3767 on whether we are using the core+ or lanman1.0 protocol */
3769 if(Protocol <= PROTOCOL_COREPLUS) {
3770 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3771 data = smb_buf(req->inbuf);
3772 } else {
3773 numtowrite = SVAL(req->vwv+10, 0);
3774 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3777 /* Ensure we don't write bytes past the end of this packet. */
3778 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3780 error_to_writebrawerr(req);
3781 END_PROFILE(SMBwritebraw);
3782 return;
3785 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3786 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3787 &lock);
3789 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3790 reply_doserror(req, ERRDOS, ERRlock);
3791 error_to_writebrawerr(req);
3792 END_PROFILE(SMBwritebraw);
3793 return;
3796 if (numtowrite>0) {
3797 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3800 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3801 "wrote=%d sync=%d\n",
3802 fsp->fnum, (double)startpos, (int)numtowrite,
3803 (int)nwritten, (int)write_through));
3805 if (nwritten < (ssize_t)numtowrite) {
3806 reply_doserror(req, ERRHRD, ERRdiskfull);
3807 error_to_writebrawerr(req);
3808 goto strict_unlock;
3811 total_written = nwritten;
3813 /* Allocate a buffer of 64k + length. */
3814 buf = TALLOC_ARRAY(NULL, char, 65540);
3815 if (!buf) {
3816 reply_doserror(req, ERRDOS, ERRnomem);
3817 error_to_writebrawerr(req);
3818 goto strict_unlock;
3821 /* Return a SMBwritebraw message to the redirector to tell
3822 * it to send more bytes */
3824 memcpy(buf, req->inbuf, smb_size);
3825 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3826 SCVAL(buf,smb_com,SMBwritebraw);
3827 SSVALS(buf,smb_vwv0,0xFFFF);
3828 show_msg(buf);
3829 if (!srv_send_smb(smbd_server_fd(),
3830 buf,
3831 false, 0, /* no signing */
3832 IS_CONN_ENCRYPTED(conn),
3833 &req->pcd)) {
3834 exit_server_cleanly("reply_writebraw: srv_send_smb "
3835 "failed.");
3838 /* Now read the raw data into the buffer and write it */
3839 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3840 &numtowrite);
3841 if (!NT_STATUS_IS_OK(status)) {
3842 exit_server_cleanly("secondary writebraw failed");
3845 /* Set up outbuf to return the correct size */
3846 reply_outbuf(req, 1, 0);
3848 if (numtowrite != 0) {
3850 if (numtowrite > 0xFFFF) {
3851 DEBUG(0,("reply_writebraw: Oversize secondary write "
3852 "raw requested (%u). Terminating\n",
3853 (unsigned int)numtowrite ));
3854 exit_server_cleanly("secondary writebraw failed");
3857 if (tcount > nwritten+numtowrite) {
3858 DEBUG(3,("reply_writebraw: Client overestimated the "
3859 "write %d %d %d\n",
3860 (int)tcount,(int)nwritten,(int)numtowrite));
3863 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3865 if (!NT_STATUS_IS_OK(status)) {
3866 DEBUG(0,("reply_writebraw: Oversize secondary write "
3867 "raw read failed (%s). Terminating\n",
3868 nt_errstr(status)));
3869 exit_server_cleanly("secondary writebraw failed");
3872 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3873 if (nwritten == -1) {
3874 TALLOC_FREE(buf);
3875 reply_nterror(req, map_nt_error_from_unix(errno));
3876 error_to_writebrawerr(req);
3877 goto strict_unlock;
3880 if (nwritten < (ssize_t)numtowrite) {
3881 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3882 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3885 if (nwritten > 0) {
3886 total_written += nwritten;
3890 TALLOC_FREE(buf);
3891 SSVAL(req->outbuf,smb_vwv0,total_written);
3893 status = sync_file(conn, fsp, write_through);
3894 if (!NT_STATUS_IS_OK(status)) {
3895 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3896 fsp_str_dbg(fsp), nt_errstr(status)));
3897 reply_nterror(req, status);
3898 error_to_writebrawerr(req);
3899 goto strict_unlock;
3902 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3903 "wrote=%d\n",
3904 fsp->fnum, (double)startpos, (int)numtowrite,
3905 (int)total_written));
3907 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3909 /* We won't return a status if write through is not selected - this
3910 * follows what WfWg does */
3911 END_PROFILE(SMBwritebraw);
3913 if (!write_through && total_written==tcount) {
3915 #if RABBIT_PELLET_FIX
3917 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3918 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3919 * JRA.
3921 if (!send_keepalive(smbd_server_fd())) {
3922 exit_server_cleanly("reply_writebraw: send of "
3923 "keepalive failed");
3925 #endif
3926 TALLOC_FREE(req->outbuf);
3928 return;
3930 strict_unlock:
3931 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3933 END_PROFILE(SMBwritebraw);
3934 return;
3937 #undef DBGC_CLASS
3938 #define DBGC_CLASS DBGC_LOCKING
3940 /****************************************************************************
3941 Reply to a writeunlock (core+).
3942 ****************************************************************************/
3944 void reply_writeunlock(struct smb_request *req)
3946 connection_struct *conn = req->conn;
3947 ssize_t nwritten = -1;
3948 size_t numtowrite;
3949 SMB_OFF_T startpos;
3950 const char *data;
3951 NTSTATUS status = NT_STATUS_OK;
3952 files_struct *fsp;
3953 struct lock_struct lock;
3954 int saved_errno = 0;
3956 START_PROFILE(SMBwriteunlock);
3958 if (req->wct < 5) {
3959 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3960 END_PROFILE(SMBwriteunlock);
3961 return;
3964 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3966 if (!check_fsp(conn, req, fsp)) {
3967 END_PROFILE(SMBwriteunlock);
3968 return;
3971 if (!CHECK_WRITE(fsp)) {
3972 reply_doserror(req, ERRDOS,ERRbadaccess);
3973 END_PROFILE(SMBwriteunlock);
3974 return;
3977 numtowrite = SVAL(req->vwv+1, 0);
3978 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3979 data = (const char *)req->buf + 3;
3981 if (numtowrite) {
3982 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3983 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3984 &lock);
3986 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3987 reply_doserror(req, ERRDOS, ERRlock);
3988 END_PROFILE(SMBwriteunlock);
3989 return;
3993 /* The special X/Open SMB protocol handling of
3994 zero length writes is *NOT* done for
3995 this call */
3996 if(numtowrite == 0) {
3997 nwritten = 0;
3998 } else {
3999 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4000 saved_errno = errno;
4003 status = sync_file(conn, fsp, False /* write through */);
4004 if (!NT_STATUS_IS_OK(status)) {
4005 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4006 fsp_str_dbg(fsp), nt_errstr(status)));
4007 reply_nterror(req, status);
4008 goto strict_unlock;
4011 if(nwritten < 0) {
4012 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4013 goto strict_unlock;
4016 if((nwritten < numtowrite) && (numtowrite != 0)) {
4017 reply_doserror(req, ERRHRD, ERRdiskfull);
4018 goto strict_unlock;
4021 if (numtowrite) {
4022 status = do_unlock(smbd_messaging_context(),
4023 fsp,
4024 req->smbpid,
4025 (uint64_t)numtowrite,
4026 (uint64_t)startpos,
4027 WINDOWS_LOCK);
4029 if (NT_STATUS_V(status)) {
4030 reply_nterror(req, status);
4031 goto strict_unlock;
4035 reply_outbuf(req, 1, 0);
4037 SSVAL(req->outbuf,smb_vwv0,nwritten);
4039 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4040 fsp->fnum, (int)numtowrite, (int)nwritten));
4042 strict_unlock:
4043 if (numtowrite) {
4044 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4047 END_PROFILE(SMBwriteunlock);
4048 return;
4051 #undef DBGC_CLASS
4052 #define DBGC_CLASS DBGC_ALL
4054 /****************************************************************************
4055 Reply to a write.
4056 ****************************************************************************/
4058 void reply_write(struct smb_request *req)
4060 connection_struct *conn = req->conn;
4061 size_t numtowrite;
4062 ssize_t nwritten = -1;
4063 SMB_OFF_T startpos;
4064 const char *data;
4065 files_struct *fsp;
4066 struct lock_struct lock;
4067 NTSTATUS status;
4068 int saved_errno = 0;
4070 START_PROFILE(SMBwrite);
4072 if (req->wct < 5) {
4073 END_PROFILE(SMBwrite);
4074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4075 return;
4078 /* If it's an IPC, pass off the pipe handler. */
4079 if (IS_IPC(conn)) {
4080 reply_pipe_write(req);
4081 END_PROFILE(SMBwrite);
4082 return;
4085 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4087 if (!check_fsp(conn, req, fsp)) {
4088 END_PROFILE(SMBwrite);
4089 return;
4092 if (!CHECK_WRITE(fsp)) {
4093 reply_doserror(req, ERRDOS, ERRbadaccess);
4094 END_PROFILE(SMBwrite);
4095 return;
4098 numtowrite = SVAL(req->vwv+1, 0);
4099 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4100 data = (const char *)req->buf + 3;
4102 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4103 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4104 &lock);
4106 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4107 reply_doserror(req, ERRDOS, ERRlock);
4108 END_PROFILE(SMBwrite);
4109 return;
4113 * X/Open SMB protocol says that if smb_vwv1 is
4114 * zero then the file size should be extended or
4115 * truncated to the size given in smb_vwv[2-3].
4118 if(numtowrite == 0) {
4120 * This is actually an allocate call, and set EOF. JRA.
4122 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4123 if (nwritten < 0) {
4124 reply_nterror(req, NT_STATUS_DISK_FULL);
4125 goto strict_unlock;
4127 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4128 if (nwritten < 0) {
4129 reply_nterror(req, NT_STATUS_DISK_FULL);
4130 goto strict_unlock;
4132 trigger_write_time_update_immediate(fsp);
4133 } else {
4134 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4137 status = sync_file(conn, fsp, False);
4138 if (!NT_STATUS_IS_OK(status)) {
4139 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4140 fsp_str_dbg(fsp), nt_errstr(status)));
4141 reply_nterror(req, status);
4142 goto strict_unlock;
4145 if(nwritten < 0) {
4146 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4147 goto strict_unlock;
4150 if((nwritten == 0) && (numtowrite != 0)) {
4151 reply_doserror(req, ERRHRD, ERRdiskfull);
4152 goto strict_unlock;
4155 reply_outbuf(req, 1, 0);
4157 SSVAL(req->outbuf,smb_vwv0,nwritten);
4159 if (nwritten < (ssize_t)numtowrite) {
4160 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4161 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4164 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4166 strict_unlock:
4167 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4169 END_PROFILE(SMBwrite);
4170 return;
4173 /****************************************************************************
4174 Ensure a buffer is a valid writeX for recvfile purposes.
4175 ****************************************************************************/
4177 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4178 (2*14) + /* word count (including bcc) */ \
4179 1 /* pad byte */)
4181 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4183 size_t numtowrite;
4184 connection_struct *conn = NULL;
4185 unsigned int doff = 0;
4186 size_t len = smb_len_large(inbuf);
4187 struct smbd_server_connection *sconn = smbd_server_conn;
4189 if (is_encrypted_packet(inbuf)) {
4190 /* Can't do this on encrypted
4191 * connections. */
4192 return false;
4195 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4196 return false;
4199 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4200 CVAL(inbuf,smb_wct) != 14) {
4201 DEBUG(10,("is_valid_writeX_buffer: chained or "
4202 "invalid word length.\n"));
4203 return false;
4206 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4207 if (conn == NULL) {
4208 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4209 return false;
4211 if (IS_IPC(conn)) {
4212 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4213 return false;
4215 if (IS_PRINT(conn)) {
4216 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4217 return false;
4219 doff = SVAL(inbuf,smb_vwv11);
4221 numtowrite = SVAL(inbuf,smb_vwv10);
4223 if (len > doff && len - doff > 0xFFFF) {
4224 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4227 if (numtowrite == 0) {
4228 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4229 return false;
4232 /* Ensure the sizes match up. */
4233 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4234 /* no pad byte...old smbclient :-( */
4235 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4236 (unsigned int)doff,
4237 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4238 return false;
4241 if (len - doff != numtowrite) {
4242 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4243 "len = %u, doff = %u, numtowrite = %u\n",
4244 (unsigned int)len,
4245 (unsigned int)doff,
4246 (unsigned int)numtowrite ));
4247 return false;
4250 DEBUG(10,("is_valid_writeX_buffer: true "
4251 "len = %u, doff = %u, numtowrite = %u\n",
4252 (unsigned int)len,
4253 (unsigned int)doff,
4254 (unsigned int)numtowrite ));
4256 return true;
4259 /****************************************************************************
4260 Reply to a write and X.
4261 ****************************************************************************/
4263 void reply_write_and_X(struct smb_request *req)
4265 connection_struct *conn = req->conn;
4266 files_struct *fsp;
4267 struct lock_struct lock;
4268 SMB_OFF_T startpos;
4269 size_t numtowrite;
4270 bool write_through;
4271 ssize_t nwritten;
4272 unsigned int smb_doff;
4273 unsigned int smblen;
4274 char *data;
4275 NTSTATUS status;
4277 START_PROFILE(SMBwriteX);
4279 if ((req->wct != 12) && (req->wct != 14)) {
4280 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4281 END_PROFILE(SMBwriteX);
4282 return;
4285 numtowrite = SVAL(req->vwv+10, 0);
4286 smb_doff = SVAL(req->vwv+11, 0);
4287 smblen = smb_len(req->inbuf);
4289 if (req->unread_bytes > 0xFFFF ||
4290 (smblen > smb_doff &&
4291 smblen - smb_doff > 0xFFFF)) {
4292 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4295 if (req->unread_bytes) {
4296 /* Can't do a recvfile write on IPC$ */
4297 if (IS_IPC(conn)) {
4298 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4299 END_PROFILE(SMBwriteX);
4300 return;
4302 if (numtowrite != req->unread_bytes) {
4303 reply_doserror(req, ERRDOS, ERRbadmem);
4304 END_PROFILE(SMBwriteX);
4305 return;
4307 } else {
4308 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4309 smb_doff + numtowrite > smblen) {
4310 reply_doserror(req, ERRDOS, ERRbadmem);
4311 END_PROFILE(SMBwriteX);
4312 return;
4316 /* If it's an IPC, pass off the pipe handler. */
4317 if (IS_IPC(conn)) {
4318 if (req->unread_bytes) {
4319 reply_doserror(req, ERRDOS, ERRbadmem);
4320 END_PROFILE(SMBwriteX);
4321 return;
4323 reply_pipe_write_and_X(req);
4324 END_PROFILE(SMBwriteX);
4325 return;
4328 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4329 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4330 write_through = BITSETW(req->vwv+7,0);
4332 if (!check_fsp(conn, req, fsp)) {
4333 END_PROFILE(SMBwriteX);
4334 return;
4337 if (!CHECK_WRITE(fsp)) {
4338 reply_doserror(req, ERRDOS, ERRbadaccess);
4339 END_PROFILE(SMBwriteX);
4340 return;
4343 data = smb_base(req->inbuf) + smb_doff;
4345 if(req->wct == 14) {
4346 #ifdef LARGE_SMB_OFF_T
4348 * This is a large offset (64 bit) write.
4350 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4352 #else /* !LARGE_SMB_OFF_T */
4355 * Ensure we haven't been sent a >32 bit offset.
4358 if(IVAL(req->vwv+12, 0) != 0) {
4359 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4360 "used and we don't support 64 bit offsets.\n",
4361 (unsigned int)IVAL(req->vwv+12, 0) ));
4362 reply_doserror(req, ERRDOS, ERRbadaccess);
4363 END_PROFILE(SMBwriteX);
4364 return;
4367 #endif /* LARGE_SMB_OFF_T */
4370 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4371 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4372 &lock);
4374 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4375 reply_doserror(req, ERRDOS, ERRlock);
4376 END_PROFILE(SMBwriteX);
4377 return;
4380 /* X/Open SMB protocol says that, unlike SMBwrite
4381 if the length is zero then NO truncation is
4382 done, just a write of zero. To truncate a file,
4383 use SMBwrite. */
4385 if(numtowrite == 0) {
4386 nwritten = 0;
4387 } else {
4389 if ((req->unread_bytes == 0) &&
4390 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4391 numtowrite)) {
4392 goto strict_unlock;
4395 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4398 if(nwritten < 0) {
4399 reply_nterror(req, map_nt_error_from_unix(errno));
4400 goto strict_unlock;
4403 if((nwritten == 0) && (numtowrite != 0)) {
4404 reply_doserror(req, ERRHRD, ERRdiskfull);
4405 goto strict_unlock;
4408 reply_outbuf(req, 6, 0);
4409 SSVAL(req->outbuf,smb_vwv2,nwritten);
4410 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4412 if (nwritten < (ssize_t)numtowrite) {
4413 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4414 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4417 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4418 fsp->fnum, (int)numtowrite, (int)nwritten));
4420 status = sync_file(conn, fsp, write_through);
4421 if (!NT_STATUS_IS_OK(status)) {
4422 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4423 fsp_str_dbg(fsp), nt_errstr(status)));
4424 reply_nterror(req, status);
4425 goto strict_unlock;
4428 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4430 END_PROFILE(SMBwriteX);
4431 chain_reply(req);
4432 return;
4434 strict_unlock:
4435 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4437 END_PROFILE(SMBwriteX);
4438 return;
4441 /****************************************************************************
4442 Reply to a lseek.
4443 ****************************************************************************/
4445 void reply_lseek(struct smb_request *req)
4447 connection_struct *conn = req->conn;
4448 SMB_OFF_T startpos;
4449 SMB_OFF_T res= -1;
4450 int mode,umode;
4451 files_struct *fsp;
4453 START_PROFILE(SMBlseek);
4455 if (req->wct < 4) {
4456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4457 END_PROFILE(SMBlseek);
4458 return;
4461 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4463 if (!check_fsp(conn, req, fsp)) {
4464 return;
4467 flush_write_cache(fsp, SEEK_FLUSH);
4469 mode = SVAL(req->vwv+1, 0) & 3;
4470 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4471 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4473 switch (mode) {
4474 case 0:
4475 umode = SEEK_SET;
4476 res = startpos;
4477 break;
4478 case 1:
4479 umode = SEEK_CUR;
4480 res = fsp->fh->pos + startpos;
4481 break;
4482 case 2:
4483 umode = SEEK_END;
4484 break;
4485 default:
4486 umode = SEEK_SET;
4487 res = startpos;
4488 break;
4491 if (umode == SEEK_END) {
4492 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4493 if(errno == EINVAL) {
4494 SMB_OFF_T current_pos = startpos;
4495 SMB_STRUCT_STAT sbuf;
4497 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4498 reply_nterror(req,
4499 map_nt_error_from_unix(errno));
4500 END_PROFILE(SMBlseek);
4501 return;
4504 current_pos += sbuf.st_ex_size;
4505 if(current_pos < 0)
4506 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4510 if(res == -1) {
4511 reply_nterror(req, map_nt_error_from_unix(errno));
4512 END_PROFILE(SMBlseek);
4513 return;
4517 fsp->fh->pos = res;
4519 reply_outbuf(req, 2, 0);
4520 SIVAL(req->outbuf,smb_vwv0,res);
4522 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4523 fsp->fnum, (double)startpos, (double)res, mode));
4525 END_PROFILE(SMBlseek);
4526 return;
4529 /****************************************************************************
4530 Reply to a flush.
4531 ****************************************************************************/
4533 void reply_flush(struct smb_request *req)
4535 connection_struct *conn = req->conn;
4536 uint16 fnum;
4537 files_struct *fsp;
4539 START_PROFILE(SMBflush);
4541 if (req->wct < 1) {
4542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4543 return;
4546 fnum = SVAL(req->vwv+0, 0);
4547 fsp = file_fsp(req, fnum);
4549 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4550 return;
4553 if (!fsp) {
4554 file_sync_all(conn);
4555 } else {
4556 NTSTATUS status = sync_file(conn, fsp, True);
4557 if (!NT_STATUS_IS_OK(status)) {
4558 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4559 fsp_str_dbg(fsp), nt_errstr(status)));
4560 reply_nterror(req, status);
4561 END_PROFILE(SMBflush);
4562 return;
4566 reply_outbuf(req, 0, 0);
4568 DEBUG(3,("flush\n"));
4569 END_PROFILE(SMBflush);
4570 return;
4573 /****************************************************************************
4574 Reply to a exit.
4575 conn POINTER CAN BE NULL HERE !
4576 ****************************************************************************/
4578 void reply_exit(struct smb_request *req)
4580 START_PROFILE(SMBexit);
4582 file_close_pid(req->smbpid, req->vuid);
4584 reply_outbuf(req, 0, 0);
4586 DEBUG(3,("exit\n"));
4588 END_PROFILE(SMBexit);
4589 return;
4592 /****************************************************************************
4593 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4594 ****************************************************************************/
4596 void reply_close(struct smb_request *req)
4598 connection_struct *conn = req->conn;
4599 NTSTATUS status = NT_STATUS_OK;
4600 files_struct *fsp = NULL;
4601 START_PROFILE(SMBclose);
4603 if (req->wct < 3) {
4604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4605 END_PROFILE(SMBclose);
4606 return;
4609 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4612 * We can only use check_fsp if we know it's not a directory.
4615 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4616 reply_doserror(req, ERRDOS, ERRbadfid);
4617 END_PROFILE(SMBclose);
4618 return;
4621 if(fsp->is_directory) {
4623 * Special case - close NT SMB directory handle.
4625 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4626 status = close_file(req, fsp, NORMAL_CLOSE);
4627 } else {
4628 time_t t;
4630 * Close ordinary file.
4633 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4634 fsp->fh->fd, fsp->fnum,
4635 conn->num_files_open));
4638 * Take care of any time sent in the close.
4641 t = srv_make_unix_date3(req->vwv+1);
4642 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4645 * close_file() returns the unix errno if an error
4646 * was detected on close - normally this is due to
4647 * a disk full error. If not then it was probably an I/O error.
4650 status = close_file(req, fsp, NORMAL_CLOSE);
4653 if (!NT_STATUS_IS_OK(status)) {
4654 reply_nterror(req, status);
4655 END_PROFILE(SMBclose);
4656 return;
4659 reply_outbuf(req, 0, 0);
4660 END_PROFILE(SMBclose);
4661 return;
4664 /****************************************************************************
4665 Reply to a writeclose (Core+ protocol).
4666 ****************************************************************************/
4668 void reply_writeclose(struct smb_request *req)
4670 connection_struct *conn = req->conn;
4671 size_t numtowrite;
4672 ssize_t nwritten = -1;
4673 NTSTATUS close_status = NT_STATUS_OK;
4674 SMB_OFF_T startpos;
4675 const char *data;
4676 struct timespec mtime;
4677 files_struct *fsp;
4678 struct lock_struct lock;
4680 START_PROFILE(SMBwriteclose);
4682 if (req->wct < 6) {
4683 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4684 END_PROFILE(SMBwriteclose);
4685 return;
4688 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4690 if (!check_fsp(conn, req, fsp)) {
4691 END_PROFILE(SMBwriteclose);
4692 return;
4694 if (!CHECK_WRITE(fsp)) {
4695 reply_doserror(req, ERRDOS,ERRbadaccess);
4696 END_PROFILE(SMBwriteclose);
4697 return;
4700 numtowrite = SVAL(req->vwv+1, 0);
4701 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4702 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4703 data = (const char *)req->buf + 1;
4705 if (numtowrite) {
4706 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4707 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4708 &lock);
4710 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4711 reply_doserror(req, ERRDOS,ERRlock);
4712 END_PROFILE(SMBwriteclose);
4713 return;
4717 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4719 set_close_write_time(fsp, mtime);
4722 * More insanity. W2K only closes the file if writelen > 0.
4723 * JRA.
4726 if (numtowrite) {
4727 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4728 "file %s\n", fsp_str_dbg(fsp)));
4729 close_status = close_file(req, fsp, NORMAL_CLOSE);
4732 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4733 fsp->fnum, (int)numtowrite, (int)nwritten,
4734 conn->num_files_open));
4736 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4737 reply_doserror(req, ERRHRD, ERRdiskfull);
4738 goto strict_unlock;
4741 if(!NT_STATUS_IS_OK(close_status)) {
4742 reply_nterror(req, close_status);
4743 goto strict_unlock;
4746 reply_outbuf(req, 1, 0);
4748 SSVAL(req->outbuf,smb_vwv0,nwritten);
4750 strict_unlock:
4751 if (numtowrite) {
4752 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4755 END_PROFILE(SMBwriteclose);
4756 return;
4759 #undef DBGC_CLASS
4760 #define DBGC_CLASS DBGC_LOCKING
4762 /****************************************************************************
4763 Reply to a lock.
4764 ****************************************************************************/
4766 void reply_lock(struct smb_request *req)
4768 connection_struct *conn = req->conn;
4769 uint64_t count,offset;
4770 NTSTATUS status;
4771 files_struct *fsp;
4772 struct byte_range_lock *br_lck = NULL;
4774 START_PROFILE(SMBlock);
4776 if (req->wct < 5) {
4777 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4778 END_PROFILE(SMBlock);
4779 return;
4782 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4784 if (!check_fsp(conn, req, fsp)) {
4785 END_PROFILE(SMBlock);
4786 return;
4789 count = (uint64_t)IVAL(req->vwv+1, 0);
4790 offset = (uint64_t)IVAL(req->vwv+3, 0);
4792 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4793 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4795 br_lck = do_lock(smbd_messaging_context(),
4796 fsp,
4797 req->smbpid,
4798 count,
4799 offset,
4800 WRITE_LOCK,
4801 WINDOWS_LOCK,
4802 False, /* Non-blocking lock. */
4803 &status,
4804 NULL,
4805 NULL);
4807 TALLOC_FREE(br_lck);
4809 if (NT_STATUS_V(status)) {
4810 reply_nterror(req, status);
4811 END_PROFILE(SMBlock);
4812 return;
4815 reply_outbuf(req, 0, 0);
4817 END_PROFILE(SMBlock);
4818 return;
4821 /****************************************************************************
4822 Reply to a unlock.
4823 ****************************************************************************/
4825 void reply_unlock(struct smb_request *req)
4827 connection_struct *conn = req->conn;
4828 uint64_t count,offset;
4829 NTSTATUS status;
4830 files_struct *fsp;
4832 START_PROFILE(SMBunlock);
4834 if (req->wct < 5) {
4835 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4836 END_PROFILE(SMBunlock);
4837 return;
4840 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4842 if (!check_fsp(conn, req, fsp)) {
4843 END_PROFILE(SMBunlock);
4844 return;
4847 count = (uint64_t)IVAL(req->vwv+1, 0);
4848 offset = (uint64_t)IVAL(req->vwv+3, 0);
4850 status = do_unlock(smbd_messaging_context(),
4851 fsp,
4852 req->smbpid,
4853 count,
4854 offset,
4855 WINDOWS_LOCK);
4857 if (NT_STATUS_V(status)) {
4858 reply_nterror(req, status);
4859 END_PROFILE(SMBunlock);
4860 return;
4863 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4864 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4866 reply_outbuf(req, 0, 0);
4868 END_PROFILE(SMBunlock);
4869 return;
4872 #undef DBGC_CLASS
4873 #define DBGC_CLASS DBGC_ALL
4875 /****************************************************************************
4876 Reply to a tdis.
4877 conn POINTER CAN BE NULL HERE !
4878 ****************************************************************************/
4880 void reply_tdis(struct smb_request *req)
4882 connection_struct *conn = req->conn;
4883 START_PROFILE(SMBtdis);
4885 if (!conn) {
4886 DEBUG(4,("Invalid connection in tdis\n"));
4887 reply_doserror(req, ERRSRV, ERRinvnid);
4888 END_PROFILE(SMBtdis);
4889 return;
4892 conn->used = False;
4894 close_cnum(conn,req->vuid);
4895 req->conn = NULL;
4897 reply_outbuf(req, 0, 0);
4898 END_PROFILE(SMBtdis);
4899 return;
4902 /****************************************************************************
4903 Reply to a echo.
4904 conn POINTER CAN BE NULL HERE !
4905 ****************************************************************************/
4907 void reply_echo(struct smb_request *req)
4909 connection_struct *conn = req->conn;
4910 struct smb_perfcount_data local_pcd;
4911 struct smb_perfcount_data *cur_pcd;
4912 int smb_reverb;
4913 int seq_num;
4915 START_PROFILE(SMBecho);
4917 smb_init_perfcount_data(&local_pcd);
4919 if (req->wct < 1) {
4920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4921 END_PROFILE(SMBecho);
4922 return;
4925 smb_reverb = SVAL(req->vwv+0, 0);
4927 reply_outbuf(req, 1, req->buflen);
4929 /* copy any incoming data back out */
4930 if (req->buflen > 0) {
4931 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4934 if (smb_reverb > 100) {
4935 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4936 smb_reverb = 100;
4939 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4941 /* this makes sure we catch the request pcd */
4942 if (seq_num == smb_reverb) {
4943 cur_pcd = &req->pcd;
4944 } else {
4945 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4946 cur_pcd = &local_pcd;
4949 SSVAL(req->outbuf,smb_vwv0,seq_num);
4951 show_msg((char *)req->outbuf);
4952 if (!srv_send_smb(smbd_server_fd(),
4953 (char *)req->outbuf,
4954 true, req->seqnum+1,
4955 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4956 cur_pcd))
4957 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4960 DEBUG(3,("echo %d times\n", smb_reverb));
4962 TALLOC_FREE(req->outbuf);
4964 END_PROFILE(SMBecho);
4965 return;
4968 /****************************************************************************
4969 Reply to a printopen.
4970 ****************************************************************************/
4972 void reply_printopen(struct smb_request *req)
4974 connection_struct *conn = req->conn;
4975 files_struct *fsp;
4976 SMB_STRUCT_STAT sbuf;
4977 NTSTATUS status;
4979 START_PROFILE(SMBsplopen);
4981 if (req->wct < 2) {
4982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4983 END_PROFILE(SMBsplopen);
4984 return;
4987 if (!CAN_PRINT(conn)) {
4988 reply_doserror(req, ERRDOS, ERRnoaccess);
4989 END_PROFILE(SMBsplopen);
4990 return;
4993 status = file_new(req, conn, &fsp);
4994 if(!NT_STATUS_IS_OK(status)) {
4995 reply_nterror(req, status);
4996 END_PROFILE(SMBsplopen);
4997 return;
5000 /* Open for exclusive use, write only. */
5001 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
5003 if (!NT_STATUS_IS_OK(status)) {
5004 file_free(req, fsp);
5005 reply_nterror(req, status);
5006 END_PROFILE(SMBsplopen);
5007 return;
5010 reply_outbuf(req, 1, 0);
5011 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5013 DEBUG(3,("openprint fd=%d fnum=%d\n",
5014 fsp->fh->fd, fsp->fnum));
5016 END_PROFILE(SMBsplopen);
5017 return;
5020 /****************************************************************************
5021 Reply to a printclose.
5022 ****************************************************************************/
5024 void reply_printclose(struct smb_request *req)
5026 connection_struct *conn = req->conn;
5027 files_struct *fsp;
5028 NTSTATUS status;
5030 START_PROFILE(SMBsplclose);
5032 if (req->wct < 1) {
5033 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5034 END_PROFILE(SMBsplclose);
5035 return;
5038 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5040 if (!check_fsp(conn, req, fsp)) {
5041 END_PROFILE(SMBsplclose);
5042 return;
5045 if (!CAN_PRINT(conn)) {
5046 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5047 END_PROFILE(SMBsplclose);
5048 return;
5051 DEBUG(3,("printclose fd=%d fnum=%d\n",
5052 fsp->fh->fd,fsp->fnum));
5054 status = close_file(req, fsp, NORMAL_CLOSE);
5056 if(!NT_STATUS_IS_OK(status)) {
5057 reply_nterror(req, status);
5058 END_PROFILE(SMBsplclose);
5059 return;
5062 reply_outbuf(req, 0, 0);
5064 END_PROFILE(SMBsplclose);
5065 return;
5068 /****************************************************************************
5069 Reply to a printqueue.
5070 ****************************************************************************/
5072 void reply_printqueue(struct smb_request *req)
5074 connection_struct *conn = req->conn;
5075 int max_count;
5076 int start_index;
5078 START_PROFILE(SMBsplretq);
5080 if (req->wct < 2) {
5081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5082 END_PROFILE(SMBsplretq);
5083 return;
5086 max_count = SVAL(req->vwv+0, 0);
5087 start_index = SVAL(req->vwv+1, 0);
5089 /* we used to allow the client to get the cnum wrong, but that
5090 is really quite gross and only worked when there was only
5091 one printer - I think we should now only accept it if they
5092 get it right (tridge) */
5093 if (!CAN_PRINT(conn)) {
5094 reply_doserror(req, ERRDOS, ERRnoaccess);
5095 END_PROFILE(SMBsplretq);
5096 return;
5099 reply_outbuf(req, 2, 3);
5100 SSVAL(req->outbuf,smb_vwv0,0);
5101 SSVAL(req->outbuf,smb_vwv1,0);
5102 SCVAL(smb_buf(req->outbuf),0,1);
5103 SSVAL(smb_buf(req->outbuf),1,0);
5105 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5106 start_index, max_count));
5109 print_queue_struct *queue = NULL;
5110 print_status_struct status;
5111 int count = print_queue_status(SNUM(conn), &queue, &status);
5112 int num_to_get = ABS(max_count);
5113 int first = (max_count>0?start_index:start_index+max_count+1);
5114 int i;
5116 if (first >= count)
5117 num_to_get = 0;
5118 else
5119 num_to_get = MIN(num_to_get,count-first);
5122 for (i=first;i<first+num_to_get;i++) {
5123 char blob[28];
5124 char *p = blob;
5126 srv_put_dos_date2(p,0,queue[i].time);
5127 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5128 SSVAL(p,5, queue[i].job);
5129 SIVAL(p,7,queue[i].size);
5130 SCVAL(p,11,0);
5131 srvstr_push(blob, req->flags2, p+12,
5132 queue[i].fs_user, 16, STR_ASCII);
5134 if (message_push_blob(
5135 &req->outbuf,
5136 data_blob_const(
5137 blob, sizeof(blob))) == -1) {
5138 reply_nterror(req, NT_STATUS_NO_MEMORY);
5139 END_PROFILE(SMBsplretq);
5140 return;
5144 if (count > 0) {
5145 SSVAL(req->outbuf,smb_vwv0,count);
5146 SSVAL(req->outbuf,smb_vwv1,
5147 (max_count>0?first+count:first-1));
5148 SCVAL(smb_buf(req->outbuf),0,1);
5149 SSVAL(smb_buf(req->outbuf),1,28*count);
5152 SAFE_FREE(queue);
5154 DEBUG(3,("%d entries returned in queue\n",count));
5157 END_PROFILE(SMBsplretq);
5158 return;
5161 /****************************************************************************
5162 Reply to a printwrite.
5163 ****************************************************************************/
5165 void reply_printwrite(struct smb_request *req)
5167 connection_struct *conn = req->conn;
5168 int numtowrite;
5169 const char *data;
5170 files_struct *fsp;
5172 START_PROFILE(SMBsplwr);
5174 if (req->wct < 1) {
5175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5176 END_PROFILE(SMBsplwr);
5177 return;
5180 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5182 if (!check_fsp(conn, req, fsp)) {
5183 END_PROFILE(SMBsplwr);
5184 return;
5187 if (!CAN_PRINT(conn)) {
5188 reply_doserror(req, ERRDOS, ERRnoaccess);
5189 END_PROFILE(SMBsplwr);
5190 return;
5193 if (!CHECK_WRITE(fsp)) {
5194 reply_doserror(req, ERRDOS, ERRbadaccess);
5195 END_PROFILE(SMBsplwr);
5196 return;
5199 numtowrite = SVAL(req->buf, 1);
5201 if (req->buflen < numtowrite + 3) {
5202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5203 END_PROFILE(SMBsplwr);
5204 return;
5207 data = (const char *)req->buf + 3;
5209 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5210 reply_nterror(req, map_nt_error_from_unix(errno));
5211 END_PROFILE(SMBsplwr);
5212 return;
5215 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5217 END_PROFILE(SMBsplwr);
5218 return;
5221 /****************************************************************************
5222 Reply to a mkdir.
5223 ****************************************************************************/
5225 void reply_mkdir(struct smb_request *req)
5227 connection_struct *conn = req->conn;
5228 struct smb_filename *smb_dname = NULL;
5229 char *directory = NULL;
5230 NTSTATUS status;
5231 TALLOC_CTX *ctx = talloc_tos();
5233 START_PROFILE(SMBmkdir);
5235 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5236 STR_TERMINATE, &status);
5237 if (!NT_STATUS_IS_OK(status)) {
5238 reply_nterror(req, status);
5239 goto out;
5242 status = filename_convert(ctx, conn,
5243 req->flags2 & FLAGS2_DFS_PATHNAMES,
5244 directory,
5246 NULL,
5247 &smb_dname);
5248 if (!NT_STATUS_IS_OK(status)) {
5249 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5250 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5251 ERRSRV, ERRbadpath);
5252 goto out;
5254 reply_nterror(req, status);
5255 goto out;
5258 status = create_directory(conn, req, smb_dname);
5260 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5262 if (!NT_STATUS_IS_OK(status)) {
5264 if (!use_nt_status()
5265 && NT_STATUS_EQUAL(status,
5266 NT_STATUS_OBJECT_NAME_COLLISION)) {
5268 * Yes, in the DOS error code case we get a
5269 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5270 * samba4 torture test.
5272 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5275 reply_nterror(req, status);
5276 goto out;
5279 reply_outbuf(req, 0, 0);
5281 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5282 out:
5283 TALLOC_FREE(smb_dname);
5284 END_PROFILE(SMBmkdir);
5285 return;
5288 /****************************************************************************
5289 Static function used by reply_rmdir to delete an entire directory
5290 tree recursively. Return True on ok, False on fail.
5291 ****************************************************************************/
5293 static bool recursive_rmdir(TALLOC_CTX *ctx,
5294 connection_struct *conn,
5295 struct smb_filename *smb_dname)
5297 char *dname = NULL;
5298 bool ret = True;
5299 long offset = 0;
5300 SMB_STRUCT_STAT st;
5301 struct smb_Dir *dir_hnd;
5303 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5305 dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
5306 if(dir_hnd == NULL)
5307 return False;
5309 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5310 struct smb_filename *smb_dname_full = NULL;
5311 char *fullname = NULL;
5312 bool do_break = true;
5313 NTSTATUS status;
5315 if (ISDOT(dname) || ISDOTDOT(dname)) {
5316 TALLOC_FREE(dname);
5317 continue;
5320 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
5321 false)) {
5322 TALLOC_FREE(dname);
5323 continue;
5326 /* Construct the full name. */
5327 fullname = talloc_asprintf(ctx,
5328 "%s/%s",
5329 smb_dname->base_name,
5330 dname);
5331 if (!fullname) {
5332 errno = ENOMEM;
5333 goto err_break;
5336 status = create_synthetic_smb_fname(talloc_tos(), fullname,
5337 NULL, NULL,
5338 &smb_dname_full);
5339 if (!NT_STATUS_IS_OK(status)) {
5340 goto err_break;
5343 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5344 goto err_break;
5347 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5348 if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
5349 goto err_break;
5351 if(SMB_VFS_RMDIR(conn,
5352 smb_dname_full->base_name) != 0) {
5353 goto err_break;
5355 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5356 goto err_break;
5359 /* Successful iteration. */
5360 do_break = false;
5362 err_break:
5363 TALLOC_FREE(smb_dname_full);
5364 TALLOC_FREE(fullname);
5365 TALLOC_FREE(dname);
5366 if (do_break) {
5367 ret = false;
5368 break;
5371 TALLOC_FREE(dir_hnd);
5372 return ret;
5375 /****************************************************************************
5376 The internals of the rmdir code - called elsewhere.
5377 ****************************************************************************/
5379 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5380 connection_struct *conn,
5381 struct smb_filename *smb_dname)
5383 int ret;
5384 SMB_STRUCT_STAT st;
5386 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5388 /* Might be a symlink. */
5389 if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
5390 return map_nt_error_from_unix(errno);
5393 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
5394 /* Is what it points to a directory ? */
5395 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
5396 return map_nt_error_from_unix(errno);
5398 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
5399 return NT_STATUS_NOT_A_DIRECTORY;
5401 ret = SMB_VFS_UNLINK(conn, smb_dname);
5402 } else {
5403 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5405 if (ret == 0) {
5406 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5407 FILE_NOTIFY_CHANGE_DIR_NAME,
5408 smb_dname->base_name);
5409 return NT_STATUS_OK;
5412 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5414 * Check to see if the only thing in this directory are
5415 * vetoed files/directories. If so then delete them and
5416 * retry. If we fail to delete any of them (and we *don't*
5417 * do a recursive delete) then fail the rmdir.
5419 char *dname = NULL;
5420 long dirpos = 0;
5421 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5422 smb_dname->base_name, NULL,
5425 if(dir_hnd == NULL) {
5426 errno = ENOTEMPTY;
5427 goto err;
5430 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5431 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
5432 TALLOC_FREE(dname);
5433 continue;
5435 if (!is_visible_file(conn, smb_dname->base_name, dname,
5436 &st, false)) {
5437 TALLOC_FREE(dname);
5438 continue;
5440 if(!IS_VETO_PATH(conn, dname)) {
5441 TALLOC_FREE(dir_hnd);
5442 TALLOC_FREE(dname);
5443 errno = ENOTEMPTY;
5444 goto err;
5446 TALLOC_FREE(dname);
5449 /* We only have veto files/directories.
5450 * Are we allowed to delete them ? */
5452 if(!lp_recursive_veto_delete(SNUM(conn))) {
5453 TALLOC_FREE(dir_hnd);
5454 errno = ENOTEMPTY;
5455 goto err;
5458 /* Do a recursive delete. */
5459 RewindDir(dir_hnd,&dirpos);
5460 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5461 struct smb_filename *smb_dname_full = NULL;
5462 char *fullname = NULL;
5463 bool do_break = true;
5464 NTSTATUS status;
5466 if (ISDOT(dname) || ISDOTDOT(dname)) {
5467 TALLOC_FREE(dname);
5468 continue;
5470 if (!is_visible_file(conn, smb_dname->base_name, dname,
5471 &st, false)) {
5472 TALLOC_FREE(dname);
5473 continue;
5476 fullname = talloc_asprintf(ctx,
5477 "%s/%s",
5478 smb_dname->base_name,
5479 dname);
5481 if(!fullname) {
5482 errno = ENOMEM;
5483 goto err_break;
5486 status = create_synthetic_smb_fname(talloc_tos(),
5487 fullname, NULL,
5488 NULL,
5489 &smb_dname_full);
5490 if (!NT_STATUS_IS_OK(status)) {
5491 errno = map_errno_from_nt_status(status);
5492 goto err_break;
5495 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5496 goto err_break;
5498 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5499 if(!recursive_rmdir(ctx, conn,
5500 smb_dname_full)) {
5501 goto err_break;
5503 if(SMB_VFS_RMDIR(conn,
5504 smb_dname_full->base_name) != 0) {
5505 goto err_break;
5507 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5508 goto err_break;
5511 /* Successful iteration. */
5512 do_break = false;
5514 err_break:
5515 TALLOC_FREE(fullname);
5516 TALLOC_FREE(smb_dname_full);
5517 TALLOC_FREE(dname);
5518 if (do_break)
5519 break;
5521 TALLOC_FREE(dir_hnd);
5522 /* Retry the rmdir */
5523 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5526 err:
5528 if (ret != 0) {
5529 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5530 "%s\n", smb_fname_str_dbg(smb_dname),
5531 strerror(errno)));
5532 return map_nt_error_from_unix(errno);
5535 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5536 FILE_NOTIFY_CHANGE_DIR_NAME,
5537 smb_dname->base_name);
5539 return NT_STATUS_OK;
5542 /****************************************************************************
5543 Reply to a rmdir.
5544 ****************************************************************************/
5546 void reply_rmdir(struct smb_request *req)
5548 connection_struct *conn = req->conn;
5549 struct smb_filename *smb_dname = NULL;
5550 char *directory = NULL;
5551 NTSTATUS status;
5552 TALLOC_CTX *ctx = talloc_tos();
5553 struct smbd_server_connection *sconn = smbd_server_conn;
5555 START_PROFILE(SMBrmdir);
5557 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5558 STR_TERMINATE, &status);
5559 if (!NT_STATUS_IS_OK(status)) {
5560 reply_nterror(req, status);
5561 goto out;
5564 status = filename_convert(ctx, conn,
5565 req->flags2 & FLAGS2_DFS_PATHNAMES,
5566 directory,
5568 NULL,
5569 &smb_dname);
5570 if (!NT_STATUS_IS_OK(status)) {
5571 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5572 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5573 ERRSRV, ERRbadpath);
5574 goto out;
5576 reply_nterror(req, status);
5577 goto out;
5580 if (is_ntfs_stream_smb_fname(smb_dname)) {
5581 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5582 goto out;
5585 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5586 status = rmdir_internals(ctx, conn, smb_dname);
5587 if (!NT_STATUS_IS_OK(status)) {
5588 reply_nterror(req, status);
5589 goto out;
5592 reply_outbuf(req, 0, 0);
5594 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5595 out:
5596 TALLOC_FREE(smb_dname);
5597 END_PROFILE(SMBrmdir);
5598 return;
5601 /*******************************************************************
5602 Resolve wildcards in a filename rename.
5603 ********************************************************************/
5605 static bool resolve_wildcards(TALLOC_CTX *ctx,
5606 const char *name1,
5607 const char *name2,
5608 char **pp_newname)
5610 char *name2_copy = NULL;
5611 char *root1 = NULL;
5612 char *root2 = NULL;
5613 char *ext1 = NULL;
5614 char *ext2 = NULL;
5615 char *p,*p2, *pname1, *pname2;
5617 name2_copy = talloc_strdup(ctx, name2);
5618 if (!name2_copy) {
5619 return False;
5622 pname1 = strrchr_m(name1,'/');
5623 pname2 = strrchr_m(name2_copy,'/');
5625 if (!pname1 || !pname2) {
5626 return False;
5629 /* Truncate the copy of name2 at the last '/' */
5630 *pname2 = '\0';
5632 /* Now go past the '/' */
5633 pname1++;
5634 pname2++;
5636 root1 = talloc_strdup(ctx, pname1);
5637 root2 = talloc_strdup(ctx, pname2);
5639 if (!root1 || !root2) {
5640 return False;
5643 p = strrchr_m(root1,'.');
5644 if (p) {
5645 *p = 0;
5646 ext1 = talloc_strdup(ctx, p+1);
5647 } else {
5648 ext1 = talloc_strdup(ctx, "");
5650 p = strrchr_m(root2,'.');
5651 if (p) {
5652 *p = 0;
5653 ext2 = talloc_strdup(ctx, p+1);
5654 } else {
5655 ext2 = talloc_strdup(ctx, "");
5658 if (!ext1 || !ext2) {
5659 return False;
5662 p = root1;
5663 p2 = root2;
5664 while (*p2) {
5665 if (*p2 == '?') {
5666 /* Hmmm. Should this be mb-aware ? */
5667 *p2 = *p;
5668 p2++;
5669 } else if (*p2 == '*') {
5670 *p2 = '\0';
5671 root2 = talloc_asprintf(ctx, "%s%s",
5672 root2,
5674 if (!root2) {
5675 return False;
5677 break;
5678 } else {
5679 p2++;
5681 if (*p) {
5682 p++;
5686 p = ext1;
5687 p2 = ext2;
5688 while (*p2) {
5689 if (*p2 == '?') {
5690 /* Hmmm. Should this be mb-aware ? */
5691 *p2 = *p;
5692 p2++;
5693 } else if (*p2 == '*') {
5694 *p2 = '\0';
5695 ext2 = talloc_asprintf(ctx, "%s%s",
5696 ext2,
5698 if (!ext2) {
5699 return False;
5701 break;
5702 } else {
5703 p2++;
5705 if (*p) {
5706 p++;
5710 if (*ext2) {
5711 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5712 name2_copy,
5713 root2,
5714 ext2);
5715 } else {
5716 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5717 name2_copy,
5718 root2);
5721 if (!*pp_newname) {
5722 return False;
5725 return True;
5728 /****************************************************************************
5729 Ensure open files have their names updated. Updated to notify other smbd's
5730 asynchronously.
5731 ****************************************************************************/
5733 static void rename_open_files(connection_struct *conn,
5734 struct share_mode_lock *lck,
5735 const struct smb_filename *smb_fname_dst)
5737 files_struct *fsp;
5738 bool did_rename = False;
5739 NTSTATUS status;
5741 for(fsp = file_find_di_first(lck->id); fsp;
5742 fsp = file_find_di_next(fsp)) {
5743 /* fsp_name is a relative path under the fsp. To change this for other
5744 sharepaths we need to manipulate relative paths. */
5745 /* TODO - create the absolute path and manipulate the newname
5746 relative to the sharepath. */
5747 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5748 continue;
5750 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5751 "(file_id %s) from %s -> %s\n", fsp->fnum,
5752 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5753 smb_fname_str_dbg(smb_fname_dst)));
5755 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5756 if (NT_STATUS_IS_OK(status)) {
5757 did_rename = True;
5761 if (!did_rename) {
5762 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5763 "for %s\n", file_id_string_tos(&lck->id),
5764 smb_fname_str_dbg(smb_fname_dst)));
5767 /* Send messages to all smbd's (not ourself) that the name has changed. */
5768 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5769 smb_fname_dst);
5773 /****************************************************************************
5774 We need to check if the source path is a parent directory of the destination
5775 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5776 refuse the rename with a sharing violation. Under UNIX the above call can
5777 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5778 probably need to check that the client is a Windows one before disallowing
5779 this as a UNIX client (one with UNIX extensions) can know the source is a
5780 symlink and make this decision intelligently. Found by an excellent bug
5781 report from <AndyLiebman@aol.com>.
5782 ****************************************************************************/
5784 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5785 const struct smb_filename *smb_fname_dst)
5787 const char *psrc = smb_fname_src->base_name;
5788 const char *pdst = smb_fname_dst->base_name;
5789 size_t slen;
5791 if (psrc[0] == '.' && psrc[1] == '/') {
5792 psrc += 2;
5794 if (pdst[0] == '.' && pdst[1] == '/') {
5795 pdst += 2;
5797 if ((slen = strlen(psrc)) > strlen(pdst)) {
5798 return False;
5800 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5804 * Do the notify calls from a rename
5807 static void notify_rename(connection_struct *conn, bool is_dir,
5808 const struct smb_filename *smb_fname_src,
5809 const struct smb_filename *smb_fname_dst)
5811 char *parent_dir_src = NULL;
5812 char *parent_dir_dst = NULL;
5813 uint32 mask;
5815 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5816 : FILE_NOTIFY_CHANGE_FILE_NAME;
5818 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5819 &parent_dir_src, NULL) ||
5820 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5821 &parent_dir_dst, NULL)) {
5822 goto out;
5825 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5826 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5827 smb_fname_src->base_name);
5828 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5829 smb_fname_dst->base_name);
5831 else {
5832 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5833 smb_fname_src->base_name);
5834 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5835 smb_fname_dst->base_name);
5838 /* this is a strange one. w2k3 gives an additional event for
5839 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5840 files, but not directories */
5841 if (!is_dir) {
5842 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5843 FILE_NOTIFY_CHANGE_ATTRIBUTES
5844 |FILE_NOTIFY_CHANGE_CREATION,
5845 smb_fname_dst->base_name);
5847 out:
5848 TALLOC_FREE(parent_dir_src);
5849 TALLOC_FREE(parent_dir_dst);
5852 /****************************************************************************
5853 Rename an open file - given an fsp.
5854 ****************************************************************************/
5856 NTSTATUS rename_internals_fsp(connection_struct *conn,
5857 files_struct *fsp,
5858 const struct smb_filename *smb_fname_dst_in,
5859 uint32 attrs,
5860 bool replace_if_exists)
5862 TALLOC_CTX *ctx = talloc_tos();
5863 struct smb_filename *smb_fname_src = NULL;
5864 struct smb_filename *smb_fname_dst = NULL;
5865 SMB_STRUCT_STAT sbuf;
5866 NTSTATUS status = NT_STATUS_OK;
5867 struct share_mode_lock *lck = NULL;
5868 bool dst_exists, old_is_stream, new_is_stream;
5870 ZERO_STRUCT(sbuf);
5872 status = check_name(conn, smb_fname_dst_in->base_name);
5873 if (!NT_STATUS_IS_OK(status)) {
5874 return status;
5877 /* Make a copy of the src and dst smb_fname structs */
5878 status = copy_smb_filename(ctx, fsp->fsp_name, &smb_fname_src);
5879 if (!NT_STATUS_IS_OK(status)) {
5880 goto out;
5883 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5884 if (!NT_STATUS_IS_OK(status)) {
5885 goto out;
5888 /* Ensure the dst smb_fname contains a '/' */
5889 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5890 char * tmp;
5891 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5892 smb_fname_dst->base_name);
5893 if (!tmp) {
5894 status = NT_STATUS_NO_MEMORY;
5895 goto out;
5897 TALLOC_FREE(smb_fname_dst->base_name);
5898 smb_fname_dst->base_name = tmp;
5902 * Check for special case with case preserving and not
5903 * case sensitive. If the old last component differs from the original
5904 * last component only by case, then we should allow
5905 * the rename (user is trying to change the case of the
5906 * filename).
5908 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5909 strequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
5910 strequal(smb_fname_src->stream_name, smb_fname_dst->stream_name)) {
5911 char *last_slash;
5912 char *fname_dst_lcomp_base_mod = NULL;
5913 struct smb_filename *smb_fname_orig_lcomp = NULL;
5916 * Get the last component of the destination name. Note that
5917 * we guarantee that destination name contains a '/' character
5918 * above.
5920 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5921 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5922 if (!fname_dst_lcomp_base_mod) {
5923 status = NT_STATUS_NO_MEMORY;
5924 goto out;
5928 * Create an smb_filename struct using the original last
5929 * component of the destination.
5931 status = create_synthetic_smb_fname_split(ctx,
5932 smb_fname_dst->original_lcomp, NULL,
5933 &smb_fname_orig_lcomp);
5934 if (!NT_STATUS_IS_OK(status)) {
5935 TALLOC_FREE(fname_dst_lcomp_base_mod);
5936 goto out;
5939 /* If the base names only differ by case, use original. */
5940 if(!strcsequal(fname_dst_lcomp_base_mod,
5941 smb_fname_orig_lcomp->base_name)) {
5942 char *tmp;
5944 * Replace the modified last component with the
5945 * original.
5947 *last_slash = '\0'; /* Truncate at the '/' */
5948 tmp = talloc_asprintf(smb_fname_dst,
5949 "%s/%s",
5950 smb_fname_dst->base_name,
5951 smb_fname_orig_lcomp->base_name);
5952 if (tmp == NULL) {
5953 status = NT_STATUS_NO_MEMORY;
5954 TALLOC_FREE(fname_dst_lcomp_base_mod);
5955 TALLOC_FREE(smb_fname_orig_lcomp);
5956 goto out;
5958 TALLOC_FREE(smb_fname_dst->base_name);
5959 smb_fname_dst->base_name = tmp;
5962 /* If the stream_names only differ by case, use original. */
5963 if(!strcsequal(smb_fname_dst->stream_name,
5964 smb_fname_orig_lcomp->stream_name)) {
5965 char *tmp = NULL;
5966 /* Use the original stream. */
5967 tmp = talloc_strdup(smb_fname_dst,
5968 smb_fname_orig_lcomp->stream_name);
5969 if (tmp == NULL) {
5970 status = NT_STATUS_NO_MEMORY;
5971 TALLOC_FREE(fname_dst_lcomp_base_mod);
5972 TALLOC_FREE(smb_fname_orig_lcomp);
5973 goto out;
5975 TALLOC_FREE(smb_fname_dst->stream_name);
5976 smb_fname_dst->stream_name = tmp;
5978 TALLOC_FREE(fname_dst_lcomp_base_mod);
5979 TALLOC_FREE(smb_fname_orig_lcomp);
5983 * If the src and dest names are identical - including case,
5984 * don't do the rename, just return success.
5987 if (strcsequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
5988 strcsequal(smb_fname_src->stream_name,
5989 smb_fname_dst->stream_name)) {
5990 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5991 "- returning success\n",
5992 smb_fname_str_dbg(smb_fname_dst)));
5993 status = NT_STATUS_OK;
5994 goto out;
5997 old_is_stream = is_ntfs_stream_smb_fname(smb_fname_src);
5998 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6000 /* Return the correct error code if both names aren't streams. */
6001 if (!old_is_stream && new_is_stream) {
6002 status = NT_STATUS_OBJECT_NAME_INVALID;
6003 goto out;
6006 if (old_is_stream && !new_is_stream) {
6007 status = NT_STATUS_INVALID_PARAMETER;
6008 goto out;
6011 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6013 if(!replace_if_exists && dst_exists) {
6014 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6015 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6016 smb_fname_str_dbg(smb_fname_dst)));
6017 status = NT_STATUS_OBJECT_NAME_COLLISION;
6018 goto out;
6021 if (dst_exists) {
6022 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6023 &smb_fname_dst->st);
6024 files_struct *dst_fsp = file_find_di_first(fileid);
6025 /* The file can be open when renaming a stream */
6026 if (dst_fsp && !new_is_stream) {
6027 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6028 status = NT_STATUS_ACCESS_DENIED;
6029 goto out;
6033 /* Ensure we have a valid stat struct for the source. */
6034 if (fsp->fh->fd != -1) {
6035 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
6036 status = map_nt_error_from_unix(errno);
6037 goto out;
6039 } else {
6040 int ret = -1;
6041 if (fsp->posix_open) {
6042 ret = SMB_VFS_LSTAT(conn, smb_fname_src);
6043 } else {
6045 ret = SMB_VFS_STAT(conn, smb_fname_src);
6047 if (ret == -1) {
6048 status = map_nt_error_from_unix(errno);
6049 goto out;
6051 sbuf = smb_fname_src->st;
6054 status = can_rename(conn, fsp, attrs, &sbuf);
6056 if (!NT_STATUS_IS_OK(status)) {
6057 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6058 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6059 smb_fname_str_dbg(smb_fname_dst)));
6060 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6061 status = NT_STATUS_ACCESS_DENIED;
6062 goto out;
6065 if (rename_path_prefix_equal(smb_fname_src, smb_fname_dst)) {
6066 status = NT_STATUS_ACCESS_DENIED;
6069 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6070 NULL);
6073 * We have the file open ourselves, so not being able to get the
6074 * corresponding share mode lock is a fatal error.
6077 SMB_ASSERT(lck != NULL);
6079 if(SMB_VFS_RENAME(conn, smb_fname_src, smb_fname_dst) == 0) {
6080 uint32 create_options = fsp->fh->private_options;
6082 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6083 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6084 smb_fname_str_dbg(smb_fname_dst)));
6086 notify_rename(conn, fsp->is_directory, smb_fname_src,
6087 smb_fname_dst);
6089 rename_open_files(conn, lck, smb_fname_dst);
6092 * A rename acts as a new file create w.r.t. allowing an initial delete
6093 * on close, probably because in Windows there is a new handle to the
6094 * new file. If initial delete on close was requested but not
6095 * originally set, we need to set it here. This is probably not 100% correct,
6096 * but will work for the CIFSFS client which in non-posix mode
6097 * depends on these semantics. JRA.
6100 if (create_options & FILE_DELETE_ON_CLOSE) {
6101 status = can_set_delete_on_close(fsp, True, 0);
6103 if (NT_STATUS_IS_OK(status)) {
6104 /* Note that here we set the *inital* delete on close flag,
6105 * not the regular one. The magic gets handled in close. */
6106 fsp->initial_delete_on_close = True;
6109 TALLOC_FREE(lck);
6110 status = NT_STATUS_OK;
6111 goto out;
6114 TALLOC_FREE(lck);
6116 if (errno == ENOTDIR || errno == EISDIR) {
6117 status = NT_STATUS_OBJECT_NAME_COLLISION;
6118 } else {
6119 status = map_nt_error_from_unix(errno);
6122 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6123 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6124 smb_fname_str_dbg(smb_fname_dst)));
6126 out:
6127 TALLOC_FREE(smb_fname_src);
6128 TALLOC_FREE(smb_fname_dst);
6130 return status;
6133 /****************************************************************************
6134 The guts of the rename command, split out so it may be called by the NT SMB
6135 code.
6136 ****************************************************************************/
6138 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6139 connection_struct *conn,
6140 struct smb_request *req,
6141 struct smb_filename *smb_fname_src,
6142 struct smb_filename *smb_fname_dst,
6143 uint32 attrs,
6144 bool replace_if_exists,
6145 bool src_has_wild,
6146 bool dest_has_wild,
6147 uint32_t access_mask)
6149 char *fname_src_dir = NULL;
6150 char *fname_src_mask = NULL;
6151 int count=0;
6152 NTSTATUS status = NT_STATUS_OK;
6153 struct smb_Dir *dir_hnd = NULL;
6154 char *dname = NULL;
6155 long offset = 0;
6156 int create_options = 0;
6157 bool posix_pathnames = lp_posix_pathnames();
6160 * Split the old name into directory and last component
6161 * strings. Note that unix_convert may have stripped off a
6162 * leading ./ from both name and newname if the rename is
6163 * at the root of the share. We need to make sure either both
6164 * name and newname contain a / character or neither of them do
6165 * as this is checked in resolve_wildcards().
6168 /* Split up the directory from the filename/mask. */
6169 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6170 &fname_src_dir, &fname_src_mask);
6171 if (!NT_STATUS_IS_OK(status)) {
6172 status = NT_STATUS_NO_MEMORY;
6173 goto out;
6177 * We should only check the mangled cache
6178 * here if unix_convert failed. This means
6179 * that the path in 'mask' doesn't exist
6180 * on the file system and so we need to look
6181 * for a possible mangle. This patch from
6182 * Tine Smukavec <valentin.smukavec@hermes.si>.
6185 if (!VALID_STAT(smb_fname_src->st) &&
6186 mangle_is_mangled(fname_src_mask, conn->params)) {
6187 char *new_mask = NULL;
6188 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6189 conn->params);
6190 if (new_mask) {
6191 TALLOC_FREE(fname_src_mask);
6192 fname_src_mask = new_mask;
6196 if (!src_has_wild) {
6197 files_struct *fsp;
6200 * Only one file needs to be renamed. Append the mask back
6201 * onto the directory.
6203 TALLOC_FREE(smb_fname_src->base_name);
6204 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6205 "%s/%s",
6206 fname_src_dir,
6207 fname_src_mask);
6208 if (!smb_fname_src->base_name) {
6209 status = NT_STATUS_NO_MEMORY;
6210 goto out;
6213 /* Ensure dst fname contains a '/' also */
6214 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6215 char *tmp;
6216 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6217 smb_fname_dst->base_name);
6218 if (!tmp) {
6219 status = NT_STATUS_NO_MEMORY;
6220 goto out;
6222 TALLOC_FREE(smb_fname_dst->base_name);
6223 smb_fname_dst->base_name = tmp;
6226 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6227 "case_preserve = %d, short case preserve = %d, "
6228 "directory = %s, newname = %s, "
6229 "last_component_dest = %s\n",
6230 conn->case_sensitive, conn->case_preserve,
6231 conn->short_case_preserve,
6232 smb_fname_str_dbg(smb_fname_src),
6233 smb_fname_str_dbg(smb_fname_dst),
6234 smb_fname_dst->original_lcomp));
6236 /* The dest name still may have wildcards. */
6237 if (dest_has_wild) {
6238 char *fname_dst_mod = NULL;
6239 if (!resolve_wildcards(smb_fname_dst,
6240 smb_fname_src->base_name,
6241 smb_fname_dst->base_name,
6242 &fname_dst_mod)) {
6243 DEBUG(6, ("rename_internals: resolve_wildcards "
6244 "%s %s failed\n",
6245 smb_fname_src->base_name,
6246 smb_fname_dst->base_name));
6247 status = NT_STATUS_NO_MEMORY;
6248 goto out;
6250 TALLOC_FREE(smb_fname_dst->base_name);
6251 smb_fname_dst->base_name = fname_dst_mod;
6254 ZERO_STRUCT(smb_fname_src->st);
6255 if (posix_pathnames) {
6256 SMB_VFS_LSTAT(conn, smb_fname_src);
6257 } else {
6258 SMB_VFS_STAT(conn, smb_fname_src);
6261 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6262 create_options |= FILE_DIRECTORY_FILE;
6265 status = SMB_VFS_CREATE_FILE(
6266 conn, /* conn */
6267 req, /* req */
6268 0, /* root_dir_fid */
6269 smb_fname_src, /* fname */
6270 access_mask, /* access_mask */
6271 (FILE_SHARE_READ | /* share_access */
6272 FILE_SHARE_WRITE),
6273 FILE_OPEN, /* create_disposition*/
6274 create_options, /* create_options */
6275 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6276 0, /* oplock_request */
6277 0, /* allocation_size */
6278 NULL, /* sd */
6279 NULL, /* ea_list */
6280 &fsp, /* result */
6281 NULL); /* pinfo */
6283 if (!NT_STATUS_IS_OK(status)) {
6284 DEBUG(3, ("Could not open rename source %s: %s\n",
6285 smb_fname_str_dbg(smb_fname_src),
6286 nt_errstr(status)));
6287 goto out;
6290 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6291 attrs, replace_if_exists);
6293 close_file(req, fsp, NORMAL_CLOSE);
6295 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6296 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6297 smb_fname_str_dbg(smb_fname_dst)));
6299 goto out;
6303 * Wildcards - process each file that matches.
6305 if (strequal(fname_src_mask, "????????.???")) {
6306 TALLOC_FREE(fname_src_mask);
6307 fname_src_mask = talloc_strdup(ctx, "*");
6308 if (!fname_src_mask) {
6309 status = NT_STATUS_NO_MEMORY;
6310 goto out;
6314 status = check_name(conn, fname_src_dir);
6315 if (!NT_STATUS_IS_OK(status)) {
6316 goto out;
6319 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6320 attrs);
6321 if (dir_hnd == NULL) {
6322 status = map_nt_error_from_unix(errno);
6323 goto out;
6326 status = NT_STATUS_NO_SUCH_FILE;
6328 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6329 * - gentest fix. JRA
6332 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6333 files_struct *fsp = NULL;
6334 char *destname = NULL;
6335 bool sysdir_entry = False;
6337 /* Quick check for "." and ".." */
6338 if (ISDOT(dname) || ISDOTDOT(dname)) {
6339 if (attrs & aDIR) {
6340 sysdir_entry = True;
6341 } else {
6342 TALLOC_FREE(dname);
6343 continue;
6347 if (!is_visible_file(conn, fname_src_dir, dname,
6348 &smb_fname_src->st, false)) {
6349 TALLOC_FREE(dname);
6350 continue;
6353 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6354 TALLOC_FREE(dname);
6355 continue;
6358 if (sysdir_entry) {
6359 status = NT_STATUS_OBJECT_NAME_INVALID;
6360 break;
6363 TALLOC_FREE(smb_fname_src->base_name);
6364 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6365 "%s/%s",
6366 fname_src_dir,
6367 dname);
6368 if (!smb_fname_src->base_name) {
6369 status = NT_STATUS_NO_MEMORY;
6370 goto out;
6373 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6374 smb_fname_dst->base_name,
6375 &destname)) {
6376 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6377 smb_fname_src->base_name, destname));
6378 TALLOC_FREE(dname);
6379 continue;
6381 if (!destname) {
6382 status = NT_STATUS_NO_MEMORY;
6383 goto out;
6386 TALLOC_FREE(smb_fname_dst->base_name);
6387 smb_fname_dst->base_name = destname;
6389 ZERO_STRUCT(smb_fname_src->st);
6390 if (posix_pathnames) {
6391 SMB_VFS_LSTAT(conn, smb_fname_src);
6392 } else {
6393 SMB_VFS_STAT(conn, smb_fname_src);
6396 create_options = 0;
6398 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6399 create_options |= FILE_DIRECTORY_FILE;
6402 status = SMB_VFS_CREATE_FILE(
6403 conn, /* conn */
6404 req, /* req */
6405 0, /* root_dir_fid */
6406 smb_fname_src, /* fname */
6407 access_mask, /* access_mask */
6408 (FILE_SHARE_READ | /* share_access */
6409 FILE_SHARE_WRITE),
6410 FILE_OPEN, /* create_disposition*/
6411 create_options, /* create_options */
6412 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6413 0, /* oplock_request */
6414 0, /* allocation_size */
6415 NULL, /* sd */
6416 NULL, /* ea_list */
6417 &fsp, /* result */
6418 NULL); /* pinfo */
6420 if (!NT_STATUS_IS_OK(status)) {
6421 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6422 "returned %s rename %s -> %s\n",
6423 nt_errstr(status),
6424 smb_fname_str_dbg(smb_fname_src),
6425 smb_fname_str_dbg(smb_fname_dst)));
6426 break;
6429 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6430 dname);
6431 if (!smb_fname_dst->original_lcomp) {
6432 status = NT_STATUS_NO_MEMORY;
6433 goto out;
6436 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6437 attrs, replace_if_exists);
6439 close_file(req, fsp, NORMAL_CLOSE);
6441 if (!NT_STATUS_IS_OK(status)) {
6442 DEBUG(3, ("rename_internals_fsp returned %s for "
6443 "rename %s -> %s\n", nt_errstr(status),
6444 smb_fname_str_dbg(smb_fname_src),
6445 smb_fname_str_dbg(smb_fname_dst)));
6446 break;
6449 count++;
6451 DEBUG(3,("rename_internals: doing rename on %s -> "
6452 "%s\n", smb_fname_str_dbg(smb_fname_src),
6453 smb_fname_str_dbg(smb_fname_src)));
6454 TALLOC_FREE(dname);
6456 TALLOC_FREE(dir_hnd);
6458 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6459 status = map_nt_error_from_unix(errno);
6462 out:
6463 TALLOC_FREE(dname);
6464 TALLOC_FREE(fname_src_dir);
6465 TALLOC_FREE(fname_src_mask);
6466 return status;
6469 /****************************************************************************
6470 Reply to a mv.
6471 ****************************************************************************/
6473 void reply_mv(struct smb_request *req)
6475 connection_struct *conn = req->conn;
6476 char *name = NULL;
6477 char *newname = NULL;
6478 const char *p;
6479 uint32 attrs;
6480 NTSTATUS status;
6481 bool src_has_wcard = False;
6482 bool dest_has_wcard = False;
6483 TALLOC_CTX *ctx = talloc_tos();
6484 struct smb_filename *smb_fname_src = NULL;
6485 struct smb_filename *smb_fname_dst = NULL;
6487 START_PROFILE(SMBmv);
6489 if (req->wct < 1) {
6490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6491 goto out;
6494 attrs = SVAL(req->vwv+0, 0);
6496 p = (const char *)req->buf + 1;
6497 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6498 &status, &src_has_wcard);
6499 if (!NT_STATUS_IS_OK(status)) {
6500 reply_nterror(req, status);
6501 goto out;
6503 p++;
6504 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6505 &status, &dest_has_wcard);
6506 if (!NT_STATUS_IS_OK(status)) {
6507 reply_nterror(req, status);
6508 goto out;
6511 status = filename_convert(ctx,
6512 conn,
6513 req->flags2 & FLAGS2_DFS_PATHNAMES,
6514 name,
6515 UCF_COND_ALLOW_WCARD_LCOMP,
6516 &src_has_wcard,
6517 &smb_fname_src);
6519 if (!NT_STATUS_IS_OK(status)) {
6520 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6521 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6522 ERRSRV, ERRbadpath);
6523 goto out;
6525 reply_nterror(req, status);
6526 goto out;
6529 status = filename_convert(ctx,
6530 conn,
6531 req->flags2 & FLAGS2_DFS_PATHNAMES,
6532 newname,
6533 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6534 &dest_has_wcard,
6535 &smb_fname_dst);
6537 if (!NT_STATUS_IS_OK(status)) {
6538 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6539 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6540 ERRSRV, ERRbadpath);
6541 goto out;
6543 reply_nterror(req, status);
6544 goto out;
6547 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6548 smb_fname_str_dbg(smb_fname_dst)));
6550 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6551 attrs, False, src_has_wcard, dest_has_wcard,
6552 DELETE_ACCESS);
6553 if (!NT_STATUS_IS_OK(status)) {
6554 if (open_was_deferred(req->mid)) {
6555 /* We have re-scheduled this call. */
6556 goto out;
6558 reply_nterror(req, status);
6559 goto out;
6562 reply_outbuf(req, 0, 0);
6563 out:
6564 TALLOC_FREE(smb_fname_src);
6565 TALLOC_FREE(smb_fname_dst);
6566 END_PROFILE(SMBmv);
6567 return;
6570 /*******************************************************************
6571 Copy a file as part of a reply_copy.
6572 ******************************************************************/
6575 * TODO: check error codes on all callers
6578 NTSTATUS copy_file(TALLOC_CTX *ctx,
6579 connection_struct *conn,
6580 struct smb_filename *smb_fname_src,
6581 struct smb_filename *smb_fname_dst,
6582 int ofun,
6583 int count,
6584 bool target_is_directory)
6586 struct smb_filename *smb_fname_dst_tmp = NULL;
6587 SMB_OFF_T ret=-1;
6588 files_struct *fsp1,*fsp2;
6589 uint32 dosattrs;
6590 uint32 new_create_disposition;
6591 NTSTATUS status;
6594 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6595 if (!NT_STATUS_IS_OK(status)) {
6596 return status;
6600 * If the target is a directory, extract the last component from the
6601 * src filename and append it to the dst filename
6603 if (target_is_directory) {
6604 const char *p;
6606 /* dest/target can't be a stream if it's a directory. */
6607 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6609 p = strrchr_m(smb_fname_src->base_name,'/');
6610 if (p) {
6611 p++;
6612 } else {
6613 p = smb_fname_src->base_name;
6615 smb_fname_dst_tmp->base_name =
6616 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6618 if (!smb_fname_dst_tmp->base_name) {
6619 status = NT_STATUS_NO_MEMORY;
6620 goto out;
6624 status = vfs_file_exist(conn, smb_fname_src);
6625 if (!NT_STATUS_IS_OK(status)) {
6626 goto out;
6629 if (!target_is_directory && count) {
6630 new_create_disposition = FILE_OPEN;
6631 } else {
6632 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6633 NULL, NULL,
6634 &new_create_disposition,
6635 NULL)) {
6636 status = NT_STATUS_INVALID_PARAMETER;
6637 goto out;
6641 /* Open the src file for reading. */
6642 status = SMB_VFS_CREATE_FILE(
6643 conn, /* conn */
6644 NULL, /* req */
6645 0, /* root_dir_fid */
6646 smb_fname_src, /* fname */
6647 FILE_GENERIC_READ, /* access_mask */
6648 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6649 FILE_OPEN, /* create_disposition*/
6650 0, /* create_options */
6651 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6652 INTERNAL_OPEN_ONLY, /* oplock_request */
6653 0, /* allocation_size */
6654 NULL, /* sd */
6655 NULL, /* ea_list */
6656 &fsp1, /* result */
6657 NULL); /* psbuf */
6659 if (!NT_STATUS_IS_OK(status)) {
6660 goto out;
6663 dosattrs = dos_mode(conn, smb_fname_src);
6665 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6666 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6669 /* Open the dst file for writing. */
6670 status = SMB_VFS_CREATE_FILE(
6671 conn, /* conn */
6672 NULL, /* req */
6673 0, /* root_dir_fid */
6674 smb_fname_dst, /* fname */
6675 FILE_GENERIC_WRITE, /* access_mask */
6676 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6677 new_create_disposition, /* create_disposition*/
6678 0, /* create_options */
6679 dosattrs, /* file_attributes */
6680 INTERNAL_OPEN_ONLY, /* oplock_request */
6681 0, /* allocation_size */
6682 NULL, /* sd */
6683 NULL, /* ea_list */
6684 &fsp2, /* result */
6685 NULL); /* psbuf */
6687 if (!NT_STATUS_IS_OK(status)) {
6688 close_file(NULL, fsp1, ERROR_CLOSE);
6689 goto out;
6692 if ((ofun&3) == 1) {
6693 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6694 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6696 * Stop the copy from occurring.
6698 ret = -1;
6699 smb_fname_src->st.st_ex_size = 0;
6703 /* Do the actual copy. */
6704 if (smb_fname_src->st.st_ex_size) {
6705 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6708 close_file(NULL, fsp1, NORMAL_CLOSE);
6710 /* Ensure the modtime is set correctly on the destination file. */
6711 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6714 * As we are opening fsp1 read-only we only expect
6715 * an error on close on fsp2 if we are out of space.
6716 * Thus we don't look at the error return from the
6717 * close of fsp1.
6719 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6721 if (!NT_STATUS_IS_OK(status)) {
6722 goto out;
6725 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6726 status = NT_STATUS_DISK_FULL;
6727 goto out;
6730 status = NT_STATUS_OK;
6732 out:
6733 TALLOC_FREE(smb_fname_dst_tmp);
6734 return status;
6737 /****************************************************************************
6738 Reply to a file copy.
6739 ****************************************************************************/
6741 void reply_copy(struct smb_request *req)
6743 connection_struct *conn = req->conn;
6744 struct smb_filename *smb_fname_src = NULL;
6745 struct smb_filename *smb_fname_dst = NULL;
6746 char *fname_src = NULL;
6747 char *fname_dst = NULL;
6748 char *fname_src_mask = NULL;
6749 char *fname_src_dir = NULL;
6750 const char *p;
6751 int count=0;
6752 int error = ERRnoaccess;
6753 int tid2;
6754 int ofun;
6755 int flags;
6756 bool target_is_directory=False;
6757 bool source_has_wild = False;
6758 bool dest_has_wild = False;
6759 NTSTATUS status;
6760 TALLOC_CTX *ctx = talloc_tos();
6762 START_PROFILE(SMBcopy);
6764 if (req->wct < 3) {
6765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6766 goto out;
6769 tid2 = SVAL(req->vwv+0, 0);
6770 ofun = SVAL(req->vwv+1, 0);
6771 flags = SVAL(req->vwv+2, 0);
6773 p = (const char *)req->buf;
6774 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6775 &status, &source_has_wild);
6776 if (!NT_STATUS_IS_OK(status)) {
6777 reply_nterror(req, status);
6778 goto out;
6780 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6781 &status, &dest_has_wild);
6782 if (!NT_STATUS_IS_OK(status)) {
6783 reply_nterror(req, status);
6784 goto out;
6787 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6789 if (tid2 != conn->cnum) {
6790 /* can't currently handle inter share copies XXXX */
6791 DEBUG(3,("Rejecting inter-share copy\n"));
6792 reply_doserror(req, ERRSRV, ERRinvdevice);
6793 goto out;
6796 status = filename_convert(ctx, conn,
6797 req->flags2 & FLAGS2_DFS_PATHNAMES,
6798 fname_src,
6799 UCF_COND_ALLOW_WCARD_LCOMP,
6800 &source_has_wild,
6801 &smb_fname_src);
6802 if (!NT_STATUS_IS_OK(status)) {
6803 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6804 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6805 ERRSRV, ERRbadpath);
6806 goto out;
6808 reply_nterror(req, status);
6809 goto out;
6812 status = filename_convert(ctx, conn,
6813 req->flags2 & FLAGS2_DFS_PATHNAMES,
6814 fname_dst,
6815 UCF_COND_ALLOW_WCARD_LCOMP,
6816 &dest_has_wild,
6817 &smb_fname_dst);
6818 if (!NT_STATUS_IS_OK(status)) {
6819 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6820 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6821 ERRSRV, ERRbadpath);
6822 goto out;
6824 reply_nterror(req, status);
6825 goto out;
6828 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6830 if ((flags&1) && target_is_directory) {
6831 reply_doserror(req, ERRDOS, ERRbadfile);
6832 goto out;
6835 if ((flags&2) && !target_is_directory) {
6836 reply_doserror(req, ERRDOS, ERRbadpath);
6837 goto out;
6840 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6841 /* wants a tree copy! XXXX */
6842 DEBUG(3,("Rejecting tree copy\n"));
6843 reply_doserror(req, ERRSRV, ERRerror);
6844 goto out;
6847 /* Split up the directory from the filename/mask. */
6848 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6849 &fname_src_dir, &fname_src_mask);
6850 if (!NT_STATUS_IS_OK(status)) {
6851 reply_nterror(req, NT_STATUS_NO_MEMORY);
6852 goto out;
6856 * We should only check the mangled cache
6857 * here if unix_convert failed. This means
6858 * that the path in 'mask' doesn't exist
6859 * on the file system and so we need to look
6860 * for a possible mangle. This patch from
6861 * Tine Smukavec <valentin.smukavec@hermes.si>.
6863 if (!VALID_STAT(smb_fname_src->st) &&
6864 mangle_is_mangled(fname_src_mask, conn->params)) {
6865 char *new_mask = NULL;
6866 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6867 &new_mask, conn->params);
6869 /* Use demangled name if one was successfully found. */
6870 if (new_mask) {
6871 TALLOC_FREE(fname_src_mask);
6872 fname_src_mask = new_mask;
6876 if (!source_has_wild) {
6879 * Only one file needs to be copied. Append the mask back onto
6880 * the directory.
6882 TALLOC_FREE(smb_fname_src->base_name);
6883 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6884 "%s/%s",
6885 fname_src_dir,
6886 fname_src_mask);
6887 if (!smb_fname_src->base_name) {
6888 reply_nterror(req, NT_STATUS_NO_MEMORY);
6889 goto out;
6892 if (dest_has_wild) {
6893 char *fname_dst_mod = NULL;
6894 if (!resolve_wildcards(smb_fname_dst,
6895 smb_fname_src->base_name,
6896 smb_fname_dst->base_name,
6897 &fname_dst_mod)) {
6898 reply_nterror(req, NT_STATUS_NO_MEMORY);
6899 goto out;
6901 TALLOC_FREE(smb_fname_dst->base_name);
6902 smb_fname_dst->base_name = fname_dst_mod;
6905 status = check_name(conn, smb_fname_src->base_name);
6906 if (!NT_STATUS_IS_OK(status)) {
6907 reply_nterror(req, status);
6908 goto out;
6911 status = check_name(conn, smb_fname_dst->base_name);
6912 if (!NT_STATUS_IS_OK(status)) {
6913 reply_nterror(req, status);
6914 goto out;
6917 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6918 ofun, count, target_is_directory);
6920 if(!NT_STATUS_IS_OK(status)) {
6921 reply_nterror(req, status);
6922 goto out;
6923 } else {
6924 count++;
6926 } else {
6927 struct smb_Dir *dir_hnd = NULL;
6928 char *dname = NULL;
6929 long offset = 0;
6932 * There is a wildcard that requires us to actually read the
6933 * src dir and copy each file matching the mask to the dst.
6934 * Right now streams won't be copied, but this could
6935 * presumably be added with a nested loop for reach dir entry.
6937 SMB_ASSERT(!smb_fname_src->stream_name);
6938 SMB_ASSERT(!smb_fname_dst->stream_name);
6940 smb_fname_src->stream_name = NULL;
6941 smb_fname_dst->stream_name = NULL;
6943 if (strequal(fname_src_mask,"????????.???")) {
6944 TALLOC_FREE(fname_src_mask);
6945 fname_src_mask = talloc_strdup(ctx, "*");
6946 if (!fname_src_mask) {
6947 reply_nterror(req, NT_STATUS_NO_MEMORY);
6948 goto out;
6952 status = check_name(conn, fname_src_dir);
6953 if (!NT_STATUS_IS_OK(status)) {
6954 reply_nterror(req, status);
6955 goto out;
6958 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6959 if (dir_hnd == NULL) {
6960 status = map_nt_error_from_unix(errno);
6961 reply_nterror(req, status);
6962 goto out;
6965 error = ERRbadfile;
6967 /* Iterate over the src dir copying each entry to the dst. */
6968 while ((dname = ReadDirName(dir_hnd, &offset,
6969 &smb_fname_src->st))) {
6970 char *destname = NULL;
6972 if (ISDOT(dname) || ISDOTDOT(dname)) {
6973 TALLOC_FREE(dname);
6974 continue;
6977 if (!is_visible_file(conn, fname_src_dir, dname,
6978 &smb_fname_src->st, false)) {
6979 TALLOC_FREE(dname);
6980 continue;
6983 if(!mask_match(dname, fname_src_mask,
6984 conn->case_sensitive)) {
6985 TALLOC_FREE(dname);
6986 continue;
6989 error = ERRnoaccess;
6991 /* Get the src smb_fname struct setup. */
6992 TALLOC_FREE(smb_fname_src->base_name);
6993 smb_fname_src->base_name =
6994 talloc_asprintf(smb_fname_src, "%s/%s",
6995 fname_src_dir, dname);
6997 if (!smb_fname_src->base_name) {
6998 TALLOC_FREE(dir_hnd);
6999 TALLOC_FREE(dname);
7000 reply_nterror(req, NT_STATUS_NO_MEMORY);
7001 goto out;
7004 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7005 smb_fname_dst->base_name,
7006 &destname)) {
7007 TALLOC_FREE(dname);
7008 continue;
7010 if (!destname) {
7011 TALLOC_FREE(dir_hnd);
7012 TALLOC_FREE(dname);
7013 reply_nterror(req, NT_STATUS_NO_MEMORY);
7014 goto out;
7017 TALLOC_FREE(smb_fname_dst->base_name);
7018 smb_fname_dst->base_name = destname;
7020 status = check_name(conn, smb_fname_src->base_name);
7021 if (!NT_STATUS_IS_OK(status)) {
7022 TALLOC_FREE(dir_hnd);
7023 TALLOC_FREE(dname);
7024 reply_nterror(req, status);
7025 goto out;
7028 status = check_name(conn, smb_fname_dst->base_name);
7029 if (!NT_STATUS_IS_OK(status)) {
7030 TALLOC_FREE(dir_hnd);
7031 TALLOC_FREE(dname);
7032 reply_nterror(req, status);
7033 goto out;
7036 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7037 smb_fname_src->base_name,
7038 smb_fname_dst->base_name));
7040 status = copy_file(ctx, conn, smb_fname_src,
7041 smb_fname_dst, ofun, count,
7042 target_is_directory);
7043 if (NT_STATUS_IS_OK(status)) {
7044 count++;
7047 TALLOC_FREE(dname);
7049 TALLOC_FREE(dir_hnd);
7052 if (count == 0) {
7053 reply_doserror(req, ERRDOS, error);
7054 goto out;
7057 reply_outbuf(req, 1, 0);
7058 SSVAL(req->outbuf,smb_vwv0,count);
7059 out:
7060 TALLOC_FREE(smb_fname_src);
7061 TALLOC_FREE(smb_fname_dst);
7062 TALLOC_FREE(fname_src);
7063 TALLOC_FREE(fname_dst);
7064 TALLOC_FREE(fname_src_mask);
7065 TALLOC_FREE(fname_src_dir);
7067 END_PROFILE(SMBcopy);
7068 return;
7071 #undef DBGC_CLASS
7072 #define DBGC_CLASS DBGC_LOCKING
7074 /****************************************************************************
7075 Get a lock pid, dealing with large count requests.
7076 ****************************************************************************/
7078 uint32 get_lock_pid(const uint8_t *data, int data_offset,
7079 bool large_file_format)
7081 if(!large_file_format)
7082 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
7083 else
7084 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7087 /****************************************************************************
7088 Get a lock count, dealing with large count requests.
7089 ****************************************************************************/
7091 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7092 bool large_file_format)
7094 uint64_t count = 0;
7096 if(!large_file_format) {
7097 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7098 } else {
7100 #if defined(HAVE_LONGLONG)
7101 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7102 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7103 #else /* HAVE_LONGLONG */
7106 * NT4.x seems to be broken in that it sends large file (64 bit)
7107 * lockingX calls even if the CAP_LARGE_FILES was *not*
7108 * negotiated. For boxes without large unsigned ints truncate the
7109 * lock count by dropping the top 32 bits.
7112 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7113 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7114 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7115 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7116 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7119 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7120 #endif /* HAVE_LONGLONG */
7123 return count;
7126 #if !defined(HAVE_LONGLONG)
7127 /****************************************************************************
7128 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7129 ****************************************************************************/
7131 static uint32 map_lock_offset(uint32 high, uint32 low)
7133 unsigned int i;
7134 uint32 mask = 0;
7135 uint32 highcopy = high;
7138 * Try and find out how many significant bits there are in high.
7141 for(i = 0; highcopy; i++)
7142 highcopy >>= 1;
7145 * We use 31 bits not 32 here as POSIX
7146 * lock offsets may not be negative.
7149 mask = (~0) << (31 - i);
7151 if(low & mask)
7152 return 0; /* Fail. */
7154 high <<= (31 - i);
7156 return (high|low);
7158 #endif /* !defined(HAVE_LONGLONG) */
7160 /****************************************************************************
7161 Get a lock offset, dealing with large offset requests.
7162 ****************************************************************************/
7164 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7165 bool large_file_format, bool *err)
7167 uint64_t offset = 0;
7169 *err = False;
7171 if(!large_file_format) {
7172 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7173 } else {
7175 #if defined(HAVE_LONGLONG)
7176 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7177 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7178 #else /* HAVE_LONGLONG */
7181 * NT4.x seems to be broken in that it sends large file (64 bit)
7182 * lockingX calls even if the CAP_LARGE_FILES was *not*
7183 * negotiated. For boxes without large unsigned ints mangle the
7184 * lock offset by mapping the top 32 bits onto the lower 32.
7187 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7188 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7189 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7190 uint32 new_low = 0;
7192 if((new_low = map_lock_offset(high, low)) == 0) {
7193 *err = True;
7194 return (uint64_t)-1;
7197 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7198 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7199 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7200 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7203 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7204 #endif /* HAVE_LONGLONG */
7207 return offset;
7210 NTSTATUS smbd_do_locking(struct smb_request *req,
7211 files_struct *fsp,
7212 uint8_t type,
7213 int32_t timeout,
7214 uint16_t num_ulocks,
7215 struct smbd_lock_element *ulocks,
7216 uint16_t num_locks,
7217 struct smbd_lock_element *locks,
7218 bool *async)
7220 connection_struct *conn = req->conn;
7221 int i;
7222 NTSTATUS status = NT_STATUS_OK;
7224 *async = false;
7226 /* Data now points at the beginning of the list
7227 of smb_unlkrng structs */
7228 for(i = 0; i < (int)num_ulocks; i++) {
7229 struct smbd_lock_element *e = &ulocks[i];
7231 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7232 "pid %u, file %s\n",
7233 (double)e->offset,
7234 (double)e->count,
7235 (unsigned int)e->smbpid,
7236 fsp_str_dbg(fsp)));
7238 if (e->brltype != UNLOCK_LOCK) {
7239 /* this can only happen with SMB2 */
7240 return NT_STATUS_INVALID_PARAMETER;
7243 status = do_unlock(smbd_messaging_context(),
7244 fsp,
7245 e->smbpid,
7246 e->count,
7247 e->offset,
7248 WINDOWS_LOCK);
7250 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7251 nt_errstr(status)));
7253 if (!NT_STATUS_IS_OK(status)) {
7254 return status;
7258 /* Setup the timeout in seconds. */
7260 if (!lp_blocking_locks(SNUM(conn))) {
7261 timeout = 0;
7264 /* Data now points at the beginning of the list
7265 of smb_lkrng structs */
7267 for(i = 0; i < (int)num_locks; i++) {
7268 struct smbd_lock_element *e = &locks[i];
7270 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
7271 "%u, file %s timeout = %d\n",
7272 (double)e->offset,
7273 (double)e->count,
7274 (unsigned int)e->smbpid,
7275 fsp_str_dbg(fsp),
7276 (int)timeout));
7278 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7279 struct blocking_lock_record *blr = NULL;
7281 if (lp_blocking_locks(SNUM(conn))) {
7283 /* Schedule a message to ourselves to
7284 remove the blocking lock record and
7285 return the right error. */
7287 blr = blocking_lock_cancel(fsp,
7288 e->smbpid,
7289 e->offset,
7290 e->count,
7291 WINDOWS_LOCK,
7292 type,
7293 NT_STATUS_FILE_LOCK_CONFLICT);
7294 if (blr == NULL) {
7295 return NT_STATUS_DOS(
7296 ERRDOS,
7297 ERRcancelviolation);
7300 /* Remove a matching pending lock. */
7301 status = do_lock_cancel(fsp,
7302 e->smbpid,
7303 e->count,
7304 e->offset,
7305 WINDOWS_LOCK,
7306 blr);
7307 } else {
7308 bool blocking_lock = timeout ? true : false;
7309 bool defer_lock = false;
7310 struct byte_range_lock *br_lck;
7311 uint32_t block_smbpid;
7313 br_lck = do_lock(smbd_messaging_context(),
7314 fsp,
7315 e->smbpid,
7316 e->count,
7317 e->offset,
7318 e->brltype,
7319 WINDOWS_LOCK,
7320 blocking_lock,
7321 &status,
7322 &block_smbpid,
7323 NULL);
7325 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7326 /* Windows internal resolution for blocking locks seems
7327 to be about 200ms... Don't wait for less than that. JRA. */
7328 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7329 timeout = lp_lock_spin_time();
7331 defer_lock = true;
7334 /* This heuristic seems to match W2K3 very well. If a
7335 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7336 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7337 far as I can tell. Replacement for do_lock_spin(). JRA. */
7339 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7340 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7341 defer_lock = true;
7342 timeout = lp_lock_spin_time();
7345 if (br_lck && defer_lock) {
7347 * A blocking lock was requested. Package up
7348 * this smb into a queued request and push it
7349 * onto the blocking lock queue.
7351 if(push_blocking_lock_request(br_lck,
7352 req,
7353 fsp,
7354 timeout,
7356 e->smbpid,
7357 e->brltype,
7358 WINDOWS_LOCK,
7359 e->offset,
7360 e->count,
7361 block_smbpid)) {
7362 TALLOC_FREE(br_lck);
7363 *async = true;
7364 return NT_STATUS_OK;
7368 TALLOC_FREE(br_lck);
7371 if (!NT_STATUS_IS_OK(status)) {
7372 break;
7376 /* If any of the above locks failed, then we must unlock
7377 all of the previous locks (X/Open spec). */
7379 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7381 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7382 i = -1; /* we want to skip the for loop */
7386 * Ensure we don't do a remove on the lock that just failed,
7387 * as under POSIX rules, if we have a lock already there, we
7388 * will delete it (and we shouldn't) .....
7390 for(i--; i >= 0; i--) {
7391 struct smbd_lock_element *e = &locks[i];
7393 do_unlock(smbd_messaging_context(),
7394 fsp,
7395 e->smbpid,
7396 e->count,
7397 e->offset,
7398 WINDOWS_LOCK);
7400 return status;
7403 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7404 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7406 return NT_STATUS_OK;
7409 /****************************************************************************
7410 Reply to a lockingX request.
7411 ****************************************************************************/
7413 void reply_lockingX(struct smb_request *req)
7415 connection_struct *conn = req->conn;
7416 files_struct *fsp;
7417 unsigned char locktype;
7418 unsigned char oplocklevel;
7419 uint16 num_ulocks;
7420 uint16 num_locks;
7421 int32 lock_timeout;
7422 int i;
7423 const uint8_t *data;
7424 bool large_file_format;
7425 bool err;
7426 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7427 struct smbd_lock_element *ulocks;
7428 struct smbd_lock_element *locks;
7429 bool async = false;
7431 START_PROFILE(SMBlockingX);
7433 if (req->wct < 8) {
7434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7435 END_PROFILE(SMBlockingX);
7436 return;
7439 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7440 locktype = CVAL(req->vwv+3, 0);
7441 oplocklevel = CVAL(req->vwv+3, 1);
7442 num_ulocks = SVAL(req->vwv+6, 0);
7443 num_locks = SVAL(req->vwv+7, 0);
7444 lock_timeout = IVAL(req->vwv+4, 0);
7445 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7447 if (!check_fsp(conn, req, fsp)) {
7448 END_PROFILE(SMBlockingX);
7449 return;
7452 data = req->buf;
7454 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7455 /* we don't support these - and CANCEL_LOCK makes w2k
7456 and XP reboot so I don't really want to be
7457 compatible! (tridge) */
7458 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7459 END_PROFILE(SMBlockingX);
7460 return;
7463 /* Check if this is an oplock break on a file
7464 we have granted an oplock on.
7466 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7467 /* Client can insist on breaking to none. */
7468 bool break_to_none = (oplocklevel == 0);
7469 bool result;
7471 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7472 "for fnum = %d\n", (unsigned int)oplocklevel,
7473 fsp->fnum ));
7476 * Make sure we have granted an exclusive or batch oplock on
7477 * this file.
7480 if (fsp->oplock_type == 0) {
7482 /* The Samba4 nbench simulator doesn't understand
7483 the difference between break to level2 and break
7484 to none from level2 - it sends oplock break
7485 replies in both cases. Don't keep logging an error
7486 message here - just ignore it. JRA. */
7488 DEBUG(5,("reply_lockingX: Error : oplock break from "
7489 "client for fnum = %d (oplock=%d) and no "
7490 "oplock granted on this file (%s).\n",
7491 fsp->fnum, fsp->oplock_type,
7492 fsp_str_dbg(fsp)));
7494 /* if this is a pure oplock break request then don't
7495 * send a reply */
7496 if (num_locks == 0 && num_ulocks == 0) {
7497 END_PROFILE(SMBlockingX);
7498 return;
7499 } else {
7500 END_PROFILE(SMBlockingX);
7501 reply_doserror(req, ERRDOS, ERRlock);
7502 return;
7506 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7507 (break_to_none)) {
7508 result = remove_oplock(fsp);
7509 } else {
7510 result = downgrade_oplock(fsp);
7513 if (!result) {
7514 DEBUG(0, ("reply_lockingX: error in removing "
7515 "oplock on file %s\n", fsp_str_dbg(fsp)));
7516 /* Hmmm. Is this panic justified? */
7517 smb_panic("internal tdb error");
7520 reply_to_oplock_break_requests(fsp);
7522 /* if this is a pure oplock break request then don't send a
7523 * reply */
7524 if (num_locks == 0 && num_ulocks == 0) {
7525 /* Sanity check - ensure a pure oplock break is not a
7526 chained request. */
7527 if(CVAL(req->vwv+0, 0) != 0xff)
7528 DEBUG(0,("reply_lockingX: Error : pure oplock "
7529 "break is a chained %d request !\n",
7530 (unsigned int)CVAL(req->vwv+0, 0)));
7531 END_PROFILE(SMBlockingX);
7532 return;
7536 if (req->buflen <
7537 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7538 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7539 END_PROFILE(SMBlockingX);
7540 return;
7543 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7544 if (ulocks == NULL) {
7545 reply_nterror(req, NT_STATUS_NO_MEMORY);
7546 END_PROFILE(SMBlockingX);
7547 return;
7550 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7551 if (locks == NULL) {
7552 reply_nterror(req, NT_STATUS_NO_MEMORY);
7553 END_PROFILE(SMBlockingX);
7554 return;
7557 /* Data now points at the beginning of the list
7558 of smb_unlkrng structs */
7559 for(i = 0; i < (int)num_ulocks; i++) {
7560 ulocks[i].smbpid = get_lock_pid(data, i, large_file_format);
7561 ulocks[i].count = get_lock_count(data, i, large_file_format);
7562 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7563 ulocks[i].brltype = UNLOCK_LOCK;
7566 * There is no error code marked "stupid client bug".... :-).
7568 if(err) {
7569 END_PROFILE(SMBlockingX);
7570 reply_doserror(req, ERRDOS, ERRnoaccess);
7571 return;
7575 /* Now do any requested locks */
7576 data += ((large_file_format ? 20 : 10)*num_ulocks);
7578 /* Data now points at the beginning of the list
7579 of smb_lkrng structs */
7581 for(i = 0; i < (int)num_locks; i++) {
7582 locks[i].smbpid = get_lock_pid(data, i, large_file_format);
7583 locks[i].count = get_lock_count(data, i, large_file_format);
7584 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7586 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7587 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7588 locks[i].brltype = PENDING_READ_LOCK;
7589 } else {
7590 locks[i].brltype = READ_LOCK;
7592 } else {
7593 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7594 locks[i].brltype = PENDING_WRITE_LOCK;
7595 } else {
7596 locks[i].brltype = WRITE_LOCK;
7601 * There is no error code marked "stupid client bug".... :-).
7603 if(err) {
7604 END_PROFILE(SMBlockingX);
7605 reply_doserror(req, ERRDOS, ERRnoaccess);
7606 return;
7610 status = smbd_do_locking(req, fsp,
7611 locktype, lock_timeout,
7612 num_ulocks, ulocks,
7613 num_locks, locks,
7614 &async);
7615 if (!NT_STATUS_IS_OK(status)) {
7616 END_PROFILE(SMBlockingX);
7617 reply_nterror(req, status);
7618 return;
7620 if (async) {
7621 END_PROFILE(SMBlockingX);
7622 return;
7625 reply_outbuf(req, 2, 0);
7627 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7628 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7630 END_PROFILE(SMBlockingX);
7631 chain_reply(req);
7634 #undef DBGC_CLASS
7635 #define DBGC_CLASS DBGC_ALL
7637 /****************************************************************************
7638 Reply to a SMBreadbmpx (read block multiplex) request.
7639 Always reply with an error, if someone has a platform really needs this,
7640 please contact vl@samba.org
7641 ****************************************************************************/
7643 void reply_readbmpx(struct smb_request *req)
7645 START_PROFILE(SMBreadBmpx);
7646 reply_doserror(req, ERRSRV, ERRuseSTD);
7647 END_PROFILE(SMBreadBmpx);
7648 return;
7651 /****************************************************************************
7652 Reply to a SMBreadbs (read block multiplex secondary) request.
7653 Always reply with an error, if someone has a platform really needs this,
7654 please contact vl@samba.org
7655 ****************************************************************************/
7657 void reply_readbs(struct smb_request *req)
7659 START_PROFILE(SMBreadBs);
7660 reply_doserror(req, ERRSRV, ERRuseSTD);
7661 END_PROFILE(SMBreadBs);
7662 return;
7665 /****************************************************************************
7666 Reply to a SMBsetattrE.
7667 ****************************************************************************/
7669 void reply_setattrE(struct smb_request *req)
7671 connection_struct *conn = req->conn;
7672 struct smb_file_time ft;
7673 files_struct *fsp;
7674 NTSTATUS status;
7676 START_PROFILE(SMBsetattrE);
7677 ZERO_STRUCT(ft);
7679 if (req->wct < 7) {
7680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7681 goto out;
7684 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7686 if(!fsp || (fsp->conn != conn)) {
7687 reply_doserror(req, ERRDOS, ERRbadfid);
7688 goto out;
7692 * Convert the DOS times into unix times.
7695 ft.atime = convert_time_t_to_timespec(
7696 srv_make_unix_date2(req->vwv+3));
7697 ft.mtime = convert_time_t_to_timespec(
7698 srv_make_unix_date2(req->vwv+5));
7699 ft.create_time = convert_time_t_to_timespec(
7700 srv_make_unix_date2(req->vwv+1));
7702 reply_outbuf(req, 0, 0);
7705 * Patch from Ray Frush <frush@engr.colostate.edu>
7706 * Sometimes times are sent as zero - ignore them.
7709 /* Ensure we have a valid stat struct for the source. */
7710 if (fsp->fh->fd != -1) {
7711 if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) == -1) {
7712 status = map_nt_error_from_unix(errno);
7713 reply_nterror(req, status);
7714 goto out;
7716 } else {
7717 int ret = -1;
7719 if (fsp->posix_open) {
7720 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name);
7721 } else {
7722 ret = SMB_VFS_STAT(conn, fsp->fsp_name);
7724 if (ret == -1) {
7725 status = map_nt_error_from_unix(errno);
7726 reply_nterror(req, status);
7727 goto out;
7731 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7732 if (!NT_STATUS_IS_OK(status)) {
7733 reply_doserror(req, ERRDOS, ERRnoaccess);
7734 goto out;
7737 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7738 " createtime=%u\n",
7739 fsp->fnum,
7740 (unsigned int)ft.atime.tv_sec,
7741 (unsigned int)ft.mtime.tv_sec,
7742 (unsigned int)ft.create_time.tv_sec
7744 out:
7745 END_PROFILE(SMBsetattrE);
7746 return;
7750 /* Back from the dead for OS/2..... JRA. */
7752 /****************************************************************************
7753 Reply to a SMBwritebmpx (write block multiplex primary) request.
7754 Always reply with an error, if someone has a platform really needs this,
7755 please contact vl@samba.org
7756 ****************************************************************************/
7758 void reply_writebmpx(struct smb_request *req)
7760 START_PROFILE(SMBwriteBmpx);
7761 reply_doserror(req, ERRSRV, ERRuseSTD);
7762 END_PROFILE(SMBwriteBmpx);
7763 return;
7766 /****************************************************************************
7767 Reply to a SMBwritebs (write block multiplex secondary) request.
7768 Always reply with an error, if someone has a platform really needs this,
7769 please contact vl@samba.org
7770 ****************************************************************************/
7772 void reply_writebs(struct smb_request *req)
7774 START_PROFILE(SMBwriteBs);
7775 reply_doserror(req, ERRSRV, ERRuseSTD);
7776 END_PROFILE(SMBwriteBs);
7777 return;
7780 /****************************************************************************
7781 Reply to a SMBgetattrE.
7782 ****************************************************************************/
7784 void reply_getattrE(struct smb_request *req)
7786 connection_struct *conn = req->conn;
7787 SMB_STRUCT_STAT sbuf;
7788 int mode;
7789 files_struct *fsp;
7790 struct timespec create_ts;
7792 START_PROFILE(SMBgetattrE);
7794 if (req->wct < 1) {
7795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7796 END_PROFILE(SMBgetattrE);
7797 return;
7800 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7802 if(!fsp || (fsp->conn != conn)) {
7803 reply_doserror(req, ERRDOS, ERRbadfid);
7804 END_PROFILE(SMBgetattrE);
7805 return;
7808 /* Do an fstat on this file */
7809 if(fsp_stat(fsp, &sbuf)) {
7810 reply_nterror(req, map_nt_error_from_unix(errno));
7811 END_PROFILE(SMBgetattrE);
7812 return;
7815 fsp->fsp_name->st = sbuf;
7817 mode = dos_mode(conn, fsp->fsp_name);
7820 * Convert the times into dos times. Set create
7821 * date to be last modify date as UNIX doesn't save
7822 * this.
7825 reply_outbuf(req, 11, 0);
7827 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7828 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7829 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7830 convert_timespec_to_time_t(sbuf.st_ex_atime));
7831 /* Should we check pending modtime here ? JRA */
7832 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7833 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7835 if (mode & aDIR) {
7836 SIVAL(req->outbuf, smb_vwv6, 0);
7837 SIVAL(req->outbuf, smb_vwv8, 0);
7838 } else {
7839 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7840 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7841 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7843 SSVAL(req->outbuf,smb_vwv10, mode);
7845 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7847 END_PROFILE(SMBgetattrE);
7848 return;