Remove unused CHECK_FSP macro
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blob48403073f73222f5750abe3c141e5ba7f67aa59b
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"
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_recv;
32 extern uint32 global_client_caps;
34 extern bool global_encrypted_passwords_negotiated;
36 /****************************************************************************
37 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
38 path or anything including wildcards.
39 We're assuming here that '/' is not the second byte in any multibyte char
40 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
41 set.
42 ****************************************************************************/
44 /* Custom version for processing POSIX paths. */
45 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
47 static NTSTATUS check_path_syntax_internal(char *path,
48 bool posix_path,
49 bool *p_last_component_contains_wcard)
51 char *d = path;
52 const char *s = path;
53 NTSTATUS ret = NT_STATUS_OK;
54 bool start_of_name_component = True;
56 *p_last_component_contains_wcard = False;
58 while (*s) {
59 if (IS_PATH_SEP(*s,posix_path)) {
61 * Safe to assume is not the second part of a mb char
62 * as this is handled below.
64 /* Eat multiple '/' or '\\' */
65 while (IS_PATH_SEP(*s,posix_path)) {
66 s++;
68 if ((d != path) && (*s != '\0')) {
69 /* We only care about non-leading or trailing '/' or '\\' */
70 *d++ = '/';
73 start_of_name_component = True;
74 /* New component. */
75 *p_last_component_contains_wcard = False;
76 continue;
79 if (start_of_name_component) {
80 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
81 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
84 * No mb char starts with '.' so we're safe checking the directory separator here.
87 /* If we just added a '/' - delete it */
88 if ((d > path) && (*(d-1) == '/')) {
89 *(d-1) = '\0';
90 d--;
93 /* Are we at the start ? Can't go back further if so. */
94 if (d <= path) {
95 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
96 break;
98 /* Go back one level... */
99 /* We know this is safe as '/' cannot be part of a mb sequence. */
100 /* NOTE - if this assumption is invalid we are not in good shape... */
101 /* Decrement d first as d points to the *next* char to write into. */
102 for (d--; d > path; d--) {
103 if (*d == '/')
104 break;
106 s += 2; /* Else go past the .. */
107 /* We're still at the start of a name component, just the previous one. */
108 continue;
110 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
111 if (posix_path) {
112 /* Eat the '.' */
113 s++;
114 continue;
120 if (!(*s & 0x80)) {
121 if (!posix_path) {
122 if (*s <= 0x1f) {
123 return NT_STATUS_OBJECT_NAME_INVALID;
125 switch (*s) {
126 case '*':
127 case '?':
128 case '<':
129 case '>':
130 case '"':
131 *p_last_component_contains_wcard = True;
132 break;
133 default:
134 break;
137 *d++ = *s++;
138 } else {
139 size_t siz;
140 /* Get the size of the next MB character. */
141 next_codepoint(s,&siz);
142 switch(siz) {
143 case 5:
144 *d++ = *s++;
145 /*fall through*/
146 case 4:
147 *d++ = *s++;
148 /*fall through*/
149 case 3:
150 *d++ = *s++;
151 /*fall through*/
152 case 2:
153 *d++ = *s++;
154 /*fall through*/
155 case 1:
156 *d++ = *s++;
157 break;
158 default:
159 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
160 *d = '\0';
161 return NT_STATUS_INVALID_PARAMETER;
164 start_of_name_component = False;
167 *d = '\0';
169 return ret;
172 /****************************************************************************
173 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
174 No wildcards allowed.
175 ****************************************************************************/
177 NTSTATUS check_path_syntax(char *path)
179 bool ignore;
180 return check_path_syntax_internal(path, False, &ignore);
183 /****************************************************************************
184 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
185 Wildcards allowed - p_contains_wcard returns true if the last component contained
186 a wildcard.
187 ****************************************************************************/
189 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
191 return check_path_syntax_internal(path, False, p_contains_wcard);
194 /****************************************************************************
195 Check the path for a POSIX client.
196 We're assuming here that '/' is not the second byte in any multibyte char
197 set (a safe assumption).
198 ****************************************************************************/
200 NTSTATUS check_path_syntax_posix(char *path)
202 bool ignore;
203 return check_path_syntax_internal(path, True, &ignore);
206 /****************************************************************************
207 Pull a string and check the path allowing a wilcard - provide for error return.
208 ****************************************************************************/
210 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
211 const char *inbuf,
212 uint16 smb_flags2,
213 char **pp_dest,
214 const char *src,
215 size_t src_len,
216 int flags,
217 NTSTATUS *err,
218 bool *contains_wcard)
220 size_t ret;
222 *pp_dest = NULL;
224 if (src_len == 0) {
225 ret = srvstr_pull_buf_talloc(ctx,
226 inbuf,
227 smb_flags2,
228 pp_dest,
229 src,
230 flags);
231 } else {
232 ret = srvstr_pull_talloc(ctx,
233 inbuf,
234 smb_flags2,
235 pp_dest,
236 src,
237 src_len,
238 flags);
241 if (!*pp_dest) {
242 *err = NT_STATUS_INVALID_PARAMETER;
243 return ret;
246 *contains_wcard = False;
248 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
250 * For a DFS path the function parse_dfs_path()
251 * will do the path processing, just make a copy.
253 *err = NT_STATUS_OK;
254 return ret;
257 if (lp_posix_pathnames()) {
258 *err = check_path_syntax_posix(*pp_dest);
259 } else {
260 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
263 return ret;
266 /****************************************************************************
267 Pull a string and check the path - provide for error return.
268 ****************************************************************************/
270 size_t srvstr_get_path(TALLOC_CTX *ctx,
271 const char *inbuf,
272 uint16 smb_flags2,
273 char **pp_dest,
274 const char *src,
275 size_t src_len,
276 int flags,
277 NTSTATUS *err)
279 size_t ret;
281 *pp_dest = NULL;
283 if (src_len == 0) {
284 ret = srvstr_pull_buf_talloc(ctx,
285 inbuf,
286 smb_flags2,
287 pp_dest,
288 src,
289 flags);
290 } else {
291 ret = srvstr_pull_talloc(ctx,
292 inbuf,
293 smb_flags2,
294 pp_dest,
295 src,
296 src_len,
297 flags);
300 if (!*pp_dest) {
301 *err = NT_STATUS_INVALID_PARAMETER;
302 return ret;
305 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
307 * For a DFS path the function parse_dfs_path()
308 * will do the path processing, just make a copy.
310 *err = NT_STATUS_OK;
311 return ret;
314 if (lp_posix_pathnames()) {
315 *err = check_path_syntax_posix(*pp_dest);
316 } else {
317 *err = check_path_syntax(*pp_dest);
320 return ret;
323 /****************************************************************************
324 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
328 files_struct *fsp)
330 if (!(fsp) || !(conn)) {
331 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
332 return False;
334 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
335 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
336 return False;
338 return True;
341 /****************************************************************************
342 Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
346 files_struct *fsp)
348 if (!check_fsp_open(conn, req, fsp)) {
349 return False;
351 if ((fsp)->is_directory) {
352 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
353 return False;
355 if ((fsp)->fh->fd == -1) {
356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
357 return False;
359 (fsp)->num_smb_operations++;
360 return True;
363 /****************************************************************************
364 Check if we have a correct fsp pointing to a quota fake file. Replacement for
365 the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
369 files_struct *fsp)
371 if (!check_fsp_open(conn, req, fsp)) {
372 return false;
375 if (fsp->is_directory) {
376 return false;
379 if (fsp->fake_file_handle == NULL) {
380 return false;
383 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
384 return false;
387 if (fsp->fake_file_handle->private_data == NULL) {
388 return false;
391 return true;
394 /****************************************************************************
395 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
398 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
399 files_struct *fsp)
401 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
402 && (req->vuid == (fsp)->vuid)) {
403 return True;
406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
407 return False;
410 /****************************************************************************
411 Reply to a (netbios-level) special message.
412 ****************************************************************************/
414 void reply_special(char *inbuf)
416 int msg_type = CVAL(inbuf,0);
417 int msg_flags = CVAL(inbuf,1);
418 fstring name1,name2;
419 char name_type = 0;
422 * We only really use 4 bytes of the outbuf, but for the smb_setlen
423 * calculation & friends (srv_send_smb uses that) we need the full smb
424 * header.
426 char outbuf[smb_size];
428 static bool already_got_session = False;
430 *name1 = *name2 = 0;
432 memset(outbuf, '\0', sizeof(outbuf));
434 smb_setlen(outbuf,0);
436 switch (msg_type) {
437 case 0x81: /* session request */
439 if (already_got_session) {
440 exit_server_cleanly("multiple session request not permitted");
443 SCVAL(outbuf,0,0x82);
444 SCVAL(outbuf,3,0);
445 if (name_len(inbuf+4) > 50 ||
446 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
447 DEBUG(0,("Invalid name length in session request\n"));
448 return;
450 name_extract(inbuf,4,name1);
451 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
452 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
453 name1,name2));
455 set_local_machine_name(name1, True);
456 set_remote_machine_name(name2, True);
458 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
459 get_local_machine_name(), get_remote_machine_name(),
460 name_type));
462 if (name_type == 'R') {
463 /* We are being asked for a pathworks session ---
464 no thanks! */
465 SCVAL(outbuf, 0,0x83);
466 break;
469 /* only add the client's machine name to the list
470 of possibly valid usernames if we are operating
471 in share mode security */
472 if (lp_security() == SEC_SHARE) {
473 add_session_user(get_remote_machine_name());
476 reload_services(True);
477 reopen_logs();
479 already_got_session = True;
480 break;
482 case 0x89: /* session keepalive request
483 (some old clients produce this?) */
484 SCVAL(outbuf,0,SMBkeepalive);
485 SCVAL(outbuf,3,0);
486 break;
488 case 0x82: /* positive session response */
489 case 0x83: /* negative session response */
490 case 0x84: /* retarget session response */
491 DEBUG(0,("Unexpected session response\n"));
492 break;
494 case SMBkeepalive: /* session keepalive */
495 default:
496 return;
499 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
500 msg_type, msg_flags));
502 srv_send_smb(smbd_server_fd(), outbuf, false);
503 return;
506 /****************************************************************************
507 Reply to a tcon.
508 conn POINTER CAN BE NULL HERE !
509 ****************************************************************************/
511 void reply_tcon(struct smb_request *req)
513 connection_struct *conn = req->conn;
514 const char *service;
515 char *service_buf = NULL;
516 char *password = NULL;
517 char *dev = NULL;
518 int pwlen=0;
519 NTSTATUS nt_status;
520 char *p;
521 DATA_BLOB password_blob;
522 TALLOC_CTX *ctx = talloc_tos();
524 START_PROFILE(SMBtcon);
526 if (smb_buflen(req->inbuf) < 4) {
527 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
528 END_PROFILE(SMBtcon);
529 return;
532 p = smb_buf(req->inbuf)+1;
533 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
534 &service_buf, p, STR_TERMINATE) + 1;
535 pwlen = srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
536 &password, p, STR_TERMINATE) + 1;
537 p += pwlen;
538 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
539 &dev, p, STR_TERMINATE) + 1;
541 if (service_buf == NULL || password == NULL || dev == NULL) {
542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
543 END_PROFILE(SMBtcon);
544 return;
546 p = strrchr_m(service_buf,'\\');
547 if (p) {
548 service = p+1;
549 } else {
550 service = service_buf;
553 password_blob = data_blob(password, pwlen+1);
555 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
556 req->conn = conn;
558 data_blob_clear_free(&password_blob);
560 if (!conn) {
561 reply_nterror(req, nt_status);
562 END_PROFILE(SMBtcon);
563 return;
566 reply_outbuf(req, 2, 0);
567 SSVAL(req->outbuf,smb_vwv0,max_recv);
568 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
569 SSVAL(req->outbuf,smb_tid,conn->cnum);
571 DEBUG(3,("tcon service=%s cnum=%d\n",
572 service, conn->cnum));
574 END_PROFILE(SMBtcon);
575 return;
578 /****************************************************************************
579 Reply to a tcon and X.
580 conn POINTER CAN BE NULL HERE !
581 ****************************************************************************/
583 void reply_tcon_and_X(struct smb_request *req)
585 connection_struct *conn = req->conn;
586 char *service = NULL;
587 DATA_BLOB password;
588 TALLOC_CTX *ctx = talloc_tos();
589 /* what the cleint thinks the device is */
590 char *client_devicetype = NULL;
591 /* what the server tells the client the share represents */
592 const char *server_devicetype;
593 NTSTATUS nt_status;
594 int passlen;
595 char *path = NULL;
596 char *p, *q;
597 uint16 tcon_flags;
599 START_PROFILE(SMBtconX);
601 if (req->wct < 4) {
602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
603 END_PROFILE(SMBtconX);
604 return;
607 passlen = SVAL(req->inbuf,smb_vwv3);
608 tcon_flags = SVAL(req->inbuf,smb_vwv2);
610 /* we might have to close an old one */
611 if ((tcon_flags & 0x1) && conn) {
612 close_cnum(conn,req->vuid);
613 req->conn = NULL;
614 conn = NULL;
617 if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
618 reply_doserror(req, ERRDOS, ERRbuftoosmall);
619 END_PROFILE(SMBtconX);
620 return;
623 if (global_encrypted_passwords_negotiated) {
624 password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf),
625 passlen);
626 if (lp_security() == SEC_SHARE) {
628 * Security = share always has a pad byte
629 * after the password.
631 p = smb_buf(req->inbuf) + passlen + 1;
632 } else {
633 p = smb_buf(req->inbuf) + passlen;
635 } else {
636 password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf),
637 passlen+1);
638 /* Ensure correct termination */
639 password.data[passlen]=0;
640 p = smb_buf(req->inbuf) + passlen + 1;
643 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
644 STR_TERMINATE);
646 if (path == NULL) {
647 data_blob_clear_free(&password);
648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
649 END_PROFILE(SMBtconX);
650 return;
654 * the service name can be either: \\server\share
655 * or share directly like on the DELL PowerVault 705
657 if (*path=='\\') {
658 q = strchr_m(path+2,'\\');
659 if (!q) {
660 data_blob_clear_free(&password);
661 reply_doserror(req, ERRDOS, ERRnosuchshare);
662 END_PROFILE(SMBtconX);
663 return;
665 service = q+1;
666 } else {
667 service = path;
670 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
671 &client_devicetype, p,
672 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
674 if (client_devicetype == NULL) {
675 data_blob_clear_free(&password);
676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
677 END_PROFILE(SMBtconX);
678 return;
681 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
683 conn = make_connection(service, password, client_devicetype,
684 req->vuid, &nt_status);
685 req->conn =conn;
687 data_blob_clear_free(&password);
689 if (!conn) {
690 reply_nterror(req, nt_status);
691 END_PROFILE(SMBtconX);
692 return;
695 if ( IS_IPC(conn) )
696 server_devicetype = "IPC";
697 else if ( IS_PRINT(conn) )
698 server_devicetype = "LPT1:";
699 else
700 server_devicetype = "A:";
702 if (Protocol < PROTOCOL_NT1) {
703 reply_outbuf(req, 2, 0);
704 if (message_push_string(&req->outbuf, server_devicetype,
705 STR_TERMINATE|STR_ASCII) == -1) {
706 reply_nterror(req, NT_STATUS_NO_MEMORY);
707 END_PROFILE(SMBtconX);
708 return;
710 } else {
711 /* NT sets the fstype of IPC$ to the null string */
712 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
714 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
715 /* Return permissions. */
716 uint32 perm1 = 0;
717 uint32 perm2 = 0;
719 reply_outbuf(req, 7, 0);
721 if (IS_IPC(conn)) {
722 perm1 = FILE_ALL_ACCESS;
723 perm2 = FILE_ALL_ACCESS;
724 } else {
725 perm1 = CAN_WRITE(conn) ?
726 SHARE_ALL_ACCESS :
727 SHARE_READ_ONLY;
730 SIVAL(req->outbuf, smb_vwv3, perm1);
731 SIVAL(req->outbuf, smb_vwv5, perm2);
732 } else {
733 reply_outbuf(req, 3, 0);
736 if ((message_push_string(&req->outbuf, server_devicetype,
737 STR_TERMINATE|STR_ASCII) == -1)
738 || (message_push_string(&req->outbuf, fstype,
739 STR_TERMINATE) == -1)) {
740 reply_nterror(req, NT_STATUS_NO_MEMORY);
741 END_PROFILE(SMBtconX);
742 return;
745 /* what does setting this bit do? It is set by NT4 and
746 may affect the ability to autorun mounted cdroms */
747 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
748 (lp_csc_policy(SNUM(conn)) << 2));
750 init_dfsroot(conn, req->inbuf, req->outbuf);
754 DEBUG(3,("tconX service=%s \n",
755 service));
757 /* set the incoming and outgoing tid to the just created one */
758 SSVAL(req->inbuf,smb_tid,conn->cnum);
759 SSVAL(req->outbuf,smb_tid,conn->cnum);
761 END_PROFILE(SMBtconX);
763 chain_reply(req);
764 return;
767 /****************************************************************************
768 Reply to an unknown type.
769 ****************************************************************************/
771 void reply_unknown_new(struct smb_request *req, uint8 type)
773 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
774 smb_fn_name(type), type, type));
775 reply_doserror(req, ERRSRV, ERRunknownsmb);
776 return;
779 /****************************************************************************
780 Reply to an ioctl.
781 conn POINTER CAN BE NULL HERE !
782 ****************************************************************************/
784 void reply_ioctl(struct smb_request *req)
786 connection_struct *conn = req->conn;
787 uint16 device;
788 uint16 function;
789 uint32 ioctl_code;
790 int replysize;
791 char *p;
793 START_PROFILE(SMBioctl);
795 if (req->wct < 3) {
796 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
797 END_PROFILE(SMBioctl);
798 return;
801 device = SVAL(req->inbuf,smb_vwv1);
802 function = SVAL(req->inbuf,smb_vwv2);
803 ioctl_code = (device << 16) + function;
805 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
807 switch (ioctl_code) {
808 case IOCTL_QUERY_JOB_INFO:
809 replysize = 32;
810 break;
811 default:
812 reply_doserror(req, ERRSRV, ERRnosupport);
813 END_PROFILE(SMBioctl);
814 return;
817 reply_outbuf(req, 8, replysize+1);
818 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
819 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
820 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
821 p = smb_buf(req->outbuf);
822 memset(p, '\0', replysize+1); /* valgrind-safe. */
823 p += 1; /* Allow for alignment */
825 switch (ioctl_code) {
826 case IOCTL_QUERY_JOB_INFO:
828 files_struct *fsp = file_fsp(SVAL(req->inbuf,
829 smb_vwv0));
830 if (!fsp) {
831 reply_doserror(req, ERRDOS, ERRbadfid);
832 END_PROFILE(SMBioctl);
833 return;
835 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
836 srvstr_push((char *)req->outbuf, req->flags2, p+2,
837 global_myname(), 15,
838 STR_TERMINATE|STR_ASCII);
839 if (conn) {
840 srvstr_push((char *)req->outbuf, req->flags2,
841 p+18, lp_servicename(SNUM(conn)),
842 13, STR_TERMINATE|STR_ASCII);
843 } else {
844 memset(p+18, 0, 13);
846 break;
850 END_PROFILE(SMBioctl);
851 return;
854 /****************************************************************************
855 Strange checkpath NTSTATUS mapping.
856 ****************************************************************************/
858 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
860 /* Strange DOS error code semantics only for checkpath... */
861 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
862 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
863 /* We need to map to ERRbadpath */
864 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
867 return status;
870 /****************************************************************************
871 Reply to a checkpath.
872 ****************************************************************************/
874 void reply_checkpath(struct smb_request *req)
876 connection_struct *conn = req->conn;
877 char *name = NULL;
878 SMB_STRUCT_STAT sbuf;
879 NTSTATUS status;
880 TALLOC_CTX *ctx = talloc_tos();
882 START_PROFILE(SMBcheckpath);
884 srvstr_get_path(ctx,(char *)req->inbuf, req->flags2, &name,
885 smb_buf(req->inbuf) + 1, 0,
886 STR_TERMINATE, &status);
887 if (!NT_STATUS_IS_OK(status)) {
888 status = map_checkpath_error((char *)req->inbuf, status);
889 reply_nterror(req, status);
890 END_PROFILE(SMBcheckpath);
891 return;
894 status = resolve_dfspath(ctx, conn,
895 req->flags2 & FLAGS2_DFS_PATHNAMES,
896 name,
897 &name);
898 if (!NT_STATUS_IS_OK(status)) {
899 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
900 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
901 ERRSRV, ERRbadpath);
902 END_PROFILE(SMBcheckpath);
903 return;
905 goto path_err;
908 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
910 status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
911 if (!NT_STATUS_IS_OK(status)) {
912 goto path_err;
915 status = check_name(conn, name);
916 if (!NT_STATUS_IS_OK(status)) {
917 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
918 goto path_err;
921 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
922 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
923 status = map_nt_error_from_unix(errno);
924 goto path_err;
927 if (!S_ISDIR(sbuf.st_mode)) {
928 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
929 ERRDOS, ERRbadpath);
930 END_PROFILE(SMBcheckpath);
931 return;
934 reply_outbuf(req, 0, 0);
936 END_PROFILE(SMBcheckpath);
937 return;
939 path_err:
941 END_PROFILE(SMBcheckpath);
943 /* We special case this - as when a Windows machine
944 is parsing a path is steps through the components
945 one at a time - if a component fails it expects
946 ERRbadpath, not ERRbadfile.
948 status = map_checkpath_error((char *)req->inbuf, status);
949 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
951 * Windows returns different error codes if
952 * the parent directory is valid but not the
953 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
954 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
955 * if the path is invalid.
957 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
958 ERRDOS, ERRbadpath);
959 return;
962 reply_nterror(req, status);
965 /****************************************************************************
966 Reply to a getatr.
967 ****************************************************************************/
969 void reply_getatr(struct smb_request *req)
971 connection_struct *conn = req->conn;
972 char *fname = NULL;
973 SMB_STRUCT_STAT sbuf;
974 int mode=0;
975 SMB_OFF_T size=0;
976 time_t mtime=0;
977 char *p;
978 NTSTATUS status;
979 TALLOC_CTX *ctx = talloc_tos();
981 START_PROFILE(SMBgetatr);
983 p = smb_buf(req->inbuf) + 1;
984 p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
985 0, STR_TERMINATE, &status);
986 if (!NT_STATUS_IS_OK(status)) {
987 reply_nterror(req, status);
988 END_PROFILE(SMBgetatr);
989 return;
992 status = resolve_dfspath(ctx, conn,
993 req->flags2 & FLAGS2_DFS_PATHNAMES,
994 fname,
995 &fname);
996 if (!NT_STATUS_IS_OK(status)) {
997 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
998 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
999 ERRSRV, ERRbadpath);
1000 END_PROFILE(SMBgetatr);
1001 return;
1003 reply_nterror(req, status);
1004 END_PROFILE(SMBgetatr);
1005 return;
1008 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1009 under WfWg - weird! */
1010 if (*fname == '\0') {
1011 mode = aHIDDEN | aDIR;
1012 if (!CAN_WRITE(conn)) {
1013 mode |= aRONLY;
1015 size = 0;
1016 mtime = 0;
1017 } else {
1018 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
1019 if (!NT_STATUS_IS_OK(status)) {
1020 reply_nterror(req, status);
1021 END_PROFILE(SMBgetatr);
1022 return;
1024 status = check_name(conn, fname);
1025 if (!NT_STATUS_IS_OK(status)) {
1026 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1027 reply_nterror(req, status);
1028 END_PROFILE(SMBgetatr);
1029 return;
1031 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1032 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1033 reply_unixerror(req, ERRDOS,ERRbadfile);
1034 END_PROFILE(SMBgetatr);
1035 return;
1038 mode = dos_mode(conn,fname,&sbuf);
1039 size = sbuf.st_size;
1040 mtime = sbuf.st_mtime;
1041 if (mode & aDIR) {
1042 size = 0;
1046 reply_outbuf(req, 10, 0);
1048 SSVAL(req->outbuf,smb_vwv0,mode);
1049 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1050 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1051 } else {
1052 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1054 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1056 if (Protocol >= PROTOCOL_NT1) {
1057 SSVAL(req->outbuf, smb_flg2,
1058 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1061 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1063 END_PROFILE(SMBgetatr);
1064 return;
1067 /****************************************************************************
1068 Reply to a setatr.
1069 ****************************************************************************/
1071 void reply_setatr(struct smb_request *req)
1073 struct timespec ts[2];
1074 connection_struct *conn = req->conn;
1075 char *fname = NULL;
1076 int mode;
1077 time_t mtime;
1078 SMB_STRUCT_STAT sbuf;
1079 char *p;
1080 NTSTATUS status;
1081 TALLOC_CTX *ctx = talloc_tos();
1083 START_PROFILE(SMBsetatr);
1085 ZERO_STRUCT(ts);
1087 if (req->wct < 2) {
1088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1089 return;
1092 p = smb_buf(req->inbuf) + 1;
1093 p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
1094 0, STR_TERMINATE, &status);
1095 if (!NT_STATUS_IS_OK(status)) {
1096 reply_nterror(req, status);
1097 END_PROFILE(SMBsetatr);
1098 return;
1101 status = resolve_dfspath(ctx, conn,
1102 req->flags2 & FLAGS2_DFS_PATHNAMES,
1103 fname,
1104 &fname);
1105 if (!NT_STATUS_IS_OK(status)) {
1106 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1107 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1108 ERRSRV, ERRbadpath);
1109 END_PROFILE(SMBsetatr);
1110 return;
1112 reply_nterror(req, status);
1113 END_PROFILE(SMBsetatr);
1114 return;
1117 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1118 if (!NT_STATUS_IS_OK(status)) {
1119 reply_nterror(req, status);
1120 END_PROFILE(SMBsetatr);
1121 return;
1124 status = check_name(conn, fname);
1125 if (!NT_STATUS_IS_OK(status)) {
1126 reply_nterror(req, status);
1127 END_PROFILE(SMBsetatr);
1128 return;
1131 if (fname[0] == '.' && fname[1] == '\0') {
1133 * Not sure here is the right place to catch this
1134 * condition. Might be moved to somewhere else later -- vl
1136 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1137 END_PROFILE(SMBsetatr);
1138 return;
1141 mode = SVAL(req->inbuf,smb_vwv0);
1142 mtime = srv_make_unix_date3(req->inbuf+smb_vwv1);
1144 ts[1] = convert_time_t_to_timespec(mtime);
1145 status = smb_set_file_time(conn, NULL, fname,
1146 &sbuf, ts, true);
1147 if (!NT_STATUS_IS_OK(status)) {
1148 reply_unixerror(req, ERRDOS, ERRnoaccess);
1149 END_PROFILE(SMBsetatr);
1150 return;
1153 if (mode != FILE_ATTRIBUTE_NORMAL) {
1154 if (VALID_STAT_OF_DIR(sbuf))
1155 mode |= aDIR;
1156 else
1157 mode &= ~aDIR;
1159 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1160 reply_unixerror(req, ERRDOS, ERRnoaccess);
1161 END_PROFILE(SMBsetatr);
1162 return;
1166 reply_outbuf(req, 0, 0);
1168 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1170 END_PROFILE(SMBsetatr);
1171 return;
1174 /****************************************************************************
1175 Reply to a dskattr.
1176 ****************************************************************************/
1178 void reply_dskattr(struct smb_request *req)
1180 connection_struct *conn = req->conn;
1181 SMB_BIG_UINT dfree,dsize,bsize;
1182 START_PROFILE(SMBdskattr);
1184 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1185 reply_unixerror(req, ERRHRD, ERRgeneral);
1186 END_PROFILE(SMBdskattr);
1187 return;
1190 reply_outbuf(req, 5, 0);
1192 if (Protocol <= PROTOCOL_LANMAN2) {
1193 double total_space, free_space;
1194 /* we need to scale this to a number that DOS6 can handle. We
1195 use floating point so we can handle large drives on systems
1196 that don't have 64 bit integers
1198 we end up displaying a maximum of 2G to DOS systems
1200 total_space = dsize * (double)bsize;
1201 free_space = dfree * (double)bsize;
1203 dsize = (SMB_BIG_UINT)((total_space+63*512) / (64*512));
1204 dfree = (SMB_BIG_UINT)((free_space+63*512) / (64*512));
1206 if (dsize > 0xFFFF) dsize = 0xFFFF;
1207 if (dfree > 0xFFFF) dfree = 0xFFFF;
1209 SSVAL(req->outbuf,smb_vwv0,dsize);
1210 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1211 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1212 SSVAL(req->outbuf,smb_vwv3,dfree);
1213 } else {
1214 SSVAL(req->outbuf,smb_vwv0,dsize);
1215 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1216 SSVAL(req->outbuf,smb_vwv2,512);
1217 SSVAL(req->outbuf,smb_vwv3,dfree);
1220 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1222 END_PROFILE(SMBdskattr);
1223 return;
1226 /****************************************************************************
1227 Reply to a search.
1228 Can be called from SMBsearch, SMBffirst or SMBfunique.
1229 ****************************************************************************/
1231 void reply_search(struct smb_request *req)
1233 connection_struct *conn = req->conn;
1234 char *mask = NULL;
1235 char *directory = NULL;
1236 char *fname = NULL;
1237 SMB_OFF_T size;
1238 uint32 mode;
1239 time_t date;
1240 uint32 dirtype;
1241 unsigned int numentries = 0;
1242 unsigned int maxentries = 0;
1243 bool finished = False;
1244 char *p;
1245 int status_len;
1246 char *path = NULL;
1247 char status[21];
1248 int dptr_num= -1;
1249 bool check_descend = False;
1250 bool expect_close = False;
1251 NTSTATUS nt_status;
1252 bool mask_contains_wcard = False;
1253 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1254 TALLOC_CTX *ctx = talloc_tos();
1255 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1257 START_PROFILE(SMBsearch);
1259 if (req->wct < 2) {
1260 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1261 END_PROFILE(SMBsearch);
1262 return;
1265 if (lp_posix_pathnames()) {
1266 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1267 END_PROFILE(SMBsearch);
1268 return;
1271 /* If we were called as SMBffirst then we must expect close. */
1272 if(CVAL(req->inbuf,smb_com) == SMBffirst) {
1273 expect_close = True;
1276 reply_outbuf(req, 1, 3);
1277 maxentries = SVAL(req->inbuf,smb_vwv0);
1278 dirtype = SVAL(req->inbuf,smb_vwv1);
1279 p = smb_buf(req->inbuf) + 1;
1280 p += srvstr_get_path_wcard(ctx,
1281 (char *)req->inbuf,
1282 req->flags2,
1283 &path,
1286 STR_TERMINATE,
1287 &nt_status,
1288 &mask_contains_wcard);
1289 if (!NT_STATUS_IS_OK(nt_status)) {
1290 reply_nterror(req, nt_status);
1291 END_PROFILE(SMBsearch);
1292 return;
1295 nt_status = resolve_dfspath_wcard(ctx, conn,
1296 req->flags2 & FLAGS2_DFS_PATHNAMES,
1297 path,
1298 &path,
1299 &mask_contains_wcard);
1300 if (!NT_STATUS_IS_OK(nt_status)) {
1301 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1302 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1303 ERRSRV, ERRbadpath);
1304 END_PROFILE(SMBsearch);
1305 return;
1307 reply_nterror(req, nt_status);
1308 END_PROFILE(SMBsearch);
1309 return;
1312 p++;
1313 status_len = SVAL(p, 0);
1314 p += 2;
1316 /* dirtype &= ~aDIR; */
1318 if (status_len == 0) {
1319 SMB_STRUCT_STAT sbuf;
1321 nt_status = unix_convert(ctx, conn, path, True,
1322 &directory, NULL, &sbuf);
1323 if (!NT_STATUS_IS_OK(nt_status)) {
1324 reply_nterror(req, nt_status);
1325 END_PROFILE(SMBsearch);
1326 return;
1329 nt_status = check_name(conn, directory);
1330 if (!NT_STATUS_IS_OK(nt_status)) {
1331 reply_nterror(req, nt_status);
1332 END_PROFILE(SMBsearch);
1333 return;
1336 p = strrchr_m(directory,'/');
1337 if (!p) {
1338 mask = directory;
1339 directory = talloc_strdup(ctx,".");
1340 if (!directory) {
1341 reply_nterror(req, NT_STATUS_NO_MEMORY);
1342 END_PROFILE(SMBsearch);
1343 return;
1345 } else {
1346 *p = 0;
1347 mask = p+1;
1350 if (*directory == '\0') {
1351 directory = talloc_strdup(ctx,".");
1352 if (!directory) {
1353 reply_nterror(req, NT_STATUS_NO_MEMORY);
1354 END_PROFILE(SMBsearch);
1355 return;
1358 memset((char *)status,'\0',21);
1359 SCVAL(status,0,(dirtype & 0x1F));
1361 nt_status = dptr_create(conn,
1362 directory,
1363 True,
1364 expect_close,
1365 req->smbpid,
1366 mask,
1367 mask_contains_wcard,
1368 dirtype,
1369 &conn->dirptr);
1370 if (!NT_STATUS_IS_OK(nt_status)) {
1371 reply_nterror(req, nt_status);
1372 END_PROFILE(SMBsearch);
1373 return;
1375 dptr_num = dptr_dnum(conn->dirptr);
1376 } else {
1377 int status_dirtype;
1379 memcpy(status,p,21);
1380 status_dirtype = CVAL(status,0) & 0x1F;
1381 if (status_dirtype != (dirtype & 0x1F)) {
1382 dirtype = status_dirtype;
1385 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1386 if (!conn->dirptr) {
1387 goto SearchEmpty;
1389 string_set(&conn->dirpath,dptr_path(dptr_num));
1390 mask = dptr_wcard(dptr_num);
1391 if (!mask) {
1392 goto SearchEmpty;
1395 * For a 'continue' search we have no string. So
1396 * check from the initial saved string.
1398 mask_contains_wcard = ms_has_wild(mask);
1399 dirtype = dptr_attr(dptr_num);
1402 DEBUG(4,("dptr_num is %d\n",dptr_num));
1404 if ((dirtype&0x1F) == aVOLID) {
1405 char buf[DIR_STRUCT_SIZE];
1406 memcpy(buf,status,21);
1407 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1408 0,aVOLID,0,!allow_long_path_components)) {
1409 reply_nterror(req, NT_STATUS_NO_MEMORY);
1410 END_PROFILE(SMBsearch);
1411 return;
1413 dptr_fill(buf+12,dptr_num);
1414 if (dptr_zero(buf+12) && (status_len==0)) {
1415 numentries = 1;
1416 } else {
1417 numentries = 0;
1419 if (message_push_blob(&req->outbuf,
1420 data_blob_const(buf, sizeof(buf)))
1421 == -1) {
1422 reply_nterror(req, NT_STATUS_NO_MEMORY);
1423 END_PROFILE(SMBsearch);
1424 return;
1426 } else {
1427 unsigned int i;
1428 maxentries = MIN(
1429 maxentries,
1430 ((BUFFER_SIZE -
1431 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1432 /DIR_STRUCT_SIZE));
1434 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1435 conn->dirpath,lp_dontdescend(SNUM(conn))));
1436 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1437 check_descend = True;
1440 for (i=numentries;(i<maxentries) && !finished;i++) {
1441 finished = !get_dir_entry(ctx,
1442 conn,
1443 mask,
1444 dirtype,
1445 &fname,
1446 &size,
1447 &mode,
1448 &date,
1449 check_descend,
1450 ask_sharemode);
1451 if (!finished) {
1452 char buf[DIR_STRUCT_SIZE];
1453 memcpy(buf,status,21);
1454 if (!make_dir_struct(ctx,
1455 buf,
1456 mask,
1457 fname,
1458 size,
1459 mode,
1460 date,
1461 !allow_long_path_components)) {
1462 reply_nterror(req, NT_STATUS_NO_MEMORY);
1463 END_PROFILE(SMBsearch);
1464 return;
1466 if (!dptr_fill(buf+12,dptr_num)) {
1467 break;
1469 if (message_push_blob(&req->outbuf,
1470 data_blob_const(buf, sizeof(buf)))
1471 == -1) {
1472 reply_nterror(req, NT_STATUS_NO_MEMORY);
1473 END_PROFILE(SMBsearch);
1474 return;
1476 numentries++;
1481 SearchEmpty:
1483 /* If we were called as SMBffirst with smb_search_id == NULL
1484 and no entries were found then return error and close dirptr
1485 (X/Open spec) */
1487 if (numentries == 0) {
1488 dptr_close(&dptr_num);
1489 } else if(expect_close && status_len == 0) {
1490 /* Close the dptr - we know it's gone */
1491 dptr_close(&dptr_num);
1494 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1495 if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) {
1496 dptr_close(&dptr_num);
1499 if ((numentries == 0) && !mask_contains_wcard) {
1500 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1501 END_PROFILE(SMBsearch);
1502 return;
1505 SSVAL(req->outbuf,smb_vwv0,numentries);
1506 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1507 SCVAL(smb_buf(req->outbuf),0,5);
1508 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1510 /* The replies here are never long name. */
1511 SSVAL(req->outbuf, smb_flg2,
1512 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1513 if (!allow_long_path_components) {
1514 SSVAL(req->outbuf, smb_flg2,
1515 SVAL(req->outbuf, smb_flg2)
1516 & (~FLAGS2_LONG_PATH_COMPONENTS));
1519 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1520 SSVAL(req->outbuf, smb_flg2,
1521 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1523 if (!directory) {
1524 directory = dptr_path(dptr_num);
1527 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1528 smb_fn_name(CVAL(req->inbuf,smb_com)),
1529 mask,
1530 directory ? directory : "./",
1531 dirtype,
1532 numentries,
1533 maxentries ));
1535 END_PROFILE(SMBsearch);
1536 return;
1539 /****************************************************************************
1540 Reply to a fclose (stop directory search).
1541 ****************************************************************************/
1543 void reply_fclose(struct smb_request *req)
1545 int status_len;
1546 char status[21];
1547 int dptr_num= -2;
1548 char *p;
1549 char *path = NULL;
1550 NTSTATUS err;
1551 bool path_contains_wcard = False;
1552 TALLOC_CTX *ctx = talloc_tos();
1554 START_PROFILE(SMBfclose);
1556 if (lp_posix_pathnames()) {
1557 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1558 END_PROFILE(SMBfclose);
1559 return;
1562 p = smb_buf(req->inbuf) + 1;
1563 p += srvstr_get_path_wcard(ctx,
1564 (char *)req->inbuf,
1565 req->flags2,
1566 &path,
1569 STR_TERMINATE,
1570 &err,
1571 &path_contains_wcard);
1572 if (!NT_STATUS_IS_OK(err)) {
1573 reply_nterror(req, err);
1574 END_PROFILE(SMBfclose);
1575 return;
1577 p++;
1578 status_len = SVAL(p,0);
1579 p += 2;
1581 if (status_len == 0) {
1582 reply_doserror(req, ERRSRV, ERRsrverror);
1583 END_PROFILE(SMBfclose);
1584 return;
1587 memcpy(status,p,21);
1589 if(dptr_fetch(status+12,&dptr_num)) {
1590 /* Close the dptr - we know it's gone */
1591 dptr_close(&dptr_num);
1594 reply_outbuf(req, 1, 0);
1595 SSVAL(req->outbuf,smb_vwv0,0);
1597 DEBUG(3,("search close\n"));
1599 END_PROFILE(SMBfclose);
1600 return;
1603 /****************************************************************************
1604 Reply to an open.
1605 ****************************************************************************/
1607 void reply_open(struct smb_request *req)
1609 connection_struct *conn = req->conn;
1610 char *fname = NULL;
1611 uint32 fattr=0;
1612 SMB_OFF_T size = 0;
1613 time_t mtime=0;
1614 int info;
1615 SMB_STRUCT_STAT sbuf;
1616 files_struct *fsp;
1617 int oplock_request;
1618 int deny_mode;
1619 uint32 dos_attr;
1620 uint32 access_mask;
1621 uint32 share_mode;
1622 uint32 create_disposition;
1623 uint32 create_options = 0;
1624 NTSTATUS status;
1625 TALLOC_CTX *ctx = talloc_tos();
1627 START_PROFILE(SMBopen);
1629 if (req->wct < 2) {
1630 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1631 END_PROFILE(SMBopen);
1632 return;
1635 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1636 deny_mode = SVAL(req->inbuf,smb_vwv0);
1637 dos_attr = SVAL(req->inbuf,smb_vwv1);
1639 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1640 smb_buf(req->inbuf)+1, 0,
1641 STR_TERMINATE, &status);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 reply_nterror(req, status);
1644 END_PROFILE(SMBopen);
1645 return;
1648 if (!map_open_params_to_ntcreate(
1649 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1650 &share_mode, &create_disposition, &create_options)) {
1651 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1652 END_PROFILE(SMBopen);
1653 return;
1656 status = create_file(conn, /* conn */
1657 req, /* req */
1658 0, /* root_dir_fid */
1659 fname, /* fname */
1660 access_mask, /* access_mask */
1661 share_mode, /* share_access */
1662 create_disposition, /* create_disposition*/
1663 create_options, /* create_options */
1664 dos_attr, /* file_attributes */
1665 oplock_request, /* oplock_request */
1666 0, /* allocation_size */
1667 NULL, /* sd */
1668 NULL, /* ea_list */
1669 &fsp, /* result */
1670 &info, /* pinfo */
1671 &sbuf); /* psbuf */
1673 if (!NT_STATUS_IS_OK(status)) {
1674 if (open_was_deferred(req->mid)) {
1675 /* We have re-scheduled this call. */
1676 END_PROFILE(SMBopen);
1677 return;
1679 reply_openerror(req, status);
1680 END_PROFILE(SMBopen);
1681 return;
1684 size = sbuf.st_size;
1685 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1686 mtime = sbuf.st_mtime;
1688 if (fattr & aDIR) {
1689 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1690 close_file(fsp,ERROR_CLOSE);
1691 reply_doserror(req, ERRDOS,ERRnoaccess);
1692 END_PROFILE(SMBopen);
1693 return;
1696 reply_outbuf(req, 7, 0);
1697 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1698 SSVAL(req->outbuf,smb_vwv1,fattr);
1699 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1700 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1701 } else {
1702 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1704 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1705 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1707 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1708 SCVAL(req->outbuf,smb_flg,
1709 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1712 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1713 SCVAL(req->outbuf,smb_flg,
1714 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1716 END_PROFILE(SMBopen);
1717 return;
1720 /****************************************************************************
1721 Reply to an open and X.
1722 ****************************************************************************/
1724 void reply_open_and_X(struct smb_request *req)
1726 connection_struct *conn = req->conn;
1727 char *fname = NULL;
1728 uint16 open_flags;
1729 int deny_mode;
1730 uint32 smb_attr;
1731 /* Breakout the oplock request bits so we can set the
1732 reply bits separately. */
1733 int ex_oplock_request;
1734 int core_oplock_request;
1735 int oplock_request;
1736 #if 0
1737 int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1738 uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1739 #endif
1740 int smb_ofun;
1741 uint32 fattr=0;
1742 int mtime=0;
1743 SMB_STRUCT_STAT sbuf;
1744 int smb_action = 0;
1745 files_struct *fsp;
1746 NTSTATUS status;
1747 SMB_BIG_UINT allocation_size;
1748 ssize_t retval = -1;
1749 uint32 access_mask;
1750 uint32 share_mode;
1751 uint32 create_disposition;
1752 uint32 create_options = 0;
1753 TALLOC_CTX *ctx = talloc_tos();
1755 START_PROFILE(SMBopenX);
1757 if (req->wct < 15) {
1758 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1759 END_PROFILE(SMBopenX);
1760 return;
1763 open_flags = SVAL(req->inbuf,smb_vwv2);
1764 deny_mode = SVAL(req->inbuf,smb_vwv3);
1765 smb_attr = SVAL(req->inbuf,smb_vwv5);
1766 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1767 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1768 oplock_request = ex_oplock_request | core_oplock_request;
1769 smb_ofun = SVAL(req->inbuf,smb_vwv8);
1770 allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1772 /* If it's an IPC, pass off the pipe handler. */
1773 if (IS_IPC(conn)) {
1774 if (lp_nt_pipe_support()) {
1775 reply_open_pipe_and_X(conn, req);
1776 } else {
1777 reply_doserror(req, ERRSRV, ERRaccess);
1779 END_PROFILE(SMBopenX);
1780 return;
1783 /* XXXX we need to handle passed times, sattr and flags */
1784 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1785 smb_buf(req->inbuf), 0, STR_TERMINATE,
1786 &status);
1787 if (!NT_STATUS_IS_OK(status)) {
1788 reply_nterror(req, status);
1789 END_PROFILE(SMBopenX);
1790 return;
1793 if (!map_open_params_to_ntcreate(
1794 fname, deny_mode, smb_ofun, &access_mask,
1795 &share_mode, &create_disposition, &create_options)) {
1796 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1797 END_PROFILE(SMBopenX);
1798 return;
1801 status = create_file(conn, /* conn */
1802 req, /* req */
1803 0, /* root_dir_fid */
1804 fname, /* fname */
1805 access_mask, /* access_mask */
1806 share_mode, /* share_access */
1807 create_disposition, /* create_disposition*/
1808 create_options, /* create_options */
1809 smb_attr, /* file_attributes */
1810 oplock_request, /* oplock_request */
1811 0, /* allocation_size */
1812 NULL, /* sd */
1813 NULL, /* ea_list */
1814 &fsp, /* result */
1815 &smb_action, /* pinfo */
1816 &sbuf); /* psbuf */
1818 if (!NT_STATUS_IS_OK(status)) {
1819 END_PROFILE(SMBopenX);
1820 if (open_was_deferred(req->mid)) {
1821 /* We have re-scheduled this call. */
1822 return;
1824 reply_openerror(req, status);
1825 return;
1828 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1829 if the file is truncated or created. */
1830 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1831 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1832 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1833 close_file(fsp,ERROR_CLOSE);
1834 reply_nterror(req, NT_STATUS_DISK_FULL);
1835 END_PROFILE(SMBopenX);
1836 return;
1838 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1839 if (retval < 0) {
1840 close_file(fsp,ERROR_CLOSE);
1841 reply_nterror(req, NT_STATUS_DISK_FULL);
1842 END_PROFILE(SMBopenX);
1843 return;
1845 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1848 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1849 mtime = sbuf.st_mtime;
1850 if (fattr & aDIR) {
1851 close_file(fsp,ERROR_CLOSE);
1852 reply_doserror(req, ERRDOS, ERRnoaccess);
1853 END_PROFILE(SMBopenX);
1854 return;
1857 /* If the caller set the extended oplock request bit
1858 and we granted one (by whatever means) - set the
1859 correct bit for extended oplock reply.
1862 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1863 smb_action |= EXTENDED_OPLOCK_GRANTED;
1866 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1867 smb_action |= EXTENDED_OPLOCK_GRANTED;
1870 /* If the caller set the core oplock request bit
1871 and we granted one (by whatever means) - set the
1872 correct bit for core oplock reply.
1875 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1876 reply_outbuf(req, 19, 0);
1877 } else {
1878 reply_outbuf(req, 15, 0);
1881 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1882 SCVAL(req->outbuf, smb_flg,
1883 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1886 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1887 SCVAL(req->outbuf, smb_flg,
1888 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1891 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1892 SSVAL(req->outbuf,smb_vwv3,fattr);
1893 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1894 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1895 } else {
1896 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1898 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1899 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1900 SSVAL(req->outbuf,smb_vwv11,smb_action);
1902 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1903 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1906 END_PROFILE(SMBopenX);
1907 chain_reply(req);
1908 return;
1911 /****************************************************************************
1912 Reply to a SMBulogoffX.
1913 ****************************************************************************/
1915 void reply_ulogoffX(struct smb_request *req)
1917 user_struct *vuser;
1919 START_PROFILE(SMBulogoffX);
1921 vuser = get_valid_user_struct(req->vuid);
1923 if(vuser == NULL) {
1924 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1925 req->vuid));
1928 /* in user level security we are supposed to close any files
1929 open by this user */
1930 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1931 file_close_user(req->vuid);
1934 invalidate_vuid(req->vuid);
1936 reply_outbuf(req, 2, 0);
1938 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1940 END_PROFILE(SMBulogoffX);
1941 chain_reply(req);
1944 /****************************************************************************
1945 Reply to a mknew or a create.
1946 ****************************************************************************/
1948 void reply_mknew(struct smb_request *req)
1950 connection_struct *conn = req->conn;
1951 char *fname = NULL;
1952 int com;
1953 uint32 fattr = 0;
1954 struct timespec ts[2];
1955 files_struct *fsp;
1956 int oplock_request = 0;
1957 SMB_STRUCT_STAT sbuf;
1958 NTSTATUS status;
1959 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1960 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1961 uint32 create_disposition;
1962 uint32 create_options = 0;
1963 TALLOC_CTX *ctx = talloc_tos();
1965 START_PROFILE(SMBcreate);
1967 if (req->wct < 3) {
1968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1969 END_PROFILE(SMBcreate);
1970 return;
1973 fattr = SVAL(req->inbuf,smb_vwv0);
1974 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1975 com = SVAL(req->inbuf,smb_com);
1977 ts[1] =convert_time_t_to_timespec(
1978 srv_make_unix_date3(req->inbuf + smb_vwv1));
1979 /* mtime. */
1981 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1982 smb_buf(req->inbuf) + 1, 0,
1983 STR_TERMINATE, &status);
1984 if (!NT_STATUS_IS_OK(status)) {
1985 reply_nterror(req, status);
1986 END_PROFILE(SMBcreate);
1987 return;
1990 if (fattr & aVOLID) {
1991 DEBUG(0,("Attempt to create file (%s) with volid set - "
1992 "please report this\n", fname));
1995 if(com == SMBmknew) {
1996 /* We should fail if file exists. */
1997 create_disposition = FILE_CREATE;
1998 } else {
1999 /* Create if file doesn't exist, truncate if it does. */
2000 create_disposition = FILE_OVERWRITE_IF;
2003 status = create_file(conn, /* conn */
2004 req, /* req */
2005 0, /* root_dir_fid */
2006 fname, /* fname */
2007 access_mask, /* access_mask */
2008 share_mode, /* share_access */
2009 create_disposition, /* create_disposition*/
2010 create_options, /* create_options */
2011 fattr, /* file_attributes */
2012 oplock_request, /* oplock_request */
2013 0, /* allocation_size */
2014 NULL, /* sd */
2015 NULL, /* ea_list */
2016 &fsp, /* result */
2017 NULL, /* pinfo */
2018 &sbuf); /* psbuf */
2020 if (!NT_STATUS_IS_OK(status)) {
2021 END_PROFILE(SMBcreate);
2022 if (open_was_deferred(req->mid)) {
2023 /* We have re-scheduled this call. */
2024 return;
2026 reply_openerror(req, status);
2027 return;
2030 ts[0] = get_atimespec(&sbuf); /* atime. */
2031 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, ts, true);
2032 if (!NT_STATUS_IS_OK(status)) {
2033 END_PROFILE(SMBcreate);
2034 reply_openerror(req, status);
2035 return;
2038 reply_outbuf(req, 1, 0);
2039 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2041 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2042 SCVAL(req->outbuf,smb_flg,
2043 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2046 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2047 SCVAL(req->outbuf,smb_flg,
2048 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2051 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2052 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2053 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2055 END_PROFILE(SMBcreate);
2056 return;
2059 /****************************************************************************
2060 Reply to a create temporary file.
2061 ****************************************************************************/
2063 void reply_ctemp(struct smb_request *req)
2065 connection_struct *conn = req->conn;
2066 char *fname = NULL;
2067 uint32 fattr;
2068 files_struct *fsp;
2069 int oplock_request;
2070 int tmpfd;
2071 SMB_STRUCT_STAT sbuf;
2072 char *s;
2073 NTSTATUS status;
2074 TALLOC_CTX *ctx = talloc_tos();
2076 START_PROFILE(SMBctemp);
2078 if (req->wct < 3) {
2079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2080 END_PROFILE(SMBctemp);
2081 return;
2084 fattr = SVAL(req->inbuf,smb_vwv0);
2085 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2087 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
2088 smb_buf(req->inbuf)+1, 0, STR_TERMINATE,
2089 &status);
2090 if (!NT_STATUS_IS_OK(status)) {
2091 reply_nterror(req, status);
2092 END_PROFILE(SMBctemp);
2093 return;
2095 if (*fname) {
2096 fname = talloc_asprintf(ctx,
2097 "%s/TMXXXXXX",
2098 fname);
2099 } else {
2100 fname = talloc_strdup(ctx, "TMXXXXXX");
2103 if (!fname) {
2104 reply_nterror(req, NT_STATUS_NO_MEMORY);
2105 END_PROFILE(SMBctemp);
2106 return;
2109 status = resolve_dfspath(ctx, conn,
2110 req->flags2 & FLAGS2_DFS_PATHNAMES,
2111 fname,
2112 &fname);
2113 if (!NT_STATUS_IS_OK(status)) {
2114 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2115 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2116 ERRSRV, ERRbadpath);
2117 END_PROFILE(SMBctemp);
2118 return;
2120 reply_nterror(req, status);
2121 END_PROFILE(SMBctemp);
2122 return;
2125 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 reply_nterror(req, status);
2128 END_PROFILE(SMBctemp);
2129 return;
2132 status = check_name(conn, fname);
2133 if (!NT_STATUS_IS_OK(status)) {
2134 reply_nterror(req, status);
2135 END_PROFILE(SMBctemp);
2136 return;
2139 tmpfd = smb_mkstemp(fname);
2140 if (tmpfd == -1) {
2141 reply_unixerror(req, ERRDOS, ERRnoaccess);
2142 END_PROFILE(SMBctemp);
2143 return;
2146 SMB_VFS_STAT(conn,fname,&sbuf);
2148 /* We should fail if file does not exist. */
2149 status = open_file_ntcreate(conn, req, fname, &sbuf,
2150 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
2151 FILE_SHARE_READ|FILE_SHARE_WRITE,
2152 FILE_OPEN,
2154 fattr,
2155 oplock_request,
2156 NULL, &fsp);
2158 /* close fd from smb_mkstemp() */
2159 close(tmpfd);
2161 if (!NT_STATUS_IS_OK(status)) {
2162 if (open_was_deferred(req->mid)) {
2163 /* We have re-scheduled this call. */
2164 END_PROFILE(SMBctemp);
2165 return;
2167 reply_openerror(req, status);
2168 END_PROFILE(SMBctemp);
2169 return;
2172 reply_outbuf(req, 1, 0);
2173 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2175 /* the returned filename is relative to the directory */
2176 s = strrchr_m(fsp->fsp_name, '/');
2177 if (!s) {
2178 s = fsp->fsp_name;
2179 } else {
2180 s++;
2183 #if 0
2184 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2185 thing in the byte section. JRA */
2186 SSVALS(p, 0, -1); /* what is this? not in spec */
2187 #endif
2188 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2189 == -1) {
2190 reply_nterror(req, NT_STATUS_NO_MEMORY);
2191 END_PROFILE(SMBctemp);
2192 return;
2195 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2196 SCVAL(req->outbuf, smb_flg,
2197 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2200 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2201 SCVAL(req->outbuf, smb_flg,
2202 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2205 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2206 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2207 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2209 END_PROFILE(SMBctemp);
2210 return;
2213 /*******************************************************************
2214 Check if a user is allowed to rename a file.
2215 ********************************************************************/
2217 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2218 uint16 dirtype, SMB_STRUCT_STAT *pst)
2220 uint32 fmode;
2222 if (!CAN_WRITE(conn)) {
2223 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2226 fmode = dos_mode(conn, fsp->fsp_name, pst);
2227 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2228 return NT_STATUS_NO_SUCH_FILE;
2231 if (S_ISDIR(pst->st_mode)) {
2232 return NT_STATUS_OK;
2235 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2236 return NT_STATUS_OK;
2239 return NT_STATUS_ACCESS_DENIED;
2242 /*******************************************************************
2243 * unlink a file with all relevant access checks
2244 *******************************************************************/
2246 static NTSTATUS do_unlink(connection_struct *conn,
2247 struct smb_request *req,
2248 const char *fname,
2249 uint32 dirtype)
2251 SMB_STRUCT_STAT sbuf;
2252 uint32 fattr;
2253 files_struct *fsp;
2254 uint32 dirtype_orig = dirtype;
2255 NTSTATUS status;
2257 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2259 if (!CAN_WRITE(conn)) {
2260 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2263 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2264 return map_nt_error_from_unix(errno);
2267 fattr = dos_mode(conn,fname,&sbuf);
2269 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2270 dirtype = aDIR|aARCH|aRONLY;
2273 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2274 if (!dirtype) {
2275 return NT_STATUS_NO_SUCH_FILE;
2278 if (!dir_check_ftype(conn, fattr, dirtype)) {
2279 if (fattr & aDIR) {
2280 return NT_STATUS_FILE_IS_A_DIRECTORY;
2282 return NT_STATUS_NO_SUCH_FILE;
2285 if (dirtype_orig & 0x8000) {
2286 /* These will never be set for POSIX. */
2287 return NT_STATUS_NO_SUCH_FILE;
2290 #if 0
2291 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2292 return NT_STATUS_FILE_IS_A_DIRECTORY;
2295 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2296 return NT_STATUS_NO_SUCH_FILE;
2299 if (dirtype & 0xFF00) {
2300 /* These will never be set for POSIX. */
2301 return NT_STATUS_NO_SUCH_FILE;
2304 dirtype &= 0xFF;
2305 if (!dirtype) {
2306 return NT_STATUS_NO_SUCH_FILE;
2309 /* Can't delete a directory. */
2310 if (fattr & aDIR) {
2311 return NT_STATUS_FILE_IS_A_DIRECTORY;
2313 #endif
2315 #if 0 /* JRATEST */
2316 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2317 return NT_STATUS_OBJECT_NAME_INVALID;
2318 #endif /* JRATEST */
2320 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2322 On a Windows share, a file with read-only dosmode can be opened with
2323 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2324 fails with NT_STATUS_CANNOT_DELETE error.
2326 This semantic causes a problem that a user can not
2327 rename a file with read-only dosmode on a Samba share
2328 from a Windows command prompt (i.e. cmd.exe, but can rename
2329 from Windows Explorer).
2332 if (!lp_delete_readonly(SNUM(conn))) {
2333 if (fattr & aRONLY) {
2334 return NT_STATUS_CANNOT_DELETE;
2338 /* On open checks the open itself will check the share mode, so
2339 don't do it here as we'll get it wrong. */
2341 status = create_file_unixpath
2342 (conn, /* conn */
2343 req, /* req */
2344 fname, /* fname */
2345 DELETE_ACCESS, /* access_mask */
2346 FILE_SHARE_NONE, /* share_access */
2347 FILE_OPEN, /* create_disposition*/
2348 FILE_NON_DIRECTORY_FILE, /* create_options */
2349 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2350 0, /* oplock_request */
2351 0, /* allocation_size */
2352 NULL, /* sd */
2353 NULL, /* ea_list */
2354 &fsp, /* result */
2355 NULL, /* pinfo */
2356 &sbuf); /* psbuf */
2358 if (!NT_STATUS_IS_OK(status)) {
2359 DEBUG(10, ("create_file_unixpath failed: %s\n",
2360 nt_errstr(status)));
2361 return status;
2364 /* The set is across all open files on this dev/inode pair. */
2365 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2366 close_file(fsp, NORMAL_CLOSE);
2367 return NT_STATUS_ACCESS_DENIED;
2370 return close_file(fsp,NORMAL_CLOSE);
2373 /****************************************************************************
2374 The guts of the unlink command, split out so it may be called by the NT SMB
2375 code.
2376 ****************************************************************************/
2378 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2379 uint32 dirtype, const char *name_in, bool has_wild)
2381 const char *directory = NULL;
2382 char *mask = NULL;
2383 char *name = NULL;
2384 char *p = NULL;
2385 int count=0;
2386 NTSTATUS status = NT_STATUS_OK;
2387 SMB_STRUCT_STAT sbuf;
2388 TALLOC_CTX *ctx = talloc_tos();
2390 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2391 if (!NT_STATUS_IS_OK(status)) {
2392 return status;
2395 p = strrchr_m(name,'/');
2396 if (!p) {
2397 directory = talloc_strdup(ctx, ".");
2398 if (!directory) {
2399 return NT_STATUS_NO_MEMORY;
2401 mask = name;
2402 } else {
2403 *p = 0;
2404 directory = name;
2405 mask = p+1;
2409 * We should only check the mangled cache
2410 * here if unix_convert failed. This means
2411 * that the path in 'mask' doesn't exist
2412 * on the file system and so we need to look
2413 * for a possible mangle. This patch from
2414 * Tine Smukavec <valentin.smukavec@hermes.si>.
2417 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2418 char *new_mask = NULL;
2419 mangle_lookup_name_from_8_3(ctx,
2420 mask,
2421 &new_mask,
2422 conn->params );
2423 if (new_mask) {
2424 mask = new_mask;
2428 if (!has_wild) {
2429 directory = talloc_asprintf(ctx,
2430 "%s/%s",
2431 directory,
2432 mask);
2433 if (!directory) {
2434 return NT_STATUS_NO_MEMORY;
2436 if (dirtype == 0) {
2437 dirtype = FILE_ATTRIBUTE_NORMAL;
2440 status = check_name(conn, directory);
2441 if (!NT_STATUS_IS_OK(status)) {
2442 return status;
2445 status = do_unlink(conn, req, directory, dirtype);
2446 if (!NT_STATUS_IS_OK(status)) {
2447 return status;
2450 count++;
2451 } else {
2452 struct smb_Dir *dir_hnd = NULL;
2453 long offset = 0;
2454 const char *dname;
2456 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2457 return NT_STATUS_OBJECT_NAME_INVALID;
2460 if (strequal(mask,"????????.???")) {
2461 mask[0] = '*';
2462 mask[1] = '\0';
2465 status = check_name(conn, directory);
2466 if (!NT_STATUS_IS_OK(status)) {
2467 return status;
2470 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2471 dirtype);
2472 if (dir_hnd == NULL) {
2473 return map_nt_error_from_unix(errno);
2476 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2477 the pattern matches against the long name, otherwise the short name
2478 We don't implement this yet XXXX
2481 status = NT_STATUS_NO_SUCH_FILE;
2483 while ((dname = ReadDirName(dir_hnd, &offset))) {
2484 SMB_STRUCT_STAT st;
2485 char *fname = NULL;
2487 if (!is_visible_file(conn, directory, dname, &st, True)) {
2488 continue;
2491 /* Quick check for "." and ".." */
2492 if (ISDOT(dname) || ISDOTDOT(dname)) {
2493 continue;
2496 if(!mask_match(dname, mask, conn->case_sensitive)) {
2497 continue;
2500 fname = talloc_asprintf(ctx, "%s/%s",
2501 directory,
2502 dname);
2503 if (!fname) {
2504 return NT_STATUS_NO_MEMORY;
2507 status = check_name(conn, fname);
2508 if (!NT_STATUS_IS_OK(status)) {
2509 TALLOC_FREE(dir_hnd);
2510 return status;
2513 status = do_unlink(conn, req, fname, dirtype);
2514 if (!NT_STATUS_IS_OK(status)) {
2515 TALLOC_FREE(fname);
2516 continue;
2519 count++;
2520 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2521 fname));
2523 TALLOC_FREE(fname);
2525 TALLOC_FREE(dir_hnd);
2528 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2529 status = map_nt_error_from_unix(errno);
2532 return status;
2535 /****************************************************************************
2536 Reply to a unlink
2537 ****************************************************************************/
2539 void reply_unlink(struct smb_request *req)
2541 connection_struct *conn = req->conn;
2542 char *name = NULL;
2543 uint32 dirtype;
2544 NTSTATUS status;
2545 bool path_contains_wcard = False;
2546 TALLOC_CTX *ctx = talloc_tos();
2548 START_PROFILE(SMBunlink);
2550 if (req->wct < 1) {
2551 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2552 END_PROFILE(SMBunlink);
2553 return;
2556 dirtype = SVAL(req->inbuf,smb_vwv0);
2558 srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name,
2559 smb_buf(req->inbuf) + 1, 0,
2560 STR_TERMINATE, &status, &path_contains_wcard);
2561 if (!NT_STATUS_IS_OK(status)) {
2562 reply_nterror(req, status);
2563 END_PROFILE(SMBunlink);
2564 return;
2567 status = resolve_dfspath_wcard(ctx, conn,
2568 req->flags2 & FLAGS2_DFS_PATHNAMES,
2569 name,
2570 &name,
2571 &path_contains_wcard);
2572 if (!NT_STATUS_IS_OK(status)) {
2573 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2574 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2575 ERRSRV, ERRbadpath);
2576 END_PROFILE(SMBunlink);
2577 return;
2579 reply_nterror(req, status);
2580 END_PROFILE(SMBunlink);
2581 return;
2584 DEBUG(3,("reply_unlink : %s\n",name));
2586 status = unlink_internals(conn, req, dirtype, name,
2587 path_contains_wcard);
2588 if (!NT_STATUS_IS_OK(status)) {
2589 if (open_was_deferred(req->mid)) {
2590 /* We have re-scheduled this call. */
2591 END_PROFILE(SMBunlink);
2592 return;
2594 reply_nterror(req, status);
2595 END_PROFILE(SMBunlink);
2596 return;
2599 reply_outbuf(req, 0, 0);
2600 END_PROFILE(SMBunlink);
2602 return;
2605 /****************************************************************************
2606 Fail for readbraw.
2607 ****************************************************************************/
2609 static void fail_readraw(void)
2611 const char *errstr = talloc_asprintf(talloc_tos(),
2612 "FAIL ! reply_readbraw: socket write fail (%s)",
2613 strerror(errno));
2614 if (!errstr) {
2615 errstr = "";
2617 exit_server_cleanly(errstr);
2620 /****************************************************************************
2621 Fake (read/write) sendfile. Returns -1 on read or write fail.
2622 ****************************************************************************/
2624 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2625 size_t nread)
2627 size_t bufsize;
2628 size_t tosend = nread;
2629 char *buf;
2631 if (nread == 0) {
2632 return 0;
2635 bufsize = MIN(nread, 65536);
2637 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2638 return -1;
2641 while (tosend > 0) {
2642 ssize_t ret;
2643 size_t cur_read;
2645 if (tosend > bufsize) {
2646 cur_read = bufsize;
2647 } else {
2648 cur_read = tosend;
2650 ret = read_file(fsp,buf,startpos,cur_read);
2651 if (ret == -1) {
2652 SAFE_FREE(buf);
2653 return -1;
2656 /* If we had a short read, fill with zeros. */
2657 if (ret < cur_read) {
2658 memset(buf, '\0', cur_read - ret);
2661 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2662 SAFE_FREE(buf);
2663 return -1;
2665 tosend -= cur_read;
2666 startpos += cur_read;
2669 SAFE_FREE(buf);
2670 return (ssize_t)nread;
2673 /****************************************************************************
2674 Return a readbraw error (4 bytes of zero).
2675 ****************************************************************************/
2677 static void reply_readbraw_error(void)
2679 char header[4];
2680 SIVAL(header,0,0);
2681 if (write_data(smbd_server_fd(),header,4) != 4) {
2682 fail_readraw();
2686 /****************************************************************************
2687 Use sendfile in readbraw.
2688 ****************************************************************************/
2690 void send_file_readbraw(connection_struct *conn,
2691 files_struct *fsp,
2692 SMB_OFF_T startpos,
2693 size_t nread,
2694 ssize_t mincount)
2696 char *outbuf = NULL;
2697 ssize_t ret=0;
2699 #if defined(WITH_SENDFILE)
2701 * We can only use sendfile on a non-chained packet
2702 * but we can use on a non-oplocked file. tridge proved this
2703 * on a train in Germany :-). JRA.
2704 * reply_readbraw has already checked the length.
2707 if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) &&
2708 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2709 char header[4];
2710 DATA_BLOB header_blob;
2712 _smb_setlen(header,nread);
2713 header_blob = data_blob_const(header, 4);
2715 if (SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2716 &header_blob, startpos, nread) == -1) {
2717 /* Returning ENOSYS means no data at all was sent.
2718 * Do this as a normal read. */
2719 if (errno == ENOSYS) {
2720 goto normal_readbraw;
2724 * Special hack for broken Linux with no working sendfile. If we
2725 * return EINTR we sent the header but not the rest of the data.
2726 * Fake this up by doing read/write calls.
2728 if (errno == EINTR) {
2729 /* Ensure we don't do this again. */
2730 set_use_sendfile(SNUM(conn), False);
2731 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2733 if (fake_sendfile(fsp, startpos, nread) == -1) {
2734 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2735 fsp->fsp_name, strerror(errno) ));
2736 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2738 return;
2741 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2742 fsp->fsp_name, strerror(errno) ));
2743 exit_server_cleanly("send_file_readbraw sendfile failed");
2746 return;
2748 #endif
2750 normal_readbraw:
2752 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2753 if (!outbuf) {
2754 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2755 (unsigned)(nread+4)));
2756 reply_readbraw_error();
2757 return;
2760 if (nread > 0) {
2761 ret = read_file(fsp,outbuf+4,startpos,nread);
2762 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2763 if (ret < mincount)
2764 ret = 0;
2765 #else
2766 if (ret < nread)
2767 ret = 0;
2768 #endif
2771 _smb_setlen(outbuf,ret);
2772 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2773 fail_readraw();
2775 TALLOC_FREE(outbuf);
2778 /****************************************************************************
2779 Reply to a readbraw (core+ protocol).
2780 ****************************************************************************/
2782 void reply_readbraw(struct smb_request *req)
2784 connection_struct *conn = req->conn;
2785 ssize_t maxcount,mincount;
2786 size_t nread = 0;
2787 SMB_OFF_T startpos;
2788 files_struct *fsp;
2789 SMB_STRUCT_STAT st;
2790 SMB_OFF_T size = 0;
2792 START_PROFILE(SMBreadbraw);
2794 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2795 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2796 "raw reads/writes are disallowed.");
2799 if (req->wct < 8) {
2800 reply_readbraw_error();
2801 END_PROFILE(SMBreadbraw);
2802 return;
2806 * Special check if an oplock break has been issued
2807 * and the readraw request croses on the wire, we must
2808 * return a zero length response here.
2811 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2814 * We have to do a check_fsp by hand here, as
2815 * we must always return 4 zero bytes on error,
2816 * not a NTSTATUS.
2819 if (!fsp || !conn || conn != fsp->conn ||
2820 req->vuid != fsp->vuid ||
2821 fsp->is_directory || fsp->fh->fd == -1) {
2823 * fsp could be NULL here so use the value from the packet. JRA.
2825 DEBUG(3,("reply_readbraw: fnum %d not valid "
2826 "- cache prime?\n",
2827 (int)SVAL(req->inbuf,smb_vwv0)));
2828 reply_readbraw_error();
2829 END_PROFILE(SMBreadbraw);
2830 return;
2833 /* Do a "by hand" version of CHECK_READ. */
2834 if (!(fsp->can_read ||
2835 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2836 (fsp->access_mask & FILE_EXECUTE)))) {
2837 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2838 (int)SVAL(req->inbuf,smb_vwv0)));
2839 reply_readbraw_error();
2840 END_PROFILE(SMBreadbraw);
2841 return;
2844 flush_write_cache(fsp, READRAW_FLUSH);
2846 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1);
2847 if(req->wct == 10) {
2849 * This is a large offset (64 bit) read.
2851 #ifdef LARGE_SMB_OFF_T
2853 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32);
2855 #else /* !LARGE_SMB_OFF_T */
2858 * Ensure we haven't been sent a >32 bit offset.
2861 if(IVAL(req->inbuf,smb_vwv8) != 0) {
2862 DEBUG(0,("reply_readbraw: large offset "
2863 "(%x << 32) used and we don't support "
2864 "64 bit offsets.\n",
2865 (unsigned int)IVAL(req->inbuf,smb_vwv8) ));
2866 reply_readbraw_error();
2867 END_PROFILE(SMBreadbraw);
2868 return;
2871 #endif /* LARGE_SMB_OFF_T */
2873 if(startpos < 0) {
2874 DEBUG(0,("reply_readbraw: negative 64 bit "
2875 "readraw offset (%.0f) !\n",
2876 (double)startpos ));
2877 reply_readbraw_error();
2878 END_PROFILE(SMBreadbraw);
2879 return;
2883 maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF);
2884 mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF);
2886 /* ensure we don't overrun the packet size */
2887 maxcount = MIN(65535,maxcount);
2889 if (is_locked(fsp,(uint32)req->smbpid,
2890 (SMB_BIG_UINT)maxcount,
2891 (SMB_BIG_UINT)startpos,
2892 READ_LOCK)) {
2893 reply_readbraw_error();
2894 END_PROFILE(SMBreadbraw);
2895 return;
2898 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
2899 size = st.st_size;
2902 if (startpos >= size) {
2903 nread = 0;
2904 } else {
2905 nread = MIN(maxcount,(size - startpos));
2908 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2909 if (nread < mincount)
2910 nread = 0;
2911 #endif
2913 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2914 "min=%lu nread=%lu\n",
2915 fsp->fnum, (double)startpos,
2916 (unsigned long)maxcount,
2917 (unsigned long)mincount,
2918 (unsigned long)nread ) );
2920 send_file_readbraw(conn, fsp, startpos, nread, mincount);
2922 DEBUG(5,("reply_readbraw finished\n"));
2923 END_PROFILE(SMBreadbraw);
2926 #undef DBGC_CLASS
2927 #define DBGC_CLASS DBGC_LOCKING
2929 /****************************************************************************
2930 Reply to a lockread (core+ protocol).
2931 ****************************************************************************/
2933 void reply_lockread(struct smb_request *req)
2935 connection_struct *conn = req->conn;
2936 ssize_t nread = -1;
2937 char *data;
2938 SMB_OFF_T startpos;
2939 size_t numtoread;
2940 NTSTATUS status;
2941 files_struct *fsp;
2942 struct byte_range_lock *br_lck = NULL;
2943 char *p = NULL;
2945 START_PROFILE(SMBlockread);
2947 if (req->wct < 5) {
2948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2949 END_PROFILE(SMBlockread);
2950 return;
2953 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2955 if (!check_fsp(conn, req, fsp)) {
2956 END_PROFILE(SMBlockread);
2957 return;
2960 if (!CHECK_READ(fsp,req->inbuf)) {
2961 reply_doserror(req, ERRDOS, ERRbadaccess);
2962 END_PROFILE(SMBlockread);
2963 return;
2966 release_level_2_oplocks_on_change(fsp);
2968 numtoread = SVAL(req->inbuf,smb_vwv1);
2969 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
2971 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
2973 reply_outbuf(req, 5, numtoread + 3);
2975 data = smb_buf(req->outbuf) + 3;
2978 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2979 * protocol request that predates the read/write lock concept.
2980 * Thus instead of asking for a read lock here we need to ask
2981 * for a write lock. JRA.
2982 * Note that the requested lock size is unaffected by max_recv.
2985 br_lck = do_lock(smbd_messaging_context(),
2986 fsp,
2987 req->smbpid,
2988 (SMB_BIG_UINT)numtoread,
2989 (SMB_BIG_UINT)startpos,
2990 WRITE_LOCK,
2991 WINDOWS_LOCK,
2992 False, /* Non-blocking lock. */
2993 &status,
2994 NULL);
2995 TALLOC_FREE(br_lck);
2997 if (NT_STATUS_V(status)) {
2998 reply_nterror(req, status);
2999 END_PROFILE(SMBlockread);
3000 return;
3004 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3007 if (numtoread > max_recv) {
3008 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3009 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3010 (unsigned int)numtoread, (unsigned int)max_recv ));
3011 numtoread = MIN(numtoread,max_recv);
3013 nread = read_file(fsp,data,startpos,numtoread);
3015 if (nread < 0) {
3016 reply_unixerror(req, ERRDOS, ERRnoaccess);
3017 END_PROFILE(SMBlockread);
3018 return;
3021 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3023 SSVAL(req->outbuf,smb_vwv0,nread);
3024 SSVAL(req->outbuf,smb_vwv5,nread+3);
3025 p = smb_buf(req->outbuf);
3026 SCVAL(p,0,0); /* pad byte. */
3027 SSVAL(p,1,nread);
3029 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3030 fsp->fnum, (int)numtoread, (int)nread));
3032 END_PROFILE(SMBlockread);
3033 return;
3036 #undef DBGC_CLASS
3037 #define DBGC_CLASS DBGC_ALL
3039 /****************************************************************************
3040 Reply to a read.
3041 ****************************************************************************/
3043 void reply_read(struct smb_request *req)
3045 connection_struct *conn = req->conn;
3046 size_t numtoread;
3047 ssize_t nread = 0;
3048 char *data;
3049 SMB_OFF_T startpos;
3050 int outsize = 0;
3051 files_struct *fsp;
3053 START_PROFILE(SMBread);
3055 if (req->wct < 3) {
3056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3057 END_PROFILE(SMBread);
3058 return;
3061 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3063 if (!check_fsp(conn, req, fsp)) {
3064 END_PROFILE(SMBread);
3065 return;
3068 if (!CHECK_READ(fsp,req->inbuf)) {
3069 reply_doserror(req, ERRDOS, ERRbadaccess);
3070 END_PROFILE(SMBread);
3071 return;
3074 numtoread = SVAL(req->inbuf,smb_vwv1);
3075 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3077 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3080 * The requested read size cannot be greater than max_recv. JRA.
3082 if (numtoread > max_recv) {
3083 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3084 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3085 (unsigned int)numtoread, (unsigned int)max_recv ));
3086 numtoread = MIN(numtoread,max_recv);
3089 reply_outbuf(req, 5, numtoread+3);
3091 data = smb_buf(req->outbuf) + 3;
3093 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtoread,
3094 (SMB_BIG_UINT)startpos, READ_LOCK)) {
3095 reply_doserror(req, ERRDOS,ERRlock);
3096 END_PROFILE(SMBread);
3097 return;
3100 if (numtoread > 0)
3101 nread = read_file(fsp,data,startpos,numtoread);
3103 if (nread < 0) {
3104 reply_unixerror(req, ERRDOS,ERRnoaccess);
3105 END_PROFILE(SMBread);
3106 return;
3109 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3111 SSVAL(req->outbuf,smb_vwv0,nread);
3112 SSVAL(req->outbuf,smb_vwv5,nread+3);
3113 SCVAL(smb_buf(req->outbuf),0,1);
3114 SSVAL(smb_buf(req->outbuf),1,nread);
3116 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3117 fsp->fnum, (int)numtoread, (int)nread ) );
3119 END_PROFILE(SMBread);
3120 return;
3123 /****************************************************************************
3124 Setup readX header.
3125 ****************************************************************************/
3127 static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3129 int outsize;
3130 char *data;
3132 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3133 data = smb_buf(outbuf);
3135 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3137 SCVAL(outbuf,smb_vwv0,0xFF);
3138 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3139 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3140 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3141 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3142 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3143 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3144 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3145 return outsize;
3148 /****************************************************************************
3149 Reply to a read and X - possibly using sendfile.
3150 ****************************************************************************/
3152 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3153 files_struct *fsp, SMB_OFF_T startpos,
3154 size_t smb_maxcnt)
3156 SMB_STRUCT_STAT sbuf;
3157 ssize_t nread = -1;
3159 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3160 reply_unixerror(req, ERRDOS, ERRnoaccess);
3161 return;
3164 if (startpos > sbuf.st_size) {
3165 smb_maxcnt = 0;
3166 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3167 smb_maxcnt = (sbuf.st_size - startpos);
3170 if (smb_maxcnt == 0) {
3171 goto normal_read;
3174 #if defined(WITH_SENDFILE)
3176 * We can only use sendfile on a non-chained packet
3177 * but we can use on a non-oplocked file. tridge proved this
3178 * on a train in Germany :-). JRA.
3181 if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
3182 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3183 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3184 uint8 headerbuf[smb_size + 12 * 2];
3185 DATA_BLOB header;
3188 * Set up the packet header before send. We
3189 * assume here the sendfile will work (get the
3190 * correct amount of data).
3193 header = data_blob_const(headerbuf, sizeof(headerbuf));
3195 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3196 setup_readX_header((char *)headerbuf, smb_maxcnt);
3198 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3199 /* Returning ENOSYS or EINVAL means no data at all was sent.
3200 Do this as a normal read. */
3201 if (errno == ENOSYS || errno == EINVAL) {
3202 goto normal_read;
3206 * Special hack for broken Linux with no working sendfile. If we
3207 * return EINTR we sent the header but not the rest of the data.
3208 * Fake this up by doing read/write calls.
3211 if (errno == EINTR) {
3212 /* Ensure we don't do this again. */
3213 set_use_sendfile(SNUM(conn), False);
3214 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3215 nread = fake_sendfile(fsp, startpos,
3216 smb_maxcnt);
3217 if (nread == -1) {
3218 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3219 fsp->fsp_name, strerror(errno) ));
3220 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3222 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3223 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3224 /* No outbuf here means successful sendfile. */
3225 TALLOC_FREE(req->outbuf);
3226 return;
3229 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3230 fsp->fsp_name, strerror(errno) ));
3231 exit_server_cleanly("send_file_readX sendfile failed");
3234 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3235 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3236 /* No outbuf here means successful sendfile. */
3237 TALLOC_FREE(req->outbuf);
3238 return;
3240 #endif
3242 normal_read:
3244 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3245 uint8 headerbuf[smb_size + 2*12];
3247 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3248 setup_readX_header((char *)headerbuf, smb_maxcnt);
3250 /* Send out the header. */
3251 if (write_data(smbd_server_fd(), (char *)headerbuf,
3252 sizeof(headerbuf)) != sizeof(headerbuf)) {
3253 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3254 fsp->fsp_name, strerror(errno) ));
3255 exit_server_cleanly("send_file_readX sendfile failed");
3257 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3258 if (nread == -1) {
3259 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3260 fsp->fsp_name, strerror(errno) ));
3261 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3263 TALLOC_FREE(req->outbuf);
3264 return;
3267 reply_outbuf(req, 12, smb_maxcnt);
3269 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3270 if (nread < 0) {
3271 reply_unixerror(req, ERRDOS, ERRnoaccess);
3272 return;
3275 setup_readX_header((char *)req->outbuf, nread);
3277 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3278 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3280 chain_reply(req);
3283 /****************************************************************************
3284 Reply to a read and X.
3285 ****************************************************************************/
3287 void reply_read_and_X(struct smb_request *req)
3289 connection_struct *conn = req->conn;
3290 files_struct *fsp;
3291 SMB_OFF_T startpos;
3292 size_t smb_maxcnt;
3293 bool big_readX = False;
3294 #if 0
3295 size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
3296 #endif
3298 START_PROFILE(SMBreadX);
3300 if ((req->wct != 10) && (req->wct != 12)) {
3301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3302 return;
3305 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3306 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3307 smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
3309 /* If it's an IPC, pass off the pipe handler. */
3310 if (IS_IPC(conn)) {
3311 reply_pipe_read_and_X(req);
3312 END_PROFILE(SMBreadX);
3313 return;
3316 if (!check_fsp(conn, req, fsp)) {
3317 END_PROFILE(SMBreadX);
3318 return;
3321 if (!CHECK_READ(fsp,req->inbuf)) {
3322 reply_doserror(req, ERRDOS,ERRbadaccess);
3323 END_PROFILE(SMBreadX);
3324 return;
3327 if (global_client_caps & CAP_LARGE_READX) {
3328 size_t upper_size = SVAL(req->inbuf,smb_vwv7);
3329 smb_maxcnt |= (upper_size<<16);
3330 if (upper_size > 1) {
3331 /* Can't do this on a chained packet. */
3332 if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
3333 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3334 END_PROFILE(SMBreadX);
3335 return;
3337 /* We currently don't do this on signed or sealed data. */
3338 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3339 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3340 END_PROFILE(SMBreadX);
3341 return;
3343 /* Is there room in the reply for this data ? */
3344 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3345 reply_nterror(req,
3346 NT_STATUS_INVALID_PARAMETER);
3347 END_PROFILE(SMBreadX);
3348 return;
3350 big_readX = True;
3354 if (req->wct == 12) {
3355 #ifdef LARGE_SMB_OFF_T
3357 * This is a large offset (64 bit) read.
3359 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
3361 #else /* !LARGE_SMB_OFF_T */
3364 * Ensure we haven't been sent a >32 bit offset.
3367 if(IVAL(req->inbuf,smb_vwv10) != 0) {
3368 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3369 "used and we don't support 64 bit offsets.\n",
3370 (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
3371 END_PROFILE(SMBreadX);
3372 reply_doserror(req, ERRDOS, ERRbadaccess);
3373 return;
3376 #endif /* LARGE_SMB_OFF_T */
3380 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
3381 (SMB_BIG_UINT)startpos, READ_LOCK)) {
3382 END_PROFILE(SMBreadX);
3383 reply_doserror(req, ERRDOS, ERRlock);
3384 return;
3387 if (!big_readX &&
3388 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3389 END_PROFILE(SMBreadX);
3390 return;
3393 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3395 END_PROFILE(SMBreadX);
3396 return;
3399 /****************************************************************************
3400 Error replies to writebraw must have smb_wct == 1. Fix this up.
3401 ****************************************************************************/
3403 void error_to_writebrawerr(struct smb_request *req)
3405 uint8 *old_outbuf = req->outbuf;
3407 reply_outbuf(req, 1, 0);
3409 memcpy(req->outbuf, old_outbuf, smb_size);
3410 TALLOC_FREE(old_outbuf);
3413 /****************************************************************************
3414 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3415 ****************************************************************************/
3417 void reply_writebraw(struct smb_request *req)
3419 connection_struct *conn = req->conn;
3420 char *buf = NULL;
3421 ssize_t nwritten=0;
3422 ssize_t total_written=0;
3423 size_t numtowrite=0;
3424 size_t tcount;
3425 SMB_OFF_T startpos;
3426 char *data=NULL;
3427 bool write_through;
3428 files_struct *fsp;
3429 NTSTATUS status;
3431 START_PROFILE(SMBwritebraw);
3434 * If we ever reply with an error, it must have the SMB command
3435 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3436 * we're finished.
3438 SCVAL(req->inbuf,smb_com,SMBwritec);
3440 if (srv_is_signing_active()) {
3441 END_PROFILE(SMBwritebraw);
3442 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3443 "raw reads/writes are disallowed.");
3446 if (req->wct < 12) {
3447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3448 error_to_writebrawerr(req);
3449 END_PROFILE(SMBwritebraw);
3450 return;
3453 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3454 if (!check_fsp(conn, req, fsp)) {
3455 error_to_writebrawerr(req);
3456 END_PROFILE(SMBwritebraw);
3457 return;
3460 if (!CHECK_WRITE(fsp)) {
3461 reply_doserror(req, ERRDOS, ERRbadaccess);
3462 error_to_writebrawerr(req);
3463 END_PROFILE(SMBwritebraw);
3464 return;
3467 tcount = IVAL(req->inbuf,smb_vwv1);
3468 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3469 write_through = BITSETW(req->inbuf+smb_vwv7,0);
3471 /* We have to deal with slightly different formats depending
3472 on whether we are using the core+ or lanman1.0 protocol */
3474 if(Protocol <= PROTOCOL_COREPLUS) {
3475 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3476 data = smb_buf(req->inbuf);
3477 } else {
3478 numtowrite = SVAL(req->inbuf,smb_vwv10);
3479 data = smb_base(req->inbuf) + SVAL(req->inbuf, smb_vwv11);
3482 /* Ensure we don't write bytes past the end of this packet. */
3483 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3485 error_to_writebrawerr(req);
3486 END_PROFILE(SMBwritebraw);
3487 return;
3490 if (is_locked(fsp,(uint32)req->smbpid,(SMB_BIG_UINT)tcount,
3491 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3492 reply_doserror(req, ERRDOS, ERRlock);
3493 error_to_writebrawerr(req);
3494 END_PROFILE(SMBwritebraw);
3495 return;
3498 if (numtowrite>0) {
3499 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3502 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3503 "wrote=%d sync=%d\n",
3504 fsp->fnum, (double)startpos, (int)numtowrite,
3505 (int)nwritten, (int)write_through));
3507 if (nwritten < (ssize_t)numtowrite) {
3508 reply_unixerror(req, ERRHRD, ERRdiskfull);
3509 error_to_writebrawerr(req);
3510 END_PROFILE(SMBwritebraw);
3511 return;
3514 total_written = nwritten;
3516 /* Allocate a buffer of 64k + length. */
3517 buf = TALLOC_ARRAY(NULL, char, 65540);
3518 if (!buf) {
3519 reply_doserror(req, ERRDOS, ERRnomem);
3520 error_to_writebrawerr(req);
3521 END_PROFILE(SMBwritebraw);
3522 return;
3525 /* Return a SMBwritebraw message to the redirector to tell
3526 * it to send more bytes */
3528 memcpy(buf, req->inbuf, smb_size);
3529 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3530 SCVAL(buf,smb_com,SMBwritebraw);
3531 SSVALS(buf,smb_vwv0,0xFFFF);
3532 show_msg(buf);
3533 if (!srv_send_smb(smbd_server_fd(),
3534 buf,
3535 IS_CONN_ENCRYPTED(conn))) {
3536 exit_server_cleanly("reply_writebraw: srv_send_smb "
3537 "failed.");
3540 /* Now read the raw data into the buffer and write it */
3541 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3542 &numtowrite);
3543 if (!NT_STATUS_IS_OK(status)) {
3544 exit_server_cleanly("secondary writebraw failed");
3547 /* Set up outbuf to return the correct size */
3548 reply_outbuf(req, 1, 0);
3550 if (numtowrite != 0) {
3552 if (numtowrite > 0xFFFF) {
3553 DEBUG(0,("reply_writebraw: Oversize secondary write "
3554 "raw requested (%u). Terminating\n",
3555 (unsigned int)numtowrite ));
3556 exit_server_cleanly("secondary writebraw failed");
3559 if (tcount > nwritten+numtowrite) {
3560 DEBUG(3,("reply_writebraw: Client overestimated the "
3561 "write %d %d %d\n",
3562 (int)tcount,(int)nwritten,(int)numtowrite));
3565 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3567 if (!NT_STATUS_IS_OK(status)) {
3568 DEBUG(0,("reply_writebraw: Oversize secondary write "
3569 "raw read failed (%s). Terminating\n",
3570 nt_errstr(status)));
3571 exit_server_cleanly("secondary writebraw failed");
3574 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3575 if (nwritten == -1) {
3576 TALLOC_FREE(buf);
3577 reply_unixerror(req, ERRHRD, ERRdiskfull);
3578 error_to_writebrawerr(req);
3579 END_PROFILE(SMBwritebraw);
3580 return;
3583 if (nwritten < (ssize_t)numtowrite) {
3584 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3585 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3588 if (nwritten > 0) {
3589 total_written += nwritten;
3593 TALLOC_FREE(buf);
3594 SSVAL(req->outbuf,smb_vwv0,total_written);
3596 status = sync_file(conn, fsp, write_through);
3597 if (!NT_STATUS_IS_OK(status)) {
3598 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3599 fsp->fsp_name, nt_errstr(status) ));
3600 reply_nterror(req, status);
3601 error_to_writebrawerr(req);
3602 END_PROFILE(SMBwritebraw);
3603 return;
3606 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3607 "wrote=%d\n",
3608 fsp->fnum, (double)startpos, (int)numtowrite,
3609 (int)total_written));
3611 /* We won't return a status if write through is not selected - this
3612 * follows what WfWg does */
3613 END_PROFILE(SMBwritebraw);
3615 if (!write_through && total_written==tcount) {
3617 #if RABBIT_PELLET_FIX
3619 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3620 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3621 * JRA.
3623 if (!send_keepalive(smbd_server_fd())) {
3624 exit_server_cleanly("reply_writebraw: send of "
3625 "keepalive failed");
3627 #endif
3628 TALLOC_FREE(req->outbuf);
3630 return;
3633 #undef DBGC_CLASS
3634 #define DBGC_CLASS DBGC_LOCKING
3636 /****************************************************************************
3637 Reply to a writeunlock (core+).
3638 ****************************************************************************/
3640 void reply_writeunlock(struct smb_request *req)
3642 connection_struct *conn = req->conn;
3643 ssize_t nwritten = -1;
3644 size_t numtowrite;
3645 SMB_OFF_T startpos;
3646 char *data;
3647 NTSTATUS status = NT_STATUS_OK;
3648 files_struct *fsp;
3650 START_PROFILE(SMBwriteunlock);
3652 if (req->wct < 5) {
3653 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3654 END_PROFILE(SMBwriteunlock);
3655 return;
3658 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3660 if (!check_fsp(conn, req, fsp)) {
3661 END_PROFILE(SMBwriteunlock);
3662 return;
3665 if (!CHECK_WRITE(fsp)) {
3666 reply_doserror(req, ERRDOS,ERRbadaccess);
3667 END_PROFILE(SMBwriteunlock);
3668 return;
3671 numtowrite = SVAL(req->inbuf,smb_vwv1);
3672 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3673 data = smb_buf(req->inbuf) + 3;
3675 if (numtowrite
3676 && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3677 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3678 reply_doserror(req, ERRDOS, ERRlock);
3679 END_PROFILE(SMBwriteunlock);
3680 return;
3683 /* The special X/Open SMB protocol handling of
3684 zero length writes is *NOT* done for
3685 this call */
3686 if(numtowrite == 0) {
3687 nwritten = 0;
3688 } else {
3689 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3692 status = sync_file(conn, fsp, False /* write through */);
3693 if (!NT_STATUS_IS_OK(status)) {
3694 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3695 fsp->fsp_name, nt_errstr(status) ));
3696 reply_nterror(req, status);
3697 END_PROFILE(SMBwriteunlock);
3698 return;
3701 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3702 reply_unixerror(req, ERRHRD, ERRdiskfull);
3703 END_PROFILE(SMBwriteunlock);
3704 return;
3707 if (numtowrite) {
3708 status = do_unlock(smbd_messaging_context(),
3709 fsp,
3710 req->smbpid,
3711 (SMB_BIG_UINT)numtowrite,
3712 (SMB_BIG_UINT)startpos,
3713 WINDOWS_LOCK);
3715 if (NT_STATUS_V(status)) {
3716 reply_nterror(req, status);
3717 END_PROFILE(SMBwriteunlock);
3718 return;
3722 reply_outbuf(req, 1, 0);
3724 SSVAL(req->outbuf,smb_vwv0,nwritten);
3726 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3727 fsp->fnum, (int)numtowrite, (int)nwritten));
3729 END_PROFILE(SMBwriteunlock);
3730 return;
3733 #undef DBGC_CLASS
3734 #define DBGC_CLASS DBGC_ALL
3736 /****************************************************************************
3737 Reply to a write.
3738 ****************************************************************************/
3740 void reply_write(struct smb_request *req)
3742 connection_struct *conn = req->conn;
3743 size_t numtowrite;
3744 ssize_t nwritten = -1;
3745 SMB_OFF_T startpos;
3746 char *data;
3747 files_struct *fsp;
3748 NTSTATUS status;
3750 START_PROFILE(SMBwrite);
3752 if (req->wct < 5) {
3753 END_PROFILE(SMBwrite);
3754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3755 return;
3758 /* If it's an IPC, pass off the pipe handler. */
3759 if (IS_IPC(conn)) {
3760 reply_pipe_write(req);
3761 END_PROFILE(SMBwrite);
3762 return;
3765 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3767 if (!check_fsp(conn, req, fsp)) {
3768 END_PROFILE(SMBwrite);
3769 return;
3772 if (!CHECK_WRITE(fsp)) {
3773 reply_doserror(req, ERRDOS, ERRbadaccess);
3774 END_PROFILE(SMBwrite);
3775 return;
3778 numtowrite = SVAL(req->inbuf,smb_vwv1);
3779 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3780 data = smb_buf(req->inbuf) + 3;
3782 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3783 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3784 reply_doserror(req, ERRDOS, ERRlock);
3785 END_PROFILE(SMBwrite);
3786 return;
3790 * X/Open SMB protocol says that if smb_vwv1 is
3791 * zero then the file size should be extended or
3792 * truncated to the size given in smb_vwv[2-3].
3795 if(numtowrite == 0) {
3797 * This is actually an allocate call, and set EOF. JRA.
3799 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3800 if (nwritten < 0) {
3801 reply_nterror(req, NT_STATUS_DISK_FULL);
3802 END_PROFILE(SMBwrite);
3803 return;
3805 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3806 if (nwritten < 0) {
3807 reply_nterror(req, NT_STATUS_DISK_FULL);
3808 END_PROFILE(SMBwrite);
3809 return;
3811 trigger_write_time_update_immediate(fsp);
3812 } else {
3813 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3816 status = sync_file(conn, fsp, False);
3817 if (!NT_STATUS_IS_OK(status)) {
3818 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3819 fsp->fsp_name, nt_errstr(status) ));
3820 reply_nterror(req, status);
3821 END_PROFILE(SMBwrite);
3822 return;
3825 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3826 reply_unixerror(req, ERRHRD, ERRdiskfull);
3827 END_PROFILE(SMBwrite);
3828 return;
3831 reply_outbuf(req, 1, 0);
3833 SSVAL(req->outbuf,smb_vwv0,nwritten);
3835 if (nwritten < (ssize_t)numtowrite) {
3836 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3837 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3840 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3842 END_PROFILE(SMBwrite);
3843 return;
3846 /****************************************************************************
3847 Ensure a buffer is a valid writeX for recvfile purposes.
3848 ****************************************************************************/
3850 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3851 (2*14) + /* word count (including bcc) */ \
3852 1 /* pad byte */)
3854 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3856 size_t numtowrite;
3857 connection_struct *conn = NULL;
3858 unsigned int doff = 0;
3859 size_t len = smb_len_large(inbuf);
3861 if (is_encrypted_packet(inbuf)) {
3862 /* Can't do this on encrypted
3863 * connections. */
3864 return false;
3867 if (CVAL(inbuf,smb_com) != SMBwriteX) {
3868 return false;
3871 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3872 CVAL(inbuf,smb_wct) != 14) {
3873 DEBUG(10,("is_valid_writeX_buffer: chained or "
3874 "invalid word length.\n"));
3875 return false;
3878 conn = conn_find(SVAL(inbuf, smb_tid));
3879 if (conn == NULL) {
3880 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3881 return false;
3883 if (IS_IPC(conn)) {
3884 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3885 return false;
3887 doff = SVAL(inbuf,smb_vwv11);
3889 numtowrite = SVAL(inbuf,smb_vwv10);
3891 if (len > doff && len - doff > 0xFFFF) {
3892 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3895 if (numtowrite == 0) {
3896 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3897 return false;
3900 /* Ensure the sizes match up. */
3901 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3902 /* no pad byte...old smbclient :-( */
3903 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3904 (unsigned int)doff,
3905 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3906 return false;
3909 if (len - doff != numtowrite) {
3910 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3911 "len = %u, doff = %u, numtowrite = %u\n",
3912 (unsigned int)len,
3913 (unsigned int)doff,
3914 (unsigned int)numtowrite ));
3915 return false;
3918 DEBUG(10,("is_valid_writeX_buffer: true "
3919 "len = %u, doff = %u, numtowrite = %u\n",
3920 (unsigned int)len,
3921 (unsigned int)doff,
3922 (unsigned int)numtowrite ));
3924 return true;
3927 /****************************************************************************
3928 Reply to a write and X.
3929 ****************************************************************************/
3931 void reply_write_and_X(struct smb_request *req)
3933 connection_struct *conn = req->conn;
3934 files_struct *fsp;
3935 SMB_OFF_T startpos;
3936 size_t numtowrite;
3937 bool write_through;
3938 ssize_t nwritten;
3939 unsigned int smb_doff;
3940 unsigned int smblen;
3941 char *data;
3942 NTSTATUS status;
3944 START_PROFILE(SMBwriteX);
3946 if ((req->wct != 12) && (req->wct != 14)) {
3947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3948 END_PROFILE(SMBwriteX);
3949 return;
3952 numtowrite = SVAL(req->inbuf,smb_vwv10);
3953 smb_doff = SVAL(req->inbuf,smb_vwv11);
3954 smblen = smb_len(req->inbuf);
3956 if (req->unread_bytes > 0xFFFF ||
3957 (smblen > smb_doff &&
3958 smblen - smb_doff > 0xFFFF)) {
3959 numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16);
3962 if (req->unread_bytes) {
3963 /* Can't do a recvfile write on IPC$ */
3964 if (IS_IPC(conn)) {
3965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3966 END_PROFILE(SMBwriteX);
3967 return;
3969 if (numtowrite != req->unread_bytes) {
3970 reply_doserror(req, ERRDOS, ERRbadmem);
3971 END_PROFILE(SMBwriteX);
3972 return;
3974 } else {
3975 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
3976 smb_doff + numtowrite > smblen) {
3977 reply_doserror(req, ERRDOS, ERRbadmem);
3978 END_PROFILE(SMBwriteX);
3979 return;
3983 /* If it's an IPC, pass off the pipe handler. */
3984 if (IS_IPC(conn)) {
3985 if (req->unread_bytes) {
3986 reply_doserror(req, ERRDOS, ERRbadmem);
3987 END_PROFILE(SMBwriteX);
3988 return;
3990 reply_pipe_write_and_X(req);
3991 END_PROFILE(SMBwriteX);
3992 return;
3995 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3996 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3997 write_through = BITSETW(req->inbuf+smb_vwv7,0);
3999 if (!check_fsp(conn, req, fsp)) {
4000 END_PROFILE(SMBwriteX);
4001 return;
4004 if (!CHECK_WRITE(fsp)) {
4005 reply_doserror(req, ERRDOS, ERRbadaccess);
4006 END_PROFILE(SMBwriteX);
4007 return;
4010 data = smb_base(req->inbuf) + smb_doff;
4012 if(req->wct == 14) {
4013 #ifdef LARGE_SMB_OFF_T
4015 * This is a large offset (64 bit) write.
4017 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
4019 #else /* !LARGE_SMB_OFF_T */
4022 * Ensure we haven't been sent a >32 bit offset.
4025 if(IVAL(req->inbuf,smb_vwv12) != 0) {
4026 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4027 "used and we don't support 64 bit offsets.\n",
4028 (unsigned int)IVAL(req->inbuf,smb_vwv12) ));
4029 reply_doserror(req, ERRDOS, ERRbadaccess);
4030 END_PROFILE(SMBwriteX);
4031 return;
4034 #endif /* LARGE_SMB_OFF_T */
4037 if (is_locked(fsp,(uint32)req->smbpid,
4038 (SMB_BIG_UINT)numtowrite,
4039 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4040 reply_doserror(req, ERRDOS, ERRlock);
4041 END_PROFILE(SMBwriteX);
4042 return;
4045 /* X/Open SMB protocol says that, unlike SMBwrite
4046 if the length is zero then NO truncation is
4047 done, just a write of zero. To truncate a file,
4048 use SMBwrite. */
4050 if(numtowrite == 0) {
4051 nwritten = 0;
4052 } else {
4054 if ((req->unread_bytes == 0) &&
4055 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4056 numtowrite)) {
4057 END_PROFILE(SMBwriteX);
4058 return;
4061 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4064 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4065 reply_unixerror(req, ERRHRD, ERRdiskfull);
4066 END_PROFILE(SMBwriteX);
4067 return;
4070 reply_outbuf(req, 6, 0);
4071 SSVAL(req->outbuf,smb_vwv2,nwritten);
4072 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4074 if (nwritten < (ssize_t)numtowrite) {
4075 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4076 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4079 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4080 fsp->fnum, (int)numtowrite, (int)nwritten));
4082 status = sync_file(conn, fsp, write_through);
4083 if (!NT_STATUS_IS_OK(status)) {
4084 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4085 fsp->fsp_name, nt_errstr(status) ));
4086 reply_nterror(req, status);
4087 END_PROFILE(SMBwriteX);
4088 return;
4091 END_PROFILE(SMBwriteX);
4092 chain_reply(req);
4093 return;
4096 /****************************************************************************
4097 Reply to a lseek.
4098 ****************************************************************************/
4100 void reply_lseek(struct smb_request *req)
4102 connection_struct *conn = req->conn;
4103 SMB_OFF_T startpos;
4104 SMB_OFF_T res= -1;
4105 int mode,umode;
4106 files_struct *fsp;
4108 START_PROFILE(SMBlseek);
4110 if (req->wct < 4) {
4111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4112 END_PROFILE(SMBlseek);
4113 return;
4116 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4118 if (!check_fsp(conn, req, fsp)) {
4119 return;
4122 flush_write_cache(fsp, SEEK_FLUSH);
4124 mode = SVAL(req->inbuf,smb_vwv1) & 3;
4125 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4126 startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2);
4128 switch (mode) {
4129 case 0:
4130 umode = SEEK_SET;
4131 res = startpos;
4132 break;
4133 case 1:
4134 umode = SEEK_CUR;
4135 res = fsp->fh->pos + startpos;
4136 break;
4137 case 2:
4138 umode = SEEK_END;
4139 break;
4140 default:
4141 umode = SEEK_SET;
4142 res = startpos;
4143 break;
4146 if (umode == SEEK_END) {
4147 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4148 if(errno == EINVAL) {
4149 SMB_OFF_T current_pos = startpos;
4150 SMB_STRUCT_STAT sbuf;
4152 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4153 reply_unixerror(req, ERRDOS,
4154 ERRnoaccess);
4155 END_PROFILE(SMBlseek);
4156 return;
4159 current_pos += sbuf.st_size;
4160 if(current_pos < 0)
4161 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4165 if(res == -1) {
4166 reply_unixerror(req, ERRDOS, ERRnoaccess);
4167 END_PROFILE(SMBlseek);
4168 return;
4172 fsp->fh->pos = res;
4174 reply_outbuf(req, 2, 0);
4175 SIVAL(req->outbuf,smb_vwv0,res);
4177 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4178 fsp->fnum, (double)startpos, (double)res, mode));
4180 END_PROFILE(SMBlseek);
4181 return;
4184 /****************************************************************************
4185 Reply to a flush.
4186 ****************************************************************************/
4188 void reply_flush(struct smb_request *req)
4190 connection_struct *conn = req->conn;
4191 uint16 fnum;
4192 files_struct *fsp;
4194 START_PROFILE(SMBflush);
4196 if (req->wct < 1) {
4197 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4198 return;
4201 fnum = SVAL(req->inbuf,smb_vwv0);
4202 fsp = file_fsp(fnum);
4204 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4205 return;
4208 if (!fsp) {
4209 file_sync_all(conn);
4210 } else {
4211 NTSTATUS status = sync_file(conn, fsp, True);
4212 if (!NT_STATUS_IS_OK(status)) {
4213 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4214 fsp->fsp_name, nt_errstr(status) ));
4215 reply_nterror(req, status);
4216 END_PROFILE(SMBflush);
4217 return;
4221 reply_outbuf(req, 0, 0);
4223 DEBUG(3,("flush\n"));
4224 END_PROFILE(SMBflush);
4225 return;
4228 /****************************************************************************
4229 Reply to a exit.
4230 conn POINTER CAN BE NULL HERE !
4231 ****************************************************************************/
4233 void reply_exit(struct smb_request *req)
4235 START_PROFILE(SMBexit);
4237 file_close_pid(req->smbpid, req->vuid);
4239 reply_outbuf(req, 0, 0);
4241 DEBUG(3,("exit\n"));
4243 END_PROFILE(SMBexit);
4244 return;
4247 /****************************************************************************
4248 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4249 ****************************************************************************/
4251 void reply_close(struct smb_request *req)
4253 connection_struct *conn = req->conn;
4254 NTSTATUS status = NT_STATUS_OK;
4255 files_struct *fsp = NULL;
4256 START_PROFILE(SMBclose);
4258 if (req->wct < 3) {
4259 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4260 END_PROFILE(SMBclose);
4261 return;
4264 /* If it's an IPC, pass off to the pipe handler. */
4265 if (IS_IPC(conn)) {
4266 reply_pipe_close(conn, req);
4267 END_PROFILE(SMBclose);
4268 return;
4271 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4274 * We can only use check_fsp if we know it's not a directory.
4277 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4278 reply_doserror(req, ERRDOS, ERRbadfid);
4279 END_PROFILE(SMBclose);
4280 return;
4283 if(fsp->is_directory) {
4285 * Special case - close NT SMB directory handle.
4287 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4288 status = close_file(fsp,NORMAL_CLOSE);
4289 } else {
4290 time_t t;
4292 * Close ordinary file.
4295 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4296 fsp->fh->fd, fsp->fnum,
4297 conn->num_files_open));
4300 * Take care of any time sent in the close.
4303 t = srv_make_unix_date3(req->inbuf+smb_vwv1);
4304 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4307 * close_file() returns the unix errno if an error
4308 * was detected on close - normally this is due to
4309 * a disk full error. If not then it was probably an I/O error.
4312 status = close_file(fsp,NORMAL_CLOSE);
4315 if (!NT_STATUS_IS_OK(status)) {
4316 reply_nterror(req, status);
4317 END_PROFILE(SMBclose);
4318 return;
4321 reply_outbuf(req, 0, 0);
4322 END_PROFILE(SMBclose);
4323 return;
4326 /****************************************************************************
4327 Reply to a writeclose (Core+ protocol).
4328 ****************************************************************************/
4330 void reply_writeclose(struct smb_request *req)
4332 connection_struct *conn = req->conn;
4333 size_t numtowrite;
4334 ssize_t nwritten = -1;
4335 NTSTATUS close_status = NT_STATUS_OK;
4336 SMB_OFF_T startpos;
4337 char *data;
4338 struct timespec mtime;
4339 files_struct *fsp;
4341 START_PROFILE(SMBwriteclose);
4343 if (req->wct < 6) {
4344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4345 END_PROFILE(SMBwriteclose);
4346 return;
4349 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4351 if (!check_fsp(conn, req, fsp)) {
4352 END_PROFILE(SMBwriteclose);
4353 return;
4355 if (!CHECK_WRITE(fsp)) {
4356 reply_doserror(req, ERRDOS,ERRbadaccess);
4357 END_PROFILE(SMBwriteclose);
4358 return;
4361 numtowrite = SVAL(req->inbuf,smb_vwv1);
4362 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
4363 mtime = convert_time_t_to_timespec(srv_make_unix_date3(
4364 req->inbuf+smb_vwv4));
4365 data = smb_buf(req->inbuf) + 1;
4367 if (numtowrite
4368 && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
4369 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4370 reply_doserror(req, ERRDOS,ERRlock);
4371 END_PROFILE(SMBwriteclose);
4372 return;
4375 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4377 set_close_write_time(fsp, mtime);
4380 * More insanity. W2K only closes the file if writelen > 0.
4381 * JRA.
4384 if (numtowrite) {
4385 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4386 fsp->fsp_name ));
4387 close_status = close_file(fsp,NORMAL_CLOSE);
4390 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4391 fsp->fnum, (int)numtowrite, (int)nwritten,
4392 conn->num_files_open));
4394 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4395 reply_doserror(req, ERRHRD, ERRdiskfull);
4396 END_PROFILE(SMBwriteclose);
4397 return;
4400 if(!NT_STATUS_IS_OK(close_status)) {
4401 reply_nterror(req, close_status);
4402 END_PROFILE(SMBwriteclose);
4403 return;
4406 reply_outbuf(req, 1, 0);
4408 SSVAL(req->outbuf,smb_vwv0,nwritten);
4409 END_PROFILE(SMBwriteclose);
4410 return;
4413 #undef DBGC_CLASS
4414 #define DBGC_CLASS DBGC_LOCKING
4416 /****************************************************************************
4417 Reply to a lock.
4418 ****************************************************************************/
4420 void reply_lock(struct smb_request *req)
4422 connection_struct *conn = req->conn;
4423 SMB_BIG_UINT count,offset;
4424 NTSTATUS status;
4425 files_struct *fsp;
4426 struct byte_range_lock *br_lck = NULL;
4428 START_PROFILE(SMBlock);
4430 if (req->wct < 5) {
4431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4432 END_PROFILE(SMBlock);
4433 return;
4436 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4438 if (!check_fsp(conn, req, fsp)) {
4439 END_PROFILE(SMBlock);
4440 return;
4443 release_level_2_oplocks_on_change(fsp);
4445 count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4446 offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4448 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4449 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4451 br_lck = do_lock(smbd_messaging_context(),
4452 fsp,
4453 req->smbpid,
4454 count,
4455 offset,
4456 WRITE_LOCK,
4457 WINDOWS_LOCK,
4458 False, /* Non-blocking lock. */
4459 &status,
4460 NULL);
4462 TALLOC_FREE(br_lck);
4464 if (NT_STATUS_V(status)) {
4465 reply_nterror(req, status);
4466 END_PROFILE(SMBlock);
4467 return;
4470 reply_outbuf(req, 0, 0);
4472 END_PROFILE(SMBlock);
4473 return;
4476 /****************************************************************************
4477 Reply to a unlock.
4478 ****************************************************************************/
4480 void reply_unlock(struct smb_request *req)
4482 connection_struct *conn = req->conn;
4483 SMB_BIG_UINT count,offset;
4484 NTSTATUS status;
4485 files_struct *fsp;
4487 START_PROFILE(SMBunlock);
4489 if (req->wct < 5) {
4490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4491 END_PROFILE(SMBunlock);
4492 return;
4495 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4497 if (!check_fsp(conn, req, fsp)) {
4498 END_PROFILE(SMBunlock);
4499 return;
4502 count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4503 offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4505 status = do_unlock(smbd_messaging_context(),
4506 fsp,
4507 req->smbpid,
4508 count,
4509 offset,
4510 WINDOWS_LOCK);
4512 if (NT_STATUS_V(status)) {
4513 reply_nterror(req, status);
4514 END_PROFILE(SMBunlock);
4515 return;
4518 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4519 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4521 reply_outbuf(req, 0, 0);
4523 END_PROFILE(SMBunlock);
4524 return;
4527 #undef DBGC_CLASS
4528 #define DBGC_CLASS DBGC_ALL
4530 /****************************************************************************
4531 Reply to a tdis.
4532 conn POINTER CAN BE NULL HERE !
4533 ****************************************************************************/
4535 void reply_tdis(struct smb_request *req)
4537 connection_struct *conn = req->conn;
4538 START_PROFILE(SMBtdis);
4540 if (!conn) {
4541 DEBUG(4,("Invalid connection in tdis\n"));
4542 reply_doserror(req, ERRSRV, ERRinvnid);
4543 END_PROFILE(SMBtdis);
4544 return;
4547 conn->used = False;
4549 close_cnum(conn,req->vuid);
4550 req->conn = NULL;
4552 reply_outbuf(req, 0, 0);
4553 END_PROFILE(SMBtdis);
4554 return;
4557 /****************************************************************************
4558 Reply to a echo.
4559 conn POINTER CAN BE NULL HERE !
4560 ****************************************************************************/
4562 void reply_echo(struct smb_request *req)
4564 connection_struct *conn = req->conn;
4565 int smb_reverb;
4566 int seq_num;
4567 unsigned int data_len = smb_buflen(req->inbuf);
4569 START_PROFILE(SMBecho);
4571 if (req->wct < 1) {
4572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4573 END_PROFILE(SMBecho);
4574 return;
4577 if (data_len > BUFFER_SIZE) {
4578 DEBUG(0,("reply_echo: data_len too large.\n"));
4579 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
4580 END_PROFILE(SMBecho);
4581 return;
4584 smb_reverb = SVAL(req->inbuf,smb_vwv0);
4586 reply_outbuf(req, 1, data_len);
4588 /* copy any incoming data back out */
4589 if (data_len > 0) {
4590 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
4593 if (smb_reverb > 100) {
4594 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4595 smb_reverb = 100;
4598 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4599 SSVAL(req->outbuf,smb_vwv0,seq_num);
4601 show_msg((char *)req->outbuf);
4602 if (!srv_send_smb(smbd_server_fd(),
4603 (char *)req->outbuf,
4604 IS_CONN_ENCRYPTED(conn)||req->encrypted))
4605 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4608 DEBUG(3,("echo %d times\n", smb_reverb));
4610 TALLOC_FREE(req->outbuf);
4612 END_PROFILE(SMBecho);
4613 return;
4616 /****************************************************************************
4617 Reply to a printopen.
4618 ****************************************************************************/
4620 void reply_printopen(struct smb_request *req)
4622 connection_struct *conn = req->conn;
4623 files_struct *fsp;
4624 NTSTATUS status;
4626 START_PROFILE(SMBsplopen);
4628 if (req->wct < 2) {
4629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4630 END_PROFILE(SMBsplopen);
4631 return;
4634 if (!CAN_PRINT(conn)) {
4635 reply_doserror(req, ERRDOS, ERRnoaccess);
4636 END_PROFILE(SMBsplopen);
4637 return;
4640 /* Open for exclusive use, write only. */
4641 status = print_fsp_open(conn, NULL, req->vuid, &fsp);
4643 if (!NT_STATUS_IS_OK(status)) {
4644 reply_nterror(req, status);
4645 END_PROFILE(SMBsplopen);
4646 return;
4649 reply_outbuf(req, 1, 0);
4650 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4652 DEBUG(3,("openprint fd=%d fnum=%d\n",
4653 fsp->fh->fd, fsp->fnum));
4655 END_PROFILE(SMBsplopen);
4656 return;
4659 /****************************************************************************
4660 Reply to a printclose.
4661 ****************************************************************************/
4663 void reply_printclose(struct smb_request *req)
4665 connection_struct *conn = req->conn;
4666 files_struct *fsp;
4667 NTSTATUS status;
4669 START_PROFILE(SMBsplclose);
4671 if (req->wct < 1) {
4672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4673 END_PROFILE(SMBsplclose);
4674 return;
4677 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4679 if (!check_fsp(conn, req, fsp)) {
4680 END_PROFILE(SMBsplclose);
4681 return;
4684 if (!CAN_PRINT(conn)) {
4685 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4686 END_PROFILE(SMBsplclose);
4687 return;
4690 DEBUG(3,("printclose fd=%d fnum=%d\n",
4691 fsp->fh->fd,fsp->fnum));
4693 status = close_file(fsp,NORMAL_CLOSE);
4695 if(!NT_STATUS_IS_OK(status)) {
4696 reply_nterror(req, status);
4697 END_PROFILE(SMBsplclose);
4698 return;
4701 reply_outbuf(req, 0, 0);
4703 END_PROFILE(SMBsplclose);
4704 return;
4707 /****************************************************************************
4708 Reply to a printqueue.
4709 ****************************************************************************/
4711 void reply_printqueue(struct smb_request *req)
4713 connection_struct *conn = req->conn;
4714 int max_count;
4715 int start_index;
4717 START_PROFILE(SMBsplretq);
4719 if (req->wct < 2) {
4720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4721 END_PROFILE(SMBsplretq);
4722 return;
4725 max_count = SVAL(req->inbuf,smb_vwv0);
4726 start_index = SVAL(req->inbuf,smb_vwv1);
4728 /* we used to allow the client to get the cnum wrong, but that
4729 is really quite gross and only worked when there was only
4730 one printer - I think we should now only accept it if they
4731 get it right (tridge) */
4732 if (!CAN_PRINT(conn)) {
4733 reply_doserror(req, ERRDOS, ERRnoaccess);
4734 END_PROFILE(SMBsplretq);
4735 return;
4738 reply_outbuf(req, 2, 3);
4739 SSVAL(req->outbuf,smb_vwv0,0);
4740 SSVAL(req->outbuf,smb_vwv1,0);
4741 SCVAL(smb_buf(req->outbuf),0,1);
4742 SSVAL(smb_buf(req->outbuf),1,0);
4744 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4745 start_index, max_count));
4748 print_queue_struct *queue = NULL;
4749 print_status_struct status;
4750 int count = print_queue_status(SNUM(conn), &queue, &status);
4751 int num_to_get = ABS(max_count);
4752 int first = (max_count>0?start_index:start_index+max_count+1);
4753 int i;
4755 if (first >= count)
4756 num_to_get = 0;
4757 else
4758 num_to_get = MIN(num_to_get,count-first);
4761 for (i=first;i<first+num_to_get;i++) {
4762 char blob[28];
4763 char *p = blob;
4765 srv_put_dos_date2(p,0,queue[i].time);
4766 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4767 SSVAL(p,5, queue[i].job);
4768 SIVAL(p,7,queue[i].size);
4769 SCVAL(p,11,0);
4770 srvstr_push(blob, req->flags2, p+12,
4771 queue[i].fs_user, 16, STR_ASCII);
4773 if (message_push_blob(
4774 &req->outbuf,
4775 data_blob_const(
4776 blob, sizeof(blob))) == -1) {
4777 reply_nterror(req, NT_STATUS_NO_MEMORY);
4778 END_PROFILE(SMBsplretq);
4779 return;
4783 if (count > 0) {
4784 SSVAL(req->outbuf,smb_vwv0,count);
4785 SSVAL(req->outbuf,smb_vwv1,
4786 (max_count>0?first+count:first-1));
4787 SCVAL(smb_buf(req->outbuf),0,1);
4788 SSVAL(smb_buf(req->outbuf),1,28*count);
4791 SAFE_FREE(queue);
4793 DEBUG(3,("%d entries returned in queue\n",count));
4796 END_PROFILE(SMBsplretq);
4797 return;
4800 /****************************************************************************
4801 Reply to a printwrite.
4802 ****************************************************************************/
4804 void reply_printwrite(struct smb_request *req)
4806 connection_struct *conn = req->conn;
4807 int numtowrite;
4808 char *data;
4809 files_struct *fsp;
4811 START_PROFILE(SMBsplwr);
4813 if (req->wct < 1) {
4814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4815 END_PROFILE(SMBsplwr);
4816 return;
4819 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4821 if (!check_fsp(conn, req, fsp)) {
4822 END_PROFILE(SMBsplwr);
4823 return;
4826 if (!CAN_PRINT(conn)) {
4827 reply_doserror(req, ERRDOS, ERRnoaccess);
4828 END_PROFILE(SMBsplwr);
4829 return;
4832 if (!CHECK_WRITE(fsp)) {
4833 reply_doserror(req, ERRDOS, ERRbadaccess);
4834 END_PROFILE(SMBsplwr);
4835 return;
4838 numtowrite = SVAL(smb_buf(req->inbuf),1);
4840 if (smb_buflen(req->inbuf) < numtowrite + 3) {
4841 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4842 END_PROFILE(SMBsplwr);
4843 return;
4846 data = smb_buf(req->inbuf) + 3;
4848 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4849 reply_unixerror(req, ERRHRD, ERRdiskfull);
4850 END_PROFILE(SMBsplwr);
4851 return;
4854 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4856 END_PROFILE(SMBsplwr);
4857 return;
4860 /****************************************************************************
4861 Reply to a mkdir.
4862 ****************************************************************************/
4864 void reply_mkdir(struct smb_request *req)
4866 connection_struct *conn = req->conn;
4867 char *directory = NULL;
4868 NTSTATUS status;
4869 SMB_STRUCT_STAT sbuf;
4870 TALLOC_CTX *ctx = talloc_tos();
4872 START_PROFILE(SMBmkdir);
4874 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
4875 smb_buf(req->inbuf) + 1, 0,
4876 STR_TERMINATE, &status);
4877 if (!NT_STATUS_IS_OK(status)) {
4878 reply_nterror(req, status);
4879 END_PROFILE(SMBmkdir);
4880 return;
4883 status = resolve_dfspath(ctx, conn,
4884 req->flags2 & FLAGS2_DFS_PATHNAMES,
4885 directory,
4886 &directory);
4887 if (!NT_STATUS_IS_OK(status)) {
4888 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4889 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4890 ERRSRV, ERRbadpath);
4891 END_PROFILE(SMBmkdir);
4892 return;
4894 reply_nterror(req, status);
4895 END_PROFILE(SMBmkdir);
4896 return;
4899 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4900 if (!NT_STATUS_IS_OK(status)) {
4901 reply_nterror(req, status);
4902 END_PROFILE(SMBmkdir);
4903 return;
4906 status = check_name(conn, directory);
4907 if (!NT_STATUS_IS_OK(status)) {
4908 reply_nterror(req, status);
4909 END_PROFILE(SMBmkdir);
4910 return;
4913 status = create_directory(conn, req, directory);
4915 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4917 if (!NT_STATUS_IS_OK(status)) {
4919 if (!use_nt_status()
4920 && NT_STATUS_EQUAL(status,
4921 NT_STATUS_OBJECT_NAME_COLLISION)) {
4923 * Yes, in the DOS error code case we get a
4924 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4925 * samba4 torture test.
4927 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4930 reply_nterror(req, status);
4931 END_PROFILE(SMBmkdir);
4932 return;
4935 reply_outbuf(req, 0, 0);
4937 DEBUG( 3, ( "mkdir %s\n", directory ) );
4939 END_PROFILE(SMBmkdir);
4940 return;
4943 /****************************************************************************
4944 Static function used by reply_rmdir to delete an entire directory
4945 tree recursively. Return True on ok, False on fail.
4946 ****************************************************************************/
4948 static bool recursive_rmdir(TALLOC_CTX *ctx,
4949 connection_struct *conn,
4950 char *directory)
4952 const char *dname = NULL;
4953 bool ret = True;
4954 long offset = 0;
4955 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
4956 NULL, 0);
4958 if(dir_hnd == NULL)
4959 return False;
4961 while((dname = ReadDirName(dir_hnd, &offset))) {
4962 char *fullname = NULL;
4963 SMB_STRUCT_STAT st;
4965 if (ISDOT(dname) || ISDOTDOT(dname)) {
4966 continue;
4969 if (!is_visible_file(conn, directory, dname, &st, False)) {
4970 continue;
4973 /* Construct the full name. */
4974 fullname = talloc_asprintf(ctx,
4975 "%s/%s",
4976 directory,
4977 dname);
4978 if (!fullname) {
4979 errno = ENOMEM;
4980 ret = False;
4981 break;
4984 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4985 ret = False;
4986 break;
4989 if(st.st_mode & S_IFDIR) {
4990 if(!recursive_rmdir(ctx, conn, fullname)) {
4991 ret = False;
4992 break;
4994 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4995 ret = False;
4996 break;
4998 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4999 ret = False;
5000 break;
5002 TALLOC_FREE(fullname);
5004 TALLOC_FREE(dir_hnd);
5005 return ret;
5008 /****************************************************************************
5009 The internals of the rmdir code - called elsewhere.
5010 ****************************************************************************/
5012 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5013 connection_struct *conn,
5014 const char *directory)
5016 int ret;
5017 SMB_STRUCT_STAT st;
5019 /* Might be a symlink. */
5020 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5021 return map_nt_error_from_unix(errno);
5024 if (S_ISLNK(st.st_mode)) {
5025 /* Is what it points to a directory ? */
5026 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5027 return map_nt_error_from_unix(errno);
5029 if (!(S_ISDIR(st.st_mode))) {
5030 return NT_STATUS_NOT_A_DIRECTORY;
5032 ret = SMB_VFS_UNLINK(conn,directory);
5033 } else {
5034 ret = SMB_VFS_RMDIR(conn,directory);
5036 if (ret == 0) {
5037 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5038 FILE_NOTIFY_CHANGE_DIR_NAME,
5039 directory);
5040 return NT_STATUS_OK;
5043 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5045 * Check to see if the only thing in this directory are
5046 * vetoed files/directories. If so then delete them and
5047 * retry. If we fail to delete any of them (and we *don't*
5048 * do a recursive delete) then fail the rmdir.
5050 const char *dname;
5051 long dirpos = 0;
5052 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5053 directory, NULL, 0);
5055 if(dir_hnd == NULL) {
5056 errno = ENOTEMPTY;
5057 goto err;
5060 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5061 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5062 continue;
5063 if (!is_visible_file(conn, directory, dname, &st, False))
5064 continue;
5065 if(!IS_VETO_PATH(conn, dname)) {
5066 TALLOC_FREE(dir_hnd);
5067 errno = ENOTEMPTY;
5068 goto err;
5072 /* We only have veto files/directories. Recursive delete. */
5074 RewindDir(dir_hnd,&dirpos);
5075 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5076 char *fullname = NULL;
5078 if (ISDOT(dname) || ISDOTDOT(dname)) {
5079 continue;
5081 if (!is_visible_file(conn, directory, dname, &st, False)) {
5082 continue;
5085 fullname = talloc_asprintf(ctx,
5086 "%s/%s",
5087 directory,
5088 dname);
5090 if(!fullname) {
5091 errno = ENOMEM;
5092 break;
5095 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5096 break;
5098 if(st.st_mode & S_IFDIR) {
5099 if(lp_recursive_veto_delete(SNUM(conn))) {
5100 if(!recursive_rmdir(ctx, conn, fullname))
5101 break;
5103 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5104 break;
5106 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5107 break;
5109 TALLOC_FREE(fullname);
5111 TALLOC_FREE(dir_hnd);
5112 /* Retry the rmdir */
5113 ret = SMB_VFS_RMDIR(conn,directory);
5116 err:
5118 if (ret != 0) {
5119 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5120 "%s\n", directory,strerror(errno)));
5121 return map_nt_error_from_unix(errno);
5124 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5125 FILE_NOTIFY_CHANGE_DIR_NAME,
5126 directory);
5128 return NT_STATUS_OK;
5131 /****************************************************************************
5132 Reply to a rmdir.
5133 ****************************************************************************/
5135 void reply_rmdir(struct smb_request *req)
5137 connection_struct *conn = req->conn;
5138 char *directory = NULL;
5139 SMB_STRUCT_STAT sbuf;
5140 NTSTATUS status;
5141 TALLOC_CTX *ctx = talloc_tos();
5143 START_PROFILE(SMBrmdir);
5145 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
5146 smb_buf(req->inbuf) + 1, 0,
5147 STR_TERMINATE, &status);
5148 if (!NT_STATUS_IS_OK(status)) {
5149 reply_nterror(req, status);
5150 END_PROFILE(SMBrmdir);
5151 return;
5154 status = resolve_dfspath(ctx, conn,
5155 req->flags2 & FLAGS2_DFS_PATHNAMES,
5156 directory,
5157 &directory);
5158 if (!NT_STATUS_IS_OK(status)) {
5159 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5160 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5161 ERRSRV, ERRbadpath);
5162 END_PROFILE(SMBrmdir);
5163 return;
5165 reply_nterror(req, status);
5166 END_PROFILE(SMBrmdir);
5167 return;
5170 status = unix_convert(ctx, conn, directory, False, &directory,
5171 NULL, &sbuf);
5172 if (!NT_STATUS_IS_OK(status)) {
5173 reply_nterror(req, status);
5174 END_PROFILE(SMBrmdir);
5175 return;
5178 status = check_name(conn, directory);
5179 if (!NT_STATUS_IS_OK(status)) {
5180 reply_nterror(req, status);
5181 END_PROFILE(SMBrmdir);
5182 return;
5185 dptr_closepath(directory, req->smbpid);
5186 status = rmdir_internals(ctx, conn, directory);
5187 if (!NT_STATUS_IS_OK(status)) {
5188 reply_nterror(req, status);
5189 END_PROFILE(SMBrmdir);
5190 return;
5193 reply_outbuf(req, 0, 0);
5195 DEBUG( 3, ( "rmdir %s\n", directory ) );
5197 END_PROFILE(SMBrmdir);
5198 return;
5201 /*******************************************************************
5202 Resolve wildcards in a filename rename.
5203 ********************************************************************/
5205 static bool resolve_wildcards(TALLOC_CTX *ctx,
5206 const char *name1,
5207 const char *name2,
5208 char **pp_newname)
5210 char *name2_copy = NULL;
5211 char *root1 = NULL;
5212 char *root2 = NULL;
5213 char *ext1 = NULL;
5214 char *ext2 = NULL;
5215 char *p,*p2, *pname1, *pname2;
5217 name2_copy = talloc_strdup(ctx, name2);
5218 if (!name2_copy) {
5219 return False;
5222 pname1 = strrchr_m(name1,'/');
5223 pname2 = strrchr_m(name2_copy,'/');
5225 if (!pname1 || !pname2) {
5226 return False;
5229 /* Truncate the copy of name2 at the last '/' */
5230 *pname2 = '\0';
5232 /* Now go past the '/' */
5233 pname1++;
5234 pname2++;
5236 root1 = talloc_strdup(ctx, pname1);
5237 root2 = talloc_strdup(ctx, pname2);
5239 if (!root1 || !root2) {
5240 return False;
5243 p = strrchr_m(root1,'.');
5244 if (p) {
5245 *p = 0;
5246 ext1 = talloc_strdup(ctx, p+1);
5247 } else {
5248 ext1 = talloc_strdup(ctx, "");
5250 p = strrchr_m(root2,'.');
5251 if (p) {
5252 *p = 0;
5253 ext2 = talloc_strdup(ctx, p+1);
5254 } else {
5255 ext2 = talloc_strdup(ctx, "");
5258 if (!ext1 || !ext2) {
5259 return False;
5262 p = root1;
5263 p2 = root2;
5264 while (*p2) {
5265 if (*p2 == '?') {
5266 /* Hmmm. Should this be mb-aware ? */
5267 *p2 = *p;
5268 p2++;
5269 } else if (*p2 == '*') {
5270 *p2 = '\0';
5271 root2 = talloc_asprintf(ctx, "%s%s",
5272 root2,
5274 if (!root2) {
5275 return False;
5277 break;
5278 } else {
5279 p2++;
5281 if (*p) {
5282 p++;
5286 p = ext1;
5287 p2 = ext2;
5288 while (*p2) {
5289 if (*p2 == '?') {
5290 /* Hmmm. Should this be mb-aware ? */
5291 *p2 = *p;
5292 p2++;
5293 } else if (*p2 == '*') {
5294 *p2 = '\0';
5295 ext2 = talloc_asprintf(ctx, "%s%s",
5296 ext2,
5298 if (!ext2) {
5299 return False;
5301 break;
5302 } else {
5303 p2++;
5305 if (*p) {
5306 p++;
5310 if (*ext2) {
5311 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5312 name2_copy,
5313 root2,
5314 ext2);
5315 } else {
5316 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5317 name2_copy,
5318 root2);
5321 if (!*pp_newname) {
5322 return False;
5325 return True;
5328 /****************************************************************************
5329 Ensure open files have their names updated. Updated to notify other smbd's
5330 asynchronously.
5331 ****************************************************************************/
5333 static void rename_open_files(connection_struct *conn,
5334 struct share_mode_lock *lck,
5335 const char *newname)
5337 files_struct *fsp;
5338 bool did_rename = False;
5340 for(fsp = file_find_di_first(lck->id); fsp;
5341 fsp = file_find_di_next(fsp)) {
5342 /* fsp_name is a relative path under the fsp. To change this for other
5343 sharepaths we need to manipulate relative paths. */
5344 /* TODO - create the absolute path and manipulate the newname
5345 relative to the sharepath. */
5346 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5347 continue;
5349 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5350 fsp->fnum, file_id_string_tos(&fsp->file_id),
5351 fsp->fsp_name, newname ));
5352 string_set(&fsp->fsp_name, newname);
5353 did_rename = True;
5356 if (!did_rename) {
5357 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5358 file_id_string_tos(&lck->id), newname ));
5361 /* Send messages to all smbd's (not ourself) that the name has changed. */
5362 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5363 newname);
5366 /****************************************************************************
5367 We need to check if the source path is a parent directory of the destination
5368 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5369 refuse the rename with a sharing violation. Under UNIX the above call can
5370 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5371 probably need to check that the client is a Windows one before disallowing
5372 this as a UNIX client (one with UNIX extensions) can know the source is a
5373 symlink and make this decision intelligently. Found by an excellent bug
5374 report from <AndyLiebman@aol.com>.
5375 ****************************************************************************/
5377 static bool rename_path_prefix_equal(const char *src, const char *dest)
5379 const char *psrc = src;
5380 const char *pdst = dest;
5381 size_t slen;
5383 if (psrc[0] == '.' && psrc[1] == '/') {
5384 psrc += 2;
5386 if (pdst[0] == '.' && pdst[1] == '/') {
5387 pdst += 2;
5389 if ((slen = strlen(psrc)) > strlen(pdst)) {
5390 return False;
5392 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5396 * Do the notify calls from a rename
5399 static void notify_rename(connection_struct *conn, bool is_dir,
5400 const char *oldpath, const char *newpath)
5402 char *olddir, *newdir;
5403 const char *oldname, *newname;
5404 uint32 mask;
5406 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5407 : FILE_NOTIFY_CHANGE_FILE_NAME;
5409 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
5410 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
5411 TALLOC_FREE(olddir);
5412 return;
5415 if (strcmp(olddir, newdir) == 0) {
5416 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5417 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5419 else {
5420 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5421 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5423 TALLOC_FREE(olddir);
5424 TALLOC_FREE(newdir);
5426 /* this is a strange one. w2k3 gives an additional event for
5427 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5428 files, but not directories */
5429 if (!is_dir) {
5430 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5431 FILE_NOTIFY_CHANGE_ATTRIBUTES
5432 |FILE_NOTIFY_CHANGE_CREATION,
5433 newpath);
5437 /****************************************************************************
5438 Rename an open file - given an fsp.
5439 ****************************************************************************/
5441 NTSTATUS rename_internals_fsp(connection_struct *conn,
5442 files_struct *fsp,
5443 char *newname,
5444 const char *newname_last_component,
5445 uint32 attrs,
5446 bool replace_if_exists)
5448 TALLOC_CTX *ctx = talloc_tos();
5449 SMB_STRUCT_STAT sbuf, sbuf1;
5450 NTSTATUS status = NT_STATUS_OK;
5451 struct share_mode_lock *lck = NULL;
5452 bool dst_exists;
5454 ZERO_STRUCT(sbuf);
5456 status = check_name(conn, newname);
5457 if (!NT_STATUS_IS_OK(status)) {
5458 return status;
5461 /* Ensure newname contains a '/' */
5462 if(strrchr_m(newname,'/') == 0) {
5463 newname = talloc_asprintf(ctx,
5464 "./%s",
5465 newname);
5466 if (!newname) {
5467 return NT_STATUS_NO_MEMORY;
5472 * Check for special case with case preserving and not
5473 * case sensitive. If the old last component differs from the original
5474 * last component only by case, then we should allow
5475 * the rename (user is trying to change the case of the
5476 * filename).
5479 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5480 strequal(newname, fsp->fsp_name)) {
5481 char *p;
5482 char *newname_modified_last_component = NULL;
5485 * Get the last component of the modified name.
5486 * Note that we guarantee that newname contains a '/'
5487 * character above.
5489 p = strrchr_m(newname,'/');
5490 newname_modified_last_component = talloc_strdup(ctx,
5491 p+1);
5492 if (!newname_modified_last_component) {
5493 return NT_STATUS_NO_MEMORY;
5496 if(strcsequal(newname_modified_last_component,
5497 newname_last_component) == False) {
5499 * Replace the modified last component with
5500 * the original.
5502 *p = '\0'; /* Truncate at the '/' */
5503 newname = talloc_asprintf(ctx,
5504 "%s/%s",
5505 newname,
5506 newname_last_component);
5511 * If the src and dest names are identical - including case,
5512 * don't do the rename, just return success.
5515 if (strcsequal(fsp->fsp_name, newname)) {
5516 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5517 newname));
5518 return NT_STATUS_OK;
5522 * Have vfs_object_exist also fill sbuf1
5524 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5526 if(!replace_if_exists && dst_exists) {
5527 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5528 fsp->fsp_name,newname));
5529 return NT_STATUS_OBJECT_NAME_COLLISION;
5532 if (dst_exists) {
5533 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5534 files_struct *dst_fsp = file_find_di_first(fileid);
5535 if (dst_fsp) {
5536 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5537 return NT_STATUS_ACCESS_DENIED;
5541 /* Ensure we have a valid stat struct for the source. */
5542 if (fsp->fh->fd != -1) {
5543 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5544 return map_nt_error_from_unix(errno);
5546 } else {
5547 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5548 return map_nt_error_from_unix(errno);
5552 status = can_rename(conn, fsp, attrs, &sbuf);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5556 nt_errstr(status), fsp->fsp_name,newname));
5557 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5558 status = NT_STATUS_ACCESS_DENIED;
5559 return status;
5562 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5563 return NT_STATUS_ACCESS_DENIED;
5566 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5567 NULL);
5570 * We have the file open ourselves, so not being able to get the
5571 * corresponding share mode lock is a fatal error.
5574 SMB_ASSERT(lck != NULL);
5576 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5577 uint32 create_options = fsp->fh->private_options;
5579 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5580 fsp->fsp_name,newname));
5582 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5584 rename_open_files(conn, lck, newname);
5587 * A rename acts as a new file create w.r.t. allowing an initial delete
5588 * on close, probably because in Windows there is a new handle to the
5589 * new file. If initial delete on close was requested but not
5590 * originally set, we need to set it here. This is probably not 100% correct,
5591 * but will work for the CIFSFS client which in non-posix mode
5592 * depends on these semantics. JRA.
5595 set_allow_initial_delete_on_close(lck, fsp, True);
5597 if (create_options & FILE_DELETE_ON_CLOSE) {
5598 status = can_set_delete_on_close(fsp, True, 0);
5600 if (NT_STATUS_IS_OK(status)) {
5601 /* Note that here we set the *inital* delete on close flag,
5602 * not the regular one. The magic gets handled in close. */
5603 fsp->initial_delete_on_close = True;
5606 TALLOC_FREE(lck);
5607 return NT_STATUS_OK;
5610 TALLOC_FREE(lck);
5612 if (errno == ENOTDIR || errno == EISDIR) {
5613 status = NT_STATUS_OBJECT_NAME_COLLISION;
5614 } else {
5615 status = map_nt_error_from_unix(errno);
5618 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5619 nt_errstr(status), fsp->fsp_name,newname));
5621 return status;
5624 /****************************************************************************
5625 The guts of the rename command, split out so it may be called by the NT SMB
5626 code.
5627 ****************************************************************************/
5629 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5630 connection_struct *conn,
5631 struct smb_request *req,
5632 const char *name_in,
5633 const char *newname_in,
5634 uint32 attrs,
5635 bool replace_if_exists,
5636 bool src_has_wild,
5637 bool dest_has_wild,
5638 uint32_t access_mask)
5640 char *directory = NULL;
5641 char *mask = NULL;
5642 char *last_component_src = NULL;
5643 char *last_component_dest = NULL;
5644 char *name = NULL;
5645 char *newname = NULL;
5646 char *p;
5647 int count=0;
5648 NTSTATUS status = NT_STATUS_OK;
5649 SMB_STRUCT_STAT sbuf1, sbuf2;
5650 struct smb_Dir *dir_hnd = NULL;
5651 const char *dname;
5652 long offset = 0;
5654 ZERO_STRUCT(sbuf1);
5655 ZERO_STRUCT(sbuf2);
5657 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5658 &last_component_src, &sbuf1);
5659 if (!NT_STATUS_IS_OK(status)) {
5660 return status;
5663 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5664 &last_component_dest, &sbuf2);
5665 if (!NT_STATUS_IS_OK(status)) {
5666 return status;
5670 * Split the old name into directory and last component
5671 * strings. Note that unix_convert may have stripped off a
5672 * leading ./ from both name and newname if the rename is
5673 * at the root of the share. We need to make sure either both
5674 * name and newname contain a / character or neither of them do
5675 * as this is checked in resolve_wildcards().
5678 p = strrchr_m(name,'/');
5679 if (!p) {
5680 directory = talloc_strdup(ctx, ".");
5681 if (!directory) {
5682 return NT_STATUS_NO_MEMORY;
5684 mask = name;
5685 } else {
5686 *p = 0;
5687 directory = talloc_strdup(ctx, name);
5688 if (!directory) {
5689 return NT_STATUS_NO_MEMORY;
5691 mask = p+1;
5692 *p = '/'; /* Replace needed for exceptional test below. */
5696 * We should only check the mangled cache
5697 * here if unix_convert failed. This means
5698 * that the path in 'mask' doesn't exist
5699 * on the file system and so we need to look
5700 * for a possible mangle. This patch from
5701 * Tine Smukavec <valentin.smukavec@hermes.si>.
5704 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5705 char *new_mask = NULL;
5706 mangle_lookup_name_from_8_3(ctx,
5707 mask,
5708 &new_mask,
5709 conn->params );
5710 if (new_mask) {
5711 mask = new_mask;
5715 if (!src_has_wild) {
5716 files_struct *fsp;
5719 * No wildcards - just process the one file.
5721 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5723 /* Add a terminating '/' to the directory name. */
5724 directory = talloc_asprintf_append(directory,
5725 "/%s",
5726 mask);
5727 if (!directory) {
5728 return NT_STATUS_NO_MEMORY;
5731 /* Ensure newname contains a '/' also */
5732 if(strrchr_m(newname,'/') == 0) {
5733 newname = talloc_asprintf(ctx,
5734 "./%s",
5735 newname);
5736 if (!newname) {
5737 return NT_STATUS_NO_MEMORY;
5741 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5742 "case_preserve = %d, short case preserve = %d, "
5743 "directory = %s, newname = %s, "
5744 "last_component_dest = %s, is_8_3 = %d\n",
5745 conn->case_sensitive, conn->case_preserve,
5746 conn->short_case_preserve, directory,
5747 newname, last_component_dest, is_short_name));
5749 /* The dest name still may have wildcards. */
5750 if (dest_has_wild) {
5751 char *mod_newname = NULL;
5752 if (!resolve_wildcards(ctx,
5753 directory,newname,&mod_newname)) {
5754 DEBUG(6, ("rename_internals: resolve_wildcards "
5755 "%s %s failed\n",
5756 directory,
5757 newname));
5758 return NT_STATUS_NO_MEMORY;
5760 newname = mod_newname;
5763 ZERO_STRUCT(sbuf1);
5764 SMB_VFS_STAT(conn, directory, &sbuf1);
5766 status = S_ISDIR(sbuf1.st_mode) ?
5767 open_directory(conn, req, directory, &sbuf1,
5768 access_mask,
5769 FILE_SHARE_READ|FILE_SHARE_WRITE,
5770 FILE_OPEN, 0, 0, NULL,
5771 &fsp)
5772 : open_file_ntcreate(conn, req, directory, &sbuf1,
5773 access_mask,
5774 FILE_SHARE_READ|FILE_SHARE_WRITE,
5775 FILE_OPEN, 0, 0, 0, NULL,
5776 &fsp);
5778 if (!NT_STATUS_IS_OK(status)) {
5779 DEBUG(3, ("Could not open rename source %s: %s\n",
5780 directory, nt_errstr(status)));
5781 return status;
5784 status = rename_internals_fsp(conn, fsp, newname,
5785 last_component_dest,
5786 attrs, replace_if_exists);
5788 close_file(fsp, NORMAL_CLOSE);
5790 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5791 nt_errstr(status), directory,newname));
5793 return status;
5797 * Wildcards - process each file that matches.
5799 if (strequal(mask,"????????.???")) {
5800 mask[0] = '*';
5801 mask[1] = '\0';
5804 status = check_name(conn, directory);
5805 if (!NT_STATUS_IS_OK(status)) {
5806 return status;
5809 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
5810 if (dir_hnd == NULL) {
5811 return map_nt_error_from_unix(errno);
5814 status = NT_STATUS_NO_SUCH_FILE;
5816 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5817 * - gentest fix. JRA
5820 while ((dname = ReadDirName(dir_hnd, &offset))) {
5821 files_struct *fsp = NULL;
5822 char *fname = NULL;
5823 char *destname = NULL;
5824 bool sysdir_entry = False;
5826 /* Quick check for "." and ".." */
5827 if (ISDOT(dname) || ISDOTDOT(dname)) {
5828 if (attrs & aDIR) {
5829 sysdir_entry = True;
5830 } else {
5831 continue;
5835 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5836 continue;
5839 if(!mask_match(dname, mask, conn->case_sensitive)) {
5840 continue;
5843 if (sysdir_entry) {
5844 status = NT_STATUS_OBJECT_NAME_INVALID;
5845 break;
5848 fname = talloc_asprintf(ctx,
5849 "%s/%s",
5850 directory,
5851 dname);
5852 if (!fname) {
5853 return NT_STATUS_NO_MEMORY;
5856 if (!resolve_wildcards(ctx,
5857 fname,newname,&destname)) {
5858 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5859 fname, destname));
5860 TALLOC_FREE(fname);
5861 continue;
5863 if (!destname) {
5864 return NT_STATUS_NO_MEMORY;
5867 ZERO_STRUCT(sbuf1);
5868 SMB_VFS_STAT(conn, fname, &sbuf1);
5870 status = S_ISDIR(sbuf1.st_mode) ?
5871 open_directory(conn, req, fname, &sbuf1,
5872 access_mask,
5873 FILE_SHARE_READ|FILE_SHARE_WRITE,
5874 FILE_OPEN, 0, 0, NULL,
5875 &fsp)
5876 : open_file_ntcreate(conn, req, fname, &sbuf1,
5877 access_mask,
5878 FILE_SHARE_READ|FILE_SHARE_WRITE,
5879 FILE_OPEN, 0, 0, 0, NULL,
5880 &fsp);
5882 if (!NT_STATUS_IS_OK(status)) {
5883 DEBUG(3,("rename_internals: open_file_ntcreate "
5884 "returned %s rename %s -> %s\n",
5885 nt_errstr(status), directory, newname));
5886 break;
5889 status = rename_internals_fsp(conn, fsp, destname, dname,
5890 attrs, replace_if_exists);
5892 close_file(fsp, NORMAL_CLOSE);
5894 if (!NT_STATUS_IS_OK(status)) {
5895 DEBUG(3, ("rename_internals_fsp returned %s for "
5896 "rename %s -> %s\n", nt_errstr(status),
5897 directory, newname));
5898 break;
5901 count++;
5903 DEBUG(3,("rename_internals: doing rename on %s -> "
5904 "%s\n",fname,destname));
5906 TALLOC_FREE(fname);
5907 TALLOC_FREE(destname);
5909 TALLOC_FREE(dir_hnd);
5911 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
5912 status = map_nt_error_from_unix(errno);
5915 return status;
5918 /****************************************************************************
5919 Reply to a mv.
5920 ****************************************************************************/
5922 void reply_mv(struct smb_request *req)
5924 connection_struct *conn = req->conn;
5925 char *name = NULL;
5926 char *newname = NULL;
5927 char *p;
5928 uint32 attrs;
5929 NTSTATUS status;
5930 bool src_has_wcard = False;
5931 bool dest_has_wcard = False;
5932 TALLOC_CTX *ctx = talloc_tos();
5934 START_PROFILE(SMBmv);
5936 if (req->wct < 1) {
5937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5938 END_PROFILE(SMBmv);
5939 return;
5942 attrs = SVAL(req->inbuf,smb_vwv0);
5944 p = smb_buf(req->inbuf) + 1;
5945 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
5946 0, STR_TERMINATE, &status,
5947 &src_has_wcard);
5948 if (!NT_STATUS_IS_OK(status)) {
5949 reply_nterror(req, status);
5950 END_PROFILE(SMBmv);
5951 return;
5953 p++;
5954 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
5955 0, STR_TERMINATE, &status,
5956 &dest_has_wcard);
5957 if (!NT_STATUS_IS_OK(status)) {
5958 reply_nterror(req, status);
5959 END_PROFILE(SMBmv);
5960 return;
5963 status = resolve_dfspath_wcard(ctx, conn,
5964 req->flags2 & FLAGS2_DFS_PATHNAMES,
5965 name,
5966 &name,
5967 &src_has_wcard);
5968 if (!NT_STATUS_IS_OK(status)) {
5969 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5970 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5971 ERRSRV, ERRbadpath);
5972 END_PROFILE(SMBmv);
5973 return;
5975 reply_nterror(req, status);
5976 END_PROFILE(SMBmv);
5977 return;
5980 status = resolve_dfspath_wcard(ctx, conn,
5981 req->flags2 & FLAGS2_DFS_PATHNAMES,
5982 newname,
5983 &newname,
5984 &dest_has_wcard);
5985 if (!NT_STATUS_IS_OK(status)) {
5986 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5987 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5988 ERRSRV, ERRbadpath);
5989 END_PROFILE(SMBmv);
5990 return;
5992 reply_nterror(req, status);
5993 END_PROFILE(SMBmv);
5994 return;
5997 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5999 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6000 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6001 if (!NT_STATUS_IS_OK(status)) {
6002 if (open_was_deferred(req->mid)) {
6003 /* We have re-scheduled this call. */
6004 END_PROFILE(SMBmv);
6005 return;
6007 reply_nterror(req, status);
6008 END_PROFILE(SMBmv);
6009 return;
6012 reply_outbuf(req, 0, 0);
6014 END_PROFILE(SMBmv);
6015 return;
6018 /*******************************************************************
6019 Copy a file as part of a reply_copy.
6020 ******************************************************************/
6023 * TODO: check error codes on all callers
6026 NTSTATUS copy_file(TALLOC_CTX *ctx,
6027 connection_struct *conn,
6028 const char *src,
6029 const char *dest1,
6030 int ofun,
6031 int count,
6032 bool target_is_directory)
6034 SMB_STRUCT_STAT src_sbuf, sbuf2;
6035 SMB_OFF_T ret=-1;
6036 files_struct *fsp1,*fsp2;
6037 char *dest = NULL;
6038 uint32 dosattrs;
6039 uint32 new_create_disposition;
6040 NTSTATUS status;
6042 dest = talloc_strdup(ctx, dest1);
6043 if (!dest) {
6044 return NT_STATUS_NO_MEMORY;
6046 if (target_is_directory) {
6047 const char *p = strrchr_m(src,'/');
6048 if (p) {
6049 p++;
6050 } else {
6051 p = src;
6053 dest = talloc_asprintf_append(dest,
6054 "/%s",
6056 if (!dest) {
6057 return NT_STATUS_NO_MEMORY;
6061 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6062 TALLOC_FREE(dest);
6063 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6066 if (!target_is_directory && count) {
6067 new_create_disposition = FILE_OPEN;
6068 } else {
6069 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6070 NULL, NULL, &new_create_disposition, NULL)) {
6071 TALLOC_FREE(dest);
6072 return NT_STATUS_INVALID_PARAMETER;
6076 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
6077 FILE_GENERIC_READ,
6078 FILE_SHARE_READ|FILE_SHARE_WRITE,
6079 FILE_OPEN,
6081 FILE_ATTRIBUTE_NORMAL,
6082 INTERNAL_OPEN_ONLY,
6083 NULL, &fsp1);
6085 if (!NT_STATUS_IS_OK(status)) {
6086 TALLOC_FREE(dest);
6087 return status;
6090 dosattrs = dos_mode(conn, src, &src_sbuf);
6091 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6092 ZERO_STRUCTP(&sbuf2);
6095 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
6096 FILE_GENERIC_WRITE,
6097 FILE_SHARE_READ|FILE_SHARE_WRITE,
6098 new_create_disposition,
6100 dosattrs,
6101 INTERNAL_OPEN_ONLY,
6102 NULL, &fsp2);
6104 TALLOC_FREE(dest);
6106 if (!NT_STATUS_IS_OK(status)) {
6107 close_file(fsp1,ERROR_CLOSE);
6108 return status;
6111 if ((ofun&3) == 1) {
6112 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6113 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6115 * Stop the copy from occurring.
6117 ret = -1;
6118 src_sbuf.st_size = 0;
6122 if (src_sbuf.st_size) {
6123 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6126 close_file(fsp1,NORMAL_CLOSE);
6128 /* Ensure the modtime is set correctly on the destination file. */
6129 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6132 * As we are opening fsp1 read-only we only expect
6133 * an error on close on fsp2 if we are out of space.
6134 * Thus we don't look at the error return from the
6135 * close of fsp1.
6137 status = close_file(fsp2,NORMAL_CLOSE);
6139 if (!NT_STATUS_IS_OK(status)) {
6140 return status;
6143 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6144 return NT_STATUS_DISK_FULL;
6147 return NT_STATUS_OK;
6150 /****************************************************************************
6151 Reply to a file copy.
6152 ****************************************************************************/
6154 void reply_copy(struct smb_request *req)
6156 connection_struct *conn = req->conn;
6157 char *name = NULL;
6158 char *newname = NULL;
6159 char *directory = NULL;
6160 char *mask = NULL;
6161 char *p;
6162 int count=0;
6163 int error = ERRnoaccess;
6164 int err = 0;
6165 int tid2;
6166 int ofun;
6167 int flags;
6168 bool target_is_directory=False;
6169 bool source_has_wild = False;
6170 bool dest_has_wild = False;
6171 SMB_STRUCT_STAT sbuf1, sbuf2;
6172 NTSTATUS status;
6173 TALLOC_CTX *ctx = talloc_tos();
6175 START_PROFILE(SMBcopy);
6177 if (req->wct < 3) {
6178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6179 END_PROFILE(SMBcopy);
6180 return;
6183 tid2 = SVAL(req->inbuf,smb_vwv0);
6184 ofun = SVAL(req->inbuf,smb_vwv1);
6185 flags = SVAL(req->inbuf,smb_vwv2);
6187 p = smb_buf(req->inbuf);
6188 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
6189 0, STR_TERMINATE, &status,
6190 &source_has_wild);
6191 if (!NT_STATUS_IS_OK(status)) {
6192 reply_nterror(req, status);
6193 END_PROFILE(SMBcopy);
6194 return;
6196 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
6197 0, STR_TERMINATE, &status,
6198 &dest_has_wild);
6199 if (!NT_STATUS_IS_OK(status)) {
6200 reply_nterror(req, status);
6201 END_PROFILE(SMBcopy);
6202 return;
6205 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6207 if (tid2 != conn->cnum) {
6208 /* can't currently handle inter share copies XXXX */
6209 DEBUG(3,("Rejecting inter-share copy\n"));
6210 reply_doserror(req, ERRSRV, ERRinvdevice);
6211 END_PROFILE(SMBcopy);
6212 return;
6215 status = resolve_dfspath_wcard(ctx, conn,
6216 req->flags2 & FLAGS2_DFS_PATHNAMES,
6217 name,
6218 &name,
6219 &source_has_wild);
6220 if (!NT_STATUS_IS_OK(status)) {
6221 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6222 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6223 ERRSRV, ERRbadpath);
6224 END_PROFILE(SMBcopy);
6225 return;
6227 reply_nterror(req, status);
6228 END_PROFILE(SMBcopy);
6229 return;
6232 status = resolve_dfspath_wcard(ctx, conn,
6233 req->flags2 & FLAGS2_DFS_PATHNAMES,
6234 newname,
6235 &newname,
6236 &dest_has_wild);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6239 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6240 ERRSRV, ERRbadpath);
6241 END_PROFILE(SMBcopy);
6242 return;
6244 reply_nterror(req, status);
6245 END_PROFILE(SMBcopy);
6246 return;
6249 status = unix_convert(ctx, conn, name, source_has_wild,
6250 &name, NULL, &sbuf1);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 reply_nterror(req, status);
6253 END_PROFILE(SMBcopy);
6254 return;
6257 status = unix_convert(ctx, conn, newname, dest_has_wild,
6258 &newname, NULL, &sbuf2);
6259 if (!NT_STATUS_IS_OK(status)) {
6260 reply_nterror(req, status);
6261 END_PROFILE(SMBcopy);
6262 return;
6265 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6267 if ((flags&1) && target_is_directory) {
6268 reply_doserror(req, ERRDOS, ERRbadfile);
6269 END_PROFILE(SMBcopy);
6270 return;
6273 if ((flags&2) && !target_is_directory) {
6274 reply_doserror(req, ERRDOS, ERRbadpath);
6275 END_PROFILE(SMBcopy);
6276 return;
6279 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6280 /* wants a tree copy! XXXX */
6281 DEBUG(3,("Rejecting tree copy\n"));
6282 reply_doserror(req, ERRSRV, ERRerror);
6283 END_PROFILE(SMBcopy);
6284 return;
6287 p = strrchr_m(name,'/');
6288 if (!p) {
6289 directory = talloc_strdup(ctx, "./");
6290 if (!directory) {
6291 reply_nterror(req, NT_STATUS_NO_MEMORY);
6292 END_PROFILE(SMBcopy);
6293 return;
6295 mask = name;
6296 } else {
6297 *p = 0;
6298 directory = talloc_strdup(ctx, name);
6299 if (!directory) {
6300 reply_nterror(req, NT_STATUS_NO_MEMORY);
6301 END_PROFILE(SMBcopy);
6302 return;
6304 mask = p+1;
6308 * We should only check the mangled cache
6309 * here if unix_convert failed. This means
6310 * that the path in 'mask' doesn't exist
6311 * on the file system and so we need to look
6312 * for a possible mangle. This patch from
6313 * Tine Smukavec <valentin.smukavec@hermes.si>.
6316 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6317 char *new_mask = NULL;
6318 mangle_lookup_name_from_8_3(ctx,
6319 mask,
6320 &new_mask,
6321 conn->params );
6322 if (new_mask) {
6323 mask = new_mask;
6327 if (!source_has_wild) {
6328 directory = talloc_asprintf_append(directory,
6329 "/%s",
6330 mask);
6331 if (dest_has_wild) {
6332 char *mod_newname = NULL;
6333 if (!resolve_wildcards(ctx,
6334 directory,newname,&mod_newname)) {
6335 reply_nterror(req, NT_STATUS_NO_MEMORY);
6336 END_PROFILE(SMBcopy);
6337 return;
6339 newname = mod_newname;
6342 status = check_name(conn, directory);
6343 if (!NT_STATUS_IS_OK(status)) {
6344 reply_nterror(req, status);
6345 END_PROFILE(SMBcopy);
6346 return;
6349 status = check_name(conn, newname);
6350 if (!NT_STATUS_IS_OK(status)) {
6351 reply_nterror(req, status);
6352 END_PROFILE(SMBcopy);
6353 return;
6356 status = copy_file(ctx,conn,directory,newname,ofun,
6357 count,target_is_directory);
6359 if(!NT_STATUS_IS_OK(status)) {
6360 reply_nterror(req, status);
6361 END_PROFILE(SMBcopy);
6362 return;
6363 } else {
6364 count++;
6366 } else {
6367 struct smb_Dir *dir_hnd = NULL;
6368 const char *dname = NULL;
6369 long offset = 0;
6371 if (strequal(mask,"????????.???")) {
6372 mask[0] = '*';
6373 mask[1] = '\0';
6376 status = check_name(conn, directory);
6377 if (!NT_STATUS_IS_OK(status)) {
6378 reply_nterror(req, status);
6379 END_PROFILE(SMBcopy);
6380 return;
6383 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6384 if (dir_hnd == NULL) {
6385 status = map_nt_error_from_unix(errno);
6386 reply_nterror(req, status);
6387 END_PROFILE(SMBcopy);
6388 return;
6391 error = ERRbadfile;
6393 while ((dname = ReadDirName(dir_hnd, &offset))) {
6394 char *destname = NULL;
6395 char *fname = NULL;
6397 if (ISDOT(dname) || ISDOTDOT(dname)) {
6398 continue;
6401 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6402 continue;
6405 if(!mask_match(dname, mask, conn->case_sensitive)) {
6406 continue;
6409 error = ERRnoaccess;
6410 fname = talloc_asprintf(ctx,
6411 "%s/%s",
6412 directory,
6413 dname);
6414 if (!fname) {
6415 TALLOC_FREE(dir_hnd);
6416 reply_nterror(req, NT_STATUS_NO_MEMORY);
6417 END_PROFILE(SMBcopy);
6418 return;
6421 if (!resolve_wildcards(ctx,
6422 fname,newname,&destname)) {
6423 continue;
6425 if (!destname) {
6426 TALLOC_FREE(dir_hnd);
6427 reply_nterror(req, NT_STATUS_NO_MEMORY);
6428 END_PROFILE(SMBcopy);
6429 return;
6432 status = check_name(conn, fname);
6433 if (!NT_STATUS_IS_OK(status)) {
6434 TALLOC_FREE(dir_hnd);
6435 reply_nterror(req, status);
6436 END_PROFILE(SMBcopy);
6437 return;
6440 status = check_name(conn, destname);
6441 if (!NT_STATUS_IS_OK(status)) {
6442 TALLOC_FREE(dir_hnd);
6443 reply_nterror(req, status);
6444 END_PROFILE(SMBcopy);
6445 return;
6448 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6450 status = copy_file(ctx,conn,fname,destname,ofun,
6451 count,target_is_directory);
6452 if (NT_STATUS_IS_OK(status)) {
6453 count++;
6455 TALLOC_FREE(fname);
6456 TALLOC_FREE(destname);
6458 TALLOC_FREE(dir_hnd);
6461 if (count == 0) {
6462 if(err) {
6463 /* Error on close... */
6464 errno = err;
6465 reply_unixerror(req, ERRHRD, ERRgeneral);
6466 END_PROFILE(SMBcopy);
6467 return;
6470 reply_doserror(req, ERRDOS, error);
6471 END_PROFILE(SMBcopy);
6472 return;
6475 reply_outbuf(req, 1, 0);
6476 SSVAL(req->outbuf,smb_vwv0,count);
6478 END_PROFILE(SMBcopy);
6479 return;
6482 #undef DBGC_CLASS
6483 #define DBGC_CLASS DBGC_LOCKING
6485 /****************************************************************************
6486 Get a lock pid, dealing with large count requests.
6487 ****************************************************************************/
6489 uint32 get_lock_pid( char *data, int data_offset, bool large_file_format)
6491 if(!large_file_format)
6492 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6493 else
6494 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6497 /****************************************************************************
6498 Get a lock count, dealing with large count requests.
6499 ****************************************************************************/
6501 SMB_BIG_UINT get_lock_count( char *data, int data_offset, bool large_file_format)
6503 SMB_BIG_UINT count = 0;
6505 if(!large_file_format) {
6506 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6507 } else {
6509 #if defined(HAVE_LONGLONG)
6510 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6511 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6512 #else /* HAVE_LONGLONG */
6515 * NT4.x seems to be broken in that it sends large file (64 bit)
6516 * lockingX calls even if the CAP_LARGE_FILES was *not*
6517 * negotiated. For boxes without large unsigned ints truncate the
6518 * lock count by dropping the top 32 bits.
6521 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6522 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6523 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6524 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6525 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6528 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6529 #endif /* HAVE_LONGLONG */
6532 return count;
6535 #if !defined(HAVE_LONGLONG)
6536 /****************************************************************************
6537 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6538 ****************************************************************************/
6540 static uint32 map_lock_offset(uint32 high, uint32 low)
6542 unsigned int i;
6543 uint32 mask = 0;
6544 uint32 highcopy = high;
6547 * Try and find out how many significant bits there are in high.
6550 for(i = 0; highcopy; i++)
6551 highcopy >>= 1;
6554 * We use 31 bits not 32 here as POSIX
6555 * lock offsets may not be negative.
6558 mask = (~0) << (31 - i);
6560 if(low & mask)
6561 return 0; /* Fail. */
6563 high <<= (31 - i);
6565 return (high|low);
6567 #endif /* !defined(HAVE_LONGLONG) */
6569 /****************************************************************************
6570 Get a lock offset, dealing with large offset requests.
6571 ****************************************************************************/
6573 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err)
6575 SMB_BIG_UINT offset = 0;
6577 *err = False;
6579 if(!large_file_format) {
6580 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6581 } else {
6583 #if defined(HAVE_LONGLONG)
6584 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6585 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6586 #else /* HAVE_LONGLONG */
6589 * NT4.x seems to be broken in that it sends large file (64 bit)
6590 * lockingX calls even if the CAP_LARGE_FILES was *not*
6591 * negotiated. For boxes without large unsigned ints mangle the
6592 * lock offset by mapping the top 32 bits onto the lower 32.
6595 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6596 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6597 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6598 uint32 new_low = 0;
6600 if((new_low = map_lock_offset(high, low)) == 0) {
6601 *err = True;
6602 return (SMB_BIG_UINT)-1;
6605 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6606 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6607 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6608 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6611 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6612 #endif /* HAVE_LONGLONG */
6615 return offset;
6618 /****************************************************************************
6619 Reply to a lockingX request.
6620 ****************************************************************************/
6622 void reply_lockingX(struct smb_request *req)
6624 connection_struct *conn = req->conn;
6625 files_struct *fsp;
6626 unsigned char locktype;
6627 unsigned char oplocklevel;
6628 uint16 num_ulocks;
6629 uint16 num_locks;
6630 SMB_BIG_UINT count = 0, offset = 0;
6631 uint32 lock_pid;
6632 int32 lock_timeout;
6633 int i;
6634 char *data;
6635 bool large_file_format;
6636 bool err;
6637 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6639 START_PROFILE(SMBlockingX);
6641 if (req->wct < 8) {
6642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6643 END_PROFILE(SMBlockingX);
6644 return;
6647 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
6648 locktype = CVAL(req->inbuf,smb_vwv3);
6649 oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
6650 num_ulocks = SVAL(req->inbuf,smb_vwv6);
6651 num_locks = SVAL(req->inbuf,smb_vwv7);
6652 lock_timeout = IVAL(req->inbuf,smb_vwv4);
6653 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6655 if (!check_fsp(conn, req, fsp)) {
6656 END_PROFILE(SMBlockingX);
6657 return;
6660 data = smb_buf(req->inbuf);
6662 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6663 /* we don't support these - and CANCEL_LOCK makes w2k
6664 and XP reboot so I don't really want to be
6665 compatible! (tridge) */
6666 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6667 END_PROFILE(SMBlockingX);
6668 return;
6671 /* Check if this is an oplock break on a file
6672 we have granted an oplock on.
6674 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6675 /* Client can insist on breaking to none. */
6676 bool break_to_none = (oplocklevel == 0);
6677 bool result;
6679 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6680 "for fnum = %d\n", (unsigned int)oplocklevel,
6681 fsp->fnum ));
6684 * Make sure we have granted an exclusive or batch oplock on
6685 * this file.
6688 if (fsp->oplock_type == 0) {
6690 /* The Samba4 nbench simulator doesn't understand
6691 the difference between break to level2 and break
6692 to none from level2 - it sends oplock break
6693 replies in both cases. Don't keep logging an error
6694 message here - just ignore it. JRA. */
6696 DEBUG(5,("reply_lockingX: Error : oplock break from "
6697 "client for fnum = %d (oplock=%d) and no "
6698 "oplock granted on this file (%s).\n",
6699 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6701 /* if this is a pure oplock break request then don't
6702 * send a reply */
6703 if (num_locks == 0 && num_ulocks == 0) {
6704 END_PROFILE(SMBlockingX);
6705 return;
6706 } else {
6707 END_PROFILE(SMBlockingX);
6708 reply_doserror(req, ERRDOS, ERRlock);
6709 return;
6713 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6714 (break_to_none)) {
6715 result = remove_oplock(fsp);
6716 } else {
6717 result = downgrade_oplock(fsp);
6720 if (!result) {
6721 DEBUG(0, ("reply_lockingX: error in removing "
6722 "oplock on file %s\n", fsp->fsp_name));
6723 /* Hmmm. Is this panic justified? */
6724 smb_panic("internal tdb error");
6727 reply_to_oplock_break_requests(fsp);
6729 /* if this is a pure oplock break request then don't send a
6730 * reply */
6731 if (num_locks == 0 && num_ulocks == 0) {
6732 /* Sanity check - ensure a pure oplock break is not a
6733 chained request. */
6734 if(CVAL(req->inbuf,smb_vwv0) != 0xff)
6735 DEBUG(0,("reply_lockingX: Error : pure oplock "
6736 "break is a chained %d request !\n",
6737 (unsigned int)CVAL(req->inbuf,
6738 smb_vwv0) ));
6739 END_PROFILE(SMBlockingX);
6740 return;
6745 * We do this check *after* we have checked this is not a oplock break
6746 * response message. JRA.
6749 release_level_2_oplocks_on_change(fsp);
6751 if (smb_buflen(req->inbuf) <
6752 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6754 END_PROFILE(SMBlockingX);
6755 return;
6758 /* Data now points at the beginning of the list
6759 of smb_unlkrng structs */
6760 for(i = 0; i < (int)num_ulocks; i++) {
6761 lock_pid = get_lock_pid( data, i, large_file_format);
6762 count = get_lock_count( data, i, large_file_format);
6763 offset = get_lock_offset( data, i, large_file_format, &err);
6766 * There is no error code marked "stupid client bug".... :-).
6768 if(err) {
6769 END_PROFILE(SMBlockingX);
6770 reply_doserror(req, ERRDOS, ERRnoaccess);
6771 return;
6774 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6775 "pid %u, file %s\n", (double)offset, (double)count,
6776 (unsigned int)lock_pid, fsp->fsp_name ));
6778 status = do_unlock(smbd_messaging_context(),
6779 fsp,
6780 lock_pid,
6781 count,
6782 offset,
6783 WINDOWS_LOCK);
6785 if (NT_STATUS_V(status)) {
6786 END_PROFILE(SMBlockingX);
6787 reply_nterror(req, status);
6788 return;
6792 /* Setup the timeout in seconds. */
6794 if (!lp_blocking_locks(SNUM(conn))) {
6795 lock_timeout = 0;
6798 /* Now do any requested locks */
6799 data += ((large_file_format ? 20 : 10)*num_ulocks);
6801 /* Data now points at the beginning of the list
6802 of smb_lkrng structs */
6804 for(i = 0; i < (int)num_locks; i++) {
6805 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6806 READ_LOCK:WRITE_LOCK);
6807 lock_pid = get_lock_pid( data, i, large_file_format);
6808 count = get_lock_count( data, i, large_file_format);
6809 offset = get_lock_offset( data, i, large_file_format, &err);
6812 * There is no error code marked "stupid client bug".... :-).
6814 if(err) {
6815 END_PROFILE(SMBlockingX);
6816 reply_doserror(req, ERRDOS, ERRnoaccess);
6817 return;
6820 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6821 "%u, file %s timeout = %d\n", (double)offset,
6822 (double)count, (unsigned int)lock_pid,
6823 fsp->fsp_name, (int)lock_timeout ));
6825 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6826 if (lp_blocking_locks(SNUM(conn))) {
6828 /* Schedule a message to ourselves to
6829 remove the blocking lock record and
6830 return the right error. */
6832 if (!blocking_lock_cancel(fsp,
6833 lock_pid,
6834 offset,
6835 count,
6836 WINDOWS_LOCK,
6837 locktype,
6838 NT_STATUS_FILE_LOCK_CONFLICT)) {
6839 END_PROFILE(SMBlockingX);
6840 reply_nterror(
6841 req,
6842 NT_STATUS_DOS(
6843 ERRDOS,
6844 ERRcancelviolation));
6845 return;
6848 /* Remove a matching pending lock. */
6849 status = do_lock_cancel(fsp,
6850 lock_pid,
6851 count,
6852 offset,
6853 WINDOWS_LOCK);
6854 } else {
6855 bool blocking_lock = lock_timeout ? True : False;
6856 bool defer_lock = False;
6857 struct byte_range_lock *br_lck;
6858 uint32 block_smbpid;
6860 br_lck = do_lock(smbd_messaging_context(),
6861 fsp,
6862 lock_pid,
6863 count,
6864 offset,
6865 lock_type,
6866 WINDOWS_LOCK,
6867 blocking_lock,
6868 &status,
6869 &block_smbpid);
6871 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6872 /* Windows internal resolution for blocking locks seems
6873 to be about 200ms... Don't wait for less than that. JRA. */
6874 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6875 lock_timeout = lp_lock_spin_time();
6877 defer_lock = True;
6880 /* This heuristic seems to match W2K3 very well. If a
6881 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6882 it pretends we asked for a timeout of between 150 - 300 milliseconds as
6883 far as I can tell. Replacement for do_lock_spin(). JRA. */
6885 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6886 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6887 defer_lock = True;
6888 lock_timeout = lp_lock_spin_time();
6891 if (br_lck && defer_lock) {
6893 * A blocking lock was requested. Package up
6894 * this smb into a queued request and push it
6895 * onto the blocking lock queue.
6897 if(push_blocking_lock_request(br_lck,
6898 req,
6899 fsp,
6900 lock_timeout,
6902 lock_pid,
6903 lock_type,
6904 WINDOWS_LOCK,
6905 offset,
6906 count,
6907 block_smbpid)) {
6908 TALLOC_FREE(br_lck);
6909 END_PROFILE(SMBlockingX);
6910 return;
6914 TALLOC_FREE(br_lck);
6917 if (NT_STATUS_V(status)) {
6918 END_PROFILE(SMBlockingX);
6919 reply_nterror(req, status);
6920 return;
6924 /* If any of the above locks failed, then we must unlock
6925 all of the previous locks (X/Open spec). */
6927 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6928 (i != num_locks) &&
6929 (num_locks != 0)) {
6931 * Ensure we don't do a remove on the lock that just failed,
6932 * as under POSIX rules, if we have a lock already there, we
6933 * will delete it (and we shouldn't) .....
6935 for(i--; i >= 0; i--) {
6936 lock_pid = get_lock_pid( data, i, large_file_format);
6937 count = get_lock_count( data, i, large_file_format);
6938 offset = get_lock_offset( data, i, large_file_format,
6939 &err);
6942 * There is no error code marked "stupid client
6943 * bug".... :-).
6945 if(err) {
6946 END_PROFILE(SMBlockingX);
6947 reply_doserror(req, ERRDOS, ERRnoaccess);
6948 return;
6951 do_unlock(smbd_messaging_context(),
6952 fsp,
6953 lock_pid,
6954 count,
6955 offset,
6956 WINDOWS_LOCK);
6958 END_PROFILE(SMBlockingX);
6959 reply_nterror(req, status);
6960 return;
6963 reply_outbuf(req, 2, 0);
6965 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
6966 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
6968 END_PROFILE(SMBlockingX);
6969 chain_reply(req);
6972 #undef DBGC_CLASS
6973 #define DBGC_CLASS DBGC_ALL
6975 /****************************************************************************
6976 Reply to a SMBreadbmpx (read block multiplex) request.
6977 Always reply with an error, if someone has a platform really needs this,
6978 please contact vl@samba.org
6979 ****************************************************************************/
6981 void reply_readbmpx(struct smb_request *req)
6983 START_PROFILE(SMBreadBmpx);
6984 reply_doserror(req, ERRSRV, ERRuseSTD);
6985 END_PROFILE(SMBreadBmpx);
6986 return;
6989 /****************************************************************************
6990 Reply to a SMBreadbs (read block multiplex secondary) request.
6991 Always reply with an error, if someone has a platform really needs this,
6992 please contact vl@samba.org
6993 ****************************************************************************/
6995 void reply_readbs(struct smb_request *req)
6997 START_PROFILE(SMBreadBs);
6998 reply_doserror(req, ERRSRV, ERRuseSTD);
6999 END_PROFILE(SMBreadBs);
7000 return;
7003 /****************************************************************************
7004 Reply to a SMBsetattrE.
7005 ****************************************************************************/
7007 void reply_setattrE(struct smb_request *req)
7009 connection_struct *conn = req->conn;
7010 struct timespec ts[2];
7011 files_struct *fsp;
7012 SMB_STRUCT_STAT sbuf;
7013 NTSTATUS status;
7015 START_PROFILE(SMBsetattrE);
7017 if (req->wct < 7) {
7018 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7019 END_PROFILE(SMBsetattrE);
7020 return;
7023 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
7025 if(!fsp || (fsp->conn != conn)) {
7026 reply_doserror(req, ERRDOS, ERRbadfid);
7027 END_PROFILE(SMBsetattrE);
7028 return;
7033 * Convert the DOS times into unix times. Ignore create
7034 * time as UNIX can't set this.
7037 ts[0] = convert_time_t_to_timespec(
7038 srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
7039 ts[1] = convert_time_t_to_timespec(
7040 srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
7042 reply_outbuf(req, 0, 0);
7045 * Patch from Ray Frush <frush@engr.colostate.edu>
7046 * Sometimes times are sent as zero - ignore them.
7049 /* Ensure we have a valid stat struct for the source. */
7050 if (fsp->fh->fd != -1) {
7051 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7052 status = map_nt_error_from_unix(errno);
7053 reply_nterror(req, status);
7054 END_PROFILE(SMBsetattrE);
7055 return;
7057 } else {
7058 if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) {
7059 status = map_nt_error_from_unix(errno);
7060 reply_nterror(req, status);
7061 END_PROFILE(SMBsetattrE);
7062 return;
7066 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7067 &sbuf, ts, true);
7068 if (!NT_STATUS_IS_OK(status)) {
7069 reply_doserror(req, ERRDOS, ERRnoaccess);
7070 END_PROFILE(SMBsetattrE);
7071 return;
7074 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7075 fsp->fnum,
7076 (unsigned int)ts[0].tv_sec,
7077 (unsigned int)ts[1].tv_sec));
7079 END_PROFILE(SMBsetattrE);
7080 return;
7084 /* Back from the dead for OS/2..... JRA. */
7086 /****************************************************************************
7087 Reply to a SMBwritebmpx (write block multiplex primary) request.
7088 Always reply with an error, if someone has a platform really needs this,
7089 please contact vl@samba.org
7090 ****************************************************************************/
7092 void reply_writebmpx(struct smb_request *req)
7094 START_PROFILE(SMBwriteBmpx);
7095 reply_doserror(req, ERRSRV, ERRuseSTD);
7096 END_PROFILE(SMBwriteBmpx);
7097 return;
7100 /****************************************************************************
7101 Reply to a SMBwritebs (write block multiplex secondary) request.
7102 Always reply with an error, if someone has a platform really needs this,
7103 please contact vl@samba.org
7104 ****************************************************************************/
7106 void reply_writebs(struct smb_request *req)
7108 START_PROFILE(SMBwriteBs);
7109 reply_doserror(req, ERRSRV, ERRuseSTD);
7110 END_PROFILE(SMBwriteBs);
7111 return;
7114 /****************************************************************************
7115 Reply to a SMBgetattrE.
7116 ****************************************************************************/
7118 void reply_getattrE(struct smb_request *req)
7120 connection_struct *conn = req->conn;
7121 SMB_STRUCT_STAT sbuf;
7122 int mode;
7123 files_struct *fsp;
7124 struct timespec create_ts;
7126 START_PROFILE(SMBgetattrE);
7128 if (req->wct < 1) {
7129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7130 END_PROFILE(SMBgetattrE);
7131 return;
7134 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
7136 if(!fsp || (fsp->conn != conn)) {
7137 reply_doserror(req, ERRDOS, ERRbadfid);
7138 END_PROFILE(SMBgetattrE);
7139 return;
7142 /* Do an fstat on this file */
7143 if(fsp_stat(fsp, &sbuf)) {
7144 reply_unixerror(req, ERRDOS, ERRnoaccess);
7145 END_PROFILE(SMBgetattrE);
7146 return;
7149 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7152 * Convert the times into dos times. Set create
7153 * date to be last modify date as UNIX doesn't save
7154 * this.
7157 reply_outbuf(req, 11, 0);
7159 create_ts = get_create_timespec(&sbuf,
7160 lp_fake_dir_create_times(SNUM(conn)));
7161 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7162 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7163 /* Should we check pending modtime here ? JRA */
7164 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7166 if (mode & aDIR) {
7167 SIVAL(req->outbuf, smb_vwv6, 0);
7168 SIVAL(req->outbuf, smb_vwv8, 0);
7169 } else {
7170 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7171 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7172 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7174 SSVAL(req->outbuf,smb_vwv10, mode);
7176 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7178 END_PROFILE(SMBgetattrE);
7179 return;