Fix bug #7892 - open_file_fchmod() leaves a stale lock.
[Samba.git] / source3 / smbd / reply.c
blob2dd4bad6afadeaf2006aa86169d1833092f20720
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 bool start_of_name_component = True;
50 bool stream_started = false;
51 bool check_quota = 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 if (StrCaseCmp(s, ":$DATA") != 0) {
69 check_quota = true;
71 break;
75 if (!posix_path && !stream_started && *s == ':') {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* Stream names allow more characters than file names.
80 We're overloading posix_path here to allow a wider
81 range of characters. If stream_started is true this
82 is still a Windows path even if posix_path is true.
83 JRA.
85 stream_started = true;
86 start_of_name_component = false;
87 posix_path = true;
89 if (s[1] == '\0') {
90 return NT_STATUS_OBJECT_NAME_INVALID;
94 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
96 * Safe to assume is not the second part of a mb char
97 * as this is handled below.
99 /* Eat multiple '/' or '\\' */
100 while (IS_PATH_SEP(*s,posix_path)) {
101 s++;
103 if ((d != path) && (*s != '\0')) {
104 /* We only care about non-leading or trailing '/' or '\\' */
105 *d++ = '/';
108 start_of_name_component = True;
109 /* New component. */
110 *p_last_component_contains_wcard = False;
111 continue;
114 if (start_of_name_component) {
115 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
119 * No mb char starts with '.' so we're safe checking the directory separator here.
122 /* If we just added a '/' - delete it */
123 if ((d > path) && (*(d-1) == '/')) {
124 *(d-1) = '\0';
125 d--;
128 /* Are we at the start ? Can't go back further if so. */
129 if (d <= path) {
130 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
132 /* Go back one level... */
133 /* We know this is safe as '/' cannot be part of a mb sequence. */
134 /* NOTE - if this assumption is invalid we are not in good shape... */
135 /* Decrement d first as d points to the *next* char to write into. */
136 for (d--; d > path; d--) {
137 if (*d == '/')
138 break;
140 s += 2; /* Else go past the .. */
141 /* We're still at the start of a name component, just the previous one. */
142 continue;
144 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
145 if (posix_path) {
146 /* Eat the '.' */
147 s++;
148 continue;
154 if (!(*s & 0x80)) {
155 if (!posix_path) {
156 if (*s <= 0x1f || *s == '|') {
157 return NT_STATUS_OBJECT_NAME_INVALID;
159 switch (*s) {
160 case '*':
161 case '?':
162 case '<':
163 case '>':
164 case '"':
165 *p_last_component_contains_wcard = True;
166 break;
167 default:
168 break;
171 *d++ = *s++;
172 } else {
173 size_t siz;
174 /* Get the size of the next MB character. */
175 next_codepoint(s,&siz);
176 switch(siz) {
177 case 5:
178 *d++ = *s++;
179 /*fall through*/
180 case 4:
181 *d++ = *s++;
182 /*fall through*/
183 case 3:
184 *d++ = *s++;
185 /*fall through*/
186 case 2:
187 *d++ = *s++;
188 /*fall through*/
189 case 1:
190 *d++ = *s++;
191 break;
192 default:
193 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
194 *d = '\0';
195 return NT_STATUS_INVALID_PARAMETER;
198 start_of_name_component = False;
201 *d = '\0';
203 if (check_quota) {
204 if (StrCaseCmp(path, FAKE_FILE_NAME_QUOTA_UNIX) != 0) {
205 return NT_STATUS_INVALID_PARAMETER;
209 return NT_STATUS_OK;
212 /****************************************************************************
213 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
214 No wildcards allowed.
215 ****************************************************************************/
217 NTSTATUS check_path_syntax(char *path)
219 bool ignore;
220 return check_path_syntax_internal(path, False, &ignore);
223 /****************************************************************************
224 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
225 Wildcards allowed - p_contains_wcard returns true if the last component contained
226 a wildcard.
227 ****************************************************************************/
229 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
231 return check_path_syntax_internal(path, False, p_contains_wcard);
234 /****************************************************************************
235 Check the path for a POSIX client.
236 We're assuming here that '/' is not the second byte in any multibyte char
237 set (a safe assumption).
238 ****************************************************************************/
240 NTSTATUS check_path_syntax_posix(char *path)
242 bool ignore;
243 return check_path_syntax_internal(path, True, &ignore);
246 /****************************************************************************
247 Pull a string and check the path allowing a wilcard - provide for error return.
248 ****************************************************************************/
250 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
251 const char *base_ptr,
252 uint16 smb_flags2,
253 char **pp_dest,
254 const char *src,
255 size_t src_len,
256 int flags,
257 NTSTATUS *err,
258 bool *contains_wcard)
260 size_t ret;
262 *pp_dest = NULL;
264 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
265 src_len, flags);
267 if (!*pp_dest) {
268 *err = NT_STATUS_INVALID_PARAMETER;
269 return ret;
272 *contains_wcard = False;
274 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
276 * For a DFS path the function parse_dfs_path()
277 * will do the path processing, just make a copy.
279 *err = NT_STATUS_OK;
280 return ret;
283 if (lp_posix_pathnames()) {
284 *err = check_path_syntax_posix(*pp_dest);
285 } else {
286 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
289 return ret;
292 /****************************************************************************
293 Pull a string and check the path - provide for error return.
294 ****************************************************************************/
296 size_t srvstr_get_path(TALLOC_CTX *ctx,
297 const char *base_ptr,
298 uint16 smb_flags2,
299 char **pp_dest,
300 const char *src,
301 size_t src_len,
302 int flags,
303 NTSTATUS *err)
305 bool ignore;
306 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
307 src_len, flags, err, &ignore);
310 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
311 char **pp_dest, const char *src, int flags,
312 NTSTATUS *err, bool *contains_wcard)
314 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
315 pp_dest, src, smbreq_bufrem(req, src),
316 flags, err, contains_wcard);
319 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
320 char **pp_dest, const char *src, int flags,
321 NTSTATUS *err)
323 bool ignore;
324 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
325 flags, err, &ignore);
328 /****************************************************************************
329 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
330 ****************************************************************************/
332 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
333 files_struct *fsp)
335 if (!(fsp) || !(conn)) {
336 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
337 return False;
339 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
340 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
341 return False;
343 return True;
346 /****************************************************************************
347 Check if we have a correct fsp pointing to a file.
348 ****************************************************************************/
350 bool check_fsp(connection_struct *conn, struct smb_request *req,
351 files_struct *fsp)
353 if (!check_fsp_open(conn, req, fsp)) {
354 return False;
356 if ((fsp)->is_directory) {
357 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
358 return False;
360 if ((fsp)->fh->fd == -1) {
361 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
362 return False;
364 (fsp)->num_smb_operations++;
365 return True;
368 /****************************************************************************
369 Check if we have a correct fsp pointing to a quota fake file. Replacement for
370 the CHECK_NTQUOTA_HANDLE_OK macro.
371 ****************************************************************************/
373 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
374 files_struct *fsp)
376 if (!check_fsp_open(conn, req, fsp)) {
377 return false;
380 if (fsp->is_directory) {
381 return false;
384 if (fsp->fake_file_handle == NULL) {
385 return false;
388 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
389 return false;
392 if (fsp->fake_file_handle->private_data == NULL) {
393 return false;
396 return true;
399 /****************************************************************************
400 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
401 ****************************************************************************/
403 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
404 files_struct *fsp)
406 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
407 && (req->vuid == (fsp)->vuid)) {
408 return True;
411 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
412 return False;
415 /****************************************************************************
416 Reply to a (netbios-level) special message.
417 ****************************************************************************/
419 void reply_special(char *inbuf)
421 int msg_type = CVAL(inbuf,0);
422 int msg_flags = CVAL(inbuf,1);
423 fstring name1,name2;
424 char name_type = 0;
427 * We only really use 4 bytes of the outbuf, but for the smb_setlen
428 * calculation & friends (srv_send_smb uses that) we need the full smb
429 * header.
431 char outbuf[smb_size];
433 *name1 = *name2 = 0;
435 memset(outbuf, '\0', sizeof(outbuf));
437 smb_setlen(outbuf,0);
439 switch (msg_type) {
440 case 0x81: /* session request */
442 if (already_got_session) {
443 exit_server_cleanly("multiple session request not permitted");
446 SCVAL(outbuf,0,0x82);
447 SCVAL(outbuf,3,0);
448 if (name_len(inbuf+4) > 50 ||
449 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
450 DEBUG(0,("Invalid name length in session request\n"));
451 return;
453 name_extract(inbuf,4,name1);
454 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
455 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
456 name1,name2));
458 set_local_machine_name(name1, True);
459 set_remote_machine_name(name2, True);
461 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
462 get_local_machine_name(), get_remote_machine_name(),
463 name_type));
465 if (name_type == 'R') {
466 /* We are being asked for a pathworks session ---
467 no thanks! */
468 SCVAL(outbuf, 0,0x83);
469 break;
472 /* only add the client's machine name to the list
473 of possibly valid usernames if we are operating
474 in share mode security */
475 if (lp_security() == SEC_SHARE) {
476 add_session_user(get_remote_machine_name());
479 reload_services(True);
480 reopen_logs();
482 already_got_session = True;
483 break;
485 case 0x89: /* session keepalive request
486 (some old clients produce this?) */
487 SCVAL(outbuf,0,SMBkeepalive);
488 SCVAL(outbuf,3,0);
489 break;
491 case 0x82: /* positive session response */
492 case 0x83: /* negative session response */
493 case 0x84: /* retarget session response */
494 DEBUG(0,("Unexpected session response\n"));
495 break;
497 case SMBkeepalive: /* session keepalive */
498 default:
499 return;
502 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
503 msg_type, msg_flags));
505 srv_send_smb(smbd_server_fd(), outbuf, false, NULL);
506 return;
509 /****************************************************************************
510 Reply to a tcon.
511 conn POINTER CAN BE NULL HERE !
512 ****************************************************************************/
514 void reply_tcon(struct smb_request *req)
516 connection_struct *conn = req->conn;
517 const char *service;
518 char *service_buf = NULL;
519 char *password = NULL;
520 char *dev = NULL;
521 int pwlen=0;
522 NTSTATUS nt_status;
523 const char *p;
524 DATA_BLOB password_blob;
525 TALLOC_CTX *ctx = talloc_tos();
527 START_PROFILE(SMBtcon);
529 if (req->buflen < 4) {
530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
531 END_PROFILE(SMBtcon);
532 return;
535 p = (const char *)req->buf + 1;
536 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
537 p += 1;
538 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
539 p += pwlen+1;
540 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
541 p += 1;
543 if (service_buf == NULL || password == NULL || dev == NULL) {
544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
545 END_PROFILE(SMBtcon);
546 return;
548 p = strrchr_m(service_buf,'\\');
549 if (p) {
550 service = p+1;
551 } else {
552 service = service_buf;
555 password_blob = data_blob(password, pwlen+1);
557 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
558 req->conn = conn;
560 data_blob_clear_free(&password_blob);
562 if (!conn) {
563 reply_nterror(req, nt_status);
564 END_PROFILE(SMBtcon);
565 return;
568 reply_outbuf(req, 2, 0);
569 SSVAL(req->outbuf,smb_vwv0,max_recv);
570 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
571 SSVAL(req->outbuf,smb_tid,conn->cnum);
573 DEBUG(3,("tcon service=%s cnum=%d\n",
574 service, conn->cnum));
576 END_PROFILE(SMBtcon);
577 return;
580 /****************************************************************************
581 Reply to a tcon and X.
582 conn POINTER CAN BE NULL HERE !
583 ****************************************************************************/
585 void reply_tcon_and_X(struct smb_request *req)
587 connection_struct *conn = req->conn;
588 const char *service = NULL;
589 DATA_BLOB password;
590 TALLOC_CTX *ctx = talloc_tos();
591 /* what the cleint thinks the device is */
592 char *client_devicetype = NULL;
593 /* what the server tells the client the share represents */
594 const char *server_devicetype;
595 NTSTATUS nt_status;
596 int passlen;
597 char *path = NULL;
598 const char *p, *q;
599 uint16 tcon_flags;
601 START_PROFILE(SMBtconX);
603 if (req->wct < 4) {
604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
605 END_PROFILE(SMBtconX);
606 return;
609 passlen = SVAL(req->vwv+3, 0);
610 tcon_flags = SVAL(req->vwv+2, 0);
612 /* we might have to close an old one */
613 if ((tcon_flags & 0x1) && conn) {
614 close_cnum(conn,req->vuid);
615 req->conn = NULL;
616 conn = NULL;
619 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
620 reply_doserror(req, ERRDOS, ERRbuftoosmall);
621 END_PROFILE(SMBtconX);
622 return;
625 if (global_encrypted_passwords_negotiated) {
626 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
627 if (lp_security() == SEC_SHARE) {
629 * Security = share always has a pad byte
630 * after the password.
632 p = (const char *)req->buf + passlen + 1;
633 } else {
634 p = (const char *)req->buf + passlen;
636 } else {
637 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
638 /* Ensure correct termination */
639 password.data[passlen]=0;
640 p = (const char *)req->buf + passlen + 1;
643 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
645 if (path == NULL) {
646 data_blob_clear_free(&password);
647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
648 END_PROFILE(SMBtconX);
649 return;
653 * the service name can be either: \\server\share
654 * or share directly like on the DELL PowerVault 705
656 if (*path=='\\') {
657 q = strchr_m(path+2,'\\');
658 if (!q) {
659 data_blob_clear_free(&password);
660 reply_doserror(req, ERRDOS, ERRnosuchshare);
661 END_PROFILE(SMBtconX);
662 return;
664 service = q+1;
665 } else {
666 service = path;
669 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
670 &client_devicetype, p,
671 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
673 if (client_devicetype == NULL) {
674 data_blob_clear_free(&password);
675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
676 END_PROFILE(SMBtconX);
677 return;
680 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
682 conn = make_connection(service, password, client_devicetype,
683 req->vuid, &nt_status);
684 req->conn =conn;
686 data_blob_clear_free(&password);
688 if (!conn) {
689 reply_nterror(req, nt_status);
690 END_PROFILE(SMBtconX);
691 return;
694 if ( IS_IPC(conn) )
695 server_devicetype = "IPC";
696 else if ( IS_PRINT(conn) )
697 server_devicetype = "LPT1:";
698 else
699 server_devicetype = "A:";
701 if (Protocol < PROTOCOL_NT1) {
702 reply_outbuf(req, 2, 0);
703 if (message_push_string(&req->outbuf, server_devicetype,
704 STR_TERMINATE|STR_ASCII) == -1) {
705 reply_nterror(req, NT_STATUS_NO_MEMORY);
706 END_PROFILE(SMBtconX);
707 return;
709 } else {
710 /* NT sets the fstype of IPC$ to the null string */
711 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
713 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
714 /* Return permissions. */
715 uint32 perm1 = 0;
716 uint32 perm2 = 0;
718 reply_outbuf(req, 7, 0);
720 if (IS_IPC(conn)) {
721 perm1 = FILE_ALL_ACCESS;
722 perm2 = FILE_ALL_ACCESS;
723 } else {
724 perm1 = CAN_WRITE(conn) ?
725 SHARE_ALL_ACCESS :
726 SHARE_READ_ONLY;
729 SIVAL(req->outbuf, smb_vwv3, perm1);
730 SIVAL(req->outbuf, smb_vwv5, perm2);
731 } else {
732 reply_outbuf(req, 3, 0);
735 if ((message_push_string(&req->outbuf, server_devicetype,
736 STR_TERMINATE|STR_ASCII) == -1)
737 || (message_push_string(&req->outbuf, fstype,
738 STR_TERMINATE) == -1)) {
739 reply_nterror(req, NT_STATUS_NO_MEMORY);
740 END_PROFILE(SMBtconX);
741 return;
744 /* what does setting this bit do? It is set by NT4 and
745 may affect the ability to autorun mounted cdroms */
746 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
747 (lp_csc_policy(SNUM(conn)) << 2));
749 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
750 DEBUG(2,("Serving %s as a Dfs root\n",
751 lp_servicename(SNUM(conn)) ));
752 SSVAL(req->outbuf, smb_vwv2,
753 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
758 DEBUG(3,("tconX service=%s \n",
759 service));
761 /* set the incoming and outgoing tid to the just created one */
762 SSVAL(req->inbuf,smb_tid,conn->cnum);
763 SSVAL(req->outbuf,smb_tid,conn->cnum);
765 END_PROFILE(SMBtconX);
767 req->tid = conn->cnum;
768 chain_reply(req);
769 return;
772 /****************************************************************************
773 Reply to an unknown type.
774 ****************************************************************************/
776 void reply_unknown_new(struct smb_request *req, uint8 type)
778 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
779 smb_fn_name(type), type, type));
780 reply_doserror(req, ERRSRV, ERRunknownsmb);
781 return;
784 /****************************************************************************
785 Reply to an ioctl.
786 conn POINTER CAN BE NULL HERE !
787 ****************************************************************************/
789 void reply_ioctl(struct smb_request *req)
791 connection_struct *conn = req->conn;
792 uint16 device;
793 uint16 function;
794 uint32 ioctl_code;
795 int replysize;
796 char *p;
798 START_PROFILE(SMBioctl);
800 if (req->wct < 3) {
801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
802 END_PROFILE(SMBioctl);
803 return;
806 device = SVAL(req->vwv+1, 0);
807 function = SVAL(req->vwv+2, 0);
808 ioctl_code = (device << 16) + function;
810 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
812 switch (ioctl_code) {
813 case IOCTL_QUERY_JOB_INFO:
814 replysize = 32;
815 break;
816 default:
817 reply_doserror(req, ERRSRV, ERRnosupport);
818 END_PROFILE(SMBioctl);
819 return;
822 reply_outbuf(req, 8, replysize+1);
823 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
824 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
825 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
826 p = smb_buf(req->outbuf);
827 memset(p, '\0', replysize+1); /* valgrind-safe. */
828 p += 1; /* Allow for alignment */
830 switch (ioctl_code) {
831 case IOCTL_QUERY_JOB_INFO:
833 files_struct *fsp = file_fsp(
834 req, SVAL(req->vwv+0, 0));
835 if (!fsp) {
836 reply_doserror(req, ERRDOS, ERRbadfid);
837 END_PROFILE(SMBioctl);
838 return;
840 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
841 srvstr_push((char *)req->outbuf, req->flags2, p+2,
842 global_myname(), 15,
843 STR_TERMINATE|STR_ASCII);
844 if (conn) {
845 srvstr_push((char *)req->outbuf, req->flags2,
846 p+18, lp_servicename(SNUM(conn)),
847 13, STR_TERMINATE|STR_ASCII);
848 } else {
849 memset(p+18, 0, 13);
851 break;
855 END_PROFILE(SMBioctl);
856 return;
859 /****************************************************************************
860 Strange checkpath NTSTATUS mapping.
861 ****************************************************************************/
863 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
865 /* Strange DOS error code semantics only for checkpath... */
866 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
867 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
868 /* We need to map to ERRbadpath */
869 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
872 return status;
875 /****************************************************************************
876 Reply to a checkpath.
877 ****************************************************************************/
879 void reply_checkpath(struct smb_request *req)
881 connection_struct *conn = req->conn;
882 char *name = NULL;
883 SMB_STRUCT_STAT sbuf;
884 NTSTATUS status;
885 TALLOC_CTX *ctx = talloc_tos();
887 START_PROFILE(SMBcheckpath);
889 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
890 STR_TERMINATE, &status);
892 if (!NT_STATUS_IS_OK(status)) {
893 status = map_checkpath_error(req->flags2, status);
894 reply_nterror(req, status);
895 END_PROFILE(SMBcheckpath);
896 return;
899 status = resolve_dfspath(ctx, conn,
900 req->flags2 & FLAGS2_DFS_PATHNAMES,
901 name,
902 &name);
903 if (!NT_STATUS_IS_OK(status)) {
904 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
905 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
906 ERRSRV, ERRbadpath);
907 END_PROFILE(SMBcheckpath);
908 return;
910 goto path_err;
913 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
915 status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
916 if (!NT_STATUS_IS_OK(status)) {
917 goto path_err;
920 status = check_name(conn, name);
921 if (!NT_STATUS_IS_OK(status)) {
922 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
923 goto path_err;
926 if (!VALID_STAT(sbuf)) {
927 int ret;
929 if (lp_posix_pathnames()) {
930 ret = SMB_VFS_LSTAT(conn,name,&sbuf);
931 } else {
932 ret = SMB_VFS_STAT(conn,name,&sbuf);
934 if (ret != 0) {
935 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
936 status = map_nt_error_from_unix(errno);
937 goto path_err;
941 if (!S_ISDIR(sbuf.st_mode)) {
942 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
943 ERRDOS, ERRbadpath);
944 END_PROFILE(SMBcheckpath);
945 return;
948 reply_outbuf(req, 0, 0);
950 END_PROFILE(SMBcheckpath);
951 return;
953 path_err:
955 END_PROFILE(SMBcheckpath);
957 /* We special case this - as when a Windows machine
958 is parsing a path is steps through the components
959 one at a time - if a component fails it expects
960 ERRbadpath, not ERRbadfile.
962 status = map_checkpath_error(req->flags2, status);
963 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
965 * Windows returns different error codes if
966 * the parent directory is valid but not the
967 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
968 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
969 * if the path is invalid.
971 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
972 ERRDOS, ERRbadpath);
973 return;
976 reply_nterror(req, status);
979 /****************************************************************************
980 Reply to a getatr.
981 ****************************************************************************/
983 void reply_getatr(struct smb_request *req)
985 connection_struct *conn = req->conn;
986 char *fname = NULL;
987 SMB_STRUCT_STAT sbuf;
988 int mode=0;
989 SMB_OFF_T size=0;
990 time_t mtime=0;
991 const char *p;
992 NTSTATUS status;
993 TALLOC_CTX *ctx = talloc_tos();
995 START_PROFILE(SMBgetatr);
997 p = (const char *)req->buf + 1;
998 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
999 if (!NT_STATUS_IS_OK(status)) {
1000 reply_nterror(req, status);
1001 END_PROFILE(SMBgetatr);
1002 return;
1005 status = resolve_dfspath(ctx, conn,
1006 req->flags2 & FLAGS2_DFS_PATHNAMES,
1007 fname,
1008 &fname);
1009 if (!NT_STATUS_IS_OK(status)) {
1010 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1011 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1012 ERRSRV, ERRbadpath);
1013 END_PROFILE(SMBgetatr);
1014 return;
1016 reply_nterror(req, status);
1017 END_PROFILE(SMBgetatr);
1018 return;
1021 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1022 under WfWg - weird! */
1023 if (*fname == '\0') {
1024 mode = aHIDDEN | aDIR;
1025 if (!CAN_WRITE(conn)) {
1026 mode |= aRONLY;
1028 size = 0;
1029 mtime = 0;
1030 } else {
1031 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
1032 if (!NT_STATUS_IS_OK(status)) {
1033 reply_nterror(req, status);
1034 END_PROFILE(SMBgetatr);
1035 return;
1037 status = check_name(conn, fname);
1038 if (!NT_STATUS_IS_OK(status)) {
1039 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1040 reply_nterror(req, status);
1041 END_PROFILE(SMBgetatr);
1042 return;
1044 if (!VALID_STAT(sbuf)) {
1045 int ret;
1047 if (lp_posix_pathnames()) {
1048 ret = SMB_VFS_LSTAT(conn,fname,&sbuf);
1049 } else {
1050 ret = SMB_VFS_STAT(conn,fname,&sbuf);
1052 if (ret != 0) {
1053 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1054 reply_unixerror(req, ERRDOS,ERRbadfile);
1055 END_PROFILE(SMBgetatr);
1056 return;
1060 mode = dos_mode(conn,fname,&sbuf);
1061 size = sbuf.st_size;
1062 mtime = sbuf.st_mtime;
1063 if (mode & aDIR) {
1064 size = 0;
1068 reply_outbuf(req, 10, 0);
1070 SSVAL(req->outbuf,smb_vwv0,mode);
1071 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1072 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1073 } else {
1074 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1076 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1078 if (Protocol >= PROTOCOL_NT1) {
1079 SSVAL(req->outbuf, smb_flg2,
1080 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1083 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1085 END_PROFILE(SMBgetatr);
1086 return;
1089 /****************************************************************************
1090 Reply to a setatr.
1091 ****************************************************************************/
1093 void reply_setatr(struct smb_request *req)
1095 struct smb_file_time ft;
1096 connection_struct *conn = req->conn;
1097 char *fname = NULL;
1098 int mode;
1099 time_t mtime;
1100 SMB_STRUCT_STAT sbuf;
1101 const char *p;
1102 NTSTATUS status;
1103 TALLOC_CTX *ctx = talloc_tos();
1105 START_PROFILE(SMBsetatr);
1107 ZERO_STRUCT(ft);
1109 if (req->wct < 2) {
1110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1111 return;
1114 p = (const char *)req->buf + 1;
1115 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1116 if (!NT_STATUS_IS_OK(status)) {
1117 reply_nterror(req, status);
1118 END_PROFILE(SMBsetatr);
1119 return;
1122 status = resolve_dfspath(ctx, conn,
1123 req->flags2 & FLAGS2_DFS_PATHNAMES,
1124 fname,
1125 &fname);
1126 if (!NT_STATUS_IS_OK(status)) {
1127 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1128 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1129 ERRSRV, ERRbadpath);
1130 END_PROFILE(SMBsetatr);
1131 return;
1133 reply_nterror(req, status);
1134 END_PROFILE(SMBsetatr);
1135 return;
1138 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1139 if (!NT_STATUS_IS_OK(status)) {
1140 reply_nterror(req, status);
1141 END_PROFILE(SMBsetatr);
1142 return;
1145 status = check_name(conn, fname);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 reply_nterror(req, status);
1148 END_PROFILE(SMBsetatr);
1149 return;
1152 if (fname[0] == '.' && fname[1] == '\0') {
1154 * Not sure here is the right place to catch this
1155 * condition. Might be moved to somewhere else later -- vl
1157 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1158 END_PROFILE(SMBsetatr);
1159 return;
1162 mode = SVAL(req->vwv+0, 0);
1163 mtime = srv_make_unix_date3(req->vwv+1);
1165 ft.mtime = convert_time_t_to_timespec(mtime);
1166 status = smb_set_file_time(conn, NULL, fname,
1167 &sbuf, &ft, true);
1168 if (!NT_STATUS_IS_OK(status)) {
1169 reply_unixerror(req, ERRDOS, ERRnoaccess);
1170 END_PROFILE(SMBsetatr);
1171 return;
1174 if (mode != FILE_ATTRIBUTE_NORMAL) {
1175 if (VALID_STAT_OF_DIR(sbuf))
1176 mode |= aDIR;
1177 else
1178 mode &= ~aDIR;
1180 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1181 reply_unixerror(req, ERRDOS, ERRnoaccess);
1182 END_PROFILE(SMBsetatr);
1183 return;
1187 reply_outbuf(req, 0, 0);
1189 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1191 END_PROFILE(SMBsetatr);
1192 return;
1195 /****************************************************************************
1196 Reply to a dskattr.
1197 ****************************************************************************/
1199 void reply_dskattr(struct smb_request *req)
1201 connection_struct *conn = req->conn;
1202 uint64_t dfree,dsize,bsize;
1203 START_PROFILE(SMBdskattr);
1205 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1206 reply_unixerror(req, ERRHRD, ERRgeneral);
1207 END_PROFILE(SMBdskattr);
1208 return;
1211 reply_outbuf(req, 5, 0);
1213 if (Protocol <= PROTOCOL_LANMAN2) {
1214 double total_space, free_space;
1215 /* we need to scale this to a number that DOS6 can handle. We
1216 use floating point so we can handle large drives on systems
1217 that don't have 64 bit integers
1219 we end up displaying a maximum of 2G to DOS systems
1221 total_space = dsize * (double)bsize;
1222 free_space = dfree * (double)bsize;
1224 dsize = (uint64_t)((total_space+63*512) / (64*512));
1225 dfree = (uint64_t)((free_space+63*512) / (64*512));
1227 if (dsize > 0xFFFF) dsize = 0xFFFF;
1228 if (dfree > 0xFFFF) dfree = 0xFFFF;
1230 SSVAL(req->outbuf,smb_vwv0,dsize);
1231 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1232 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1233 SSVAL(req->outbuf,smb_vwv3,dfree);
1234 } else {
1235 SSVAL(req->outbuf,smb_vwv0,dsize);
1236 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1237 SSVAL(req->outbuf,smb_vwv2,512);
1238 SSVAL(req->outbuf,smb_vwv3,dfree);
1241 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1243 END_PROFILE(SMBdskattr);
1244 return;
1247 /****************************************************************************
1248 Reply to a search.
1249 Can be called from SMBsearch, SMBffirst or SMBfunique.
1250 ****************************************************************************/
1252 void reply_search(struct smb_request *req)
1254 connection_struct *conn = req->conn;
1255 const char *mask = NULL;
1256 char *directory = NULL;
1257 char *fname = NULL;
1258 SMB_OFF_T size;
1259 uint32 mode;
1260 time_t date;
1261 uint32 dirtype;
1262 unsigned int numentries = 0;
1263 unsigned int maxentries = 0;
1264 bool finished = False;
1265 const char *p;
1266 int status_len;
1267 char *path = NULL;
1268 char status[21];
1269 int dptr_num= -1;
1270 bool check_descend = False;
1271 bool expect_close = False;
1272 NTSTATUS nt_status;
1273 bool mask_contains_wcard = False;
1274 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1275 TALLOC_CTX *ctx = talloc_tos();
1276 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1278 START_PROFILE(SMBsearch);
1280 if (req->wct < 2) {
1281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1282 END_PROFILE(SMBsearch);
1283 return;
1286 if (lp_posix_pathnames()) {
1287 reply_unknown_new(req, req->cmd);
1288 END_PROFILE(SMBsearch);
1289 return;
1292 /* If we were called as SMBffirst then we must expect close. */
1293 if(req->cmd == SMBffirst) {
1294 expect_close = True;
1297 reply_outbuf(req, 1, 3);
1298 maxentries = SVAL(req->vwv+0, 0);
1299 dirtype = SVAL(req->vwv+1, 0);
1300 p = (const char *)req->buf + 1;
1301 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1302 &nt_status, &mask_contains_wcard);
1303 if (!NT_STATUS_IS_OK(nt_status)) {
1304 reply_nterror(req, nt_status);
1305 END_PROFILE(SMBsearch);
1306 return;
1309 nt_status = resolve_dfspath_wcard(ctx, conn,
1310 req->flags2 & FLAGS2_DFS_PATHNAMES,
1311 path,
1312 &path,
1313 &mask_contains_wcard);
1314 if (!NT_STATUS_IS_OK(nt_status)) {
1315 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1316 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1317 ERRSRV, ERRbadpath);
1318 END_PROFILE(SMBsearch);
1319 return;
1321 reply_nterror(req, nt_status);
1322 END_PROFILE(SMBsearch);
1323 return;
1326 p++;
1327 status_len = SVAL(p, 0);
1328 p += 2;
1330 /* dirtype &= ~aDIR; */
1332 if (status_len == 0) {
1333 SMB_STRUCT_STAT sbuf;
1335 nt_status = unix_convert(ctx, conn, path, True,
1336 &directory, NULL, &sbuf);
1337 if (!NT_STATUS_IS_OK(nt_status)) {
1338 reply_nterror(req, nt_status);
1339 END_PROFILE(SMBsearch);
1340 return;
1343 nt_status = check_name(conn, directory);
1344 if (!NT_STATUS_IS_OK(nt_status)) {
1345 reply_nterror(req, nt_status);
1346 END_PROFILE(SMBsearch);
1347 return;
1350 p = strrchr_m(directory,'/');
1351 if ((p != NULL) && (*directory != '/')) {
1352 mask = p + 1;
1353 directory = talloc_strndup(ctx, directory,
1354 PTR_DIFF(p, directory));
1355 } else {
1356 mask = directory;
1357 directory = talloc_strdup(ctx,".");
1360 if (!directory) {
1361 reply_nterror(req, NT_STATUS_NO_MEMORY);
1362 END_PROFILE(SMBsearch);
1363 return;
1366 memset((char *)status,'\0',21);
1367 SCVAL(status,0,(dirtype & 0x1F));
1369 nt_status = dptr_create(conn,
1370 directory,
1371 True,
1372 expect_close,
1373 req->smbpid,
1374 mask,
1375 mask_contains_wcard,
1376 dirtype,
1377 &conn->dirptr);
1378 if (!NT_STATUS_IS_OK(nt_status)) {
1379 reply_nterror(req, nt_status);
1380 END_PROFILE(SMBsearch);
1381 return;
1383 dptr_num = dptr_dnum(conn->dirptr);
1384 } else {
1385 int status_dirtype;
1387 memcpy(status,p,21);
1388 status_dirtype = CVAL(status,0) & 0x1F;
1389 if (status_dirtype != (dirtype & 0x1F)) {
1390 dirtype = status_dirtype;
1393 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1394 if (!conn->dirptr) {
1395 goto SearchEmpty;
1397 string_set(&conn->dirpath,dptr_path(dptr_num));
1398 mask = dptr_wcard(dptr_num);
1399 if (!mask) {
1400 goto SearchEmpty;
1403 * For a 'continue' search we have no string. So
1404 * check from the initial saved string.
1406 mask_contains_wcard = ms_has_wild(mask);
1407 dirtype = dptr_attr(dptr_num);
1410 DEBUG(4,("dptr_num is %d\n",dptr_num));
1412 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1413 dptr_init_search_op(conn->dirptr);
1415 if ((dirtype&0x1F) == aVOLID) {
1416 char buf[DIR_STRUCT_SIZE];
1417 memcpy(buf,status,21);
1418 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1419 0,aVOLID,0,!allow_long_path_components)) {
1420 reply_nterror(req, NT_STATUS_NO_MEMORY);
1421 END_PROFILE(SMBsearch);
1422 return;
1424 dptr_fill(buf+12,dptr_num);
1425 if (dptr_zero(buf+12) && (status_len==0)) {
1426 numentries = 1;
1427 } else {
1428 numentries = 0;
1430 if (message_push_blob(&req->outbuf,
1431 data_blob_const(buf, sizeof(buf)))
1432 == -1) {
1433 reply_nterror(req, NT_STATUS_NO_MEMORY);
1434 END_PROFILE(SMBsearch);
1435 return;
1437 } else {
1438 unsigned int i;
1439 maxentries = MIN(
1440 maxentries,
1441 ((BUFFER_SIZE -
1442 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1443 /DIR_STRUCT_SIZE));
1445 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1446 conn->dirpath,lp_dontdescend(SNUM(conn))));
1447 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1448 check_descend = True;
1451 for (i=numentries;(i<maxentries) && !finished;i++) {
1452 finished = !get_dir_entry(ctx,
1453 conn,
1454 mask,
1455 dirtype,
1456 &fname,
1457 &size,
1458 &mode,
1459 &date,
1460 check_descend,
1461 ask_sharemode);
1462 if (!finished) {
1463 char buf[DIR_STRUCT_SIZE];
1464 memcpy(buf,status,21);
1465 if (!make_dir_struct(ctx,
1466 buf,
1467 mask,
1468 fname,
1469 size,
1470 mode,
1471 date,
1472 !allow_long_path_components)) {
1473 reply_nterror(req, NT_STATUS_NO_MEMORY);
1474 END_PROFILE(SMBsearch);
1475 return;
1477 if (!dptr_fill(buf+12,dptr_num)) {
1478 break;
1480 if (message_push_blob(&req->outbuf,
1481 data_blob_const(buf, sizeof(buf)))
1482 == -1) {
1483 reply_nterror(req, NT_STATUS_NO_MEMORY);
1484 END_PROFILE(SMBsearch);
1485 return;
1487 numentries++;
1492 SearchEmpty:
1494 /* If we were called as SMBffirst with smb_search_id == NULL
1495 and no entries were found then return error and close dirptr
1496 (X/Open spec) */
1498 if (numentries == 0) {
1499 dptr_close(&dptr_num);
1500 } else if(expect_close && status_len == 0) {
1501 /* Close the dptr - we know it's gone */
1502 dptr_close(&dptr_num);
1505 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1506 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1507 dptr_close(&dptr_num);
1510 if ((numentries == 0) && !mask_contains_wcard) {
1511 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1512 END_PROFILE(SMBsearch);
1513 return;
1516 SSVAL(req->outbuf,smb_vwv0,numentries);
1517 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1518 SCVAL(smb_buf(req->outbuf),0,5);
1519 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1521 /* The replies here are never long name. */
1522 SSVAL(req->outbuf, smb_flg2,
1523 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1524 if (!allow_long_path_components) {
1525 SSVAL(req->outbuf, smb_flg2,
1526 SVAL(req->outbuf, smb_flg2)
1527 & (~FLAGS2_LONG_PATH_COMPONENTS));
1530 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1531 SSVAL(req->outbuf, smb_flg2,
1532 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1534 if (!directory) {
1535 directory = dptr_path(dptr_num);
1538 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1539 smb_fn_name(req->cmd),
1540 mask,
1541 directory ? directory : "./",
1542 dirtype,
1543 numentries,
1544 maxentries ));
1546 END_PROFILE(SMBsearch);
1547 return;
1550 /****************************************************************************
1551 Reply to a fclose (stop directory search).
1552 ****************************************************************************/
1554 void reply_fclose(struct smb_request *req)
1556 int status_len;
1557 char status[21];
1558 int dptr_num= -2;
1559 const char *p;
1560 char *path = NULL;
1561 NTSTATUS err;
1562 bool path_contains_wcard = False;
1563 TALLOC_CTX *ctx = talloc_tos();
1565 START_PROFILE(SMBfclose);
1567 if (lp_posix_pathnames()) {
1568 reply_unknown_new(req, req->cmd);
1569 END_PROFILE(SMBfclose);
1570 return;
1573 p = (const char *)req->buf + 1;
1574 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1575 &err, &path_contains_wcard);
1576 if (!NT_STATUS_IS_OK(err)) {
1577 reply_nterror(req, err);
1578 END_PROFILE(SMBfclose);
1579 return;
1581 p++;
1582 status_len = SVAL(p,0);
1583 p += 2;
1585 if (status_len == 0) {
1586 reply_doserror(req, ERRSRV, ERRsrverror);
1587 END_PROFILE(SMBfclose);
1588 return;
1591 memcpy(status,p,21);
1593 if(dptr_fetch(status+12,&dptr_num)) {
1594 /* Close the dptr - we know it's gone */
1595 dptr_close(&dptr_num);
1598 reply_outbuf(req, 1, 0);
1599 SSVAL(req->outbuf,smb_vwv0,0);
1601 DEBUG(3,("search close\n"));
1603 END_PROFILE(SMBfclose);
1604 return;
1607 /****************************************************************************
1608 Reply to an open.
1609 ****************************************************************************/
1611 void reply_open(struct smb_request *req)
1613 connection_struct *conn = req->conn;
1614 char *fname = NULL;
1615 uint32 fattr=0;
1616 SMB_OFF_T size = 0;
1617 time_t mtime=0;
1618 int info;
1619 SMB_STRUCT_STAT sbuf;
1620 files_struct *fsp;
1621 int oplock_request;
1622 int deny_mode;
1623 uint32 dos_attr;
1624 uint32 access_mask;
1625 uint32 share_mode;
1626 uint32 create_disposition;
1627 uint32 create_options = 0;
1628 NTSTATUS status;
1629 TALLOC_CTX *ctx = talloc_tos();
1631 START_PROFILE(SMBopen);
1633 SET_STAT_INVALID(sbuf);
1635 if (req->wct < 2) {
1636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1637 END_PROFILE(SMBopen);
1638 return;
1641 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1642 deny_mode = SVAL(req->vwv+0, 0);
1643 dos_attr = SVAL(req->vwv+1, 0);
1645 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1646 STR_TERMINATE, &status);
1647 if (!NT_STATUS_IS_OK(status)) {
1648 reply_nterror(req, status);
1649 END_PROFILE(SMBopen);
1650 return;
1653 if (!map_open_params_to_ntcreate(
1654 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1655 &share_mode, &create_disposition, &create_options)) {
1656 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1657 END_PROFILE(SMBopen);
1658 return;
1661 status = SMB_VFS_CREATE_FILE(
1662 conn, /* conn */
1663 req, /* req */
1664 0, /* root_dir_fid */
1665 fname, /* fname */
1666 CFF_DOS_PATH, /* create_file_flags */
1667 access_mask, /* access_mask */
1668 share_mode, /* share_access */
1669 create_disposition, /* create_disposition*/
1670 create_options, /* create_options */
1671 dos_attr, /* file_attributes */
1672 oplock_request, /* oplock_request */
1673 0, /* allocation_size */
1674 NULL, /* sd */
1675 NULL, /* ea_list */
1676 &fsp, /* result */
1677 &info, /* pinfo */
1678 &sbuf); /* psbuf */
1680 if (!NT_STATUS_IS_OK(status)) {
1681 if (open_was_deferred(req->mid)) {
1682 /* We have re-scheduled this call. */
1683 END_PROFILE(SMBopen);
1684 return;
1686 reply_openerror(req, status);
1687 END_PROFILE(SMBopen);
1688 return;
1691 size = sbuf.st_size;
1692 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1693 mtime = sbuf.st_mtime;
1695 if (fattr & aDIR) {
1696 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1697 close_file(req, fsp, ERROR_CLOSE);
1698 reply_doserror(req, ERRDOS,ERRnoaccess);
1699 END_PROFILE(SMBopen);
1700 return;
1703 reply_outbuf(req, 7, 0);
1704 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1705 SSVAL(req->outbuf,smb_vwv1,fattr);
1706 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1707 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1708 } else {
1709 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1711 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1712 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1714 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1715 SCVAL(req->outbuf,smb_flg,
1716 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1719 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1720 SCVAL(req->outbuf,smb_flg,
1721 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1723 END_PROFILE(SMBopen);
1724 return;
1727 /****************************************************************************
1728 Reply to an open and X.
1729 ****************************************************************************/
1731 void reply_open_and_X(struct smb_request *req)
1733 connection_struct *conn = req->conn;
1734 char *fname = NULL;
1735 uint16 open_flags;
1736 int deny_mode;
1737 uint32 smb_attr;
1738 /* Breakout the oplock request bits so we can set the
1739 reply bits separately. */
1740 int ex_oplock_request;
1741 int core_oplock_request;
1742 int oplock_request;
1743 #if 0
1744 int smb_sattr = SVAL(req->vwv+4, 0);
1745 uint32 smb_time = make_unix_date3(req->vwv+6);
1746 #endif
1747 int smb_ofun;
1748 uint32 fattr=0;
1749 int mtime=0;
1750 SMB_STRUCT_STAT sbuf;
1751 int smb_action = 0;
1752 files_struct *fsp;
1753 NTSTATUS status;
1754 uint64_t allocation_size;
1755 ssize_t retval = -1;
1756 uint32 access_mask;
1757 uint32 share_mode;
1758 uint32 create_disposition;
1759 uint32 create_options = 0;
1760 TALLOC_CTX *ctx = talloc_tos();
1762 START_PROFILE(SMBopenX);
1764 if (req->wct < 15) {
1765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1766 END_PROFILE(SMBopenX);
1767 return;
1770 SET_STAT_INVALID(sbuf);
1772 open_flags = SVAL(req->vwv+2, 0);
1773 deny_mode = SVAL(req->vwv+3, 0);
1774 smb_attr = SVAL(req->vwv+5, 0);
1775 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1776 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1777 oplock_request = ex_oplock_request | core_oplock_request;
1778 smb_ofun = SVAL(req->vwv+8, 0);
1779 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1781 /* If it's an IPC, pass off the pipe handler. */
1782 if (IS_IPC(conn)) {
1783 if (lp_nt_pipe_support()) {
1784 reply_open_pipe_and_X(conn, req);
1785 } else {
1786 reply_doserror(req, ERRSRV, ERRaccess);
1788 END_PROFILE(SMBopenX);
1789 return;
1792 /* XXXX we need to handle passed times, sattr and flags */
1793 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1794 STR_TERMINATE, &status);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 reply_nterror(req, status);
1797 END_PROFILE(SMBopenX);
1798 return;
1801 if (!map_open_params_to_ntcreate(
1802 fname, deny_mode, smb_ofun, &access_mask,
1803 &share_mode, &create_disposition, &create_options)) {
1804 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1805 END_PROFILE(SMBopenX);
1806 return;
1809 status = SMB_VFS_CREATE_FILE(
1810 conn, /* conn */
1811 req, /* req */
1812 0, /* root_dir_fid */
1813 fname, /* fname */
1814 CFF_DOS_PATH, /* create_file_flags */
1815 access_mask, /* access_mask */
1816 share_mode, /* share_access */
1817 create_disposition, /* create_disposition*/
1818 create_options, /* create_options */
1819 smb_attr, /* file_attributes */
1820 oplock_request, /* oplock_request */
1821 0, /* allocation_size */
1822 NULL, /* sd */
1823 NULL, /* ea_list */
1824 &fsp, /* result */
1825 &smb_action, /* pinfo */
1826 &sbuf); /* psbuf */
1828 if (!NT_STATUS_IS_OK(status)) {
1829 END_PROFILE(SMBopenX);
1830 if (open_was_deferred(req->mid)) {
1831 /* We have re-scheduled this call. */
1832 return;
1834 reply_openerror(req, status);
1835 return;
1838 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1839 if the file is truncated or created. */
1840 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1841 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1842 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1843 close_file(req, fsp, ERROR_CLOSE);
1844 reply_nterror(req, NT_STATUS_DISK_FULL);
1845 END_PROFILE(SMBopenX);
1846 return;
1848 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1849 if (retval < 0) {
1850 close_file(req, fsp, ERROR_CLOSE);
1851 reply_nterror(req, NT_STATUS_DISK_FULL);
1852 END_PROFILE(SMBopenX);
1853 return;
1855 sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1858 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1859 mtime = sbuf.st_mtime;
1860 if (fattr & aDIR) {
1861 close_file(req, fsp, ERROR_CLOSE);
1862 reply_doserror(req, ERRDOS, ERRnoaccess);
1863 END_PROFILE(SMBopenX);
1864 return;
1867 /* If the caller set the extended oplock request bit
1868 and we granted one (by whatever means) - set the
1869 correct bit for extended oplock reply.
1872 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1873 smb_action |= EXTENDED_OPLOCK_GRANTED;
1876 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1877 smb_action |= EXTENDED_OPLOCK_GRANTED;
1880 /* If the caller set the core oplock request bit
1881 and we granted one (by whatever means) - set the
1882 correct bit for core oplock reply.
1885 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1886 reply_outbuf(req, 19, 0);
1887 } else {
1888 reply_outbuf(req, 15, 0);
1891 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1892 SCVAL(req->outbuf, smb_flg,
1893 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1896 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1897 SCVAL(req->outbuf, smb_flg,
1898 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1901 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1902 SSVAL(req->outbuf,smb_vwv3,fattr);
1903 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1904 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1905 } else {
1906 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1908 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1909 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1910 SSVAL(req->outbuf,smb_vwv11,smb_action);
1912 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1913 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1916 END_PROFILE(SMBopenX);
1917 chain_reply(req);
1918 return;
1921 /****************************************************************************
1922 Reply to a SMBulogoffX.
1923 ****************************************************************************/
1925 void reply_ulogoffX(struct smb_request *req)
1927 user_struct *vuser;
1929 START_PROFILE(SMBulogoffX);
1931 vuser = get_valid_user_struct(req->vuid);
1933 if(vuser == NULL) {
1934 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1935 req->vuid));
1938 /* in user level security we are supposed to close any files
1939 open by this user */
1940 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1941 file_close_user(req->vuid);
1944 invalidate_vuid(req->vuid);
1946 reply_outbuf(req, 2, 0);
1948 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1950 END_PROFILE(SMBulogoffX);
1951 req->vuid = UID_FIELD_INVALID;
1952 chain_reply(req);
1955 /****************************************************************************
1956 Reply to a mknew or a create.
1957 ****************************************************************************/
1959 void reply_mknew(struct smb_request *req)
1961 connection_struct *conn = req->conn;
1962 char *fname = NULL;
1963 uint32 fattr = 0;
1964 struct smb_file_time ft;
1965 files_struct *fsp;
1966 int oplock_request = 0;
1967 SMB_STRUCT_STAT sbuf;
1968 NTSTATUS status;
1969 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1970 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1971 uint32 create_disposition;
1972 uint32 create_options = 0;
1973 TALLOC_CTX *ctx = talloc_tos();
1975 START_PROFILE(SMBcreate);
1976 ZERO_STRUCT(ft);
1977 SET_STAT_INVALID(sbuf);
1979 if (req->wct < 3) {
1980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1981 END_PROFILE(SMBcreate);
1982 return;
1985 fattr = SVAL(req->vwv+0, 0);
1986 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1988 /* mtime. */
1989 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
1991 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
1992 STR_TERMINATE, &status);
1993 if (!NT_STATUS_IS_OK(status)) {
1994 reply_nterror(req, status);
1995 END_PROFILE(SMBcreate);
1996 return;
1999 if (fattr & aVOLID) {
2000 DEBUG(0,("Attempt to create file (%s) with volid set - "
2001 "please report this\n", fname));
2004 if(req->cmd == SMBmknew) {
2005 /* We should fail if file exists. */
2006 create_disposition = FILE_CREATE;
2007 } else {
2008 /* Create if file doesn't exist, truncate if it does. */
2009 create_disposition = FILE_OVERWRITE_IF;
2012 status = SMB_VFS_CREATE_FILE(
2013 conn, /* conn */
2014 req, /* req */
2015 0, /* root_dir_fid */
2016 fname, /* fname */
2017 CFF_DOS_PATH, /* create_file_flags */
2018 access_mask, /* access_mask */
2019 share_mode, /* share_access */
2020 create_disposition, /* create_disposition*/
2021 create_options, /* create_options */
2022 fattr, /* file_attributes */
2023 oplock_request, /* oplock_request */
2024 0, /* allocation_size */
2025 NULL, /* sd */
2026 NULL, /* ea_list */
2027 &fsp, /* result */
2028 NULL, /* pinfo */
2029 &sbuf); /* psbuf */
2031 if (!NT_STATUS_IS_OK(status)) {
2032 END_PROFILE(SMBcreate);
2033 if (open_was_deferred(req->mid)) {
2034 /* We have re-scheduled this call. */
2035 return;
2037 reply_openerror(req, status);
2038 return;
2041 ft.atime = get_atimespec(&sbuf); /* atime. */
2042 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2043 if (!NT_STATUS_IS_OK(status)) {
2044 END_PROFILE(SMBcreate);
2045 reply_openerror(req, status);
2046 return;
2049 reply_outbuf(req, 1, 0);
2050 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2052 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2053 SCVAL(req->outbuf,smb_flg,
2054 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2057 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2058 SCVAL(req->outbuf,smb_flg,
2059 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2062 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2063 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2064 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2066 END_PROFILE(SMBcreate);
2067 return;
2070 /****************************************************************************
2071 Reply to a create temporary file.
2072 ****************************************************************************/
2074 void reply_ctemp(struct smb_request *req)
2076 connection_struct *conn = req->conn;
2077 char *fname = NULL;
2078 uint32 fattr;
2079 files_struct *fsp;
2080 int oplock_request;
2081 int tmpfd;
2082 SMB_STRUCT_STAT sbuf;
2083 char *s;
2084 NTSTATUS status;
2085 TALLOC_CTX *ctx = talloc_tos();
2087 START_PROFILE(SMBctemp);
2089 if (req->wct < 3) {
2090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2091 END_PROFILE(SMBctemp);
2092 return;
2095 fattr = SVAL(req->vwv+0, 0);
2096 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2098 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2099 STR_TERMINATE, &status);
2100 if (!NT_STATUS_IS_OK(status)) {
2101 reply_nterror(req, status);
2102 END_PROFILE(SMBctemp);
2103 return;
2105 if (*fname) {
2106 fname = talloc_asprintf(ctx,
2107 "%s/TMXXXXXX",
2108 fname);
2109 } else {
2110 fname = talloc_strdup(ctx, "TMXXXXXX");
2113 if (!fname) {
2114 reply_nterror(req, NT_STATUS_NO_MEMORY);
2115 END_PROFILE(SMBctemp);
2116 return;
2119 status = resolve_dfspath(ctx, conn,
2120 req->flags2 & FLAGS2_DFS_PATHNAMES,
2121 fname,
2122 &fname);
2123 if (!NT_STATUS_IS_OK(status)) {
2124 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2125 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2126 ERRSRV, ERRbadpath);
2127 END_PROFILE(SMBctemp);
2128 return;
2130 reply_nterror(req, status);
2131 END_PROFILE(SMBctemp);
2132 return;
2135 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2136 if (!NT_STATUS_IS_OK(status)) {
2137 reply_nterror(req, status);
2138 END_PROFILE(SMBctemp);
2139 return;
2142 status = check_name(conn, fname);
2143 if (!NT_STATUS_IS_OK(status)) {
2144 reply_nterror(req, status);
2145 END_PROFILE(SMBctemp);
2146 return;
2149 tmpfd = smb_mkstemp(fname);
2150 if (tmpfd == -1) {
2151 reply_unixerror(req, ERRDOS, ERRnoaccess);
2152 END_PROFILE(SMBctemp);
2153 return;
2156 SET_STAT_INVALID(sbuf);
2157 SMB_VFS_STAT(conn,fname,&sbuf);
2159 /* We should fail if file does not exist. */
2160 status = SMB_VFS_CREATE_FILE(
2161 conn, /* conn */
2162 req, /* req */
2163 0, /* root_dir_fid */
2164 fname, /* fname */
2165 0, /* create_file_flags */
2166 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2167 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2168 FILE_OPEN, /* create_disposition*/
2169 0, /* create_options */
2170 fattr, /* file_attributes */
2171 oplock_request, /* oplock_request */
2172 0, /* allocation_size */
2173 NULL, /* sd */
2174 NULL, /* ea_list */
2175 &fsp, /* result */
2176 NULL, /* pinfo */
2177 &sbuf); /* psbuf */
2179 /* close fd from smb_mkstemp() */
2180 close(tmpfd);
2182 if (!NT_STATUS_IS_OK(status)) {
2183 if (open_was_deferred(req->mid)) {
2184 /* We have re-scheduled this call. */
2185 END_PROFILE(SMBctemp);
2186 return;
2188 reply_openerror(req, status);
2189 END_PROFILE(SMBctemp);
2190 return;
2193 reply_outbuf(req, 1, 0);
2194 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2196 /* the returned filename is relative to the directory */
2197 s = strrchr_m(fsp->fsp_name, '/');
2198 if (!s) {
2199 s = fsp->fsp_name;
2200 } else {
2201 s++;
2204 #if 0
2205 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2206 thing in the byte section. JRA */
2207 SSVALS(p, 0, -1); /* what is this? not in spec */
2208 #endif
2209 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2210 == -1) {
2211 reply_nterror(req, NT_STATUS_NO_MEMORY);
2212 END_PROFILE(SMBctemp);
2213 return;
2216 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2217 SCVAL(req->outbuf, smb_flg,
2218 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2221 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2222 SCVAL(req->outbuf, smb_flg,
2223 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2226 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2227 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2228 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2230 END_PROFILE(SMBctemp);
2231 return;
2234 /*******************************************************************
2235 Check if a user is allowed to rename a file.
2236 ********************************************************************/
2238 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2239 uint16 dirtype, SMB_STRUCT_STAT *pst)
2241 uint32 fmode;
2243 if (!CAN_WRITE(conn)) {
2244 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2247 fmode = dos_mode(conn, fsp->fsp_name, pst);
2248 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2249 return NT_STATUS_NO_SUCH_FILE;
2252 if (S_ISDIR(pst->st_mode)) {
2253 if (fsp->posix_open) {
2254 return NT_STATUS_OK;
2257 /* If no pathnames are open below this
2258 directory, allow the rename. */
2260 if (file_find_subpath(fsp)) {
2261 return NT_STATUS_ACCESS_DENIED;
2263 return NT_STATUS_OK;
2266 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2267 return NT_STATUS_OK;
2270 return NT_STATUS_ACCESS_DENIED;
2273 /*******************************************************************
2274 * unlink a file with all relevant access checks
2275 *******************************************************************/
2277 static NTSTATUS do_unlink(connection_struct *conn,
2278 struct smb_request *req,
2279 const char *fname,
2280 uint32 dirtype)
2282 SMB_STRUCT_STAT sbuf;
2283 uint32 fattr;
2284 files_struct *fsp;
2285 uint32 dirtype_orig = dirtype;
2286 bool posix_paths = lp_posix_pathnames();
2287 int ret;
2288 NTSTATUS status;
2290 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2292 if (!CAN_WRITE(conn)) {
2293 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2296 if (posix_paths) {
2297 ret = SMB_VFS_LSTAT(conn,fname,&sbuf);
2298 } else {
2299 ret = SMB_VFS_STAT(conn,fname,&sbuf);
2301 if (ret != 0) {
2302 return map_nt_error_from_unix(errno);
2305 fattr = dos_mode(conn,fname,&sbuf);
2307 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2308 dirtype = aDIR|aARCH|aRONLY;
2311 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2312 if (!dirtype) {
2313 return NT_STATUS_NO_SUCH_FILE;
2316 if (!dir_check_ftype(conn, fattr, dirtype)) {
2317 if (fattr & aDIR) {
2318 return NT_STATUS_FILE_IS_A_DIRECTORY;
2320 return NT_STATUS_NO_SUCH_FILE;
2323 if (dirtype_orig & 0x8000) {
2324 /* These will never be set for POSIX. */
2325 return NT_STATUS_NO_SUCH_FILE;
2328 #if 0
2329 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2330 return NT_STATUS_FILE_IS_A_DIRECTORY;
2333 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2334 return NT_STATUS_NO_SUCH_FILE;
2337 if (dirtype & 0xFF00) {
2338 /* These will never be set for POSIX. */
2339 return NT_STATUS_NO_SUCH_FILE;
2342 dirtype &= 0xFF;
2343 if (!dirtype) {
2344 return NT_STATUS_NO_SUCH_FILE;
2347 /* Can't delete a directory. */
2348 if (fattr & aDIR) {
2349 return NT_STATUS_FILE_IS_A_DIRECTORY;
2351 #endif
2353 #if 0 /* JRATEST */
2354 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2355 return NT_STATUS_OBJECT_NAME_INVALID;
2356 #endif /* JRATEST */
2358 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2360 On a Windows share, a file with read-only dosmode can be opened with
2361 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2362 fails with NT_STATUS_CANNOT_DELETE error.
2364 This semantic causes a problem that a user can not
2365 rename a file with read-only dosmode on a Samba share
2366 from a Windows command prompt (i.e. cmd.exe, but can rename
2367 from Windows Explorer).
2370 if (!lp_delete_readonly(SNUM(conn))) {
2371 if (fattr & aRONLY) {
2372 return NT_STATUS_CANNOT_DELETE;
2376 /* On open checks the open itself will check the share mode, so
2377 don't do it here as we'll get it wrong. */
2379 status = SMB_VFS_CREATE_FILE
2380 (conn, /* conn */
2381 req, /* req */
2382 0, /* root_dir_fid */
2383 fname, /* fname */
2384 0, /* create_file_flags */
2385 DELETE_ACCESS, /* access_mask */
2386 FILE_SHARE_NONE, /* share_access */
2387 FILE_OPEN, /* create_disposition*/
2388 FILE_NON_DIRECTORY_FILE, /* create_options */
2389 /* file_attributes */
2390 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2391 FILE_ATTRIBUTE_NORMAL,
2392 0, /* oplock_request */
2393 0, /* allocation_size */
2394 NULL, /* sd */
2395 NULL, /* ea_list */
2396 &fsp, /* result */
2397 NULL, /* pinfo */
2398 &sbuf); /* psbuf */
2400 if (!NT_STATUS_IS_OK(status)) {
2401 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2402 nt_errstr(status)));
2403 return status;
2406 /* The set is across all open files on this dev/inode pair. */
2407 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2408 close_file(req, fsp, NORMAL_CLOSE);
2409 return NT_STATUS_ACCESS_DENIED;
2412 return close_file(req, fsp, NORMAL_CLOSE);
2415 /****************************************************************************
2416 The guts of the unlink command, split out so it may be called by the NT SMB
2417 code.
2418 ****************************************************************************/
2420 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2421 uint32 dirtype, const char *name_in, bool has_wild)
2423 const char *directory = NULL;
2424 char *mask = NULL;
2425 char *name = NULL;
2426 char *p = NULL;
2427 int count=0;
2428 NTSTATUS status = NT_STATUS_OK;
2429 SMB_STRUCT_STAT sbuf, st;
2430 TALLOC_CTX *ctx = talloc_tos();
2432 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2433 if (!NT_STATUS_IS_OK(status)) {
2434 return status;
2437 p = strrchr_m(name,'/');
2438 if (!p) {
2439 directory = talloc_strdup(ctx, ".");
2440 if (!directory) {
2441 return NT_STATUS_NO_MEMORY;
2443 mask = name;
2444 } else {
2445 *p = 0;
2446 directory = name;
2447 mask = p+1;
2451 * We should only check the mangled cache
2452 * here if unix_convert failed. This means
2453 * that the path in 'mask' doesn't exist
2454 * on the file system and so we need to look
2455 * for a possible mangle. This patch from
2456 * Tine Smukavec <valentin.smukavec@hermes.si>.
2459 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2460 char *new_mask = NULL;
2461 mangle_lookup_name_from_8_3(ctx,
2462 mask,
2463 &new_mask,
2464 conn->params );
2465 if (new_mask) {
2466 mask = new_mask;
2470 if (!has_wild) {
2471 directory = talloc_asprintf(ctx,
2472 "%s/%s",
2473 directory,
2474 mask);
2475 if (!directory) {
2476 return NT_STATUS_NO_MEMORY;
2478 if (dirtype == 0) {
2479 dirtype = FILE_ATTRIBUTE_NORMAL;
2482 status = check_name(conn, directory);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 return status;
2487 status = do_unlink(conn, req, directory, dirtype);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 return status;
2492 count++;
2493 } else {
2494 struct smb_Dir *dir_hnd = NULL;
2495 long offset = 0;
2496 const char *dname;
2498 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2499 return NT_STATUS_OBJECT_NAME_INVALID;
2502 if (strequal(mask,"????????.???")) {
2503 mask[0] = '*';
2504 mask[1] = '\0';
2507 status = check_name(conn, directory);
2508 if (!NT_STATUS_IS_OK(status)) {
2509 return status;
2512 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2513 dirtype);
2514 if (dir_hnd == NULL) {
2515 return map_nt_error_from_unix(errno);
2518 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2519 the pattern matches against the long name, otherwise the short name
2520 We don't implement this yet XXXX
2523 status = NT_STATUS_NO_SUCH_FILE;
2525 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2526 char *fname = NULL;
2528 if (!is_visible_file(conn, directory, dname, &st,
2529 true))
2531 continue;
2534 /* Quick check for "." and ".." */
2535 if (ISDOT(dname) || ISDOTDOT(dname)) {
2536 continue;
2539 if(!mask_match(dname, mask, conn->case_sensitive)) {
2540 continue;
2543 fname = talloc_asprintf(ctx, "%s/%s",
2544 directory,
2545 dname);
2546 if (!fname) {
2547 return NT_STATUS_NO_MEMORY;
2550 status = check_name(conn, fname);
2551 if (!NT_STATUS_IS_OK(status)) {
2552 TALLOC_FREE(dir_hnd);
2553 return status;
2556 status = do_unlink(conn, req, fname, dirtype);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 TALLOC_FREE(fname);
2559 continue;
2562 count++;
2563 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2564 fname));
2566 TALLOC_FREE(fname);
2568 TALLOC_FREE(dir_hnd);
2571 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2572 status = map_nt_error_from_unix(errno);
2575 return status;
2578 /****************************************************************************
2579 Reply to a unlink
2580 ****************************************************************************/
2582 void reply_unlink(struct smb_request *req)
2584 connection_struct *conn = req->conn;
2585 char *name = NULL;
2586 uint32 dirtype;
2587 NTSTATUS status;
2588 bool path_contains_wcard = False;
2589 TALLOC_CTX *ctx = talloc_tos();
2591 START_PROFILE(SMBunlink);
2593 if (req->wct < 1) {
2594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2595 END_PROFILE(SMBunlink);
2596 return;
2599 dirtype = SVAL(req->vwv+0, 0);
2601 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2602 STR_TERMINATE, &status,
2603 &path_contains_wcard);
2604 if (!NT_STATUS_IS_OK(status)) {
2605 reply_nterror(req, status);
2606 END_PROFILE(SMBunlink);
2607 return;
2610 status = resolve_dfspath_wcard(ctx, conn,
2611 req->flags2 & FLAGS2_DFS_PATHNAMES,
2612 name,
2613 &name,
2614 &path_contains_wcard);
2615 if (!NT_STATUS_IS_OK(status)) {
2616 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2617 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2618 ERRSRV, ERRbadpath);
2619 END_PROFILE(SMBunlink);
2620 return;
2622 reply_nterror(req, status);
2623 END_PROFILE(SMBunlink);
2624 return;
2627 DEBUG(3,("reply_unlink : %s\n",name));
2629 status = unlink_internals(conn, req, dirtype, name,
2630 path_contains_wcard);
2631 if (!NT_STATUS_IS_OK(status)) {
2632 if (open_was_deferred(req->mid)) {
2633 /* We have re-scheduled this call. */
2634 END_PROFILE(SMBunlink);
2635 return;
2637 reply_nterror(req, status);
2638 END_PROFILE(SMBunlink);
2639 return;
2642 reply_outbuf(req, 0, 0);
2643 END_PROFILE(SMBunlink);
2645 return;
2648 /****************************************************************************
2649 Fail for readbraw.
2650 ****************************************************************************/
2652 static void fail_readraw(void)
2654 const char *errstr = talloc_asprintf(talloc_tos(),
2655 "FAIL ! reply_readbraw: socket write fail (%s)",
2656 strerror(errno));
2657 if (!errstr) {
2658 errstr = "";
2660 exit_server_cleanly(errstr);
2663 /****************************************************************************
2664 Fake (read/write) sendfile. Returns -1 on read or write fail.
2665 ****************************************************************************/
2667 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2668 size_t nread)
2670 size_t bufsize;
2671 size_t tosend = nread;
2672 char *buf;
2674 if (nread == 0) {
2675 return 0;
2678 bufsize = MIN(nread, 65536);
2680 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2681 return -1;
2684 while (tosend > 0) {
2685 ssize_t ret;
2686 size_t cur_read;
2688 if (tosend > bufsize) {
2689 cur_read = bufsize;
2690 } else {
2691 cur_read = tosend;
2693 ret = read_file(fsp,buf,startpos,cur_read);
2694 if (ret == -1) {
2695 SAFE_FREE(buf);
2696 return -1;
2699 /* If we had a short read, fill with zeros. */
2700 if (ret < cur_read) {
2701 memset(buf + ret, '\0', cur_read - ret);
2704 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2705 SAFE_FREE(buf);
2706 return -1;
2708 tosend -= cur_read;
2709 startpos += cur_read;
2712 SAFE_FREE(buf);
2713 return (ssize_t)nread;
2716 #if defined(WITH_SENDFILE)
2717 /****************************************************************************
2718 Deal with the case of sendfile reading less bytes from the file than
2719 requested. Fill with zeros (all we can do).
2720 ****************************************************************************/
2722 static void sendfile_short_send(files_struct *fsp,
2723 ssize_t nread,
2724 size_t headersize,
2725 size_t smb_maxcnt)
2727 #define SHORT_SEND_BUFSIZE 1024
2728 if (nread < headersize) {
2729 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2730 "header for file %s (%s). Terminating\n",
2731 fsp->fsp_name, strerror(errno) ));
2732 exit_server_cleanly("sendfile_short_send failed");
2735 nread -= headersize;
2737 if (nread < smb_maxcnt) {
2738 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2739 if (!buf) {
2740 exit_server_cleanly("sendfile_short_send: "
2741 "malloc failed");
2744 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2745 "with zeros !\n", fsp->fsp_name));
2747 while (nread < smb_maxcnt) {
2749 * We asked for the real file size and told sendfile
2750 * to not go beyond the end of the file. But it can
2751 * happen that in between our fstat call and the
2752 * sendfile call the file was truncated. This is very
2753 * bad because we have already announced the larger
2754 * number of bytes to the client.
2756 * The best we can do now is to send 0-bytes, just as
2757 * a read from a hole in a sparse file would do.
2759 * This should happen rarely enough that I don't care
2760 * about efficiency here :-)
2762 size_t to_write;
2764 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2765 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2766 exit_server_cleanly("sendfile_short_send: "
2767 "write_data failed");
2769 nread += to_write;
2771 SAFE_FREE(buf);
2774 #endif /* defined WITH_SENDFILE */
2776 /****************************************************************************
2777 Return a readbraw error (4 bytes of zero).
2778 ****************************************************************************/
2780 static void reply_readbraw_error(void)
2782 char header[4];
2783 SIVAL(header,0,0);
2784 if (write_data(smbd_server_fd(),header,4) != 4) {
2785 fail_readraw();
2789 /****************************************************************************
2790 Use sendfile in readbraw.
2791 ****************************************************************************/
2793 static void send_file_readbraw(connection_struct *conn,
2794 struct smb_request *req,
2795 files_struct *fsp,
2796 SMB_OFF_T startpos,
2797 size_t nread,
2798 ssize_t mincount)
2800 char *outbuf = NULL;
2801 ssize_t ret=0;
2803 #if defined(WITH_SENDFILE)
2805 * We can only use sendfile on a non-chained packet
2806 * but we can use on a non-oplocked file. tridge proved this
2807 * on a train in Germany :-). JRA.
2808 * reply_readbraw has already checked the length.
2811 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2812 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2813 ssize_t sendfile_read = -1;
2814 char header[4];
2815 DATA_BLOB header_blob;
2817 _smb_setlen(header,nread);
2818 header_blob = data_blob_const(header, 4);
2820 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2821 &header_blob, startpos, nread)) == -1) {
2822 /* Returning ENOSYS means no data at all was sent.
2823 * Do this as a normal read. */
2824 if (errno == ENOSYS) {
2825 goto normal_readbraw;
2829 * Special hack for broken Linux with no working sendfile. If we
2830 * return EINTR we sent the header but not the rest of the data.
2831 * Fake this up by doing read/write calls.
2833 if (errno == EINTR) {
2834 /* Ensure we don't do this again. */
2835 set_use_sendfile(SNUM(conn), False);
2836 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2838 if (fake_sendfile(fsp, startpos, nread) == -1) {
2839 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2840 fsp->fsp_name, strerror(errno) ));
2841 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2843 return;
2846 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2847 fsp->fsp_name, strerror(errno) ));
2848 exit_server_cleanly("send_file_readbraw sendfile failed");
2849 } else if (sendfile_read == 0) {
2851 * Some sendfile implementations return 0 to indicate
2852 * that there was a short read, but nothing was
2853 * actually written to the socket. In this case,
2854 * fallback to the normal read path so the header gets
2855 * the correct byte count.
2857 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2858 "bytes falling back to the normal read: "
2859 "%s\n", fsp->fsp_name));
2860 goto normal_readbraw;
2863 /* Deal with possible short send. */
2864 if (sendfile_read != 4+nread) {
2865 sendfile_short_send(fsp, sendfile_read, 4, nread);
2867 return;
2870 normal_readbraw:
2871 #endif
2873 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2874 if (!outbuf) {
2875 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2876 (unsigned)(nread+4)));
2877 reply_readbraw_error();
2878 return;
2881 if (nread > 0) {
2882 ret = read_file(fsp,outbuf+4,startpos,nread);
2883 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2884 if (ret < mincount)
2885 ret = 0;
2886 #else
2887 if (ret < nread)
2888 ret = 0;
2889 #endif
2892 _smb_setlen(outbuf,ret);
2893 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2894 fail_readraw();
2896 TALLOC_FREE(outbuf);
2899 /****************************************************************************
2900 Reply to a readbraw (core+ protocol).
2901 ****************************************************************************/
2903 void reply_readbraw(struct smb_request *req)
2905 connection_struct *conn = req->conn;
2906 ssize_t maxcount,mincount;
2907 size_t nread = 0;
2908 SMB_OFF_T startpos;
2909 files_struct *fsp;
2910 struct lock_struct lock;
2911 SMB_STRUCT_STAT st;
2912 SMB_OFF_T size = 0;
2914 START_PROFILE(SMBreadbraw);
2916 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2917 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2918 "raw reads/writes are disallowed.");
2921 if (req->wct < 8) {
2922 reply_readbraw_error();
2923 END_PROFILE(SMBreadbraw);
2924 return;
2928 * Special check if an oplock break has been issued
2929 * and the readraw request croses on the wire, we must
2930 * return a zero length response here.
2933 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2936 * We have to do a check_fsp by hand here, as
2937 * we must always return 4 zero bytes on error,
2938 * not a NTSTATUS.
2941 if (!fsp || !conn || conn != fsp->conn ||
2942 req->vuid != fsp->vuid ||
2943 fsp->is_directory || fsp->fh->fd == -1) {
2945 * fsp could be NULL here so use the value from the packet. JRA.
2947 DEBUG(3,("reply_readbraw: fnum %d not valid "
2948 "- cache prime?\n",
2949 (int)SVAL(req->vwv+0, 0)));
2950 reply_readbraw_error();
2951 END_PROFILE(SMBreadbraw);
2952 return;
2955 /* Do a "by hand" version of CHECK_READ. */
2956 if (!(fsp->can_read ||
2957 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2958 (fsp->access_mask & FILE_EXECUTE)))) {
2959 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2960 (int)SVAL(req->vwv+0, 0)));
2961 reply_readbraw_error();
2962 END_PROFILE(SMBreadbraw);
2963 return;
2966 flush_write_cache(fsp, READRAW_FLUSH);
2968 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2969 if(req->wct == 10) {
2971 * This is a large offset (64 bit) read.
2973 #ifdef LARGE_SMB_OFF_T
2975 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
2977 #else /* !LARGE_SMB_OFF_T */
2980 * Ensure we haven't been sent a >32 bit offset.
2983 if(IVAL(req->vwv+8, 0) != 0) {
2984 DEBUG(0,("reply_readbraw: large offset "
2985 "(%x << 32) used and we don't support "
2986 "64 bit offsets.\n",
2987 (unsigned int)IVAL(req->vwv+8, 0) ));
2988 reply_readbraw_error();
2989 END_PROFILE(SMBreadbraw);
2990 return;
2993 #endif /* LARGE_SMB_OFF_T */
2995 if(startpos < 0) {
2996 DEBUG(0,("reply_readbraw: negative 64 bit "
2997 "readraw offset (%.0f) !\n",
2998 (double)startpos ));
2999 reply_readbraw_error();
3000 END_PROFILE(SMBreadbraw);
3001 return;
3005 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3006 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3008 /* ensure we don't overrun the packet size */
3009 maxcount = MIN(65535,maxcount);
3011 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3012 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3013 &lock);
3015 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3016 reply_readbraw_error();
3017 END_PROFILE(SMBreadbraw);
3018 return;
3021 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3022 size = st.st_size;
3025 if (startpos >= size) {
3026 nread = 0;
3027 } else {
3028 nread = MIN(maxcount,(size - startpos));
3031 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3032 if (nread < mincount)
3033 nread = 0;
3034 #endif
3036 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3037 "min=%lu nread=%lu\n",
3038 fsp->fnum, (double)startpos,
3039 (unsigned long)maxcount,
3040 (unsigned long)mincount,
3041 (unsigned long)nread ) );
3043 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3045 DEBUG(5,("reply_readbraw finished\n"));
3047 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3049 END_PROFILE(SMBreadbraw);
3050 return;
3053 #undef DBGC_CLASS
3054 #define DBGC_CLASS DBGC_LOCKING
3056 /****************************************************************************
3057 Reply to a lockread (core+ protocol).
3058 ****************************************************************************/
3060 void reply_lockread(struct smb_request *req)
3062 connection_struct *conn = req->conn;
3063 ssize_t nread = -1;
3064 char *data;
3065 SMB_OFF_T startpos;
3066 size_t numtoread;
3067 NTSTATUS status;
3068 files_struct *fsp;
3069 struct byte_range_lock *br_lck = NULL;
3070 char *p = NULL;
3072 START_PROFILE(SMBlockread);
3074 if (req->wct < 5) {
3075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3076 END_PROFILE(SMBlockread);
3077 return;
3080 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3082 if (!check_fsp(conn, req, fsp)) {
3083 END_PROFILE(SMBlockread);
3084 return;
3087 if (!CHECK_READ(fsp,req)) {
3088 reply_doserror(req, ERRDOS, ERRbadaccess);
3089 END_PROFILE(SMBlockread);
3090 return;
3093 numtoread = SVAL(req->vwv+1, 0);
3094 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3096 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3098 reply_outbuf(req, 5, numtoread + 3);
3100 data = smb_buf(req->outbuf) + 3;
3103 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3104 * protocol request that predates the read/write lock concept.
3105 * Thus instead of asking for a read lock here we need to ask
3106 * for a write lock. JRA.
3107 * Note that the requested lock size is unaffected by max_recv.
3110 br_lck = do_lock(smbd_messaging_context(),
3111 fsp,
3112 req->smbpid,
3113 (uint64_t)numtoread,
3114 (uint64_t)startpos,
3115 WRITE_LOCK,
3116 WINDOWS_LOCK,
3117 False, /* Non-blocking lock. */
3118 &status,
3119 NULL,
3120 NULL);
3121 TALLOC_FREE(br_lck);
3123 if (NT_STATUS_V(status)) {
3124 reply_nterror(req, status);
3125 END_PROFILE(SMBlockread);
3126 return;
3130 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3133 if (numtoread > max_recv) {
3134 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3135 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3136 (unsigned int)numtoread, (unsigned int)max_recv ));
3137 numtoread = MIN(numtoread,max_recv);
3139 nread = read_file(fsp,data,startpos,numtoread);
3141 if (nread < 0) {
3142 reply_unixerror(req, ERRDOS, ERRnoaccess);
3143 END_PROFILE(SMBlockread);
3144 return;
3147 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3149 SSVAL(req->outbuf,smb_vwv0,nread);
3150 SSVAL(req->outbuf,smb_vwv5,nread+3);
3151 p = smb_buf(req->outbuf);
3152 SCVAL(p,0,0); /* pad byte. */
3153 SSVAL(p,1,nread);
3155 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3156 fsp->fnum, (int)numtoread, (int)nread));
3158 END_PROFILE(SMBlockread);
3159 return;
3162 #undef DBGC_CLASS
3163 #define DBGC_CLASS DBGC_ALL
3165 /****************************************************************************
3166 Reply to a read.
3167 ****************************************************************************/
3169 void reply_read(struct smb_request *req)
3171 connection_struct *conn = req->conn;
3172 size_t numtoread;
3173 ssize_t nread = 0;
3174 char *data;
3175 SMB_OFF_T startpos;
3176 int outsize = 0;
3177 files_struct *fsp;
3178 struct lock_struct lock;
3180 START_PROFILE(SMBread);
3182 if (req->wct < 3) {
3183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3184 END_PROFILE(SMBread);
3185 return;
3188 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3190 if (!check_fsp(conn, req, fsp)) {
3191 END_PROFILE(SMBread);
3192 return;
3195 if (!CHECK_READ(fsp,req)) {
3196 reply_doserror(req, ERRDOS, ERRbadaccess);
3197 END_PROFILE(SMBread);
3198 return;
3201 numtoread = SVAL(req->vwv+1, 0);
3202 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3204 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3207 * The requested read size cannot be greater than max_recv. JRA.
3209 if (numtoread > max_recv) {
3210 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3211 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3212 (unsigned int)numtoread, (unsigned int)max_recv ));
3213 numtoread = MIN(numtoread,max_recv);
3216 reply_outbuf(req, 5, numtoread+3);
3218 data = smb_buf(req->outbuf) + 3;
3220 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3221 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3222 &lock);
3224 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3225 reply_doserror(req, ERRDOS,ERRlock);
3226 END_PROFILE(SMBread);
3227 return;
3230 if (numtoread > 0)
3231 nread = read_file(fsp,data,startpos,numtoread);
3233 if (nread < 0) {
3234 reply_unixerror(req, ERRDOS,ERRnoaccess);
3235 goto strict_unlock;
3238 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3240 SSVAL(req->outbuf,smb_vwv0,nread);
3241 SSVAL(req->outbuf,smb_vwv5,nread+3);
3242 SCVAL(smb_buf(req->outbuf),0,1);
3243 SSVAL(smb_buf(req->outbuf),1,nread);
3245 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3246 fsp->fnum, (int)numtoread, (int)nread ) );
3248 strict_unlock:
3249 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3251 END_PROFILE(SMBread);
3252 return;
3255 /****************************************************************************
3256 Setup readX header.
3257 ****************************************************************************/
3259 static int setup_readX_header(struct smb_request *req, char *outbuf,
3260 size_t smb_maxcnt)
3262 int outsize;
3263 char *data;
3265 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3266 data = smb_buf(outbuf);
3268 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3270 SCVAL(outbuf,smb_vwv0,0xFF);
3271 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3272 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3273 SSVAL(outbuf,smb_vwv6,
3274 req_wct_ofs(req)
3275 + 1 /* the wct field */
3276 + 12 * sizeof(uint16_t) /* vwv */
3277 + 2); /* the buflen field */
3278 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3279 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3280 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3281 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3282 return outsize;
3285 /****************************************************************************
3286 Reply to a read and X - possibly using sendfile.
3287 ****************************************************************************/
3289 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3290 files_struct *fsp, SMB_OFF_T startpos,
3291 size_t smb_maxcnt)
3293 SMB_STRUCT_STAT sbuf;
3294 ssize_t nread = -1;
3295 struct lock_struct lock;
3297 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3298 reply_unixerror(req, ERRDOS, ERRnoaccess);
3299 return;
3302 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3303 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3304 &lock);
3306 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3307 reply_doserror(req, ERRDOS, ERRlock);
3308 return;
3311 if (!S_ISREG(sbuf.st_mode) || (startpos > sbuf.st_size)
3312 || (smb_maxcnt > (sbuf.st_size - startpos))) {
3314 * We already know that we would do a short read, so don't
3315 * try the sendfile() path.
3317 goto nosendfile_read;
3320 #if defined(WITH_SENDFILE)
3322 * We can only use sendfile on a non-chained packet
3323 * but we can use on a non-oplocked file. tridge proved this
3324 * on a train in Germany :-). JRA.
3327 if (!req_is_in_chain(req) &&
3328 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3329 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3330 uint8 headerbuf[smb_size + 12 * 2];
3331 DATA_BLOB header;
3334 * Set up the packet header before send. We
3335 * assume here the sendfile will work (get the
3336 * correct amount of data).
3339 header = data_blob_const(headerbuf, sizeof(headerbuf));
3341 construct_reply_common_req(req, (char *)headerbuf);
3342 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3344 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3345 /* Returning ENOSYS means no data at all was sent.
3346 Do this as a normal read. */
3347 if (errno == ENOSYS) {
3348 goto normal_read;
3352 * Special hack for broken Linux with no working sendfile. If we
3353 * return EINTR we sent the header but not the rest of the data.
3354 * Fake this up by doing read/write calls.
3357 if (errno == EINTR) {
3358 /* Ensure we don't do this again. */
3359 set_use_sendfile(SNUM(conn), False);
3360 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3361 nread = fake_sendfile(fsp, startpos,
3362 smb_maxcnt);
3363 if (nread == -1) {
3364 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3365 fsp->fsp_name, strerror(errno) ));
3366 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3368 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3369 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3370 /* No outbuf here means successful sendfile. */
3371 goto strict_unlock;
3374 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3375 fsp->fsp_name, strerror(errno) ));
3376 exit_server_cleanly("send_file_readX sendfile failed");
3377 } else if (nread == 0) {
3379 * Some sendfile implementations return 0 to indicate
3380 * that there was a short read, but nothing was
3381 * actually written to the socket. In this case,
3382 * fallback to the normal read path so the header gets
3383 * the correct byte count.
3385 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3386 "falling back to the normal read: %s\n",
3387 fsp->fsp_name));
3388 goto normal_read;
3391 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3392 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3394 /* Deal with possible short send. */
3395 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3396 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3398 /* No outbuf here means successful sendfile. */
3399 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3400 SMB_PERFCOUNT_END(&req->pcd);
3401 goto strict_unlock;
3404 normal_read:
3406 #endif
3408 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3409 uint8 headerbuf[smb_size + 2*12];
3411 construct_reply_common_req(req, (char *)headerbuf);
3412 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3414 /* Send out the header. */
3415 if (write_data(smbd_server_fd(), (char *)headerbuf,
3416 sizeof(headerbuf)) != sizeof(headerbuf)) {
3417 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3418 fsp->fsp_name, strerror(errno) ));
3419 exit_server_cleanly("send_file_readX sendfile failed");
3421 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3422 if (nread == -1) {
3423 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3424 fsp->fsp_name, strerror(errno) ));
3425 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3427 goto strict_unlock;
3430 nosendfile_read:
3432 reply_outbuf(req, 12, smb_maxcnt);
3434 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3436 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3438 if (nread < 0) {
3439 reply_unixerror(req, ERRDOS, ERRnoaccess);
3440 return;
3443 setup_readX_header(req, (char *)req->outbuf, nread);
3445 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3446 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3448 chain_reply(req);
3449 return;
3451 strict_unlock:
3452 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3453 TALLOC_FREE(req->outbuf);
3454 return;
3457 /****************************************************************************
3458 Reply to a read and X.
3459 ****************************************************************************/
3461 void reply_read_and_X(struct smb_request *req)
3463 connection_struct *conn = req->conn;
3464 files_struct *fsp;
3465 SMB_OFF_T startpos;
3466 size_t smb_maxcnt;
3467 bool big_readX = False;
3468 #if 0
3469 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3470 #endif
3472 START_PROFILE(SMBreadX);
3474 if ((req->wct != 10) && (req->wct != 12)) {
3475 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3476 return;
3479 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3480 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3481 smb_maxcnt = SVAL(req->vwv+5, 0);
3483 /* If it's an IPC, pass off the pipe handler. */
3484 if (IS_IPC(conn)) {
3485 reply_pipe_read_and_X(req);
3486 END_PROFILE(SMBreadX);
3487 return;
3490 if (!check_fsp(conn, req, fsp)) {
3491 END_PROFILE(SMBreadX);
3492 return;
3495 if (!CHECK_READ(fsp,req)) {
3496 reply_doserror(req, ERRDOS,ERRbadaccess);
3497 END_PROFILE(SMBreadX);
3498 return;
3501 if (global_client_caps & CAP_LARGE_READX) {
3502 size_t upper_size = SVAL(req->vwv+7, 0);
3503 smb_maxcnt |= (upper_size<<16);
3504 if (upper_size > 1) {
3505 /* Can't do this on a chained packet. */
3506 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3507 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3508 END_PROFILE(SMBreadX);
3509 return;
3511 /* We currently don't do this on signed or sealed data. */
3512 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3513 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3514 END_PROFILE(SMBreadX);
3515 return;
3517 /* Is there room in the reply for this data ? */
3518 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3519 reply_nterror(req,
3520 NT_STATUS_INVALID_PARAMETER);
3521 END_PROFILE(SMBreadX);
3522 return;
3524 big_readX = True;
3528 if (req->wct == 12) {
3529 #ifdef LARGE_SMB_OFF_T
3531 * This is a large offset (64 bit) read.
3533 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3535 #else /* !LARGE_SMB_OFF_T */
3538 * Ensure we haven't been sent a >32 bit offset.
3541 if(IVAL(req->vwv+10, 0) != 0) {
3542 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3543 "used and we don't support 64 bit offsets.\n",
3544 (unsigned int)IVAL(req->vwv+10, 0) ));
3545 END_PROFILE(SMBreadX);
3546 reply_doserror(req, ERRDOS, ERRbadaccess);
3547 return;
3550 #endif /* LARGE_SMB_OFF_T */
3554 if (!big_readX &&
3555 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3556 goto out;
3559 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3561 out:
3562 END_PROFILE(SMBreadX);
3563 return;
3566 /****************************************************************************
3567 Error replies to writebraw must have smb_wct == 1. Fix this up.
3568 ****************************************************************************/
3570 void error_to_writebrawerr(struct smb_request *req)
3572 uint8 *old_outbuf = req->outbuf;
3574 reply_outbuf(req, 1, 0);
3576 memcpy(req->outbuf, old_outbuf, smb_size);
3577 TALLOC_FREE(old_outbuf);
3580 /****************************************************************************
3581 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3582 ****************************************************************************/
3584 void reply_writebraw(struct smb_request *req)
3586 connection_struct *conn = req->conn;
3587 char *buf = NULL;
3588 ssize_t nwritten=0;
3589 ssize_t total_written=0;
3590 size_t numtowrite=0;
3591 size_t tcount;
3592 SMB_OFF_T startpos;
3593 char *data=NULL;
3594 bool write_through;
3595 files_struct *fsp;
3596 struct lock_struct lock;
3597 NTSTATUS status;
3599 START_PROFILE(SMBwritebraw);
3602 * If we ever reply with an error, it must have the SMB command
3603 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3604 * we're finished.
3606 SCVAL(req->inbuf,smb_com,SMBwritec);
3608 if (srv_is_signing_active()) {
3609 END_PROFILE(SMBwritebraw);
3610 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3611 "raw reads/writes are disallowed.");
3614 if (req->wct < 12) {
3615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3616 error_to_writebrawerr(req);
3617 END_PROFILE(SMBwritebraw);
3618 return;
3621 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3622 if (!check_fsp(conn, req, fsp)) {
3623 error_to_writebrawerr(req);
3624 END_PROFILE(SMBwritebraw);
3625 return;
3628 if (!CHECK_WRITE(fsp)) {
3629 reply_doserror(req, ERRDOS, ERRbadaccess);
3630 error_to_writebrawerr(req);
3631 END_PROFILE(SMBwritebraw);
3632 return;
3635 tcount = IVAL(req->vwv+1, 0);
3636 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3637 write_through = BITSETW(req->vwv+7,0);
3639 /* We have to deal with slightly different formats depending
3640 on whether we are using the core+ or lanman1.0 protocol */
3642 if(Protocol <= PROTOCOL_COREPLUS) {
3643 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3644 data = smb_buf(req->inbuf);
3645 } else {
3646 numtowrite = SVAL(req->vwv+10, 0);
3647 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3650 /* Ensure we don't write bytes past the end of this packet. */
3651 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3652 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3653 error_to_writebrawerr(req);
3654 END_PROFILE(SMBwritebraw);
3655 return;
3658 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3659 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3660 &lock);
3662 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3663 reply_doserror(req, ERRDOS, ERRlock);
3664 error_to_writebrawerr(req);
3665 END_PROFILE(SMBwritebraw);
3666 return;
3669 if (numtowrite>0) {
3670 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3673 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3674 "wrote=%d sync=%d\n",
3675 fsp->fnum, (double)startpos, (int)numtowrite,
3676 (int)nwritten, (int)write_through));
3678 if (nwritten < (ssize_t)numtowrite) {
3679 reply_unixerror(req, ERRHRD, ERRdiskfull);
3680 error_to_writebrawerr(req);
3681 goto strict_unlock;
3684 total_written = nwritten;
3686 /* Allocate a buffer of 64k + length. */
3687 buf = TALLOC_ARRAY(NULL, char, 65540);
3688 if (!buf) {
3689 reply_doserror(req, ERRDOS, ERRnomem);
3690 error_to_writebrawerr(req);
3691 goto strict_unlock;
3694 /* Return a SMBwritebraw message to the redirector to tell
3695 * it to send more bytes */
3697 memcpy(buf, req->inbuf, smb_size);
3698 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3699 SCVAL(buf,smb_com,SMBwritebraw);
3700 SSVALS(buf,smb_vwv0,0xFFFF);
3701 show_msg(buf);
3702 if (!srv_send_smb(smbd_server_fd(),
3703 buf,
3704 IS_CONN_ENCRYPTED(conn),
3705 &req->pcd)) {
3706 exit_server_cleanly("reply_writebraw: srv_send_smb "
3707 "failed.");
3710 /* Now read the raw data into the buffer and write it */
3711 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3712 &numtowrite);
3713 if (!NT_STATUS_IS_OK(status)) {
3714 exit_server_cleanly("secondary writebraw failed");
3717 /* Set up outbuf to return the correct size */
3718 reply_outbuf(req, 1, 0);
3720 if (numtowrite != 0) {
3722 if (numtowrite > 0xFFFF) {
3723 DEBUG(0,("reply_writebraw: Oversize secondary write "
3724 "raw requested (%u). Terminating\n",
3725 (unsigned int)numtowrite ));
3726 exit_server_cleanly("secondary writebraw failed");
3729 if (tcount > nwritten+numtowrite) {
3730 DEBUG(3,("reply_writebraw: Client overestimated the "
3731 "write %d %d %d\n",
3732 (int)tcount,(int)nwritten,(int)numtowrite));
3735 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3737 if (!NT_STATUS_IS_OK(status)) {
3738 DEBUG(0,("reply_writebraw: Oversize secondary write "
3739 "raw read failed (%s). Terminating\n",
3740 nt_errstr(status)));
3741 exit_server_cleanly("secondary writebraw failed");
3744 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3745 if (nwritten == -1) {
3746 TALLOC_FREE(buf);
3747 reply_unixerror(req, ERRHRD, ERRdiskfull);
3748 error_to_writebrawerr(req);
3749 goto strict_unlock;
3752 if (nwritten < (ssize_t)numtowrite) {
3753 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3754 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3757 if (nwritten > 0) {
3758 total_written += nwritten;
3762 TALLOC_FREE(buf);
3763 SSVAL(req->outbuf,smb_vwv0,total_written);
3765 status = sync_file(conn, fsp, write_through);
3766 if (!NT_STATUS_IS_OK(status)) {
3767 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3768 fsp->fsp_name, nt_errstr(status) ));
3769 reply_nterror(req, status);
3770 error_to_writebrawerr(req);
3771 goto strict_unlock;
3774 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3775 "wrote=%d\n",
3776 fsp->fnum, (double)startpos, (int)numtowrite,
3777 (int)total_written));
3779 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3781 /* We won't return a status if write through is not selected - this
3782 * follows what WfWg does */
3783 END_PROFILE(SMBwritebraw);
3785 if (!write_through && total_written==tcount) {
3787 #if RABBIT_PELLET_FIX
3789 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3790 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3791 * JRA.
3793 if (!send_keepalive(smbd_server_fd())) {
3794 exit_server_cleanly("reply_writebraw: send of "
3795 "keepalive failed");
3797 #endif
3798 TALLOC_FREE(req->outbuf);
3800 return;
3802 strict_unlock:
3803 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3805 END_PROFILE(SMBwritebraw);
3806 return;
3809 #undef DBGC_CLASS
3810 #define DBGC_CLASS DBGC_LOCKING
3812 /****************************************************************************
3813 Reply to a writeunlock (core+).
3814 ****************************************************************************/
3816 void reply_writeunlock(struct smb_request *req)
3818 connection_struct *conn = req->conn;
3819 ssize_t nwritten = -1;
3820 size_t numtowrite;
3821 SMB_OFF_T startpos;
3822 const char *data;
3823 NTSTATUS status = NT_STATUS_OK;
3824 files_struct *fsp;
3825 struct lock_struct lock;
3827 START_PROFILE(SMBwriteunlock);
3829 if (req->wct < 5) {
3830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3831 END_PROFILE(SMBwriteunlock);
3832 return;
3835 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3837 if (!check_fsp(conn, req, fsp)) {
3838 END_PROFILE(SMBwriteunlock);
3839 return;
3842 if (!CHECK_WRITE(fsp)) {
3843 reply_doserror(req, ERRDOS,ERRbadaccess);
3844 END_PROFILE(SMBwriteunlock);
3845 return;
3848 numtowrite = SVAL(req->vwv+1, 0);
3849 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3850 data = (const char *)req->buf + 3;
3852 if (numtowrite) {
3853 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3854 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3855 &lock);
3857 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3858 reply_doserror(req, ERRDOS, ERRlock);
3859 END_PROFILE(SMBwriteunlock);
3860 return;
3864 /* The special X/Open SMB protocol handling of
3865 zero length writes is *NOT* done for
3866 this call */
3867 if(numtowrite == 0) {
3868 nwritten = 0;
3869 } else {
3870 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3873 status = sync_file(conn, fsp, False /* write through */);
3874 if (!NT_STATUS_IS_OK(status)) {
3875 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3876 fsp->fsp_name, nt_errstr(status) ));
3877 reply_nterror(req, status);
3878 goto strict_unlock;
3881 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3882 reply_unixerror(req, ERRHRD, ERRdiskfull);
3883 goto strict_unlock;
3886 if (numtowrite) {
3887 status = do_unlock(smbd_messaging_context(),
3888 fsp,
3889 req->smbpid,
3890 (uint64_t)numtowrite,
3891 (uint64_t)startpos,
3892 WINDOWS_LOCK);
3894 if (NT_STATUS_V(status)) {
3895 reply_nterror(req, status);
3896 goto strict_unlock;
3900 reply_outbuf(req, 1, 0);
3902 SSVAL(req->outbuf,smb_vwv0,nwritten);
3904 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3905 fsp->fnum, (int)numtowrite, (int)nwritten));
3907 strict_unlock:
3908 if (numtowrite) {
3909 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3912 END_PROFILE(SMBwriteunlock);
3913 return;
3916 #undef DBGC_CLASS
3917 #define DBGC_CLASS DBGC_ALL
3919 /****************************************************************************
3920 Reply to a write.
3921 ****************************************************************************/
3923 void reply_write(struct smb_request *req)
3925 connection_struct *conn = req->conn;
3926 size_t numtowrite;
3927 ssize_t nwritten = -1;
3928 SMB_OFF_T startpos;
3929 const char *data;
3930 files_struct *fsp;
3931 struct lock_struct lock;
3932 NTSTATUS status;
3934 START_PROFILE(SMBwrite);
3936 if (req->wct < 5) {
3937 END_PROFILE(SMBwrite);
3938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3939 return;
3942 /* If it's an IPC, pass off the pipe handler. */
3943 if (IS_IPC(conn)) {
3944 reply_pipe_write(req);
3945 END_PROFILE(SMBwrite);
3946 return;
3949 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3951 if (!check_fsp(conn, req, fsp)) {
3952 END_PROFILE(SMBwrite);
3953 return;
3956 if (!CHECK_WRITE(fsp)) {
3957 reply_doserror(req, ERRDOS, ERRbadaccess);
3958 END_PROFILE(SMBwrite);
3959 return;
3962 numtowrite = SVAL(req->vwv+1, 0);
3963 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3964 data = (const char *)req->buf + 3;
3966 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3967 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3968 &lock);
3970 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3971 reply_doserror(req, ERRDOS, ERRlock);
3972 END_PROFILE(SMBwrite);
3973 return;
3977 * X/Open SMB protocol says that if smb_vwv1 is
3978 * zero then the file size should be extended or
3979 * truncated to the size given in smb_vwv[2-3].
3982 if(numtowrite == 0) {
3984 * This is actually an allocate call, and set EOF. JRA.
3986 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3987 if (nwritten < 0) {
3988 reply_nterror(req, NT_STATUS_DISK_FULL);
3989 goto strict_unlock;
3991 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3992 if (nwritten < 0) {
3993 reply_nterror(req, NT_STATUS_DISK_FULL);
3994 goto strict_unlock;
3996 trigger_write_time_update_immediate(fsp);
3997 } else {
3998 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4001 status = sync_file(conn, fsp, False);
4002 if (!NT_STATUS_IS_OK(status)) {
4003 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4004 fsp->fsp_name, nt_errstr(status) ));
4005 reply_nterror(req, status);
4006 goto strict_unlock;
4009 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4010 reply_unixerror(req, ERRHRD, ERRdiskfull);
4011 goto strict_unlock;
4014 reply_outbuf(req, 1, 0);
4016 SSVAL(req->outbuf,smb_vwv0,nwritten);
4018 if (nwritten < (ssize_t)numtowrite) {
4019 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4020 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4023 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4025 strict_unlock:
4026 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4028 END_PROFILE(SMBwrite);
4029 return;
4032 /****************************************************************************
4033 Ensure a buffer is a valid writeX for recvfile purposes.
4034 ****************************************************************************/
4036 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4037 (2*14) + /* word count (including bcc) */ \
4038 1 /* pad byte */)
4040 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4042 size_t numtowrite;
4043 connection_struct *conn = NULL;
4044 unsigned int doff = 0;
4045 size_t len = smb_len_large(inbuf);
4047 if (is_encrypted_packet(inbuf)) {
4048 /* Can't do this on encrypted
4049 * connections. */
4050 return false;
4053 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4054 return false;
4057 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4058 CVAL(inbuf,smb_wct) != 14) {
4059 DEBUG(10,("is_valid_writeX_buffer: chained or "
4060 "invalid word length.\n"));
4061 return false;
4064 conn = conn_find(SVAL(inbuf, smb_tid));
4065 if (conn == NULL) {
4066 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4067 return false;
4069 if (IS_IPC(conn)) {
4070 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4071 return false;
4073 if (IS_PRINT(conn)) {
4074 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4075 return false;
4077 doff = SVAL(inbuf,smb_vwv11);
4079 numtowrite = SVAL(inbuf,smb_vwv10);
4081 if (len > doff && len - doff > 0xFFFF) {
4082 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4085 if (numtowrite == 0) {
4086 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4087 return false;
4090 /* Ensure the sizes match up. */
4091 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4092 /* no pad byte...old smbclient :-( */
4093 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4094 (unsigned int)doff,
4095 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4096 return false;
4099 if (len - doff != numtowrite) {
4100 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4101 "len = %u, doff = %u, numtowrite = %u\n",
4102 (unsigned int)len,
4103 (unsigned int)doff,
4104 (unsigned int)numtowrite ));
4105 return false;
4108 DEBUG(10,("is_valid_writeX_buffer: true "
4109 "len = %u, doff = %u, numtowrite = %u\n",
4110 (unsigned int)len,
4111 (unsigned int)doff,
4112 (unsigned int)numtowrite ));
4114 return true;
4117 /****************************************************************************
4118 Reply to a write and X.
4119 ****************************************************************************/
4121 void reply_write_and_X(struct smb_request *req)
4123 connection_struct *conn = req->conn;
4124 files_struct *fsp;
4125 struct lock_struct lock;
4126 SMB_OFF_T startpos;
4127 size_t numtowrite;
4128 bool write_through;
4129 ssize_t nwritten;
4130 unsigned int smb_doff;
4131 unsigned int smblen;
4132 char *data;
4133 NTSTATUS status;
4135 START_PROFILE(SMBwriteX);
4137 if ((req->wct != 12) && (req->wct != 14)) {
4138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4139 END_PROFILE(SMBwriteX);
4140 return;
4143 numtowrite = SVAL(req->vwv+10, 0);
4144 smb_doff = SVAL(req->vwv+11, 0);
4145 smblen = smb_len(req->inbuf);
4147 if (req->unread_bytes > 0xFFFF ||
4148 (smblen > smb_doff &&
4149 smblen - smb_doff > 0xFFFF)) {
4150 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4153 if (req->unread_bytes) {
4154 /* Can't do a recvfile write on IPC$ */
4155 if (IS_IPC(conn)) {
4156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4157 END_PROFILE(SMBwriteX);
4158 return;
4160 if (numtowrite != req->unread_bytes) {
4161 reply_doserror(req, ERRDOS, ERRbadmem);
4162 END_PROFILE(SMBwriteX);
4163 return;
4165 } else {
4166 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4167 smb_doff + numtowrite > smblen) {
4168 reply_doserror(req, ERRDOS, ERRbadmem);
4169 END_PROFILE(SMBwriteX);
4170 return;
4174 /* If it's an IPC, pass off the pipe handler. */
4175 if (IS_IPC(conn)) {
4176 if (req->unread_bytes) {
4177 reply_doserror(req, ERRDOS, ERRbadmem);
4178 END_PROFILE(SMBwriteX);
4179 return;
4181 reply_pipe_write_and_X(req);
4182 END_PROFILE(SMBwriteX);
4183 return;
4186 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4187 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4188 write_through = BITSETW(req->vwv+7,0);
4190 if (!check_fsp(conn, req, fsp)) {
4191 END_PROFILE(SMBwriteX);
4192 return;
4195 if (!CHECK_WRITE(fsp)) {
4196 reply_doserror(req, ERRDOS, ERRbadaccess);
4197 END_PROFILE(SMBwriteX);
4198 return;
4201 data = smb_base(req->inbuf) + smb_doff;
4203 if(req->wct == 14) {
4204 #ifdef LARGE_SMB_OFF_T
4206 * This is a large offset (64 bit) write.
4208 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4210 #else /* !LARGE_SMB_OFF_T */
4213 * Ensure we haven't been sent a >32 bit offset.
4216 if(IVAL(req->vwv+12, 0) != 0) {
4217 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4218 "used and we don't support 64 bit offsets.\n",
4219 (unsigned int)IVAL(req->vwv+12, 0) ));
4220 reply_doserror(req, ERRDOS, ERRbadaccess);
4221 END_PROFILE(SMBwriteX);
4222 return;
4225 #endif /* LARGE_SMB_OFF_T */
4228 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4229 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4230 &lock);
4232 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4233 reply_doserror(req, ERRDOS, ERRlock);
4234 END_PROFILE(SMBwriteX);
4235 return;
4238 /* X/Open SMB protocol says that, unlike SMBwrite
4239 if the length is zero then NO truncation is
4240 done, just a write of zero. To truncate a file,
4241 use SMBwrite. */
4243 if(numtowrite == 0) {
4244 nwritten = 0;
4245 } else {
4247 if ((req->unread_bytes == 0) &&
4248 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4249 numtowrite)) {
4250 goto strict_unlock;
4253 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4256 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4257 reply_unixerror(req, ERRHRD, ERRdiskfull);
4258 goto strict_unlock;
4261 reply_outbuf(req, 6, 0);
4262 SSVAL(req->outbuf,smb_vwv2,nwritten);
4263 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4265 if (nwritten < (ssize_t)numtowrite) {
4266 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4267 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4270 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4271 fsp->fnum, (int)numtowrite, (int)nwritten));
4273 status = sync_file(conn, fsp, write_through);
4274 if (!NT_STATUS_IS_OK(status)) {
4275 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4276 fsp->fsp_name, nt_errstr(status) ));
4277 reply_nterror(req, status);
4278 goto strict_unlock;
4281 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4283 END_PROFILE(SMBwriteX);
4284 chain_reply(req);
4285 return;
4287 strict_unlock:
4288 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4290 END_PROFILE(SMBwriteX);
4291 return;
4294 /****************************************************************************
4295 Reply to a lseek.
4296 ****************************************************************************/
4298 void reply_lseek(struct smb_request *req)
4300 connection_struct *conn = req->conn;
4301 SMB_OFF_T startpos;
4302 SMB_OFF_T res= -1;
4303 int mode,umode;
4304 files_struct *fsp;
4306 START_PROFILE(SMBlseek);
4308 if (req->wct < 4) {
4309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4310 END_PROFILE(SMBlseek);
4311 return;
4314 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4316 if (!check_fsp(conn, req, fsp)) {
4317 return;
4320 flush_write_cache(fsp, SEEK_FLUSH);
4322 mode = SVAL(req->vwv+1, 0) & 3;
4323 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4324 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4326 switch (mode) {
4327 case 0:
4328 umode = SEEK_SET;
4329 res = startpos;
4330 break;
4331 case 1:
4332 umode = SEEK_CUR;
4333 res = fsp->fh->pos + startpos;
4334 break;
4335 case 2:
4336 umode = SEEK_END;
4337 break;
4338 default:
4339 umode = SEEK_SET;
4340 res = startpos;
4341 break;
4344 if (umode == SEEK_END) {
4345 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4346 if(errno == EINVAL) {
4347 SMB_OFF_T current_pos = startpos;
4348 SMB_STRUCT_STAT sbuf;
4350 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4351 reply_unixerror(req, ERRDOS,
4352 ERRnoaccess);
4353 END_PROFILE(SMBlseek);
4354 return;
4357 current_pos += sbuf.st_size;
4358 if(current_pos < 0)
4359 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4363 if(res == -1) {
4364 reply_unixerror(req, ERRDOS, ERRnoaccess);
4365 END_PROFILE(SMBlseek);
4366 return;
4370 fsp->fh->pos = res;
4372 reply_outbuf(req, 2, 0);
4373 SIVAL(req->outbuf,smb_vwv0,res);
4375 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4376 fsp->fnum, (double)startpos, (double)res, mode));
4378 END_PROFILE(SMBlseek);
4379 return;
4382 /****************************************************************************
4383 Reply to a flush.
4384 ****************************************************************************/
4386 void reply_flush(struct smb_request *req)
4388 connection_struct *conn = req->conn;
4389 uint16 fnum;
4390 files_struct *fsp;
4392 START_PROFILE(SMBflush);
4394 if (req->wct < 1) {
4395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4396 return;
4399 fnum = SVAL(req->vwv+0, 0);
4400 fsp = file_fsp(req, fnum);
4402 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4403 return;
4406 if (!fsp) {
4407 file_sync_all(conn);
4408 } else {
4409 NTSTATUS status = sync_file(conn, fsp, True);
4410 if (!NT_STATUS_IS_OK(status)) {
4411 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4412 fsp->fsp_name, nt_errstr(status) ));
4413 reply_nterror(req, status);
4414 END_PROFILE(SMBflush);
4415 return;
4419 reply_outbuf(req, 0, 0);
4421 DEBUG(3,("flush\n"));
4422 END_PROFILE(SMBflush);
4423 return;
4426 /****************************************************************************
4427 Reply to a exit.
4428 conn POINTER CAN BE NULL HERE !
4429 ****************************************************************************/
4431 void reply_exit(struct smb_request *req)
4433 START_PROFILE(SMBexit);
4435 file_close_pid(req->smbpid, req->vuid);
4437 reply_outbuf(req, 0, 0);
4439 DEBUG(3,("exit\n"));
4441 END_PROFILE(SMBexit);
4442 return;
4445 /****************************************************************************
4446 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4447 ****************************************************************************/
4449 void reply_close(struct smb_request *req)
4451 connection_struct *conn = req->conn;
4452 NTSTATUS status = NT_STATUS_OK;
4453 files_struct *fsp = NULL;
4454 START_PROFILE(SMBclose);
4456 if (req->wct < 3) {
4457 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4458 END_PROFILE(SMBclose);
4459 return;
4462 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4465 * We can only use check_fsp if we know it's not a directory.
4468 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4469 reply_doserror(req, ERRDOS, ERRbadfid);
4470 END_PROFILE(SMBclose);
4471 return;
4474 if(fsp->is_directory) {
4476 * Special case - close NT SMB directory handle.
4478 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4479 status = close_file(req, fsp, NORMAL_CLOSE);
4480 } else {
4481 time_t t;
4483 * Close ordinary file.
4486 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4487 fsp->fh->fd, fsp->fnum,
4488 conn->num_files_open));
4491 * Take care of any time sent in the close.
4494 t = srv_make_unix_date3(req->vwv+1);
4495 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4498 * close_file() returns the unix errno if an error
4499 * was detected on close - normally this is due to
4500 * a disk full error. If not then it was probably an I/O error.
4503 status = close_file(req, fsp, NORMAL_CLOSE);
4506 if (!NT_STATUS_IS_OK(status)) {
4507 reply_nterror(req, status);
4508 END_PROFILE(SMBclose);
4509 return;
4512 reply_outbuf(req, 0, 0);
4513 END_PROFILE(SMBclose);
4514 return;
4517 /****************************************************************************
4518 Reply to a writeclose (Core+ protocol).
4519 ****************************************************************************/
4521 void reply_writeclose(struct smb_request *req)
4523 connection_struct *conn = req->conn;
4524 size_t numtowrite;
4525 ssize_t nwritten = -1;
4526 NTSTATUS close_status = NT_STATUS_OK;
4527 SMB_OFF_T startpos;
4528 const char *data;
4529 struct timespec mtime;
4530 files_struct *fsp;
4531 struct lock_struct lock;
4533 START_PROFILE(SMBwriteclose);
4535 if (req->wct < 6) {
4536 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4537 END_PROFILE(SMBwriteclose);
4538 return;
4541 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4543 if (!check_fsp(conn, req, fsp)) {
4544 END_PROFILE(SMBwriteclose);
4545 return;
4547 if (!CHECK_WRITE(fsp)) {
4548 reply_doserror(req, ERRDOS,ERRbadaccess);
4549 END_PROFILE(SMBwriteclose);
4550 return;
4553 numtowrite = SVAL(req->vwv+1, 0);
4554 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4555 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4556 data = (const char *)req->buf + 1;
4558 if (numtowrite) {
4559 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4560 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4561 &lock);
4563 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4564 reply_doserror(req, ERRDOS,ERRlock);
4565 END_PROFILE(SMBwriteclose);
4566 return;
4570 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4572 set_close_write_time(fsp, mtime);
4575 * More insanity. W2K only closes the file if writelen > 0.
4576 * JRA.
4579 if (numtowrite) {
4580 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4581 fsp->fsp_name ));
4582 close_status = close_file(req, fsp, NORMAL_CLOSE);
4585 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4586 fsp->fnum, (int)numtowrite, (int)nwritten,
4587 conn->num_files_open));
4589 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4590 reply_doserror(req, ERRHRD, ERRdiskfull);
4591 goto strict_unlock;
4594 if(!NT_STATUS_IS_OK(close_status)) {
4595 reply_nterror(req, close_status);
4596 goto strict_unlock;
4599 reply_outbuf(req, 1, 0);
4601 SSVAL(req->outbuf,smb_vwv0,nwritten);
4603 strict_unlock:
4604 if (numtowrite) {
4605 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4608 END_PROFILE(SMBwriteclose);
4609 return;
4612 #undef DBGC_CLASS
4613 #define DBGC_CLASS DBGC_LOCKING
4615 /****************************************************************************
4616 Reply to a lock.
4617 ****************************************************************************/
4619 void reply_lock(struct smb_request *req)
4621 connection_struct *conn = req->conn;
4622 uint64_t count,offset;
4623 NTSTATUS status;
4624 files_struct *fsp;
4625 struct byte_range_lock *br_lck = NULL;
4627 START_PROFILE(SMBlock);
4629 if (req->wct < 5) {
4630 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4631 END_PROFILE(SMBlock);
4632 return;
4635 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4637 if (!check_fsp(conn, req, fsp)) {
4638 END_PROFILE(SMBlock);
4639 return;
4642 count = (uint64_t)IVAL(req->vwv+1, 0);
4643 offset = (uint64_t)IVAL(req->vwv+3, 0);
4645 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4646 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4648 br_lck = do_lock(smbd_messaging_context(),
4649 fsp,
4650 req->smbpid,
4651 count,
4652 offset,
4653 WRITE_LOCK,
4654 WINDOWS_LOCK,
4655 False, /* Non-blocking lock. */
4656 &status,
4657 NULL,
4658 NULL);
4660 TALLOC_FREE(br_lck);
4662 if (NT_STATUS_V(status)) {
4663 reply_nterror(req, status);
4664 END_PROFILE(SMBlock);
4665 return;
4668 reply_outbuf(req, 0, 0);
4670 END_PROFILE(SMBlock);
4671 return;
4674 /****************************************************************************
4675 Reply to a unlock.
4676 ****************************************************************************/
4678 void reply_unlock(struct smb_request *req)
4680 connection_struct *conn = req->conn;
4681 uint64_t count,offset;
4682 NTSTATUS status;
4683 files_struct *fsp;
4685 START_PROFILE(SMBunlock);
4687 if (req->wct < 5) {
4688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4689 END_PROFILE(SMBunlock);
4690 return;
4693 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4695 if (!check_fsp(conn, req, fsp)) {
4696 END_PROFILE(SMBunlock);
4697 return;
4700 count = (uint64_t)IVAL(req->vwv+1, 0);
4701 offset = (uint64_t)IVAL(req->vwv+3, 0);
4703 status = do_unlock(smbd_messaging_context(),
4704 fsp,
4705 req->smbpid,
4706 count,
4707 offset,
4708 WINDOWS_LOCK);
4710 if (NT_STATUS_V(status)) {
4711 reply_nterror(req, status);
4712 END_PROFILE(SMBunlock);
4713 return;
4716 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4717 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4719 reply_outbuf(req, 0, 0);
4721 END_PROFILE(SMBunlock);
4722 return;
4725 #undef DBGC_CLASS
4726 #define DBGC_CLASS DBGC_ALL
4728 /****************************************************************************
4729 Reply to a tdis.
4730 conn POINTER CAN BE NULL HERE !
4731 ****************************************************************************/
4733 void reply_tdis(struct smb_request *req)
4735 connection_struct *conn = req->conn;
4736 START_PROFILE(SMBtdis);
4738 if (!conn) {
4739 DEBUG(4,("Invalid connection in tdis\n"));
4740 reply_doserror(req, ERRSRV, ERRinvnid);
4741 END_PROFILE(SMBtdis);
4742 return;
4745 conn->used = False;
4747 close_cnum(conn,req->vuid);
4748 req->conn = NULL;
4750 reply_outbuf(req, 0, 0);
4751 END_PROFILE(SMBtdis);
4752 return;
4755 /****************************************************************************
4756 Reply to a echo.
4757 conn POINTER CAN BE NULL HERE !
4758 ****************************************************************************/
4760 void reply_echo(struct smb_request *req)
4762 connection_struct *conn = req->conn;
4763 struct smb_perfcount_data local_pcd;
4764 struct smb_perfcount_data *cur_pcd;
4765 int smb_reverb;
4766 int seq_num;
4768 START_PROFILE(SMBecho);
4770 smb_init_perfcount_data(&local_pcd);
4772 if (req->wct < 1) {
4773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4774 END_PROFILE(SMBecho);
4775 return;
4778 smb_reverb = SVAL(req->vwv+0, 0);
4780 reply_outbuf(req, 1, req->buflen);
4782 /* copy any incoming data back out */
4783 if (req->buflen > 0) {
4784 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4787 if (smb_reverb > 100) {
4788 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4789 smb_reverb = 100;
4792 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4794 /* this makes sure we catch the request pcd */
4795 if (seq_num == smb_reverb) {
4796 cur_pcd = &req->pcd;
4797 } else {
4798 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4799 cur_pcd = &local_pcd;
4802 SSVAL(req->outbuf,smb_vwv0,seq_num);
4804 show_msg((char *)req->outbuf);
4805 if (!srv_send_smb(smbd_server_fd(),
4806 (char *)req->outbuf,
4807 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4808 cur_pcd))
4809 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4812 DEBUG(3,("echo %d times\n", smb_reverb));
4814 TALLOC_FREE(req->outbuf);
4816 END_PROFILE(SMBecho);
4817 return;
4820 /****************************************************************************
4821 Reply to a printopen.
4822 ****************************************************************************/
4824 void reply_printopen(struct smb_request *req)
4826 connection_struct *conn = req->conn;
4827 files_struct *fsp;
4828 SMB_STRUCT_STAT sbuf;
4829 NTSTATUS status;
4831 START_PROFILE(SMBsplopen);
4833 if (req->wct < 2) {
4834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4835 END_PROFILE(SMBsplopen);
4836 return;
4839 if (!CAN_PRINT(conn)) {
4840 reply_doserror(req, ERRDOS, ERRnoaccess);
4841 END_PROFILE(SMBsplopen);
4842 return;
4845 status = file_new(req, conn, &fsp);
4846 if(!NT_STATUS_IS_OK(status)) {
4847 reply_nterror(req, status);
4848 END_PROFILE(SMBsplopen);
4849 return;
4852 /* Open for exclusive use, write only. */
4853 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4855 if (!NT_STATUS_IS_OK(status)) {
4856 reply_nterror(req, status);
4857 END_PROFILE(SMBsplopen);
4858 return;
4861 reply_outbuf(req, 1, 0);
4862 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4864 DEBUG(3,("openprint fd=%d fnum=%d\n",
4865 fsp->fh->fd, fsp->fnum));
4867 END_PROFILE(SMBsplopen);
4868 return;
4871 /****************************************************************************
4872 Reply to a printclose.
4873 ****************************************************************************/
4875 void reply_printclose(struct smb_request *req)
4877 connection_struct *conn = req->conn;
4878 files_struct *fsp;
4879 NTSTATUS status;
4881 START_PROFILE(SMBsplclose);
4883 if (req->wct < 1) {
4884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4885 END_PROFILE(SMBsplclose);
4886 return;
4889 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4891 if (!check_fsp(conn, req, fsp)) {
4892 END_PROFILE(SMBsplclose);
4893 return;
4896 if (!CAN_PRINT(conn)) {
4897 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4898 END_PROFILE(SMBsplclose);
4899 return;
4902 DEBUG(3,("printclose fd=%d fnum=%d\n",
4903 fsp->fh->fd,fsp->fnum));
4905 status = close_file(req, fsp, NORMAL_CLOSE);
4907 if(!NT_STATUS_IS_OK(status)) {
4908 reply_nterror(req, status);
4909 END_PROFILE(SMBsplclose);
4910 return;
4913 reply_outbuf(req, 0, 0);
4915 END_PROFILE(SMBsplclose);
4916 return;
4919 /****************************************************************************
4920 Reply to a printqueue.
4921 ****************************************************************************/
4923 void reply_printqueue(struct smb_request *req)
4925 connection_struct *conn = req->conn;
4926 int max_count;
4927 int start_index;
4929 START_PROFILE(SMBsplretq);
4931 if (req->wct < 2) {
4932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4933 END_PROFILE(SMBsplretq);
4934 return;
4937 max_count = SVAL(req->vwv+0, 0);
4938 start_index = SVAL(req->vwv+1, 0);
4940 /* we used to allow the client to get the cnum wrong, but that
4941 is really quite gross and only worked when there was only
4942 one printer - I think we should now only accept it if they
4943 get it right (tridge) */
4944 if (!CAN_PRINT(conn)) {
4945 reply_doserror(req, ERRDOS, ERRnoaccess);
4946 END_PROFILE(SMBsplretq);
4947 return;
4950 reply_outbuf(req, 2, 3);
4951 SSVAL(req->outbuf,smb_vwv0,0);
4952 SSVAL(req->outbuf,smb_vwv1,0);
4953 SCVAL(smb_buf(req->outbuf),0,1);
4954 SSVAL(smb_buf(req->outbuf),1,0);
4956 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4957 start_index, max_count));
4960 print_queue_struct *queue = NULL;
4961 print_status_struct status;
4962 int count = print_queue_status(SNUM(conn), &queue, &status);
4963 int num_to_get = ABS(max_count);
4964 int first = (max_count>0?start_index:start_index+max_count+1);
4965 int i;
4967 if (first >= count)
4968 num_to_get = 0;
4969 else
4970 num_to_get = MIN(num_to_get,count-first);
4973 for (i=first;i<first+num_to_get;i++) {
4974 char blob[28];
4975 char *p = blob;
4977 srv_put_dos_date2(p,0,queue[i].time);
4978 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4979 SSVAL(p,5, queue[i].job);
4980 SIVAL(p,7,queue[i].size);
4981 SCVAL(p,11,0);
4982 srvstr_push(blob, req->flags2, p+12,
4983 queue[i].fs_user, 16, STR_ASCII);
4985 if (message_push_blob(
4986 &req->outbuf,
4987 data_blob_const(
4988 blob, sizeof(blob))) == -1) {
4989 reply_nterror(req, NT_STATUS_NO_MEMORY);
4990 END_PROFILE(SMBsplretq);
4991 return;
4995 if (count > 0) {
4996 SSVAL(req->outbuf,smb_vwv0,count);
4997 SSVAL(req->outbuf,smb_vwv1,
4998 (max_count>0?first+count:first-1));
4999 SCVAL(smb_buf(req->outbuf),0,1);
5000 SSVAL(smb_buf(req->outbuf),1,28*count);
5003 SAFE_FREE(queue);
5005 DEBUG(3,("%d entries returned in queue\n",count));
5008 END_PROFILE(SMBsplretq);
5009 return;
5012 /****************************************************************************
5013 Reply to a printwrite.
5014 ****************************************************************************/
5016 void reply_printwrite(struct smb_request *req)
5018 connection_struct *conn = req->conn;
5019 int numtowrite;
5020 const char *data;
5021 files_struct *fsp;
5023 START_PROFILE(SMBsplwr);
5025 if (req->wct < 1) {
5026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5027 END_PROFILE(SMBsplwr);
5028 return;
5031 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5033 if (!check_fsp(conn, req, fsp)) {
5034 END_PROFILE(SMBsplwr);
5035 return;
5038 if (!CAN_PRINT(conn)) {
5039 reply_doserror(req, ERRDOS, ERRnoaccess);
5040 END_PROFILE(SMBsplwr);
5041 return;
5044 if (!CHECK_WRITE(fsp)) {
5045 reply_doserror(req, ERRDOS, ERRbadaccess);
5046 END_PROFILE(SMBsplwr);
5047 return;
5050 numtowrite = SVAL(req->buf, 1);
5052 if (req->buflen < numtowrite + 3) {
5053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5054 END_PROFILE(SMBsplwr);
5055 return;
5058 data = (const char *)req->buf + 3;
5060 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5061 reply_unixerror(req, ERRHRD, ERRdiskfull);
5062 END_PROFILE(SMBsplwr);
5063 return;
5066 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5068 END_PROFILE(SMBsplwr);
5069 return;
5072 /****************************************************************************
5073 Reply to a mkdir.
5074 ****************************************************************************/
5076 void reply_mkdir(struct smb_request *req)
5078 connection_struct *conn = req->conn;
5079 char *directory = NULL;
5080 NTSTATUS status;
5081 SMB_STRUCT_STAT sbuf;
5082 TALLOC_CTX *ctx = talloc_tos();
5084 START_PROFILE(SMBmkdir);
5086 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5087 STR_TERMINATE, &status);
5088 if (!NT_STATUS_IS_OK(status)) {
5089 reply_nterror(req, status);
5090 END_PROFILE(SMBmkdir);
5091 return;
5094 status = resolve_dfspath(ctx, conn,
5095 req->flags2 & FLAGS2_DFS_PATHNAMES,
5096 directory,
5097 &directory);
5098 if (!NT_STATUS_IS_OK(status)) {
5099 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5100 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5101 ERRSRV, ERRbadpath);
5102 END_PROFILE(SMBmkdir);
5103 return;
5105 reply_nterror(req, status);
5106 END_PROFILE(SMBmkdir);
5107 return;
5110 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
5111 if (!NT_STATUS_IS_OK(status)) {
5112 reply_nterror(req, status);
5113 END_PROFILE(SMBmkdir);
5114 return;
5117 status = check_name(conn, directory);
5118 if (!NT_STATUS_IS_OK(status)) {
5119 reply_nterror(req, status);
5120 END_PROFILE(SMBmkdir);
5121 return;
5124 status = create_directory(conn, req, directory);
5126 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5128 if (!NT_STATUS_IS_OK(status)) {
5130 if (!use_nt_status()
5131 && NT_STATUS_EQUAL(status,
5132 NT_STATUS_OBJECT_NAME_COLLISION)) {
5134 * Yes, in the DOS error code case we get a
5135 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5136 * samba4 torture test.
5138 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5141 reply_nterror(req, status);
5142 END_PROFILE(SMBmkdir);
5143 return;
5146 reply_outbuf(req, 0, 0);
5148 DEBUG( 3, ( "mkdir %s\n", directory ) );
5150 END_PROFILE(SMBmkdir);
5151 return;
5154 /****************************************************************************
5155 Static function used by reply_rmdir to delete an entire directory
5156 tree recursively. Return True on ok, False on fail.
5157 ****************************************************************************/
5159 static bool recursive_rmdir(TALLOC_CTX *ctx,
5160 connection_struct *conn,
5161 char *directory)
5163 const char *dname = NULL;
5164 bool ret = True;
5165 long offset = 0;
5166 SMB_STRUCT_STAT st;
5167 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5168 NULL, 0);
5170 if(dir_hnd == NULL)
5171 return False;
5173 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5174 char *fullname = NULL;
5176 if (ISDOT(dname) || ISDOTDOT(dname)) {
5177 continue;
5180 if (!is_visible_file(conn, directory, dname, &st, False)) {
5181 continue;
5184 /* Construct the full name. */
5185 fullname = talloc_asprintf(ctx,
5186 "%s/%s",
5187 directory,
5188 dname);
5189 if (!fullname) {
5190 errno = ENOMEM;
5191 ret = False;
5192 break;
5195 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5196 ret = False;
5197 break;
5200 if(st.st_mode & S_IFDIR) {
5201 if(!recursive_rmdir(ctx, conn, fullname)) {
5202 ret = False;
5203 break;
5205 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5206 ret = False;
5207 break;
5209 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5210 ret = False;
5211 break;
5213 TALLOC_FREE(fullname);
5215 TALLOC_FREE(dir_hnd);
5216 return ret;
5219 /****************************************************************************
5220 The internals of the rmdir code - called elsewhere.
5221 ****************************************************************************/
5223 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5224 connection_struct *conn,
5225 const char *directory)
5227 int ret;
5228 SMB_STRUCT_STAT st;
5230 /* Might be a symlink. */
5231 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5232 return map_nt_error_from_unix(errno);
5235 if (S_ISLNK(st.st_mode)) {
5236 /* Is what it points to a directory ? */
5237 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5238 return map_nt_error_from_unix(errno);
5240 if (!(S_ISDIR(st.st_mode))) {
5241 return NT_STATUS_NOT_A_DIRECTORY;
5243 ret = SMB_VFS_UNLINK(conn,directory);
5244 } else {
5245 ret = SMB_VFS_RMDIR(conn,directory);
5247 if (ret == 0) {
5248 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5249 FILE_NOTIFY_CHANGE_DIR_NAME,
5250 directory);
5251 return NT_STATUS_OK;
5254 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5256 * Check to see if the only thing in this directory are
5257 * vetoed files/directories. If so then delete them and
5258 * retry. If we fail to delete any of them (and we *don't*
5259 * do a recursive delete) then fail the rmdir.
5261 const char *dname;
5262 long dirpos = 0;
5263 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5264 directory, NULL, 0);
5266 if(dir_hnd == NULL) {
5267 errno = ENOTEMPTY;
5268 goto err;
5271 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5272 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5273 continue;
5274 if (!is_visible_file(conn, directory, dname, &st, False))
5275 continue;
5276 if(!IS_VETO_PATH(conn, dname)) {
5277 TALLOC_FREE(dir_hnd);
5278 errno = ENOTEMPTY;
5279 goto err;
5283 /* We only have veto files/directories.
5284 * Are we allowed to delete them ? */
5286 if(!lp_recursive_veto_delete(SNUM(conn))) {
5287 TALLOC_FREE(dir_hnd);
5288 errno = ENOTEMPTY;
5289 goto err;
5292 /* Do a recursive delete. */
5293 RewindDir(dir_hnd,&dirpos);
5294 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5295 char *fullname = NULL;
5297 if (ISDOT(dname) || ISDOTDOT(dname)) {
5298 continue;
5300 if (!is_visible_file(conn, directory, dname, &st, False)) {
5301 continue;
5304 fullname = talloc_asprintf(ctx,
5305 "%s/%s",
5306 directory,
5307 dname);
5309 if(!fullname) {
5310 errno = ENOMEM;
5311 break;
5314 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5315 break;
5317 if(st.st_mode & S_IFDIR) {
5318 if(!recursive_rmdir(ctx, conn, fullname)) {
5319 break;
5321 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5322 break;
5324 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5325 break;
5327 TALLOC_FREE(fullname);
5329 TALLOC_FREE(dir_hnd);
5330 /* Retry the rmdir */
5331 ret = SMB_VFS_RMDIR(conn,directory);
5334 err:
5336 if (ret != 0) {
5337 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5338 "%s\n", directory,strerror(errno)));
5339 return map_nt_error_from_unix(errno);
5342 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5343 FILE_NOTIFY_CHANGE_DIR_NAME,
5344 directory);
5346 return NT_STATUS_OK;
5349 /****************************************************************************
5350 Reply to a rmdir.
5351 ****************************************************************************/
5353 void reply_rmdir(struct smb_request *req)
5355 connection_struct *conn = req->conn;
5356 char *directory = NULL;
5357 SMB_STRUCT_STAT sbuf;
5358 NTSTATUS status;
5359 TALLOC_CTX *ctx = talloc_tos();
5361 START_PROFILE(SMBrmdir);
5363 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5364 STR_TERMINATE, &status);
5365 if (!NT_STATUS_IS_OK(status)) {
5366 reply_nterror(req, status);
5367 END_PROFILE(SMBrmdir);
5368 return;
5371 status = resolve_dfspath(ctx, conn,
5372 req->flags2 & FLAGS2_DFS_PATHNAMES,
5373 directory,
5374 &directory);
5375 if (!NT_STATUS_IS_OK(status)) {
5376 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5377 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5378 ERRSRV, ERRbadpath);
5379 END_PROFILE(SMBrmdir);
5380 return;
5382 reply_nterror(req, status);
5383 END_PROFILE(SMBrmdir);
5384 return;
5387 status = unix_convert(ctx, conn, directory, False, &directory,
5388 NULL, &sbuf);
5389 if (!NT_STATUS_IS_OK(status)) {
5390 reply_nterror(req, status);
5391 END_PROFILE(SMBrmdir);
5392 return;
5395 status = check_name(conn, directory);
5396 if (!NT_STATUS_IS_OK(status)) {
5397 reply_nterror(req, status);
5398 END_PROFILE(SMBrmdir);
5399 return;
5402 dptr_closepath(directory, req->smbpid);
5403 status = rmdir_internals(ctx, conn, directory);
5404 if (!NT_STATUS_IS_OK(status)) {
5405 reply_nterror(req, status);
5406 END_PROFILE(SMBrmdir);
5407 return;
5410 reply_outbuf(req, 0, 0);
5412 DEBUG( 3, ( "rmdir %s\n", directory ) );
5414 END_PROFILE(SMBrmdir);
5415 return;
5418 /*******************************************************************
5419 Resolve wildcards in a filename rename.
5420 ********************************************************************/
5422 static bool resolve_wildcards(TALLOC_CTX *ctx,
5423 const char *name1,
5424 const char *name2,
5425 char **pp_newname)
5427 char *name2_copy = NULL;
5428 char *root1 = NULL;
5429 char *root2 = NULL;
5430 char *ext1 = NULL;
5431 char *ext2 = NULL;
5432 char *p,*p2, *pname1, *pname2;
5434 name2_copy = talloc_strdup(ctx, name2);
5435 if (!name2_copy) {
5436 return False;
5439 pname1 = strrchr_m(name1,'/');
5440 pname2 = strrchr_m(name2_copy,'/');
5442 if (!pname1 || !pname2) {
5443 return False;
5446 /* Truncate the copy of name2 at the last '/' */
5447 *pname2 = '\0';
5449 /* Now go past the '/' */
5450 pname1++;
5451 pname2++;
5453 root1 = talloc_strdup(ctx, pname1);
5454 root2 = talloc_strdup(ctx, pname2);
5456 if (!root1 || !root2) {
5457 return False;
5460 p = strrchr_m(root1,'.');
5461 if (p) {
5462 *p = 0;
5463 ext1 = talloc_strdup(ctx, p+1);
5464 } else {
5465 ext1 = talloc_strdup(ctx, "");
5467 p = strrchr_m(root2,'.');
5468 if (p) {
5469 *p = 0;
5470 ext2 = talloc_strdup(ctx, p+1);
5471 } else {
5472 ext2 = talloc_strdup(ctx, "");
5475 if (!ext1 || !ext2) {
5476 return False;
5479 p = root1;
5480 p2 = root2;
5481 while (*p2) {
5482 if (*p2 == '?') {
5483 /* Hmmm. Should this be mb-aware ? */
5484 *p2 = *p;
5485 p2++;
5486 } else if (*p2 == '*') {
5487 *p2 = '\0';
5488 root2 = talloc_asprintf(ctx, "%s%s",
5489 root2,
5491 if (!root2) {
5492 return False;
5494 break;
5495 } else {
5496 p2++;
5498 if (*p) {
5499 p++;
5503 p = ext1;
5504 p2 = ext2;
5505 while (*p2) {
5506 if (*p2 == '?') {
5507 /* Hmmm. Should this be mb-aware ? */
5508 *p2 = *p;
5509 p2++;
5510 } else if (*p2 == '*') {
5511 *p2 = '\0';
5512 ext2 = talloc_asprintf(ctx, "%s%s",
5513 ext2,
5515 if (!ext2) {
5516 return False;
5518 break;
5519 } else {
5520 p2++;
5522 if (*p) {
5523 p++;
5527 if (*ext2) {
5528 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5529 name2_copy,
5530 root2,
5531 ext2);
5532 } else {
5533 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5534 name2_copy,
5535 root2);
5538 if (!*pp_newname) {
5539 return False;
5542 return True;
5545 /****************************************************************************
5546 Ensure open files have their names updated. Updated to notify other smbd's
5547 asynchronously.
5548 ****************************************************************************/
5550 static void rename_open_files(connection_struct *conn,
5551 struct share_mode_lock *lck,
5552 const char *newname)
5554 files_struct *fsp;
5555 bool did_rename = False;
5557 for(fsp = file_find_di_first(lck->id); fsp;
5558 fsp = file_find_di_next(fsp)) {
5559 /* fsp_name is a relative path under the fsp. To change this for other
5560 sharepaths we need to manipulate relative paths. */
5561 /* TODO - create the absolute path and manipulate the newname
5562 relative to the sharepath. */
5563 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5564 continue;
5566 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5567 fsp->fnum, file_id_string_tos(&fsp->file_id),
5568 fsp->fsp_name, newname ));
5569 string_set(&fsp->fsp_name, newname);
5570 did_rename = True;
5573 if (!did_rename) {
5574 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5575 file_id_string_tos(&lck->id), newname ));
5578 /* Send messages to all smbd's (not ourself) that the name has changed. */
5579 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5580 newname);
5583 /****************************************************************************
5584 We need to check if the source path is a parent directory of the destination
5585 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5586 refuse the rename with a sharing violation. Under UNIX the above call can
5587 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5588 probably need to check that the client is a Windows one before disallowing
5589 this as a UNIX client (one with UNIX extensions) can know the source is a
5590 symlink and make this decision intelligently. Found by an excellent bug
5591 report from <AndyLiebman@aol.com>.
5592 ****************************************************************************/
5594 static bool rename_path_prefix_equal(const char *src, const char *dest)
5596 const char *psrc = src;
5597 const char *pdst = dest;
5598 size_t slen;
5600 if (psrc[0] == '.' && psrc[1] == '/') {
5601 psrc += 2;
5603 if (pdst[0] == '.' && pdst[1] == '/') {
5604 pdst += 2;
5606 if ((slen = strlen(psrc)) > strlen(pdst)) {
5607 return False;
5609 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5613 * Do the notify calls from a rename
5616 static void notify_rename(connection_struct *conn, bool is_dir,
5617 const char *oldpath, const char *newpath)
5619 char *olddir, *newdir;
5620 const char *oldname, *newname;
5621 uint32 mask;
5623 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5624 : FILE_NOTIFY_CHANGE_FILE_NAME;
5626 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5627 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5628 TALLOC_FREE(olddir);
5629 return;
5632 if (strcmp(olddir, newdir) == 0) {
5633 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5634 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5636 else {
5637 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5638 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5640 TALLOC_FREE(olddir);
5641 TALLOC_FREE(newdir);
5643 /* this is a strange one. w2k3 gives an additional event for
5644 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5645 files, but not directories */
5646 if (!is_dir) {
5647 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5648 FILE_NOTIFY_CHANGE_ATTRIBUTES
5649 |FILE_NOTIFY_CHANGE_CREATION,
5650 newpath);
5654 /****************************************************************************
5655 Rename an open file - given an fsp.
5656 ****************************************************************************/
5658 NTSTATUS rename_internals_fsp(connection_struct *conn,
5659 files_struct *fsp,
5660 char *newname,
5661 const char *newname_last_component,
5662 uint32 attrs,
5663 bool replace_if_exists)
5665 TALLOC_CTX *ctx = talloc_tos();
5666 SMB_STRUCT_STAT sbuf, sbuf1;
5667 NTSTATUS status = NT_STATUS_OK;
5668 struct share_mode_lock *lck = NULL;
5669 bool dst_exists, old_is_stream, new_is_stream;
5671 ZERO_STRUCT(sbuf);
5673 status = check_name(conn, newname);
5674 if (!NT_STATUS_IS_OK(status)) {
5675 return status;
5678 /* Ensure newname contains a '/' */
5679 if(strrchr_m(newname,'/') == 0) {
5680 newname = talloc_asprintf(ctx,
5681 "./%s",
5682 newname);
5683 if (!newname) {
5684 return NT_STATUS_NO_MEMORY;
5689 * Check for special case with case preserving and not
5690 * case sensitive. If the old last component differs from the original
5691 * last component only by case, then we should allow
5692 * the rename (user is trying to change the case of the
5693 * filename).
5696 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5697 strequal(newname, fsp->fsp_name)) {
5698 char *p;
5699 char *newname_modified_last_component = NULL;
5702 * Get the last component of the modified name.
5703 * Note that we guarantee that newname contains a '/'
5704 * character above.
5706 p = strrchr_m(newname,'/');
5707 newname_modified_last_component = talloc_strdup(ctx,
5708 p+1);
5709 if (!newname_modified_last_component) {
5710 return NT_STATUS_NO_MEMORY;
5713 if(strcsequal(newname_modified_last_component,
5714 newname_last_component) == False) {
5716 * Replace the modified last component with
5717 * the original.
5719 *p = '\0'; /* Truncate at the '/' */
5720 newname = talloc_asprintf(ctx,
5721 "%s/%s",
5722 newname,
5723 newname_last_component);
5728 * If the src and dest names are identical - including case,
5729 * don't do the rename, just return success.
5732 if (strcsequal(fsp->fsp_name, newname)) {
5733 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5734 newname));
5735 return NT_STATUS_OK;
5738 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5739 new_is_stream = is_ntfs_stream_name(newname);
5741 /* Return the correct error code if both names aren't streams. */
5742 if (!old_is_stream && new_is_stream) {
5743 return NT_STATUS_OBJECT_NAME_INVALID;
5746 if (old_is_stream && !new_is_stream) {
5747 return NT_STATUS_INVALID_PARAMETER;
5751 * Have vfs_object_exist also fill sbuf1
5753 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5755 if(!replace_if_exists && dst_exists) {
5756 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5757 fsp->fsp_name,newname));
5758 return NT_STATUS_OBJECT_NAME_COLLISION;
5761 if (dst_exists) {
5762 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5763 files_struct *dst_fsp = file_find_di_first(fileid);
5764 /* The file can be open when renaming a stream */
5765 if (dst_fsp && !new_is_stream) {
5766 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5767 return NT_STATUS_ACCESS_DENIED;
5771 /* Ensure we have a valid stat struct for the source. */
5772 if (fsp->fh->fd != -1) {
5773 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5774 return map_nt_error_from_unix(errno);
5776 } else {
5777 int ret = -1;
5778 if (fsp->posix_open) {
5779 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5780 } else {
5781 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5783 if (ret == -1) {
5784 return map_nt_error_from_unix(errno);
5788 status = can_rename(conn, fsp, attrs, &sbuf);
5790 if (!NT_STATUS_IS_OK(status)) {
5791 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5792 nt_errstr(status), fsp->fsp_name,newname));
5793 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5794 status = NT_STATUS_ACCESS_DENIED;
5795 return status;
5798 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5799 return NT_STATUS_ACCESS_DENIED;
5802 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5803 NULL);
5806 * We have the file open ourselves, so not being able to get the
5807 * corresponding share mode lock is a fatal error.
5810 SMB_ASSERT(lck != NULL);
5812 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5813 uint32 create_options = fsp->fh->private_options;
5815 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5816 fsp->fsp_name,newname));
5818 if (lp_map_archive(SNUM(conn)) ||
5819 lp_store_dos_attributes(SNUM(conn))) {
5820 /* We must set the archive bit on the newly
5821 renamed file. */
5822 if (SMB_VFS_STAT(conn,newname,&sbuf1) == 0) {
5823 uint32_t old_dosmode = dos_mode(conn,
5824 newname,
5825 &sbuf1);
5826 file_set_dosmode(conn,
5827 newname,
5828 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
5829 &sbuf1,
5830 NULL,
5831 true);
5835 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5837 rename_open_files(conn, lck, newname);
5840 * A rename acts as a new file create w.r.t. allowing an initial delete
5841 * on close, probably because in Windows there is a new handle to the
5842 * new file. If initial delete on close was requested but not
5843 * originally set, we need to set it here. This is probably not 100% correct,
5844 * but will work for the CIFSFS client which in non-posix mode
5845 * depends on these semantics. JRA.
5848 if (create_options & FILE_DELETE_ON_CLOSE) {
5849 status = can_set_delete_on_close(fsp, True, 0);
5851 if (NT_STATUS_IS_OK(status)) {
5852 /* Note that here we set the *inital* delete on close flag,
5853 * not the regular one. The magic gets handled in close. */
5854 fsp->initial_delete_on_close = True;
5857 TALLOC_FREE(lck);
5858 return NT_STATUS_OK;
5861 TALLOC_FREE(lck);
5863 if (errno == ENOTDIR || errno == EISDIR) {
5864 status = NT_STATUS_OBJECT_NAME_COLLISION;
5865 } else {
5866 status = map_nt_error_from_unix(errno);
5869 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5870 nt_errstr(status), fsp->fsp_name,newname));
5872 return status;
5875 /****************************************************************************
5876 The guts of the rename command, split out so it may be called by the NT SMB
5877 code.
5878 ****************************************************************************/
5880 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5881 connection_struct *conn,
5882 struct smb_request *req,
5883 const char *name_in,
5884 const char *newname_in,
5885 uint32 attrs,
5886 bool replace_if_exists,
5887 bool src_has_wild,
5888 bool dest_has_wild,
5889 uint32_t access_mask)
5891 char *directory = NULL;
5892 char *mask = NULL;
5893 char *last_component_src = NULL;
5894 char *last_component_dest = NULL;
5895 char *name = NULL;
5896 char *newname = NULL;
5897 char *p;
5898 int count=0;
5899 NTSTATUS status = NT_STATUS_OK;
5900 SMB_STRUCT_STAT sbuf1, sbuf2;
5901 struct smb_Dir *dir_hnd = NULL;
5902 const char *dname;
5903 long offset = 0;
5904 int create_options = 0;
5905 bool posix_pathnames = lp_posix_pathnames();
5907 ZERO_STRUCT(sbuf1);
5908 ZERO_STRUCT(sbuf2);
5910 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5911 &last_component_src, &sbuf1);
5912 if (!NT_STATUS_IS_OK(status)) {
5913 return status;
5916 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5917 &last_component_dest, &sbuf2);
5918 if (!NT_STATUS_IS_OK(status)) {
5919 return status;
5923 * Split the old name into directory and last component
5924 * strings. Note that unix_convert may have stripped off a
5925 * leading ./ from both name and newname if the rename is
5926 * at the root of the share. We need to make sure either both
5927 * name and newname contain a / character or neither of them do
5928 * as this is checked in resolve_wildcards().
5931 p = strrchr_m(name,'/');
5932 if (!p) {
5933 directory = talloc_strdup(ctx, ".");
5934 if (!directory) {
5935 return NT_STATUS_NO_MEMORY;
5937 mask = name;
5938 } else {
5939 *p = 0;
5940 directory = talloc_strdup(ctx, name);
5941 if (!directory) {
5942 return NT_STATUS_NO_MEMORY;
5944 mask = p+1;
5945 *p = '/'; /* Replace needed for exceptional test below. */
5949 * We should only check the mangled cache
5950 * here if unix_convert failed. This means
5951 * that the path in 'mask' doesn't exist
5952 * on the file system and so we need to look
5953 * for a possible mangle. This patch from
5954 * Tine Smukavec <valentin.smukavec@hermes.si>.
5957 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5958 char *new_mask = NULL;
5959 mangle_lookup_name_from_8_3(ctx,
5960 mask,
5961 &new_mask,
5962 conn->params );
5963 if (new_mask) {
5964 mask = new_mask;
5968 if (!src_has_wild) {
5969 files_struct *fsp;
5972 * No wildcards - just process the one file.
5974 /* Add a terminating '/' to the directory name. */
5975 directory = talloc_asprintf_append(directory,
5976 "/%s",
5977 mask);
5978 if (!directory) {
5979 return NT_STATUS_NO_MEMORY;
5982 /* Ensure newname contains a '/' also */
5983 if(strrchr_m(newname,'/') == 0) {
5984 newname = talloc_asprintf(ctx,
5985 "./%s",
5986 newname);
5987 if (!newname) {
5988 return NT_STATUS_NO_MEMORY;
5992 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5993 "case_preserve = %d, short case preserve = %d, "
5994 "directory = %s, newname = %s, "
5995 "last_component_dest = %s\n",
5996 conn->case_sensitive, conn->case_preserve,
5997 conn->short_case_preserve, directory,
5998 newname, last_component_dest));
6000 /* The dest name still may have wildcards. */
6001 if (dest_has_wild) {
6002 char *mod_newname = NULL;
6003 if (!resolve_wildcards(ctx,
6004 directory,newname,&mod_newname)) {
6005 DEBUG(6, ("rename_internals: resolve_wildcards "
6006 "%s %s failed\n",
6007 directory,
6008 newname));
6009 return NT_STATUS_NO_MEMORY;
6011 newname = mod_newname;
6014 ZERO_STRUCT(sbuf1);
6015 if (posix_pathnames) {
6016 SMB_VFS_LSTAT(conn, directory, &sbuf1);
6017 } else {
6018 SMB_VFS_STAT(conn, directory, &sbuf1);
6021 if (S_ISDIR(sbuf1.st_mode)) {
6022 create_options |= FILE_DIRECTORY_FILE;
6025 status = SMB_VFS_CREATE_FILE(
6026 conn, /* conn */
6027 req, /* req */
6028 0, /* root_dir_fid */
6029 directory, /* fname */
6030 0, /* create_file_flags */
6031 access_mask, /* access_mask */
6032 (FILE_SHARE_READ | /* share_access */
6033 FILE_SHARE_WRITE),
6034 FILE_OPEN, /* create_disposition*/
6035 create_options, /* create_options */
6036 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6037 0, /* oplock_request */
6038 0, /* allocation_size */
6039 NULL, /* sd */
6040 NULL, /* ea_list */
6041 &fsp, /* result */
6042 NULL, /* pinfo */
6043 &sbuf1); /* psbuf */
6045 if (!NT_STATUS_IS_OK(status)) {
6046 DEBUG(3, ("Could not open rename source %s: %s\n",
6047 directory, nt_errstr(status)));
6048 return status;
6051 status = rename_internals_fsp(conn, fsp, newname,
6052 last_component_dest,
6053 attrs, replace_if_exists);
6055 close_file(req, fsp, NORMAL_CLOSE);
6057 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6058 nt_errstr(status), directory,newname));
6060 return status;
6064 * Wildcards - process each file that matches.
6066 if (strequal(mask,"????????.???")) {
6067 mask[0] = '*';
6068 mask[1] = '\0';
6071 status = check_name(conn, directory);
6072 if (!NT_STATUS_IS_OK(status)) {
6073 return status;
6076 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6077 if (dir_hnd == NULL) {
6078 return map_nt_error_from_unix(errno);
6081 status = NT_STATUS_NO_SUCH_FILE;
6083 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6084 * - gentest fix. JRA
6087 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6088 files_struct *fsp = NULL;
6089 char *fname = NULL;
6090 char *destname = NULL;
6091 bool sysdir_entry = False;
6093 /* Quick check for "." and ".." */
6094 if (ISDOT(dname) || ISDOTDOT(dname)) {
6095 if (attrs & aDIR) {
6096 sysdir_entry = True;
6097 } else {
6098 continue;
6102 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6103 continue;
6106 if(!mask_match(dname, mask, conn->case_sensitive)) {
6107 continue;
6110 if (sysdir_entry) {
6111 status = NT_STATUS_OBJECT_NAME_INVALID;
6112 break;
6115 fname = talloc_asprintf(ctx,
6116 "%s/%s",
6117 directory,
6118 dname);
6119 if (!fname) {
6120 return NT_STATUS_NO_MEMORY;
6123 if (!resolve_wildcards(ctx,
6124 fname,newname,&destname)) {
6125 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6126 fname, destname));
6127 TALLOC_FREE(fname);
6128 continue;
6130 if (!destname) {
6131 return NT_STATUS_NO_MEMORY;
6134 ZERO_STRUCT(sbuf1);
6135 if (posix_pathnames) {
6136 SMB_VFS_LSTAT(conn, fname, &sbuf1);
6137 } else {
6138 SMB_VFS_STAT(conn, fname, &sbuf1);
6141 create_options = 0;
6143 if (S_ISDIR(sbuf1.st_mode)) {
6144 create_options |= FILE_DIRECTORY_FILE;
6147 status = SMB_VFS_CREATE_FILE(
6148 conn, /* conn */
6149 req, /* req */
6150 0, /* root_dir_fid */
6151 fname, /* fname */
6152 0, /* create_file_flags */
6153 access_mask, /* access_mask */
6154 (FILE_SHARE_READ | /* share_access */
6155 FILE_SHARE_WRITE),
6156 FILE_OPEN, /* create_disposition*/
6157 create_options, /* create_options */
6158 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6159 0, /* oplock_request */
6160 0, /* allocation_size */
6161 NULL, /* sd */
6162 NULL, /* ea_list */
6163 &fsp, /* result */
6164 NULL, /* pinfo */
6165 &sbuf1); /* psbuf */
6167 if (!NT_STATUS_IS_OK(status)) {
6168 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6169 "returned %s rename %s -> %s\n",
6170 nt_errstr(status), directory, newname));
6171 break;
6174 status = rename_internals_fsp(conn, fsp, destname, dname,
6175 attrs, replace_if_exists);
6177 close_file(req, fsp, NORMAL_CLOSE);
6179 if (!NT_STATUS_IS_OK(status)) {
6180 DEBUG(3, ("rename_internals_fsp returned %s for "
6181 "rename %s -> %s\n", nt_errstr(status),
6182 directory, newname));
6183 break;
6186 count++;
6188 DEBUG(3,("rename_internals: doing rename on %s -> "
6189 "%s\n",fname,destname));
6191 TALLOC_FREE(fname);
6192 TALLOC_FREE(destname);
6194 TALLOC_FREE(dir_hnd);
6196 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6197 status = map_nt_error_from_unix(errno);
6200 return status;
6203 /****************************************************************************
6204 Reply to a mv.
6205 ****************************************************************************/
6207 void reply_mv(struct smb_request *req)
6209 connection_struct *conn = req->conn;
6210 char *name = NULL;
6211 char *newname = NULL;
6212 const char *p;
6213 uint32 attrs;
6214 NTSTATUS status;
6215 bool src_has_wcard = False;
6216 bool dest_has_wcard = False;
6217 TALLOC_CTX *ctx = talloc_tos();
6219 START_PROFILE(SMBmv);
6221 if (req->wct < 1) {
6222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6223 END_PROFILE(SMBmv);
6224 return;
6227 attrs = SVAL(req->vwv+0, 0);
6229 p = (const char *)req->buf + 1;
6230 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6231 &status, &src_has_wcard);
6232 if (!NT_STATUS_IS_OK(status)) {
6233 reply_nterror(req, status);
6234 END_PROFILE(SMBmv);
6235 return;
6237 p++;
6238 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6239 &status, &dest_has_wcard);
6240 if (!NT_STATUS_IS_OK(status)) {
6241 reply_nterror(req, status);
6242 END_PROFILE(SMBmv);
6243 return;
6246 status = resolve_dfspath_wcard(ctx, conn,
6247 req->flags2 & FLAGS2_DFS_PATHNAMES,
6248 name,
6249 &name,
6250 &src_has_wcard);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6253 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6254 ERRSRV, ERRbadpath);
6255 END_PROFILE(SMBmv);
6256 return;
6258 reply_nterror(req, status);
6259 END_PROFILE(SMBmv);
6260 return;
6263 status = resolve_dfspath_wcard(ctx, conn,
6264 req->flags2 & FLAGS2_DFS_PATHNAMES,
6265 newname,
6266 &newname,
6267 &dest_has_wcard);
6268 if (!NT_STATUS_IS_OK(status)) {
6269 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6270 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6271 ERRSRV, ERRbadpath);
6272 END_PROFILE(SMBmv);
6273 return;
6275 reply_nterror(req, status);
6276 END_PROFILE(SMBmv);
6277 return;
6280 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6282 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6283 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6284 if (!NT_STATUS_IS_OK(status)) {
6285 if (open_was_deferred(req->mid)) {
6286 /* We have re-scheduled this call. */
6287 END_PROFILE(SMBmv);
6288 return;
6290 reply_nterror(req, status);
6291 END_PROFILE(SMBmv);
6292 return;
6295 reply_outbuf(req, 0, 0);
6297 END_PROFILE(SMBmv);
6298 return;
6301 /*******************************************************************
6302 Copy a file as part of a reply_copy.
6303 ******************************************************************/
6306 * TODO: check error codes on all callers
6309 NTSTATUS copy_file(TALLOC_CTX *ctx,
6310 connection_struct *conn,
6311 const char *src,
6312 const char *dest1,
6313 int ofun,
6314 int count,
6315 bool target_is_directory)
6317 SMB_STRUCT_STAT src_sbuf, sbuf2;
6318 SMB_OFF_T ret=-1;
6319 files_struct *fsp1,*fsp2;
6320 char *dest = NULL;
6321 uint32 dosattrs;
6322 uint32 new_create_disposition;
6323 NTSTATUS status;
6325 dest = talloc_strdup(ctx, dest1);
6326 if (!dest) {
6327 return NT_STATUS_NO_MEMORY;
6329 if (target_is_directory) {
6330 const char *p = strrchr_m(src,'/');
6331 if (p) {
6332 p++;
6333 } else {
6334 p = src;
6336 dest = talloc_asprintf_append(dest,
6337 "/%s",
6339 if (!dest) {
6340 return NT_STATUS_NO_MEMORY;
6344 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6345 TALLOC_FREE(dest);
6346 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6349 if (!target_is_directory && count) {
6350 new_create_disposition = FILE_OPEN;
6351 } else {
6352 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6353 NULL, NULL, &new_create_disposition, NULL)) {
6354 TALLOC_FREE(dest);
6355 return NT_STATUS_INVALID_PARAMETER;
6359 status = SMB_VFS_CREATE_FILE(
6360 conn, /* conn */
6361 NULL, /* req */
6362 0, /* root_dir_fid */
6363 src, /* fname */
6364 0, /* create_file_flags */
6365 FILE_GENERIC_READ, /* access_mask */
6366 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6367 FILE_OPEN, /* create_disposition*/
6368 0, /* create_options */
6369 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6370 INTERNAL_OPEN_ONLY, /* oplock_request */
6371 0, /* allocation_size */
6372 NULL, /* sd */
6373 NULL, /* ea_list */
6374 &fsp1, /* result */
6375 NULL, /* pinfo */
6376 &src_sbuf); /* psbuf */
6378 if (!NT_STATUS_IS_OK(status)) {
6379 TALLOC_FREE(dest);
6380 return status;
6383 dosattrs = dos_mode(conn, src, &src_sbuf);
6384 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6385 ZERO_STRUCTP(&sbuf2);
6388 status = SMB_VFS_CREATE_FILE(
6389 conn, /* conn */
6390 NULL, /* req */
6391 0, /* root_dir_fid */
6392 dest, /* fname */
6393 0, /* create_file_flags */
6394 FILE_GENERIC_WRITE, /* access_mask */
6395 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6396 new_create_disposition, /* create_disposition*/
6397 0, /* create_options */
6398 dosattrs, /* file_attributes */
6399 INTERNAL_OPEN_ONLY, /* oplock_request */
6400 0, /* allocation_size */
6401 NULL, /* sd */
6402 NULL, /* ea_list */
6403 &fsp2, /* result */
6404 NULL, /* pinfo */
6405 &sbuf2); /* psbuf */
6407 TALLOC_FREE(dest);
6409 if (!NT_STATUS_IS_OK(status)) {
6410 close_file(NULL, fsp1, ERROR_CLOSE);
6411 return status;
6414 if ((ofun&3) == 1) {
6415 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6416 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6418 * Stop the copy from occurring.
6420 ret = -1;
6421 src_sbuf.st_size = 0;
6425 if (src_sbuf.st_size) {
6426 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6429 close_file(NULL, fsp1, NORMAL_CLOSE);
6431 /* Ensure the modtime is set correctly on the destination file. */
6432 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6435 * As we are opening fsp1 read-only we only expect
6436 * an error on close on fsp2 if we are out of space.
6437 * Thus we don't look at the error return from the
6438 * close of fsp1.
6440 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6442 if (!NT_STATUS_IS_OK(status)) {
6443 return status;
6446 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6447 return NT_STATUS_DISK_FULL;
6450 return NT_STATUS_OK;
6453 /****************************************************************************
6454 Reply to a file copy.
6455 ****************************************************************************/
6457 void reply_copy(struct smb_request *req)
6459 connection_struct *conn = req->conn;
6460 char *name = NULL;
6461 char *newname = NULL;
6462 char *directory = NULL;
6463 const char *mask = NULL;
6464 const char mask_star[] = "*";
6465 const char *p;
6466 int count=0;
6467 int error = ERRnoaccess;
6468 int err = 0;
6469 int tid2;
6470 int ofun;
6471 int flags;
6472 bool target_is_directory=False;
6473 bool source_has_wild = False;
6474 bool dest_has_wild = False;
6475 SMB_STRUCT_STAT sbuf1, sbuf2;
6476 NTSTATUS status;
6477 TALLOC_CTX *ctx = talloc_tos();
6479 START_PROFILE(SMBcopy);
6481 if (req->wct < 3) {
6482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6483 END_PROFILE(SMBcopy);
6484 return;
6487 tid2 = SVAL(req->vwv+0, 0);
6488 ofun = SVAL(req->vwv+1, 0);
6489 flags = SVAL(req->vwv+2, 0);
6491 p = (const char *)req->buf;
6492 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6493 &status, &source_has_wild);
6494 if (!NT_STATUS_IS_OK(status)) {
6495 reply_nterror(req, status);
6496 END_PROFILE(SMBcopy);
6497 return;
6499 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6500 &status, &dest_has_wild);
6501 if (!NT_STATUS_IS_OK(status)) {
6502 reply_nterror(req, status);
6503 END_PROFILE(SMBcopy);
6504 return;
6507 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6509 if (tid2 != conn->cnum) {
6510 /* can't currently handle inter share copies XXXX */
6511 DEBUG(3,("Rejecting inter-share copy\n"));
6512 reply_doserror(req, ERRSRV, ERRinvdevice);
6513 END_PROFILE(SMBcopy);
6514 return;
6517 status = resolve_dfspath_wcard(ctx, conn,
6518 req->flags2 & FLAGS2_DFS_PATHNAMES,
6519 name,
6520 &name,
6521 &source_has_wild);
6522 if (!NT_STATUS_IS_OK(status)) {
6523 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6524 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6525 ERRSRV, ERRbadpath);
6526 END_PROFILE(SMBcopy);
6527 return;
6529 reply_nterror(req, status);
6530 END_PROFILE(SMBcopy);
6531 return;
6534 status = resolve_dfspath_wcard(ctx, conn,
6535 req->flags2 & FLAGS2_DFS_PATHNAMES,
6536 newname,
6537 &newname,
6538 &dest_has_wild);
6539 if (!NT_STATUS_IS_OK(status)) {
6540 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6541 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6542 ERRSRV, ERRbadpath);
6543 END_PROFILE(SMBcopy);
6544 return;
6546 reply_nterror(req, status);
6547 END_PROFILE(SMBcopy);
6548 return;
6551 status = unix_convert(ctx, conn, name, source_has_wild,
6552 &name, NULL, &sbuf1);
6553 if (!NT_STATUS_IS_OK(status)) {
6554 reply_nterror(req, status);
6555 END_PROFILE(SMBcopy);
6556 return;
6559 status = unix_convert(ctx, conn, newname, dest_has_wild,
6560 &newname, NULL, &sbuf2);
6561 if (!NT_STATUS_IS_OK(status)) {
6562 reply_nterror(req, status);
6563 END_PROFILE(SMBcopy);
6564 return;
6567 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6569 if ((flags&1) && target_is_directory) {
6570 reply_doserror(req, ERRDOS, ERRbadfile);
6571 END_PROFILE(SMBcopy);
6572 return;
6575 if ((flags&2) && !target_is_directory) {
6576 reply_doserror(req, ERRDOS, ERRbadpath);
6577 END_PROFILE(SMBcopy);
6578 return;
6581 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6582 /* wants a tree copy! XXXX */
6583 DEBUG(3,("Rejecting tree copy\n"));
6584 reply_doserror(req, ERRSRV, ERRerror);
6585 END_PROFILE(SMBcopy);
6586 return;
6589 p = strrchr_m(name,'/');
6590 if (p != NULL) {
6591 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6592 mask = p+1;
6593 } else {
6594 directory = talloc_strdup(ctx, "./");
6595 mask = name;
6598 if (!directory) {
6599 reply_nterror(req, NT_STATUS_NO_MEMORY);
6600 END_PROFILE(SMBcopy);
6601 return;
6605 * We should only check the mangled cache
6606 * here if unix_convert failed. This means
6607 * that the path in 'mask' doesn't exist
6608 * on the file system and so we need to look
6609 * for a possible mangle. This patch from
6610 * Tine Smukavec <valentin.smukavec@hermes.si>.
6613 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6614 char *new_mask = NULL;
6615 mangle_lookup_name_from_8_3(ctx,
6616 mask,
6617 &new_mask,
6618 conn->params );
6619 if (new_mask) {
6620 mask = new_mask;
6624 if (!source_has_wild) {
6625 directory = talloc_asprintf_append(directory,
6626 "/%s",
6627 mask);
6628 if (dest_has_wild) {
6629 char *mod_newname = NULL;
6630 if (!resolve_wildcards(ctx,
6631 directory,newname,&mod_newname)) {
6632 reply_nterror(req, NT_STATUS_NO_MEMORY);
6633 END_PROFILE(SMBcopy);
6634 return;
6636 newname = mod_newname;
6639 status = check_name(conn, directory);
6640 if (!NT_STATUS_IS_OK(status)) {
6641 reply_nterror(req, status);
6642 END_PROFILE(SMBcopy);
6643 return;
6646 status = check_name(conn, newname);
6647 if (!NT_STATUS_IS_OK(status)) {
6648 reply_nterror(req, status);
6649 END_PROFILE(SMBcopy);
6650 return;
6653 status = copy_file(ctx,conn,directory,newname,ofun,
6654 count,target_is_directory);
6656 if(!NT_STATUS_IS_OK(status)) {
6657 reply_nterror(req, status);
6658 END_PROFILE(SMBcopy);
6659 return;
6660 } else {
6661 count++;
6663 } else {
6664 struct smb_Dir *dir_hnd = NULL;
6665 const char *dname = NULL;
6666 long offset = 0;
6668 if (strequal(mask,"????????.???")) {
6669 mask = mask_star;
6672 status = check_name(conn, directory);
6673 if (!NT_STATUS_IS_OK(status)) {
6674 reply_nterror(req, status);
6675 END_PROFILE(SMBcopy);
6676 return;
6679 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6680 if (dir_hnd == NULL) {
6681 status = map_nt_error_from_unix(errno);
6682 reply_nterror(req, status);
6683 END_PROFILE(SMBcopy);
6684 return;
6687 error = ERRbadfile;
6689 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6690 char *destname = NULL;
6691 char *fname = NULL;
6693 if (ISDOT(dname) || ISDOTDOT(dname)) {
6694 continue;
6697 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6698 continue;
6701 if(!mask_match(dname, mask, conn->case_sensitive)) {
6702 continue;
6705 error = ERRnoaccess;
6706 fname = talloc_asprintf(ctx,
6707 "%s/%s",
6708 directory,
6709 dname);
6710 if (!fname) {
6711 TALLOC_FREE(dir_hnd);
6712 reply_nterror(req, NT_STATUS_NO_MEMORY);
6713 END_PROFILE(SMBcopy);
6714 return;
6717 if (!resolve_wildcards(ctx,
6718 fname,newname,&destname)) {
6719 continue;
6721 if (!destname) {
6722 TALLOC_FREE(dir_hnd);
6723 reply_nterror(req, NT_STATUS_NO_MEMORY);
6724 END_PROFILE(SMBcopy);
6725 return;
6728 status = check_name(conn, fname);
6729 if (!NT_STATUS_IS_OK(status)) {
6730 TALLOC_FREE(dir_hnd);
6731 reply_nterror(req, status);
6732 END_PROFILE(SMBcopy);
6733 return;
6736 status = check_name(conn, destname);
6737 if (!NT_STATUS_IS_OK(status)) {
6738 TALLOC_FREE(dir_hnd);
6739 reply_nterror(req, status);
6740 END_PROFILE(SMBcopy);
6741 return;
6744 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6746 status = copy_file(ctx,conn,fname,destname,ofun,
6747 count,target_is_directory);
6748 if (NT_STATUS_IS_OK(status)) {
6749 count++;
6751 TALLOC_FREE(fname);
6752 TALLOC_FREE(destname);
6754 TALLOC_FREE(dir_hnd);
6757 if (count == 0) {
6758 if(err) {
6759 /* Error on close... */
6760 errno = err;
6761 reply_unixerror(req, ERRHRD, ERRgeneral);
6762 END_PROFILE(SMBcopy);
6763 return;
6766 reply_doserror(req, ERRDOS, error);
6767 END_PROFILE(SMBcopy);
6768 return;
6771 reply_outbuf(req, 1, 0);
6772 SSVAL(req->outbuf,smb_vwv0,count);
6774 END_PROFILE(SMBcopy);
6775 return;
6778 #undef DBGC_CLASS
6779 #define DBGC_CLASS DBGC_LOCKING
6781 /****************************************************************************
6782 Get a lock pid, dealing with large count requests.
6783 ****************************************************************************/
6785 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6786 bool large_file_format)
6788 if(!large_file_format)
6789 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6790 else
6791 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6794 /****************************************************************************
6795 Get a lock count, dealing with large count requests.
6796 ****************************************************************************/
6798 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6799 bool large_file_format)
6801 uint64_t count = 0;
6803 if(!large_file_format) {
6804 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6805 } else {
6807 #if defined(HAVE_LONGLONG)
6808 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6809 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6810 #else /* HAVE_LONGLONG */
6813 * NT4.x seems to be broken in that it sends large file (64 bit)
6814 * lockingX calls even if the CAP_LARGE_FILES was *not*
6815 * negotiated. For boxes without large unsigned ints truncate the
6816 * lock count by dropping the top 32 bits.
6819 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6820 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6821 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6822 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6823 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6826 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6827 #endif /* HAVE_LONGLONG */
6830 return count;
6833 #if !defined(HAVE_LONGLONG)
6834 /****************************************************************************
6835 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6836 ****************************************************************************/
6838 static uint32 map_lock_offset(uint32 high, uint32 low)
6840 unsigned int i;
6841 uint32 mask = 0;
6842 uint32 highcopy = high;
6845 * Try and find out how many significant bits there are in high.
6848 for(i = 0; highcopy; i++)
6849 highcopy >>= 1;
6852 * We use 31 bits not 32 here as POSIX
6853 * lock offsets may not be negative.
6856 mask = (~0) << (31 - i);
6858 if(low & mask)
6859 return 0; /* Fail. */
6861 high <<= (31 - i);
6863 return (high|low);
6865 #endif /* !defined(HAVE_LONGLONG) */
6867 /****************************************************************************
6868 Get a lock offset, dealing with large offset requests.
6869 ****************************************************************************/
6871 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6872 bool large_file_format, bool *err)
6874 uint64_t offset = 0;
6876 *err = False;
6878 if(!large_file_format) {
6879 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6880 } else {
6882 #if defined(HAVE_LONGLONG)
6883 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6884 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6885 #else /* HAVE_LONGLONG */
6888 * NT4.x seems to be broken in that it sends large file (64 bit)
6889 * lockingX calls even if the CAP_LARGE_FILES was *not*
6890 * negotiated. For boxes without large unsigned ints mangle the
6891 * lock offset by mapping the top 32 bits onto the lower 32.
6894 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6895 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6896 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6897 uint32 new_low = 0;
6899 if((new_low = map_lock_offset(high, low)) == 0) {
6900 *err = True;
6901 return (uint64_t)-1;
6904 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6905 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6906 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6907 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6910 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6911 #endif /* HAVE_LONGLONG */
6914 return offset;
6917 /****************************************************************************
6918 Reply to a lockingX request.
6919 ****************************************************************************/
6921 void reply_lockingX(struct smb_request *req)
6923 connection_struct *conn = req->conn;
6924 files_struct *fsp;
6925 unsigned char locktype;
6926 unsigned char oplocklevel;
6927 uint16 num_ulocks;
6928 uint16 num_locks;
6929 uint64_t count = 0, offset = 0;
6930 uint32 lock_pid;
6931 int32 lock_timeout;
6932 int i;
6933 const uint8_t *data;
6934 bool large_file_format;
6935 bool err;
6936 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6938 START_PROFILE(SMBlockingX);
6940 if (req->wct < 8) {
6941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6942 END_PROFILE(SMBlockingX);
6943 return;
6946 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6947 locktype = CVAL(req->vwv+3, 0);
6948 oplocklevel = CVAL(req->vwv+3, 1);
6949 num_ulocks = SVAL(req->vwv+6, 0);
6950 num_locks = SVAL(req->vwv+7, 0);
6951 lock_timeout = IVAL(req->vwv+4, 0);
6952 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6954 if (!check_fsp(conn, req, fsp)) {
6955 END_PROFILE(SMBlockingX);
6956 return;
6959 data = req->buf;
6961 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6962 /* we don't support these - and CANCEL_LOCK makes w2k
6963 and XP reboot so I don't really want to be
6964 compatible! (tridge) */
6965 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6966 END_PROFILE(SMBlockingX);
6967 return;
6970 /* Check if this is an oplock break on a file
6971 we have granted an oplock on.
6973 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6974 /* Client can insist on breaking to none. */
6975 bool break_to_none = (oplocklevel == 0);
6976 bool result;
6978 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6979 "for fnum = %d\n", (unsigned int)oplocklevel,
6980 fsp->fnum ));
6983 * Make sure we have granted an exclusive or batch oplock on
6984 * this file.
6987 if (fsp->oplock_type == 0) {
6989 /* The Samba4 nbench simulator doesn't understand
6990 the difference between break to level2 and break
6991 to none from level2 - it sends oplock break
6992 replies in both cases. Don't keep logging an error
6993 message here - just ignore it. JRA. */
6995 DEBUG(5,("reply_lockingX: Error : oplock break from "
6996 "client for fnum = %d (oplock=%d) and no "
6997 "oplock granted on this file (%s).\n",
6998 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7000 /* if this is a pure oplock break request then don't
7001 * send a reply */
7002 if (num_locks == 0 && num_ulocks == 0) {
7003 END_PROFILE(SMBlockingX);
7004 return;
7005 } else {
7006 END_PROFILE(SMBlockingX);
7007 reply_doserror(req, ERRDOS, ERRlock);
7008 return;
7012 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7013 (break_to_none)) {
7014 result = remove_oplock(fsp);
7015 } else {
7016 result = downgrade_oplock(fsp);
7019 if (!result) {
7020 DEBUG(0, ("reply_lockingX: error in removing "
7021 "oplock on file %s\n", fsp->fsp_name));
7022 /* Hmmm. Is this panic justified? */
7023 smb_panic("internal tdb error");
7026 reply_to_oplock_break_requests(fsp);
7028 /* if this is a pure oplock break request then don't send a
7029 * reply */
7030 if (num_locks == 0 && num_ulocks == 0) {
7031 /* Sanity check - ensure a pure oplock break is not a
7032 chained request. */
7033 if(CVAL(req->vwv+0, 0) != 0xff)
7034 DEBUG(0,("reply_lockingX: Error : pure oplock "
7035 "break is a chained %d request !\n",
7036 (unsigned int)CVAL(req->vwv+0, 0)));
7037 END_PROFILE(SMBlockingX);
7038 return;
7042 if (req->buflen <
7043 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7044 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7045 END_PROFILE(SMBlockingX);
7046 return;
7049 /* Data now points at the beginning of the list
7050 of smb_unlkrng structs */
7051 for(i = 0; i < (int)num_ulocks; i++) {
7052 lock_pid = get_lock_pid( data, i, large_file_format);
7053 count = get_lock_count( data, i, large_file_format);
7054 offset = get_lock_offset( data, i, large_file_format, &err);
7057 * There is no error code marked "stupid client bug".... :-).
7059 if(err) {
7060 END_PROFILE(SMBlockingX);
7061 reply_doserror(req, ERRDOS, ERRnoaccess);
7062 return;
7065 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7066 "pid %u, file %s\n", (double)offset, (double)count,
7067 (unsigned int)lock_pid, fsp->fsp_name ));
7069 status = do_unlock(smbd_messaging_context(),
7070 fsp,
7071 lock_pid,
7072 count,
7073 offset,
7074 WINDOWS_LOCK);
7076 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7077 nt_errstr(status)));
7079 if (NT_STATUS_V(status)) {
7080 END_PROFILE(SMBlockingX);
7081 reply_nterror(req, status);
7082 return;
7086 /* Setup the timeout in seconds. */
7088 if (!lp_blocking_locks(SNUM(conn))) {
7089 lock_timeout = 0;
7092 /* Now do any requested locks */
7093 data += ((large_file_format ? 20 : 10)*num_ulocks);
7095 /* Data now points at the beginning of the list
7096 of smb_lkrng structs */
7098 for(i = 0; i < (int)num_locks; i++) {
7099 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7100 READ_LOCK:WRITE_LOCK);
7101 lock_pid = get_lock_pid( data, i, large_file_format);
7102 count = get_lock_count( data, i, large_file_format);
7103 offset = get_lock_offset( data, i, large_file_format, &err);
7106 * There is no error code marked "stupid client bug".... :-).
7108 if(err) {
7109 END_PROFILE(SMBlockingX);
7110 reply_doserror(req, ERRDOS, ERRnoaccess);
7111 return;
7114 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7115 "%u, file %s timeout = %d\n", (double)offset,
7116 (double)count, (unsigned int)lock_pid,
7117 fsp->fsp_name, (int)lock_timeout ));
7119 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7120 struct blocking_lock_record *blr = NULL;
7122 if (lp_blocking_locks(SNUM(conn))) {
7124 /* Schedule a message to ourselves to
7125 remove the blocking lock record and
7126 return the right error. */
7128 blr = blocking_lock_cancel(fsp,
7129 lock_pid,
7130 offset,
7131 count,
7132 WINDOWS_LOCK,
7133 locktype,
7134 NT_STATUS_FILE_LOCK_CONFLICT);
7135 if (blr == NULL) {
7136 END_PROFILE(SMBlockingX);
7137 reply_nterror(
7138 req,
7139 NT_STATUS_DOS(
7140 ERRDOS,
7141 ERRcancelviolation));
7142 return;
7145 /* Remove a matching pending lock. */
7146 status = do_lock_cancel(fsp,
7147 lock_pid,
7148 count,
7149 offset,
7150 WINDOWS_LOCK,
7151 blr);
7152 } else {
7153 bool blocking_lock = lock_timeout ? True : False;
7154 bool defer_lock = False;
7155 struct byte_range_lock *br_lck;
7156 uint32 block_smbpid;
7158 br_lck = do_lock(smbd_messaging_context(),
7159 fsp,
7160 lock_pid,
7161 count,
7162 offset,
7163 lock_type,
7164 WINDOWS_LOCK,
7165 blocking_lock,
7166 &status,
7167 &block_smbpid,
7168 NULL);
7170 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7171 /* Windows internal resolution for blocking locks seems
7172 to be about 200ms... Don't wait for less than that. JRA. */
7173 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7174 lock_timeout = lp_lock_spin_time();
7176 defer_lock = True;
7179 /* This heuristic seems to match W2K3 very well. If a
7180 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7181 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7182 far as I can tell. Replacement for do_lock_spin(). JRA. */
7184 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7185 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7186 defer_lock = True;
7187 lock_timeout = lp_lock_spin_time();
7190 if (br_lck && defer_lock) {
7192 * A blocking lock was requested. Package up
7193 * this smb into a queued request and push it
7194 * onto the blocking lock queue.
7196 if(push_blocking_lock_request(br_lck,
7197 req,
7198 fsp,
7199 lock_timeout,
7201 lock_pid,
7202 lock_type,
7203 WINDOWS_LOCK,
7204 offset,
7205 count,
7206 block_smbpid)) {
7207 TALLOC_FREE(br_lck);
7208 END_PROFILE(SMBlockingX);
7209 return;
7213 TALLOC_FREE(br_lck);
7216 if (NT_STATUS_V(status)) {
7217 break;
7221 /* If any of the above locks failed, then we must unlock
7222 all of the previous locks (X/Open spec). */
7223 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7225 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7226 i = -1; /* we want to skip the for loop */
7230 * Ensure we don't do a remove on the lock that just failed,
7231 * as under POSIX rules, if we have a lock already there, we
7232 * will delete it (and we shouldn't) .....
7234 for(i--; i >= 0; i--) {
7235 lock_pid = get_lock_pid( data, i, large_file_format);
7236 count = get_lock_count( data, i, large_file_format);
7237 offset = get_lock_offset( data, i, large_file_format,
7238 &err);
7241 * There is no error code marked "stupid client
7242 * bug".... :-).
7244 if(err) {
7245 END_PROFILE(SMBlockingX);
7246 reply_doserror(req, ERRDOS, ERRnoaccess);
7247 return;
7250 do_unlock(smbd_messaging_context(),
7251 fsp,
7252 lock_pid,
7253 count,
7254 offset,
7255 WINDOWS_LOCK);
7257 END_PROFILE(SMBlockingX);
7258 reply_nterror(req, status);
7259 return;
7262 reply_outbuf(req, 2, 0);
7264 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7265 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7267 END_PROFILE(SMBlockingX);
7268 chain_reply(req);
7271 #undef DBGC_CLASS
7272 #define DBGC_CLASS DBGC_ALL
7274 /****************************************************************************
7275 Reply to a SMBreadbmpx (read block multiplex) request.
7276 Always reply with an error, if someone has a platform really needs this,
7277 please contact vl@samba.org
7278 ****************************************************************************/
7280 void reply_readbmpx(struct smb_request *req)
7282 START_PROFILE(SMBreadBmpx);
7283 reply_doserror(req, ERRSRV, ERRuseSTD);
7284 END_PROFILE(SMBreadBmpx);
7285 return;
7288 /****************************************************************************
7289 Reply to a SMBreadbs (read block multiplex secondary) request.
7290 Always reply with an error, if someone has a platform really needs this,
7291 please contact vl@samba.org
7292 ****************************************************************************/
7294 void reply_readbs(struct smb_request *req)
7296 START_PROFILE(SMBreadBs);
7297 reply_doserror(req, ERRSRV, ERRuseSTD);
7298 END_PROFILE(SMBreadBs);
7299 return;
7302 /****************************************************************************
7303 Reply to a SMBsetattrE.
7304 ****************************************************************************/
7306 void reply_setattrE(struct smb_request *req)
7308 connection_struct *conn = req->conn;
7309 struct smb_file_time ft;
7310 files_struct *fsp;
7311 SMB_STRUCT_STAT sbuf;
7312 NTSTATUS status;
7314 START_PROFILE(SMBsetattrE);
7315 ZERO_STRUCT(ft);
7317 if (req->wct < 7) {
7318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7319 END_PROFILE(SMBsetattrE);
7320 return;
7323 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7325 if(!fsp || (fsp->conn != conn)) {
7326 reply_doserror(req, ERRDOS, ERRbadfid);
7327 END_PROFILE(SMBsetattrE);
7328 return;
7333 * Convert the DOS times into unix times.
7336 ft.atime = convert_time_t_to_timespec(
7337 srv_make_unix_date2(req->vwv+3));
7338 ft.mtime = convert_time_t_to_timespec(
7339 srv_make_unix_date2(req->vwv+5));
7340 ft.create_time = convert_time_t_to_timespec(
7341 srv_make_unix_date2(req->vwv+1));
7343 reply_outbuf(req, 0, 0);
7346 * Patch from Ray Frush <frush@engr.colostate.edu>
7347 * Sometimes times are sent as zero - ignore them.
7350 /* Ensure we have a valid stat struct for the source. */
7351 if (fsp->fh->fd != -1) {
7352 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7353 status = map_nt_error_from_unix(errno);
7354 reply_nterror(req, status);
7355 END_PROFILE(SMBsetattrE);
7356 return;
7358 } else {
7359 int ret = -1;
7361 if (fsp->posix_open) {
7362 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7363 } else {
7364 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7366 if (ret == -1) {
7367 status = map_nt_error_from_unix(errno);
7368 reply_nterror(req, status);
7369 END_PROFILE(SMBsetattrE);
7370 return;
7374 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7375 &sbuf, &ft, true);
7376 if (!NT_STATUS_IS_OK(status)) {
7377 reply_doserror(req, ERRDOS, ERRnoaccess);
7378 END_PROFILE(SMBsetattrE);
7379 return;
7382 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7383 " createtime=%u\n",
7384 fsp->fnum,
7385 (unsigned int)ft.atime.tv_sec,
7386 (unsigned int)ft.mtime.tv_sec,
7387 (unsigned int)ft.create_time.tv_sec
7390 END_PROFILE(SMBsetattrE);
7391 return;
7395 /* Back from the dead for OS/2..... JRA. */
7397 /****************************************************************************
7398 Reply to a SMBwritebmpx (write block multiplex primary) request.
7399 Always reply with an error, if someone has a platform really needs this,
7400 please contact vl@samba.org
7401 ****************************************************************************/
7403 void reply_writebmpx(struct smb_request *req)
7405 START_PROFILE(SMBwriteBmpx);
7406 reply_doserror(req, ERRSRV, ERRuseSTD);
7407 END_PROFILE(SMBwriteBmpx);
7408 return;
7411 /****************************************************************************
7412 Reply to a SMBwritebs (write block multiplex secondary) request.
7413 Always reply with an error, if someone has a platform really needs this,
7414 please contact vl@samba.org
7415 ****************************************************************************/
7417 void reply_writebs(struct smb_request *req)
7419 START_PROFILE(SMBwriteBs);
7420 reply_doserror(req, ERRSRV, ERRuseSTD);
7421 END_PROFILE(SMBwriteBs);
7422 return;
7425 /****************************************************************************
7426 Reply to a SMBgetattrE.
7427 ****************************************************************************/
7429 void reply_getattrE(struct smb_request *req)
7431 connection_struct *conn = req->conn;
7432 SMB_STRUCT_STAT sbuf;
7433 int mode;
7434 files_struct *fsp;
7435 struct timespec create_ts;
7437 START_PROFILE(SMBgetattrE);
7439 if (req->wct < 1) {
7440 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7441 END_PROFILE(SMBgetattrE);
7442 return;
7445 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7447 if(!fsp || (fsp->conn != conn)) {
7448 reply_doserror(req, ERRDOS, ERRbadfid);
7449 END_PROFILE(SMBgetattrE);
7450 return;
7453 /* Do an fstat on this file */
7454 if(fsp_stat(fsp, &sbuf)) {
7455 reply_unixerror(req, ERRDOS, ERRnoaccess);
7456 END_PROFILE(SMBgetattrE);
7457 return;
7460 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7463 * Convert the times into dos times. Set create
7464 * date to be last modify date as UNIX doesn't save
7465 * this.
7468 reply_outbuf(req, 11, 0);
7470 create_ts = get_create_timespec(&sbuf,
7471 lp_fake_dir_create_times(SNUM(conn)));
7472 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7473 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7474 /* Should we check pending modtime here ? JRA */
7475 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7477 if (mode & aDIR) {
7478 SIVAL(req->outbuf, smb_vwv6, 0);
7479 SIVAL(req->outbuf, smb_vwv8, 0);
7480 } else {
7481 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7482 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7483 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7485 SSVAL(req->outbuf,smb_vwv10, mode);
7487 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7489 END_PROFILE(SMBgetattrE);
7490 return;