Fix the build of nfs4_acls.c
[Samba.git] / source3 / smbd / reply.c
blob8657bd6e1807b9103b6c8ba34a97954c15c78f2b
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 *)(void *)&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 struct smb_filename *smb_fname = NULL;
970 char *name = NULL;
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, &smb_fname, 0);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 goto path_err;
1007 status = get_full_smb_filename(ctx, smb_fname, &name);
1008 if (!NT_STATUS_IS_OK(status)) {
1009 goto path_err;
1012 status = check_name(conn, name);
1013 if (!NT_STATUS_IS_OK(status)) {
1014 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
1015 goto path_err;
1018 if (!VALID_STAT(smb_fname->st) &&
1019 (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
1020 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1021 status = map_nt_error_from_unix(errno);
1022 goto path_err;
1025 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1026 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1027 ERRDOS, ERRbadpath);
1028 goto out;
1031 reply_outbuf(req, 0, 0);
1032 out:
1033 TALLOC_FREE(smb_fname);
1034 END_PROFILE(SMBcheckpath);
1035 return;
1037 path_err:
1039 TALLOC_FREE(smb_fname);
1041 END_PROFILE(SMBcheckpath);
1043 /* We special case this - as when a Windows machine
1044 is parsing a path is steps through the components
1045 one at a time - if a component fails it expects
1046 ERRbadpath, not ERRbadfile.
1048 status = map_checkpath_error(req->flags2, status);
1049 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1051 * Windows returns different error codes if
1052 * the parent directory is valid but not the
1053 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1054 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1055 * if the path is invalid.
1057 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1058 ERRDOS, ERRbadpath);
1059 return;
1062 reply_nterror(req, status);
1065 /****************************************************************************
1066 Reply to a getatr.
1067 ****************************************************************************/
1069 void reply_getatr(struct smb_request *req)
1071 connection_struct *conn = req->conn;
1072 struct smb_filename *smb_fname = NULL;
1073 char *fname = NULL;
1074 int mode=0;
1075 SMB_OFF_T size=0;
1076 time_t mtime=0;
1077 const char *p;
1078 NTSTATUS status;
1079 TALLOC_CTX *ctx = talloc_tos();
1081 START_PROFILE(SMBgetatr);
1083 p = (const char *)req->buf + 1;
1084 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1085 if (!NT_STATUS_IS_OK(status)) {
1086 reply_nterror(req, status);
1087 goto out;
1090 status = resolve_dfspath(ctx, conn,
1091 req->flags2 & FLAGS2_DFS_PATHNAMES,
1092 fname,
1093 &fname);
1094 if (!NT_STATUS_IS_OK(status)) {
1095 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1096 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1097 ERRSRV, ERRbadpath);
1098 goto out;
1100 reply_nterror(req, status);
1101 goto out;
1104 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1105 under WfWg - weird! */
1106 if (*fname == '\0') {
1107 mode = aHIDDEN | aDIR;
1108 if (!CAN_WRITE(conn)) {
1109 mode |= aRONLY;
1111 size = 0;
1112 mtime = 0;
1113 } else {
1114 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 reply_nterror(req, status);
1117 goto out;
1119 status = get_full_smb_filename(ctx, smb_fname, &fname);
1120 if (!NT_STATUS_IS_OK(status)) {
1121 reply_nterror(req, status);
1122 goto out;
1124 status = check_name(conn, fname);
1125 if (!NT_STATUS_IS_OK(status)) {
1126 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1127 reply_nterror(req, status);
1128 goto out;
1130 if (!VALID_STAT(smb_fname->st) &&
1131 (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
1132 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1133 reply_unixerror(req, ERRDOS,ERRbadfile);
1134 goto out;
1137 mode = dos_mode(conn, fname, &smb_fname->st);
1138 size = smb_fname->st.st_ex_size;
1139 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1140 if (mode & aDIR) {
1141 size = 0;
1145 reply_outbuf(req, 10, 0);
1147 SSVAL(req->outbuf,smb_vwv0,mode);
1148 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1149 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1150 } else {
1151 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1153 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1155 if (Protocol >= PROTOCOL_NT1) {
1156 SSVAL(req->outbuf, smb_flg2,
1157 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1160 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1162 out:
1163 TALLOC_FREE(smb_fname);
1164 END_PROFILE(SMBgetatr);
1165 return;
1168 /****************************************************************************
1169 Reply to a setatr.
1170 ****************************************************************************/
1172 void reply_setatr(struct smb_request *req)
1174 struct smb_file_time ft;
1175 connection_struct *conn = req->conn;
1176 struct smb_filename *smb_fname = NULL;
1177 char *fname = NULL;
1178 int mode;
1179 time_t mtime;
1180 const char *p;
1181 NTSTATUS status;
1182 TALLOC_CTX *ctx = talloc_tos();
1184 START_PROFILE(SMBsetatr);
1186 ZERO_STRUCT(ft);
1188 if (req->wct < 2) {
1189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1190 goto out;
1193 p = (const char *)req->buf + 1;
1194 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1195 if (!NT_STATUS_IS_OK(status)) {
1196 reply_nterror(req, status);
1197 goto out;
1200 status = resolve_dfspath(ctx, conn,
1201 req->flags2 & FLAGS2_DFS_PATHNAMES,
1202 fname,
1203 &fname);
1204 if (!NT_STATUS_IS_OK(status)) {
1205 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1206 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1207 ERRSRV, ERRbadpath);
1208 goto out;
1210 reply_nterror(req, status);
1211 goto out;
1214 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 reply_nterror(req, status);
1217 goto out;
1220 status = get_full_smb_filename(ctx, smb_fname, &fname);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 reply_nterror(req, status);
1223 goto out;
1226 status = check_name(conn, fname);
1227 if (!NT_STATUS_IS_OK(status)) {
1228 reply_nterror(req, status);
1229 goto out;
1232 if (fname[0] == '.' && fname[1] == '\0') {
1234 * Not sure here is the right place to catch this
1235 * condition. Might be moved to somewhere else later -- vl
1237 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1238 goto out;
1241 mode = SVAL(req->vwv+0, 0);
1242 mtime = srv_make_unix_date3(req->vwv+1);
1244 ft.mtime = convert_time_t_to_timespec(mtime);
1245 status = smb_set_file_time(conn, NULL, fname,
1246 &smb_fname->st, &ft, true);
1247 if (!NT_STATUS_IS_OK(status)) {
1248 reply_unixerror(req, ERRDOS, ERRnoaccess);
1249 goto out;
1252 if (mode != FILE_ATTRIBUTE_NORMAL) {
1253 if (VALID_STAT_OF_DIR(smb_fname->st))
1254 mode |= aDIR;
1255 else
1256 mode &= ~aDIR;
1258 if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
1259 false) != 0) {
1260 reply_unixerror(req, ERRDOS, ERRnoaccess);
1261 goto out;
1265 reply_outbuf(req, 0, 0);
1267 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1268 out:
1269 TALLOC_FREE(smb_fname);
1270 END_PROFILE(SMBsetatr);
1271 return;
1274 /****************************************************************************
1275 Reply to a dskattr.
1276 ****************************************************************************/
1278 void reply_dskattr(struct smb_request *req)
1280 connection_struct *conn = req->conn;
1281 uint64_t dfree,dsize,bsize;
1282 START_PROFILE(SMBdskattr);
1284 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1285 reply_unixerror(req, ERRHRD, ERRgeneral);
1286 END_PROFILE(SMBdskattr);
1287 return;
1290 reply_outbuf(req, 5, 0);
1292 if (Protocol <= PROTOCOL_LANMAN2) {
1293 double total_space, free_space;
1294 /* we need to scale this to a number that DOS6 can handle. We
1295 use floating point so we can handle large drives on systems
1296 that don't have 64 bit integers
1298 we end up displaying a maximum of 2G to DOS systems
1300 total_space = dsize * (double)bsize;
1301 free_space = dfree * (double)bsize;
1303 dsize = (uint64_t)((total_space+63*512) / (64*512));
1304 dfree = (uint64_t)((free_space+63*512) / (64*512));
1306 if (dsize > 0xFFFF) dsize = 0xFFFF;
1307 if (dfree > 0xFFFF) dfree = 0xFFFF;
1309 SSVAL(req->outbuf,smb_vwv0,dsize);
1310 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1311 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1312 SSVAL(req->outbuf,smb_vwv3,dfree);
1313 } else {
1314 SSVAL(req->outbuf,smb_vwv0,dsize);
1315 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1316 SSVAL(req->outbuf,smb_vwv2,512);
1317 SSVAL(req->outbuf,smb_vwv3,dfree);
1320 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1322 END_PROFILE(SMBdskattr);
1323 return;
1326 /****************************************************************************
1327 Reply to a search.
1328 Can be called from SMBsearch, SMBffirst or SMBfunique.
1329 ****************************************************************************/
1331 void reply_search(struct smb_request *req)
1333 connection_struct *conn = req->conn;
1334 const char *mask = NULL;
1335 char *directory = NULL;
1336 char *fname = NULL;
1337 SMB_OFF_T size;
1338 uint32 mode;
1339 struct timespec date;
1340 uint32 dirtype;
1341 unsigned int numentries = 0;
1342 unsigned int maxentries = 0;
1343 bool finished = False;
1344 const char *p;
1345 int status_len;
1346 char *path = NULL;
1347 char status[21];
1348 int dptr_num= -1;
1349 bool check_descend = False;
1350 bool expect_close = False;
1351 NTSTATUS nt_status;
1352 bool mask_contains_wcard = False;
1353 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1354 TALLOC_CTX *ctx = talloc_tos();
1355 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1357 START_PROFILE(SMBsearch);
1359 if (req->wct < 2) {
1360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1361 END_PROFILE(SMBsearch);
1362 return;
1365 if (lp_posix_pathnames()) {
1366 reply_unknown_new(req, req->cmd);
1367 END_PROFILE(SMBsearch);
1368 return;
1371 /* If we were called as SMBffirst then we must expect close. */
1372 if(req->cmd == SMBffirst) {
1373 expect_close = True;
1376 reply_outbuf(req, 1, 3);
1377 maxentries = SVAL(req->vwv+0, 0);
1378 dirtype = SVAL(req->vwv+1, 0);
1379 p = (const char *)req->buf + 1;
1380 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1381 &nt_status, &mask_contains_wcard);
1382 if (!NT_STATUS_IS_OK(nt_status)) {
1383 reply_nterror(req, nt_status);
1384 END_PROFILE(SMBsearch);
1385 return;
1388 nt_status = resolve_dfspath_wcard(ctx, conn,
1389 req->flags2 & FLAGS2_DFS_PATHNAMES,
1390 path,
1391 &path,
1392 &mask_contains_wcard);
1393 if (!NT_STATUS_IS_OK(nt_status)) {
1394 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1395 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1396 ERRSRV, ERRbadpath);
1397 END_PROFILE(SMBsearch);
1398 return;
1400 reply_nterror(req, nt_status);
1401 END_PROFILE(SMBsearch);
1402 return;
1405 p++;
1406 status_len = SVAL(p, 0);
1407 p += 2;
1409 /* dirtype &= ~aDIR; */
1411 if (status_len == 0) {
1412 struct smb_filename *smb_fname = NULL;
1414 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1415 UCF_ALLOW_WCARD_LCOMP);
1416 if (!NT_STATUS_IS_OK(nt_status)) {
1417 reply_nterror(req, nt_status);
1418 END_PROFILE(SMBsearch);
1419 return;
1422 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1423 TALLOC_FREE(smb_fname);
1424 if (!NT_STATUS_IS_OK(nt_status)) {
1425 reply_nterror(req, nt_status);
1426 END_PROFILE(SMBsearch);
1427 return;
1430 nt_status = check_name(conn, directory);
1431 if (!NT_STATUS_IS_OK(nt_status)) {
1432 reply_nterror(req, nt_status);
1433 END_PROFILE(SMBsearch);
1434 return;
1437 p = strrchr_m(directory,'/');
1438 if ((p != NULL) && (*directory != '/')) {
1439 mask = p + 1;
1440 directory = talloc_strndup(ctx, directory,
1441 PTR_DIFF(p, directory));
1442 } else {
1443 mask = directory;
1444 directory = talloc_strdup(ctx,".");
1447 if (!directory) {
1448 reply_nterror(req, NT_STATUS_NO_MEMORY);
1449 END_PROFILE(SMBsearch);
1450 return;
1453 memset((char *)status,'\0',21);
1454 SCVAL(status,0,(dirtype & 0x1F));
1456 nt_status = dptr_create(conn,
1457 directory,
1458 True,
1459 expect_close,
1460 req->smbpid,
1461 mask,
1462 mask_contains_wcard,
1463 dirtype,
1464 &conn->dirptr);
1465 if (!NT_STATUS_IS_OK(nt_status)) {
1466 reply_nterror(req, nt_status);
1467 END_PROFILE(SMBsearch);
1468 return;
1470 dptr_num = dptr_dnum(conn->dirptr);
1471 } else {
1472 int status_dirtype;
1474 memcpy(status,p,21);
1475 status_dirtype = CVAL(status,0) & 0x1F;
1476 if (status_dirtype != (dirtype & 0x1F)) {
1477 dirtype = status_dirtype;
1480 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1481 if (!conn->dirptr) {
1482 goto SearchEmpty;
1484 string_set(&conn->dirpath,dptr_path(dptr_num));
1485 mask = dptr_wcard(dptr_num);
1486 if (!mask) {
1487 goto SearchEmpty;
1490 * For a 'continue' search we have no string. So
1491 * check from the initial saved string.
1493 mask_contains_wcard = ms_has_wild(mask);
1494 dirtype = dptr_attr(dptr_num);
1497 DEBUG(4,("dptr_num is %d\n",dptr_num));
1499 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1500 dptr_init_search_op(conn->dirptr);
1502 if ((dirtype&0x1F) == aVOLID) {
1503 char buf[DIR_STRUCT_SIZE];
1504 memcpy(buf,status,21);
1505 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1506 0,aVOLID,0,!allow_long_path_components)) {
1507 reply_nterror(req, NT_STATUS_NO_MEMORY);
1508 END_PROFILE(SMBsearch);
1509 return;
1511 dptr_fill(buf+12,dptr_num);
1512 if (dptr_zero(buf+12) && (status_len==0)) {
1513 numentries = 1;
1514 } else {
1515 numentries = 0;
1517 if (message_push_blob(&req->outbuf,
1518 data_blob_const(buf, sizeof(buf)))
1519 == -1) {
1520 reply_nterror(req, NT_STATUS_NO_MEMORY);
1521 END_PROFILE(SMBsearch);
1522 return;
1524 } else {
1525 unsigned int i;
1526 maxentries = MIN(
1527 maxentries,
1528 ((BUFFER_SIZE -
1529 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1530 /DIR_STRUCT_SIZE));
1532 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1533 conn->dirpath,lp_dontdescend(SNUM(conn))));
1534 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1535 check_descend = True;
1538 for (i=numentries;(i<maxentries) && !finished;i++) {
1539 finished = !get_dir_entry(ctx,
1540 conn,
1541 mask,
1542 dirtype,
1543 &fname,
1544 &size,
1545 &mode,
1546 &date,
1547 check_descend,
1548 ask_sharemode);
1549 if (!finished) {
1550 char buf[DIR_STRUCT_SIZE];
1551 memcpy(buf,status,21);
1552 if (!make_dir_struct(ctx,
1553 buf,
1554 mask,
1555 fname,
1556 size,
1557 mode,
1558 convert_timespec_to_time_t(date),
1559 !allow_long_path_components)) {
1560 reply_nterror(req, NT_STATUS_NO_MEMORY);
1561 END_PROFILE(SMBsearch);
1562 return;
1564 if (!dptr_fill(buf+12,dptr_num)) {
1565 break;
1567 if (message_push_blob(&req->outbuf,
1568 data_blob_const(buf, sizeof(buf)))
1569 == -1) {
1570 reply_nterror(req, NT_STATUS_NO_MEMORY);
1571 END_PROFILE(SMBsearch);
1572 return;
1574 numentries++;
1579 SearchEmpty:
1581 /* If we were called as SMBffirst with smb_search_id == NULL
1582 and no entries were found then return error and close dirptr
1583 (X/Open spec) */
1585 if (numentries == 0) {
1586 dptr_close(&dptr_num);
1587 } else if(expect_close && status_len == 0) {
1588 /* Close the dptr - we know it's gone */
1589 dptr_close(&dptr_num);
1592 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1593 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1594 dptr_close(&dptr_num);
1597 if ((numentries == 0) && !mask_contains_wcard) {
1598 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1599 END_PROFILE(SMBsearch);
1600 return;
1603 SSVAL(req->outbuf,smb_vwv0,numentries);
1604 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1605 SCVAL(smb_buf(req->outbuf),0,5);
1606 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1608 /* The replies here are never long name. */
1609 SSVAL(req->outbuf, smb_flg2,
1610 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1611 if (!allow_long_path_components) {
1612 SSVAL(req->outbuf, smb_flg2,
1613 SVAL(req->outbuf, smb_flg2)
1614 & (~FLAGS2_LONG_PATH_COMPONENTS));
1617 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1618 SSVAL(req->outbuf, smb_flg2,
1619 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1621 if (!directory) {
1622 directory = dptr_path(dptr_num);
1625 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1626 smb_fn_name(req->cmd),
1627 mask,
1628 directory ? directory : "./",
1629 dirtype,
1630 numentries,
1631 maxentries ));
1633 END_PROFILE(SMBsearch);
1634 return;
1637 /****************************************************************************
1638 Reply to a fclose (stop directory search).
1639 ****************************************************************************/
1641 void reply_fclose(struct smb_request *req)
1643 int status_len;
1644 char status[21];
1645 int dptr_num= -2;
1646 const char *p;
1647 char *path = NULL;
1648 NTSTATUS err;
1649 bool path_contains_wcard = False;
1650 TALLOC_CTX *ctx = talloc_tos();
1652 START_PROFILE(SMBfclose);
1654 if (lp_posix_pathnames()) {
1655 reply_unknown_new(req, req->cmd);
1656 END_PROFILE(SMBfclose);
1657 return;
1660 p = (const char *)req->buf + 1;
1661 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1662 &err, &path_contains_wcard);
1663 if (!NT_STATUS_IS_OK(err)) {
1664 reply_nterror(req, err);
1665 END_PROFILE(SMBfclose);
1666 return;
1668 p++;
1669 status_len = SVAL(p,0);
1670 p += 2;
1672 if (status_len == 0) {
1673 reply_doserror(req, ERRSRV, ERRsrverror);
1674 END_PROFILE(SMBfclose);
1675 return;
1678 memcpy(status,p,21);
1680 if(dptr_fetch(status+12,&dptr_num)) {
1681 /* Close the dptr - we know it's gone */
1682 dptr_close(&dptr_num);
1685 reply_outbuf(req, 1, 0);
1686 SSVAL(req->outbuf,smb_vwv0,0);
1688 DEBUG(3,("search close\n"));
1690 END_PROFILE(SMBfclose);
1691 return;
1694 /****************************************************************************
1695 Reply to an open.
1696 ****************************************************************************/
1698 void reply_open(struct smb_request *req)
1700 connection_struct *conn = req->conn;
1701 char *fname = NULL;
1702 uint32 fattr=0;
1703 SMB_OFF_T size = 0;
1704 time_t mtime=0;
1705 int info;
1706 SMB_STRUCT_STAT sbuf;
1707 files_struct *fsp;
1708 int oplock_request;
1709 int deny_mode;
1710 uint32 dos_attr;
1711 uint32 access_mask;
1712 uint32 share_mode;
1713 uint32 create_disposition;
1714 uint32 create_options = 0;
1715 NTSTATUS status;
1716 TALLOC_CTX *ctx = talloc_tos();
1718 START_PROFILE(SMBopen);
1720 SET_STAT_INVALID(sbuf);
1722 if (req->wct < 2) {
1723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1724 END_PROFILE(SMBopen);
1725 return;
1728 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1729 deny_mode = SVAL(req->vwv+0, 0);
1730 dos_attr = SVAL(req->vwv+1, 0);
1732 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1733 STR_TERMINATE, &status);
1734 if (!NT_STATUS_IS_OK(status)) {
1735 reply_nterror(req, status);
1736 END_PROFILE(SMBopen);
1737 return;
1740 if (!map_open_params_to_ntcreate(
1741 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1742 &share_mode, &create_disposition, &create_options)) {
1743 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1744 END_PROFILE(SMBopen);
1745 return;
1748 status = SMB_VFS_CREATE_FILE(
1749 conn, /* conn */
1750 req, /* req */
1751 0, /* root_dir_fid */
1752 fname, /* fname */
1753 CFF_DOS_PATH, /* create_file_flags */
1754 access_mask, /* access_mask */
1755 share_mode, /* share_access */
1756 create_disposition, /* create_disposition*/
1757 create_options, /* create_options */
1758 dos_attr, /* file_attributes */
1759 oplock_request, /* oplock_request */
1760 0, /* allocation_size */
1761 NULL, /* sd */
1762 NULL, /* ea_list */
1763 &fsp, /* result */
1764 &info, /* pinfo */
1765 &sbuf); /* psbuf */
1767 if (!NT_STATUS_IS_OK(status)) {
1768 if (open_was_deferred(req->mid)) {
1769 /* We have re-scheduled this call. */
1770 END_PROFILE(SMBopen);
1771 return;
1773 reply_openerror(req, status);
1774 END_PROFILE(SMBopen);
1775 return;
1778 size = sbuf.st_ex_size;
1779 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1780 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1782 if (fattr & aDIR) {
1783 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1784 close_file(req, fsp, ERROR_CLOSE);
1785 reply_doserror(req, ERRDOS,ERRnoaccess);
1786 END_PROFILE(SMBopen);
1787 return;
1790 reply_outbuf(req, 7, 0);
1791 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1792 SSVAL(req->outbuf,smb_vwv1,fattr);
1793 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1794 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1795 } else {
1796 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1798 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1799 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1801 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1802 SCVAL(req->outbuf,smb_flg,
1803 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1806 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1807 SCVAL(req->outbuf,smb_flg,
1808 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1810 END_PROFILE(SMBopen);
1811 return;
1814 /****************************************************************************
1815 Reply to an open and X.
1816 ****************************************************************************/
1818 void reply_open_and_X(struct smb_request *req)
1820 connection_struct *conn = req->conn;
1821 char *fname = NULL;
1822 uint16 open_flags;
1823 int deny_mode;
1824 uint32 smb_attr;
1825 /* Breakout the oplock request bits so we can set the
1826 reply bits separately. */
1827 int ex_oplock_request;
1828 int core_oplock_request;
1829 int oplock_request;
1830 #if 0
1831 int smb_sattr = SVAL(req->vwv+4, 0);
1832 uint32 smb_time = make_unix_date3(req->vwv+6);
1833 #endif
1834 int smb_ofun;
1835 uint32 fattr=0;
1836 int mtime=0;
1837 SMB_STRUCT_STAT sbuf;
1838 int smb_action = 0;
1839 files_struct *fsp;
1840 NTSTATUS status;
1841 uint64_t allocation_size;
1842 ssize_t retval = -1;
1843 uint32 access_mask;
1844 uint32 share_mode;
1845 uint32 create_disposition;
1846 uint32 create_options = 0;
1847 TALLOC_CTX *ctx = talloc_tos();
1849 START_PROFILE(SMBopenX);
1851 if (req->wct < 15) {
1852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1853 END_PROFILE(SMBopenX);
1854 return;
1857 SET_STAT_INVALID(sbuf);
1859 open_flags = SVAL(req->vwv+2, 0);
1860 deny_mode = SVAL(req->vwv+3, 0);
1861 smb_attr = SVAL(req->vwv+5, 0);
1862 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1863 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1864 oplock_request = ex_oplock_request | core_oplock_request;
1865 smb_ofun = SVAL(req->vwv+8, 0);
1866 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1868 /* If it's an IPC, pass off the pipe handler. */
1869 if (IS_IPC(conn)) {
1870 if (lp_nt_pipe_support()) {
1871 reply_open_pipe_and_X(conn, req);
1872 } else {
1873 reply_doserror(req, ERRSRV, ERRaccess);
1875 END_PROFILE(SMBopenX);
1876 return;
1879 /* XXXX we need to handle passed times, sattr and flags */
1880 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1881 STR_TERMINATE, &status);
1882 if (!NT_STATUS_IS_OK(status)) {
1883 reply_nterror(req, status);
1884 END_PROFILE(SMBopenX);
1885 return;
1888 if (!map_open_params_to_ntcreate(
1889 fname, deny_mode, smb_ofun, &access_mask,
1890 &share_mode, &create_disposition, &create_options)) {
1891 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1892 END_PROFILE(SMBopenX);
1893 return;
1896 status = SMB_VFS_CREATE_FILE(
1897 conn, /* conn */
1898 req, /* req */
1899 0, /* root_dir_fid */
1900 fname, /* fname */
1901 CFF_DOS_PATH, /* create_file_flags */
1902 access_mask, /* access_mask */
1903 share_mode, /* share_access */
1904 create_disposition, /* create_disposition*/
1905 create_options, /* create_options */
1906 smb_attr, /* file_attributes */
1907 oplock_request, /* oplock_request */
1908 0, /* allocation_size */
1909 NULL, /* sd */
1910 NULL, /* ea_list */
1911 &fsp, /* result */
1912 &smb_action, /* pinfo */
1913 &sbuf); /* psbuf */
1915 if (!NT_STATUS_IS_OK(status)) {
1916 END_PROFILE(SMBopenX);
1917 if (open_was_deferred(req->mid)) {
1918 /* We have re-scheduled this call. */
1919 return;
1921 reply_openerror(req, status);
1922 return;
1925 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1926 if the file is truncated or created. */
1927 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1928 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1929 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1930 close_file(req, fsp, ERROR_CLOSE);
1931 reply_nterror(req, NT_STATUS_DISK_FULL);
1932 END_PROFILE(SMBopenX);
1933 return;
1935 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1936 if (retval < 0) {
1937 close_file(req, fsp, ERROR_CLOSE);
1938 reply_nterror(req, NT_STATUS_DISK_FULL);
1939 END_PROFILE(SMBopenX);
1940 return;
1942 sbuf.st_ex_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1945 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1946 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1947 if (fattr & aDIR) {
1948 close_file(req, fsp, ERROR_CLOSE);
1949 reply_doserror(req, ERRDOS, ERRnoaccess);
1950 END_PROFILE(SMBopenX);
1951 return;
1954 /* If the caller set the extended oplock request bit
1955 and we granted one (by whatever means) - set the
1956 correct bit for extended oplock reply.
1959 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1960 smb_action |= EXTENDED_OPLOCK_GRANTED;
1963 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1964 smb_action |= EXTENDED_OPLOCK_GRANTED;
1967 /* If the caller set the core oplock request bit
1968 and we granted one (by whatever means) - set the
1969 correct bit for core oplock reply.
1972 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1973 reply_outbuf(req, 19, 0);
1974 } else {
1975 reply_outbuf(req, 15, 0);
1978 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1979 SCVAL(req->outbuf, smb_flg,
1980 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1983 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1984 SCVAL(req->outbuf, smb_flg,
1985 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1988 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1989 SSVAL(req->outbuf,smb_vwv3,fattr);
1990 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1991 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1992 } else {
1993 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1995 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_ex_size);
1996 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1997 SSVAL(req->outbuf,smb_vwv11,smb_action);
1999 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2000 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2003 END_PROFILE(SMBopenX);
2004 chain_reply(req);
2005 return;
2008 /****************************************************************************
2009 Reply to a SMBulogoffX.
2010 ****************************************************************************/
2012 void reply_ulogoffX(struct smb_request *req)
2014 user_struct *vuser;
2016 START_PROFILE(SMBulogoffX);
2018 vuser = get_valid_user_struct(req->vuid);
2020 if(vuser == NULL) {
2021 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2022 req->vuid));
2025 /* in user level security we are supposed to close any files
2026 open by this user */
2027 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2028 file_close_user(req->vuid);
2031 invalidate_vuid(req->vuid);
2033 reply_outbuf(req, 2, 0);
2035 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2037 END_PROFILE(SMBulogoffX);
2038 chain_reply(req);
2041 /****************************************************************************
2042 Reply to a mknew or a create.
2043 ****************************************************************************/
2045 void reply_mknew(struct smb_request *req)
2047 connection_struct *conn = req->conn;
2048 char *fname = NULL;
2049 uint32 fattr = 0;
2050 struct smb_file_time ft;
2051 files_struct *fsp;
2052 int oplock_request = 0;
2053 SMB_STRUCT_STAT sbuf;
2054 NTSTATUS status;
2055 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2056 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2057 uint32 create_disposition;
2058 uint32 create_options = 0;
2059 TALLOC_CTX *ctx = talloc_tos();
2061 START_PROFILE(SMBcreate);
2062 ZERO_STRUCT(ft);
2063 SET_STAT_INVALID(sbuf);
2065 if (req->wct < 3) {
2066 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2067 END_PROFILE(SMBcreate);
2068 return;
2071 fattr = SVAL(req->vwv+0, 0);
2072 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2074 /* mtime. */
2075 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2077 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2078 STR_TERMINATE, &status);
2079 if (!NT_STATUS_IS_OK(status)) {
2080 reply_nterror(req, status);
2081 END_PROFILE(SMBcreate);
2082 return;
2085 if (fattr & aVOLID) {
2086 DEBUG(0,("Attempt to create file (%s) with volid set - "
2087 "please report this\n", fname));
2090 if(req->cmd == SMBmknew) {
2091 /* We should fail if file exists. */
2092 create_disposition = FILE_CREATE;
2093 } else {
2094 /* Create if file doesn't exist, truncate if it does. */
2095 create_disposition = FILE_OVERWRITE_IF;
2098 status = SMB_VFS_CREATE_FILE(
2099 conn, /* conn */
2100 req, /* req */
2101 0, /* root_dir_fid */
2102 fname, /* fname */
2103 CFF_DOS_PATH, /* create_file_flags */
2104 access_mask, /* access_mask */
2105 share_mode, /* share_access */
2106 create_disposition, /* create_disposition*/
2107 create_options, /* create_options */
2108 fattr, /* file_attributes */
2109 oplock_request, /* oplock_request */
2110 0, /* allocation_size */
2111 NULL, /* sd */
2112 NULL, /* ea_list */
2113 &fsp, /* result */
2114 NULL, /* pinfo */
2115 &sbuf); /* psbuf */
2117 if (!NT_STATUS_IS_OK(status)) {
2118 END_PROFILE(SMBcreate);
2119 if (open_was_deferred(req->mid)) {
2120 /* We have re-scheduled this call. */
2121 return;
2123 reply_openerror(req, status);
2124 return;
2127 ft.atime = sbuf.st_ex_atime; /* atime. */
2128 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2129 if (!NT_STATUS_IS_OK(status)) {
2130 END_PROFILE(SMBcreate);
2131 reply_openerror(req, status);
2132 return;
2135 reply_outbuf(req, 1, 0);
2136 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2138 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2139 SCVAL(req->outbuf,smb_flg,
2140 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2143 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2144 SCVAL(req->outbuf,smb_flg,
2145 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2148 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2149 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2150 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2152 END_PROFILE(SMBcreate);
2153 return;
2156 /****************************************************************************
2157 Reply to a create temporary file.
2158 ****************************************************************************/
2160 void reply_ctemp(struct smb_request *req)
2162 connection_struct *conn = req->conn;
2163 struct smb_filename *smb_fname = NULL;
2164 char *fname = NULL;
2165 uint32 fattr;
2166 files_struct *fsp;
2167 int oplock_request;
2168 int tmpfd;
2169 char *s;
2170 NTSTATUS status;
2171 TALLOC_CTX *ctx = talloc_tos();
2173 START_PROFILE(SMBctemp);
2175 if (req->wct < 3) {
2176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2177 goto out;
2180 fattr = SVAL(req->vwv+0, 0);
2181 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2183 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2184 STR_TERMINATE, &status);
2185 if (!NT_STATUS_IS_OK(status)) {
2186 reply_nterror(req, status);
2187 goto out;
2189 if (*fname) {
2190 fname = talloc_asprintf(ctx,
2191 "%s/TMXXXXXX",
2192 fname);
2193 } else {
2194 fname = talloc_strdup(ctx, "TMXXXXXX");
2197 if (!fname) {
2198 reply_nterror(req, NT_STATUS_NO_MEMORY);
2199 goto out;
2202 status = resolve_dfspath(ctx, conn,
2203 req->flags2 & FLAGS2_DFS_PATHNAMES,
2204 fname,
2205 &fname);
2206 if (!NT_STATUS_IS_OK(status)) {
2207 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2208 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2209 ERRSRV, ERRbadpath);
2210 goto out;
2212 reply_nterror(req, status);
2213 goto out;
2216 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
2217 if (!NT_STATUS_IS_OK(status)) {
2218 reply_nterror(req, status);
2219 goto out;
2222 status = get_full_smb_filename(ctx, smb_fname, &fname);
2223 if (!NT_STATUS_IS_OK(status)) {
2224 reply_nterror(req, status);
2225 goto out;
2228 status = check_name(conn, fname);
2229 if (!NT_STATUS_IS_OK(status)) {
2230 reply_nterror(req, status);
2231 goto out;
2234 tmpfd = mkstemp(fname);
2235 if (tmpfd == -1) {
2236 reply_unixerror(req, ERRDOS, ERRnoaccess);
2237 goto out;
2240 SET_STAT_INVALID(smb_fname->st);
2241 SMB_VFS_STAT(conn, fname, &smb_fname->st);
2243 /* We should fail if file does not exist. */
2244 status = SMB_VFS_CREATE_FILE(
2245 conn, /* conn */
2246 req, /* req */
2247 0, /* root_dir_fid */
2248 fname, /* fname */
2249 0, /* create_file_flags */
2250 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2251 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2252 FILE_OPEN, /* create_disposition*/
2253 0, /* create_options */
2254 fattr, /* file_attributes */
2255 oplock_request, /* oplock_request */
2256 0, /* allocation_size */
2257 NULL, /* sd */
2258 NULL, /* ea_list */
2259 &fsp, /* result */
2260 NULL, /* pinfo */
2261 &smb_fname->st); /* psbuf */
2263 /* close fd from mkstemp() */
2264 close(tmpfd);
2266 if (!NT_STATUS_IS_OK(status)) {
2267 if (open_was_deferred(req->mid)) {
2268 /* We have re-scheduled this call. */
2269 goto out;
2271 reply_openerror(req, status);
2272 goto out;
2275 reply_outbuf(req, 1, 0);
2276 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2278 /* the returned filename is relative to the directory */
2279 s = strrchr_m(fsp->fsp_name, '/');
2280 if (!s) {
2281 s = fsp->fsp_name;
2282 } else {
2283 s++;
2286 #if 0
2287 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2288 thing in the byte section. JRA */
2289 SSVALS(p, 0, -1); /* what is this? not in spec */
2290 #endif
2291 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2292 == -1) {
2293 reply_nterror(req, NT_STATUS_NO_MEMORY);
2294 goto out;
2297 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2298 SCVAL(req->outbuf, smb_flg,
2299 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2302 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2303 SCVAL(req->outbuf, smb_flg,
2304 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2307 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2308 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2309 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2310 out:
2311 TALLOC_FREE(smb_fname);
2312 END_PROFILE(SMBctemp);
2313 return;
2316 /*******************************************************************
2317 Check if a user is allowed to rename a file.
2318 ********************************************************************/
2320 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2321 uint16 dirtype, SMB_STRUCT_STAT *pst)
2323 uint32 fmode;
2325 if (!CAN_WRITE(conn)) {
2326 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2329 fmode = dos_mode(conn, fsp->fsp_name, pst);
2330 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2331 return NT_STATUS_NO_SUCH_FILE;
2334 if (S_ISDIR(pst->st_ex_mode)) {
2335 if (fsp->posix_open) {
2336 return NT_STATUS_OK;
2339 /* If no pathnames are open below this
2340 directory, allow the rename. */
2342 if (file_find_subpath(fsp)) {
2343 return NT_STATUS_ACCESS_DENIED;
2345 return NT_STATUS_OK;
2348 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2349 return NT_STATUS_OK;
2352 return NT_STATUS_ACCESS_DENIED;
2355 /*******************************************************************
2356 * unlink a file with all relevant access checks
2357 *******************************************************************/
2359 static NTSTATUS do_unlink(connection_struct *conn,
2360 struct smb_request *req,
2361 const char *fname,
2362 uint32 dirtype)
2364 SMB_STRUCT_STAT sbuf;
2365 uint32 fattr;
2366 files_struct *fsp;
2367 uint32 dirtype_orig = dirtype;
2368 NTSTATUS status;
2370 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2372 if (!CAN_WRITE(conn)) {
2373 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2376 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2377 return map_nt_error_from_unix(errno);
2380 fattr = dos_mode(conn,fname,&sbuf);
2382 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2383 dirtype = aDIR|aARCH|aRONLY;
2386 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2387 if (!dirtype) {
2388 return NT_STATUS_NO_SUCH_FILE;
2391 if (!dir_check_ftype(conn, fattr, dirtype)) {
2392 if (fattr & aDIR) {
2393 return NT_STATUS_FILE_IS_A_DIRECTORY;
2395 return NT_STATUS_NO_SUCH_FILE;
2398 if (dirtype_orig & 0x8000) {
2399 /* These will never be set for POSIX. */
2400 return NT_STATUS_NO_SUCH_FILE;
2403 #if 0
2404 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2405 return NT_STATUS_FILE_IS_A_DIRECTORY;
2408 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2409 return NT_STATUS_NO_SUCH_FILE;
2412 if (dirtype & 0xFF00) {
2413 /* These will never be set for POSIX. */
2414 return NT_STATUS_NO_SUCH_FILE;
2417 dirtype &= 0xFF;
2418 if (!dirtype) {
2419 return NT_STATUS_NO_SUCH_FILE;
2422 /* Can't delete a directory. */
2423 if (fattr & aDIR) {
2424 return NT_STATUS_FILE_IS_A_DIRECTORY;
2426 #endif
2428 #if 0 /* JRATEST */
2429 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2430 return NT_STATUS_OBJECT_NAME_INVALID;
2431 #endif /* JRATEST */
2433 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2435 On a Windows share, a file with read-only dosmode can be opened with
2436 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2437 fails with NT_STATUS_CANNOT_DELETE error.
2439 This semantic causes a problem that a user can not
2440 rename a file with read-only dosmode on a Samba share
2441 from a Windows command prompt (i.e. cmd.exe, but can rename
2442 from Windows Explorer).
2445 if (!lp_delete_readonly(SNUM(conn))) {
2446 if (fattr & aRONLY) {
2447 return NT_STATUS_CANNOT_DELETE;
2451 /* On open checks the open itself will check the share mode, so
2452 don't do it here as we'll get it wrong. */
2454 status = SMB_VFS_CREATE_FILE
2455 (conn, /* conn */
2456 req, /* req */
2457 0, /* root_dir_fid */
2458 fname, /* fname */
2459 0, /* create_file_flags */
2460 DELETE_ACCESS, /* access_mask */
2461 FILE_SHARE_NONE, /* share_access */
2462 FILE_OPEN, /* create_disposition*/
2463 FILE_NON_DIRECTORY_FILE, /* create_options */
2464 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2465 0, /* oplock_request */
2466 0, /* allocation_size */
2467 NULL, /* sd */
2468 NULL, /* ea_list */
2469 &fsp, /* result */
2470 NULL, /* pinfo */
2471 &sbuf); /* psbuf */
2473 if (!NT_STATUS_IS_OK(status)) {
2474 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2475 nt_errstr(status)));
2476 return status;
2479 /* The set is across all open files on this dev/inode pair. */
2480 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2481 close_file(req, fsp, NORMAL_CLOSE);
2482 return NT_STATUS_ACCESS_DENIED;
2485 return close_file(req, fsp, NORMAL_CLOSE);
2488 /****************************************************************************
2489 The guts of the unlink command, split out so it may be called by the NT SMB
2490 code.
2491 ****************************************************************************/
2493 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2494 uint32 dirtype, const char *name_in, bool has_wild)
2496 struct smb_filename *smb_fname = NULL;
2497 const char *directory = NULL;
2498 char *mask = NULL;
2499 char *name = NULL;
2500 char *p = NULL;
2501 int count=0;
2502 NTSTATUS status = NT_STATUS_OK;
2503 SMB_STRUCT_STAT st;
2504 TALLOC_CTX *ctx = talloc_tos();
2506 status = unix_convert(ctx, conn, name_in, &smb_fname,
2507 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2508 if (!NT_STATUS_IS_OK(status)) {
2509 return status;
2512 status = get_full_smb_filename(ctx, smb_fname, &name);
2513 if (!NT_STATUS_IS_OK(status)) {
2514 TALLOC_FREE(smb_fname);
2515 return status;
2518 p = strrchr_m(name,'/');
2519 if (!p) {
2520 directory = talloc_strdup(ctx, ".");
2521 if (!directory) {
2522 TALLOC_FREE(smb_fname);
2523 return NT_STATUS_NO_MEMORY;
2525 mask = name;
2526 } else {
2527 *p = 0;
2528 directory = name;
2529 mask = p+1;
2533 * We should only check the mangled cache
2534 * here if unix_convert failed. This means
2535 * that the path in 'mask' doesn't exist
2536 * on the file system and so we need to look
2537 * for a possible mangle. This patch from
2538 * Tine Smukavec <valentin.smukavec@hermes.si>.
2541 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask,conn->params)) {
2542 char *new_mask = NULL;
2543 mangle_lookup_name_from_8_3(ctx,
2544 mask,
2545 &new_mask,
2546 conn->params );
2547 if (new_mask) {
2548 mask = new_mask;
2551 TALLOC_FREE(smb_fname);
2553 if (!has_wild) {
2554 directory = talloc_asprintf(ctx,
2555 "%s/%s",
2556 directory,
2557 mask);
2558 if (!directory) {
2559 return NT_STATUS_NO_MEMORY;
2561 if (dirtype == 0) {
2562 dirtype = FILE_ATTRIBUTE_NORMAL;
2565 status = check_name(conn, directory);
2566 if (!NT_STATUS_IS_OK(status)) {
2567 return status;
2570 status = do_unlink(conn, req, directory, dirtype);
2571 if (!NT_STATUS_IS_OK(status)) {
2572 return status;
2575 count++;
2576 } else {
2577 struct smb_Dir *dir_hnd = NULL;
2578 long offset = 0;
2579 const char *dname;
2581 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2582 return NT_STATUS_OBJECT_NAME_INVALID;
2585 if (strequal(mask,"????????.???")) {
2586 mask[0] = '*';
2587 mask[1] = '\0';
2590 status = check_name(conn, directory);
2591 if (!NT_STATUS_IS_OK(status)) {
2592 return status;
2595 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2596 dirtype);
2597 if (dir_hnd == NULL) {
2598 return map_nt_error_from_unix(errno);
2601 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2602 the pattern matches against the long name, otherwise the short name
2603 We don't implement this yet XXXX
2606 status = NT_STATUS_NO_SUCH_FILE;
2608 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2609 char *fname = NULL;
2611 if (!is_visible_file(conn, directory, dname, &st,
2612 true))
2614 continue;
2617 /* Quick check for "." and ".." */
2618 if (ISDOT(dname) || ISDOTDOT(dname)) {
2619 continue;
2622 if(!mask_match(dname, mask, conn->case_sensitive)) {
2623 continue;
2626 fname = talloc_asprintf(ctx, "%s/%s",
2627 directory,
2628 dname);
2629 if (!fname) {
2630 return NT_STATUS_NO_MEMORY;
2633 status = check_name(conn, fname);
2634 if (!NT_STATUS_IS_OK(status)) {
2635 TALLOC_FREE(dir_hnd);
2636 return status;
2639 status = do_unlink(conn, req, fname, dirtype);
2640 if (!NT_STATUS_IS_OK(status)) {
2641 TALLOC_FREE(fname);
2642 continue;
2645 count++;
2646 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2647 fname));
2649 TALLOC_FREE(fname);
2651 TALLOC_FREE(dir_hnd);
2654 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2655 status = map_nt_error_from_unix(errno);
2658 return status;
2661 /****************************************************************************
2662 Reply to a unlink
2663 ****************************************************************************/
2665 void reply_unlink(struct smb_request *req)
2667 connection_struct *conn = req->conn;
2668 char *name = NULL;
2669 uint32 dirtype;
2670 NTSTATUS status;
2671 bool path_contains_wcard = False;
2672 TALLOC_CTX *ctx = talloc_tos();
2674 START_PROFILE(SMBunlink);
2676 if (req->wct < 1) {
2677 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2678 END_PROFILE(SMBunlink);
2679 return;
2682 dirtype = SVAL(req->vwv+0, 0);
2684 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2685 STR_TERMINATE, &status,
2686 &path_contains_wcard);
2687 if (!NT_STATUS_IS_OK(status)) {
2688 reply_nterror(req, status);
2689 END_PROFILE(SMBunlink);
2690 return;
2693 status = resolve_dfspath_wcard(ctx, conn,
2694 req->flags2 & FLAGS2_DFS_PATHNAMES,
2695 name,
2696 &name,
2697 &path_contains_wcard);
2698 if (!NT_STATUS_IS_OK(status)) {
2699 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2700 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2701 ERRSRV, ERRbadpath);
2702 END_PROFILE(SMBunlink);
2703 return;
2705 reply_nterror(req, status);
2706 END_PROFILE(SMBunlink);
2707 return;
2710 DEBUG(3,("reply_unlink : %s\n",name));
2712 status = unlink_internals(conn, req, dirtype, name,
2713 path_contains_wcard);
2714 if (!NT_STATUS_IS_OK(status)) {
2715 if (open_was_deferred(req->mid)) {
2716 /* We have re-scheduled this call. */
2717 END_PROFILE(SMBunlink);
2718 return;
2720 reply_nterror(req, status);
2721 END_PROFILE(SMBunlink);
2722 return;
2725 reply_outbuf(req, 0, 0);
2726 END_PROFILE(SMBunlink);
2728 return;
2731 /****************************************************************************
2732 Fail for readbraw.
2733 ****************************************************************************/
2735 static void fail_readraw(void)
2737 const char *errstr = talloc_asprintf(talloc_tos(),
2738 "FAIL ! reply_readbraw: socket write fail (%s)",
2739 strerror(errno));
2740 if (!errstr) {
2741 errstr = "";
2743 exit_server_cleanly(errstr);
2746 /****************************************************************************
2747 Fake (read/write) sendfile. Returns -1 on read or write fail.
2748 ****************************************************************************/
2750 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2751 size_t nread)
2753 size_t bufsize;
2754 size_t tosend = nread;
2755 char *buf;
2757 if (nread == 0) {
2758 return 0;
2761 bufsize = MIN(nread, 65536);
2763 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2764 return -1;
2767 while (tosend > 0) {
2768 ssize_t ret;
2769 size_t cur_read;
2771 if (tosend > bufsize) {
2772 cur_read = bufsize;
2773 } else {
2774 cur_read = tosend;
2776 ret = read_file(fsp,buf,startpos,cur_read);
2777 if (ret == -1) {
2778 SAFE_FREE(buf);
2779 return -1;
2782 /* If we had a short read, fill with zeros. */
2783 if (ret < cur_read) {
2784 memset(buf + ret, '\0', cur_read - ret);
2787 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2788 SAFE_FREE(buf);
2789 return -1;
2791 tosend -= cur_read;
2792 startpos += cur_read;
2795 SAFE_FREE(buf);
2796 return (ssize_t)nread;
2799 #if defined(WITH_SENDFILE)
2800 /****************************************************************************
2801 Deal with the case of sendfile reading less bytes from the file than
2802 requested. Fill with zeros (all we can do).
2803 ****************************************************************************/
2805 static void sendfile_short_send(files_struct *fsp,
2806 ssize_t nread,
2807 size_t headersize,
2808 size_t smb_maxcnt)
2810 #define SHORT_SEND_BUFSIZE 1024
2811 if (nread < headersize) {
2812 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2813 "header for file %s (%s). Terminating\n",
2814 fsp->fsp_name, strerror(errno) ));
2815 exit_server_cleanly("sendfile_short_send failed");
2818 nread -= headersize;
2820 if (nread < smb_maxcnt) {
2821 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2822 if (!buf) {
2823 exit_server_cleanly("sendfile_short_send: "
2824 "malloc failed");
2827 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2828 "with zeros !\n", fsp->fsp_name));
2830 while (nread < smb_maxcnt) {
2832 * We asked for the real file size and told sendfile
2833 * to not go beyond the end of the file. But it can
2834 * happen that in between our fstat call and the
2835 * sendfile call the file was truncated. This is very
2836 * bad because we have already announced the larger
2837 * number of bytes to the client.
2839 * The best we can do now is to send 0-bytes, just as
2840 * a read from a hole in a sparse file would do.
2842 * This should happen rarely enough that I don't care
2843 * about efficiency here :-)
2845 size_t to_write;
2847 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2848 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2849 exit_server_cleanly("sendfile_short_send: "
2850 "write_data failed");
2852 nread += to_write;
2854 SAFE_FREE(buf);
2857 #endif /* defined WITH_SENDFILE */
2859 /****************************************************************************
2860 Return a readbraw error (4 bytes of zero).
2861 ****************************************************************************/
2863 static void reply_readbraw_error(void)
2865 char header[4];
2866 SIVAL(header,0,0);
2867 if (write_data(smbd_server_fd(),header,4) != 4) {
2868 fail_readraw();
2872 /****************************************************************************
2873 Use sendfile in readbraw.
2874 ****************************************************************************/
2876 static void send_file_readbraw(connection_struct *conn,
2877 struct smb_request *req,
2878 files_struct *fsp,
2879 SMB_OFF_T startpos,
2880 size_t nread,
2881 ssize_t mincount)
2883 char *outbuf = NULL;
2884 ssize_t ret=0;
2886 #if defined(WITH_SENDFILE)
2888 * We can only use sendfile on a non-chained packet
2889 * but we can use on a non-oplocked file. tridge proved this
2890 * on a train in Germany :-). JRA.
2891 * reply_readbraw has already checked the length.
2894 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2895 (fsp->wcp == NULL) &&
2896 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2897 ssize_t sendfile_read = -1;
2898 char header[4];
2899 DATA_BLOB header_blob;
2901 _smb_setlen(header,nread);
2902 header_blob = data_blob_const(header, 4);
2904 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2905 &header_blob, startpos, nread)) == -1) {
2906 /* Returning ENOSYS means no data at all was sent.
2907 * Do this as a normal read. */
2908 if (errno == ENOSYS) {
2909 goto normal_readbraw;
2913 * Special hack for broken Linux with no working sendfile. If we
2914 * return EINTR we sent the header but not the rest of the data.
2915 * Fake this up by doing read/write calls.
2917 if (errno == EINTR) {
2918 /* Ensure we don't do this again. */
2919 set_use_sendfile(SNUM(conn), False);
2920 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2922 if (fake_sendfile(fsp, startpos, nread) == -1) {
2923 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2924 fsp->fsp_name, strerror(errno) ));
2925 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2927 return;
2930 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2931 fsp->fsp_name, strerror(errno) ));
2932 exit_server_cleanly("send_file_readbraw sendfile failed");
2933 } else if (sendfile_read == 0) {
2935 * Some sendfile implementations return 0 to indicate
2936 * that there was a short read, but nothing was
2937 * actually written to the socket. In this case,
2938 * fallback to the normal read path so the header gets
2939 * the correct byte count.
2941 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2942 "bytes falling back to the normal read: "
2943 "%s\n", fsp->fsp_name));
2944 goto normal_readbraw;
2947 /* Deal with possible short send. */
2948 if (sendfile_read != 4+nread) {
2949 sendfile_short_send(fsp, sendfile_read, 4, nread);
2951 return;
2954 normal_readbraw:
2955 #endif
2957 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2958 if (!outbuf) {
2959 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2960 (unsigned)(nread+4)));
2961 reply_readbraw_error();
2962 return;
2965 if (nread > 0) {
2966 ret = read_file(fsp,outbuf+4,startpos,nread);
2967 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2968 if (ret < mincount)
2969 ret = 0;
2970 #else
2971 if (ret < nread)
2972 ret = 0;
2973 #endif
2976 _smb_setlen(outbuf,ret);
2977 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2978 fail_readraw();
2980 TALLOC_FREE(outbuf);
2983 /****************************************************************************
2984 Reply to a readbraw (core+ protocol).
2985 ****************************************************************************/
2987 void reply_readbraw(struct smb_request *req)
2989 connection_struct *conn = req->conn;
2990 ssize_t maxcount,mincount;
2991 size_t nread = 0;
2992 SMB_OFF_T startpos;
2993 files_struct *fsp;
2994 struct lock_struct lock;
2995 SMB_STRUCT_STAT st;
2996 SMB_OFF_T size = 0;
2998 START_PROFILE(SMBreadbraw);
3000 if (srv_is_signing_active(smbd_server_conn) ||
3001 is_encrypted_packet(req->inbuf)) {
3002 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3003 "raw reads/writes are disallowed.");
3006 if (req->wct < 8) {
3007 reply_readbraw_error();
3008 END_PROFILE(SMBreadbraw);
3009 return;
3013 * Special check if an oplock break has been issued
3014 * and the readraw request croses on the wire, we must
3015 * return a zero length response here.
3018 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3021 * We have to do a check_fsp by hand here, as
3022 * we must always return 4 zero bytes on error,
3023 * not a NTSTATUS.
3026 if (!fsp || !conn || conn != fsp->conn ||
3027 req->vuid != fsp->vuid ||
3028 fsp->is_directory || fsp->fh->fd == -1) {
3030 * fsp could be NULL here so use the value from the packet. JRA.
3032 DEBUG(3,("reply_readbraw: fnum %d not valid "
3033 "- cache prime?\n",
3034 (int)SVAL(req->vwv+0, 0)));
3035 reply_readbraw_error();
3036 END_PROFILE(SMBreadbraw);
3037 return;
3040 /* Do a "by hand" version of CHECK_READ. */
3041 if (!(fsp->can_read ||
3042 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3043 (fsp->access_mask & FILE_EXECUTE)))) {
3044 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3045 (int)SVAL(req->vwv+0, 0)));
3046 reply_readbraw_error();
3047 END_PROFILE(SMBreadbraw);
3048 return;
3051 flush_write_cache(fsp, READRAW_FLUSH);
3053 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3054 if(req->wct == 10) {
3056 * This is a large offset (64 bit) read.
3058 #ifdef LARGE_SMB_OFF_T
3060 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3062 #else /* !LARGE_SMB_OFF_T */
3065 * Ensure we haven't been sent a >32 bit offset.
3068 if(IVAL(req->vwv+8, 0) != 0) {
3069 DEBUG(0,("reply_readbraw: large offset "
3070 "(%x << 32) used and we don't support "
3071 "64 bit offsets.\n",
3072 (unsigned int)IVAL(req->vwv+8, 0) ));
3073 reply_readbraw_error();
3074 END_PROFILE(SMBreadbraw);
3075 return;
3078 #endif /* LARGE_SMB_OFF_T */
3080 if(startpos < 0) {
3081 DEBUG(0,("reply_readbraw: negative 64 bit "
3082 "readraw offset (%.0f) !\n",
3083 (double)startpos ));
3084 reply_readbraw_error();
3085 END_PROFILE(SMBreadbraw);
3086 return;
3090 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3091 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3093 /* ensure we don't overrun the packet size */
3094 maxcount = MIN(65535,maxcount);
3096 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3097 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3098 &lock);
3100 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3101 reply_readbraw_error();
3102 END_PROFILE(SMBreadbraw);
3103 return;
3106 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3107 size = st.st_ex_size;
3110 if (startpos >= size) {
3111 nread = 0;
3112 } else {
3113 nread = MIN(maxcount,(size - startpos));
3116 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3117 if (nread < mincount)
3118 nread = 0;
3119 #endif
3121 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3122 "min=%lu nread=%lu\n",
3123 fsp->fnum, (double)startpos,
3124 (unsigned long)maxcount,
3125 (unsigned long)mincount,
3126 (unsigned long)nread ) );
3128 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3130 DEBUG(5,("reply_readbraw finished\n"));
3132 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3134 END_PROFILE(SMBreadbraw);
3135 return;
3138 #undef DBGC_CLASS
3139 #define DBGC_CLASS DBGC_LOCKING
3141 /****************************************************************************
3142 Reply to a lockread (core+ protocol).
3143 ****************************************************************************/
3145 void reply_lockread(struct smb_request *req)
3147 connection_struct *conn = req->conn;
3148 ssize_t nread = -1;
3149 char *data;
3150 SMB_OFF_T startpos;
3151 size_t numtoread;
3152 NTSTATUS status;
3153 files_struct *fsp;
3154 struct byte_range_lock *br_lck = NULL;
3155 char *p = NULL;
3157 START_PROFILE(SMBlockread);
3159 if (req->wct < 5) {
3160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3161 END_PROFILE(SMBlockread);
3162 return;
3165 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3167 if (!check_fsp(conn, req, fsp)) {
3168 END_PROFILE(SMBlockread);
3169 return;
3172 if (!CHECK_READ(fsp,req)) {
3173 reply_doserror(req, ERRDOS, ERRbadaccess);
3174 END_PROFILE(SMBlockread);
3175 return;
3178 numtoread = SVAL(req->vwv+1, 0);
3179 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3181 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3183 reply_outbuf(req, 5, numtoread + 3);
3185 data = smb_buf(req->outbuf) + 3;
3188 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3189 * protocol request that predates the read/write lock concept.
3190 * Thus instead of asking for a read lock here we need to ask
3191 * for a write lock. JRA.
3192 * Note that the requested lock size is unaffected by max_recv.
3195 br_lck = do_lock(smbd_messaging_context(),
3196 fsp,
3197 req->smbpid,
3198 (uint64_t)numtoread,
3199 (uint64_t)startpos,
3200 WRITE_LOCK,
3201 WINDOWS_LOCK,
3202 False, /* Non-blocking lock. */
3203 &status,
3204 NULL,
3205 NULL);
3206 TALLOC_FREE(br_lck);
3208 if (NT_STATUS_V(status)) {
3209 reply_nterror(req, status);
3210 END_PROFILE(SMBlockread);
3211 return;
3215 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3218 if (numtoread > max_recv) {
3219 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3220 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3221 (unsigned int)numtoread, (unsigned int)max_recv ));
3222 numtoread = MIN(numtoread,max_recv);
3224 nread = read_file(fsp,data,startpos,numtoread);
3226 if (nread < 0) {
3227 reply_unixerror(req, ERRDOS, ERRnoaccess);
3228 END_PROFILE(SMBlockread);
3229 return;
3232 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3234 SSVAL(req->outbuf,smb_vwv0,nread);
3235 SSVAL(req->outbuf,smb_vwv5,nread+3);
3236 p = smb_buf(req->outbuf);
3237 SCVAL(p,0,0); /* pad byte. */
3238 SSVAL(p,1,nread);
3240 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3241 fsp->fnum, (int)numtoread, (int)nread));
3243 END_PROFILE(SMBlockread);
3244 return;
3247 #undef DBGC_CLASS
3248 #define DBGC_CLASS DBGC_ALL
3250 /****************************************************************************
3251 Reply to a read.
3252 ****************************************************************************/
3254 void reply_read(struct smb_request *req)
3256 connection_struct *conn = req->conn;
3257 size_t numtoread;
3258 ssize_t nread = 0;
3259 char *data;
3260 SMB_OFF_T startpos;
3261 int outsize = 0;
3262 files_struct *fsp;
3263 struct lock_struct lock;
3265 START_PROFILE(SMBread);
3267 if (req->wct < 3) {
3268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3269 END_PROFILE(SMBread);
3270 return;
3273 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3275 if (!check_fsp(conn, req, fsp)) {
3276 END_PROFILE(SMBread);
3277 return;
3280 if (!CHECK_READ(fsp,req)) {
3281 reply_doserror(req, ERRDOS, ERRbadaccess);
3282 END_PROFILE(SMBread);
3283 return;
3286 numtoread = SVAL(req->vwv+1, 0);
3287 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3289 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3292 * The requested read size cannot be greater than max_recv. JRA.
3294 if (numtoread > max_recv) {
3295 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3296 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3297 (unsigned int)numtoread, (unsigned int)max_recv ));
3298 numtoread = MIN(numtoread,max_recv);
3301 reply_outbuf(req, 5, numtoread+3);
3303 data = smb_buf(req->outbuf) + 3;
3305 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3306 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3307 &lock);
3309 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3310 reply_doserror(req, ERRDOS,ERRlock);
3311 END_PROFILE(SMBread);
3312 return;
3315 if (numtoread > 0)
3316 nread = read_file(fsp,data,startpos,numtoread);
3318 if (nread < 0) {
3319 reply_unixerror(req, ERRDOS,ERRnoaccess);
3320 goto strict_unlock;
3323 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3325 SSVAL(req->outbuf,smb_vwv0,nread);
3326 SSVAL(req->outbuf,smb_vwv5,nread+3);
3327 SCVAL(smb_buf(req->outbuf),0,1);
3328 SSVAL(smb_buf(req->outbuf),1,nread);
3330 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3331 fsp->fnum, (int)numtoread, (int)nread ) );
3333 strict_unlock:
3334 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3336 END_PROFILE(SMBread);
3337 return;
3340 /****************************************************************************
3341 Setup readX header.
3342 ****************************************************************************/
3344 static int setup_readX_header(struct smb_request *req, char *outbuf,
3345 size_t smb_maxcnt)
3347 int outsize;
3348 char *data;
3350 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3351 data = smb_buf(outbuf);
3353 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3355 SCVAL(outbuf,smb_vwv0,0xFF);
3356 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3357 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3358 SSVAL(outbuf,smb_vwv6,
3359 req_wct_ofs(req)
3360 + 1 /* the wct field */
3361 + 12 * sizeof(uint16_t) /* vwv */
3362 + 2); /* the buflen field */
3363 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3364 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3365 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3366 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3367 return outsize;
3370 /****************************************************************************
3371 Reply to a read and X - possibly using sendfile.
3372 ****************************************************************************/
3374 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3375 files_struct *fsp, SMB_OFF_T startpos,
3376 size_t smb_maxcnt)
3378 SMB_STRUCT_STAT sbuf;
3379 ssize_t nread = -1;
3380 struct lock_struct lock;
3382 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3383 reply_unixerror(req, ERRDOS, ERRnoaccess);
3384 return;
3387 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3388 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3389 &lock);
3391 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3392 reply_doserror(req, ERRDOS, ERRlock);
3393 return;
3396 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3397 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3399 * We already know that we would do a short read, so don't
3400 * try the sendfile() path.
3402 goto nosendfile_read;
3405 #if defined(WITH_SENDFILE)
3407 * We can only use sendfile on a non-chained packet
3408 * but we can use on a non-oplocked file. tridge proved this
3409 * on a train in Germany :-). JRA.
3412 if (!req_is_in_chain(req) &&
3413 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3414 (fsp->wcp == NULL) &&
3415 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3416 uint8 headerbuf[smb_size + 12 * 2];
3417 DATA_BLOB header;
3420 * Set up the packet header before send. We
3421 * assume here the sendfile will work (get the
3422 * correct amount of data).
3425 header = data_blob_const(headerbuf, sizeof(headerbuf));
3427 construct_reply_common_req(req, (char *)headerbuf);
3428 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3430 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3431 /* Returning ENOSYS means no data at all was sent.
3432 Do this as a normal read. */
3433 if (errno == ENOSYS) {
3434 goto normal_read;
3438 * Special hack for broken Linux with no working sendfile. If we
3439 * return EINTR we sent the header but not the rest of the data.
3440 * Fake this up by doing read/write calls.
3443 if (errno == EINTR) {
3444 /* Ensure we don't do this again. */
3445 set_use_sendfile(SNUM(conn), False);
3446 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3447 nread = fake_sendfile(fsp, startpos,
3448 smb_maxcnt);
3449 if (nread == -1) {
3450 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3451 fsp->fsp_name, strerror(errno) ));
3452 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3454 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3455 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3456 /* No outbuf here means successful sendfile. */
3457 goto strict_unlock;
3460 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3461 fsp->fsp_name, strerror(errno) ));
3462 exit_server_cleanly("send_file_readX sendfile failed");
3463 } else if (nread == 0) {
3465 * Some sendfile implementations return 0 to indicate
3466 * that there was a short read, but nothing was
3467 * actually written to the socket. In this case,
3468 * fallback to the normal read path so the header gets
3469 * the correct byte count.
3471 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3472 "falling back to the normal read: %s\n",
3473 fsp->fsp_name));
3474 goto normal_read;
3477 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3478 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3480 /* Deal with possible short send. */
3481 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3482 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3484 /* No outbuf here means successful sendfile. */
3485 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3486 SMB_PERFCOUNT_END(&req->pcd);
3487 goto strict_unlock;
3490 normal_read:
3492 #endif
3494 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3495 uint8 headerbuf[smb_size + 2*12];
3497 construct_reply_common_req(req, (char *)headerbuf);
3498 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3500 /* Send out the header. */
3501 if (write_data(smbd_server_fd(), (char *)headerbuf,
3502 sizeof(headerbuf)) != sizeof(headerbuf)) {
3503 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3504 fsp->fsp_name, strerror(errno) ));
3505 exit_server_cleanly("send_file_readX sendfile failed");
3507 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3508 if (nread == -1) {
3509 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3510 fsp->fsp_name, strerror(errno) ));
3511 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3513 goto strict_unlock;
3516 nosendfile_read:
3518 reply_outbuf(req, 12, smb_maxcnt);
3520 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3522 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3524 if (nread < 0) {
3525 reply_unixerror(req, ERRDOS, ERRnoaccess);
3526 return;
3529 setup_readX_header(req, (char *)req->outbuf, nread);
3531 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3532 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3534 chain_reply(req);
3535 return;
3537 strict_unlock:
3538 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3539 TALLOC_FREE(req->outbuf);
3540 return;
3543 /****************************************************************************
3544 Reply to a read and X.
3545 ****************************************************************************/
3547 void reply_read_and_X(struct smb_request *req)
3549 connection_struct *conn = req->conn;
3550 files_struct *fsp;
3551 SMB_OFF_T startpos;
3552 size_t smb_maxcnt;
3553 bool big_readX = False;
3554 #if 0
3555 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3556 #endif
3558 START_PROFILE(SMBreadX);
3560 if ((req->wct != 10) && (req->wct != 12)) {
3561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3562 return;
3565 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3566 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3567 smb_maxcnt = SVAL(req->vwv+5, 0);
3569 /* If it's an IPC, pass off the pipe handler. */
3570 if (IS_IPC(conn)) {
3571 reply_pipe_read_and_X(req);
3572 END_PROFILE(SMBreadX);
3573 return;
3576 if (!check_fsp(conn, req, fsp)) {
3577 END_PROFILE(SMBreadX);
3578 return;
3581 if (!CHECK_READ(fsp,req)) {
3582 reply_doserror(req, ERRDOS,ERRbadaccess);
3583 END_PROFILE(SMBreadX);
3584 return;
3587 if (global_client_caps & CAP_LARGE_READX) {
3588 size_t upper_size = SVAL(req->vwv+7, 0);
3589 smb_maxcnt |= (upper_size<<16);
3590 if (upper_size > 1) {
3591 /* Can't do this on a chained packet. */
3592 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3593 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3594 END_PROFILE(SMBreadX);
3595 return;
3597 /* We currently don't do this on signed or sealed data. */
3598 if (srv_is_signing_active(smbd_server_conn) ||
3599 is_encrypted_packet(req->inbuf)) {
3600 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3601 END_PROFILE(SMBreadX);
3602 return;
3604 /* Is there room in the reply for this data ? */
3605 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3606 reply_nterror(req,
3607 NT_STATUS_INVALID_PARAMETER);
3608 END_PROFILE(SMBreadX);
3609 return;
3611 big_readX = True;
3615 if (req->wct == 12) {
3616 #ifdef LARGE_SMB_OFF_T
3618 * This is a large offset (64 bit) read.
3620 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3622 #else /* !LARGE_SMB_OFF_T */
3625 * Ensure we haven't been sent a >32 bit offset.
3628 if(IVAL(req->vwv+10, 0) != 0) {
3629 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3630 "used and we don't support 64 bit offsets.\n",
3631 (unsigned int)IVAL(req->vwv+10, 0) ));
3632 END_PROFILE(SMBreadX);
3633 reply_doserror(req, ERRDOS, ERRbadaccess);
3634 return;
3637 #endif /* LARGE_SMB_OFF_T */
3641 if (!big_readX &&
3642 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3643 goto out;
3646 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3648 out:
3649 END_PROFILE(SMBreadX);
3650 return;
3653 /****************************************************************************
3654 Error replies to writebraw must have smb_wct == 1. Fix this up.
3655 ****************************************************************************/
3657 void error_to_writebrawerr(struct smb_request *req)
3659 uint8 *old_outbuf = req->outbuf;
3661 reply_outbuf(req, 1, 0);
3663 memcpy(req->outbuf, old_outbuf, smb_size);
3664 TALLOC_FREE(old_outbuf);
3667 /****************************************************************************
3668 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3669 ****************************************************************************/
3671 void reply_writebraw(struct smb_request *req)
3673 connection_struct *conn = req->conn;
3674 char *buf = NULL;
3675 ssize_t nwritten=0;
3676 ssize_t total_written=0;
3677 size_t numtowrite=0;
3678 size_t tcount;
3679 SMB_OFF_T startpos;
3680 char *data=NULL;
3681 bool write_through;
3682 files_struct *fsp;
3683 struct lock_struct lock;
3684 NTSTATUS status;
3686 START_PROFILE(SMBwritebraw);
3689 * If we ever reply with an error, it must have the SMB command
3690 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3691 * we're finished.
3693 SCVAL(req->inbuf,smb_com,SMBwritec);
3695 if (srv_is_signing_active(smbd_server_conn)) {
3696 END_PROFILE(SMBwritebraw);
3697 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3698 "raw reads/writes are disallowed.");
3701 if (req->wct < 12) {
3702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3703 error_to_writebrawerr(req);
3704 END_PROFILE(SMBwritebraw);
3705 return;
3708 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3709 if (!check_fsp(conn, req, fsp)) {
3710 error_to_writebrawerr(req);
3711 END_PROFILE(SMBwritebraw);
3712 return;
3715 if (!CHECK_WRITE(fsp)) {
3716 reply_doserror(req, ERRDOS, ERRbadaccess);
3717 error_to_writebrawerr(req);
3718 END_PROFILE(SMBwritebraw);
3719 return;
3722 tcount = IVAL(req->vwv+1, 0);
3723 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3724 write_through = BITSETW(req->vwv+7,0);
3726 /* We have to deal with slightly different formats depending
3727 on whether we are using the core+ or lanman1.0 protocol */
3729 if(Protocol <= PROTOCOL_COREPLUS) {
3730 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3731 data = smb_buf(req->inbuf);
3732 } else {
3733 numtowrite = SVAL(req->vwv+10, 0);
3734 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3737 /* Ensure we don't write bytes past the end of this packet. */
3738 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3740 error_to_writebrawerr(req);
3741 END_PROFILE(SMBwritebraw);
3742 return;
3745 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3746 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3747 &lock);
3749 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3750 reply_doserror(req, ERRDOS, ERRlock);
3751 error_to_writebrawerr(req);
3752 END_PROFILE(SMBwritebraw);
3753 return;
3756 if (numtowrite>0) {
3757 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3760 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3761 "wrote=%d sync=%d\n",
3762 fsp->fnum, (double)startpos, (int)numtowrite,
3763 (int)nwritten, (int)write_through));
3765 if (nwritten < (ssize_t)numtowrite) {
3766 reply_unixerror(req, ERRHRD, ERRdiskfull);
3767 error_to_writebrawerr(req);
3768 goto strict_unlock;
3771 total_written = nwritten;
3773 /* Allocate a buffer of 64k + length. */
3774 buf = TALLOC_ARRAY(NULL, char, 65540);
3775 if (!buf) {
3776 reply_doserror(req, ERRDOS, ERRnomem);
3777 error_to_writebrawerr(req);
3778 goto strict_unlock;
3781 /* Return a SMBwritebraw message to the redirector to tell
3782 * it to send more bytes */
3784 memcpy(buf, req->inbuf, smb_size);
3785 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3786 SCVAL(buf,smb_com,SMBwritebraw);
3787 SSVALS(buf,smb_vwv0,0xFFFF);
3788 show_msg(buf);
3789 if (!srv_send_smb(smbd_server_fd(),
3790 buf,
3791 false, 0, /* no signing */
3792 IS_CONN_ENCRYPTED(conn),
3793 &req->pcd)) {
3794 exit_server_cleanly("reply_writebraw: srv_send_smb "
3795 "failed.");
3798 /* Now read the raw data into the buffer and write it */
3799 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3800 &numtowrite);
3801 if (!NT_STATUS_IS_OK(status)) {
3802 exit_server_cleanly("secondary writebraw failed");
3805 /* Set up outbuf to return the correct size */
3806 reply_outbuf(req, 1, 0);
3808 if (numtowrite != 0) {
3810 if (numtowrite > 0xFFFF) {
3811 DEBUG(0,("reply_writebraw: Oversize secondary write "
3812 "raw requested (%u). Terminating\n",
3813 (unsigned int)numtowrite ));
3814 exit_server_cleanly("secondary writebraw failed");
3817 if (tcount > nwritten+numtowrite) {
3818 DEBUG(3,("reply_writebraw: Client overestimated the "
3819 "write %d %d %d\n",
3820 (int)tcount,(int)nwritten,(int)numtowrite));
3823 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3825 if (!NT_STATUS_IS_OK(status)) {
3826 DEBUG(0,("reply_writebraw: Oversize secondary write "
3827 "raw read failed (%s). Terminating\n",
3828 nt_errstr(status)));
3829 exit_server_cleanly("secondary writebraw failed");
3832 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3833 if (nwritten == -1) {
3834 TALLOC_FREE(buf);
3835 reply_unixerror(req, ERRHRD, ERRdiskfull);
3836 error_to_writebrawerr(req);
3837 goto strict_unlock;
3840 if (nwritten < (ssize_t)numtowrite) {
3841 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3842 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3845 if (nwritten > 0) {
3846 total_written += nwritten;
3850 TALLOC_FREE(buf);
3851 SSVAL(req->outbuf,smb_vwv0,total_written);
3853 status = sync_file(conn, fsp, write_through);
3854 if (!NT_STATUS_IS_OK(status)) {
3855 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3856 fsp->fsp_name, nt_errstr(status) ));
3857 reply_nterror(req, status);
3858 error_to_writebrawerr(req);
3859 goto strict_unlock;
3862 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3863 "wrote=%d\n",
3864 fsp->fnum, (double)startpos, (int)numtowrite,
3865 (int)total_written));
3867 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3869 /* We won't return a status if write through is not selected - this
3870 * follows what WfWg does */
3871 END_PROFILE(SMBwritebraw);
3873 if (!write_through && total_written==tcount) {
3875 #if RABBIT_PELLET_FIX
3877 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3878 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3879 * JRA.
3881 if (!send_keepalive(smbd_server_fd())) {
3882 exit_server_cleanly("reply_writebraw: send of "
3883 "keepalive failed");
3885 #endif
3886 TALLOC_FREE(req->outbuf);
3888 return;
3890 strict_unlock:
3891 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3893 END_PROFILE(SMBwritebraw);
3894 return;
3897 #undef DBGC_CLASS
3898 #define DBGC_CLASS DBGC_LOCKING
3900 /****************************************************************************
3901 Reply to a writeunlock (core+).
3902 ****************************************************************************/
3904 void reply_writeunlock(struct smb_request *req)
3906 connection_struct *conn = req->conn;
3907 ssize_t nwritten = -1;
3908 size_t numtowrite;
3909 SMB_OFF_T startpos;
3910 const char *data;
3911 NTSTATUS status = NT_STATUS_OK;
3912 files_struct *fsp;
3913 struct lock_struct lock;
3915 START_PROFILE(SMBwriteunlock);
3917 if (req->wct < 5) {
3918 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3919 END_PROFILE(SMBwriteunlock);
3920 return;
3923 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3925 if (!check_fsp(conn, req, fsp)) {
3926 END_PROFILE(SMBwriteunlock);
3927 return;
3930 if (!CHECK_WRITE(fsp)) {
3931 reply_doserror(req, ERRDOS,ERRbadaccess);
3932 END_PROFILE(SMBwriteunlock);
3933 return;
3936 numtowrite = SVAL(req->vwv+1, 0);
3937 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3938 data = (const char *)req->buf + 3;
3940 if (numtowrite) {
3941 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3942 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3943 &lock);
3945 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3946 reply_doserror(req, ERRDOS, ERRlock);
3947 END_PROFILE(SMBwriteunlock);
3948 return;
3952 /* The special X/Open SMB protocol handling of
3953 zero length writes is *NOT* done for
3954 this call */
3955 if(numtowrite == 0) {
3956 nwritten = 0;
3957 } else {
3958 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3961 status = sync_file(conn, fsp, False /* write through */);
3962 if (!NT_STATUS_IS_OK(status)) {
3963 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3964 fsp->fsp_name, nt_errstr(status) ));
3965 reply_nterror(req, status);
3966 goto strict_unlock;
3969 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3970 reply_unixerror(req, ERRHRD, ERRdiskfull);
3971 goto strict_unlock;
3974 if (numtowrite) {
3975 status = do_unlock(smbd_messaging_context(),
3976 fsp,
3977 req->smbpid,
3978 (uint64_t)numtowrite,
3979 (uint64_t)startpos,
3980 WINDOWS_LOCK);
3982 if (NT_STATUS_V(status)) {
3983 reply_nterror(req, status);
3984 goto strict_unlock;
3988 reply_outbuf(req, 1, 0);
3990 SSVAL(req->outbuf,smb_vwv0,nwritten);
3992 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3993 fsp->fnum, (int)numtowrite, (int)nwritten));
3995 strict_unlock:
3996 if (numtowrite) {
3997 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4000 END_PROFILE(SMBwriteunlock);
4001 return;
4004 #undef DBGC_CLASS
4005 #define DBGC_CLASS DBGC_ALL
4007 /****************************************************************************
4008 Reply to a write.
4009 ****************************************************************************/
4011 void reply_write(struct smb_request *req)
4013 connection_struct *conn = req->conn;
4014 size_t numtowrite;
4015 ssize_t nwritten = -1;
4016 SMB_OFF_T startpos;
4017 const char *data;
4018 files_struct *fsp;
4019 struct lock_struct lock;
4020 NTSTATUS status;
4022 START_PROFILE(SMBwrite);
4024 if (req->wct < 5) {
4025 END_PROFILE(SMBwrite);
4026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4027 return;
4030 /* If it's an IPC, pass off the pipe handler. */
4031 if (IS_IPC(conn)) {
4032 reply_pipe_write(req);
4033 END_PROFILE(SMBwrite);
4034 return;
4037 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4039 if (!check_fsp(conn, req, fsp)) {
4040 END_PROFILE(SMBwrite);
4041 return;
4044 if (!CHECK_WRITE(fsp)) {
4045 reply_doserror(req, ERRDOS, ERRbadaccess);
4046 END_PROFILE(SMBwrite);
4047 return;
4050 numtowrite = SVAL(req->vwv+1, 0);
4051 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4052 data = (const char *)req->buf + 3;
4054 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4055 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4056 &lock);
4058 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4059 reply_doserror(req, ERRDOS, ERRlock);
4060 END_PROFILE(SMBwrite);
4061 return;
4065 * X/Open SMB protocol says that if smb_vwv1 is
4066 * zero then the file size should be extended or
4067 * truncated to the size given in smb_vwv[2-3].
4070 if(numtowrite == 0) {
4072 * This is actually an allocate call, and set EOF. JRA.
4074 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4075 if (nwritten < 0) {
4076 reply_nterror(req, NT_STATUS_DISK_FULL);
4077 goto strict_unlock;
4079 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4080 if (nwritten < 0) {
4081 reply_nterror(req, NT_STATUS_DISK_FULL);
4082 goto strict_unlock;
4084 trigger_write_time_update_immediate(fsp);
4085 } else {
4086 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4089 status = sync_file(conn, fsp, False);
4090 if (!NT_STATUS_IS_OK(status)) {
4091 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4092 fsp->fsp_name, nt_errstr(status) ));
4093 reply_nterror(req, status);
4094 goto strict_unlock;
4097 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4098 reply_unixerror(req, ERRHRD, ERRdiskfull);
4099 goto strict_unlock;
4102 reply_outbuf(req, 1, 0);
4104 SSVAL(req->outbuf,smb_vwv0,nwritten);
4106 if (nwritten < (ssize_t)numtowrite) {
4107 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4108 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4111 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4113 strict_unlock:
4114 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4116 END_PROFILE(SMBwrite);
4117 return;
4120 /****************************************************************************
4121 Ensure a buffer is a valid writeX for recvfile purposes.
4122 ****************************************************************************/
4124 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4125 (2*14) + /* word count (including bcc) */ \
4126 1 /* pad byte */)
4128 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4130 size_t numtowrite;
4131 connection_struct *conn = NULL;
4132 unsigned int doff = 0;
4133 size_t len = smb_len_large(inbuf);
4135 if (is_encrypted_packet(inbuf)) {
4136 /* Can't do this on encrypted
4137 * connections. */
4138 return false;
4141 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4142 return false;
4145 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4146 CVAL(inbuf,smb_wct) != 14) {
4147 DEBUG(10,("is_valid_writeX_buffer: chained or "
4148 "invalid word length.\n"));
4149 return false;
4152 conn = conn_find(SVAL(inbuf, smb_tid));
4153 if (conn == NULL) {
4154 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4155 return false;
4157 if (IS_IPC(conn)) {
4158 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4159 return false;
4161 if (IS_PRINT(conn)) {
4162 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4163 return false;
4165 doff = SVAL(inbuf,smb_vwv11);
4167 numtowrite = SVAL(inbuf,smb_vwv10);
4169 if (len > doff && len - doff > 0xFFFF) {
4170 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4173 if (numtowrite == 0) {
4174 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4175 return false;
4178 /* Ensure the sizes match up. */
4179 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4180 /* no pad byte...old smbclient :-( */
4181 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4182 (unsigned int)doff,
4183 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4184 return false;
4187 if (len - doff != numtowrite) {
4188 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4189 "len = %u, doff = %u, numtowrite = %u\n",
4190 (unsigned int)len,
4191 (unsigned int)doff,
4192 (unsigned int)numtowrite ));
4193 return false;
4196 DEBUG(10,("is_valid_writeX_buffer: true "
4197 "len = %u, doff = %u, numtowrite = %u\n",
4198 (unsigned int)len,
4199 (unsigned int)doff,
4200 (unsigned int)numtowrite ));
4202 return true;
4205 /****************************************************************************
4206 Reply to a write and X.
4207 ****************************************************************************/
4209 void reply_write_and_X(struct smb_request *req)
4211 connection_struct *conn = req->conn;
4212 files_struct *fsp;
4213 struct lock_struct lock;
4214 SMB_OFF_T startpos;
4215 size_t numtowrite;
4216 bool write_through;
4217 ssize_t nwritten;
4218 unsigned int smb_doff;
4219 unsigned int smblen;
4220 char *data;
4221 NTSTATUS status;
4223 START_PROFILE(SMBwriteX);
4225 if ((req->wct != 12) && (req->wct != 14)) {
4226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4227 END_PROFILE(SMBwriteX);
4228 return;
4231 numtowrite = SVAL(req->vwv+10, 0);
4232 smb_doff = SVAL(req->vwv+11, 0);
4233 smblen = smb_len(req->inbuf);
4235 if (req->unread_bytes > 0xFFFF ||
4236 (smblen > smb_doff &&
4237 smblen - smb_doff > 0xFFFF)) {
4238 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4241 if (req->unread_bytes) {
4242 /* Can't do a recvfile write on IPC$ */
4243 if (IS_IPC(conn)) {
4244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4245 END_PROFILE(SMBwriteX);
4246 return;
4248 if (numtowrite != req->unread_bytes) {
4249 reply_doserror(req, ERRDOS, ERRbadmem);
4250 END_PROFILE(SMBwriteX);
4251 return;
4253 } else {
4254 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4255 smb_doff + numtowrite > smblen) {
4256 reply_doserror(req, ERRDOS, ERRbadmem);
4257 END_PROFILE(SMBwriteX);
4258 return;
4262 /* If it's an IPC, pass off the pipe handler. */
4263 if (IS_IPC(conn)) {
4264 if (req->unread_bytes) {
4265 reply_doserror(req, ERRDOS, ERRbadmem);
4266 END_PROFILE(SMBwriteX);
4267 return;
4269 reply_pipe_write_and_X(req);
4270 END_PROFILE(SMBwriteX);
4271 return;
4274 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4275 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4276 write_through = BITSETW(req->vwv+7,0);
4278 if (!check_fsp(conn, req, fsp)) {
4279 END_PROFILE(SMBwriteX);
4280 return;
4283 if (!CHECK_WRITE(fsp)) {
4284 reply_doserror(req, ERRDOS, ERRbadaccess);
4285 END_PROFILE(SMBwriteX);
4286 return;
4289 data = smb_base(req->inbuf) + smb_doff;
4291 if(req->wct == 14) {
4292 #ifdef LARGE_SMB_OFF_T
4294 * This is a large offset (64 bit) write.
4296 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4298 #else /* !LARGE_SMB_OFF_T */
4301 * Ensure we haven't been sent a >32 bit offset.
4304 if(IVAL(req->vwv+12, 0) != 0) {
4305 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4306 "used and we don't support 64 bit offsets.\n",
4307 (unsigned int)IVAL(req->vwv+12, 0) ));
4308 reply_doserror(req, ERRDOS, ERRbadaccess);
4309 END_PROFILE(SMBwriteX);
4310 return;
4313 #endif /* LARGE_SMB_OFF_T */
4316 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4317 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4318 &lock);
4320 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4321 reply_doserror(req, ERRDOS, ERRlock);
4322 END_PROFILE(SMBwriteX);
4323 return;
4326 /* X/Open SMB protocol says that, unlike SMBwrite
4327 if the length is zero then NO truncation is
4328 done, just a write of zero. To truncate a file,
4329 use SMBwrite. */
4331 if(numtowrite == 0) {
4332 nwritten = 0;
4333 } else {
4335 if ((req->unread_bytes == 0) &&
4336 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4337 numtowrite)) {
4338 goto strict_unlock;
4341 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4344 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4345 reply_unixerror(req, ERRHRD, ERRdiskfull);
4346 goto strict_unlock;
4349 reply_outbuf(req, 6, 0);
4350 SSVAL(req->outbuf,smb_vwv2,nwritten);
4351 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4353 if (nwritten < (ssize_t)numtowrite) {
4354 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4355 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4358 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4359 fsp->fnum, (int)numtowrite, (int)nwritten));
4361 status = sync_file(conn, fsp, write_through);
4362 if (!NT_STATUS_IS_OK(status)) {
4363 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4364 fsp->fsp_name, nt_errstr(status) ));
4365 reply_nterror(req, status);
4366 goto strict_unlock;
4369 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4371 END_PROFILE(SMBwriteX);
4372 chain_reply(req);
4373 return;
4375 strict_unlock:
4376 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4378 END_PROFILE(SMBwriteX);
4379 return;
4382 /****************************************************************************
4383 Reply to a lseek.
4384 ****************************************************************************/
4386 void reply_lseek(struct smb_request *req)
4388 connection_struct *conn = req->conn;
4389 SMB_OFF_T startpos;
4390 SMB_OFF_T res= -1;
4391 int mode,umode;
4392 files_struct *fsp;
4394 START_PROFILE(SMBlseek);
4396 if (req->wct < 4) {
4397 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4398 END_PROFILE(SMBlseek);
4399 return;
4402 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4404 if (!check_fsp(conn, req, fsp)) {
4405 return;
4408 flush_write_cache(fsp, SEEK_FLUSH);
4410 mode = SVAL(req->vwv+1, 0) & 3;
4411 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4412 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4414 switch (mode) {
4415 case 0:
4416 umode = SEEK_SET;
4417 res = startpos;
4418 break;
4419 case 1:
4420 umode = SEEK_CUR;
4421 res = fsp->fh->pos + startpos;
4422 break;
4423 case 2:
4424 umode = SEEK_END;
4425 break;
4426 default:
4427 umode = SEEK_SET;
4428 res = startpos;
4429 break;
4432 if (umode == SEEK_END) {
4433 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4434 if(errno == EINVAL) {
4435 SMB_OFF_T current_pos = startpos;
4436 SMB_STRUCT_STAT sbuf;
4438 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4439 reply_unixerror(req, ERRDOS,
4440 ERRnoaccess);
4441 END_PROFILE(SMBlseek);
4442 return;
4445 current_pos += sbuf.st_ex_size;
4446 if(current_pos < 0)
4447 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4451 if(res == -1) {
4452 reply_unixerror(req, ERRDOS, ERRnoaccess);
4453 END_PROFILE(SMBlseek);
4454 return;
4458 fsp->fh->pos = res;
4460 reply_outbuf(req, 2, 0);
4461 SIVAL(req->outbuf,smb_vwv0,res);
4463 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4464 fsp->fnum, (double)startpos, (double)res, mode));
4466 END_PROFILE(SMBlseek);
4467 return;
4470 /****************************************************************************
4471 Reply to a flush.
4472 ****************************************************************************/
4474 void reply_flush(struct smb_request *req)
4476 connection_struct *conn = req->conn;
4477 uint16 fnum;
4478 files_struct *fsp;
4480 START_PROFILE(SMBflush);
4482 if (req->wct < 1) {
4483 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4484 return;
4487 fnum = SVAL(req->vwv+0, 0);
4488 fsp = file_fsp(req, fnum);
4490 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4491 return;
4494 if (!fsp) {
4495 file_sync_all(conn);
4496 } else {
4497 NTSTATUS status = sync_file(conn, fsp, True);
4498 if (!NT_STATUS_IS_OK(status)) {
4499 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4500 fsp->fsp_name, nt_errstr(status) ));
4501 reply_nterror(req, status);
4502 END_PROFILE(SMBflush);
4503 return;
4507 reply_outbuf(req, 0, 0);
4509 DEBUG(3,("flush\n"));
4510 END_PROFILE(SMBflush);
4511 return;
4514 /****************************************************************************
4515 Reply to a exit.
4516 conn POINTER CAN BE NULL HERE !
4517 ****************************************************************************/
4519 void reply_exit(struct smb_request *req)
4521 START_PROFILE(SMBexit);
4523 file_close_pid(req->smbpid, req->vuid);
4525 reply_outbuf(req, 0, 0);
4527 DEBUG(3,("exit\n"));
4529 END_PROFILE(SMBexit);
4530 return;
4533 /****************************************************************************
4534 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4535 ****************************************************************************/
4537 void reply_close(struct smb_request *req)
4539 connection_struct *conn = req->conn;
4540 NTSTATUS status = NT_STATUS_OK;
4541 files_struct *fsp = NULL;
4542 START_PROFILE(SMBclose);
4544 if (req->wct < 3) {
4545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4546 END_PROFILE(SMBclose);
4547 return;
4550 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4553 * We can only use check_fsp if we know it's not a directory.
4556 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4557 reply_doserror(req, ERRDOS, ERRbadfid);
4558 END_PROFILE(SMBclose);
4559 return;
4562 if(fsp->is_directory) {
4564 * Special case - close NT SMB directory handle.
4566 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4567 status = close_file(req, fsp, NORMAL_CLOSE);
4568 } else {
4569 time_t t;
4571 * Close ordinary file.
4574 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4575 fsp->fh->fd, fsp->fnum,
4576 conn->num_files_open));
4579 * Take care of any time sent in the close.
4582 t = srv_make_unix_date3(req->vwv+1);
4583 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4586 * close_file() returns the unix errno if an error
4587 * was detected on close - normally this is due to
4588 * a disk full error. If not then it was probably an I/O error.
4591 status = close_file(req, fsp, NORMAL_CLOSE);
4594 if (!NT_STATUS_IS_OK(status)) {
4595 reply_nterror(req, status);
4596 END_PROFILE(SMBclose);
4597 return;
4600 reply_outbuf(req, 0, 0);
4601 END_PROFILE(SMBclose);
4602 return;
4605 /****************************************************************************
4606 Reply to a writeclose (Core+ protocol).
4607 ****************************************************************************/
4609 void reply_writeclose(struct smb_request *req)
4611 connection_struct *conn = req->conn;
4612 size_t numtowrite;
4613 ssize_t nwritten = -1;
4614 NTSTATUS close_status = NT_STATUS_OK;
4615 SMB_OFF_T startpos;
4616 const char *data;
4617 struct timespec mtime;
4618 files_struct *fsp;
4619 struct lock_struct lock;
4621 START_PROFILE(SMBwriteclose);
4623 if (req->wct < 6) {
4624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4625 END_PROFILE(SMBwriteclose);
4626 return;
4629 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4631 if (!check_fsp(conn, req, fsp)) {
4632 END_PROFILE(SMBwriteclose);
4633 return;
4635 if (!CHECK_WRITE(fsp)) {
4636 reply_doserror(req, ERRDOS,ERRbadaccess);
4637 END_PROFILE(SMBwriteclose);
4638 return;
4641 numtowrite = SVAL(req->vwv+1, 0);
4642 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4643 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4644 data = (const char *)req->buf + 1;
4646 if (numtowrite) {
4647 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4648 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4649 &lock);
4651 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4652 reply_doserror(req, ERRDOS,ERRlock);
4653 END_PROFILE(SMBwriteclose);
4654 return;
4658 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4660 set_close_write_time(fsp, mtime);
4663 * More insanity. W2K only closes the file if writelen > 0.
4664 * JRA.
4667 if (numtowrite) {
4668 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4669 fsp->fsp_name ));
4670 close_status = close_file(req, fsp, NORMAL_CLOSE);
4673 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4674 fsp->fnum, (int)numtowrite, (int)nwritten,
4675 conn->num_files_open));
4677 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4678 reply_doserror(req, ERRHRD, ERRdiskfull);
4679 goto strict_unlock;
4682 if(!NT_STATUS_IS_OK(close_status)) {
4683 reply_nterror(req, close_status);
4684 goto strict_unlock;
4687 reply_outbuf(req, 1, 0);
4689 SSVAL(req->outbuf,smb_vwv0,nwritten);
4691 strict_unlock:
4692 if (numtowrite) {
4693 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4696 END_PROFILE(SMBwriteclose);
4697 return;
4700 #undef DBGC_CLASS
4701 #define DBGC_CLASS DBGC_LOCKING
4703 /****************************************************************************
4704 Reply to a lock.
4705 ****************************************************************************/
4707 void reply_lock(struct smb_request *req)
4709 connection_struct *conn = req->conn;
4710 uint64_t count,offset;
4711 NTSTATUS status;
4712 files_struct *fsp;
4713 struct byte_range_lock *br_lck = NULL;
4715 START_PROFILE(SMBlock);
4717 if (req->wct < 5) {
4718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4719 END_PROFILE(SMBlock);
4720 return;
4723 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4725 if (!check_fsp(conn, req, fsp)) {
4726 END_PROFILE(SMBlock);
4727 return;
4730 count = (uint64_t)IVAL(req->vwv+1, 0);
4731 offset = (uint64_t)IVAL(req->vwv+3, 0);
4733 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4734 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4736 br_lck = do_lock(smbd_messaging_context(),
4737 fsp,
4738 req->smbpid,
4739 count,
4740 offset,
4741 WRITE_LOCK,
4742 WINDOWS_LOCK,
4743 False, /* Non-blocking lock. */
4744 &status,
4745 NULL,
4746 NULL);
4748 TALLOC_FREE(br_lck);
4750 if (NT_STATUS_V(status)) {
4751 reply_nterror(req, status);
4752 END_PROFILE(SMBlock);
4753 return;
4756 reply_outbuf(req, 0, 0);
4758 END_PROFILE(SMBlock);
4759 return;
4762 /****************************************************************************
4763 Reply to a unlock.
4764 ****************************************************************************/
4766 void reply_unlock(struct smb_request *req)
4768 connection_struct *conn = req->conn;
4769 uint64_t count,offset;
4770 NTSTATUS status;
4771 files_struct *fsp;
4773 START_PROFILE(SMBunlock);
4775 if (req->wct < 5) {
4776 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4777 END_PROFILE(SMBunlock);
4778 return;
4781 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4783 if (!check_fsp(conn, req, fsp)) {
4784 END_PROFILE(SMBunlock);
4785 return;
4788 count = (uint64_t)IVAL(req->vwv+1, 0);
4789 offset = (uint64_t)IVAL(req->vwv+3, 0);
4791 status = do_unlock(smbd_messaging_context(),
4792 fsp,
4793 req->smbpid,
4794 count,
4795 offset,
4796 WINDOWS_LOCK);
4798 if (NT_STATUS_V(status)) {
4799 reply_nterror(req, status);
4800 END_PROFILE(SMBunlock);
4801 return;
4804 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4805 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4807 reply_outbuf(req, 0, 0);
4809 END_PROFILE(SMBunlock);
4810 return;
4813 #undef DBGC_CLASS
4814 #define DBGC_CLASS DBGC_ALL
4816 /****************************************************************************
4817 Reply to a tdis.
4818 conn POINTER CAN BE NULL HERE !
4819 ****************************************************************************/
4821 void reply_tdis(struct smb_request *req)
4823 connection_struct *conn = req->conn;
4824 START_PROFILE(SMBtdis);
4826 if (!conn) {
4827 DEBUG(4,("Invalid connection in tdis\n"));
4828 reply_doserror(req, ERRSRV, ERRinvnid);
4829 END_PROFILE(SMBtdis);
4830 return;
4833 conn->used = False;
4835 close_cnum(conn,req->vuid);
4836 req->conn = NULL;
4838 reply_outbuf(req, 0, 0);
4839 END_PROFILE(SMBtdis);
4840 return;
4843 /****************************************************************************
4844 Reply to a echo.
4845 conn POINTER CAN BE NULL HERE !
4846 ****************************************************************************/
4848 void reply_echo(struct smb_request *req)
4850 connection_struct *conn = req->conn;
4851 struct smb_perfcount_data local_pcd;
4852 struct smb_perfcount_data *cur_pcd;
4853 int smb_reverb;
4854 int seq_num;
4856 START_PROFILE(SMBecho);
4858 smb_init_perfcount_data(&local_pcd);
4860 if (req->wct < 1) {
4861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4862 END_PROFILE(SMBecho);
4863 return;
4866 smb_reverb = SVAL(req->vwv+0, 0);
4868 reply_outbuf(req, 1, req->buflen);
4870 /* copy any incoming data back out */
4871 if (req->buflen > 0) {
4872 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4875 if (smb_reverb > 100) {
4876 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4877 smb_reverb = 100;
4880 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4882 /* this makes sure we catch the request pcd */
4883 if (seq_num == smb_reverb) {
4884 cur_pcd = &req->pcd;
4885 } else {
4886 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4887 cur_pcd = &local_pcd;
4890 SSVAL(req->outbuf,smb_vwv0,seq_num);
4892 show_msg((char *)req->outbuf);
4893 if (!srv_send_smb(smbd_server_fd(),
4894 (char *)req->outbuf,
4895 true, req->seqnum+1,
4896 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4897 cur_pcd))
4898 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4901 DEBUG(3,("echo %d times\n", smb_reverb));
4903 TALLOC_FREE(req->outbuf);
4905 END_PROFILE(SMBecho);
4906 return;
4909 /****************************************************************************
4910 Reply to a printopen.
4911 ****************************************************************************/
4913 void reply_printopen(struct smb_request *req)
4915 connection_struct *conn = req->conn;
4916 files_struct *fsp;
4917 SMB_STRUCT_STAT sbuf;
4918 NTSTATUS status;
4920 START_PROFILE(SMBsplopen);
4922 if (req->wct < 2) {
4923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4924 END_PROFILE(SMBsplopen);
4925 return;
4928 if (!CAN_PRINT(conn)) {
4929 reply_doserror(req, ERRDOS, ERRnoaccess);
4930 END_PROFILE(SMBsplopen);
4931 return;
4934 status = file_new(req, conn, &fsp);
4935 if(!NT_STATUS_IS_OK(status)) {
4936 reply_nterror(req, status);
4937 END_PROFILE(SMBsplopen);
4938 return;
4941 /* Open for exclusive use, write only. */
4942 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4944 if (!NT_STATUS_IS_OK(status)) {
4945 reply_nterror(req, status);
4946 END_PROFILE(SMBsplopen);
4947 return;
4950 reply_outbuf(req, 1, 0);
4951 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4953 DEBUG(3,("openprint fd=%d fnum=%d\n",
4954 fsp->fh->fd, fsp->fnum));
4956 END_PROFILE(SMBsplopen);
4957 return;
4960 /****************************************************************************
4961 Reply to a printclose.
4962 ****************************************************************************/
4964 void reply_printclose(struct smb_request *req)
4966 connection_struct *conn = req->conn;
4967 files_struct *fsp;
4968 NTSTATUS status;
4970 START_PROFILE(SMBsplclose);
4972 if (req->wct < 1) {
4973 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4974 END_PROFILE(SMBsplclose);
4975 return;
4978 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4980 if (!check_fsp(conn, req, fsp)) {
4981 END_PROFILE(SMBsplclose);
4982 return;
4985 if (!CAN_PRINT(conn)) {
4986 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4987 END_PROFILE(SMBsplclose);
4988 return;
4991 DEBUG(3,("printclose fd=%d fnum=%d\n",
4992 fsp->fh->fd,fsp->fnum));
4994 status = close_file(req, fsp, NORMAL_CLOSE);
4996 if(!NT_STATUS_IS_OK(status)) {
4997 reply_nterror(req, status);
4998 END_PROFILE(SMBsplclose);
4999 return;
5002 reply_outbuf(req, 0, 0);
5004 END_PROFILE(SMBsplclose);
5005 return;
5008 /****************************************************************************
5009 Reply to a printqueue.
5010 ****************************************************************************/
5012 void reply_printqueue(struct smb_request *req)
5014 connection_struct *conn = req->conn;
5015 int max_count;
5016 int start_index;
5018 START_PROFILE(SMBsplretq);
5020 if (req->wct < 2) {
5021 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5022 END_PROFILE(SMBsplretq);
5023 return;
5026 max_count = SVAL(req->vwv+0, 0);
5027 start_index = SVAL(req->vwv+1, 0);
5029 /* we used to allow the client to get the cnum wrong, but that
5030 is really quite gross and only worked when there was only
5031 one printer - I think we should now only accept it if they
5032 get it right (tridge) */
5033 if (!CAN_PRINT(conn)) {
5034 reply_doserror(req, ERRDOS, ERRnoaccess);
5035 END_PROFILE(SMBsplretq);
5036 return;
5039 reply_outbuf(req, 2, 3);
5040 SSVAL(req->outbuf,smb_vwv0,0);
5041 SSVAL(req->outbuf,smb_vwv1,0);
5042 SCVAL(smb_buf(req->outbuf),0,1);
5043 SSVAL(smb_buf(req->outbuf),1,0);
5045 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5046 start_index, max_count));
5049 print_queue_struct *queue = NULL;
5050 print_status_struct status;
5051 int count = print_queue_status(SNUM(conn), &queue, &status);
5052 int num_to_get = ABS(max_count);
5053 int first = (max_count>0?start_index:start_index+max_count+1);
5054 int i;
5056 if (first >= count)
5057 num_to_get = 0;
5058 else
5059 num_to_get = MIN(num_to_get,count-first);
5062 for (i=first;i<first+num_to_get;i++) {
5063 char blob[28];
5064 char *p = blob;
5066 srv_put_dos_date2(p,0,queue[i].time);
5067 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5068 SSVAL(p,5, queue[i].job);
5069 SIVAL(p,7,queue[i].size);
5070 SCVAL(p,11,0);
5071 srvstr_push(blob, req->flags2, p+12,
5072 queue[i].fs_user, 16, STR_ASCII);
5074 if (message_push_blob(
5075 &req->outbuf,
5076 data_blob_const(
5077 blob, sizeof(blob))) == -1) {
5078 reply_nterror(req, NT_STATUS_NO_MEMORY);
5079 END_PROFILE(SMBsplretq);
5080 return;
5084 if (count > 0) {
5085 SSVAL(req->outbuf,smb_vwv0,count);
5086 SSVAL(req->outbuf,smb_vwv1,
5087 (max_count>0?first+count:first-1));
5088 SCVAL(smb_buf(req->outbuf),0,1);
5089 SSVAL(smb_buf(req->outbuf),1,28*count);
5092 SAFE_FREE(queue);
5094 DEBUG(3,("%d entries returned in queue\n",count));
5097 END_PROFILE(SMBsplretq);
5098 return;
5101 /****************************************************************************
5102 Reply to a printwrite.
5103 ****************************************************************************/
5105 void reply_printwrite(struct smb_request *req)
5107 connection_struct *conn = req->conn;
5108 int numtowrite;
5109 const char *data;
5110 files_struct *fsp;
5112 START_PROFILE(SMBsplwr);
5114 if (req->wct < 1) {
5115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5116 END_PROFILE(SMBsplwr);
5117 return;
5120 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5122 if (!check_fsp(conn, req, fsp)) {
5123 END_PROFILE(SMBsplwr);
5124 return;
5127 if (!CAN_PRINT(conn)) {
5128 reply_doserror(req, ERRDOS, ERRnoaccess);
5129 END_PROFILE(SMBsplwr);
5130 return;
5133 if (!CHECK_WRITE(fsp)) {
5134 reply_doserror(req, ERRDOS, ERRbadaccess);
5135 END_PROFILE(SMBsplwr);
5136 return;
5139 numtowrite = SVAL(req->buf, 1);
5141 if (req->buflen < numtowrite + 3) {
5142 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5143 END_PROFILE(SMBsplwr);
5144 return;
5147 data = (const char *)req->buf + 3;
5149 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5150 reply_unixerror(req, ERRHRD, ERRdiskfull);
5151 END_PROFILE(SMBsplwr);
5152 return;
5155 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5157 END_PROFILE(SMBsplwr);
5158 return;
5161 /****************************************************************************
5162 Reply to a mkdir.
5163 ****************************************************************************/
5165 void reply_mkdir(struct smb_request *req)
5167 connection_struct *conn = req->conn;
5168 struct smb_filename *smb_dname = NULL;
5169 char *directory = NULL;
5170 NTSTATUS status;
5171 TALLOC_CTX *ctx = talloc_tos();
5173 START_PROFILE(SMBmkdir);
5175 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5176 STR_TERMINATE, &status);
5177 if (!NT_STATUS_IS_OK(status)) {
5178 reply_nterror(req, status);
5179 goto out;
5182 status = resolve_dfspath(ctx, conn,
5183 req->flags2 & FLAGS2_DFS_PATHNAMES,
5184 directory,
5185 &directory);
5186 if (!NT_STATUS_IS_OK(status)) {
5187 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5188 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5189 ERRSRV, ERRbadpath);
5190 goto out;
5192 reply_nterror(req, status);
5193 goto out;
5196 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5197 if (!NT_STATUS_IS_OK(status)) {
5198 reply_nterror(req, status);
5199 goto out;
5202 status = get_full_smb_filename(ctx, smb_dname, &directory);
5203 if (!NT_STATUS_IS_OK(status)) {
5204 reply_nterror(req, status);
5205 goto out;
5208 status = check_name(conn, directory);
5209 if (!NT_STATUS_IS_OK(status)) {
5210 reply_nterror(req, status);
5211 goto out;
5214 status = create_directory(conn, req, directory);
5216 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5218 if (!NT_STATUS_IS_OK(status)) {
5220 if (!use_nt_status()
5221 && NT_STATUS_EQUAL(status,
5222 NT_STATUS_OBJECT_NAME_COLLISION)) {
5224 * Yes, in the DOS error code case we get a
5225 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5226 * samba4 torture test.
5228 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5231 reply_nterror(req, status);
5232 goto out;
5235 reply_outbuf(req, 0, 0);
5237 DEBUG( 3, ( "mkdir %s\n", directory ) );
5238 out:
5239 TALLOC_FREE(smb_dname);
5240 END_PROFILE(SMBmkdir);
5241 return;
5244 /****************************************************************************
5245 Static function used by reply_rmdir to delete an entire directory
5246 tree recursively. Return True on ok, False on fail.
5247 ****************************************************************************/
5249 static bool recursive_rmdir(TALLOC_CTX *ctx,
5250 connection_struct *conn,
5251 char *directory)
5253 const char *dname = NULL;
5254 bool ret = True;
5255 long offset = 0;
5256 SMB_STRUCT_STAT st;
5257 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
5258 NULL, 0);
5260 if(dir_hnd == NULL)
5261 return False;
5263 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5264 char *fullname = NULL;
5266 if (ISDOT(dname) || ISDOTDOT(dname)) {
5267 continue;
5270 if (!is_visible_file(conn, directory, dname, &st, False)) {
5271 continue;
5274 /* Construct the full name. */
5275 fullname = talloc_asprintf(ctx,
5276 "%s/%s",
5277 directory,
5278 dname);
5279 if (!fullname) {
5280 errno = ENOMEM;
5281 ret = False;
5282 break;
5285 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5286 ret = False;
5287 break;
5290 if(st.st_ex_mode & S_IFDIR) {
5291 if(!recursive_rmdir(ctx, conn, fullname)) {
5292 ret = False;
5293 break;
5295 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5296 ret = False;
5297 break;
5299 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5300 ret = False;
5301 break;
5303 TALLOC_FREE(fullname);
5305 TALLOC_FREE(dir_hnd);
5306 return ret;
5309 /****************************************************************************
5310 The internals of the rmdir code - called elsewhere.
5311 ****************************************************************************/
5313 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5314 connection_struct *conn,
5315 const char *directory)
5317 int ret;
5318 SMB_STRUCT_STAT st;
5320 /* Might be a symlink. */
5321 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
5322 return map_nt_error_from_unix(errno);
5325 if (S_ISLNK(st.st_ex_mode)) {
5326 /* Is what it points to a directory ? */
5327 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
5328 return map_nt_error_from_unix(errno);
5330 if (!(S_ISDIR(st.st_ex_mode))) {
5331 return NT_STATUS_NOT_A_DIRECTORY;
5333 ret = SMB_VFS_UNLINK(conn,directory);
5334 } else {
5335 ret = SMB_VFS_RMDIR(conn,directory);
5337 if (ret == 0) {
5338 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5339 FILE_NOTIFY_CHANGE_DIR_NAME,
5340 directory);
5341 return NT_STATUS_OK;
5344 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5346 * Check to see if the only thing in this directory are
5347 * vetoed files/directories. If so then delete them and
5348 * retry. If we fail to delete any of them (and we *don't*
5349 * do a recursive delete) then fail the rmdir.
5351 const char *dname;
5352 long dirpos = 0;
5353 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5354 directory, NULL, 0);
5356 if(dir_hnd == NULL) {
5357 errno = ENOTEMPTY;
5358 goto err;
5361 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5362 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5363 continue;
5364 if (!is_visible_file(conn, directory, dname, &st, False))
5365 continue;
5366 if(!IS_VETO_PATH(conn, dname)) {
5367 TALLOC_FREE(dir_hnd);
5368 errno = ENOTEMPTY;
5369 goto err;
5373 /* We only have veto files/directories.
5374 * Are we allowed to delete them ? */
5376 if(!lp_recursive_veto_delete(SNUM(conn))) {
5377 TALLOC_FREE(dir_hnd);
5378 errno = ENOTEMPTY;
5379 goto err;
5382 /* Do a recursive delete. */
5383 RewindDir(dir_hnd,&dirpos);
5384 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5385 char *fullname = NULL;
5387 if (ISDOT(dname) || ISDOTDOT(dname)) {
5388 continue;
5390 if (!is_visible_file(conn, directory, dname, &st, False)) {
5391 continue;
5394 fullname = talloc_asprintf(ctx,
5395 "%s/%s",
5396 directory,
5397 dname);
5399 if(!fullname) {
5400 errno = ENOMEM;
5401 break;
5404 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5405 break;
5407 if(st.st_ex_mode & S_IFDIR) {
5408 if(!recursive_rmdir(ctx, conn, fullname)) {
5409 break;
5411 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5412 break;
5414 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5415 break;
5417 TALLOC_FREE(fullname);
5419 TALLOC_FREE(dir_hnd);
5420 /* Retry the rmdir */
5421 ret = SMB_VFS_RMDIR(conn,directory);
5424 err:
5426 if (ret != 0) {
5427 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5428 "%s\n", directory,strerror(errno)));
5429 return map_nt_error_from_unix(errno);
5432 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5433 FILE_NOTIFY_CHANGE_DIR_NAME,
5434 directory);
5436 return NT_STATUS_OK;
5439 /****************************************************************************
5440 Reply to a rmdir.
5441 ****************************************************************************/
5443 void reply_rmdir(struct smb_request *req)
5445 connection_struct *conn = req->conn;
5446 struct smb_filename *smb_dname = NULL;
5447 char *directory = NULL;
5448 NTSTATUS status;
5449 TALLOC_CTX *ctx = talloc_tos();
5451 START_PROFILE(SMBrmdir);
5453 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5454 STR_TERMINATE, &status);
5455 if (!NT_STATUS_IS_OK(status)) {
5456 reply_nterror(req, status);
5457 goto out;
5460 status = resolve_dfspath(ctx, conn,
5461 req->flags2 & FLAGS2_DFS_PATHNAMES,
5462 directory,
5463 &directory);
5464 if (!NT_STATUS_IS_OK(status)) {
5465 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5466 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5467 ERRSRV, ERRbadpath);
5468 goto out;
5470 reply_nterror(req, status);
5471 goto out;
5474 status = unix_convert(ctx, conn, directory, &smb_dname, 0);
5475 if (!NT_STATUS_IS_OK(status)) {
5476 reply_nterror(req, status);
5477 goto out;
5480 status = get_full_smb_filename(ctx, smb_dname, &directory);
5481 if (!NT_STATUS_IS_OK(status)) {
5482 reply_nterror(req, status);
5483 goto out;
5486 status = check_name(conn, directory);
5487 if (!NT_STATUS_IS_OK(status)) {
5488 reply_nterror(req, status);
5489 goto out;
5492 dptr_closepath(directory, req->smbpid);
5493 status = rmdir_internals(ctx, conn, directory);
5494 if (!NT_STATUS_IS_OK(status)) {
5495 reply_nterror(req, status);
5496 goto out;
5499 reply_outbuf(req, 0, 0);
5501 DEBUG( 3, ( "rmdir %s\n", directory ) );
5502 out:
5503 TALLOC_FREE(smb_dname);
5504 END_PROFILE(SMBrmdir);
5505 return;
5508 /*******************************************************************
5509 Resolve wildcards in a filename rename.
5510 ********************************************************************/
5512 static bool resolve_wildcards(TALLOC_CTX *ctx,
5513 const char *name1,
5514 const char *name2,
5515 char **pp_newname)
5517 char *name2_copy = NULL;
5518 char *root1 = NULL;
5519 char *root2 = NULL;
5520 char *ext1 = NULL;
5521 char *ext2 = NULL;
5522 char *p,*p2, *pname1, *pname2;
5524 name2_copy = talloc_strdup(ctx, name2);
5525 if (!name2_copy) {
5526 return False;
5529 pname1 = strrchr_m(name1,'/');
5530 pname2 = strrchr_m(name2_copy,'/');
5532 if (!pname1 || !pname2) {
5533 return False;
5536 /* Truncate the copy of name2 at the last '/' */
5537 *pname2 = '\0';
5539 /* Now go past the '/' */
5540 pname1++;
5541 pname2++;
5543 root1 = talloc_strdup(ctx, pname1);
5544 root2 = talloc_strdup(ctx, pname2);
5546 if (!root1 || !root2) {
5547 return False;
5550 p = strrchr_m(root1,'.');
5551 if (p) {
5552 *p = 0;
5553 ext1 = talloc_strdup(ctx, p+1);
5554 } else {
5555 ext1 = talloc_strdup(ctx, "");
5557 p = strrchr_m(root2,'.');
5558 if (p) {
5559 *p = 0;
5560 ext2 = talloc_strdup(ctx, p+1);
5561 } else {
5562 ext2 = talloc_strdup(ctx, "");
5565 if (!ext1 || !ext2) {
5566 return False;
5569 p = root1;
5570 p2 = root2;
5571 while (*p2) {
5572 if (*p2 == '?') {
5573 /* Hmmm. Should this be mb-aware ? */
5574 *p2 = *p;
5575 p2++;
5576 } else if (*p2 == '*') {
5577 *p2 = '\0';
5578 root2 = talloc_asprintf(ctx, "%s%s",
5579 root2,
5581 if (!root2) {
5582 return False;
5584 break;
5585 } else {
5586 p2++;
5588 if (*p) {
5589 p++;
5593 p = ext1;
5594 p2 = ext2;
5595 while (*p2) {
5596 if (*p2 == '?') {
5597 /* Hmmm. Should this be mb-aware ? */
5598 *p2 = *p;
5599 p2++;
5600 } else if (*p2 == '*') {
5601 *p2 = '\0';
5602 ext2 = talloc_asprintf(ctx, "%s%s",
5603 ext2,
5605 if (!ext2) {
5606 return False;
5608 break;
5609 } else {
5610 p2++;
5612 if (*p) {
5613 p++;
5617 if (*ext2) {
5618 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5619 name2_copy,
5620 root2,
5621 ext2);
5622 } else {
5623 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5624 name2_copy,
5625 root2);
5628 if (!*pp_newname) {
5629 return False;
5632 return True;
5635 /****************************************************************************
5636 Ensure open files have their names updated. Updated to notify other smbd's
5637 asynchronously.
5638 ****************************************************************************/
5640 static void rename_open_files(connection_struct *conn,
5641 struct share_mode_lock *lck,
5642 const char *newname)
5644 files_struct *fsp;
5645 bool did_rename = False;
5647 for(fsp = file_find_di_first(lck->id); fsp;
5648 fsp = file_find_di_next(fsp)) {
5649 /* fsp_name is a relative path under the fsp. To change this for other
5650 sharepaths we need to manipulate relative paths. */
5651 /* TODO - create the absolute path and manipulate the newname
5652 relative to the sharepath. */
5653 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5654 continue;
5656 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5657 fsp->fnum, file_id_string_tos(&fsp->file_id),
5658 fsp->fsp_name, newname ));
5659 string_set(&fsp->fsp_name, newname);
5660 did_rename = True;
5663 if (!did_rename) {
5664 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5665 file_id_string_tos(&lck->id), newname ));
5668 /* Send messages to all smbd's (not ourself) that the name has changed. */
5669 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5670 newname);
5673 /****************************************************************************
5674 We need to check if the source path is a parent directory of the destination
5675 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5676 refuse the rename with a sharing violation. Under UNIX the above call can
5677 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5678 probably need to check that the client is a Windows one before disallowing
5679 this as a UNIX client (one with UNIX extensions) can know the source is a
5680 symlink and make this decision intelligently. Found by an excellent bug
5681 report from <AndyLiebman@aol.com>.
5682 ****************************************************************************/
5684 static bool rename_path_prefix_equal(const char *src, const char *dest)
5686 const char *psrc = src;
5687 const char *pdst = dest;
5688 size_t slen;
5690 if (psrc[0] == '.' && psrc[1] == '/') {
5691 psrc += 2;
5693 if (pdst[0] == '.' && pdst[1] == '/') {
5694 pdst += 2;
5696 if ((slen = strlen(psrc)) > strlen(pdst)) {
5697 return False;
5699 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5703 * Do the notify calls from a rename
5706 static void notify_rename(connection_struct *conn, bool is_dir,
5707 const char *oldpath, const char *newpath)
5709 char *olddir, *newdir;
5710 const char *oldname, *newname;
5711 uint32 mask;
5713 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5714 : FILE_NOTIFY_CHANGE_FILE_NAME;
5716 if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
5717 || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
5718 TALLOC_FREE(olddir);
5719 return;
5722 if (strcmp(olddir, newdir) == 0) {
5723 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5724 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5726 else {
5727 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5728 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5730 TALLOC_FREE(olddir);
5731 TALLOC_FREE(newdir);
5733 /* this is a strange one. w2k3 gives an additional event for
5734 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5735 files, but not directories */
5736 if (!is_dir) {
5737 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5738 FILE_NOTIFY_CHANGE_ATTRIBUTES
5739 |FILE_NOTIFY_CHANGE_CREATION,
5740 newpath);
5744 /****************************************************************************
5745 Rename an open file - given an fsp.
5746 ****************************************************************************/
5748 NTSTATUS rename_internals_fsp(connection_struct *conn,
5749 files_struct *fsp,
5750 char *newname,
5751 const char *newname_last_component,
5752 uint32 attrs,
5753 bool replace_if_exists)
5755 TALLOC_CTX *ctx = talloc_tos();
5756 SMB_STRUCT_STAT sbuf, sbuf1;
5757 NTSTATUS status = NT_STATUS_OK;
5758 struct share_mode_lock *lck = NULL;
5759 bool dst_exists, old_is_stream, new_is_stream;
5761 ZERO_STRUCT(sbuf);
5763 status = check_name(conn, newname);
5764 if (!NT_STATUS_IS_OK(status)) {
5765 return status;
5768 /* Ensure newname contains a '/' */
5769 if(strrchr_m(newname,'/') == 0) {
5770 newname = talloc_asprintf(ctx,
5771 "./%s",
5772 newname);
5773 if (!newname) {
5774 return NT_STATUS_NO_MEMORY;
5779 * Check for special case with case preserving and not
5780 * case sensitive. If the old last component differs from the original
5781 * last component only by case, then we should allow
5782 * the rename (user is trying to change the case of the
5783 * filename).
5786 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5787 strequal(newname, fsp->fsp_name)) {
5788 char *p;
5789 char *newname_modified_last_component = NULL;
5792 * Get the last component of the modified name.
5793 * Note that we guarantee that newname contains a '/'
5794 * character above.
5796 p = strrchr_m(newname,'/');
5797 newname_modified_last_component = talloc_strdup(ctx,
5798 p+1);
5799 if (!newname_modified_last_component) {
5800 return NT_STATUS_NO_MEMORY;
5803 if(strcsequal(newname_modified_last_component,
5804 newname_last_component) == False) {
5806 * Replace the modified last component with
5807 * the original.
5809 *p = '\0'; /* Truncate at the '/' */
5810 newname = talloc_asprintf(ctx,
5811 "%s/%s",
5812 newname,
5813 newname_last_component);
5818 * If the src and dest names are identical - including case,
5819 * don't do the rename, just return success.
5822 if (strcsequal(fsp->fsp_name, newname)) {
5823 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5824 newname));
5825 return NT_STATUS_OK;
5828 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5829 new_is_stream = is_ntfs_stream_name(newname);
5831 /* Return the correct error code if both names aren't streams. */
5832 if (!old_is_stream && new_is_stream) {
5833 return NT_STATUS_OBJECT_NAME_INVALID;
5836 if (old_is_stream && !new_is_stream) {
5837 return NT_STATUS_INVALID_PARAMETER;
5841 * Have vfs_object_exist also fill sbuf1
5843 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5845 if(!replace_if_exists && dst_exists) {
5846 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5847 fsp->fsp_name,newname));
5848 return NT_STATUS_OBJECT_NAME_COLLISION;
5851 if (dst_exists) {
5852 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5853 files_struct *dst_fsp = file_find_di_first(fileid);
5854 /* The file can be open when renaming a stream */
5855 if (dst_fsp && !new_is_stream) {
5856 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5857 return NT_STATUS_ACCESS_DENIED;
5861 /* Ensure we have a valid stat struct for the source. */
5862 if (fsp->fh->fd != -1) {
5863 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5864 return map_nt_error_from_unix(errno);
5866 } else {
5867 int ret = -1;
5868 if (fsp->posix_open) {
5869 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
5870 } else {
5871 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
5873 if (ret == -1) {
5874 return map_nt_error_from_unix(errno);
5878 status = can_rename(conn, fsp, attrs, &sbuf);
5880 if (!NT_STATUS_IS_OK(status)) {
5881 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5882 nt_errstr(status), fsp->fsp_name,newname));
5883 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5884 status = NT_STATUS_ACCESS_DENIED;
5885 return status;
5888 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5889 return NT_STATUS_ACCESS_DENIED;
5892 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5893 NULL);
5896 * We have the file open ourselves, so not being able to get the
5897 * corresponding share mode lock is a fatal error.
5900 SMB_ASSERT(lck != NULL);
5902 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5903 uint32 create_options = fsp->fh->private_options;
5905 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5906 fsp->fsp_name,newname));
5908 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5910 rename_open_files(conn, lck, newname);
5913 * A rename acts as a new file create w.r.t. allowing an initial delete
5914 * on close, probably because in Windows there is a new handle to the
5915 * new file. If initial delete on close was requested but not
5916 * originally set, we need to set it here. This is probably not 100% correct,
5917 * but will work for the CIFSFS client which in non-posix mode
5918 * depends on these semantics. JRA.
5921 if (create_options & FILE_DELETE_ON_CLOSE) {
5922 status = can_set_delete_on_close(fsp, True, 0);
5924 if (NT_STATUS_IS_OK(status)) {
5925 /* Note that here we set the *inital* delete on close flag,
5926 * not the regular one. The magic gets handled in close. */
5927 fsp->initial_delete_on_close = True;
5930 TALLOC_FREE(lck);
5931 return NT_STATUS_OK;
5934 TALLOC_FREE(lck);
5936 if (errno == ENOTDIR || errno == EISDIR) {
5937 status = NT_STATUS_OBJECT_NAME_COLLISION;
5938 } else {
5939 status = map_nt_error_from_unix(errno);
5942 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5943 nt_errstr(status), fsp->fsp_name,newname));
5945 return status;
5948 /****************************************************************************
5949 The guts of the rename command, split out so it may be called by the NT SMB
5950 code.
5951 ****************************************************************************/
5953 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5954 connection_struct *conn,
5955 struct smb_request *req,
5956 const char *name_in,
5957 const char *newname_in,
5958 uint32 attrs,
5959 bool replace_if_exists,
5960 bool src_has_wild,
5961 bool dest_has_wild,
5962 uint32_t access_mask)
5964 struct smb_filename *smb_fname = NULL;
5965 struct smb_filename *smb_fname_new = NULL;
5966 char *directory = NULL;
5967 char *mask = NULL;
5968 char *name = NULL;
5969 char *newname = NULL;
5970 char *p;
5971 int count=0;
5972 NTSTATUS status = NT_STATUS_OK;
5973 struct smb_Dir *dir_hnd = NULL;
5974 const char *dname;
5975 long offset = 0;
5976 int create_options = 0;
5977 bool posix_pathnames = lp_posix_pathnames();
5979 status = unix_convert(ctx, conn, name_in, &smb_fname,
5980 src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
5981 if (!NT_STATUS_IS_OK(status)) {
5982 goto out;
5985 status = get_full_smb_filename(ctx, smb_fname, &name);
5986 if (!NT_STATUS_IS_OK(status)) {
5987 goto out;
5990 status = unix_convert(ctx, conn, newname_in, &smb_fname_new,
5991 (UCF_SAVE_LCOMP |
5992 (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
5993 if (!NT_STATUS_IS_OK(status)) {
5994 goto out;
5997 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
5998 if (!NT_STATUS_IS_OK(status)) {
5999 goto out;
6003 * Split the old name into directory and last component
6004 * strings. Note that unix_convert may have stripped off a
6005 * leading ./ from both name and newname if the rename is
6006 * at the root of the share. We need to make sure either both
6007 * name and newname contain a / character or neither of them do
6008 * as this is checked in resolve_wildcards().
6011 p = strrchr_m(name,'/');
6012 if (!p) {
6013 directory = talloc_strdup(ctx, ".");
6014 if (!directory) {
6015 status = NT_STATUS_NO_MEMORY;
6016 goto out;
6018 mask = name;
6019 } else {
6020 *p = 0;
6021 directory = talloc_strdup(ctx, name);
6022 if (!directory) {
6023 status = NT_STATUS_NO_MEMORY;
6024 goto out;
6026 mask = p+1;
6027 *p = '/'; /* Replace needed for exceptional test below. */
6031 * We should only check the mangled cache
6032 * here if unix_convert failed. This means
6033 * that the path in 'mask' doesn't exist
6034 * on the file system and so we need to look
6035 * for a possible mangle. This patch from
6036 * Tine Smukavec <valentin.smukavec@hermes.si>.
6039 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask, conn->params)) {
6040 char *new_mask = NULL;
6041 mangle_lookup_name_from_8_3(ctx,
6042 mask,
6043 &new_mask,
6044 conn->params );
6045 if (new_mask) {
6046 mask = new_mask;
6050 if (!src_has_wild) {
6051 files_struct *fsp;
6054 * No wildcards - just process the one file.
6056 /* Add a terminating '/' to the directory name. */
6057 directory = talloc_asprintf_append(directory,
6058 "/%s",
6059 mask);
6060 if (!directory) {
6061 status = NT_STATUS_NO_MEMORY;
6062 goto out;
6065 /* Ensure newname contains a '/' also */
6066 if(strrchr_m(newname,'/') == 0) {
6067 newname = talloc_asprintf(ctx,
6068 "./%s",
6069 newname);
6070 if (!newname) {
6071 status = NT_STATUS_NO_MEMORY;
6072 goto out;
6076 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6077 "case_preserve = %d, short case preserve = %d, "
6078 "directory = %s, newname = %s, "
6079 "last_component_dest = %s\n",
6080 conn->case_sensitive, conn->case_preserve,
6081 conn->short_case_preserve, directory,
6082 newname, smb_fname_new->original_lcomp));
6084 /* The dest name still may have wildcards. */
6085 if (dest_has_wild) {
6086 char *mod_newname = NULL;
6087 if (!resolve_wildcards(ctx,
6088 directory,newname,&mod_newname)) {
6089 DEBUG(6, ("rename_internals: resolve_wildcards "
6090 "%s %s failed\n",
6091 directory,
6092 newname));
6093 status = NT_STATUS_NO_MEMORY;
6094 goto out;
6096 newname = mod_newname;
6099 ZERO_STRUCT(smb_fname->st);
6100 if (posix_pathnames) {
6101 SMB_VFS_LSTAT(conn, directory, &smb_fname->st);
6102 } else {
6103 SMB_VFS_STAT(conn, directory, &smb_fname->st);
6106 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6107 create_options |= FILE_DIRECTORY_FILE;
6110 status = SMB_VFS_CREATE_FILE(
6111 conn, /* conn */
6112 req, /* req */
6113 0, /* root_dir_fid */
6114 directory, /* fname */
6115 0, /* create_file_flags */
6116 access_mask, /* access_mask */
6117 (FILE_SHARE_READ | /* share_access */
6118 FILE_SHARE_WRITE),
6119 FILE_OPEN, /* create_disposition*/
6120 create_options, /* create_options */
6121 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6122 0, /* oplock_request */
6123 0, /* allocation_size */
6124 NULL, /* sd */
6125 NULL, /* ea_list */
6126 &fsp, /* result */
6127 NULL, /* pinfo */
6128 &smb_fname->st); /* psbuf */
6130 if (!NT_STATUS_IS_OK(status)) {
6131 DEBUG(3, ("Could not open rename source %s: %s\n",
6132 directory, nt_errstr(status)));
6133 goto out;
6136 status = rename_internals_fsp(conn, fsp, newname,
6137 smb_fname_new->original_lcomp,
6138 attrs, replace_if_exists);
6140 close_file(req, fsp, NORMAL_CLOSE);
6142 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6143 nt_errstr(status), directory,newname));
6145 goto out;
6149 * Wildcards - process each file that matches.
6151 if (strequal(mask,"????????.???")) {
6152 mask[0] = '*';
6153 mask[1] = '\0';
6156 status = check_name(conn, directory);
6157 if (!NT_STATUS_IS_OK(status)) {
6158 goto out;
6161 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
6162 if (dir_hnd == NULL) {
6163 status = map_nt_error_from_unix(errno);
6164 goto out;
6167 status = NT_STATUS_NO_SUCH_FILE;
6169 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6170 * - gentest fix. JRA
6173 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname->st))) {
6174 files_struct *fsp = NULL;
6175 char *fname = NULL;
6176 char *destname = NULL;
6177 bool sysdir_entry = False;
6179 /* Quick check for "." and ".." */
6180 if (ISDOT(dname) || ISDOTDOT(dname)) {
6181 if (attrs & aDIR) {
6182 sysdir_entry = True;
6183 } else {
6184 continue;
6188 if (!is_visible_file(conn, directory, dname, &smb_fname->st,
6189 False)) {
6190 continue;
6193 if(!mask_match(dname, mask, conn->case_sensitive)) {
6194 continue;
6197 if (sysdir_entry) {
6198 status = NT_STATUS_OBJECT_NAME_INVALID;
6199 break;
6202 fname = talloc_asprintf(ctx,
6203 "%s/%s",
6204 directory,
6205 dname);
6206 if (!fname) {
6207 status = NT_STATUS_NO_MEMORY;
6208 goto out;
6211 if (!resolve_wildcards(ctx,
6212 fname,newname,&destname)) {
6213 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6214 fname, destname));
6215 TALLOC_FREE(fname);
6216 continue;
6218 if (!destname) {
6219 status = NT_STATUS_NO_MEMORY;
6220 goto out;
6223 ZERO_STRUCT(smb_fname->st);
6224 if (posix_pathnames) {
6225 SMB_VFS_LSTAT(conn, fname, &smb_fname->st);
6226 } else {
6227 SMB_VFS_STAT(conn, fname, &smb_fname->st);
6230 create_options = 0;
6232 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6233 create_options |= FILE_DIRECTORY_FILE;
6236 status = SMB_VFS_CREATE_FILE(
6237 conn, /* conn */
6238 req, /* req */
6239 0, /* root_dir_fid */
6240 fname, /* fname */
6241 0, /* create_file_flags */
6242 access_mask, /* access_mask */
6243 (FILE_SHARE_READ | /* share_access */
6244 FILE_SHARE_WRITE),
6245 FILE_OPEN, /* create_disposition*/
6246 create_options, /* create_options */
6247 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6248 0, /* oplock_request */
6249 0, /* allocation_size */
6250 NULL, /* sd */
6251 NULL, /* ea_list */
6252 &fsp, /* result */
6253 NULL, /* pinfo */
6254 &smb_fname->st); /* psbuf */
6256 if (!NT_STATUS_IS_OK(status)) {
6257 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6258 "returned %s rename %s -> %s\n",
6259 nt_errstr(status), directory, newname));
6260 break;
6263 status = rename_internals_fsp(conn, fsp, destname, dname,
6264 attrs, replace_if_exists);
6266 close_file(req, fsp, NORMAL_CLOSE);
6268 if (!NT_STATUS_IS_OK(status)) {
6269 DEBUG(3, ("rename_internals_fsp returned %s for "
6270 "rename %s -> %s\n", nt_errstr(status),
6271 directory, newname));
6272 break;
6275 count++;
6277 DEBUG(3,("rename_internals: doing rename on %s -> "
6278 "%s\n",fname,destname));
6280 TALLOC_FREE(fname);
6281 TALLOC_FREE(destname);
6283 TALLOC_FREE(dir_hnd);
6285 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6286 status = map_nt_error_from_unix(errno);
6289 out:
6290 TALLOC_FREE(smb_fname);
6291 TALLOC_FREE(smb_fname_new);
6292 return status;
6295 /****************************************************************************
6296 Reply to a mv.
6297 ****************************************************************************/
6299 void reply_mv(struct smb_request *req)
6301 connection_struct *conn = req->conn;
6302 char *name = NULL;
6303 char *newname = NULL;
6304 const char *p;
6305 uint32 attrs;
6306 NTSTATUS status;
6307 bool src_has_wcard = False;
6308 bool dest_has_wcard = False;
6309 TALLOC_CTX *ctx = talloc_tos();
6311 START_PROFILE(SMBmv);
6313 if (req->wct < 1) {
6314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6315 END_PROFILE(SMBmv);
6316 return;
6319 attrs = SVAL(req->vwv+0, 0);
6321 p = (const char *)req->buf + 1;
6322 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6323 &status, &src_has_wcard);
6324 if (!NT_STATUS_IS_OK(status)) {
6325 reply_nterror(req, status);
6326 END_PROFILE(SMBmv);
6327 return;
6329 p++;
6330 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6331 &status, &dest_has_wcard);
6332 if (!NT_STATUS_IS_OK(status)) {
6333 reply_nterror(req, status);
6334 END_PROFILE(SMBmv);
6335 return;
6338 status = resolve_dfspath_wcard(ctx, conn,
6339 req->flags2 & FLAGS2_DFS_PATHNAMES,
6340 name,
6341 &name,
6342 &src_has_wcard);
6343 if (!NT_STATUS_IS_OK(status)) {
6344 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6345 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6346 ERRSRV, ERRbadpath);
6347 END_PROFILE(SMBmv);
6348 return;
6350 reply_nterror(req, status);
6351 END_PROFILE(SMBmv);
6352 return;
6355 status = resolve_dfspath_wcard(ctx, conn,
6356 req->flags2 & FLAGS2_DFS_PATHNAMES,
6357 newname,
6358 &newname,
6359 &dest_has_wcard);
6360 if (!NT_STATUS_IS_OK(status)) {
6361 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6362 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6363 ERRSRV, ERRbadpath);
6364 END_PROFILE(SMBmv);
6365 return;
6367 reply_nterror(req, status);
6368 END_PROFILE(SMBmv);
6369 return;
6372 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6374 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6375 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6376 if (!NT_STATUS_IS_OK(status)) {
6377 if (open_was_deferred(req->mid)) {
6378 /* We have re-scheduled this call. */
6379 END_PROFILE(SMBmv);
6380 return;
6382 reply_nterror(req, status);
6383 END_PROFILE(SMBmv);
6384 return;
6387 reply_outbuf(req, 0, 0);
6389 END_PROFILE(SMBmv);
6390 return;
6393 /*******************************************************************
6394 Copy a file as part of a reply_copy.
6395 ******************************************************************/
6398 * TODO: check error codes on all callers
6401 NTSTATUS copy_file(TALLOC_CTX *ctx,
6402 connection_struct *conn,
6403 const char *src,
6404 const char *dest1,
6405 int ofun,
6406 int count,
6407 bool target_is_directory)
6409 SMB_STRUCT_STAT src_sbuf, sbuf2;
6410 SMB_OFF_T ret=-1;
6411 files_struct *fsp1,*fsp2;
6412 char *dest = NULL;
6413 uint32 dosattrs;
6414 uint32 new_create_disposition;
6415 NTSTATUS status;
6417 dest = talloc_strdup(ctx, dest1);
6418 if (!dest) {
6419 return NT_STATUS_NO_MEMORY;
6421 if (target_is_directory) {
6422 const char *p = strrchr_m(src,'/');
6423 if (p) {
6424 p++;
6425 } else {
6426 p = src;
6428 dest = talloc_asprintf_append(dest,
6429 "/%s",
6431 if (!dest) {
6432 return NT_STATUS_NO_MEMORY;
6436 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6437 TALLOC_FREE(dest);
6438 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6441 if (!target_is_directory && count) {
6442 new_create_disposition = FILE_OPEN;
6443 } else {
6444 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6445 NULL, NULL, &new_create_disposition, NULL)) {
6446 TALLOC_FREE(dest);
6447 return NT_STATUS_INVALID_PARAMETER;
6451 status = SMB_VFS_CREATE_FILE(
6452 conn, /* conn */
6453 NULL, /* req */
6454 0, /* root_dir_fid */
6455 src, /* fname */
6456 0, /* create_file_flags */
6457 FILE_GENERIC_READ, /* access_mask */
6458 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6459 FILE_OPEN, /* create_disposition*/
6460 0, /* create_options */
6461 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6462 INTERNAL_OPEN_ONLY, /* oplock_request */
6463 0, /* allocation_size */
6464 NULL, /* sd */
6465 NULL, /* ea_list */
6466 &fsp1, /* result */
6467 NULL, /* pinfo */
6468 &src_sbuf); /* psbuf */
6470 if (!NT_STATUS_IS_OK(status)) {
6471 TALLOC_FREE(dest);
6472 return status;
6475 dosattrs = dos_mode(conn, src, &src_sbuf);
6476 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6477 ZERO_STRUCTP(&sbuf2);
6480 status = SMB_VFS_CREATE_FILE(
6481 conn, /* conn */
6482 NULL, /* req */
6483 0, /* root_dir_fid */
6484 dest, /* fname */
6485 0, /* create_file_flags */
6486 FILE_GENERIC_WRITE, /* access_mask */
6487 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6488 new_create_disposition, /* create_disposition*/
6489 0, /* create_options */
6490 dosattrs, /* file_attributes */
6491 INTERNAL_OPEN_ONLY, /* oplock_request */
6492 0, /* allocation_size */
6493 NULL, /* sd */
6494 NULL, /* ea_list */
6495 &fsp2, /* result */
6496 NULL, /* pinfo */
6497 &sbuf2); /* psbuf */
6499 TALLOC_FREE(dest);
6501 if (!NT_STATUS_IS_OK(status)) {
6502 close_file(NULL, fsp1, ERROR_CLOSE);
6503 return status;
6506 if ((ofun&3) == 1) {
6507 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6508 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6510 * Stop the copy from occurring.
6512 ret = -1;
6513 src_sbuf.st_ex_size = 0;
6517 if (src_sbuf.st_ex_size) {
6518 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_ex_size);
6521 close_file(NULL, fsp1, NORMAL_CLOSE);
6523 /* Ensure the modtime is set correctly on the destination file. */
6524 set_close_write_time(fsp2, src_sbuf.st_ex_mtime);
6527 * As we are opening fsp1 read-only we only expect
6528 * an error on close on fsp2 if we are out of space.
6529 * Thus we don't look at the error return from the
6530 * close of fsp1.
6532 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6534 if (!NT_STATUS_IS_OK(status)) {
6535 return status;
6538 if (ret != (SMB_OFF_T)src_sbuf.st_ex_size) {
6539 return NT_STATUS_DISK_FULL;
6542 return NT_STATUS_OK;
6545 /****************************************************************************
6546 Reply to a file copy.
6547 ****************************************************************************/
6549 void reply_copy(struct smb_request *req)
6551 connection_struct *conn = req->conn;
6552 struct smb_filename *smb_fname = NULL;
6553 struct smb_filename *smb_fname_new = NULL;
6554 char *name = NULL;
6555 char *newname = NULL;
6556 char *directory = NULL;
6557 const char *mask = NULL;
6558 const char mask_star[] = "*";
6559 const char *p;
6560 int count=0;
6561 int error = ERRnoaccess;
6562 int err = 0;
6563 int tid2;
6564 int ofun;
6565 int flags;
6566 bool target_is_directory=False;
6567 bool source_has_wild = False;
6568 bool dest_has_wild = False;
6569 NTSTATUS status;
6570 TALLOC_CTX *ctx = talloc_tos();
6572 START_PROFILE(SMBcopy);
6574 if (req->wct < 3) {
6575 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6576 goto out;
6579 tid2 = SVAL(req->vwv+0, 0);
6580 ofun = SVAL(req->vwv+1, 0);
6581 flags = SVAL(req->vwv+2, 0);
6583 p = (const char *)req->buf;
6584 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6585 &status, &source_has_wild);
6586 if (!NT_STATUS_IS_OK(status)) {
6587 reply_nterror(req, status);
6588 goto out;
6590 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6591 &status, &dest_has_wild);
6592 if (!NT_STATUS_IS_OK(status)) {
6593 reply_nterror(req, status);
6594 goto out;
6597 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6599 if (tid2 != conn->cnum) {
6600 /* can't currently handle inter share copies XXXX */
6601 DEBUG(3,("Rejecting inter-share copy\n"));
6602 reply_doserror(req, ERRSRV, ERRinvdevice);
6603 goto out;
6606 status = resolve_dfspath_wcard(ctx, conn,
6607 req->flags2 & FLAGS2_DFS_PATHNAMES,
6608 name,
6609 &name,
6610 &source_has_wild);
6611 if (!NT_STATUS_IS_OK(status)) {
6612 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6613 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6614 ERRSRV, ERRbadpath);
6615 goto out;
6617 reply_nterror(req, status);
6618 goto out;
6621 status = resolve_dfspath_wcard(ctx, conn,
6622 req->flags2 & FLAGS2_DFS_PATHNAMES,
6623 newname,
6624 &newname,
6625 &dest_has_wild);
6626 if (!NT_STATUS_IS_OK(status)) {
6627 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6628 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6629 ERRSRV, ERRbadpath);
6630 goto out;
6632 reply_nterror(req, status);
6633 goto out;
6636 status = unix_convert(ctx, conn, name, &smb_fname,
6637 source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6638 if (!NT_STATUS_IS_OK(status)) {
6639 reply_nterror(req, status);
6640 goto out;
6643 status = get_full_smb_filename(ctx, smb_fname, &name);
6644 if (!NT_STATUS_IS_OK(status)) {
6645 reply_nterror(req, status);
6646 goto out;
6649 status = unix_convert(ctx, conn, newname, &smb_fname_new,
6650 dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
6651 if (!NT_STATUS_IS_OK(status)) {
6652 reply_nterror(req, status);
6653 goto out;
6656 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
6657 if (!NT_STATUS_IS_OK(status)) {
6658 reply_nterror(req, status);
6659 goto out;
6662 target_is_directory = VALID_STAT_OF_DIR(smb_fname_new->st);
6664 if ((flags&1) && target_is_directory) {
6665 reply_doserror(req, ERRDOS, ERRbadfile);
6666 goto out;
6669 if ((flags&2) && !target_is_directory) {
6670 reply_doserror(req, ERRDOS, ERRbadpath);
6671 goto out;
6674 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname->st)) {
6675 /* wants a tree copy! XXXX */
6676 DEBUG(3,("Rejecting tree copy\n"));
6677 reply_doserror(req, ERRSRV, ERRerror);
6678 goto out;
6681 p = strrchr_m(name,'/');
6682 if (p != NULL) {
6683 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6684 mask = p+1;
6685 } else {
6686 directory = talloc_strdup(ctx, "./");
6687 mask = name;
6690 if (!directory) {
6691 reply_nterror(req, NT_STATUS_NO_MEMORY);
6692 goto out;
6696 * We should only check the mangled cache
6697 * here if unix_convert failed. This means
6698 * that the path in 'mask' doesn't exist
6699 * on the file system and so we need to look
6700 * for a possible mangle. This patch from
6701 * Tine Smukavec <valentin.smukavec@hermes.si>.
6704 if (!VALID_STAT(smb_fname->st) &&
6705 mangle_is_mangled(mask, conn->params)) {
6706 char *new_mask = NULL;
6707 mangle_lookup_name_from_8_3(ctx,
6708 mask,
6709 &new_mask,
6710 conn->params );
6711 if (new_mask) {
6712 mask = new_mask;
6716 if (!source_has_wild) {
6717 directory = talloc_asprintf_append(directory,
6718 "/%s",
6719 mask);
6720 if (dest_has_wild) {
6721 char *mod_newname = NULL;
6722 if (!resolve_wildcards(ctx,
6723 directory,newname,&mod_newname)) {
6724 reply_nterror(req, NT_STATUS_NO_MEMORY);
6725 goto out;
6727 newname = mod_newname;
6730 status = check_name(conn, directory);
6731 if (!NT_STATUS_IS_OK(status)) {
6732 reply_nterror(req, status);
6733 goto out;
6736 status = check_name(conn, newname);
6737 if (!NT_STATUS_IS_OK(status)) {
6738 reply_nterror(req, status);
6739 goto out;
6742 status = copy_file(ctx,conn,directory,newname,ofun,
6743 count,target_is_directory);
6745 if(!NT_STATUS_IS_OK(status)) {
6746 reply_nterror(req, status);
6747 goto out;
6748 } else {
6749 count++;
6751 } else {
6752 struct smb_Dir *dir_hnd = NULL;
6753 const char *dname = NULL;
6754 long offset = 0;
6756 if (strequal(mask,"????????.???")) {
6757 mask = mask_star;
6760 status = check_name(conn, directory);
6761 if (!NT_STATUS_IS_OK(status)) {
6762 reply_nterror(req, status);
6763 goto out;
6766 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6767 if (dir_hnd == NULL) {
6768 status = map_nt_error_from_unix(errno);
6769 reply_nterror(req, status);
6770 goto out;
6773 error = ERRbadfile;
6775 while ((dname = ReadDirName(dir_hnd, &offset,
6776 &smb_fname->st))) {
6777 char *destname = NULL;
6778 char *fname = NULL;
6780 if (ISDOT(dname) || ISDOTDOT(dname)) {
6781 continue;
6784 if (!is_visible_file(conn, directory, dname,
6785 &smb_fname->st, False)) {
6786 continue;
6789 if(!mask_match(dname, mask, conn->case_sensitive)) {
6790 continue;
6793 error = ERRnoaccess;
6794 fname = talloc_asprintf(ctx,
6795 "%s/%s",
6796 directory,
6797 dname);
6798 if (!fname) {
6799 TALLOC_FREE(dir_hnd);
6800 reply_nterror(req, NT_STATUS_NO_MEMORY);
6801 goto out;
6804 if (!resolve_wildcards(ctx,
6805 fname,newname,&destname)) {
6806 continue;
6808 if (!destname) {
6809 TALLOC_FREE(dir_hnd);
6810 reply_nterror(req, NT_STATUS_NO_MEMORY);
6811 goto out;
6814 status = check_name(conn, fname);
6815 if (!NT_STATUS_IS_OK(status)) {
6816 TALLOC_FREE(dir_hnd);
6817 reply_nterror(req, status);
6818 goto out;
6821 status = check_name(conn, destname);
6822 if (!NT_STATUS_IS_OK(status)) {
6823 TALLOC_FREE(dir_hnd);
6824 reply_nterror(req, status);
6825 goto out;
6828 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6830 status = copy_file(ctx,conn,fname,destname,ofun,
6831 count,target_is_directory);
6832 if (NT_STATUS_IS_OK(status)) {
6833 count++;
6835 TALLOC_FREE(fname);
6836 TALLOC_FREE(destname);
6838 TALLOC_FREE(dir_hnd);
6841 if (count == 0) {
6842 if(err) {
6843 /* Error on close... */
6844 errno = err;
6845 reply_unixerror(req, ERRHRD, ERRgeneral);
6846 goto out;
6849 reply_doserror(req, ERRDOS, error);
6850 goto out;
6853 reply_outbuf(req, 1, 0);
6854 SSVAL(req->outbuf,smb_vwv0,count);
6855 out:
6856 TALLOC_FREE(smb_fname);
6857 TALLOC_FREE(smb_fname_new);
6858 END_PROFILE(SMBcopy);
6859 return;
6862 #undef DBGC_CLASS
6863 #define DBGC_CLASS DBGC_LOCKING
6865 /****************************************************************************
6866 Get a lock pid, dealing with large count requests.
6867 ****************************************************************************/
6869 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6870 bool large_file_format)
6872 if(!large_file_format)
6873 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6874 else
6875 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6878 /****************************************************************************
6879 Get a lock count, dealing with large count requests.
6880 ****************************************************************************/
6882 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6883 bool large_file_format)
6885 uint64_t count = 0;
6887 if(!large_file_format) {
6888 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6889 } else {
6891 #if defined(HAVE_LONGLONG)
6892 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6893 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6894 #else /* HAVE_LONGLONG */
6897 * NT4.x seems to be broken in that it sends large file (64 bit)
6898 * lockingX calls even if the CAP_LARGE_FILES was *not*
6899 * negotiated. For boxes without large unsigned ints truncate the
6900 * lock count by dropping the top 32 bits.
6903 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6904 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6905 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6906 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6907 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6910 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6911 #endif /* HAVE_LONGLONG */
6914 return count;
6917 #if !defined(HAVE_LONGLONG)
6918 /****************************************************************************
6919 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6920 ****************************************************************************/
6922 static uint32 map_lock_offset(uint32 high, uint32 low)
6924 unsigned int i;
6925 uint32 mask = 0;
6926 uint32 highcopy = high;
6929 * Try and find out how many significant bits there are in high.
6932 for(i = 0; highcopy; i++)
6933 highcopy >>= 1;
6936 * We use 31 bits not 32 here as POSIX
6937 * lock offsets may not be negative.
6940 mask = (~0) << (31 - i);
6942 if(low & mask)
6943 return 0; /* Fail. */
6945 high <<= (31 - i);
6947 return (high|low);
6949 #endif /* !defined(HAVE_LONGLONG) */
6951 /****************************************************************************
6952 Get a lock offset, dealing with large offset requests.
6953 ****************************************************************************/
6955 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6956 bool large_file_format, bool *err)
6958 uint64_t offset = 0;
6960 *err = False;
6962 if(!large_file_format) {
6963 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6964 } else {
6966 #if defined(HAVE_LONGLONG)
6967 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6968 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6969 #else /* HAVE_LONGLONG */
6972 * NT4.x seems to be broken in that it sends large file (64 bit)
6973 * lockingX calls even if the CAP_LARGE_FILES was *not*
6974 * negotiated. For boxes without large unsigned ints mangle the
6975 * lock offset by mapping the top 32 bits onto the lower 32.
6978 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6979 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6980 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6981 uint32 new_low = 0;
6983 if((new_low = map_lock_offset(high, low)) == 0) {
6984 *err = True;
6985 return (uint64_t)-1;
6988 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6989 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6990 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6991 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6994 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6995 #endif /* HAVE_LONGLONG */
6998 return offset;
7001 /****************************************************************************
7002 Reply to a lockingX request.
7003 ****************************************************************************/
7005 void reply_lockingX(struct smb_request *req)
7007 connection_struct *conn = req->conn;
7008 files_struct *fsp;
7009 unsigned char locktype;
7010 unsigned char oplocklevel;
7011 uint16 num_ulocks;
7012 uint16 num_locks;
7013 uint64_t count = 0, offset = 0;
7014 uint32 lock_pid;
7015 int32 lock_timeout;
7016 int i;
7017 const uint8_t *data;
7018 bool large_file_format;
7019 bool err;
7020 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7022 START_PROFILE(SMBlockingX);
7024 if (req->wct < 8) {
7025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7026 END_PROFILE(SMBlockingX);
7027 return;
7030 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7031 locktype = CVAL(req->vwv+3, 0);
7032 oplocklevel = CVAL(req->vwv+3, 1);
7033 num_ulocks = SVAL(req->vwv+6, 0);
7034 num_locks = SVAL(req->vwv+7, 0);
7035 lock_timeout = IVAL(req->vwv+4, 0);
7036 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7038 if (!check_fsp(conn, req, fsp)) {
7039 END_PROFILE(SMBlockingX);
7040 return;
7043 data = req->buf;
7045 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7046 /* we don't support these - and CANCEL_LOCK makes w2k
7047 and XP reboot so I don't really want to be
7048 compatible! (tridge) */
7049 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7050 END_PROFILE(SMBlockingX);
7051 return;
7054 /* Check if this is an oplock break on a file
7055 we have granted an oplock on.
7057 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7058 /* Client can insist on breaking to none. */
7059 bool break_to_none = (oplocklevel == 0);
7060 bool result;
7062 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7063 "for fnum = %d\n", (unsigned int)oplocklevel,
7064 fsp->fnum ));
7067 * Make sure we have granted an exclusive or batch oplock on
7068 * this file.
7071 if (fsp->oplock_type == 0) {
7073 /* The Samba4 nbench simulator doesn't understand
7074 the difference between break to level2 and break
7075 to none from level2 - it sends oplock break
7076 replies in both cases. Don't keep logging an error
7077 message here - just ignore it. JRA. */
7079 DEBUG(5,("reply_lockingX: Error : oplock break from "
7080 "client for fnum = %d (oplock=%d) and no "
7081 "oplock granted on this file (%s).\n",
7082 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
7084 /* if this is a pure oplock break request then don't
7085 * send a reply */
7086 if (num_locks == 0 && num_ulocks == 0) {
7087 END_PROFILE(SMBlockingX);
7088 return;
7089 } else {
7090 END_PROFILE(SMBlockingX);
7091 reply_doserror(req, ERRDOS, ERRlock);
7092 return;
7096 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7097 (break_to_none)) {
7098 result = remove_oplock(fsp);
7099 } else {
7100 result = downgrade_oplock(fsp);
7103 if (!result) {
7104 DEBUG(0, ("reply_lockingX: error in removing "
7105 "oplock on file %s\n", fsp->fsp_name));
7106 /* Hmmm. Is this panic justified? */
7107 smb_panic("internal tdb error");
7110 reply_to_oplock_break_requests(fsp);
7112 /* if this is a pure oplock break request then don't send a
7113 * reply */
7114 if (num_locks == 0 && num_ulocks == 0) {
7115 /* Sanity check - ensure a pure oplock break is not a
7116 chained request. */
7117 if(CVAL(req->vwv+0, 0) != 0xff)
7118 DEBUG(0,("reply_lockingX: Error : pure oplock "
7119 "break is a chained %d request !\n",
7120 (unsigned int)CVAL(req->vwv+0, 0)));
7121 END_PROFILE(SMBlockingX);
7122 return;
7126 if (req->buflen <
7127 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7129 END_PROFILE(SMBlockingX);
7130 return;
7133 /* Data now points at the beginning of the list
7134 of smb_unlkrng structs */
7135 for(i = 0; i < (int)num_ulocks; i++) {
7136 lock_pid = get_lock_pid( data, i, large_file_format);
7137 count = get_lock_count( data, i, large_file_format);
7138 offset = get_lock_offset( data, i, large_file_format, &err);
7141 * There is no error code marked "stupid client bug".... :-).
7143 if(err) {
7144 END_PROFILE(SMBlockingX);
7145 reply_doserror(req, ERRDOS, ERRnoaccess);
7146 return;
7149 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
7150 "pid %u, file %s\n", (double)offset, (double)count,
7151 (unsigned int)lock_pid, fsp->fsp_name ));
7153 status = do_unlock(smbd_messaging_context(),
7154 fsp,
7155 lock_pid,
7156 count,
7157 offset,
7158 WINDOWS_LOCK);
7160 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
7161 nt_errstr(status)));
7163 if (NT_STATUS_V(status)) {
7164 END_PROFILE(SMBlockingX);
7165 reply_nterror(req, status);
7166 return;
7170 /* Setup the timeout in seconds. */
7172 if (!lp_blocking_locks(SNUM(conn))) {
7173 lock_timeout = 0;
7176 /* Now do any requested locks */
7177 data += ((large_file_format ? 20 : 10)*num_ulocks);
7179 /* Data now points at the beginning of the list
7180 of smb_lkrng structs */
7182 for(i = 0; i < (int)num_locks; i++) {
7183 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
7184 READ_LOCK:WRITE_LOCK);
7185 lock_pid = get_lock_pid( data, i, large_file_format);
7186 count = get_lock_count( data, i, large_file_format);
7187 offset = get_lock_offset( data, i, large_file_format, &err);
7190 * There is no error code marked "stupid client bug".... :-).
7192 if(err) {
7193 END_PROFILE(SMBlockingX);
7194 reply_doserror(req, ERRDOS, ERRnoaccess);
7195 return;
7198 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
7199 "%u, file %s timeout = %d\n", (double)offset,
7200 (double)count, (unsigned int)lock_pid,
7201 fsp->fsp_name, (int)lock_timeout ));
7203 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7204 struct blocking_lock_record *blr = NULL;
7206 if (lp_blocking_locks(SNUM(conn))) {
7208 /* Schedule a message to ourselves to
7209 remove the blocking lock record and
7210 return the right error. */
7212 blr = blocking_lock_cancel(fsp,
7213 lock_pid,
7214 offset,
7215 count,
7216 WINDOWS_LOCK,
7217 locktype,
7218 NT_STATUS_FILE_LOCK_CONFLICT);
7219 if (blr == NULL) {
7220 END_PROFILE(SMBlockingX);
7221 reply_nterror(
7222 req,
7223 NT_STATUS_DOS(
7224 ERRDOS,
7225 ERRcancelviolation));
7226 return;
7229 /* Remove a matching pending lock. */
7230 status = do_lock_cancel(fsp,
7231 lock_pid,
7232 count,
7233 offset,
7234 WINDOWS_LOCK,
7235 blr);
7236 } else {
7237 bool blocking_lock = lock_timeout ? True : False;
7238 bool defer_lock = False;
7239 struct byte_range_lock *br_lck;
7240 uint32 block_smbpid;
7242 br_lck = do_lock(smbd_messaging_context(),
7243 fsp,
7244 lock_pid,
7245 count,
7246 offset,
7247 lock_type,
7248 WINDOWS_LOCK,
7249 blocking_lock,
7250 &status,
7251 &block_smbpid,
7252 NULL);
7254 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7255 /* Windows internal resolution for blocking locks seems
7256 to be about 200ms... Don't wait for less than that. JRA. */
7257 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
7258 lock_timeout = lp_lock_spin_time();
7260 defer_lock = True;
7263 /* This heuristic seems to match W2K3 very well. If a
7264 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7265 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7266 far as I can tell. Replacement for do_lock_spin(). JRA. */
7268 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7269 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7270 defer_lock = True;
7271 lock_timeout = lp_lock_spin_time();
7274 if (br_lck && defer_lock) {
7276 * A blocking lock was requested. Package up
7277 * this smb into a queued request and push it
7278 * onto the blocking lock queue.
7280 if(push_blocking_lock_request(br_lck,
7281 req,
7282 fsp,
7283 lock_timeout,
7285 lock_pid,
7286 lock_type,
7287 WINDOWS_LOCK,
7288 offset,
7289 count,
7290 block_smbpid)) {
7291 TALLOC_FREE(br_lck);
7292 END_PROFILE(SMBlockingX);
7293 return;
7297 TALLOC_FREE(br_lck);
7300 if (NT_STATUS_V(status)) {
7301 END_PROFILE(SMBlockingX);
7302 reply_nterror(req, status);
7303 return;
7307 /* If any of the above locks failed, then we must unlock
7308 all of the previous locks (X/Open spec). */
7310 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
7311 (i != num_locks) &&
7312 (num_locks != 0)) {
7314 * Ensure we don't do a remove on the lock that just failed,
7315 * as under POSIX rules, if we have a lock already there, we
7316 * will delete it (and we shouldn't) .....
7318 for(i--; i >= 0; i--) {
7319 lock_pid = get_lock_pid( data, i, large_file_format);
7320 count = get_lock_count( data, i, large_file_format);
7321 offset = get_lock_offset( data, i, large_file_format,
7322 &err);
7325 * There is no error code marked "stupid client
7326 * bug".... :-).
7328 if(err) {
7329 END_PROFILE(SMBlockingX);
7330 reply_doserror(req, ERRDOS, ERRnoaccess);
7331 return;
7334 do_unlock(smbd_messaging_context(),
7335 fsp,
7336 lock_pid,
7337 count,
7338 offset,
7339 WINDOWS_LOCK);
7341 END_PROFILE(SMBlockingX);
7342 reply_nterror(req, status);
7343 return;
7346 reply_outbuf(req, 2, 0);
7348 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7349 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7351 END_PROFILE(SMBlockingX);
7352 chain_reply(req);
7355 #undef DBGC_CLASS
7356 #define DBGC_CLASS DBGC_ALL
7358 /****************************************************************************
7359 Reply to a SMBreadbmpx (read block multiplex) request.
7360 Always reply with an error, if someone has a platform really needs this,
7361 please contact vl@samba.org
7362 ****************************************************************************/
7364 void reply_readbmpx(struct smb_request *req)
7366 START_PROFILE(SMBreadBmpx);
7367 reply_doserror(req, ERRSRV, ERRuseSTD);
7368 END_PROFILE(SMBreadBmpx);
7369 return;
7372 /****************************************************************************
7373 Reply to a SMBreadbs (read block multiplex secondary) request.
7374 Always reply with an error, if someone has a platform really needs this,
7375 please contact vl@samba.org
7376 ****************************************************************************/
7378 void reply_readbs(struct smb_request *req)
7380 START_PROFILE(SMBreadBs);
7381 reply_doserror(req, ERRSRV, ERRuseSTD);
7382 END_PROFILE(SMBreadBs);
7383 return;
7386 /****************************************************************************
7387 Reply to a SMBsetattrE.
7388 ****************************************************************************/
7390 void reply_setattrE(struct smb_request *req)
7392 connection_struct *conn = req->conn;
7393 struct smb_file_time ft;
7394 files_struct *fsp;
7395 SMB_STRUCT_STAT sbuf;
7396 NTSTATUS status;
7398 START_PROFILE(SMBsetattrE);
7399 ZERO_STRUCT(ft);
7401 if (req->wct < 7) {
7402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7403 END_PROFILE(SMBsetattrE);
7404 return;
7407 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7409 if(!fsp || (fsp->conn != conn)) {
7410 reply_doserror(req, ERRDOS, ERRbadfid);
7411 END_PROFILE(SMBsetattrE);
7412 return;
7417 * Convert the DOS times into unix times.
7420 ft.atime = convert_time_t_to_timespec(
7421 srv_make_unix_date2(req->vwv+3));
7422 ft.mtime = convert_time_t_to_timespec(
7423 srv_make_unix_date2(req->vwv+5));
7424 ft.create_time = convert_time_t_to_timespec(
7425 srv_make_unix_date2(req->vwv+1));
7427 reply_outbuf(req, 0, 0);
7430 * Patch from Ray Frush <frush@engr.colostate.edu>
7431 * Sometimes times are sent as zero - ignore them.
7434 /* Ensure we have a valid stat struct for the source. */
7435 if (fsp->fh->fd != -1) {
7436 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7437 status = map_nt_error_from_unix(errno);
7438 reply_nterror(req, status);
7439 END_PROFILE(SMBsetattrE);
7440 return;
7442 } else {
7443 int ret = -1;
7445 if (fsp->posix_open) {
7446 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
7447 } else {
7448 ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
7450 if (ret == -1) {
7451 status = map_nt_error_from_unix(errno);
7452 reply_nterror(req, status);
7453 END_PROFILE(SMBsetattrE);
7454 return;
7458 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7459 &sbuf, &ft, true);
7460 if (!NT_STATUS_IS_OK(status)) {
7461 reply_doserror(req, ERRDOS, ERRnoaccess);
7462 END_PROFILE(SMBsetattrE);
7463 return;
7466 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7467 " createtime=%u\n",
7468 fsp->fnum,
7469 (unsigned int)ft.atime.tv_sec,
7470 (unsigned int)ft.mtime.tv_sec,
7471 (unsigned int)ft.create_time.tv_sec
7474 END_PROFILE(SMBsetattrE);
7475 return;
7479 /* Back from the dead for OS/2..... JRA. */
7481 /****************************************************************************
7482 Reply to a SMBwritebmpx (write block multiplex primary) request.
7483 Always reply with an error, if someone has a platform really needs this,
7484 please contact vl@samba.org
7485 ****************************************************************************/
7487 void reply_writebmpx(struct smb_request *req)
7489 START_PROFILE(SMBwriteBmpx);
7490 reply_doserror(req, ERRSRV, ERRuseSTD);
7491 END_PROFILE(SMBwriteBmpx);
7492 return;
7495 /****************************************************************************
7496 Reply to a SMBwritebs (write block multiplex secondary) request.
7497 Always reply with an error, if someone has a platform really needs this,
7498 please contact vl@samba.org
7499 ****************************************************************************/
7501 void reply_writebs(struct smb_request *req)
7503 START_PROFILE(SMBwriteBs);
7504 reply_doserror(req, ERRSRV, ERRuseSTD);
7505 END_PROFILE(SMBwriteBs);
7506 return;
7509 /****************************************************************************
7510 Reply to a SMBgetattrE.
7511 ****************************************************************************/
7513 void reply_getattrE(struct smb_request *req)
7515 connection_struct *conn = req->conn;
7516 SMB_STRUCT_STAT sbuf;
7517 int mode;
7518 files_struct *fsp;
7519 struct timespec create_ts;
7521 START_PROFILE(SMBgetattrE);
7523 if (req->wct < 1) {
7524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7525 END_PROFILE(SMBgetattrE);
7526 return;
7529 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7531 if(!fsp || (fsp->conn != conn)) {
7532 reply_doserror(req, ERRDOS, ERRbadfid);
7533 END_PROFILE(SMBgetattrE);
7534 return;
7537 /* Do an fstat on this file */
7538 if(fsp_stat(fsp, &sbuf)) {
7539 reply_unixerror(req, ERRDOS, ERRnoaccess);
7540 END_PROFILE(SMBgetattrE);
7541 return;
7544 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7547 * Convert the times into dos times. Set create
7548 * date to be last modify date as UNIX doesn't save
7549 * this.
7552 reply_outbuf(req, 11, 0);
7554 create_ts = sbuf.st_ex_btime;
7555 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7556 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7557 convert_timespec_to_time_t(sbuf.st_ex_atime));
7558 /* Should we check pending modtime here ? JRA */
7559 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7560 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7562 if (mode & aDIR) {
7563 SIVAL(req->outbuf, smb_vwv6, 0);
7564 SIVAL(req->outbuf, smb_vwv8, 0);
7565 } else {
7566 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7567 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7568 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7570 SSVAL(req->outbuf,smb_vwv10, mode);
7572 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7574 END_PROFILE(SMBgetattrE);
7575 return;