spoolss: use nstring_array in spoolss_EnumPrinterKey.
[Samba.git] / source3 / smbd / reply.c
bloba743385f7f51fa7c454f66875ba4fd7a19ba1104
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 if (fsp->posix_open) {
2218 return NT_STATUS_OK;
2221 /* If no pathnames are open below this
2222 directory, allow the rename. */
2224 if (file_find_subpath(fsp)) {
2225 return NT_STATUS_ACCESS_DENIED;
2227 return NT_STATUS_OK;
2230 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2231 return NT_STATUS_OK;
2234 return NT_STATUS_ACCESS_DENIED;
2237 /*******************************************************************
2238 * unlink a file with all relevant access checks
2239 *******************************************************************/
2241 static NTSTATUS do_unlink(connection_struct *conn,
2242 struct smb_request *req,
2243 const char *fname,
2244 uint32 dirtype)
2246 SMB_STRUCT_STAT sbuf;
2247 uint32 fattr;
2248 files_struct *fsp;
2249 uint32 dirtype_orig = dirtype;
2250 NTSTATUS status;
2252 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2254 if (!CAN_WRITE(conn)) {
2255 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2258 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2259 return map_nt_error_from_unix(errno);
2262 fattr = dos_mode(conn,fname,&sbuf);
2264 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2265 dirtype = aDIR|aARCH|aRONLY;
2268 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2269 if (!dirtype) {
2270 return NT_STATUS_NO_SUCH_FILE;
2273 if (!dir_check_ftype(conn, fattr, dirtype)) {
2274 if (fattr & aDIR) {
2275 return NT_STATUS_FILE_IS_A_DIRECTORY;
2277 return NT_STATUS_NO_SUCH_FILE;
2280 if (dirtype_orig & 0x8000) {
2281 /* These will never be set for POSIX. */
2282 return NT_STATUS_NO_SUCH_FILE;
2285 #if 0
2286 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2287 return NT_STATUS_FILE_IS_A_DIRECTORY;
2290 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2291 return NT_STATUS_NO_SUCH_FILE;
2294 if (dirtype & 0xFF00) {
2295 /* These will never be set for POSIX. */
2296 return NT_STATUS_NO_SUCH_FILE;
2299 dirtype &= 0xFF;
2300 if (!dirtype) {
2301 return NT_STATUS_NO_SUCH_FILE;
2304 /* Can't delete a directory. */
2305 if (fattr & aDIR) {
2306 return NT_STATUS_FILE_IS_A_DIRECTORY;
2308 #endif
2310 #if 0 /* JRATEST */
2311 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2312 return NT_STATUS_OBJECT_NAME_INVALID;
2313 #endif /* JRATEST */
2315 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2317 On a Windows share, a file with read-only dosmode can be opened with
2318 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2319 fails with NT_STATUS_CANNOT_DELETE error.
2321 This semantic causes a problem that a user can not
2322 rename a file with read-only dosmode on a Samba share
2323 from a Windows command prompt (i.e. cmd.exe, but can rename
2324 from Windows Explorer).
2327 if (!lp_delete_readonly(SNUM(conn))) {
2328 if (fattr & aRONLY) {
2329 return NT_STATUS_CANNOT_DELETE;
2333 /* On open checks the open itself will check the share mode, so
2334 don't do it here as we'll get it wrong. */
2336 status = SMB_VFS_CREATE_FILE
2337 (conn, /* conn */
2338 req, /* req */
2339 0, /* root_dir_fid */
2340 fname, /* fname */
2341 0, /* create_file_flags */
2342 DELETE_ACCESS, /* access_mask */
2343 FILE_SHARE_NONE, /* share_access */
2344 FILE_OPEN, /* create_disposition*/
2345 FILE_NON_DIRECTORY_FILE, /* create_options */
2346 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2347 0, /* oplock_request */
2348 0, /* allocation_size */
2349 NULL, /* sd */
2350 NULL, /* ea_list */
2351 &fsp, /* result */
2352 NULL, /* pinfo */
2353 &sbuf); /* psbuf */
2355 if (!NT_STATUS_IS_OK(status)) {
2356 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2357 nt_errstr(status)));
2358 return status;
2361 /* The set is across all open files on this dev/inode pair. */
2362 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2363 close_file(req, fsp, NORMAL_CLOSE);
2364 return NT_STATUS_ACCESS_DENIED;
2367 return close_file(req, fsp, NORMAL_CLOSE);
2370 /****************************************************************************
2371 The guts of the unlink command, split out so it may be called by the NT SMB
2372 code.
2373 ****************************************************************************/
2375 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2376 uint32 dirtype, const char *name_in, bool has_wild)
2378 const char *directory = NULL;
2379 char *mask = NULL;
2380 char *name = NULL;
2381 char *p = NULL;
2382 int count=0;
2383 NTSTATUS status = NT_STATUS_OK;
2384 SMB_STRUCT_STAT sbuf, st;
2385 TALLOC_CTX *ctx = talloc_tos();
2387 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2388 if (!NT_STATUS_IS_OK(status)) {
2389 return status;
2392 p = strrchr_m(name,'/');
2393 if (!p) {
2394 directory = talloc_strdup(ctx, ".");
2395 if (!directory) {
2396 return NT_STATUS_NO_MEMORY;
2398 mask = name;
2399 } else {
2400 *p = 0;
2401 directory = name;
2402 mask = p+1;
2406 * We should only check the mangled cache
2407 * here if unix_convert failed. This means
2408 * that the path in 'mask' doesn't exist
2409 * on the file system and so we need to look
2410 * for a possible mangle. This patch from
2411 * Tine Smukavec <valentin.smukavec@hermes.si>.
2414 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2415 char *new_mask = NULL;
2416 mangle_lookup_name_from_8_3(ctx,
2417 mask,
2418 &new_mask,
2419 conn->params );
2420 if (new_mask) {
2421 mask = new_mask;
2425 if (!has_wild) {
2426 directory = talloc_asprintf(ctx,
2427 "%s/%s",
2428 directory,
2429 mask);
2430 if (!directory) {
2431 return NT_STATUS_NO_MEMORY;
2433 if (dirtype == 0) {
2434 dirtype = FILE_ATTRIBUTE_NORMAL;
2437 status = check_name(conn, directory);
2438 if (!NT_STATUS_IS_OK(status)) {
2439 return status;
2442 status = do_unlink(conn, req, directory, dirtype);
2443 if (!NT_STATUS_IS_OK(status)) {
2444 return status;
2447 count++;
2448 } else {
2449 struct smb_Dir *dir_hnd = NULL;
2450 long offset = 0;
2451 const char *dname;
2453 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2454 return NT_STATUS_OBJECT_NAME_INVALID;
2457 if (strequal(mask,"????????.???")) {
2458 mask[0] = '*';
2459 mask[1] = '\0';
2462 status = check_name(conn, directory);
2463 if (!NT_STATUS_IS_OK(status)) {
2464 return status;
2467 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2468 dirtype);
2469 if (dir_hnd == NULL) {
2470 return map_nt_error_from_unix(errno);
2473 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2474 the pattern matches against the long name, otherwise the short name
2475 We don't implement this yet XXXX
2478 status = NT_STATUS_NO_SUCH_FILE;
2480 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2481 char *fname = NULL;
2483 if (!is_visible_file(conn, directory, dname, &st,
2484 true))
2486 continue;
2489 /* Quick check for "." and ".." */
2490 if (ISDOT(dname) || ISDOTDOT(dname)) {
2491 continue;
2494 if(!mask_match(dname, mask, conn->case_sensitive)) {
2495 continue;
2498 fname = talloc_asprintf(ctx, "%s/%s",
2499 directory,
2500 dname);
2501 if (!fname) {
2502 return NT_STATUS_NO_MEMORY;
2505 status = check_name(conn, fname);
2506 if (!NT_STATUS_IS_OK(status)) {
2507 TALLOC_FREE(dir_hnd);
2508 return status;
2511 status = do_unlink(conn, req, fname, dirtype);
2512 if (!NT_STATUS_IS_OK(status)) {
2513 TALLOC_FREE(fname);
2514 continue;
2517 count++;
2518 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2519 fname));
2521 TALLOC_FREE(fname);
2523 TALLOC_FREE(dir_hnd);
2526 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2527 status = map_nt_error_from_unix(errno);
2530 return status;
2533 /****************************************************************************
2534 Reply to a unlink
2535 ****************************************************************************/
2537 void reply_unlink(struct smb_request *req)
2539 connection_struct *conn = req->conn;
2540 char *name = NULL;
2541 uint32 dirtype;
2542 NTSTATUS status;
2543 bool path_contains_wcard = False;
2544 TALLOC_CTX *ctx = talloc_tos();
2546 START_PROFILE(SMBunlink);
2548 if (req->wct < 1) {
2549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2550 END_PROFILE(SMBunlink);
2551 return;
2554 dirtype = SVAL(req->vwv+0, 0);
2556 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2557 STR_TERMINATE, &status,
2558 &path_contains_wcard);
2559 if (!NT_STATUS_IS_OK(status)) {
2560 reply_nterror(req, status);
2561 END_PROFILE(SMBunlink);
2562 return;
2565 status = resolve_dfspath_wcard(ctx, conn,
2566 req->flags2 & FLAGS2_DFS_PATHNAMES,
2567 name,
2568 &name,
2569 &path_contains_wcard);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2572 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2573 ERRSRV, ERRbadpath);
2574 END_PROFILE(SMBunlink);
2575 return;
2577 reply_nterror(req, status);
2578 END_PROFILE(SMBunlink);
2579 return;
2582 DEBUG(3,("reply_unlink : %s\n",name));
2584 status = unlink_internals(conn, req, dirtype, name,
2585 path_contains_wcard);
2586 if (!NT_STATUS_IS_OK(status)) {
2587 if (open_was_deferred(req->mid)) {
2588 /* We have re-scheduled this call. */
2589 END_PROFILE(SMBunlink);
2590 return;
2592 reply_nterror(req, status);
2593 END_PROFILE(SMBunlink);
2594 return;
2597 reply_outbuf(req, 0, 0);
2598 END_PROFILE(SMBunlink);
2600 return;
2603 /****************************************************************************
2604 Fail for readbraw.
2605 ****************************************************************************/
2607 static void fail_readraw(void)
2609 const char *errstr = talloc_asprintf(talloc_tos(),
2610 "FAIL ! reply_readbraw: socket write fail (%s)",
2611 strerror(errno));
2612 if (!errstr) {
2613 errstr = "";
2615 exit_server_cleanly(errstr);
2618 /****************************************************************************
2619 Fake (read/write) sendfile. Returns -1 on read or write fail.
2620 ****************************************************************************/
2622 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2623 size_t nread)
2625 size_t bufsize;
2626 size_t tosend = nread;
2627 char *buf;
2629 if (nread == 0) {
2630 return 0;
2633 bufsize = MIN(nread, 65536);
2635 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2636 return -1;
2639 while (tosend > 0) {
2640 ssize_t ret;
2641 size_t cur_read;
2643 if (tosend > bufsize) {
2644 cur_read = bufsize;
2645 } else {
2646 cur_read = tosend;
2648 ret = read_file(fsp,buf,startpos,cur_read);
2649 if (ret == -1) {
2650 SAFE_FREE(buf);
2651 return -1;
2654 /* If we had a short read, fill with zeros. */
2655 if (ret < cur_read) {
2656 memset(buf, '\0', cur_read - ret);
2659 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2660 SAFE_FREE(buf);
2661 return -1;
2663 tosend -= cur_read;
2664 startpos += cur_read;
2667 SAFE_FREE(buf);
2668 return (ssize_t)nread;
2671 /****************************************************************************
2672 Deal with the case of sendfile reading less bytes from the file than
2673 requested. Fill with zeros (all we can do).
2674 ****************************************************************************/
2676 static void sendfile_short_send(files_struct *fsp,
2677 ssize_t nread,
2678 size_t headersize,
2679 size_t smb_maxcnt)
2681 if (nread < headersize) {
2682 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2683 "header for file %s (%s). Terminating\n",
2684 fsp->fsp_name, strerror(errno) ));
2685 exit_server_cleanly("sendfile_short_send failed");
2688 nread -= headersize;
2690 if (nread < smb_maxcnt) {
2691 char *buf = SMB_CALLOC_ARRAY(char, 1024);
2692 if (!buf) {
2693 exit_server_cleanly("sendfile_short_send: "
2694 "malloc failed");
2697 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2698 "with zeros !\n", fsp->fsp_name));
2700 while (nread < smb_maxcnt) {
2702 * We asked for the real file size and told sendfile
2703 * to not go beyond the end of the file. But it can
2704 * happen that in between our fstat call and the
2705 * sendfile call the file was truncated. This is very
2706 * bad because we have already announced the larger
2707 * number of bytes to the client.
2709 * The best we can do now is to send 0-bytes, just as
2710 * a read from a hole in a sparse file would do.
2712 * This should happen rarely enough that I don't care
2713 * about efficiency here :-)
2715 size_t to_write;
2717 to_write = MIN(sizeof(buf), smb_maxcnt - nread);
2718 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2719 exit_server_cleanly("sendfile_short_send: "
2720 "write_data failed");
2722 nread += to_write;
2724 SAFE_FREE(buf);
2728 /****************************************************************************
2729 Return a readbraw error (4 bytes of zero).
2730 ****************************************************************************/
2732 static void reply_readbraw_error(void)
2734 char header[4];
2735 SIVAL(header,0,0);
2736 if (write_data(smbd_server_fd(),header,4) != 4) {
2737 fail_readraw();
2741 /****************************************************************************
2742 Use sendfile in readbraw.
2743 ****************************************************************************/
2745 static void send_file_readbraw(connection_struct *conn,
2746 struct smb_request *req,
2747 files_struct *fsp,
2748 SMB_OFF_T startpos,
2749 size_t nread,
2750 ssize_t mincount)
2752 char *outbuf = NULL;
2753 ssize_t ret=0;
2755 #if defined(WITH_SENDFILE)
2757 * We can only use sendfile on a non-chained packet
2758 * but we can use on a non-oplocked file. tridge proved this
2759 * on a train in Germany :-). JRA.
2760 * reply_readbraw has already checked the length.
2763 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2764 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2765 ssize_t sendfile_read = -1;
2766 char header[4];
2767 DATA_BLOB header_blob;
2769 _smb_setlen(header,nread);
2770 header_blob = data_blob_const(header, 4);
2772 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2773 &header_blob, startpos, nread)) == -1) {
2774 /* Returning ENOSYS means no data at all was sent.
2775 * Do this as a normal read. */
2776 if (errno == ENOSYS) {
2777 goto normal_readbraw;
2781 * Special hack for broken Linux with no working sendfile. If we
2782 * return EINTR we sent the header but not the rest of the data.
2783 * Fake this up by doing read/write calls.
2785 if (errno == EINTR) {
2786 /* Ensure we don't do this again. */
2787 set_use_sendfile(SNUM(conn), False);
2788 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2790 if (fake_sendfile(fsp, startpos, nread) == -1) {
2791 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2792 fsp->fsp_name, strerror(errno) ));
2793 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2795 return;
2798 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2799 fsp->fsp_name, strerror(errno) ));
2800 exit_server_cleanly("send_file_readbraw sendfile failed");
2801 } else if (sendfile_read == 0) {
2803 * Some sendfile implementations return 0 to indicate
2804 * that there was a short read, but nothing was
2805 * actually written to the socket. In this case,
2806 * fallback to the normal read path so the header gets
2807 * the correct byte count.
2809 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2810 "bytes falling back to the normal read: "
2811 "%s\n", fsp->fsp_name));
2812 goto normal_readbraw;
2815 /* Deal with possible short send. */
2816 if (sendfile_read != 4+nread) {
2817 sendfile_short_send(fsp, sendfile_read, 4, nread);
2819 return;
2822 normal_readbraw:
2823 #endif
2825 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2826 if (!outbuf) {
2827 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2828 (unsigned)(nread+4)));
2829 reply_readbraw_error();
2830 return;
2833 if (nread > 0) {
2834 ret = read_file(fsp,outbuf+4,startpos,nread);
2835 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2836 if (ret < mincount)
2837 ret = 0;
2838 #else
2839 if (ret < nread)
2840 ret = 0;
2841 #endif
2844 _smb_setlen(outbuf,ret);
2845 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2846 fail_readraw();
2848 TALLOC_FREE(outbuf);
2851 /****************************************************************************
2852 Reply to a readbraw (core+ protocol).
2853 ****************************************************************************/
2855 void reply_readbraw(struct smb_request *req)
2857 connection_struct *conn = req->conn;
2858 ssize_t maxcount,mincount;
2859 size_t nread = 0;
2860 SMB_OFF_T startpos;
2861 files_struct *fsp;
2862 struct lock_struct lock;
2863 SMB_STRUCT_STAT st;
2864 SMB_OFF_T size = 0;
2866 START_PROFILE(SMBreadbraw);
2868 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2869 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2870 "raw reads/writes are disallowed.");
2873 if (req->wct < 8) {
2874 reply_readbraw_error();
2875 END_PROFILE(SMBreadbraw);
2876 return;
2880 * Special check if an oplock break has been issued
2881 * and the readraw request croses on the wire, we must
2882 * return a zero length response here.
2885 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2888 * We have to do a check_fsp by hand here, as
2889 * we must always return 4 zero bytes on error,
2890 * not a NTSTATUS.
2893 if (!fsp || !conn || conn != fsp->conn ||
2894 req->vuid != fsp->vuid ||
2895 fsp->is_directory || fsp->fh->fd == -1) {
2897 * fsp could be NULL here so use the value from the packet. JRA.
2899 DEBUG(3,("reply_readbraw: fnum %d not valid "
2900 "- cache prime?\n",
2901 (int)SVAL(req->vwv+0, 0)));
2902 reply_readbraw_error();
2903 END_PROFILE(SMBreadbraw);
2904 return;
2907 /* Do a "by hand" version of CHECK_READ. */
2908 if (!(fsp->can_read ||
2909 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2910 (fsp->access_mask & FILE_EXECUTE)))) {
2911 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2912 (int)SVAL(req->vwv+0, 0)));
2913 reply_readbraw_error();
2914 END_PROFILE(SMBreadbraw);
2915 return;
2918 flush_write_cache(fsp, READRAW_FLUSH);
2920 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2921 if(req->wct == 10) {
2923 * This is a large offset (64 bit) read.
2925 #ifdef LARGE_SMB_OFF_T
2927 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
2929 #else /* !LARGE_SMB_OFF_T */
2932 * Ensure we haven't been sent a >32 bit offset.
2935 if(IVAL(req->vwv+8, 0) != 0) {
2936 DEBUG(0,("reply_readbraw: large offset "
2937 "(%x << 32) used and we don't support "
2938 "64 bit offsets.\n",
2939 (unsigned int)IVAL(req->vwv+8, 0) ));
2940 reply_readbraw_error();
2941 END_PROFILE(SMBreadbraw);
2942 return;
2945 #endif /* LARGE_SMB_OFF_T */
2947 if(startpos < 0) {
2948 DEBUG(0,("reply_readbraw: negative 64 bit "
2949 "readraw offset (%.0f) !\n",
2950 (double)startpos ));
2951 reply_readbraw_error();
2952 END_PROFILE(SMBreadbraw);
2953 return;
2957 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
2958 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
2960 /* ensure we don't overrun the packet size */
2961 maxcount = MIN(65535,maxcount);
2963 init_strict_lock_struct(fsp, (uint32)req->smbpid,
2964 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
2965 &lock);
2967 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
2968 reply_readbraw_error();
2969 END_PROFILE(SMBreadbraw);
2970 return;
2973 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
2974 size = st.st_size;
2977 if (startpos >= size) {
2978 nread = 0;
2979 } else {
2980 nread = MIN(maxcount,(size - startpos));
2983 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2984 if (nread < mincount)
2985 nread = 0;
2986 #endif
2988 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2989 "min=%lu nread=%lu\n",
2990 fsp->fnum, (double)startpos,
2991 (unsigned long)maxcount,
2992 (unsigned long)mincount,
2993 (unsigned long)nread ) );
2995 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
2997 DEBUG(5,("reply_readbraw finished\n"));
2999 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3001 END_PROFILE(SMBreadbraw);
3002 return;
3005 #undef DBGC_CLASS
3006 #define DBGC_CLASS DBGC_LOCKING
3008 /****************************************************************************
3009 Reply to a lockread (core+ protocol).
3010 ****************************************************************************/
3012 void reply_lockread(struct smb_request *req)
3014 connection_struct *conn = req->conn;
3015 ssize_t nread = -1;
3016 char *data;
3017 SMB_OFF_T startpos;
3018 size_t numtoread;
3019 NTSTATUS status;
3020 files_struct *fsp;
3021 struct byte_range_lock *br_lck = NULL;
3022 char *p = NULL;
3024 START_PROFILE(SMBlockread);
3026 if (req->wct < 5) {
3027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3028 END_PROFILE(SMBlockread);
3029 return;
3032 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3034 if (!check_fsp(conn, req, fsp)) {
3035 END_PROFILE(SMBlockread);
3036 return;
3039 if (!CHECK_READ(fsp,req)) {
3040 reply_doserror(req, ERRDOS, ERRbadaccess);
3041 END_PROFILE(SMBlockread);
3042 return;
3045 numtoread = SVAL(req->vwv+1, 0);
3046 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3048 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3050 reply_outbuf(req, 5, numtoread + 3);
3052 data = smb_buf(req->outbuf) + 3;
3055 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3056 * protocol request that predates the read/write lock concept.
3057 * Thus instead of asking for a read lock here we need to ask
3058 * for a write lock. JRA.
3059 * Note that the requested lock size is unaffected by max_recv.
3062 br_lck = do_lock(smbd_messaging_context(),
3063 fsp,
3064 req->smbpid,
3065 (uint64_t)numtoread,
3066 (uint64_t)startpos,
3067 WRITE_LOCK,
3068 WINDOWS_LOCK,
3069 False, /* Non-blocking lock. */
3070 &status,
3071 NULL,
3072 NULL);
3073 TALLOC_FREE(br_lck);
3075 if (NT_STATUS_V(status)) {
3076 reply_nterror(req, status);
3077 END_PROFILE(SMBlockread);
3078 return;
3082 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3085 if (numtoread > max_recv) {
3086 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3087 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3088 (unsigned int)numtoread, (unsigned int)max_recv ));
3089 numtoread = MIN(numtoread,max_recv);
3091 nread = read_file(fsp,data,startpos,numtoread);
3093 if (nread < 0) {
3094 reply_unixerror(req, ERRDOS, ERRnoaccess);
3095 END_PROFILE(SMBlockread);
3096 return;
3099 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3101 SSVAL(req->outbuf,smb_vwv0,nread);
3102 SSVAL(req->outbuf,smb_vwv5,nread+3);
3103 p = smb_buf(req->outbuf);
3104 SCVAL(p,0,0); /* pad byte. */
3105 SSVAL(p,1,nread);
3107 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3108 fsp->fnum, (int)numtoread, (int)nread));
3110 END_PROFILE(SMBlockread);
3111 return;
3114 #undef DBGC_CLASS
3115 #define DBGC_CLASS DBGC_ALL
3117 /****************************************************************************
3118 Reply to a read.
3119 ****************************************************************************/
3121 void reply_read(struct smb_request *req)
3123 connection_struct *conn = req->conn;
3124 size_t numtoread;
3125 ssize_t nread = 0;
3126 char *data;
3127 SMB_OFF_T startpos;
3128 int outsize = 0;
3129 files_struct *fsp;
3130 struct lock_struct lock;
3132 START_PROFILE(SMBread);
3134 if (req->wct < 3) {
3135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3136 END_PROFILE(SMBread);
3137 return;
3140 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3142 if (!check_fsp(conn, req, fsp)) {
3143 END_PROFILE(SMBread);
3144 return;
3147 if (!CHECK_READ(fsp,req)) {
3148 reply_doserror(req, ERRDOS, ERRbadaccess);
3149 END_PROFILE(SMBread);
3150 return;
3153 numtoread = SVAL(req->vwv+1, 0);
3154 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3156 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3159 * The requested read size cannot be greater than max_recv. JRA.
3161 if (numtoread > max_recv) {
3162 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3163 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3164 (unsigned int)numtoread, (unsigned int)max_recv ));
3165 numtoread = MIN(numtoread,max_recv);
3168 reply_outbuf(req, 5, numtoread+3);
3170 data = smb_buf(req->outbuf) + 3;
3172 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3173 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3174 &lock);
3176 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3177 reply_doserror(req, ERRDOS,ERRlock);
3178 END_PROFILE(SMBread);
3179 return;
3182 if (numtoread > 0)
3183 nread = read_file(fsp,data,startpos,numtoread);
3185 if (nread < 0) {
3186 reply_unixerror(req, ERRDOS,ERRnoaccess);
3187 goto strict_unlock;
3190 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3192 SSVAL(req->outbuf,smb_vwv0,nread);
3193 SSVAL(req->outbuf,smb_vwv5,nread+3);
3194 SCVAL(smb_buf(req->outbuf),0,1);
3195 SSVAL(smb_buf(req->outbuf),1,nread);
3197 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3198 fsp->fnum, (int)numtoread, (int)nread ) );
3200 strict_unlock:
3201 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3203 END_PROFILE(SMBread);
3204 return;
3207 /****************************************************************************
3208 Setup readX header.
3209 ****************************************************************************/
3211 static int setup_readX_header(struct smb_request *req, char *outbuf,
3212 size_t smb_maxcnt)
3214 int outsize;
3215 char *data;
3217 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3218 data = smb_buf(outbuf);
3220 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3222 SCVAL(outbuf,smb_vwv0,0xFF);
3223 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3224 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3225 SSVAL(outbuf,smb_vwv6,
3226 req_wct_ofs(req)
3227 + 1 /* the wct field */
3228 + 12 * sizeof(uint16_t) /* vwv */
3229 + 2); /* the buflen field */
3230 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3231 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3232 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3233 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3234 return outsize;
3237 /****************************************************************************
3238 Reply to a read and X - possibly using sendfile.
3239 ****************************************************************************/
3241 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3242 files_struct *fsp, SMB_OFF_T startpos,
3243 size_t smb_maxcnt)
3245 SMB_STRUCT_STAT sbuf;
3246 ssize_t nread = -1;
3248 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3249 reply_unixerror(req, ERRDOS, ERRnoaccess);
3250 return;
3253 if (startpos > sbuf.st_size) {
3254 smb_maxcnt = 0;
3255 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3256 smb_maxcnt = (sbuf.st_size - startpos);
3259 if (smb_maxcnt == 0) {
3260 goto normal_read;
3263 #if defined(WITH_SENDFILE)
3265 * We can only use sendfile on a non-chained packet
3266 * but we can use on a non-oplocked file. tridge proved this
3267 * on a train in Germany :-). JRA.
3270 if (!req_is_in_chain(req) &&
3271 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3272 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3273 uint8 headerbuf[smb_size + 12 * 2];
3274 DATA_BLOB header;
3277 * Set up the packet header before send. We
3278 * assume here the sendfile will work (get the
3279 * correct amount of data).
3282 header = data_blob_const(headerbuf, sizeof(headerbuf));
3284 construct_reply_common_req(req, (char *)headerbuf);
3285 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3287 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3288 /* Returning ENOSYS means no data at all was sent.
3289 Do this as a normal read. */
3290 if (errno == ENOSYS) {
3291 goto normal_read;
3295 * Special hack for broken Linux with no working sendfile. If we
3296 * return EINTR we sent the header but not the rest of the data.
3297 * Fake this up by doing read/write calls.
3300 if (errno == EINTR) {
3301 /* Ensure we don't do this again. */
3302 set_use_sendfile(SNUM(conn), False);
3303 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3304 nread = fake_sendfile(fsp, startpos,
3305 smb_maxcnt);
3306 if (nread == -1) {
3307 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3308 fsp->fsp_name, strerror(errno) ));
3309 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3311 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3312 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3313 /* No outbuf here means successful sendfile. */
3314 TALLOC_FREE(req->outbuf);
3315 return;
3318 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3319 fsp->fsp_name, strerror(errno) ));
3320 exit_server_cleanly("send_file_readX sendfile failed");
3321 } else if (nread == 0) {
3323 * Some sendfile implementations return 0 to indicate
3324 * that there was a short read, but nothing was
3325 * actually written to the socket. In this case,
3326 * fallback to the normal read path so the header gets
3327 * the correct byte count.
3329 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3330 "falling back to the normal read: %s\n",
3331 fsp->fsp_name));
3332 goto normal_read;
3335 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3336 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3338 /* Deal with possible short send. */
3339 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3340 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3343 /* No outbuf here means successful sendfile. */
3344 TALLOC_FREE(req->outbuf);
3345 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3346 SMB_PERFCOUNT_END(&req->pcd);
3347 return;
3349 #endif
3351 normal_read:
3353 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3354 uint8 headerbuf[smb_size + 2*12];
3356 construct_reply_common_req(req, (char *)headerbuf);
3357 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3359 /* Send out the header. */
3360 if (write_data(smbd_server_fd(), (char *)headerbuf,
3361 sizeof(headerbuf)) != sizeof(headerbuf)) {
3362 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3363 fsp->fsp_name, strerror(errno) ));
3364 exit_server_cleanly("send_file_readX sendfile failed");
3366 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3367 if (nread == -1) {
3368 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3369 fsp->fsp_name, strerror(errno) ));
3370 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3372 TALLOC_FREE(req->outbuf);
3373 return;
3376 reply_outbuf(req, 12, smb_maxcnt);
3378 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3379 if (nread < 0) {
3380 reply_unixerror(req, ERRDOS, ERRnoaccess);
3381 return;
3384 setup_readX_header(req, (char *)req->outbuf, nread);
3386 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3387 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3389 chain_reply(req);
3392 /****************************************************************************
3393 Reply to a read and X.
3394 ****************************************************************************/
3396 void reply_read_and_X(struct smb_request *req)
3398 connection_struct *conn = req->conn;
3399 files_struct *fsp;
3400 SMB_OFF_T startpos;
3401 size_t smb_maxcnt;
3402 struct lock_struct lock;
3403 bool big_readX = False;
3404 #if 0
3405 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3406 #endif
3408 START_PROFILE(SMBreadX);
3410 if ((req->wct != 10) && (req->wct != 12)) {
3411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3412 return;
3415 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3416 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3417 smb_maxcnt = SVAL(req->vwv+5, 0);
3419 /* If it's an IPC, pass off the pipe handler. */
3420 if (IS_IPC(conn)) {
3421 reply_pipe_read_and_X(req);
3422 END_PROFILE(SMBreadX);
3423 return;
3426 if (!check_fsp(conn, req, fsp)) {
3427 END_PROFILE(SMBreadX);
3428 return;
3431 if (!CHECK_READ(fsp,req)) {
3432 reply_doserror(req, ERRDOS,ERRbadaccess);
3433 END_PROFILE(SMBreadX);
3434 return;
3437 if (global_client_caps & CAP_LARGE_READX) {
3438 size_t upper_size = SVAL(req->vwv+7, 0);
3439 smb_maxcnt |= (upper_size<<16);
3440 if (upper_size > 1) {
3441 /* Can't do this on a chained packet. */
3442 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3443 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3444 END_PROFILE(SMBreadX);
3445 return;
3447 /* We currently don't do this on signed or sealed data. */
3448 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3449 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3450 END_PROFILE(SMBreadX);
3451 return;
3453 /* Is there room in the reply for this data ? */
3454 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3455 reply_nterror(req,
3456 NT_STATUS_INVALID_PARAMETER);
3457 END_PROFILE(SMBreadX);
3458 return;
3460 big_readX = True;
3464 if (req->wct == 12) {
3465 #ifdef LARGE_SMB_OFF_T
3467 * This is a large offset (64 bit) read.
3469 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3471 #else /* !LARGE_SMB_OFF_T */
3474 * Ensure we haven't been sent a >32 bit offset.
3477 if(IVAL(req->vwv+10, 0) != 0) {
3478 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3479 "used and we don't support 64 bit offsets.\n",
3480 (unsigned int)IVAL(req->vwv+10, 0) ));
3481 END_PROFILE(SMBreadX);
3482 reply_doserror(req, ERRDOS, ERRbadaccess);
3483 return;
3486 #endif /* LARGE_SMB_OFF_T */
3490 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3491 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3492 &lock);
3494 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3495 END_PROFILE(SMBreadX);
3496 reply_doserror(req, ERRDOS, ERRlock);
3497 return;
3500 if (!big_readX &&
3501 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3502 goto strict_unlock;
3505 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3507 strict_unlock:
3508 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3510 END_PROFILE(SMBreadX);
3511 return;
3514 /****************************************************************************
3515 Error replies to writebraw must have smb_wct == 1. Fix this up.
3516 ****************************************************************************/
3518 void error_to_writebrawerr(struct smb_request *req)
3520 uint8 *old_outbuf = req->outbuf;
3522 reply_outbuf(req, 1, 0);
3524 memcpy(req->outbuf, old_outbuf, smb_size);
3525 TALLOC_FREE(old_outbuf);
3528 /****************************************************************************
3529 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3530 ****************************************************************************/
3532 void reply_writebraw(struct smb_request *req)
3534 connection_struct *conn = req->conn;
3535 char *buf = NULL;
3536 ssize_t nwritten=0;
3537 ssize_t total_written=0;
3538 size_t numtowrite=0;
3539 size_t tcount;
3540 SMB_OFF_T startpos;
3541 char *data=NULL;
3542 bool write_through;
3543 files_struct *fsp;
3544 struct lock_struct lock;
3545 NTSTATUS status;
3547 START_PROFILE(SMBwritebraw);
3550 * If we ever reply with an error, it must have the SMB command
3551 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3552 * we're finished.
3554 SCVAL(req->inbuf,smb_com,SMBwritec);
3556 if (srv_is_signing_active()) {
3557 END_PROFILE(SMBwritebraw);
3558 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3559 "raw reads/writes are disallowed.");
3562 if (req->wct < 12) {
3563 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3564 error_to_writebrawerr(req);
3565 END_PROFILE(SMBwritebraw);
3566 return;
3569 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3570 if (!check_fsp(conn, req, fsp)) {
3571 error_to_writebrawerr(req);
3572 END_PROFILE(SMBwritebraw);
3573 return;
3576 if (!CHECK_WRITE(fsp)) {
3577 reply_doserror(req, ERRDOS, ERRbadaccess);
3578 error_to_writebrawerr(req);
3579 END_PROFILE(SMBwritebraw);
3580 return;
3583 tcount = IVAL(req->vwv+1, 0);
3584 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3585 write_through = BITSETW(req->vwv+7,0);
3587 /* We have to deal with slightly different formats depending
3588 on whether we are using the core+ or lanman1.0 protocol */
3590 if(Protocol <= PROTOCOL_COREPLUS) {
3591 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3592 data = smb_buf(req->inbuf);
3593 } else {
3594 numtowrite = SVAL(req->vwv+10, 0);
3595 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3598 /* Ensure we don't write bytes past the end of this packet. */
3599 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3601 error_to_writebrawerr(req);
3602 END_PROFILE(SMBwritebraw);
3603 return;
3606 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3607 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3608 &lock);
3610 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3611 reply_doserror(req, ERRDOS, ERRlock);
3612 error_to_writebrawerr(req);
3613 END_PROFILE(SMBwritebraw);
3614 return;
3617 if (numtowrite>0) {
3618 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3621 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3622 "wrote=%d sync=%d\n",
3623 fsp->fnum, (double)startpos, (int)numtowrite,
3624 (int)nwritten, (int)write_through));
3626 if (nwritten < (ssize_t)numtowrite) {
3627 reply_unixerror(req, ERRHRD, ERRdiskfull);
3628 error_to_writebrawerr(req);
3629 goto strict_unlock;
3632 total_written = nwritten;
3634 /* Allocate a buffer of 64k + length. */
3635 buf = TALLOC_ARRAY(NULL, char, 65540);
3636 if (!buf) {
3637 reply_doserror(req, ERRDOS, ERRnomem);
3638 error_to_writebrawerr(req);
3639 goto strict_unlock;
3642 /* Return a SMBwritebraw message to the redirector to tell
3643 * it to send more bytes */
3645 memcpy(buf, req->inbuf, smb_size);
3646 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3647 SCVAL(buf,smb_com,SMBwritebraw);
3648 SSVALS(buf,smb_vwv0,0xFFFF);
3649 show_msg(buf);
3650 if (!srv_send_smb(smbd_server_fd(),
3651 buf,
3652 IS_CONN_ENCRYPTED(conn),
3653 &req->pcd)) {
3654 exit_server_cleanly("reply_writebraw: srv_send_smb "
3655 "failed.");
3658 /* Now read the raw data into the buffer and write it */
3659 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3660 &numtowrite);
3661 if (!NT_STATUS_IS_OK(status)) {
3662 exit_server_cleanly("secondary writebraw failed");
3665 /* Set up outbuf to return the correct size */
3666 reply_outbuf(req, 1, 0);
3668 if (numtowrite != 0) {
3670 if (numtowrite > 0xFFFF) {
3671 DEBUG(0,("reply_writebraw: Oversize secondary write "
3672 "raw requested (%u). Terminating\n",
3673 (unsigned int)numtowrite ));
3674 exit_server_cleanly("secondary writebraw failed");
3677 if (tcount > nwritten+numtowrite) {
3678 DEBUG(3,("reply_writebraw: Client overestimated the "
3679 "write %d %d %d\n",
3680 (int)tcount,(int)nwritten,(int)numtowrite));
3683 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3685 if (!NT_STATUS_IS_OK(status)) {
3686 DEBUG(0,("reply_writebraw: Oversize secondary write "
3687 "raw read failed (%s). Terminating\n",
3688 nt_errstr(status)));
3689 exit_server_cleanly("secondary writebraw failed");
3692 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3693 if (nwritten == -1) {
3694 TALLOC_FREE(buf);
3695 reply_unixerror(req, ERRHRD, ERRdiskfull);
3696 error_to_writebrawerr(req);
3697 goto strict_unlock;
3700 if (nwritten < (ssize_t)numtowrite) {
3701 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3702 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3705 if (nwritten > 0) {
3706 total_written += nwritten;
3710 TALLOC_FREE(buf);
3711 SSVAL(req->outbuf,smb_vwv0,total_written);
3713 status = sync_file(conn, fsp, write_through);
3714 if (!NT_STATUS_IS_OK(status)) {
3715 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3716 fsp->fsp_name, nt_errstr(status) ));
3717 reply_nterror(req, status);
3718 error_to_writebrawerr(req);
3719 goto strict_unlock;
3722 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3723 "wrote=%d\n",
3724 fsp->fnum, (double)startpos, (int)numtowrite,
3725 (int)total_written));
3727 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3729 /* We won't return a status if write through is not selected - this
3730 * follows what WfWg does */
3731 END_PROFILE(SMBwritebraw);
3733 if (!write_through && total_written==tcount) {
3735 #if RABBIT_PELLET_FIX
3737 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3738 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3739 * JRA.
3741 if (!send_keepalive(smbd_server_fd())) {
3742 exit_server_cleanly("reply_writebraw: send of "
3743 "keepalive failed");
3745 #endif
3746 TALLOC_FREE(req->outbuf);
3748 return;
3750 strict_unlock:
3751 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3753 END_PROFILE(SMBwritebraw);
3754 return;
3757 #undef DBGC_CLASS
3758 #define DBGC_CLASS DBGC_LOCKING
3760 /****************************************************************************
3761 Reply to a writeunlock (core+).
3762 ****************************************************************************/
3764 void reply_writeunlock(struct smb_request *req)
3766 connection_struct *conn = req->conn;
3767 ssize_t nwritten = -1;
3768 size_t numtowrite;
3769 SMB_OFF_T startpos;
3770 const char *data;
3771 NTSTATUS status = NT_STATUS_OK;
3772 files_struct *fsp;
3773 struct lock_struct lock;
3775 START_PROFILE(SMBwriteunlock);
3777 if (req->wct < 5) {
3778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3779 END_PROFILE(SMBwriteunlock);
3780 return;
3783 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3785 if (!check_fsp(conn, req, fsp)) {
3786 END_PROFILE(SMBwriteunlock);
3787 return;
3790 if (!CHECK_WRITE(fsp)) {
3791 reply_doserror(req, ERRDOS,ERRbadaccess);
3792 END_PROFILE(SMBwriteunlock);
3793 return;
3796 numtowrite = SVAL(req->vwv+1, 0);
3797 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3798 data = (const char *)req->buf + 3;
3800 if (numtowrite) {
3801 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3802 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3803 &lock);
3805 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3806 reply_doserror(req, ERRDOS, ERRlock);
3807 END_PROFILE(SMBwriteunlock);
3808 return;
3812 /* The special X/Open SMB protocol handling of
3813 zero length writes is *NOT* done for
3814 this call */
3815 if(numtowrite == 0) {
3816 nwritten = 0;
3817 } else {
3818 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3821 status = sync_file(conn, fsp, False /* write through */);
3822 if (!NT_STATUS_IS_OK(status)) {
3823 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3824 fsp->fsp_name, nt_errstr(status) ));
3825 reply_nterror(req, status);
3826 goto strict_unlock;
3829 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3830 reply_unixerror(req, ERRHRD, ERRdiskfull);
3831 goto strict_unlock;
3834 if (numtowrite) {
3835 status = do_unlock(smbd_messaging_context(),
3836 fsp,
3837 req->smbpid,
3838 (uint64_t)numtowrite,
3839 (uint64_t)startpos,
3840 WINDOWS_LOCK);
3842 if (NT_STATUS_V(status)) {
3843 reply_nterror(req, status);
3844 goto strict_unlock;
3848 reply_outbuf(req, 1, 0);
3850 SSVAL(req->outbuf,smb_vwv0,nwritten);
3852 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3853 fsp->fnum, (int)numtowrite, (int)nwritten));
3855 strict_unlock:
3856 if (numtowrite) {
3857 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3860 END_PROFILE(SMBwriteunlock);
3861 return;
3864 #undef DBGC_CLASS
3865 #define DBGC_CLASS DBGC_ALL
3867 /****************************************************************************
3868 Reply to a write.
3869 ****************************************************************************/
3871 void reply_write(struct smb_request *req)
3873 connection_struct *conn = req->conn;
3874 size_t numtowrite;
3875 ssize_t nwritten = -1;
3876 SMB_OFF_T startpos;
3877 const char *data;
3878 files_struct *fsp;
3879 struct lock_struct lock;
3880 NTSTATUS status;
3882 START_PROFILE(SMBwrite);
3884 if (req->wct < 5) {
3885 END_PROFILE(SMBwrite);
3886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3887 return;
3890 /* If it's an IPC, pass off the pipe handler. */
3891 if (IS_IPC(conn)) {
3892 reply_pipe_write(req);
3893 END_PROFILE(SMBwrite);
3894 return;
3897 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3899 if (!check_fsp(conn, req, fsp)) {
3900 END_PROFILE(SMBwrite);
3901 return;
3904 if (!CHECK_WRITE(fsp)) {
3905 reply_doserror(req, ERRDOS, ERRbadaccess);
3906 END_PROFILE(SMBwrite);
3907 return;
3910 numtowrite = SVAL(req->vwv+1, 0);
3911 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3912 data = (const char *)req->buf + 3;
3914 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3915 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3916 &lock);
3918 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3919 reply_doserror(req, ERRDOS, ERRlock);
3920 END_PROFILE(SMBwrite);
3921 return;
3925 * X/Open SMB protocol says that if smb_vwv1 is
3926 * zero then the file size should be extended or
3927 * truncated to the size given in smb_vwv[2-3].
3930 if(numtowrite == 0) {
3932 * This is actually an allocate call, and set EOF. JRA.
3934 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3935 if (nwritten < 0) {
3936 reply_nterror(req, NT_STATUS_DISK_FULL);
3937 goto strict_unlock;
3939 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3940 if (nwritten < 0) {
3941 reply_nterror(req, NT_STATUS_DISK_FULL);
3942 goto strict_unlock;
3944 trigger_write_time_update_immediate(fsp);
3945 } else {
3946 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3949 status = sync_file(conn, fsp, False);
3950 if (!NT_STATUS_IS_OK(status)) {
3951 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3952 fsp->fsp_name, nt_errstr(status) ));
3953 reply_nterror(req, status);
3954 goto strict_unlock;
3957 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3958 reply_unixerror(req, ERRHRD, ERRdiskfull);
3959 goto strict_unlock;
3962 reply_outbuf(req, 1, 0);
3964 SSVAL(req->outbuf,smb_vwv0,nwritten);
3966 if (nwritten < (ssize_t)numtowrite) {
3967 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3968 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3971 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3973 strict_unlock:
3974 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3976 END_PROFILE(SMBwrite);
3977 return;
3980 /****************************************************************************
3981 Ensure a buffer is a valid writeX for recvfile purposes.
3982 ****************************************************************************/
3984 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3985 (2*14) + /* word count (including bcc) */ \
3986 1 /* pad byte */)
3988 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3990 size_t numtowrite;
3991 connection_struct *conn = NULL;
3992 unsigned int doff = 0;
3993 size_t len = smb_len_large(inbuf);
3995 if (is_encrypted_packet(inbuf)) {
3996 /* Can't do this on encrypted
3997 * connections. */
3998 return false;
4001 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4002 return false;
4005 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4006 CVAL(inbuf,smb_wct) != 14) {
4007 DEBUG(10,("is_valid_writeX_buffer: chained or "
4008 "invalid word length.\n"));
4009 return false;
4012 conn = conn_find(SVAL(inbuf, smb_tid));
4013 if (conn == NULL) {
4014 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4015 return false;
4017 if (IS_IPC(conn)) {
4018 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4019 return false;
4021 if (IS_PRINT(conn)) {
4022 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4023 return false;
4025 doff = SVAL(inbuf,smb_vwv11);
4027 numtowrite = SVAL(inbuf,smb_vwv10);
4029 if (len > doff && len - doff > 0xFFFF) {
4030 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4033 if (numtowrite == 0) {
4034 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4035 return false;
4038 /* Ensure the sizes match up. */
4039 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4040 /* no pad byte...old smbclient :-( */
4041 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4042 (unsigned int)doff,
4043 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4044 return false;
4047 if (len - doff != numtowrite) {
4048 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4049 "len = %u, doff = %u, numtowrite = %u\n",
4050 (unsigned int)len,
4051 (unsigned int)doff,
4052 (unsigned int)numtowrite ));
4053 return false;
4056 DEBUG(10,("is_valid_writeX_buffer: true "
4057 "len = %u, doff = %u, numtowrite = %u\n",
4058 (unsigned int)len,
4059 (unsigned int)doff,
4060 (unsigned int)numtowrite ));
4062 return true;
4065 /****************************************************************************
4066 Reply to a write and X.
4067 ****************************************************************************/
4069 void reply_write_and_X(struct smb_request *req)
4071 connection_struct *conn = req->conn;
4072 files_struct *fsp;
4073 struct lock_struct lock;
4074 SMB_OFF_T startpos;
4075 size_t numtowrite;
4076 bool write_through;
4077 ssize_t nwritten;
4078 unsigned int smb_doff;
4079 unsigned int smblen;
4080 char *data;
4081 NTSTATUS status;
4083 START_PROFILE(SMBwriteX);
4085 if ((req->wct != 12) && (req->wct != 14)) {
4086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4087 END_PROFILE(SMBwriteX);
4088 return;
4091 numtowrite = SVAL(req->vwv+10, 0);
4092 smb_doff = SVAL(req->vwv+11, 0);
4093 smblen = smb_len(req->inbuf);
4095 if (req->unread_bytes > 0xFFFF ||
4096 (smblen > smb_doff &&
4097 smblen - smb_doff > 0xFFFF)) {
4098 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4101 if (req->unread_bytes) {
4102 /* Can't do a recvfile write on IPC$ */
4103 if (IS_IPC(conn)) {
4104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4105 END_PROFILE(SMBwriteX);
4106 return;
4108 if (numtowrite != req->unread_bytes) {
4109 reply_doserror(req, ERRDOS, ERRbadmem);
4110 END_PROFILE(SMBwriteX);
4111 return;
4113 } else {
4114 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4115 smb_doff + numtowrite > smblen) {
4116 reply_doserror(req, ERRDOS, ERRbadmem);
4117 END_PROFILE(SMBwriteX);
4118 return;
4122 /* If it's an IPC, pass off the pipe handler. */
4123 if (IS_IPC(conn)) {
4124 if (req->unread_bytes) {
4125 reply_doserror(req, ERRDOS, ERRbadmem);
4126 END_PROFILE(SMBwriteX);
4127 return;
4129 reply_pipe_write_and_X(req);
4130 END_PROFILE(SMBwriteX);
4131 return;
4134 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4135 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4136 write_through = BITSETW(req->vwv+7,0);
4138 if (!check_fsp(conn, req, fsp)) {
4139 END_PROFILE(SMBwriteX);
4140 return;
4143 if (!CHECK_WRITE(fsp)) {
4144 reply_doserror(req, ERRDOS, ERRbadaccess);
4145 END_PROFILE(SMBwriteX);
4146 return;
4149 data = smb_base(req->inbuf) + smb_doff;
4151 if(req->wct == 14) {
4152 #ifdef LARGE_SMB_OFF_T
4154 * This is a large offset (64 bit) write.
4156 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4158 #else /* !LARGE_SMB_OFF_T */
4161 * Ensure we haven't been sent a >32 bit offset.
4164 if(IVAL(req->vwv+12, 0) != 0) {
4165 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4166 "used and we don't support 64 bit offsets.\n",
4167 (unsigned int)IVAL(req->vwv+12, 0) ));
4168 reply_doserror(req, ERRDOS, ERRbadaccess);
4169 END_PROFILE(SMBwriteX);
4170 return;
4173 #endif /* LARGE_SMB_OFF_T */
4176 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4177 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4178 &lock);
4180 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4181 reply_doserror(req, ERRDOS, ERRlock);
4182 END_PROFILE(SMBwriteX);
4183 return;
4186 /* X/Open SMB protocol says that, unlike SMBwrite
4187 if the length is zero then NO truncation is
4188 done, just a write of zero. To truncate a file,
4189 use SMBwrite. */
4191 if(numtowrite == 0) {
4192 nwritten = 0;
4193 } else {
4195 if ((req->unread_bytes == 0) &&
4196 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4197 numtowrite)) {
4198 goto strict_unlock;
4201 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4204 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4205 reply_unixerror(req, ERRHRD, ERRdiskfull);
4206 goto strict_unlock;
4209 reply_outbuf(req, 6, 0);
4210 SSVAL(req->outbuf,smb_vwv2,nwritten);
4211 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4213 if (nwritten < (ssize_t)numtowrite) {
4214 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4215 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4218 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4219 fsp->fnum, (int)numtowrite, (int)nwritten));
4221 status = sync_file(conn, fsp, write_through);
4222 if (!NT_STATUS_IS_OK(status)) {
4223 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4224 fsp->fsp_name, nt_errstr(status) ));
4225 reply_nterror(req, status);
4226 goto strict_unlock;
4229 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4231 END_PROFILE(SMBwriteX);
4232 chain_reply(req);
4233 return;
4235 strict_unlock:
4236 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4238 END_PROFILE(SMBwriteX);
4239 return;
4242 /****************************************************************************
4243 Reply to a lseek.
4244 ****************************************************************************/
4246 void reply_lseek(struct smb_request *req)
4248 connection_struct *conn = req->conn;
4249 SMB_OFF_T startpos;
4250 SMB_OFF_T res= -1;
4251 int mode,umode;
4252 files_struct *fsp;
4254 START_PROFILE(SMBlseek);
4256 if (req->wct < 4) {
4257 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4258 END_PROFILE(SMBlseek);
4259 return;
4262 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4264 if (!check_fsp(conn, req, fsp)) {
4265 return;
4268 flush_write_cache(fsp, SEEK_FLUSH);
4270 mode = SVAL(req->vwv+1, 0) & 3;
4271 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4272 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4274 switch (mode) {
4275 case 0:
4276 umode = SEEK_SET;
4277 res = startpos;
4278 break;
4279 case 1:
4280 umode = SEEK_CUR;
4281 res = fsp->fh->pos + startpos;
4282 break;
4283 case 2:
4284 umode = SEEK_END;
4285 break;
4286 default:
4287 umode = SEEK_SET;
4288 res = startpos;
4289 break;
4292 if (umode == SEEK_END) {
4293 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4294 if(errno == EINVAL) {
4295 SMB_OFF_T current_pos = startpos;
4296 SMB_STRUCT_STAT sbuf;
4298 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4299 reply_unixerror(req, ERRDOS,
4300 ERRnoaccess);
4301 END_PROFILE(SMBlseek);
4302 return;
4305 current_pos += sbuf.st_size;
4306 if(current_pos < 0)
4307 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4311 if(res == -1) {
4312 reply_unixerror(req, ERRDOS, ERRnoaccess);
4313 END_PROFILE(SMBlseek);
4314 return;
4318 fsp->fh->pos = res;
4320 reply_outbuf(req, 2, 0);
4321 SIVAL(req->outbuf,smb_vwv0,res);
4323 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4324 fsp->fnum, (double)startpos, (double)res, mode));
4326 END_PROFILE(SMBlseek);
4327 return;
4330 /****************************************************************************
4331 Reply to a flush.
4332 ****************************************************************************/
4334 void reply_flush(struct smb_request *req)
4336 connection_struct *conn = req->conn;
4337 uint16 fnum;
4338 files_struct *fsp;
4340 START_PROFILE(SMBflush);
4342 if (req->wct < 1) {
4343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4344 return;
4347 fnum = SVAL(req->vwv+0, 0);
4348 fsp = file_fsp(req, fnum);
4350 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4351 return;
4354 if (!fsp) {
4355 file_sync_all(conn);
4356 } else {
4357 NTSTATUS status = sync_file(conn, fsp, True);
4358 if (!NT_STATUS_IS_OK(status)) {
4359 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4360 fsp->fsp_name, nt_errstr(status) ));
4361 reply_nterror(req, status);
4362 END_PROFILE(SMBflush);
4363 return;
4367 reply_outbuf(req, 0, 0);
4369 DEBUG(3,("flush\n"));
4370 END_PROFILE(SMBflush);
4371 return;
4374 /****************************************************************************
4375 Reply to a exit.
4376 conn POINTER CAN BE NULL HERE !
4377 ****************************************************************************/
4379 void reply_exit(struct smb_request *req)
4381 START_PROFILE(SMBexit);
4383 file_close_pid(req->smbpid, req->vuid);
4385 reply_outbuf(req, 0, 0);
4387 DEBUG(3,("exit\n"));
4389 END_PROFILE(SMBexit);
4390 return;
4393 /****************************************************************************
4394 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4395 ****************************************************************************/
4397 void reply_close(struct smb_request *req)
4399 connection_struct *conn = req->conn;
4400 NTSTATUS status = NT_STATUS_OK;
4401 files_struct *fsp = NULL;
4402 START_PROFILE(SMBclose);
4404 if (req->wct < 3) {
4405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4406 END_PROFILE(SMBclose);
4407 return;
4410 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4413 * We can only use check_fsp if we know it's not a directory.
4416 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4417 reply_doserror(req, ERRDOS, ERRbadfid);
4418 END_PROFILE(SMBclose);
4419 return;
4422 if(fsp->is_directory) {
4424 * Special case - close NT SMB directory handle.
4426 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4427 status = close_file(req, fsp, NORMAL_CLOSE);
4428 } else {
4429 time_t t;
4431 * Close ordinary file.
4434 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4435 fsp->fh->fd, fsp->fnum,
4436 conn->num_files_open));
4439 * Take care of any time sent in the close.
4442 t = srv_make_unix_date3(req->vwv+1);
4443 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4446 * close_file() returns the unix errno if an error
4447 * was detected on close - normally this is due to
4448 * a disk full error. If not then it was probably an I/O error.
4451 status = close_file(req, fsp, NORMAL_CLOSE);
4454 if (!NT_STATUS_IS_OK(status)) {
4455 reply_nterror(req, status);
4456 END_PROFILE(SMBclose);
4457 return;
4460 reply_outbuf(req, 0, 0);
4461 END_PROFILE(SMBclose);
4462 return;
4465 /****************************************************************************
4466 Reply to a writeclose (Core+ protocol).
4467 ****************************************************************************/
4469 void reply_writeclose(struct smb_request *req)
4471 connection_struct *conn = req->conn;
4472 size_t numtowrite;
4473 ssize_t nwritten = -1;
4474 NTSTATUS close_status = NT_STATUS_OK;
4475 SMB_OFF_T startpos;
4476 const char *data;
4477 struct timespec mtime;
4478 files_struct *fsp;
4479 struct lock_struct lock;
4481 START_PROFILE(SMBwriteclose);
4483 if (req->wct < 6) {
4484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4485 END_PROFILE(SMBwriteclose);
4486 return;
4489 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4491 if (!check_fsp(conn, req, fsp)) {
4492 END_PROFILE(SMBwriteclose);
4493 return;
4495 if (!CHECK_WRITE(fsp)) {
4496 reply_doserror(req, ERRDOS,ERRbadaccess);
4497 END_PROFILE(SMBwriteclose);
4498 return;
4501 numtowrite = SVAL(req->vwv+1, 0);
4502 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4503 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4504 data = (const char *)req->buf + 1;
4506 if (numtowrite) {
4507 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4508 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4509 &lock);
4511 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4512 reply_doserror(req, ERRDOS,ERRlock);
4513 END_PROFILE(SMBwriteclose);
4514 return;
4518 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4520 set_close_write_time(fsp, mtime);
4523 * More insanity. W2K only closes the file if writelen > 0.
4524 * JRA.
4527 if (numtowrite) {
4528 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4529 fsp->fsp_name ));
4530 close_status = close_file(req, fsp, NORMAL_CLOSE);
4533 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4534 fsp->fnum, (int)numtowrite, (int)nwritten,
4535 conn->num_files_open));
4537 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4538 reply_doserror(req, ERRHRD, ERRdiskfull);
4539 goto strict_unlock;
4542 if(!NT_STATUS_IS_OK(close_status)) {
4543 reply_nterror(req, close_status);
4544 goto strict_unlock;
4547 reply_outbuf(req, 1, 0);
4549 SSVAL(req->outbuf,smb_vwv0,nwritten);
4551 strict_unlock:
4552 if (numtowrite) {
4553 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4556 END_PROFILE(SMBwriteclose);
4557 return;
4560 #undef DBGC_CLASS
4561 #define DBGC_CLASS DBGC_LOCKING
4563 /****************************************************************************
4564 Reply to a lock.
4565 ****************************************************************************/
4567 void reply_lock(struct smb_request *req)
4569 connection_struct *conn = req->conn;
4570 uint64_t count,offset;
4571 NTSTATUS status;
4572 files_struct *fsp;
4573 struct byte_range_lock *br_lck = NULL;
4575 START_PROFILE(SMBlock);
4577 if (req->wct < 5) {
4578 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4579 END_PROFILE(SMBlock);
4580 return;
4583 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4585 if (!check_fsp(conn, req, fsp)) {
4586 END_PROFILE(SMBlock);
4587 return;
4590 count = (uint64_t)IVAL(req->vwv+1, 0);
4591 offset = (uint64_t)IVAL(req->vwv+3, 0);
4593 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4594 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4596 br_lck = do_lock(smbd_messaging_context(),
4597 fsp,
4598 req->smbpid,
4599 count,
4600 offset,
4601 WRITE_LOCK,
4602 WINDOWS_LOCK,
4603 False, /* Non-blocking lock. */
4604 &status,
4605 NULL,
4606 NULL);
4608 TALLOC_FREE(br_lck);
4610 if (NT_STATUS_V(status)) {
4611 reply_nterror(req, status);
4612 END_PROFILE(SMBlock);
4613 return;
4616 reply_outbuf(req, 0, 0);
4618 END_PROFILE(SMBlock);
4619 return;
4622 /****************************************************************************
4623 Reply to a unlock.
4624 ****************************************************************************/
4626 void reply_unlock(struct smb_request *req)
4628 connection_struct *conn = req->conn;
4629 uint64_t count,offset;
4630 NTSTATUS status;
4631 files_struct *fsp;
4633 START_PROFILE(SMBunlock);
4635 if (req->wct < 5) {
4636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4637 END_PROFILE(SMBunlock);
4638 return;
4641 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4643 if (!check_fsp(conn, req, fsp)) {
4644 END_PROFILE(SMBunlock);
4645 return;
4648 count = (uint64_t)IVAL(req->vwv+1, 0);
4649 offset = (uint64_t)IVAL(req->vwv+3, 0);
4651 status = do_unlock(smbd_messaging_context(),
4652 fsp,
4653 req->smbpid,
4654 count,
4655 offset,
4656 WINDOWS_LOCK);
4658 if (NT_STATUS_V(status)) {
4659 reply_nterror(req, status);
4660 END_PROFILE(SMBunlock);
4661 return;
4664 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4665 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4667 reply_outbuf(req, 0, 0);
4669 END_PROFILE(SMBunlock);
4670 return;
4673 #undef DBGC_CLASS
4674 #define DBGC_CLASS DBGC_ALL
4676 /****************************************************************************
4677 Reply to a tdis.
4678 conn POINTER CAN BE NULL HERE !
4679 ****************************************************************************/
4681 void reply_tdis(struct smb_request *req)
4683 connection_struct *conn = req->conn;
4684 START_PROFILE(SMBtdis);
4686 if (!conn) {
4687 DEBUG(4,("Invalid connection in tdis\n"));
4688 reply_doserror(req, ERRSRV, ERRinvnid);
4689 END_PROFILE(SMBtdis);
4690 return;
4693 conn->used = False;
4695 close_cnum(conn,req->vuid);
4696 req->conn = NULL;
4698 reply_outbuf(req, 0, 0);
4699 END_PROFILE(SMBtdis);
4700 return;
4703 /****************************************************************************
4704 Reply to a echo.
4705 conn POINTER CAN BE NULL HERE !
4706 ****************************************************************************/
4708 void reply_echo(struct smb_request *req)
4710 connection_struct *conn = req->conn;
4711 struct smb_perfcount_data local_pcd;
4712 struct smb_perfcount_data *cur_pcd;
4713 int smb_reverb;
4714 int seq_num;
4716 START_PROFILE(SMBecho);
4718 smb_init_perfcount_data(&local_pcd);
4720 if (req->wct < 1) {
4721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4722 END_PROFILE(SMBecho);
4723 return;
4726 smb_reverb = SVAL(req->vwv+0, 0);
4728 reply_outbuf(req, 1, req->buflen);
4730 /* copy any incoming data back out */
4731 if (req->buflen > 0) {
4732 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4735 if (smb_reverb > 100) {
4736 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4737 smb_reverb = 100;
4740 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4742 /* this makes sure we catch the request pcd */
4743 if (seq_num == smb_reverb) {
4744 cur_pcd = &req->pcd;
4745 } else {
4746 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4747 cur_pcd = &local_pcd;
4750 SSVAL(req->outbuf,smb_vwv0,seq_num);
4752 show_msg((char *)req->outbuf);
4753 if (!srv_send_smb(smbd_server_fd(),
4754 (char *)req->outbuf,
4755 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4756 cur_pcd))
4757 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4760 DEBUG(3,("echo %d times\n", smb_reverb));
4762 TALLOC_FREE(req->outbuf);
4764 END_PROFILE(SMBecho);
4765 return;
4768 /****************************************************************************
4769 Reply to a printopen.
4770 ****************************************************************************/
4772 void reply_printopen(struct smb_request *req)
4774 connection_struct *conn = req->conn;
4775 files_struct *fsp;
4776 SMB_STRUCT_STAT sbuf;
4777 NTSTATUS status;
4779 START_PROFILE(SMBsplopen);
4781 if (req->wct < 2) {
4782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4783 END_PROFILE(SMBsplopen);
4784 return;
4787 if (!CAN_PRINT(conn)) {
4788 reply_doserror(req, ERRDOS, ERRnoaccess);
4789 END_PROFILE(SMBsplopen);
4790 return;
4793 status = file_new(req, conn, &fsp);
4794 if(!NT_STATUS_IS_OK(status)) {
4795 reply_nterror(req, status);
4796 END_PROFILE(SMBsplopen);
4797 return;
4800 /* Open for exclusive use, write only. */
4801 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4803 if (!NT_STATUS_IS_OK(status)) {
4804 reply_nterror(req, status);
4805 END_PROFILE(SMBsplopen);
4806 return;
4809 reply_outbuf(req, 1, 0);
4810 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4812 DEBUG(3,("openprint fd=%d fnum=%d\n",
4813 fsp->fh->fd, fsp->fnum));
4815 END_PROFILE(SMBsplopen);
4816 return;
4819 /****************************************************************************
4820 Reply to a printclose.
4821 ****************************************************************************/
4823 void reply_printclose(struct smb_request *req)
4825 connection_struct *conn = req->conn;
4826 files_struct *fsp;
4827 NTSTATUS status;
4829 START_PROFILE(SMBsplclose);
4831 if (req->wct < 1) {
4832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4833 END_PROFILE(SMBsplclose);
4834 return;
4837 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4839 if (!check_fsp(conn, req, fsp)) {
4840 END_PROFILE(SMBsplclose);
4841 return;
4844 if (!CAN_PRINT(conn)) {
4845 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4846 END_PROFILE(SMBsplclose);
4847 return;
4850 DEBUG(3,("printclose fd=%d fnum=%d\n",
4851 fsp->fh->fd,fsp->fnum));
4853 status = close_file(req, fsp, NORMAL_CLOSE);
4855 if(!NT_STATUS_IS_OK(status)) {
4856 reply_nterror(req, status);
4857 END_PROFILE(SMBsplclose);
4858 return;
4861 reply_outbuf(req, 0, 0);
4863 END_PROFILE(SMBsplclose);
4864 return;
4867 /****************************************************************************
4868 Reply to a printqueue.
4869 ****************************************************************************/
4871 void reply_printqueue(struct smb_request *req)
4873 connection_struct *conn = req->conn;
4874 int max_count;
4875 int start_index;
4877 START_PROFILE(SMBsplretq);
4879 if (req->wct < 2) {
4880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4881 END_PROFILE(SMBsplretq);
4882 return;
4885 max_count = SVAL(req->vwv+0, 0);
4886 start_index = SVAL(req->vwv+1, 0);
4888 /* we used to allow the client to get the cnum wrong, but that
4889 is really quite gross and only worked when there was only
4890 one printer - I think we should now only accept it if they
4891 get it right (tridge) */
4892 if (!CAN_PRINT(conn)) {
4893 reply_doserror(req, ERRDOS, ERRnoaccess);
4894 END_PROFILE(SMBsplretq);
4895 return;
4898 reply_outbuf(req, 2, 3);
4899 SSVAL(req->outbuf,smb_vwv0,0);
4900 SSVAL(req->outbuf,smb_vwv1,0);
4901 SCVAL(smb_buf(req->outbuf),0,1);
4902 SSVAL(smb_buf(req->outbuf),1,0);
4904 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4905 start_index, max_count));
4908 print_queue_struct *queue = NULL;
4909 print_status_struct status;
4910 int count = print_queue_status(SNUM(conn), &queue, &status);
4911 int num_to_get = ABS(max_count);
4912 int first = (max_count>0?start_index:start_index+max_count+1);
4913 int i;
4915 if (first >= count)
4916 num_to_get = 0;
4917 else
4918 num_to_get = MIN(num_to_get,count-first);
4921 for (i=first;i<first+num_to_get;i++) {
4922 char blob[28];
4923 char *p = blob;
4925 srv_put_dos_date2(p,0,queue[i].time);
4926 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4927 SSVAL(p,5, queue[i].job);
4928 SIVAL(p,7,queue[i].size);
4929 SCVAL(p,11,0);
4930 srvstr_push(blob, req->flags2, p+12,
4931 queue[i].fs_user, 16, STR_ASCII);
4933 if (message_push_blob(
4934 &req->outbuf,
4935 data_blob_const(
4936 blob, sizeof(blob))) == -1) {
4937 reply_nterror(req, NT_STATUS_NO_MEMORY);
4938 END_PROFILE(SMBsplretq);
4939 return;
4943 if (count > 0) {
4944 SSVAL(req->outbuf,smb_vwv0,count);
4945 SSVAL(req->outbuf,smb_vwv1,
4946 (max_count>0?first+count:first-1));
4947 SCVAL(smb_buf(req->outbuf),0,1);
4948 SSVAL(smb_buf(req->outbuf),1,28*count);
4951 SAFE_FREE(queue);
4953 DEBUG(3,("%d entries returned in queue\n",count));
4956 END_PROFILE(SMBsplretq);
4957 return;
4960 /****************************************************************************
4961 Reply to a printwrite.
4962 ****************************************************************************/
4964 void reply_printwrite(struct smb_request *req)
4966 connection_struct *conn = req->conn;
4967 int numtowrite;
4968 const char *data;
4969 files_struct *fsp;
4971 START_PROFILE(SMBsplwr);
4973 if (req->wct < 1) {
4974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4975 END_PROFILE(SMBsplwr);
4976 return;
4979 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4981 if (!check_fsp(conn, req, fsp)) {
4982 END_PROFILE(SMBsplwr);
4983 return;
4986 if (!CAN_PRINT(conn)) {
4987 reply_doserror(req, ERRDOS, ERRnoaccess);
4988 END_PROFILE(SMBsplwr);
4989 return;
4992 if (!CHECK_WRITE(fsp)) {
4993 reply_doserror(req, ERRDOS, ERRbadaccess);
4994 END_PROFILE(SMBsplwr);
4995 return;
4998 numtowrite = SVAL(req->buf, 1);
5000 if (req->buflen < numtowrite + 3) {
5001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5002 END_PROFILE(SMBsplwr);
5003 return;
5006 data = (const char *)req->buf + 3;
5008 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5009 reply_unixerror(req, ERRHRD, ERRdiskfull);
5010 END_PROFILE(SMBsplwr);
5011 return;
5014 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5016 END_PROFILE(SMBsplwr);
5017 return;
5020 /****************************************************************************
5021 Reply to a mkdir.
5022 ****************************************************************************/
5024 void reply_mkdir(struct smb_request *req)
5026 connection_struct *conn = req->conn;
5027 char *directory = NULL;
5028 NTSTATUS status;
5029 SMB_STRUCT_STAT sbuf;
5030 TALLOC_CTX *ctx = talloc_tos();
5032 START_PROFILE(SMBmkdir);
5034 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5035 STR_TERMINATE, &status);
5036 if (!NT_STATUS_IS_OK(status)) {
5037 reply_nterror(req, status);
5038 END_PROFILE(SMBmkdir);
5039 return;
5042 status = resolve_dfspath(ctx, conn,
5043 req->flags2 & FLAGS2_DFS_PATHNAMES,
5044 directory,
5045 &directory);
5046 if (!NT_STATUS_IS_OK(status)) {
5047 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5048 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5049 ERRSRV, ERRbadpath);
5050 END_PROFILE(SMBmkdir);
5051 return;
5053 reply_nterror(req, status);
5054 END_PROFILE(SMBmkdir);
5055 return;
5058 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
5059 if (!NT_STATUS_IS_OK(status)) {
5060 reply_nterror(req, status);
5061 END_PROFILE(SMBmkdir);
5062 return;
5065 status = check_name(conn, directory);
5066 if (!NT_STATUS_IS_OK(status)) {
5067 reply_nterror(req, status);
5068 END_PROFILE(SMBmkdir);
5069 return;
5072 status = create_directory(conn, req, directory);
5074 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5076 if (!NT_STATUS_IS_OK(status)) {
5078 if (!use_nt_status()
5079 && NT_STATUS_EQUAL(status,
5080 NT_STATUS_OBJECT_NAME_COLLISION)) {
5082 * Yes, in the DOS error code case we get a
5083 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5084 * samba4 torture test.
5086 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5089 reply_nterror(req, status);
5090 END_PROFILE(SMBmkdir);
5091 return;
5094 reply_outbuf(req, 0, 0);
5096 DEBUG( 3, ( "mkdir %s\n", directory ) );
5098 END_PROFILE(SMBmkdir);
5099 return;
5102 /****************************************************************************
5103 Static function used by reply_rmdir to delete an entire directory
5104 tree recursively. Return True on ok, False on fail.
5105 ****************************************************************************/
5107 static bool recursive_rmdir(TALLOC_CTX *ctx,
5108 connection_struct *conn,
5109 char *directory)
5111 const char *dname = NULL;
5112 bool ret = True;
5113 long offset = 0;
5114 SMB_STRUCT_STAT st;
5115 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5116 NULL, 0);
5118 if(dir_hnd == NULL)
5119 return False;
5121 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5122 char *fullname = NULL;
5124 if (ISDOT(dname) || ISDOTDOT(dname)) {
5125 continue;
5128 if (!is_visible_file(conn, directory, dname, &st, False)) {
5129 continue;
5132 /* Construct the full name. */
5133 fullname = talloc_asprintf(ctx,
5134 "%s/%s",
5135 directory,
5136 dname);
5137 if (!fullname) {
5138 errno = ENOMEM;
5139 ret = False;
5140 break;
5143 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5144 ret = False;
5145 break;
5148 if(st.st_mode & S_IFDIR) {
5149 if(!recursive_rmdir(ctx, conn, fullname)) {
5150 ret = False;
5151 break;
5153 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5154 ret = False;
5155 break;
5157 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5158 ret = False;
5159 break;
5161 TALLOC_FREE(fullname);
5163 TALLOC_FREE(dir_hnd);
5164 return ret;
5167 /****************************************************************************
5168 The internals of the rmdir code - called elsewhere.
5169 ****************************************************************************/
5171 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5172 connection_struct *conn,
5173 const char *directory)
5175 int ret;
5176 SMB_STRUCT_STAT st;
5178 /* Might be a symlink. */
5179 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5180 return map_nt_error_from_unix(errno);
5183 if (S_ISLNK(st.st_mode)) {
5184 /* Is what it points to a directory ? */
5185 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5186 return map_nt_error_from_unix(errno);
5188 if (!(S_ISDIR(st.st_mode))) {
5189 return NT_STATUS_NOT_A_DIRECTORY;
5191 ret = SMB_VFS_UNLINK(conn,directory);
5192 } else {
5193 ret = SMB_VFS_RMDIR(conn,directory);
5195 if (ret == 0) {
5196 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5197 FILE_NOTIFY_CHANGE_DIR_NAME,
5198 directory);
5199 return NT_STATUS_OK;
5202 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5204 * Check to see if the only thing in this directory are
5205 * vetoed files/directories. If so then delete them and
5206 * retry. If we fail to delete any of them (and we *don't*
5207 * do a recursive delete) then fail the rmdir.
5209 const char *dname;
5210 long dirpos = 0;
5211 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5212 directory, NULL, 0);
5214 if(dir_hnd == NULL) {
5215 errno = ENOTEMPTY;
5216 goto err;
5219 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5220 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5221 continue;
5222 if (!is_visible_file(conn, directory, dname, &st, False))
5223 continue;
5224 if(!IS_VETO_PATH(conn, dname)) {
5225 TALLOC_FREE(dir_hnd);
5226 errno = ENOTEMPTY;
5227 goto err;
5231 /* We only have veto files/directories.
5232 * Are we allowed to delete them ? */
5234 if(!lp_recursive_veto_delete(SNUM(conn))) {
5235 TALLOC_FREE(dir_hnd);
5236 errno = ENOTEMPTY;
5237 goto err;
5240 /* Do a recursive delete. */
5241 RewindDir(dir_hnd,&dirpos);
5242 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5243 char *fullname = NULL;
5245 if (ISDOT(dname) || ISDOTDOT(dname)) {
5246 continue;
5248 if (!is_visible_file(conn, directory, dname, &st, False)) {
5249 continue;
5252 fullname = talloc_asprintf(ctx,
5253 "%s/%s",
5254 directory,
5255 dname);
5257 if(!fullname) {
5258 errno = ENOMEM;
5259 break;
5262 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5263 break;
5265 if(st.st_mode & S_IFDIR) {
5266 if(!recursive_rmdir(ctx, conn, fullname)) {
5267 break;
5269 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5270 break;
5272 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5273 break;
5275 TALLOC_FREE(fullname);
5277 TALLOC_FREE(dir_hnd);
5278 /* Retry the rmdir */
5279 ret = SMB_VFS_RMDIR(conn,directory);
5282 err:
5284 if (ret != 0) {
5285 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5286 "%s\n", directory,strerror(errno)));
5287 return map_nt_error_from_unix(errno);
5290 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5291 FILE_NOTIFY_CHANGE_DIR_NAME,
5292 directory);
5294 return NT_STATUS_OK;
5297 /****************************************************************************
5298 Reply to a rmdir.
5299 ****************************************************************************/
5301 void reply_rmdir(struct smb_request *req)
5303 connection_struct *conn = req->conn;
5304 char *directory = NULL;
5305 SMB_STRUCT_STAT sbuf;
5306 NTSTATUS status;
5307 TALLOC_CTX *ctx = talloc_tos();
5309 START_PROFILE(SMBrmdir);
5311 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5312 STR_TERMINATE, &status);
5313 if (!NT_STATUS_IS_OK(status)) {
5314 reply_nterror(req, status);
5315 END_PROFILE(SMBrmdir);
5316 return;
5319 status = resolve_dfspath(ctx, conn,
5320 req->flags2 & FLAGS2_DFS_PATHNAMES,
5321 directory,
5322 &directory);
5323 if (!NT_STATUS_IS_OK(status)) {
5324 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5325 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5326 ERRSRV, ERRbadpath);
5327 END_PROFILE(SMBrmdir);
5328 return;
5330 reply_nterror(req, status);
5331 END_PROFILE(SMBrmdir);
5332 return;
5335 status = unix_convert(ctx, conn, directory, False, &directory,
5336 NULL, &sbuf);
5337 if (!NT_STATUS_IS_OK(status)) {
5338 reply_nterror(req, status);
5339 END_PROFILE(SMBrmdir);
5340 return;
5343 status = check_name(conn, directory);
5344 if (!NT_STATUS_IS_OK(status)) {
5345 reply_nterror(req, status);
5346 END_PROFILE(SMBrmdir);
5347 return;
5350 dptr_closepath(directory, req->smbpid);
5351 status = rmdir_internals(ctx, conn, directory);
5352 if (!NT_STATUS_IS_OK(status)) {
5353 reply_nterror(req, status);
5354 END_PROFILE(SMBrmdir);
5355 return;
5358 reply_outbuf(req, 0, 0);
5360 DEBUG( 3, ( "rmdir %s\n", directory ) );
5362 END_PROFILE(SMBrmdir);
5363 return;
5366 /*******************************************************************
5367 Resolve wildcards in a filename rename.
5368 ********************************************************************/
5370 static bool resolve_wildcards(TALLOC_CTX *ctx,
5371 const char *name1,
5372 const char *name2,
5373 char **pp_newname)
5375 char *name2_copy = NULL;
5376 char *root1 = NULL;
5377 char *root2 = NULL;
5378 char *ext1 = NULL;
5379 char *ext2 = NULL;
5380 char *p,*p2, *pname1, *pname2;
5382 name2_copy = talloc_strdup(ctx, name2);
5383 if (!name2_copy) {
5384 return False;
5387 pname1 = strrchr_m(name1,'/');
5388 pname2 = strrchr_m(name2_copy,'/');
5390 if (!pname1 || !pname2) {
5391 return False;
5394 /* Truncate the copy of name2 at the last '/' */
5395 *pname2 = '\0';
5397 /* Now go past the '/' */
5398 pname1++;
5399 pname2++;
5401 root1 = talloc_strdup(ctx, pname1);
5402 root2 = talloc_strdup(ctx, pname2);
5404 if (!root1 || !root2) {
5405 return False;
5408 p = strrchr_m(root1,'.');
5409 if (p) {
5410 *p = 0;
5411 ext1 = talloc_strdup(ctx, p+1);
5412 } else {
5413 ext1 = talloc_strdup(ctx, "");
5415 p = strrchr_m(root2,'.');
5416 if (p) {
5417 *p = 0;
5418 ext2 = talloc_strdup(ctx, p+1);
5419 } else {
5420 ext2 = talloc_strdup(ctx, "");
5423 if (!ext1 || !ext2) {
5424 return False;
5427 p = root1;
5428 p2 = root2;
5429 while (*p2) {
5430 if (*p2 == '?') {
5431 /* Hmmm. Should this be mb-aware ? */
5432 *p2 = *p;
5433 p2++;
5434 } else if (*p2 == '*') {
5435 *p2 = '\0';
5436 root2 = talloc_asprintf(ctx, "%s%s",
5437 root2,
5439 if (!root2) {
5440 return False;
5442 break;
5443 } else {
5444 p2++;
5446 if (*p) {
5447 p++;
5451 p = ext1;
5452 p2 = ext2;
5453 while (*p2) {
5454 if (*p2 == '?') {
5455 /* Hmmm. Should this be mb-aware ? */
5456 *p2 = *p;
5457 p2++;
5458 } else if (*p2 == '*') {
5459 *p2 = '\0';
5460 ext2 = talloc_asprintf(ctx, "%s%s",
5461 ext2,
5463 if (!ext2) {
5464 return False;
5466 break;
5467 } else {
5468 p2++;
5470 if (*p) {
5471 p++;
5475 if (*ext2) {
5476 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5477 name2_copy,
5478 root2,
5479 ext2);
5480 } else {
5481 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5482 name2_copy,
5483 root2);
5486 if (!*pp_newname) {
5487 return False;
5490 return True;
5493 /****************************************************************************
5494 Ensure open files have their names updated. Updated to notify other smbd's
5495 asynchronously.
5496 ****************************************************************************/
5498 static void rename_open_files(connection_struct *conn,
5499 struct share_mode_lock *lck,
5500 const char *newname)
5502 files_struct *fsp;
5503 bool did_rename = False;
5505 for(fsp = file_find_di_first(lck->id); fsp;
5506 fsp = file_find_di_next(fsp)) {
5507 /* fsp_name is a relative path under the fsp. To change this for other
5508 sharepaths we need to manipulate relative paths. */
5509 /* TODO - create the absolute path and manipulate the newname
5510 relative to the sharepath. */
5511 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5512 continue;
5514 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5515 fsp->fnum, file_id_string_tos(&fsp->file_id),
5516 fsp->fsp_name, newname ));
5517 string_set(&fsp->fsp_name, newname);
5518 did_rename = True;
5521 if (!did_rename) {
5522 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5523 file_id_string_tos(&lck->id), newname ));
5526 /* Send messages to all smbd's (not ourself) that the name has changed. */
5527 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5528 newname);
5531 /****************************************************************************
5532 We need to check if the source path is a parent directory of the destination
5533 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5534 refuse the rename with a sharing violation. Under UNIX the above call can
5535 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5536 probably need to check that the client is a Windows one before disallowing
5537 this as a UNIX client (one with UNIX extensions) can know the source is a
5538 symlink and make this decision intelligently. Found by an excellent bug
5539 report from <AndyLiebman@aol.com>.
5540 ****************************************************************************/
5542 static bool rename_path_prefix_equal(const char *src, const char *dest)
5544 const char *psrc = src;
5545 const char *pdst = dest;
5546 size_t slen;
5548 if (psrc[0] == '.' && psrc[1] == '/') {
5549 psrc += 2;
5551 if (pdst[0] == '.' && pdst[1] == '/') {
5552 pdst += 2;
5554 if ((slen = strlen(psrc)) > strlen(pdst)) {
5555 return False;
5557 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5561 * Do the notify calls from a rename
5564 static void notify_rename(connection_struct *conn, bool is_dir,
5565 const char *oldpath, const char *newpath)
5567 char *olddir, *newdir;
5568 const char *oldname, *newname;
5569 uint32 mask;
5571 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5572 : FILE_NOTIFY_CHANGE_FILE_NAME;
5574 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5575 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5576 TALLOC_FREE(olddir);
5577 return;
5580 if (strcmp(olddir, newdir) == 0) {
5581 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5582 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5584 else {
5585 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5586 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5588 TALLOC_FREE(olddir);
5589 TALLOC_FREE(newdir);
5591 /* this is a strange one. w2k3 gives an additional event for
5592 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5593 files, but not directories */
5594 if (!is_dir) {
5595 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5596 FILE_NOTIFY_CHANGE_ATTRIBUTES
5597 |FILE_NOTIFY_CHANGE_CREATION,
5598 newpath);
5602 /****************************************************************************
5603 Rename an open file - given an fsp.
5604 ****************************************************************************/
5606 NTSTATUS rename_internals_fsp(connection_struct *conn,
5607 files_struct *fsp,
5608 char *newname,
5609 const char *newname_last_component,
5610 uint32 attrs,
5611 bool replace_if_exists)
5613 TALLOC_CTX *ctx = talloc_tos();
5614 SMB_STRUCT_STAT sbuf, sbuf1;
5615 NTSTATUS status = NT_STATUS_OK;
5616 struct share_mode_lock *lck = NULL;
5617 bool dst_exists, old_is_stream, new_is_stream;
5619 ZERO_STRUCT(sbuf);
5621 status = check_name(conn, newname);
5622 if (!NT_STATUS_IS_OK(status)) {
5623 return status;
5626 /* Ensure newname contains a '/' */
5627 if(strrchr_m(newname,'/') == 0) {
5628 newname = talloc_asprintf(ctx,
5629 "./%s",
5630 newname);
5631 if (!newname) {
5632 return NT_STATUS_NO_MEMORY;
5637 * Check for special case with case preserving and not
5638 * case sensitive. If the old last component differs from the original
5639 * last component only by case, then we should allow
5640 * the rename (user is trying to change the case of the
5641 * filename).
5644 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5645 strequal(newname, fsp->fsp_name)) {
5646 char *p;
5647 char *newname_modified_last_component = NULL;
5650 * Get the last component of the modified name.
5651 * Note that we guarantee that newname contains a '/'
5652 * character above.
5654 p = strrchr_m(newname,'/');
5655 newname_modified_last_component = talloc_strdup(ctx,
5656 p+1);
5657 if (!newname_modified_last_component) {
5658 return NT_STATUS_NO_MEMORY;
5661 if(strcsequal(newname_modified_last_component,
5662 newname_last_component) == False) {
5664 * Replace the modified last component with
5665 * the original.
5667 *p = '\0'; /* Truncate at the '/' */
5668 newname = talloc_asprintf(ctx,
5669 "%s/%s",
5670 newname,
5671 newname_last_component);
5676 * If the src and dest names are identical - including case,
5677 * don't do the rename, just return success.
5680 if (strcsequal(fsp->fsp_name, newname)) {
5681 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5682 newname));
5683 return NT_STATUS_OK;
5686 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5687 new_is_stream = is_ntfs_stream_name(newname);
5689 /* Return the correct error code if both names aren't streams. */
5690 if (!old_is_stream && new_is_stream) {
5691 return NT_STATUS_OBJECT_NAME_INVALID;
5694 if (old_is_stream && !new_is_stream) {
5695 return NT_STATUS_INVALID_PARAMETER;
5699 * Have vfs_object_exist also fill sbuf1
5701 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5703 if(!replace_if_exists && dst_exists) {
5704 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5705 fsp->fsp_name,newname));
5706 return NT_STATUS_OBJECT_NAME_COLLISION;
5709 if (dst_exists) {
5710 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5711 files_struct *dst_fsp = file_find_di_first(fileid);
5712 /* The file can be open when renaming a stream */
5713 if (dst_fsp && !new_is_stream) {
5714 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5715 return NT_STATUS_ACCESS_DENIED;
5719 /* Ensure we have a valid stat struct for the source. */
5720 if (fsp->fh->fd != -1) {
5721 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5722 return map_nt_error_from_unix(errno);
5724 } else {
5725 int ret = -1;
5726 if (fsp->posix_open) {
5727 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5728 } else {
5729 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5731 if (ret == -1) {
5732 return map_nt_error_from_unix(errno);
5736 status = can_rename(conn, fsp, attrs, &sbuf);
5738 if (!NT_STATUS_IS_OK(status)) {
5739 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5740 nt_errstr(status), fsp->fsp_name,newname));
5741 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5742 status = NT_STATUS_ACCESS_DENIED;
5743 return status;
5746 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5747 return NT_STATUS_ACCESS_DENIED;
5750 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5751 NULL);
5754 * We have the file open ourselves, so not being able to get the
5755 * corresponding share mode lock is a fatal error.
5758 SMB_ASSERT(lck != NULL);
5760 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5761 uint32 create_options = fsp->fh->private_options;
5763 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5764 fsp->fsp_name,newname));
5766 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5768 rename_open_files(conn, lck, newname);
5771 * A rename acts as a new file create w.r.t. allowing an initial delete
5772 * on close, probably because in Windows there is a new handle to the
5773 * new file. If initial delete on close was requested but not
5774 * originally set, we need to set it here. This is probably not 100% correct,
5775 * but will work for the CIFSFS client which in non-posix mode
5776 * depends on these semantics. JRA.
5779 if (create_options & FILE_DELETE_ON_CLOSE) {
5780 status = can_set_delete_on_close(fsp, True, 0);
5782 if (NT_STATUS_IS_OK(status)) {
5783 /* Note that here we set the *inital* delete on close flag,
5784 * not the regular one. The magic gets handled in close. */
5785 fsp->initial_delete_on_close = True;
5788 TALLOC_FREE(lck);
5789 return NT_STATUS_OK;
5792 TALLOC_FREE(lck);
5794 if (errno == ENOTDIR || errno == EISDIR) {
5795 status = NT_STATUS_OBJECT_NAME_COLLISION;
5796 } else {
5797 status = map_nt_error_from_unix(errno);
5800 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5801 nt_errstr(status), fsp->fsp_name,newname));
5803 return status;
5806 /****************************************************************************
5807 The guts of the rename command, split out so it may be called by the NT SMB
5808 code.
5809 ****************************************************************************/
5811 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5812 connection_struct *conn,
5813 struct smb_request *req,
5814 const char *name_in,
5815 const char *newname_in,
5816 uint32 attrs,
5817 bool replace_if_exists,
5818 bool src_has_wild,
5819 bool dest_has_wild,
5820 uint32_t access_mask)
5822 char *directory = NULL;
5823 char *mask = NULL;
5824 char *last_component_src = NULL;
5825 char *last_component_dest = NULL;
5826 char *name = NULL;
5827 char *newname = NULL;
5828 char *p;
5829 int count=0;
5830 NTSTATUS status = NT_STATUS_OK;
5831 SMB_STRUCT_STAT sbuf1, sbuf2;
5832 struct smb_Dir *dir_hnd = NULL;
5833 const char *dname;
5834 long offset = 0;
5835 int create_options = 0;
5836 bool posix_pathnames = lp_posix_pathnames();
5838 ZERO_STRUCT(sbuf1);
5839 ZERO_STRUCT(sbuf2);
5841 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5842 &last_component_src, &sbuf1);
5843 if (!NT_STATUS_IS_OK(status)) {
5844 return status;
5847 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5848 &last_component_dest, &sbuf2);
5849 if (!NT_STATUS_IS_OK(status)) {
5850 return status;
5854 * Split the old name into directory and last component
5855 * strings. Note that unix_convert may have stripped off a
5856 * leading ./ from both name and newname if the rename is
5857 * at the root of the share. We need to make sure either both
5858 * name and newname contain a / character or neither of them do
5859 * as this is checked in resolve_wildcards().
5862 p = strrchr_m(name,'/');
5863 if (!p) {
5864 directory = talloc_strdup(ctx, ".");
5865 if (!directory) {
5866 return NT_STATUS_NO_MEMORY;
5868 mask = name;
5869 } else {
5870 *p = 0;
5871 directory = talloc_strdup(ctx, name);
5872 if (!directory) {
5873 return NT_STATUS_NO_MEMORY;
5875 mask = p+1;
5876 *p = '/'; /* Replace needed for exceptional test below. */
5880 * We should only check the mangled cache
5881 * here if unix_convert failed. This means
5882 * that the path in 'mask' doesn't exist
5883 * on the file system and so we need to look
5884 * for a possible mangle. This patch from
5885 * Tine Smukavec <valentin.smukavec@hermes.si>.
5888 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5889 char *new_mask = NULL;
5890 mangle_lookup_name_from_8_3(ctx,
5891 mask,
5892 &new_mask,
5893 conn->params );
5894 if (new_mask) {
5895 mask = new_mask;
5899 if (!src_has_wild) {
5900 files_struct *fsp;
5903 * No wildcards - just process the one file.
5905 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5907 /* Add a terminating '/' to the directory name. */
5908 directory = talloc_asprintf_append(directory,
5909 "/%s",
5910 mask);
5911 if (!directory) {
5912 return NT_STATUS_NO_MEMORY;
5915 /* Ensure newname contains a '/' also */
5916 if(strrchr_m(newname,'/') == 0) {
5917 newname = talloc_asprintf(ctx,
5918 "./%s",
5919 newname);
5920 if (!newname) {
5921 return NT_STATUS_NO_MEMORY;
5925 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5926 "case_preserve = %d, short case preserve = %d, "
5927 "directory = %s, newname = %s, "
5928 "last_component_dest = %s, is_8_3 = %d\n",
5929 conn->case_sensitive, conn->case_preserve,
5930 conn->short_case_preserve, directory,
5931 newname, last_component_dest, is_short_name));
5933 /* The dest name still may have wildcards. */
5934 if (dest_has_wild) {
5935 char *mod_newname = NULL;
5936 if (!resolve_wildcards(ctx,
5937 directory,newname,&mod_newname)) {
5938 DEBUG(6, ("rename_internals: resolve_wildcards "
5939 "%s %s failed\n",
5940 directory,
5941 newname));
5942 return NT_STATUS_NO_MEMORY;
5944 newname = mod_newname;
5947 ZERO_STRUCT(sbuf1);
5948 if (posix_pathnames) {
5949 SMB_VFS_LSTAT(conn, directory, &sbuf1);
5950 } else {
5951 SMB_VFS_STAT(conn, directory, &sbuf1);
5954 if (S_ISDIR(sbuf1.st_mode)) {
5955 create_options |= FILE_DIRECTORY_FILE;
5958 status = SMB_VFS_CREATE_FILE(
5959 conn, /* conn */
5960 req, /* req */
5961 0, /* root_dir_fid */
5962 directory, /* fname */
5963 0, /* create_file_flags */
5964 access_mask, /* access_mask */
5965 (FILE_SHARE_READ | /* share_access */
5966 FILE_SHARE_WRITE),
5967 FILE_OPEN, /* create_disposition*/
5968 create_options, /* create_options */
5969 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
5970 0, /* oplock_request */
5971 0, /* allocation_size */
5972 NULL, /* sd */
5973 NULL, /* ea_list */
5974 &fsp, /* result */
5975 NULL, /* pinfo */
5976 &sbuf1); /* psbuf */
5978 if (!NT_STATUS_IS_OK(status)) {
5979 DEBUG(3, ("Could not open rename source %s: %s\n",
5980 directory, nt_errstr(status)));
5981 return status;
5984 status = rename_internals_fsp(conn, fsp, newname,
5985 last_component_dest,
5986 attrs, replace_if_exists);
5988 close_file(req, fsp, NORMAL_CLOSE);
5990 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5991 nt_errstr(status), directory,newname));
5993 return status;
5997 * Wildcards - process each file that matches.
5999 if (strequal(mask,"????????.???")) {
6000 mask[0] = '*';
6001 mask[1] = '\0';
6004 status = check_name(conn, directory);
6005 if (!NT_STATUS_IS_OK(status)) {
6006 return status;
6009 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6010 if (dir_hnd == NULL) {
6011 return map_nt_error_from_unix(errno);
6014 status = NT_STATUS_NO_SUCH_FILE;
6016 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6017 * - gentest fix. JRA
6020 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6021 files_struct *fsp = NULL;
6022 char *fname = NULL;
6023 char *destname = NULL;
6024 bool sysdir_entry = False;
6026 /* Quick check for "." and ".." */
6027 if (ISDOT(dname) || ISDOTDOT(dname)) {
6028 if (attrs & aDIR) {
6029 sysdir_entry = True;
6030 } else {
6031 continue;
6035 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6036 continue;
6039 if(!mask_match(dname, mask, conn->case_sensitive)) {
6040 continue;
6043 if (sysdir_entry) {
6044 status = NT_STATUS_OBJECT_NAME_INVALID;
6045 break;
6048 fname = talloc_asprintf(ctx,
6049 "%s/%s",
6050 directory,
6051 dname);
6052 if (!fname) {
6053 return NT_STATUS_NO_MEMORY;
6056 if (!resolve_wildcards(ctx,
6057 fname,newname,&destname)) {
6058 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6059 fname, destname));
6060 TALLOC_FREE(fname);
6061 continue;
6063 if (!destname) {
6064 return NT_STATUS_NO_MEMORY;
6067 ZERO_STRUCT(sbuf1);
6068 if (posix_pathnames) {
6069 SMB_VFS_LSTAT(conn, fname, &sbuf1);
6070 } else {
6071 SMB_VFS_STAT(conn, fname, &sbuf1);
6074 create_options = 0;
6076 if (S_ISDIR(sbuf1.st_mode)) {
6077 create_options |= FILE_DIRECTORY_FILE;
6080 status = SMB_VFS_CREATE_FILE(
6081 conn, /* conn */
6082 req, /* req */
6083 0, /* root_dir_fid */
6084 fname, /* fname */
6085 0, /* create_file_flags */
6086 access_mask, /* access_mask */
6087 (FILE_SHARE_READ | /* share_access */
6088 FILE_SHARE_WRITE),
6089 FILE_OPEN, /* create_disposition*/
6090 create_options, /* create_options */
6091 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6092 0, /* oplock_request */
6093 0, /* allocation_size */
6094 NULL, /* sd */
6095 NULL, /* ea_list */
6096 &fsp, /* result */
6097 NULL, /* pinfo */
6098 &sbuf1); /* psbuf */
6100 if (!NT_STATUS_IS_OK(status)) {
6101 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6102 "returned %s rename %s -> %s\n",
6103 nt_errstr(status), directory, newname));
6104 break;
6107 status = rename_internals_fsp(conn, fsp, destname, dname,
6108 attrs, replace_if_exists);
6110 close_file(req, fsp, NORMAL_CLOSE);
6112 if (!NT_STATUS_IS_OK(status)) {
6113 DEBUG(3, ("rename_internals_fsp returned %s for "
6114 "rename %s -> %s\n", nt_errstr(status),
6115 directory, newname));
6116 break;
6119 count++;
6121 DEBUG(3,("rename_internals: doing rename on %s -> "
6122 "%s\n",fname,destname));
6124 TALLOC_FREE(fname);
6125 TALLOC_FREE(destname);
6127 TALLOC_FREE(dir_hnd);
6129 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6130 status = map_nt_error_from_unix(errno);
6133 return status;
6136 /****************************************************************************
6137 Reply to a mv.
6138 ****************************************************************************/
6140 void reply_mv(struct smb_request *req)
6142 connection_struct *conn = req->conn;
6143 char *name = NULL;
6144 char *newname = NULL;
6145 const char *p;
6146 uint32 attrs;
6147 NTSTATUS status;
6148 bool src_has_wcard = False;
6149 bool dest_has_wcard = False;
6150 TALLOC_CTX *ctx = talloc_tos();
6152 START_PROFILE(SMBmv);
6154 if (req->wct < 1) {
6155 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6156 END_PROFILE(SMBmv);
6157 return;
6160 attrs = SVAL(req->vwv+0, 0);
6162 p = (const char *)req->buf + 1;
6163 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6164 &status, &src_has_wcard);
6165 if (!NT_STATUS_IS_OK(status)) {
6166 reply_nterror(req, status);
6167 END_PROFILE(SMBmv);
6168 return;
6170 p++;
6171 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6172 &status, &dest_has_wcard);
6173 if (!NT_STATUS_IS_OK(status)) {
6174 reply_nterror(req, status);
6175 END_PROFILE(SMBmv);
6176 return;
6179 status = resolve_dfspath_wcard(ctx, conn,
6180 req->flags2 & FLAGS2_DFS_PATHNAMES,
6181 name,
6182 &name,
6183 &src_has_wcard);
6184 if (!NT_STATUS_IS_OK(status)) {
6185 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6186 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6187 ERRSRV, ERRbadpath);
6188 END_PROFILE(SMBmv);
6189 return;
6191 reply_nterror(req, status);
6192 END_PROFILE(SMBmv);
6193 return;
6196 status = resolve_dfspath_wcard(ctx, conn,
6197 req->flags2 & FLAGS2_DFS_PATHNAMES,
6198 newname,
6199 &newname,
6200 &dest_has_wcard);
6201 if (!NT_STATUS_IS_OK(status)) {
6202 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6203 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6204 ERRSRV, ERRbadpath);
6205 END_PROFILE(SMBmv);
6206 return;
6208 reply_nterror(req, status);
6209 END_PROFILE(SMBmv);
6210 return;
6213 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6215 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6216 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6217 if (!NT_STATUS_IS_OK(status)) {
6218 if (open_was_deferred(req->mid)) {
6219 /* We have re-scheduled this call. */
6220 END_PROFILE(SMBmv);
6221 return;
6223 reply_nterror(req, status);
6224 END_PROFILE(SMBmv);
6225 return;
6228 reply_outbuf(req, 0, 0);
6230 END_PROFILE(SMBmv);
6231 return;
6234 /*******************************************************************
6235 Copy a file as part of a reply_copy.
6236 ******************************************************************/
6239 * TODO: check error codes on all callers
6242 NTSTATUS copy_file(TALLOC_CTX *ctx,
6243 connection_struct *conn,
6244 const char *src,
6245 const char *dest1,
6246 int ofun,
6247 int count,
6248 bool target_is_directory)
6250 SMB_STRUCT_STAT src_sbuf, sbuf2;
6251 SMB_OFF_T ret=-1;
6252 files_struct *fsp1,*fsp2;
6253 char *dest = NULL;
6254 uint32 dosattrs;
6255 uint32 new_create_disposition;
6256 NTSTATUS status;
6258 dest = talloc_strdup(ctx, dest1);
6259 if (!dest) {
6260 return NT_STATUS_NO_MEMORY;
6262 if (target_is_directory) {
6263 const char *p = strrchr_m(src,'/');
6264 if (p) {
6265 p++;
6266 } else {
6267 p = src;
6269 dest = talloc_asprintf_append(dest,
6270 "/%s",
6272 if (!dest) {
6273 return NT_STATUS_NO_MEMORY;
6277 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6278 TALLOC_FREE(dest);
6279 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6282 if (!target_is_directory && count) {
6283 new_create_disposition = FILE_OPEN;
6284 } else {
6285 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6286 NULL, NULL, &new_create_disposition, NULL)) {
6287 TALLOC_FREE(dest);
6288 return NT_STATUS_INVALID_PARAMETER;
6292 status = SMB_VFS_CREATE_FILE(
6293 conn, /* conn */
6294 NULL, /* req */
6295 0, /* root_dir_fid */
6296 src, /* fname */
6297 0, /* create_file_flags */
6298 FILE_GENERIC_READ, /* access_mask */
6299 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6300 FILE_OPEN, /* create_disposition*/
6301 0, /* create_options */
6302 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6303 INTERNAL_OPEN_ONLY, /* oplock_request */
6304 0, /* allocation_size */
6305 NULL, /* sd */
6306 NULL, /* ea_list */
6307 &fsp1, /* result */
6308 NULL, /* pinfo */
6309 &src_sbuf); /* psbuf */
6311 if (!NT_STATUS_IS_OK(status)) {
6312 TALLOC_FREE(dest);
6313 return status;
6316 dosattrs = dos_mode(conn, src, &src_sbuf);
6317 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6318 ZERO_STRUCTP(&sbuf2);
6321 status = SMB_VFS_CREATE_FILE(
6322 conn, /* conn */
6323 NULL, /* req */
6324 0, /* root_dir_fid */
6325 dest, /* fname */
6326 0, /* create_file_flags */
6327 FILE_GENERIC_WRITE, /* access_mask */
6328 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6329 new_create_disposition, /* create_disposition*/
6330 0, /* create_options */
6331 dosattrs, /* file_attributes */
6332 INTERNAL_OPEN_ONLY, /* oplock_request */
6333 0, /* allocation_size */
6334 NULL, /* sd */
6335 NULL, /* ea_list */
6336 &fsp2, /* result */
6337 NULL, /* pinfo */
6338 &sbuf2); /* psbuf */
6340 TALLOC_FREE(dest);
6342 if (!NT_STATUS_IS_OK(status)) {
6343 close_file(NULL, fsp1, ERROR_CLOSE);
6344 return status;
6347 if ((ofun&3) == 1) {
6348 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6349 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6351 * Stop the copy from occurring.
6353 ret = -1;
6354 src_sbuf.st_size = 0;
6358 if (src_sbuf.st_size) {
6359 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6362 close_file(NULL, fsp1, NORMAL_CLOSE);
6364 /* Ensure the modtime is set correctly on the destination file. */
6365 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6368 * As we are opening fsp1 read-only we only expect
6369 * an error on close on fsp2 if we are out of space.
6370 * Thus we don't look at the error return from the
6371 * close of fsp1.
6373 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6375 if (!NT_STATUS_IS_OK(status)) {
6376 return status;
6379 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6380 return NT_STATUS_DISK_FULL;
6383 return NT_STATUS_OK;
6386 /****************************************************************************
6387 Reply to a file copy.
6388 ****************************************************************************/
6390 void reply_copy(struct smb_request *req)
6392 connection_struct *conn = req->conn;
6393 char *name = NULL;
6394 char *newname = NULL;
6395 char *directory = NULL;
6396 const char *mask = NULL;
6397 const char mask_star[] = "*";
6398 const char *p;
6399 int count=0;
6400 int error = ERRnoaccess;
6401 int err = 0;
6402 int tid2;
6403 int ofun;
6404 int flags;
6405 bool target_is_directory=False;
6406 bool source_has_wild = False;
6407 bool dest_has_wild = False;
6408 SMB_STRUCT_STAT sbuf1, sbuf2;
6409 NTSTATUS status;
6410 TALLOC_CTX *ctx = talloc_tos();
6412 START_PROFILE(SMBcopy);
6414 if (req->wct < 3) {
6415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6416 END_PROFILE(SMBcopy);
6417 return;
6420 tid2 = SVAL(req->vwv+0, 0);
6421 ofun = SVAL(req->vwv+1, 0);
6422 flags = SVAL(req->vwv+2, 0);
6424 p = (const char *)req->buf;
6425 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6426 &status, &source_has_wild);
6427 if (!NT_STATUS_IS_OK(status)) {
6428 reply_nterror(req, status);
6429 END_PROFILE(SMBcopy);
6430 return;
6432 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6433 &status, &dest_has_wild);
6434 if (!NT_STATUS_IS_OK(status)) {
6435 reply_nterror(req, status);
6436 END_PROFILE(SMBcopy);
6437 return;
6440 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6442 if (tid2 != conn->cnum) {
6443 /* can't currently handle inter share copies XXXX */
6444 DEBUG(3,("Rejecting inter-share copy\n"));
6445 reply_doserror(req, ERRSRV, ERRinvdevice);
6446 END_PROFILE(SMBcopy);
6447 return;
6450 status = resolve_dfspath_wcard(ctx, conn,
6451 req->flags2 & FLAGS2_DFS_PATHNAMES,
6452 name,
6453 &name,
6454 &source_has_wild);
6455 if (!NT_STATUS_IS_OK(status)) {
6456 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6457 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6458 ERRSRV, ERRbadpath);
6459 END_PROFILE(SMBcopy);
6460 return;
6462 reply_nterror(req, status);
6463 END_PROFILE(SMBcopy);
6464 return;
6467 status = resolve_dfspath_wcard(ctx, conn,
6468 req->flags2 & FLAGS2_DFS_PATHNAMES,
6469 newname,
6470 &newname,
6471 &dest_has_wild);
6472 if (!NT_STATUS_IS_OK(status)) {
6473 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6474 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6475 ERRSRV, ERRbadpath);
6476 END_PROFILE(SMBcopy);
6477 return;
6479 reply_nterror(req, status);
6480 END_PROFILE(SMBcopy);
6481 return;
6484 status = unix_convert(ctx, conn, name, source_has_wild,
6485 &name, NULL, &sbuf1);
6486 if (!NT_STATUS_IS_OK(status)) {
6487 reply_nterror(req, status);
6488 END_PROFILE(SMBcopy);
6489 return;
6492 status = unix_convert(ctx, conn, newname, dest_has_wild,
6493 &newname, NULL, &sbuf2);
6494 if (!NT_STATUS_IS_OK(status)) {
6495 reply_nterror(req, status);
6496 END_PROFILE(SMBcopy);
6497 return;
6500 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6502 if ((flags&1) && target_is_directory) {
6503 reply_doserror(req, ERRDOS, ERRbadfile);
6504 END_PROFILE(SMBcopy);
6505 return;
6508 if ((flags&2) && !target_is_directory) {
6509 reply_doserror(req, ERRDOS, ERRbadpath);
6510 END_PROFILE(SMBcopy);
6511 return;
6514 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6515 /* wants a tree copy! XXXX */
6516 DEBUG(3,("Rejecting tree copy\n"));
6517 reply_doserror(req, ERRSRV, ERRerror);
6518 END_PROFILE(SMBcopy);
6519 return;
6522 p = strrchr_m(name,'/');
6523 if (p != NULL) {
6524 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6525 mask = p+1;
6526 } else {
6527 directory = talloc_strdup(ctx, "./");
6528 mask = name;
6531 if (!directory) {
6532 reply_nterror(req, NT_STATUS_NO_MEMORY);
6533 END_PROFILE(SMBcopy);
6534 return;
6538 * We should only check the mangled cache
6539 * here if unix_convert failed. This means
6540 * that the path in 'mask' doesn't exist
6541 * on the file system and so we need to look
6542 * for a possible mangle. This patch from
6543 * Tine Smukavec <valentin.smukavec@hermes.si>.
6546 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6547 char *new_mask = NULL;
6548 mangle_lookup_name_from_8_3(ctx,
6549 mask,
6550 &new_mask,
6551 conn->params );
6552 if (new_mask) {
6553 mask = new_mask;
6557 if (!source_has_wild) {
6558 directory = talloc_asprintf_append(directory,
6559 "/%s",
6560 mask);
6561 if (dest_has_wild) {
6562 char *mod_newname = NULL;
6563 if (!resolve_wildcards(ctx,
6564 directory,newname,&mod_newname)) {
6565 reply_nterror(req, NT_STATUS_NO_MEMORY);
6566 END_PROFILE(SMBcopy);
6567 return;
6569 newname = mod_newname;
6572 status = check_name(conn, directory);
6573 if (!NT_STATUS_IS_OK(status)) {
6574 reply_nterror(req, status);
6575 END_PROFILE(SMBcopy);
6576 return;
6579 status = check_name(conn, newname);
6580 if (!NT_STATUS_IS_OK(status)) {
6581 reply_nterror(req, status);
6582 END_PROFILE(SMBcopy);
6583 return;
6586 status = copy_file(ctx,conn,directory,newname,ofun,
6587 count,target_is_directory);
6589 if(!NT_STATUS_IS_OK(status)) {
6590 reply_nterror(req, status);
6591 END_PROFILE(SMBcopy);
6592 return;
6593 } else {
6594 count++;
6596 } else {
6597 struct smb_Dir *dir_hnd = NULL;
6598 const char *dname = NULL;
6599 long offset = 0;
6601 if (strequal(mask,"????????.???")) {
6602 mask = mask_star;
6605 status = check_name(conn, directory);
6606 if (!NT_STATUS_IS_OK(status)) {
6607 reply_nterror(req, status);
6608 END_PROFILE(SMBcopy);
6609 return;
6612 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6613 if (dir_hnd == NULL) {
6614 status = map_nt_error_from_unix(errno);
6615 reply_nterror(req, status);
6616 END_PROFILE(SMBcopy);
6617 return;
6620 error = ERRbadfile;
6622 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6623 char *destname = NULL;
6624 char *fname = NULL;
6626 if (ISDOT(dname) || ISDOTDOT(dname)) {
6627 continue;
6630 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6631 continue;
6634 if(!mask_match(dname, mask, conn->case_sensitive)) {
6635 continue;
6638 error = ERRnoaccess;
6639 fname = talloc_asprintf(ctx,
6640 "%s/%s",
6641 directory,
6642 dname);
6643 if (!fname) {
6644 TALLOC_FREE(dir_hnd);
6645 reply_nterror(req, NT_STATUS_NO_MEMORY);
6646 END_PROFILE(SMBcopy);
6647 return;
6650 if (!resolve_wildcards(ctx,
6651 fname,newname,&destname)) {
6652 continue;
6654 if (!destname) {
6655 TALLOC_FREE(dir_hnd);
6656 reply_nterror(req, NT_STATUS_NO_MEMORY);
6657 END_PROFILE(SMBcopy);
6658 return;
6661 status = check_name(conn, fname);
6662 if (!NT_STATUS_IS_OK(status)) {
6663 TALLOC_FREE(dir_hnd);
6664 reply_nterror(req, status);
6665 END_PROFILE(SMBcopy);
6666 return;
6669 status = check_name(conn, destname);
6670 if (!NT_STATUS_IS_OK(status)) {
6671 TALLOC_FREE(dir_hnd);
6672 reply_nterror(req, status);
6673 END_PROFILE(SMBcopy);
6674 return;
6677 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6679 status = copy_file(ctx,conn,fname,destname,ofun,
6680 count,target_is_directory);
6681 if (NT_STATUS_IS_OK(status)) {
6682 count++;
6684 TALLOC_FREE(fname);
6685 TALLOC_FREE(destname);
6687 TALLOC_FREE(dir_hnd);
6690 if (count == 0) {
6691 if(err) {
6692 /* Error on close... */
6693 errno = err;
6694 reply_unixerror(req, ERRHRD, ERRgeneral);
6695 END_PROFILE(SMBcopy);
6696 return;
6699 reply_doserror(req, ERRDOS, error);
6700 END_PROFILE(SMBcopy);
6701 return;
6704 reply_outbuf(req, 1, 0);
6705 SSVAL(req->outbuf,smb_vwv0,count);
6707 END_PROFILE(SMBcopy);
6708 return;
6711 #undef DBGC_CLASS
6712 #define DBGC_CLASS DBGC_LOCKING
6714 /****************************************************************************
6715 Get a lock pid, dealing with large count requests.
6716 ****************************************************************************/
6718 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6719 bool large_file_format)
6721 if(!large_file_format)
6722 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6723 else
6724 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6727 /****************************************************************************
6728 Get a lock count, dealing with large count requests.
6729 ****************************************************************************/
6731 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6732 bool large_file_format)
6734 uint64_t count = 0;
6736 if(!large_file_format) {
6737 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6738 } else {
6740 #if defined(HAVE_LONGLONG)
6741 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6742 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6743 #else /* HAVE_LONGLONG */
6746 * NT4.x seems to be broken in that it sends large file (64 bit)
6747 * lockingX calls even if the CAP_LARGE_FILES was *not*
6748 * negotiated. For boxes without large unsigned ints truncate the
6749 * lock count by dropping the top 32 bits.
6752 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6753 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6754 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6755 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6756 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6759 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6760 #endif /* HAVE_LONGLONG */
6763 return count;
6766 #if !defined(HAVE_LONGLONG)
6767 /****************************************************************************
6768 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6769 ****************************************************************************/
6771 static uint32 map_lock_offset(uint32 high, uint32 low)
6773 unsigned int i;
6774 uint32 mask = 0;
6775 uint32 highcopy = high;
6778 * Try and find out how many significant bits there are in high.
6781 for(i = 0; highcopy; i++)
6782 highcopy >>= 1;
6785 * We use 31 bits not 32 here as POSIX
6786 * lock offsets may not be negative.
6789 mask = (~0) << (31 - i);
6791 if(low & mask)
6792 return 0; /* Fail. */
6794 high <<= (31 - i);
6796 return (high|low);
6798 #endif /* !defined(HAVE_LONGLONG) */
6800 /****************************************************************************
6801 Get a lock offset, dealing with large offset requests.
6802 ****************************************************************************/
6804 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6805 bool large_file_format, bool *err)
6807 uint64_t offset = 0;
6809 *err = False;
6811 if(!large_file_format) {
6812 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6813 } else {
6815 #if defined(HAVE_LONGLONG)
6816 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6817 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6818 #else /* HAVE_LONGLONG */
6821 * NT4.x seems to be broken in that it sends large file (64 bit)
6822 * lockingX calls even if the CAP_LARGE_FILES was *not*
6823 * negotiated. For boxes without large unsigned ints mangle the
6824 * lock offset by mapping the top 32 bits onto the lower 32.
6827 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6828 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6829 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6830 uint32 new_low = 0;
6832 if((new_low = map_lock_offset(high, low)) == 0) {
6833 *err = True;
6834 return (uint64_t)-1;
6837 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6838 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6839 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6840 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6843 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6844 #endif /* HAVE_LONGLONG */
6847 return offset;
6850 /****************************************************************************
6851 Reply to a lockingX request.
6852 ****************************************************************************/
6854 void reply_lockingX(struct smb_request *req)
6856 connection_struct *conn = req->conn;
6857 files_struct *fsp;
6858 unsigned char locktype;
6859 unsigned char oplocklevel;
6860 uint16 num_ulocks;
6861 uint16 num_locks;
6862 uint64_t count = 0, offset = 0;
6863 uint32 lock_pid;
6864 int32 lock_timeout;
6865 int i;
6866 const uint8_t *data;
6867 bool large_file_format;
6868 bool err;
6869 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6871 START_PROFILE(SMBlockingX);
6873 if (req->wct < 8) {
6874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6875 END_PROFILE(SMBlockingX);
6876 return;
6879 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6880 locktype = CVAL(req->vwv+3, 0);
6881 oplocklevel = CVAL(req->vwv+3, 1);
6882 num_ulocks = SVAL(req->vwv+6, 0);
6883 num_locks = SVAL(req->vwv+7, 0);
6884 lock_timeout = IVAL(req->vwv+4, 0);
6885 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6887 if (!check_fsp(conn, req, fsp)) {
6888 END_PROFILE(SMBlockingX);
6889 return;
6892 data = req->buf;
6894 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6895 /* we don't support these - and CANCEL_LOCK makes w2k
6896 and XP reboot so I don't really want to be
6897 compatible! (tridge) */
6898 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6899 END_PROFILE(SMBlockingX);
6900 return;
6903 /* Check if this is an oplock break on a file
6904 we have granted an oplock on.
6906 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6907 /* Client can insist on breaking to none. */
6908 bool break_to_none = (oplocklevel == 0);
6909 bool result;
6911 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6912 "for fnum = %d\n", (unsigned int)oplocklevel,
6913 fsp->fnum ));
6916 * Make sure we have granted an exclusive or batch oplock on
6917 * this file.
6920 if (fsp->oplock_type == 0) {
6922 /* The Samba4 nbench simulator doesn't understand
6923 the difference between break to level2 and break
6924 to none from level2 - it sends oplock break
6925 replies in both cases. Don't keep logging an error
6926 message here - just ignore it. JRA. */
6928 DEBUG(5,("reply_lockingX: Error : oplock break from "
6929 "client for fnum = %d (oplock=%d) and no "
6930 "oplock granted on this file (%s).\n",
6931 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6933 /* if this is a pure oplock break request then don't
6934 * send a reply */
6935 if (num_locks == 0 && num_ulocks == 0) {
6936 END_PROFILE(SMBlockingX);
6937 return;
6938 } else {
6939 END_PROFILE(SMBlockingX);
6940 reply_doserror(req, ERRDOS, ERRlock);
6941 return;
6945 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6946 (break_to_none)) {
6947 result = remove_oplock(fsp);
6948 } else {
6949 result = downgrade_oplock(fsp);
6952 if (!result) {
6953 DEBUG(0, ("reply_lockingX: error in removing "
6954 "oplock on file %s\n", fsp->fsp_name));
6955 /* Hmmm. Is this panic justified? */
6956 smb_panic("internal tdb error");
6959 reply_to_oplock_break_requests(fsp);
6961 /* if this is a pure oplock break request then don't send a
6962 * reply */
6963 if (num_locks == 0 && num_ulocks == 0) {
6964 /* Sanity check - ensure a pure oplock break is not a
6965 chained request. */
6966 if(CVAL(req->vwv+0, 0) != 0xff)
6967 DEBUG(0,("reply_lockingX: Error : pure oplock "
6968 "break is a chained %d request !\n",
6969 (unsigned int)CVAL(req->vwv+0, 0)));
6970 END_PROFILE(SMBlockingX);
6971 return;
6975 if (req->buflen <
6976 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6977 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6978 END_PROFILE(SMBlockingX);
6979 return;
6982 /* Data now points at the beginning of the list
6983 of smb_unlkrng structs */
6984 for(i = 0; i < (int)num_ulocks; i++) {
6985 lock_pid = get_lock_pid( data, i, large_file_format);
6986 count = get_lock_count( data, i, large_file_format);
6987 offset = get_lock_offset( data, i, large_file_format, &err);
6990 * There is no error code marked "stupid client bug".... :-).
6992 if(err) {
6993 END_PROFILE(SMBlockingX);
6994 reply_doserror(req, ERRDOS, ERRnoaccess);
6995 return;
6998 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6999 "pid %u, file %s\n", (double)offset, (double)count,
7000 (unsigned int)lock_pid, fsp->fsp_name ));
7002 status = do_unlock(smbd_messaging_context(),
7003 fsp,
7004 lock_pid,
7005 count,
7006 offset,
7007 WINDOWS_LOCK);
7009 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7010 nt_errstr(status)));
7012 if (NT_STATUS_V(status)) {
7013 END_PROFILE(SMBlockingX);
7014 reply_nterror(req, status);
7015 return;
7019 /* Setup the timeout in seconds. */
7021 if (!lp_blocking_locks(SNUM(conn))) {
7022 lock_timeout = 0;
7025 /* Now do any requested locks */
7026 data += ((large_file_format ? 20 : 10)*num_ulocks);
7028 /* Data now points at the beginning of the list
7029 of smb_lkrng structs */
7031 for(i = 0; i < (int)num_locks; i++) {
7032 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7033 READ_LOCK:WRITE_LOCK);
7034 lock_pid = get_lock_pid( data, i, large_file_format);
7035 count = get_lock_count( data, i, large_file_format);
7036 offset = get_lock_offset( data, i, large_file_format, &err);
7039 * There is no error code marked "stupid client bug".... :-).
7041 if(err) {
7042 END_PROFILE(SMBlockingX);
7043 reply_doserror(req, ERRDOS, ERRnoaccess);
7044 return;
7047 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7048 "%u, file %s timeout = %d\n", (double)offset,
7049 (double)count, (unsigned int)lock_pid,
7050 fsp->fsp_name, (int)lock_timeout ));
7052 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7053 struct blocking_lock_record *blr = NULL;
7055 if (lp_blocking_locks(SNUM(conn))) {
7057 /* Schedule a message to ourselves to
7058 remove the blocking lock record and
7059 return the right error. */
7061 blr = blocking_lock_cancel(fsp,
7062 lock_pid,
7063 offset,
7064 count,
7065 WINDOWS_LOCK,
7066 locktype,
7067 NT_STATUS_FILE_LOCK_CONFLICT);
7068 if (blr == NULL) {
7069 END_PROFILE(SMBlockingX);
7070 reply_nterror(
7071 req,
7072 NT_STATUS_DOS(
7073 ERRDOS,
7074 ERRcancelviolation));
7075 return;
7078 /* Remove a matching pending lock. */
7079 status = do_lock_cancel(fsp,
7080 lock_pid,
7081 count,
7082 offset,
7083 WINDOWS_LOCK,
7084 blr);
7085 } else {
7086 bool blocking_lock = lock_timeout ? True : False;
7087 bool defer_lock = False;
7088 struct byte_range_lock *br_lck;
7089 uint32 block_smbpid;
7091 br_lck = do_lock(smbd_messaging_context(),
7092 fsp,
7093 lock_pid,
7094 count,
7095 offset,
7096 lock_type,
7097 WINDOWS_LOCK,
7098 blocking_lock,
7099 &status,
7100 &block_smbpid,
7101 NULL);
7103 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7104 /* Windows internal resolution for blocking locks seems
7105 to be about 200ms... Don't wait for less than that. JRA. */
7106 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7107 lock_timeout = lp_lock_spin_time();
7109 defer_lock = True;
7112 /* This heuristic seems to match W2K3 very well. If a
7113 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7114 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7115 far as I can tell. Replacement for do_lock_spin(). JRA. */
7117 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7118 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7119 defer_lock = True;
7120 lock_timeout = lp_lock_spin_time();
7123 if (br_lck && defer_lock) {
7125 * A blocking lock was requested. Package up
7126 * this smb into a queued request and push it
7127 * onto the blocking lock queue.
7129 if(push_blocking_lock_request(br_lck,
7130 req,
7131 fsp,
7132 lock_timeout,
7134 lock_pid,
7135 lock_type,
7136 WINDOWS_LOCK,
7137 offset,
7138 count,
7139 block_smbpid)) {
7140 TALLOC_FREE(br_lck);
7141 END_PROFILE(SMBlockingX);
7142 return;
7146 TALLOC_FREE(br_lck);
7149 if (NT_STATUS_V(status)) {
7150 END_PROFILE(SMBlockingX);
7151 reply_nterror(req, status);
7152 return;
7156 /* If any of the above locks failed, then we must unlock
7157 all of the previous locks (X/Open spec). */
7159 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7160 (i != num_locks) &&
7161 (num_locks != 0)) {
7163 * Ensure we don't do a remove on the lock that just failed,
7164 * as under POSIX rules, if we have a lock already there, we
7165 * will delete it (and we shouldn't) .....
7167 for(i--; i >= 0; i--) {
7168 lock_pid = get_lock_pid( data, i, large_file_format);
7169 count = get_lock_count( data, i, large_file_format);
7170 offset = get_lock_offset( data, i, large_file_format,
7171 &err);
7174 * There is no error code marked "stupid client
7175 * bug".... :-).
7177 if(err) {
7178 END_PROFILE(SMBlockingX);
7179 reply_doserror(req, ERRDOS, ERRnoaccess);
7180 return;
7183 do_unlock(smbd_messaging_context(),
7184 fsp,
7185 lock_pid,
7186 count,
7187 offset,
7188 WINDOWS_LOCK);
7190 END_PROFILE(SMBlockingX);
7191 reply_nterror(req, status);
7192 return;
7195 reply_outbuf(req, 2, 0);
7197 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7198 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7200 END_PROFILE(SMBlockingX);
7201 chain_reply(req);
7204 #undef DBGC_CLASS
7205 #define DBGC_CLASS DBGC_ALL
7207 /****************************************************************************
7208 Reply to a SMBreadbmpx (read block multiplex) request.
7209 Always reply with an error, if someone has a platform really needs this,
7210 please contact vl@samba.org
7211 ****************************************************************************/
7213 void reply_readbmpx(struct smb_request *req)
7215 START_PROFILE(SMBreadBmpx);
7216 reply_doserror(req, ERRSRV, ERRuseSTD);
7217 END_PROFILE(SMBreadBmpx);
7218 return;
7221 /****************************************************************************
7222 Reply to a SMBreadbs (read block multiplex secondary) request.
7223 Always reply with an error, if someone has a platform really needs this,
7224 please contact vl@samba.org
7225 ****************************************************************************/
7227 void reply_readbs(struct smb_request *req)
7229 START_PROFILE(SMBreadBs);
7230 reply_doserror(req, ERRSRV, ERRuseSTD);
7231 END_PROFILE(SMBreadBs);
7232 return;
7235 /****************************************************************************
7236 Reply to a SMBsetattrE.
7237 ****************************************************************************/
7239 void reply_setattrE(struct smb_request *req)
7241 connection_struct *conn = req->conn;
7242 struct smb_file_time ft;
7243 files_struct *fsp;
7244 SMB_STRUCT_STAT sbuf;
7245 NTSTATUS status;
7247 START_PROFILE(SMBsetattrE);
7248 ZERO_STRUCT(ft);
7250 if (req->wct < 7) {
7251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7252 END_PROFILE(SMBsetattrE);
7253 return;
7256 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7258 if(!fsp || (fsp->conn != conn)) {
7259 reply_doserror(req, ERRDOS, ERRbadfid);
7260 END_PROFILE(SMBsetattrE);
7261 return;
7266 * Convert the DOS times into unix times.
7269 ft.atime = convert_time_t_to_timespec(
7270 srv_make_unix_date2(req->vwv+3));
7271 ft.mtime = convert_time_t_to_timespec(
7272 srv_make_unix_date2(req->vwv+5));
7273 ft.create_time = convert_time_t_to_timespec(
7274 srv_make_unix_date2(req->vwv+1));
7276 reply_outbuf(req, 0, 0);
7279 * Patch from Ray Frush <frush@engr.colostate.edu>
7280 * Sometimes times are sent as zero - ignore them.
7283 /* Ensure we have a valid stat struct for the source. */
7284 if (fsp->fh->fd != -1) {
7285 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7286 status = map_nt_error_from_unix(errno);
7287 reply_nterror(req, status);
7288 END_PROFILE(SMBsetattrE);
7289 return;
7291 } else {
7292 int ret = -1;
7294 if (fsp->posix_open) {
7295 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7296 } else {
7297 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7299 if (ret == -1) {
7300 status = map_nt_error_from_unix(errno);
7301 reply_nterror(req, status);
7302 END_PROFILE(SMBsetattrE);
7303 return;
7307 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7308 &sbuf, &ft, true);
7309 if (!NT_STATUS_IS_OK(status)) {
7310 reply_doserror(req, ERRDOS, ERRnoaccess);
7311 END_PROFILE(SMBsetattrE);
7312 return;
7315 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7316 " createtime=%u\n",
7317 fsp->fnum,
7318 (unsigned int)ft.atime.tv_sec,
7319 (unsigned int)ft.mtime.tv_sec,
7320 (unsigned int)ft.create_time.tv_sec
7323 END_PROFILE(SMBsetattrE);
7324 return;
7328 /* Back from the dead for OS/2..... JRA. */
7330 /****************************************************************************
7331 Reply to a SMBwritebmpx (write block multiplex primary) request.
7332 Always reply with an error, if someone has a platform really needs this,
7333 please contact vl@samba.org
7334 ****************************************************************************/
7336 void reply_writebmpx(struct smb_request *req)
7338 START_PROFILE(SMBwriteBmpx);
7339 reply_doserror(req, ERRSRV, ERRuseSTD);
7340 END_PROFILE(SMBwriteBmpx);
7341 return;
7344 /****************************************************************************
7345 Reply to a SMBwritebs (write block multiplex secondary) request.
7346 Always reply with an error, if someone has a platform really needs this,
7347 please contact vl@samba.org
7348 ****************************************************************************/
7350 void reply_writebs(struct smb_request *req)
7352 START_PROFILE(SMBwriteBs);
7353 reply_doserror(req, ERRSRV, ERRuseSTD);
7354 END_PROFILE(SMBwriteBs);
7355 return;
7358 /****************************************************************************
7359 Reply to a SMBgetattrE.
7360 ****************************************************************************/
7362 void reply_getattrE(struct smb_request *req)
7364 connection_struct *conn = req->conn;
7365 SMB_STRUCT_STAT sbuf;
7366 int mode;
7367 files_struct *fsp;
7368 struct timespec create_ts;
7370 START_PROFILE(SMBgetattrE);
7372 if (req->wct < 1) {
7373 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7374 END_PROFILE(SMBgetattrE);
7375 return;
7378 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7380 if(!fsp || (fsp->conn != conn)) {
7381 reply_doserror(req, ERRDOS, ERRbadfid);
7382 END_PROFILE(SMBgetattrE);
7383 return;
7386 /* Do an fstat on this file */
7387 if(fsp_stat(fsp, &sbuf)) {
7388 reply_unixerror(req, ERRDOS, ERRnoaccess);
7389 END_PROFILE(SMBgetattrE);
7390 return;
7393 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7396 * Convert the times into dos times. Set create
7397 * date to be last modify date as UNIX doesn't save
7398 * this.
7401 reply_outbuf(req, 11, 0);
7403 create_ts = get_create_timespec(&sbuf,
7404 lp_fake_dir_create_times(SNUM(conn)));
7405 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7406 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7407 /* Should we check pending modtime here ? JRA */
7408 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7410 if (mode & aDIR) {
7411 SIVAL(req->outbuf, smb_vwv6, 0);
7412 SIVAL(req->outbuf, smb_vwv8, 0);
7413 } else {
7414 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7415 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7416 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7418 SSVAL(req->outbuf,smb_vwv10, mode);
7420 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7422 END_PROFILE(SMBgetattrE);
7423 return;