Fix bug 6302: Give the VFS a chance to read from 0-byte files
[Samba/ekacnet.git] / source3 / smbd / reply.c
blob418c8ba7884928faacddb85a1aa1c323ec9ad3a2
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 (!posix_path && !stream_started && *s == ':') {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* Stream names allow more characters than file names.
80 We're overloading posix_path here to allow a wider
81 range of characters. If stream_started is true this
82 is still a Windows path even if posix_path is true.
83 JRA.
85 stream_started = true;
86 start_of_name_component = false;
87 posix_path = true;
89 if (s[1] == '\0') {
90 return NT_STATUS_OBJECT_NAME_INVALID;
94 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
96 * Safe to assume is not the second part of a mb char
97 * as this is handled below.
99 /* Eat multiple '/' or '\\' */
100 while (IS_PATH_SEP(*s,posix_path)) {
101 s++;
103 if ((d != path) && (*s != '\0')) {
104 /* We only care about non-leading or trailing '/' or '\\' */
105 *d++ = '/';
108 start_of_name_component = True;
109 /* New component. */
110 *p_last_component_contains_wcard = False;
111 continue;
114 if (start_of_name_component) {
115 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
119 * No mb char starts with '.' so we're safe checking the directory separator here.
122 /* If we just added a '/' - delete it */
123 if ((d > path) && (*(d-1) == '/')) {
124 *(d-1) = '\0';
125 d--;
128 /* Are we at the start ? Can't go back further if so. */
129 if (d <= path) {
130 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
131 break;
133 /* Go back one level... */
134 /* We know this is safe as '/' cannot be part of a mb sequence. */
135 /* NOTE - if this assumption is invalid we are not in good shape... */
136 /* Decrement d first as d points to the *next* char to write into. */
137 for (d--; d > path; d--) {
138 if (*d == '/')
139 break;
141 s += 2; /* Else go past the .. */
142 /* We're still at the start of a name component, just the previous one. */
143 continue;
145 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
146 if (posix_path) {
147 /* Eat the '.' */
148 s++;
149 continue;
155 if (!(*s & 0x80)) {
156 if (!posix_path) {
157 if (*s <= 0x1f || *s == '|') {
158 return NT_STATUS_OBJECT_NAME_INVALID;
160 switch (*s) {
161 case '*':
162 case '?':
163 case '<':
164 case '>':
165 case '"':
166 *p_last_component_contains_wcard = True;
167 break;
168 default:
169 break;
172 *d++ = *s++;
173 } else {
174 size_t siz;
175 /* Get the size of the next MB character. */
176 next_codepoint(s,&siz);
177 switch(siz) {
178 case 5:
179 *d++ = *s++;
180 /*fall through*/
181 case 4:
182 *d++ = *s++;
183 /*fall through*/
184 case 3:
185 *d++ = *s++;
186 /*fall through*/
187 case 2:
188 *d++ = *s++;
189 /*fall through*/
190 case 1:
191 *d++ = *s++;
192 break;
193 default:
194 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
195 *d = '\0';
196 return NT_STATUS_INVALID_PARAMETER;
199 start_of_name_component = False;
202 *d = '\0';
204 return ret;
207 /****************************************************************************
208 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209 No wildcards allowed.
210 ****************************************************************************/
212 NTSTATUS check_path_syntax(char *path)
214 bool ignore;
215 return check_path_syntax_internal(path, False, &ignore);
218 /****************************************************************************
219 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220 Wildcards allowed - p_contains_wcard returns true if the last component contained
221 a wildcard.
222 ****************************************************************************/
224 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
226 return check_path_syntax_internal(path, False, p_contains_wcard);
229 /****************************************************************************
230 Check the path for a POSIX client.
231 We're assuming here that '/' is not the second byte in any multibyte char
232 set (a safe assumption).
233 ****************************************************************************/
235 NTSTATUS check_path_syntax_posix(char *path)
237 bool ignore;
238 return check_path_syntax_internal(path, True, &ignore);
241 /****************************************************************************
242 Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
245 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
246 const char *base_ptr,
247 uint16 smb_flags2,
248 char **pp_dest,
249 const char *src,
250 size_t src_len,
251 int flags,
252 NTSTATUS *err,
253 bool *contains_wcard)
255 size_t ret;
257 *pp_dest = NULL;
259 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
260 src_len, flags);
262 if (!*pp_dest) {
263 *err = NT_STATUS_INVALID_PARAMETER;
264 return ret;
267 *contains_wcard = False;
269 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
274 *err = NT_STATUS_OK;
275 return ret;
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(*pp_dest);
280 } else {
281 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
284 return ret;
287 /****************************************************************************
288 Pull a string and check the path - provide for error return.
289 ****************************************************************************/
291 size_t srvstr_get_path(TALLOC_CTX *ctx,
292 const char *base_ptr,
293 uint16 smb_flags2,
294 char **pp_dest,
295 const char *src,
296 size_t src_len,
297 int flags,
298 NTSTATUS *err)
300 bool ignore;
301 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
302 src_len, flags, err, &ignore);
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
306 char **pp_dest, const char *src, int flags,
307 NTSTATUS *err, bool *contains_wcard)
309 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
310 pp_dest, src, smbreq_bufrem(req, src),
311 flags, err, contains_wcard);
314 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
315 char **pp_dest, const char *src, int flags,
316 NTSTATUS *err)
318 bool ignore;
319 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
320 flags, err, &ignore);
323 /****************************************************************************
324 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
328 files_struct *fsp)
330 if (!(fsp) || !(conn)) {
331 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
332 return False;
334 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
335 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
336 return False;
338 return True;
341 /****************************************************************************
342 Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
346 files_struct *fsp)
348 if (!check_fsp_open(conn, req, fsp)) {
349 return False;
351 if ((fsp)->is_directory) {
352 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
353 return False;
355 if ((fsp)->fh->fd == -1) {
356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
357 return False;
359 (fsp)->num_smb_operations++;
360 return True;
363 /****************************************************************************
364 Check if we have a correct fsp pointing to a quota fake file. Replacement for
365 the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
369 files_struct *fsp)
371 if (!check_fsp_open(conn, req, fsp)) {
372 return false;
375 if (fsp->is_directory) {
376 return false;
379 if (fsp->fake_file_handle == NULL) {
380 return false;
383 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
384 return false;
387 if (fsp->fake_file_handle->private_data == NULL) {
388 return false;
391 return true;
394 /****************************************************************************
395 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
398 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
399 files_struct *fsp)
401 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
402 && (req->vuid == (fsp)->vuid)) {
403 return True;
406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
407 return False;
410 static bool netbios_session_retarget(const char *name, int name_type)
412 char *trim_name;
413 char *trim_name_type;
414 const char *retarget_parm;
415 char *retarget;
416 char *p;
417 int retarget_type = 0x20;
418 int retarget_port = 139;
419 struct sockaddr_storage retarget_addr;
420 struct sockaddr_in *in_addr;
421 bool ret = false;
422 uint8_t outbuf[10];
424 if (get_socket_port(smbd_server_fd()) != 139) {
425 return false;
428 trim_name = talloc_strdup(talloc_tos(), name);
429 if (trim_name == NULL) {
430 goto fail;
432 trim_char(trim_name, ' ', ' ');
434 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
435 name_type);
436 if (trim_name_type == NULL) {
437 goto fail;
440 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 trim_name_type, NULL);
442 if (retarget_parm == NULL) {
443 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
444 trim_name, NULL);
446 if (retarget_parm == NULL) {
447 goto fail;
450 retarget = talloc_strdup(trim_name, retarget_parm);
451 if (retarget == NULL) {
452 goto fail;
455 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
457 p = strchr(retarget, ':');
458 if (p != NULL) {
459 *p++ = '\0';
460 retarget_port = atoi(p);
463 p = strchr_m(retarget, '#');
464 if (p != NULL) {
465 *p++ = '\0';
466 sscanf(p, "%x", &retarget_type);
469 ret = resolve_name(retarget, &retarget_addr, retarget_type);
470 if (!ret) {
471 DEBUG(10, ("could not resolve %s\n", retarget));
472 goto fail;
475 if (retarget_addr.ss_family != AF_INET) {
476 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
477 goto fail;
480 in_addr = (struct sockaddr_in *)&retarget_addr;
482 _smb_setlen(outbuf, 6);
483 SCVAL(outbuf, 0, 0x84);
484 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
485 *(uint16_t *)(outbuf+8) = htons(retarget_port);
487 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
488 NULL)) {
489 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
490 "failed.");
493 ret = true;
494 fail:
495 TALLOC_FREE(trim_name);
496 return ret;
499 /****************************************************************************
500 Reply to a (netbios-level) special message.
501 ****************************************************************************/
503 void reply_special(char *inbuf)
505 int msg_type = CVAL(inbuf,0);
506 int msg_flags = CVAL(inbuf,1);
507 fstring name1,name2;
508 char name_type1, name_type2;
511 * We only really use 4 bytes of the outbuf, but for the smb_setlen
512 * calculation & friends (srv_send_smb uses that) we need the full smb
513 * header.
515 char outbuf[smb_size];
517 *name1 = *name2 = 0;
519 memset(outbuf, '\0', sizeof(outbuf));
521 smb_setlen(outbuf,0);
523 switch (msg_type) {
524 case 0x81: /* session request */
526 if (already_got_session) {
527 exit_server_cleanly("multiple session request not permitted");
530 SCVAL(outbuf,0,0x82);
531 SCVAL(outbuf,3,0);
532 if (name_len(inbuf+4) > 50 ||
533 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
534 DEBUG(0,("Invalid name length in session request\n"));
535 return;
537 name_type1 = name_extract(inbuf,4,name1);
538 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
539 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
540 name1, name_type1, name2, name_type2));
542 if (netbios_session_retarget(name1, name_type1)) {
543 exit_server_cleanly("retargeted client");
546 set_local_machine_name(name1, True);
547 set_remote_machine_name(name2, True);
549 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
550 get_local_machine_name(), get_remote_machine_name(),
551 name_type2));
553 if (name_type2 == 'R') {
554 /* We are being asked for a pathworks session ---
555 no thanks! */
556 SCVAL(outbuf, 0,0x83);
557 break;
560 /* only add the client's machine name to the list
561 of possibly valid usernames if we are operating
562 in share mode security */
563 if (lp_security() == SEC_SHARE) {
564 add_session_user(get_remote_machine_name());
567 reload_services(True);
568 reopen_logs();
570 already_got_session = True;
571 break;
573 case 0x89: /* session keepalive request
574 (some old clients produce this?) */
575 SCVAL(outbuf,0,SMBkeepalive);
576 SCVAL(outbuf,3,0);
577 break;
579 case 0x82: /* positive session response */
580 case 0x83: /* negative session response */
581 case 0x84: /* retarget session response */
582 DEBUG(0,("Unexpected session response\n"));
583 break;
585 case SMBkeepalive: /* session keepalive */
586 default:
587 return;
590 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
591 msg_type, msg_flags));
593 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
594 return;
597 /****************************************************************************
598 Reply to a tcon.
599 conn POINTER CAN BE NULL HERE !
600 ****************************************************************************/
602 void reply_tcon(struct smb_request *req)
604 connection_struct *conn = req->conn;
605 const char *service;
606 char *service_buf = NULL;
607 char *password = NULL;
608 char *dev = NULL;
609 int pwlen=0;
610 NTSTATUS nt_status;
611 const char *p;
612 DATA_BLOB password_blob;
613 TALLOC_CTX *ctx = talloc_tos();
615 START_PROFILE(SMBtcon);
617 if (req->buflen < 4) {
618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
619 END_PROFILE(SMBtcon);
620 return;
623 p = (const char *)req->buf + 1;
624 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
625 p += 1;
626 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
627 p += pwlen+1;
628 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
629 p += 1;
631 if (service_buf == NULL || password == NULL || dev == NULL) {
632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
633 END_PROFILE(SMBtcon);
634 return;
636 p = strrchr_m(service_buf,'\\');
637 if (p) {
638 service = p+1;
639 } else {
640 service = service_buf;
643 password_blob = data_blob(password, pwlen+1);
645 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
646 req->conn = conn;
648 data_blob_clear_free(&password_blob);
650 if (!conn) {
651 reply_nterror(req, nt_status);
652 END_PROFILE(SMBtcon);
653 return;
656 reply_outbuf(req, 2, 0);
657 SSVAL(req->outbuf,smb_vwv0,max_recv);
658 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
659 SSVAL(req->outbuf,smb_tid,conn->cnum);
661 DEBUG(3,("tcon service=%s cnum=%d\n",
662 service, conn->cnum));
664 END_PROFILE(SMBtcon);
665 return;
668 /****************************************************************************
669 Reply to a tcon and X.
670 conn POINTER CAN BE NULL HERE !
671 ****************************************************************************/
673 void reply_tcon_and_X(struct smb_request *req)
675 connection_struct *conn = req->conn;
676 const char *service = NULL;
677 DATA_BLOB password;
678 TALLOC_CTX *ctx = talloc_tos();
679 /* what the cleint thinks the device is */
680 char *client_devicetype = NULL;
681 /* what the server tells the client the share represents */
682 const char *server_devicetype;
683 NTSTATUS nt_status;
684 int passlen;
685 char *path = NULL;
686 const char *p, *q;
687 uint16 tcon_flags;
689 START_PROFILE(SMBtconX);
691 if (req->wct < 4) {
692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
693 END_PROFILE(SMBtconX);
694 return;
697 passlen = SVAL(req->vwv+3, 0);
698 tcon_flags = SVAL(req->vwv+2, 0);
700 /* we might have to close an old one */
701 if ((tcon_flags & 0x1) && conn) {
702 close_cnum(conn,req->vuid);
703 req->conn = NULL;
704 conn = NULL;
707 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
708 reply_doserror(req, ERRDOS, ERRbuftoosmall);
709 END_PROFILE(SMBtconX);
710 return;
713 if (global_encrypted_passwords_negotiated) {
714 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
715 if (lp_security() == SEC_SHARE) {
717 * Security = share always has a pad byte
718 * after the password.
720 p = (const char *)req->buf + passlen + 1;
721 } else {
722 p = (const char *)req->buf + passlen;
724 } else {
725 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
726 /* Ensure correct termination */
727 password.data[passlen]=0;
728 p = (const char *)req->buf + passlen + 1;
731 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
733 if (path == NULL) {
734 data_blob_clear_free(&password);
735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
736 END_PROFILE(SMBtconX);
737 return;
741 * the service name can be either: \\server\share
742 * or share directly like on the DELL PowerVault 705
744 if (*path=='\\') {
745 q = strchr_m(path+2,'\\');
746 if (!q) {
747 data_blob_clear_free(&password);
748 reply_doserror(req, ERRDOS, ERRnosuchshare);
749 END_PROFILE(SMBtconX);
750 return;
752 service = q+1;
753 } else {
754 service = path;
757 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
758 &client_devicetype, p,
759 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
761 if (client_devicetype == NULL) {
762 data_blob_clear_free(&password);
763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
764 END_PROFILE(SMBtconX);
765 return;
768 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
770 conn = make_connection(service, password, client_devicetype,
771 req->vuid, &nt_status);
772 req->conn =conn;
774 data_blob_clear_free(&password);
776 if (!conn) {
777 reply_nterror(req, nt_status);
778 END_PROFILE(SMBtconX);
779 return;
782 if ( IS_IPC(conn) )
783 server_devicetype = "IPC";
784 else if ( IS_PRINT(conn) )
785 server_devicetype = "LPT1:";
786 else
787 server_devicetype = "A:";
789 if (Protocol < PROTOCOL_NT1) {
790 reply_outbuf(req, 2, 0);
791 if (message_push_string(&req->outbuf, server_devicetype,
792 STR_TERMINATE|STR_ASCII) == -1) {
793 reply_nterror(req, NT_STATUS_NO_MEMORY);
794 END_PROFILE(SMBtconX);
795 return;
797 } else {
798 /* NT sets the fstype of IPC$ to the null string */
799 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
801 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
802 /* Return permissions. */
803 uint32 perm1 = 0;
804 uint32 perm2 = 0;
806 reply_outbuf(req, 7, 0);
808 if (IS_IPC(conn)) {
809 perm1 = FILE_ALL_ACCESS;
810 perm2 = FILE_ALL_ACCESS;
811 } else {
812 perm1 = CAN_WRITE(conn) ?
813 SHARE_ALL_ACCESS :
814 SHARE_READ_ONLY;
817 SIVAL(req->outbuf, smb_vwv3, perm1);
818 SIVAL(req->outbuf, smb_vwv5, perm2);
819 } else {
820 reply_outbuf(req, 3, 0);
823 if ((message_push_string(&req->outbuf, server_devicetype,
824 STR_TERMINATE|STR_ASCII) == -1)
825 || (message_push_string(&req->outbuf, fstype,
826 STR_TERMINATE) == -1)) {
827 reply_nterror(req, NT_STATUS_NO_MEMORY);
828 END_PROFILE(SMBtconX);
829 return;
832 /* what does setting this bit do? It is set by NT4 and
833 may affect the ability to autorun mounted cdroms */
834 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
835 (lp_csc_policy(SNUM(conn)) << 2));
837 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
838 DEBUG(2,("Serving %s as a Dfs root\n",
839 lp_servicename(SNUM(conn)) ));
840 SSVAL(req->outbuf, smb_vwv2,
841 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
846 DEBUG(3,("tconX service=%s \n",
847 service));
849 /* set the incoming and outgoing tid to the just created one */
850 SSVAL(req->inbuf,smb_tid,conn->cnum);
851 SSVAL(req->outbuf,smb_tid,conn->cnum);
853 END_PROFILE(SMBtconX);
855 chain_reply(req);
856 return;
859 /****************************************************************************
860 Reply to an unknown type.
861 ****************************************************************************/
863 void reply_unknown_new(struct smb_request *req, uint8 type)
865 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
866 smb_fn_name(type), type, type));
867 reply_doserror(req, ERRSRV, ERRunknownsmb);
868 return;
871 /****************************************************************************
872 Reply to an ioctl.
873 conn POINTER CAN BE NULL HERE !
874 ****************************************************************************/
876 void reply_ioctl(struct smb_request *req)
878 connection_struct *conn = req->conn;
879 uint16 device;
880 uint16 function;
881 uint32 ioctl_code;
882 int replysize;
883 char *p;
885 START_PROFILE(SMBioctl);
887 if (req->wct < 3) {
888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
889 END_PROFILE(SMBioctl);
890 return;
893 device = SVAL(req->vwv+1, 0);
894 function = SVAL(req->vwv+2, 0);
895 ioctl_code = (device << 16) + function;
897 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
899 switch (ioctl_code) {
900 case IOCTL_QUERY_JOB_INFO:
901 replysize = 32;
902 break;
903 default:
904 reply_doserror(req, ERRSRV, ERRnosupport);
905 END_PROFILE(SMBioctl);
906 return;
909 reply_outbuf(req, 8, replysize+1);
910 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
911 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
912 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
913 p = smb_buf(req->outbuf);
914 memset(p, '\0', replysize+1); /* valgrind-safe. */
915 p += 1; /* Allow for alignment */
917 switch (ioctl_code) {
918 case IOCTL_QUERY_JOB_INFO:
920 files_struct *fsp = file_fsp(
921 req, SVAL(req->vwv+0, 0));
922 if (!fsp) {
923 reply_doserror(req, ERRDOS, ERRbadfid);
924 END_PROFILE(SMBioctl);
925 return;
927 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
928 srvstr_push((char *)req->outbuf, req->flags2, p+2,
929 global_myname(), 15,
930 STR_TERMINATE|STR_ASCII);
931 if (conn) {
932 srvstr_push((char *)req->outbuf, req->flags2,
933 p+18, lp_servicename(SNUM(conn)),
934 13, STR_TERMINATE|STR_ASCII);
935 } else {
936 memset(p+18, 0, 13);
938 break;
942 END_PROFILE(SMBioctl);
943 return;
946 /****************************************************************************
947 Strange checkpath NTSTATUS mapping.
948 ****************************************************************************/
950 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
952 /* Strange DOS error code semantics only for checkpath... */
953 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
954 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
955 /* We need to map to ERRbadpath */
956 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
959 return status;
962 /****************************************************************************
963 Reply to a checkpath.
964 ****************************************************************************/
966 void reply_checkpath(struct smb_request *req)
968 connection_struct *conn = req->conn;
969 char *name = NULL;
970 SMB_STRUCT_STAT sbuf;
971 NTSTATUS status;
972 TALLOC_CTX *ctx = talloc_tos();
974 START_PROFILE(SMBcheckpath);
976 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
977 STR_TERMINATE, &status);
979 if (!NT_STATUS_IS_OK(status)) {
980 status = map_checkpath_error(req->flags2, status);
981 reply_nterror(req, status);
982 END_PROFILE(SMBcheckpath);
983 return;
986 status = resolve_dfspath(ctx, conn,
987 req->flags2 & FLAGS2_DFS_PATHNAMES,
988 name,
989 &name);
990 if (!NT_STATUS_IS_OK(status)) {
991 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
992 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
993 ERRSRV, ERRbadpath);
994 END_PROFILE(SMBcheckpath);
995 return;
997 goto path_err;
1000 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1002 status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 goto path_err;
1007 status = check_name(conn, name);
1008 if (!NT_STATUS_IS_OK(status)) {
1009 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
1010 goto path_err;
1013 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
1014 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1015 status = map_nt_error_from_unix(errno);
1016 goto path_err;
1019 if (!S_ISDIR(sbuf.st_mode)) {
1020 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1021 ERRDOS, ERRbadpath);
1022 END_PROFILE(SMBcheckpath);
1023 return;
1026 reply_outbuf(req, 0, 0);
1028 END_PROFILE(SMBcheckpath);
1029 return;
1031 path_err:
1033 END_PROFILE(SMBcheckpath);
1035 /* We special case this - as when a Windows machine
1036 is parsing a path is steps through the components
1037 one at a time - if a component fails it expects
1038 ERRbadpath, not ERRbadfile.
1040 status = map_checkpath_error(req->flags2, status);
1041 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1043 * Windows returns different error codes if
1044 * the parent directory is valid but not the
1045 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1046 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1047 * if the path is invalid.
1049 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1050 ERRDOS, ERRbadpath);
1051 return;
1054 reply_nterror(req, status);
1057 /****************************************************************************
1058 Reply to a getatr.
1059 ****************************************************************************/
1061 void reply_getatr(struct smb_request *req)
1063 connection_struct *conn = req->conn;
1064 char *fname = NULL;
1065 SMB_STRUCT_STAT sbuf;
1066 int mode=0;
1067 SMB_OFF_T size=0;
1068 time_t mtime=0;
1069 const char *p;
1070 NTSTATUS status;
1071 TALLOC_CTX *ctx = talloc_tos();
1073 START_PROFILE(SMBgetatr);
1075 p = (const char *)req->buf + 1;
1076 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1077 if (!NT_STATUS_IS_OK(status)) {
1078 reply_nterror(req, status);
1079 END_PROFILE(SMBgetatr);
1080 return;
1083 status = resolve_dfspath(ctx, conn,
1084 req->flags2 & FLAGS2_DFS_PATHNAMES,
1085 fname,
1086 &fname);
1087 if (!NT_STATUS_IS_OK(status)) {
1088 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1089 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1090 ERRSRV, ERRbadpath);
1091 END_PROFILE(SMBgetatr);
1092 return;
1094 reply_nterror(req, status);
1095 END_PROFILE(SMBgetatr);
1096 return;
1099 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1100 under WfWg - weird! */
1101 if (*fname == '\0') {
1102 mode = aHIDDEN | aDIR;
1103 if (!CAN_WRITE(conn)) {
1104 mode |= aRONLY;
1106 size = 0;
1107 mtime = 0;
1108 } else {
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(SMBgetatr);
1113 return;
1115 status = check_name(conn, fname);
1116 if (!NT_STATUS_IS_OK(status)) {
1117 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1118 reply_nterror(req, status);
1119 END_PROFILE(SMBgetatr);
1120 return;
1122 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1123 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1124 reply_unixerror(req, ERRDOS,ERRbadfile);
1125 END_PROFILE(SMBgetatr);
1126 return;
1129 mode = dos_mode(conn,fname,&sbuf);
1130 size = sbuf.st_size;
1131 mtime = sbuf.st_mtime;
1132 if (mode & aDIR) {
1133 size = 0;
1137 reply_outbuf(req, 10, 0);
1139 SSVAL(req->outbuf,smb_vwv0,mode);
1140 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1141 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1142 } else {
1143 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1145 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1147 if (Protocol >= PROTOCOL_NT1) {
1148 SSVAL(req->outbuf, smb_flg2,
1149 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1152 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1154 END_PROFILE(SMBgetatr);
1155 return;
1158 /****************************************************************************
1159 Reply to a setatr.
1160 ****************************************************************************/
1162 void reply_setatr(struct smb_request *req)
1164 struct smb_file_time ft;
1165 connection_struct *conn = req->conn;
1166 char *fname = NULL;
1167 int mode;
1168 time_t mtime;
1169 SMB_STRUCT_STAT sbuf;
1170 const char *p;
1171 NTSTATUS status;
1172 TALLOC_CTX *ctx = talloc_tos();
1174 START_PROFILE(SMBsetatr);
1176 ZERO_STRUCT(ft);
1178 if (req->wct < 2) {
1179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1180 return;
1183 p = (const char *)req->buf + 1;
1184 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1185 if (!NT_STATUS_IS_OK(status)) {
1186 reply_nterror(req, status);
1187 END_PROFILE(SMBsetatr);
1188 return;
1191 status = resolve_dfspath(ctx, conn,
1192 req->flags2 & FLAGS2_DFS_PATHNAMES,
1193 fname,
1194 &fname);
1195 if (!NT_STATUS_IS_OK(status)) {
1196 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1197 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1198 ERRSRV, ERRbadpath);
1199 END_PROFILE(SMBsetatr);
1200 return;
1202 reply_nterror(req, status);
1203 END_PROFILE(SMBsetatr);
1204 return;
1207 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 reply_nterror(req, status);
1210 END_PROFILE(SMBsetatr);
1211 return;
1214 status = check_name(conn, fname);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 reply_nterror(req, status);
1217 END_PROFILE(SMBsetatr);
1218 return;
1221 if (fname[0] == '.' && fname[1] == '\0') {
1223 * Not sure here is the right place to catch this
1224 * condition. Might be moved to somewhere else later -- vl
1226 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1227 END_PROFILE(SMBsetatr);
1228 return;
1231 mode = SVAL(req->vwv+0, 0);
1232 mtime = srv_make_unix_date3(req->vwv+1);
1234 ft.mtime = convert_time_t_to_timespec(mtime);
1235 status = smb_set_file_time(conn, NULL, fname,
1236 &sbuf, &ft, true);
1237 if (!NT_STATUS_IS_OK(status)) {
1238 reply_unixerror(req, ERRDOS, ERRnoaccess);
1239 END_PROFILE(SMBsetatr);
1240 return;
1243 if (mode != FILE_ATTRIBUTE_NORMAL) {
1244 if (VALID_STAT_OF_DIR(sbuf))
1245 mode |= aDIR;
1246 else
1247 mode &= ~aDIR;
1249 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1250 reply_unixerror(req, ERRDOS, ERRnoaccess);
1251 END_PROFILE(SMBsetatr);
1252 return;
1256 reply_outbuf(req, 0, 0);
1258 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1260 END_PROFILE(SMBsetatr);
1261 return;
1264 /****************************************************************************
1265 Reply to a dskattr.
1266 ****************************************************************************/
1268 void reply_dskattr(struct smb_request *req)
1270 connection_struct *conn = req->conn;
1271 uint64_t dfree,dsize,bsize;
1272 START_PROFILE(SMBdskattr);
1274 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1275 reply_unixerror(req, ERRHRD, ERRgeneral);
1276 END_PROFILE(SMBdskattr);
1277 return;
1280 reply_outbuf(req, 5, 0);
1282 if (Protocol <= PROTOCOL_LANMAN2) {
1283 double total_space, free_space;
1284 /* we need to scale this to a number that DOS6 can handle. We
1285 use floating point so we can handle large drives on systems
1286 that don't have 64 bit integers
1288 we end up displaying a maximum of 2G to DOS systems
1290 total_space = dsize * (double)bsize;
1291 free_space = dfree * (double)bsize;
1293 dsize = (uint64_t)((total_space+63*512) / (64*512));
1294 dfree = (uint64_t)((free_space+63*512) / (64*512));
1296 if (dsize > 0xFFFF) dsize = 0xFFFF;
1297 if (dfree > 0xFFFF) dfree = 0xFFFF;
1299 SSVAL(req->outbuf,smb_vwv0,dsize);
1300 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1301 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1302 SSVAL(req->outbuf,smb_vwv3,dfree);
1303 } else {
1304 SSVAL(req->outbuf,smb_vwv0,dsize);
1305 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1306 SSVAL(req->outbuf,smb_vwv2,512);
1307 SSVAL(req->outbuf,smb_vwv3,dfree);
1310 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1312 END_PROFILE(SMBdskattr);
1313 return;
1316 /****************************************************************************
1317 Reply to a search.
1318 Can be called from SMBsearch, SMBffirst or SMBfunique.
1319 ****************************************************************************/
1321 void reply_search(struct smb_request *req)
1323 connection_struct *conn = req->conn;
1324 const char *mask = NULL;
1325 char *directory = NULL;
1326 char *fname = NULL;
1327 SMB_OFF_T size;
1328 uint32 mode;
1329 time_t date;
1330 uint32 dirtype;
1331 unsigned int numentries = 0;
1332 unsigned int maxentries = 0;
1333 bool finished = False;
1334 const char *p;
1335 int status_len;
1336 char *path = NULL;
1337 char status[21];
1338 int dptr_num= -1;
1339 bool check_descend = False;
1340 bool expect_close = False;
1341 NTSTATUS nt_status;
1342 bool mask_contains_wcard = False;
1343 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1344 TALLOC_CTX *ctx = talloc_tos();
1345 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1347 START_PROFILE(SMBsearch);
1349 if (req->wct < 2) {
1350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1351 END_PROFILE(SMBsearch);
1352 return;
1355 if (lp_posix_pathnames()) {
1356 reply_unknown_new(req, req->cmd);
1357 END_PROFILE(SMBsearch);
1358 return;
1361 /* If we were called as SMBffirst then we must expect close. */
1362 if(req->cmd == SMBffirst) {
1363 expect_close = True;
1366 reply_outbuf(req, 1, 3);
1367 maxentries = SVAL(req->vwv+0, 0);
1368 dirtype = SVAL(req->vwv+1, 0);
1369 p = (const char *)req->buf + 1;
1370 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1371 &nt_status, &mask_contains_wcard);
1372 if (!NT_STATUS_IS_OK(nt_status)) {
1373 reply_nterror(req, nt_status);
1374 END_PROFILE(SMBsearch);
1375 return;
1378 nt_status = resolve_dfspath_wcard(ctx, conn,
1379 req->flags2 & FLAGS2_DFS_PATHNAMES,
1380 path,
1381 &path,
1382 &mask_contains_wcard);
1383 if (!NT_STATUS_IS_OK(nt_status)) {
1384 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1385 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1386 ERRSRV, ERRbadpath);
1387 END_PROFILE(SMBsearch);
1388 return;
1390 reply_nterror(req, nt_status);
1391 END_PROFILE(SMBsearch);
1392 return;
1395 p++;
1396 status_len = SVAL(p, 0);
1397 p += 2;
1399 /* dirtype &= ~aDIR; */
1401 if (status_len == 0) {
1402 SMB_STRUCT_STAT sbuf;
1404 nt_status = unix_convert(ctx, conn, path, True,
1405 &directory, NULL, &sbuf);
1406 if (!NT_STATUS_IS_OK(nt_status)) {
1407 reply_nterror(req, nt_status);
1408 END_PROFILE(SMBsearch);
1409 return;
1412 nt_status = check_name(conn, directory);
1413 if (!NT_STATUS_IS_OK(nt_status)) {
1414 reply_nterror(req, nt_status);
1415 END_PROFILE(SMBsearch);
1416 return;
1419 p = strrchr_m(directory,'/');
1420 if ((p != NULL) && (*directory != '/')) {
1421 mask = p + 1;
1422 directory = talloc_strndup(ctx, directory,
1423 PTR_DIFF(p, directory));
1424 } else {
1425 mask = directory;
1426 directory = talloc_strdup(ctx,".");
1429 if (!directory) {
1430 reply_nterror(req, NT_STATUS_NO_MEMORY);
1431 END_PROFILE(SMBsearch);
1432 return;
1435 memset((char *)status,'\0',21);
1436 SCVAL(status,0,(dirtype & 0x1F));
1438 nt_status = dptr_create(conn,
1439 directory,
1440 True,
1441 expect_close,
1442 req->smbpid,
1443 mask,
1444 mask_contains_wcard,
1445 dirtype,
1446 &conn->dirptr);
1447 if (!NT_STATUS_IS_OK(nt_status)) {
1448 reply_nterror(req, nt_status);
1449 END_PROFILE(SMBsearch);
1450 return;
1452 dptr_num = dptr_dnum(conn->dirptr);
1453 } else {
1454 int status_dirtype;
1456 memcpy(status,p,21);
1457 status_dirtype = CVAL(status,0) & 0x1F;
1458 if (status_dirtype != (dirtype & 0x1F)) {
1459 dirtype = status_dirtype;
1462 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1463 if (!conn->dirptr) {
1464 goto SearchEmpty;
1466 string_set(&conn->dirpath,dptr_path(dptr_num));
1467 mask = dptr_wcard(dptr_num);
1468 if (!mask) {
1469 goto SearchEmpty;
1472 * For a 'continue' search we have no string. So
1473 * check from the initial saved string.
1475 mask_contains_wcard = ms_has_wild(mask);
1476 dirtype = dptr_attr(dptr_num);
1479 DEBUG(4,("dptr_num is %d\n",dptr_num));
1481 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1482 dptr_init_search_op(conn->dirptr);
1484 if ((dirtype&0x1F) == aVOLID) {
1485 char buf[DIR_STRUCT_SIZE];
1486 memcpy(buf,status,21);
1487 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1488 0,aVOLID,0,!allow_long_path_components)) {
1489 reply_nterror(req, NT_STATUS_NO_MEMORY);
1490 END_PROFILE(SMBsearch);
1491 return;
1493 dptr_fill(buf+12,dptr_num);
1494 if (dptr_zero(buf+12) && (status_len==0)) {
1495 numentries = 1;
1496 } else {
1497 numentries = 0;
1499 if (message_push_blob(&req->outbuf,
1500 data_blob_const(buf, sizeof(buf)))
1501 == -1) {
1502 reply_nterror(req, NT_STATUS_NO_MEMORY);
1503 END_PROFILE(SMBsearch);
1504 return;
1506 } else {
1507 unsigned int i;
1508 maxentries = MIN(
1509 maxentries,
1510 ((BUFFER_SIZE -
1511 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1512 /DIR_STRUCT_SIZE));
1514 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1515 conn->dirpath,lp_dontdescend(SNUM(conn))));
1516 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1517 check_descend = True;
1520 for (i=numentries;(i<maxentries) && !finished;i++) {
1521 finished = !get_dir_entry(ctx,
1522 conn,
1523 mask,
1524 dirtype,
1525 &fname,
1526 &size,
1527 &mode,
1528 &date,
1529 check_descend,
1530 ask_sharemode);
1531 if (!finished) {
1532 char buf[DIR_STRUCT_SIZE];
1533 memcpy(buf,status,21);
1534 if (!make_dir_struct(ctx,
1535 buf,
1536 mask,
1537 fname,
1538 size,
1539 mode,
1540 date,
1541 !allow_long_path_components)) {
1542 reply_nterror(req, NT_STATUS_NO_MEMORY);
1543 END_PROFILE(SMBsearch);
1544 return;
1546 if (!dptr_fill(buf+12,dptr_num)) {
1547 break;
1549 if (message_push_blob(&req->outbuf,
1550 data_blob_const(buf, sizeof(buf)))
1551 == -1) {
1552 reply_nterror(req, NT_STATUS_NO_MEMORY);
1553 END_PROFILE(SMBsearch);
1554 return;
1556 numentries++;
1561 SearchEmpty:
1563 /* If we were called as SMBffirst with smb_search_id == NULL
1564 and no entries were found then return error and close dirptr
1565 (X/Open spec) */
1567 if (numentries == 0) {
1568 dptr_close(&dptr_num);
1569 } else if(expect_close && status_len == 0) {
1570 /* Close the dptr - we know it's gone */
1571 dptr_close(&dptr_num);
1574 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1575 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1576 dptr_close(&dptr_num);
1579 if ((numentries == 0) && !mask_contains_wcard) {
1580 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1581 END_PROFILE(SMBsearch);
1582 return;
1585 SSVAL(req->outbuf,smb_vwv0,numentries);
1586 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1587 SCVAL(smb_buf(req->outbuf),0,5);
1588 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1590 /* The replies here are never long name. */
1591 SSVAL(req->outbuf, smb_flg2,
1592 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1593 if (!allow_long_path_components) {
1594 SSVAL(req->outbuf, smb_flg2,
1595 SVAL(req->outbuf, smb_flg2)
1596 & (~FLAGS2_LONG_PATH_COMPONENTS));
1599 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1600 SSVAL(req->outbuf, smb_flg2,
1601 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1603 if (!directory) {
1604 directory = dptr_path(dptr_num);
1607 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1608 smb_fn_name(req->cmd),
1609 mask,
1610 directory ? directory : "./",
1611 dirtype,
1612 numentries,
1613 maxentries ));
1615 END_PROFILE(SMBsearch);
1616 return;
1619 /****************************************************************************
1620 Reply to a fclose (stop directory search).
1621 ****************************************************************************/
1623 void reply_fclose(struct smb_request *req)
1625 int status_len;
1626 char status[21];
1627 int dptr_num= -2;
1628 const char *p;
1629 char *path = NULL;
1630 NTSTATUS err;
1631 bool path_contains_wcard = False;
1632 TALLOC_CTX *ctx = talloc_tos();
1634 START_PROFILE(SMBfclose);
1636 if (lp_posix_pathnames()) {
1637 reply_unknown_new(req, req->cmd);
1638 END_PROFILE(SMBfclose);
1639 return;
1642 p = (const char *)req->buf + 1;
1643 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1644 &err, &path_contains_wcard);
1645 if (!NT_STATUS_IS_OK(err)) {
1646 reply_nterror(req, err);
1647 END_PROFILE(SMBfclose);
1648 return;
1650 p++;
1651 status_len = SVAL(p,0);
1652 p += 2;
1654 if (status_len == 0) {
1655 reply_doserror(req, ERRSRV, ERRsrverror);
1656 END_PROFILE(SMBfclose);
1657 return;
1660 memcpy(status,p,21);
1662 if(dptr_fetch(status+12,&dptr_num)) {
1663 /* Close the dptr - we know it's gone */
1664 dptr_close(&dptr_num);
1667 reply_outbuf(req, 1, 0);
1668 SSVAL(req->outbuf,smb_vwv0,0);
1670 DEBUG(3,("search close\n"));
1672 END_PROFILE(SMBfclose);
1673 return;
1676 /****************************************************************************
1677 Reply to an open.
1678 ****************************************************************************/
1680 void reply_open(struct smb_request *req)
1682 connection_struct *conn = req->conn;
1683 char *fname = NULL;
1684 uint32 fattr=0;
1685 SMB_OFF_T size = 0;
1686 time_t mtime=0;
1687 int info;
1688 SMB_STRUCT_STAT sbuf;
1689 files_struct *fsp;
1690 int oplock_request;
1691 int deny_mode;
1692 uint32 dos_attr;
1693 uint32 access_mask;
1694 uint32 share_mode;
1695 uint32 create_disposition;
1696 uint32 create_options = 0;
1697 NTSTATUS status;
1698 TALLOC_CTX *ctx = talloc_tos();
1700 START_PROFILE(SMBopen);
1702 SET_STAT_INVALID(sbuf);
1704 if (req->wct < 2) {
1705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1706 END_PROFILE(SMBopen);
1707 return;
1710 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1711 deny_mode = SVAL(req->vwv+0, 0);
1712 dos_attr = SVAL(req->vwv+1, 0);
1714 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1715 STR_TERMINATE, &status);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 reply_nterror(req, status);
1718 END_PROFILE(SMBopen);
1719 return;
1722 if (!map_open_params_to_ntcreate(
1723 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1724 &share_mode, &create_disposition, &create_options)) {
1725 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1726 END_PROFILE(SMBopen);
1727 return;
1730 status = SMB_VFS_CREATE_FILE(
1731 conn, /* conn */
1732 req, /* req */
1733 0, /* root_dir_fid */
1734 fname, /* fname */
1735 CFF_DOS_PATH, /* create_file_flags */
1736 access_mask, /* access_mask */
1737 share_mode, /* share_access */
1738 create_disposition, /* create_disposition*/
1739 create_options, /* create_options */
1740 dos_attr, /* file_attributes */
1741 oplock_request, /* oplock_request */
1742 0, /* allocation_size */
1743 NULL, /* sd */
1744 NULL, /* ea_list */
1745 &fsp, /* result */
1746 &info, /* pinfo */
1747 &sbuf); /* psbuf */
1749 if (!NT_STATUS_IS_OK(status)) {
1750 if (open_was_deferred(req->mid)) {
1751 /* We have re-scheduled this call. */
1752 END_PROFILE(SMBopen);
1753 return;
1755 reply_openerror(req, status);
1756 END_PROFILE(SMBopen);
1757 return;
1760 size = sbuf.st_size;
1761 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1762 mtime = sbuf.st_mtime;
1764 if (fattr & aDIR) {
1765 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1766 close_file(req, fsp, ERROR_CLOSE);
1767 reply_doserror(req, ERRDOS,ERRnoaccess);
1768 END_PROFILE(SMBopen);
1769 return;
1772 reply_outbuf(req, 7, 0);
1773 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1774 SSVAL(req->outbuf,smb_vwv1,fattr);
1775 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1776 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1777 } else {
1778 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1780 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1781 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1783 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1784 SCVAL(req->outbuf,smb_flg,
1785 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1788 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1789 SCVAL(req->outbuf,smb_flg,
1790 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1792 END_PROFILE(SMBopen);
1793 return;
1796 /****************************************************************************
1797 Reply to an open and X.
1798 ****************************************************************************/
1800 void reply_open_and_X(struct smb_request *req)
1802 connection_struct *conn = req->conn;
1803 char *fname = NULL;
1804 uint16 open_flags;
1805 int deny_mode;
1806 uint32 smb_attr;
1807 /* Breakout the oplock request bits so we can set the
1808 reply bits separately. */
1809 int ex_oplock_request;
1810 int core_oplock_request;
1811 int oplock_request;
1812 #if 0
1813 int smb_sattr = SVAL(req->vwv+4, 0);
1814 uint32 smb_time = make_unix_date3(req->vwv+6);
1815 #endif
1816 int smb_ofun;
1817 uint32 fattr=0;
1818 int mtime=0;
1819 SMB_STRUCT_STAT sbuf;
1820 int smb_action = 0;
1821 files_struct *fsp;
1822 NTSTATUS status;
1823 uint64_t allocation_size;
1824 ssize_t retval = -1;
1825 uint32 access_mask;
1826 uint32 share_mode;
1827 uint32 create_disposition;
1828 uint32 create_options = 0;
1829 TALLOC_CTX *ctx = talloc_tos();
1831 START_PROFILE(SMBopenX);
1833 if (req->wct < 15) {
1834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1835 END_PROFILE(SMBopenX);
1836 return;
1839 SET_STAT_INVALID(sbuf);
1841 open_flags = SVAL(req->vwv+2, 0);
1842 deny_mode = SVAL(req->vwv+3, 0);
1843 smb_attr = SVAL(req->vwv+5, 0);
1844 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1845 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1846 oplock_request = ex_oplock_request | core_oplock_request;
1847 smb_ofun = SVAL(req->vwv+8, 0);
1848 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1850 /* If it's an IPC, pass off the pipe handler. */
1851 if (IS_IPC(conn)) {
1852 if (lp_nt_pipe_support()) {
1853 reply_open_pipe_and_X(conn, req);
1854 } else {
1855 reply_doserror(req, ERRSRV, ERRaccess);
1857 END_PROFILE(SMBopenX);
1858 return;
1861 /* XXXX we need to handle passed times, sattr and flags */
1862 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1863 STR_TERMINATE, &status);
1864 if (!NT_STATUS_IS_OK(status)) {
1865 reply_nterror(req, status);
1866 END_PROFILE(SMBopenX);
1867 return;
1870 if (!map_open_params_to_ntcreate(
1871 fname, deny_mode, smb_ofun, &access_mask,
1872 &share_mode, &create_disposition, &create_options)) {
1873 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1874 END_PROFILE(SMBopenX);
1875 return;
1878 status = SMB_VFS_CREATE_FILE(
1879 conn, /* conn */
1880 req, /* req */
1881 0, /* root_dir_fid */
1882 fname, /* fname */
1883 CFF_DOS_PATH, /* create_file_flags */
1884 access_mask, /* access_mask */
1885 share_mode, /* share_access */
1886 create_disposition, /* create_disposition*/
1887 create_options, /* create_options */
1888 smb_attr, /* file_attributes */
1889 oplock_request, /* oplock_request */
1890 0, /* allocation_size */
1891 NULL, /* sd */
1892 NULL, /* ea_list */
1893 &fsp, /* result */
1894 &smb_action, /* pinfo */
1895 &sbuf); /* psbuf */
1897 if (!NT_STATUS_IS_OK(status)) {
1898 END_PROFILE(SMBopenX);
1899 if (open_was_deferred(req->mid)) {
1900 /* We have re-scheduled this call. */
1901 return;
1903 reply_openerror(req, status);
1904 return;
1907 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1908 if the file is truncated or created. */
1909 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1910 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1911 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1912 close_file(req, fsp, ERROR_CLOSE);
1913 reply_nterror(req, NT_STATUS_DISK_FULL);
1914 END_PROFILE(SMBopenX);
1915 return;
1917 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1918 if (retval < 0) {
1919 close_file(req, fsp, ERROR_CLOSE);
1920 reply_nterror(req, NT_STATUS_DISK_FULL);
1921 END_PROFILE(SMBopenX);
1922 return;
1924 sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1927 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1928 mtime = sbuf.st_mtime;
1929 if (fattr & aDIR) {
1930 close_file(req, fsp, ERROR_CLOSE);
1931 reply_doserror(req, ERRDOS, ERRnoaccess);
1932 END_PROFILE(SMBopenX);
1933 return;
1936 /* If the caller set the extended oplock request bit
1937 and we granted one (by whatever means) - set the
1938 correct bit for extended oplock reply.
1941 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1942 smb_action |= EXTENDED_OPLOCK_GRANTED;
1945 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1946 smb_action |= EXTENDED_OPLOCK_GRANTED;
1949 /* If the caller set the core oplock request bit
1950 and we granted one (by whatever means) - set the
1951 correct bit for core oplock reply.
1954 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1955 reply_outbuf(req, 19, 0);
1956 } else {
1957 reply_outbuf(req, 15, 0);
1960 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1961 SCVAL(req->outbuf, smb_flg,
1962 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1965 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1966 SCVAL(req->outbuf, smb_flg,
1967 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1970 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1971 SSVAL(req->outbuf,smb_vwv3,fattr);
1972 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1973 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1974 } else {
1975 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1977 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1978 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1979 SSVAL(req->outbuf,smb_vwv11,smb_action);
1981 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1982 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1985 END_PROFILE(SMBopenX);
1986 chain_reply(req);
1987 return;
1990 /****************************************************************************
1991 Reply to a SMBulogoffX.
1992 ****************************************************************************/
1994 void reply_ulogoffX(struct smb_request *req)
1996 user_struct *vuser;
1998 START_PROFILE(SMBulogoffX);
2000 vuser = get_valid_user_struct(req->vuid);
2002 if(vuser == NULL) {
2003 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2004 req->vuid));
2007 /* in user level security we are supposed to close any files
2008 open by this user */
2009 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2010 file_close_user(req->vuid);
2013 invalidate_vuid(req->vuid);
2015 reply_outbuf(req, 2, 0);
2017 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2019 END_PROFILE(SMBulogoffX);
2020 chain_reply(req);
2023 /****************************************************************************
2024 Reply to a mknew or a create.
2025 ****************************************************************************/
2027 void reply_mknew(struct smb_request *req)
2029 connection_struct *conn = req->conn;
2030 char *fname = NULL;
2031 uint32 fattr = 0;
2032 struct smb_file_time ft;
2033 files_struct *fsp;
2034 int oplock_request = 0;
2035 SMB_STRUCT_STAT sbuf;
2036 NTSTATUS status;
2037 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2038 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2039 uint32 create_disposition;
2040 uint32 create_options = 0;
2041 TALLOC_CTX *ctx = talloc_tos();
2043 START_PROFILE(SMBcreate);
2044 ZERO_STRUCT(ft);
2045 SET_STAT_INVALID(sbuf);
2047 if (req->wct < 3) {
2048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2049 END_PROFILE(SMBcreate);
2050 return;
2053 fattr = SVAL(req->vwv+0, 0);
2054 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2056 /* mtime. */
2057 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2059 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2060 STR_TERMINATE, &status);
2061 if (!NT_STATUS_IS_OK(status)) {
2062 reply_nterror(req, status);
2063 END_PROFILE(SMBcreate);
2064 return;
2067 if (fattr & aVOLID) {
2068 DEBUG(0,("Attempt to create file (%s) with volid set - "
2069 "please report this\n", fname));
2072 if(req->cmd == SMBmknew) {
2073 /* We should fail if file exists. */
2074 create_disposition = FILE_CREATE;
2075 } else {
2076 /* Create if file doesn't exist, truncate if it does. */
2077 create_disposition = FILE_OVERWRITE_IF;
2080 status = SMB_VFS_CREATE_FILE(
2081 conn, /* conn */
2082 req, /* req */
2083 0, /* root_dir_fid */
2084 fname, /* fname */
2085 CFF_DOS_PATH, /* create_file_flags */
2086 access_mask, /* access_mask */
2087 share_mode, /* share_access */
2088 create_disposition, /* create_disposition*/
2089 create_options, /* create_options */
2090 fattr, /* file_attributes */
2091 oplock_request, /* oplock_request */
2092 0, /* allocation_size */
2093 NULL, /* sd */
2094 NULL, /* ea_list */
2095 &fsp, /* result */
2096 NULL, /* pinfo */
2097 &sbuf); /* psbuf */
2099 if (!NT_STATUS_IS_OK(status)) {
2100 END_PROFILE(SMBcreate);
2101 if (open_was_deferred(req->mid)) {
2102 /* We have re-scheduled this call. */
2103 return;
2105 reply_openerror(req, status);
2106 return;
2109 ft.atime = get_atimespec(&sbuf); /* atime. */
2110 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2111 if (!NT_STATUS_IS_OK(status)) {
2112 END_PROFILE(SMBcreate);
2113 reply_openerror(req, status);
2114 return;
2117 reply_outbuf(req, 1, 0);
2118 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2120 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2121 SCVAL(req->outbuf,smb_flg,
2122 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2125 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2126 SCVAL(req->outbuf,smb_flg,
2127 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2130 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2131 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2132 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2134 END_PROFILE(SMBcreate);
2135 return;
2138 /****************************************************************************
2139 Reply to a create temporary file.
2140 ****************************************************************************/
2142 void reply_ctemp(struct smb_request *req)
2144 connection_struct *conn = req->conn;
2145 char *fname = NULL;
2146 uint32 fattr;
2147 files_struct *fsp;
2148 int oplock_request;
2149 int tmpfd;
2150 SMB_STRUCT_STAT sbuf;
2151 char *s;
2152 NTSTATUS status;
2153 TALLOC_CTX *ctx = talloc_tos();
2155 START_PROFILE(SMBctemp);
2157 if (req->wct < 3) {
2158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2159 END_PROFILE(SMBctemp);
2160 return;
2163 fattr = SVAL(req->vwv+0, 0);
2164 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2166 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2167 STR_TERMINATE, &status);
2168 if (!NT_STATUS_IS_OK(status)) {
2169 reply_nterror(req, status);
2170 END_PROFILE(SMBctemp);
2171 return;
2173 if (*fname) {
2174 fname = talloc_asprintf(ctx,
2175 "%s/TMXXXXXX",
2176 fname);
2177 } else {
2178 fname = talloc_strdup(ctx, "TMXXXXXX");
2181 if (!fname) {
2182 reply_nterror(req, NT_STATUS_NO_MEMORY);
2183 END_PROFILE(SMBctemp);
2184 return;
2187 status = resolve_dfspath(ctx, conn,
2188 req->flags2 & FLAGS2_DFS_PATHNAMES,
2189 fname,
2190 &fname);
2191 if (!NT_STATUS_IS_OK(status)) {
2192 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2193 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2194 ERRSRV, ERRbadpath);
2195 END_PROFILE(SMBctemp);
2196 return;
2198 reply_nterror(req, status);
2199 END_PROFILE(SMBctemp);
2200 return;
2203 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2204 if (!NT_STATUS_IS_OK(status)) {
2205 reply_nterror(req, status);
2206 END_PROFILE(SMBctemp);
2207 return;
2210 status = check_name(conn, fname);
2211 if (!NT_STATUS_IS_OK(status)) {
2212 reply_nterror(req, status);
2213 END_PROFILE(SMBctemp);
2214 return;
2217 tmpfd = mkstemp(fname);
2218 if (tmpfd == -1) {
2219 reply_unixerror(req, ERRDOS, ERRnoaccess);
2220 END_PROFILE(SMBctemp);
2221 return;
2224 SET_STAT_INVALID(sbuf);
2225 SMB_VFS_STAT(conn,fname,&sbuf);
2227 /* We should fail if file does not exist. */
2228 status = SMB_VFS_CREATE_FILE(
2229 conn, /* conn */
2230 req, /* req */
2231 0, /* root_dir_fid */
2232 fname, /* fname */
2233 0, /* create_file_flags */
2234 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2235 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2236 FILE_OPEN, /* create_disposition*/
2237 0, /* create_options */
2238 fattr, /* file_attributes */
2239 oplock_request, /* oplock_request */
2240 0, /* allocation_size */
2241 NULL, /* sd */
2242 NULL, /* ea_list */
2243 &fsp, /* result */
2244 NULL, /* pinfo */
2245 &sbuf); /* psbuf */
2247 /* close fd from mkstemp() */
2248 close(tmpfd);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 if (open_was_deferred(req->mid)) {
2252 /* We have re-scheduled this call. */
2253 END_PROFILE(SMBctemp);
2254 return;
2256 reply_openerror(req, status);
2257 END_PROFILE(SMBctemp);
2258 return;
2261 reply_outbuf(req, 1, 0);
2262 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2264 /* the returned filename is relative to the directory */
2265 s = strrchr_m(fsp->fsp_name, '/');
2266 if (!s) {
2267 s = fsp->fsp_name;
2268 } else {
2269 s++;
2272 #if 0
2273 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2274 thing in the byte section. JRA */
2275 SSVALS(p, 0, -1); /* what is this? not in spec */
2276 #endif
2277 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2278 == -1) {
2279 reply_nterror(req, NT_STATUS_NO_MEMORY);
2280 END_PROFILE(SMBctemp);
2281 return;
2284 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2285 SCVAL(req->outbuf, smb_flg,
2286 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2289 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2290 SCVAL(req->outbuf, smb_flg,
2291 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2294 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2295 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2296 fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2298 END_PROFILE(SMBctemp);
2299 return;
2302 /*******************************************************************
2303 Check if a user is allowed to rename a file.
2304 ********************************************************************/
2306 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2307 uint16 dirtype, SMB_STRUCT_STAT *pst)
2309 uint32 fmode;
2311 if (!CAN_WRITE(conn)) {
2312 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2315 fmode = dos_mode(conn, fsp->fsp_name, pst);
2316 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2317 return NT_STATUS_NO_SUCH_FILE;
2320 if (S_ISDIR(pst->st_mode)) {
2321 if (fsp->posix_open) {
2322 return NT_STATUS_OK;
2325 /* If no pathnames are open below this
2326 directory, allow the rename. */
2328 if (file_find_subpath(fsp)) {
2329 return NT_STATUS_ACCESS_DENIED;
2331 return NT_STATUS_OK;
2334 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2335 return NT_STATUS_OK;
2338 return NT_STATUS_ACCESS_DENIED;
2341 /*******************************************************************
2342 * unlink a file with all relevant access checks
2343 *******************************************************************/
2345 static NTSTATUS do_unlink(connection_struct *conn,
2346 struct smb_request *req,
2347 const char *fname,
2348 uint32 dirtype)
2350 SMB_STRUCT_STAT sbuf;
2351 uint32 fattr;
2352 files_struct *fsp;
2353 uint32 dirtype_orig = dirtype;
2354 NTSTATUS status;
2356 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2358 if (!CAN_WRITE(conn)) {
2359 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2362 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2363 return map_nt_error_from_unix(errno);
2366 fattr = dos_mode(conn,fname,&sbuf);
2368 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2369 dirtype = aDIR|aARCH|aRONLY;
2372 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2373 if (!dirtype) {
2374 return NT_STATUS_NO_SUCH_FILE;
2377 if (!dir_check_ftype(conn, fattr, dirtype)) {
2378 if (fattr & aDIR) {
2379 return NT_STATUS_FILE_IS_A_DIRECTORY;
2381 return NT_STATUS_NO_SUCH_FILE;
2384 if (dirtype_orig & 0x8000) {
2385 /* These will never be set for POSIX. */
2386 return NT_STATUS_NO_SUCH_FILE;
2389 #if 0
2390 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2391 return NT_STATUS_FILE_IS_A_DIRECTORY;
2394 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2395 return NT_STATUS_NO_SUCH_FILE;
2398 if (dirtype & 0xFF00) {
2399 /* These will never be set for POSIX. */
2400 return NT_STATUS_NO_SUCH_FILE;
2403 dirtype &= 0xFF;
2404 if (!dirtype) {
2405 return NT_STATUS_NO_SUCH_FILE;
2408 /* Can't delete a directory. */
2409 if (fattr & aDIR) {
2410 return NT_STATUS_FILE_IS_A_DIRECTORY;
2412 #endif
2414 #if 0 /* JRATEST */
2415 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2416 return NT_STATUS_OBJECT_NAME_INVALID;
2417 #endif /* JRATEST */
2419 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2421 On a Windows share, a file with read-only dosmode can be opened with
2422 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2423 fails with NT_STATUS_CANNOT_DELETE error.
2425 This semantic causes a problem that a user can not
2426 rename a file with read-only dosmode on a Samba share
2427 from a Windows command prompt (i.e. cmd.exe, but can rename
2428 from Windows Explorer).
2431 if (!lp_delete_readonly(SNUM(conn))) {
2432 if (fattr & aRONLY) {
2433 return NT_STATUS_CANNOT_DELETE;
2437 /* On open checks the open itself will check the share mode, so
2438 don't do it here as we'll get it wrong. */
2440 status = SMB_VFS_CREATE_FILE
2441 (conn, /* conn */
2442 req, /* req */
2443 0, /* root_dir_fid */
2444 fname, /* fname */
2445 0, /* create_file_flags */
2446 DELETE_ACCESS, /* access_mask */
2447 FILE_SHARE_NONE, /* share_access */
2448 FILE_OPEN, /* create_disposition*/
2449 FILE_NON_DIRECTORY_FILE, /* create_options */
2450 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2451 0, /* oplock_request */
2452 0, /* allocation_size */
2453 NULL, /* sd */
2454 NULL, /* ea_list */
2455 &fsp, /* result */
2456 NULL, /* pinfo */
2457 &sbuf); /* psbuf */
2459 if (!NT_STATUS_IS_OK(status)) {
2460 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2461 nt_errstr(status)));
2462 return status;
2465 /* The set is across all open files on this dev/inode pair. */
2466 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2467 close_file(req, fsp, NORMAL_CLOSE);
2468 return NT_STATUS_ACCESS_DENIED;
2471 return close_file(req, fsp, NORMAL_CLOSE);
2474 /****************************************************************************
2475 The guts of the unlink command, split out so it may be called by the NT SMB
2476 code.
2477 ****************************************************************************/
2479 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2480 uint32 dirtype, const char *name_in, bool has_wild)
2482 const char *directory = NULL;
2483 char *mask = NULL;
2484 char *name = NULL;
2485 char *p = NULL;
2486 int count=0;
2487 NTSTATUS status = NT_STATUS_OK;
2488 SMB_STRUCT_STAT sbuf, st;
2489 TALLOC_CTX *ctx = talloc_tos();
2491 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2492 if (!NT_STATUS_IS_OK(status)) {
2493 return status;
2496 p = strrchr_m(name,'/');
2497 if (!p) {
2498 directory = talloc_strdup(ctx, ".");
2499 if (!directory) {
2500 return NT_STATUS_NO_MEMORY;
2502 mask = name;
2503 } else {
2504 *p = 0;
2505 directory = name;
2506 mask = p+1;
2510 * We should only check the mangled cache
2511 * here if unix_convert failed. This means
2512 * that the path in 'mask' doesn't exist
2513 * on the file system and so we need to look
2514 * for a possible mangle. This patch from
2515 * Tine Smukavec <valentin.smukavec@hermes.si>.
2518 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2519 char *new_mask = NULL;
2520 mangle_lookup_name_from_8_3(ctx,
2521 mask,
2522 &new_mask,
2523 conn->params );
2524 if (new_mask) {
2525 mask = new_mask;
2529 if (!has_wild) {
2530 directory = talloc_asprintf(ctx,
2531 "%s/%s",
2532 directory,
2533 mask);
2534 if (!directory) {
2535 return NT_STATUS_NO_MEMORY;
2537 if (dirtype == 0) {
2538 dirtype = FILE_ATTRIBUTE_NORMAL;
2541 status = check_name(conn, directory);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 return status;
2546 status = do_unlink(conn, req, directory, dirtype);
2547 if (!NT_STATUS_IS_OK(status)) {
2548 return status;
2551 count++;
2552 } else {
2553 struct smb_Dir *dir_hnd = NULL;
2554 long offset = 0;
2555 const char *dname;
2557 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2558 return NT_STATUS_OBJECT_NAME_INVALID;
2561 if (strequal(mask,"????????.???")) {
2562 mask[0] = '*';
2563 mask[1] = '\0';
2566 status = check_name(conn, directory);
2567 if (!NT_STATUS_IS_OK(status)) {
2568 return status;
2571 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2572 dirtype);
2573 if (dir_hnd == NULL) {
2574 return map_nt_error_from_unix(errno);
2577 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2578 the pattern matches against the long name, otherwise the short name
2579 We don't implement this yet XXXX
2582 status = NT_STATUS_NO_SUCH_FILE;
2584 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2585 char *fname = NULL;
2587 if (!is_visible_file(conn, directory, dname, &st,
2588 true))
2590 continue;
2593 /* Quick check for "." and ".." */
2594 if (ISDOT(dname) || ISDOTDOT(dname)) {
2595 continue;
2598 if(!mask_match(dname, mask, conn->case_sensitive)) {
2599 continue;
2602 fname = talloc_asprintf(ctx, "%s/%s",
2603 directory,
2604 dname);
2605 if (!fname) {
2606 return NT_STATUS_NO_MEMORY;
2609 status = check_name(conn, fname);
2610 if (!NT_STATUS_IS_OK(status)) {
2611 TALLOC_FREE(dir_hnd);
2612 return status;
2615 status = do_unlink(conn, req, fname, dirtype);
2616 if (!NT_STATUS_IS_OK(status)) {
2617 TALLOC_FREE(fname);
2618 continue;
2621 count++;
2622 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2623 fname));
2625 TALLOC_FREE(fname);
2627 TALLOC_FREE(dir_hnd);
2630 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2631 status = map_nt_error_from_unix(errno);
2634 return status;
2637 /****************************************************************************
2638 Reply to a unlink
2639 ****************************************************************************/
2641 void reply_unlink(struct smb_request *req)
2643 connection_struct *conn = req->conn;
2644 char *name = NULL;
2645 uint32 dirtype;
2646 NTSTATUS status;
2647 bool path_contains_wcard = False;
2648 TALLOC_CTX *ctx = talloc_tos();
2650 START_PROFILE(SMBunlink);
2652 if (req->wct < 1) {
2653 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2654 END_PROFILE(SMBunlink);
2655 return;
2658 dirtype = SVAL(req->vwv+0, 0);
2660 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2661 STR_TERMINATE, &status,
2662 &path_contains_wcard);
2663 if (!NT_STATUS_IS_OK(status)) {
2664 reply_nterror(req, status);
2665 END_PROFILE(SMBunlink);
2666 return;
2669 status = resolve_dfspath_wcard(ctx, conn,
2670 req->flags2 & FLAGS2_DFS_PATHNAMES,
2671 name,
2672 &name,
2673 &path_contains_wcard);
2674 if (!NT_STATUS_IS_OK(status)) {
2675 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2676 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2677 ERRSRV, ERRbadpath);
2678 END_PROFILE(SMBunlink);
2679 return;
2681 reply_nterror(req, status);
2682 END_PROFILE(SMBunlink);
2683 return;
2686 DEBUG(3,("reply_unlink : %s\n",name));
2688 status = unlink_internals(conn, req, dirtype, name,
2689 path_contains_wcard);
2690 if (!NT_STATUS_IS_OK(status)) {
2691 if (open_was_deferred(req->mid)) {
2692 /* We have re-scheduled this call. */
2693 END_PROFILE(SMBunlink);
2694 return;
2696 reply_nterror(req, status);
2697 END_PROFILE(SMBunlink);
2698 return;
2701 reply_outbuf(req, 0, 0);
2702 END_PROFILE(SMBunlink);
2704 return;
2707 /****************************************************************************
2708 Fail for readbraw.
2709 ****************************************************************************/
2711 static void fail_readraw(void)
2713 const char *errstr = talloc_asprintf(talloc_tos(),
2714 "FAIL ! reply_readbraw: socket write fail (%s)",
2715 strerror(errno));
2716 if (!errstr) {
2717 errstr = "";
2719 exit_server_cleanly(errstr);
2722 /****************************************************************************
2723 Fake (read/write) sendfile. Returns -1 on read or write fail.
2724 ****************************************************************************/
2726 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2727 size_t nread)
2729 size_t bufsize;
2730 size_t tosend = nread;
2731 char *buf;
2733 if (nread == 0) {
2734 return 0;
2737 bufsize = MIN(nread, 65536);
2739 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2740 return -1;
2743 while (tosend > 0) {
2744 ssize_t ret;
2745 size_t cur_read;
2747 if (tosend > bufsize) {
2748 cur_read = bufsize;
2749 } else {
2750 cur_read = tosend;
2752 ret = read_file(fsp,buf,startpos,cur_read);
2753 if (ret == -1) {
2754 SAFE_FREE(buf);
2755 return -1;
2758 /* If we had a short read, fill with zeros. */
2759 if (ret < cur_read) {
2760 memset(buf, '\0', cur_read - ret);
2763 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2764 SAFE_FREE(buf);
2765 return -1;
2767 tosend -= cur_read;
2768 startpos += cur_read;
2771 SAFE_FREE(buf);
2772 return (ssize_t)nread;
2775 #if defined(WITH_SENDFILE)
2776 /****************************************************************************
2777 Deal with the case of sendfile reading less bytes from the file than
2778 requested. Fill with zeros (all we can do).
2779 ****************************************************************************/
2781 static void sendfile_short_send(files_struct *fsp,
2782 ssize_t nread,
2783 size_t headersize,
2784 size_t smb_maxcnt)
2786 if (nread < headersize) {
2787 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2788 "header for file %s (%s). Terminating\n",
2789 fsp->fsp_name, strerror(errno) ));
2790 exit_server_cleanly("sendfile_short_send failed");
2793 nread -= headersize;
2795 if (nread < smb_maxcnt) {
2796 char *buf = SMB_CALLOC_ARRAY(char, 1024);
2797 if (!buf) {
2798 exit_server_cleanly("sendfile_short_send: "
2799 "malloc failed");
2802 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2803 "with zeros !\n", fsp->fsp_name));
2805 while (nread < smb_maxcnt) {
2807 * We asked for the real file size and told sendfile
2808 * to not go beyond the end of the file. But it can
2809 * happen that in between our fstat call and the
2810 * sendfile call the file was truncated. This is very
2811 * bad because we have already announced the larger
2812 * number of bytes to the client.
2814 * The best we can do now is to send 0-bytes, just as
2815 * a read from a hole in a sparse file would do.
2817 * This should happen rarely enough that I don't care
2818 * about efficiency here :-)
2820 size_t to_write;
2822 to_write = MIN(sizeof(buf), smb_maxcnt - nread);
2823 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2824 exit_server_cleanly("sendfile_short_send: "
2825 "write_data failed");
2827 nread += to_write;
2829 SAFE_FREE(buf);
2832 #endif /* defined WITH_SENDFILE */
2834 /****************************************************************************
2835 Return a readbraw error (4 bytes of zero).
2836 ****************************************************************************/
2838 static void reply_readbraw_error(void)
2840 char header[4];
2841 SIVAL(header,0,0);
2842 if (write_data(smbd_server_fd(),header,4) != 4) {
2843 fail_readraw();
2847 /****************************************************************************
2848 Use sendfile in readbraw.
2849 ****************************************************************************/
2851 static void send_file_readbraw(connection_struct *conn,
2852 struct smb_request *req,
2853 files_struct *fsp,
2854 SMB_OFF_T startpos,
2855 size_t nread,
2856 ssize_t mincount)
2858 char *outbuf = NULL;
2859 ssize_t ret=0;
2861 #if defined(WITH_SENDFILE)
2863 * We can only use sendfile on a non-chained packet
2864 * but we can use on a non-oplocked file. tridge proved this
2865 * on a train in Germany :-). JRA.
2866 * reply_readbraw has already checked the length.
2869 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2870 (fsp->wcp == NULL) &&
2871 lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
2872 ssize_t sendfile_read = -1;
2873 char header[4];
2874 DATA_BLOB header_blob;
2876 _smb_setlen(header,nread);
2877 header_blob = data_blob_const(header, 4);
2879 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2880 &header_blob, startpos, nread)) == -1) {
2881 /* Returning ENOSYS means no data at all was sent.
2882 * Do this as a normal read. */
2883 if (errno == ENOSYS) {
2884 goto normal_readbraw;
2888 * Special hack for broken Linux with no working sendfile. If we
2889 * return EINTR we sent the header but not the rest of the data.
2890 * Fake this up by doing read/write calls.
2892 if (errno == EINTR) {
2893 /* Ensure we don't do this again. */
2894 set_use_sendfile(SNUM(conn), False);
2895 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2897 if (fake_sendfile(fsp, startpos, nread) == -1) {
2898 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2899 fsp->fsp_name, strerror(errno) ));
2900 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2902 return;
2905 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2906 fsp->fsp_name, strerror(errno) ));
2907 exit_server_cleanly("send_file_readbraw sendfile failed");
2908 } else if (sendfile_read == 0) {
2910 * Some sendfile implementations return 0 to indicate
2911 * that there was a short read, but nothing was
2912 * actually written to the socket. In this case,
2913 * fallback to the normal read path so the header gets
2914 * the correct byte count.
2916 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2917 "bytes falling back to the normal read: "
2918 "%s\n", fsp->fsp_name));
2919 goto normal_readbraw;
2922 /* Deal with possible short send. */
2923 if (sendfile_read != 4+nread) {
2924 sendfile_short_send(fsp, sendfile_read, 4, nread);
2926 return;
2929 normal_readbraw:
2930 #endif
2932 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2933 if (!outbuf) {
2934 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2935 (unsigned)(nread+4)));
2936 reply_readbraw_error();
2937 return;
2940 if (nread > 0) {
2941 ret = read_file(fsp,outbuf+4,startpos,nread);
2942 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2943 if (ret < mincount)
2944 ret = 0;
2945 #else
2946 if (ret < nread)
2947 ret = 0;
2948 #endif
2951 _smb_setlen(outbuf,ret);
2952 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2953 fail_readraw();
2955 TALLOC_FREE(outbuf);
2958 /****************************************************************************
2959 Reply to a readbraw (core+ protocol).
2960 ****************************************************************************/
2962 void reply_readbraw(struct smb_request *req)
2964 connection_struct *conn = req->conn;
2965 ssize_t maxcount,mincount;
2966 size_t nread = 0;
2967 SMB_OFF_T startpos;
2968 files_struct *fsp;
2969 struct lock_struct lock;
2970 SMB_STRUCT_STAT st;
2971 SMB_OFF_T size = 0;
2973 START_PROFILE(SMBreadbraw);
2975 if (srv_is_signing_active(smbd_server_conn) ||
2976 is_encrypted_packet(req->inbuf)) {
2977 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2978 "raw reads/writes are disallowed.");
2981 if (req->wct < 8) {
2982 reply_readbraw_error();
2983 END_PROFILE(SMBreadbraw);
2984 return;
2988 * Special check if an oplock break has been issued
2989 * and the readraw request croses on the wire, we must
2990 * return a zero length response here.
2993 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2996 * We have to do a check_fsp by hand here, as
2997 * we must always return 4 zero bytes on error,
2998 * not a NTSTATUS.
3001 if (!fsp || !conn || conn != fsp->conn ||
3002 req->vuid != fsp->vuid ||
3003 fsp->is_directory || fsp->fh->fd == -1) {
3005 * fsp could be NULL here so use the value from the packet. JRA.
3007 DEBUG(3,("reply_readbraw: fnum %d not valid "
3008 "- cache prime?\n",
3009 (int)SVAL(req->vwv+0, 0)));
3010 reply_readbraw_error();
3011 END_PROFILE(SMBreadbraw);
3012 return;
3015 /* Do a "by hand" version of CHECK_READ. */
3016 if (!(fsp->can_read ||
3017 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3018 (fsp->access_mask & FILE_EXECUTE)))) {
3019 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3020 (int)SVAL(req->vwv+0, 0)));
3021 reply_readbraw_error();
3022 END_PROFILE(SMBreadbraw);
3023 return;
3026 flush_write_cache(fsp, READRAW_FLUSH);
3028 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3029 if(req->wct == 10) {
3031 * This is a large offset (64 bit) read.
3033 #ifdef LARGE_SMB_OFF_T
3035 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3037 #else /* !LARGE_SMB_OFF_T */
3040 * Ensure we haven't been sent a >32 bit offset.
3043 if(IVAL(req->vwv+8, 0) != 0) {
3044 DEBUG(0,("reply_readbraw: large offset "
3045 "(%x << 32) used and we don't support "
3046 "64 bit offsets.\n",
3047 (unsigned int)IVAL(req->vwv+8, 0) ));
3048 reply_readbraw_error();
3049 END_PROFILE(SMBreadbraw);
3050 return;
3053 #endif /* LARGE_SMB_OFF_T */
3055 if(startpos < 0) {
3056 DEBUG(0,("reply_readbraw: negative 64 bit "
3057 "readraw offset (%.0f) !\n",
3058 (double)startpos ));
3059 reply_readbraw_error();
3060 END_PROFILE(SMBreadbraw);
3061 return;
3065 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3066 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3068 /* ensure we don't overrun the packet size */
3069 maxcount = MIN(65535,maxcount);
3071 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3072 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3073 &lock);
3075 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3076 reply_readbraw_error();
3077 END_PROFILE(SMBreadbraw);
3078 return;
3081 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3082 size = st.st_size;
3085 if (startpos >= size) {
3086 nread = 0;
3087 } else {
3088 nread = MIN(maxcount,(size - startpos));
3091 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3092 if (nread < mincount)
3093 nread = 0;
3094 #endif
3096 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3097 "min=%lu nread=%lu\n",
3098 fsp->fnum, (double)startpos,
3099 (unsigned long)maxcount,
3100 (unsigned long)mincount,
3101 (unsigned long)nread ) );
3103 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3105 DEBUG(5,("reply_readbraw finished\n"));
3107 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3109 END_PROFILE(SMBreadbraw);
3110 return;
3113 #undef DBGC_CLASS
3114 #define DBGC_CLASS DBGC_LOCKING
3116 /****************************************************************************
3117 Reply to a lockread (core+ protocol).
3118 ****************************************************************************/
3120 void reply_lockread(struct smb_request *req)
3122 connection_struct *conn = req->conn;
3123 ssize_t nread = -1;
3124 char *data;
3125 SMB_OFF_T startpos;
3126 size_t numtoread;
3127 NTSTATUS status;
3128 files_struct *fsp;
3129 struct byte_range_lock *br_lck = NULL;
3130 char *p = NULL;
3132 START_PROFILE(SMBlockread);
3134 if (req->wct < 5) {
3135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3136 END_PROFILE(SMBlockread);
3137 return;
3140 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3142 if (!check_fsp(conn, req, fsp)) {
3143 END_PROFILE(SMBlockread);
3144 return;
3147 if (!CHECK_READ(fsp,req)) {
3148 reply_doserror(req, ERRDOS, ERRbadaccess);
3149 END_PROFILE(SMBlockread);
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 - (smb_size + 3*2 + 3), numtoread);
3158 reply_outbuf(req, 5, numtoread + 3);
3160 data = smb_buf(req->outbuf) + 3;
3163 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3164 * protocol request that predates the read/write lock concept.
3165 * Thus instead of asking for a read lock here we need to ask
3166 * for a write lock. JRA.
3167 * Note that the requested lock size is unaffected by max_recv.
3170 br_lck = do_lock(smbd_messaging_context(),
3171 fsp,
3172 req->smbpid,
3173 (uint64_t)numtoread,
3174 (uint64_t)startpos,
3175 WRITE_LOCK,
3176 WINDOWS_LOCK,
3177 False, /* Non-blocking lock. */
3178 &status,
3179 NULL,
3180 NULL);
3181 TALLOC_FREE(br_lck);
3183 if (NT_STATUS_V(status)) {
3184 reply_nterror(req, status);
3185 END_PROFILE(SMBlockread);
3186 return;
3190 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3193 if (numtoread > max_recv) {
3194 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3195 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3196 (unsigned int)numtoread, (unsigned int)max_recv ));
3197 numtoread = MIN(numtoread,max_recv);
3199 nread = read_file(fsp,data,startpos,numtoread);
3201 if (nread < 0) {
3202 reply_unixerror(req, ERRDOS, ERRnoaccess);
3203 END_PROFILE(SMBlockread);
3204 return;
3207 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3209 SSVAL(req->outbuf,smb_vwv0,nread);
3210 SSVAL(req->outbuf,smb_vwv5,nread+3);
3211 p = smb_buf(req->outbuf);
3212 SCVAL(p,0,0); /* pad byte. */
3213 SSVAL(p,1,nread);
3215 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3216 fsp->fnum, (int)numtoread, (int)nread));
3218 END_PROFILE(SMBlockread);
3219 return;
3222 #undef DBGC_CLASS
3223 #define DBGC_CLASS DBGC_ALL
3225 /****************************************************************************
3226 Reply to a read.
3227 ****************************************************************************/
3229 void reply_read(struct smb_request *req)
3231 connection_struct *conn = req->conn;
3232 size_t numtoread;
3233 ssize_t nread = 0;
3234 char *data;
3235 SMB_OFF_T startpos;
3236 int outsize = 0;
3237 files_struct *fsp;
3238 struct lock_struct lock;
3240 START_PROFILE(SMBread);
3242 if (req->wct < 3) {
3243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3244 END_PROFILE(SMBread);
3245 return;
3248 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3250 if (!check_fsp(conn, req, fsp)) {
3251 END_PROFILE(SMBread);
3252 return;
3255 if (!CHECK_READ(fsp,req)) {
3256 reply_doserror(req, ERRDOS, ERRbadaccess);
3257 END_PROFILE(SMBread);
3258 return;
3261 numtoread = SVAL(req->vwv+1, 0);
3262 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3264 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3267 * The requested read size cannot be greater than max_recv. JRA.
3269 if (numtoread > max_recv) {
3270 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3271 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3272 (unsigned int)numtoread, (unsigned int)max_recv ));
3273 numtoread = MIN(numtoread,max_recv);
3276 reply_outbuf(req, 5, numtoread+3);
3278 data = smb_buf(req->outbuf) + 3;
3280 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3281 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3282 &lock);
3284 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3285 reply_doserror(req, ERRDOS,ERRlock);
3286 END_PROFILE(SMBread);
3287 return;
3290 if (numtoread > 0)
3291 nread = read_file(fsp,data,startpos,numtoread);
3293 if (nread < 0) {
3294 reply_unixerror(req, ERRDOS,ERRnoaccess);
3295 goto strict_unlock;
3298 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3300 SSVAL(req->outbuf,smb_vwv0,nread);
3301 SSVAL(req->outbuf,smb_vwv5,nread+3);
3302 SCVAL(smb_buf(req->outbuf),0,1);
3303 SSVAL(smb_buf(req->outbuf),1,nread);
3305 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3306 fsp->fnum, (int)numtoread, (int)nread ) );
3308 strict_unlock:
3309 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3311 END_PROFILE(SMBread);
3312 return;
3315 /****************************************************************************
3316 Setup readX header.
3317 ****************************************************************************/
3319 static int setup_readX_header(struct smb_request *req, char *outbuf,
3320 size_t smb_maxcnt)
3322 int outsize;
3323 char *data;
3325 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3326 data = smb_buf(outbuf);
3328 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3330 SCVAL(outbuf,smb_vwv0,0xFF);
3331 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3332 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3333 SSVAL(outbuf,smb_vwv6,
3334 req_wct_ofs(req)
3335 + 1 /* the wct field */
3336 + 12 * sizeof(uint16_t) /* vwv */
3337 + 2); /* the buflen field */
3338 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3339 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3340 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3341 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3342 return outsize;
3345 /****************************************************************************
3346 Reply to a read and X - possibly using sendfile.
3347 ****************************************************************************/
3349 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3350 files_struct *fsp, SMB_OFF_T startpos,
3351 size_t smb_maxcnt)
3353 SMB_STRUCT_STAT sbuf;
3354 ssize_t nread = -1;
3356 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3357 reply_unixerror(req, ERRDOS, ERRnoaccess);
3358 return;
3361 if (!S_ISREG(sbuf.st_mode) || (startpos > sbuf.st_size)
3362 || (smb_maxcnt > (sbuf.st_size - startpos))) {
3364 * We already know that we would do a short read, so don't
3365 * try the sendfile() path.
3367 goto nosendfile_read;
3370 #if defined(WITH_SENDFILE)
3372 * We can only use sendfile on a non-chained packet
3373 * but we can use on a non-oplocked file. tridge proved this
3374 * on a train in Germany :-). JRA.
3377 if (!req_is_in_chain(req) &&
3378 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3379 (fsp->wcp == NULL) &&
3380 lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
3381 uint8 headerbuf[smb_size + 12 * 2];
3382 DATA_BLOB header;
3385 * Set up the packet header before send. We
3386 * assume here the sendfile will work (get the
3387 * correct amount of data).
3390 header = data_blob_const(headerbuf, sizeof(headerbuf));
3392 construct_reply_common_req(req, (char *)headerbuf);
3393 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3395 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3396 /* Returning ENOSYS means no data at all was sent.
3397 Do this as a normal read. */
3398 if (errno == ENOSYS) {
3399 goto normal_read;
3403 * Special hack for broken Linux with no working sendfile. If we
3404 * return EINTR we sent the header but not the rest of the data.
3405 * Fake this up by doing read/write calls.
3408 if (errno == EINTR) {
3409 /* Ensure we don't do this again. */
3410 set_use_sendfile(SNUM(conn), False);
3411 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3412 nread = fake_sendfile(fsp, startpos,
3413 smb_maxcnt);
3414 if (nread == -1) {
3415 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3416 fsp->fsp_name, strerror(errno) ));
3417 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3419 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3420 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3421 /* No outbuf here means successful sendfile. */
3422 TALLOC_FREE(req->outbuf);
3423 return;
3426 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3427 fsp->fsp_name, strerror(errno) ));
3428 exit_server_cleanly("send_file_readX sendfile failed");
3429 } else if (nread == 0) {
3431 * Some sendfile implementations return 0 to indicate
3432 * that there was a short read, but nothing was
3433 * actually written to the socket. In this case,
3434 * fallback to the normal read path so the header gets
3435 * the correct byte count.
3437 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3438 "falling back to the normal read: %s\n",
3439 fsp->fsp_name));
3440 goto normal_read;
3443 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3444 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3446 /* Deal with possible short send. */
3447 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3448 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3451 /* No outbuf here means successful sendfile. */
3452 TALLOC_FREE(req->outbuf);
3453 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3454 SMB_PERFCOUNT_END(&req->pcd);
3455 return;
3457 #endif
3459 normal_read:
3461 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3462 uint8 headerbuf[smb_size + 2*12];
3464 construct_reply_common_req(req, (char *)headerbuf);
3465 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3467 /* Send out the header. */
3468 if (write_data(smbd_server_fd(), (char *)headerbuf,
3469 sizeof(headerbuf)) != sizeof(headerbuf)) {
3470 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3471 fsp->fsp_name, strerror(errno) ));
3472 exit_server_cleanly("send_file_readX sendfile failed");
3474 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3475 if (nread == -1) {
3476 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3477 fsp->fsp_name, strerror(errno) ));
3478 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3480 TALLOC_FREE(req->outbuf);
3481 return;
3484 nosendfile_read:
3486 reply_outbuf(req, 12, smb_maxcnt);
3488 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3489 if (nread < 0) {
3490 reply_unixerror(req, ERRDOS, ERRnoaccess);
3491 return;
3494 setup_readX_header(req, (char *)req->outbuf, nread);
3496 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3497 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3499 chain_reply(req);
3502 /****************************************************************************
3503 Reply to a read and X.
3504 ****************************************************************************/
3506 void reply_read_and_X(struct smb_request *req)
3508 connection_struct *conn = req->conn;
3509 files_struct *fsp;
3510 SMB_OFF_T startpos;
3511 size_t smb_maxcnt;
3512 struct lock_struct lock;
3513 bool big_readX = False;
3514 #if 0
3515 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3516 #endif
3518 START_PROFILE(SMBreadX);
3520 if ((req->wct != 10) && (req->wct != 12)) {
3521 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3522 return;
3525 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3526 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3527 smb_maxcnt = SVAL(req->vwv+5, 0);
3529 /* If it's an IPC, pass off the pipe handler. */
3530 if (IS_IPC(conn)) {
3531 reply_pipe_read_and_X(req);
3532 END_PROFILE(SMBreadX);
3533 return;
3536 if (!check_fsp(conn, req, fsp)) {
3537 END_PROFILE(SMBreadX);
3538 return;
3541 if (!CHECK_READ(fsp,req)) {
3542 reply_doserror(req, ERRDOS,ERRbadaccess);
3543 END_PROFILE(SMBreadX);
3544 return;
3547 if (global_client_caps & CAP_LARGE_READX) {
3548 size_t upper_size = SVAL(req->vwv+7, 0);
3549 smb_maxcnt |= (upper_size<<16);
3550 if (upper_size > 1) {
3551 /* Can't do this on a chained packet. */
3552 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3553 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3554 END_PROFILE(SMBreadX);
3555 return;
3557 /* We currently don't do this on signed or sealed data. */
3558 if (srv_is_signing_active(smbd_server_conn) ||
3559 is_encrypted_packet(req->inbuf)) {
3560 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3561 END_PROFILE(SMBreadX);
3562 return;
3564 /* Is there room in the reply for this data ? */
3565 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3566 reply_nterror(req,
3567 NT_STATUS_INVALID_PARAMETER);
3568 END_PROFILE(SMBreadX);
3569 return;
3571 big_readX = True;
3575 if (req->wct == 12) {
3576 #ifdef LARGE_SMB_OFF_T
3578 * This is a large offset (64 bit) read.
3580 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3582 #else /* !LARGE_SMB_OFF_T */
3585 * Ensure we haven't been sent a >32 bit offset.
3588 if(IVAL(req->vwv+10, 0) != 0) {
3589 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3590 "used and we don't support 64 bit offsets.\n",
3591 (unsigned int)IVAL(req->vwv+10, 0) ));
3592 END_PROFILE(SMBreadX);
3593 reply_doserror(req, ERRDOS, ERRbadaccess);
3594 return;
3597 #endif /* LARGE_SMB_OFF_T */
3601 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3602 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3603 &lock);
3605 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3606 END_PROFILE(SMBreadX);
3607 reply_doserror(req, ERRDOS, ERRlock);
3608 return;
3611 if (!big_readX &&
3612 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3613 goto strict_unlock;
3616 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3618 strict_unlock:
3619 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3621 END_PROFILE(SMBreadX);
3622 return;
3625 /****************************************************************************
3626 Error replies to writebraw must have smb_wct == 1. Fix this up.
3627 ****************************************************************************/
3629 void error_to_writebrawerr(struct smb_request *req)
3631 uint8 *old_outbuf = req->outbuf;
3633 reply_outbuf(req, 1, 0);
3635 memcpy(req->outbuf, old_outbuf, smb_size);
3636 TALLOC_FREE(old_outbuf);
3639 /****************************************************************************
3640 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3641 ****************************************************************************/
3643 void reply_writebraw(struct smb_request *req)
3645 connection_struct *conn = req->conn;
3646 char *buf = NULL;
3647 ssize_t nwritten=0;
3648 ssize_t total_written=0;
3649 size_t numtowrite=0;
3650 size_t tcount;
3651 SMB_OFF_T startpos;
3652 char *data=NULL;
3653 bool write_through;
3654 files_struct *fsp;
3655 struct lock_struct lock;
3656 NTSTATUS status;
3658 START_PROFILE(SMBwritebraw);
3661 * If we ever reply with an error, it must have the SMB command
3662 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3663 * we're finished.
3665 SCVAL(req->inbuf,smb_com,SMBwritec);
3667 if (srv_is_signing_active(smbd_server_conn)) {
3668 END_PROFILE(SMBwritebraw);
3669 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3670 "raw reads/writes are disallowed.");
3673 if (req->wct < 12) {
3674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3675 error_to_writebrawerr(req);
3676 END_PROFILE(SMBwritebraw);
3677 return;
3680 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3681 if (!check_fsp(conn, req, fsp)) {
3682 error_to_writebrawerr(req);
3683 END_PROFILE(SMBwritebraw);
3684 return;
3687 if (!CHECK_WRITE(fsp)) {
3688 reply_doserror(req, ERRDOS, ERRbadaccess);
3689 error_to_writebrawerr(req);
3690 END_PROFILE(SMBwritebraw);
3691 return;
3694 tcount = IVAL(req->vwv+1, 0);
3695 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3696 write_through = BITSETW(req->vwv+7,0);
3698 /* We have to deal with slightly different formats depending
3699 on whether we are using the core+ or lanman1.0 protocol */
3701 if(Protocol <= PROTOCOL_COREPLUS) {
3702 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3703 data = smb_buf(req->inbuf);
3704 } else {
3705 numtowrite = SVAL(req->vwv+10, 0);
3706 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3709 /* Ensure we don't write bytes past the end of this packet. */
3710 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3712 error_to_writebrawerr(req);
3713 END_PROFILE(SMBwritebraw);
3714 return;
3717 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3718 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3719 &lock);
3721 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3722 reply_doserror(req, ERRDOS, ERRlock);
3723 error_to_writebrawerr(req);
3724 END_PROFILE(SMBwritebraw);
3725 return;
3728 if (numtowrite>0) {
3729 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3732 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3733 "wrote=%d sync=%d\n",
3734 fsp->fnum, (double)startpos, (int)numtowrite,
3735 (int)nwritten, (int)write_through));
3737 if (nwritten < (ssize_t)numtowrite) {
3738 reply_unixerror(req, ERRHRD, ERRdiskfull);
3739 error_to_writebrawerr(req);
3740 goto strict_unlock;
3743 total_written = nwritten;
3745 /* Allocate a buffer of 64k + length. */
3746 buf = TALLOC_ARRAY(NULL, char, 65540);
3747 if (!buf) {
3748 reply_doserror(req, ERRDOS, ERRnomem);
3749 error_to_writebrawerr(req);
3750 goto strict_unlock;
3753 /* Return a SMBwritebraw message to the redirector to tell
3754 * it to send more bytes */
3756 memcpy(buf, req->inbuf, smb_size);
3757 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3758 SCVAL(buf,smb_com,SMBwritebraw);
3759 SSVALS(buf,smb_vwv0,0xFFFF);
3760 show_msg(buf);
3761 if (!srv_send_smb(smbd_server_fd(),
3762 buf,
3763 false, 0, /* no signing */
3764 IS_CONN_ENCRYPTED(conn),
3765 &req->pcd)) {
3766 exit_server_cleanly("reply_writebraw: srv_send_smb "
3767 "failed.");
3770 /* Now read the raw data into the buffer and write it */
3771 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3772 &numtowrite);
3773 if (!NT_STATUS_IS_OK(status)) {
3774 exit_server_cleanly("secondary writebraw failed");
3777 /* Set up outbuf to return the correct size */
3778 reply_outbuf(req, 1, 0);
3780 if (numtowrite != 0) {
3782 if (numtowrite > 0xFFFF) {
3783 DEBUG(0,("reply_writebraw: Oversize secondary write "
3784 "raw requested (%u). Terminating\n",
3785 (unsigned int)numtowrite ));
3786 exit_server_cleanly("secondary writebraw failed");
3789 if (tcount > nwritten+numtowrite) {
3790 DEBUG(3,("reply_writebraw: Client overestimated the "
3791 "write %d %d %d\n",
3792 (int)tcount,(int)nwritten,(int)numtowrite));
3795 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3797 if (!NT_STATUS_IS_OK(status)) {
3798 DEBUG(0,("reply_writebraw: Oversize secondary write "
3799 "raw read failed (%s). Terminating\n",
3800 nt_errstr(status)));
3801 exit_server_cleanly("secondary writebraw failed");
3804 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3805 if (nwritten == -1) {
3806 TALLOC_FREE(buf);
3807 reply_unixerror(req, ERRHRD, ERRdiskfull);
3808 error_to_writebrawerr(req);
3809 goto strict_unlock;
3812 if (nwritten < (ssize_t)numtowrite) {
3813 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3814 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3817 if (nwritten > 0) {
3818 total_written += nwritten;
3822 TALLOC_FREE(buf);
3823 SSVAL(req->outbuf,smb_vwv0,total_written);
3825 status = sync_file(conn, fsp, write_through);
3826 if (!NT_STATUS_IS_OK(status)) {
3827 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3828 fsp->fsp_name, nt_errstr(status) ));
3829 reply_nterror(req, status);
3830 error_to_writebrawerr(req);
3831 goto strict_unlock;
3834 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3835 "wrote=%d\n",
3836 fsp->fnum, (double)startpos, (int)numtowrite,
3837 (int)total_written));
3839 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3841 /* We won't return a status if write through is not selected - this
3842 * follows what WfWg does */
3843 END_PROFILE(SMBwritebraw);
3845 if (!write_through && total_written==tcount) {
3847 #if RABBIT_PELLET_FIX
3849 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3850 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3851 * JRA.
3853 if (!send_keepalive(smbd_server_fd())) {
3854 exit_server_cleanly("reply_writebraw: send of "
3855 "keepalive failed");
3857 #endif
3858 TALLOC_FREE(req->outbuf);
3860 return;
3862 strict_unlock:
3863 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3865 END_PROFILE(SMBwritebraw);
3866 return;
3869 #undef DBGC_CLASS
3870 #define DBGC_CLASS DBGC_LOCKING
3872 /****************************************************************************
3873 Reply to a writeunlock (core+).
3874 ****************************************************************************/
3876 void reply_writeunlock(struct smb_request *req)
3878 connection_struct *conn = req->conn;
3879 ssize_t nwritten = -1;
3880 size_t numtowrite;
3881 SMB_OFF_T startpos;
3882 const char *data;
3883 NTSTATUS status = NT_STATUS_OK;
3884 files_struct *fsp;
3885 struct lock_struct lock;
3887 START_PROFILE(SMBwriteunlock);
3889 if (req->wct < 5) {
3890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3891 END_PROFILE(SMBwriteunlock);
3892 return;
3895 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3897 if (!check_fsp(conn, req, fsp)) {
3898 END_PROFILE(SMBwriteunlock);
3899 return;
3902 if (!CHECK_WRITE(fsp)) {
3903 reply_doserror(req, ERRDOS,ERRbadaccess);
3904 END_PROFILE(SMBwriteunlock);
3905 return;
3908 numtowrite = SVAL(req->vwv+1, 0);
3909 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3910 data = (const char *)req->buf + 3;
3912 if (numtowrite) {
3913 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3914 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3915 &lock);
3917 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3918 reply_doserror(req, ERRDOS, ERRlock);
3919 END_PROFILE(SMBwriteunlock);
3920 return;
3924 /* The special X/Open SMB protocol handling of
3925 zero length writes is *NOT* done for
3926 this call */
3927 if(numtowrite == 0) {
3928 nwritten = 0;
3929 } else {
3930 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3933 status = sync_file(conn, fsp, False /* write through */);
3934 if (!NT_STATUS_IS_OK(status)) {
3935 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3936 fsp->fsp_name, nt_errstr(status) ));
3937 reply_nterror(req, status);
3938 goto strict_unlock;
3941 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3942 reply_unixerror(req, ERRHRD, ERRdiskfull);
3943 goto strict_unlock;
3946 if (numtowrite) {
3947 status = do_unlock(smbd_messaging_context(),
3948 fsp,
3949 req->smbpid,
3950 (uint64_t)numtowrite,
3951 (uint64_t)startpos,
3952 WINDOWS_LOCK);
3954 if (NT_STATUS_V(status)) {
3955 reply_nterror(req, status);
3956 goto strict_unlock;
3960 reply_outbuf(req, 1, 0);
3962 SSVAL(req->outbuf,smb_vwv0,nwritten);
3964 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3965 fsp->fnum, (int)numtowrite, (int)nwritten));
3967 strict_unlock:
3968 if (numtowrite) {
3969 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3972 END_PROFILE(SMBwriteunlock);
3973 return;
3976 #undef DBGC_CLASS
3977 #define DBGC_CLASS DBGC_ALL
3979 /****************************************************************************
3980 Reply to a write.
3981 ****************************************************************************/
3983 void reply_write(struct smb_request *req)
3985 connection_struct *conn = req->conn;
3986 size_t numtowrite;
3987 ssize_t nwritten = -1;
3988 SMB_OFF_T startpos;
3989 const char *data;
3990 files_struct *fsp;
3991 struct lock_struct lock;
3992 NTSTATUS status;
3994 START_PROFILE(SMBwrite);
3996 if (req->wct < 5) {
3997 END_PROFILE(SMBwrite);
3998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3999 return;
4002 /* If it's an IPC, pass off the pipe handler. */
4003 if (IS_IPC(conn)) {
4004 reply_pipe_write(req);
4005 END_PROFILE(SMBwrite);
4006 return;
4009 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4011 if (!check_fsp(conn, req, fsp)) {
4012 END_PROFILE(SMBwrite);
4013 return;
4016 if (!CHECK_WRITE(fsp)) {
4017 reply_doserror(req, ERRDOS, ERRbadaccess);
4018 END_PROFILE(SMBwrite);
4019 return;
4022 numtowrite = SVAL(req->vwv+1, 0);
4023 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4024 data = (const char *)req->buf + 3;
4026 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4027 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4028 &lock);
4030 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4031 reply_doserror(req, ERRDOS, ERRlock);
4032 END_PROFILE(SMBwrite);
4033 return;
4037 * X/Open SMB protocol says that if smb_vwv1 is
4038 * zero then the file size should be extended or
4039 * truncated to the size given in smb_vwv[2-3].
4042 if(numtowrite == 0) {
4044 * This is actually an allocate call, and set EOF. JRA.
4046 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4047 if (nwritten < 0) {
4048 reply_nterror(req, NT_STATUS_DISK_FULL);
4049 goto strict_unlock;
4051 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4052 if (nwritten < 0) {
4053 reply_nterror(req, NT_STATUS_DISK_FULL);
4054 goto strict_unlock;
4056 trigger_write_time_update_immediate(fsp);
4057 } else {
4058 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4061 status = sync_file(conn, fsp, False);
4062 if (!NT_STATUS_IS_OK(status)) {
4063 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4064 fsp->fsp_name, nt_errstr(status) ));
4065 reply_nterror(req, status);
4066 goto strict_unlock;
4069 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4070 reply_unixerror(req, ERRHRD, ERRdiskfull);
4071 goto strict_unlock;
4074 reply_outbuf(req, 1, 0);
4076 SSVAL(req->outbuf,smb_vwv0,nwritten);
4078 if (nwritten < (ssize_t)numtowrite) {
4079 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4080 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4083 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4085 strict_unlock:
4086 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4088 END_PROFILE(SMBwrite);
4089 return;
4092 /****************************************************************************
4093 Ensure a buffer is a valid writeX for recvfile purposes.
4094 ****************************************************************************/
4096 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4097 (2*14) + /* word count (including bcc) */ \
4098 1 /* pad byte */)
4100 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4102 size_t numtowrite;
4103 connection_struct *conn = NULL;
4104 unsigned int doff = 0;
4105 size_t len = smb_len_large(inbuf);
4107 if (is_encrypted_packet(inbuf)) {
4108 /* Can't do this on encrypted
4109 * connections. */
4110 return false;
4113 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4114 return false;
4117 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4118 CVAL(inbuf,smb_wct) != 14) {
4119 DEBUG(10,("is_valid_writeX_buffer: chained or "
4120 "invalid word length.\n"));
4121 return false;
4124 conn = conn_find(SVAL(inbuf, smb_tid));
4125 if (conn == NULL) {
4126 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4127 return false;
4129 if (IS_IPC(conn)) {
4130 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4131 return false;
4133 if (IS_PRINT(conn)) {
4134 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4135 return false;
4137 doff = SVAL(inbuf,smb_vwv11);
4139 numtowrite = SVAL(inbuf,smb_vwv10);
4141 if (len > doff && len - doff > 0xFFFF) {
4142 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4145 if (numtowrite == 0) {
4146 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4147 return false;
4150 /* Ensure the sizes match up. */
4151 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4152 /* no pad byte...old smbclient :-( */
4153 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4154 (unsigned int)doff,
4155 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4156 return false;
4159 if (len - doff != numtowrite) {
4160 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4161 "len = %u, doff = %u, numtowrite = %u\n",
4162 (unsigned int)len,
4163 (unsigned int)doff,
4164 (unsigned int)numtowrite ));
4165 return false;
4168 DEBUG(10,("is_valid_writeX_buffer: true "
4169 "len = %u, doff = %u, numtowrite = %u\n",
4170 (unsigned int)len,
4171 (unsigned int)doff,
4172 (unsigned int)numtowrite ));
4174 return true;
4177 /****************************************************************************
4178 Reply to a write and X.
4179 ****************************************************************************/
4181 void reply_write_and_X(struct smb_request *req)
4183 connection_struct *conn = req->conn;
4184 files_struct *fsp;
4185 struct lock_struct lock;
4186 SMB_OFF_T startpos;
4187 size_t numtowrite;
4188 bool write_through;
4189 ssize_t nwritten;
4190 unsigned int smb_doff;
4191 unsigned int smblen;
4192 char *data;
4193 NTSTATUS status;
4195 START_PROFILE(SMBwriteX);
4197 if ((req->wct != 12) && (req->wct != 14)) {
4198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4199 END_PROFILE(SMBwriteX);
4200 return;
4203 numtowrite = SVAL(req->vwv+10, 0);
4204 smb_doff = SVAL(req->vwv+11, 0);
4205 smblen = smb_len(req->inbuf);
4207 if (req->unread_bytes > 0xFFFF ||
4208 (smblen > smb_doff &&
4209 smblen - smb_doff > 0xFFFF)) {
4210 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4213 if (req->unread_bytes) {
4214 /* Can't do a recvfile write on IPC$ */
4215 if (IS_IPC(conn)) {
4216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4217 END_PROFILE(SMBwriteX);
4218 return;
4220 if (numtowrite != req->unread_bytes) {
4221 reply_doserror(req, ERRDOS, ERRbadmem);
4222 END_PROFILE(SMBwriteX);
4223 return;
4225 } else {
4226 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4227 smb_doff + numtowrite > smblen) {
4228 reply_doserror(req, ERRDOS, ERRbadmem);
4229 END_PROFILE(SMBwriteX);
4230 return;
4234 /* If it's an IPC, pass off the pipe handler. */
4235 if (IS_IPC(conn)) {
4236 if (req->unread_bytes) {
4237 reply_doserror(req, ERRDOS, ERRbadmem);
4238 END_PROFILE(SMBwriteX);
4239 return;
4241 reply_pipe_write_and_X(req);
4242 END_PROFILE(SMBwriteX);
4243 return;
4246 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4247 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4248 write_through = BITSETW(req->vwv+7,0);
4250 if (!check_fsp(conn, req, fsp)) {
4251 END_PROFILE(SMBwriteX);
4252 return;
4255 if (!CHECK_WRITE(fsp)) {
4256 reply_doserror(req, ERRDOS, ERRbadaccess);
4257 END_PROFILE(SMBwriteX);
4258 return;
4261 data = smb_base(req->inbuf) + smb_doff;
4263 if(req->wct == 14) {
4264 #ifdef LARGE_SMB_OFF_T
4266 * This is a large offset (64 bit) write.
4268 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4270 #else /* !LARGE_SMB_OFF_T */
4273 * Ensure we haven't been sent a >32 bit offset.
4276 if(IVAL(req->vwv+12, 0) != 0) {
4277 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4278 "used and we don't support 64 bit offsets.\n",
4279 (unsigned int)IVAL(req->vwv+12, 0) ));
4280 reply_doserror(req, ERRDOS, ERRbadaccess);
4281 END_PROFILE(SMBwriteX);
4282 return;
4285 #endif /* LARGE_SMB_OFF_T */
4288 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4289 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4290 &lock);
4292 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4293 reply_doserror(req, ERRDOS, ERRlock);
4294 END_PROFILE(SMBwriteX);
4295 return;
4298 /* X/Open SMB protocol says that, unlike SMBwrite
4299 if the length is zero then NO truncation is
4300 done, just a write of zero. To truncate a file,
4301 use SMBwrite. */
4303 if(numtowrite == 0) {
4304 nwritten = 0;
4305 } else {
4307 if ((req->unread_bytes == 0) &&
4308 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4309 numtowrite)) {
4310 goto strict_unlock;
4313 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4316 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4317 reply_unixerror(req, ERRHRD, ERRdiskfull);
4318 goto strict_unlock;
4321 reply_outbuf(req, 6, 0);
4322 SSVAL(req->outbuf,smb_vwv2,nwritten);
4323 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4325 if (nwritten < (ssize_t)numtowrite) {
4326 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4327 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4330 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4331 fsp->fnum, (int)numtowrite, (int)nwritten));
4333 status = sync_file(conn, fsp, write_through);
4334 if (!NT_STATUS_IS_OK(status)) {
4335 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4336 fsp->fsp_name, nt_errstr(status) ));
4337 reply_nterror(req, status);
4338 goto strict_unlock;
4341 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4343 END_PROFILE(SMBwriteX);
4344 chain_reply(req);
4345 return;
4347 strict_unlock:
4348 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4350 END_PROFILE(SMBwriteX);
4351 return;
4354 /****************************************************************************
4355 Reply to a lseek.
4356 ****************************************************************************/
4358 void reply_lseek(struct smb_request *req)
4360 connection_struct *conn = req->conn;
4361 SMB_OFF_T startpos;
4362 SMB_OFF_T res= -1;
4363 int mode,umode;
4364 files_struct *fsp;
4366 START_PROFILE(SMBlseek);
4368 if (req->wct < 4) {
4369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4370 END_PROFILE(SMBlseek);
4371 return;
4374 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4376 if (!check_fsp(conn, req, fsp)) {
4377 return;
4380 flush_write_cache(fsp, SEEK_FLUSH);
4382 mode = SVAL(req->vwv+1, 0) & 3;
4383 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4384 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4386 switch (mode) {
4387 case 0:
4388 umode = SEEK_SET;
4389 res = startpos;
4390 break;
4391 case 1:
4392 umode = SEEK_CUR;
4393 res = fsp->fh->pos + startpos;
4394 break;
4395 case 2:
4396 umode = SEEK_END;
4397 break;
4398 default:
4399 umode = SEEK_SET;
4400 res = startpos;
4401 break;
4404 if (umode == SEEK_END) {
4405 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4406 if(errno == EINVAL) {
4407 SMB_OFF_T current_pos = startpos;
4408 SMB_STRUCT_STAT sbuf;
4410 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4411 reply_unixerror(req, ERRDOS,
4412 ERRnoaccess);
4413 END_PROFILE(SMBlseek);
4414 return;
4417 current_pos += sbuf.st_size;
4418 if(current_pos < 0)
4419 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4423 if(res == -1) {
4424 reply_unixerror(req, ERRDOS, ERRnoaccess);
4425 END_PROFILE(SMBlseek);
4426 return;
4430 fsp->fh->pos = res;
4432 reply_outbuf(req, 2, 0);
4433 SIVAL(req->outbuf,smb_vwv0,res);
4435 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4436 fsp->fnum, (double)startpos, (double)res, mode));
4438 END_PROFILE(SMBlseek);
4439 return;
4442 /****************************************************************************
4443 Reply to a flush.
4444 ****************************************************************************/
4446 void reply_flush(struct smb_request *req)
4448 connection_struct *conn = req->conn;
4449 uint16 fnum;
4450 files_struct *fsp;
4452 START_PROFILE(SMBflush);
4454 if (req->wct < 1) {
4455 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4456 return;
4459 fnum = SVAL(req->vwv+0, 0);
4460 fsp = file_fsp(req, fnum);
4462 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4463 return;
4466 if (!fsp) {
4467 file_sync_all(conn);
4468 } else {
4469 NTSTATUS status = sync_file(conn, fsp, True);
4470 if (!NT_STATUS_IS_OK(status)) {
4471 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4472 fsp->fsp_name, nt_errstr(status) ));
4473 reply_nterror(req, status);
4474 END_PROFILE(SMBflush);
4475 return;
4479 reply_outbuf(req, 0, 0);
4481 DEBUG(3,("flush\n"));
4482 END_PROFILE(SMBflush);
4483 return;
4486 /****************************************************************************
4487 Reply to a exit.
4488 conn POINTER CAN BE NULL HERE !
4489 ****************************************************************************/
4491 void reply_exit(struct smb_request *req)
4493 START_PROFILE(SMBexit);
4495 file_close_pid(req->smbpid, req->vuid);
4497 reply_outbuf(req, 0, 0);
4499 DEBUG(3,("exit\n"));
4501 END_PROFILE(SMBexit);
4502 return;
4505 /****************************************************************************
4506 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4507 ****************************************************************************/
4509 void reply_close(struct smb_request *req)
4511 connection_struct *conn = req->conn;
4512 NTSTATUS status = NT_STATUS_OK;
4513 files_struct *fsp = NULL;
4514 START_PROFILE(SMBclose);
4516 if (req->wct < 3) {
4517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4518 END_PROFILE(SMBclose);
4519 return;
4522 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4525 * We can only use check_fsp if we know it's not a directory.
4528 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4529 reply_doserror(req, ERRDOS, ERRbadfid);
4530 END_PROFILE(SMBclose);
4531 return;
4534 if(fsp->is_directory) {
4536 * Special case - close NT SMB directory handle.
4538 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4539 status = close_file(req, fsp, NORMAL_CLOSE);
4540 } else {
4541 time_t t;
4543 * Close ordinary file.
4546 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4547 fsp->fh->fd, fsp->fnum,
4548 conn->num_files_open));
4551 * Take care of any time sent in the close.
4554 t = srv_make_unix_date3(req->vwv+1);
4555 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4558 * close_file() returns the unix errno if an error
4559 * was detected on close - normally this is due to
4560 * a disk full error. If not then it was probably an I/O error.
4563 status = close_file(req, fsp, NORMAL_CLOSE);
4566 if (!NT_STATUS_IS_OK(status)) {
4567 reply_nterror(req, status);
4568 END_PROFILE(SMBclose);
4569 return;
4572 reply_outbuf(req, 0, 0);
4573 END_PROFILE(SMBclose);
4574 return;
4577 /****************************************************************************
4578 Reply to a writeclose (Core+ protocol).
4579 ****************************************************************************/
4581 void reply_writeclose(struct smb_request *req)
4583 connection_struct *conn = req->conn;
4584 size_t numtowrite;
4585 ssize_t nwritten = -1;
4586 NTSTATUS close_status = NT_STATUS_OK;
4587 SMB_OFF_T startpos;
4588 const char *data;
4589 struct timespec mtime;
4590 files_struct *fsp;
4591 struct lock_struct lock;
4593 START_PROFILE(SMBwriteclose);
4595 if (req->wct < 6) {
4596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4597 END_PROFILE(SMBwriteclose);
4598 return;
4601 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4603 if (!check_fsp(conn, req, fsp)) {
4604 END_PROFILE(SMBwriteclose);
4605 return;
4607 if (!CHECK_WRITE(fsp)) {
4608 reply_doserror(req, ERRDOS,ERRbadaccess);
4609 END_PROFILE(SMBwriteclose);
4610 return;
4613 numtowrite = SVAL(req->vwv+1, 0);
4614 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4615 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4616 data = (const char *)req->buf + 1;
4618 if (numtowrite) {
4619 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4620 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4621 &lock);
4623 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4624 reply_doserror(req, ERRDOS,ERRlock);
4625 END_PROFILE(SMBwriteclose);
4626 return;
4630 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4632 set_close_write_time(fsp, mtime);
4635 * More insanity. W2K only closes the file if writelen > 0.
4636 * JRA.
4639 if (numtowrite) {
4640 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4641 fsp->fsp_name ));
4642 close_status = close_file(req, fsp, NORMAL_CLOSE);
4645 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4646 fsp->fnum, (int)numtowrite, (int)nwritten,
4647 conn->num_files_open));
4649 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4650 reply_doserror(req, ERRHRD, ERRdiskfull);
4651 goto strict_unlock;
4654 if(!NT_STATUS_IS_OK(close_status)) {
4655 reply_nterror(req, close_status);
4656 goto strict_unlock;
4659 reply_outbuf(req, 1, 0);
4661 SSVAL(req->outbuf,smb_vwv0,nwritten);
4663 strict_unlock:
4664 if (numtowrite) {
4665 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4668 END_PROFILE(SMBwriteclose);
4669 return;
4672 #undef DBGC_CLASS
4673 #define DBGC_CLASS DBGC_LOCKING
4675 /****************************************************************************
4676 Reply to a lock.
4677 ****************************************************************************/
4679 void reply_lock(struct smb_request *req)
4681 connection_struct *conn = req->conn;
4682 uint64_t count,offset;
4683 NTSTATUS status;
4684 files_struct *fsp;
4685 struct byte_range_lock *br_lck = NULL;
4687 START_PROFILE(SMBlock);
4689 if (req->wct < 5) {
4690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4691 END_PROFILE(SMBlock);
4692 return;
4695 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4697 if (!check_fsp(conn, req, fsp)) {
4698 END_PROFILE(SMBlock);
4699 return;
4702 count = (uint64_t)IVAL(req->vwv+1, 0);
4703 offset = (uint64_t)IVAL(req->vwv+3, 0);
4705 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4706 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4708 br_lck = do_lock(smbd_messaging_context(),
4709 fsp,
4710 req->smbpid,
4711 count,
4712 offset,
4713 WRITE_LOCK,
4714 WINDOWS_LOCK,
4715 False, /* Non-blocking lock. */
4716 &status,
4717 NULL,
4718 NULL);
4720 TALLOC_FREE(br_lck);
4722 if (NT_STATUS_V(status)) {
4723 reply_nterror(req, status);
4724 END_PROFILE(SMBlock);
4725 return;
4728 reply_outbuf(req, 0, 0);
4730 END_PROFILE(SMBlock);
4731 return;
4734 /****************************************************************************
4735 Reply to a unlock.
4736 ****************************************************************************/
4738 void reply_unlock(struct smb_request *req)
4740 connection_struct *conn = req->conn;
4741 uint64_t count,offset;
4742 NTSTATUS status;
4743 files_struct *fsp;
4745 START_PROFILE(SMBunlock);
4747 if (req->wct < 5) {
4748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4749 END_PROFILE(SMBunlock);
4750 return;
4753 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4755 if (!check_fsp(conn, req, fsp)) {
4756 END_PROFILE(SMBunlock);
4757 return;
4760 count = (uint64_t)IVAL(req->vwv+1, 0);
4761 offset = (uint64_t)IVAL(req->vwv+3, 0);
4763 status = do_unlock(smbd_messaging_context(),
4764 fsp,
4765 req->smbpid,
4766 count,
4767 offset,
4768 WINDOWS_LOCK);
4770 if (NT_STATUS_V(status)) {
4771 reply_nterror(req, status);
4772 END_PROFILE(SMBunlock);
4773 return;
4776 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4777 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4779 reply_outbuf(req, 0, 0);
4781 END_PROFILE(SMBunlock);
4782 return;
4785 #undef DBGC_CLASS
4786 #define DBGC_CLASS DBGC_ALL
4788 /****************************************************************************
4789 Reply to a tdis.
4790 conn POINTER CAN BE NULL HERE !
4791 ****************************************************************************/
4793 void reply_tdis(struct smb_request *req)
4795 connection_struct *conn = req->conn;
4796 START_PROFILE(SMBtdis);
4798 if (!conn) {
4799 DEBUG(4,("Invalid connection in tdis\n"));
4800 reply_doserror(req, ERRSRV, ERRinvnid);
4801 END_PROFILE(SMBtdis);
4802 return;
4805 conn->used = False;
4807 close_cnum(conn,req->vuid);
4808 req->conn = NULL;
4810 reply_outbuf(req, 0, 0);
4811 END_PROFILE(SMBtdis);
4812 return;
4815 /****************************************************************************
4816 Reply to a echo.
4817 conn POINTER CAN BE NULL HERE !
4818 ****************************************************************************/
4820 void reply_echo(struct smb_request *req)
4822 connection_struct *conn = req->conn;
4823 struct smb_perfcount_data local_pcd;
4824 struct smb_perfcount_data *cur_pcd;
4825 int smb_reverb;
4826 int seq_num;
4828 START_PROFILE(SMBecho);
4830 smb_init_perfcount_data(&local_pcd);
4832 if (req->wct < 1) {
4833 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4834 END_PROFILE(SMBecho);
4835 return;
4838 smb_reverb = SVAL(req->vwv+0, 0);
4840 reply_outbuf(req, 1, req->buflen);
4842 /* copy any incoming data back out */
4843 if (req->buflen > 0) {
4844 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4847 if (smb_reverb > 100) {
4848 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4849 smb_reverb = 100;
4852 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4854 /* this makes sure we catch the request pcd */
4855 if (seq_num == smb_reverb) {
4856 cur_pcd = &req->pcd;
4857 } else {
4858 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4859 cur_pcd = &local_pcd;
4862 SSVAL(req->outbuf,smb_vwv0,seq_num);
4864 show_msg((char *)req->outbuf);
4865 if (!srv_send_smb(smbd_server_fd(),
4866 (char *)req->outbuf,
4867 true, req->seqnum+1,
4868 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4869 cur_pcd))
4870 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4873 DEBUG(3,("echo %d times\n", smb_reverb));
4875 TALLOC_FREE(req->outbuf);
4877 END_PROFILE(SMBecho);
4878 return;
4881 /****************************************************************************
4882 Reply to a printopen.
4883 ****************************************************************************/
4885 void reply_printopen(struct smb_request *req)
4887 connection_struct *conn = req->conn;
4888 files_struct *fsp;
4889 SMB_STRUCT_STAT sbuf;
4890 NTSTATUS status;
4892 START_PROFILE(SMBsplopen);
4894 if (req->wct < 2) {
4895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4896 END_PROFILE(SMBsplopen);
4897 return;
4900 if (!CAN_PRINT(conn)) {
4901 reply_doserror(req, ERRDOS, ERRnoaccess);
4902 END_PROFILE(SMBsplopen);
4903 return;
4906 status = file_new(req, conn, &fsp);
4907 if(!NT_STATUS_IS_OK(status)) {
4908 reply_nterror(req, status);
4909 END_PROFILE(SMBsplopen);
4910 return;
4913 /* Open for exclusive use, write only. */
4914 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4916 if (!NT_STATUS_IS_OK(status)) {
4917 reply_nterror(req, status);
4918 END_PROFILE(SMBsplopen);
4919 return;
4922 reply_outbuf(req, 1, 0);
4923 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4925 DEBUG(3,("openprint fd=%d fnum=%d\n",
4926 fsp->fh->fd, fsp->fnum));
4928 END_PROFILE(SMBsplopen);
4929 return;
4932 /****************************************************************************
4933 Reply to a printclose.
4934 ****************************************************************************/
4936 void reply_printclose(struct smb_request *req)
4938 connection_struct *conn = req->conn;
4939 files_struct *fsp;
4940 NTSTATUS status;
4942 START_PROFILE(SMBsplclose);
4944 if (req->wct < 1) {
4945 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4946 END_PROFILE(SMBsplclose);
4947 return;
4950 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4952 if (!check_fsp(conn, req, fsp)) {
4953 END_PROFILE(SMBsplclose);
4954 return;
4957 if (!CAN_PRINT(conn)) {
4958 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4959 END_PROFILE(SMBsplclose);
4960 return;
4963 DEBUG(3,("printclose fd=%d fnum=%d\n",
4964 fsp->fh->fd,fsp->fnum));
4966 status = close_file(req, fsp, NORMAL_CLOSE);
4968 if(!NT_STATUS_IS_OK(status)) {
4969 reply_nterror(req, status);
4970 END_PROFILE(SMBsplclose);
4971 return;
4974 reply_outbuf(req, 0, 0);
4976 END_PROFILE(SMBsplclose);
4977 return;
4980 /****************************************************************************
4981 Reply to a printqueue.
4982 ****************************************************************************/
4984 void reply_printqueue(struct smb_request *req)
4986 connection_struct *conn = req->conn;
4987 int max_count;
4988 int start_index;
4990 START_PROFILE(SMBsplretq);
4992 if (req->wct < 2) {
4993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4994 END_PROFILE(SMBsplretq);
4995 return;
4998 max_count = SVAL(req->vwv+0, 0);
4999 start_index = SVAL(req->vwv+1, 0);
5001 /* we used to allow the client to get the cnum wrong, but that
5002 is really quite gross and only worked when there was only
5003 one printer - I think we should now only accept it if they
5004 get it right (tridge) */
5005 if (!CAN_PRINT(conn)) {
5006 reply_doserror(req, ERRDOS, ERRnoaccess);
5007 END_PROFILE(SMBsplretq);
5008 return;
5011 reply_outbuf(req, 2, 3);
5012 SSVAL(req->outbuf,smb_vwv0,0);
5013 SSVAL(req->outbuf,smb_vwv1,0);
5014 SCVAL(smb_buf(req->outbuf),0,1);
5015 SSVAL(smb_buf(req->outbuf),1,0);
5017 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5018 start_index, max_count));
5021 print_queue_struct *queue = NULL;
5022 print_status_struct status;
5023 int count = print_queue_status(SNUM(conn), &queue, &status);
5024 int num_to_get = ABS(max_count);
5025 int first = (max_count>0?start_index:start_index+max_count+1);
5026 int i;
5028 if (first >= count)
5029 num_to_get = 0;
5030 else
5031 num_to_get = MIN(num_to_get,count-first);
5034 for (i=first;i<first+num_to_get;i++) {
5035 char blob[28];
5036 char *p = blob;
5038 srv_put_dos_date2(p,0,queue[i].time);
5039 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5040 SSVAL(p,5, queue[i].job);
5041 SIVAL(p,7,queue[i].size);
5042 SCVAL(p,11,0);
5043 srvstr_push(blob, req->flags2, p+12,
5044 queue[i].fs_user, 16, STR_ASCII);
5046 if (message_push_blob(
5047 &req->outbuf,
5048 data_blob_const(
5049 blob, sizeof(blob))) == -1) {
5050 reply_nterror(req, NT_STATUS_NO_MEMORY);
5051 END_PROFILE(SMBsplretq);
5052 return;
5056 if (count > 0) {
5057 SSVAL(req->outbuf,smb_vwv0,count);
5058 SSVAL(req->outbuf,smb_vwv1,
5059 (max_count>0?first+count:first-1));
5060 SCVAL(smb_buf(req->outbuf),0,1);
5061 SSVAL(smb_buf(req->outbuf),1,28*count);
5064 SAFE_FREE(queue);
5066 DEBUG(3,("%d entries returned in queue\n",count));
5069 END_PROFILE(SMBsplretq);
5070 return;
5073 /****************************************************************************
5074 Reply to a printwrite.
5075 ****************************************************************************/
5077 void reply_printwrite(struct smb_request *req)
5079 connection_struct *conn = req->conn;
5080 int numtowrite;
5081 const char *data;
5082 files_struct *fsp;
5084 START_PROFILE(SMBsplwr);
5086 if (req->wct < 1) {
5087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5088 END_PROFILE(SMBsplwr);
5089 return;
5092 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5094 if (!check_fsp(conn, req, fsp)) {
5095 END_PROFILE(SMBsplwr);
5096 return;
5099 if (!CAN_PRINT(conn)) {
5100 reply_doserror(req, ERRDOS, ERRnoaccess);
5101 END_PROFILE(SMBsplwr);
5102 return;
5105 if (!CHECK_WRITE(fsp)) {
5106 reply_doserror(req, ERRDOS, ERRbadaccess);
5107 END_PROFILE(SMBsplwr);
5108 return;
5111 numtowrite = SVAL(req->buf, 1);
5113 if (req->buflen < numtowrite + 3) {
5114 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5115 END_PROFILE(SMBsplwr);
5116 return;
5119 data = (const char *)req->buf + 3;
5121 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5122 reply_unixerror(req, ERRHRD, ERRdiskfull);
5123 END_PROFILE(SMBsplwr);
5124 return;
5127 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5129 END_PROFILE(SMBsplwr);
5130 return;
5133 /****************************************************************************
5134 Reply to a mkdir.
5135 ****************************************************************************/
5137 void reply_mkdir(struct smb_request *req)
5139 connection_struct *conn = req->conn;
5140 char *directory = NULL;
5141 NTSTATUS status;
5142 SMB_STRUCT_STAT sbuf;
5143 TALLOC_CTX *ctx = talloc_tos();
5145 START_PROFILE(SMBmkdir);
5147 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5148 STR_TERMINATE, &status);
5149 if (!NT_STATUS_IS_OK(status)) {
5150 reply_nterror(req, status);
5151 END_PROFILE(SMBmkdir);
5152 return;
5155 status = resolve_dfspath(ctx, conn,
5156 req->flags2 & FLAGS2_DFS_PATHNAMES,
5157 directory,
5158 &directory);
5159 if (!NT_STATUS_IS_OK(status)) {
5160 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5161 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5162 ERRSRV, ERRbadpath);
5163 END_PROFILE(SMBmkdir);
5164 return;
5166 reply_nterror(req, status);
5167 END_PROFILE(SMBmkdir);
5168 return;
5171 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
5172 if (!NT_STATUS_IS_OK(status)) {
5173 reply_nterror(req, status);
5174 END_PROFILE(SMBmkdir);
5175 return;
5178 status = check_name(conn, directory);
5179 if (!NT_STATUS_IS_OK(status)) {
5180 reply_nterror(req, status);
5181 END_PROFILE(SMBmkdir);
5182 return;
5185 status = create_directory(conn, req, directory);
5187 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5189 if (!NT_STATUS_IS_OK(status)) {
5191 if (!use_nt_status()
5192 && NT_STATUS_EQUAL(status,
5193 NT_STATUS_OBJECT_NAME_COLLISION)) {
5195 * Yes, in the DOS error code case we get a
5196 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5197 * samba4 torture test.
5199 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5202 reply_nterror(req, status);
5203 END_PROFILE(SMBmkdir);
5204 return;
5207 reply_outbuf(req, 0, 0);
5209 DEBUG( 3, ( "mkdir %s\n", directory ) );
5211 END_PROFILE(SMBmkdir);
5212 return;
5215 /****************************************************************************
5216 Static function used by reply_rmdir to delete an entire directory
5217 tree recursively. Return True on ok, False on fail.
5218 ****************************************************************************/
5220 static bool recursive_rmdir(TALLOC_CTX *ctx,
5221 connection_struct *conn,
5222 char *directory)
5224 const char *dname = NULL;
5225 bool ret = True;
5226 long offset = 0;
5227 SMB_STRUCT_STAT st;
5228 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5229 NULL, 0);
5231 if(dir_hnd == NULL)
5232 return False;
5234 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5235 char *fullname = NULL;
5237 if (ISDOT(dname) || ISDOTDOT(dname)) {
5238 continue;
5241 if (!is_visible_file(conn, directory, dname, &st, False)) {
5242 continue;
5245 /* Construct the full name. */
5246 fullname = talloc_asprintf(ctx,
5247 "%s/%s",
5248 directory,
5249 dname);
5250 if (!fullname) {
5251 errno = ENOMEM;
5252 ret = False;
5253 break;
5256 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5257 ret = False;
5258 break;
5261 if(st.st_mode & S_IFDIR) {
5262 if(!recursive_rmdir(ctx, conn, fullname)) {
5263 ret = False;
5264 break;
5266 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5267 ret = False;
5268 break;
5270 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5271 ret = False;
5272 break;
5274 TALLOC_FREE(fullname);
5276 TALLOC_FREE(dir_hnd);
5277 return ret;
5280 /****************************************************************************
5281 The internals of the rmdir code - called elsewhere.
5282 ****************************************************************************/
5284 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5285 connection_struct *conn,
5286 const char *directory)
5288 int ret;
5289 SMB_STRUCT_STAT st;
5291 /* Might be a symlink. */
5292 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5293 return map_nt_error_from_unix(errno);
5296 if (S_ISLNK(st.st_mode)) {
5297 /* Is what it points to a directory ? */
5298 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5299 return map_nt_error_from_unix(errno);
5301 if (!(S_ISDIR(st.st_mode))) {
5302 return NT_STATUS_NOT_A_DIRECTORY;
5304 ret = SMB_VFS_UNLINK(conn,directory);
5305 } else {
5306 ret = SMB_VFS_RMDIR(conn,directory);
5308 if (ret == 0) {
5309 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5310 FILE_NOTIFY_CHANGE_DIR_NAME,
5311 directory);
5312 return NT_STATUS_OK;
5315 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5317 * Check to see if the only thing in this directory are
5318 * vetoed files/directories. If so then delete them and
5319 * retry. If we fail to delete any of them (and we *don't*
5320 * do a recursive delete) then fail the rmdir.
5322 const char *dname;
5323 long dirpos = 0;
5324 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5325 directory, NULL, 0);
5327 if(dir_hnd == NULL) {
5328 errno = ENOTEMPTY;
5329 goto err;
5332 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5333 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5334 continue;
5335 if (!is_visible_file(conn, directory, dname, &st, False))
5336 continue;
5337 if(!IS_VETO_PATH(conn, dname)) {
5338 TALLOC_FREE(dir_hnd);
5339 errno = ENOTEMPTY;
5340 goto err;
5344 /* We only have veto files/directories.
5345 * Are we allowed to delete them ? */
5347 if(!lp_recursive_veto_delete(SNUM(conn))) {
5348 TALLOC_FREE(dir_hnd);
5349 errno = ENOTEMPTY;
5350 goto err;
5353 /* Do a recursive delete. */
5354 RewindDir(dir_hnd,&dirpos);
5355 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5356 char *fullname = NULL;
5358 if (ISDOT(dname) || ISDOTDOT(dname)) {
5359 continue;
5361 if (!is_visible_file(conn, directory, dname, &st, False)) {
5362 continue;
5365 fullname = talloc_asprintf(ctx,
5366 "%s/%s",
5367 directory,
5368 dname);
5370 if(!fullname) {
5371 errno = ENOMEM;
5372 break;
5375 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5376 break;
5378 if(st.st_mode & S_IFDIR) {
5379 if(!recursive_rmdir(ctx, conn, fullname)) {
5380 break;
5382 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5383 break;
5385 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5386 break;
5388 TALLOC_FREE(fullname);
5390 TALLOC_FREE(dir_hnd);
5391 /* Retry the rmdir */
5392 ret = SMB_VFS_RMDIR(conn,directory);
5395 err:
5397 if (ret != 0) {
5398 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5399 "%s\n", directory,strerror(errno)));
5400 return map_nt_error_from_unix(errno);
5403 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5404 FILE_NOTIFY_CHANGE_DIR_NAME,
5405 directory);
5407 return NT_STATUS_OK;
5410 /****************************************************************************
5411 Reply to a rmdir.
5412 ****************************************************************************/
5414 void reply_rmdir(struct smb_request *req)
5416 connection_struct *conn = req->conn;
5417 char *directory = NULL;
5418 SMB_STRUCT_STAT sbuf;
5419 NTSTATUS status;
5420 TALLOC_CTX *ctx = talloc_tos();
5422 START_PROFILE(SMBrmdir);
5424 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5425 STR_TERMINATE, &status);
5426 if (!NT_STATUS_IS_OK(status)) {
5427 reply_nterror(req, status);
5428 END_PROFILE(SMBrmdir);
5429 return;
5432 status = resolve_dfspath(ctx, conn,
5433 req->flags2 & FLAGS2_DFS_PATHNAMES,
5434 directory,
5435 &directory);
5436 if (!NT_STATUS_IS_OK(status)) {
5437 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5438 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5439 ERRSRV, ERRbadpath);
5440 END_PROFILE(SMBrmdir);
5441 return;
5443 reply_nterror(req, status);
5444 END_PROFILE(SMBrmdir);
5445 return;
5448 status = unix_convert(ctx, conn, directory, False, &directory,
5449 NULL, &sbuf);
5450 if (!NT_STATUS_IS_OK(status)) {
5451 reply_nterror(req, status);
5452 END_PROFILE(SMBrmdir);
5453 return;
5456 status = check_name(conn, directory);
5457 if (!NT_STATUS_IS_OK(status)) {
5458 reply_nterror(req, status);
5459 END_PROFILE(SMBrmdir);
5460 return;
5463 dptr_closepath(directory, req->smbpid);
5464 status = rmdir_internals(ctx, conn, directory);
5465 if (!NT_STATUS_IS_OK(status)) {
5466 reply_nterror(req, status);
5467 END_PROFILE(SMBrmdir);
5468 return;
5471 reply_outbuf(req, 0, 0);
5473 DEBUG( 3, ( "rmdir %s\n", directory ) );
5475 END_PROFILE(SMBrmdir);
5476 return;
5479 /*******************************************************************
5480 Resolve wildcards in a filename rename.
5481 ********************************************************************/
5483 static bool resolve_wildcards(TALLOC_CTX *ctx,
5484 const char *name1,
5485 const char *name2,
5486 char **pp_newname)
5488 char *name2_copy = NULL;
5489 char *root1 = NULL;
5490 char *root2 = NULL;
5491 char *ext1 = NULL;
5492 char *ext2 = NULL;
5493 char *p,*p2, *pname1, *pname2;
5495 name2_copy = talloc_strdup(ctx, name2);
5496 if (!name2_copy) {
5497 return False;
5500 pname1 = strrchr_m(name1,'/');
5501 pname2 = strrchr_m(name2_copy,'/');
5503 if (!pname1 || !pname2) {
5504 return False;
5507 /* Truncate the copy of name2 at the last '/' */
5508 *pname2 = '\0';
5510 /* Now go past the '/' */
5511 pname1++;
5512 pname2++;
5514 root1 = talloc_strdup(ctx, pname1);
5515 root2 = talloc_strdup(ctx, pname2);
5517 if (!root1 || !root2) {
5518 return False;
5521 p = strrchr_m(root1,'.');
5522 if (p) {
5523 *p = 0;
5524 ext1 = talloc_strdup(ctx, p+1);
5525 } else {
5526 ext1 = talloc_strdup(ctx, "");
5528 p = strrchr_m(root2,'.');
5529 if (p) {
5530 *p = 0;
5531 ext2 = talloc_strdup(ctx, p+1);
5532 } else {
5533 ext2 = talloc_strdup(ctx, "");
5536 if (!ext1 || !ext2) {
5537 return False;
5540 p = root1;
5541 p2 = root2;
5542 while (*p2) {
5543 if (*p2 == '?') {
5544 /* Hmmm. Should this be mb-aware ? */
5545 *p2 = *p;
5546 p2++;
5547 } else if (*p2 == '*') {
5548 *p2 = '\0';
5549 root2 = talloc_asprintf(ctx, "%s%s",
5550 root2,
5552 if (!root2) {
5553 return False;
5555 break;
5556 } else {
5557 p2++;
5559 if (*p) {
5560 p++;
5564 p = ext1;
5565 p2 = ext2;
5566 while (*p2) {
5567 if (*p2 == '?') {
5568 /* Hmmm. Should this be mb-aware ? */
5569 *p2 = *p;
5570 p2++;
5571 } else if (*p2 == '*') {
5572 *p2 = '\0';
5573 ext2 = talloc_asprintf(ctx, "%s%s",
5574 ext2,
5576 if (!ext2) {
5577 return False;
5579 break;
5580 } else {
5581 p2++;
5583 if (*p) {
5584 p++;
5588 if (*ext2) {
5589 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5590 name2_copy,
5591 root2,
5592 ext2);
5593 } else {
5594 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5595 name2_copy,
5596 root2);
5599 if (!*pp_newname) {
5600 return False;
5603 return True;
5606 /****************************************************************************
5607 Ensure open files have their names updated. Updated to notify other smbd's
5608 asynchronously.
5609 ****************************************************************************/
5611 static void rename_open_files(connection_struct *conn,
5612 struct share_mode_lock *lck,
5613 const char *newname)
5615 files_struct *fsp;
5616 bool did_rename = False;
5618 for(fsp = file_find_di_first(lck->id); fsp;
5619 fsp = file_find_di_next(fsp)) {
5620 /* fsp_name is a relative path under the fsp. To change this for other
5621 sharepaths we need to manipulate relative paths. */
5622 /* TODO - create the absolute path and manipulate the newname
5623 relative to the sharepath. */
5624 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5625 continue;
5627 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5628 fsp->fnum, file_id_string_tos(&fsp->file_id),
5629 fsp->fsp_name, newname ));
5630 string_set(&fsp->fsp_name, newname);
5631 did_rename = True;
5634 if (!did_rename) {
5635 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5636 file_id_string_tos(&lck->id), newname ));
5639 /* Send messages to all smbd's (not ourself) that the name has changed. */
5640 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5641 newname);
5644 /****************************************************************************
5645 We need to check if the source path is a parent directory of the destination
5646 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5647 refuse the rename with a sharing violation. Under UNIX the above call can
5648 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5649 probably need to check that the client is a Windows one before disallowing
5650 this as a UNIX client (one with UNIX extensions) can know the source is a
5651 symlink and make this decision intelligently. Found by an excellent bug
5652 report from <AndyLiebman@aol.com>.
5653 ****************************************************************************/
5655 static bool rename_path_prefix_equal(const char *src, const char *dest)
5657 const char *psrc = src;
5658 const char *pdst = dest;
5659 size_t slen;
5661 if (psrc[0] == '.' && psrc[1] == '/') {
5662 psrc += 2;
5664 if (pdst[0] == '.' && pdst[1] == '/') {
5665 pdst += 2;
5667 if ((slen = strlen(psrc)) > strlen(pdst)) {
5668 return False;
5670 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5674 * Do the notify calls from a rename
5677 static void notify_rename(connection_struct *conn, bool is_dir,
5678 const char *oldpath, const char *newpath)
5680 char *olddir, *newdir;
5681 const char *oldname, *newname;
5682 uint32 mask;
5684 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5685 : FILE_NOTIFY_CHANGE_FILE_NAME;
5687 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5688 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5689 TALLOC_FREE(olddir);
5690 return;
5693 if (strcmp(olddir, newdir) == 0) {
5694 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5695 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5697 else {
5698 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5699 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5701 TALLOC_FREE(olddir);
5702 TALLOC_FREE(newdir);
5704 /* this is a strange one. w2k3 gives an additional event for
5705 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5706 files, but not directories */
5707 if (!is_dir) {
5708 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5709 FILE_NOTIFY_CHANGE_ATTRIBUTES
5710 |FILE_NOTIFY_CHANGE_CREATION,
5711 newpath);
5715 /****************************************************************************
5716 Rename an open file - given an fsp.
5717 ****************************************************************************/
5719 NTSTATUS rename_internals_fsp(connection_struct *conn,
5720 files_struct *fsp,
5721 char *newname,
5722 const char *newname_last_component,
5723 uint32 attrs,
5724 bool replace_if_exists)
5726 TALLOC_CTX *ctx = talloc_tos();
5727 SMB_STRUCT_STAT sbuf, sbuf1;
5728 NTSTATUS status = NT_STATUS_OK;
5729 struct share_mode_lock *lck = NULL;
5730 bool dst_exists, old_is_stream, new_is_stream;
5732 ZERO_STRUCT(sbuf);
5734 status = check_name(conn, newname);
5735 if (!NT_STATUS_IS_OK(status)) {
5736 return status;
5739 /* Ensure newname contains a '/' */
5740 if(strrchr_m(newname,'/') == 0) {
5741 newname = talloc_asprintf(ctx,
5742 "./%s",
5743 newname);
5744 if (!newname) {
5745 return NT_STATUS_NO_MEMORY;
5750 * Check for special case with case preserving and not
5751 * case sensitive. If the old last component differs from the original
5752 * last component only by case, then we should allow
5753 * the rename (user is trying to change the case of the
5754 * filename).
5757 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5758 strequal(newname, fsp->fsp_name)) {
5759 char *p;
5760 char *newname_modified_last_component = NULL;
5763 * Get the last component of the modified name.
5764 * Note that we guarantee that newname contains a '/'
5765 * character above.
5767 p = strrchr_m(newname,'/');
5768 newname_modified_last_component = talloc_strdup(ctx,
5769 p+1);
5770 if (!newname_modified_last_component) {
5771 return NT_STATUS_NO_MEMORY;
5774 if(strcsequal(newname_modified_last_component,
5775 newname_last_component) == False) {
5777 * Replace the modified last component with
5778 * the original.
5780 *p = '\0'; /* Truncate at the '/' */
5781 newname = talloc_asprintf(ctx,
5782 "%s/%s",
5783 newname,
5784 newname_last_component);
5789 * If the src and dest names are identical - including case,
5790 * don't do the rename, just return success.
5793 if (strcsequal(fsp->fsp_name, newname)) {
5794 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5795 newname));
5796 return NT_STATUS_OK;
5799 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5800 new_is_stream = is_ntfs_stream_name(newname);
5802 /* Return the correct error code if both names aren't streams. */
5803 if (!old_is_stream && new_is_stream) {
5804 return NT_STATUS_OBJECT_NAME_INVALID;
5807 if (old_is_stream && !new_is_stream) {
5808 return NT_STATUS_INVALID_PARAMETER;
5812 * Have vfs_object_exist also fill sbuf1
5814 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5816 if(!replace_if_exists && dst_exists) {
5817 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5818 fsp->fsp_name,newname));
5819 return NT_STATUS_OBJECT_NAME_COLLISION;
5822 if (dst_exists) {
5823 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5824 files_struct *dst_fsp = file_find_di_first(fileid);
5825 /* The file can be open when renaming a stream */
5826 if (dst_fsp && !new_is_stream) {
5827 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5828 return NT_STATUS_ACCESS_DENIED;
5832 /* Ensure we have a valid stat struct for the source. */
5833 if (fsp->fh->fd != -1) {
5834 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5835 return map_nt_error_from_unix(errno);
5837 } else {
5838 int ret = -1;
5839 if (fsp->posix_open) {
5840 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5841 } else {
5842 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5844 if (ret == -1) {
5845 return map_nt_error_from_unix(errno);
5849 status = can_rename(conn, fsp, attrs, &sbuf);
5851 if (!NT_STATUS_IS_OK(status)) {
5852 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5853 nt_errstr(status), fsp->fsp_name,newname));
5854 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5855 status = NT_STATUS_ACCESS_DENIED;
5856 return status;
5859 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5860 return NT_STATUS_ACCESS_DENIED;
5863 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5864 NULL);
5867 * We have the file open ourselves, so not being able to get the
5868 * corresponding share mode lock is a fatal error.
5871 SMB_ASSERT(lck != NULL);
5873 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5874 uint32 create_options = fsp->fh->private_options;
5876 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5877 fsp->fsp_name,newname));
5879 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5881 rename_open_files(conn, lck, newname);
5884 * A rename acts as a new file create w.r.t. allowing an initial delete
5885 * on close, probably because in Windows there is a new handle to the
5886 * new file. If initial delete on close was requested but not
5887 * originally set, we need to set it here. This is probably not 100% correct,
5888 * but will work for the CIFSFS client which in non-posix mode
5889 * depends on these semantics. JRA.
5892 if (create_options & FILE_DELETE_ON_CLOSE) {
5893 status = can_set_delete_on_close(fsp, True, 0);
5895 if (NT_STATUS_IS_OK(status)) {
5896 /* Note that here we set the *inital* delete on close flag,
5897 * not the regular one. The magic gets handled in close. */
5898 fsp->initial_delete_on_close = True;
5901 TALLOC_FREE(lck);
5902 return NT_STATUS_OK;
5905 TALLOC_FREE(lck);
5907 if (errno == ENOTDIR || errno == EISDIR) {
5908 status = NT_STATUS_OBJECT_NAME_COLLISION;
5909 } else {
5910 status = map_nt_error_from_unix(errno);
5913 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5914 nt_errstr(status), fsp->fsp_name,newname));
5916 return status;
5919 /****************************************************************************
5920 The guts of the rename command, split out so it may be called by the NT SMB
5921 code.
5922 ****************************************************************************/
5924 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5925 connection_struct *conn,
5926 struct smb_request *req,
5927 const char *name_in,
5928 const char *newname_in,
5929 uint32 attrs,
5930 bool replace_if_exists,
5931 bool src_has_wild,
5932 bool dest_has_wild,
5933 uint32_t access_mask)
5935 char *directory = NULL;
5936 char *mask = NULL;
5937 char *last_component_src = NULL;
5938 char *last_component_dest = NULL;
5939 char *name = NULL;
5940 char *newname = NULL;
5941 char *p;
5942 int count=0;
5943 NTSTATUS status = NT_STATUS_OK;
5944 SMB_STRUCT_STAT sbuf1, sbuf2;
5945 struct smb_Dir *dir_hnd = NULL;
5946 const char *dname;
5947 long offset = 0;
5948 int create_options = 0;
5949 bool posix_pathnames = lp_posix_pathnames();
5951 ZERO_STRUCT(sbuf1);
5952 ZERO_STRUCT(sbuf2);
5954 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5955 &last_component_src, &sbuf1);
5956 if (!NT_STATUS_IS_OK(status)) {
5957 return status;
5960 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5961 &last_component_dest, &sbuf2);
5962 if (!NT_STATUS_IS_OK(status)) {
5963 return status;
5967 * Split the old name into directory and last component
5968 * strings. Note that unix_convert may have stripped off a
5969 * leading ./ from both name and newname if the rename is
5970 * at the root of the share. We need to make sure either both
5971 * name and newname contain a / character or neither of them do
5972 * as this is checked in resolve_wildcards().
5975 p = strrchr_m(name,'/');
5976 if (!p) {
5977 directory = talloc_strdup(ctx, ".");
5978 if (!directory) {
5979 return NT_STATUS_NO_MEMORY;
5981 mask = name;
5982 } else {
5983 *p = 0;
5984 directory = talloc_strdup(ctx, name);
5985 if (!directory) {
5986 return NT_STATUS_NO_MEMORY;
5988 mask = p+1;
5989 *p = '/'; /* Replace needed for exceptional test below. */
5993 * We should only check the mangled cache
5994 * here if unix_convert failed. This means
5995 * that the path in 'mask' doesn't exist
5996 * on the file system and so we need to look
5997 * for a possible mangle. This patch from
5998 * Tine Smukavec <valentin.smukavec@hermes.si>.
6001 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6002 char *new_mask = NULL;
6003 mangle_lookup_name_from_8_3(ctx,
6004 mask,
6005 &new_mask,
6006 conn->params );
6007 if (new_mask) {
6008 mask = new_mask;
6012 if (!src_has_wild) {
6013 files_struct *fsp;
6016 * No wildcards - just process the one file.
6018 bool is_short_name = mangle_is_8_3(name, True, conn->params);
6020 /* Add a terminating '/' to the directory name. */
6021 directory = talloc_asprintf_append(directory,
6022 "/%s",
6023 mask);
6024 if (!directory) {
6025 return NT_STATUS_NO_MEMORY;
6028 /* Ensure newname contains a '/' also */
6029 if(strrchr_m(newname,'/') == 0) {
6030 newname = talloc_asprintf(ctx,
6031 "./%s",
6032 newname);
6033 if (!newname) {
6034 return NT_STATUS_NO_MEMORY;
6038 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6039 "case_preserve = %d, short case preserve = %d, "
6040 "directory = %s, newname = %s, "
6041 "last_component_dest = %s, is_8_3 = %d\n",
6042 conn->case_sensitive, conn->case_preserve,
6043 conn->short_case_preserve, directory,
6044 newname, last_component_dest, is_short_name));
6046 /* The dest name still may have wildcards. */
6047 if (dest_has_wild) {
6048 char *mod_newname = NULL;
6049 if (!resolve_wildcards(ctx,
6050 directory,newname,&mod_newname)) {
6051 DEBUG(6, ("rename_internals: resolve_wildcards "
6052 "%s %s failed\n",
6053 directory,
6054 newname));
6055 return NT_STATUS_NO_MEMORY;
6057 newname = mod_newname;
6060 ZERO_STRUCT(sbuf1);
6061 if (posix_pathnames) {
6062 SMB_VFS_LSTAT(conn, directory, &sbuf1);
6063 } else {
6064 SMB_VFS_STAT(conn, directory, &sbuf1);
6067 if (S_ISDIR(sbuf1.st_mode)) {
6068 create_options |= FILE_DIRECTORY_FILE;
6071 status = SMB_VFS_CREATE_FILE(
6072 conn, /* conn */
6073 req, /* req */
6074 0, /* root_dir_fid */
6075 directory, /* fname */
6076 0, /* create_file_flags */
6077 access_mask, /* access_mask */
6078 (FILE_SHARE_READ | /* share_access */
6079 FILE_SHARE_WRITE),
6080 FILE_OPEN, /* create_disposition*/
6081 create_options, /* create_options */
6082 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6083 0, /* oplock_request */
6084 0, /* allocation_size */
6085 NULL, /* sd */
6086 NULL, /* ea_list */
6087 &fsp, /* result */
6088 NULL, /* pinfo */
6089 &sbuf1); /* psbuf */
6091 if (!NT_STATUS_IS_OK(status)) {
6092 DEBUG(3, ("Could not open rename source %s: %s\n",
6093 directory, nt_errstr(status)));
6094 return status;
6097 status = rename_internals_fsp(conn, fsp, newname,
6098 last_component_dest,
6099 attrs, replace_if_exists);
6101 close_file(req, fsp, NORMAL_CLOSE);
6103 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6104 nt_errstr(status), directory,newname));
6106 return status;
6110 * Wildcards - process each file that matches.
6112 if (strequal(mask,"????????.???")) {
6113 mask[0] = '*';
6114 mask[1] = '\0';
6117 status = check_name(conn, directory);
6118 if (!NT_STATUS_IS_OK(status)) {
6119 return status;
6122 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6123 if (dir_hnd == NULL) {
6124 return map_nt_error_from_unix(errno);
6127 status = NT_STATUS_NO_SUCH_FILE;
6129 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6130 * - gentest fix. JRA
6133 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6134 files_struct *fsp = NULL;
6135 char *fname = NULL;
6136 char *destname = NULL;
6137 bool sysdir_entry = False;
6139 /* Quick check for "." and ".." */
6140 if (ISDOT(dname) || ISDOTDOT(dname)) {
6141 if (attrs & aDIR) {
6142 sysdir_entry = True;
6143 } else {
6144 continue;
6148 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6149 continue;
6152 if(!mask_match(dname, mask, conn->case_sensitive)) {
6153 continue;
6156 if (sysdir_entry) {
6157 status = NT_STATUS_OBJECT_NAME_INVALID;
6158 break;
6161 fname = talloc_asprintf(ctx,
6162 "%s/%s",
6163 directory,
6164 dname);
6165 if (!fname) {
6166 return NT_STATUS_NO_MEMORY;
6169 if (!resolve_wildcards(ctx,
6170 fname,newname,&destname)) {
6171 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6172 fname, destname));
6173 TALLOC_FREE(fname);
6174 continue;
6176 if (!destname) {
6177 return NT_STATUS_NO_MEMORY;
6180 ZERO_STRUCT(sbuf1);
6181 if (posix_pathnames) {
6182 SMB_VFS_LSTAT(conn, fname, &sbuf1);
6183 } else {
6184 SMB_VFS_STAT(conn, fname, &sbuf1);
6187 create_options = 0;
6189 if (S_ISDIR(sbuf1.st_mode)) {
6190 create_options |= FILE_DIRECTORY_FILE;
6193 status = SMB_VFS_CREATE_FILE(
6194 conn, /* conn */
6195 req, /* req */
6196 0, /* root_dir_fid */
6197 fname, /* fname */
6198 0, /* create_file_flags */
6199 access_mask, /* access_mask */
6200 (FILE_SHARE_READ | /* share_access */
6201 FILE_SHARE_WRITE),
6202 FILE_OPEN, /* create_disposition*/
6203 create_options, /* create_options */
6204 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6205 0, /* oplock_request */
6206 0, /* allocation_size */
6207 NULL, /* sd */
6208 NULL, /* ea_list */
6209 &fsp, /* result */
6210 NULL, /* pinfo */
6211 &sbuf1); /* psbuf */
6213 if (!NT_STATUS_IS_OK(status)) {
6214 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6215 "returned %s rename %s -> %s\n",
6216 nt_errstr(status), directory, newname));
6217 break;
6220 status = rename_internals_fsp(conn, fsp, destname, dname,
6221 attrs, replace_if_exists);
6223 close_file(req, fsp, NORMAL_CLOSE);
6225 if (!NT_STATUS_IS_OK(status)) {
6226 DEBUG(3, ("rename_internals_fsp returned %s for "
6227 "rename %s -> %s\n", nt_errstr(status),
6228 directory, newname));
6229 break;
6232 count++;
6234 DEBUG(3,("rename_internals: doing rename on %s -> "
6235 "%s\n",fname,destname));
6237 TALLOC_FREE(fname);
6238 TALLOC_FREE(destname);
6240 TALLOC_FREE(dir_hnd);
6242 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6243 status = map_nt_error_from_unix(errno);
6246 return status;
6249 /****************************************************************************
6250 Reply to a mv.
6251 ****************************************************************************/
6253 void reply_mv(struct smb_request *req)
6255 connection_struct *conn = req->conn;
6256 char *name = NULL;
6257 char *newname = NULL;
6258 const char *p;
6259 uint32 attrs;
6260 NTSTATUS status;
6261 bool src_has_wcard = False;
6262 bool dest_has_wcard = False;
6263 TALLOC_CTX *ctx = talloc_tos();
6265 START_PROFILE(SMBmv);
6267 if (req->wct < 1) {
6268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6269 END_PROFILE(SMBmv);
6270 return;
6273 attrs = SVAL(req->vwv+0, 0);
6275 p = (const char *)req->buf + 1;
6276 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6277 &status, &src_has_wcard);
6278 if (!NT_STATUS_IS_OK(status)) {
6279 reply_nterror(req, status);
6280 END_PROFILE(SMBmv);
6281 return;
6283 p++;
6284 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6285 &status, &dest_has_wcard);
6286 if (!NT_STATUS_IS_OK(status)) {
6287 reply_nterror(req, status);
6288 END_PROFILE(SMBmv);
6289 return;
6292 status = resolve_dfspath_wcard(ctx, conn,
6293 req->flags2 & FLAGS2_DFS_PATHNAMES,
6294 name,
6295 &name,
6296 &src_has_wcard);
6297 if (!NT_STATUS_IS_OK(status)) {
6298 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6299 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6300 ERRSRV, ERRbadpath);
6301 END_PROFILE(SMBmv);
6302 return;
6304 reply_nterror(req, status);
6305 END_PROFILE(SMBmv);
6306 return;
6309 status = resolve_dfspath_wcard(ctx, conn,
6310 req->flags2 & FLAGS2_DFS_PATHNAMES,
6311 newname,
6312 &newname,
6313 &dest_has_wcard);
6314 if (!NT_STATUS_IS_OK(status)) {
6315 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6316 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6317 ERRSRV, ERRbadpath);
6318 END_PROFILE(SMBmv);
6319 return;
6321 reply_nterror(req, status);
6322 END_PROFILE(SMBmv);
6323 return;
6326 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6328 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6329 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6330 if (!NT_STATUS_IS_OK(status)) {
6331 if (open_was_deferred(req->mid)) {
6332 /* We have re-scheduled this call. */
6333 END_PROFILE(SMBmv);
6334 return;
6336 reply_nterror(req, status);
6337 END_PROFILE(SMBmv);
6338 return;
6341 reply_outbuf(req, 0, 0);
6343 END_PROFILE(SMBmv);
6344 return;
6347 /*******************************************************************
6348 Copy a file as part of a reply_copy.
6349 ******************************************************************/
6352 * TODO: check error codes on all callers
6355 NTSTATUS copy_file(TALLOC_CTX *ctx,
6356 connection_struct *conn,
6357 const char *src,
6358 const char *dest1,
6359 int ofun,
6360 int count,
6361 bool target_is_directory)
6363 SMB_STRUCT_STAT src_sbuf, sbuf2;
6364 SMB_OFF_T ret=-1;
6365 files_struct *fsp1,*fsp2;
6366 char *dest = NULL;
6367 uint32 dosattrs;
6368 uint32 new_create_disposition;
6369 NTSTATUS status;
6371 dest = talloc_strdup(ctx, dest1);
6372 if (!dest) {
6373 return NT_STATUS_NO_MEMORY;
6375 if (target_is_directory) {
6376 const char *p = strrchr_m(src,'/');
6377 if (p) {
6378 p++;
6379 } else {
6380 p = src;
6382 dest = talloc_asprintf_append(dest,
6383 "/%s",
6385 if (!dest) {
6386 return NT_STATUS_NO_MEMORY;
6390 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6391 TALLOC_FREE(dest);
6392 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6395 if (!target_is_directory && count) {
6396 new_create_disposition = FILE_OPEN;
6397 } else {
6398 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6399 NULL, NULL, &new_create_disposition, NULL)) {
6400 TALLOC_FREE(dest);
6401 return NT_STATUS_INVALID_PARAMETER;
6405 status = SMB_VFS_CREATE_FILE(
6406 conn, /* conn */
6407 NULL, /* req */
6408 0, /* root_dir_fid */
6409 src, /* fname */
6410 0, /* create_file_flags */
6411 FILE_GENERIC_READ, /* access_mask */
6412 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6413 FILE_OPEN, /* create_disposition*/
6414 0, /* create_options */
6415 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6416 INTERNAL_OPEN_ONLY, /* oplock_request */
6417 0, /* allocation_size */
6418 NULL, /* sd */
6419 NULL, /* ea_list */
6420 &fsp1, /* result */
6421 NULL, /* pinfo */
6422 &src_sbuf); /* psbuf */
6424 if (!NT_STATUS_IS_OK(status)) {
6425 TALLOC_FREE(dest);
6426 return status;
6429 dosattrs = dos_mode(conn, src, &src_sbuf);
6430 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6431 ZERO_STRUCTP(&sbuf2);
6434 status = SMB_VFS_CREATE_FILE(
6435 conn, /* conn */
6436 NULL, /* req */
6437 0, /* root_dir_fid */
6438 dest, /* fname */
6439 0, /* create_file_flags */
6440 FILE_GENERIC_WRITE, /* access_mask */
6441 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6442 new_create_disposition, /* create_disposition*/
6443 0, /* create_options */
6444 dosattrs, /* file_attributes */
6445 INTERNAL_OPEN_ONLY, /* oplock_request */
6446 0, /* allocation_size */
6447 NULL, /* sd */
6448 NULL, /* ea_list */
6449 &fsp2, /* result */
6450 NULL, /* pinfo */
6451 &sbuf2); /* psbuf */
6453 TALLOC_FREE(dest);
6455 if (!NT_STATUS_IS_OK(status)) {
6456 close_file(NULL, fsp1, ERROR_CLOSE);
6457 return status;
6460 if ((ofun&3) == 1) {
6461 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6462 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6464 * Stop the copy from occurring.
6466 ret = -1;
6467 src_sbuf.st_size = 0;
6471 if (src_sbuf.st_size) {
6472 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6475 close_file(NULL, fsp1, NORMAL_CLOSE);
6477 /* Ensure the modtime is set correctly on the destination file. */
6478 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6481 * As we are opening fsp1 read-only we only expect
6482 * an error on close on fsp2 if we are out of space.
6483 * Thus we don't look at the error return from the
6484 * close of fsp1.
6486 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6488 if (!NT_STATUS_IS_OK(status)) {
6489 return status;
6492 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6493 return NT_STATUS_DISK_FULL;
6496 return NT_STATUS_OK;
6499 /****************************************************************************
6500 Reply to a file copy.
6501 ****************************************************************************/
6503 void reply_copy(struct smb_request *req)
6505 connection_struct *conn = req->conn;
6506 char *name = NULL;
6507 char *newname = NULL;
6508 char *directory = NULL;
6509 const char *mask = NULL;
6510 const char mask_star[] = "*";
6511 const char *p;
6512 int count=0;
6513 int error = ERRnoaccess;
6514 int err = 0;
6515 int tid2;
6516 int ofun;
6517 int flags;
6518 bool target_is_directory=False;
6519 bool source_has_wild = False;
6520 bool dest_has_wild = False;
6521 SMB_STRUCT_STAT sbuf1, sbuf2;
6522 NTSTATUS status;
6523 TALLOC_CTX *ctx = talloc_tos();
6525 START_PROFILE(SMBcopy);
6527 if (req->wct < 3) {
6528 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6529 END_PROFILE(SMBcopy);
6530 return;
6533 tid2 = SVAL(req->vwv+0, 0);
6534 ofun = SVAL(req->vwv+1, 0);
6535 flags = SVAL(req->vwv+2, 0);
6537 p = (const char *)req->buf;
6538 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6539 &status, &source_has_wild);
6540 if (!NT_STATUS_IS_OK(status)) {
6541 reply_nterror(req, status);
6542 END_PROFILE(SMBcopy);
6543 return;
6545 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6546 &status, &dest_has_wild);
6547 if (!NT_STATUS_IS_OK(status)) {
6548 reply_nterror(req, status);
6549 END_PROFILE(SMBcopy);
6550 return;
6553 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6555 if (tid2 != conn->cnum) {
6556 /* can't currently handle inter share copies XXXX */
6557 DEBUG(3,("Rejecting inter-share copy\n"));
6558 reply_doserror(req, ERRSRV, ERRinvdevice);
6559 END_PROFILE(SMBcopy);
6560 return;
6563 status = resolve_dfspath_wcard(ctx, conn,
6564 req->flags2 & FLAGS2_DFS_PATHNAMES,
6565 name,
6566 &name,
6567 &source_has_wild);
6568 if (!NT_STATUS_IS_OK(status)) {
6569 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6570 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6571 ERRSRV, ERRbadpath);
6572 END_PROFILE(SMBcopy);
6573 return;
6575 reply_nterror(req, status);
6576 END_PROFILE(SMBcopy);
6577 return;
6580 status = resolve_dfspath_wcard(ctx, conn,
6581 req->flags2 & FLAGS2_DFS_PATHNAMES,
6582 newname,
6583 &newname,
6584 &dest_has_wild);
6585 if (!NT_STATUS_IS_OK(status)) {
6586 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6587 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6588 ERRSRV, ERRbadpath);
6589 END_PROFILE(SMBcopy);
6590 return;
6592 reply_nterror(req, status);
6593 END_PROFILE(SMBcopy);
6594 return;
6597 status = unix_convert(ctx, conn, name, source_has_wild,
6598 &name, NULL, &sbuf1);
6599 if (!NT_STATUS_IS_OK(status)) {
6600 reply_nterror(req, status);
6601 END_PROFILE(SMBcopy);
6602 return;
6605 status = unix_convert(ctx, conn, newname, dest_has_wild,
6606 &newname, NULL, &sbuf2);
6607 if (!NT_STATUS_IS_OK(status)) {
6608 reply_nterror(req, status);
6609 END_PROFILE(SMBcopy);
6610 return;
6613 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6615 if ((flags&1) && target_is_directory) {
6616 reply_doserror(req, ERRDOS, ERRbadfile);
6617 END_PROFILE(SMBcopy);
6618 return;
6621 if ((flags&2) && !target_is_directory) {
6622 reply_doserror(req, ERRDOS, ERRbadpath);
6623 END_PROFILE(SMBcopy);
6624 return;
6627 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6628 /* wants a tree copy! XXXX */
6629 DEBUG(3,("Rejecting tree copy\n"));
6630 reply_doserror(req, ERRSRV, ERRerror);
6631 END_PROFILE(SMBcopy);
6632 return;
6635 p = strrchr_m(name,'/');
6636 if (p != NULL) {
6637 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6638 mask = p+1;
6639 } else {
6640 directory = talloc_strdup(ctx, "./");
6641 mask = name;
6644 if (!directory) {
6645 reply_nterror(req, NT_STATUS_NO_MEMORY);
6646 END_PROFILE(SMBcopy);
6647 return;
6651 * We should only check the mangled cache
6652 * here if unix_convert failed. This means
6653 * that the path in 'mask' doesn't exist
6654 * on the file system and so we need to look
6655 * for a possible mangle. This patch from
6656 * Tine Smukavec <valentin.smukavec@hermes.si>.
6659 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6660 char *new_mask = NULL;
6661 mangle_lookup_name_from_8_3(ctx,
6662 mask,
6663 &new_mask,
6664 conn->params );
6665 if (new_mask) {
6666 mask = new_mask;
6670 if (!source_has_wild) {
6671 directory = talloc_asprintf_append(directory,
6672 "/%s",
6673 mask);
6674 if (dest_has_wild) {
6675 char *mod_newname = NULL;
6676 if (!resolve_wildcards(ctx,
6677 directory,newname,&mod_newname)) {
6678 reply_nterror(req, NT_STATUS_NO_MEMORY);
6679 END_PROFILE(SMBcopy);
6680 return;
6682 newname = mod_newname;
6685 status = check_name(conn, directory);
6686 if (!NT_STATUS_IS_OK(status)) {
6687 reply_nterror(req, status);
6688 END_PROFILE(SMBcopy);
6689 return;
6692 status = check_name(conn, newname);
6693 if (!NT_STATUS_IS_OK(status)) {
6694 reply_nterror(req, status);
6695 END_PROFILE(SMBcopy);
6696 return;
6699 status = copy_file(ctx,conn,directory,newname,ofun,
6700 count,target_is_directory);
6702 if(!NT_STATUS_IS_OK(status)) {
6703 reply_nterror(req, status);
6704 END_PROFILE(SMBcopy);
6705 return;
6706 } else {
6707 count++;
6709 } else {
6710 struct smb_Dir *dir_hnd = NULL;
6711 const char *dname = NULL;
6712 long offset = 0;
6714 if (strequal(mask,"????????.???")) {
6715 mask = mask_star;
6718 status = check_name(conn, directory);
6719 if (!NT_STATUS_IS_OK(status)) {
6720 reply_nterror(req, status);
6721 END_PROFILE(SMBcopy);
6722 return;
6725 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6726 if (dir_hnd == NULL) {
6727 status = map_nt_error_from_unix(errno);
6728 reply_nterror(req, status);
6729 END_PROFILE(SMBcopy);
6730 return;
6733 error = ERRbadfile;
6735 while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
6736 char *destname = NULL;
6737 char *fname = NULL;
6739 if (ISDOT(dname) || ISDOTDOT(dname)) {
6740 continue;
6743 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6744 continue;
6747 if(!mask_match(dname, mask, conn->case_sensitive)) {
6748 continue;
6751 error = ERRnoaccess;
6752 fname = talloc_asprintf(ctx,
6753 "%s/%s",
6754 directory,
6755 dname);
6756 if (!fname) {
6757 TALLOC_FREE(dir_hnd);
6758 reply_nterror(req, NT_STATUS_NO_MEMORY);
6759 END_PROFILE(SMBcopy);
6760 return;
6763 if (!resolve_wildcards(ctx,
6764 fname,newname,&destname)) {
6765 continue;
6767 if (!destname) {
6768 TALLOC_FREE(dir_hnd);
6769 reply_nterror(req, NT_STATUS_NO_MEMORY);
6770 END_PROFILE(SMBcopy);
6771 return;
6774 status = check_name(conn, fname);
6775 if (!NT_STATUS_IS_OK(status)) {
6776 TALLOC_FREE(dir_hnd);
6777 reply_nterror(req, status);
6778 END_PROFILE(SMBcopy);
6779 return;
6782 status = check_name(conn, destname);
6783 if (!NT_STATUS_IS_OK(status)) {
6784 TALLOC_FREE(dir_hnd);
6785 reply_nterror(req, status);
6786 END_PROFILE(SMBcopy);
6787 return;
6790 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6792 status = copy_file(ctx,conn,fname,destname,ofun,
6793 count,target_is_directory);
6794 if (NT_STATUS_IS_OK(status)) {
6795 count++;
6797 TALLOC_FREE(fname);
6798 TALLOC_FREE(destname);
6800 TALLOC_FREE(dir_hnd);
6803 if (count == 0) {
6804 if(err) {
6805 /* Error on close... */
6806 errno = err;
6807 reply_unixerror(req, ERRHRD, ERRgeneral);
6808 END_PROFILE(SMBcopy);
6809 return;
6812 reply_doserror(req, ERRDOS, error);
6813 END_PROFILE(SMBcopy);
6814 return;
6817 reply_outbuf(req, 1, 0);
6818 SSVAL(req->outbuf,smb_vwv0,count);
6820 END_PROFILE(SMBcopy);
6821 return;
6824 #undef DBGC_CLASS
6825 #define DBGC_CLASS DBGC_LOCKING
6827 /****************************************************************************
6828 Get a lock pid, dealing with large count requests.
6829 ****************************************************************************/
6831 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6832 bool large_file_format)
6834 if(!large_file_format)
6835 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6836 else
6837 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6840 /****************************************************************************
6841 Get a lock count, dealing with large count requests.
6842 ****************************************************************************/
6844 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6845 bool large_file_format)
6847 uint64_t count = 0;
6849 if(!large_file_format) {
6850 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6851 } else {
6853 #if defined(HAVE_LONGLONG)
6854 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6855 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6856 #else /* HAVE_LONGLONG */
6859 * NT4.x seems to be broken in that it sends large file (64 bit)
6860 * lockingX calls even if the CAP_LARGE_FILES was *not*
6861 * negotiated. For boxes without large unsigned ints truncate the
6862 * lock count by dropping the top 32 bits.
6865 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6866 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6867 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6868 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6869 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6872 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6873 #endif /* HAVE_LONGLONG */
6876 return count;
6879 #if !defined(HAVE_LONGLONG)
6880 /****************************************************************************
6881 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6882 ****************************************************************************/
6884 static uint32 map_lock_offset(uint32 high, uint32 low)
6886 unsigned int i;
6887 uint32 mask = 0;
6888 uint32 highcopy = high;
6891 * Try and find out how many significant bits there are in high.
6894 for(i = 0; highcopy; i++)
6895 highcopy >>= 1;
6898 * We use 31 bits not 32 here as POSIX
6899 * lock offsets may not be negative.
6902 mask = (~0) << (31 - i);
6904 if(low & mask)
6905 return 0; /* Fail. */
6907 high <<= (31 - i);
6909 return (high|low);
6911 #endif /* !defined(HAVE_LONGLONG) */
6913 /****************************************************************************
6914 Get a lock offset, dealing with large offset requests.
6915 ****************************************************************************/
6917 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6918 bool large_file_format, bool *err)
6920 uint64_t offset = 0;
6922 *err = False;
6924 if(!large_file_format) {
6925 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6926 } else {
6928 #if defined(HAVE_LONGLONG)
6929 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6930 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6931 #else /* HAVE_LONGLONG */
6934 * NT4.x seems to be broken in that it sends large file (64 bit)
6935 * lockingX calls even if the CAP_LARGE_FILES was *not*
6936 * negotiated. For boxes without large unsigned ints mangle the
6937 * lock offset by mapping the top 32 bits onto the lower 32.
6940 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6941 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6942 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6943 uint32 new_low = 0;
6945 if((new_low = map_lock_offset(high, low)) == 0) {
6946 *err = True;
6947 return (uint64_t)-1;
6950 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6951 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6952 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6953 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6956 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6957 #endif /* HAVE_LONGLONG */
6960 return offset;
6963 /****************************************************************************
6964 Reply to a lockingX request.
6965 ****************************************************************************/
6967 void reply_lockingX(struct smb_request *req)
6969 connection_struct *conn = req->conn;
6970 files_struct *fsp;
6971 unsigned char locktype;
6972 unsigned char oplocklevel;
6973 uint16 num_ulocks;
6974 uint16 num_locks;
6975 uint64_t count = 0, offset = 0;
6976 uint32 lock_pid;
6977 int32 lock_timeout;
6978 int i;
6979 const uint8_t *data;
6980 bool large_file_format;
6981 bool err;
6982 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6984 START_PROFILE(SMBlockingX);
6986 if (req->wct < 8) {
6987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6988 END_PROFILE(SMBlockingX);
6989 return;
6992 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6993 locktype = CVAL(req->vwv+3, 0);
6994 oplocklevel = CVAL(req->vwv+3, 1);
6995 num_ulocks = SVAL(req->vwv+6, 0);
6996 num_locks = SVAL(req->vwv+7, 0);
6997 lock_timeout = IVAL(req->vwv+4, 0);
6998 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7000 if (!check_fsp(conn, req, fsp)) {
7001 END_PROFILE(SMBlockingX);
7002 return;
7005 data = req->buf;
7007 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7008 /* we don't support these - and CANCEL_LOCK makes w2k
7009 and XP reboot so I don't really want to be
7010 compatible! (tridge) */
7011 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7012 END_PROFILE(SMBlockingX);
7013 return;
7016 /* Check if this is an oplock break on a file
7017 we have granted an oplock on.
7019 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7020 /* Client can insist on breaking to none. */
7021 bool break_to_none = (oplocklevel == 0);
7022 bool result;
7024 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7025 "for fnum = %d\n", (unsigned int)oplocklevel,
7026 fsp->fnum ));
7029 * Make sure we have granted an exclusive or batch oplock on
7030 * this file.
7033 if (fsp->oplock_type == 0) {
7035 /* The Samba4 nbench simulator doesn't understand
7036 the difference between break to level2 and break
7037 to none from level2 - it sends oplock break
7038 replies in both cases. Don't keep logging an error
7039 message here - just ignore it. JRA. */
7041 DEBUG(5,("reply_lockingX: Error : oplock break from "
7042 "client for fnum = %d (oplock=%d) and no "
7043 "oplock granted on this file (%s).\n",
7044 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7046 /* if this is a pure oplock break request then don't
7047 * send a reply */
7048 if (num_locks == 0 && num_ulocks == 0) {
7049 END_PROFILE(SMBlockingX);
7050 return;
7051 } else {
7052 END_PROFILE(SMBlockingX);
7053 reply_doserror(req, ERRDOS, ERRlock);
7054 return;
7058 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7059 (break_to_none)) {
7060 result = remove_oplock(fsp);
7061 } else {
7062 result = downgrade_oplock(fsp);
7065 if (!result) {
7066 DEBUG(0, ("reply_lockingX: error in removing "
7067 "oplock on file %s\n", fsp->fsp_name));
7068 /* Hmmm. Is this panic justified? */
7069 smb_panic("internal tdb error");
7072 reply_to_oplock_break_requests(fsp);
7074 /* if this is a pure oplock break request then don't send a
7075 * reply */
7076 if (num_locks == 0 && num_ulocks == 0) {
7077 /* Sanity check - ensure a pure oplock break is not a
7078 chained request. */
7079 if(CVAL(req->vwv+0, 0) != 0xff)
7080 DEBUG(0,("reply_lockingX: Error : pure oplock "
7081 "break is a chained %d request !\n",
7082 (unsigned int)CVAL(req->vwv+0, 0)));
7083 END_PROFILE(SMBlockingX);
7084 return;
7088 if (req->buflen <
7089 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7091 END_PROFILE(SMBlockingX);
7092 return;
7095 /* Data now points at the beginning of the list
7096 of smb_unlkrng structs */
7097 for(i = 0; i < (int)num_ulocks; i++) {
7098 lock_pid = get_lock_pid( data, i, large_file_format);
7099 count = get_lock_count( data, i, large_file_format);
7100 offset = get_lock_offset( data, i, large_file_format, &err);
7103 * There is no error code marked "stupid client bug".... :-).
7105 if(err) {
7106 END_PROFILE(SMBlockingX);
7107 reply_doserror(req, ERRDOS, ERRnoaccess);
7108 return;
7111 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7112 "pid %u, file %s\n", (double)offset, (double)count,
7113 (unsigned int)lock_pid, fsp->fsp_name ));
7115 status = do_unlock(smbd_messaging_context(),
7116 fsp,
7117 lock_pid,
7118 count,
7119 offset,
7120 WINDOWS_LOCK);
7122 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7123 nt_errstr(status)));
7125 if (NT_STATUS_V(status)) {
7126 END_PROFILE(SMBlockingX);
7127 reply_nterror(req, status);
7128 return;
7132 /* Setup the timeout in seconds. */
7134 if (!lp_blocking_locks(SNUM(conn))) {
7135 lock_timeout = 0;
7138 /* Now do any requested locks */
7139 data += ((large_file_format ? 20 : 10)*num_ulocks);
7141 /* Data now points at the beginning of the list
7142 of smb_lkrng structs */
7144 for(i = 0; i < (int)num_locks; i++) {
7145 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7146 READ_LOCK:WRITE_LOCK);
7147 lock_pid = get_lock_pid( data, i, large_file_format);
7148 count = get_lock_count( data, i, large_file_format);
7149 offset = get_lock_offset( data, i, large_file_format, &err);
7152 * There is no error code marked "stupid client bug".... :-).
7154 if(err) {
7155 END_PROFILE(SMBlockingX);
7156 reply_doserror(req, ERRDOS, ERRnoaccess);
7157 return;
7160 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7161 "%u, file %s timeout = %d\n", (double)offset,
7162 (double)count, (unsigned int)lock_pid,
7163 fsp->fsp_name, (int)lock_timeout ));
7165 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7166 struct blocking_lock_record *blr = NULL;
7168 if (lp_blocking_locks(SNUM(conn))) {
7170 /* Schedule a message to ourselves to
7171 remove the blocking lock record and
7172 return the right error. */
7174 blr = blocking_lock_cancel(fsp,
7175 lock_pid,
7176 offset,
7177 count,
7178 WINDOWS_LOCK,
7179 locktype,
7180 NT_STATUS_FILE_LOCK_CONFLICT);
7181 if (blr == NULL) {
7182 END_PROFILE(SMBlockingX);
7183 reply_nterror(
7184 req,
7185 NT_STATUS_DOS(
7186 ERRDOS,
7187 ERRcancelviolation));
7188 return;
7191 /* Remove a matching pending lock. */
7192 status = do_lock_cancel(fsp,
7193 lock_pid,
7194 count,
7195 offset,
7196 WINDOWS_LOCK,
7197 blr);
7198 } else {
7199 bool blocking_lock = lock_timeout ? True : False;
7200 bool defer_lock = False;
7201 struct byte_range_lock *br_lck;
7202 uint32 block_smbpid;
7204 br_lck = do_lock(smbd_messaging_context(),
7205 fsp,
7206 lock_pid,
7207 count,
7208 offset,
7209 lock_type,
7210 WINDOWS_LOCK,
7211 blocking_lock,
7212 &status,
7213 &block_smbpid,
7214 NULL);
7216 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7217 /* Windows internal resolution for blocking locks seems
7218 to be about 200ms... Don't wait for less than that. JRA. */
7219 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7220 lock_timeout = lp_lock_spin_time();
7222 defer_lock = True;
7225 /* This heuristic seems to match W2K3 very well. If a
7226 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7227 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7228 far as I can tell. Replacement for do_lock_spin(). JRA. */
7230 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7231 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7232 defer_lock = True;
7233 lock_timeout = lp_lock_spin_time();
7236 if (br_lck && defer_lock) {
7238 * A blocking lock was requested. Package up
7239 * this smb into a queued request and push it
7240 * onto the blocking lock queue.
7242 if(push_blocking_lock_request(br_lck,
7243 req,
7244 fsp,
7245 lock_timeout,
7247 lock_pid,
7248 lock_type,
7249 WINDOWS_LOCK,
7250 offset,
7251 count,
7252 block_smbpid)) {
7253 TALLOC_FREE(br_lck);
7254 END_PROFILE(SMBlockingX);
7255 return;
7259 TALLOC_FREE(br_lck);
7262 if (NT_STATUS_V(status)) {
7263 END_PROFILE(SMBlockingX);
7264 reply_nterror(req, status);
7265 return;
7269 /* If any of the above locks failed, then we must unlock
7270 all of the previous locks (X/Open spec). */
7272 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7273 (i != num_locks) &&
7274 (num_locks != 0)) {
7276 * Ensure we don't do a remove on the lock that just failed,
7277 * as under POSIX rules, if we have a lock already there, we
7278 * will delete it (and we shouldn't) .....
7280 for(i--; i >= 0; i--) {
7281 lock_pid = get_lock_pid( data, i, large_file_format);
7282 count = get_lock_count( data, i, large_file_format);
7283 offset = get_lock_offset( data, i, large_file_format,
7284 &err);
7287 * There is no error code marked "stupid client
7288 * bug".... :-).
7290 if(err) {
7291 END_PROFILE(SMBlockingX);
7292 reply_doserror(req, ERRDOS, ERRnoaccess);
7293 return;
7296 do_unlock(smbd_messaging_context(),
7297 fsp,
7298 lock_pid,
7299 count,
7300 offset,
7301 WINDOWS_LOCK);
7303 END_PROFILE(SMBlockingX);
7304 reply_nterror(req, status);
7305 return;
7308 reply_outbuf(req, 2, 0);
7310 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7311 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7313 END_PROFILE(SMBlockingX);
7314 chain_reply(req);
7317 #undef DBGC_CLASS
7318 #define DBGC_CLASS DBGC_ALL
7320 /****************************************************************************
7321 Reply to a SMBreadbmpx (read block multiplex) request.
7322 Always reply with an error, if someone has a platform really needs this,
7323 please contact vl@samba.org
7324 ****************************************************************************/
7326 void reply_readbmpx(struct smb_request *req)
7328 START_PROFILE(SMBreadBmpx);
7329 reply_doserror(req, ERRSRV, ERRuseSTD);
7330 END_PROFILE(SMBreadBmpx);
7331 return;
7334 /****************************************************************************
7335 Reply to a SMBreadbs (read block multiplex secondary) request.
7336 Always reply with an error, if someone has a platform really needs this,
7337 please contact vl@samba.org
7338 ****************************************************************************/
7340 void reply_readbs(struct smb_request *req)
7342 START_PROFILE(SMBreadBs);
7343 reply_doserror(req, ERRSRV, ERRuseSTD);
7344 END_PROFILE(SMBreadBs);
7345 return;
7348 /****************************************************************************
7349 Reply to a SMBsetattrE.
7350 ****************************************************************************/
7352 void reply_setattrE(struct smb_request *req)
7354 connection_struct *conn = req->conn;
7355 struct smb_file_time ft;
7356 files_struct *fsp;
7357 SMB_STRUCT_STAT sbuf;
7358 NTSTATUS status;
7360 START_PROFILE(SMBsetattrE);
7361 ZERO_STRUCT(ft);
7363 if (req->wct < 7) {
7364 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7365 END_PROFILE(SMBsetattrE);
7366 return;
7369 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7371 if(!fsp || (fsp->conn != conn)) {
7372 reply_doserror(req, ERRDOS, ERRbadfid);
7373 END_PROFILE(SMBsetattrE);
7374 return;
7379 * Convert the DOS times into unix times.
7382 ft.atime = convert_time_t_to_timespec(
7383 srv_make_unix_date2(req->vwv+3));
7384 ft.mtime = convert_time_t_to_timespec(
7385 srv_make_unix_date2(req->vwv+5));
7386 ft.create_time = convert_time_t_to_timespec(
7387 srv_make_unix_date2(req->vwv+1));
7389 reply_outbuf(req, 0, 0);
7392 * Patch from Ray Frush <frush@engr.colostate.edu>
7393 * Sometimes times are sent as zero - ignore them.
7396 /* Ensure we have a valid stat struct for the source. */
7397 if (fsp->fh->fd != -1) {
7398 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7399 status = map_nt_error_from_unix(errno);
7400 reply_nterror(req, status);
7401 END_PROFILE(SMBsetattrE);
7402 return;
7404 } else {
7405 int ret = -1;
7407 if (fsp->posix_open) {
7408 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7409 } else {
7410 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7412 if (ret == -1) {
7413 status = map_nt_error_from_unix(errno);
7414 reply_nterror(req, status);
7415 END_PROFILE(SMBsetattrE);
7416 return;
7420 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7421 &sbuf, &ft, true);
7422 if (!NT_STATUS_IS_OK(status)) {
7423 reply_doserror(req, ERRDOS, ERRnoaccess);
7424 END_PROFILE(SMBsetattrE);
7425 return;
7428 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7429 " createtime=%u\n",
7430 fsp->fnum,
7431 (unsigned int)ft.atime.tv_sec,
7432 (unsigned int)ft.mtime.tv_sec,
7433 (unsigned int)ft.create_time.tv_sec
7436 END_PROFILE(SMBsetattrE);
7437 return;
7441 /* Back from the dead for OS/2..... JRA. */
7443 /****************************************************************************
7444 Reply to a SMBwritebmpx (write block multiplex primary) request.
7445 Always reply with an error, if someone has a platform really needs this,
7446 please contact vl@samba.org
7447 ****************************************************************************/
7449 void reply_writebmpx(struct smb_request *req)
7451 START_PROFILE(SMBwriteBmpx);
7452 reply_doserror(req, ERRSRV, ERRuseSTD);
7453 END_PROFILE(SMBwriteBmpx);
7454 return;
7457 /****************************************************************************
7458 Reply to a SMBwritebs (write block multiplex secondary) request.
7459 Always reply with an error, if someone has a platform really needs this,
7460 please contact vl@samba.org
7461 ****************************************************************************/
7463 void reply_writebs(struct smb_request *req)
7465 START_PROFILE(SMBwriteBs);
7466 reply_doserror(req, ERRSRV, ERRuseSTD);
7467 END_PROFILE(SMBwriteBs);
7468 return;
7471 /****************************************************************************
7472 Reply to a SMBgetattrE.
7473 ****************************************************************************/
7475 void reply_getattrE(struct smb_request *req)
7477 connection_struct *conn = req->conn;
7478 SMB_STRUCT_STAT sbuf;
7479 int mode;
7480 files_struct *fsp;
7481 struct timespec create_ts;
7483 START_PROFILE(SMBgetattrE);
7485 if (req->wct < 1) {
7486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7487 END_PROFILE(SMBgetattrE);
7488 return;
7491 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7493 if(!fsp || (fsp->conn != conn)) {
7494 reply_doserror(req, ERRDOS, ERRbadfid);
7495 END_PROFILE(SMBgetattrE);
7496 return;
7499 /* Do an fstat on this file */
7500 if(fsp_stat(fsp, &sbuf)) {
7501 reply_unixerror(req, ERRDOS, ERRnoaccess);
7502 END_PROFILE(SMBgetattrE);
7503 return;
7506 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7509 * Convert the times into dos times. Set create
7510 * date to be last modify date as UNIX doesn't save
7511 * this.
7514 reply_outbuf(req, 11, 0);
7516 create_ts = get_create_timespec(&sbuf,
7517 lp_fake_dir_create_times(SNUM(conn)));
7518 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7519 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7520 /* Should we check pending modtime here ? JRA */
7521 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7523 if (mode & aDIR) {
7524 SIVAL(req->outbuf, smb_vwv6, 0);
7525 SIVAL(req->outbuf, smb_vwv8, 0);
7526 } else {
7527 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7528 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7529 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7531 SSVAL(req->outbuf,smb_vwv10, mode);
7533 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7535 END_PROFILE(SMBgetattrE);
7536 return;