librpc: rerun make idl
[Samba/gbeck.git] / source3 / smbd / reply.c
blob457f9412a91d0bbe771c56437c0868c38061f825
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
27 #include "includes.h"
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
37 set.
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS check_path_syntax_internal(char *path,
44 bool posix_path,
45 bool *p_last_component_contains_wcard)
47 char *d = path;
48 const char *s = path;
49 NTSTATUS ret = NT_STATUS_OK;
50 bool start_of_name_component = True;
51 bool stream_started = false;
53 *p_last_component_contains_wcard = False;
55 while (*s) {
56 if (stream_started) {
57 switch (*s) {
58 case '/':
59 case '\\':
60 return NT_STATUS_OBJECT_NAME_INVALID;
61 case ':':
62 if (s[1] == '\0') {
63 return NT_STATUS_OBJECT_NAME_INVALID;
65 if (strchr_m(&s[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID;
68 if (StrCaseCmp(s, ":$DATA") != 0) {
69 return NT_STATUS_INVALID_PARAMETER;
71 break;
75 if (!stream_started && *s == ':') {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* stream names allow more characters than file names */
80 stream_started = true;
81 start_of_name_component = false;
82 posix_path = true;
84 if (s[1] == '\0') {
85 return NT_STATUS_OBJECT_NAME_INVALID;
89 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
91 * Safe to assume is not the second part of a mb char
92 * as this is handled below.
94 /* Eat multiple '/' or '\\' */
95 while (IS_PATH_SEP(*s,posix_path)) {
96 s++;
98 if ((d != path) && (*s != '\0')) {
99 /* We only care about non-leading or trailing '/' or '\\' */
100 *d++ = '/';
103 start_of_name_component = True;
104 /* New component. */
105 *p_last_component_contains_wcard = False;
106 continue;
109 if (start_of_name_component) {
110 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
111 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
114 * No mb char starts with '.' so we're safe checking the directory separator here.
117 /* If we just added a '/' - delete it */
118 if ((d > path) && (*(d-1) == '/')) {
119 *(d-1) = '\0';
120 d--;
123 /* Are we at the start ? Can't go back further if so. */
124 if (d <= path) {
125 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
126 break;
128 /* Go back one level... */
129 /* We know this is safe as '/' cannot be part of a mb sequence. */
130 /* NOTE - if this assumption is invalid we are not in good shape... */
131 /* Decrement d first as d points to the *next* char to write into. */
132 for (d--; d > path; d--) {
133 if (*d == '/')
134 break;
136 s += 2; /* Else go past the .. */
137 /* We're still at the start of a name component, just the previous one. */
138 continue;
140 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
141 if (posix_path) {
142 /* Eat the '.' */
143 s++;
144 continue;
150 if (!(*s & 0x80)) {
151 if (!posix_path) {
152 if (*s <= 0x1f || *s == '|') {
153 return NT_STATUS_OBJECT_NAME_INVALID;
155 switch (*s) {
156 case '*':
157 case '?':
158 case '<':
159 case '>':
160 case '"':
161 *p_last_component_contains_wcard = True;
162 break;
163 default:
164 break;
167 *d++ = *s++;
168 } else {
169 size_t siz;
170 /* Get the size of the next MB character. */
171 next_codepoint(s,&siz);
172 switch(siz) {
173 case 5:
174 *d++ = *s++;
175 /*fall through*/
176 case 4:
177 *d++ = *s++;
178 /*fall through*/
179 case 3:
180 *d++ = *s++;
181 /*fall through*/
182 case 2:
183 *d++ = *s++;
184 /*fall through*/
185 case 1:
186 *d++ = *s++;
187 break;
188 default:
189 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
190 *d = '\0';
191 return NT_STATUS_INVALID_PARAMETER;
194 start_of_name_component = False;
197 *d = '\0';
199 return ret;
202 /****************************************************************************
203 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
204 No wildcards allowed.
205 ****************************************************************************/
207 NTSTATUS check_path_syntax(char *path)
209 bool ignore;
210 return check_path_syntax_internal(path, False, &ignore);
213 /****************************************************************************
214 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
215 Wildcards allowed - p_contains_wcard returns true if the last component contained
216 a wildcard.
217 ****************************************************************************/
219 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
221 return check_path_syntax_internal(path, False, p_contains_wcard);
224 /****************************************************************************
225 Check the path for a POSIX client.
226 We're assuming here that '/' is not the second byte in any multibyte char
227 set (a safe assumption).
228 ****************************************************************************/
230 NTSTATUS check_path_syntax_posix(char *path)
232 bool ignore;
233 return check_path_syntax_internal(path, True, &ignore);
236 /****************************************************************************
237 Pull a string and check the path allowing a wilcard - provide for error return.
238 ****************************************************************************/
240 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
241 const char *base_ptr,
242 uint16 smb_flags2,
243 char **pp_dest,
244 const char *src,
245 size_t src_len,
246 int flags,
247 NTSTATUS *err,
248 bool *contains_wcard)
250 size_t ret;
252 *pp_dest = NULL;
254 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
255 src_len, flags);
257 if (!*pp_dest) {
258 *err = NT_STATUS_INVALID_PARAMETER;
259 return ret;
262 *contains_wcard = False;
264 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
266 * For a DFS path the function parse_dfs_path()
267 * will do the path processing, just make a copy.
269 *err = NT_STATUS_OK;
270 return ret;
273 if (lp_posix_pathnames()) {
274 *err = check_path_syntax_posix(*pp_dest);
275 } else {
276 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
279 return ret;
282 /****************************************************************************
283 Pull a string and check the path - provide for error return.
284 ****************************************************************************/
286 size_t srvstr_get_path(TALLOC_CTX *ctx,
287 const char *base_ptr,
288 uint16 smb_flags2,
289 char **pp_dest,
290 const char *src,
291 size_t src_len,
292 int flags,
293 NTSTATUS *err)
295 bool ignore;
296 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
297 src_len, flags, err, &ignore);
300 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
301 char **pp_dest, const char *src, int flags,
302 NTSTATUS *err, bool *contains_wcard)
304 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
305 pp_dest, src, smbreq_bufrem(req, src),
306 flags, err, contains_wcard);
309 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
310 char **pp_dest, const char *src, int flags,
311 NTSTATUS *err)
313 bool ignore;
314 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
315 flags, err, &ignore);
318 /****************************************************************************
319 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
320 ****************************************************************************/
322 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
323 files_struct *fsp)
325 if (!(fsp) || !(conn)) {
326 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
327 return False;
329 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
331 return False;
333 return True;
336 /****************************************************************************
337 Check if we have a correct fsp pointing to a file.
338 ****************************************************************************/
340 bool check_fsp(connection_struct *conn, struct smb_request *req,
341 files_struct *fsp)
343 if (!check_fsp_open(conn, req, fsp)) {
344 return False;
346 if ((fsp)->is_directory) {
347 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
348 return False;
350 if ((fsp)->fh->fd == -1) {
351 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
352 return False;
354 (fsp)->num_smb_operations++;
355 return True;
358 /****************************************************************************
359 Check if we have a correct fsp pointing to a quota fake file. Replacement for
360 the CHECK_NTQUOTA_HANDLE_OK macro.
361 ****************************************************************************/
363 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
364 files_struct *fsp)
366 if (!check_fsp_open(conn, req, fsp)) {
367 return false;
370 if (fsp->is_directory) {
371 return false;
374 if (fsp->fake_file_handle == NULL) {
375 return false;
378 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
379 return false;
382 if (fsp->fake_file_handle->private_data == NULL) {
383 return false;
386 return true;
389 /****************************************************************************
390 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
391 ****************************************************************************/
393 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
394 files_struct *fsp)
396 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
397 && (req->vuid == (fsp)->vuid)) {
398 return True;
401 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
402 return False;
405 /****************************************************************************
406 Reply to a (netbios-level) special message.
407 ****************************************************************************/
409 void reply_special(char *inbuf)
411 int msg_type = CVAL(inbuf,0);
412 int msg_flags = CVAL(inbuf,1);
413 fstring name1,name2;
414 char name_type = 0;
417 * We only really use 4 bytes of the outbuf, but for the smb_setlen
418 * calculation & friends (srv_send_smb uses that) we need the full smb
419 * header.
421 char outbuf[smb_size];
423 *name1 = *name2 = 0;
425 memset(outbuf, '\0', sizeof(outbuf));
427 smb_setlen(outbuf,0);
429 switch (msg_type) {
430 case 0x81: /* session request */
432 if (already_got_session) {
433 exit_server_cleanly("multiple session request not permitted");
436 SCVAL(outbuf,0,0x82);
437 SCVAL(outbuf,3,0);
438 if (name_len(inbuf+4) > 50 ||
439 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
440 DEBUG(0,("Invalid name length in session request\n"));
441 return;
443 name_extract(inbuf,4,name1);
444 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
445 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
446 name1,name2));
448 set_local_machine_name(name1, True);
449 set_remote_machine_name(name2, True);
451 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
452 get_local_machine_name(), get_remote_machine_name(),
453 name_type));
455 if (name_type == 'R') {
456 /* We are being asked for a pathworks session ---
457 no thanks! */
458 SCVAL(outbuf, 0,0x83);
459 break;
462 /* only add the client's machine name to the list
463 of possibly valid usernames if we are operating
464 in share mode security */
465 if (lp_security() == SEC_SHARE) {
466 add_session_user(get_remote_machine_name());
469 reload_services(True);
470 reopen_logs();
472 already_got_session = True;
473 break;
475 case 0x89: /* session keepalive request
476 (some old clients produce this?) */
477 SCVAL(outbuf,0,SMBkeepalive);
478 SCVAL(outbuf,3,0);
479 break;
481 case 0x82: /* positive session response */
482 case 0x83: /* negative session response */
483 case 0x84: /* retarget session response */
484 DEBUG(0,("Unexpected session response\n"));
485 break;
487 case SMBkeepalive: /* session keepalive */
488 default:
489 return;
492 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
493 msg_type, msg_flags));
495 srv_send_smb(smbd_server_fd(), outbuf, false, NULL);
496 return;
499 /****************************************************************************
500 Reply to a tcon.
501 conn POINTER CAN BE NULL HERE !
502 ****************************************************************************/
504 void reply_tcon(struct smb_request *req)
506 connection_struct *conn = req->conn;
507 const char *service;
508 char *service_buf = NULL;
509 char *password = NULL;
510 char *dev = NULL;
511 int pwlen=0;
512 NTSTATUS nt_status;
513 const char *p;
514 DATA_BLOB password_blob;
515 TALLOC_CTX *ctx = talloc_tos();
517 START_PROFILE(SMBtcon);
519 if (req->buflen < 4) {
520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
521 END_PROFILE(SMBtcon);
522 return;
525 p = (const char *)req->buf + 1;
526 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
527 p += 1;
528 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
529 p += pwlen+1;
530 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
531 p += 1;
533 if (service_buf == NULL || password == NULL || dev == NULL) {
534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
535 END_PROFILE(SMBtcon);
536 return;
538 p = strrchr_m(service_buf,'\\');
539 if (p) {
540 service = p+1;
541 } else {
542 service = service_buf;
545 password_blob = data_blob(password, pwlen+1);
547 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
548 req->conn = conn;
550 data_blob_clear_free(&password_blob);
552 if (!conn) {
553 reply_nterror(req, nt_status);
554 END_PROFILE(SMBtcon);
555 return;
558 reply_outbuf(req, 2, 0);
559 SSVAL(req->outbuf,smb_vwv0,max_recv);
560 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
561 SSVAL(req->outbuf,smb_tid,conn->cnum);
563 DEBUG(3,("tcon service=%s cnum=%d\n",
564 service, conn->cnum));
566 END_PROFILE(SMBtcon);
567 return;
570 /****************************************************************************
571 Reply to a tcon and X.
572 conn POINTER CAN BE NULL HERE !
573 ****************************************************************************/
575 void reply_tcon_and_X(struct smb_request *req)
577 connection_struct *conn = req->conn;
578 const char *service = NULL;
579 DATA_BLOB password;
580 TALLOC_CTX *ctx = talloc_tos();
581 /* what the cleint thinks the device is */
582 char *client_devicetype = NULL;
583 /* what the server tells the client the share represents */
584 const char *server_devicetype;
585 NTSTATUS nt_status;
586 int passlen;
587 char *path = NULL;
588 const char *p, *q;
589 uint16 tcon_flags;
591 START_PROFILE(SMBtconX);
593 if (req->wct < 4) {
594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
595 END_PROFILE(SMBtconX);
596 return;
599 passlen = SVAL(req->vwv+3, 0);
600 tcon_flags = SVAL(req->vwv+2, 0);
602 /* we might have to close an old one */
603 if ((tcon_flags & 0x1) && conn) {
604 close_cnum(conn,req->vuid);
605 req->conn = NULL;
606 conn = NULL;
609 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
610 reply_doserror(req, ERRDOS, ERRbuftoosmall);
611 END_PROFILE(SMBtconX);
612 return;
615 if (global_encrypted_passwords_negotiated) {
616 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
617 if (lp_security() == SEC_SHARE) {
619 * Security = share always has a pad byte
620 * after the password.
622 p = (const char *)req->buf + passlen + 1;
623 } else {
624 p = (const char *)req->buf + passlen;
626 } else {
627 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
628 /* Ensure correct termination */
629 password.data[passlen]=0;
630 p = (const char *)req->buf + passlen + 1;
633 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
635 if (path == NULL) {
636 data_blob_clear_free(&password);
637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
638 END_PROFILE(SMBtconX);
639 return;
643 * the service name can be either: \\server\share
644 * or share directly like on the DELL PowerVault 705
646 if (*path=='\\') {
647 q = strchr_m(path+2,'\\');
648 if (!q) {
649 data_blob_clear_free(&password);
650 reply_doserror(req, ERRDOS, ERRnosuchshare);
651 END_PROFILE(SMBtconX);
652 return;
654 service = q+1;
655 } else {
656 service = path;
659 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
660 &client_devicetype, p,
661 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
663 if (client_devicetype == NULL) {
664 data_blob_clear_free(&password);
665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
666 END_PROFILE(SMBtconX);
667 return;
670 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
672 conn = make_connection(service, password, client_devicetype,
673 req->vuid, &nt_status);
674 req->conn =conn;
676 data_blob_clear_free(&password);
678 if (!conn) {
679 reply_nterror(req, nt_status);
680 END_PROFILE(SMBtconX);
681 return;
684 if ( IS_IPC(conn) )
685 server_devicetype = "IPC";
686 else if ( IS_PRINT(conn) )
687 server_devicetype = "LPT1:";
688 else
689 server_devicetype = "A:";
691 if (Protocol < PROTOCOL_NT1) {
692 reply_outbuf(req, 2, 0);
693 if (message_push_string(&req->outbuf, server_devicetype,
694 STR_TERMINATE|STR_ASCII) == -1) {
695 reply_nterror(req, NT_STATUS_NO_MEMORY);
696 END_PROFILE(SMBtconX);
697 return;
699 } else {
700 /* NT sets the fstype of IPC$ to the null string */
701 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
703 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
704 /* Return permissions. */
705 uint32 perm1 = 0;
706 uint32 perm2 = 0;
708 reply_outbuf(req, 7, 0);
710 if (IS_IPC(conn)) {
711 perm1 = FILE_ALL_ACCESS;
712 perm2 = FILE_ALL_ACCESS;
713 } else {
714 perm1 = CAN_WRITE(conn) ?
715 SHARE_ALL_ACCESS :
716 SHARE_READ_ONLY;
719 SIVAL(req->outbuf, smb_vwv3, perm1);
720 SIVAL(req->outbuf, smb_vwv5, perm2);
721 } else {
722 reply_outbuf(req, 3, 0);
725 if ((message_push_string(&req->outbuf, server_devicetype,
726 STR_TERMINATE|STR_ASCII) == -1)
727 || (message_push_string(&req->outbuf, fstype,
728 STR_TERMINATE) == -1)) {
729 reply_nterror(req, NT_STATUS_NO_MEMORY);
730 END_PROFILE(SMBtconX);
731 return;
734 /* what does setting this bit do? It is set by NT4 and
735 may affect the ability to autorun mounted cdroms */
736 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
737 (lp_csc_policy(SNUM(conn)) << 2));
739 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
740 DEBUG(2,("Serving %s as a Dfs root\n",
741 lp_servicename(SNUM(conn)) ));
742 SSVAL(req->outbuf, smb_vwv2,
743 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
748 DEBUG(3,("tconX service=%s \n",
749 service));
751 /* set the incoming and outgoing tid to the just created one */
752 SSVAL(req->inbuf,smb_tid,conn->cnum);
753 SSVAL(req->outbuf,smb_tid,conn->cnum);
755 END_PROFILE(SMBtconX);
757 chain_reply(req);
758 return;
761 /****************************************************************************
762 Reply to an unknown type.
763 ****************************************************************************/
765 void reply_unknown_new(struct smb_request *req, uint8 type)
767 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
768 smb_fn_name(type), type, type));
769 reply_doserror(req, ERRSRV, ERRunknownsmb);
770 return;
773 /****************************************************************************
774 Reply to an ioctl.
775 conn POINTER CAN BE NULL HERE !
776 ****************************************************************************/
778 void reply_ioctl(struct smb_request *req)
780 connection_struct *conn = req->conn;
781 uint16 device;
782 uint16 function;
783 uint32 ioctl_code;
784 int replysize;
785 char *p;
787 START_PROFILE(SMBioctl);
789 if (req->wct < 3) {
790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
791 END_PROFILE(SMBioctl);
792 return;
795 device = SVAL(req->vwv+1, 0);
796 function = SVAL(req->vwv+2, 0);
797 ioctl_code = (device << 16) + function;
799 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
801 switch (ioctl_code) {
802 case IOCTL_QUERY_JOB_INFO:
803 replysize = 32;
804 break;
805 default:
806 reply_doserror(req, ERRSRV, ERRnosupport);
807 END_PROFILE(SMBioctl);
808 return;
811 reply_outbuf(req, 8, replysize+1);
812 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
813 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
814 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
815 p = smb_buf(req->outbuf);
816 memset(p, '\0', replysize+1); /* valgrind-safe. */
817 p += 1; /* Allow for alignment */
819 switch (ioctl_code) {
820 case IOCTL_QUERY_JOB_INFO:
822 files_struct *fsp = file_fsp(
823 req, SVAL(req->vwv+0, 0));
824 if (!fsp) {
825 reply_doserror(req, ERRDOS, ERRbadfid);
826 END_PROFILE(SMBioctl);
827 return;
829 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
830 srvstr_push((char *)req->outbuf, req->flags2, p+2,
831 global_myname(), 15,
832 STR_TERMINATE|STR_ASCII);
833 if (conn) {
834 srvstr_push((char *)req->outbuf, req->flags2,
835 p+18, lp_servicename(SNUM(conn)),
836 13, STR_TERMINATE|STR_ASCII);
837 } else {
838 memset(p+18, 0, 13);
840 break;
844 END_PROFILE(SMBioctl);
845 return;
848 /****************************************************************************
849 Strange checkpath NTSTATUS mapping.
850 ****************************************************************************/
852 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
854 /* Strange DOS error code semantics only for checkpath... */
855 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
856 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
857 /* We need to map to ERRbadpath */
858 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
861 return status;
864 /****************************************************************************
865 Reply to a checkpath.
866 ****************************************************************************/
868 void reply_checkpath(struct smb_request *req)
870 connection_struct *conn = req->conn;
871 char *name = NULL;
872 SMB_STRUCT_STAT sbuf;
873 NTSTATUS status;
874 TALLOC_CTX *ctx = talloc_tos();
876 START_PROFILE(SMBcheckpath);
878 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
879 STR_TERMINATE, &status);
881 if (!NT_STATUS_IS_OK(status)) {
882 status = map_checkpath_error(req->flags2, status);
883 reply_nterror(req, status);
884 END_PROFILE(SMBcheckpath);
885 return;
888 status = resolve_dfspath(ctx, conn,
889 req->flags2 & FLAGS2_DFS_PATHNAMES,
890 name,
891 &name);
892 if (!NT_STATUS_IS_OK(status)) {
893 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
894 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
895 ERRSRV, ERRbadpath);
896 END_PROFILE(SMBcheckpath);
897 return;
899 goto path_err;
902 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
904 status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
905 if (!NT_STATUS_IS_OK(status)) {
906 goto path_err;
909 status = check_name(conn, name);
910 if (!NT_STATUS_IS_OK(status)) {
911 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
912 goto path_err;
915 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
916 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
917 status = map_nt_error_from_unix(errno);
918 goto path_err;
921 if (!S_ISDIR(sbuf.st_mode)) {
922 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
923 ERRDOS, ERRbadpath);
924 END_PROFILE(SMBcheckpath);
925 return;
928 reply_outbuf(req, 0, 0);
930 END_PROFILE(SMBcheckpath);
931 return;
933 path_err:
935 END_PROFILE(SMBcheckpath);
937 /* We special case this - as when a Windows machine
938 is parsing a path is steps through the components
939 one at a time - if a component fails it expects
940 ERRbadpath, not ERRbadfile.
942 status = map_checkpath_error(req->flags2, status);
943 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
945 * Windows returns different error codes if
946 * the parent directory is valid but not the
947 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
948 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
949 * if the path is invalid.
951 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
952 ERRDOS, ERRbadpath);
953 return;
956 reply_nterror(req, status);
959 /****************************************************************************
960 Reply to a getatr.
961 ****************************************************************************/
963 void reply_getatr(struct smb_request *req)
965 connection_struct *conn = req->conn;
966 char *fname = NULL;
967 SMB_STRUCT_STAT sbuf;
968 int mode=0;
969 SMB_OFF_T size=0;
970 time_t mtime=0;
971 const char *p;
972 NTSTATUS status;
973 TALLOC_CTX *ctx = talloc_tos();
975 START_PROFILE(SMBgetatr);
977 p = (const char *)req->buf + 1;
978 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
979 if (!NT_STATUS_IS_OK(status)) {
980 reply_nterror(req, status);
981 END_PROFILE(SMBgetatr);
982 return;
985 status = resolve_dfspath(ctx, conn,
986 req->flags2 & FLAGS2_DFS_PATHNAMES,
987 fname,
988 &fname);
989 if (!NT_STATUS_IS_OK(status)) {
990 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
991 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
992 ERRSRV, ERRbadpath);
993 END_PROFILE(SMBgetatr);
994 return;
996 reply_nterror(req, status);
997 END_PROFILE(SMBgetatr);
998 return;
1001 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1002 under WfWg - weird! */
1003 if (*fname == '\0') {
1004 mode = aHIDDEN | aDIR;
1005 if (!CAN_WRITE(conn)) {
1006 mode |= aRONLY;
1008 size = 0;
1009 mtime = 0;
1010 } else {
1011 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
1012 if (!NT_STATUS_IS_OK(status)) {
1013 reply_nterror(req, status);
1014 END_PROFILE(SMBgetatr);
1015 return;
1017 status = check_name(conn, fname);
1018 if (!NT_STATUS_IS_OK(status)) {
1019 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1020 reply_nterror(req, status);
1021 END_PROFILE(SMBgetatr);
1022 return;
1024 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1025 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1026 reply_unixerror(req, ERRDOS,ERRbadfile);
1027 END_PROFILE(SMBgetatr);
1028 return;
1031 mode = dos_mode(conn,fname,&sbuf);
1032 size = sbuf.st_size;
1033 mtime = sbuf.st_mtime;
1034 if (mode & aDIR) {
1035 size = 0;
1039 reply_outbuf(req, 10, 0);
1041 SSVAL(req->outbuf,smb_vwv0,mode);
1042 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1043 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1044 } else {
1045 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1047 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1049 if (Protocol >= PROTOCOL_NT1) {
1050 SSVAL(req->outbuf, smb_flg2,
1051 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1054 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1056 END_PROFILE(SMBgetatr);
1057 return;
1060 /****************************************************************************
1061 Reply to a setatr.
1062 ****************************************************************************/
1064 void reply_setatr(struct smb_request *req)
1066 struct smb_file_time ft;
1067 connection_struct *conn = req->conn;
1068 char *fname = NULL;
1069 int mode;
1070 time_t mtime;
1071 SMB_STRUCT_STAT sbuf;
1072 const char *p;
1073 NTSTATUS status;
1074 TALLOC_CTX *ctx = talloc_tos();
1076 START_PROFILE(SMBsetatr);
1078 ZERO_STRUCT(ft);
1080 if (req->wct < 2) {
1081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1082 return;
1085 p = (const char *)req->buf + 1;
1086 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1087 if (!NT_STATUS_IS_OK(status)) {
1088 reply_nterror(req, status);
1089 END_PROFILE(SMBsetatr);
1090 return;
1093 status = resolve_dfspath(ctx, conn,
1094 req->flags2 & FLAGS2_DFS_PATHNAMES,
1095 fname,
1096 &fname);
1097 if (!NT_STATUS_IS_OK(status)) {
1098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1099 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1100 ERRSRV, ERRbadpath);
1101 END_PROFILE(SMBsetatr);
1102 return;
1104 reply_nterror(req, status);
1105 END_PROFILE(SMBsetatr);
1106 return;
1109 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1110 if (!NT_STATUS_IS_OK(status)) {
1111 reply_nterror(req, status);
1112 END_PROFILE(SMBsetatr);
1113 return;
1116 status = check_name(conn, fname);
1117 if (!NT_STATUS_IS_OK(status)) {
1118 reply_nterror(req, status);
1119 END_PROFILE(SMBsetatr);
1120 return;
1123 if (fname[0] == '.' && fname[1] == '\0') {
1125 * Not sure here is the right place to catch this
1126 * condition. Might be moved to somewhere else later -- vl
1128 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1129 END_PROFILE(SMBsetatr);
1130 return;
1133 mode = SVAL(req->vwv+0, 0);
1134 mtime = srv_make_unix_date3(req->vwv+1);
1136 ft.mtime = convert_time_t_to_timespec(mtime);
1137 status = smb_set_file_time(conn, NULL, fname,
1138 &sbuf, &ft, true);
1139 if (!NT_STATUS_IS_OK(status)) {
1140 reply_unixerror(req, ERRDOS, ERRnoaccess);
1141 END_PROFILE(SMBsetatr);
1142 return;
1145 if (mode != FILE_ATTRIBUTE_NORMAL) {
1146 if (VALID_STAT_OF_DIR(sbuf))
1147 mode |= aDIR;
1148 else
1149 mode &= ~aDIR;
1151 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1152 reply_unixerror(req, ERRDOS, ERRnoaccess);
1153 END_PROFILE(SMBsetatr);
1154 return;
1158 reply_outbuf(req, 0, 0);
1160 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1162 END_PROFILE(SMBsetatr);
1163 return;
1166 /****************************************************************************
1167 Reply to a dskattr.
1168 ****************************************************************************/
1170 void reply_dskattr(struct smb_request *req)
1172 connection_struct *conn = req->conn;
1173 uint64_t dfree,dsize,bsize;
1174 START_PROFILE(SMBdskattr);
1176 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1177 reply_unixerror(req, ERRHRD, ERRgeneral);
1178 END_PROFILE(SMBdskattr);
1179 return;
1182 reply_outbuf(req, 5, 0);
1184 if (Protocol <= PROTOCOL_LANMAN2) {
1185 double total_space, free_space;
1186 /* we need to scale this to a number that DOS6 can handle. We
1187 use floating point so we can handle large drives on systems
1188 that don't have 64 bit integers
1190 we end up displaying a maximum of 2G to DOS systems
1192 total_space = dsize * (double)bsize;
1193 free_space = dfree * (double)bsize;
1195 dsize = (uint64_t)((total_space+63*512) / (64*512));
1196 dfree = (uint64_t)((free_space+63*512) / (64*512));
1198 if (dsize > 0xFFFF) dsize = 0xFFFF;
1199 if (dfree > 0xFFFF) dfree = 0xFFFF;
1201 SSVAL(req->outbuf,smb_vwv0,dsize);
1202 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1203 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1204 SSVAL(req->outbuf,smb_vwv3,dfree);
1205 } else {
1206 SSVAL(req->outbuf,smb_vwv0,dsize);
1207 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1208 SSVAL(req->outbuf,smb_vwv2,512);
1209 SSVAL(req->outbuf,smb_vwv3,dfree);
1212 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1214 END_PROFILE(SMBdskattr);
1215 return;
1218 /****************************************************************************
1219 Reply to a search.
1220 Can be called from SMBsearch, SMBffirst or SMBfunique.
1221 ****************************************************************************/
1223 void reply_search(struct smb_request *req)
1225 connection_struct *conn = req->conn;
1226 const char *mask = NULL;
1227 char *directory = NULL;
1228 char *fname = NULL;
1229 SMB_OFF_T size;
1230 uint32 mode;
1231 time_t date;
1232 uint32 dirtype;
1233 unsigned int numentries = 0;
1234 unsigned int maxentries = 0;
1235 bool finished = False;
1236 const char *p;
1237 int status_len;
1238 char *path = NULL;
1239 char status[21];
1240 int dptr_num= -1;
1241 bool check_descend = False;
1242 bool expect_close = False;
1243 NTSTATUS nt_status;
1244 bool mask_contains_wcard = False;
1245 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1246 TALLOC_CTX *ctx = talloc_tos();
1247 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1249 START_PROFILE(SMBsearch);
1251 if (req->wct < 2) {
1252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1253 END_PROFILE(SMBsearch);
1254 return;
1257 if (lp_posix_pathnames()) {
1258 reply_unknown_new(req, req->cmd);
1259 END_PROFILE(SMBsearch);
1260 return;
1263 /* If we were called as SMBffirst then we must expect close. */
1264 if(req->cmd == SMBffirst) {
1265 expect_close = True;
1268 reply_outbuf(req, 1, 3);
1269 maxentries = SVAL(req->vwv+0, 0);
1270 dirtype = SVAL(req->vwv+1, 0);
1271 p = (const char *)req->buf + 1;
1272 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1273 &nt_status, &mask_contains_wcard);
1274 if (!NT_STATUS_IS_OK(nt_status)) {
1275 reply_nterror(req, nt_status);
1276 END_PROFILE(SMBsearch);
1277 return;
1280 nt_status = resolve_dfspath_wcard(ctx, conn,
1281 req->flags2 & FLAGS2_DFS_PATHNAMES,
1282 path,
1283 &path,
1284 &mask_contains_wcard);
1285 if (!NT_STATUS_IS_OK(nt_status)) {
1286 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1287 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1288 ERRSRV, ERRbadpath);
1289 END_PROFILE(SMBsearch);
1290 return;
1292 reply_nterror(req, nt_status);
1293 END_PROFILE(SMBsearch);
1294 return;
1297 p++;
1298 status_len = SVAL(p, 0);
1299 p += 2;
1301 /* dirtype &= ~aDIR; */
1303 if (status_len == 0) {
1304 SMB_STRUCT_STAT sbuf;
1306 nt_status = unix_convert(ctx, conn, path, True,
1307 &directory, NULL, &sbuf);
1308 if (!NT_STATUS_IS_OK(nt_status)) {
1309 reply_nterror(req, nt_status);
1310 END_PROFILE(SMBsearch);
1311 return;
1314 nt_status = check_name(conn, directory);
1315 if (!NT_STATUS_IS_OK(nt_status)) {
1316 reply_nterror(req, nt_status);
1317 END_PROFILE(SMBsearch);
1318 return;
1321 p = strrchr_m(directory,'/');
1322 if ((p != NULL) && (*directory != '/')) {
1323 mask = p + 1;
1324 directory = talloc_strndup(ctx, directory,
1325 PTR_DIFF(p, directory));
1326 } else {
1327 mask = directory;
1328 directory = talloc_strdup(ctx,".");
1331 if (!directory) {
1332 reply_nterror(req, NT_STATUS_NO_MEMORY);
1333 END_PROFILE(SMBsearch);
1334 return;
1337 memset((char *)status,'\0',21);
1338 SCVAL(status,0,(dirtype & 0x1F));
1340 nt_status = dptr_create(conn,
1341 directory,
1342 True,
1343 expect_close,
1344 req->smbpid,
1345 mask,
1346 mask_contains_wcard,
1347 dirtype,
1348 &conn->dirptr);
1349 if (!NT_STATUS_IS_OK(nt_status)) {
1350 reply_nterror(req, nt_status);
1351 END_PROFILE(SMBsearch);
1352 return;
1354 dptr_num = dptr_dnum(conn->dirptr);
1355 } else {
1356 int status_dirtype;
1358 memcpy(status,p,21);
1359 status_dirtype = CVAL(status,0) & 0x1F;
1360 if (status_dirtype != (dirtype & 0x1F)) {
1361 dirtype = status_dirtype;
1364 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1365 if (!conn->dirptr) {
1366 goto SearchEmpty;
1368 string_set(&conn->dirpath,dptr_path(dptr_num));
1369 mask = dptr_wcard(dptr_num);
1370 if (!mask) {
1371 goto SearchEmpty;
1374 * For a 'continue' search we have no string. So
1375 * check from the initial saved string.
1377 mask_contains_wcard = ms_has_wild(mask);
1378 dirtype = dptr_attr(dptr_num);
1381 DEBUG(4,("dptr_num is %d\n",dptr_num));
1383 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1384 dptr_init_search_op(conn->dirptr);
1386 if ((dirtype&0x1F) == aVOLID) {
1387 char buf[DIR_STRUCT_SIZE];
1388 memcpy(buf,status,21);
1389 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1390 0,aVOLID,0,!allow_long_path_components)) {
1391 reply_nterror(req, NT_STATUS_NO_MEMORY);
1392 END_PROFILE(SMBsearch);
1393 return;
1395 dptr_fill(buf+12,dptr_num);
1396 if (dptr_zero(buf+12) && (status_len==0)) {
1397 numentries = 1;
1398 } else {
1399 numentries = 0;
1401 if (message_push_blob(&req->outbuf,
1402 data_blob_const(buf, sizeof(buf)))
1403 == -1) {
1404 reply_nterror(req, NT_STATUS_NO_MEMORY);
1405 END_PROFILE(SMBsearch);
1406 return;
1408 } else {
1409 unsigned int i;
1410 maxentries = MIN(
1411 maxentries,
1412 ((BUFFER_SIZE -
1413 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1414 /DIR_STRUCT_SIZE));
1416 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1417 conn->dirpath,lp_dontdescend(SNUM(conn))));
1418 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1419 check_descend = True;
1422 for (i=numentries;(i<maxentries) && !finished;i++) {
1423 finished = !get_dir_entry(ctx,
1424 conn,
1425 mask,
1426 dirtype,
1427 &fname,
1428 &size,
1429 &mode,
1430 &date,
1431 check_descend,
1432 ask_sharemode);
1433 if (!finished) {
1434 char buf[DIR_STRUCT_SIZE];
1435 memcpy(buf,status,21);
1436 if (!make_dir_struct(ctx,
1437 buf,
1438 mask,
1439 fname,
1440 size,
1441 mode,
1442 date,
1443 !allow_long_path_components)) {
1444 reply_nterror(req, NT_STATUS_NO_MEMORY);
1445 END_PROFILE(SMBsearch);
1446 return;
1448 if (!dptr_fill(buf+12,dptr_num)) {
1449 break;
1451 if (message_push_blob(&req->outbuf,
1452 data_blob_const(buf, sizeof(buf)))
1453 == -1) {
1454 reply_nterror(req, NT_STATUS_NO_MEMORY);
1455 END_PROFILE(SMBsearch);
1456 return;
1458 numentries++;
1463 SearchEmpty:
1465 /* If we were called as SMBffirst with smb_search_id == NULL
1466 and no entries were found then return error and close dirptr
1467 (X/Open spec) */
1469 if (numentries == 0) {
1470 dptr_close(&dptr_num);
1471 } else if(expect_close && status_len == 0) {
1472 /* Close the dptr - we know it's gone */
1473 dptr_close(&dptr_num);
1476 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1477 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1478 dptr_close(&dptr_num);
1481 if ((numentries == 0) && !mask_contains_wcard) {
1482 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1483 END_PROFILE(SMBsearch);
1484 return;
1487 SSVAL(req->outbuf,smb_vwv0,numentries);
1488 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1489 SCVAL(smb_buf(req->outbuf),0,5);
1490 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1492 /* The replies here are never long name. */
1493 SSVAL(req->outbuf, smb_flg2,
1494 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1495 if (!allow_long_path_components) {
1496 SSVAL(req->outbuf, smb_flg2,
1497 SVAL(req->outbuf, smb_flg2)
1498 & (~FLAGS2_LONG_PATH_COMPONENTS));
1501 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1502 SSVAL(req->outbuf, smb_flg2,
1503 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1505 if (!directory) {
1506 directory = dptr_path(dptr_num);
1509 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1510 smb_fn_name(req->cmd),
1511 mask,
1512 directory ? directory : "./",
1513 dirtype,
1514 numentries,
1515 maxentries ));
1517 END_PROFILE(SMBsearch);
1518 return;
1521 /****************************************************************************
1522 Reply to a fclose (stop directory search).
1523 ****************************************************************************/
1525 void reply_fclose(struct smb_request *req)
1527 int status_len;
1528 char status[21];
1529 int dptr_num= -2;
1530 const char *p;
1531 char *path = NULL;
1532 NTSTATUS err;
1533 bool path_contains_wcard = False;
1534 TALLOC_CTX *ctx = talloc_tos();
1536 START_PROFILE(SMBfclose);
1538 if (lp_posix_pathnames()) {
1539 reply_unknown_new(req, req->cmd);
1540 END_PROFILE(SMBfclose);
1541 return;
1544 p = (const char *)req->buf + 1;
1545 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1546 &err, &path_contains_wcard);
1547 if (!NT_STATUS_IS_OK(err)) {
1548 reply_nterror(req, err);
1549 END_PROFILE(SMBfclose);
1550 return;
1552 p++;
1553 status_len = SVAL(p,0);
1554 p += 2;
1556 if (status_len == 0) {
1557 reply_doserror(req, ERRSRV, ERRsrverror);
1558 END_PROFILE(SMBfclose);
1559 return;
1562 memcpy(status,p,21);
1564 if(dptr_fetch(status+12,&dptr_num)) {
1565 /* Close the dptr - we know it's gone */
1566 dptr_close(&dptr_num);
1569 reply_outbuf(req, 1, 0);
1570 SSVAL(req->outbuf,smb_vwv0,0);
1572 DEBUG(3,("search close\n"));
1574 END_PROFILE(SMBfclose);
1575 return;
1578 /****************************************************************************
1579 Reply to an open.
1580 ****************************************************************************/
1582 void reply_open(struct smb_request *req)
1584 connection_struct *conn = req->conn;
1585 char *fname = NULL;
1586 uint32 fattr=0;
1587 SMB_OFF_T size = 0;
1588 time_t mtime=0;
1589 int info;
1590 SMB_STRUCT_STAT sbuf;
1591 files_struct *fsp;
1592 int oplock_request;
1593 int deny_mode;
1594 uint32 dos_attr;
1595 uint32 access_mask;
1596 uint32 share_mode;
1597 uint32 create_disposition;
1598 uint32 create_options = 0;
1599 NTSTATUS status;
1600 TALLOC_CTX *ctx = talloc_tos();
1602 START_PROFILE(SMBopen);
1604 if (req->wct < 2) {
1605 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1606 END_PROFILE(SMBopen);
1607 return;
1610 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1611 deny_mode = SVAL(req->vwv+0, 0);
1612 dos_attr = SVAL(req->vwv+1, 0);
1614 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1615 STR_TERMINATE, &status);
1616 if (!NT_STATUS_IS_OK(status)) {
1617 reply_nterror(req, status);
1618 END_PROFILE(SMBopen);
1619 return;
1622 if (!map_open_params_to_ntcreate(
1623 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1624 &share_mode, &create_disposition, &create_options)) {
1625 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1626 END_PROFILE(SMBopen);
1627 return;
1630 status = SMB_VFS_CREATE_FILE(
1631 conn, /* conn */
1632 req, /* req */
1633 0, /* root_dir_fid */
1634 fname, /* fname */
1635 CFF_DOS_PATH, /* create_file_flags */
1636 access_mask, /* access_mask */
1637 share_mode, /* share_access */
1638 create_disposition, /* create_disposition*/
1639 create_options, /* create_options */
1640 dos_attr, /* file_attributes */
1641 oplock_request, /* oplock_request */
1642 0, /* allocation_size */
1643 NULL, /* sd */
1644 NULL, /* ea_list */
1645 &fsp, /* result */
1646 &info, /* pinfo */
1647 &sbuf); /* psbuf */
1649 if (!NT_STATUS_IS_OK(status)) {
1650 if (open_was_deferred(req->mid)) {
1651 /* We have re-scheduled this call. */
1652 END_PROFILE(SMBopen);
1653 return;
1655 reply_openerror(req, status);
1656 END_PROFILE(SMBopen);
1657 return;
1660 size = sbuf.st_size;
1661 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1662 mtime = sbuf.st_mtime;
1664 if (fattr & aDIR) {
1665 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1666 close_file(req, fsp, ERROR_CLOSE);
1667 reply_doserror(req, ERRDOS,ERRnoaccess);
1668 END_PROFILE(SMBopen);
1669 return;
1672 reply_outbuf(req, 7, 0);
1673 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1674 SSVAL(req->outbuf,smb_vwv1,fattr);
1675 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1676 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1677 } else {
1678 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1680 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1681 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1683 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1684 SCVAL(req->outbuf,smb_flg,
1685 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1688 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1689 SCVAL(req->outbuf,smb_flg,
1690 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1692 END_PROFILE(SMBopen);
1693 return;
1696 /****************************************************************************
1697 Reply to an open and X.
1698 ****************************************************************************/
1700 void reply_open_and_X(struct smb_request *req)
1702 connection_struct *conn = req->conn;
1703 char *fname = NULL;
1704 uint16 open_flags;
1705 int deny_mode;
1706 uint32 smb_attr;
1707 /* Breakout the oplock request bits so we can set the
1708 reply bits separately. */
1709 int ex_oplock_request;
1710 int core_oplock_request;
1711 int oplock_request;
1712 #if 0
1713 int smb_sattr = SVAL(req->vwv+4, 0);
1714 uint32 smb_time = make_unix_date3(req->vwv+6);
1715 #endif
1716 int smb_ofun;
1717 uint32 fattr=0;
1718 int mtime=0;
1719 SMB_STRUCT_STAT sbuf;
1720 int smb_action = 0;
1721 files_struct *fsp;
1722 NTSTATUS status;
1723 uint64_t allocation_size;
1724 ssize_t retval = -1;
1725 uint32 access_mask;
1726 uint32 share_mode;
1727 uint32 create_disposition;
1728 uint32 create_options = 0;
1729 TALLOC_CTX *ctx = talloc_tos();
1731 START_PROFILE(SMBopenX);
1733 if (req->wct < 15) {
1734 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1735 END_PROFILE(SMBopenX);
1736 return;
1739 open_flags = SVAL(req->vwv+2, 0);
1740 deny_mode = SVAL(req->vwv+3, 0);
1741 smb_attr = SVAL(req->vwv+5, 0);
1742 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1743 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1744 oplock_request = ex_oplock_request | core_oplock_request;
1745 smb_ofun = SVAL(req->vwv+8, 0);
1746 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1748 /* If it's an IPC, pass off the pipe handler. */
1749 if (IS_IPC(conn)) {
1750 if (lp_nt_pipe_support()) {
1751 reply_open_pipe_and_X(conn, req);
1752 } else {
1753 reply_doserror(req, ERRSRV, ERRaccess);
1755 END_PROFILE(SMBopenX);
1756 return;
1759 /* XXXX we need to handle passed times, sattr and flags */
1760 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1761 STR_TERMINATE, &status);
1762 if (!NT_STATUS_IS_OK(status)) {
1763 reply_nterror(req, status);
1764 END_PROFILE(SMBopenX);
1765 return;
1768 if (!map_open_params_to_ntcreate(
1769 fname, deny_mode, smb_ofun, &access_mask,
1770 &share_mode, &create_disposition, &create_options)) {
1771 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1772 END_PROFILE(SMBopenX);
1773 return;
1776 status = SMB_VFS_CREATE_FILE(
1777 conn, /* conn */
1778 req, /* req */
1779 0, /* root_dir_fid */
1780 fname, /* fname */
1781 CFF_DOS_PATH, /* create_file_flags */
1782 access_mask, /* access_mask */
1783 share_mode, /* share_access */
1784 create_disposition, /* create_disposition*/
1785 create_options, /* create_options */
1786 smb_attr, /* file_attributes */
1787 oplock_request, /* oplock_request */
1788 0, /* allocation_size */
1789 NULL, /* sd */
1790 NULL, /* ea_list */
1791 &fsp, /* result */
1792 &smb_action, /* pinfo */
1793 &sbuf); /* psbuf */
1795 if (!NT_STATUS_IS_OK(status)) {
1796 END_PROFILE(SMBopenX);
1797 if (open_was_deferred(req->mid)) {
1798 /* We have re-scheduled this call. */
1799 return;
1801 reply_openerror(req, status);
1802 return;
1805 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1806 if the file is truncated or created. */
1807 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1808 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1809 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1810 close_file(req, fsp, ERROR_CLOSE);
1811 reply_nterror(req, NT_STATUS_DISK_FULL);
1812 END_PROFILE(SMBopenX);
1813 return;
1815 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1816 if (retval < 0) {
1817 close_file(req, fsp, ERROR_CLOSE);
1818 reply_nterror(req, NT_STATUS_DISK_FULL);
1819 END_PROFILE(SMBopenX);
1820 return;
1822 sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1825 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1826 mtime = sbuf.st_mtime;
1827 if (fattr & aDIR) {
1828 close_file(req, fsp, ERROR_CLOSE);
1829 reply_doserror(req, ERRDOS, ERRnoaccess);
1830 END_PROFILE(SMBopenX);
1831 return;
1834 /* If the caller set the extended oplock request bit
1835 and we granted one (by whatever means) - set the
1836 correct bit for extended oplock reply.
1839 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1840 smb_action |= EXTENDED_OPLOCK_GRANTED;
1843 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1844 smb_action |= EXTENDED_OPLOCK_GRANTED;
1847 /* If the caller set the core oplock request bit
1848 and we granted one (by whatever means) - set the
1849 correct bit for core oplock reply.
1852 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1853 reply_outbuf(req, 19, 0);
1854 } else {
1855 reply_outbuf(req, 15, 0);
1858 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1859 SCVAL(req->outbuf, smb_flg,
1860 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1863 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1864 SCVAL(req->outbuf, smb_flg,
1865 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1868 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1869 SSVAL(req->outbuf,smb_vwv3,fattr);
1870 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1871 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1872 } else {
1873 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1875 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1876 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1877 SSVAL(req->outbuf,smb_vwv11,smb_action);
1879 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1880 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1883 END_PROFILE(SMBopenX);
1884 chain_reply(req);
1885 return;
1888 /****************************************************************************
1889 Reply to a SMBulogoffX.
1890 ****************************************************************************/
1892 void reply_ulogoffX(struct smb_request *req)
1894 user_struct *vuser;
1896 START_PROFILE(SMBulogoffX);
1898 vuser = get_valid_user_struct(req->vuid);
1900 if(vuser == NULL) {
1901 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1902 req->vuid));
1905 /* in user level security we are supposed to close any files
1906 open by this user */
1907 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1908 file_close_user(req->vuid);
1911 invalidate_vuid(req->vuid);
1913 reply_outbuf(req, 2, 0);
1915 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1917 END_PROFILE(SMBulogoffX);
1918 chain_reply(req);
1921 /****************************************************************************
1922 Reply to a mknew or a create.
1923 ****************************************************************************/
1925 void reply_mknew(struct smb_request *req)
1927 connection_struct *conn = req->conn;
1928 char *fname = NULL;
1929 uint32 fattr = 0;
1930 struct smb_file_time ft;
1931 files_struct *fsp;
1932 int oplock_request = 0;
1933 SMB_STRUCT_STAT sbuf;
1934 NTSTATUS status;
1935 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1936 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1937 uint32 create_disposition;
1938 uint32 create_options = 0;
1939 TALLOC_CTX *ctx = talloc_tos();
1941 START_PROFILE(SMBcreate);
1942 ZERO_STRUCT(ft);
1944 if (req->wct < 3) {
1945 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1946 END_PROFILE(SMBcreate);
1947 return;
1950 fattr = SVAL(req->vwv+0, 0);
1951 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1953 /* mtime. */
1954 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
1956 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
1957 STR_TERMINATE, &status);
1958 if (!NT_STATUS_IS_OK(status)) {
1959 reply_nterror(req, status);
1960 END_PROFILE(SMBcreate);
1961 return;
1964 if (fattr & aVOLID) {
1965 DEBUG(0,("Attempt to create file (%s) with volid set - "
1966 "please report this\n", fname));
1969 if(req->cmd == SMBmknew) {
1970 /* We should fail if file exists. */
1971 create_disposition = FILE_CREATE;
1972 } else {
1973 /* Create if file doesn't exist, truncate if it does. */
1974 create_disposition = FILE_OVERWRITE_IF;
1977 status = SMB_VFS_CREATE_FILE(
1978 conn, /* conn */
1979 req, /* req */
1980 0, /* root_dir_fid */
1981 fname, /* fname */
1982 CFF_DOS_PATH, /* create_file_flags */
1983 access_mask, /* access_mask */
1984 share_mode, /* share_access */
1985 create_disposition, /* create_disposition*/
1986 create_options, /* create_options */
1987 fattr, /* file_attributes */
1988 oplock_request, /* oplock_request */
1989 0, /* allocation_size */
1990 NULL, /* sd */
1991 NULL, /* ea_list */
1992 &fsp, /* result */
1993 NULL, /* pinfo */
1994 &sbuf); /* psbuf */
1996 if (!NT_STATUS_IS_OK(status)) {
1997 END_PROFILE(SMBcreate);
1998 if (open_was_deferred(req->mid)) {
1999 /* We have re-scheduled this call. */
2000 return;
2002 reply_openerror(req, status);
2003 return;
2006 ft.atime = get_atimespec(&sbuf); /* atime. */
2007 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2008 if (!NT_STATUS_IS_OK(status)) {
2009 END_PROFILE(SMBcreate);
2010 reply_openerror(req, status);
2011 return;
2014 reply_outbuf(req, 1, 0);
2015 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2017 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2018 SCVAL(req->outbuf,smb_flg,
2019 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2022 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2023 SCVAL(req->outbuf,smb_flg,
2024 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2027 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2028 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2029 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2031 END_PROFILE(SMBcreate);
2032 return;
2035 /****************************************************************************
2036 Reply to a create temporary file.
2037 ****************************************************************************/
2039 void reply_ctemp(struct smb_request *req)
2041 connection_struct *conn = req->conn;
2042 char *fname = NULL;
2043 uint32 fattr;
2044 files_struct *fsp;
2045 int oplock_request;
2046 int tmpfd;
2047 SMB_STRUCT_STAT sbuf;
2048 char *s;
2049 NTSTATUS status;
2050 TALLOC_CTX *ctx = talloc_tos();
2052 START_PROFILE(SMBctemp);
2054 if (req->wct < 3) {
2055 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2056 END_PROFILE(SMBctemp);
2057 return;
2060 fattr = SVAL(req->vwv+0, 0);
2061 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2063 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2064 STR_TERMINATE, &status);
2065 if (!NT_STATUS_IS_OK(status)) {
2066 reply_nterror(req, status);
2067 END_PROFILE(SMBctemp);
2068 return;
2070 if (*fname) {
2071 fname = talloc_asprintf(ctx,
2072 "%s/TMXXXXXX",
2073 fname);
2074 } else {
2075 fname = talloc_strdup(ctx, "TMXXXXXX");
2078 if (!fname) {
2079 reply_nterror(req, NT_STATUS_NO_MEMORY);
2080 END_PROFILE(SMBctemp);
2081 return;
2084 status = resolve_dfspath(ctx, conn,
2085 req->flags2 & FLAGS2_DFS_PATHNAMES,
2086 fname,
2087 &fname);
2088 if (!NT_STATUS_IS_OK(status)) {
2089 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2090 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2091 ERRSRV, ERRbadpath);
2092 END_PROFILE(SMBctemp);
2093 return;
2095 reply_nterror(req, status);
2096 END_PROFILE(SMBctemp);
2097 return;
2100 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2101 if (!NT_STATUS_IS_OK(status)) {
2102 reply_nterror(req, status);
2103 END_PROFILE(SMBctemp);
2104 return;
2107 status = check_name(conn, fname);
2108 if (!NT_STATUS_IS_OK(status)) {
2109 reply_nterror(req, status);
2110 END_PROFILE(SMBctemp);
2111 return;
2114 tmpfd = smb_mkstemp(fname);
2115 if (tmpfd == -1) {
2116 reply_unixerror(req, ERRDOS, ERRnoaccess);
2117 END_PROFILE(SMBctemp);
2118 return;
2121 SMB_VFS_STAT(conn,fname,&sbuf);
2123 /* We should fail if file does not exist. */
2124 status = SMB_VFS_CREATE_FILE(
2125 conn, /* conn */
2126 req, /* req */
2127 0, /* root_dir_fid */
2128 fname, /* fname */
2129 0, /* create_file_flags */
2130 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2131 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2132 FILE_OPEN, /* create_disposition*/
2133 0, /* create_options */
2134 fattr, /* file_attributes */
2135 oplock_request, /* oplock_request */
2136 0, /* allocation_size */
2137 NULL, /* sd */
2138 NULL, /* ea_list */
2139 &fsp, /* result */
2140 NULL, /* pinfo */
2141 &sbuf); /* psbuf */
2143 /* close fd from smb_mkstemp() */
2144 close(tmpfd);
2146 if (!NT_STATUS_IS_OK(status)) {
2147 if (open_was_deferred(req->mid)) {
2148 /* We have re-scheduled this call. */
2149 END_PROFILE(SMBctemp);
2150 return;
2152 reply_openerror(req, status);
2153 END_PROFILE(SMBctemp);
2154 return;
2157 reply_outbuf(req, 1, 0);
2158 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2160 /* the returned filename is relative to the directory */
2161 s = strrchr_m(fsp->fsp_name, '/');
2162 if (!s) {
2163 s = fsp->fsp_name;
2164 } else {
2165 s++;
2168 #if 0
2169 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2170 thing in the byte section. JRA */
2171 SSVALS(p, 0, -1); /* what is this? not in spec */
2172 #endif
2173 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2174 == -1) {
2175 reply_nterror(req, NT_STATUS_NO_MEMORY);
2176 END_PROFILE(SMBctemp);
2177 return;
2180 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2181 SCVAL(req->outbuf, smb_flg,
2182 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2185 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2186 SCVAL(req->outbuf, smb_flg,
2187 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2190 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2191 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2192 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2194 END_PROFILE(SMBctemp);
2195 return;
2198 /*******************************************************************
2199 Check if a user is allowed to rename a file.
2200 ********************************************************************/
2202 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2203 uint16 dirtype, SMB_STRUCT_STAT *pst)
2205 uint32 fmode;
2207 if (!CAN_WRITE(conn)) {
2208 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2211 fmode = dos_mode(conn, fsp->fsp_name, pst);
2212 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2213 return NT_STATUS_NO_SUCH_FILE;
2216 if (S_ISDIR(pst->st_mode)) {
2217 return NT_STATUS_OK;
2220 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2221 return NT_STATUS_OK;
2224 return NT_STATUS_ACCESS_DENIED;
2227 /*******************************************************************
2228 * unlink a file with all relevant access checks
2229 *******************************************************************/
2231 static NTSTATUS do_unlink(connection_struct *conn,
2232 struct smb_request *req,
2233 const char *fname,
2234 uint32 dirtype)
2236 SMB_STRUCT_STAT sbuf;
2237 uint32 fattr;
2238 files_struct *fsp;
2239 uint32 dirtype_orig = dirtype;
2240 NTSTATUS status;
2242 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2244 if (!CAN_WRITE(conn)) {
2245 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2248 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2249 return map_nt_error_from_unix(errno);
2252 fattr = dos_mode(conn,fname,&sbuf);
2254 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2255 dirtype = aDIR|aARCH|aRONLY;
2258 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2259 if (!dirtype) {
2260 return NT_STATUS_NO_SUCH_FILE;
2263 if (!dir_check_ftype(conn, fattr, dirtype)) {
2264 if (fattr & aDIR) {
2265 return NT_STATUS_FILE_IS_A_DIRECTORY;
2267 return NT_STATUS_NO_SUCH_FILE;
2270 if (dirtype_orig & 0x8000) {
2271 /* These will never be set for POSIX. */
2272 return NT_STATUS_NO_SUCH_FILE;
2275 #if 0
2276 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2277 return NT_STATUS_FILE_IS_A_DIRECTORY;
2280 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2281 return NT_STATUS_NO_SUCH_FILE;
2284 if (dirtype & 0xFF00) {
2285 /* These will never be set for POSIX. */
2286 return NT_STATUS_NO_SUCH_FILE;
2289 dirtype &= 0xFF;
2290 if (!dirtype) {
2291 return NT_STATUS_NO_SUCH_FILE;
2294 /* Can't delete a directory. */
2295 if (fattr & aDIR) {
2296 return NT_STATUS_FILE_IS_A_DIRECTORY;
2298 #endif
2300 #if 0 /* JRATEST */
2301 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2302 return NT_STATUS_OBJECT_NAME_INVALID;
2303 #endif /* JRATEST */
2305 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2307 On a Windows share, a file with read-only dosmode can be opened with
2308 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2309 fails with NT_STATUS_CANNOT_DELETE error.
2311 This semantic causes a problem that a user can not
2312 rename a file with read-only dosmode on a Samba share
2313 from a Windows command prompt (i.e. cmd.exe, but can rename
2314 from Windows Explorer).
2317 if (!lp_delete_readonly(SNUM(conn))) {
2318 if (fattr & aRONLY) {
2319 return NT_STATUS_CANNOT_DELETE;
2323 /* On open checks the open itself will check the share mode, so
2324 don't do it here as we'll get it wrong. */
2326 status = SMB_VFS_CREATE_FILE
2327 (conn, /* conn */
2328 req, /* req */
2329 0, /* root_dir_fid */
2330 fname, /* fname */
2331 0, /* create_file_flags */
2332 DELETE_ACCESS, /* access_mask */
2333 FILE_SHARE_NONE, /* share_access */
2334 FILE_OPEN, /* create_disposition*/
2335 FILE_NON_DIRECTORY_FILE, /* create_options */
2336 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2337 0, /* oplock_request */
2338 0, /* allocation_size */
2339 NULL, /* sd */
2340 NULL, /* ea_list */
2341 &fsp, /* result */
2342 NULL, /* pinfo */
2343 &sbuf); /* psbuf */
2345 if (!NT_STATUS_IS_OK(status)) {
2346 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2347 nt_errstr(status)));
2348 return status;
2351 /* The set is across all open files on this dev/inode pair. */
2352 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2353 close_file(req, fsp, NORMAL_CLOSE);
2354 return NT_STATUS_ACCESS_DENIED;
2357 return close_file(req, fsp, NORMAL_CLOSE);
2360 /****************************************************************************
2361 The guts of the unlink command, split out so it may be called by the NT SMB
2362 code.
2363 ****************************************************************************/
2365 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2366 uint32 dirtype, const char *name_in, bool has_wild)
2368 const char *directory = NULL;
2369 char *mask = NULL;
2370 char *name = NULL;
2371 char *p = NULL;
2372 int count=0;
2373 NTSTATUS status = NT_STATUS_OK;
2374 SMB_STRUCT_STAT sbuf, st;
2375 TALLOC_CTX *ctx = talloc_tos();
2377 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 return status;
2382 p = strrchr_m(name,'/');
2383 if (!p) {
2384 directory = talloc_strdup(ctx, ".");
2385 if (!directory) {
2386 return NT_STATUS_NO_MEMORY;
2388 mask = name;
2389 } else {
2390 *p = 0;
2391 directory = name;
2392 mask = p+1;
2396 * We should only check the mangled cache
2397 * here if unix_convert failed. This means
2398 * that the path in 'mask' doesn't exist
2399 * on the file system and so we need to look
2400 * for a possible mangle. This patch from
2401 * Tine Smukavec <valentin.smukavec@hermes.si>.
2404 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2405 char *new_mask = NULL;
2406 mangle_lookup_name_from_8_3(ctx,
2407 mask,
2408 &new_mask,
2409 conn->params );
2410 if (new_mask) {
2411 mask = new_mask;
2415 if (!has_wild) {
2416 directory = talloc_asprintf(ctx,
2417 "%s/%s",
2418 directory,
2419 mask);
2420 if (!directory) {
2421 return NT_STATUS_NO_MEMORY;
2423 if (dirtype == 0) {
2424 dirtype = FILE_ATTRIBUTE_NORMAL;
2427 status = check_name(conn, directory);
2428 if (!NT_STATUS_IS_OK(status)) {
2429 return status;
2432 status = do_unlink(conn, req, directory, dirtype);
2433 if (!NT_STATUS_IS_OK(status)) {
2434 return status;
2437 count++;
2438 } else {
2439 struct smb_Dir *dir_hnd = NULL;
2440 long offset = 0;
2441 const char *dname;
2443 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2444 return NT_STATUS_OBJECT_NAME_INVALID;
2447 if (strequal(mask,"????????.???")) {
2448 mask[0] = '*';
2449 mask[1] = '\0';
2452 status = check_name(conn, directory);
2453 if (!NT_STATUS_IS_OK(status)) {
2454 return status;
2457 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2458 dirtype);
2459 if (dir_hnd == NULL) {
2460 return map_nt_error_from_unix(errno);
2463 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2464 the pattern matches against the long name, otherwise the short name
2465 We don't implement this yet XXXX
2468 status = NT_STATUS_NO_SUCH_FILE;
2470 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2471 char *fname = NULL;
2473 if (!is_visible_file(conn, directory, dname, &st,
2474 true))
2476 continue;
2479 /* Quick check for "." and ".." */
2480 if (ISDOT(dname) || ISDOTDOT(dname)) {
2481 continue;
2484 if(!mask_match(dname, mask, conn->case_sensitive)) {
2485 continue;
2488 fname = talloc_asprintf(ctx, "%s/%s",
2489 directory,
2490 dname);
2491 if (!fname) {
2492 return NT_STATUS_NO_MEMORY;
2495 status = check_name(conn, fname);
2496 if (!NT_STATUS_IS_OK(status)) {
2497 TALLOC_FREE(dir_hnd);
2498 return status;
2501 status = do_unlink(conn, req, fname, dirtype);
2502 if (!NT_STATUS_IS_OK(status)) {
2503 TALLOC_FREE(fname);
2504 continue;
2507 count++;
2508 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2509 fname));
2511 TALLOC_FREE(fname);
2513 TALLOC_FREE(dir_hnd);
2516 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2517 status = map_nt_error_from_unix(errno);
2520 return status;
2523 /****************************************************************************
2524 Reply to a unlink
2525 ****************************************************************************/
2527 void reply_unlink(struct smb_request *req)
2529 connection_struct *conn = req->conn;
2530 char *name = NULL;
2531 uint32 dirtype;
2532 NTSTATUS status;
2533 bool path_contains_wcard = False;
2534 TALLOC_CTX *ctx = talloc_tos();
2536 START_PROFILE(SMBunlink);
2538 if (req->wct < 1) {
2539 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2540 END_PROFILE(SMBunlink);
2541 return;
2544 dirtype = SVAL(req->vwv+0, 0);
2546 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2547 STR_TERMINATE, &status,
2548 &path_contains_wcard);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 reply_nterror(req, status);
2551 END_PROFILE(SMBunlink);
2552 return;
2555 status = resolve_dfspath_wcard(ctx, conn,
2556 req->flags2 & FLAGS2_DFS_PATHNAMES,
2557 name,
2558 &name,
2559 &path_contains_wcard);
2560 if (!NT_STATUS_IS_OK(status)) {
2561 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2562 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2563 ERRSRV, ERRbadpath);
2564 END_PROFILE(SMBunlink);
2565 return;
2567 reply_nterror(req, status);
2568 END_PROFILE(SMBunlink);
2569 return;
2572 DEBUG(3,("reply_unlink : %s\n",name));
2574 status = unlink_internals(conn, req, dirtype, name,
2575 path_contains_wcard);
2576 if (!NT_STATUS_IS_OK(status)) {
2577 if (open_was_deferred(req->mid)) {
2578 /* We have re-scheduled this call. */
2579 END_PROFILE(SMBunlink);
2580 return;
2582 reply_nterror(req, status);
2583 END_PROFILE(SMBunlink);
2584 return;
2587 reply_outbuf(req, 0, 0);
2588 END_PROFILE(SMBunlink);
2590 return;
2593 /****************************************************************************
2594 Fail for readbraw.
2595 ****************************************************************************/
2597 static void fail_readraw(void)
2599 const char *errstr = talloc_asprintf(talloc_tos(),
2600 "FAIL ! reply_readbraw: socket write fail (%s)",
2601 strerror(errno));
2602 if (!errstr) {
2603 errstr = "";
2605 exit_server_cleanly(errstr);
2608 /****************************************************************************
2609 Fake (read/write) sendfile. Returns -1 on read or write fail.
2610 ****************************************************************************/
2612 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2613 size_t nread)
2615 size_t bufsize;
2616 size_t tosend = nread;
2617 char *buf;
2619 if (nread == 0) {
2620 return 0;
2623 bufsize = MIN(nread, 65536);
2625 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2626 return -1;
2629 while (tosend > 0) {
2630 ssize_t ret;
2631 size_t cur_read;
2633 if (tosend > bufsize) {
2634 cur_read = bufsize;
2635 } else {
2636 cur_read = tosend;
2638 ret = read_file(fsp,buf,startpos,cur_read);
2639 if (ret == -1) {
2640 SAFE_FREE(buf);
2641 return -1;
2644 /* If we had a short read, fill with zeros. */
2645 if (ret < cur_read) {
2646 memset(buf, '\0', cur_read - ret);
2649 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2650 SAFE_FREE(buf);
2651 return -1;
2653 tosend -= cur_read;
2654 startpos += cur_read;
2657 SAFE_FREE(buf);
2658 return (ssize_t)nread;
2661 /****************************************************************************
2662 Deal with the case of sendfile reading less bytes from the file than
2663 requested. Fill with zeros (all we can do).
2664 ****************************************************************************/
2666 static void sendfile_short_send(files_struct *fsp,
2667 ssize_t nread,
2668 size_t headersize,
2669 size_t smb_maxcnt)
2671 if (nread < headersize) {
2672 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2673 "header for file %s (%s). Terminating\n",
2674 fsp->fsp_name, strerror(errno) ));
2675 exit_server_cleanly("sendfile_short_send failed");
2678 nread -= headersize;
2680 if (nread < smb_maxcnt) {
2681 char *buf = SMB_CALLOC_ARRAY(char, 1024);
2682 if (!buf) {
2683 exit_server_cleanly("sendfile_short_send: "
2684 "malloc failed");
2687 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2688 "with zeros !\n", fsp->fsp_name));
2690 while (nread < smb_maxcnt) {
2692 * We asked for the real file size and told sendfile
2693 * to not go beyond the end of the file. But it can
2694 * happen that in between our fstat call and the
2695 * sendfile call the file was truncated. This is very
2696 * bad because we have already announced the larger
2697 * number of bytes to the client.
2699 * The best we can do now is to send 0-bytes, just as
2700 * a read from a hole in a sparse file would do.
2702 * This should happen rarely enough that I don't care
2703 * about efficiency here :-)
2705 size_t to_write;
2707 to_write = MIN(sizeof(buf), smb_maxcnt - nread);
2708 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2709 exit_server_cleanly("sendfile_short_send: "
2710 "write_data failed");
2712 nread += to_write;
2714 SAFE_FREE(buf);
2718 /****************************************************************************
2719 Return a readbraw error (4 bytes of zero).
2720 ****************************************************************************/
2722 static void reply_readbraw_error(void)
2724 char header[4];
2725 SIVAL(header,0,0);
2726 if (write_data(smbd_server_fd(),header,4) != 4) {
2727 fail_readraw();
2731 /****************************************************************************
2732 Use sendfile in readbraw.
2733 ****************************************************************************/
2735 static void send_file_readbraw(connection_struct *conn,
2736 struct smb_request *req,
2737 files_struct *fsp,
2738 SMB_OFF_T startpos,
2739 size_t nread,
2740 ssize_t mincount)
2742 char *outbuf = NULL;
2743 ssize_t ret=0;
2745 #if defined(WITH_SENDFILE)
2747 * We can only use sendfile on a non-chained packet
2748 * but we can use on a non-oplocked file. tridge proved this
2749 * on a train in Germany :-). JRA.
2750 * reply_readbraw has already checked the length.
2753 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2754 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2755 ssize_t sendfile_read = -1;
2756 char header[4];
2757 DATA_BLOB header_blob;
2759 _smb_setlen(header,nread);
2760 header_blob = data_blob_const(header, 4);
2762 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2763 &header_blob, startpos, nread)) == -1) {
2764 /* Returning ENOSYS means no data at all was sent.
2765 * Do this as a normal read. */
2766 if (errno == ENOSYS) {
2767 goto normal_readbraw;
2771 * Special hack for broken Linux with no working sendfile. If we
2772 * return EINTR we sent the header but not the rest of the data.
2773 * Fake this up by doing read/write calls.
2775 if (errno == EINTR) {
2776 /* Ensure we don't do this again. */
2777 set_use_sendfile(SNUM(conn), False);
2778 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2780 if (fake_sendfile(fsp, startpos, nread) == -1) {
2781 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2782 fsp->fsp_name, strerror(errno) ));
2783 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2785 return;
2788 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2789 fsp->fsp_name, strerror(errno) ));
2790 exit_server_cleanly("send_file_readbraw sendfile failed");
2793 /* Deal with possible short send. */
2794 if (sendfile_read != 4+nread) {
2795 sendfile_short_send(fsp, sendfile_read, 4, nread);
2797 return;
2799 #endif
2801 normal_readbraw:
2803 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2804 if (!outbuf) {
2805 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2806 (unsigned)(nread+4)));
2807 reply_readbraw_error();
2808 return;
2811 if (nread > 0) {
2812 ret = read_file(fsp,outbuf+4,startpos,nread);
2813 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2814 if (ret < mincount)
2815 ret = 0;
2816 #else
2817 if (ret < nread)
2818 ret = 0;
2819 #endif
2822 _smb_setlen(outbuf,ret);
2823 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2824 fail_readraw();
2826 TALLOC_FREE(outbuf);
2829 /****************************************************************************
2830 Reply to a readbraw (core+ protocol).
2831 ****************************************************************************/
2833 void reply_readbraw(struct smb_request *req)
2835 connection_struct *conn = req->conn;
2836 ssize_t maxcount,mincount;
2837 size_t nread = 0;
2838 SMB_OFF_T startpos;
2839 files_struct *fsp;
2840 SMB_STRUCT_STAT st;
2841 SMB_OFF_T size = 0;
2843 START_PROFILE(SMBreadbraw);
2845 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2846 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2847 "raw reads/writes are disallowed.");
2850 if (req->wct < 8) {
2851 reply_readbraw_error();
2852 END_PROFILE(SMBreadbraw);
2853 return;
2857 * Special check if an oplock break has been issued
2858 * and the readraw request croses on the wire, we must
2859 * return a zero length response here.
2862 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2865 * We have to do a check_fsp by hand here, as
2866 * we must always return 4 zero bytes on error,
2867 * not a NTSTATUS.
2870 if (!fsp || !conn || conn != fsp->conn ||
2871 req->vuid != fsp->vuid ||
2872 fsp->is_directory || fsp->fh->fd == -1) {
2874 * fsp could be NULL here so use the value from the packet. JRA.
2876 DEBUG(3,("reply_readbraw: fnum %d not valid "
2877 "- cache prime?\n",
2878 (int)SVAL(req->vwv+0, 0)));
2879 reply_readbraw_error();
2880 END_PROFILE(SMBreadbraw);
2881 return;
2884 /* Do a "by hand" version of CHECK_READ. */
2885 if (!(fsp->can_read ||
2886 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2887 (fsp->access_mask & FILE_EXECUTE)))) {
2888 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2889 (int)SVAL(req->vwv+0, 0)));
2890 reply_readbraw_error();
2891 END_PROFILE(SMBreadbraw);
2892 return;
2895 flush_write_cache(fsp, READRAW_FLUSH);
2897 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2898 if(req->wct == 10) {
2900 * This is a large offset (64 bit) read.
2902 #ifdef LARGE_SMB_OFF_T
2904 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
2906 #else /* !LARGE_SMB_OFF_T */
2909 * Ensure we haven't been sent a >32 bit offset.
2912 if(IVAL(req->vwv+8, 0) != 0) {
2913 DEBUG(0,("reply_readbraw: large offset "
2914 "(%x << 32) used and we don't support "
2915 "64 bit offsets.\n",
2916 (unsigned int)IVAL(req->vwv+8, 0) ));
2917 reply_readbraw_error();
2918 END_PROFILE(SMBreadbraw);
2919 return;
2922 #endif /* LARGE_SMB_OFF_T */
2924 if(startpos < 0) {
2925 DEBUG(0,("reply_readbraw: negative 64 bit "
2926 "readraw offset (%.0f) !\n",
2927 (double)startpos ));
2928 reply_readbraw_error();
2929 END_PROFILE(SMBreadbraw);
2930 return;
2934 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
2935 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
2937 /* ensure we don't overrun the packet size */
2938 maxcount = MIN(65535,maxcount);
2940 if (is_locked(fsp,(uint32)req->smbpid,
2941 (uint64_t)maxcount,
2942 (uint64_t)startpos,
2943 READ_LOCK)) {
2944 reply_readbraw_error();
2945 END_PROFILE(SMBreadbraw);
2946 return;
2949 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
2950 size = st.st_size;
2953 if (startpos >= size) {
2954 nread = 0;
2955 } else {
2956 nread = MIN(maxcount,(size - startpos));
2959 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2960 if (nread < mincount)
2961 nread = 0;
2962 #endif
2964 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2965 "min=%lu nread=%lu\n",
2966 fsp->fnum, (double)startpos,
2967 (unsigned long)maxcount,
2968 (unsigned long)mincount,
2969 (unsigned long)nread ) );
2971 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
2973 DEBUG(5,("reply_readbraw finished\n"));
2974 END_PROFILE(SMBreadbraw);
2977 #undef DBGC_CLASS
2978 #define DBGC_CLASS DBGC_LOCKING
2980 /****************************************************************************
2981 Reply to a lockread (core+ protocol).
2982 ****************************************************************************/
2984 void reply_lockread(struct smb_request *req)
2986 connection_struct *conn = req->conn;
2987 ssize_t nread = -1;
2988 char *data;
2989 SMB_OFF_T startpos;
2990 size_t numtoread;
2991 NTSTATUS status;
2992 files_struct *fsp;
2993 struct byte_range_lock *br_lck = NULL;
2994 char *p = NULL;
2996 START_PROFILE(SMBlockread);
2998 if (req->wct < 5) {
2999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3000 END_PROFILE(SMBlockread);
3001 return;
3004 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3006 if (!check_fsp(conn, req, fsp)) {
3007 END_PROFILE(SMBlockread);
3008 return;
3011 if (!CHECK_READ(fsp,req)) {
3012 reply_doserror(req, ERRDOS, ERRbadaccess);
3013 END_PROFILE(SMBlockread);
3014 return;
3017 numtoread = SVAL(req->vwv+1, 0);
3018 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3020 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3022 reply_outbuf(req, 5, numtoread + 3);
3024 data = smb_buf(req->outbuf) + 3;
3027 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3028 * protocol request that predates the read/write lock concept.
3029 * Thus instead of asking for a read lock here we need to ask
3030 * for a write lock. JRA.
3031 * Note that the requested lock size is unaffected by max_recv.
3034 br_lck = do_lock(smbd_messaging_context(),
3035 fsp,
3036 req->smbpid,
3037 (uint64_t)numtoread,
3038 (uint64_t)startpos,
3039 WRITE_LOCK,
3040 WINDOWS_LOCK,
3041 False, /* Non-blocking lock. */
3042 &status,
3043 NULL,
3044 NULL);
3045 TALLOC_FREE(br_lck);
3047 if (NT_STATUS_V(status)) {
3048 reply_nterror(req, status);
3049 END_PROFILE(SMBlockread);
3050 return;
3054 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3057 if (numtoread > max_recv) {
3058 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3059 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3060 (unsigned int)numtoread, (unsigned int)max_recv ));
3061 numtoread = MIN(numtoread,max_recv);
3063 nread = read_file(fsp,data,startpos,numtoread);
3065 if (nread < 0) {
3066 reply_unixerror(req, ERRDOS, ERRnoaccess);
3067 END_PROFILE(SMBlockread);
3068 return;
3071 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3073 SSVAL(req->outbuf,smb_vwv0,nread);
3074 SSVAL(req->outbuf,smb_vwv5,nread+3);
3075 p = smb_buf(req->outbuf);
3076 SCVAL(p,0,0); /* pad byte. */
3077 SSVAL(p,1,nread);
3079 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3080 fsp->fnum, (int)numtoread, (int)nread));
3082 END_PROFILE(SMBlockread);
3083 return;
3086 #undef DBGC_CLASS
3087 #define DBGC_CLASS DBGC_ALL
3089 /****************************************************************************
3090 Reply to a read.
3091 ****************************************************************************/
3093 void reply_read(struct smb_request *req)
3095 connection_struct *conn = req->conn;
3096 size_t numtoread;
3097 ssize_t nread = 0;
3098 char *data;
3099 SMB_OFF_T startpos;
3100 int outsize = 0;
3101 files_struct *fsp;
3103 START_PROFILE(SMBread);
3105 if (req->wct < 3) {
3106 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3107 END_PROFILE(SMBread);
3108 return;
3111 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3113 if (!check_fsp(conn, req, fsp)) {
3114 END_PROFILE(SMBread);
3115 return;
3118 if (!CHECK_READ(fsp,req)) {
3119 reply_doserror(req, ERRDOS, ERRbadaccess);
3120 END_PROFILE(SMBread);
3121 return;
3124 numtoread = SVAL(req->vwv+1, 0);
3125 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3127 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3130 * The requested read size cannot be greater than max_recv. JRA.
3132 if (numtoread > max_recv) {
3133 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3134 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3135 (unsigned int)numtoread, (unsigned int)max_recv ));
3136 numtoread = MIN(numtoread,max_recv);
3139 reply_outbuf(req, 5, numtoread+3);
3141 data = smb_buf(req->outbuf) + 3;
3143 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtoread,
3144 (uint64_t)startpos, READ_LOCK)) {
3145 reply_doserror(req, ERRDOS,ERRlock);
3146 END_PROFILE(SMBread);
3147 return;
3150 if (numtoread > 0)
3151 nread = read_file(fsp,data,startpos,numtoread);
3153 if (nread < 0) {
3154 reply_unixerror(req, ERRDOS,ERRnoaccess);
3155 END_PROFILE(SMBread);
3156 return;
3159 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3161 SSVAL(req->outbuf,smb_vwv0,nread);
3162 SSVAL(req->outbuf,smb_vwv5,nread+3);
3163 SCVAL(smb_buf(req->outbuf),0,1);
3164 SSVAL(smb_buf(req->outbuf),1,nread);
3166 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3167 fsp->fnum, (int)numtoread, (int)nread ) );
3169 END_PROFILE(SMBread);
3170 return;
3173 /****************************************************************************
3174 Setup readX header.
3175 ****************************************************************************/
3177 static int setup_readX_header(struct smb_request *req, char *outbuf,
3178 size_t smb_maxcnt)
3180 int outsize;
3181 char *data;
3183 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3184 data = smb_buf(outbuf);
3186 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3188 SCVAL(outbuf,smb_vwv0,0xFF);
3189 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3190 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3191 SSVAL(outbuf,smb_vwv6,
3192 req_wct_ofs(req)
3193 + 1 /* the wct field */
3194 + 12 * sizeof(uint16_t) /* vwv */
3195 + 2); /* the buflen field */
3196 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3197 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3198 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3199 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3200 return outsize;
3203 /****************************************************************************
3204 Reply to a read and X - possibly using sendfile.
3205 ****************************************************************************/
3207 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3208 files_struct *fsp, SMB_OFF_T startpos,
3209 size_t smb_maxcnt)
3211 SMB_STRUCT_STAT sbuf;
3212 ssize_t nread = -1;
3214 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3215 reply_unixerror(req, ERRDOS, ERRnoaccess);
3216 return;
3219 if (startpos > sbuf.st_size) {
3220 smb_maxcnt = 0;
3221 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3222 smb_maxcnt = (sbuf.st_size - startpos);
3225 if (smb_maxcnt == 0) {
3226 goto normal_read;
3229 #if defined(WITH_SENDFILE)
3231 * We can only use sendfile on a non-chained packet
3232 * but we can use on a non-oplocked file. tridge proved this
3233 * on a train in Germany :-). JRA.
3236 if (!req_is_in_chain(req) &&
3237 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3238 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3239 uint8 headerbuf[smb_size + 12 * 2];
3240 DATA_BLOB header;
3243 * Set up the packet header before send. We
3244 * assume here the sendfile will work (get the
3245 * correct amount of data).
3248 header = data_blob_const(headerbuf, sizeof(headerbuf));
3250 construct_reply_common_req(req, (char *)headerbuf);
3251 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3253 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3254 /* Returning ENOSYS means no data at all was sent.
3255 Do this as a normal read. */
3256 if (errno == ENOSYS) {
3257 goto normal_read;
3261 * Special hack for broken Linux with no working sendfile. If we
3262 * return EINTR we sent the header but not the rest of the data.
3263 * Fake this up by doing read/write calls.
3266 if (errno == EINTR) {
3267 /* Ensure we don't do this again. */
3268 set_use_sendfile(SNUM(conn), False);
3269 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3270 nread = fake_sendfile(fsp, startpos,
3271 smb_maxcnt);
3272 if (nread == -1) {
3273 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3274 fsp->fsp_name, strerror(errno) ));
3275 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3277 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3278 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3279 /* No outbuf here means successful sendfile. */
3280 TALLOC_FREE(req->outbuf);
3281 return;
3284 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3285 fsp->fsp_name, strerror(errno) ));
3286 exit_server_cleanly("send_file_readX sendfile failed");
3289 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3290 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3292 /* Deal with possible short send. */
3293 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3294 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3297 /* No outbuf here means successful sendfile. */
3298 TALLOC_FREE(req->outbuf);
3299 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3300 SMB_PERFCOUNT_END(&req->pcd);
3301 return;
3303 #endif
3305 normal_read:
3307 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3308 uint8 headerbuf[smb_size + 2*12];
3310 construct_reply_common_req(req, (char *)headerbuf);
3311 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3313 /* Send out the header. */
3314 if (write_data(smbd_server_fd(), (char *)headerbuf,
3315 sizeof(headerbuf)) != sizeof(headerbuf)) {
3316 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3317 fsp->fsp_name, strerror(errno) ));
3318 exit_server_cleanly("send_file_readX sendfile failed");
3320 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3321 if (nread == -1) {
3322 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3323 fsp->fsp_name, strerror(errno) ));
3324 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3326 TALLOC_FREE(req->outbuf);
3327 return;
3330 reply_outbuf(req, 12, smb_maxcnt);
3332 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3333 if (nread < 0) {
3334 reply_unixerror(req, ERRDOS, ERRnoaccess);
3335 return;
3338 setup_readX_header(req, (char *)req->outbuf, nread);
3340 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3341 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3343 chain_reply(req);
3346 /****************************************************************************
3347 Reply to a read and X.
3348 ****************************************************************************/
3350 void reply_read_and_X(struct smb_request *req)
3352 connection_struct *conn = req->conn;
3353 files_struct *fsp;
3354 SMB_OFF_T startpos;
3355 size_t smb_maxcnt;
3356 bool big_readX = False;
3357 #if 0
3358 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3359 #endif
3361 START_PROFILE(SMBreadX);
3363 if ((req->wct != 10) && (req->wct != 12)) {
3364 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3365 return;
3368 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3369 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3370 smb_maxcnt = SVAL(req->vwv+5, 0);
3372 /* If it's an IPC, pass off the pipe handler. */
3373 if (IS_IPC(conn)) {
3374 reply_pipe_read_and_X(req);
3375 END_PROFILE(SMBreadX);
3376 return;
3379 if (!check_fsp(conn, req, fsp)) {
3380 END_PROFILE(SMBreadX);
3381 return;
3384 if (!CHECK_READ(fsp,req)) {
3385 reply_doserror(req, ERRDOS,ERRbadaccess);
3386 END_PROFILE(SMBreadX);
3387 return;
3390 if (global_client_caps & CAP_LARGE_READX) {
3391 size_t upper_size = SVAL(req->vwv+7, 0);
3392 smb_maxcnt |= (upper_size<<16);
3393 if (upper_size > 1) {
3394 /* Can't do this on a chained packet. */
3395 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3396 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3397 END_PROFILE(SMBreadX);
3398 return;
3400 /* We currently don't do this on signed or sealed data. */
3401 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3402 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3403 END_PROFILE(SMBreadX);
3404 return;
3406 /* Is there room in the reply for this data ? */
3407 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3408 reply_nterror(req,
3409 NT_STATUS_INVALID_PARAMETER);
3410 END_PROFILE(SMBreadX);
3411 return;
3413 big_readX = True;
3417 if (req->wct == 12) {
3418 #ifdef LARGE_SMB_OFF_T
3420 * This is a large offset (64 bit) read.
3422 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3424 #else /* !LARGE_SMB_OFF_T */
3427 * Ensure we haven't been sent a >32 bit offset.
3430 if(IVAL(req->vwv+10, 0) != 0) {
3431 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3432 "used and we don't support 64 bit offsets.\n",
3433 (unsigned int)IVAL(req->vwv+10, 0) ));
3434 END_PROFILE(SMBreadX);
3435 reply_doserror(req, ERRDOS, ERRbadaccess);
3436 return;
3439 #endif /* LARGE_SMB_OFF_T */
3443 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)smb_maxcnt,
3444 (uint64_t)startpos, READ_LOCK)) {
3445 END_PROFILE(SMBreadX);
3446 reply_doserror(req, ERRDOS, ERRlock);
3447 return;
3450 if (!big_readX &&
3451 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3452 END_PROFILE(SMBreadX);
3453 return;
3456 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3458 END_PROFILE(SMBreadX);
3459 return;
3462 /****************************************************************************
3463 Error replies to writebraw must have smb_wct == 1. Fix this up.
3464 ****************************************************************************/
3466 void error_to_writebrawerr(struct smb_request *req)
3468 uint8 *old_outbuf = req->outbuf;
3470 reply_outbuf(req, 1, 0);
3472 memcpy(req->outbuf, old_outbuf, smb_size);
3473 TALLOC_FREE(old_outbuf);
3476 /****************************************************************************
3477 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3478 ****************************************************************************/
3480 void reply_writebraw(struct smb_request *req)
3482 connection_struct *conn = req->conn;
3483 char *buf = NULL;
3484 ssize_t nwritten=0;
3485 ssize_t total_written=0;
3486 size_t numtowrite=0;
3487 size_t tcount;
3488 SMB_OFF_T startpos;
3489 char *data=NULL;
3490 bool write_through;
3491 files_struct *fsp;
3492 NTSTATUS status;
3494 START_PROFILE(SMBwritebraw);
3497 * If we ever reply with an error, it must have the SMB command
3498 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3499 * we're finished.
3501 SCVAL(req->inbuf,smb_com,SMBwritec);
3503 if (srv_is_signing_active()) {
3504 END_PROFILE(SMBwritebraw);
3505 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3506 "raw reads/writes are disallowed.");
3509 if (req->wct < 12) {
3510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3511 error_to_writebrawerr(req);
3512 END_PROFILE(SMBwritebraw);
3513 return;
3516 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3517 if (!check_fsp(conn, req, fsp)) {
3518 error_to_writebrawerr(req);
3519 END_PROFILE(SMBwritebraw);
3520 return;
3523 if (!CHECK_WRITE(fsp)) {
3524 reply_doserror(req, ERRDOS, ERRbadaccess);
3525 error_to_writebrawerr(req);
3526 END_PROFILE(SMBwritebraw);
3527 return;
3530 tcount = IVAL(req->vwv+1, 0);
3531 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3532 write_through = BITSETW(req->vwv+7,0);
3534 /* We have to deal with slightly different formats depending
3535 on whether we are using the core+ or lanman1.0 protocol */
3537 if(Protocol <= PROTOCOL_COREPLUS) {
3538 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3539 data = smb_buf(req->inbuf);
3540 } else {
3541 numtowrite = SVAL(req->vwv+10, 0);
3542 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3545 /* Ensure we don't write bytes past the end of this packet. */
3546 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3547 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3548 error_to_writebrawerr(req);
3549 END_PROFILE(SMBwritebraw);
3550 return;
3553 if (is_locked(fsp,(uint32)req->smbpid,(uint64_t)tcount,
3554 (uint64_t)startpos, WRITE_LOCK)) {
3555 reply_doserror(req, ERRDOS, ERRlock);
3556 error_to_writebrawerr(req);
3557 END_PROFILE(SMBwritebraw);
3558 return;
3561 if (numtowrite>0) {
3562 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3565 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3566 "wrote=%d sync=%d\n",
3567 fsp->fnum, (double)startpos, (int)numtowrite,
3568 (int)nwritten, (int)write_through));
3570 if (nwritten < (ssize_t)numtowrite) {
3571 reply_unixerror(req, ERRHRD, ERRdiskfull);
3572 error_to_writebrawerr(req);
3573 END_PROFILE(SMBwritebraw);
3574 return;
3577 total_written = nwritten;
3579 /* Allocate a buffer of 64k + length. */
3580 buf = TALLOC_ARRAY(NULL, char, 65540);
3581 if (!buf) {
3582 reply_doserror(req, ERRDOS, ERRnomem);
3583 error_to_writebrawerr(req);
3584 END_PROFILE(SMBwritebraw);
3585 return;
3588 /* Return a SMBwritebraw message to the redirector to tell
3589 * it to send more bytes */
3591 memcpy(buf, req->inbuf, smb_size);
3592 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3593 SCVAL(buf,smb_com,SMBwritebraw);
3594 SSVALS(buf,smb_vwv0,0xFFFF);
3595 show_msg(buf);
3596 if (!srv_send_smb(smbd_server_fd(),
3597 buf,
3598 IS_CONN_ENCRYPTED(conn),
3599 &req->pcd)) {
3600 exit_server_cleanly("reply_writebraw: srv_send_smb "
3601 "failed.");
3604 /* Now read the raw data into the buffer and write it */
3605 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3606 &numtowrite);
3607 if (!NT_STATUS_IS_OK(status)) {
3608 exit_server_cleanly("secondary writebraw failed");
3611 /* Set up outbuf to return the correct size */
3612 reply_outbuf(req, 1, 0);
3614 if (numtowrite != 0) {
3616 if (numtowrite > 0xFFFF) {
3617 DEBUG(0,("reply_writebraw: Oversize secondary write "
3618 "raw requested (%u). Terminating\n",
3619 (unsigned int)numtowrite ));
3620 exit_server_cleanly("secondary writebraw failed");
3623 if (tcount > nwritten+numtowrite) {
3624 DEBUG(3,("reply_writebraw: Client overestimated the "
3625 "write %d %d %d\n",
3626 (int)tcount,(int)nwritten,(int)numtowrite));
3629 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3631 if (!NT_STATUS_IS_OK(status)) {
3632 DEBUG(0,("reply_writebraw: Oversize secondary write "
3633 "raw read failed (%s). Terminating\n",
3634 nt_errstr(status)));
3635 exit_server_cleanly("secondary writebraw failed");
3638 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3639 if (nwritten == -1) {
3640 TALLOC_FREE(buf);
3641 reply_unixerror(req, ERRHRD, ERRdiskfull);
3642 error_to_writebrawerr(req);
3643 END_PROFILE(SMBwritebraw);
3644 return;
3647 if (nwritten < (ssize_t)numtowrite) {
3648 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3649 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3652 if (nwritten > 0) {
3653 total_written += nwritten;
3657 TALLOC_FREE(buf);
3658 SSVAL(req->outbuf,smb_vwv0,total_written);
3660 status = sync_file(conn, fsp, write_through);
3661 if (!NT_STATUS_IS_OK(status)) {
3662 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3663 fsp->fsp_name, nt_errstr(status) ));
3664 reply_nterror(req, status);
3665 error_to_writebrawerr(req);
3666 END_PROFILE(SMBwritebraw);
3667 return;
3670 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3671 "wrote=%d\n",
3672 fsp->fnum, (double)startpos, (int)numtowrite,
3673 (int)total_written));
3675 /* We won't return a status if write through is not selected - this
3676 * follows what WfWg does */
3677 END_PROFILE(SMBwritebraw);
3679 if (!write_through && total_written==tcount) {
3681 #if RABBIT_PELLET_FIX
3683 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3684 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3685 * JRA.
3687 if (!send_keepalive(smbd_server_fd())) {
3688 exit_server_cleanly("reply_writebraw: send of "
3689 "keepalive failed");
3691 #endif
3692 TALLOC_FREE(req->outbuf);
3694 return;
3697 #undef DBGC_CLASS
3698 #define DBGC_CLASS DBGC_LOCKING
3700 /****************************************************************************
3701 Reply to a writeunlock (core+).
3702 ****************************************************************************/
3704 void reply_writeunlock(struct smb_request *req)
3706 connection_struct *conn = req->conn;
3707 ssize_t nwritten = -1;
3708 size_t numtowrite;
3709 SMB_OFF_T startpos;
3710 const char *data;
3711 NTSTATUS status = NT_STATUS_OK;
3712 files_struct *fsp;
3714 START_PROFILE(SMBwriteunlock);
3716 if (req->wct < 5) {
3717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3718 END_PROFILE(SMBwriteunlock);
3719 return;
3722 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3724 if (!check_fsp(conn, req, fsp)) {
3725 END_PROFILE(SMBwriteunlock);
3726 return;
3729 if (!CHECK_WRITE(fsp)) {
3730 reply_doserror(req, ERRDOS,ERRbadaccess);
3731 END_PROFILE(SMBwriteunlock);
3732 return;
3735 numtowrite = SVAL(req->vwv+1, 0);
3736 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3737 data = (const char *)req->buf + 3;
3739 if (numtowrite
3740 && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3741 (uint64_t)startpos, WRITE_LOCK)) {
3742 reply_doserror(req, ERRDOS, ERRlock);
3743 END_PROFILE(SMBwriteunlock);
3744 return;
3747 /* The special X/Open SMB protocol handling of
3748 zero length writes is *NOT* done for
3749 this call */
3750 if(numtowrite == 0) {
3751 nwritten = 0;
3752 } else {
3753 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3756 status = sync_file(conn, fsp, False /* write through */);
3757 if (!NT_STATUS_IS_OK(status)) {
3758 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3759 fsp->fsp_name, nt_errstr(status) ));
3760 reply_nterror(req, status);
3761 END_PROFILE(SMBwriteunlock);
3762 return;
3765 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3766 reply_unixerror(req, ERRHRD, ERRdiskfull);
3767 END_PROFILE(SMBwriteunlock);
3768 return;
3771 if (numtowrite) {
3772 status = do_unlock(smbd_messaging_context(),
3773 fsp,
3774 req->smbpid,
3775 (uint64_t)numtowrite,
3776 (uint64_t)startpos,
3777 WINDOWS_LOCK);
3779 if (NT_STATUS_V(status)) {
3780 reply_nterror(req, status);
3781 END_PROFILE(SMBwriteunlock);
3782 return;
3786 reply_outbuf(req, 1, 0);
3788 SSVAL(req->outbuf,smb_vwv0,nwritten);
3790 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3791 fsp->fnum, (int)numtowrite, (int)nwritten));
3793 END_PROFILE(SMBwriteunlock);
3794 return;
3797 #undef DBGC_CLASS
3798 #define DBGC_CLASS DBGC_ALL
3800 /****************************************************************************
3801 Reply to a write.
3802 ****************************************************************************/
3804 void reply_write(struct smb_request *req)
3806 connection_struct *conn = req->conn;
3807 size_t numtowrite;
3808 ssize_t nwritten = -1;
3809 SMB_OFF_T startpos;
3810 const char *data;
3811 files_struct *fsp;
3812 NTSTATUS status;
3814 START_PROFILE(SMBwrite);
3816 if (req->wct < 5) {
3817 END_PROFILE(SMBwrite);
3818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3819 return;
3822 /* If it's an IPC, pass off the pipe handler. */
3823 if (IS_IPC(conn)) {
3824 reply_pipe_write(req);
3825 END_PROFILE(SMBwrite);
3826 return;
3829 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3831 if (!check_fsp(conn, req, fsp)) {
3832 END_PROFILE(SMBwrite);
3833 return;
3836 if (!CHECK_WRITE(fsp)) {
3837 reply_doserror(req, ERRDOS, ERRbadaccess);
3838 END_PROFILE(SMBwrite);
3839 return;
3842 numtowrite = SVAL(req->vwv+1, 0);
3843 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3844 data = (const char *)req->buf + 3;
3846 if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3847 (uint64_t)startpos, WRITE_LOCK)) {
3848 reply_doserror(req, ERRDOS, ERRlock);
3849 END_PROFILE(SMBwrite);
3850 return;
3854 * X/Open SMB protocol says that if smb_vwv1 is
3855 * zero then the file size should be extended or
3856 * truncated to the size given in smb_vwv[2-3].
3859 if(numtowrite == 0) {
3861 * This is actually an allocate call, and set EOF. JRA.
3863 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3864 if (nwritten < 0) {
3865 reply_nterror(req, NT_STATUS_DISK_FULL);
3866 END_PROFILE(SMBwrite);
3867 return;
3869 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3870 if (nwritten < 0) {
3871 reply_nterror(req, NT_STATUS_DISK_FULL);
3872 END_PROFILE(SMBwrite);
3873 return;
3875 trigger_write_time_update_immediate(fsp);
3876 } else {
3877 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3880 status = sync_file(conn, fsp, False);
3881 if (!NT_STATUS_IS_OK(status)) {
3882 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3883 fsp->fsp_name, nt_errstr(status) ));
3884 reply_nterror(req, status);
3885 END_PROFILE(SMBwrite);
3886 return;
3889 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3890 reply_unixerror(req, ERRHRD, ERRdiskfull);
3891 END_PROFILE(SMBwrite);
3892 return;
3895 reply_outbuf(req, 1, 0);
3897 SSVAL(req->outbuf,smb_vwv0,nwritten);
3899 if (nwritten < (ssize_t)numtowrite) {
3900 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3901 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3904 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3906 END_PROFILE(SMBwrite);
3907 return;
3910 /****************************************************************************
3911 Ensure a buffer is a valid writeX for recvfile purposes.
3912 ****************************************************************************/
3914 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3915 (2*14) + /* word count (including bcc) */ \
3916 1 /* pad byte */)
3918 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3920 size_t numtowrite;
3921 connection_struct *conn = NULL;
3922 unsigned int doff = 0;
3923 size_t len = smb_len_large(inbuf);
3925 if (is_encrypted_packet(inbuf)) {
3926 /* Can't do this on encrypted
3927 * connections. */
3928 return false;
3931 if (CVAL(inbuf,smb_com) != SMBwriteX) {
3932 return false;
3935 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3936 CVAL(inbuf,smb_wct) != 14) {
3937 DEBUG(10,("is_valid_writeX_buffer: chained or "
3938 "invalid word length.\n"));
3939 return false;
3942 conn = conn_find(SVAL(inbuf, smb_tid));
3943 if (conn == NULL) {
3944 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3945 return false;
3947 if (IS_IPC(conn)) {
3948 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3949 return false;
3951 if (IS_PRINT(conn)) {
3952 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
3953 return false;
3955 doff = SVAL(inbuf,smb_vwv11);
3957 numtowrite = SVAL(inbuf,smb_vwv10);
3959 if (len > doff && len - doff > 0xFFFF) {
3960 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3963 if (numtowrite == 0) {
3964 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3965 return false;
3968 /* Ensure the sizes match up. */
3969 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3970 /* no pad byte...old smbclient :-( */
3971 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3972 (unsigned int)doff,
3973 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3974 return false;
3977 if (len - doff != numtowrite) {
3978 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3979 "len = %u, doff = %u, numtowrite = %u\n",
3980 (unsigned int)len,
3981 (unsigned int)doff,
3982 (unsigned int)numtowrite ));
3983 return false;
3986 DEBUG(10,("is_valid_writeX_buffer: true "
3987 "len = %u, doff = %u, numtowrite = %u\n",
3988 (unsigned int)len,
3989 (unsigned int)doff,
3990 (unsigned int)numtowrite ));
3992 return true;
3995 /****************************************************************************
3996 Reply to a write and X.
3997 ****************************************************************************/
3999 void reply_write_and_X(struct smb_request *req)
4001 connection_struct *conn = req->conn;
4002 files_struct *fsp;
4003 SMB_OFF_T startpos;
4004 size_t numtowrite;
4005 bool write_through;
4006 ssize_t nwritten;
4007 unsigned int smb_doff;
4008 unsigned int smblen;
4009 char *data;
4010 NTSTATUS status;
4012 START_PROFILE(SMBwriteX);
4014 if ((req->wct != 12) && (req->wct != 14)) {
4015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4016 END_PROFILE(SMBwriteX);
4017 return;
4020 numtowrite = SVAL(req->vwv+10, 0);
4021 smb_doff = SVAL(req->vwv+11, 0);
4022 smblen = smb_len(req->inbuf);
4024 if (req->unread_bytes > 0xFFFF ||
4025 (smblen > smb_doff &&
4026 smblen - smb_doff > 0xFFFF)) {
4027 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4030 if (req->unread_bytes) {
4031 /* Can't do a recvfile write on IPC$ */
4032 if (IS_IPC(conn)) {
4033 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4034 END_PROFILE(SMBwriteX);
4035 return;
4037 if (numtowrite != req->unread_bytes) {
4038 reply_doserror(req, ERRDOS, ERRbadmem);
4039 END_PROFILE(SMBwriteX);
4040 return;
4042 } else {
4043 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4044 smb_doff + numtowrite > smblen) {
4045 reply_doserror(req, ERRDOS, ERRbadmem);
4046 END_PROFILE(SMBwriteX);
4047 return;
4051 /* If it's an IPC, pass off the pipe handler. */
4052 if (IS_IPC(conn)) {
4053 if (req->unread_bytes) {
4054 reply_doserror(req, ERRDOS, ERRbadmem);
4055 END_PROFILE(SMBwriteX);
4056 return;
4058 reply_pipe_write_and_X(req);
4059 END_PROFILE(SMBwriteX);
4060 return;
4063 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4064 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4065 write_through = BITSETW(req->vwv+7,0);
4067 if (!check_fsp(conn, req, fsp)) {
4068 END_PROFILE(SMBwriteX);
4069 return;
4072 if (!CHECK_WRITE(fsp)) {
4073 reply_doserror(req, ERRDOS, ERRbadaccess);
4074 END_PROFILE(SMBwriteX);
4075 return;
4078 data = smb_base(req->inbuf) + smb_doff;
4080 if(req->wct == 14) {
4081 #ifdef LARGE_SMB_OFF_T
4083 * This is a large offset (64 bit) write.
4085 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4087 #else /* !LARGE_SMB_OFF_T */
4090 * Ensure we haven't been sent a >32 bit offset.
4093 if(IVAL(req->vwv+12, 0) != 0) {
4094 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4095 "used and we don't support 64 bit offsets.\n",
4096 (unsigned int)IVAL(req->vwv+12, 0) ));
4097 reply_doserror(req, ERRDOS, ERRbadaccess);
4098 END_PROFILE(SMBwriteX);
4099 return;
4102 #endif /* LARGE_SMB_OFF_T */
4105 if (is_locked(fsp,(uint32)req->smbpid,
4106 (uint64_t)numtowrite,
4107 (uint64_t)startpos, WRITE_LOCK)) {
4108 reply_doserror(req, ERRDOS, ERRlock);
4109 END_PROFILE(SMBwriteX);
4110 return;
4113 /* X/Open SMB protocol says that, unlike SMBwrite
4114 if the length is zero then NO truncation is
4115 done, just a write of zero. To truncate a file,
4116 use SMBwrite. */
4118 if(numtowrite == 0) {
4119 nwritten = 0;
4120 } else {
4122 if ((req->unread_bytes == 0) &&
4123 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4124 numtowrite)) {
4125 END_PROFILE(SMBwriteX);
4126 return;
4129 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4132 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4133 reply_unixerror(req, ERRHRD, ERRdiskfull);
4134 END_PROFILE(SMBwriteX);
4135 return;
4138 reply_outbuf(req, 6, 0);
4139 SSVAL(req->outbuf,smb_vwv2,nwritten);
4140 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4142 if (nwritten < (ssize_t)numtowrite) {
4143 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4144 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4147 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4148 fsp->fnum, (int)numtowrite, (int)nwritten));
4150 status = sync_file(conn, fsp, write_through);
4151 if (!NT_STATUS_IS_OK(status)) {
4152 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4153 fsp->fsp_name, nt_errstr(status) ));
4154 reply_nterror(req, status);
4155 END_PROFILE(SMBwriteX);
4156 return;
4159 END_PROFILE(SMBwriteX);
4160 chain_reply(req);
4161 return;
4164 /****************************************************************************
4165 Reply to a lseek.
4166 ****************************************************************************/
4168 void reply_lseek(struct smb_request *req)
4170 connection_struct *conn = req->conn;
4171 SMB_OFF_T startpos;
4172 SMB_OFF_T res= -1;
4173 int mode,umode;
4174 files_struct *fsp;
4176 START_PROFILE(SMBlseek);
4178 if (req->wct < 4) {
4179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4180 END_PROFILE(SMBlseek);
4181 return;
4184 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4186 if (!check_fsp(conn, req, fsp)) {
4187 return;
4190 flush_write_cache(fsp, SEEK_FLUSH);
4192 mode = SVAL(req->vwv+1, 0) & 3;
4193 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4194 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4196 switch (mode) {
4197 case 0:
4198 umode = SEEK_SET;
4199 res = startpos;
4200 break;
4201 case 1:
4202 umode = SEEK_CUR;
4203 res = fsp->fh->pos + startpos;
4204 break;
4205 case 2:
4206 umode = SEEK_END;
4207 break;
4208 default:
4209 umode = SEEK_SET;
4210 res = startpos;
4211 break;
4214 if (umode == SEEK_END) {
4215 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4216 if(errno == EINVAL) {
4217 SMB_OFF_T current_pos = startpos;
4218 SMB_STRUCT_STAT sbuf;
4220 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4221 reply_unixerror(req, ERRDOS,
4222 ERRnoaccess);
4223 END_PROFILE(SMBlseek);
4224 return;
4227 current_pos += sbuf.st_size;
4228 if(current_pos < 0)
4229 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4233 if(res == -1) {
4234 reply_unixerror(req, ERRDOS, ERRnoaccess);
4235 END_PROFILE(SMBlseek);
4236 return;
4240 fsp->fh->pos = res;
4242 reply_outbuf(req, 2, 0);
4243 SIVAL(req->outbuf,smb_vwv0,res);
4245 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4246 fsp->fnum, (double)startpos, (double)res, mode));
4248 END_PROFILE(SMBlseek);
4249 return;
4252 /****************************************************************************
4253 Reply to a flush.
4254 ****************************************************************************/
4256 void reply_flush(struct smb_request *req)
4258 connection_struct *conn = req->conn;
4259 uint16 fnum;
4260 files_struct *fsp;
4262 START_PROFILE(SMBflush);
4264 if (req->wct < 1) {
4265 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4266 return;
4269 fnum = SVAL(req->vwv+0, 0);
4270 fsp = file_fsp(req, fnum);
4272 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4273 return;
4276 if (!fsp) {
4277 file_sync_all(conn);
4278 } else {
4279 NTSTATUS status = sync_file(conn, fsp, True);
4280 if (!NT_STATUS_IS_OK(status)) {
4281 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4282 fsp->fsp_name, nt_errstr(status) ));
4283 reply_nterror(req, status);
4284 END_PROFILE(SMBflush);
4285 return;
4289 reply_outbuf(req, 0, 0);
4291 DEBUG(3,("flush\n"));
4292 END_PROFILE(SMBflush);
4293 return;
4296 /****************************************************************************
4297 Reply to a exit.
4298 conn POINTER CAN BE NULL HERE !
4299 ****************************************************************************/
4301 void reply_exit(struct smb_request *req)
4303 START_PROFILE(SMBexit);
4305 file_close_pid(req->smbpid, req->vuid);
4307 reply_outbuf(req, 0, 0);
4309 DEBUG(3,("exit\n"));
4311 END_PROFILE(SMBexit);
4312 return;
4315 /****************************************************************************
4316 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4317 ****************************************************************************/
4319 void reply_close(struct smb_request *req)
4321 connection_struct *conn = req->conn;
4322 NTSTATUS status = NT_STATUS_OK;
4323 files_struct *fsp = NULL;
4324 START_PROFILE(SMBclose);
4326 if (req->wct < 3) {
4327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4328 END_PROFILE(SMBclose);
4329 return;
4332 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4335 * We can only use check_fsp if we know it's not a directory.
4338 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4339 reply_doserror(req, ERRDOS, ERRbadfid);
4340 END_PROFILE(SMBclose);
4341 return;
4344 if(fsp->is_directory) {
4346 * Special case - close NT SMB directory handle.
4348 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4349 status = close_file(req, fsp, NORMAL_CLOSE);
4350 } else {
4351 time_t t;
4353 * Close ordinary file.
4356 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4357 fsp->fh->fd, fsp->fnum,
4358 conn->num_files_open));
4361 * Take care of any time sent in the close.
4364 t = srv_make_unix_date3(req->vwv+1);
4365 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4368 * close_file() returns the unix errno if an error
4369 * was detected on close - normally this is due to
4370 * a disk full error. If not then it was probably an I/O error.
4373 status = close_file(req, fsp, NORMAL_CLOSE);
4376 if (!NT_STATUS_IS_OK(status)) {
4377 reply_nterror(req, status);
4378 END_PROFILE(SMBclose);
4379 return;
4382 reply_outbuf(req, 0, 0);
4383 END_PROFILE(SMBclose);
4384 return;
4387 /****************************************************************************
4388 Reply to a writeclose (Core+ protocol).
4389 ****************************************************************************/
4391 void reply_writeclose(struct smb_request *req)
4393 connection_struct *conn = req->conn;
4394 size_t numtowrite;
4395 ssize_t nwritten = -1;
4396 NTSTATUS close_status = NT_STATUS_OK;
4397 SMB_OFF_T startpos;
4398 const char *data;
4399 struct timespec mtime;
4400 files_struct *fsp;
4402 START_PROFILE(SMBwriteclose);
4404 if (req->wct < 6) {
4405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4406 END_PROFILE(SMBwriteclose);
4407 return;
4410 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4412 if (!check_fsp(conn, req, fsp)) {
4413 END_PROFILE(SMBwriteclose);
4414 return;
4416 if (!CHECK_WRITE(fsp)) {
4417 reply_doserror(req, ERRDOS,ERRbadaccess);
4418 END_PROFILE(SMBwriteclose);
4419 return;
4422 numtowrite = SVAL(req->vwv+1, 0);
4423 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4424 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4425 data = (const char *)req->buf + 1;
4427 if (numtowrite
4428 && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
4429 (uint64_t)startpos, WRITE_LOCK)) {
4430 reply_doserror(req, ERRDOS,ERRlock);
4431 END_PROFILE(SMBwriteclose);
4432 return;
4435 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4437 set_close_write_time(fsp, mtime);
4440 * More insanity. W2K only closes the file if writelen > 0.
4441 * JRA.
4444 if (numtowrite) {
4445 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4446 fsp->fsp_name ));
4447 close_status = close_file(req, fsp, NORMAL_CLOSE);
4450 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4451 fsp->fnum, (int)numtowrite, (int)nwritten,
4452 conn->num_files_open));
4454 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4455 reply_doserror(req, ERRHRD, ERRdiskfull);
4456 END_PROFILE(SMBwriteclose);
4457 return;
4460 if(!NT_STATUS_IS_OK(close_status)) {
4461 reply_nterror(req, close_status);
4462 END_PROFILE(SMBwriteclose);
4463 return;
4466 reply_outbuf(req, 1, 0);
4468 SSVAL(req->outbuf,smb_vwv0,nwritten);
4469 END_PROFILE(SMBwriteclose);
4470 return;
4473 #undef DBGC_CLASS
4474 #define DBGC_CLASS DBGC_LOCKING
4476 /****************************************************************************
4477 Reply to a lock.
4478 ****************************************************************************/
4480 void reply_lock(struct smb_request *req)
4482 connection_struct *conn = req->conn;
4483 uint64_t count,offset;
4484 NTSTATUS status;
4485 files_struct *fsp;
4486 struct byte_range_lock *br_lck = NULL;
4488 START_PROFILE(SMBlock);
4490 if (req->wct < 5) {
4491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4492 END_PROFILE(SMBlock);
4493 return;
4496 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4498 if (!check_fsp(conn, req, fsp)) {
4499 END_PROFILE(SMBlock);
4500 return;
4503 count = (uint64_t)IVAL(req->vwv+1, 0);
4504 offset = (uint64_t)IVAL(req->vwv+3, 0);
4506 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4507 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4509 br_lck = do_lock(smbd_messaging_context(),
4510 fsp,
4511 req->smbpid,
4512 count,
4513 offset,
4514 WRITE_LOCK,
4515 WINDOWS_LOCK,
4516 False, /* Non-blocking lock. */
4517 &status,
4518 NULL,
4519 NULL);
4521 TALLOC_FREE(br_lck);
4523 if (NT_STATUS_V(status)) {
4524 reply_nterror(req, status);
4525 END_PROFILE(SMBlock);
4526 return;
4529 reply_outbuf(req, 0, 0);
4531 END_PROFILE(SMBlock);
4532 return;
4535 /****************************************************************************
4536 Reply to a unlock.
4537 ****************************************************************************/
4539 void reply_unlock(struct smb_request *req)
4541 connection_struct *conn = req->conn;
4542 uint64_t count,offset;
4543 NTSTATUS status;
4544 files_struct *fsp;
4546 START_PROFILE(SMBunlock);
4548 if (req->wct < 5) {
4549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4550 END_PROFILE(SMBunlock);
4551 return;
4554 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4556 if (!check_fsp(conn, req, fsp)) {
4557 END_PROFILE(SMBunlock);
4558 return;
4561 count = (uint64_t)IVAL(req->vwv+1, 0);
4562 offset = (uint64_t)IVAL(req->vwv+3, 0);
4564 status = do_unlock(smbd_messaging_context(),
4565 fsp,
4566 req->smbpid,
4567 count,
4568 offset,
4569 WINDOWS_LOCK);
4571 if (NT_STATUS_V(status)) {
4572 reply_nterror(req, status);
4573 END_PROFILE(SMBunlock);
4574 return;
4577 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4578 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4580 reply_outbuf(req, 0, 0);
4582 END_PROFILE(SMBunlock);
4583 return;
4586 #undef DBGC_CLASS
4587 #define DBGC_CLASS DBGC_ALL
4589 /****************************************************************************
4590 Reply to a tdis.
4591 conn POINTER CAN BE NULL HERE !
4592 ****************************************************************************/
4594 void reply_tdis(struct smb_request *req)
4596 connection_struct *conn = req->conn;
4597 START_PROFILE(SMBtdis);
4599 if (!conn) {
4600 DEBUG(4,("Invalid connection in tdis\n"));
4601 reply_doserror(req, ERRSRV, ERRinvnid);
4602 END_PROFILE(SMBtdis);
4603 return;
4606 conn->used = False;
4608 close_cnum(conn,req->vuid);
4609 req->conn = NULL;
4611 reply_outbuf(req, 0, 0);
4612 END_PROFILE(SMBtdis);
4613 return;
4616 /****************************************************************************
4617 Reply to a echo.
4618 conn POINTER CAN BE NULL HERE !
4619 ****************************************************************************/
4621 void reply_echo(struct smb_request *req)
4623 connection_struct *conn = req->conn;
4624 struct smb_perfcount_data local_pcd;
4625 struct smb_perfcount_data *cur_pcd;
4626 int smb_reverb;
4627 int seq_num;
4629 START_PROFILE(SMBecho);
4631 smb_init_perfcount_data(&local_pcd);
4633 if (req->wct < 1) {
4634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4635 END_PROFILE(SMBecho);
4636 return;
4639 smb_reverb = SVAL(req->vwv+0, 0);
4641 reply_outbuf(req, 1, req->buflen);
4643 /* copy any incoming data back out */
4644 if (req->buflen > 0) {
4645 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4648 if (smb_reverb > 100) {
4649 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4650 smb_reverb = 100;
4653 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4655 /* this makes sure we catch the request pcd */
4656 if (seq_num == smb_reverb) {
4657 cur_pcd = &req->pcd;
4658 } else {
4659 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4660 cur_pcd = &local_pcd;
4663 SSVAL(req->outbuf,smb_vwv0,seq_num);
4665 show_msg((char *)req->outbuf);
4666 if (!srv_send_smb(smbd_server_fd(),
4667 (char *)req->outbuf,
4668 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4669 cur_pcd))
4670 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4673 DEBUG(3,("echo %d times\n", smb_reverb));
4675 TALLOC_FREE(req->outbuf);
4677 END_PROFILE(SMBecho);
4678 return;
4681 /****************************************************************************
4682 Reply to a printopen.
4683 ****************************************************************************/
4685 void reply_printopen(struct smb_request *req)
4687 connection_struct *conn = req->conn;
4688 files_struct *fsp;
4689 SMB_STRUCT_STAT sbuf;
4690 NTSTATUS status;
4692 START_PROFILE(SMBsplopen);
4694 if (req->wct < 2) {
4695 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4696 END_PROFILE(SMBsplopen);
4697 return;
4700 if (!CAN_PRINT(conn)) {
4701 reply_doserror(req, ERRDOS, ERRnoaccess);
4702 END_PROFILE(SMBsplopen);
4703 return;
4706 status = file_new(req, conn, &fsp);
4707 if(!NT_STATUS_IS_OK(status)) {
4708 reply_nterror(req, status);
4709 END_PROFILE(SMBsplopen);
4710 return;
4713 /* Open for exclusive use, write only. */
4714 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4716 if (!NT_STATUS_IS_OK(status)) {
4717 reply_nterror(req, status);
4718 END_PROFILE(SMBsplopen);
4719 return;
4722 reply_outbuf(req, 1, 0);
4723 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4725 DEBUG(3,("openprint fd=%d fnum=%d\n",
4726 fsp->fh->fd, fsp->fnum));
4728 END_PROFILE(SMBsplopen);
4729 return;
4732 /****************************************************************************
4733 Reply to a printclose.
4734 ****************************************************************************/
4736 void reply_printclose(struct smb_request *req)
4738 connection_struct *conn = req->conn;
4739 files_struct *fsp;
4740 NTSTATUS status;
4742 START_PROFILE(SMBsplclose);
4744 if (req->wct < 1) {
4745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4746 END_PROFILE(SMBsplclose);
4747 return;
4750 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4752 if (!check_fsp(conn, req, fsp)) {
4753 END_PROFILE(SMBsplclose);
4754 return;
4757 if (!CAN_PRINT(conn)) {
4758 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4759 END_PROFILE(SMBsplclose);
4760 return;
4763 DEBUG(3,("printclose fd=%d fnum=%d\n",
4764 fsp->fh->fd,fsp->fnum));
4766 status = close_file(req, fsp, NORMAL_CLOSE);
4768 if(!NT_STATUS_IS_OK(status)) {
4769 reply_nterror(req, status);
4770 END_PROFILE(SMBsplclose);
4771 return;
4774 reply_outbuf(req, 0, 0);
4776 END_PROFILE(SMBsplclose);
4777 return;
4780 /****************************************************************************
4781 Reply to a printqueue.
4782 ****************************************************************************/
4784 void reply_printqueue(struct smb_request *req)
4786 connection_struct *conn = req->conn;
4787 int max_count;
4788 int start_index;
4790 START_PROFILE(SMBsplretq);
4792 if (req->wct < 2) {
4793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4794 END_PROFILE(SMBsplretq);
4795 return;
4798 max_count = SVAL(req->vwv+0, 0);
4799 start_index = SVAL(req->vwv+1, 0);
4801 /* we used to allow the client to get the cnum wrong, but that
4802 is really quite gross and only worked when there was only
4803 one printer - I think we should now only accept it if they
4804 get it right (tridge) */
4805 if (!CAN_PRINT(conn)) {
4806 reply_doserror(req, ERRDOS, ERRnoaccess);
4807 END_PROFILE(SMBsplretq);
4808 return;
4811 reply_outbuf(req, 2, 3);
4812 SSVAL(req->outbuf,smb_vwv0,0);
4813 SSVAL(req->outbuf,smb_vwv1,0);
4814 SCVAL(smb_buf(req->outbuf),0,1);
4815 SSVAL(smb_buf(req->outbuf),1,0);
4817 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4818 start_index, max_count));
4821 print_queue_struct *queue = NULL;
4822 print_status_struct status;
4823 int count = print_queue_status(SNUM(conn), &queue, &status);
4824 int num_to_get = ABS(max_count);
4825 int first = (max_count>0?start_index:start_index+max_count+1);
4826 int i;
4828 if (first >= count)
4829 num_to_get = 0;
4830 else
4831 num_to_get = MIN(num_to_get,count-first);
4834 for (i=first;i<first+num_to_get;i++) {
4835 char blob[28];
4836 char *p = blob;
4838 srv_put_dos_date2(p,0,queue[i].time);
4839 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4840 SSVAL(p,5, queue[i].job);
4841 SIVAL(p,7,queue[i].size);
4842 SCVAL(p,11,0);
4843 srvstr_push(blob, req->flags2, p+12,
4844 queue[i].fs_user, 16, STR_ASCII);
4846 if (message_push_blob(
4847 &req->outbuf,
4848 data_blob_const(
4849 blob, sizeof(blob))) == -1) {
4850 reply_nterror(req, NT_STATUS_NO_MEMORY);
4851 END_PROFILE(SMBsplretq);
4852 return;
4856 if (count > 0) {
4857 SSVAL(req->outbuf,smb_vwv0,count);
4858 SSVAL(req->outbuf,smb_vwv1,
4859 (max_count>0?first+count:first-1));
4860 SCVAL(smb_buf(req->outbuf),0,1);
4861 SSVAL(smb_buf(req->outbuf),1,28*count);
4864 SAFE_FREE(queue);
4866 DEBUG(3,("%d entries returned in queue\n",count));
4869 END_PROFILE(SMBsplretq);
4870 return;
4873 /****************************************************************************
4874 Reply to a printwrite.
4875 ****************************************************************************/
4877 void reply_printwrite(struct smb_request *req)
4879 connection_struct *conn = req->conn;
4880 int numtowrite;
4881 const char *data;
4882 files_struct *fsp;
4884 START_PROFILE(SMBsplwr);
4886 if (req->wct < 1) {
4887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4888 END_PROFILE(SMBsplwr);
4889 return;
4892 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4894 if (!check_fsp(conn, req, fsp)) {
4895 END_PROFILE(SMBsplwr);
4896 return;
4899 if (!CAN_PRINT(conn)) {
4900 reply_doserror(req, ERRDOS, ERRnoaccess);
4901 END_PROFILE(SMBsplwr);
4902 return;
4905 if (!CHECK_WRITE(fsp)) {
4906 reply_doserror(req, ERRDOS, ERRbadaccess);
4907 END_PROFILE(SMBsplwr);
4908 return;
4911 numtowrite = SVAL(req->buf, 1);
4913 if (req->buflen < numtowrite + 3) {
4914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4915 END_PROFILE(SMBsplwr);
4916 return;
4919 data = (const char *)req->buf + 3;
4921 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4922 reply_unixerror(req, ERRHRD, ERRdiskfull);
4923 END_PROFILE(SMBsplwr);
4924 return;
4927 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4929 END_PROFILE(SMBsplwr);
4930 return;
4933 /****************************************************************************
4934 Reply to a mkdir.
4935 ****************************************************************************/
4937 void reply_mkdir(struct smb_request *req)
4939 connection_struct *conn = req->conn;
4940 char *directory = NULL;
4941 NTSTATUS status;
4942 SMB_STRUCT_STAT sbuf;
4943 TALLOC_CTX *ctx = talloc_tos();
4945 START_PROFILE(SMBmkdir);
4947 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
4948 STR_TERMINATE, &status);
4949 if (!NT_STATUS_IS_OK(status)) {
4950 reply_nterror(req, status);
4951 END_PROFILE(SMBmkdir);
4952 return;
4955 status = resolve_dfspath(ctx, conn,
4956 req->flags2 & FLAGS2_DFS_PATHNAMES,
4957 directory,
4958 &directory);
4959 if (!NT_STATUS_IS_OK(status)) {
4960 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4961 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4962 ERRSRV, ERRbadpath);
4963 END_PROFILE(SMBmkdir);
4964 return;
4966 reply_nterror(req, status);
4967 END_PROFILE(SMBmkdir);
4968 return;
4971 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4972 if (!NT_STATUS_IS_OK(status)) {
4973 reply_nterror(req, status);
4974 END_PROFILE(SMBmkdir);
4975 return;
4978 status = check_name(conn, directory);
4979 if (!NT_STATUS_IS_OK(status)) {
4980 reply_nterror(req, status);
4981 END_PROFILE(SMBmkdir);
4982 return;
4985 status = create_directory(conn, req, directory);
4987 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4989 if (!NT_STATUS_IS_OK(status)) {
4991 if (!use_nt_status()
4992 && NT_STATUS_EQUAL(status,
4993 NT_STATUS_OBJECT_NAME_COLLISION)) {
4995 * Yes, in the DOS error code case we get a
4996 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4997 * samba4 torture test.
4999 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5002 reply_nterror(req, status);
5003 END_PROFILE(SMBmkdir);
5004 return;
5007 reply_outbuf(req, 0, 0);
5009 DEBUG( 3, ( "mkdir %s\n", directory ) );
5011 END_PROFILE(SMBmkdir);
5012 return;
5015 /****************************************************************************
5016 Static function used by reply_rmdir to delete an entire directory
5017 tree recursively. Return True on ok, False on fail.
5018 ****************************************************************************/
5020 static bool recursive_rmdir(TALLOC_CTX *ctx,
5021 connection_struct *conn,
5022 char *directory)
5024 const char *dname = NULL;
5025 bool ret = True;
5026 long offset = 0;
5027 SMB_STRUCT_STAT st;
5028 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5029 NULL, 0);
5031 if(dir_hnd == NULL)
5032 return False;
5034 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5035 char *fullname = NULL;
5037 if (ISDOT(dname) || ISDOTDOT(dname)) {
5038 continue;
5041 if (!is_visible_file(conn, directory, dname, &st, False)) {
5042 continue;
5045 /* Construct the full name. */
5046 fullname = talloc_asprintf(ctx,
5047 "%s/%s",
5048 directory,
5049 dname);
5050 if (!fullname) {
5051 errno = ENOMEM;
5052 ret = False;
5053 break;
5056 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5057 ret = False;
5058 break;
5061 if(st.st_mode & S_IFDIR) {
5062 if(!recursive_rmdir(ctx, conn, fullname)) {
5063 ret = False;
5064 break;
5066 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5067 ret = False;
5068 break;
5070 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5071 ret = False;
5072 break;
5074 TALLOC_FREE(fullname);
5076 TALLOC_FREE(dir_hnd);
5077 return ret;
5080 /****************************************************************************
5081 The internals of the rmdir code - called elsewhere.
5082 ****************************************************************************/
5084 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5085 connection_struct *conn,
5086 const char *directory)
5088 int ret;
5089 SMB_STRUCT_STAT st;
5091 /* Might be a symlink. */
5092 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5093 return map_nt_error_from_unix(errno);
5096 if (S_ISLNK(st.st_mode)) {
5097 /* Is what it points to a directory ? */
5098 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5099 return map_nt_error_from_unix(errno);
5101 if (!(S_ISDIR(st.st_mode))) {
5102 return NT_STATUS_NOT_A_DIRECTORY;
5104 ret = SMB_VFS_UNLINK(conn,directory);
5105 } else {
5106 ret = SMB_VFS_RMDIR(conn,directory);
5108 if (ret == 0) {
5109 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5110 FILE_NOTIFY_CHANGE_DIR_NAME,
5111 directory);
5112 return NT_STATUS_OK;
5115 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5117 * Check to see if the only thing in this directory are
5118 * vetoed files/directories. If so then delete them and
5119 * retry. If we fail to delete any of them (and we *don't*
5120 * do a recursive delete) then fail the rmdir.
5122 const char *dname;
5123 long dirpos = 0;
5124 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5125 directory, NULL, 0);
5127 if(dir_hnd == NULL) {
5128 errno = ENOTEMPTY;
5129 goto err;
5132 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5133 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5134 continue;
5135 if (!is_visible_file(conn, directory, dname, &st, False))
5136 continue;
5137 if(!IS_VETO_PATH(conn, dname)) {
5138 TALLOC_FREE(dir_hnd);
5139 errno = ENOTEMPTY;
5140 goto err;
5144 /* We only have veto files/directories.
5145 * Are we allowed to delete them ? */
5147 if(!lp_recursive_veto_delete(SNUM(conn))) {
5148 TALLOC_FREE(dir_hnd);
5149 errno = ENOTEMPTY;
5150 goto err;
5153 /* Do a recursive delete. */
5154 RewindDir(dir_hnd,&dirpos);
5155 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5156 char *fullname = NULL;
5158 if (ISDOT(dname) || ISDOTDOT(dname)) {
5159 continue;
5161 if (!is_visible_file(conn, directory, dname, &st, False)) {
5162 continue;
5165 fullname = talloc_asprintf(ctx,
5166 "%s/%s",
5167 directory,
5168 dname);
5170 if(!fullname) {
5171 errno = ENOMEM;
5172 break;
5175 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5176 break;
5178 if(st.st_mode & S_IFDIR) {
5179 if(!recursive_rmdir(ctx, conn, fullname)) {
5180 break;
5182 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5183 break;
5185 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5186 break;
5188 TALLOC_FREE(fullname);
5190 TALLOC_FREE(dir_hnd);
5191 /* Retry the rmdir */
5192 ret = SMB_VFS_RMDIR(conn,directory);
5195 err:
5197 if (ret != 0) {
5198 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5199 "%s\n", directory,strerror(errno)));
5200 return map_nt_error_from_unix(errno);
5203 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5204 FILE_NOTIFY_CHANGE_DIR_NAME,
5205 directory);
5207 return NT_STATUS_OK;
5210 /****************************************************************************
5211 Reply to a rmdir.
5212 ****************************************************************************/
5214 void reply_rmdir(struct smb_request *req)
5216 connection_struct *conn = req->conn;
5217 char *directory = NULL;
5218 SMB_STRUCT_STAT sbuf;
5219 NTSTATUS status;
5220 TALLOC_CTX *ctx = talloc_tos();
5222 START_PROFILE(SMBrmdir);
5224 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5225 STR_TERMINATE, &status);
5226 if (!NT_STATUS_IS_OK(status)) {
5227 reply_nterror(req, status);
5228 END_PROFILE(SMBrmdir);
5229 return;
5232 status = resolve_dfspath(ctx, conn,
5233 req->flags2 & FLAGS2_DFS_PATHNAMES,
5234 directory,
5235 &directory);
5236 if (!NT_STATUS_IS_OK(status)) {
5237 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5238 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5239 ERRSRV, ERRbadpath);
5240 END_PROFILE(SMBrmdir);
5241 return;
5243 reply_nterror(req, status);
5244 END_PROFILE(SMBrmdir);
5245 return;
5248 status = unix_convert(ctx, conn, directory, False, &directory,
5249 NULL, &sbuf);
5250 if (!NT_STATUS_IS_OK(status)) {
5251 reply_nterror(req, status);
5252 END_PROFILE(SMBrmdir);
5253 return;
5256 status = check_name(conn, directory);
5257 if (!NT_STATUS_IS_OK(status)) {
5258 reply_nterror(req, status);
5259 END_PROFILE(SMBrmdir);
5260 return;
5263 dptr_closepath(directory, req->smbpid);
5264 status = rmdir_internals(ctx, conn, directory);
5265 if (!NT_STATUS_IS_OK(status)) {
5266 reply_nterror(req, status);
5267 END_PROFILE(SMBrmdir);
5268 return;
5271 reply_outbuf(req, 0, 0);
5273 DEBUG( 3, ( "rmdir %s\n", directory ) );
5275 END_PROFILE(SMBrmdir);
5276 return;
5279 /*******************************************************************
5280 Resolve wildcards in a filename rename.
5281 ********************************************************************/
5283 static bool resolve_wildcards(TALLOC_CTX *ctx,
5284 const char *name1,
5285 const char *name2,
5286 char **pp_newname)
5288 char *name2_copy = NULL;
5289 char *root1 = NULL;
5290 char *root2 = NULL;
5291 char *ext1 = NULL;
5292 char *ext2 = NULL;
5293 char *p,*p2, *pname1, *pname2;
5295 name2_copy = talloc_strdup(ctx, name2);
5296 if (!name2_copy) {
5297 return False;
5300 pname1 = strrchr_m(name1,'/');
5301 pname2 = strrchr_m(name2_copy,'/');
5303 if (!pname1 || !pname2) {
5304 return False;
5307 /* Truncate the copy of name2 at the last '/' */
5308 *pname2 = '\0';
5310 /* Now go past the '/' */
5311 pname1++;
5312 pname2++;
5314 root1 = talloc_strdup(ctx, pname1);
5315 root2 = talloc_strdup(ctx, pname2);
5317 if (!root1 || !root2) {
5318 return False;
5321 p = strrchr_m(root1,'.');
5322 if (p) {
5323 *p = 0;
5324 ext1 = talloc_strdup(ctx, p+1);
5325 } else {
5326 ext1 = talloc_strdup(ctx, "");
5328 p = strrchr_m(root2,'.');
5329 if (p) {
5330 *p = 0;
5331 ext2 = talloc_strdup(ctx, p+1);
5332 } else {
5333 ext2 = talloc_strdup(ctx, "");
5336 if (!ext1 || !ext2) {
5337 return False;
5340 p = root1;
5341 p2 = root2;
5342 while (*p2) {
5343 if (*p2 == '?') {
5344 /* Hmmm. Should this be mb-aware ? */
5345 *p2 = *p;
5346 p2++;
5347 } else if (*p2 == '*') {
5348 *p2 = '\0';
5349 root2 = talloc_asprintf(ctx, "%s%s",
5350 root2,
5352 if (!root2) {
5353 return False;
5355 break;
5356 } else {
5357 p2++;
5359 if (*p) {
5360 p++;
5364 p = ext1;
5365 p2 = ext2;
5366 while (*p2) {
5367 if (*p2 == '?') {
5368 /* Hmmm. Should this be mb-aware ? */
5369 *p2 = *p;
5370 p2++;
5371 } else if (*p2 == '*') {
5372 *p2 = '\0';
5373 ext2 = talloc_asprintf(ctx, "%s%s",
5374 ext2,
5376 if (!ext2) {
5377 return False;
5379 break;
5380 } else {
5381 p2++;
5383 if (*p) {
5384 p++;
5388 if (*ext2) {
5389 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5390 name2_copy,
5391 root2,
5392 ext2);
5393 } else {
5394 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5395 name2_copy,
5396 root2);
5399 if (!*pp_newname) {
5400 return False;
5403 return True;
5406 /****************************************************************************
5407 Ensure open files have their names updated. Updated to notify other smbd's
5408 asynchronously.
5409 ****************************************************************************/
5411 static void rename_open_files(connection_struct *conn,
5412 struct share_mode_lock *lck,
5413 const char *newname)
5415 files_struct *fsp;
5416 bool did_rename = False;
5418 for(fsp = file_find_di_first(lck->id); fsp;
5419 fsp = file_find_di_next(fsp)) {
5420 /* fsp_name is a relative path under the fsp. To change this for other
5421 sharepaths we need to manipulate relative paths. */
5422 /* TODO - create the absolute path and manipulate the newname
5423 relative to the sharepath. */
5424 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5425 continue;
5427 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5428 fsp->fnum, file_id_string_tos(&fsp->file_id),
5429 fsp->fsp_name, newname ));
5430 string_set(&fsp->fsp_name, newname);
5431 did_rename = True;
5434 if (!did_rename) {
5435 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5436 file_id_string_tos(&lck->id), newname ));
5439 /* Send messages to all smbd's (not ourself) that the name has changed. */
5440 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5441 newname);
5444 /****************************************************************************
5445 We need to check if the source path is a parent directory of the destination
5446 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5447 refuse the rename with a sharing violation. Under UNIX the above call can
5448 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5449 probably need to check that the client is a Windows one before disallowing
5450 this as a UNIX client (one with UNIX extensions) can know the source is a
5451 symlink and make this decision intelligently. Found by an excellent bug
5452 report from <AndyLiebman@aol.com>.
5453 ****************************************************************************/
5455 static bool rename_path_prefix_equal(const char *src, const char *dest)
5457 const char *psrc = src;
5458 const char *pdst = dest;
5459 size_t slen;
5461 if (psrc[0] == '.' && psrc[1] == '/') {
5462 psrc += 2;
5464 if (pdst[0] == '.' && pdst[1] == '/') {
5465 pdst += 2;
5467 if ((slen = strlen(psrc)) > strlen(pdst)) {
5468 return False;
5470 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5474 * Do the notify calls from a rename
5477 static void notify_rename(connection_struct *conn, bool is_dir,
5478 const char *oldpath, const char *newpath)
5480 char *olddir, *newdir;
5481 const char *oldname, *newname;
5482 uint32 mask;
5484 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5485 : FILE_NOTIFY_CHANGE_FILE_NAME;
5487 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5488 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5489 TALLOC_FREE(olddir);
5490 return;
5493 if (strcmp(olddir, newdir) == 0) {
5494 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5495 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5497 else {
5498 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5499 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5501 TALLOC_FREE(olddir);
5502 TALLOC_FREE(newdir);
5504 /* this is a strange one. w2k3 gives an additional event for
5505 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5506 files, but not directories */
5507 if (!is_dir) {
5508 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5509 FILE_NOTIFY_CHANGE_ATTRIBUTES
5510 |FILE_NOTIFY_CHANGE_CREATION,
5511 newpath);
5515 /****************************************************************************
5516 Rename an open file - given an fsp.
5517 ****************************************************************************/
5519 NTSTATUS rename_internals_fsp(connection_struct *conn,
5520 files_struct *fsp,
5521 char *newname,
5522 const char *newname_last_component,
5523 uint32 attrs,
5524 bool replace_if_exists)
5526 TALLOC_CTX *ctx = talloc_tos();
5527 SMB_STRUCT_STAT sbuf, sbuf1;
5528 NTSTATUS status = NT_STATUS_OK;
5529 struct share_mode_lock *lck = NULL;
5530 bool dst_exists, old_is_stream, new_is_stream;
5532 ZERO_STRUCT(sbuf);
5534 status = check_name(conn, newname);
5535 if (!NT_STATUS_IS_OK(status)) {
5536 return status;
5539 /* Ensure newname contains a '/' */
5540 if(strrchr_m(newname,'/') == 0) {
5541 newname = talloc_asprintf(ctx,
5542 "./%s",
5543 newname);
5544 if (!newname) {
5545 return NT_STATUS_NO_MEMORY;
5550 * Check for special case with case preserving and not
5551 * case sensitive. If the old last component differs from the original
5552 * last component only by case, then we should allow
5553 * the rename (user is trying to change the case of the
5554 * filename).
5557 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5558 strequal(newname, fsp->fsp_name)) {
5559 char *p;
5560 char *newname_modified_last_component = NULL;
5563 * Get the last component of the modified name.
5564 * Note that we guarantee that newname contains a '/'
5565 * character above.
5567 p = strrchr_m(newname,'/');
5568 newname_modified_last_component = talloc_strdup(ctx,
5569 p+1);
5570 if (!newname_modified_last_component) {
5571 return NT_STATUS_NO_MEMORY;
5574 if(strcsequal(newname_modified_last_component,
5575 newname_last_component) == False) {
5577 * Replace the modified last component with
5578 * the original.
5580 *p = '\0'; /* Truncate at the '/' */
5581 newname = talloc_asprintf(ctx,
5582 "%s/%s",
5583 newname,
5584 newname_last_component);
5589 * If the src and dest names are identical - including case,
5590 * don't do the rename, just return success.
5593 if (strcsequal(fsp->fsp_name, newname)) {
5594 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5595 newname));
5596 return NT_STATUS_OK;
5599 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5600 new_is_stream = is_ntfs_stream_name(newname);
5602 /* Return the correct error code if both names aren't streams. */
5603 if (!old_is_stream && new_is_stream) {
5604 return NT_STATUS_OBJECT_NAME_INVALID;
5607 if (old_is_stream && !new_is_stream) {
5608 return NT_STATUS_INVALID_PARAMETER;
5612 * Have vfs_object_exist also fill sbuf1
5614 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5616 if(!replace_if_exists && dst_exists) {
5617 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5618 fsp->fsp_name,newname));
5619 return NT_STATUS_OBJECT_NAME_COLLISION;
5622 if (dst_exists) {
5623 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5624 files_struct *dst_fsp = file_find_di_first(fileid);
5625 /* The file can be open when renaming a stream */
5626 if (dst_fsp && !new_is_stream) {
5627 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5628 return NT_STATUS_ACCESS_DENIED;
5632 /* Ensure we have a valid stat struct for the source. */
5633 if (fsp->fh->fd != -1) {
5634 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5635 return map_nt_error_from_unix(errno);
5637 } else {
5638 int ret = -1;
5639 if (fsp->posix_open) {
5640 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5641 } else {
5642 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5644 if (ret == -1) {
5645 return map_nt_error_from_unix(errno);
5649 status = can_rename(conn, fsp, attrs, &sbuf);
5651 if (!NT_STATUS_IS_OK(status)) {
5652 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5653 nt_errstr(status), fsp->fsp_name,newname));
5654 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5655 status = NT_STATUS_ACCESS_DENIED;
5656 return status;
5659 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5660 return NT_STATUS_ACCESS_DENIED;
5663 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5664 NULL);
5667 * We have the file open ourselves, so not being able to get the
5668 * corresponding share mode lock is a fatal error.
5671 SMB_ASSERT(lck != NULL);
5673 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5674 uint32 create_options = fsp->fh->private_options;
5676 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5677 fsp->fsp_name,newname));
5679 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5681 rename_open_files(conn, lck, newname);
5684 * A rename acts as a new file create w.r.t. allowing an initial delete
5685 * on close, probably because in Windows there is a new handle to the
5686 * new file. If initial delete on close was requested but not
5687 * originally set, we need to set it here. This is probably not 100% correct,
5688 * but will work for the CIFSFS client which in non-posix mode
5689 * depends on these semantics. JRA.
5692 if (create_options & FILE_DELETE_ON_CLOSE) {
5693 status = can_set_delete_on_close(fsp, True, 0);
5695 if (NT_STATUS_IS_OK(status)) {
5696 /* Note that here we set the *inital* delete on close flag,
5697 * not the regular one. The magic gets handled in close. */
5698 fsp->initial_delete_on_close = True;
5701 TALLOC_FREE(lck);
5702 return NT_STATUS_OK;
5705 TALLOC_FREE(lck);
5707 if (errno == ENOTDIR || errno == EISDIR) {
5708 status = NT_STATUS_OBJECT_NAME_COLLISION;
5709 } else {
5710 status = map_nt_error_from_unix(errno);
5713 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5714 nt_errstr(status), fsp->fsp_name,newname));
5716 return status;
5719 /****************************************************************************
5720 The guts of the rename command, split out so it may be called by the NT SMB
5721 code.
5722 ****************************************************************************/
5724 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5725 connection_struct *conn,
5726 struct smb_request *req,
5727 const char *name_in,
5728 const char *newname_in,
5729 uint32 attrs,
5730 bool replace_if_exists,
5731 bool src_has_wild,
5732 bool dest_has_wild,
5733 uint32_t access_mask)
5735 char *directory = NULL;
5736 char *mask = NULL;
5737 char *last_component_src = NULL;
5738 char *last_component_dest = NULL;
5739 char *name = NULL;
5740 char *newname = NULL;
5741 char *p;
5742 int count=0;
5743 NTSTATUS status = NT_STATUS_OK;
5744 SMB_STRUCT_STAT sbuf1, sbuf2;
5745 struct smb_Dir *dir_hnd = NULL;
5746 const char *dname;
5747 long offset = 0;
5748 int create_options = 0;
5749 bool posix_pathnames = lp_posix_pathnames();
5751 ZERO_STRUCT(sbuf1);
5752 ZERO_STRUCT(sbuf2);
5754 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5755 &last_component_src, &sbuf1);
5756 if (!NT_STATUS_IS_OK(status)) {
5757 return status;
5760 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5761 &last_component_dest, &sbuf2);
5762 if (!NT_STATUS_IS_OK(status)) {
5763 return status;
5767 * Split the old name into directory and last component
5768 * strings. Note that unix_convert may have stripped off a
5769 * leading ./ from both name and newname if the rename is
5770 * at the root of the share. We need to make sure either both
5771 * name and newname contain a / character or neither of them do
5772 * as this is checked in resolve_wildcards().
5775 p = strrchr_m(name,'/');
5776 if (!p) {
5777 directory = talloc_strdup(ctx, ".");
5778 if (!directory) {
5779 return NT_STATUS_NO_MEMORY;
5781 mask = name;
5782 } else {
5783 *p = 0;
5784 directory = talloc_strdup(ctx, name);
5785 if (!directory) {
5786 return NT_STATUS_NO_MEMORY;
5788 mask = p+1;
5789 *p = '/'; /* Replace needed for exceptional test below. */
5793 * We should only check the mangled cache
5794 * here if unix_convert failed. This means
5795 * that the path in 'mask' doesn't exist
5796 * on the file system and so we need to look
5797 * for a possible mangle. This patch from
5798 * Tine Smukavec <valentin.smukavec@hermes.si>.
5801 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5802 char *new_mask = NULL;
5803 mangle_lookup_name_from_8_3(ctx,
5804 mask,
5805 &new_mask,
5806 conn->params );
5807 if (new_mask) {
5808 mask = new_mask;
5812 if (!src_has_wild) {
5813 files_struct *fsp;
5816 * No wildcards - just process the one file.
5818 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5820 /* Add a terminating '/' to the directory name. */
5821 directory = talloc_asprintf_append(directory,
5822 "/%s",
5823 mask);
5824 if (!directory) {
5825 return NT_STATUS_NO_MEMORY;
5828 /* Ensure newname contains a '/' also */
5829 if(strrchr_m(newname,'/') == 0) {
5830 newname = talloc_asprintf(ctx,
5831 "./%s",
5832 newname);
5833 if (!newname) {
5834 return NT_STATUS_NO_MEMORY;
5838 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5839 "case_preserve = %d, short case preserve = %d, "
5840 "directory = %s, newname = %s, "
5841 "last_component_dest = %s, is_8_3 = %d\n",
5842 conn->case_sensitive, conn->case_preserve,
5843 conn->short_case_preserve, directory,
5844 newname, last_component_dest, is_short_name));
5846 /* The dest name still may have wildcards. */
5847 if (dest_has_wild) {
5848 char *mod_newname = NULL;
5849 if (!resolve_wildcards(ctx,
5850 directory,newname,&mod_newname)) {
5851 DEBUG(6, ("rename_internals: resolve_wildcards "
5852 "%s %s failed\n",
5853 directory,
5854 newname));
5855 return NT_STATUS_NO_MEMORY;
5857 newname = mod_newname;
5860 ZERO_STRUCT(sbuf1);
5861 if (posix_pathnames) {
5862 SMB_VFS_LSTAT(conn, directory, &sbuf1);
5863 } else {
5864 SMB_VFS_STAT(conn, directory, &sbuf1);
5867 if (S_ISDIR(sbuf1.st_mode)) {
5868 create_options |= FILE_DIRECTORY_FILE;
5871 status = SMB_VFS_CREATE_FILE(
5872 conn, /* conn */
5873 req, /* req */
5874 0, /* root_dir_fid */
5875 directory, /* fname */
5876 0, /* create_file_flags */
5877 access_mask, /* access_mask */
5878 (FILE_SHARE_READ | /* share_access */
5879 FILE_SHARE_WRITE),
5880 FILE_OPEN, /* create_disposition*/
5881 create_options, /* create_options */
5882 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
5883 0, /* oplock_request */
5884 0, /* allocation_size */
5885 NULL, /* sd */
5886 NULL, /* ea_list */
5887 &fsp, /* result */
5888 NULL, /* pinfo */
5889 &sbuf1); /* psbuf */
5891 if (!NT_STATUS_IS_OK(status)) {
5892 DEBUG(3, ("Could not open rename source %s: %s\n",
5893 directory, nt_errstr(status)));
5894 return status;
5897 status = rename_internals_fsp(conn, fsp, newname,
5898 last_component_dest,
5899 attrs, replace_if_exists);
5901 close_file(req, fsp, NORMAL_CLOSE);
5903 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5904 nt_errstr(status), directory,newname));
5906 return status;
5910 * Wildcards - process each file that matches.
5912 if (strequal(mask,"????????.???")) {
5913 mask[0] = '*';
5914 mask[1] = '\0';
5917 status = check_name(conn, directory);
5918 if (!NT_STATUS_IS_OK(status)) {
5919 return status;
5922 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
5923 if (dir_hnd == NULL) {
5924 return map_nt_error_from_unix(errno);
5927 status = NT_STATUS_NO_SUCH_FILE;
5929 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5930 * - gentest fix. JRA
5933 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
5934 files_struct *fsp = NULL;
5935 char *fname = NULL;
5936 char *destname = NULL;
5937 bool sysdir_entry = False;
5939 /* Quick check for "." and ".." */
5940 if (ISDOT(dname) || ISDOTDOT(dname)) {
5941 if (attrs & aDIR) {
5942 sysdir_entry = True;
5943 } else {
5944 continue;
5948 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5949 continue;
5952 if(!mask_match(dname, mask, conn->case_sensitive)) {
5953 continue;
5956 if (sysdir_entry) {
5957 status = NT_STATUS_OBJECT_NAME_INVALID;
5958 break;
5961 fname = talloc_asprintf(ctx,
5962 "%s/%s",
5963 directory,
5964 dname);
5965 if (!fname) {
5966 return NT_STATUS_NO_MEMORY;
5969 if (!resolve_wildcards(ctx,
5970 fname,newname,&destname)) {
5971 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5972 fname, destname));
5973 TALLOC_FREE(fname);
5974 continue;
5976 if (!destname) {
5977 return NT_STATUS_NO_MEMORY;
5980 ZERO_STRUCT(sbuf1);
5981 if (posix_pathnames) {
5982 SMB_VFS_LSTAT(conn, fname, &sbuf1);
5983 } else {
5984 SMB_VFS_STAT(conn, fname, &sbuf1);
5987 create_options = 0;
5989 if (S_ISDIR(sbuf1.st_mode)) {
5990 create_options |= FILE_DIRECTORY_FILE;
5993 status = SMB_VFS_CREATE_FILE(
5994 conn, /* conn */
5995 req, /* req */
5996 0, /* root_dir_fid */
5997 fname, /* fname */
5998 0, /* create_file_flags */
5999 access_mask, /* access_mask */
6000 (FILE_SHARE_READ | /* share_access */
6001 FILE_SHARE_WRITE),
6002 FILE_OPEN, /* create_disposition*/
6003 create_options, /* create_options */
6004 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6005 0, /* oplock_request */
6006 0, /* allocation_size */
6007 NULL, /* sd */
6008 NULL, /* ea_list */
6009 &fsp, /* result */
6010 NULL, /* pinfo */
6011 &sbuf1); /* psbuf */
6013 if (!NT_STATUS_IS_OK(status)) {
6014 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6015 "returned %s rename %s -> %s\n",
6016 nt_errstr(status), directory, newname));
6017 break;
6020 status = rename_internals_fsp(conn, fsp, destname, dname,
6021 attrs, replace_if_exists);
6023 close_file(req, fsp, NORMAL_CLOSE);
6025 if (!NT_STATUS_IS_OK(status)) {
6026 DEBUG(3, ("rename_internals_fsp returned %s for "
6027 "rename %s -> %s\n", nt_errstr(status),
6028 directory, newname));
6029 break;
6032 count++;
6034 DEBUG(3,("rename_internals: doing rename on %s -> "
6035 "%s\n",fname,destname));
6037 TALLOC_FREE(fname);
6038 TALLOC_FREE(destname);
6040 TALLOC_FREE(dir_hnd);
6042 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6043 status = map_nt_error_from_unix(errno);
6046 return status;
6049 /****************************************************************************
6050 Reply to a mv.
6051 ****************************************************************************/
6053 void reply_mv(struct smb_request *req)
6055 connection_struct *conn = req->conn;
6056 char *name = NULL;
6057 char *newname = NULL;
6058 const char *p;
6059 uint32 attrs;
6060 NTSTATUS status;
6061 bool src_has_wcard = False;
6062 bool dest_has_wcard = False;
6063 TALLOC_CTX *ctx = talloc_tos();
6065 START_PROFILE(SMBmv);
6067 if (req->wct < 1) {
6068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6069 END_PROFILE(SMBmv);
6070 return;
6073 attrs = SVAL(req->vwv+0, 0);
6075 p = (const char *)req->buf + 1;
6076 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6077 &status, &src_has_wcard);
6078 if (!NT_STATUS_IS_OK(status)) {
6079 reply_nterror(req, status);
6080 END_PROFILE(SMBmv);
6081 return;
6083 p++;
6084 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6085 &status, &dest_has_wcard);
6086 if (!NT_STATUS_IS_OK(status)) {
6087 reply_nterror(req, status);
6088 END_PROFILE(SMBmv);
6089 return;
6092 status = resolve_dfspath_wcard(ctx, conn,
6093 req->flags2 & FLAGS2_DFS_PATHNAMES,
6094 name,
6095 &name,
6096 &src_has_wcard);
6097 if (!NT_STATUS_IS_OK(status)) {
6098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6099 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6100 ERRSRV, ERRbadpath);
6101 END_PROFILE(SMBmv);
6102 return;
6104 reply_nterror(req, status);
6105 END_PROFILE(SMBmv);
6106 return;
6109 status = resolve_dfspath_wcard(ctx, conn,
6110 req->flags2 & FLAGS2_DFS_PATHNAMES,
6111 newname,
6112 &newname,
6113 &dest_has_wcard);
6114 if (!NT_STATUS_IS_OK(status)) {
6115 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6116 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6117 ERRSRV, ERRbadpath);
6118 END_PROFILE(SMBmv);
6119 return;
6121 reply_nterror(req, status);
6122 END_PROFILE(SMBmv);
6123 return;
6126 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6128 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6129 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6130 if (!NT_STATUS_IS_OK(status)) {
6131 if (open_was_deferred(req->mid)) {
6132 /* We have re-scheduled this call. */
6133 END_PROFILE(SMBmv);
6134 return;
6136 reply_nterror(req, status);
6137 END_PROFILE(SMBmv);
6138 return;
6141 reply_outbuf(req, 0, 0);
6143 END_PROFILE(SMBmv);
6144 return;
6147 /*******************************************************************
6148 Copy a file as part of a reply_copy.
6149 ******************************************************************/
6152 * TODO: check error codes on all callers
6155 NTSTATUS copy_file(TALLOC_CTX *ctx,
6156 connection_struct *conn,
6157 const char *src,
6158 const char *dest1,
6159 int ofun,
6160 int count,
6161 bool target_is_directory)
6163 SMB_STRUCT_STAT src_sbuf, sbuf2;
6164 SMB_OFF_T ret=-1;
6165 files_struct *fsp1,*fsp2;
6166 char *dest = NULL;
6167 uint32 dosattrs;
6168 uint32 new_create_disposition;
6169 NTSTATUS status;
6171 dest = talloc_strdup(ctx, dest1);
6172 if (!dest) {
6173 return NT_STATUS_NO_MEMORY;
6175 if (target_is_directory) {
6176 const char *p = strrchr_m(src,'/');
6177 if (p) {
6178 p++;
6179 } else {
6180 p = src;
6182 dest = talloc_asprintf_append(dest,
6183 "/%s",
6185 if (!dest) {
6186 return NT_STATUS_NO_MEMORY;
6190 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6191 TALLOC_FREE(dest);
6192 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6195 if (!target_is_directory && count) {
6196 new_create_disposition = FILE_OPEN;
6197 } else {
6198 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6199 NULL, NULL, &new_create_disposition, NULL)) {
6200 TALLOC_FREE(dest);
6201 return NT_STATUS_INVALID_PARAMETER;
6205 status = SMB_VFS_CREATE_FILE(
6206 conn, /* conn */
6207 NULL, /* req */
6208 0, /* root_dir_fid */
6209 src, /* fname */
6210 0, /* create_file_flags */
6211 FILE_GENERIC_READ, /* access_mask */
6212 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6213 FILE_OPEN, /* create_disposition*/
6214 0, /* create_options */
6215 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6216 INTERNAL_OPEN_ONLY, /* oplock_request */
6217 0, /* allocation_size */
6218 NULL, /* sd */
6219 NULL, /* ea_list */
6220 &fsp1, /* result */
6221 NULL, /* pinfo */
6222 &src_sbuf); /* psbuf */
6224 if (!NT_STATUS_IS_OK(status)) {
6225 TALLOC_FREE(dest);
6226 return status;
6229 dosattrs = dos_mode(conn, src, &src_sbuf);
6230 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6231 ZERO_STRUCTP(&sbuf2);
6234 status = SMB_VFS_CREATE_FILE(
6235 conn, /* conn */
6236 NULL, /* req */
6237 0, /* root_dir_fid */
6238 dest, /* fname */
6239 0, /* create_file_flags */
6240 FILE_GENERIC_WRITE, /* access_mask */
6241 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6242 new_create_disposition, /* create_disposition*/
6243 0, /* create_options */
6244 dosattrs, /* file_attributes */
6245 INTERNAL_OPEN_ONLY, /* oplock_request */
6246 0, /* allocation_size */
6247 NULL, /* sd */
6248 NULL, /* ea_list */
6249 &fsp2, /* result */
6250 NULL, /* pinfo */
6251 &sbuf2); /* psbuf */
6253 TALLOC_FREE(dest);
6255 if (!NT_STATUS_IS_OK(status)) {
6256 close_file(NULL, fsp1, ERROR_CLOSE);
6257 return status;
6260 if ((ofun&3) == 1) {
6261 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6262 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6264 * Stop the copy from occurring.
6266 ret = -1;
6267 src_sbuf.st_size = 0;
6271 if (src_sbuf.st_size) {
6272 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6275 close_file(NULL, fsp1, NORMAL_CLOSE);
6277 /* Ensure the modtime is set correctly on the destination file. */
6278 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6281 * As we are opening fsp1 read-only we only expect
6282 * an error on close on fsp2 if we are out of space.
6283 * Thus we don't look at the error return from the
6284 * close of fsp1.
6286 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6288 if (!NT_STATUS_IS_OK(status)) {
6289 return status;
6292 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6293 return NT_STATUS_DISK_FULL;
6296 return NT_STATUS_OK;
6299 /****************************************************************************
6300 Reply to a file copy.
6301 ****************************************************************************/
6303 void reply_copy(struct smb_request *req)
6305 connection_struct *conn = req->conn;
6306 char *name = NULL;
6307 char *newname = NULL;
6308 char *directory = NULL;
6309 const char *mask = NULL;
6310 const char mask_star[] = "*";
6311 const char *p;
6312 int count=0;
6313 int error = ERRnoaccess;
6314 int err = 0;
6315 int tid2;
6316 int ofun;
6317 int flags;
6318 bool target_is_directory=False;
6319 bool source_has_wild = False;
6320 bool dest_has_wild = False;
6321 SMB_STRUCT_STAT sbuf1, sbuf2;
6322 NTSTATUS status;
6323 TALLOC_CTX *ctx = talloc_tos();
6325 START_PROFILE(SMBcopy);
6327 if (req->wct < 3) {
6328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6329 END_PROFILE(SMBcopy);
6330 return;
6333 tid2 = SVAL(req->vwv+0, 0);
6334 ofun = SVAL(req->vwv+1, 0);
6335 flags = SVAL(req->vwv+2, 0);
6337 p = (const char *)req->buf;
6338 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6339 &status, &source_has_wild);
6340 if (!NT_STATUS_IS_OK(status)) {
6341 reply_nterror(req, status);
6342 END_PROFILE(SMBcopy);
6343 return;
6345 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6346 &status, &dest_has_wild);
6347 if (!NT_STATUS_IS_OK(status)) {
6348 reply_nterror(req, status);
6349 END_PROFILE(SMBcopy);
6350 return;
6353 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6355 if (tid2 != conn->cnum) {
6356 /* can't currently handle inter share copies XXXX */
6357 DEBUG(3,("Rejecting inter-share copy\n"));
6358 reply_doserror(req, ERRSRV, ERRinvdevice);
6359 END_PROFILE(SMBcopy);
6360 return;
6363 status = resolve_dfspath_wcard(ctx, conn,
6364 req->flags2 & FLAGS2_DFS_PATHNAMES,
6365 name,
6366 &name,
6367 &source_has_wild);
6368 if (!NT_STATUS_IS_OK(status)) {
6369 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6370 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6371 ERRSRV, ERRbadpath);
6372 END_PROFILE(SMBcopy);
6373 return;
6375 reply_nterror(req, status);
6376 END_PROFILE(SMBcopy);
6377 return;
6380 status = resolve_dfspath_wcard(ctx, conn,
6381 req->flags2 & FLAGS2_DFS_PATHNAMES,
6382 newname,
6383 &newname,
6384 &dest_has_wild);
6385 if (!NT_STATUS_IS_OK(status)) {
6386 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6387 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6388 ERRSRV, ERRbadpath);
6389 END_PROFILE(SMBcopy);
6390 return;
6392 reply_nterror(req, status);
6393 END_PROFILE(SMBcopy);
6394 return;
6397 status = unix_convert(ctx, conn, name, source_has_wild,
6398 &name, NULL, &sbuf1);
6399 if (!NT_STATUS_IS_OK(status)) {
6400 reply_nterror(req, status);
6401 END_PROFILE(SMBcopy);
6402 return;
6405 status = unix_convert(ctx, conn, newname, dest_has_wild,
6406 &newname, NULL, &sbuf2);
6407 if (!NT_STATUS_IS_OK(status)) {
6408 reply_nterror(req, status);
6409 END_PROFILE(SMBcopy);
6410 return;
6413 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6415 if ((flags&1) && target_is_directory) {
6416 reply_doserror(req, ERRDOS, ERRbadfile);
6417 END_PROFILE(SMBcopy);
6418 return;
6421 if ((flags&2) && !target_is_directory) {
6422 reply_doserror(req, ERRDOS, ERRbadpath);
6423 END_PROFILE(SMBcopy);
6424 return;
6427 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6428 /* wants a tree copy! XXXX */
6429 DEBUG(3,("Rejecting tree copy\n"));
6430 reply_doserror(req, ERRSRV, ERRerror);
6431 END_PROFILE(SMBcopy);
6432 return;
6435 p = strrchr_m(name,'/');
6436 if (p != NULL) {
6437 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6438 mask = p+1;
6439 } else {
6440 directory = talloc_strdup(ctx, "./");
6441 mask = name;
6444 if (!directory) {
6445 reply_nterror(req, NT_STATUS_NO_MEMORY);
6446 END_PROFILE(SMBcopy);
6447 return;
6451 * We should only check the mangled cache
6452 * here if unix_convert failed. This means
6453 * that the path in 'mask' doesn't exist
6454 * on the file system and so we need to look
6455 * for a possible mangle. This patch from
6456 * Tine Smukavec <valentin.smukavec@hermes.si>.
6459 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6460 char *new_mask = NULL;
6461 mangle_lookup_name_from_8_3(ctx,
6462 mask,
6463 &new_mask,
6464 conn->params );
6465 if (new_mask) {
6466 mask = new_mask;
6470 if (!source_has_wild) {
6471 directory = talloc_asprintf_append(directory,
6472 "/%s",
6473 mask);
6474 if (dest_has_wild) {
6475 char *mod_newname = NULL;
6476 if (!resolve_wildcards(ctx,
6477 directory,newname,&mod_newname)) {
6478 reply_nterror(req, NT_STATUS_NO_MEMORY);
6479 END_PROFILE(SMBcopy);
6480 return;
6482 newname = mod_newname;
6485 status = check_name(conn, directory);
6486 if (!NT_STATUS_IS_OK(status)) {
6487 reply_nterror(req, status);
6488 END_PROFILE(SMBcopy);
6489 return;
6492 status = check_name(conn, newname);
6493 if (!NT_STATUS_IS_OK(status)) {
6494 reply_nterror(req, status);
6495 END_PROFILE(SMBcopy);
6496 return;
6499 status = copy_file(ctx,conn,directory,newname,ofun,
6500 count,target_is_directory);
6502 if(!NT_STATUS_IS_OK(status)) {
6503 reply_nterror(req, status);
6504 END_PROFILE(SMBcopy);
6505 return;
6506 } else {
6507 count++;
6509 } else {
6510 struct smb_Dir *dir_hnd = NULL;
6511 const char *dname = NULL;
6512 long offset = 0;
6514 if (strequal(mask,"????????.???")) {
6515 mask = mask_star;
6518 status = check_name(conn, directory);
6519 if (!NT_STATUS_IS_OK(status)) {
6520 reply_nterror(req, status);
6521 END_PROFILE(SMBcopy);
6522 return;
6525 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6526 if (dir_hnd == NULL) {
6527 status = map_nt_error_from_unix(errno);
6528 reply_nterror(req, status);
6529 END_PROFILE(SMBcopy);
6530 return;
6533 error = ERRbadfile;
6535 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6536 char *destname = NULL;
6537 char *fname = NULL;
6539 if (ISDOT(dname) || ISDOTDOT(dname)) {
6540 continue;
6543 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6544 continue;
6547 if(!mask_match(dname, mask, conn->case_sensitive)) {
6548 continue;
6551 error = ERRnoaccess;
6552 fname = talloc_asprintf(ctx,
6553 "%s/%s",
6554 directory,
6555 dname);
6556 if (!fname) {
6557 TALLOC_FREE(dir_hnd);
6558 reply_nterror(req, NT_STATUS_NO_MEMORY);
6559 END_PROFILE(SMBcopy);
6560 return;
6563 if (!resolve_wildcards(ctx,
6564 fname,newname,&destname)) {
6565 continue;
6567 if (!destname) {
6568 TALLOC_FREE(dir_hnd);
6569 reply_nterror(req, NT_STATUS_NO_MEMORY);
6570 END_PROFILE(SMBcopy);
6571 return;
6574 status = check_name(conn, fname);
6575 if (!NT_STATUS_IS_OK(status)) {
6576 TALLOC_FREE(dir_hnd);
6577 reply_nterror(req, status);
6578 END_PROFILE(SMBcopy);
6579 return;
6582 status = check_name(conn, destname);
6583 if (!NT_STATUS_IS_OK(status)) {
6584 TALLOC_FREE(dir_hnd);
6585 reply_nterror(req, status);
6586 END_PROFILE(SMBcopy);
6587 return;
6590 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6592 status = copy_file(ctx,conn,fname,destname,ofun,
6593 count,target_is_directory);
6594 if (NT_STATUS_IS_OK(status)) {
6595 count++;
6597 TALLOC_FREE(fname);
6598 TALLOC_FREE(destname);
6600 TALLOC_FREE(dir_hnd);
6603 if (count == 0) {
6604 if(err) {
6605 /* Error on close... */
6606 errno = err;
6607 reply_unixerror(req, ERRHRD, ERRgeneral);
6608 END_PROFILE(SMBcopy);
6609 return;
6612 reply_doserror(req, ERRDOS, error);
6613 END_PROFILE(SMBcopy);
6614 return;
6617 reply_outbuf(req, 1, 0);
6618 SSVAL(req->outbuf,smb_vwv0,count);
6620 END_PROFILE(SMBcopy);
6621 return;
6624 #undef DBGC_CLASS
6625 #define DBGC_CLASS DBGC_LOCKING
6627 /****************************************************************************
6628 Get a lock pid, dealing with large count requests.
6629 ****************************************************************************/
6631 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6632 bool large_file_format)
6634 if(!large_file_format)
6635 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6636 else
6637 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6640 /****************************************************************************
6641 Get a lock count, dealing with large count requests.
6642 ****************************************************************************/
6644 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6645 bool large_file_format)
6647 uint64_t count = 0;
6649 if(!large_file_format) {
6650 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6651 } else {
6653 #if defined(HAVE_LONGLONG)
6654 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6655 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6656 #else /* HAVE_LONGLONG */
6659 * NT4.x seems to be broken in that it sends large file (64 bit)
6660 * lockingX calls even if the CAP_LARGE_FILES was *not*
6661 * negotiated. For boxes without large unsigned ints truncate the
6662 * lock count by dropping the top 32 bits.
6665 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6666 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6667 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6668 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6669 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6672 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6673 #endif /* HAVE_LONGLONG */
6676 return count;
6679 #if !defined(HAVE_LONGLONG)
6680 /****************************************************************************
6681 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6682 ****************************************************************************/
6684 static uint32 map_lock_offset(uint32 high, uint32 low)
6686 unsigned int i;
6687 uint32 mask = 0;
6688 uint32 highcopy = high;
6691 * Try and find out how many significant bits there are in high.
6694 for(i = 0; highcopy; i++)
6695 highcopy >>= 1;
6698 * We use 31 bits not 32 here as POSIX
6699 * lock offsets may not be negative.
6702 mask = (~0) << (31 - i);
6704 if(low & mask)
6705 return 0; /* Fail. */
6707 high <<= (31 - i);
6709 return (high|low);
6711 #endif /* !defined(HAVE_LONGLONG) */
6713 /****************************************************************************
6714 Get a lock offset, dealing with large offset requests.
6715 ****************************************************************************/
6717 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6718 bool large_file_format, bool *err)
6720 uint64_t offset = 0;
6722 *err = False;
6724 if(!large_file_format) {
6725 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6726 } else {
6728 #if defined(HAVE_LONGLONG)
6729 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6730 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6731 #else /* HAVE_LONGLONG */
6734 * NT4.x seems to be broken in that it sends large file (64 bit)
6735 * lockingX calls even if the CAP_LARGE_FILES was *not*
6736 * negotiated. For boxes without large unsigned ints mangle the
6737 * lock offset by mapping the top 32 bits onto the lower 32.
6740 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6741 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6742 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6743 uint32 new_low = 0;
6745 if((new_low = map_lock_offset(high, low)) == 0) {
6746 *err = True;
6747 return (uint64_t)-1;
6750 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6751 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6752 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6753 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6756 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6757 #endif /* HAVE_LONGLONG */
6760 return offset;
6763 /****************************************************************************
6764 Reply to a lockingX request.
6765 ****************************************************************************/
6767 void reply_lockingX(struct smb_request *req)
6769 connection_struct *conn = req->conn;
6770 files_struct *fsp;
6771 unsigned char locktype;
6772 unsigned char oplocklevel;
6773 uint16 num_ulocks;
6774 uint16 num_locks;
6775 uint64_t count = 0, offset = 0;
6776 uint32 lock_pid;
6777 int32 lock_timeout;
6778 int i;
6779 const uint8_t *data;
6780 bool large_file_format;
6781 bool err;
6782 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6784 START_PROFILE(SMBlockingX);
6786 if (req->wct < 8) {
6787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6788 END_PROFILE(SMBlockingX);
6789 return;
6792 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6793 locktype = CVAL(req->vwv+3, 0);
6794 oplocklevel = CVAL(req->vwv+3, 1);
6795 num_ulocks = SVAL(req->vwv+6, 0);
6796 num_locks = SVAL(req->vwv+7, 0);
6797 lock_timeout = IVAL(req->vwv+4, 0);
6798 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6800 if (!check_fsp(conn, req, fsp)) {
6801 END_PROFILE(SMBlockingX);
6802 return;
6805 data = req->buf;
6807 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6808 /* we don't support these - and CANCEL_LOCK makes w2k
6809 and XP reboot so I don't really want to be
6810 compatible! (tridge) */
6811 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6812 END_PROFILE(SMBlockingX);
6813 return;
6816 /* Check if this is an oplock break on a file
6817 we have granted an oplock on.
6819 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6820 /* Client can insist on breaking to none. */
6821 bool break_to_none = (oplocklevel == 0);
6822 bool result;
6824 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6825 "for fnum = %d\n", (unsigned int)oplocklevel,
6826 fsp->fnum ));
6829 * Make sure we have granted an exclusive or batch oplock on
6830 * this file.
6833 if (fsp->oplock_type == 0) {
6835 /* The Samba4 nbench simulator doesn't understand
6836 the difference between break to level2 and break
6837 to none from level2 - it sends oplock break
6838 replies in both cases. Don't keep logging an error
6839 message here - just ignore it. JRA. */
6841 DEBUG(5,("reply_lockingX: Error : oplock break from "
6842 "client for fnum = %d (oplock=%d) and no "
6843 "oplock granted on this file (%s).\n",
6844 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6846 /* if this is a pure oplock break request then don't
6847 * send a reply */
6848 if (num_locks == 0 && num_ulocks == 0) {
6849 END_PROFILE(SMBlockingX);
6850 return;
6851 } else {
6852 END_PROFILE(SMBlockingX);
6853 reply_doserror(req, ERRDOS, ERRlock);
6854 return;
6858 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6859 (break_to_none)) {
6860 result = remove_oplock(fsp);
6861 } else {
6862 result = downgrade_oplock(fsp);
6865 if (!result) {
6866 DEBUG(0, ("reply_lockingX: error in removing "
6867 "oplock on file %s\n", fsp->fsp_name));
6868 /* Hmmm. Is this panic justified? */
6869 smb_panic("internal tdb error");
6872 reply_to_oplock_break_requests(fsp);
6874 /* if this is a pure oplock break request then don't send a
6875 * reply */
6876 if (num_locks == 0 && num_ulocks == 0) {
6877 /* Sanity check - ensure a pure oplock break is not a
6878 chained request. */
6879 if(CVAL(req->vwv+0, 0) != 0xff)
6880 DEBUG(0,("reply_lockingX: Error : pure oplock "
6881 "break is a chained %d request !\n",
6882 (unsigned int)CVAL(req->vwv+0, 0)));
6883 END_PROFILE(SMBlockingX);
6884 return;
6888 if (req->buflen <
6889 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6891 END_PROFILE(SMBlockingX);
6892 return;
6895 /* Data now points at the beginning of the list
6896 of smb_unlkrng structs */
6897 for(i = 0; i < (int)num_ulocks; i++) {
6898 lock_pid = get_lock_pid( data, i, large_file_format);
6899 count = get_lock_count( data, i, large_file_format);
6900 offset = get_lock_offset( data, i, large_file_format, &err);
6903 * There is no error code marked "stupid client bug".... :-).
6905 if(err) {
6906 END_PROFILE(SMBlockingX);
6907 reply_doserror(req, ERRDOS, ERRnoaccess);
6908 return;
6911 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6912 "pid %u, file %s\n", (double)offset, (double)count,
6913 (unsigned int)lock_pid, fsp->fsp_name ));
6915 status = do_unlock(smbd_messaging_context(),
6916 fsp,
6917 lock_pid,
6918 count,
6919 offset,
6920 WINDOWS_LOCK);
6922 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
6923 nt_errstr(status)));
6925 if (NT_STATUS_V(status)) {
6926 END_PROFILE(SMBlockingX);
6927 reply_nterror(req, status);
6928 return;
6932 /* Setup the timeout in seconds. */
6934 if (!lp_blocking_locks(SNUM(conn))) {
6935 lock_timeout = 0;
6938 /* Now do any requested locks */
6939 data += ((large_file_format ? 20 : 10)*num_ulocks);
6941 /* Data now points at the beginning of the list
6942 of smb_lkrng structs */
6944 for(i = 0; i < (int)num_locks; i++) {
6945 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6946 READ_LOCK:WRITE_LOCK);
6947 lock_pid = get_lock_pid( data, i, large_file_format);
6948 count = get_lock_count( data, i, large_file_format);
6949 offset = get_lock_offset( data, i, large_file_format, &err);
6952 * There is no error code marked "stupid client bug".... :-).
6954 if(err) {
6955 END_PROFILE(SMBlockingX);
6956 reply_doserror(req, ERRDOS, ERRnoaccess);
6957 return;
6960 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6961 "%u, file %s timeout = %d\n", (double)offset,
6962 (double)count, (unsigned int)lock_pid,
6963 fsp->fsp_name, (int)lock_timeout ));
6965 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6966 struct blocking_lock_record *blr = NULL;
6968 if (lp_blocking_locks(SNUM(conn))) {
6970 /* Schedule a message to ourselves to
6971 remove the blocking lock record and
6972 return the right error. */
6974 blr = blocking_lock_cancel(fsp,
6975 lock_pid,
6976 offset,
6977 count,
6978 WINDOWS_LOCK,
6979 locktype,
6980 NT_STATUS_FILE_LOCK_CONFLICT);
6981 if (blr == NULL) {
6982 END_PROFILE(SMBlockingX);
6983 reply_nterror(
6984 req,
6985 NT_STATUS_DOS(
6986 ERRDOS,
6987 ERRcancelviolation));
6988 return;
6991 /* Remove a matching pending lock. */
6992 status = do_lock_cancel(fsp,
6993 lock_pid,
6994 count,
6995 offset,
6996 WINDOWS_LOCK,
6997 blr);
6998 } else {
6999 bool blocking_lock = lock_timeout ? True : False;
7000 bool defer_lock = False;
7001 struct byte_range_lock *br_lck;
7002 uint32 block_smbpid;
7004 br_lck = do_lock(smbd_messaging_context(),
7005 fsp,
7006 lock_pid,
7007 count,
7008 offset,
7009 lock_type,
7010 WINDOWS_LOCK,
7011 blocking_lock,
7012 &status,
7013 &block_smbpid,
7014 NULL);
7016 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7017 /* Windows internal resolution for blocking locks seems
7018 to be about 200ms... Don't wait for less than that. JRA. */
7019 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7020 lock_timeout = lp_lock_spin_time();
7022 defer_lock = True;
7025 /* This heuristic seems to match W2K3 very well. If a
7026 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7027 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7028 far as I can tell. Replacement for do_lock_spin(). JRA. */
7030 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7031 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7032 defer_lock = True;
7033 lock_timeout = lp_lock_spin_time();
7036 if (br_lck && defer_lock) {
7038 * A blocking lock was requested. Package up
7039 * this smb into a queued request and push it
7040 * onto the blocking lock queue.
7042 if(push_blocking_lock_request(br_lck,
7043 req,
7044 fsp,
7045 lock_timeout,
7047 lock_pid,
7048 lock_type,
7049 WINDOWS_LOCK,
7050 offset,
7051 count,
7052 block_smbpid)) {
7053 TALLOC_FREE(br_lck);
7054 END_PROFILE(SMBlockingX);
7055 return;
7059 TALLOC_FREE(br_lck);
7062 if (NT_STATUS_V(status)) {
7063 END_PROFILE(SMBlockingX);
7064 reply_nterror(req, status);
7065 return;
7069 /* If any of the above locks failed, then we must unlock
7070 all of the previous locks (X/Open spec). */
7072 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7073 (i != num_locks) &&
7074 (num_locks != 0)) {
7076 * Ensure we don't do a remove on the lock that just failed,
7077 * as under POSIX rules, if we have a lock already there, we
7078 * will delete it (and we shouldn't) .....
7080 for(i--; i >= 0; i--) {
7081 lock_pid = get_lock_pid( data, i, large_file_format);
7082 count = get_lock_count( data, i, large_file_format);
7083 offset = get_lock_offset( data, i, large_file_format,
7084 &err);
7087 * There is no error code marked "stupid client
7088 * bug".... :-).
7090 if(err) {
7091 END_PROFILE(SMBlockingX);
7092 reply_doserror(req, ERRDOS, ERRnoaccess);
7093 return;
7096 do_unlock(smbd_messaging_context(),
7097 fsp,
7098 lock_pid,
7099 count,
7100 offset,
7101 WINDOWS_LOCK);
7103 END_PROFILE(SMBlockingX);
7104 reply_nterror(req, status);
7105 return;
7108 reply_outbuf(req, 2, 0);
7110 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7111 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7113 END_PROFILE(SMBlockingX);
7114 chain_reply(req);
7117 #undef DBGC_CLASS
7118 #define DBGC_CLASS DBGC_ALL
7120 /****************************************************************************
7121 Reply to a SMBreadbmpx (read block multiplex) request.
7122 Always reply with an error, if someone has a platform really needs this,
7123 please contact vl@samba.org
7124 ****************************************************************************/
7126 void reply_readbmpx(struct smb_request *req)
7128 START_PROFILE(SMBreadBmpx);
7129 reply_doserror(req, ERRSRV, ERRuseSTD);
7130 END_PROFILE(SMBreadBmpx);
7131 return;
7134 /****************************************************************************
7135 Reply to a SMBreadbs (read block multiplex secondary) request.
7136 Always reply with an error, if someone has a platform really needs this,
7137 please contact vl@samba.org
7138 ****************************************************************************/
7140 void reply_readbs(struct smb_request *req)
7142 START_PROFILE(SMBreadBs);
7143 reply_doserror(req, ERRSRV, ERRuseSTD);
7144 END_PROFILE(SMBreadBs);
7145 return;
7148 /****************************************************************************
7149 Reply to a SMBsetattrE.
7150 ****************************************************************************/
7152 void reply_setattrE(struct smb_request *req)
7154 connection_struct *conn = req->conn;
7155 struct smb_file_time ft;
7156 files_struct *fsp;
7157 SMB_STRUCT_STAT sbuf;
7158 NTSTATUS status;
7160 START_PROFILE(SMBsetattrE);
7161 ZERO_STRUCT(ft);
7163 if (req->wct < 7) {
7164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7165 END_PROFILE(SMBsetattrE);
7166 return;
7169 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7171 if(!fsp || (fsp->conn != conn)) {
7172 reply_doserror(req, ERRDOS, ERRbadfid);
7173 END_PROFILE(SMBsetattrE);
7174 return;
7179 * Convert the DOS times into unix times.
7182 ft.atime = convert_time_t_to_timespec(
7183 srv_make_unix_date2(req->vwv+3));
7184 ft.mtime = convert_time_t_to_timespec(
7185 srv_make_unix_date2(req->vwv+5));
7186 ft.create_time = convert_time_t_to_timespec(
7187 srv_make_unix_date2(req->vwv+1));
7189 reply_outbuf(req, 0, 0);
7192 * Patch from Ray Frush <frush@engr.colostate.edu>
7193 * Sometimes times are sent as zero - ignore them.
7196 /* Ensure we have a valid stat struct for the source. */
7197 if (fsp->fh->fd != -1) {
7198 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7199 status = map_nt_error_from_unix(errno);
7200 reply_nterror(req, status);
7201 END_PROFILE(SMBsetattrE);
7202 return;
7204 } else {
7205 int ret = -1;
7207 if (fsp->posix_open) {
7208 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7209 } else {
7210 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7212 if (ret == -1) {
7213 status = map_nt_error_from_unix(errno);
7214 reply_nterror(req, status);
7215 END_PROFILE(SMBsetattrE);
7216 return;
7220 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7221 &sbuf, &ft, true);
7222 if (!NT_STATUS_IS_OK(status)) {
7223 reply_doserror(req, ERRDOS, ERRnoaccess);
7224 END_PROFILE(SMBsetattrE);
7225 return;
7228 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7229 " createtime=%u\n",
7230 fsp->fnum,
7231 (unsigned int)ft.atime.tv_sec,
7232 (unsigned int)ft.mtime.tv_sec,
7233 (unsigned int)ft.create_time.tv_sec
7236 END_PROFILE(SMBsetattrE);
7237 return;
7241 /* Back from the dead for OS/2..... JRA. */
7243 /****************************************************************************
7244 Reply to a SMBwritebmpx (write block multiplex primary) request.
7245 Always reply with an error, if someone has a platform really needs this,
7246 please contact vl@samba.org
7247 ****************************************************************************/
7249 void reply_writebmpx(struct smb_request *req)
7251 START_PROFILE(SMBwriteBmpx);
7252 reply_doserror(req, ERRSRV, ERRuseSTD);
7253 END_PROFILE(SMBwriteBmpx);
7254 return;
7257 /****************************************************************************
7258 Reply to a SMBwritebs (write block multiplex secondary) request.
7259 Always reply with an error, if someone has a platform really needs this,
7260 please contact vl@samba.org
7261 ****************************************************************************/
7263 void reply_writebs(struct smb_request *req)
7265 START_PROFILE(SMBwriteBs);
7266 reply_doserror(req, ERRSRV, ERRuseSTD);
7267 END_PROFILE(SMBwriteBs);
7268 return;
7271 /****************************************************************************
7272 Reply to a SMBgetattrE.
7273 ****************************************************************************/
7275 void reply_getattrE(struct smb_request *req)
7277 connection_struct *conn = req->conn;
7278 SMB_STRUCT_STAT sbuf;
7279 int mode;
7280 files_struct *fsp;
7281 struct timespec create_ts;
7283 START_PROFILE(SMBgetattrE);
7285 if (req->wct < 1) {
7286 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7287 END_PROFILE(SMBgetattrE);
7288 return;
7291 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7293 if(!fsp || (fsp->conn != conn)) {
7294 reply_doserror(req, ERRDOS, ERRbadfid);
7295 END_PROFILE(SMBgetattrE);
7296 return;
7299 /* Do an fstat on this file */
7300 if(fsp_stat(fsp, &sbuf)) {
7301 reply_unixerror(req, ERRDOS, ERRnoaccess);
7302 END_PROFILE(SMBgetattrE);
7303 return;
7306 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7309 * Convert the times into dos times. Set create
7310 * date to be last modify date as UNIX doesn't save
7311 * this.
7314 reply_outbuf(req, 11, 0);
7316 create_ts = get_create_timespec(&sbuf,
7317 lp_fake_dir_create_times(SNUM(conn)));
7318 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7319 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7320 /* Should we check pending modtime here ? JRA */
7321 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7323 if (mode & aDIR) {
7324 SIVAL(req->outbuf, smb_vwv6, 0);
7325 SIVAL(req->outbuf, smb_vwv8, 0);
7326 } else {
7327 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7328 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7329 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7331 SSVAL(req->outbuf,smb_vwv10, mode);
7333 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7335 END_PROFILE(SMBgetattrE);
7336 return;