Reserve IOCTL 0xACE for proxy<->proxy communication channel
[Samba/vfs_proxy.git] / source3 / smbd / reply.c
blob9f7a1896b83f9be20ecbbd481671814b57e513a1
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;
55 bool stream_started = false;
57 *p_last_component_contains_wcard = False;
59 while (*s) {
60 if (stream_started) {
61 switch (*s) {
62 case '/':
63 case '\\':
64 return NT_STATUS_OBJECT_NAME_INVALID;
65 case ':':
66 if (s[1] == '\0') {
67 return NT_STATUS_OBJECT_NAME_INVALID;
69 if (strchr_m(&s[1], ':')) {
70 return NT_STATUS_OBJECT_NAME_INVALID;
72 if (StrCaseCmp(s, ":$DATA") != 0) {
73 return NT_STATUS_INVALID_PARAMETER;
75 break;
79 if (!stream_started && *s == ':') {
80 if (*p_last_component_contains_wcard) {
81 return NT_STATUS_OBJECT_NAME_INVALID;
83 /* stream names allow more characters than file names */
84 stream_started = true;
85 start_of_name_component = false;
86 posix_path = true;
88 if (s[1] == '\0') {
89 return NT_STATUS_OBJECT_NAME_INVALID;
93 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
95 * Safe to assume is not the second part of a mb char
96 * as this is handled below.
98 /* Eat multiple '/' or '\\' */
99 while (IS_PATH_SEP(*s,posix_path)) {
100 s++;
102 if ((d != path) && (*s != '\0')) {
103 /* We only care about non-leading or trailing '/' or '\\' */
104 *d++ = '/';
107 start_of_name_component = True;
108 /* New component. */
109 *p_last_component_contains_wcard = False;
110 continue;
113 if (start_of_name_component) {
114 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
115 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
118 * No mb char starts with '.' so we're safe checking the directory separator here.
121 /* If we just added a '/' - delete it */
122 if ((d > path) && (*(d-1) == '/')) {
123 *(d-1) = '\0';
124 d--;
127 /* Are we at the start ? Can't go back further if so. */
128 if (d <= path) {
129 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
130 break;
132 /* Go back one level... */
133 /* We know this is safe as '/' cannot be part of a mb sequence. */
134 /* NOTE - if this assumption is invalid we are not in good shape... */
135 /* Decrement d first as d points to the *next* char to write into. */
136 for (d--; d > path; d--) {
137 if (*d == '/')
138 break;
140 s += 2; /* Else go past the .. */
141 /* We're still at the start of a name component, just the previous one. */
142 continue;
144 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
145 if (posix_path) {
146 /* Eat the '.' */
147 s++;
148 continue;
154 if (!(*s & 0x80)) {
155 if (!posix_path) {
156 if (*s <= 0x1f || *s == '|') {
157 return NT_STATUS_OBJECT_NAME_INVALID;
159 switch (*s) {
160 case '*':
161 case '?':
162 case '<':
163 case '>':
164 case '"':
165 *p_last_component_contains_wcard = True;
166 break;
167 default:
168 break;
171 *d++ = *s++;
172 } else {
173 size_t siz;
174 /* Get the size of the next MB character. */
175 next_codepoint(s,&siz);
176 switch(siz) {
177 case 5:
178 *d++ = *s++;
179 /*fall through*/
180 case 4:
181 *d++ = *s++;
182 /*fall through*/
183 case 3:
184 *d++ = *s++;
185 /*fall through*/
186 case 2:
187 *d++ = *s++;
188 /*fall through*/
189 case 1:
190 *d++ = *s++;
191 break;
192 default:
193 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
194 *d = '\0';
195 return NT_STATUS_INVALID_PARAMETER;
198 start_of_name_component = False;
201 *d = '\0';
203 return ret;
206 /****************************************************************************
207 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
208 No wildcards allowed.
209 ****************************************************************************/
211 NTSTATUS check_path_syntax(char *path)
213 bool ignore;
214 return check_path_syntax_internal(path, False, &ignore);
217 /****************************************************************************
218 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219 Wildcards allowed - p_contains_wcard returns true if the last component contained
220 a wildcard.
221 ****************************************************************************/
223 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
225 return check_path_syntax_internal(path, False, p_contains_wcard);
228 /****************************************************************************
229 Check the path for a POSIX client.
230 We're assuming here that '/' is not the second byte in any multibyte char
231 set (a safe assumption).
232 ****************************************************************************/
234 NTSTATUS check_path_syntax_posix(char *path)
236 bool ignore;
237 return check_path_syntax_internal(path, True, &ignore);
240 /****************************************************************************
241 Pull a string and check the path allowing a wilcard - provide for error return.
242 ****************************************************************************/
244 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
245 const char *base_ptr,
246 uint16 smb_flags2,
247 char **pp_dest,
248 const char *src,
249 size_t src_len,
250 int flags,
251 NTSTATUS *err,
252 bool *contains_wcard)
254 size_t ret;
256 *pp_dest = NULL;
258 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
259 src_len, flags);
261 if (!*pp_dest) {
262 *err = NT_STATUS_INVALID_PARAMETER;
263 return ret;
266 *contains_wcard = False;
268 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270 * For a DFS path the function parse_dfs_path()
271 * will do the path processing, just make a copy.
273 *err = NT_STATUS_OK;
274 return ret;
277 if (lp_posix_pathnames()) {
278 *err = check_path_syntax_posix(*pp_dest);
279 } else {
280 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
283 return ret;
286 /****************************************************************************
287 Pull a string and check the path - provide for error return.
288 ****************************************************************************/
290 size_t srvstr_get_path(TALLOC_CTX *ctx,
291 const char *base_ptr,
292 uint16 smb_flags2,
293 char **pp_dest,
294 const char *src,
295 size_t src_len,
296 int flags,
297 NTSTATUS *err)
299 bool ignore;
300 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
301 src_len, flags, err, &ignore);
304 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
305 char **pp_dest, const char *src, int flags,
306 NTSTATUS *err, bool *contains_wcard)
308 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
309 pp_dest, src, smbreq_bufrem(req, src),
310 flags, err, contains_wcard);
313 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
314 char **pp_dest, const char *src, int flags,
315 NTSTATUS *err)
317 bool ignore;
318 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
319 flags, err, &ignore);
322 /****************************************************************************
323 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
324 ****************************************************************************/
326 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
327 files_struct *fsp)
329 if (!(fsp) || !(conn)) {
330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
331 return False;
333 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
334 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
335 return False;
337 return True;
340 /****************************************************************************
341 Check if we have a correct fsp pointing to a file.
342 ****************************************************************************/
344 bool check_fsp(connection_struct *conn, struct smb_request *req,
345 files_struct *fsp)
347 if (!check_fsp_open(conn, req, fsp)) {
348 return False;
350 if ((fsp)->is_directory) {
351 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
352 return False;
354 if ((fsp)->fh->fd == -1) {
355 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
356 return False;
358 (fsp)->num_smb_operations++;
359 return True;
362 /****************************************************************************
363 Check if we have a correct fsp pointing to a quota fake file. Replacement for
364 the CHECK_NTQUOTA_HANDLE_OK macro.
365 ****************************************************************************/
367 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
368 files_struct *fsp)
370 if (!check_fsp_open(conn, req, fsp)) {
371 return false;
374 if (fsp->is_directory) {
375 return false;
378 if (fsp->fake_file_handle == NULL) {
379 return false;
382 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
383 return false;
386 if (fsp->fake_file_handle->private_data == NULL) {
387 return false;
390 return true;
393 /****************************************************************************
394 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
395 ****************************************************************************/
397 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
398 files_struct *fsp)
400 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
401 && (req->vuid == (fsp)->vuid)) {
402 return True;
405 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
406 return False;
409 /****************************************************************************
410 Reply to a (netbios-level) special message.
411 ****************************************************************************/
413 void reply_special(char *inbuf)
415 int msg_type = CVAL(inbuf,0);
416 int msg_flags = CVAL(inbuf,1);
417 fstring name1,name2;
418 char name_type = 0;
421 * We only really use 4 bytes of the outbuf, but for the smb_setlen
422 * calculation & friends (srv_send_smb uses that) we need the full smb
423 * header.
425 char outbuf[smb_size];
427 static bool already_got_session = False;
429 *name1 = *name2 = 0;
431 memset(outbuf, '\0', sizeof(outbuf));
433 smb_setlen(outbuf,0);
435 switch (msg_type) {
436 case 0x81: /* session request */
438 if (already_got_session) {
439 exit_server_cleanly("multiple session request not permitted");
442 SCVAL(outbuf,0,0x82);
443 SCVAL(outbuf,3,0);
444 if (name_len(inbuf+4) > 50 ||
445 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
446 DEBUG(0,("Invalid name length in session request\n"));
447 return;
449 name_extract(inbuf,4,name1);
450 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
451 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
452 name1,name2));
454 set_local_machine_name(name1, True);
455 set_remote_machine_name(name2, True);
457 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
458 get_local_machine_name(), get_remote_machine_name(),
459 name_type));
461 if (name_type == 'R') {
462 /* We are being asked for a pathworks session ---
463 no thanks! */
464 SCVAL(outbuf, 0,0x83);
465 break;
468 /* only add the client's machine name to the list
469 of possibly valid usernames if we are operating
470 in share mode security */
471 if (lp_security() == SEC_SHARE) {
472 add_session_user(get_remote_machine_name());
475 reload_services(True);
476 reopen_logs();
478 already_got_session = True;
479 break;
481 case 0x89: /* session keepalive request
482 (some old clients produce this?) */
483 SCVAL(outbuf,0,SMBkeepalive);
484 SCVAL(outbuf,3,0);
485 break;
487 case 0x82: /* positive session response */
488 case 0x83: /* negative session response */
489 case 0x84: /* retarget session response */
490 DEBUG(0,("Unexpected session response\n"));
491 break;
493 case SMBkeepalive: /* session keepalive */
494 default:
495 return;
498 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
499 msg_type, msg_flags));
501 srv_send_smb(smbd_server_fd(), outbuf, false);
502 return;
505 /****************************************************************************
506 Reply to a tcon.
507 conn POINTER CAN BE NULL HERE !
508 ****************************************************************************/
510 void reply_tcon(struct smb_request *req)
512 connection_struct *conn = req->conn;
513 const char *service;
514 char *service_buf = NULL;
515 char *password = NULL;
516 char *dev = NULL;
517 int pwlen=0;
518 NTSTATUS nt_status;
519 const char *p;
520 DATA_BLOB password_blob;
521 TALLOC_CTX *ctx = talloc_tos();
523 START_PROFILE(SMBtcon);
525 if (req->buflen < 4) {
526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
527 END_PROFILE(SMBtcon);
528 return;
531 p = (const char *)req->buf + 1;
532 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
533 p += 1;
534 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
535 p += pwlen+1;
536 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
537 p += 1;
539 if (service_buf == NULL || password == NULL || dev == NULL) {
540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
541 END_PROFILE(SMBtcon);
542 return;
544 p = strrchr_m(service_buf,'\\');
545 if (p) {
546 service = p+1;
547 } else {
548 service = service_buf;
551 password_blob = data_blob(password, pwlen+1);
553 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
554 req->conn = conn;
556 data_blob_clear_free(&password_blob);
558 if (!conn) {
559 reply_nterror(req, nt_status);
560 END_PROFILE(SMBtcon);
561 return;
564 reply_outbuf(req, 2, 0);
565 SSVAL(req->outbuf,smb_vwv0,max_recv);
566 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
567 SSVAL(req->outbuf,smb_tid,conn->cnum);
569 DEBUG(3,("tcon service=%s cnum=%d\n",
570 service, conn->cnum));
572 END_PROFILE(SMBtcon);
573 return;
576 /****************************************************************************
577 Reply to a tcon and X.
578 conn POINTER CAN BE NULL HERE !
579 ****************************************************************************/
581 void reply_tcon_and_X(struct smb_request *req)
583 connection_struct *conn = req->conn;
584 const char *service = NULL;
585 DATA_BLOB password;
586 TALLOC_CTX *ctx = talloc_tos();
587 /* what the cleint thinks the device is */
588 char *client_devicetype = NULL;
589 /* what the server tells the client the share represents */
590 const char *server_devicetype;
591 NTSTATUS nt_status;
592 int passlen;
593 char *path = NULL;
594 const char *p, *q;
595 uint16 tcon_flags;
597 START_PROFILE(SMBtconX);
599 if (req->wct < 4) {
600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
601 END_PROFILE(SMBtconX);
602 return;
605 passlen = SVAL(req->vwv+3, 0);
606 tcon_flags = SVAL(req->vwv+2, 0);
608 /* we might have to close an old one */
609 if ((tcon_flags & 0x1) && conn) {
610 close_cnum(conn,req->vuid);
611 req->conn = NULL;
612 conn = NULL;
615 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
616 reply_doserror(req, ERRDOS, ERRbuftoosmall);
617 END_PROFILE(SMBtconX);
618 return;
621 if (global_encrypted_passwords_negotiated) {
622 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
623 if (lp_security() == SEC_SHARE) {
625 * Security = share always has a pad byte
626 * after the password.
628 p = (const char *)req->buf + passlen + 1;
629 } else {
630 p = (const char *)req->buf + passlen;
632 } else {
633 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
634 /* Ensure correct termination */
635 password.data[passlen]=0;
636 p = (const char *)req->buf + passlen + 1;
639 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
641 if (path == NULL) {
642 data_blob_clear_free(&password);
643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
644 END_PROFILE(SMBtconX);
645 return;
649 * the service name can be either: \\server\share
650 * or share directly like on the DELL PowerVault 705
652 if (*path=='\\') {
653 q = strchr_m(path+2,'\\');
654 if (!q) {
655 data_blob_clear_free(&password);
656 reply_doserror(req, ERRDOS, ERRnosuchshare);
657 END_PROFILE(SMBtconX);
658 return;
660 service = q+1;
661 } else {
662 service = path;
665 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
666 &client_devicetype, p,
667 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
669 if (client_devicetype == NULL) {
670 data_blob_clear_free(&password);
671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
672 END_PROFILE(SMBtconX);
673 return;
676 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
678 conn = make_connection(service, password, client_devicetype,
679 req->vuid, &nt_status);
680 req->conn =conn;
682 data_blob_clear_free(&password);
684 if (!conn) {
685 reply_nterror(req, nt_status);
686 END_PROFILE(SMBtconX);
687 return;
690 if ( IS_IPC(conn) )
691 server_devicetype = "IPC";
692 else if ( IS_PRINT(conn) )
693 server_devicetype = "LPT1:";
694 else
695 server_devicetype = "A:";
697 if (Protocol < PROTOCOL_NT1) {
698 reply_outbuf(req, 2, 0);
699 if (message_push_string(&req->outbuf, server_devicetype,
700 STR_TERMINATE|STR_ASCII) == -1) {
701 reply_nterror(req, NT_STATUS_NO_MEMORY);
702 END_PROFILE(SMBtconX);
703 return;
705 } else {
706 /* NT sets the fstype of IPC$ to the null string */
707 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
709 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
710 /* Return permissions. */
711 uint32 perm1 = 0;
712 uint32 perm2 = 0;
714 reply_outbuf(req, 7, 0);
716 if (IS_IPC(conn)) {
717 perm1 = FILE_ALL_ACCESS;
718 perm2 = FILE_ALL_ACCESS;
719 } else {
720 perm1 = CAN_WRITE(conn) ?
721 SHARE_ALL_ACCESS :
722 SHARE_READ_ONLY;
725 SIVAL(req->outbuf, smb_vwv3, perm1);
726 SIVAL(req->outbuf, smb_vwv5, perm2);
727 } else {
728 reply_outbuf(req, 3, 0);
731 if ((message_push_string(&req->outbuf, server_devicetype,
732 STR_TERMINATE|STR_ASCII) == -1)
733 || (message_push_string(&req->outbuf, fstype,
734 STR_TERMINATE) == -1)) {
735 reply_nterror(req, NT_STATUS_NO_MEMORY);
736 END_PROFILE(SMBtconX);
737 return;
740 /* what does setting this bit do? It is set by NT4 and
741 may affect the ability to autorun mounted cdroms */
742 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
743 (lp_csc_policy(SNUM(conn)) << 2));
745 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
746 DEBUG(2,("Serving %s as a Dfs root\n",
747 lp_servicename(SNUM(conn)) ));
748 SSVAL(req->outbuf, smb_vwv2,
749 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
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->vwv+1, 0);
802 function = SVAL(req->vwv+2, 0);
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(
829 req, SVAL(req->vwv+0, 0));
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(uint16_t flags2, NTSTATUS status)
860 /* Strange DOS error code semantics only for checkpath... */
861 if (!(flags2 & 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_req(ctx, req, &name, (const char *)req->buf + 1,
885 STR_TERMINATE, &status);
887 if (!NT_STATUS_IS_OK(status)) {
888 status = map_checkpath_error(req->flags2, 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->vwv+0, 0)));
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(req->flags2, 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 const char *p;
978 NTSTATUS status;
979 TALLOC_CTX *ctx = talloc_tos();
981 START_PROFILE(SMBgetatr);
983 p = (const char *)req->buf + 1;
984 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
985 if (!NT_STATUS_IS_OK(status)) {
986 reply_nterror(req, status);
987 END_PROFILE(SMBgetatr);
988 return;
991 status = resolve_dfspath(ctx, conn,
992 req->flags2 & FLAGS2_DFS_PATHNAMES,
993 fname,
994 &fname);
995 if (!NT_STATUS_IS_OK(status)) {
996 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
997 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
998 ERRSRV, ERRbadpath);
999 END_PROFILE(SMBgetatr);
1000 return;
1002 reply_nterror(req, status);
1003 END_PROFILE(SMBgetatr);
1004 return;
1007 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1008 under WfWg - weird! */
1009 if (*fname == '\0') {
1010 mode = aHIDDEN | aDIR;
1011 if (!CAN_WRITE(conn)) {
1012 mode |= aRONLY;
1014 size = 0;
1015 mtime = 0;
1016 } else {
1017 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
1018 if (!NT_STATUS_IS_OK(status)) {
1019 reply_nterror(req, status);
1020 END_PROFILE(SMBgetatr);
1021 return;
1023 status = check_name(conn, fname);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1026 reply_nterror(req, status);
1027 END_PROFILE(SMBgetatr);
1028 return;
1030 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1031 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1032 reply_unixerror(req, ERRDOS,ERRbadfile);
1033 END_PROFILE(SMBgetatr);
1034 return;
1037 mode = dos_mode(conn,fname,&sbuf);
1038 size = sbuf.st_size;
1039 mtime = sbuf.st_mtime;
1040 if (mode & aDIR) {
1041 size = 0;
1045 reply_outbuf(req, 10, 0);
1047 SSVAL(req->outbuf,smb_vwv0,mode);
1048 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1049 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1050 } else {
1051 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1053 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1055 if (Protocol >= PROTOCOL_NT1) {
1056 SSVAL(req->outbuf, smb_flg2,
1057 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1060 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1062 END_PROFILE(SMBgetatr);
1063 return;
1066 /****************************************************************************
1067 Reply to a setatr.
1068 ****************************************************************************/
1070 void reply_setatr(struct smb_request *req)
1072 struct timespec ts[2];
1073 connection_struct *conn = req->conn;
1074 char *fname = NULL;
1075 int mode;
1076 time_t mtime;
1077 SMB_STRUCT_STAT sbuf;
1078 const char *p;
1079 NTSTATUS status;
1080 TALLOC_CTX *ctx = talloc_tos();
1082 START_PROFILE(SMBsetatr);
1084 ZERO_STRUCT(ts);
1086 if (req->wct < 2) {
1087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1088 return;
1091 p = (const char *)req->buf + 1;
1092 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1093 if (!NT_STATUS_IS_OK(status)) {
1094 reply_nterror(req, status);
1095 END_PROFILE(SMBsetatr);
1096 return;
1099 status = resolve_dfspath(ctx, conn,
1100 req->flags2 & FLAGS2_DFS_PATHNAMES,
1101 fname,
1102 &fname);
1103 if (!NT_STATUS_IS_OK(status)) {
1104 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1105 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1106 ERRSRV, ERRbadpath);
1107 END_PROFILE(SMBsetatr);
1108 return;
1110 reply_nterror(req, status);
1111 END_PROFILE(SMBsetatr);
1112 return;
1115 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1116 if (!NT_STATUS_IS_OK(status)) {
1117 reply_nterror(req, status);
1118 END_PROFILE(SMBsetatr);
1119 return;
1122 status = check_name(conn, fname);
1123 if (!NT_STATUS_IS_OK(status)) {
1124 reply_nterror(req, status);
1125 END_PROFILE(SMBsetatr);
1126 return;
1129 if (fname[0] == '.' && fname[1] == '\0') {
1131 * Not sure here is the right place to catch this
1132 * condition. Might be moved to somewhere else later -- vl
1134 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1135 END_PROFILE(SMBsetatr);
1136 return;
1139 mode = SVAL(req->vwv+0, 0);
1140 mtime = srv_make_unix_date3(req->vwv+1);
1142 ts[1] = convert_time_t_to_timespec(mtime);
1143 status = smb_set_file_time(conn, NULL, fname,
1144 &sbuf, ts, true);
1145 if (!NT_STATUS_IS_OK(status)) {
1146 reply_unixerror(req, ERRDOS, ERRnoaccess);
1147 END_PROFILE(SMBsetatr);
1148 return;
1151 if (mode != FILE_ATTRIBUTE_NORMAL) {
1152 if (VALID_STAT_OF_DIR(sbuf))
1153 mode |= aDIR;
1154 else
1155 mode &= ~aDIR;
1157 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1158 reply_unixerror(req, ERRDOS, ERRnoaccess);
1159 END_PROFILE(SMBsetatr);
1160 return;
1164 reply_outbuf(req, 0, 0);
1166 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1168 END_PROFILE(SMBsetatr);
1169 return;
1172 /****************************************************************************
1173 Reply to a dskattr.
1174 ****************************************************************************/
1176 void reply_dskattr(struct smb_request *req)
1178 connection_struct *conn = req->conn;
1179 uint64_t dfree,dsize,bsize;
1180 START_PROFILE(SMBdskattr);
1182 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1183 reply_unixerror(req, ERRHRD, ERRgeneral);
1184 END_PROFILE(SMBdskattr);
1185 return;
1188 reply_outbuf(req, 5, 0);
1190 if (Protocol <= PROTOCOL_LANMAN2) {
1191 double total_space, free_space;
1192 /* we need to scale this to a number that DOS6 can handle. We
1193 use floating point so we can handle large drives on systems
1194 that don't have 64 bit integers
1196 we end up displaying a maximum of 2G to DOS systems
1198 total_space = dsize * (double)bsize;
1199 free_space = dfree * (double)bsize;
1201 dsize = (uint64_t)((total_space+63*512) / (64*512));
1202 dfree = (uint64_t)((free_space+63*512) / (64*512));
1204 if (dsize > 0xFFFF) dsize = 0xFFFF;
1205 if (dfree > 0xFFFF) dfree = 0xFFFF;
1207 SSVAL(req->outbuf,smb_vwv0,dsize);
1208 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1209 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1210 SSVAL(req->outbuf,smb_vwv3,dfree);
1211 } else {
1212 SSVAL(req->outbuf,smb_vwv0,dsize);
1213 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1214 SSVAL(req->outbuf,smb_vwv2,512);
1215 SSVAL(req->outbuf,smb_vwv3,dfree);
1218 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1220 END_PROFILE(SMBdskattr);
1221 return;
1224 /****************************************************************************
1225 Reply to a search.
1226 Can be called from SMBsearch, SMBffirst or SMBfunique.
1227 ****************************************************************************/
1229 void reply_search(struct smb_request *req)
1231 connection_struct *conn = req->conn;
1232 const char *mask = NULL;
1233 char *directory = NULL;
1234 char *fname = NULL;
1235 SMB_OFF_T size;
1236 uint32 mode;
1237 time_t date;
1238 uint32 dirtype;
1239 unsigned int numentries = 0;
1240 unsigned int maxentries = 0;
1241 bool finished = False;
1242 const char *p;
1243 int status_len;
1244 char *path = NULL;
1245 char status[21];
1246 int dptr_num= -1;
1247 bool check_descend = False;
1248 bool expect_close = False;
1249 NTSTATUS nt_status;
1250 bool mask_contains_wcard = False;
1251 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1252 TALLOC_CTX *ctx = talloc_tos();
1253 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1255 START_PROFILE(SMBsearch);
1257 if (req->wct < 2) {
1258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1259 END_PROFILE(SMBsearch);
1260 return;
1263 if (lp_posix_pathnames()) {
1264 reply_unknown_new(req, req->cmd);
1265 END_PROFILE(SMBsearch);
1266 return;
1269 /* If we were called as SMBffirst then we must expect close. */
1270 if(req->cmd == SMBffirst) {
1271 expect_close = True;
1274 reply_outbuf(req, 1, 3);
1275 maxentries = SVAL(req->vwv+0, 0);
1276 dirtype = SVAL(req->vwv+1, 0);
1277 p = (const char *)req->buf + 1;
1278 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1279 &nt_status, &mask_contains_wcard);
1280 if (!NT_STATUS_IS_OK(nt_status)) {
1281 reply_nterror(req, nt_status);
1282 END_PROFILE(SMBsearch);
1283 return;
1286 nt_status = resolve_dfspath_wcard(ctx, conn,
1287 req->flags2 & FLAGS2_DFS_PATHNAMES,
1288 path,
1289 &path,
1290 &mask_contains_wcard);
1291 if (!NT_STATUS_IS_OK(nt_status)) {
1292 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1293 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1294 ERRSRV, ERRbadpath);
1295 END_PROFILE(SMBsearch);
1296 return;
1298 reply_nterror(req, nt_status);
1299 END_PROFILE(SMBsearch);
1300 return;
1303 p++;
1304 status_len = SVAL(p, 0);
1305 p += 2;
1307 /* dirtype &= ~aDIR; */
1309 if (status_len == 0) {
1310 SMB_STRUCT_STAT sbuf;
1312 nt_status = unix_convert(ctx, conn, path, True,
1313 &directory, NULL, &sbuf);
1314 if (!NT_STATUS_IS_OK(nt_status)) {
1315 reply_nterror(req, nt_status);
1316 END_PROFILE(SMBsearch);
1317 return;
1320 nt_status = check_name(conn, directory);
1321 if (!NT_STATUS_IS_OK(nt_status)) {
1322 reply_nterror(req, nt_status);
1323 END_PROFILE(SMBsearch);
1324 return;
1327 p = strrchr_m(directory,'/');
1328 if ((p != NULL) && (*directory != '/')) {
1329 mask = p + 1;
1330 directory = talloc_strndup(ctx, directory,
1331 PTR_DIFF(p, directory));
1332 } else {
1333 mask = directory;
1334 directory = talloc_strdup(ctx,".");
1337 if (!directory) {
1338 reply_nterror(req, NT_STATUS_NO_MEMORY);
1339 END_PROFILE(SMBsearch);
1340 return;
1343 memset((char *)status,'\0',21);
1344 SCVAL(status,0,(dirtype & 0x1F));
1346 nt_status = dptr_create(conn,
1347 directory,
1348 True,
1349 expect_close,
1350 req->smbpid,
1351 mask,
1352 mask_contains_wcard,
1353 dirtype,
1354 &conn->dirptr);
1355 if (!NT_STATUS_IS_OK(nt_status)) {
1356 reply_nterror(req, nt_status);
1357 END_PROFILE(SMBsearch);
1358 return;
1360 dptr_num = dptr_dnum(conn->dirptr);
1361 } else {
1362 int status_dirtype;
1364 memcpy(status,p,21);
1365 status_dirtype = CVAL(status,0) & 0x1F;
1366 if (status_dirtype != (dirtype & 0x1F)) {
1367 dirtype = status_dirtype;
1370 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1371 if (!conn->dirptr) {
1372 goto SearchEmpty;
1374 string_set(&conn->dirpath,dptr_path(dptr_num));
1375 mask = dptr_wcard(dptr_num);
1376 if (!mask) {
1377 goto SearchEmpty;
1380 * For a 'continue' search we have no string. So
1381 * check from the initial saved string.
1383 mask_contains_wcard = ms_has_wild(mask);
1384 dirtype = dptr_attr(dptr_num);
1387 DEBUG(4,("dptr_num is %d\n",dptr_num));
1389 if ((dirtype&0x1F) == aVOLID) {
1390 char buf[DIR_STRUCT_SIZE];
1391 memcpy(buf,status,21);
1392 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1393 0,aVOLID,0,!allow_long_path_components)) {
1394 reply_nterror(req, NT_STATUS_NO_MEMORY);
1395 END_PROFILE(SMBsearch);
1396 return;
1398 dptr_fill(buf+12,dptr_num);
1399 if (dptr_zero(buf+12) && (status_len==0)) {
1400 numentries = 1;
1401 } else {
1402 numentries = 0;
1404 if (message_push_blob(&req->outbuf,
1405 data_blob_const(buf, sizeof(buf)))
1406 == -1) {
1407 reply_nterror(req, NT_STATUS_NO_MEMORY);
1408 END_PROFILE(SMBsearch);
1409 return;
1411 } else {
1412 unsigned int i;
1413 maxentries = MIN(
1414 maxentries,
1415 ((BUFFER_SIZE -
1416 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1417 /DIR_STRUCT_SIZE));
1419 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1420 conn->dirpath,lp_dontdescend(SNUM(conn))));
1421 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1422 check_descend = True;
1425 for (i=numentries;(i<maxentries) && !finished;i++) {
1426 finished = !get_dir_entry(ctx,
1427 conn,
1428 mask,
1429 dirtype,
1430 &fname,
1431 &size,
1432 &mode,
1433 &date,
1434 check_descend,
1435 ask_sharemode);
1436 if (!finished) {
1437 char buf[DIR_STRUCT_SIZE];
1438 memcpy(buf,status,21);
1439 if (!make_dir_struct(ctx,
1440 buf,
1441 mask,
1442 fname,
1443 size,
1444 mode,
1445 date,
1446 !allow_long_path_components)) {
1447 reply_nterror(req, NT_STATUS_NO_MEMORY);
1448 END_PROFILE(SMBsearch);
1449 return;
1451 if (!dptr_fill(buf+12,dptr_num)) {
1452 break;
1454 if (message_push_blob(&req->outbuf,
1455 data_blob_const(buf, sizeof(buf)))
1456 == -1) {
1457 reply_nterror(req, NT_STATUS_NO_MEMORY);
1458 END_PROFILE(SMBsearch);
1459 return;
1461 numentries++;
1466 SearchEmpty:
1468 /* If we were called as SMBffirst with smb_search_id == NULL
1469 and no entries were found then return error and close dirptr
1470 (X/Open spec) */
1472 if (numentries == 0) {
1473 dptr_close(&dptr_num);
1474 } else if(expect_close && status_len == 0) {
1475 /* Close the dptr - we know it's gone */
1476 dptr_close(&dptr_num);
1479 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1480 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1481 dptr_close(&dptr_num);
1484 if ((numentries == 0) && !mask_contains_wcard) {
1485 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1486 END_PROFILE(SMBsearch);
1487 return;
1490 SSVAL(req->outbuf,smb_vwv0,numentries);
1491 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1492 SCVAL(smb_buf(req->outbuf),0,5);
1493 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1495 /* The replies here are never long name. */
1496 SSVAL(req->outbuf, smb_flg2,
1497 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1498 if (!allow_long_path_components) {
1499 SSVAL(req->outbuf, smb_flg2,
1500 SVAL(req->outbuf, smb_flg2)
1501 & (~FLAGS2_LONG_PATH_COMPONENTS));
1504 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1505 SSVAL(req->outbuf, smb_flg2,
1506 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1508 if (!directory) {
1509 directory = dptr_path(dptr_num);
1512 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1513 smb_fn_name(req->cmd),
1514 mask,
1515 directory ? directory : "./",
1516 dirtype,
1517 numentries,
1518 maxentries ));
1520 END_PROFILE(SMBsearch);
1521 return;
1524 /****************************************************************************
1525 Reply to a fclose (stop directory search).
1526 ****************************************************************************/
1528 void reply_fclose(struct smb_request *req)
1530 int status_len;
1531 char status[21];
1532 int dptr_num= -2;
1533 const char *p;
1534 char *path = NULL;
1535 NTSTATUS err;
1536 bool path_contains_wcard = False;
1537 TALLOC_CTX *ctx = talloc_tos();
1539 START_PROFILE(SMBfclose);
1541 if (lp_posix_pathnames()) {
1542 reply_unknown_new(req, req->cmd);
1543 END_PROFILE(SMBfclose);
1544 return;
1547 p = (const char *)req->buf + 1;
1548 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1549 &err, &path_contains_wcard);
1550 if (!NT_STATUS_IS_OK(err)) {
1551 reply_nterror(req, err);
1552 END_PROFILE(SMBfclose);
1553 return;
1555 p++;
1556 status_len = SVAL(p,0);
1557 p += 2;
1559 if (status_len == 0) {
1560 reply_doserror(req, ERRSRV, ERRsrverror);
1561 END_PROFILE(SMBfclose);
1562 return;
1565 memcpy(status,p,21);
1567 if(dptr_fetch(status+12,&dptr_num)) {
1568 /* Close the dptr - we know it's gone */
1569 dptr_close(&dptr_num);
1572 reply_outbuf(req, 1, 0);
1573 SSVAL(req->outbuf,smb_vwv0,0);
1575 DEBUG(3,("search close\n"));
1577 END_PROFILE(SMBfclose);
1578 return;
1581 /****************************************************************************
1582 Reply to an open.
1583 ****************************************************************************/
1585 void reply_open(struct smb_request *req)
1587 connection_struct *conn = req->conn;
1588 char *fname = NULL;
1589 uint32 fattr=0;
1590 SMB_OFF_T size = 0;
1591 time_t mtime=0;
1592 int info;
1593 SMB_STRUCT_STAT sbuf;
1594 files_struct *fsp;
1595 int oplock_request;
1596 int deny_mode;
1597 uint32 dos_attr;
1598 uint32 access_mask;
1599 uint32 share_mode;
1600 uint32 create_disposition;
1601 uint32 create_options = 0;
1602 NTSTATUS status;
1603 TALLOC_CTX *ctx = talloc_tos();
1605 START_PROFILE(SMBopen);
1607 if (req->wct < 2) {
1608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1609 END_PROFILE(SMBopen);
1610 return;
1613 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1614 deny_mode = SVAL(req->vwv+0, 0);
1615 dos_attr = SVAL(req->vwv+1, 0);
1617 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1618 STR_TERMINATE, &status);
1619 if (!NT_STATUS_IS_OK(status)) {
1620 reply_nterror(req, status);
1621 END_PROFILE(SMBopen);
1622 return;
1625 if (!map_open_params_to_ntcreate(
1626 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1627 &share_mode, &create_disposition, &create_options)) {
1628 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1629 END_PROFILE(SMBopen);
1630 return;
1633 status = SMB_VFS_CREATE_FILE(
1634 conn, /* conn */
1635 req, /* req */
1636 0, /* root_dir_fid */
1637 fname, /* fname */
1638 CFF_DOS_PATH, /* create_file_flags */
1639 access_mask, /* access_mask */
1640 share_mode, /* share_access */
1641 create_disposition, /* create_disposition*/
1642 create_options, /* create_options */
1643 dos_attr, /* file_attributes */
1644 oplock_request, /* oplock_request */
1645 0, /* allocation_size */
1646 NULL, /* sd */
1647 NULL, /* ea_list */
1648 &fsp, /* result */
1649 &info, /* pinfo */
1650 &sbuf); /* psbuf */
1652 if (!NT_STATUS_IS_OK(status)) {
1653 if (open_was_deferred(req->mid)) {
1654 /* We have re-scheduled this call. */
1655 END_PROFILE(SMBopen);
1656 return;
1658 reply_openerror(req, status);
1659 END_PROFILE(SMBopen);
1660 return;
1663 size = sbuf.st_size;
1664 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1665 mtime = sbuf.st_mtime;
1667 if (fattr & aDIR) {
1668 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1669 close_file(req, fsp, ERROR_CLOSE);
1670 reply_doserror(req, ERRDOS,ERRnoaccess);
1671 END_PROFILE(SMBopen);
1672 return;
1675 reply_outbuf(req, 7, 0);
1676 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1677 SSVAL(req->outbuf,smb_vwv1,fattr);
1678 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1679 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1680 } else {
1681 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1683 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1684 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1686 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1687 SCVAL(req->outbuf,smb_flg,
1688 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1691 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1692 SCVAL(req->outbuf,smb_flg,
1693 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1695 END_PROFILE(SMBopen);
1696 return;
1699 /****************************************************************************
1700 Reply to an open and X.
1701 ****************************************************************************/
1703 void reply_open_and_X(struct smb_request *req)
1705 connection_struct *conn = req->conn;
1706 char *fname = NULL;
1707 uint16 open_flags;
1708 int deny_mode;
1709 uint32 smb_attr;
1710 /* Breakout the oplock request bits so we can set the
1711 reply bits separately. */
1712 int ex_oplock_request;
1713 int core_oplock_request;
1714 int oplock_request;
1715 #if 0
1716 int smb_sattr = SVAL(req->vwv+4, 0);
1717 uint32 smb_time = make_unix_date3(req->vwv+6);
1718 #endif
1719 int smb_ofun;
1720 uint32 fattr=0;
1721 int mtime=0;
1722 SMB_STRUCT_STAT sbuf;
1723 int smb_action = 0;
1724 files_struct *fsp;
1725 NTSTATUS status;
1726 uint64_t allocation_size;
1727 ssize_t retval = -1;
1728 uint32 access_mask;
1729 uint32 share_mode;
1730 uint32 create_disposition;
1731 uint32 create_options = 0;
1732 TALLOC_CTX *ctx = talloc_tos();
1734 START_PROFILE(SMBopenX);
1736 if (req->wct < 15) {
1737 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1738 END_PROFILE(SMBopenX);
1739 return;
1742 open_flags = SVAL(req->vwv+2, 0);
1743 deny_mode = SVAL(req->vwv+3, 0);
1744 smb_attr = SVAL(req->vwv+5, 0);
1745 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1746 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1747 oplock_request = ex_oplock_request | core_oplock_request;
1748 smb_ofun = SVAL(req->vwv+8, 0);
1749 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1751 /* If it's an IPC, pass off the pipe handler. */
1752 if (IS_IPC(conn)) {
1753 if (lp_nt_pipe_support()) {
1754 reply_open_pipe_and_X(conn, req);
1755 } else {
1756 reply_doserror(req, ERRSRV, ERRaccess);
1758 END_PROFILE(SMBopenX);
1759 return;
1762 /* XXXX we need to handle passed times, sattr and flags */
1763 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1764 STR_TERMINATE, &status);
1765 if (!NT_STATUS_IS_OK(status)) {
1766 reply_nterror(req, status);
1767 END_PROFILE(SMBopenX);
1768 return;
1771 if (!map_open_params_to_ntcreate(
1772 fname, deny_mode, smb_ofun, &access_mask,
1773 &share_mode, &create_disposition, &create_options)) {
1774 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1775 END_PROFILE(SMBopenX);
1776 return;
1779 status = SMB_VFS_CREATE_FILE(
1780 conn, /* conn */
1781 req, /* req */
1782 0, /* root_dir_fid */
1783 fname, /* fname */
1784 CFF_DOS_PATH, /* create_file_flags */
1785 access_mask, /* access_mask */
1786 share_mode, /* share_access */
1787 create_disposition, /* create_disposition*/
1788 create_options, /* create_options */
1789 smb_attr, /* file_attributes */
1790 oplock_request, /* oplock_request */
1791 0, /* allocation_size */
1792 NULL, /* sd */
1793 NULL, /* ea_list */
1794 &fsp, /* result */
1795 &smb_action, /* pinfo */
1796 &sbuf); /* psbuf */
1798 if (!NT_STATUS_IS_OK(status)) {
1799 END_PROFILE(SMBopenX);
1800 if (open_was_deferred(req->mid)) {
1801 /* We have re-scheduled this call. */
1802 return;
1804 reply_openerror(req, status);
1805 return;
1808 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1809 if the file is truncated or created. */
1810 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1811 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1812 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1813 close_file(req, fsp, ERROR_CLOSE);
1814 reply_nterror(req, NT_STATUS_DISK_FULL);
1815 END_PROFILE(SMBopenX);
1816 return;
1818 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1819 if (retval < 0) {
1820 close_file(req, fsp, ERROR_CLOSE);
1821 reply_nterror(req, NT_STATUS_DISK_FULL);
1822 END_PROFILE(SMBopenX);
1823 return;
1825 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1828 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1829 mtime = sbuf.st_mtime;
1830 if (fattr & aDIR) {
1831 close_file(req, fsp, ERROR_CLOSE);
1832 reply_doserror(req, ERRDOS, ERRnoaccess);
1833 END_PROFILE(SMBopenX);
1834 return;
1837 /* If the caller set the extended oplock request bit
1838 and we granted one (by whatever means) - set the
1839 correct bit for extended oplock reply.
1842 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1843 smb_action |= EXTENDED_OPLOCK_GRANTED;
1846 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1847 smb_action |= EXTENDED_OPLOCK_GRANTED;
1850 /* If the caller set the core oplock request bit
1851 and we granted one (by whatever means) - set the
1852 correct bit for core oplock reply.
1855 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1856 reply_outbuf(req, 19, 0);
1857 } else {
1858 reply_outbuf(req, 15, 0);
1861 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1862 SCVAL(req->outbuf, smb_flg,
1863 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1866 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1867 SCVAL(req->outbuf, smb_flg,
1868 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1871 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1872 SSVAL(req->outbuf,smb_vwv3,fattr);
1873 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1874 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1875 } else {
1876 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1878 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1879 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1880 SSVAL(req->outbuf,smb_vwv11,smb_action);
1882 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1883 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1886 END_PROFILE(SMBopenX);
1887 chain_reply(req);
1888 return;
1891 /****************************************************************************
1892 Reply to a SMBulogoffX.
1893 ****************************************************************************/
1895 void reply_ulogoffX(struct smb_request *req)
1897 user_struct *vuser;
1899 START_PROFILE(SMBulogoffX);
1901 vuser = get_valid_user_struct(req->vuid);
1903 if(vuser == NULL) {
1904 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1905 req->vuid));
1908 /* in user level security we are supposed to close any files
1909 open by this user */
1910 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1911 file_close_user(req->vuid);
1914 invalidate_vuid(req->vuid);
1916 reply_outbuf(req, 2, 0);
1918 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1920 END_PROFILE(SMBulogoffX);
1921 chain_reply(req);
1924 /****************************************************************************
1925 Reply to a mknew or a create.
1926 ****************************************************************************/
1928 void reply_mknew(struct smb_request *req)
1930 connection_struct *conn = req->conn;
1931 char *fname = NULL;
1932 uint32 fattr = 0;
1933 struct timespec ts[2];
1934 files_struct *fsp;
1935 int oplock_request = 0;
1936 SMB_STRUCT_STAT sbuf;
1937 NTSTATUS status;
1938 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1939 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1940 uint32 create_disposition;
1941 uint32 create_options = 0;
1942 TALLOC_CTX *ctx = talloc_tos();
1944 START_PROFILE(SMBcreate);
1946 if (req->wct < 3) {
1947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1948 END_PROFILE(SMBcreate);
1949 return;
1952 fattr = SVAL(req->vwv+0, 0);
1953 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1955 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
1956 /* mtime. */
1958 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
1959 STR_TERMINATE, &status);
1960 if (!NT_STATUS_IS_OK(status)) {
1961 reply_nterror(req, status);
1962 END_PROFILE(SMBcreate);
1963 return;
1966 if (fattr & aVOLID) {
1967 DEBUG(0,("Attempt to create file (%s) with volid set - "
1968 "please report this\n", fname));
1971 if(req->cmd == SMBmknew) {
1972 /* We should fail if file exists. */
1973 create_disposition = FILE_CREATE;
1974 } else {
1975 /* Create if file doesn't exist, truncate if it does. */
1976 create_disposition = FILE_OVERWRITE_IF;
1979 status = SMB_VFS_CREATE_FILE(
1980 conn, /* conn */
1981 req, /* req */
1982 0, /* root_dir_fid */
1983 fname, /* fname */
1984 CFF_DOS_PATH, /* create_file_flags */
1985 access_mask, /* access_mask */
1986 share_mode, /* share_access */
1987 create_disposition, /* create_disposition*/
1988 create_options, /* create_options */
1989 fattr, /* file_attributes */
1990 oplock_request, /* oplock_request */
1991 0, /* allocation_size */
1992 NULL, /* sd */
1993 NULL, /* ea_list */
1994 &fsp, /* result */
1995 NULL, /* pinfo */
1996 &sbuf); /* psbuf */
1998 if (!NT_STATUS_IS_OK(status)) {
1999 END_PROFILE(SMBcreate);
2000 if (open_was_deferred(req->mid)) {
2001 /* We have re-scheduled this call. */
2002 return;
2004 reply_openerror(req, status);
2005 return;
2008 ts[0] = get_atimespec(&sbuf); /* atime. */
2009 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, ts, true);
2010 if (!NT_STATUS_IS_OK(status)) {
2011 END_PROFILE(SMBcreate);
2012 reply_openerror(req, status);
2013 return;
2016 reply_outbuf(req, 1, 0);
2017 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2019 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2020 SCVAL(req->outbuf,smb_flg,
2021 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2024 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2025 SCVAL(req->outbuf,smb_flg,
2026 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2029 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2030 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2031 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2033 END_PROFILE(SMBcreate);
2034 return;
2037 /****************************************************************************
2038 Reply to a create temporary file.
2039 ****************************************************************************/
2041 void reply_ctemp(struct smb_request *req)
2043 connection_struct *conn = req->conn;
2044 char *fname = NULL;
2045 uint32 fattr;
2046 files_struct *fsp;
2047 int oplock_request;
2048 int tmpfd;
2049 SMB_STRUCT_STAT sbuf;
2050 char *s;
2051 NTSTATUS status;
2052 TALLOC_CTX *ctx = talloc_tos();
2054 START_PROFILE(SMBctemp);
2056 if (req->wct < 3) {
2057 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2058 END_PROFILE(SMBctemp);
2059 return;
2062 fattr = SVAL(req->vwv+0, 0);
2063 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2065 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2066 STR_TERMINATE, &status);
2067 if (!NT_STATUS_IS_OK(status)) {
2068 reply_nterror(req, status);
2069 END_PROFILE(SMBctemp);
2070 return;
2072 if (*fname) {
2073 fname = talloc_asprintf(ctx,
2074 "%s/TMXXXXXX",
2075 fname);
2076 } else {
2077 fname = talloc_strdup(ctx, "TMXXXXXX");
2080 if (!fname) {
2081 reply_nterror(req, NT_STATUS_NO_MEMORY);
2082 END_PROFILE(SMBctemp);
2083 return;
2086 status = resolve_dfspath(ctx, conn,
2087 req->flags2 & FLAGS2_DFS_PATHNAMES,
2088 fname,
2089 &fname);
2090 if (!NT_STATUS_IS_OK(status)) {
2091 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2092 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2093 ERRSRV, ERRbadpath);
2094 END_PROFILE(SMBctemp);
2095 return;
2097 reply_nterror(req, status);
2098 END_PROFILE(SMBctemp);
2099 return;
2102 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2103 if (!NT_STATUS_IS_OK(status)) {
2104 reply_nterror(req, status);
2105 END_PROFILE(SMBctemp);
2106 return;
2109 status = check_name(conn, fname);
2110 if (!NT_STATUS_IS_OK(status)) {
2111 reply_nterror(req, status);
2112 END_PROFILE(SMBctemp);
2113 return;
2116 tmpfd = smb_mkstemp(fname);
2117 if (tmpfd == -1) {
2118 reply_unixerror(req, ERRDOS, ERRnoaccess);
2119 END_PROFILE(SMBctemp);
2120 return;
2123 SMB_VFS_STAT(conn,fname,&sbuf);
2125 /* We should fail if file does not exist. */
2126 status = SMB_VFS_CREATE_FILE(
2127 conn, /* conn */
2128 req, /* req */
2129 0, /* root_dir_fid */
2130 fname, /* fname */
2131 0, /* create_file_flags */
2132 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2133 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2134 FILE_OPEN, /* create_disposition*/
2135 0, /* create_options */
2136 fattr, /* file_attributes */
2137 oplock_request, /* oplock_request */
2138 0, /* allocation_size */
2139 NULL, /* sd */
2140 NULL, /* ea_list */
2141 &fsp, /* result */
2142 NULL, /* pinfo */
2143 &sbuf); /* psbuf */
2145 /* close fd from smb_mkstemp() */
2146 close(tmpfd);
2148 if (!NT_STATUS_IS_OK(status)) {
2149 if (open_was_deferred(req->mid)) {
2150 /* We have re-scheduled this call. */
2151 END_PROFILE(SMBctemp);
2152 return;
2154 reply_openerror(req, status);
2155 END_PROFILE(SMBctemp);
2156 return;
2159 reply_outbuf(req, 1, 0);
2160 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2162 /* the returned filename is relative to the directory */
2163 s = strrchr_m(fsp->fsp_name, '/');
2164 if (!s) {
2165 s = fsp->fsp_name;
2166 } else {
2167 s++;
2170 #if 0
2171 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2172 thing in the byte section. JRA */
2173 SSVALS(p, 0, -1); /* what is this? not in spec */
2174 #endif
2175 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2176 == -1) {
2177 reply_nterror(req, NT_STATUS_NO_MEMORY);
2178 END_PROFILE(SMBctemp);
2179 return;
2182 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2183 SCVAL(req->outbuf, smb_flg,
2184 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2187 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2188 SCVAL(req->outbuf, smb_flg,
2189 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2192 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2193 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2194 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2196 END_PROFILE(SMBctemp);
2197 return;
2200 /*******************************************************************
2201 Check if a user is allowed to rename a file.
2202 ********************************************************************/
2204 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2205 uint16 dirtype, SMB_STRUCT_STAT *pst)
2207 uint32 fmode;
2209 if (!CAN_WRITE(conn)) {
2210 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2213 fmode = dos_mode(conn, fsp->fsp_name, pst);
2214 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2215 return NT_STATUS_NO_SUCH_FILE;
2218 if (S_ISDIR(pst->st_mode)) {
2219 return NT_STATUS_OK;
2222 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2223 return NT_STATUS_OK;
2226 return NT_STATUS_ACCESS_DENIED;
2229 /*******************************************************************
2230 * unlink a file with all relevant access checks
2231 *******************************************************************/
2233 static NTSTATUS do_unlink(connection_struct *conn,
2234 struct smb_request *req,
2235 const char *fname,
2236 uint32 dirtype)
2238 SMB_STRUCT_STAT sbuf;
2239 uint32 fattr;
2240 files_struct *fsp;
2241 uint32 dirtype_orig = dirtype;
2242 NTSTATUS status;
2244 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2246 if (!CAN_WRITE(conn)) {
2247 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2250 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2251 return map_nt_error_from_unix(errno);
2254 fattr = dos_mode(conn,fname,&sbuf);
2256 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2257 dirtype = aDIR|aARCH|aRONLY;
2260 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2261 if (!dirtype) {
2262 return NT_STATUS_NO_SUCH_FILE;
2265 if (!dir_check_ftype(conn, fattr, dirtype)) {
2266 if (fattr & aDIR) {
2267 return NT_STATUS_FILE_IS_A_DIRECTORY;
2269 return NT_STATUS_NO_SUCH_FILE;
2272 if (dirtype_orig & 0x8000) {
2273 /* These will never be set for POSIX. */
2274 return NT_STATUS_NO_SUCH_FILE;
2277 #if 0
2278 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2279 return NT_STATUS_FILE_IS_A_DIRECTORY;
2282 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2283 return NT_STATUS_NO_SUCH_FILE;
2286 if (dirtype & 0xFF00) {
2287 /* These will never be set for POSIX. */
2288 return NT_STATUS_NO_SUCH_FILE;
2291 dirtype &= 0xFF;
2292 if (!dirtype) {
2293 return NT_STATUS_NO_SUCH_FILE;
2296 /* Can't delete a directory. */
2297 if (fattr & aDIR) {
2298 return NT_STATUS_FILE_IS_A_DIRECTORY;
2300 #endif
2302 #if 0 /* JRATEST */
2303 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2304 return NT_STATUS_OBJECT_NAME_INVALID;
2305 #endif /* JRATEST */
2307 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2309 On a Windows share, a file with read-only dosmode can be opened with
2310 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2311 fails with NT_STATUS_CANNOT_DELETE error.
2313 This semantic causes a problem that a user can not
2314 rename a file with read-only dosmode on a Samba share
2315 from a Windows command prompt (i.e. cmd.exe, but can rename
2316 from Windows Explorer).
2319 if (!lp_delete_readonly(SNUM(conn))) {
2320 if (fattr & aRONLY) {
2321 return NT_STATUS_CANNOT_DELETE;
2325 /* On open checks the open itself will check the share mode, so
2326 don't do it here as we'll get it wrong. */
2328 status = SMB_VFS_CREATE_FILE
2329 (conn, /* conn */
2330 req, /* req */
2331 0, /* root_dir_fid */
2332 fname, /* fname */
2333 0, /* create_file_flags */
2334 DELETE_ACCESS, /* access_mask */
2335 FILE_SHARE_NONE, /* share_access */
2336 FILE_OPEN, /* create_disposition*/
2337 FILE_NON_DIRECTORY_FILE, /* create_options */
2338 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2339 0, /* oplock_request */
2340 0, /* allocation_size */
2341 NULL, /* sd */
2342 NULL, /* ea_list */
2343 &fsp, /* result */
2344 NULL, /* pinfo */
2345 &sbuf); /* psbuf */
2347 if (!NT_STATUS_IS_OK(status)) {
2348 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2349 nt_errstr(status)));
2350 return status;
2353 /* The set is across all open files on this dev/inode pair. */
2354 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2355 close_file(req, fsp, NORMAL_CLOSE);
2356 return NT_STATUS_ACCESS_DENIED;
2359 return close_file(req, fsp, NORMAL_CLOSE);
2362 /****************************************************************************
2363 The guts of the unlink command, split out so it may be called by the NT SMB
2364 code.
2365 ****************************************************************************/
2367 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2368 uint32 dirtype, const char *name_in, bool has_wild)
2370 const char *directory = NULL;
2371 char *mask = NULL;
2372 char *name = NULL;
2373 char *p = NULL;
2374 int count=0;
2375 NTSTATUS status = NT_STATUS_OK;
2376 SMB_STRUCT_STAT sbuf;
2377 TALLOC_CTX *ctx = talloc_tos();
2379 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2380 if (!NT_STATUS_IS_OK(status)) {
2381 return status;
2384 p = strrchr_m(name,'/');
2385 if (!p) {
2386 directory = talloc_strdup(ctx, ".");
2387 if (!directory) {
2388 return NT_STATUS_NO_MEMORY;
2390 mask = name;
2391 } else {
2392 *p = 0;
2393 directory = name;
2394 mask = p+1;
2398 * We should only check the mangled cache
2399 * here if unix_convert failed. This means
2400 * that the path in 'mask' doesn't exist
2401 * on the file system and so we need to look
2402 * for a possible mangle. This patch from
2403 * Tine Smukavec <valentin.smukavec@hermes.si>.
2406 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2407 char *new_mask = NULL;
2408 mangle_lookup_name_from_8_3(ctx,
2409 mask,
2410 &new_mask,
2411 conn->params );
2412 if (new_mask) {
2413 mask = new_mask;
2417 if (!has_wild) {
2418 directory = talloc_asprintf(ctx,
2419 "%s/%s",
2420 directory,
2421 mask);
2422 if (!directory) {
2423 return NT_STATUS_NO_MEMORY;
2425 if (dirtype == 0) {
2426 dirtype = FILE_ATTRIBUTE_NORMAL;
2429 status = check_name(conn, directory);
2430 if (!NT_STATUS_IS_OK(status)) {
2431 return status;
2434 status = do_unlink(conn, req, directory, dirtype);
2435 if (!NT_STATUS_IS_OK(status)) {
2436 return status;
2439 count++;
2440 } else {
2441 struct smb_Dir *dir_hnd = NULL;
2442 long offset = 0;
2443 const char *dname;
2445 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2446 return NT_STATUS_OBJECT_NAME_INVALID;
2449 if (strequal(mask,"????????.???")) {
2450 mask[0] = '*';
2451 mask[1] = '\0';
2454 status = check_name(conn, directory);
2455 if (!NT_STATUS_IS_OK(status)) {
2456 return status;
2459 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2460 dirtype);
2461 if (dir_hnd == NULL) {
2462 return map_nt_error_from_unix(errno);
2465 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2466 the pattern matches against the long name, otherwise the short name
2467 We don't implement this yet XXXX
2470 status = NT_STATUS_NO_SUCH_FILE;
2472 while ((dname = ReadDirName(dir_hnd, &offset))) {
2473 SMB_STRUCT_STAT st;
2474 char *fname = NULL;
2476 if (!is_visible_file(conn, directory, dname, &st, True)) {
2477 continue;
2480 /* Quick check for "." and ".." */
2481 if (ISDOT(dname) || ISDOTDOT(dname)) {
2482 continue;
2485 if(!mask_match(dname, mask, conn->case_sensitive)) {
2486 continue;
2489 fname = talloc_asprintf(ctx, "%s/%s",
2490 directory,
2491 dname);
2492 if (!fname) {
2493 return NT_STATUS_NO_MEMORY;
2496 status = check_name(conn, fname);
2497 if (!NT_STATUS_IS_OK(status)) {
2498 TALLOC_FREE(dir_hnd);
2499 return status;
2502 status = do_unlink(conn, req, fname, dirtype);
2503 if (!NT_STATUS_IS_OK(status)) {
2504 TALLOC_FREE(fname);
2505 continue;
2508 count++;
2509 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2510 fname));
2512 TALLOC_FREE(fname);
2514 TALLOC_FREE(dir_hnd);
2517 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2518 status = map_nt_error_from_unix(errno);
2521 return status;
2524 /****************************************************************************
2525 Reply to a unlink
2526 ****************************************************************************/
2528 void reply_unlink(struct smb_request *req)
2530 connection_struct *conn = req->conn;
2531 char *name = NULL;
2532 uint32 dirtype;
2533 NTSTATUS status;
2534 bool path_contains_wcard = False;
2535 TALLOC_CTX *ctx = talloc_tos();
2537 START_PROFILE(SMBunlink);
2539 if (req->wct < 1) {
2540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2541 END_PROFILE(SMBunlink);
2542 return;
2545 dirtype = SVAL(req->vwv+0, 0);
2547 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2548 STR_TERMINATE, &status,
2549 &path_contains_wcard);
2550 if (!NT_STATUS_IS_OK(status)) {
2551 reply_nterror(req, status);
2552 END_PROFILE(SMBunlink);
2553 return;
2556 status = resolve_dfspath_wcard(ctx, conn,
2557 req->flags2 & FLAGS2_DFS_PATHNAMES,
2558 name,
2559 &name,
2560 &path_contains_wcard);
2561 if (!NT_STATUS_IS_OK(status)) {
2562 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2563 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2564 ERRSRV, ERRbadpath);
2565 END_PROFILE(SMBunlink);
2566 return;
2568 reply_nterror(req, status);
2569 END_PROFILE(SMBunlink);
2570 return;
2573 DEBUG(3,("reply_unlink : %s\n",name));
2575 status = unlink_internals(conn, req, dirtype, name,
2576 path_contains_wcard);
2577 if (!NT_STATUS_IS_OK(status)) {
2578 if (open_was_deferred(req->mid)) {
2579 /* We have re-scheduled this call. */
2580 END_PROFILE(SMBunlink);
2581 return;
2583 reply_nterror(req, status);
2584 END_PROFILE(SMBunlink);
2585 return;
2588 reply_outbuf(req, 0, 0);
2589 END_PROFILE(SMBunlink);
2591 return;
2594 /****************************************************************************
2595 Fail for readbraw.
2596 ****************************************************************************/
2598 static void fail_readraw(void)
2600 const char *errstr = talloc_asprintf(talloc_tos(),
2601 "FAIL ! reply_readbraw: socket write fail (%s)",
2602 strerror(errno));
2603 if (!errstr) {
2604 errstr = "";
2606 exit_server_cleanly(errstr);
2609 /****************************************************************************
2610 Fake (read/write) sendfile. Returns -1 on read or write fail.
2611 ****************************************************************************/
2613 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2614 size_t nread)
2616 size_t bufsize;
2617 size_t tosend = nread;
2618 char *buf;
2620 if (nread == 0) {
2621 return 0;
2624 bufsize = MIN(nread, 65536);
2626 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2627 return -1;
2630 while (tosend > 0) {
2631 ssize_t ret;
2632 size_t cur_read;
2634 if (tosend > bufsize) {
2635 cur_read = bufsize;
2636 } else {
2637 cur_read = tosend;
2639 ret = read_file(fsp,buf,startpos,cur_read);
2640 if (ret == -1) {
2641 SAFE_FREE(buf);
2642 return -1;
2645 /* If we had a short read, fill with zeros. */
2646 if (ret < cur_read) {
2647 memset(buf, '\0', cur_read - ret);
2650 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2651 SAFE_FREE(buf);
2652 return -1;
2654 tosend -= cur_read;
2655 startpos += cur_read;
2658 SAFE_FREE(buf);
2659 return (ssize_t)nread;
2662 /****************************************************************************
2663 Return a readbraw error (4 bytes of zero).
2664 ****************************************************************************/
2666 static void reply_readbraw_error(void)
2668 char header[4];
2669 SIVAL(header,0,0);
2670 if (write_data(smbd_server_fd(),header,4) != 4) {
2671 fail_readraw();
2675 /****************************************************************************
2676 Use sendfile in readbraw.
2677 ****************************************************************************/
2679 void send_file_readbraw(connection_struct *conn,
2680 files_struct *fsp,
2681 SMB_OFF_T startpos,
2682 size_t nread,
2683 ssize_t mincount)
2685 char *outbuf = NULL;
2686 ssize_t ret=0;
2688 #if defined(WITH_SENDFILE)
2690 * We can only use sendfile on a non-chained packet
2691 * but we can use on a non-oplocked file. tridge proved this
2692 * on a train in Germany :-). JRA.
2693 * reply_readbraw has already checked the length.
2696 if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) &&
2697 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2698 char header[4];
2699 DATA_BLOB header_blob;
2701 _smb_setlen(header,nread);
2702 header_blob = data_blob_const(header, 4);
2704 if (SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2705 &header_blob, startpos, nread) == -1) {
2706 /* Returning ENOSYS means no data at all was sent.
2707 * Do this as a normal read. */
2708 if (errno == ENOSYS) {
2709 goto normal_readbraw;
2713 * Special hack for broken Linux with no working sendfile. If we
2714 * return EINTR we sent the header but not the rest of the data.
2715 * Fake this up by doing read/write calls.
2717 if (errno == EINTR) {
2718 /* Ensure we don't do this again. */
2719 set_use_sendfile(SNUM(conn), False);
2720 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2722 if (fake_sendfile(fsp, startpos, nread) == -1) {
2723 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2724 fsp->fsp_name, strerror(errno) ));
2725 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2727 return;
2730 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2731 fsp->fsp_name, strerror(errno) ));
2732 exit_server_cleanly("send_file_readbraw sendfile failed");
2735 return;
2737 #endif
2739 normal_readbraw:
2741 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2742 if (!outbuf) {
2743 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2744 (unsigned)(nread+4)));
2745 reply_readbraw_error();
2746 return;
2749 if (nread > 0) {
2750 ret = read_file(fsp,outbuf+4,startpos,nread);
2751 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2752 if (ret < mincount)
2753 ret = 0;
2754 #else
2755 if (ret < nread)
2756 ret = 0;
2757 #endif
2760 _smb_setlen(outbuf,ret);
2761 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2762 fail_readraw();
2764 TALLOC_FREE(outbuf);
2767 /****************************************************************************
2768 Reply to a readbraw (core+ protocol).
2769 ****************************************************************************/
2771 void reply_readbraw(struct smb_request *req)
2773 connection_struct *conn = req->conn;
2774 ssize_t maxcount,mincount;
2775 size_t nread = 0;
2776 SMB_OFF_T startpos;
2777 files_struct *fsp;
2778 SMB_STRUCT_STAT st;
2779 SMB_OFF_T size = 0;
2781 START_PROFILE(SMBreadbraw);
2783 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2784 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2785 "raw reads/writes are disallowed.");
2788 if (req->wct < 8) {
2789 reply_readbraw_error();
2790 END_PROFILE(SMBreadbraw);
2791 return;
2795 * Special check if an oplock break has been issued
2796 * and the readraw request croses on the wire, we must
2797 * return a zero length response here.
2800 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2803 * We have to do a check_fsp by hand here, as
2804 * we must always return 4 zero bytes on error,
2805 * not a NTSTATUS.
2808 if (!fsp || !conn || conn != fsp->conn ||
2809 req->vuid != fsp->vuid ||
2810 fsp->is_directory || fsp->fh->fd == -1) {
2812 * fsp could be NULL here so use the value from the packet. JRA.
2814 DEBUG(3,("reply_readbraw: fnum %d not valid "
2815 "- cache prime?\n",
2816 (int)SVAL(req->vwv+0, 0)));
2817 reply_readbraw_error();
2818 END_PROFILE(SMBreadbraw);
2819 return;
2822 /* Do a "by hand" version of CHECK_READ. */
2823 if (!(fsp->can_read ||
2824 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2825 (fsp->access_mask & FILE_EXECUTE)))) {
2826 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2827 (int)SVAL(req->vwv+0, 0)));
2828 reply_readbraw_error();
2829 END_PROFILE(SMBreadbraw);
2830 return;
2833 flush_write_cache(fsp, READRAW_FLUSH);
2835 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2836 if(req->wct == 10) {
2838 * This is a large offset (64 bit) read.
2840 #ifdef LARGE_SMB_OFF_T
2842 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
2844 #else /* !LARGE_SMB_OFF_T */
2847 * Ensure we haven't been sent a >32 bit offset.
2850 if(IVAL(req->vwv+8, 0) != 0) {
2851 DEBUG(0,("reply_readbraw: large offset "
2852 "(%x << 32) used and we don't support "
2853 "64 bit offsets.\n",
2854 (unsigned int)IVAL(req->vwv+8, 0) ));
2855 reply_readbraw_error();
2856 END_PROFILE(SMBreadbraw);
2857 return;
2860 #endif /* LARGE_SMB_OFF_T */
2862 if(startpos < 0) {
2863 DEBUG(0,("reply_readbraw: negative 64 bit "
2864 "readraw offset (%.0f) !\n",
2865 (double)startpos ));
2866 reply_readbraw_error();
2867 END_PROFILE(SMBreadbraw);
2868 return;
2872 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
2873 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
2875 /* ensure we don't overrun the packet size */
2876 maxcount = MIN(65535,maxcount);
2878 if (is_locked(fsp,(uint32)req->smbpid,
2879 (uint64_t)maxcount,
2880 (uint64_t)startpos,
2881 READ_LOCK)) {
2882 reply_readbraw_error();
2883 END_PROFILE(SMBreadbraw);
2884 return;
2887 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
2888 size = st.st_size;
2891 if (startpos >= size) {
2892 nread = 0;
2893 } else {
2894 nread = MIN(maxcount,(size - startpos));
2897 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2898 if (nread < mincount)
2899 nread = 0;
2900 #endif
2902 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2903 "min=%lu nread=%lu\n",
2904 fsp->fnum, (double)startpos,
2905 (unsigned long)maxcount,
2906 (unsigned long)mincount,
2907 (unsigned long)nread ) );
2909 send_file_readbraw(conn, fsp, startpos, nread, mincount);
2911 DEBUG(5,("reply_readbraw finished\n"));
2912 END_PROFILE(SMBreadbraw);
2915 #undef DBGC_CLASS
2916 #define DBGC_CLASS DBGC_LOCKING
2918 /****************************************************************************
2919 Reply to a lockread (core+ protocol).
2920 ****************************************************************************/
2922 void reply_lockread(struct smb_request *req)
2924 connection_struct *conn = req->conn;
2925 ssize_t nread = -1;
2926 char *data;
2927 SMB_OFF_T startpos;
2928 size_t numtoread;
2929 NTSTATUS status;
2930 files_struct *fsp;
2931 struct byte_range_lock *br_lck = NULL;
2932 char *p = NULL;
2934 START_PROFILE(SMBlockread);
2936 if (req->wct < 5) {
2937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2938 END_PROFILE(SMBlockread);
2939 return;
2942 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2944 if (!check_fsp(conn, req, fsp)) {
2945 END_PROFILE(SMBlockread);
2946 return;
2949 if (!CHECK_READ(fsp,req)) {
2950 reply_doserror(req, ERRDOS, ERRbadaccess);
2951 END_PROFILE(SMBlockread);
2952 return;
2955 release_level_2_oplocks_on_change(fsp);
2957 numtoread = SVAL(req->vwv+1, 0);
2958 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
2960 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
2962 reply_outbuf(req, 5, numtoread + 3);
2964 data = smb_buf(req->outbuf) + 3;
2967 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2968 * protocol request that predates the read/write lock concept.
2969 * Thus instead of asking for a read lock here we need to ask
2970 * for a write lock. JRA.
2971 * Note that the requested lock size is unaffected by max_recv.
2974 br_lck = do_lock(smbd_messaging_context(),
2975 fsp,
2976 req->smbpid,
2977 (uint64_t)numtoread,
2978 (uint64_t)startpos,
2979 WRITE_LOCK,
2980 WINDOWS_LOCK,
2981 False, /* Non-blocking lock. */
2982 &status,
2983 NULL);
2984 TALLOC_FREE(br_lck);
2986 if (NT_STATUS_V(status)) {
2987 reply_nterror(req, status);
2988 END_PROFILE(SMBlockread);
2989 return;
2993 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2996 if (numtoread > max_recv) {
2997 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2998 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2999 (unsigned int)numtoread, (unsigned int)max_recv ));
3000 numtoread = MIN(numtoread,max_recv);
3002 nread = read_file(fsp,data,startpos,numtoread);
3004 if (nread < 0) {
3005 reply_unixerror(req, ERRDOS, ERRnoaccess);
3006 END_PROFILE(SMBlockread);
3007 return;
3010 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3012 SSVAL(req->outbuf,smb_vwv0,nread);
3013 SSVAL(req->outbuf,smb_vwv5,nread+3);
3014 p = smb_buf(req->outbuf);
3015 SCVAL(p,0,0); /* pad byte. */
3016 SSVAL(p,1,nread);
3018 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3019 fsp->fnum, (int)numtoread, (int)nread));
3021 END_PROFILE(SMBlockread);
3022 return;
3025 #undef DBGC_CLASS
3026 #define DBGC_CLASS DBGC_ALL
3028 /****************************************************************************
3029 Reply to a read.
3030 ****************************************************************************/
3032 void reply_read(struct smb_request *req)
3034 connection_struct *conn = req->conn;
3035 size_t numtoread;
3036 ssize_t nread = 0;
3037 char *data;
3038 SMB_OFF_T startpos;
3039 int outsize = 0;
3040 files_struct *fsp;
3042 START_PROFILE(SMBread);
3044 if (req->wct < 3) {
3045 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3046 END_PROFILE(SMBread);
3047 return;
3050 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3052 if (!check_fsp(conn, req, fsp)) {
3053 END_PROFILE(SMBread);
3054 return;
3057 if (!CHECK_READ(fsp,req)) {
3058 reply_doserror(req, ERRDOS, ERRbadaccess);
3059 END_PROFILE(SMBread);
3060 return;
3063 numtoread = SVAL(req->vwv+1, 0);
3064 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3066 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3069 * The requested read size cannot be greater than max_recv. JRA.
3071 if (numtoread > max_recv) {
3072 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3073 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3074 (unsigned int)numtoread, (unsigned int)max_recv ));
3075 numtoread = MIN(numtoread,max_recv);
3078 reply_outbuf(req, 5, numtoread+3);
3080 data = smb_buf(req->outbuf) + 3;
3082 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtoread,
3083 (uint64_t)startpos, READ_LOCK)) {
3084 reply_doserror(req, ERRDOS,ERRlock);
3085 END_PROFILE(SMBread);
3086 return;
3089 if (numtoread > 0)
3090 nread = read_file(fsp,data,startpos,numtoread);
3092 if (nread < 0) {
3093 reply_unixerror(req, ERRDOS,ERRnoaccess);
3094 END_PROFILE(SMBread);
3095 return;
3098 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3100 SSVAL(req->outbuf,smb_vwv0,nread);
3101 SSVAL(req->outbuf,smb_vwv5,nread+3);
3102 SCVAL(smb_buf(req->outbuf),0,1);
3103 SSVAL(smb_buf(req->outbuf),1,nread);
3105 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3106 fsp->fnum, (int)numtoread, (int)nread ) );
3108 END_PROFILE(SMBread);
3109 return;
3112 /****************************************************************************
3113 Setup readX header.
3114 ****************************************************************************/
3116 static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3118 int outsize;
3119 char *data;
3121 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3122 data = smb_buf(outbuf);
3124 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3126 SCVAL(outbuf,smb_vwv0,0xFF);
3127 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3128 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3129 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3130 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3131 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3132 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3133 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3134 return outsize;
3137 /****************************************************************************
3138 Reply to a read and X - possibly using sendfile.
3139 ****************************************************************************/
3141 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3142 files_struct *fsp, SMB_OFF_T startpos,
3143 size_t smb_maxcnt)
3145 SMB_STRUCT_STAT sbuf;
3146 ssize_t nread = -1;
3148 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3149 reply_unixerror(req, ERRDOS, ERRnoaccess);
3150 return;
3153 if (startpos > sbuf.st_size) {
3154 smb_maxcnt = 0;
3155 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3156 smb_maxcnt = (sbuf.st_size - startpos);
3159 if (smb_maxcnt == 0) {
3160 goto normal_read;
3163 #if defined(WITH_SENDFILE)
3165 * We can only use sendfile on a non-chained packet
3166 * but we can use on a non-oplocked file. tridge proved this
3167 * on a train in Germany :-). JRA.
3170 if ((chain_size == 0) && (CVAL(req->vwv+0, 0) == 0xFF) &&
3171 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3172 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3173 uint8 headerbuf[smb_size + 12 * 2];
3174 DATA_BLOB header;
3177 * Set up the packet header before send. We
3178 * assume here the sendfile will work (get the
3179 * correct amount of data).
3182 header = data_blob_const(headerbuf, sizeof(headerbuf));
3184 construct_reply_common_req(req, (char *)headerbuf);
3185 setup_readX_header((char *)headerbuf, smb_maxcnt);
3187 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3188 /* Returning ENOSYS or EINVAL means no data at all was sent.
3189 Do this as a normal read. */
3190 if (errno == ENOSYS || errno == EINVAL) {
3191 goto normal_read;
3195 * Special hack for broken Linux with no working sendfile. If we
3196 * return EINTR we sent the header but not the rest of the data.
3197 * Fake this up by doing read/write calls.
3200 if (errno == EINTR) {
3201 /* Ensure we don't do this again. */
3202 set_use_sendfile(SNUM(conn), False);
3203 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3204 nread = fake_sendfile(fsp, startpos,
3205 smb_maxcnt);
3206 if (nread == -1) {
3207 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3208 fsp->fsp_name, strerror(errno) ));
3209 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3211 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3212 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3213 /* No outbuf here means successful sendfile. */
3214 TALLOC_FREE(req->outbuf);
3215 return;
3218 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3219 fsp->fsp_name, strerror(errno) ));
3220 exit_server_cleanly("send_file_readX sendfile failed");
3223 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3224 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3225 /* No outbuf here means successful sendfile. */
3226 TALLOC_FREE(req->outbuf);
3227 return;
3229 #endif
3231 normal_read:
3233 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3234 uint8 headerbuf[smb_size + 2*12];
3236 construct_reply_common_req(req, (char *)headerbuf);
3237 setup_readX_header((char *)headerbuf, smb_maxcnt);
3239 /* Send out the header. */
3240 if (write_data(smbd_server_fd(), (char *)headerbuf,
3241 sizeof(headerbuf)) != sizeof(headerbuf)) {
3242 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3243 fsp->fsp_name, strerror(errno) ));
3244 exit_server_cleanly("send_file_readX sendfile failed");
3246 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3247 if (nread == -1) {
3248 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3249 fsp->fsp_name, strerror(errno) ));
3250 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3252 TALLOC_FREE(req->outbuf);
3253 return;
3256 reply_outbuf(req, 12, smb_maxcnt);
3258 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3259 if (nread < 0) {
3260 reply_unixerror(req, ERRDOS, ERRnoaccess);
3261 return;
3264 setup_readX_header((char *)req->outbuf, nread);
3266 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3267 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3269 chain_reply(req);
3272 /****************************************************************************
3273 Reply to a read and X.
3274 ****************************************************************************/
3276 void reply_read_and_X(struct smb_request *req)
3278 connection_struct *conn = req->conn;
3279 files_struct *fsp;
3280 SMB_OFF_T startpos;
3281 size_t smb_maxcnt;
3282 bool big_readX = False;
3283 #if 0
3284 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3285 #endif
3287 START_PROFILE(SMBreadX);
3289 if ((req->wct != 10) && (req->wct != 12)) {
3290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3291 return;
3294 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3295 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3296 smb_maxcnt = SVAL(req->vwv+5, 0);
3298 /* If it's an IPC, pass off the pipe handler. */
3299 if (IS_IPC(conn)) {
3300 reply_pipe_read_and_X(req);
3301 END_PROFILE(SMBreadX);
3302 return;
3305 if (!check_fsp(conn, req, fsp)) {
3306 END_PROFILE(SMBreadX);
3307 return;
3310 if (!CHECK_READ(fsp,req)) {
3311 reply_doserror(req, ERRDOS,ERRbadaccess);
3312 END_PROFILE(SMBreadX);
3313 return;
3316 if (global_client_caps & CAP_LARGE_READX) {
3317 size_t upper_size = SVAL(req->vwv+7, 0);
3318 smb_maxcnt |= (upper_size<<16);
3319 if (upper_size > 1) {
3320 /* Can't do this on a chained packet. */
3321 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3322 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3323 END_PROFILE(SMBreadX);
3324 return;
3326 /* We currently don't do this on signed or sealed data. */
3327 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3328 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3329 END_PROFILE(SMBreadX);
3330 return;
3332 /* Is there room in the reply for this data ? */
3333 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3334 reply_nterror(req,
3335 NT_STATUS_INVALID_PARAMETER);
3336 END_PROFILE(SMBreadX);
3337 return;
3339 big_readX = True;
3343 if (req->wct == 12) {
3344 #ifdef LARGE_SMB_OFF_T
3346 * This is a large offset (64 bit) read.
3348 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3350 #else /* !LARGE_SMB_OFF_T */
3353 * Ensure we haven't been sent a >32 bit offset.
3356 if(IVAL(req->vwv+10, 0) != 0) {
3357 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3358 "used and we don't support 64 bit offsets.\n",
3359 (unsigned int)IVAL(req->vwv+10, 0) ));
3360 END_PROFILE(SMBreadX);
3361 reply_doserror(req, ERRDOS, ERRbadaccess);
3362 return;
3365 #endif /* LARGE_SMB_OFF_T */
3369 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)smb_maxcnt,
3370 (uint64_t)startpos, READ_LOCK)) {
3371 END_PROFILE(SMBreadX);
3372 reply_doserror(req, ERRDOS, ERRlock);
3373 return;
3376 if (!big_readX &&
3377 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3378 END_PROFILE(SMBreadX);
3379 return;
3382 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3384 END_PROFILE(SMBreadX);
3385 return;
3388 /****************************************************************************
3389 Error replies to writebraw must have smb_wct == 1. Fix this up.
3390 ****************************************************************************/
3392 void error_to_writebrawerr(struct smb_request *req)
3394 uint8 *old_outbuf = req->outbuf;
3396 reply_outbuf(req, 1, 0);
3398 memcpy(req->outbuf, old_outbuf, smb_size);
3399 TALLOC_FREE(old_outbuf);
3402 /****************************************************************************
3403 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3404 ****************************************************************************/
3406 void reply_writebraw(struct smb_request *req)
3408 connection_struct *conn = req->conn;
3409 char *buf = NULL;
3410 ssize_t nwritten=0;
3411 ssize_t total_written=0;
3412 size_t numtowrite=0;
3413 size_t tcount;
3414 SMB_OFF_T startpos;
3415 char *data=NULL;
3416 bool write_through;
3417 files_struct *fsp;
3418 NTSTATUS status;
3420 START_PROFILE(SMBwritebraw);
3423 * If we ever reply with an error, it must have the SMB command
3424 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3425 * we're finished.
3427 SCVAL(req->inbuf,smb_com,SMBwritec);
3429 if (srv_is_signing_active()) {
3430 END_PROFILE(SMBwritebraw);
3431 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3432 "raw reads/writes are disallowed.");
3435 if (req->wct < 12) {
3436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3437 error_to_writebrawerr(req);
3438 END_PROFILE(SMBwritebraw);
3439 return;
3442 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3443 if (!check_fsp(conn, req, fsp)) {
3444 error_to_writebrawerr(req);
3445 END_PROFILE(SMBwritebraw);
3446 return;
3449 if (!CHECK_WRITE(fsp)) {
3450 reply_doserror(req, ERRDOS, ERRbadaccess);
3451 error_to_writebrawerr(req);
3452 END_PROFILE(SMBwritebraw);
3453 return;
3456 tcount = IVAL(req->vwv+1, 0);
3457 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3458 write_through = BITSETW(req->vwv+7,0);
3460 /* We have to deal with slightly different formats depending
3461 on whether we are using the core+ or lanman1.0 protocol */
3463 if(Protocol <= PROTOCOL_COREPLUS) {
3464 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3465 data = smb_buf(req->inbuf);
3466 } else {
3467 numtowrite = SVAL(req->vwv+10, 0);
3468 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3471 /* Ensure we don't write bytes past the end of this packet. */
3472 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3474 error_to_writebrawerr(req);
3475 END_PROFILE(SMBwritebraw);
3476 return;
3479 if (is_locked(fsp,(uint32)req->smbpid,(uint64_t)tcount,
3480 (uint64_t)startpos, WRITE_LOCK)) {
3481 reply_doserror(req, ERRDOS, ERRlock);
3482 error_to_writebrawerr(req);
3483 END_PROFILE(SMBwritebraw);
3484 return;
3487 if (numtowrite>0) {
3488 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3491 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3492 "wrote=%d sync=%d\n",
3493 fsp->fnum, (double)startpos, (int)numtowrite,
3494 (int)nwritten, (int)write_through));
3496 if (nwritten < (ssize_t)numtowrite) {
3497 reply_unixerror(req, ERRHRD, ERRdiskfull);
3498 error_to_writebrawerr(req);
3499 END_PROFILE(SMBwritebraw);
3500 return;
3503 total_written = nwritten;
3505 /* Allocate a buffer of 64k + length. */
3506 buf = TALLOC_ARRAY(NULL, char, 65540);
3507 if (!buf) {
3508 reply_doserror(req, ERRDOS, ERRnomem);
3509 error_to_writebrawerr(req);
3510 END_PROFILE(SMBwritebraw);
3511 return;
3514 /* Return a SMBwritebraw message to the redirector to tell
3515 * it to send more bytes */
3517 memcpy(buf, req->inbuf, smb_size);
3518 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3519 SCVAL(buf,smb_com,SMBwritebraw);
3520 SSVALS(buf,smb_vwv0,0xFFFF);
3521 show_msg(buf);
3522 if (!srv_send_smb(smbd_server_fd(),
3523 buf,
3524 IS_CONN_ENCRYPTED(conn))) {
3525 exit_server_cleanly("reply_writebraw: srv_send_smb "
3526 "failed.");
3529 /* Now read the raw data into the buffer and write it */
3530 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3531 &numtowrite);
3532 if (!NT_STATUS_IS_OK(status)) {
3533 exit_server_cleanly("secondary writebraw failed");
3536 /* Set up outbuf to return the correct size */
3537 reply_outbuf(req, 1, 0);
3539 if (numtowrite != 0) {
3541 if (numtowrite > 0xFFFF) {
3542 DEBUG(0,("reply_writebraw: Oversize secondary write "
3543 "raw requested (%u). Terminating\n",
3544 (unsigned int)numtowrite ));
3545 exit_server_cleanly("secondary writebraw failed");
3548 if (tcount > nwritten+numtowrite) {
3549 DEBUG(3,("reply_writebraw: Client overestimated the "
3550 "write %d %d %d\n",
3551 (int)tcount,(int)nwritten,(int)numtowrite));
3554 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3556 if (!NT_STATUS_IS_OK(status)) {
3557 DEBUG(0,("reply_writebraw: Oversize secondary write "
3558 "raw read failed (%s). Terminating\n",
3559 nt_errstr(status)));
3560 exit_server_cleanly("secondary writebraw failed");
3563 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3564 if (nwritten == -1) {
3565 TALLOC_FREE(buf);
3566 reply_unixerror(req, ERRHRD, ERRdiskfull);
3567 error_to_writebrawerr(req);
3568 END_PROFILE(SMBwritebraw);
3569 return;
3572 if (nwritten < (ssize_t)numtowrite) {
3573 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3574 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3577 if (nwritten > 0) {
3578 total_written += nwritten;
3582 TALLOC_FREE(buf);
3583 SSVAL(req->outbuf,smb_vwv0,total_written);
3585 status = sync_file(conn, fsp, write_through);
3586 if (!NT_STATUS_IS_OK(status)) {
3587 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3588 fsp->fsp_name, nt_errstr(status) ));
3589 reply_nterror(req, status);
3590 error_to_writebrawerr(req);
3591 END_PROFILE(SMBwritebraw);
3592 return;
3595 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3596 "wrote=%d\n",
3597 fsp->fnum, (double)startpos, (int)numtowrite,
3598 (int)total_written));
3600 /* We won't return a status if write through is not selected - this
3601 * follows what WfWg does */
3602 END_PROFILE(SMBwritebraw);
3604 if (!write_through && total_written==tcount) {
3606 #if RABBIT_PELLET_FIX
3608 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3609 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3610 * JRA.
3612 if (!send_keepalive(smbd_server_fd())) {
3613 exit_server_cleanly("reply_writebraw: send of "
3614 "keepalive failed");
3616 #endif
3617 TALLOC_FREE(req->outbuf);
3619 return;
3622 #undef DBGC_CLASS
3623 #define DBGC_CLASS DBGC_LOCKING
3625 /****************************************************************************
3626 Reply to a writeunlock (core+).
3627 ****************************************************************************/
3629 void reply_writeunlock(struct smb_request *req)
3631 connection_struct *conn = req->conn;
3632 ssize_t nwritten = -1;
3633 size_t numtowrite;
3634 SMB_OFF_T startpos;
3635 const char *data;
3636 NTSTATUS status = NT_STATUS_OK;
3637 files_struct *fsp;
3639 START_PROFILE(SMBwriteunlock);
3641 if (req->wct < 5) {
3642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3643 END_PROFILE(SMBwriteunlock);
3644 return;
3647 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3649 if (!check_fsp(conn, req, fsp)) {
3650 END_PROFILE(SMBwriteunlock);
3651 return;
3654 if (!CHECK_WRITE(fsp)) {
3655 reply_doserror(req, ERRDOS,ERRbadaccess);
3656 END_PROFILE(SMBwriteunlock);
3657 return;
3660 numtowrite = SVAL(req->vwv+1, 0);
3661 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3662 data = (const char *)req->buf + 3;
3664 if (numtowrite
3665 && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3666 (uint64_t)startpos, WRITE_LOCK)) {
3667 reply_doserror(req, ERRDOS, ERRlock);
3668 END_PROFILE(SMBwriteunlock);
3669 return;
3672 /* The special X/Open SMB protocol handling of
3673 zero length writes is *NOT* done for
3674 this call */
3675 if(numtowrite == 0) {
3676 nwritten = 0;
3677 } else {
3678 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3681 status = sync_file(conn, fsp, False /* write through */);
3682 if (!NT_STATUS_IS_OK(status)) {
3683 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3684 fsp->fsp_name, nt_errstr(status) ));
3685 reply_nterror(req, status);
3686 END_PROFILE(SMBwriteunlock);
3687 return;
3690 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3691 reply_unixerror(req, ERRHRD, ERRdiskfull);
3692 END_PROFILE(SMBwriteunlock);
3693 return;
3696 if (numtowrite) {
3697 status = do_unlock(smbd_messaging_context(),
3698 fsp,
3699 req->smbpid,
3700 (uint64_t)numtowrite,
3701 (uint64_t)startpos,
3702 WINDOWS_LOCK);
3704 if (NT_STATUS_V(status)) {
3705 reply_nterror(req, status);
3706 END_PROFILE(SMBwriteunlock);
3707 return;
3711 reply_outbuf(req, 1, 0);
3713 SSVAL(req->outbuf,smb_vwv0,nwritten);
3715 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3716 fsp->fnum, (int)numtowrite, (int)nwritten));
3718 END_PROFILE(SMBwriteunlock);
3719 return;
3722 #undef DBGC_CLASS
3723 #define DBGC_CLASS DBGC_ALL
3725 /****************************************************************************
3726 Reply to a write.
3727 ****************************************************************************/
3729 void reply_write(struct smb_request *req)
3731 connection_struct *conn = req->conn;
3732 size_t numtowrite;
3733 ssize_t nwritten = -1;
3734 SMB_OFF_T startpos;
3735 const char *data;
3736 files_struct *fsp;
3737 NTSTATUS status;
3739 START_PROFILE(SMBwrite);
3741 if (req->wct < 5) {
3742 END_PROFILE(SMBwrite);
3743 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3744 return;
3747 /* If it's an IPC, pass off the pipe handler. */
3748 if (IS_IPC(conn)) {
3749 reply_pipe_write(req);
3750 END_PROFILE(SMBwrite);
3751 return;
3754 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3756 if (!check_fsp(conn, req, fsp)) {
3757 END_PROFILE(SMBwrite);
3758 return;
3761 if (!CHECK_WRITE(fsp)) {
3762 reply_doserror(req, ERRDOS, ERRbadaccess);
3763 END_PROFILE(SMBwrite);
3764 return;
3767 numtowrite = SVAL(req->vwv+1, 0);
3768 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3769 data = (const char *)req->buf + 3;
3771 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3772 (uint64_t)startpos, WRITE_LOCK)) {
3773 reply_doserror(req, ERRDOS, ERRlock);
3774 END_PROFILE(SMBwrite);
3775 return;
3779 * X/Open SMB protocol says that if smb_vwv1 is
3780 * zero then the file size should be extended or
3781 * truncated to the size given in smb_vwv[2-3].
3784 if(numtowrite == 0) {
3786 * This is actually an allocate call, and set EOF. JRA.
3788 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3789 if (nwritten < 0) {
3790 reply_nterror(req, NT_STATUS_DISK_FULL);
3791 END_PROFILE(SMBwrite);
3792 return;
3794 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3795 if (nwritten < 0) {
3796 reply_nterror(req, NT_STATUS_DISK_FULL);
3797 END_PROFILE(SMBwrite);
3798 return;
3800 trigger_write_time_update_immediate(fsp);
3801 } else {
3802 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3805 status = sync_file(conn, fsp, False);
3806 if (!NT_STATUS_IS_OK(status)) {
3807 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3808 fsp->fsp_name, nt_errstr(status) ));
3809 reply_nterror(req, status);
3810 END_PROFILE(SMBwrite);
3811 return;
3814 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3815 reply_unixerror(req, ERRHRD, ERRdiskfull);
3816 END_PROFILE(SMBwrite);
3817 return;
3820 reply_outbuf(req, 1, 0);
3822 SSVAL(req->outbuf,smb_vwv0,nwritten);
3824 if (nwritten < (ssize_t)numtowrite) {
3825 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3826 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3829 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3831 END_PROFILE(SMBwrite);
3832 return;
3835 /****************************************************************************
3836 Ensure a buffer is a valid writeX for recvfile purposes.
3837 ****************************************************************************/
3839 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3840 (2*14) + /* word count (including bcc) */ \
3841 1 /* pad byte */)
3843 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3845 size_t numtowrite;
3846 connection_struct *conn = NULL;
3847 unsigned int doff = 0;
3848 size_t len = smb_len_large(inbuf);
3850 if (is_encrypted_packet(inbuf)) {
3851 /* Can't do this on encrypted
3852 * connections. */
3853 return false;
3856 if (CVAL(inbuf,smb_com) != SMBwriteX) {
3857 return false;
3860 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3861 CVAL(inbuf,smb_wct) != 14) {
3862 DEBUG(10,("is_valid_writeX_buffer: chained or "
3863 "invalid word length.\n"));
3864 return false;
3867 conn = conn_find(SVAL(inbuf, smb_tid));
3868 if (conn == NULL) {
3869 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3870 return false;
3872 if (IS_IPC(conn)) {
3873 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3874 return false;
3876 doff = SVAL(inbuf,smb_vwv11);
3878 numtowrite = SVAL(inbuf,smb_vwv10);
3880 if (len > doff && len - doff > 0xFFFF) {
3881 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3884 if (numtowrite == 0) {
3885 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3886 return false;
3889 /* Ensure the sizes match up. */
3890 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3891 /* no pad byte...old smbclient :-( */
3892 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3893 (unsigned int)doff,
3894 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3895 return false;
3898 if (len - doff != numtowrite) {
3899 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3900 "len = %u, doff = %u, numtowrite = %u\n",
3901 (unsigned int)len,
3902 (unsigned int)doff,
3903 (unsigned int)numtowrite ));
3904 return false;
3907 DEBUG(10,("is_valid_writeX_buffer: true "
3908 "len = %u, doff = %u, numtowrite = %u\n",
3909 (unsigned int)len,
3910 (unsigned int)doff,
3911 (unsigned int)numtowrite ));
3913 return true;
3916 /****************************************************************************
3917 Reply to a write and X.
3918 ****************************************************************************/
3920 void reply_write_and_X(struct smb_request *req)
3922 connection_struct *conn = req->conn;
3923 files_struct *fsp;
3924 SMB_OFF_T startpos;
3925 size_t numtowrite;
3926 bool write_through;
3927 ssize_t nwritten;
3928 unsigned int smb_doff;
3929 unsigned int smblen;
3930 char *data;
3931 NTSTATUS status;
3933 START_PROFILE(SMBwriteX);
3935 if ((req->wct != 12) && (req->wct != 14)) {
3936 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3937 END_PROFILE(SMBwriteX);
3938 return;
3941 numtowrite = SVAL(req->vwv+10, 0);
3942 smb_doff = SVAL(req->vwv+11, 0);
3943 smblen = smb_len(req->inbuf);
3945 if (req->unread_bytes > 0xFFFF ||
3946 (smblen > smb_doff &&
3947 smblen - smb_doff > 0xFFFF)) {
3948 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
3951 if (req->unread_bytes) {
3952 /* Can't do a recvfile write on IPC$ */
3953 if (IS_IPC(conn)) {
3954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3955 END_PROFILE(SMBwriteX);
3956 return;
3958 if (numtowrite != req->unread_bytes) {
3959 reply_doserror(req, ERRDOS, ERRbadmem);
3960 END_PROFILE(SMBwriteX);
3961 return;
3963 } else {
3964 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
3965 smb_doff + numtowrite > smblen) {
3966 reply_doserror(req, ERRDOS, ERRbadmem);
3967 END_PROFILE(SMBwriteX);
3968 return;
3972 /* If it's an IPC, pass off the pipe handler. */
3973 if (IS_IPC(conn)) {
3974 if (req->unread_bytes) {
3975 reply_doserror(req, ERRDOS, ERRbadmem);
3976 END_PROFILE(SMBwriteX);
3977 return;
3979 reply_pipe_write_and_X(req);
3980 END_PROFILE(SMBwriteX);
3981 return;
3984 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3985 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3986 write_through = BITSETW(req->vwv+7,0);
3988 if (!check_fsp(conn, req, fsp)) {
3989 END_PROFILE(SMBwriteX);
3990 return;
3993 if (!CHECK_WRITE(fsp)) {
3994 reply_doserror(req, ERRDOS, ERRbadaccess);
3995 END_PROFILE(SMBwriteX);
3996 return;
3999 data = smb_base(req->inbuf) + smb_doff;
4001 if(req->wct == 14) {
4002 #ifdef LARGE_SMB_OFF_T
4004 * This is a large offset (64 bit) write.
4006 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4008 #else /* !LARGE_SMB_OFF_T */
4011 * Ensure we haven't been sent a >32 bit offset.
4014 if(IVAL(req->vwv+12, 0) != 0) {
4015 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4016 "used and we don't support 64 bit offsets.\n",
4017 (unsigned int)IVAL(req->vwv+12, 0) ));
4018 reply_doserror(req, ERRDOS, ERRbadaccess);
4019 END_PROFILE(SMBwriteX);
4020 return;
4023 #endif /* LARGE_SMB_OFF_T */
4026 if (is_locked(fsp,(uint32)req->smbpid,
4027 (uint64_t)numtowrite,
4028 (uint64_t)startpos, WRITE_LOCK)) {
4029 reply_doserror(req, ERRDOS, ERRlock);
4030 END_PROFILE(SMBwriteX);
4031 return;
4034 /* X/Open SMB protocol says that, unlike SMBwrite
4035 if the length is zero then NO truncation is
4036 done, just a write of zero. To truncate a file,
4037 use SMBwrite. */
4039 if(numtowrite == 0) {
4040 nwritten = 0;
4041 } else {
4043 if ((req->unread_bytes == 0) &&
4044 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4045 numtowrite)) {
4046 END_PROFILE(SMBwriteX);
4047 return;
4050 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4053 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4054 reply_unixerror(req, ERRHRD, ERRdiskfull);
4055 END_PROFILE(SMBwriteX);
4056 return;
4059 reply_outbuf(req, 6, 0);
4060 SSVAL(req->outbuf,smb_vwv2,nwritten);
4061 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4063 if (nwritten < (ssize_t)numtowrite) {
4064 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4065 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4068 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4069 fsp->fnum, (int)numtowrite, (int)nwritten));
4071 status = sync_file(conn, fsp, write_through);
4072 if (!NT_STATUS_IS_OK(status)) {
4073 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4074 fsp->fsp_name, nt_errstr(status) ));
4075 reply_nterror(req, status);
4076 END_PROFILE(SMBwriteX);
4077 return;
4080 END_PROFILE(SMBwriteX);
4081 chain_reply(req);
4082 return;
4085 /****************************************************************************
4086 Reply to a lseek.
4087 ****************************************************************************/
4089 void reply_lseek(struct smb_request *req)
4091 connection_struct *conn = req->conn;
4092 SMB_OFF_T startpos;
4093 SMB_OFF_T res= -1;
4094 int mode,umode;
4095 files_struct *fsp;
4097 START_PROFILE(SMBlseek);
4099 if (req->wct < 4) {
4100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4101 END_PROFILE(SMBlseek);
4102 return;
4105 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4107 if (!check_fsp(conn, req, fsp)) {
4108 return;
4111 flush_write_cache(fsp, SEEK_FLUSH);
4113 mode = SVAL(req->vwv+1, 0) & 3;
4114 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4115 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4117 switch (mode) {
4118 case 0:
4119 umode = SEEK_SET;
4120 res = startpos;
4121 break;
4122 case 1:
4123 umode = SEEK_CUR;
4124 res = fsp->fh->pos + startpos;
4125 break;
4126 case 2:
4127 umode = SEEK_END;
4128 break;
4129 default:
4130 umode = SEEK_SET;
4131 res = startpos;
4132 break;
4135 if (umode == SEEK_END) {
4136 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4137 if(errno == EINVAL) {
4138 SMB_OFF_T current_pos = startpos;
4139 SMB_STRUCT_STAT sbuf;
4141 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4142 reply_unixerror(req, ERRDOS,
4143 ERRnoaccess);
4144 END_PROFILE(SMBlseek);
4145 return;
4148 current_pos += sbuf.st_size;
4149 if(current_pos < 0)
4150 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4154 if(res == -1) {
4155 reply_unixerror(req, ERRDOS, ERRnoaccess);
4156 END_PROFILE(SMBlseek);
4157 return;
4161 fsp->fh->pos = res;
4163 reply_outbuf(req, 2, 0);
4164 SIVAL(req->outbuf,smb_vwv0,res);
4166 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4167 fsp->fnum, (double)startpos, (double)res, mode));
4169 END_PROFILE(SMBlseek);
4170 return;
4173 /****************************************************************************
4174 Reply to a flush.
4175 ****************************************************************************/
4177 void reply_flush(struct smb_request *req)
4179 connection_struct *conn = req->conn;
4180 uint16 fnum;
4181 files_struct *fsp;
4183 START_PROFILE(SMBflush);
4185 if (req->wct < 1) {
4186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4187 return;
4190 fnum = SVAL(req->vwv+0, 0);
4191 fsp = file_fsp(req, fnum);
4193 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4194 return;
4197 if (!fsp) {
4198 file_sync_all(conn);
4199 } else {
4200 NTSTATUS status = sync_file(conn, fsp, True);
4201 if (!NT_STATUS_IS_OK(status)) {
4202 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4203 fsp->fsp_name, nt_errstr(status) ));
4204 reply_nterror(req, status);
4205 END_PROFILE(SMBflush);
4206 return;
4210 reply_outbuf(req, 0, 0);
4212 DEBUG(3,("flush\n"));
4213 END_PROFILE(SMBflush);
4214 return;
4217 /****************************************************************************
4218 Reply to a exit.
4219 conn POINTER CAN BE NULL HERE !
4220 ****************************************************************************/
4222 void reply_exit(struct smb_request *req)
4224 START_PROFILE(SMBexit);
4226 file_close_pid(req->smbpid, req->vuid);
4228 reply_outbuf(req, 0, 0);
4230 DEBUG(3,("exit\n"));
4232 END_PROFILE(SMBexit);
4233 return;
4236 /****************************************************************************
4237 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4238 ****************************************************************************/
4240 void reply_close(struct smb_request *req)
4242 connection_struct *conn = req->conn;
4243 NTSTATUS status = NT_STATUS_OK;
4244 files_struct *fsp = NULL;
4245 START_PROFILE(SMBclose);
4247 if (req->wct < 3) {
4248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4249 END_PROFILE(SMBclose);
4250 return;
4253 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4256 * We can only use check_fsp if we know it's not a directory.
4259 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4260 reply_doserror(req, ERRDOS, ERRbadfid);
4261 END_PROFILE(SMBclose);
4262 return;
4265 if(fsp->is_directory) {
4267 * Special case - close NT SMB directory handle.
4269 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4270 status = close_file(req, fsp, NORMAL_CLOSE);
4271 } else {
4272 time_t t;
4274 * Close ordinary file.
4277 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4278 fsp->fh->fd, fsp->fnum,
4279 conn->num_files_open));
4282 * Take care of any time sent in the close.
4285 t = srv_make_unix_date3(req->vwv+1);
4286 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4289 * close_file() returns the unix errno if an error
4290 * was detected on close - normally this is due to
4291 * a disk full error. If not then it was probably an I/O error.
4294 status = close_file(req, fsp, NORMAL_CLOSE);
4297 if (!NT_STATUS_IS_OK(status)) {
4298 reply_nterror(req, status);
4299 END_PROFILE(SMBclose);
4300 return;
4303 reply_outbuf(req, 0, 0);
4304 END_PROFILE(SMBclose);
4305 return;
4308 /****************************************************************************
4309 Reply to a writeclose (Core+ protocol).
4310 ****************************************************************************/
4312 void reply_writeclose(struct smb_request *req)
4314 connection_struct *conn = req->conn;
4315 size_t numtowrite;
4316 ssize_t nwritten = -1;
4317 NTSTATUS close_status = NT_STATUS_OK;
4318 SMB_OFF_T startpos;
4319 const char *data;
4320 struct timespec mtime;
4321 files_struct *fsp;
4323 START_PROFILE(SMBwriteclose);
4325 if (req->wct < 6) {
4326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4327 END_PROFILE(SMBwriteclose);
4328 return;
4331 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4333 if (!check_fsp(conn, req, fsp)) {
4334 END_PROFILE(SMBwriteclose);
4335 return;
4337 if (!CHECK_WRITE(fsp)) {
4338 reply_doserror(req, ERRDOS,ERRbadaccess);
4339 END_PROFILE(SMBwriteclose);
4340 return;
4343 numtowrite = SVAL(req->vwv+1, 0);
4344 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4345 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4346 data = (const char *)req->buf + 1;
4348 if (numtowrite
4349 && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
4350 (uint64_t)startpos, WRITE_LOCK)) {
4351 reply_doserror(req, ERRDOS,ERRlock);
4352 END_PROFILE(SMBwriteclose);
4353 return;
4356 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4358 set_close_write_time(fsp, mtime);
4361 * More insanity. W2K only closes the file if writelen > 0.
4362 * JRA.
4365 if (numtowrite) {
4366 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4367 fsp->fsp_name ));
4368 close_status = close_file(req, fsp, NORMAL_CLOSE);
4371 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4372 fsp->fnum, (int)numtowrite, (int)nwritten,
4373 conn->num_files_open));
4375 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4376 reply_doserror(req, ERRHRD, ERRdiskfull);
4377 END_PROFILE(SMBwriteclose);
4378 return;
4381 if(!NT_STATUS_IS_OK(close_status)) {
4382 reply_nterror(req, close_status);
4383 END_PROFILE(SMBwriteclose);
4384 return;
4387 reply_outbuf(req, 1, 0);
4389 SSVAL(req->outbuf,smb_vwv0,nwritten);
4390 END_PROFILE(SMBwriteclose);
4391 return;
4394 #undef DBGC_CLASS
4395 #define DBGC_CLASS DBGC_LOCKING
4397 /****************************************************************************
4398 Reply to a lock.
4399 ****************************************************************************/
4401 void reply_lock(struct smb_request *req)
4403 connection_struct *conn = req->conn;
4404 uint64_t count,offset;
4405 NTSTATUS status;
4406 files_struct *fsp;
4407 struct byte_range_lock *br_lck = NULL;
4409 START_PROFILE(SMBlock);
4411 if (req->wct < 5) {
4412 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4413 END_PROFILE(SMBlock);
4414 return;
4417 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4419 if (!check_fsp(conn, req, fsp)) {
4420 END_PROFILE(SMBlock);
4421 return;
4424 release_level_2_oplocks_on_change(fsp);
4426 count = (uint64_t)IVAL(req->vwv+1, 0);
4427 offset = (uint64_t)IVAL(req->vwv+3, 0);
4429 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4430 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4432 br_lck = do_lock(smbd_messaging_context(),
4433 fsp,
4434 req->smbpid,
4435 count,
4436 offset,
4437 WRITE_LOCK,
4438 WINDOWS_LOCK,
4439 False, /* Non-blocking lock. */
4440 &status,
4441 NULL);
4443 TALLOC_FREE(br_lck);
4445 if (NT_STATUS_V(status)) {
4446 reply_nterror(req, status);
4447 END_PROFILE(SMBlock);
4448 return;
4451 reply_outbuf(req, 0, 0);
4453 END_PROFILE(SMBlock);
4454 return;
4457 /****************************************************************************
4458 Reply to a unlock.
4459 ****************************************************************************/
4461 void reply_unlock(struct smb_request *req)
4463 connection_struct *conn = req->conn;
4464 uint64_t count,offset;
4465 NTSTATUS status;
4466 files_struct *fsp;
4468 START_PROFILE(SMBunlock);
4470 if (req->wct < 5) {
4471 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4472 END_PROFILE(SMBunlock);
4473 return;
4476 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4478 if (!check_fsp(conn, req, fsp)) {
4479 END_PROFILE(SMBunlock);
4480 return;
4483 count = (uint64_t)IVAL(req->vwv+1, 0);
4484 offset = (uint64_t)IVAL(req->vwv+3, 0);
4486 status = do_unlock(smbd_messaging_context(),
4487 fsp,
4488 req->smbpid,
4489 count,
4490 offset,
4491 WINDOWS_LOCK);
4493 if (NT_STATUS_V(status)) {
4494 reply_nterror(req, status);
4495 END_PROFILE(SMBunlock);
4496 return;
4499 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4500 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4502 reply_outbuf(req, 0, 0);
4504 END_PROFILE(SMBunlock);
4505 return;
4508 #undef DBGC_CLASS
4509 #define DBGC_CLASS DBGC_ALL
4511 /****************************************************************************
4512 Reply to a tdis.
4513 conn POINTER CAN BE NULL HERE !
4514 ****************************************************************************/
4516 void reply_tdis(struct smb_request *req)
4518 connection_struct *conn = req->conn;
4519 START_PROFILE(SMBtdis);
4521 if (!conn) {
4522 DEBUG(4,("Invalid connection in tdis\n"));
4523 reply_doserror(req, ERRSRV, ERRinvnid);
4524 END_PROFILE(SMBtdis);
4525 return;
4528 conn->used = False;
4530 close_cnum(conn,req->vuid);
4531 req->conn = NULL;
4533 reply_outbuf(req, 0, 0);
4534 END_PROFILE(SMBtdis);
4535 return;
4538 /****************************************************************************
4539 Reply to a echo.
4540 conn POINTER CAN BE NULL HERE !
4541 ****************************************************************************/
4543 void reply_echo(struct smb_request *req)
4545 connection_struct *conn = req->conn;
4546 int smb_reverb;
4547 int seq_num;
4549 START_PROFILE(SMBecho);
4551 if (req->wct < 1) {
4552 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4553 END_PROFILE(SMBecho);
4554 return;
4557 smb_reverb = SVAL(req->vwv+0, 0);
4559 reply_outbuf(req, 1, req->buflen);
4561 /* copy any incoming data back out */
4562 if (req->buflen > 0) {
4563 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4566 if (smb_reverb > 100) {
4567 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4568 smb_reverb = 100;
4571 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4572 SSVAL(req->outbuf,smb_vwv0,seq_num);
4574 show_msg((char *)req->outbuf);
4575 if (!srv_send_smb(smbd_server_fd(),
4576 (char *)req->outbuf,
4577 IS_CONN_ENCRYPTED(conn)||req->encrypted))
4578 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4581 DEBUG(3,("echo %d times\n", smb_reverb));
4583 TALLOC_FREE(req->outbuf);
4585 END_PROFILE(SMBecho);
4586 return;
4589 /****************************************************************************
4590 Reply to a printopen.
4591 ****************************************************************************/
4593 void reply_printopen(struct smb_request *req)
4595 connection_struct *conn = req->conn;
4596 files_struct *fsp;
4597 NTSTATUS status;
4599 START_PROFILE(SMBsplopen);
4601 if (req->wct < 2) {
4602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4603 END_PROFILE(SMBsplopen);
4604 return;
4607 if (!CAN_PRINT(conn)) {
4608 reply_doserror(req, ERRDOS, ERRnoaccess);
4609 END_PROFILE(SMBsplopen);
4610 return;
4613 status = file_new(req, conn, &fsp);
4614 if(!NT_STATUS_IS_OK(status)) {
4615 reply_nterror(req, status);
4616 END_PROFILE(SMBsplopen);
4617 return;
4620 /* Open for exclusive use, write only. */
4621 status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
4623 if (!NT_STATUS_IS_OK(status)) {
4624 reply_nterror(req, status);
4625 END_PROFILE(SMBsplopen);
4626 return;
4629 reply_outbuf(req, 1, 0);
4630 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4632 DEBUG(3,("openprint fd=%d fnum=%d\n",
4633 fsp->fh->fd, fsp->fnum));
4635 END_PROFILE(SMBsplopen);
4636 return;
4639 /****************************************************************************
4640 Reply to a printclose.
4641 ****************************************************************************/
4643 void reply_printclose(struct smb_request *req)
4645 connection_struct *conn = req->conn;
4646 files_struct *fsp;
4647 NTSTATUS status;
4649 START_PROFILE(SMBsplclose);
4651 if (req->wct < 1) {
4652 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4653 END_PROFILE(SMBsplclose);
4654 return;
4657 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4659 if (!check_fsp(conn, req, fsp)) {
4660 END_PROFILE(SMBsplclose);
4661 return;
4664 if (!CAN_PRINT(conn)) {
4665 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4666 END_PROFILE(SMBsplclose);
4667 return;
4670 DEBUG(3,("printclose fd=%d fnum=%d\n",
4671 fsp->fh->fd,fsp->fnum));
4673 status = close_file(req, fsp, NORMAL_CLOSE);
4675 if(!NT_STATUS_IS_OK(status)) {
4676 reply_nterror(req, status);
4677 END_PROFILE(SMBsplclose);
4678 return;
4681 reply_outbuf(req, 0, 0);
4683 END_PROFILE(SMBsplclose);
4684 return;
4687 /****************************************************************************
4688 Reply to a printqueue.
4689 ****************************************************************************/
4691 void reply_printqueue(struct smb_request *req)
4693 connection_struct *conn = req->conn;
4694 int max_count;
4695 int start_index;
4697 START_PROFILE(SMBsplretq);
4699 if (req->wct < 2) {
4700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4701 END_PROFILE(SMBsplretq);
4702 return;
4705 max_count = SVAL(req->vwv+0, 0);
4706 start_index = SVAL(req->vwv+1, 0);
4708 /* we used to allow the client to get the cnum wrong, but that
4709 is really quite gross and only worked when there was only
4710 one printer - I think we should now only accept it if they
4711 get it right (tridge) */
4712 if (!CAN_PRINT(conn)) {
4713 reply_doserror(req, ERRDOS, ERRnoaccess);
4714 END_PROFILE(SMBsplretq);
4715 return;
4718 reply_outbuf(req, 2, 3);
4719 SSVAL(req->outbuf,smb_vwv0,0);
4720 SSVAL(req->outbuf,smb_vwv1,0);
4721 SCVAL(smb_buf(req->outbuf),0,1);
4722 SSVAL(smb_buf(req->outbuf),1,0);
4724 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4725 start_index, max_count));
4728 print_queue_struct *queue = NULL;
4729 print_status_struct status;
4730 int count = print_queue_status(SNUM(conn), &queue, &status);
4731 int num_to_get = ABS(max_count);
4732 int first = (max_count>0?start_index:start_index+max_count+1);
4733 int i;
4735 if (first >= count)
4736 num_to_get = 0;
4737 else
4738 num_to_get = MIN(num_to_get,count-first);
4741 for (i=first;i<first+num_to_get;i++) {
4742 char blob[28];
4743 char *p = blob;
4745 srv_put_dos_date2(p,0,queue[i].time);
4746 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4747 SSVAL(p,5, queue[i].job);
4748 SIVAL(p,7,queue[i].size);
4749 SCVAL(p,11,0);
4750 srvstr_push(blob, req->flags2, p+12,
4751 queue[i].fs_user, 16, STR_ASCII);
4753 if (message_push_blob(
4754 &req->outbuf,
4755 data_blob_const(
4756 blob, sizeof(blob))) == -1) {
4757 reply_nterror(req, NT_STATUS_NO_MEMORY);
4758 END_PROFILE(SMBsplretq);
4759 return;
4763 if (count > 0) {
4764 SSVAL(req->outbuf,smb_vwv0,count);
4765 SSVAL(req->outbuf,smb_vwv1,
4766 (max_count>0?first+count:first-1));
4767 SCVAL(smb_buf(req->outbuf),0,1);
4768 SSVAL(smb_buf(req->outbuf),1,28*count);
4771 SAFE_FREE(queue);
4773 DEBUG(3,("%d entries returned in queue\n",count));
4776 END_PROFILE(SMBsplretq);
4777 return;
4780 /****************************************************************************
4781 Reply to a printwrite.
4782 ****************************************************************************/
4784 void reply_printwrite(struct smb_request *req)
4786 connection_struct *conn = req->conn;
4787 int numtowrite;
4788 const char *data;
4789 files_struct *fsp;
4791 START_PROFILE(SMBsplwr);
4793 if (req->wct < 1) {
4794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4795 END_PROFILE(SMBsplwr);
4796 return;
4799 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4801 if (!check_fsp(conn, req, fsp)) {
4802 END_PROFILE(SMBsplwr);
4803 return;
4806 if (!CAN_PRINT(conn)) {
4807 reply_doserror(req, ERRDOS, ERRnoaccess);
4808 END_PROFILE(SMBsplwr);
4809 return;
4812 if (!CHECK_WRITE(fsp)) {
4813 reply_doserror(req, ERRDOS, ERRbadaccess);
4814 END_PROFILE(SMBsplwr);
4815 return;
4818 numtowrite = SVAL(req->buf, 1);
4820 if (req->buflen < numtowrite + 3) {
4821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4822 END_PROFILE(SMBsplwr);
4823 return;
4826 data = (const char *)req->buf + 3;
4828 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4829 reply_unixerror(req, ERRHRD, ERRdiskfull);
4830 END_PROFILE(SMBsplwr);
4831 return;
4834 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4836 END_PROFILE(SMBsplwr);
4837 return;
4840 /****************************************************************************
4841 Reply to a mkdir.
4842 ****************************************************************************/
4844 void reply_mkdir(struct smb_request *req)
4846 connection_struct *conn = req->conn;
4847 char *directory = NULL;
4848 NTSTATUS status;
4849 SMB_STRUCT_STAT sbuf;
4850 TALLOC_CTX *ctx = talloc_tos();
4852 START_PROFILE(SMBmkdir);
4854 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
4855 STR_TERMINATE, &status);
4856 if (!NT_STATUS_IS_OK(status)) {
4857 reply_nterror(req, status);
4858 END_PROFILE(SMBmkdir);
4859 return;
4862 status = resolve_dfspath(ctx, conn,
4863 req->flags2 & FLAGS2_DFS_PATHNAMES,
4864 directory,
4865 &directory);
4866 if (!NT_STATUS_IS_OK(status)) {
4867 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4868 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4869 ERRSRV, ERRbadpath);
4870 END_PROFILE(SMBmkdir);
4871 return;
4873 reply_nterror(req, status);
4874 END_PROFILE(SMBmkdir);
4875 return;
4878 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4879 if (!NT_STATUS_IS_OK(status)) {
4880 reply_nterror(req, status);
4881 END_PROFILE(SMBmkdir);
4882 return;
4885 status = check_name(conn, directory);
4886 if (!NT_STATUS_IS_OK(status)) {
4887 reply_nterror(req, status);
4888 END_PROFILE(SMBmkdir);
4889 return;
4892 status = create_directory(conn, req, directory);
4894 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4896 if (!NT_STATUS_IS_OK(status)) {
4898 if (!use_nt_status()
4899 && NT_STATUS_EQUAL(status,
4900 NT_STATUS_OBJECT_NAME_COLLISION)) {
4902 * Yes, in the DOS error code case we get a
4903 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4904 * samba4 torture test.
4906 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4909 reply_nterror(req, status);
4910 END_PROFILE(SMBmkdir);
4911 return;
4914 reply_outbuf(req, 0, 0);
4916 DEBUG( 3, ( "mkdir %s\n", directory ) );
4918 END_PROFILE(SMBmkdir);
4919 return;
4922 /****************************************************************************
4923 Static function used by reply_rmdir to delete an entire directory
4924 tree recursively. Return True on ok, False on fail.
4925 ****************************************************************************/
4927 static bool recursive_rmdir(TALLOC_CTX *ctx,
4928 connection_struct *conn,
4929 char *directory)
4931 const char *dname = NULL;
4932 bool ret = True;
4933 long offset = 0;
4934 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
4935 NULL, 0);
4937 if(dir_hnd == NULL)
4938 return False;
4940 while((dname = ReadDirName(dir_hnd, &offset))) {
4941 char *fullname = NULL;
4942 SMB_STRUCT_STAT st;
4944 if (ISDOT(dname) || ISDOTDOT(dname)) {
4945 continue;
4948 if (!is_visible_file(conn, directory, dname, &st, False)) {
4949 continue;
4952 /* Construct the full name. */
4953 fullname = talloc_asprintf(ctx,
4954 "%s/%s",
4955 directory,
4956 dname);
4957 if (!fullname) {
4958 errno = ENOMEM;
4959 ret = False;
4960 break;
4963 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4964 ret = False;
4965 break;
4968 if(st.st_mode & S_IFDIR) {
4969 if(!recursive_rmdir(ctx, conn, fullname)) {
4970 ret = False;
4971 break;
4973 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4974 ret = False;
4975 break;
4977 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4978 ret = False;
4979 break;
4981 TALLOC_FREE(fullname);
4983 TALLOC_FREE(dir_hnd);
4984 return ret;
4987 /****************************************************************************
4988 The internals of the rmdir code - called elsewhere.
4989 ****************************************************************************/
4991 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
4992 connection_struct *conn,
4993 const char *directory)
4995 int ret;
4996 SMB_STRUCT_STAT st;
4998 /* Might be a symlink. */
4999 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5000 return map_nt_error_from_unix(errno);
5003 if (S_ISLNK(st.st_mode)) {
5004 /* Is what it points to a directory ? */
5005 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5006 return map_nt_error_from_unix(errno);
5008 if (!(S_ISDIR(st.st_mode))) {
5009 return NT_STATUS_NOT_A_DIRECTORY;
5011 ret = SMB_VFS_UNLINK(conn,directory);
5012 } else {
5013 ret = SMB_VFS_RMDIR(conn,directory);
5015 if (ret == 0) {
5016 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5017 FILE_NOTIFY_CHANGE_DIR_NAME,
5018 directory);
5019 return NT_STATUS_OK;
5022 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5024 * Check to see if the only thing in this directory are
5025 * vetoed files/directories. If so then delete them and
5026 * retry. If we fail to delete any of them (and we *don't*
5027 * do a recursive delete) then fail the rmdir.
5029 const char *dname;
5030 long dirpos = 0;
5031 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5032 directory, NULL, 0);
5034 if(dir_hnd == NULL) {
5035 errno = ENOTEMPTY;
5036 goto err;
5039 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5040 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5041 continue;
5042 if (!is_visible_file(conn, directory, dname, &st, False))
5043 continue;
5044 if(!IS_VETO_PATH(conn, dname)) {
5045 TALLOC_FREE(dir_hnd);
5046 errno = ENOTEMPTY;
5047 goto err;
5051 /* We only have veto files/directories.
5052 * Are we allowed to delete them ? */
5054 if(!lp_recursive_veto_delete(SNUM(conn))) {
5055 TALLOC_FREE(dir_hnd);
5056 errno = ENOTEMPTY;
5057 goto err;
5060 /* Do a recursive delete. */
5061 RewindDir(dir_hnd,&dirpos);
5062 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5063 char *fullname = NULL;
5065 if (ISDOT(dname) || ISDOTDOT(dname)) {
5066 continue;
5068 if (!is_visible_file(conn, directory, dname, &st, False)) {
5069 continue;
5072 fullname = talloc_asprintf(ctx,
5073 "%s/%s",
5074 directory,
5075 dname);
5077 if(!fullname) {
5078 errno = ENOMEM;
5079 break;
5082 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5083 break;
5085 if(st.st_mode & S_IFDIR) {
5086 if(!recursive_rmdir(ctx, conn, fullname)) {
5087 break;
5089 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5090 break;
5092 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5093 break;
5095 TALLOC_FREE(fullname);
5097 TALLOC_FREE(dir_hnd);
5098 /* Retry the rmdir */
5099 ret = SMB_VFS_RMDIR(conn,directory);
5102 err:
5104 if (ret != 0) {
5105 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5106 "%s\n", directory,strerror(errno)));
5107 return map_nt_error_from_unix(errno);
5110 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5111 FILE_NOTIFY_CHANGE_DIR_NAME,
5112 directory);
5114 return NT_STATUS_OK;
5117 /****************************************************************************
5118 Reply to a rmdir.
5119 ****************************************************************************/
5121 void reply_rmdir(struct smb_request *req)
5123 connection_struct *conn = req->conn;
5124 char *directory = NULL;
5125 SMB_STRUCT_STAT sbuf;
5126 NTSTATUS status;
5127 TALLOC_CTX *ctx = talloc_tos();
5129 START_PROFILE(SMBrmdir);
5131 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5132 STR_TERMINATE, &status);
5133 if (!NT_STATUS_IS_OK(status)) {
5134 reply_nterror(req, status);
5135 END_PROFILE(SMBrmdir);
5136 return;
5139 status = resolve_dfspath(ctx, conn,
5140 req->flags2 & FLAGS2_DFS_PATHNAMES,
5141 directory,
5142 &directory);
5143 if (!NT_STATUS_IS_OK(status)) {
5144 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5145 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5146 ERRSRV, ERRbadpath);
5147 END_PROFILE(SMBrmdir);
5148 return;
5150 reply_nterror(req, status);
5151 END_PROFILE(SMBrmdir);
5152 return;
5155 status = unix_convert(ctx, conn, directory, False, &directory,
5156 NULL, &sbuf);
5157 if (!NT_STATUS_IS_OK(status)) {
5158 reply_nterror(req, status);
5159 END_PROFILE(SMBrmdir);
5160 return;
5163 status = check_name(conn, directory);
5164 if (!NT_STATUS_IS_OK(status)) {
5165 reply_nterror(req, status);
5166 END_PROFILE(SMBrmdir);
5167 return;
5170 dptr_closepath(directory, req->smbpid);
5171 status = rmdir_internals(ctx, conn, directory);
5172 if (!NT_STATUS_IS_OK(status)) {
5173 reply_nterror(req, status);
5174 END_PROFILE(SMBrmdir);
5175 return;
5178 reply_outbuf(req, 0, 0);
5180 DEBUG( 3, ( "rmdir %s\n", directory ) );
5182 END_PROFILE(SMBrmdir);
5183 return;
5186 /*******************************************************************
5187 Resolve wildcards in a filename rename.
5188 ********************************************************************/
5190 static bool resolve_wildcards(TALLOC_CTX *ctx,
5191 const char *name1,
5192 const char *name2,
5193 char **pp_newname)
5195 char *name2_copy = NULL;
5196 char *root1 = NULL;
5197 char *root2 = NULL;
5198 char *ext1 = NULL;
5199 char *ext2 = NULL;
5200 char *p,*p2, *pname1, *pname2;
5202 name2_copy = talloc_strdup(ctx, name2);
5203 if (!name2_copy) {
5204 return False;
5207 pname1 = strrchr_m(name1,'/');
5208 pname2 = strrchr_m(name2_copy,'/');
5210 if (!pname1 || !pname2) {
5211 return False;
5214 /* Truncate the copy of name2 at the last '/' */
5215 *pname2 = '\0';
5217 /* Now go past the '/' */
5218 pname1++;
5219 pname2++;
5221 root1 = talloc_strdup(ctx, pname1);
5222 root2 = talloc_strdup(ctx, pname2);
5224 if (!root1 || !root2) {
5225 return False;
5228 p = strrchr_m(root1,'.');
5229 if (p) {
5230 *p = 0;
5231 ext1 = talloc_strdup(ctx, p+1);
5232 } else {
5233 ext1 = talloc_strdup(ctx, "");
5235 p = strrchr_m(root2,'.');
5236 if (p) {
5237 *p = 0;
5238 ext2 = talloc_strdup(ctx, p+1);
5239 } else {
5240 ext2 = talloc_strdup(ctx, "");
5243 if (!ext1 || !ext2) {
5244 return False;
5247 p = root1;
5248 p2 = root2;
5249 while (*p2) {
5250 if (*p2 == '?') {
5251 /* Hmmm. Should this be mb-aware ? */
5252 *p2 = *p;
5253 p2++;
5254 } else if (*p2 == '*') {
5255 *p2 = '\0';
5256 root2 = talloc_asprintf(ctx, "%s%s",
5257 root2,
5259 if (!root2) {
5260 return False;
5262 break;
5263 } else {
5264 p2++;
5266 if (*p) {
5267 p++;
5271 p = ext1;
5272 p2 = ext2;
5273 while (*p2) {
5274 if (*p2 == '?') {
5275 /* Hmmm. Should this be mb-aware ? */
5276 *p2 = *p;
5277 p2++;
5278 } else if (*p2 == '*') {
5279 *p2 = '\0';
5280 ext2 = talloc_asprintf(ctx, "%s%s",
5281 ext2,
5283 if (!ext2) {
5284 return False;
5286 break;
5287 } else {
5288 p2++;
5290 if (*p) {
5291 p++;
5295 if (*ext2) {
5296 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5297 name2_copy,
5298 root2,
5299 ext2);
5300 } else {
5301 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5302 name2_copy,
5303 root2);
5306 if (!*pp_newname) {
5307 return False;
5310 return True;
5313 /****************************************************************************
5314 Ensure open files have their names updated. Updated to notify other smbd's
5315 asynchronously.
5316 ****************************************************************************/
5318 static void rename_open_files(connection_struct *conn,
5319 struct share_mode_lock *lck,
5320 const char *newname)
5322 files_struct *fsp;
5323 bool did_rename = False;
5325 for(fsp = file_find_di_first(lck->id); fsp;
5326 fsp = file_find_di_next(fsp)) {
5327 /* fsp_name is a relative path under the fsp. To change this for other
5328 sharepaths we need to manipulate relative paths. */
5329 /* TODO - create the absolute path and manipulate the newname
5330 relative to the sharepath. */
5331 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5332 continue;
5334 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5335 fsp->fnum, file_id_string_tos(&fsp->file_id),
5336 fsp->fsp_name, newname ));
5337 string_set(&fsp->fsp_name, newname);
5338 did_rename = True;
5341 if (!did_rename) {
5342 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5343 file_id_string_tos(&lck->id), newname ));
5346 /* Send messages to all smbd's (not ourself) that the name has changed. */
5347 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5348 newname);
5351 /****************************************************************************
5352 We need to check if the source path is a parent directory of the destination
5353 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5354 refuse the rename with a sharing violation. Under UNIX the above call can
5355 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5356 probably need to check that the client is a Windows one before disallowing
5357 this as a UNIX client (one with UNIX extensions) can know the source is a
5358 symlink and make this decision intelligently. Found by an excellent bug
5359 report from <AndyLiebman@aol.com>.
5360 ****************************************************************************/
5362 static bool rename_path_prefix_equal(const char *src, const char *dest)
5364 const char *psrc = src;
5365 const char *pdst = dest;
5366 size_t slen;
5368 if (psrc[0] == '.' && psrc[1] == '/') {
5369 psrc += 2;
5371 if (pdst[0] == '.' && pdst[1] == '/') {
5372 pdst += 2;
5374 if ((slen = strlen(psrc)) > strlen(pdst)) {
5375 return False;
5377 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5381 * Do the notify calls from a rename
5384 static void notify_rename(connection_struct *conn, bool is_dir,
5385 const char *oldpath, const char *newpath)
5387 char *olddir, *newdir;
5388 const char *oldname, *newname;
5389 uint32 mask;
5391 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5392 : FILE_NOTIFY_CHANGE_FILE_NAME;
5394 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
5395 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
5396 TALLOC_FREE(olddir);
5397 return;
5400 if (strcmp(olddir, newdir) == 0) {
5401 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5402 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5404 else {
5405 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5406 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5408 TALLOC_FREE(olddir);
5409 TALLOC_FREE(newdir);
5411 /* this is a strange one. w2k3 gives an additional event for
5412 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5413 files, but not directories */
5414 if (!is_dir) {
5415 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5416 FILE_NOTIFY_CHANGE_ATTRIBUTES
5417 |FILE_NOTIFY_CHANGE_CREATION,
5418 newpath);
5422 /****************************************************************************
5423 Rename an open file - given an fsp.
5424 ****************************************************************************/
5426 NTSTATUS rename_internals_fsp(connection_struct *conn,
5427 files_struct *fsp,
5428 char *newname,
5429 const char *newname_last_component,
5430 uint32 attrs,
5431 bool replace_if_exists)
5433 TALLOC_CTX *ctx = talloc_tos();
5434 SMB_STRUCT_STAT sbuf, sbuf1;
5435 NTSTATUS status = NT_STATUS_OK;
5436 struct share_mode_lock *lck = NULL;
5437 bool dst_exists;
5439 ZERO_STRUCT(sbuf);
5441 status = check_name(conn, newname);
5442 if (!NT_STATUS_IS_OK(status)) {
5443 return status;
5446 /* Ensure newname contains a '/' */
5447 if(strrchr_m(newname,'/') == 0) {
5448 newname = talloc_asprintf(ctx,
5449 "./%s",
5450 newname);
5451 if (!newname) {
5452 return NT_STATUS_NO_MEMORY;
5457 * Check for special case with case preserving and not
5458 * case sensitive. If the old last component differs from the original
5459 * last component only by case, then we should allow
5460 * the rename (user is trying to change the case of the
5461 * filename).
5464 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5465 strequal(newname, fsp->fsp_name)) {
5466 char *p;
5467 char *newname_modified_last_component = NULL;
5470 * Get the last component of the modified name.
5471 * Note that we guarantee that newname contains a '/'
5472 * character above.
5474 p = strrchr_m(newname,'/');
5475 newname_modified_last_component = talloc_strdup(ctx,
5476 p+1);
5477 if (!newname_modified_last_component) {
5478 return NT_STATUS_NO_MEMORY;
5481 if(strcsequal(newname_modified_last_component,
5482 newname_last_component) == False) {
5484 * Replace the modified last component with
5485 * the original.
5487 *p = '\0'; /* Truncate at the '/' */
5488 newname = talloc_asprintf(ctx,
5489 "%s/%s",
5490 newname,
5491 newname_last_component);
5496 * If the src and dest names are identical - including case,
5497 * don't do the rename, just return success.
5500 if (strcsequal(fsp->fsp_name, newname)) {
5501 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5502 newname));
5503 return NT_STATUS_OK;
5507 * Have vfs_object_exist also fill sbuf1
5509 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5511 if(!replace_if_exists && dst_exists) {
5512 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5513 fsp->fsp_name,newname));
5514 return NT_STATUS_OBJECT_NAME_COLLISION;
5517 if(replace_if_exists && dst_exists) {
5518 if (is_ntfs_stream_name(newname)) {
5519 return NT_STATUS_INVALID_PARAMETER;
5523 if (dst_exists) {
5524 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5525 files_struct *dst_fsp = file_find_di_first(fileid);
5526 if (dst_fsp) {
5527 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5528 return NT_STATUS_ACCESS_DENIED;
5532 /* Ensure we have a valid stat struct for the source. */
5533 if (fsp->fh->fd != -1) {
5534 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5535 return map_nt_error_from_unix(errno);
5537 } else {
5538 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5539 return map_nt_error_from_unix(errno);
5543 status = can_rename(conn, fsp, attrs, &sbuf);
5545 if (!NT_STATUS_IS_OK(status)) {
5546 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5547 nt_errstr(status), fsp->fsp_name,newname));
5548 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5549 status = NT_STATUS_ACCESS_DENIED;
5550 return status;
5553 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5554 return NT_STATUS_ACCESS_DENIED;
5557 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5558 NULL);
5561 * We have the file open ourselves, so not being able to get the
5562 * corresponding share mode lock is a fatal error.
5565 SMB_ASSERT(lck != NULL);
5567 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5568 uint32 create_options = fsp->fh->private_options;
5570 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5571 fsp->fsp_name,newname));
5573 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5575 rename_open_files(conn, lck, newname);
5578 * A rename acts as a new file create w.r.t. allowing an initial delete
5579 * on close, probably because in Windows there is a new handle to the
5580 * new file. If initial delete on close was requested but not
5581 * originally set, we need to set it here. This is probably not 100% correct,
5582 * but will work for the CIFSFS client which in non-posix mode
5583 * depends on these semantics. JRA.
5586 if (create_options & FILE_DELETE_ON_CLOSE) {
5587 status = can_set_delete_on_close(fsp, True, 0);
5589 if (NT_STATUS_IS_OK(status)) {
5590 /* Note that here we set the *inital* delete on close flag,
5591 * not the regular one. The magic gets handled in close. */
5592 fsp->initial_delete_on_close = True;
5595 TALLOC_FREE(lck);
5596 return NT_STATUS_OK;
5599 TALLOC_FREE(lck);
5601 if (errno == ENOTDIR || errno == EISDIR) {
5602 status = NT_STATUS_OBJECT_NAME_COLLISION;
5603 } else {
5604 status = map_nt_error_from_unix(errno);
5607 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5608 nt_errstr(status), fsp->fsp_name,newname));
5610 return status;
5613 /****************************************************************************
5614 The guts of the rename command, split out so it may be called by the NT SMB
5615 code.
5616 ****************************************************************************/
5618 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5619 connection_struct *conn,
5620 struct smb_request *req,
5621 const char *name_in,
5622 const char *newname_in,
5623 uint32 attrs,
5624 bool replace_if_exists,
5625 bool src_has_wild,
5626 bool dest_has_wild,
5627 uint32_t access_mask)
5629 char *directory = NULL;
5630 char *mask = NULL;
5631 char *last_component_src = NULL;
5632 char *last_component_dest = NULL;
5633 char *name = NULL;
5634 char *newname = NULL;
5635 char *p;
5636 int count=0;
5637 NTSTATUS status = NT_STATUS_OK;
5638 SMB_STRUCT_STAT sbuf1, sbuf2;
5639 struct smb_Dir *dir_hnd = NULL;
5640 const char *dname;
5641 long offset = 0;
5642 int create_options = 0;
5644 ZERO_STRUCT(sbuf1);
5645 ZERO_STRUCT(sbuf2);
5647 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5648 &last_component_src, &sbuf1);
5649 if (!NT_STATUS_IS_OK(status)) {
5650 return status;
5653 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5654 &last_component_dest, &sbuf2);
5655 if (!NT_STATUS_IS_OK(status)) {
5656 return status;
5660 * Split the old name into directory and last component
5661 * strings. Note that unix_convert may have stripped off a
5662 * leading ./ from both name and newname if the rename is
5663 * at the root of the share. We need to make sure either both
5664 * name and newname contain a / character or neither of them do
5665 * as this is checked in resolve_wildcards().
5668 p = strrchr_m(name,'/');
5669 if (!p) {
5670 directory = talloc_strdup(ctx, ".");
5671 if (!directory) {
5672 return NT_STATUS_NO_MEMORY;
5674 mask = name;
5675 } else {
5676 *p = 0;
5677 directory = talloc_strdup(ctx, name);
5678 if (!directory) {
5679 return NT_STATUS_NO_MEMORY;
5681 mask = p+1;
5682 *p = '/'; /* Replace needed for exceptional test below. */
5686 * We should only check the mangled cache
5687 * here if unix_convert failed. This means
5688 * that the path in 'mask' doesn't exist
5689 * on the file system and so we need to look
5690 * for a possible mangle. This patch from
5691 * Tine Smukavec <valentin.smukavec@hermes.si>.
5694 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5695 char *new_mask = NULL;
5696 mangle_lookup_name_from_8_3(ctx,
5697 mask,
5698 &new_mask,
5699 conn->params );
5700 if (new_mask) {
5701 mask = new_mask;
5705 if (!src_has_wild) {
5706 files_struct *fsp;
5709 * No wildcards - just process the one file.
5711 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5713 /* Add a terminating '/' to the directory name. */
5714 directory = talloc_asprintf_append(directory,
5715 "/%s",
5716 mask);
5717 if (!directory) {
5718 return NT_STATUS_NO_MEMORY;
5721 /* Ensure newname contains a '/' also */
5722 if(strrchr_m(newname,'/') == 0) {
5723 newname = talloc_asprintf(ctx,
5724 "./%s",
5725 newname);
5726 if (!newname) {
5727 return NT_STATUS_NO_MEMORY;
5731 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5732 "case_preserve = %d, short case preserve = %d, "
5733 "directory = %s, newname = %s, "
5734 "last_component_dest = %s, is_8_3 = %d\n",
5735 conn->case_sensitive, conn->case_preserve,
5736 conn->short_case_preserve, directory,
5737 newname, last_component_dest, is_short_name));
5739 /* The dest name still may have wildcards. */
5740 if (dest_has_wild) {
5741 char *mod_newname = NULL;
5742 if (!resolve_wildcards(ctx,
5743 directory,newname,&mod_newname)) {
5744 DEBUG(6, ("rename_internals: resolve_wildcards "
5745 "%s %s failed\n",
5746 directory,
5747 newname));
5748 return NT_STATUS_NO_MEMORY;
5750 newname = mod_newname;
5753 ZERO_STRUCT(sbuf1);
5754 SMB_VFS_STAT(conn, directory, &sbuf1);
5756 if (S_ISDIR(sbuf1.st_mode)) {
5757 create_options |= FILE_DIRECTORY_FILE;
5760 status = SMB_VFS_CREATE_FILE(
5761 conn, /* conn */
5762 req, /* req */
5763 0, /* root_dir_fid */
5764 directory, /* fname */
5765 0, /* create_file_flags */
5766 access_mask, /* access_mask */
5767 (FILE_SHARE_READ | /* share_access */
5768 FILE_SHARE_WRITE),
5769 FILE_OPEN, /* create_disposition*/
5770 create_options, /* create_options */
5771 0, /* file_attributes */
5772 0, /* oplock_request */
5773 0, /* allocation_size */
5774 NULL, /* sd */
5775 NULL, /* ea_list */
5776 &fsp, /* result */
5777 NULL, /* pinfo */
5778 &sbuf1); /* psbuf */
5780 if (!NT_STATUS_IS_OK(status)) {
5781 DEBUG(3, ("Could not open rename source %s: %s\n",
5782 directory, nt_errstr(status)));
5783 return status;
5786 status = rename_internals_fsp(conn, fsp, newname,
5787 last_component_dest,
5788 attrs, replace_if_exists);
5790 close_file(req, fsp, NORMAL_CLOSE);
5792 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5793 nt_errstr(status), directory,newname));
5795 return status;
5799 * Wildcards - process each file that matches.
5801 if (strequal(mask,"????????.???")) {
5802 mask[0] = '*';
5803 mask[1] = '\0';
5806 status = check_name(conn, directory);
5807 if (!NT_STATUS_IS_OK(status)) {
5808 return status;
5811 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
5812 if (dir_hnd == NULL) {
5813 return map_nt_error_from_unix(errno);
5816 status = NT_STATUS_NO_SUCH_FILE;
5818 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5819 * - gentest fix. JRA
5822 while ((dname = ReadDirName(dir_hnd, &offset))) {
5823 files_struct *fsp = NULL;
5824 char *fname = NULL;
5825 char *destname = NULL;
5826 bool sysdir_entry = False;
5828 /* Quick check for "." and ".." */
5829 if (ISDOT(dname) || ISDOTDOT(dname)) {
5830 if (attrs & aDIR) {
5831 sysdir_entry = True;
5832 } else {
5833 continue;
5837 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5838 continue;
5841 if(!mask_match(dname, mask, conn->case_sensitive)) {
5842 continue;
5845 if (sysdir_entry) {
5846 status = NT_STATUS_OBJECT_NAME_INVALID;
5847 break;
5850 fname = talloc_asprintf(ctx,
5851 "%s/%s",
5852 directory,
5853 dname);
5854 if (!fname) {
5855 return NT_STATUS_NO_MEMORY;
5858 if (!resolve_wildcards(ctx,
5859 fname,newname,&destname)) {
5860 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5861 fname, destname));
5862 TALLOC_FREE(fname);
5863 continue;
5865 if (!destname) {
5866 return NT_STATUS_NO_MEMORY;
5869 ZERO_STRUCT(sbuf1);
5870 SMB_VFS_STAT(conn, fname, &sbuf1);
5872 create_options = 0;
5874 if (S_ISDIR(sbuf1.st_mode)) {
5875 create_options |= FILE_DIRECTORY_FILE;
5878 status = SMB_VFS_CREATE_FILE(
5879 conn, /* conn */
5880 req, /* req */
5881 0, /* root_dir_fid */
5882 fname, /* fname */
5883 0, /* create_file_flags */
5884 access_mask, /* access_mask */
5885 (FILE_SHARE_READ | /* share_access */
5886 FILE_SHARE_WRITE),
5887 FILE_OPEN, /* create_disposition*/
5888 create_options, /* create_options */
5889 0, /* file_attributes */
5890 0, /* oplock_request */
5891 0, /* allocation_size */
5892 NULL, /* sd */
5893 NULL, /* ea_list */
5894 &fsp, /* result */
5895 NULL, /* pinfo */
5896 &sbuf1); /* psbuf */
5898 if (!NT_STATUS_IS_OK(status)) {
5899 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
5900 "returned %s rename %s -> %s\n",
5901 nt_errstr(status), directory, newname));
5902 break;
5905 status = rename_internals_fsp(conn, fsp, destname, dname,
5906 attrs, replace_if_exists);
5908 close_file(req, fsp, NORMAL_CLOSE);
5910 if (!NT_STATUS_IS_OK(status)) {
5911 DEBUG(3, ("rename_internals_fsp returned %s for "
5912 "rename %s -> %s\n", nt_errstr(status),
5913 directory, newname));
5914 break;
5917 count++;
5919 DEBUG(3,("rename_internals: doing rename on %s -> "
5920 "%s\n",fname,destname));
5922 TALLOC_FREE(fname);
5923 TALLOC_FREE(destname);
5925 TALLOC_FREE(dir_hnd);
5927 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
5928 status = map_nt_error_from_unix(errno);
5931 return status;
5934 /****************************************************************************
5935 Reply to a mv.
5936 ****************************************************************************/
5938 void reply_mv(struct smb_request *req)
5940 connection_struct *conn = req->conn;
5941 char *name = NULL;
5942 char *newname = NULL;
5943 const char *p;
5944 uint32 attrs;
5945 NTSTATUS status;
5946 bool src_has_wcard = False;
5947 bool dest_has_wcard = False;
5948 TALLOC_CTX *ctx = talloc_tos();
5950 START_PROFILE(SMBmv);
5952 if (req->wct < 1) {
5953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5954 END_PROFILE(SMBmv);
5955 return;
5958 attrs = SVAL(req->vwv+0, 0);
5960 p = (const char *)req->buf + 1;
5961 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
5962 &status, &src_has_wcard);
5963 if (!NT_STATUS_IS_OK(status)) {
5964 reply_nterror(req, status);
5965 END_PROFILE(SMBmv);
5966 return;
5968 p++;
5969 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
5970 &status, &dest_has_wcard);
5971 if (!NT_STATUS_IS_OK(status)) {
5972 reply_nterror(req, status);
5973 END_PROFILE(SMBmv);
5974 return;
5977 status = resolve_dfspath_wcard(ctx, conn,
5978 req->flags2 & FLAGS2_DFS_PATHNAMES,
5979 name,
5980 &name,
5981 &src_has_wcard);
5982 if (!NT_STATUS_IS_OK(status)) {
5983 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5984 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5985 ERRSRV, ERRbadpath);
5986 END_PROFILE(SMBmv);
5987 return;
5989 reply_nterror(req, status);
5990 END_PROFILE(SMBmv);
5991 return;
5994 status = resolve_dfspath_wcard(ctx, conn,
5995 req->flags2 & FLAGS2_DFS_PATHNAMES,
5996 newname,
5997 &newname,
5998 &dest_has_wcard);
5999 if (!NT_STATUS_IS_OK(status)) {
6000 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6001 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6002 ERRSRV, ERRbadpath);
6003 END_PROFILE(SMBmv);
6004 return;
6006 reply_nterror(req, status);
6007 END_PROFILE(SMBmv);
6008 return;
6011 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6013 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6014 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6015 if (!NT_STATUS_IS_OK(status)) {
6016 if (open_was_deferred(req->mid)) {
6017 /* We have re-scheduled this call. */
6018 END_PROFILE(SMBmv);
6019 return;
6021 reply_nterror(req, status);
6022 END_PROFILE(SMBmv);
6023 return;
6026 reply_outbuf(req, 0, 0);
6028 END_PROFILE(SMBmv);
6029 return;
6032 /*******************************************************************
6033 Copy a file as part of a reply_copy.
6034 ******************************************************************/
6037 * TODO: check error codes on all callers
6040 NTSTATUS copy_file(TALLOC_CTX *ctx,
6041 connection_struct *conn,
6042 const char *src,
6043 const char *dest1,
6044 int ofun,
6045 int count,
6046 bool target_is_directory)
6048 SMB_STRUCT_STAT src_sbuf, sbuf2;
6049 SMB_OFF_T ret=-1;
6050 files_struct *fsp1,*fsp2;
6051 char *dest = NULL;
6052 uint32 dosattrs;
6053 uint32 new_create_disposition;
6054 NTSTATUS status;
6056 dest = talloc_strdup(ctx, dest1);
6057 if (!dest) {
6058 return NT_STATUS_NO_MEMORY;
6060 if (target_is_directory) {
6061 const char *p = strrchr_m(src,'/');
6062 if (p) {
6063 p++;
6064 } else {
6065 p = src;
6067 dest = talloc_asprintf_append(dest,
6068 "/%s",
6070 if (!dest) {
6071 return NT_STATUS_NO_MEMORY;
6075 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6076 TALLOC_FREE(dest);
6077 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6080 if (!target_is_directory && count) {
6081 new_create_disposition = FILE_OPEN;
6082 } else {
6083 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6084 NULL, NULL, &new_create_disposition, NULL)) {
6085 TALLOC_FREE(dest);
6086 return NT_STATUS_INVALID_PARAMETER;
6090 status = SMB_VFS_CREATE_FILE(
6091 conn, /* conn */
6092 NULL, /* req */
6093 0, /* root_dir_fid */
6094 src, /* fname */
6095 0, /* create_file_flags */
6096 FILE_GENERIC_READ, /* access_mask */
6097 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6098 FILE_OPEN, /* create_disposition*/
6099 0, /* create_options */
6100 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6101 INTERNAL_OPEN_ONLY, /* oplock_request */
6102 0, /* allocation_size */
6103 NULL, /* sd */
6104 NULL, /* ea_list */
6105 &fsp1, /* result */
6106 NULL, /* pinfo */
6107 &src_sbuf); /* psbuf */
6109 if (!NT_STATUS_IS_OK(status)) {
6110 TALLOC_FREE(dest);
6111 return status;
6114 dosattrs = dos_mode(conn, src, &src_sbuf);
6115 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6116 ZERO_STRUCTP(&sbuf2);
6119 status = SMB_VFS_CREATE_FILE(
6120 conn, /* conn */
6121 NULL, /* req */
6122 0, /* root_dir_fid */
6123 dest, /* fname */
6124 0, /* create_file_flags */
6125 FILE_GENERIC_WRITE, /* access_mask */
6126 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6127 new_create_disposition, /* create_disposition*/
6128 0, /* create_options */
6129 dosattrs, /* file_attributes */
6130 INTERNAL_OPEN_ONLY, /* oplock_request */
6131 0, /* allocation_size */
6132 NULL, /* sd */
6133 NULL, /* ea_list */
6134 &fsp2, /* result */
6135 NULL, /* pinfo */
6136 &sbuf2); /* psbuf */
6138 TALLOC_FREE(dest);
6140 if (!NT_STATUS_IS_OK(status)) {
6141 close_file(NULL, fsp1, ERROR_CLOSE);
6142 return status;
6145 if ((ofun&3) == 1) {
6146 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6147 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6149 * Stop the copy from occurring.
6151 ret = -1;
6152 src_sbuf.st_size = 0;
6156 if (src_sbuf.st_size) {
6157 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6160 close_file(NULL, fsp1, NORMAL_CLOSE);
6162 /* Ensure the modtime is set correctly on the destination file. */
6163 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6166 * As we are opening fsp1 read-only we only expect
6167 * an error on close on fsp2 if we are out of space.
6168 * Thus we don't look at the error return from the
6169 * close of fsp1.
6171 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6173 if (!NT_STATUS_IS_OK(status)) {
6174 return status;
6177 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6178 return NT_STATUS_DISK_FULL;
6181 return NT_STATUS_OK;
6184 /****************************************************************************
6185 Reply to a file copy.
6186 ****************************************************************************/
6188 void reply_copy(struct smb_request *req)
6190 connection_struct *conn = req->conn;
6191 char *name = NULL;
6192 char *newname = NULL;
6193 char *directory = NULL;
6194 const char *mask = NULL;
6195 const char mask_star[] = "*";
6196 const char *p;
6197 int count=0;
6198 int error = ERRnoaccess;
6199 int err = 0;
6200 int tid2;
6201 int ofun;
6202 int flags;
6203 bool target_is_directory=False;
6204 bool source_has_wild = False;
6205 bool dest_has_wild = False;
6206 SMB_STRUCT_STAT sbuf1, sbuf2;
6207 NTSTATUS status;
6208 TALLOC_CTX *ctx = talloc_tos();
6210 START_PROFILE(SMBcopy);
6212 if (req->wct < 3) {
6213 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6214 END_PROFILE(SMBcopy);
6215 return;
6218 tid2 = SVAL(req->vwv+0, 0);
6219 ofun = SVAL(req->vwv+1, 0);
6220 flags = SVAL(req->vwv+2, 0);
6222 p = (const char *)req->buf;
6223 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6224 &status, &source_has_wild);
6225 if (!NT_STATUS_IS_OK(status)) {
6226 reply_nterror(req, status);
6227 END_PROFILE(SMBcopy);
6228 return;
6230 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6231 &status, &dest_has_wild);
6232 if (!NT_STATUS_IS_OK(status)) {
6233 reply_nterror(req, status);
6234 END_PROFILE(SMBcopy);
6235 return;
6238 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6240 if (tid2 != conn->cnum) {
6241 /* can't currently handle inter share copies XXXX */
6242 DEBUG(3,("Rejecting inter-share copy\n"));
6243 reply_doserror(req, ERRSRV, ERRinvdevice);
6244 END_PROFILE(SMBcopy);
6245 return;
6248 status = resolve_dfspath_wcard(ctx, conn,
6249 req->flags2 & FLAGS2_DFS_PATHNAMES,
6250 name,
6251 &name,
6252 &source_has_wild);
6253 if (!NT_STATUS_IS_OK(status)) {
6254 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6255 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6256 ERRSRV, ERRbadpath);
6257 END_PROFILE(SMBcopy);
6258 return;
6260 reply_nterror(req, status);
6261 END_PROFILE(SMBcopy);
6262 return;
6265 status = resolve_dfspath_wcard(ctx, conn,
6266 req->flags2 & FLAGS2_DFS_PATHNAMES,
6267 newname,
6268 &newname,
6269 &dest_has_wild);
6270 if (!NT_STATUS_IS_OK(status)) {
6271 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6272 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6273 ERRSRV, ERRbadpath);
6274 END_PROFILE(SMBcopy);
6275 return;
6277 reply_nterror(req, status);
6278 END_PROFILE(SMBcopy);
6279 return;
6282 status = unix_convert(ctx, conn, name, source_has_wild,
6283 &name, NULL, &sbuf1);
6284 if (!NT_STATUS_IS_OK(status)) {
6285 reply_nterror(req, status);
6286 END_PROFILE(SMBcopy);
6287 return;
6290 status = unix_convert(ctx, conn, newname, dest_has_wild,
6291 &newname, NULL, &sbuf2);
6292 if (!NT_STATUS_IS_OK(status)) {
6293 reply_nterror(req, status);
6294 END_PROFILE(SMBcopy);
6295 return;
6298 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6300 if ((flags&1) && target_is_directory) {
6301 reply_doserror(req, ERRDOS, ERRbadfile);
6302 END_PROFILE(SMBcopy);
6303 return;
6306 if ((flags&2) && !target_is_directory) {
6307 reply_doserror(req, ERRDOS, ERRbadpath);
6308 END_PROFILE(SMBcopy);
6309 return;
6312 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6313 /* wants a tree copy! XXXX */
6314 DEBUG(3,("Rejecting tree copy\n"));
6315 reply_doserror(req, ERRSRV, ERRerror);
6316 END_PROFILE(SMBcopy);
6317 return;
6320 p = strrchr_m(name,'/');
6321 if (p != NULL) {
6322 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6323 mask = p+1;
6324 } else {
6325 directory = talloc_strdup(ctx, "./");
6326 mask = name;
6329 if (!directory) {
6330 reply_nterror(req, NT_STATUS_NO_MEMORY);
6331 END_PROFILE(SMBcopy);
6332 return;
6336 * We should only check the mangled cache
6337 * here if unix_convert failed. This means
6338 * that the path in 'mask' doesn't exist
6339 * on the file system and so we need to look
6340 * for a possible mangle. This patch from
6341 * Tine Smukavec <valentin.smukavec@hermes.si>.
6344 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6345 char *new_mask = NULL;
6346 mangle_lookup_name_from_8_3(ctx,
6347 mask,
6348 &new_mask,
6349 conn->params );
6350 if (new_mask) {
6351 mask = new_mask;
6355 if (!source_has_wild) {
6356 directory = talloc_asprintf_append(directory,
6357 "/%s",
6358 mask);
6359 if (dest_has_wild) {
6360 char *mod_newname = NULL;
6361 if (!resolve_wildcards(ctx,
6362 directory,newname,&mod_newname)) {
6363 reply_nterror(req, NT_STATUS_NO_MEMORY);
6364 END_PROFILE(SMBcopy);
6365 return;
6367 newname = mod_newname;
6370 status = check_name(conn, directory);
6371 if (!NT_STATUS_IS_OK(status)) {
6372 reply_nterror(req, status);
6373 END_PROFILE(SMBcopy);
6374 return;
6377 status = check_name(conn, newname);
6378 if (!NT_STATUS_IS_OK(status)) {
6379 reply_nterror(req, status);
6380 END_PROFILE(SMBcopy);
6381 return;
6384 status = copy_file(ctx,conn,directory,newname,ofun,
6385 count,target_is_directory);
6387 if(!NT_STATUS_IS_OK(status)) {
6388 reply_nterror(req, status);
6389 END_PROFILE(SMBcopy);
6390 return;
6391 } else {
6392 count++;
6394 } else {
6395 struct smb_Dir *dir_hnd = NULL;
6396 const char *dname = NULL;
6397 long offset = 0;
6399 if (strequal(mask,"????????.???")) {
6400 mask = mask_star;
6403 status = check_name(conn, directory);
6404 if (!NT_STATUS_IS_OK(status)) {
6405 reply_nterror(req, status);
6406 END_PROFILE(SMBcopy);
6407 return;
6410 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6411 if (dir_hnd == NULL) {
6412 status = map_nt_error_from_unix(errno);
6413 reply_nterror(req, status);
6414 END_PROFILE(SMBcopy);
6415 return;
6418 error = ERRbadfile;
6420 while ((dname = ReadDirName(dir_hnd, &offset))) {
6421 char *destname = NULL;
6422 char *fname = NULL;
6424 if (ISDOT(dname) || ISDOTDOT(dname)) {
6425 continue;
6428 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6429 continue;
6432 if(!mask_match(dname, mask, conn->case_sensitive)) {
6433 continue;
6436 error = ERRnoaccess;
6437 fname = talloc_asprintf(ctx,
6438 "%s/%s",
6439 directory,
6440 dname);
6441 if (!fname) {
6442 TALLOC_FREE(dir_hnd);
6443 reply_nterror(req, NT_STATUS_NO_MEMORY);
6444 END_PROFILE(SMBcopy);
6445 return;
6448 if (!resolve_wildcards(ctx,
6449 fname,newname,&destname)) {
6450 continue;
6452 if (!destname) {
6453 TALLOC_FREE(dir_hnd);
6454 reply_nterror(req, NT_STATUS_NO_MEMORY);
6455 END_PROFILE(SMBcopy);
6456 return;
6459 status = check_name(conn, fname);
6460 if (!NT_STATUS_IS_OK(status)) {
6461 TALLOC_FREE(dir_hnd);
6462 reply_nterror(req, status);
6463 END_PROFILE(SMBcopy);
6464 return;
6467 status = check_name(conn, destname);
6468 if (!NT_STATUS_IS_OK(status)) {
6469 TALLOC_FREE(dir_hnd);
6470 reply_nterror(req, status);
6471 END_PROFILE(SMBcopy);
6472 return;
6475 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6477 status = copy_file(ctx,conn,fname,destname,ofun,
6478 count,target_is_directory);
6479 if (NT_STATUS_IS_OK(status)) {
6480 count++;
6482 TALLOC_FREE(fname);
6483 TALLOC_FREE(destname);
6485 TALLOC_FREE(dir_hnd);
6488 if (count == 0) {
6489 if(err) {
6490 /* Error on close... */
6491 errno = err;
6492 reply_unixerror(req, ERRHRD, ERRgeneral);
6493 END_PROFILE(SMBcopy);
6494 return;
6497 reply_doserror(req, ERRDOS, error);
6498 END_PROFILE(SMBcopy);
6499 return;
6502 reply_outbuf(req, 1, 0);
6503 SSVAL(req->outbuf,smb_vwv0,count);
6505 END_PROFILE(SMBcopy);
6506 return;
6509 #undef DBGC_CLASS
6510 #define DBGC_CLASS DBGC_LOCKING
6512 /****************************************************************************
6513 Get a lock pid, dealing with large count requests.
6514 ****************************************************************************/
6516 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6517 bool large_file_format)
6519 if(!large_file_format)
6520 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6521 else
6522 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6525 /****************************************************************************
6526 Get a lock count, dealing with large count requests.
6527 ****************************************************************************/
6529 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6530 bool large_file_format)
6532 uint64_t count = 0;
6534 if(!large_file_format) {
6535 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6536 } else {
6538 #if defined(HAVE_LONGLONG)
6539 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6540 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6541 #else /* HAVE_LONGLONG */
6544 * NT4.x seems to be broken in that it sends large file (64 bit)
6545 * lockingX calls even if the CAP_LARGE_FILES was *not*
6546 * negotiated. For boxes without large unsigned ints truncate the
6547 * lock count by dropping the top 32 bits.
6550 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6551 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6552 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6553 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6554 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6557 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6558 #endif /* HAVE_LONGLONG */
6561 return count;
6564 #if !defined(HAVE_LONGLONG)
6565 /****************************************************************************
6566 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6567 ****************************************************************************/
6569 static uint32 map_lock_offset(uint32 high, uint32 low)
6571 unsigned int i;
6572 uint32 mask = 0;
6573 uint32 highcopy = high;
6576 * Try and find out how many significant bits there are in high.
6579 for(i = 0; highcopy; i++)
6580 highcopy >>= 1;
6583 * We use 31 bits not 32 here as POSIX
6584 * lock offsets may not be negative.
6587 mask = (~0) << (31 - i);
6589 if(low & mask)
6590 return 0; /* Fail. */
6592 high <<= (31 - i);
6594 return (high|low);
6596 #endif /* !defined(HAVE_LONGLONG) */
6598 /****************************************************************************
6599 Get a lock offset, dealing with large offset requests.
6600 ****************************************************************************/
6602 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6603 bool large_file_format, bool *err)
6605 uint64_t offset = 0;
6607 *err = False;
6609 if(!large_file_format) {
6610 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6611 } else {
6613 #if defined(HAVE_LONGLONG)
6614 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6615 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6616 #else /* HAVE_LONGLONG */
6619 * NT4.x seems to be broken in that it sends large file (64 bit)
6620 * lockingX calls even if the CAP_LARGE_FILES was *not*
6621 * negotiated. For boxes without large unsigned ints mangle the
6622 * lock offset by mapping the top 32 bits onto the lower 32.
6625 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6626 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6627 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6628 uint32 new_low = 0;
6630 if((new_low = map_lock_offset(high, low)) == 0) {
6631 *err = True;
6632 return (uint64_t)-1;
6635 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6636 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6637 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6638 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6641 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6642 #endif /* HAVE_LONGLONG */
6645 return offset;
6648 /****************************************************************************
6649 Reply to a lockingX request.
6650 ****************************************************************************/
6652 void reply_lockingX(struct smb_request *req)
6654 connection_struct *conn = req->conn;
6655 files_struct *fsp;
6656 unsigned char locktype;
6657 unsigned char oplocklevel;
6658 uint16 num_ulocks;
6659 uint16 num_locks;
6660 uint64_t count = 0, offset = 0;
6661 uint32 lock_pid;
6662 int32 lock_timeout;
6663 int i;
6664 const uint8_t *data;
6665 bool large_file_format;
6666 bool err;
6667 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6669 START_PROFILE(SMBlockingX);
6671 if (req->wct < 8) {
6672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6673 END_PROFILE(SMBlockingX);
6674 return;
6677 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6678 locktype = CVAL(req->vwv+3, 0);
6679 oplocklevel = CVAL(req->vwv+3, 1);
6680 num_ulocks = SVAL(req->vwv+6, 0);
6681 num_locks = SVAL(req->vwv+7, 0);
6682 lock_timeout = IVAL(req->vwv+4, 0);
6683 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6685 if (!check_fsp(conn, req, fsp)) {
6686 END_PROFILE(SMBlockingX);
6687 return;
6690 data = req->buf;
6692 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6693 /* we don't support these - and CANCEL_LOCK makes w2k
6694 and XP reboot so I don't really want to be
6695 compatible! (tridge) */
6696 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6697 END_PROFILE(SMBlockingX);
6698 return;
6701 /* Check if this is an oplock break on a file
6702 we have granted an oplock on.
6704 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6705 /* Client can insist on breaking to none. */
6706 bool break_to_none = (oplocklevel == 0);
6707 bool result;
6709 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6710 "for fnum = %d\n", (unsigned int)oplocklevel,
6711 fsp->fnum ));
6714 * Make sure we have granted an exclusive or batch oplock on
6715 * this file.
6718 if (fsp->oplock_type == 0) {
6720 /* The Samba4 nbench simulator doesn't understand
6721 the difference between break to level2 and break
6722 to none from level2 - it sends oplock break
6723 replies in both cases. Don't keep logging an error
6724 message here - just ignore it. JRA. */
6726 DEBUG(5,("reply_lockingX: Error : oplock break from "
6727 "client for fnum = %d (oplock=%d) and no "
6728 "oplock granted on this file (%s).\n",
6729 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6731 /* if this is a pure oplock break request then don't
6732 * send a reply */
6733 if (num_locks == 0 && num_ulocks == 0) {
6734 END_PROFILE(SMBlockingX);
6735 return;
6736 } else {
6737 END_PROFILE(SMBlockingX);
6738 reply_doserror(req, ERRDOS, ERRlock);
6739 return;
6743 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6744 (break_to_none)) {
6745 result = remove_oplock(fsp);
6746 } else {
6747 result = downgrade_oplock(fsp);
6750 if (!result) {
6751 DEBUG(0, ("reply_lockingX: error in removing "
6752 "oplock on file %s\n", fsp->fsp_name));
6753 /* Hmmm. Is this panic justified? */
6754 smb_panic("internal tdb error");
6757 reply_to_oplock_break_requests(fsp);
6759 /* if this is a pure oplock break request then don't send a
6760 * reply */
6761 if (num_locks == 0 && num_ulocks == 0) {
6762 /* Sanity check - ensure a pure oplock break is not a
6763 chained request. */
6764 if(CVAL(req->vwv+0, 0) != 0xff)
6765 DEBUG(0,("reply_lockingX: Error : pure oplock "
6766 "break is a chained %d request !\n",
6767 (unsigned int)CVAL(req->vwv+0, 0)));
6768 END_PROFILE(SMBlockingX);
6769 return;
6774 * We do this check *after* we have checked this is not a oplock break
6775 * response message. JRA.
6778 release_level_2_oplocks_on_change(fsp);
6780 if (req->buflen <
6781 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6783 END_PROFILE(SMBlockingX);
6784 return;
6787 /* Data now points at the beginning of the list
6788 of smb_unlkrng structs */
6789 for(i = 0; i < (int)num_ulocks; i++) {
6790 lock_pid = get_lock_pid( data, i, large_file_format);
6791 count = get_lock_count( data, i, large_file_format);
6792 offset = get_lock_offset( data, i, large_file_format, &err);
6795 * There is no error code marked "stupid client bug".... :-).
6797 if(err) {
6798 END_PROFILE(SMBlockingX);
6799 reply_doserror(req, ERRDOS, ERRnoaccess);
6800 return;
6803 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6804 "pid %u, file %s\n", (double)offset, (double)count,
6805 (unsigned int)lock_pid, fsp->fsp_name ));
6807 status = do_unlock(smbd_messaging_context(),
6808 fsp,
6809 lock_pid,
6810 count,
6811 offset,
6812 WINDOWS_LOCK);
6814 if (NT_STATUS_V(status)) {
6815 END_PROFILE(SMBlockingX);
6816 reply_nterror(req, status);
6817 return;
6821 /* Setup the timeout in seconds. */
6823 if (!lp_blocking_locks(SNUM(conn))) {
6824 lock_timeout = 0;
6827 /* Now do any requested locks */
6828 data += ((large_file_format ? 20 : 10)*num_ulocks);
6830 /* Data now points at the beginning of the list
6831 of smb_lkrng structs */
6833 for(i = 0; i < (int)num_locks; i++) {
6834 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6835 READ_LOCK:WRITE_LOCK);
6836 lock_pid = get_lock_pid( data, i, large_file_format);
6837 count = get_lock_count( data, i, large_file_format);
6838 offset = get_lock_offset( data, i, large_file_format, &err);
6841 * There is no error code marked "stupid client bug".... :-).
6843 if(err) {
6844 END_PROFILE(SMBlockingX);
6845 reply_doserror(req, ERRDOS, ERRnoaccess);
6846 return;
6849 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6850 "%u, file %s timeout = %d\n", (double)offset,
6851 (double)count, (unsigned int)lock_pid,
6852 fsp->fsp_name, (int)lock_timeout ));
6854 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6855 if (lp_blocking_locks(SNUM(conn))) {
6857 /* Schedule a message to ourselves to
6858 remove the blocking lock record and
6859 return the right error. */
6861 if (!blocking_lock_cancel(fsp,
6862 lock_pid,
6863 offset,
6864 count,
6865 WINDOWS_LOCK,
6866 locktype,
6867 NT_STATUS_FILE_LOCK_CONFLICT)) {
6868 END_PROFILE(SMBlockingX);
6869 reply_nterror(
6870 req,
6871 NT_STATUS_DOS(
6872 ERRDOS,
6873 ERRcancelviolation));
6874 return;
6877 /* Remove a matching pending lock. */
6878 status = do_lock_cancel(fsp,
6879 lock_pid,
6880 count,
6881 offset,
6882 WINDOWS_LOCK);
6883 } else {
6884 bool blocking_lock = lock_timeout ? True : False;
6885 bool defer_lock = False;
6886 struct byte_range_lock *br_lck;
6887 uint32 block_smbpid;
6889 br_lck = do_lock(smbd_messaging_context(),
6890 fsp,
6891 lock_pid,
6892 count,
6893 offset,
6894 lock_type,
6895 WINDOWS_LOCK,
6896 blocking_lock,
6897 &status,
6898 &block_smbpid);
6900 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6901 /* Windows internal resolution for blocking locks seems
6902 to be about 200ms... Don't wait for less than that. JRA. */
6903 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6904 lock_timeout = lp_lock_spin_time();
6906 defer_lock = True;
6909 /* This heuristic seems to match W2K3 very well. If a
6910 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6911 it pretends we asked for a timeout of between 150 - 300 milliseconds as
6912 far as I can tell. Replacement for do_lock_spin(). JRA. */
6914 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6915 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6916 defer_lock = True;
6917 lock_timeout = lp_lock_spin_time();
6920 if (br_lck && defer_lock) {
6922 * A blocking lock was requested. Package up
6923 * this smb into a queued request and push it
6924 * onto the blocking lock queue.
6926 if(push_blocking_lock_request(br_lck,
6927 req,
6928 fsp,
6929 lock_timeout,
6931 lock_pid,
6932 lock_type,
6933 WINDOWS_LOCK,
6934 offset,
6935 count,
6936 block_smbpid)) {
6937 TALLOC_FREE(br_lck);
6938 END_PROFILE(SMBlockingX);
6939 return;
6943 TALLOC_FREE(br_lck);
6946 if (NT_STATUS_V(status)) {
6947 END_PROFILE(SMBlockingX);
6948 reply_nterror(req, status);
6949 return;
6953 /* If any of the above locks failed, then we must unlock
6954 all of the previous locks (X/Open spec). */
6956 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6957 (i != num_locks) &&
6958 (num_locks != 0)) {
6960 * Ensure we don't do a remove on the lock that just failed,
6961 * as under POSIX rules, if we have a lock already there, we
6962 * will delete it (and we shouldn't) .....
6964 for(i--; i >= 0; i--) {
6965 lock_pid = get_lock_pid( data, i, large_file_format);
6966 count = get_lock_count( data, i, large_file_format);
6967 offset = get_lock_offset( data, i, large_file_format,
6968 &err);
6971 * There is no error code marked "stupid client
6972 * bug".... :-).
6974 if(err) {
6975 END_PROFILE(SMBlockingX);
6976 reply_doserror(req, ERRDOS, ERRnoaccess);
6977 return;
6980 do_unlock(smbd_messaging_context(),
6981 fsp,
6982 lock_pid,
6983 count,
6984 offset,
6985 WINDOWS_LOCK);
6987 END_PROFILE(SMBlockingX);
6988 reply_nterror(req, status);
6989 return;
6992 reply_outbuf(req, 2, 0);
6994 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
6995 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
6997 END_PROFILE(SMBlockingX);
6998 chain_reply(req);
7001 #undef DBGC_CLASS
7002 #define DBGC_CLASS DBGC_ALL
7004 /****************************************************************************
7005 Reply to a SMBreadbmpx (read block multiplex) request.
7006 Always reply with an error, if someone has a platform really needs this,
7007 please contact vl@samba.org
7008 ****************************************************************************/
7010 void reply_readbmpx(struct smb_request *req)
7012 START_PROFILE(SMBreadBmpx);
7013 reply_doserror(req, ERRSRV, ERRuseSTD);
7014 END_PROFILE(SMBreadBmpx);
7015 return;
7018 /****************************************************************************
7019 Reply to a SMBreadbs (read block multiplex secondary) request.
7020 Always reply with an error, if someone has a platform really needs this,
7021 please contact vl@samba.org
7022 ****************************************************************************/
7024 void reply_readbs(struct smb_request *req)
7026 START_PROFILE(SMBreadBs);
7027 reply_doserror(req, ERRSRV, ERRuseSTD);
7028 END_PROFILE(SMBreadBs);
7029 return;
7032 /****************************************************************************
7033 Reply to a SMBsetattrE.
7034 ****************************************************************************/
7036 void reply_setattrE(struct smb_request *req)
7038 connection_struct *conn = req->conn;
7039 struct timespec ts[2];
7040 files_struct *fsp;
7041 SMB_STRUCT_STAT sbuf;
7042 NTSTATUS status;
7044 START_PROFILE(SMBsetattrE);
7046 if (req->wct < 7) {
7047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7048 END_PROFILE(SMBsetattrE);
7049 return;
7052 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7054 if(!fsp || (fsp->conn != conn)) {
7055 reply_doserror(req, ERRDOS, ERRbadfid);
7056 END_PROFILE(SMBsetattrE);
7057 return;
7062 * Convert the DOS times into unix times. Ignore create
7063 * time as UNIX can't set this.
7066 ts[0] = convert_time_t_to_timespec(
7067 srv_make_unix_date2(req->vwv+3)); /* atime. */
7068 ts[1] = convert_time_t_to_timespec(
7069 srv_make_unix_date2(req->vwv+5)); /* mtime. */
7071 reply_outbuf(req, 0, 0);
7074 * Patch from Ray Frush <frush@engr.colostate.edu>
7075 * Sometimes times are sent as zero - ignore them.
7078 /* Ensure we have a valid stat struct for the source. */
7079 if (fsp->fh->fd != -1) {
7080 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7081 status = map_nt_error_from_unix(errno);
7082 reply_nterror(req, status);
7083 END_PROFILE(SMBsetattrE);
7084 return;
7086 } else {
7087 if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) {
7088 status = map_nt_error_from_unix(errno);
7089 reply_nterror(req, status);
7090 END_PROFILE(SMBsetattrE);
7091 return;
7095 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7096 &sbuf, ts, true);
7097 if (!NT_STATUS_IS_OK(status)) {
7098 reply_doserror(req, ERRDOS, ERRnoaccess);
7099 END_PROFILE(SMBsetattrE);
7100 return;
7103 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7104 fsp->fnum,
7105 (unsigned int)ts[0].tv_sec,
7106 (unsigned int)ts[1].tv_sec));
7108 END_PROFILE(SMBsetattrE);
7109 return;
7113 /* Back from the dead for OS/2..... JRA. */
7115 /****************************************************************************
7116 Reply to a SMBwritebmpx (write block multiplex primary) request.
7117 Always reply with an error, if someone has a platform really needs this,
7118 please contact vl@samba.org
7119 ****************************************************************************/
7121 void reply_writebmpx(struct smb_request *req)
7123 START_PROFILE(SMBwriteBmpx);
7124 reply_doserror(req, ERRSRV, ERRuseSTD);
7125 END_PROFILE(SMBwriteBmpx);
7126 return;
7129 /****************************************************************************
7130 Reply to a SMBwritebs (write block multiplex secondary) request.
7131 Always reply with an error, if someone has a platform really needs this,
7132 please contact vl@samba.org
7133 ****************************************************************************/
7135 void reply_writebs(struct smb_request *req)
7137 START_PROFILE(SMBwriteBs);
7138 reply_doserror(req, ERRSRV, ERRuseSTD);
7139 END_PROFILE(SMBwriteBs);
7140 return;
7143 /****************************************************************************
7144 Reply to a SMBgetattrE.
7145 ****************************************************************************/
7147 void reply_getattrE(struct smb_request *req)
7149 connection_struct *conn = req->conn;
7150 SMB_STRUCT_STAT sbuf;
7151 int mode;
7152 files_struct *fsp;
7153 struct timespec create_ts;
7155 START_PROFILE(SMBgetattrE);
7157 if (req->wct < 1) {
7158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7159 END_PROFILE(SMBgetattrE);
7160 return;
7163 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7165 if(!fsp || (fsp->conn != conn)) {
7166 reply_doserror(req, ERRDOS, ERRbadfid);
7167 END_PROFILE(SMBgetattrE);
7168 return;
7171 /* Do an fstat on this file */
7172 if(fsp_stat(fsp, &sbuf)) {
7173 reply_unixerror(req, ERRDOS, ERRnoaccess);
7174 END_PROFILE(SMBgetattrE);
7175 return;
7178 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7181 * Convert the times into dos times. Set create
7182 * date to be last modify date as UNIX doesn't save
7183 * this.
7186 reply_outbuf(req, 11, 0);
7188 create_ts = get_create_timespec(&sbuf,
7189 lp_fake_dir_create_times(SNUM(conn)));
7190 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7191 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7192 /* Should we check pending modtime here ? JRA */
7193 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7195 if (mode & aDIR) {
7196 SIVAL(req->outbuf, smb_vwv6, 0);
7197 SIVAL(req->outbuf, smb_vwv8, 0);
7198 } else {
7199 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7200 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7201 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7203 SSVAL(req->outbuf,smb_vwv10, mode);
7205 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7207 END_PROFILE(SMBgetattrE);
7208 return;