Add "store create time" parameter (docs to follow)
[Samba/fernandojvsilva.git] / source3 / smbd / reply.c
blob7b290a6b0ea909e6050d3052f393016f7999af8d
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, false);
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;
509 struct smbd_server_connection *sconn = smbd_server_conn;
512 * We only really use 4 bytes of the outbuf, but for the smb_setlen
513 * calculation & friends (srv_send_smb uses that) we need the full smb
514 * header.
516 char outbuf[smb_size];
518 *name1 = *name2 = 0;
520 memset(outbuf, '\0', sizeof(outbuf));
522 smb_setlen(outbuf,0);
524 switch (msg_type) {
525 case 0x81: /* session request */
527 if (sconn->nbt.got_session) {
528 exit_server_cleanly("multiple session request not permitted");
531 SCVAL(outbuf,0,0x82);
532 SCVAL(outbuf,3,0);
533 if (name_len(inbuf+4) > 50 ||
534 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
535 DEBUG(0,("Invalid name length in session request\n"));
536 return;
538 name_type1 = name_extract(inbuf,4,name1);
539 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
540 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
541 name1, name_type1, name2, name_type2));
543 if (netbios_session_retarget(name1, name_type1)) {
544 exit_server_cleanly("retargeted client");
547 set_local_machine_name(name1, True);
548 set_remote_machine_name(name2, True);
550 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
551 get_local_machine_name(), get_remote_machine_name(),
552 name_type2));
554 if (name_type2 == 'R') {
555 /* We are being asked for a pathworks session ---
556 no thanks! */
557 SCVAL(outbuf, 0,0x83);
558 break;
561 /* only add the client's machine name to the list
562 of possibly valid usernames if we are operating
563 in share mode security */
564 if (lp_security() == SEC_SHARE) {
565 add_session_user(sconn, get_remote_machine_name());
568 reload_services(True);
569 reopen_logs();
571 sconn->nbt.got_session = true;
572 break;
574 case 0x89: /* session keepalive request
575 (some old clients produce this?) */
576 SCVAL(outbuf,0,SMBkeepalive);
577 SCVAL(outbuf,3,0);
578 break;
580 case 0x82: /* positive session response */
581 case 0x83: /* negative session response */
582 case 0x84: /* retarget session response */
583 DEBUG(0,("Unexpected session response\n"));
584 break;
586 case SMBkeepalive: /* session keepalive */
587 default:
588 return;
591 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
592 msg_type, msg_flags));
594 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
595 return;
598 /****************************************************************************
599 Reply to a tcon.
600 conn POINTER CAN BE NULL HERE !
601 ****************************************************************************/
603 void reply_tcon(struct smb_request *req)
605 connection_struct *conn = req->conn;
606 const char *service;
607 char *service_buf = NULL;
608 char *password = NULL;
609 char *dev = NULL;
610 int pwlen=0;
611 NTSTATUS nt_status;
612 const char *p;
613 DATA_BLOB password_blob;
614 TALLOC_CTX *ctx = talloc_tos();
615 struct smbd_server_connection *sconn = smbd_server_conn;
617 START_PROFILE(SMBtcon);
619 if (req->buflen < 4) {
620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
621 END_PROFILE(SMBtcon);
622 return;
625 p = (const char *)req->buf + 1;
626 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
627 p += 1;
628 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
629 p += pwlen+1;
630 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
631 p += 1;
633 if (service_buf == NULL || password == NULL || dev == NULL) {
634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
635 END_PROFILE(SMBtcon);
636 return;
638 p = strrchr_m(service_buf,'\\');
639 if (p) {
640 service = p+1;
641 } else {
642 service = service_buf;
645 password_blob = data_blob(password, pwlen+1);
647 conn = make_connection(sconn,service,password_blob,dev,
648 req->vuid,&nt_status);
649 req->conn = conn;
651 data_blob_clear_free(&password_blob);
653 if (!conn) {
654 reply_nterror(req, nt_status);
655 END_PROFILE(SMBtcon);
656 return;
659 reply_outbuf(req, 2, 0);
660 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
661 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
662 SSVAL(req->outbuf,smb_tid,conn->cnum);
664 DEBUG(3,("tcon service=%s cnum=%d\n",
665 service, conn->cnum));
667 END_PROFILE(SMBtcon);
668 return;
671 /****************************************************************************
672 Reply to a tcon and X.
673 conn POINTER CAN BE NULL HERE !
674 ****************************************************************************/
676 void reply_tcon_and_X(struct smb_request *req)
678 connection_struct *conn = req->conn;
679 const char *service = NULL;
680 DATA_BLOB password;
681 TALLOC_CTX *ctx = talloc_tos();
682 /* what the cleint thinks the device is */
683 char *client_devicetype = NULL;
684 /* what the server tells the client the share represents */
685 const char *server_devicetype;
686 NTSTATUS nt_status;
687 int passlen;
688 char *path = NULL;
689 const char *p, *q;
690 uint16 tcon_flags;
691 struct smbd_server_connection *sconn = smbd_server_conn;
693 START_PROFILE(SMBtconX);
695 if (req->wct < 4) {
696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
697 END_PROFILE(SMBtconX);
698 return;
701 passlen = SVAL(req->vwv+3, 0);
702 tcon_flags = SVAL(req->vwv+2, 0);
704 /* we might have to close an old one */
705 if ((tcon_flags & 0x1) && conn) {
706 close_cnum(conn,req->vuid);
707 req->conn = NULL;
708 conn = NULL;
711 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
712 reply_doserror(req, ERRDOS, ERRbuftoosmall);
713 END_PROFILE(SMBtconX);
714 return;
717 if (sconn->smb1.negprot.encrypted_passwords) {
718 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
719 if (lp_security() == SEC_SHARE) {
721 * Security = share always has a pad byte
722 * after the password.
724 p = (const char *)req->buf + passlen + 1;
725 } else {
726 p = (const char *)req->buf + passlen;
728 } else {
729 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
730 /* Ensure correct termination */
731 password.data[passlen]=0;
732 p = (const char *)req->buf + passlen + 1;
735 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
737 if (path == NULL) {
738 data_blob_clear_free(&password);
739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
740 END_PROFILE(SMBtconX);
741 return;
745 * the service name can be either: \\server\share
746 * or share directly like on the DELL PowerVault 705
748 if (*path=='\\') {
749 q = strchr_m(path+2,'\\');
750 if (!q) {
751 data_blob_clear_free(&password);
752 reply_doserror(req, ERRDOS, ERRnosuchshare);
753 END_PROFILE(SMBtconX);
754 return;
756 service = q+1;
757 } else {
758 service = path;
761 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
762 &client_devicetype, p,
763 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
765 if (client_devicetype == NULL) {
766 data_blob_clear_free(&password);
767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
768 END_PROFILE(SMBtconX);
769 return;
772 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
774 conn = make_connection(sconn, service, password, client_devicetype,
775 req->vuid, &nt_status);
776 req->conn =conn;
778 data_blob_clear_free(&password);
780 if (!conn) {
781 reply_nterror(req, nt_status);
782 END_PROFILE(SMBtconX);
783 return;
786 if ( IS_IPC(conn) )
787 server_devicetype = "IPC";
788 else if ( IS_PRINT(conn) )
789 server_devicetype = "LPT1:";
790 else
791 server_devicetype = "A:";
793 if (Protocol < PROTOCOL_NT1) {
794 reply_outbuf(req, 2, 0);
795 if (message_push_string(&req->outbuf, server_devicetype,
796 STR_TERMINATE|STR_ASCII) == -1) {
797 reply_nterror(req, NT_STATUS_NO_MEMORY);
798 END_PROFILE(SMBtconX);
799 return;
801 } else {
802 /* NT sets the fstype of IPC$ to the null string */
803 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
805 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
806 /* Return permissions. */
807 uint32 perm1 = 0;
808 uint32 perm2 = 0;
810 reply_outbuf(req, 7, 0);
812 if (IS_IPC(conn)) {
813 perm1 = FILE_ALL_ACCESS;
814 perm2 = FILE_ALL_ACCESS;
815 } else {
816 perm1 = CAN_WRITE(conn) ?
817 SHARE_ALL_ACCESS :
818 SHARE_READ_ONLY;
821 SIVAL(req->outbuf, smb_vwv3, perm1);
822 SIVAL(req->outbuf, smb_vwv5, perm2);
823 } else {
824 reply_outbuf(req, 3, 0);
827 if ((message_push_string(&req->outbuf, server_devicetype,
828 STR_TERMINATE|STR_ASCII) == -1)
829 || (message_push_string(&req->outbuf, fstype,
830 STR_TERMINATE) == -1)) {
831 reply_nterror(req, NT_STATUS_NO_MEMORY);
832 END_PROFILE(SMBtconX);
833 return;
836 /* what does setting this bit do? It is set by NT4 and
837 may affect the ability to autorun mounted cdroms */
838 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
839 (lp_csc_policy(SNUM(conn)) << 2));
841 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
842 DEBUG(2,("Serving %s as a Dfs root\n",
843 lp_servicename(SNUM(conn)) ));
844 SSVAL(req->outbuf, smb_vwv2,
845 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
850 DEBUG(3,("tconX service=%s \n",
851 service));
853 /* set the incoming and outgoing tid to the just created one */
854 SSVAL(req->inbuf,smb_tid,conn->cnum);
855 SSVAL(req->outbuf,smb_tid,conn->cnum);
857 END_PROFILE(SMBtconX);
859 req->tid = conn->cnum;
860 chain_reply(req);
861 return;
864 /****************************************************************************
865 Reply to an unknown type.
866 ****************************************************************************/
868 void reply_unknown_new(struct smb_request *req, uint8 type)
870 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
871 smb_fn_name(type), type, type));
872 reply_doserror(req, ERRSRV, ERRunknownsmb);
873 return;
876 /****************************************************************************
877 Reply to an ioctl.
878 conn POINTER CAN BE NULL HERE !
879 ****************************************************************************/
881 void reply_ioctl(struct smb_request *req)
883 connection_struct *conn = req->conn;
884 uint16 device;
885 uint16 function;
886 uint32 ioctl_code;
887 int replysize;
888 char *p;
890 START_PROFILE(SMBioctl);
892 if (req->wct < 3) {
893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
894 END_PROFILE(SMBioctl);
895 return;
898 device = SVAL(req->vwv+1, 0);
899 function = SVAL(req->vwv+2, 0);
900 ioctl_code = (device << 16) + function;
902 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
904 switch (ioctl_code) {
905 case IOCTL_QUERY_JOB_INFO:
906 replysize = 32;
907 break;
908 default:
909 reply_doserror(req, ERRSRV, ERRnosupport);
910 END_PROFILE(SMBioctl);
911 return;
914 reply_outbuf(req, 8, replysize+1);
915 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
916 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
917 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
918 p = smb_buf(req->outbuf);
919 memset(p, '\0', replysize+1); /* valgrind-safe. */
920 p += 1; /* Allow for alignment */
922 switch (ioctl_code) {
923 case IOCTL_QUERY_JOB_INFO:
925 files_struct *fsp = file_fsp(
926 req, SVAL(req->vwv+0, 0));
927 if (!fsp) {
928 reply_doserror(req, ERRDOS, ERRbadfid);
929 END_PROFILE(SMBioctl);
930 return;
932 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
933 srvstr_push((char *)req->outbuf, req->flags2, p+2,
934 global_myname(), 15,
935 STR_TERMINATE|STR_ASCII);
936 if (conn) {
937 srvstr_push((char *)req->outbuf, req->flags2,
938 p+18, lp_servicename(SNUM(conn)),
939 13, STR_TERMINATE|STR_ASCII);
940 } else {
941 memset(p+18, 0, 13);
943 break;
947 END_PROFILE(SMBioctl);
948 return;
951 /****************************************************************************
952 Strange checkpath NTSTATUS mapping.
953 ****************************************************************************/
955 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
957 /* Strange DOS error code semantics only for checkpath... */
958 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
959 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
960 /* We need to map to ERRbadpath */
961 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
964 return status;
967 /****************************************************************************
968 Reply to a checkpath.
969 ****************************************************************************/
971 void reply_checkpath(struct smb_request *req)
973 connection_struct *conn = req->conn;
974 struct smb_filename *smb_fname = NULL;
975 char *name = NULL;
976 NTSTATUS status;
977 TALLOC_CTX *ctx = talloc_tos();
979 START_PROFILE(SMBcheckpath);
981 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
982 STR_TERMINATE, &status);
984 if (!NT_STATUS_IS_OK(status)) {
985 status = map_checkpath_error(req->flags2, status);
986 reply_nterror(req, status);
987 END_PROFILE(SMBcheckpath);
988 return;
991 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
993 status = filename_convert(ctx,
994 conn,
995 req->flags2 & FLAGS2_DFS_PATHNAMES,
996 name,
998 NULL,
999 &smb_fname);
1001 if (!NT_STATUS_IS_OK(status)) {
1002 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1003 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1004 ERRSRV, ERRbadpath);
1005 END_PROFILE(SMBcheckpath);
1006 return;
1008 goto path_err;
1011 if (!VALID_STAT(smb_fname->st) &&
1012 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1013 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1014 smb_fname_str_dbg(smb_fname), strerror(errno)));
1015 status = map_nt_error_from_unix(errno);
1016 goto path_err;
1019 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1020 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1021 ERRDOS, ERRbadpath);
1022 goto out;
1025 reply_outbuf(req, 0, 0);
1027 path_err:
1028 /* We special case this - as when a Windows machine
1029 is parsing a path is steps through the components
1030 one at a time - if a component fails it expects
1031 ERRbadpath, not ERRbadfile.
1033 status = map_checkpath_error(req->flags2, status);
1034 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1036 * Windows returns different error codes if
1037 * the parent directory is valid but not the
1038 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1039 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1040 * if the path is invalid.
1042 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1043 ERRDOS, ERRbadpath);
1044 goto out;
1047 reply_nterror(req, status);
1049 out:
1050 TALLOC_FREE(smb_fname);
1051 END_PROFILE(SMBcheckpath);
1052 return;
1055 /****************************************************************************
1056 Reply to a getatr.
1057 ****************************************************************************/
1059 void reply_getatr(struct smb_request *req)
1061 connection_struct *conn = req->conn;
1062 struct smb_filename *smb_fname = NULL;
1063 char *fname = NULL;
1064 int mode=0;
1065 SMB_OFF_T size=0;
1066 time_t mtime=0;
1067 const char *p;
1068 NTSTATUS status;
1069 TALLOC_CTX *ctx = talloc_tos();
1070 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1072 START_PROFILE(SMBgetatr);
1074 p = (const char *)req->buf + 1;
1075 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1076 if (!NT_STATUS_IS_OK(status)) {
1077 reply_nterror(req, status);
1078 goto out;
1081 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1082 under WfWg - weird! */
1083 if (*fname == '\0') {
1084 mode = aHIDDEN | aDIR;
1085 if (!CAN_WRITE(conn)) {
1086 mode |= aRONLY;
1088 size = 0;
1089 mtime = 0;
1090 } else {
1091 status = filename_convert(ctx,
1092 conn,
1093 req->flags2 & FLAGS2_DFS_PATHNAMES,
1094 fname,
1096 NULL,
1097 &smb_fname);
1098 if (!NT_STATUS_IS_OK(status)) {
1099 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1100 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1101 ERRSRV, ERRbadpath);
1102 goto out;
1104 reply_nterror(req, status);
1105 goto out;
1107 if (!VALID_STAT(smb_fname->st) &&
1108 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1109 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1110 smb_fname_str_dbg(smb_fname),
1111 strerror(errno)));
1112 reply_nterror(req, map_nt_error_from_unix(errno));
1113 goto out;
1116 mode = dos_mode(conn, smb_fname);
1117 size = smb_fname->st.st_ex_size;
1119 if (ask_sharemode) {
1120 struct timespec write_time_ts;
1121 struct file_id fileid;
1123 ZERO_STRUCT(write_time_ts);
1124 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1125 get_file_infos(fileid, NULL, &write_time_ts);
1126 if (!null_timespec(write_time_ts)) {
1127 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1131 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1132 if (mode & aDIR) {
1133 size = 0;
1137 reply_outbuf(req, 10, 0);
1139 SSVAL(req->outbuf,smb_vwv0,mode);
1140 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1141 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1142 } else {
1143 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1145 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1147 if (Protocol >= PROTOCOL_NT1) {
1148 SSVAL(req->outbuf, smb_flg2,
1149 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1152 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1153 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1155 out:
1156 TALLOC_FREE(smb_fname);
1157 TALLOC_FREE(fname);
1158 END_PROFILE(SMBgetatr);
1159 return;
1162 /****************************************************************************
1163 Reply to a setatr.
1164 ****************************************************************************/
1166 void reply_setatr(struct smb_request *req)
1168 struct smb_file_time ft;
1169 connection_struct *conn = req->conn;
1170 struct smb_filename *smb_fname = NULL;
1171 char *fname = NULL;
1172 int mode;
1173 time_t mtime;
1174 const char *p;
1175 NTSTATUS status;
1176 TALLOC_CTX *ctx = talloc_tos();
1178 START_PROFILE(SMBsetatr);
1180 ZERO_STRUCT(ft);
1182 if (req->wct < 2) {
1183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1184 goto out;
1187 p = (const char *)req->buf + 1;
1188 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 reply_nterror(req, status);
1191 goto out;
1194 status = filename_convert(ctx,
1195 conn,
1196 req->flags2 & FLAGS2_DFS_PATHNAMES,
1197 fname,
1199 NULL,
1200 &smb_fname);
1201 if (!NT_STATUS_IS_OK(status)) {
1202 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1203 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1204 ERRSRV, ERRbadpath);
1205 goto out;
1207 reply_nterror(req, status);
1208 goto out;
1211 if (smb_fname->base_name[0] == '.' &&
1212 smb_fname->base_name[1] == '\0') {
1214 * Not sure here is the right place to catch this
1215 * condition. Might be moved to somewhere else later -- vl
1217 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1218 goto out;
1221 mode = SVAL(req->vwv+0, 0);
1222 mtime = srv_make_unix_date3(req->vwv+1);
1224 ft.mtime = convert_time_t_to_timespec(mtime);
1225 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1226 if (!NT_STATUS_IS_OK(status)) {
1227 reply_nterror(req, status);
1228 goto out;
1231 if (mode != FILE_ATTRIBUTE_NORMAL) {
1232 if (VALID_STAT_OF_DIR(smb_fname->st))
1233 mode |= aDIR;
1234 else
1235 mode &= ~aDIR;
1237 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1238 false) != 0) {
1239 reply_nterror(req, map_nt_error_from_unix(errno));
1240 goto out;
1244 reply_outbuf(req, 0, 0);
1246 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1247 mode));
1248 out:
1249 TALLOC_FREE(smb_fname);
1250 END_PROFILE(SMBsetatr);
1251 return;
1254 /****************************************************************************
1255 Reply to a dskattr.
1256 ****************************************************************************/
1258 void reply_dskattr(struct smb_request *req)
1260 connection_struct *conn = req->conn;
1261 uint64_t dfree,dsize,bsize;
1262 START_PROFILE(SMBdskattr);
1264 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1265 reply_nterror(req, map_nt_error_from_unix(errno));
1266 END_PROFILE(SMBdskattr);
1267 return;
1270 reply_outbuf(req, 5, 0);
1272 if (Protocol <= PROTOCOL_LANMAN2) {
1273 double total_space, free_space;
1274 /* we need to scale this to a number that DOS6 can handle. We
1275 use floating point so we can handle large drives on systems
1276 that don't have 64 bit integers
1278 we end up displaying a maximum of 2G to DOS systems
1280 total_space = dsize * (double)bsize;
1281 free_space = dfree * (double)bsize;
1283 dsize = (uint64_t)((total_space+63*512) / (64*512));
1284 dfree = (uint64_t)((free_space+63*512) / (64*512));
1286 if (dsize > 0xFFFF) dsize = 0xFFFF;
1287 if (dfree > 0xFFFF) dfree = 0xFFFF;
1289 SSVAL(req->outbuf,smb_vwv0,dsize);
1290 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1291 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1292 SSVAL(req->outbuf,smb_vwv3,dfree);
1293 } else {
1294 SSVAL(req->outbuf,smb_vwv0,dsize);
1295 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1296 SSVAL(req->outbuf,smb_vwv2,512);
1297 SSVAL(req->outbuf,smb_vwv3,dfree);
1300 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1302 END_PROFILE(SMBdskattr);
1303 return;
1307 * Utility function to split the filename from the directory.
1309 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1310 char **fname_dir_out,
1311 char **fname_mask_out)
1313 const char *p = NULL;
1314 char *fname_dir = NULL;
1315 char *fname_mask = NULL;
1317 p = strrchr_m(fname_in, '/');
1318 if (!p) {
1319 fname_dir = talloc_strdup(ctx, ".");
1320 fname_mask = talloc_strdup(ctx, fname_in);
1321 } else {
1322 fname_dir = talloc_strndup(ctx, fname_in,
1323 PTR_DIFF(p, fname_in));
1324 fname_mask = talloc_strdup(ctx, p+1);
1327 if (!fname_dir || !fname_mask) {
1328 TALLOC_FREE(fname_dir);
1329 TALLOC_FREE(fname_mask);
1330 return NT_STATUS_NO_MEMORY;
1333 *fname_dir_out = fname_dir;
1334 *fname_mask_out = fname_mask;
1335 return NT_STATUS_OK;
1338 /****************************************************************************
1339 Reply to a search.
1340 Can be called from SMBsearch, SMBffirst or SMBfunique.
1341 ****************************************************************************/
1343 void reply_search(struct smb_request *req)
1345 connection_struct *conn = req->conn;
1346 char *path = NULL;
1347 const char *mask = NULL;
1348 char *directory = NULL;
1349 struct smb_filename *smb_fname = NULL;
1350 char *fname = NULL;
1351 SMB_OFF_T size;
1352 uint32 mode;
1353 struct timespec date;
1354 uint32 dirtype;
1355 unsigned int numentries = 0;
1356 unsigned int maxentries = 0;
1357 bool finished = False;
1358 const char *p;
1359 int status_len;
1360 char status[21];
1361 int dptr_num= -1;
1362 bool check_descend = False;
1363 bool expect_close = False;
1364 NTSTATUS nt_status;
1365 bool mask_contains_wcard = False;
1366 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1367 TALLOC_CTX *ctx = talloc_tos();
1368 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1369 struct dptr_struct *dirptr = NULL;
1370 struct smbd_server_connection *sconn = smbd_server_conn;
1372 START_PROFILE(SMBsearch);
1374 if (req->wct < 2) {
1375 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1376 goto out;
1379 if (lp_posix_pathnames()) {
1380 reply_unknown_new(req, req->cmd);
1381 goto out;
1384 /* If we were called as SMBffirst then we must expect close. */
1385 if(req->cmd == SMBffirst) {
1386 expect_close = True;
1389 reply_outbuf(req, 1, 3);
1390 maxentries = SVAL(req->vwv+0, 0);
1391 dirtype = SVAL(req->vwv+1, 0);
1392 p = (const char *)req->buf + 1;
1393 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1394 &nt_status, &mask_contains_wcard);
1395 if (!NT_STATUS_IS_OK(nt_status)) {
1396 reply_nterror(req, nt_status);
1397 goto out;
1400 p++;
1401 status_len = SVAL(p, 0);
1402 p += 2;
1404 /* dirtype &= ~aDIR; */
1406 if (status_len == 0) {
1407 nt_status = filename_convert(ctx, conn,
1408 req->flags2 & FLAGS2_DFS_PATHNAMES,
1409 path,
1410 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1411 &mask_contains_wcard,
1412 &smb_fname);
1413 if (!NT_STATUS_IS_OK(nt_status)) {
1414 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1415 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1416 ERRSRV, ERRbadpath);
1417 goto out;
1419 reply_nterror(req, nt_status);
1420 goto out;
1423 directory = smb_fname->base_name;
1425 p = strrchr_m(directory,'/');
1426 if ((p != NULL) && (*directory != '/')) {
1427 mask = p + 1;
1428 directory = talloc_strndup(ctx, directory,
1429 PTR_DIFF(p, directory));
1430 } else {
1431 mask = directory;
1432 directory = talloc_strdup(ctx,".");
1435 if (!directory) {
1436 reply_nterror(req, NT_STATUS_NO_MEMORY);
1437 goto out;
1440 memset((char *)status,'\0',21);
1441 SCVAL(status,0,(dirtype & 0x1F));
1443 nt_status = dptr_create(conn,
1444 directory,
1445 True,
1446 expect_close,
1447 req->smbpid,
1448 mask,
1449 mask_contains_wcard,
1450 dirtype,
1451 &dirptr);
1452 if (!NT_STATUS_IS_OK(nt_status)) {
1453 reply_nterror(req, nt_status);
1454 goto out;
1456 dptr_num = dptr_dnum(dirptr);
1457 } else {
1458 int status_dirtype;
1459 const char *dirpath;
1461 memcpy(status,p,21);
1462 status_dirtype = CVAL(status,0) & 0x1F;
1463 if (status_dirtype != (dirtype & 0x1F)) {
1464 dirtype = status_dirtype;
1467 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1468 if (!dirptr) {
1469 goto SearchEmpty;
1471 dirpath = dptr_path(sconn, dptr_num);
1472 directory = talloc_strdup(ctx, dirpath);
1473 if (!directory) {
1474 reply_nterror(req, NT_STATUS_NO_MEMORY);
1475 goto out;
1478 mask = dptr_wcard(sconn, dptr_num);
1479 if (!mask) {
1480 goto SearchEmpty;
1483 * For a 'continue' search we have no string. So
1484 * check from the initial saved string.
1486 mask_contains_wcard = ms_has_wild(mask);
1487 dirtype = dptr_attr(sconn, dptr_num);
1490 DEBUG(4,("dptr_num is %d\n",dptr_num));
1492 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1493 dptr_init_search_op(dirptr);
1495 if ((dirtype&0x1F) == aVOLID) {
1496 char buf[DIR_STRUCT_SIZE];
1497 memcpy(buf,status,21);
1498 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1499 0,aVOLID,0,!allow_long_path_components)) {
1500 reply_nterror(req, NT_STATUS_NO_MEMORY);
1501 goto out;
1503 dptr_fill(sconn, buf+12,dptr_num);
1504 if (dptr_zero(buf+12) && (status_len==0)) {
1505 numentries = 1;
1506 } else {
1507 numentries = 0;
1509 if (message_push_blob(&req->outbuf,
1510 data_blob_const(buf, sizeof(buf)))
1511 == -1) {
1512 reply_nterror(req, NT_STATUS_NO_MEMORY);
1513 goto out;
1515 } else {
1516 unsigned int i;
1517 maxentries = MIN(
1518 maxentries,
1519 ((BUFFER_SIZE -
1520 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1521 /DIR_STRUCT_SIZE));
1523 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1524 directory,lp_dontdescend(SNUM(conn))));
1525 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1526 check_descend = True;
1529 for (i=numentries;(i<maxentries) && !finished;i++) {
1530 finished = !get_dir_entry(ctx,
1531 dirptr,
1532 mask,
1533 dirtype,
1534 &fname,
1535 &size,
1536 &mode,
1537 &date,
1538 check_descend,
1539 ask_sharemode);
1540 if (!finished) {
1541 char buf[DIR_STRUCT_SIZE];
1542 memcpy(buf,status,21);
1543 if (!make_dir_struct(ctx,
1544 buf,
1545 mask,
1546 fname,
1547 size,
1548 mode,
1549 convert_timespec_to_time_t(date),
1550 !allow_long_path_components)) {
1551 reply_nterror(req, NT_STATUS_NO_MEMORY);
1552 goto out;
1554 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1555 break;
1557 if (message_push_blob(&req->outbuf,
1558 data_blob_const(buf, sizeof(buf)))
1559 == -1) {
1560 reply_nterror(req, NT_STATUS_NO_MEMORY);
1561 goto out;
1563 numentries++;
1568 SearchEmpty:
1570 /* If we were called as SMBffirst with smb_search_id == NULL
1571 and no entries were found then return error and close dirptr
1572 (X/Open spec) */
1574 if (numentries == 0) {
1575 dptr_close(sconn, &dptr_num);
1576 } else if(expect_close && status_len == 0) {
1577 /* Close the dptr - we know it's gone */
1578 dptr_close(sconn, &dptr_num);
1581 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1582 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1583 dptr_close(sconn, &dptr_num);
1586 if ((numentries == 0) && !mask_contains_wcard) {
1587 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1588 goto out;
1591 SSVAL(req->outbuf,smb_vwv0,numentries);
1592 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1593 SCVAL(smb_buf(req->outbuf),0,5);
1594 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1596 /* The replies here are never long name. */
1597 SSVAL(req->outbuf, smb_flg2,
1598 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1599 if (!allow_long_path_components) {
1600 SSVAL(req->outbuf, smb_flg2,
1601 SVAL(req->outbuf, smb_flg2)
1602 & (~FLAGS2_LONG_PATH_COMPONENTS));
1605 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1606 SSVAL(req->outbuf, smb_flg2,
1607 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1609 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1610 smb_fn_name(req->cmd),
1611 mask,
1612 directory,
1613 dirtype,
1614 numentries,
1615 maxentries ));
1616 out:
1617 TALLOC_FREE(directory);
1618 TALLOC_FREE(smb_fname);
1619 END_PROFILE(SMBsearch);
1620 return;
1623 /****************************************************************************
1624 Reply to a fclose (stop directory search).
1625 ****************************************************************************/
1627 void reply_fclose(struct smb_request *req)
1629 int status_len;
1630 char status[21];
1631 int dptr_num= -2;
1632 const char *p;
1633 char *path = NULL;
1634 NTSTATUS err;
1635 bool path_contains_wcard = False;
1636 TALLOC_CTX *ctx = talloc_tos();
1637 struct smbd_server_connection *sconn = smbd_server_conn;
1639 START_PROFILE(SMBfclose);
1641 if (lp_posix_pathnames()) {
1642 reply_unknown_new(req, req->cmd);
1643 END_PROFILE(SMBfclose);
1644 return;
1647 p = (const char *)req->buf + 1;
1648 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1649 &err, &path_contains_wcard);
1650 if (!NT_STATUS_IS_OK(err)) {
1651 reply_nterror(req, err);
1652 END_PROFILE(SMBfclose);
1653 return;
1655 p++;
1656 status_len = SVAL(p,0);
1657 p += 2;
1659 if (status_len == 0) {
1660 reply_doserror(req, ERRSRV, ERRsrverror);
1661 END_PROFILE(SMBfclose);
1662 return;
1665 memcpy(status,p,21);
1667 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1668 /* Close the dptr - we know it's gone */
1669 dptr_close(sconn, &dptr_num);
1672 reply_outbuf(req, 1, 0);
1673 SSVAL(req->outbuf,smb_vwv0,0);
1675 DEBUG(3,("search close\n"));
1677 END_PROFILE(SMBfclose);
1678 return;
1681 /****************************************************************************
1682 Reply to an open.
1683 ****************************************************************************/
1685 void reply_open(struct smb_request *req)
1687 connection_struct *conn = req->conn;
1688 struct smb_filename *smb_fname = NULL;
1689 char *fname = NULL;
1690 uint32 fattr=0;
1691 SMB_OFF_T size = 0;
1692 time_t mtime=0;
1693 int info;
1694 files_struct *fsp;
1695 int oplock_request;
1696 int deny_mode;
1697 uint32 dos_attr;
1698 uint32 access_mask;
1699 uint32 share_mode;
1700 uint32 create_disposition;
1701 uint32 create_options = 0;
1702 NTSTATUS status;
1703 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1704 TALLOC_CTX *ctx = talloc_tos();
1706 START_PROFILE(SMBopen);
1708 if (req->wct < 2) {
1709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1710 goto out;
1713 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1714 deny_mode = SVAL(req->vwv+0, 0);
1715 dos_attr = SVAL(req->vwv+1, 0);
1717 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1718 STR_TERMINATE, &status);
1719 if (!NT_STATUS_IS_OK(status)) {
1720 reply_nterror(req, status);
1721 goto out;
1724 status = filename_convert(ctx,
1725 conn,
1726 req->flags2 & FLAGS2_DFS_PATHNAMES,
1727 fname,
1729 NULL,
1730 &smb_fname);
1731 if (!NT_STATUS_IS_OK(status)) {
1732 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1733 reply_botherror(req,
1734 NT_STATUS_PATH_NOT_COVERED,
1735 ERRSRV, ERRbadpath);
1736 goto out;
1738 reply_nterror(req, status);
1739 goto out;
1742 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1743 OPENX_FILE_EXISTS_OPEN, &access_mask,
1744 &share_mode, &create_disposition,
1745 &create_options)) {
1746 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1747 goto out;
1750 status = SMB_VFS_CREATE_FILE(
1751 conn, /* conn */
1752 req, /* req */
1753 0, /* root_dir_fid */
1754 smb_fname, /* fname */
1755 access_mask, /* access_mask */
1756 share_mode, /* share_access */
1757 create_disposition, /* create_disposition*/
1758 create_options, /* create_options */
1759 dos_attr, /* file_attributes */
1760 oplock_request, /* oplock_request */
1761 0, /* allocation_size */
1762 NULL, /* sd */
1763 NULL, /* ea_list */
1764 &fsp, /* result */
1765 &info); /* pinfo */
1767 if (!NT_STATUS_IS_OK(status)) {
1768 if (open_was_deferred(req->mid)) {
1769 /* We have re-scheduled this call. */
1770 goto out;
1772 reply_openerror(req, status);
1773 goto out;
1776 size = smb_fname->st.st_ex_size;
1777 fattr = dos_mode(conn, smb_fname);
1779 /* Deal with other possible opens having a modified
1780 write time. JRA. */
1781 if (ask_sharemode) {
1782 struct timespec write_time_ts;
1784 ZERO_STRUCT(write_time_ts);
1785 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1786 if (!null_timespec(write_time_ts)) {
1787 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1791 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1793 if (fattr & aDIR) {
1794 DEBUG(3,("attempt to open a directory %s\n",
1795 fsp_str_dbg(fsp)));
1796 close_file(req, fsp, ERROR_CLOSE);
1797 reply_doserror(req, ERRDOS,ERRnoaccess);
1798 goto out;
1801 reply_outbuf(req, 7, 0);
1802 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1803 SSVAL(req->outbuf,smb_vwv1,fattr);
1804 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1805 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1806 } else {
1807 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1809 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1810 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1812 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1813 SCVAL(req->outbuf,smb_flg,
1814 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1817 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1818 SCVAL(req->outbuf,smb_flg,
1819 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1821 out:
1822 TALLOC_FREE(smb_fname);
1823 END_PROFILE(SMBopen);
1824 return;
1827 /****************************************************************************
1828 Reply to an open and X.
1829 ****************************************************************************/
1831 void reply_open_and_X(struct smb_request *req)
1833 connection_struct *conn = req->conn;
1834 struct smb_filename *smb_fname = NULL;
1835 char *fname = NULL;
1836 uint16 open_flags;
1837 int deny_mode;
1838 uint32 smb_attr;
1839 /* Breakout the oplock request bits so we can set the
1840 reply bits separately. */
1841 int ex_oplock_request;
1842 int core_oplock_request;
1843 int oplock_request;
1844 #if 0
1845 int smb_sattr = SVAL(req->vwv+4, 0);
1846 uint32 smb_time = make_unix_date3(req->vwv+6);
1847 #endif
1848 int smb_ofun;
1849 uint32 fattr=0;
1850 int mtime=0;
1851 int smb_action = 0;
1852 files_struct *fsp;
1853 NTSTATUS status;
1854 uint64_t allocation_size;
1855 ssize_t retval = -1;
1856 uint32 access_mask;
1857 uint32 share_mode;
1858 uint32 create_disposition;
1859 uint32 create_options = 0;
1860 TALLOC_CTX *ctx = talloc_tos();
1862 START_PROFILE(SMBopenX);
1864 if (req->wct < 15) {
1865 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1866 goto out;
1869 open_flags = SVAL(req->vwv+2, 0);
1870 deny_mode = SVAL(req->vwv+3, 0);
1871 smb_attr = SVAL(req->vwv+5, 0);
1872 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1873 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1874 oplock_request = ex_oplock_request | core_oplock_request;
1875 smb_ofun = SVAL(req->vwv+8, 0);
1876 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1878 /* If it's an IPC, pass off the pipe handler. */
1879 if (IS_IPC(conn)) {
1880 if (lp_nt_pipe_support()) {
1881 reply_open_pipe_and_X(conn, req);
1882 } else {
1883 reply_doserror(req, ERRSRV, ERRaccess);
1885 goto out;
1888 /* XXXX we need to handle passed times, sattr and flags */
1889 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1890 STR_TERMINATE, &status);
1891 if (!NT_STATUS_IS_OK(status)) {
1892 reply_nterror(req, status);
1893 goto out;
1896 status = filename_convert(ctx,
1897 conn,
1898 req->flags2 & FLAGS2_DFS_PATHNAMES,
1899 fname,
1901 NULL,
1902 &smb_fname);
1903 if (!NT_STATUS_IS_OK(status)) {
1904 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1905 reply_botherror(req,
1906 NT_STATUS_PATH_NOT_COVERED,
1907 ERRSRV, ERRbadpath);
1908 goto out;
1910 reply_nterror(req, status);
1911 goto out;
1914 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1915 &access_mask, &share_mode,
1916 &create_disposition,
1917 &create_options)) {
1918 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1919 goto out;
1922 status = SMB_VFS_CREATE_FILE(
1923 conn, /* conn */
1924 req, /* req */
1925 0, /* root_dir_fid */
1926 smb_fname, /* fname */
1927 access_mask, /* access_mask */
1928 share_mode, /* share_access */
1929 create_disposition, /* create_disposition*/
1930 create_options, /* create_options */
1931 smb_attr, /* file_attributes */
1932 oplock_request, /* oplock_request */
1933 0, /* allocation_size */
1934 NULL, /* sd */
1935 NULL, /* ea_list */
1936 &fsp, /* result */
1937 &smb_action); /* pinfo */
1939 if (!NT_STATUS_IS_OK(status)) {
1940 if (open_was_deferred(req->mid)) {
1941 /* We have re-scheduled this call. */
1942 goto out;
1944 reply_openerror(req, status);
1945 goto out;
1948 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1949 if the file is truncated or created. */
1950 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1951 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1952 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1953 close_file(req, fsp, ERROR_CLOSE);
1954 reply_nterror(req, NT_STATUS_DISK_FULL);
1955 goto out;
1957 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1958 if (retval < 0) {
1959 close_file(req, fsp, ERROR_CLOSE);
1960 reply_nterror(req, NT_STATUS_DISK_FULL);
1961 goto out;
1963 smb_fname->st.st_ex_size =
1964 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1967 fattr = dos_mode(conn, smb_fname);
1968 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1969 if (fattr & aDIR) {
1970 close_file(req, fsp, ERROR_CLOSE);
1971 reply_doserror(req, ERRDOS, ERRnoaccess);
1972 goto out;
1975 /* If the caller set the extended oplock request bit
1976 and we granted one (by whatever means) - set the
1977 correct bit for extended oplock reply.
1980 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1981 smb_action |= EXTENDED_OPLOCK_GRANTED;
1984 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1985 smb_action |= EXTENDED_OPLOCK_GRANTED;
1988 /* If the caller set the core oplock request bit
1989 and we granted one (by whatever means) - set the
1990 correct bit for core oplock reply.
1993 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1994 reply_outbuf(req, 19, 0);
1995 } else {
1996 reply_outbuf(req, 15, 0);
1999 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2000 SCVAL(req->outbuf, smb_flg,
2001 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2004 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2005 SCVAL(req->outbuf, smb_flg,
2006 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2009 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2010 SSVAL(req->outbuf,smb_vwv3,fattr);
2011 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2012 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2013 } else {
2014 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2016 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2017 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2018 SSVAL(req->outbuf,smb_vwv11,smb_action);
2020 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2021 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2024 chain_reply(req);
2025 out:
2026 TALLOC_FREE(smb_fname);
2027 END_PROFILE(SMBopenX);
2028 return;
2031 /****************************************************************************
2032 Reply to a SMBulogoffX.
2033 ****************************************************************************/
2035 void reply_ulogoffX(struct smb_request *req)
2037 struct smbd_server_connection *sconn = smbd_server_conn;
2038 user_struct *vuser;
2040 START_PROFILE(SMBulogoffX);
2042 vuser = get_valid_user_struct(sconn, req->vuid);
2044 if(vuser == NULL) {
2045 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2046 req->vuid));
2049 /* in user level security we are supposed to close any files
2050 open by this user */
2051 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2052 file_close_user(req->vuid);
2055 invalidate_vuid(sconn, req->vuid);
2057 reply_outbuf(req, 2, 0);
2059 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2061 END_PROFILE(SMBulogoffX);
2062 req->vuid = UID_FIELD_INVALID;
2063 chain_reply(req);
2066 /****************************************************************************
2067 Reply to a mknew or a create.
2068 ****************************************************************************/
2070 void reply_mknew(struct smb_request *req)
2072 connection_struct *conn = req->conn;
2073 struct smb_filename *smb_fname = NULL;
2074 char *fname = NULL;
2075 uint32 fattr = 0;
2076 struct smb_file_time ft;
2077 files_struct *fsp;
2078 int oplock_request = 0;
2079 NTSTATUS status;
2080 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2081 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2082 uint32 create_disposition;
2083 uint32 create_options = 0;
2084 TALLOC_CTX *ctx = talloc_tos();
2086 START_PROFILE(SMBcreate);
2087 ZERO_STRUCT(ft);
2089 if (req->wct < 3) {
2090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2091 goto out;
2094 fattr = SVAL(req->vwv+0, 0);
2095 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2097 /* mtime. */
2098 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2100 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2101 STR_TERMINATE, &status);
2102 if (!NT_STATUS_IS_OK(status)) {
2103 reply_nterror(req, status);
2104 goto out;
2107 status = filename_convert(ctx,
2108 conn,
2109 req->flags2 & FLAGS2_DFS_PATHNAMES,
2110 fname,
2112 NULL,
2113 &smb_fname);
2114 if (!NT_STATUS_IS_OK(status)) {
2115 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2116 reply_botherror(req,
2117 NT_STATUS_PATH_NOT_COVERED,
2118 ERRSRV, ERRbadpath);
2119 goto out;
2121 reply_nterror(req, status);
2122 goto out;
2125 if (fattr & aVOLID) {
2126 DEBUG(0,("Attempt to create file (%s) with volid set - "
2127 "please report this\n",
2128 smb_fname_str_dbg(smb_fname)));
2131 if(req->cmd == SMBmknew) {
2132 /* We should fail if file exists. */
2133 create_disposition = FILE_CREATE;
2134 } else {
2135 /* Create if file doesn't exist, truncate if it does. */
2136 create_disposition = FILE_OVERWRITE_IF;
2139 status = SMB_VFS_CREATE_FILE(
2140 conn, /* conn */
2141 req, /* req */
2142 0, /* root_dir_fid */
2143 smb_fname, /* fname */
2144 access_mask, /* access_mask */
2145 share_mode, /* share_access */
2146 create_disposition, /* create_disposition*/
2147 create_options, /* create_options */
2148 fattr, /* file_attributes */
2149 oplock_request, /* oplock_request */
2150 0, /* allocation_size */
2151 NULL, /* sd */
2152 NULL, /* ea_list */
2153 &fsp, /* result */
2154 NULL); /* pinfo */
2156 if (!NT_STATUS_IS_OK(status)) {
2157 if (open_was_deferred(req->mid)) {
2158 /* We have re-scheduled this call. */
2159 goto out;
2161 reply_openerror(req, status);
2162 goto out;
2165 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2166 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2167 if (!NT_STATUS_IS_OK(status)) {
2168 END_PROFILE(SMBcreate);
2169 goto out;
2172 reply_outbuf(req, 1, 0);
2173 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2175 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2176 SCVAL(req->outbuf,smb_flg,
2177 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2180 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2181 SCVAL(req->outbuf,smb_flg,
2182 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2185 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2186 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2187 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2188 (unsigned int)fattr));
2190 out:
2191 TALLOC_FREE(smb_fname);
2192 END_PROFILE(SMBcreate);
2193 return;
2196 /****************************************************************************
2197 Reply to a create temporary file.
2198 ****************************************************************************/
2200 void reply_ctemp(struct smb_request *req)
2202 connection_struct *conn = req->conn;
2203 struct smb_filename *smb_fname = NULL;
2204 char *fname = NULL;
2205 uint32 fattr;
2206 files_struct *fsp;
2207 int oplock_request;
2208 int tmpfd;
2209 char *s;
2210 NTSTATUS status;
2211 TALLOC_CTX *ctx = talloc_tos();
2213 START_PROFILE(SMBctemp);
2215 if (req->wct < 3) {
2216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2217 goto out;
2220 fattr = SVAL(req->vwv+0, 0);
2221 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2223 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2224 STR_TERMINATE, &status);
2225 if (!NT_STATUS_IS_OK(status)) {
2226 reply_nterror(req, status);
2227 goto out;
2229 if (*fname) {
2230 fname = talloc_asprintf(ctx,
2231 "%s/TMXXXXXX",
2232 fname);
2233 } else {
2234 fname = talloc_strdup(ctx, "TMXXXXXX");
2237 if (!fname) {
2238 reply_nterror(req, NT_STATUS_NO_MEMORY);
2239 goto out;
2242 status = filename_convert(ctx, conn,
2243 req->flags2 & FLAGS2_DFS_PATHNAMES,
2244 fname,
2246 NULL,
2247 &smb_fname);
2248 if (!NT_STATUS_IS_OK(status)) {
2249 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2250 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2251 ERRSRV, ERRbadpath);
2252 goto out;
2254 reply_nterror(req, status);
2255 goto out;
2258 tmpfd = mkstemp(smb_fname->base_name);
2259 if (tmpfd == -1) {
2260 reply_nterror(req, map_nt_error_from_unix(errno));
2261 goto out;
2264 SMB_VFS_STAT(conn, smb_fname);
2266 /* We should fail if file does not exist. */
2267 status = SMB_VFS_CREATE_FILE(
2268 conn, /* conn */
2269 req, /* req */
2270 0, /* root_dir_fid */
2271 smb_fname, /* fname */
2272 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2273 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2274 FILE_OPEN, /* create_disposition*/
2275 0, /* create_options */
2276 fattr, /* file_attributes */
2277 oplock_request, /* oplock_request */
2278 0, /* allocation_size */
2279 NULL, /* sd */
2280 NULL, /* ea_list */
2281 &fsp, /* result */
2282 NULL); /* pinfo */
2284 /* close fd from mkstemp() */
2285 close(tmpfd);
2287 if (!NT_STATUS_IS_OK(status)) {
2288 if (open_was_deferred(req->mid)) {
2289 /* We have re-scheduled this call. */
2290 goto out;
2292 reply_openerror(req, status);
2293 goto out;
2296 reply_outbuf(req, 1, 0);
2297 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2299 /* the returned filename is relative to the directory */
2300 s = strrchr_m(fsp->fsp_name->base_name, '/');
2301 if (!s) {
2302 s = fsp->fsp_name->base_name;
2303 } else {
2304 s++;
2307 #if 0
2308 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2309 thing in the byte section. JRA */
2310 SSVALS(p, 0, -1); /* what is this? not in spec */
2311 #endif
2312 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2313 == -1) {
2314 reply_nterror(req, NT_STATUS_NO_MEMORY);
2315 goto out;
2318 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2319 SCVAL(req->outbuf, smb_flg,
2320 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2323 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2324 SCVAL(req->outbuf, smb_flg,
2325 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2328 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2329 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2330 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2331 out:
2332 TALLOC_FREE(smb_fname);
2333 END_PROFILE(SMBctemp);
2334 return;
2337 /*******************************************************************
2338 Check if a user is allowed to rename a file.
2339 ********************************************************************/
2341 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2342 uint16 dirtype, SMB_STRUCT_STAT *pst)
2344 uint32 fmode;
2346 if (!CAN_WRITE(conn)) {
2347 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2350 fmode = dos_mode(conn, fsp->fsp_name);
2351 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2352 return NT_STATUS_NO_SUCH_FILE;
2355 if (S_ISDIR(pst->st_ex_mode)) {
2356 if (fsp->posix_open) {
2357 return NT_STATUS_OK;
2360 /* If no pathnames are open below this
2361 directory, allow the rename. */
2363 if (file_find_subpath(fsp)) {
2364 return NT_STATUS_ACCESS_DENIED;
2366 return NT_STATUS_OK;
2369 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2370 return NT_STATUS_OK;
2373 return NT_STATUS_ACCESS_DENIED;
2376 /*******************************************************************
2377 * unlink a file with all relevant access checks
2378 *******************************************************************/
2380 static NTSTATUS do_unlink(connection_struct *conn,
2381 struct smb_request *req,
2382 struct smb_filename *smb_fname,
2383 uint32 dirtype)
2385 uint32 fattr;
2386 files_struct *fsp;
2387 uint32 dirtype_orig = dirtype;
2388 NTSTATUS status;
2390 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2391 smb_fname_str_dbg(smb_fname),
2392 dirtype));
2394 if (!CAN_WRITE(conn)) {
2395 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2398 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
2399 return map_nt_error_from_unix(errno);
2402 fattr = dos_mode(conn, smb_fname);
2404 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2405 dirtype = aDIR|aARCH|aRONLY;
2408 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2409 if (!dirtype) {
2410 return NT_STATUS_NO_SUCH_FILE;
2413 if (!dir_check_ftype(conn, fattr, dirtype)) {
2414 if (fattr & aDIR) {
2415 return NT_STATUS_FILE_IS_A_DIRECTORY;
2417 return NT_STATUS_NO_SUCH_FILE;
2420 if (dirtype_orig & 0x8000) {
2421 /* These will never be set for POSIX. */
2422 return NT_STATUS_NO_SUCH_FILE;
2425 #if 0
2426 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2427 return NT_STATUS_FILE_IS_A_DIRECTORY;
2430 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2431 return NT_STATUS_NO_SUCH_FILE;
2434 if (dirtype & 0xFF00) {
2435 /* These will never be set for POSIX. */
2436 return NT_STATUS_NO_SUCH_FILE;
2439 dirtype &= 0xFF;
2440 if (!dirtype) {
2441 return NT_STATUS_NO_SUCH_FILE;
2444 /* Can't delete a directory. */
2445 if (fattr & aDIR) {
2446 return NT_STATUS_FILE_IS_A_DIRECTORY;
2448 #endif
2450 #if 0 /* JRATEST */
2451 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2452 return NT_STATUS_OBJECT_NAME_INVALID;
2453 #endif /* JRATEST */
2455 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2457 On a Windows share, a file with read-only dosmode can be opened with
2458 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2459 fails with NT_STATUS_CANNOT_DELETE error.
2461 This semantic causes a problem that a user can not
2462 rename a file with read-only dosmode on a Samba share
2463 from a Windows command prompt (i.e. cmd.exe, but can rename
2464 from Windows Explorer).
2467 if (!lp_delete_readonly(SNUM(conn))) {
2468 if (fattr & aRONLY) {
2469 return NT_STATUS_CANNOT_DELETE;
2473 /* On open checks the open itself will check the share mode, so
2474 don't do it here as we'll get it wrong. */
2476 status = SMB_VFS_CREATE_FILE
2477 (conn, /* conn */
2478 req, /* req */
2479 0, /* root_dir_fid */
2480 smb_fname, /* fname */
2481 DELETE_ACCESS, /* access_mask */
2482 FILE_SHARE_NONE, /* share_access */
2483 FILE_OPEN, /* create_disposition*/
2484 FILE_NON_DIRECTORY_FILE, /* create_options */
2485 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2486 0, /* oplock_request */
2487 0, /* allocation_size */
2488 NULL, /* sd */
2489 NULL, /* ea_list */
2490 &fsp, /* result */
2491 NULL); /* pinfo */
2493 if (!NT_STATUS_IS_OK(status)) {
2494 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2495 nt_errstr(status)));
2496 return status;
2499 /* The set is across all open files on this dev/inode pair. */
2500 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2501 close_file(req, fsp, NORMAL_CLOSE);
2502 return NT_STATUS_ACCESS_DENIED;
2505 return close_file(req, fsp, NORMAL_CLOSE);
2508 /****************************************************************************
2509 The guts of the unlink command, split out so it may be called by the NT SMB
2510 code.
2511 ****************************************************************************/
2513 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2514 uint32 dirtype, struct smb_filename *smb_fname,
2515 bool has_wild)
2517 char *fname_dir = NULL;
2518 char *fname_mask = NULL;
2519 int count=0;
2520 NTSTATUS status = NT_STATUS_OK;
2521 TALLOC_CTX *ctx = talloc_tos();
2523 /* Split up the directory from the filename/mask. */
2524 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2525 &fname_dir, &fname_mask);
2526 if (!NT_STATUS_IS_OK(status)) {
2527 goto out;
2531 * We should only check the mangled cache
2532 * here if unix_convert failed. This means
2533 * that the path in 'mask' doesn't exist
2534 * on the file system and so we need to look
2535 * for a possible mangle. This patch from
2536 * Tine Smukavec <valentin.smukavec@hermes.si>.
2539 if (!VALID_STAT(smb_fname->st) &&
2540 mangle_is_mangled(fname_mask, conn->params)) {
2541 char *new_mask = NULL;
2542 mangle_lookup_name_from_8_3(ctx, fname_mask,
2543 &new_mask, conn->params);
2544 if (new_mask) {
2545 TALLOC_FREE(fname_mask);
2546 fname_mask = new_mask;
2550 if (!has_wild) {
2553 * Only one file needs to be unlinked. Append the mask back
2554 * onto the directory.
2556 TALLOC_FREE(smb_fname->base_name);
2557 smb_fname->base_name = talloc_asprintf(smb_fname,
2558 "%s/%s",
2559 fname_dir,
2560 fname_mask);
2561 if (!smb_fname->base_name) {
2562 status = NT_STATUS_NO_MEMORY;
2563 goto out;
2565 if (dirtype == 0) {
2566 dirtype = FILE_ATTRIBUTE_NORMAL;
2569 status = check_name(conn, smb_fname->base_name);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 goto out;
2574 status = do_unlink(conn, req, smb_fname, dirtype);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 goto out;
2579 count++;
2580 } else {
2581 struct smb_Dir *dir_hnd = NULL;
2582 long offset = 0;
2583 const char *dname;
2585 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2586 status = NT_STATUS_OBJECT_NAME_INVALID;
2587 goto out;
2590 if (strequal(fname_mask,"????????.???")) {
2591 TALLOC_FREE(fname_mask);
2592 fname_mask = talloc_strdup(ctx, "*");
2593 if (!fname_mask) {
2594 status = NT_STATUS_NO_MEMORY;
2595 goto out;
2599 status = check_name(conn, fname_dir);
2600 if (!NT_STATUS_IS_OK(status)) {
2601 goto out;
2604 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2605 dirtype);
2606 if (dir_hnd == NULL) {
2607 status = map_nt_error_from_unix(errno);
2608 goto out;
2611 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2612 the pattern matches against the long name, otherwise the short name
2613 We don't implement this yet XXXX
2616 status = NT_STATUS_NO_SUCH_FILE;
2618 while ((dname = ReadDirName(dir_hnd, &offset,
2619 &smb_fname->st))) {
2620 TALLOC_CTX *frame = talloc_stackframe();
2622 if (!is_visible_file(conn, fname_dir, dname,
2623 &smb_fname->st, true)) {
2624 TALLOC_FREE(frame);
2625 continue;
2628 /* Quick check for "." and ".." */
2629 if (ISDOT(dname) || ISDOTDOT(dname)) {
2630 TALLOC_FREE(frame);
2631 continue;
2634 if(!mask_match(dname, fname_mask,
2635 conn->case_sensitive)) {
2636 TALLOC_FREE(frame);
2637 continue;
2640 TALLOC_FREE(smb_fname->base_name);
2641 smb_fname->base_name =
2642 talloc_asprintf(smb_fname, "%s/%s",
2643 fname_dir, dname);
2645 if (!smb_fname->base_name) {
2646 TALLOC_FREE(dir_hnd);
2647 status = NT_STATUS_NO_MEMORY;
2648 TALLOC_FREE(frame);
2649 goto out;
2652 status = check_name(conn, smb_fname->base_name);
2653 if (!NT_STATUS_IS_OK(status)) {
2654 TALLOC_FREE(dir_hnd);
2655 TALLOC_FREE(frame);
2656 goto out;
2659 status = do_unlink(conn, req, smb_fname, dirtype);
2660 if (!NT_STATUS_IS_OK(status)) {
2661 TALLOC_FREE(frame);
2662 continue;
2665 count++;
2666 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2667 smb_fname->base_name));
2669 TALLOC_FREE(frame);
2671 TALLOC_FREE(dir_hnd);
2674 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2675 status = map_nt_error_from_unix(errno);
2678 out:
2679 TALLOC_FREE(fname_dir);
2680 TALLOC_FREE(fname_mask);
2681 return status;
2684 /****************************************************************************
2685 Reply to a unlink
2686 ****************************************************************************/
2688 void reply_unlink(struct smb_request *req)
2690 connection_struct *conn = req->conn;
2691 char *name = NULL;
2692 struct smb_filename *smb_fname = NULL;
2693 uint32 dirtype;
2694 NTSTATUS status;
2695 bool path_contains_wcard = False;
2696 TALLOC_CTX *ctx = talloc_tos();
2698 START_PROFILE(SMBunlink);
2700 if (req->wct < 1) {
2701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2702 goto out;
2705 dirtype = SVAL(req->vwv+0, 0);
2707 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2708 STR_TERMINATE, &status,
2709 &path_contains_wcard);
2710 if (!NT_STATUS_IS_OK(status)) {
2711 reply_nterror(req, status);
2712 goto out;
2715 status = filename_convert(ctx, conn,
2716 req->flags2 & FLAGS2_DFS_PATHNAMES,
2717 name,
2718 UCF_COND_ALLOW_WCARD_LCOMP,
2719 &path_contains_wcard,
2720 &smb_fname);
2721 if (!NT_STATUS_IS_OK(status)) {
2722 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2723 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2724 ERRSRV, ERRbadpath);
2725 goto out;
2727 reply_nterror(req, status);
2728 goto out;
2731 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2733 status = unlink_internals(conn, req, dirtype, smb_fname,
2734 path_contains_wcard);
2735 if (!NT_STATUS_IS_OK(status)) {
2736 if (open_was_deferred(req->mid)) {
2737 /* We have re-scheduled this call. */
2738 goto out;
2740 reply_nterror(req, status);
2741 goto out;
2744 reply_outbuf(req, 0, 0);
2745 out:
2746 TALLOC_FREE(smb_fname);
2747 END_PROFILE(SMBunlink);
2748 return;
2751 /****************************************************************************
2752 Fail for readbraw.
2753 ****************************************************************************/
2755 static void fail_readraw(void)
2757 const char *errstr = talloc_asprintf(talloc_tos(),
2758 "FAIL ! reply_readbraw: socket write fail (%s)",
2759 strerror(errno));
2760 if (!errstr) {
2761 errstr = "";
2763 exit_server_cleanly(errstr);
2766 /****************************************************************************
2767 Fake (read/write) sendfile. Returns -1 on read or write fail.
2768 ****************************************************************************/
2770 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2771 size_t nread)
2773 size_t bufsize;
2774 size_t tosend = nread;
2775 char *buf;
2777 if (nread == 0) {
2778 return 0;
2781 bufsize = MIN(nread, 65536);
2783 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2784 return -1;
2787 while (tosend > 0) {
2788 ssize_t ret;
2789 size_t cur_read;
2791 if (tosend > bufsize) {
2792 cur_read = bufsize;
2793 } else {
2794 cur_read = tosend;
2796 ret = read_file(fsp,buf,startpos,cur_read);
2797 if (ret == -1) {
2798 SAFE_FREE(buf);
2799 return -1;
2802 /* If we had a short read, fill with zeros. */
2803 if (ret < cur_read) {
2804 memset(buf + ret, '\0', cur_read - ret);
2807 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2808 SAFE_FREE(buf);
2809 return -1;
2811 tosend -= cur_read;
2812 startpos += cur_read;
2815 SAFE_FREE(buf);
2816 return (ssize_t)nread;
2819 #if defined(WITH_SENDFILE)
2820 /****************************************************************************
2821 Deal with the case of sendfile reading less bytes from the file than
2822 requested. Fill with zeros (all we can do).
2823 ****************************************************************************/
2825 static void sendfile_short_send(files_struct *fsp,
2826 ssize_t nread,
2827 size_t headersize,
2828 size_t smb_maxcnt)
2830 #define SHORT_SEND_BUFSIZE 1024
2831 if (nread < headersize) {
2832 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2833 "header for file %s (%s). Terminating\n",
2834 fsp_str_dbg(fsp), strerror(errno)));
2835 exit_server_cleanly("sendfile_short_send failed");
2838 nread -= headersize;
2840 if (nread < smb_maxcnt) {
2841 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2842 if (!buf) {
2843 exit_server_cleanly("sendfile_short_send: "
2844 "malloc failed");
2847 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2848 "with zeros !\n", fsp_str_dbg(fsp)));
2850 while (nread < smb_maxcnt) {
2852 * We asked for the real file size and told sendfile
2853 * to not go beyond the end of the file. But it can
2854 * happen that in between our fstat call and the
2855 * sendfile call the file was truncated. This is very
2856 * bad because we have already announced the larger
2857 * number of bytes to the client.
2859 * The best we can do now is to send 0-bytes, just as
2860 * a read from a hole in a sparse file would do.
2862 * This should happen rarely enough that I don't care
2863 * about efficiency here :-)
2865 size_t to_write;
2867 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2868 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2869 exit_server_cleanly("sendfile_short_send: "
2870 "write_data failed");
2872 nread += to_write;
2874 SAFE_FREE(buf);
2877 #endif /* defined WITH_SENDFILE */
2879 /****************************************************************************
2880 Return a readbraw error (4 bytes of zero).
2881 ****************************************************************************/
2883 static void reply_readbraw_error(void)
2885 char header[4];
2886 SIVAL(header,0,0);
2887 if (write_data(smbd_server_fd(),header,4) != 4) {
2888 fail_readraw();
2892 /****************************************************************************
2893 Use sendfile in readbraw.
2894 ****************************************************************************/
2896 static void send_file_readbraw(connection_struct *conn,
2897 struct smb_request *req,
2898 files_struct *fsp,
2899 SMB_OFF_T startpos,
2900 size_t nread,
2901 ssize_t mincount)
2903 char *outbuf = NULL;
2904 ssize_t ret=0;
2906 #if defined(WITH_SENDFILE)
2908 * We can only use sendfile on a non-chained packet
2909 * but we can use on a non-oplocked file. tridge proved this
2910 * on a train in Germany :-). JRA.
2911 * reply_readbraw has already checked the length.
2914 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2915 (fsp->wcp == NULL) &&
2916 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2917 ssize_t sendfile_read = -1;
2918 char header[4];
2919 DATA_BLOB header_blob;
2921 _smb_setlen(header,nread);
2922 header_blob = data_blob_const(header, 4);
2924 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2925 &header_blob, startpos, nread)) == -1) {
2926 /* Returning ENOSYS means no data at all was sent.
2927 * Do this as a normal read. */
2928 if (errno == ENOSYS) {
2929 goto normal_readbraw;
2933 * Special hack for broken Linux with no working sendfile. If we
2934 * return EINTR we sent the header but not the rest of the data.
2935 * Fake this up by doing read/write calls.
2937 if (errno == EINTR) {
2938 /* Ensure we don't do this again. */
2939 set_use_sendfile(SNUM(conn), False);
2940 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2942 if (fake_sendfile(fsp, startpos, nread) == -1) {
2943 DEBUG(0,("send_file_readbraw: "
2944 "fake_sendfile failed for "
2945 "file %s (%s).\n",
2946 fsp_str_dbg(fsp),
2947 strerror(errno)));
2948 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2950 return;
2953 DEBUG(0,("send_file_readbraw: sendfile failed for "
2954 "file %s (%s). Terminating\n",
2955 fsp_str_dbg(fsp), strerror(errno)));
2956 exit_server_cleanly("send_file_readbraw sendfile failed");
2957 } else if (sendfile_read == 0) {
2959 * Some sendfile implementations return 0 to indicate
2960 * that there was a short read, but nothing was
2961 * actually written to the socket. In this case,
2962 * fallback to the normal read path so the header gets
2963 * the correct byte count.
2965 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2966 "bytes falling back to the normal read: "
2967 "%s\n", fsp_str_dbg(fsp)));
2968 goto normal_readbraw;
2971 /* Deal with possible short send. */
2972 if (sendfile_read != 4+nread) {
2973 sendfile_short_send(fsp, sendfile_read, 4, nread);
2975 return;
2978 normal_readbraw:
2979 #endif
2981 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2982 if (!outbuf) {
2983 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2984 (unsigned)(nread+4)));
2985 reply_readbraw_error();
2986 return;
2989 if (nread > 0) {
2990 ret = read_file(fsp,outbuf+4,startpos,nread);
2991 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2992 if (ret < mincount)
2993 ret = 0;
2994 #else
2995 if (ret < nread)
2996 ret = 0;
2997 #endif
3000 _smb_setlen(outbuf,ret);
3001 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3002 fail_readraw();
3004 TALLOC_FREE(outbuf);
3007 /****************************************************************************
3008 Reply to a readbraw (core+ protocol).
3009 ****************************************************************************/
3011 void reply_readbraw(struct smb_request *req)
3013 connection_struct *conn = req->conn;
3014 ssize_t maxcount,mincount;
3015 size_t nread = 0;
3016 SMB_OFF_T startpos;
3017 files_struct *fsp;
3018 struct lock_struct lock;
3019 SMB_STRUCT_STAT st;
3020 SMB_OFF_T size = 0;
3022 START_PROFILE(SMBreadbraw);
3024 if (srv_is_signing_active(smbd_server_conn) ||
3025 is_encrypted_packet(req->inbuf)) {
3026 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3027 "raw reads/writes are disallowed.");
3030 if (req->wct < 8) {
3031 reply_readbraw_error();
3032 END_PROFILE(SMBreadbraw);
3033 return;
3037 * Special check if an oplock break has been issued
3038 * and the readraw request croses on the wire, we must
3039 * return a zero length response here.
3042 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3045 * We have to do a check_fsp by hand here, as
3046 * we must always return 4 zero bytes on error,
3047 * not a NTSTATUS.
3050 if (!fsp || !conn || conn != fsp->conn ||
3051 req->vuid != fsp->vuid ||
3052 fsp->is_directory || fsp->fh->fd == -1) {
3054 * fsp could be NULL here so use the value from the packet. JRA.
3056 DEBUG(3,("reply_readbraw: fnum %d not valid "
3057 "- cache prime?\n",
3058 (int)SVAL(req->vwv+0, 0)));
3059 reply_readbraw_error();
3060 END_PROFILE(SMBreadbraw);
3061 return;
3064 /* Do a "by hand" version of CHECK_READ. */
3065 if (!(fsp->can_read ||
3066 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3067 (fsp->access_mask & FILE_EXECUTE)))) {
3068 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3069 (int)SVAL(req->vwv+0, 0)));
3070 reply_readbraw_error();
3071 END_PROFILE(SMBreadbraw);
3072 return;
3075 flush_write_cache(fsp, READRAW_FLUSH);
3077 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3078 if(req->wct == 10) {
3080 * This is a large offset (64 bit) read.
3082 #ifdef LARGE_SMB_OFF_T
3084 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3086 #else /* !LARGE_SMB_OFF_T */
3089 * Ensure we haven't been sent a >32 bit offset.
3092 if(IVAL(req->vwv+8, 0) != 0) {
3093 DEBUG(0,("reply_readbraw: large offset "
3094 "(%x << 32) used and we don't support "
3095 "64 bit offsets.\n",
3096 (unsigned int)IVAL(req->vwv+8, 0) ));
3097 reply_readbraw_error();
3098 END_PROFILE(SMBreadbraw);
3099 return;
3102 #endif /* LARGE_SMB_OFF_T */
3104 if(startpos < 0) {
3105 DEBUG(0,("reply_readbraw: negative 64 bit "
3106 "readraw offset (%.0f) !\n",
3107 (double)startpos ));
3108 reply_readbraw_error();
3109 END_PROFILE(SMBreadbraw);
3110 return;
3114 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3115 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3117 /* ensure we don't overrun the packet size */
3118 maxcount = MIN(65535,maxcount);
3120 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3121 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3122 &lock);
3124 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3125 reply_readbraw_error();
3126 END_PROFILE(SMBreadbraw);
3127 return;
3130 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3131 size = st.st_ex_size;
3134 if (startpos >= size) {
3135 nread = 0;
3136 } else {
3137 nread = MIN(maxcount,(size - startpos));
3140 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3141 if (nread < mincount)
3142 nread = 0;
3143 #endif
3145 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3146 "min=%lu nread=%lu\n",
3147 fsp->fnum, (double)startpos,
3148 (unsigned long)maxcount,
3149 (unsigned long)mincount,
3150 (unsigned long)nread ) );
3152 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3154 DEBUG(5,("reply_readbraw finished\n"));
3156 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3158 END_PROFILE(SMBreadbraw);
3159 return;
3162 #undef DBGC_CLASS
3163 #define DBGC_CLASS DBGC_LOCKING
3165 /****************************************************************************
3166 Reply to a lockread (core+ protocol).
3167 ****************************************************************************/
3169 void reply_lockread(struct smb_request *req)
3171 connection_struct *conn = req->conn;
3172 ssize_t nread = -1;
3173 char *data;
3174 SMB_OFF_T startpos;
3175 size_t numtoread;
3176 NTSTATUS status;
3177 files_struct *fsp;
3178 struct byte_range_lock *br_lck = NULL;
3179 char *p = NULL;
3180 struct smbd_server_connection *sconn = smbd_server_conn;
3182 START_PROFILE(SMBlockread);
3184 if (req->wct < 5) {
3185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3186 END_PROFILE(SMBlockread);
3187 return;
3190 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3192 if (!check_fsp(conn, req, fsp)) {
3193 END_PROFILE(SMBlockread);
3194 return;
3197 if (!CHECK_READ(fsp,req)) {
3198 reply_doserror(req, ERRDOS, ERRbadaccess);
3199 END_PROFILE(SMBlockread);
3200 return;
3203 numtoread = SVAL(req->vwv+1, 0);
3204 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3206 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3208 reply_outbuf(req, 5, numtoread + 3);
3210 data = smb_buf(req->outbuf) + 3;
3213 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3214 * protocol request that predates the read/write lock concept.
3215 * Thus instead of asking for a read lock here we need to ask
3216 * for a write lock. JRA.
3217 * Note that the requested lock size is unaffected by max_recv.
3220 br_lck = do_lock(smbd_messaging_context(),
3221 fsp,
3222 req->smbpid,
3223 (uint64_t)numtoread,
3224 (uint64_t)startpos,
3225 WRITE_LOCK,
3226 WINDOWS_LOCK,
3227 False, /* Non-blocking lock. */
3228 &status,
3229 NULL,
3230 NULL);
3231 TALLOC_FREE(br_lck);
3233 if (NT_STATUS_V(status)) {
3234 reply_nterror(req, status);
3235 END_PROFILE(SMBlockread);
3236 return;
3240 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3243 if (numtoread > sconn->smb1.negprot.max_recv) {
3244 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3245 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3246 (unsigned int)numtoread,
3247 (unsigned int)sconn->smb1.negprot.max_recv));
3248 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3250 nread = read_file(fsp,data,startpos,numtoread);
3252 if (nread < 0) {
3253 reply_nterror(req, map_nt_error_from_unix(errno));
3254 END_PROFILE(SMBlockread);
3255 return;
3258 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3260 SSVAL(req->outbuf,smb_vwv0,nread);
3261 SSVAL(req->outbuf,smb_vwv5,nread+3);
3262 p = smb_buf(req->outbuf);
3263 SCVAL(p,0,0); /* pad byte. */
3264 SSVAL(p,1,nread);
3266 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3267 fsp->fnum, (int)numtoread, (int)nread));
3269 END_PROFILE(SMBlockread);
3270 return;
3273 #undef DBGC_CLASS
3274 #define DBGC_CLASS DBGC_ALL
3276 /****************************************************************************
3277 Reply to a read.
3278 ****************************************************************************/
3280 void reply_read(struct smb_request *req)
3282 connection_struct *conn = req->conn;
3283 size_t numtoread;
3284 ssize_t nread = 0;
3285 char *data;
3286 SMB_OFF_T startpos;
3287 int outsize = 0;
3288 files_struct *fsp;
3289 struct lock_struct lock;
3290 struct smbd_server_connection *sconn = smbd_server_conn;
3292 START_PROFILE(SMBread);
3294 if (req->wct < 3) {
3295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3296 END_PROFILE(SMBread);
3297 return;
3300 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3302 if (!check_fsp(conn, req, fsp)) {
3303 END_PROFILE(SMBread);
3304 return;
3307 if (!CHECK_READ(fsp,req)) {
3308 reply_doserror(req, ERRDOS, ERRbadaccess);
3309 END_PROFILE(SMBread);
3310 return;
3313 numtoread = SVAL(req->vwv+1, 0);
3314 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3316 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3319 * The requested read size cannot be greater than max_recv. JRA.
3321 if (numtoread > sconn->smb1.negprot.max_recv) {
3322 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3323 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3324 (unsigned int)numtoread,
3325 (unsigned int)sconn->smb1.negprot.max_recv));
3326 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3329 reply_outbuf(req, 5, numtoread+3);
3331 data = smb_buf(req->outbuf) + 3;
3333 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3334 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3335 &lock);
3337 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3338 reply_doserror(req, ERRDOS,ERRlock);
3339 END_PROFILE(SMBread);
3340 return;
3343 if (numtoread > 0)
3344 nread = read_file(fsp,data,startpos,numtoread);
3346 if (nread < 0) {
3347 reply_nterror(req, map_nt_error_from_unix(errno));
3348 goto strict_unlock;
3351 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3353 SSVAL(req->outbuf,smb_vwv0,nread);
3354 SSVAL(req->outbuf,smb_vwv5,nread+3);
3355 SCVAL(smb_buf(req->outbuf),0,1);
3356 SSVAL(smb_buf(req->outbuf),1,nread);
3358 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3359 fsp->fnum, (int)numtoread, (int)nread ) );
3361 strict_unlock:
3362 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3364 END_PROFILE(SMBread);
3365 return;
3368 /****************************************************************************
3369 Setup readX header.
3370 ****************************************************************************/
3372 static int setup_readX_header(struct smb_request *req, char *outbuf,
3373 size_t smb_maxcnt)
3375 int outsize;
3376 char *data;
3378 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3379 data = smb_buf(outbuf);
3381 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3383 SCVAL(outbuf,smb_vwv0,0xFF);
3384 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3385 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3386 SSVAL(outbuf,smb_vwv6,
3387 req_wct_ofs(req)
3388 + 1 /* the wct field */
3389 + 12 * sizeof(uint16_t) /* vwv */
3390 + 2); /* the buflen field */
3391 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3392 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3393 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3394 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3395 return outsize;
3398 /****************************************************************************
3399 Reply to a read and X - possibly using sendfile.
3400 ****************************************************************************/
3402 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3403 files_struct *fsp, SMB_OFF_T startpos,
3404 size_t smb_maxcnt)
3406 SMB_STRUCT_STAT sbuf;
3407 ssize_t nread = -1;
3408 struct lock_struct lock;
3409 int saved_errno = 0;
3411 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3412 reply_nterror(req, map_nt_error_from_unix(errno));
3413 return;
3416 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3417 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3418 &lock);
3420 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3421 reply_doserror(req, ERRDOS, ERRlock);
3422 return;
3425 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3426 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3428 * We already know that we would do a short read, so don't
3429 * try the sendfile() path.
3431 goto nosendfile_read;
3434 #if defined(WITH_SENDFILE)
3436 * We can only use sendfile on a non-chained packet
3437 * but we can use on a non-oplocked file. tridge proved this
3438 * on a train in Germany :-). JRA.
3441 if (!req_is_in_chain(req) &&
3442 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3443 (fsp->wcp == NULL) &&
3444 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3445 uint8 headerbuf[smb_size + 12 * 2];
3446 DATA_BLOB header;
3449 * Set up the packet header before send. We
3450 * assume here the sendfile will work (get the
3451 * correct amount of data).
3454 header = data_blob_const(headerbuf, sizeof(headerbuf));
3456 construct_reply_common_req(req, (char *)headerbuf);
3457 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3459 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3460 /* Returning ENOSYS means no data at all was sent.
3461 Do this as a normal read. */
3462 if (errno == ENOSYS) {
3463 goto normal_read;
3467 * Special hack for broken Linux with no working sendfile. If we
3468 * return EINTR we sent the header but not the rest of the data.
3469 * Fake this up by doing read/write calls.
3472 if (errno == EINTR) {
3473 /* Ensure we don't do this again. */
3474 set_use_sendfile(SNUM(conn), False);
3475 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3476 nread = fake_sendfile(fsp, startpos,
3477 smb_maxcnt);
3478 if (nread == -1) {
3479 DEBUG(0,("send_file_readX: "
3480 "fake_sendfile failed for "
3481 "file %s (%s).\n",
3482 fsp_str_dbg(fsp),
3483 strerror(errno)));
3484 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3486 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3487 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3488 /* No outbuf here means successful sendfile. */
3489 goto strict_unlock;
3492 DEBUG(0,("send_file_readX: sendfile failed for file "
3493 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3494 strerror(errno)));
3495 exit_server_cleanly("send_file_readX sendfile failed");
3496 } else if (nread == 0) {
3498 * Some sendfile implementations return 0 to indicate
3499 * that there was a short read, but nothing was
3500 * actually written to the socket. In this case,
3501 * fallback to the normal read path so the header gets
3502 * the correct byte count.
3504 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3505 "falling back to the normal read: %s\n",
3506 fsp_str_dbg(fsp)));
3507 goto normal_read;
3510 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3511 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3513 /* Deal with possible short send. */
3514 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3515 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3517 /* No outbuf here means successful sendfile. */
3518 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3519 SMB_PERFCOUNT_END(&req->pcd);
3520 goto strict_unlock;
3523 normal_read:
3525 #endif
3527 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3528 uint8 headerbuf[smb_size + 2*12];
3530 construct_reply_common_req(req, (char *)headerbuf);
3531 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3533 /* Send out the header. */
3534 if (write_data(smbd_server_fd(), (char *)headerbuf,
3535 sizeof(headerbuf)) != sizeof(headerbuf)) {
3536 DEBUG(0,("send_file_readX: write_data failed for file "
3537 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3538 strerror(errno)));
3539 exit_server_cleanly("send_file_readX sendfile failed");
3541 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3542 if (nread == -1) {
3543 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3544 "file %s (%s).\n", fsp_str_dbg(fsp),
3545 strerror(errno)));
3546 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3548 goto strict_unlock;
3551 nosendfile_read:
3553 reply_outbuf(req, 12, smb_maxcnt);
3555 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3556 saved_errno = errno;
3558 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3560 if (nread < 0) {
3561 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3562 return;
3565 setup_readX_header(req, (char *)req->outbuf, nread);
3567 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3568 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3570 chain_reply(req);
3571 return;
3573 strict_unlock:
3574 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3575 TALLOC_FREE(req->outbuf);
3576 return;
3579 /****************************************************************************
3580 Reply to a read and X.
3581 ****************************************************************************/
3583 void reply_read_and_X(struct smb_request *req)
3585 connection_struct *conn = req->conn;
3586 files_struct *fsp;
3587 SMB_OFF_T startpos;
3588 size_t smb_maxcnt;
3589 bool big_readX = False;
3590 #if 0
3591 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3592 #endif
3594 START_PROFILE(SMBreadX);
3596 if ((req->wct != 10) && (req->wct != 12)) {
3597 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3598 return;
3601 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3602 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3603 smb_maxcnt = SVAL(req->vwv+5, 0);
3605 /* If it's an IPC, pass off the pipe handler. */
3606 if (IS_IPC(conn)) {
3607 reply_pipe_read_and_X(req);
3608 END_PROFILE(SMBreadX);
3609 return;
3612 if (!check_fsp(conn, req, fsp)) {
3613 END_PROFILE(SMBreadX);
3614 return;
3617 if (!CHECK_READ(fsp,req)) {
3618 reply_doserror(req, ERRDOS,ERRbadaccess);
3619 END_PROFILE(SMBreadX);
3620 return;
3623 if (global_client_caps & CAP_LARGE_READX) {
3624 size_t upper_size = SVAL(req->vwv+7, 0);
3625 smb_maxcnt |= (upper_size<<16);
3626 if (upper_size > 1) {
3627 /* Can't do this on a chained packet. */
3628 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3629 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3630 END_PROFILE(SMBreadX);
3631 return;
3633 /* We currently don't do this on signed or sealed data. */
3634 if (srv_is_signing_active(smbd_server_conn) ||
3635 is_encrypted_packet(req->inbuf)) {
3636 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3637 END_PROFILE(SMBreadX);
3638 return;
3640 /* Is there room in the reply for this data ? */
3641 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3642 reply_nterror(req,
3643 NT_STATUS_INVALID_PARAMETER);
3644 END_PROFILE(SMBreadX);
3645 return;
3647 big_readX = True;
3651 if (req->wct == 12) {
3652 #ifdef LARGE_SMB_OFF_T
3654 * This is a large offset (64 bit) read.
3656 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3658 #else /* !LARGE_SMB_OFF_T */
3661 * Ensure we haven't been sent a >32 bit offset.
3664 if(IVAL(req->vwv+10, 0) != 0) {
3665 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3666 "used and we don't support 64 bit offsets.\n",
3667 (unsigned int)IVAL(req->vwv+10, 0) ));
3668 END_PROFILE(SMBreadX);
3669 reply_doserror(req, ERRDOS, ERRbadaccess);
3670 return;
3673 #endif /* LARGE_SMB_OFF_T */
3677 if (!big_readX &&
3678 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3679 goto out;
3682 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3684 out:
3685 END_PROFILE(SMBreadX);
3686 return;
3689 /****************************************************************************
3690 Error replies to writebraw must have smb_wct == 1. Fix this up.
3691 ****************************************************************************/
3693 void error_to_writebrawerr(struct smb_request *req)
3695 uint8 *old_outbuf = req->outbuf;
3697 reply_outbuf(req, 1, 0);
3699 memcpy(req->outbuf, old_outbuf, smb_size);
3700 TALLOC_FREE(old_outbuf);
3703 /****************************************************************************
3704 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3705 ****************************************************************************/
3707 void reply_writebraw(struct smb_request *req)
3709 connection_struct *conn = req->conn;
3710 char *buf = NULL;
3711 ssize_t nwritten=0;
3712 ssize_t total_written=0;
3713 size_t numtowrite=0;
3714 size_t tcount;
3715 SMB_OFF_T startpos;
3716 char *data=NULL;
3717 bool write_through;
3718 files_struct *fsp;
3719 struct lock_struct lock;
3720 NTSTATUS status;
3722 START_PROFILE(SMBwritebraw);
3725 * If we ever reply with an error, it must have the SMB command
3726 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3727 * we're finished.
3729 SCVAL(req->inbuf,smb_com,SMBwritec);
3731 if (srv_is_signing_active(smbd_server_conn)) {
3732 END_PROFILE(SMBwritebraw);
3733 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3734 "raw reads/writes are disallowed.");
3737 if (req->wct < 12) {
3738 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3739 error_to_writebrawerr(req);
3740 END_PROFILE(SMBwritebraw);
3741 return;
3744 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3745 if (!check_fsp(conn, req, fsp)) {
3746 error_to_writebrawerr(req);
3747 END_PROFILE(SMBwritebraw);
3748 return;
3751 if (!CHECK_WRITE(fsp)) {
3752 reply_doserror(req, ERRDOS, ERRbadaccess);
3753 error_to_writebrawerr(req);
3754 END_PROFILE(SMBwritebraw);
3755 return;
3758 tcount = IVAL(req->vwv+1, 0);
3759 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3760 write_through = BITSETW(req->vwv+7,0);
3762 /* We have to deal with slightly different formats depending
3763 on whether we are using the core+ or lanman1.0 protocol */
3765 if(Protocol <= PROTOCOL_COREPLUS) {
3766 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3767 data = smb_buf(req->inbuf);
3768 } else {
3769 numtowrite = SVAL(req->vwv+10, 0);
3770 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3773 /* Ensure we don't write bytes past the end of this packet. */
3774 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3776 error_to_writebrawerr(req);
3777 END_PROFILE(SMBwritebraw);
3778 return;
3781 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3782 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3783 &lock);
3785 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3786 reply_doserror(req, ERRDOS, ERRlock);
3787 error_to_writebrawerr(req);
3788 END_PROFILE(SMBwritebraw);
3789 return;
3792 if (numtowrite>0) {
3793 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3796 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3797 "wrote=%d sync=%d\n",
3798 fsp->fnum, (double)startpos, (int)numtowrite,
3799 (int)nwritten, (int)write_through));
3801 if (nwritten < (ssize_t)numtowrite) {
3802 reply_doserror(req, ERRHRD, ERRdiskfull);
3803 error_to_writebrawerr(req);
3804 goto strict_unlock;
3807 total_written = nwritten;
3809 /* Allocate a buffer of 64k + length. */
3810 buf = TALLOC_ARRAY(NULL, char, 65540);
3811 if (!buf) {
3812 reply_doserror(req, ERRDOS, ERRnomem);
3813 error_to_writebrawerr(req);
3814 goto strict_unlock;
3817 /* Return a SMBwritebraw message to the redirector to tell
3818 * it to send more bytes */
3820 memcpy(buf, req->inbuf, smb_size);
3821 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3822 SCVAL(buf,smb_com,SMBwritebraw);
3823 SSVALS(buf,smb_vwv0,0xFFFF);
3824 show_msg(buf);
3825 if (!srv_send_smb(smbd_server_fd(),
3826 buf,
3827 false, 0, /* no signing */
3828 IS_CONN_ENCRYPTED(conn),
3829 &req->pcd)) {
3830 exit_server_cleanly("reply_writebraw: srv_send_smb "
3831 "failed.");
3834 /* Now read the raw data into the buffer and write it */
3835 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3836 &numtowrite);
3837 if (!NT_STATUS_IS_OK(status)) {
3838 exit_server_cleanly("secondary writebraw failed");
3841 /* Set up outbuf to return the correct size */
3842 reply_outbuf(req, 1, 0);
3844 if (numtowrite != 0) {
3846 if (numtowrite > 0xFFFF) {
3847 DEBUG(0,("reply_writebraw: Oversize secondary write "
3848 "raw requested (%u). Terminating\n",
3849 (unsigned int)numtowrite ));
3850 exit_server_cleanly("secondary writebraw failed");
3853 if (tcount > nwritten+numtowrite) {
3854 DEBUG(3,("reply_writebraw: Client overestimated the "
3855 "write %d %d %d\n",
3856 (int)tcount,(int)nwritten,(int)numtowrite));
3859 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3861 if (!NT_STATUS_IS_OK(status)) {
3862 DEBUG(0,("reply_writebraw: Oversize secondary write "
3863 "raw read failed (%s). Terminating\n",
3864 nt_errstr(status)));
3865 exit_server_cleanly("secondary writebraw failed");
3868 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3869 if (nwritten == -1) {
3870 TALLOC_FREE(buf);
3871 reply_nterror(req, map_nt_error_from_unix(errno));
3872 error_to_writebrawerr(req);
3873 goto strict_unlock;
3876 if (nwritten < (ssize_t)numtowrite) {
3877 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3878 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3881 if (nwritten > 0) {
3882 total_written += nwritten;
3886 TALLOC_FREE(buf);
3887 SSVAL(req->outbuf,smb_vwv0,total_written);
3889 status = sync_file(conn, fsp, write_through);
3890 if (!NT_STATUS_IS_OK(status)) {
3891 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3892 fsp_str_dbg(fsp), nt_errstr(status)));
3893 reply_nterror(req, status);
3894 error_to_writebrawerr(req);
3895 goto strict_unlock;
3898 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3899 "wrote=%d\n",
3900 fsp->fnum, (double)startpos, (int)numtowrite,
3901 (int)total_written));
3903 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3905 /* We won't return a status if write through is not selected - this
3906 * follows what WfWg does */
3907 END_PROFILE(SMBwritebraw);
3909 if (!write_through && total_written==tcount) {
3911 #if RABBIT_PELLET_FIX
3913 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3914 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3915 * JRA.
3917 if (!send_keepalive(smbd_server_fd())) {
3918 exit_server_cleanly("reply_writebraw: send of "
3919 "keepalive failed");
3921 #endif
3922 TALLOC_FREE(req->outbuf);
3924 return;
3926 strict_unlock:
3927 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3929 END_PROFILE(SMBwritebraw);
3930 return;
3933 #undef DBGC_CLASS
3934 #define DBGC_CLASS DBGC_LOCKING
3936 /****************************************************************************
3937 Reply to a writeunlock (core+).
3938 ****************************************************************************/
3940 void reply_writeunlock(struct smb_request *req)
3942 connection_struct *conn = req->conn;
3943 ssize_t nwritten = -1;
3944 size_t numtowrite;
3945 SMB_OFF_T startpos;
3946 const char *data;
3947 NTSTATUS status = NT_STATUS_OK;
3948 files_struct *fsp;
3949 struct lock_struct lock;
3950 int saved_errno = 0;
3952 START_PROFILE(SMBwriteunlock);
3954 if (req->wct < 5) {
3955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3956 END_PROFILE(SMBwriteunlock);
3957 return;
3960 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3962 if (!check_fsp(conn, req, fsp)) {
3963 END_PROFILE(SMBwriteunlock);
3964 return;
3967 if (!CHECK_WRITE(fsp)) {
3968 reply_doserror(req, ERRDOS,ERRbadaccess);
3969 END_PROFILE(SMBwriteunlock);
3970 return;
3973 numtowrite = SVAL(req->vwv+1, 0);
3974 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3975 data = (const char *)req->buf + 3;
3977 if (numtowrite) {
3978 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3979 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3980 &lock);
3982 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3983 reply_doserror(req, ERRDOS, ERRlock);
3984 END_PROFILE(SMBwriteunlock);
3985 return;
3989 /* The special X/Open SMB protocol handling of
3990 zero length writes is *NOT* done for
3991 this call */
3992 if(numtowrite == 0) {
3993 nwritten = 0;
3994 } else {
3995 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3996 saved_errno = errno;
3999 status = sync_file(conn, fsp, False /* write through */);
4000 if (!NT_STATUS_IS_OK(status)) {
4001 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4002 fsp_str_dbg(fsp), nt_errstr(status)));
4003 reply_nterror(req, status);
4004 goto strict_unlock;
4007 if(nwritten < 0) {
4008 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4009 goto strict_unlock;
4012 if((nwritten < numtowrite) && (numtowrite != 0)) {
4013 reply_doserror(req, ERRHRD, ERRdiskfull);
4014 goto strict_unlock;
4017 if (numtowrite) {
4018 status = do_unlock(smbd_messaging_context(),
4019 fsp,
4020 req->smbpid,
4021 (uint64_t)numtowrite,
4022 (uint64_t)startpos,
4023 WINDOWS_LOCK);
4025 if (NT_STATUS_V(status)) {
4026 reply_nterror(req, status);
4027 goto strict_unlock;
4031 reply_outbuf(req, 1, 0);
4033 SSVAL(req->outbuf,smb_vwv0,nwritten);
4035 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4036 fsp->fnum, (int)numtowrite, (int)nwritten));
4038 strict_unlock:
4039 if (numtowrite) {
4040 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4043 END_PROFILE(SMBwriteunlock);
4044 return;
4047 #undef DBGC_CLASS
4048 #define DBGC_CLASS DBGC_ALL
4050 /****************************************************************************
4051 Reply to a write.
4052 ****************************************************************************/
4054 void reply_write(struct smb_request *req)
4056 connection_struct *conn = req->conn;
4057 size_t numtowrite;
4058 ssize_t nwritten = -1;
4059 SMB_OFF_T startpos;
4060 const char *data;
4061 files_struct *fsp;
4062 struct lock_struct lock;
4063 NTSTATUS status;
4064 int saved_errno = 0;
4066 START_PROFILE(SMBwrite);
4068 if (req->wct < 5) {
4069 END_PROFILE(SMBwrite);
4070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4071 return;
4074 /* If it's an IPC, pass off the pipe handler. */
4075 if (IS_IPC(conn)) {
4076 reply_pipe_write(req);
4077 END_PROFILE(SMBwrite);
4078 return;
4081 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4083 if (!check_fsp(conn, req, fsp)) {
4084 END_PROFILE(SMBwrite);
4085 return;
4088 if (!CHECK_WRITE(fsp)) {
4089 reply_doserror(req, ERRDOS, ERRbadaccess);
4090 END_PROFILE(SMBwrite);
4091 return;
4094 numtowrite = SVAL(req->vwv+1, 0);
4095 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4096 data = (const char *)req->buf + 3;
4098 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4099 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4100 &lock);
4102 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4103 reply_doserror(req, ERRDOS, ERRlock);
4104 END_PROFILE(SMBwrite);
4105 return;
4109 * X/Open SMB protocol says that if smb_vwv1 is
4110 * zero then the file size should be extended or
4111 * truncated to the size given in smb_vwv[2-3].
4114 if(numtowrite == 0) {
4116 * This is actually an allocate call, and set EOF. JRA.
4118 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4119 if (nwritten < 0) {
4120 reply_nterror(req, NT_STATUS_DISK_FULL);
4121 goto strict_unlock;
4123 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4124 if (nwritten < 0) {
4125 reply_nterror(req, NT_STATUS_DISK_FULL);
4126 goto strict_unlock;
4128 trigger_write_time_update_immediate(fsp);
4129 } else {
4130 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4133 status = sync_file(conn, fsp, False);
4134 if (!NT_STATUS_IS_OK(status)) {
4135 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4136 fsp_str_dbg(fsp), nt_errstr(status)));
4137 reply_nterror(req, status);
4138 goto strict_unlock;
4141 if(nwritten < 0) {
4142 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4143 goto strict_unlock;
4146 if((nwritten == 0) && (numtowrite != 0)) {
4147 reply_doserror(req, ERRHRD, ERRdiskfull);
4148 goto strict_unlock;
4151 reply_outbuf(req, 1, 0);
4153 SSVAL(req->outbuf,smb_vwv0,nwritten);
4155 if (nwritten < (ssize_t)numtowrite) {
4156 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4157 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4160 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4162 strict_unlock:
4163 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4165 END_PROFILE(SMBwrite);
4166 return;
4169 /****************************************************************************
4170 Ensure a buffer is a valid writeX for recvfile purposes.
4171 ****************************************************************************/
4173 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4174 (2*14) + /* word count (including bcc) */ \
4175 1 /* pad byte */)
4177 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4179 size_t numtowrite;
4180 connection_struct *conn = NULL;
4181 unsigned int doff = 0;
4182 size_t len = smb_len_large(inbuf);
4183 struct smbd_server_connection *sconn = smbd_server_conn;
4185 if (is_encrypted_packet(inbuf)) {
4186 /* Can't do this on encrypted
4187 * connections. */
4188 return false;
4191 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4192 return false;
4195 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4196 CVAL(inbuf,smb_wct) != 14) {
4197 DEBUG(10,("is_valid_writeX_buffer: chained or "
4198 "invalid word length.\n"));
4199 return false;
4202 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4203 if (conn == NULL) {
4204 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4205 return false;
4207 if (IS_IPC(conn)) {
4208 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4209 return false;
4211 if (IS_PRINT(conn)) {
4212 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4213 return false;
4215 doff = SVAL(inbuf,smb_vwv11);
4217 numtowrite = SVAL(inbuf,smb_vwv10);
4219 if (len > doff && len - doff > 0xFFFF) {
4220 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4223 if (numtowrite == 0) {
4224 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4225 return false;
4228 /* Ensure the sizes match up. */
4229 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4230 /* no pad byte...old smbclient :-( */
4231 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4232 (unsigned int)doff,
4233 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4234 return false;
4237 if (len - doff != numtowrite) {
4238 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4239 "len = %u, doff = %u, numtowrite = %u\n",
4240 (unsigned int)len,
4241 (unsigned int)doff,
4242 (unsigned int)numtowrite ));
4243 return false;
4246 DEBUG(10,("is_valid_writeX_buffer: true "
4247 "len = %u, doff = %u, numtowrite = %u\n",
4248 (unsigned int)len,
4249 (unsigned int)doff,
4250 (unsigned int)numtowrite ));
4252 return true;
4255 /****************************************************************************
4256 Reply to a write and X.
4257 ****************************************************************************/
4259 void reply_write_and_X(struct smb_request *req)
4261 connection_struct *conn = req->conn;
4262 files_struct *fsp;
4263 struct lock_struct lock;
4264 SMB_OFF_T startpos;
4265 size_t numtowrite;
4266 bool write_through;
4267 ssize_t nwritten;
4268 unsigned int smb_doff;
4269 unsigned int smblen;
4270 char *data;
4271 NTSTATUS status;
4273 START_PROFILE(SMBwriteX);
4275 if ((req->wct != 12) && (req->wct != 14)) {
4276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4277 END_PROFILE(SMBwriteX);
4278 return;
4281 numtowrite = SVAL(req->vwv+10, 0);
4282 smb_doff = SVAL(req->vwv+11, 0);
4283 smblen = smb_len(req->inbuf);
4285 if (req->unread_bytes > 0xFFFF ||
4286 (smblen > smb_doff &&
4287 smblen - smb_doff > 0xFFFF)) {
4288 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4291 if (req->unread_bytes) {
4292 /* Can't do a recvfile write on IPC$ */
4293 if (IS_IPC(conn)) {
4294 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4295 END_PROFILE(SMBwriteX);
4296 return;
4298 if (numtowrite != req->unread_bytes) {
4299 reply_doserror(req, ERRDOS, ERRbadmem);
4300 END_PROFILE(SMBwriteX);
4301 return;
4303 } else {
4304 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4305 smb_doff + numtowrite > smblen) {
4306 reply_doserror(req, ERRDOS, ERRbadmem);
4307 END_PROFILE(SMBwriteX);
4308 return;
4312 /* If it's an IPC, pass off the pipe handler. */
4313 if (IS_IPC(conn)) {
4314 if (req->unread_bytes) {
4315 reply_doserror(req, ERRDOS, ERRbadmem);
4316 END_PROFILE(SMBwriteX);
4317 return;
4319 reply_pipe_write_and_X(req);
4320 END_PROFILE(SMBwriteX);
4321 return;
4324 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4325 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4326 write_through = BITSETW(req->vwv+7,0);
4328 if (!check_fsp(conn, req, fsp)) {
4329 END_PROFILE(SMBwriteX);
4330 return;
4333 if (!CHECK_WRITE(fsp)) {
4334 reply_doserror(req, ERRDOS, ERRbadaccess);
4335 END_PROFILE(SMBwriteX);
4336 return;
4339 data = smb_base(req->inbuf) + smb_doff;
4341 if(req->wct == 14) {
4342 #ifdef LARGE_SMB_OFF_T
4344 * This is a large offset (64 bit) write.
4346 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4348 #else /* !LARGE_SMB_OFF_T */
4351 * Ensure we haven't been sent a >32 bit offset.
4354 if(IVAL(req->vwv+12, 0) != 0) {
4355 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4356 "used and we don't support 64 bit offsets.\n",
4357 (unsigned int)IVAL(req->vwv+12, 0) ));
4358 reply_doserror(req, ERRDOS, ERRbadaccess);
4359 END_PROFILE(SMBwriteX);
4360 return;
4363 #endif /* LARGE_SMB_OFF_T */
4366 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4367 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4368 &lock);
4370 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4371 reply_doserror(req, ERRDOS, ERRlock);
4372 END_PROFILE(SMBwriteX);
4373 return;
4376 /* X/Open SMB protocol says that, unlike SMBwrite
4377 if the length is zero then NO truncation is
4378 done, just a write of zero. To truncate a file,
4379 use SMBwrite. */
4381 if(numtowrite == 0) {
4382 nwritten = 0;
4383 } else {
4385 if ((req->unread_bytes == 0) &&
4386 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4387 numtowrite)) {
4388 goto strict_unlock;
4391 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4394 if(nwritten < 0) {
4395 reply_nterror(req, map_nt_error_from_unix(errno));
4396 goto strict_unlock;
4399 if((nwritten == 0) && (numtowrite != 0)) {
4400 reply_doserror(req, ERRHRD, ERRdiskfull);
4401 goto strict_unlock;
4404 reply_outbuf(req, 6, 0);
4405 SSVAL(req->outbuf,smb_vwv2,nwritten);
4406 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4408 if (nwritten < (ssize_t)numtowrite) {
4409 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4410 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4413 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4414 fsp->fnum, (int)numtowrite, (int)nwritten));
4416 status = sync_file(conn, fsp, write_through);
4417 if (!NT_STATUS_IS_OK(status)) {
4418 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4419 fsp_str_dbg(fsp), nt_errstr(status)));
4420 reply_nterror(req, status);
4421 goto strict_unlock;
4424 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4426 END_PROFILE(SMBwriteX);
4427 chain_reply(req);
4428 return;
4430 strict_unlock:
4431 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4433 END_PROFILE(SMBwriteX);
4434 return;
4437 /****************************************************************************
4438 Reply to a lseek.
4439 ****************************************************************************/
4441 void reply_lseek(struct smb_request *req)
4443 connection_struct *conn = req->conn;
4444 SMB_OFF_T startpos;
4445 SMB_OFF_T res= -1;
4446 int mode,umode;
4447 files_struct *fsp;
4449 START_PROFILE(SMBlseek);
4451 if (req->wct < 4) {
4452 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4453 END_PROFILE(SMBlseek);
4454 return;
4457 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4459 if (!check_fsp(conn, req, fsp)) {
4460 return;
4463 flush_write_cache(fsp, SEEK_FLUSH);
4465 mode = SVAL(req->vwv+1, 0) & 3;
4466 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4467 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4469 switch (mode) {
4470 case 0:
4471 umode = SEEK_SET;
4472 res = startpos;
4473 break;
4474 case 1:
4475 umode = SEEK_CUR;
4476 res = fsp->fh->pos + startpos;
4477 break;
4478 case 2:
4479 umode = SEEK_END;
4480 break;
4481 default:
4482 umode = SEEK_SET;
4483 res = startpos;
4484 break;
4487 if (umode == SEEK_END) {
4488 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4489 if(errno == EINVAL) {
4490 SMB_OFF_T current_pos = startpos;
4491 SMB_STRUCT_STAT sbuf;
4493 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4494 reply_nterror(req,
4495 map_nt_error_from_unix(errno));
4496 END_PROFILE(SMBlseek);
4497 return;
4500 current_pos += sbuf.st_ex_size;
4501 if(current_pos < 0)
4502 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4506 if(res == -1) {
4507 reply_nterror(req, map_nt_error_from_unix(errno));
4508 END_PROFILE(SMBlseek);
4509 return;
4513 fsp->fh->pos = res;
4515 reply_outbuf(req, 2, 0);
4516 SIVAL(req->outbuf,smb_vwv0,res);
4518 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4519 fsp->fnum, (double)startpos, (double)res, mode));
4521 END_PROFILE(SMBlseek);
4522 return;
4525 /****************************************************************************
4526 Reply to a flush.
4527 ****************************************************************************/
4529 void reply_flush(struct smb_request *req)
4531 connection_struct *conn = req->conn;
4532 uint16 fnum;
4533 files_struct *fsp;
4535 START_PROFILE(SMBflush);
4537 if (req->wct < 1) {
4538 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4539 return;
4542 fnum = SVAL(req->vwv+0, 0);
4543 fsp = file_fsp(req, fnum);
4545 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4546 return;
4549 if (!fsp) {
4550 file_sync_all(conn);
4551 } else {
4552 NTSTATUS status = sync_file(conn, fsp, True);
4553 if (!NT_STATUS_IS_OK(status)) {
4554 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4555 fsp_str_dbg(fsp), nt_errstr(status)));
4556 reply_nterror(req, status);
4557 END_PROFILE(SMBflush);
4558 return;
4562 reply_outbuf(req, 0, 0);
4564 DEBUG(3,("flush\n"));
4565 END_PROFILE(SMBflush);
4566 return;
4569 /****************************************************************************
4570 Reply to a exit.
4571 conn POINTER CAN BE NULL HERE !
4572 ****************************************************************************/
4574 void reply_exit(struct smb_request *req)
4576 START_PROFILE(SMBexit);
4578 file_close_pid(req->smbpid, req->vuid);
4580 reply_outbuf(req, 0, 0);
4582 DEBUG(3,("exit\n"));
4584 END_PROFILE(SMBexit);
4585 return;
4588 /****************************************************************************
4589 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4590 ****************************************************************************/
4592 void reply_close(struct smb_request *req)
4594 connection_struct *conn = req->conn;
4595 NTSTATUS status = NT_STATUS_OK;
4596 files_struct *fsp = NULL;
4597 START_PROFILE(SMBclose);
4599 if (req->wct < 3) {
4600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4601 END_PROFILE(SMBclose);
4602 return;
4605 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4608 * We can only use check_fsp if we know it's not a directory.
4611 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4612 reply_doserror(req, ERRDOS, ERRbadfid);
4613 END_PROFILE(SMBclose);
4614 return;
4617 if(fsp->is_directory) {
4619 * Special case - close NT SMB directory handle.
4621 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4622 status = close_file(req, fsp, NORMAL_CLOSE);
4623 } else {
4624 time_t t;
4626 * Close ordinary file.
4629 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4630 fsp->fh->fd, fsp->fnum,
4631 conn->num_files_open));
4634 * Take care of any time sent in the close.
4637 t = srv_make_unix_date3(req->vwv+1);
4638 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4641 * close_file() returns the unix errno if an error
4642 * was detected on close - normally this is due to
4643 * a disk full error. If not then it was probably an I/O error.
4646 status = close_file(req, fsp, NORMAL_CLOSE);
4649 if (!NT_STATUS_IS_OK(status)) {
4650 reply_nterror(req, status);
4651 END_PROFILE(SMBclose);
4652 return;
4655 reply_outbuf(req, 0, 0);
4656 END_PROFILE(SMBclose);
4657 return;
4660 /****************************************************************************
4661 Reply to a writeclose (Core+ protocol).
4662 ****************************************************************************/
4664 void reply_writeclose(struct smb_request *req)
4666 connection_struct *conn = req->conn;
4667 size_t numtowrite;
4668 ssize_t nwritten = -1;
4669 NTSTATUS close_status = NT_STATUS_OK;
4670 SMB_OFF_T startpos;
4671 const char *data;
4672 struct timespec mtime;
4673 files_struct *fsp;
4674 struct lock_struct lock;
4676 START_PROFILE(SMBwriteclose);
4678 if (req->wct < 6) {
4679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4680 END_PROFILE(SMBwriteclose);
4681 return;
4684 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4686 if (!check_fsp(conn, req, fsp)) {
4687 END_PROFILE(SMBwriteclose);
4688 return;
4690 if (!CHECK_WRITE(fsp)) {
4691 reply_doserror(req, ERRDOS,ERRbadaccess);
4692 END_PROFILE(SMBwriteclose);
4693 return;
4696 numtowrite = SVAL(req->vwv+1, 0);
4697 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4698 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4699 data = (const char *)req->buf + 1;
4701 if (numtowrite) {
4702 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4703 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4704 &lock);
4706 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4707 reply_doserror(req, ERRDOS,ERRlock);
4708 END_PROFILE(SMBwriteclose);
4709 return;
4713 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4715 set_close_write_time(fsp, mtime);
4718 * More insanity. W2K only closes the file if writelen > 0.
4719 * JRA.
4722 if (numtowrite) {
4723 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4724 "file %s\n", fsp_str_dbg(fsp)));
4725 close_status = close_file(req, fsp, NORMAL_CLOSE);
4728 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4729 fsp->fnum, (int)numtowrite, (int)nwritten,
4730 conn->num_files_open));
4732 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4733 reply_doserror(req, ERRHRD, ERRdiskfull);
4734 goto strict_unlock;
4737 if(!NT_STATUS_IS_OK(close_status)) {
4738 reply_nterror(req, close_status);
4739 goto strict_unlock;
4742 reply_outbuf(req, 1, 0);
4744 SSVAL(req->outbuf,smb_vwv0,nwritten);
4746 strict_unlock:
4747 if (numtowrite) {
4748 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4751 END_PROFILE(SMBwriteclose);
4752 return;
4755 #undef DBGC_CLASS
4756 #define DBGC_CLASS DBGC_LOCKING
4758 /****************************************************************************
4759 Reply to a lock.
4760 ****************************************************************************/
4762 void reply_lock(struct smb_request *req)
4764 connection_struct *conn = req->conn;
4765 uint64_t count,offset;
4766 NTSTATUS status;
4767 files_struct *fsp;
4768 struct byte_range_lock *br_lck = NULL;
4770 START_PROFILE(SMBlock);
4772 if (req->wct < 5) {
4773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4774 END_PROFILE(SMBlock);
4775 return;
4778 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4780 if (!check_fsp(conn, req, fsp)) {
4781 END_PROFILE(SMBlock);
4782 return;
4785 count = (uint64_t)IVAL(req->vwv+1, 0);
4786 offset = (uint64_t)IVAL(req->vwv+3, 0);
4788 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4789 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4791 br_lck = do_lock(smbd_messaging_context(),
4792 fsp,
4793 req->smbpid,
4794 count,
4795 offset,
4796 WRITE_LOCK,
4797 WINDOWS_LOCK,
4798 False, /* Non-blocking lock. */
4799 &status,
4800 NULL,
4801 NULL);
4803 TALLOC_FREE(br_lck);
4805 if (NT_STATUS_V(status)) {
4806 reply_nterror(req, status);
4807 END_PROFILE(SMBlock);
4808 return;
4811 reply_outbuf(req, 0, 0);
4813 END_PROFILE(SMBlock);
4814 return;
4817 /****************************************************************************
4818 Reply to a unlock.
4819 ****************************************************************************/
4821 void reply_unlock(struct smb_request *req)
4823 connection_struct *conn = req->conn;
4824 uint64_t count,offset;
4825 NTSTATUS status;
4826 files_struct *fsp;
4828 START_PROFILE(SMBunlock);
4830 if (req->wct < 5) {
4831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4832 END_PROFILE(SMBunlock);
4833 return;
4836 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4838 if (!check_fsp(conn, req, fsp)) {
4839 END_PROFILE(SMBunlock);
4840 return;
4843 count = (uint64_t)IVAL(req->vwv+1, 0);
4844 offset = (uint64_t)IVAL(req->vwv+3, 0);
4846 status = do_unlock(smbd_messaging_context(),
4847 fsp,
4848 req->smbpid,
4849 count,
4850 offset,
4851 WINDOWS_LOCK);
4853 if (NT_STATUS_V(status)) {
4854 reply_nterror(req, status);
4855 END_PROFILE(SMBunlock);
4856 return;
4859 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4860 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4862 reply_outbuf(req, 0, 0);
4864 END_PROFILE(SMBunlock);
4865 return;
4868 #undef DBGC_CLASS
4869 #define DBGC_CLASS DBGC_ALL
4871 /****************************************************************************
4872 Reply to a tdis.
4873 conn POINTER CAN BE NULL HERE !
4874 ****************************************************************************/
4876 void reply_tdis(struct smb_request *req)
4878 connection_struct *conn = req->conn;
4879 START_PROFILE(SMBtdis);
4881 if (!conn) {
4882 DEBUG(4,("Invalid connection in tdis\n"));
4883 reply_doserror(req, ERRSRV, ERRinvnid);
4884 END_PROFILE(SMBtdis);
4885 return;
4888 conn->used = False;
4890 close_cnum(conn,req->vuid);
4891 req->conn = NULL;
4893 reply_outbuf(req, 0, 0);
4894 END_PROFILE(SMBtdis);
4895 return;
4898 /****************************************************************************
4899 Reply to a echo.
4900 conn POINTER CAN BE NULL HERE !
4901 ****************************************************************************/
4903 void reply_echo(struct smb_request *req)
4905 connection_struct *conn = req->conn;
4906 struct smb_perfcount_data local_pcd;
4907 struct smb_perfcount_data *cur_pcd;
4908 int smb_reverb;
4909 int seq_num;
4911 START_PROFILE(SMBecho);
4913 smb_init_perfcount_data(&local_pcd);
4915 if (req->wct < 1) {
4916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4917 END_PROFILE(SMBecho);
4918 return;
4921 smb_reverb = SVAL(req->vwv+0, 0);
4923 reply_outbuf(req, 1, req->buflen);
4925 /* copy any incoming data back out */
4926 if (req->buflen > 0) {
4927 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4930 if (smb_reverb > 100) {
4931 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4932 smb_reverb = 100;
4935 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4937 /* this makes sure we catch the request pcd */
4938 if (seq_num == smb_reverb) {
4939 cur_pcd = &req->pcd;
4940 } else {
4941 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4942 cur_pcd = &local_pcd;
4945 SSVAL(req->outbuf,smb_vwv0,seq_num);
4947 show_msg((char *)req->outbuf);
4948 if (!srv_send_smb(smbd_server_fd(),
4949 (char *)req->outbuf,
4950 true, req->seqnum+1,
4951 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4952 cur_pcd))
4953 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4956 DEBUG(3,("echo %d times\n", smb_reverb));
4958 TALLOC_FREE(req->outbuf);
4960 END_PROFILE(SMBecho);
4961 return;
4964 /****************************************************************************
4965 Reply to a printopen.
4966 ****************************************************************************/
4968 void reply_printopen(struct smb_request *req)
4970 connection_struct *conn = req->conn;
4971 files_struct *fsp;
4972 SMB_STRUCT_STAT sbuf;
4973 NTSTATUS status;
4975 START_PROFILE(SMBsplopen);
4977 if (req->wct < 2) {
4978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4979 END_PROFILE(SMBsplopen);
4980 return;
4983 if (!CAN_PRINT(conn)) {
4984 reply_doserror(req, ERRDOS, ERRnoaccess);
4985 END_PROFILE(SMBsplopen);
4986 return;
4989 status = file_new(req, conn, &fsp);
4990 if(!NT_STATUS_IS_OK(status)) {
4991 reply_nterror(req, status);
4992 END_PROFILE(SMBsplopen);
4993 return;
4996 /* Open for exclusive use, write only. */
4997 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4999 if (!NT_STATUS_IS_OK(status)) {
5000 file_free(req, fsp);
5001 reply_nterror(req, status);
5002 END_PROFILE(SMBsplopen);
5003 return;
5006 reply_outbuf(req, 1, 0);
5007 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5009 DEBUG(3,("openprint fd=%d fnum=%d\n",
5010 fsp->fh->fd, fsp->fnum));
5012 END_PROFILE(SMBsplopen);
5013 return;
5016 /****************************************************************************
5017 Reply to a printclose.
5018 ****************************************************************************/
5020 void reply_printclose(struct smb_request *req)
5022 connection_struct *conn = req->conn;
5023 files_struct *fsp;
5024 NTSTATUS status;
5026 START_PROFILE(SMBsplclose);
5028 if (req->wct < 1) {
5029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5030 END_PROFILE(SMBsplclose);
5031 return;
5034 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5036 if (!check_fsp(conn, req, fsp)) {
5037 END_PROFILE(SMBsplclose);
5038 return;
5041 if (!CAN_PRINT(conn)) {
5042 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5043 END_PROFILE(SMBsplclose);
5044 return;
5047 DEBUG(3,("printclose fd=%d fnum=%d\n",
5048 fsp->fh->fd,fsp->fnum));
5050 status = close_file(req, fsp, NORMAL_CLOSE);
5052 if(!NT_STATUS_IS_OK(status)) {
5053 reply_nterror(req, status);
5054 END_PROFILE(SMBsplclose);
5055 return;
5058 reply_outbuf(req, 0, 0);
5060 END_PROFILE(SMBsplclose);
5061 return;
5064 /****************************************************************************
5065 Reply to a printqueue.
5066 ****************************************************************************/
5068 void reply_printqueue(struct smb_request *req)
5070 connection_struct *conn = req->conn;
5071 int max_count;
5072 int start_index;
5074 START_PROFILE(SMBsplretq);
5076 if (req->wct < 2) {
5077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5078 END_PROFILE(SMBsplretq);
5079 return;
5082 max_count = SVAL(req->vwv+0, 0);
5083 start_index = SVAL(req->vwv+1, 0);
5085 /* we used to allow the client to get the cnum wrong, but that
5086 is really quite gross and only worked when there was only
5087 one printer - I think we should now only accept it if they
5088 get it right (tridge) */
5089 if (!CAN_PRINT(conn)) {
5090 reply_doserror(req, ERRDOS, ERRnoaccess);
5091 END_PROFILE(SMBsplretq);
5092 return;
5095 reply_outbuf(req, 2, 3);
5096 SSVAL(req->outbuf,smb_vwv0,0);
5097 SSVAL(req->outbuf,smb_vwv1,0);
5098 SCVAL(smb_buf(req->outbuf),0,1);
5099 SSVAL(smb_buf(req->outbuf),1,0);
5101 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5102 start_index, max_count));
5105 print_queue_struct *queue = NULL;
5106 print_status_struct status;
5107 int count = print_queue_status(SNUM(conn), &queue, &status);
5108 int num_to_get = ABS(max_count);
5109 int first = (max_count>0?start_index:start_index+max_count+1);
5110 int i;
5112 if (first >= count)
5113 num_to_get = 0;
5114 else
5115 num_to_get = MIN(num_to_get,count-first);
5118 for (i=first;i<first+num_to_get;i++) {
5119 char blob[28];
5120 char *p = blob;
5122 srv_put_dos_date2(p,0,queue[i].time);
5123 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5124 SSVAL(p,5, queue[i].job);
5125 SIVAL(p,7,queue[i].size);
5126 SCVAL(p,11,0);
5127 srvstr_push(blob, req->flags2, p+12,
5128 queue[i].fs_user, 16, STR_ASCII);
5130 if (message_push_blob(
5131 &req->outbuf,
5132 data_blob_const(
5133 blob, sizeof(blob))) == -1) {
5134 reply_nterror(req, NT_STATUS_NO_MEMORY);
5135 END_PROFILE(SMBsplretq);
5136 return;
5140 if (count > 0) {
5141 SSVAL(req->outbuf,smb_vwv0,count);
5142 SSVAL(req->outbuf,smb_vwv1,
5143 (max_count>0?first+count:first-1));
5144 SCVAL(smb_buf(req->outbuf),0,1);
5145 SSVAL(smb_buf(req->outbuf),1,28*count);
5148 SAFE_FREE(queue);
5150 DEBUG(3,("%d entries returned in queue\n",count));
5153 END_PROFILE(SMBsplretq);
5154 return;
5157 /****************************************************************************
5158 Reply to a printwrite.
5159 ****************************************************************************/
5161 void reply_printwrite(struct smb_request *req)
5163 connection_struct *conn = req->conn;
5164 int numtowrite;
5165 const char *data;
5166 files_struct *fsp;
5168 START_PROFILE(SMBsplwr);
5170 if (req->wct < 1) {
5171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5172 END_PROFILE(SMBsplwr);
5173 return;
5176 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5178 if (!check_fsp(conn, req, fsp)) {
5179 END_PROFILE(SMBsplwr);
5180 return;
5183 if (!CAN_PRINT(conn)) {
5184 reply_doserror(req, ERRDOS, ERRnoaccess);
5185 END_PROFILE(SMBsplwr);
5186 return;
5189 if (!CHECK_WRITE(fsp)) {
5190 reply_doserror(req, ERRDOS, ERRbadaccess);
5191 END_PROFILE(SMBsplwr);
5192 return;
5195 numtowrite = SVAL(req->buf, 1);
5197 if (req->buflen < numtowrite + 3) {
5198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5199 END_PROFILE(SMBsplwr);
5200 return;
5203 data = (const char *)req->buf + 3;
5205 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5206 reply_nterror(req, map_nt_error_from_unix(errno));
5207 END_PROFILE(SMBsplwr);
5208 return;
5211 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5213 END_PROFILE(SMBsplwr);
5214 return;
5217 /****************************************************************************
5218 Reply to a mkdir.
5219 ****************************************************************************/
5221 void reply_mkdir(struct smb_request *req)
5223 connection_struct *conn = req->conn;
5224 struct smb_filename *smb_dname = NULL;
5225 char *directory = NULL;
5226 NTSTATUS status;
5227 TALLOC_CTX *ctx = talloc_tos();
5229 START_PROFILE(SMBmkdir);
5231 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5232 STR_TERMINATE, &status);
5233 if (!NT_STATUS_IS_OK(status)) {
5234 reply_nterror(req, status);
5235 goto out;
5238 status = filename_convert(ctx, conn,
5239 req->flags2 & FLAGS2_DFS_PATHNAMES,
5240 directory,
5242 NULL,
5243 &smb_dname);
5244 if (!NT_STATUS_IS_OK(status)) {
5245 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5246 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5247 ERRSRV, ERRbadpath);
5248 goto out;
5250 reply_nterror(req, status);
5251 goto out;
5254 status = create_directory(conn, req, smb_dname);
5256 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5258 if (!NT_STATUS_IS_OK(status)) {
5260 if (!use_nt_status()
5261 && NT_STATUS_EQUAL(status,
5262 NT_STATUS_OBJECT_NAME_COLLISION)) {
5264 * Yes, in the DOS error code case we get a
5265 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5266 * samba4 torture test.
5268 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5271 reply_nterror(req, status);
5272 goto out;
5275 reply_outbuf(req, 0, 0);
5277 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5278 out:
5279 TALLOC_FREE(smb_dname);
5280 END_PROFILE(SMBmkdir);
5281 return;
5284 /****************************************************************************
5285 Static function used by reply_rmdir to delete an entire directory
5286 tree recursively. Return True on ok, False on fail.
5287 ****************************************************************************/
5289 static bool recursive_rmdir(TALLOC_CTX *ctx,
5290 connection_struct *conn,
5291 struct smb_filename *smb_dname)
5293 const char *dname = NULL;
5294 bool ret = True;
5295 long offset = 0;
5296 SMB_STRUCT_STAT st;
5297 struct smb_Dir *dir_hnd;
5299 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5301 dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
5302 if(dir_hnd == NULL)
5303 return False;
5305 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5306 struct smb_filename *smb_dname_full = NULL;
5307 char *fullname = NULL;
5308 bool do_break = true;
5309 NTSTATUS status;
5311 if (ISDOT(dname) || ISDOTDOT(dname)) {
5312 continue;
5315 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
5316 false)) {
5317 continue;
5320 /* Construct the full name. */
5321 fullname = talloc_asprintf(ctx,
5322 "%s/%s",
5323 smb_dname->base_name,
5324 dname);
5325 if (!fullname) {
5326 errno = ENOMEM;
5327 goto err_break;
5330 status = create_synthetic_smb_fname(talloc_tos(), fullname,
5331 NULL, NULL,
5332 &smb_dname_full);
5333 if (!NT_STATUS_IS_OK(status)) {
5334 goto err_break;
5337 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5338 goto err_break;
5341 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5342 if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
5343 goto err_break;
5345 if(SMB_VFS_RMDIR(conn,
5346 smb_dname_full->base_name) != 0) {
5347 goto err_break;
5349 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5350 goto err_break;
5353 /* Successful iteration. */
5354 do_break = false;
5356 err_break:
5357 TALLOC_FREE(smb_dname_full);
5358 TALLOC_FREE(fullname);
5359 if (do_break) {
5360 ret = false;
5361 break;
5364 TALLOC_FREE(dir_hnd);
5365 return ret;
5368 /****************************************************************************
5369 The internals of the rmdir code - called elsewhere.
5370 ****************************************************************************/
5372 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5373 connection_struct *conn,
5374 struct smb_filename *smb_dname)
5376 int ret;
5377 SMB_STRUCT_STAT st;
5379 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5381 /* Might be a symlink. */
5382 if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
5383 return map_nt_error_from_unix(errno);
5386 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
5387 /* Is what it points to a directory ? */
5388 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
5389 return map_nt_error_from_unix(errno);
5391 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
5392 return NT_STATUS_NOT_A_DIRECTORY;
5394 ret = SMB_VFS_UNLINK(conn, smb_dname);
5395 } else {
5396 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5398 if (ret == 0) {
5399 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5400 FILE_NOTIFY_CHANGE_DIR_NAME,
5401 smb_dname->base_name);
5402 return NT_STATUS_OK;
5405 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5407 * Check to see if the only thing in this directory are
5408 * vetoed files/directories. If so then delete them and
5409 * retry. If we fail to delete any of them (and we *don't*
5410 * do a recursive delete) then fail the rmdir.
5412 const char *dname;
5413 long dirpos = 0;
5414 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5415 smb_dname->base_name, NULL,
5418 if(dir_hnd == NULL) {
5419 errno = ENOTEMPTY;
5420 goto err;
5423 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5424 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5425 continue;
5426 if (!is_visible_file(conn, smb_dname->base_name, dname,
5427 &st, false))
5428 continue;
5429 if(!IS_VETO_PATH(conn, dname)) {
5430 TALLOC_FREE(dir_hnd);
5431 errno = ENOTEMPTY;
5432 goto err;
5436 /* We only have veto files/directories.
5437 * Are we allowed to delete them ? */
5439 if(!lp_recursive_veto_delete(SNUM(conn))) {
5440 TALLOC_FREE(dir_hnd);
5441 errno = ENOTEMPTY;
5442 goto err;
5445 /* Do a recursive delete. */
5446 RewindDir(dir_hnd,&dirpos);
5447 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5448 struct smb_filename *smb_dname_full = NULL;
5449 char *fullname = NULL;
5450 bool do_break = true;
5451 NTSTATUS status;
5453 if (ISDOT(dname) || ISDOTDOT(dname)) {
5454 continue;
5456 if (!is_visible_file(conn, smb_dname->base_name, dname,
5457 &st, false)) {
5458 continue;
5461 fullname = talloc_asprintf(ctx,
5462 "%s/%s",
5463 smb_dname->base_name,
5464 dname);
5466 if(!fullname) {
5467 errno = ENOMEM;
5468 goto err_break;
5471 status = create_synthetic_smb_fname(talloc_tos(),
5472 fullname, NULL,
5473 NULL,
5474 &smb_dname_full);
5475 if (!NT_STATUS_IS_OK(status)) {
5476 errno = map_errno_from_nt_status(status);
5477 goto err_break;
5480 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5481 goto err_break;
5483 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5484 if(!recursive_rmdir(ctx, conn,
5485 smb_dname_full)) {
5486 goto err_break;
5488 if(SMB_VFS_RMDIR(conn,
5489 smb_dname_full->base_name) != 0) {
5490 goto err_break;
5492 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5493 goto err_break;
5496 /* Successful iteration. */
5497 do_break = false;
5499 err_break:
5500 TALLOC_FREE(fullname);
5501 TALLOC_FREE(smb_dname_full);
5502 if (do_break)
5503 break;
5505 TALLOC_FREE(dir_hnd);
5506 /* Retry the rmdir */
5507 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5510 err:
5512 if (ret != 0) {
5513 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5514 "%s\n", smb_fname_str_dbg(smb_dname),
5515 strerror(errno)));
5516 return map_nt_error_from_unix(errno);
5519 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5520 FILE_NOTIFY_CHANGE_DIR_NAME,
5521 smb_dname->base_name);
5523 return NT_STATUS_OK;
5526 /****************************************************************************
5527 Reply to a rmdir.
5528 ****************************************************************************/
5530 void reply_rmdir(struct smb_request *req)
5532 connection_struct *conn = req->conn;
5533 struct smb_filename *smb_dname = NULL;
5534 char *directory = NULL;
5535 NTSTATUS status;
5536 TALLOC_CTX *ctx = talloc_tos();
5537 struct smbd_server_connection *sconn = smbd_server_conn;
5539 START_PROFILE(SMBrmdir);
5541 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5542 STR_TERMINATE, &status);
5543 if (!NT_STATUS_IS_OK(status)) {
5544 reply_nterror(req, status);
5545 goto out;
5548 status = filename_convert(ctx, conn,
5549 req->flags2 & FLAGS2_DFS_PATHNAMES,
5550 directory,
5552 NULL,
5553 &smb_dname);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5556 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5557 ERRSRV, ERRbadpath);
5558 goto out;
5560 reply_nterror(req, status);
5561 goto out;
5564 if (is_ntfs_stream_smb_fname(smb_dname)) {
5565 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5566 goto out;
5569 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5570 status = rmdir_internals(ctx, conn, smb_dname);
5571 if (!NT_STATUS_IS_OK(status)) {
5572 reply_nterror(req, status);
5573 goto out;
5576 reply_outbuf(req, 0, 0);
5578 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5579 out:
5580 TALLOC_FREE(smb_dname);
5581 END_PROFILE(SMBrmdir);
5582 return;
5585 /*******************************************************************
5586 Resolve wildcards in a filename rename.
5587 ********************************************************************/
5589 static bool resolve_wildcards(TALLOC_CTX *ctx,
5590 const char *name1,
5591 const char *name2,
5592 char **pp_newname)
5594 char *name2_copy = NULL;
5595 char *root1 = NULL;
5596 char *root2 = NULL;
5597 char *ext1 = NULL;
5598 char *ext2 = NULL;
5599 char *p,*p2, *pname1, *pname2;
5601 name2_copy = talloc_strdup(ctx, name2);
5602 if (!name2_copy) {
5603 return False;
5606 pname1 = strrchr_m(name1,'/');
5607 pname2 = strrchr_m(name2_copy,'/');
5609 if (!pname1 || !pname2) {
5610 return False;
5613 /* Truncate the copy of name2 at the last '/' */
5614 *pname2 = '\0';
5616 /* Now go past the '/' */
5617 pname1++;
5618 pname2++;
5620 root1 = talloc_strdup(ctx, pname1);
5621 root2 = talloc_strdup(ctx, pname2);
5623 if (!root1 || !root2) {
5624 return False;
5627 p = strrchr_m(root1,'.');
5628 if (p) {
5629 *p = 0;
5630 ext1 = talloc_strdup(ctx, p+1);
5631 } else {
5632 ext1 = talloc_strdup(ctx, "");
5634 p = strrchr_m(root2,'.');
5635 if (p) {
5636 *p = 0;
5637 ext2 = talloc_strdup(ctx, p+1);
5638 } else {
5639 ext2 = talloc_strdup(ctx, "");
5642 if (!ext1 || !ext2) {
5643 return False;
5646 p = root1;
5647 p2 = root2;
5648 while (*p2) {
5649 if (*p2 == '?') {
5650 /* Hmmm. Should this be mb-aware ? */
5651 *p2 = *p;
5652 p2++;
5653 } else if (*p2 == '*') {
5654 *p2 = '\0';
5655 root2 = talloc_asprintf(ctx, "%s%s",
5656 root2,
5658 if (!root2) {
5659 return False;
5661 break;
5662 } else {
5663 p2++;
5665 if (*p) {
5666 p++;
5670 p = ext1;
5671 p2 = ext2;
5672 while (*p2) {
5673 if (*p2 == '?') {
5674 /* Hmmm. Should this be mb-aware ? */
5675 *p2 = *p;
5676 p2++;
5677 } else if (*p2 == '*') {
5678 *p2 = '\0';
5679 ext2 = talloc_asprintf(ctx, "%s%s",
5680 ext2,
5682 if (!ext2) {
5683 return False;
5685 break;
5686 } else {
5687 p2++;
5689 if (*p) {
5690 p++;
5694 if (*ext2) {
5695 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5696 name2_copy,
5697 root2,
5698 ext2);
5699 } else {
5700 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5701 name2_copy,
5702 root2);
5705 if (!*pp_newname) {
5706 return False;
5709 return True;
5712 /****************************************************************************
5713 Ensure open files have their names updated. Updated to notify other smbd's
5714 asynchronously.
5715 ****************************************************************************/
5717 static void rename_open_files(connection_struct *conn,
5718 struct share_mode_lock *lck,
5719 const struct smb_filename *smb_fname_dst)
5721 files_struct *fsp;
5722 bool did_rename = False;
5723 NTSTATUS status;
5725 for(fsp = file_find_di_first(lck->id); fsp;
5726 fsp = file_find_di_next(fsp)) {
5727 /* fsp_name is a relative path under the fsp. To change this for other
5728 sharepaths we need to manipulate relative paths. */
5729 /* TODO - create the absolute path and manipulate the newname
5730 relative to the sharepath. */
5731 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5732 continue;
5734 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5735 "(file_id %s) from %s -> %s\n", fsp->fnum,
5736 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5737 smb_fname_str_dbg(smb_fname_dst)));
5739 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5740 if (NT_STATUS_IS_OK(status)) {
5741 did_rename = True;
5745 if (!did_rename) {
5746 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5747 "for %s\n", file_id_string_tos(&lck->id),
5748 smb_fname_str_dbg(smb_fname_dst)));
5751 /* Send messages to all smbd's (not ourself) that the name has changed. */
5752 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5753 smb_fname_dst);
5757 /****************************************************************************
5758 We need to check if the source path is a parent directory of the destination
5759 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5760 refuse the rename with a sharing violation. Under UNIX the above call can
5761 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5762 probably need to check that the client is a Windows one before disallowing
5763 this as a UNIX client (one with UNIX extensions) can know the source is a
5764 symlink and make this decision intelligently. Found by an excellent bug
5765 report from <AndyLiebman@aol.com>.
5766 ****************************************************************************/
5768 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5769 const struct smb_filename *smb_fname_dst)
5771 const char *psrc = smb_fname_src->base_name;
5772 const char *pdst = smb_fname_dst->base_name;
5773 size_t slen;
5775 if (psrc[0] == '.' && psrc[1] == '/') {
5776 psrc += 2;
5778 if (pdst[0] == '.' && pdst[1] == '/') {
5779 pdst += 2;
5781 if ((slen = strlen(psrc)) > strlen(pdst)) {
5782 return False;
5784 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5788 * Do the notify calls from a rename
5791 static void notify_rename(connection_struct *conn, bool is_dir,
5792 const struct smb_filename *smb_fname_src,
5793 const struct smb_filename *smb_fname_dst)
5795 char *parent_dir_src = NULL;
5796 char *parent_dir_dst = NULL;
5797 uint32 mask;
5799 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5800 : FILE_NOTIFY_CHANGE_FILE_NAME;
5802 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5803 &parent_dir_src, NULL) ||
5804 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5805 &parent_dir_dst, NULL)) {
5806 goto out;
5809 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5810 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5811 smb_fname_src->base_name);
5812 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5813 smb_fname_dst->base_name);
5815 else {
5816 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5817 smb_fname_src->base_name);
5818 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5819 smb_fname_dst->base_name);
5822 /* this is a strange one. w2k3 gives an additional event for
5823 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5824 files, but not directories */
5825 if (!is_dir) {
5826 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5827 FILE_NOTIFY_CHANGE_ATTRIBUTES
5828 |FILE_NOTIFY_CHANGE_CREATION,
5829 smb_fname_dst->base_name);
5831 out:
5832 TALLOC_FREE(parent_dir_src);
5833 TALLOC_FREE(parent_dir_dst);
5836 /****************************************************************************
5837 Rename an open file - given an fsp.
5838 ****************************************************************************/
5840 NTSTATUS rename_internals_fsp(connection_struct *conn,
5841 files_struct *fsp,
5842 const struct smb_filename *smb_fname_dst_in,
5843 uint32 attrs,
5844 bool replace_if_exists)
5846 TALLOC_CTX *ctx = talloc_tos();
5847 struct smb_filename *smb_fname_src = NULL;
5848 struct smb_filename *smb_fname_dst = NULL;
5849 SMB_STRUCT_STAT sbuf;
5850 NTSTATUS status = NT_STATUS_OK;
5851 struct share_mode_lock *lck = NULL;
5852 bool dst_exists, old_is_stream, new_is_stream;
5854 ZERO_STRUCT(sbuf);
5856 status = check_name(conn, smb_fname_dst_in->base_name);
5857 if (!NT_STATUS_IS_OK(status)) {
5858 return status;
5861 /* Make a copy of the src and dst smb_fname structs */
5862 status = copy_smb_filename(ctx, fsp->fsp_name, &smb_fname_src);
5863 if (!NT_STATUS_IS_OK(status)) {
5864 goto out;
5867 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5868 if (!NT_STATUS_IS_OK(status)) {
5869 goto out;
5872 /* Ensure the dst smb_fname contains a '/' */
5873 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5874 char * tmp;
5875 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5876 smb_fname_dst->base_name);
5877 if (!tmp) {
5878 status = NT_STATUS_NO_MEMORY;
5879 goto out;
5881 TALLOC_FREE(smb_fname_dst->base_name);
5882 smb_fname_dst->base_name = tmp;
5886 * Check for special case with case preserving and not
5887 * case sensitive. If the old last component differs from the original
5888 * last component only by case, then we should allow
5889 * the rename (user is trying to change the case of the
5890 * filename).
5892 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5893 strequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
5894 strequal(smb_fname_src->stream_name, smb_fname_dst->stream_name)) {
5895 char *last_slash;
5896 char *fname_dst_lcomp_base_mod = NULL;
5897 struct smb_filename *smb_fname_orig_lcomp = NULL;
5900 * Get the last component of the destination name. Note that
5901 * we guarantee that destination name contains a '/' character
5902 * above.
5904 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5905 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5906 if (!fname_dst_lcomp_base_mod) {
5907 status = NT_STATUS_NO_MEMORY;
5908 goto out;
5912 * Create an smb_filename struct using the original last
5913 * component of the destination.
5915 status = create_synthetic_smb_fname_split(ctx,
5916 smb_fname_dst->original_lcomp, NULL,
5917 &smb_fname_orig_lcomp);
5918 if (!NT_STATUS_IS_OK(status)) {
5919 TALLOC_FREE(fname_dst_lcomp_base_mod);
5920 goto out;
5923 /* If the base names only differ by case, use original. */
5924 if(!strcsequal(fname_dst_lcomp_base_mod,
5925 smb_fname_orig_lcomp->base_name)) {
5926 char *tmp;
5928 * Replace the modified last component with the
5929 * original.
5931 *last_slash = '\0'; /* Truncate at the '/' */
5932 tmp = talloc_asprintf(smb_fname_dst,
5933 "%s/%s",
5934 smb_fname_dst->base_name,
5935 smb_fname_orig_lcomp->base_name);
5936 if (tmp == NULL) {
5937 status = NT_STATUS_NO_MEMORY;
5938 TALLOC_FREE(fname_dst_lcomp_base_mod);
5939 TALLOC_FREE(smb_fname_orig_lcomp);
5940 goto out;
5942 TALLOC_FREE(smb_fname_dst->base_name);
5943 smb_fname_dst->base_name = tmp;
5946 /* If the stream_names only differ by case, use original. */
5947 if(!strcsequal(smb_fname_dst->stream_name,
5948 smb_fname_orig_lcomp->stream_name)) {
5949 char *tmp = NULL;
5950 /* Use the original stream. */
5951 tmp = talloc_strdup(smb_fname_dst,
5952 smb_fname_orig_lcomp->stream_name);
5953 if (tmp == NULL) {
5954 status = NT_STATUS_NO_MEMORY;
5955 TALLOC_FREE(fname_dst_lcomp_base_mod);
5956 TALLOC_FREE(smb_fname_orig_lcomp);
5957 goto out;
5959 TALLOC_FREE(smb_fname_dst->stream_name);
5960 smb_fname_dst->stream_name = tmp;
5962 TALLOC_FREE(fname_dst_lcomp_base_mod);
5963 TALLOC_FREE(smb_fname_orig_lcomp);
5967 * If the src and dest names are identical - including case,
5968 * don't do the rename, just return success.
5971 if (strcsequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
5972 strcsequal(smb_fname_src->stream_name,
5973 smb_fname_dst->stream_name)) {
5974 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5975 "- returning success\n",
5976 smb_fname_str_dbg(smb_fname_dst)));
5977 status = NT_STATUS_OK;
5978 goto out;
5981 old_is_stream = is_ntfs_stream_smb_fname(smb_fname_src);
5982 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5984 /* Return the correct error code if both names aren't streams. */
5985 if (!old_is_stream && new_is_stream) {
5986 status = NT_STATUS_OBJECT_NAME_INVALID;
5987 goto out;
5990 if (old_is_stream && !new_is_stream) {
5991 status = NT_STATUS_INVALID_PARAMETER;
5992 goto out;
5995 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5997 if(!replace_if_exists && dst_exists) {
5998 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5999 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6000 smb_fname_str_dbg(smb_fname_dst)));
6001 status = NT_STATUS_OBJECT_NAME_COLLISION;
6002 goto out;
6005 if (dst_exists) {
6006 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6007 &smb_fname_dst->st);
6008 files_struct *dst_fsp = file_find_di_first(fileid);
6009 /* The file can be open when renaming a stream */
6010 if (dst_fsp && !new_is_stream) {
6011 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6012 status = NT_STATUS_ACCESS_DENIED;
6013 goto out;
6017 /* Ensure we have a valid stat struct for the source. */
6018 if (fsp->fh->fd != -1) {
6019 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
6020 status = map_nt_error_from_unix(errno);
6021 goto out;
6023 } else {
6024 int ret = -1;
6025 if (fsp->posix_open) {
6026 ret = SMB_VFS_LSTAT(conn, smb_fname_src);
6027 } else {
6029 ret = SMB_VFS_STAT(conn, smb_fname_src);
6031 if (ret == -1) {
6032 status = map_nt_error_from_unix(errno);
6033 goto out;
6035 sbuf = smb_fname_src->st;
6038 status = can_rename(conn, fsp, attrs, &sbuf);
6040 if (!NT_STATUS_IS_OK(status)) {
6041 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6042 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6043 smb_fname_str_dbg(smb_fname_dst)));
6044 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6045 status = NT_STATUS_ACCESS_DENIED;
6046 goto out;
6049 if (rename_path_prefix_equal(smb_fname_src, smb_fname_dst)) {
6050 status = NT_STATUS_ACCESS_DENIED;
6053 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6054 NULL);
6057 * We have the file open ourselves, so not being able to get the
6058 * corresponding share mode lock is a fatal error.
6061 SMB_ASSERT(lck != NULL);
6063 if(SMB_VFS_RENAME(conn, smb_fname_src, smb_fname_dst) == 0) {
6064 uint32 create_options = fsp->fh->private_options;
6066 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6067 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6068 smb_fname_str_dbg(smb_fname_dst)));
6070 notify_rename(conn, fsp->is_directory, smb_fname_src,
6071 smb_fname_dst);
6073 rename_open_files(conn, lck, smb_fname_dst);
6076 * A rename acts as a new file create w.r.t. allowing an initial delete
6077 * on close, probably because in Windows there is a new handle to the
6078 * new file. If initial delete on close was requested but not
6079 * originally set, we need to set it here. This is probably not 100% correct,
6080 * but will work for the CIFSFS client which in non-posix mode
6081 * depends on these semantics. JRA.
6084 if (create_options & FILE_DELETE_ON_CLOSE) {
6085 status = can_set_delete_on_close(fsp, True, 0);
6087 if (NT_STATUS_IS_OK(status)) {
6088 /* Note that here we set the *inital* delete on close flag,
6089 * not the regular one. The magic gets handled in close. */
6090 fsp->initial_delete_on_close = True;
6093 TALLOC_FREE(lck);
6094 status = NT_STATUS_OK;
6095 goto out;
6098 TALLOC_FREE(lck);
6100 if (errno == ENOTDIR || errno == EISDIR) {
6101 status = NT_STATUS_OBJECT_NAME_COLLISION;
6102 } else {
6103 status = map_nt_error_from_unix(errno);
6106 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6107 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6108 smb_fname_str_dbg(smb_fname_dst)));
6110 out:
6111 TALLOC_FREE(smb_fname_src);
6112 TALLOC_FREE(smb_fname_dst);
6114 return status;
6117 /****************************************************************************
6118 The guts of the rename command, split out so it may be called by the NT SMB
6119 code.
6120 ****************************************************************************/
6122 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6123 connection_struct *conn,
6124 struct smb_request *req,
6125 struct smb_filename *smb_fname_src,
6126 struct smb_filename *smb_fname_dst,
6127 uint32 attrs,
6128 bool replace_if_exists,
6129 bool src_has_wild,
6130 bool dest_has_wild,
6131 uint32_t access_mask)
6133 char *fname_src_dir = NULL;
6134 char *fname_src_mask = NULL;
6135 int count=0;
6136 NTSTATUS status = NT_STATUS_OK;
6137 struct smb_Dir *dir_hnd = NULL;
6138 const char *dname;
6139 long offset = 0;
6140 int create_options = 0;
6141 bool posix_pathnames = lp_posix_pathnames();
6144 * Split the old name into directory and last component
6145 * strings. Note that unix_convert may have stripped off a
6146 * leading ./ from both name and newname if the rename is
6147 * at the root of the share. We need to make sure either both
6148 * name and newname contain a / character or neither of them do
6149 * as this is checked in resolve_wildcards().
6152 /* Split up the directory from the filename/mask. */
6153 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6154 &fname_src_dir, &fname_src_mask);
6155 if (!NT_STATUS_IS_OK(status)) {
6156 status = NT_STATUS_NO_MEMORY;
6157 goto out;
6161 * We should only check the mangled cache
6162 * here if unix_convert failed. This means
6163 * that the path in 'mask' doesn't exist
6164 * on the file system and so we need to look
6165 * for a possible mangle. This patch from
6166 * Tine Smukavec <valentin.smukavec@hermes.si>.
6169 if (!VALID_STAT(smb_fname_src->st) &&
6170 mangle_is_mangled(fname_src_mask, conn->params)) {
6171 char *new_mask = NULL;
6172 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6173 conn->params);
6174 if (new_mask) {
6175 TALLOC_FREE(fname_src_mask);
6176 fname_src_mask = new_mask;
6180 if (!src_has_wild) {
6181 files_struct *fsp;
6184 * Only one file needs to be renamed. Append the mask back
6185 * onto the directory.
6187 TALLOC_FREE(smb_fname_src->base_name);
6188 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6189 "%s/%s",
6190 fname_src_dir,
6191 fname_src_mask);
6192 if (!smb_fname_src->base_name) {
6193 status = NT_STATUS_NO_MEMORY;
6194 goto out;
6197 /* Ensure dst fname contains a '/' also */
6198 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6199 char *tmp;
6200 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6201 smb_fname_dst->base_name);
6202 if (!tmp) {
6203 status = NT_STATUS_NO_MEMORY;
6204 goto out;
6206 TALLOC_FREE(smb_fname_dst->base_name);
6207 smb_fname_dst->base_name = tmp;
6210 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6211 "case_preserve = %d, short case preserve = %d, "
6212 "directory = %s, newname = %s, "
6213 "last_component_dest = %s\n",
6214 conn->case_sensitive, conn->case_preserve,
6215 conn->short_case_preserve,
6216 smb_fname_str_dbg(smb_fname_src),
6217 smb_fname_str_dbg(smb_fname_dst),
6218 smb_fname_dst->original_lcomp));
6220 /* The dest name still may have wildcards. */
6221 if (dest_has_wild) {
6222 char *fname_dst_mod = NULL;
6223 if (!resolve_wildcards(smb_fname_dst,
6224 smb_fname_src->base_name,
6225 smb_fname_dst->base_name,
6226 &fname_dst_mod)) {
6227 DEBUG(6, ("rename_internals: resolve_wildcards "
6228 "%s %s failed\n",
6229 smb_fname_src->base_name,
6230 smb_fname_dst->base_name));
6231 status = NT_STATUS_NO_MEMORY;
6232 goto out;
6234 TALLOC_FREE(smb_fname_dst->base_name);
6235 smb_fname_dst->base_name = fname_dst_mod;
6238 ZERO_STRUCT(smb_fname_src->st);
6239 if (posix_pathnames) {
6240 SMB_VFS_LSTAT(conn, smb_fname_src);
6241 } else {
6242 SMB_VFS_STAT(conn, smb_fname_src);
6245 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6246 create_options |= FILE_DIRECTORY_FILE;
6249 status = SMB_VFS_CREATE_FILE(
6250 conn, /* conn */
6251 req, /* req */
6252 0, /* root_dir_fid */
6253 smb_fname_src, /* fname */
6254 access_mask, /* access_mask */
6255 (FILE_SHARE_READ | /* share_access */
6256 FILE_SHARE_WRITE),
6257 FILE_OPEN, /* create_disposition*/
6258 create_options, /* create_options */
6259 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6260 0, /* oplock_request */
6261 0, /* allocation_size */
6262 NULL, /* sd */
6263 NULL, /* ea_list */
6264 &fsp, /* result */
6265 NULL); /* pinfo */
6267 if (!NT_STATUS_IS_OK(status)) {
6268 DEBUG(3, ("Could not open rename source %s: %s\n",
6269 smb_fname_str_dbg(smb_fname_src),
6270 nt_errstr(status)));
6271 goto out;
6274 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6275 attrs, replace_if_exists);
6277 close_file(req, fsp, NORMAL_CLOSE);
6279 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6280 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6281 smb_fname_str_dbg(smb_fname_dst)));
6283 goto out;
6287 * Wildcards - process each file that matches.
6289 if (strequal(fname_src_mask, "????????.???")) {
6290 TALLOC_FREE(fname_src_mask);
6291 fname_src_mask = talloc_strdup(ctx, "*");
6292 if (!fname_src_mask) {
6293 status = NT_STATUS_NO_MEMORY;
6294 goto out;
6298 status = check_name(conn, fname_src_dir);
6299 if (!NT_STATUS_IS_OK(status)) {
6300 goto out;
6303 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6304 attrs);
6305 if (dir_hnd == NULL) {
6306 status = map_nt_error_from_unix(errno);
6307 goto out;
6310 status = NT_STATUS_NO_SUCH_FILE;
6312 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6313 * - gentest fix. JRA
6316 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6317 files_struct *fsp = NULL;
6318 char *destname = NULL;
6319 bool sysdir_entry = False;
6321 /* Quick check for "." and ".." */
6322 if (ISDOT(dname) || ISDOTDOT(dname)) {
6323 if (attrs & aDIR) {
6324 sysdir_entry = True;
6325 } else {
6326 continue;
6330 if (!is_visible_file(conn, fname_src_dir, dname,
6331 &smb_fname_src->st, false)) {
6332 continue;
6335 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6336 continue;
6339 if (sysdir_entry) {
6340 status = NT_STATUS_OBJECT_NAME_INVALID;
6341 break;
6344 TALLOC_FREE(smb_fname_src->base_name);
6345 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6346 "%s/%s",
6347 fname_src_dir,
6348 dname);
6349 if (!smb_fname_src->base_name) {
6350 status = NT_STATUS_NO_MEMORY;
6351 goto out;
6354 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6355 smb_fname_dst->base_name,
6356 &destname)) {
6357 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6358 smb_fname_src->base_name, destname));
6359 continue;
6361 if (!destname) {
6362 status = NT_STATUS_NO_MEMORY;
6363 goto out;
6366 TALLOC_FREE(smb_fname_dst->base_name);
6367 smb_fname_dst->base_name = destname;
6369 ZERO_STRUCT(smb_fname_src->st);
6370 if (posix_pathnames) {
6371 SMB_VFS_LSTAT(conn, smb_fname_src);
6372 } else {
6373 SMB_VFS_STAT(conn, smb_fname_src);
6376 create_options = 0;
6378 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6379 create_options |= FILE_DIRECTORY_FILE;
6382 status = SMB_VFS_CREATE_FILE(
6383 conn, /* conn */
6384 req, /* req */
6385 0, /* root_dir_fid */
6386 smb_fname_src, /* fname */
6387 access_mask, /* access_mask */
6388 (FILE_SHARE_READ | /* share_access */
6389 FILE_SHARE_WRITE),
6390 FILE_OPEN, /* create_disposition*/
6391 create_options, /* create_options */
6392 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6393 0, /* oplock_request */
6394 0, /* allocation_size */
6395 NULL, /* sd */
6396 NULL, /* ea_list */
6397 &fsp, /* result */
6398 NULL); /* pinfo */
6400 if (!NT_STATUS_IS_OK(status)) {
6401 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6402 "returned %s rename %s -> %s\n",
6403 nt_errstr(status),
6404 smb_fname_str_dbg(smb_fname_src),
6405 smb_fname_str_dbg(smb_fname_dst)));
6406 break;
6409 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6410 dname);
6411 if (!smb_fname_dst->original_lcomp) {
6412 status = NT_STATUS_NO_MEMORY;
6413 goto out;
6416 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6417 attrs, replace_if_exists);
6419 close_file(req, fsp, NORMAL_CLOSE);
6421 if (!NT_STATUS_IS_OK(status)) {
6422 DEBUG(3, ("rename_internals_fsp returned %s for "
6423 "rename %s -> %s\n", nt_errstr(status),
6424 smb_fname_str_dbg(smb_fname_src),
6425 smb_fname_str_dbg(smb_fname_dst)));
6426 break;
6429 count++;
6431 DEBUG(3,("rename_internals: doing rename on %s -> "
6432 "%s\n", smb_fname_str_dbg(smb_fname_src),
6433 smb_fname_str_dbg(smb_fname_src)));
6436 TALLOC_FREE(dir_hnd);
6438 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6439 status = map_nt_error_from_unix(errno);
6442 out:
6443 TALLOC_FREE(fname_src_dir);
6444 TALLOC_FREE(fname_src_mask);
6445 return status;
6448 /****************************************************************************
6449 Reply to a mv.
6450 ****************************************************************************/
6452 void reply_mv(struct smb_request *req)
6454 connection_struct *conn = req->conn;
6455 char *name = NULL;
6456 char *newname = NULL;
6457 const char *p;
6458 uint32 attrs;
6459 NTSTATUS status;
6460 bool src_has_wcard = False;
6461 bool dest_has_wcard = False;
6462 TALLOC_CTX *ctx = talloc_tos();
6463 struct smb_filename *smb_fname_src = NULL;
6464 struct smb_filename *smb_fname_dst = NULL;
6466 START_PROFILE(SMBmv);
6468 if (req->wct < 1) {
6469 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6470 goto out;
6473 attrs = SVAL(req->vwv+0, 0);
6475 p = (const char *)req->buf + 1;
6476 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6477 &status, &src_has_wcard);
6478 if (!NT_STATUS_IS_OK(status)) {
6479 reply_nterror(req, status);
6480 goto out;
6482 p++;
6483 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6484 &status, &dest_has_wcard);
6485 if (!NT_STATUS_IS_OK(status)) {
6486 reply_nterror(req, status);
6487 goto out;
6490 status = filename_convert(ctx,
6491 conn,
6492 req->flags2 & FLAGS2_DFS_PATHNAMES,
6493 name,
6494 UCF_COND_ALLOW_WCARD_LCOMP,
6495 &src_has_wcard,
6496 &smb_fname_src);
6498 if (!NT_STATUS_IS_OK(status)) {
6499 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6500 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6501 ERRSRV, ERRbadpath);
6502 goto out;
6504 reply_nterror(req, status);
6505 goto out;
6508 status = filename_convert(ctx,
6509 conn,
6510 req->flags2 & FLAGS2_DFS_PATHNAMES,
6511 newname,
6512 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6513 &dest_has_wcard,
6514 &smb_fname_dst);
6516 if (!NT_STATUS_IS_OK(status)) {
6517 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6518 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6519 ERRSRV, ERRbadpath);
6520 goto out;
6522 reply_nterror(req, status);
6523 goto out;
6526 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6527 smb_fname_str_dbg(smb_fname_dst)));
6529 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6530 attrs, False, src_has_wcard, dest_has_wcard,
6531 DELETE_ACCESS);
6532 if (!NT_STATUS_IS_OK(status)) {
6533 if (open_was_deferred(req->mid)) {
6534 /* We have re-scheduled this call. */
6535 goto out;
6537 reply_nterror(req, status);
6538 goto out;
6541 reply_outbuf(req, 0, 0);
6542 out:
6543 TALLOC_FREE(smb_fname_src);
6544 TALLOC_FREE(smb_fname_dst);
6545 END_PROFILE(SMBmv);
6546 return;
6549 /*******************************************************************
6550 Copy a file as part of a reply_copy.
6551 ******************************************************************/
6554 * TODO: check error codes on all callers
6557 NTSTATUS copy_file(TALLOC_CTX *ctx,
6558 connection_struct *conn,
6559 struct smb_filename *smb_fname_src,
6560 struct smb_filename *smb_fname_dst,
6561 int ofun,
6562 int count,
6563 bool target_is_directory)
6565 struct smb_filename *smb_fname_dst_tmp = NULL;
6566 SMB_OFF_T ret=-1;
6567 files_struct *fsp1,*fsp2;
6568 uint32 dosattrs;
6569 uint32 new_create_disposition;
6570 NTSTATUS status;
6573 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6574 if (!NT_STATUS_IS_OK(status)) {
6575 return status;
6579 * If the target is a directory, extract the last component from the
6580 * src filename and append it to the dst filename
6582 if (target_is_directory) {
6583 const char *p;
6585 /* dest/target can't be a stream if it's a directory. */
6586 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6588 p = strrchr_m(smb_fname_src->base_name,'/');
6589 if (p) {
6590 p++;
6591 } else {
6592 p = smb_fname_src->base_name;
6594 smb_fname_dst_tmp->base_name =
6595 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6597 if (!smb_fname_dst_tmp->base_name) {
6598 status = NT_STATUS_NO_MEMORY;
6599 goto out;
6603 status = vfs_file_exist(conn, smb_fname_src);
6604 if (!NT_STATUS_IS_OK(status)) {
6605 goto out;
6608 if (!target_is_directory && count) {
6609 new_create_disposition = FILE_OPEN;
6610 } else {
6611 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6612 NULL, NULL,
6613 &new_create_disposition,
6614 NULL)) {
6615 status = NT_STATUS_INVALID_PARAMETER;
6616 goto out;
6620 /* Open the src file for reading. */
6621 status = SMB_VFS_CREATE_FILE(
6622 conn, /* conn */
6623 NULL, /* req */
6624 0, /* root_dir_fid */
6625 smb_fname_src, /* fname */
6626 FILE_GENERIC_READ, /* access_mask */
6627 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6628 FILE_OPEN, /* create_disposition*/
6629 0, /* create_options */
6630 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6631 INTERNAL_OPEN_ONLY, /* oplock_request */
6632 0, /* allocation_size */
6633 NULL, /* sd */
6634 NULL, /* ea_list */
6635 &fsp1, /* result */
6636 NULL); /* psbuf */
6638 if (!NT_STATUS_IS_OK(status)) {
6639 goto out;
6642 dosattrs = dos_mode(conn, smb_fname_src);
6644 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6645 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6648 /* Open the dst file for writing. */
6649 status = SMB_VFS_CREATE_FILE(
6650 conn, /* conn */
6651 NULL, /* req */
6652 0, /* root_dir_fid */
6653 smb_fname_dst, /* fname */
6654 FILE_GENERIC_WRITE, /* access_mask */
6655 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6656 new_create_disposition, /* create_disposition*/
6657 0, /* create_options */
6658 dosattrs, /* file_attributes */
6659 INTERNAL_OPEN_ONLY, /* oplock_request */
6660 0, /* allocation_size */
6661 NULL, /* sd */
6662 NULL, /* ea_list */
6663 &fsp2, /* result */
6664 NULL); /* psbuf */
6666 if (!NT_STATUS_IS_OK(status)) {
6667 close_file(NULL, fsp1, ERROR_CLOSE);
6668 goto out;
6671 if ((ofun&3) == 1) {
6672 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6673 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6675 * Stop the copy from occurring.
6677 ret = -1;
6678 smb_fname_src->st.st_ex_size = 0;
6682 /* Do the actual copy. */
6683 if (smb_fname_src->st.st_ex_size) {
6684 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6687 close_file(NULL, fsp1, NORMAL_CLOSE);
6689 /* Ensure the modtime is set correctly on the destination file. */
6690 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6693 * As we are opening fsp1 read-only we only expect
6694 * an error on close on fsp2 if we are out of space.
6695 * Thus we don't look at the error return from the
6696 * close of fsp1.
6698 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6700 if (!NT_STATUS_IS_OK(status)) {
6701 goto out;
6704 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6705 status = NT_STATUS_DISK_FULL;
6706 goto out;
6709 status = NT_STATUS_OK;
6711 out:
6712 TALLOC_FREE(smb_fname_dst_tmp);
6713 return status;
6716 /****************************************************************************
6717 Reply to a file copy.
6718 ****************************************************************************/
6720 void reply_copy(struct smb_request *req)
6722 connection_struct *conn = req->conn;
6723 struct smb_filename *smb_fname_src = NULL;
6724 struct smb_filename *smb_fname_dst = NULL;
6725 char *fname_src = NULL;
6726 char *fname_dst = NULL;
6727 char *fname_src_mask = NULL;
6728 char *fname_src_dir = NULL;
6729 const char *p;
6730 int count=0;
6731 int error = ERRnoaccess;
6732 int tid2;
6733 int ofun;
6734 int flags;
6735 bool target_is_directory=False;
6736 bool source_has_wild = False;
6737 bool dest_has_wild = False;
6738 NTSTATUS status;
6739 TALLOC_CTX *ctx = talloc_tos();
6741 START_PROFILE(SMBcopy);
6743 if (req->wct < 3) {
6744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6745 goto out;
6748 tid2 = SVAL(req->vwv+0, 0);
6749 ofun = SVAL(req->vwv+1, 0);
6750 flags = SVAL(req->vwv+2, 0);
6752 p = (const char *)req->buf;
6753 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6754 &status, &source_has_wild);
6755 if (!NT_STATUS_IS_OK(status)) {
6756 reply_nterror(req, status);
6757 goto out;
6759 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6760 &status, &dest_has_wild);
6761 if (!NT_STATUS_IS_OK(status)) {
6762 reply_nterror(req, status);
6763 goto out;
6766 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6768 if (tid2 != conn->cnum) {
6769 /* can't currently handle inter share copies XXXX */
6770 DEBUG(3,("Rejecting inter-share copy\n"));
6771 reply_doserror(req, ERRSRV, ERRinvdevice);
6772 goto out;
6775 status = filename_convert(ctx, conn,
6776 req->flags2 & FLAGS2_DFS_PATHNAMES,
6777 fname_src,
6778 UCF_COND_ALLOW_WCARD_LCOMP,
6779 &source_has_wild,
6780 &smb_fname_src);
6781 if (!NT_STATUS_IS_OK(status)) {
6782 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6783 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6784 ERRSRV, ERRbadpath);
6785 goto out;
6787 reply_nterror(req, status);
6788 goto out;
6791 status = filename_convert(ctx, conn,
6792 req->flags2 & FLAGS2_DFS_PATHNAMES,
6793 fname_dst,
6794 UCF_COND_ALLOW_WCARD_LCOMP,
6795 &dest_has_wild,
6796 &smb_fname_dst);
6797 if (!NT_STATUS_IS_OK(status)) {
6798 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6799 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6800 ERRSRV, ERRbadpath);
6801 goto out;
6803 reply_nterror(req, status);
6804 goto out;
6807 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6809 if ((flags&1) && target_is_directory) {
6810 reply_doserror(req, ERRDOS, ERRbadfile);
6811 goto out;
6814 if ((flags&2) && !target_is_directory) {
6815 reply_doserror(req, ERRDOS, ERRbadpath);
6816 goto out;
6819 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6820 /* wants a tree copy! XXXX */
6821 DEBUG(3,("Rejecting tree copy\n"));
6822 reply_doserror(req, ERRSRV, ERRerror);
6823 goto out;
6826 /* Split up the directory from the filename/mask. */
6827 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6828 &fname_src_dir, &fname_src_mask);
6829 if (!NT_STATUS_IS_OK(status)) {
6830 reply_nterror(req, NT_STATUS_NO_MEMORY);
6831 goto out;
6835 * We should only check the mangled cache
6836 * here if unix_convert failed. This means
6837 * that the path in 'mask' doesn't exist
6838 * on the file system and so we need to look
6839 * for a possible mangle. This patch from
6840 * Tine Smukavec <valentin.smukavec@hermes.si>.
6842 if (!VALID_STAT(smb_fname_src->st) &&
6843 mangle_is_mangled(fname_src_mask, conn->params)) {
6844 char *new_mask = NULL;
6845 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6846 &new_mask, conn->params);
6848 /* Use demangled name if one was successfully found. */
6849 if (new_mask) {
6850 TALLOC_FREE(fname_src_mask);
6851 fname_src_mask = new_mask;
6855 if (!source_has_wild) {
6858 * Only one file needs to be copied. Append the mask back onto
6859 * the directory.
6861 TALLOC_FREE(smb_fname_src->base_name);
6862 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6863 "%s/%s",
6864 fname_src_dir,
6865 fname_src_mask);
6866 if (!smb_fname_src->base_name) {
6867 reply_nterror(req, NT_STATUS_NO_MEMORY);
6868 goto out;
6871 if (dest_has_wild) {
6872 char *fname_dst_mod = NULL;
6873 if (!resolve_wildcards(smb_fname_dst,
6874 smb_fname_src->base_name,
6875 smb_fname_dst->base_name,
6876 &fname_dst_mod)) {
6877 reply_nterror(req, NT_STATUS_NO_MEMORY);
6878 goto out;
6880 TALLOC_FREE(smb_fname_dst->base_name);
6881 smb_fname_dst->base_name = fname_dst_mod;
6884 status = check_name(conn, smb_fname_src->base_name);
6885 if (!NT_STATUS_IS_OK(status)) {
6886 reply_nterror(req, status);
6887 goto out;
6890 status = check_name(conn, smb_fname_dst->base_name);
6891 if (!NT_STATUS_IS_OK(status)) {
6892 reply_nterror(req, status);
6893 goto out;
6896 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6897 ofun, count, target_is_directory);
6899 if(!NT_STATUS_IS_OK(status)) {
6900 reply_nterror(req, status);
6901 goto out;
6902 } else {
6903 count++;
6905 } else {
6906 struct smb_Dir *dir_hnd = NULL;
6907 const char *dname = NULL;
6908 long offset = 0;
6911 * There is a wildcard that requires us to actually read the
6912 * src dir and copy each file matching the mask to the dst.
6913 * Right now streams won't be copied, but this could
6914 * presumably be added with a nested loop for reach dir entry.
6916 SMB_ASSERT(!smb_fname_src->stream_name);
6917 SMB_ASSERT(!smb_fname_dst->stream_name);
6919 smb_fname_src->stream_name = NULL;
6920 smb_fname_dst->stream_name = NULL;
6922 if (strequal(fname_src_mask,"????????.???")) {
6923 TALLOC_FREE(fname_src_mask);
6924 fname_src_mask = talloc_strdup(ctx, "*");
6925 if (!fname_src_mask) {
6926 reply_nterror(req, NT_STATUS_NO_MEMORY);
6927 goto out;
6931 status = check_name(conn, fname_src_dir);
6932 if (!NT_STATUS_IS_OK(status)) {
6933 reply_nterror(req, status);
6934 goto out;
6937 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6938 if (dir_hnd == NULL) {
6939 status = map_nt_error_from_unix(errno);
6940 reply_nterror(req, status);
6941 goto out;
6944 error = ERRbadfile;
6946 /* Iterate over the src dir copying each entry to the dst. */
6947 while ((dname = ReadDirName(dir_hnd, &offset,
6948 &smb_fname_src->st))) {
6949 char *destname = NULL;
6951 if (ISDOT(dname) || ISDOTDOT(dname)) {
6952 continue;
6955 if (!is_visible_file(conn, fname_src_dir, dname,
6956 &smb_fname_src->st, false)) {
6957 continue;
6960 if(!mask_match(dname, fname_src_mask,
6961 conn->case_sensitive)) {
6962 continue;
6965 error = ERRnoaccess;
6967 /* Get the src smb_fname struct setup. */
6968 TALLOC_FREE(smb_fname_src->base_name);
6969 smb_fname_src->base_name =
6970 talloc_asprintf(smb_fname_src, "%s/%s",
6971 fname_src_dir, dname);
6973 if (!smb_fname_src->base_name) {
6974 TALLOC_FREE(dir_hnd);
6975 reply_nterror(req, NT_STATUS_NO_MEMORY);
6976 goto out;
6979 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6980 smb_fname_dst->base_name,
6981 &destname)) {
6982 continue;
6984 if (!destname) {
6985 TALLOC_FREE(dir_hnd);
6986 reply_nterror(req, NT_STATUS_NO_MEMORY);
6987 goto out;
6990 TALLOC_FREE(smb_fname_dst->base_name);
6991 smb_fname_dst->base_name = destname;
6993 status = check_name(conn, smb_fname_src->base_name);
6994 if (!NT_STATUS_IS_OK(status)) {
6995 TALLOC_FREE(dir_hnd);
6996 reply_nterror(req, status);
6997 goto out;
7000 status = check_name(conn, smb_fname_dst->base_name);
7001 if (!NT_STATUS_IS_OK(status)) {
7002 TALLOC_FREE(dir_hnd);
7003 reply_nterror(req, status);
7004 goto out;
7007 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7008 smb_fname_src->base_name,
7009 smb_fname_dst->base_name));
7011 status = copy_file(ctx, conn, smb_fname_src,
7012 smb_fname_dst, ofun, count,
7013 target_is_directory);
7014 if (NT_STATUS_IS_OK(status)) {
7015 count++;
7018 TALLOC_FREE(dir_hnd);
7021 if (count == 0) {
7022 reply_doserror(req, ERRDOS, error);
7023 goto out;
7026 reply_outbuf(req, 1, 0);
7027 SSVAL(req->outbuf,smb_vwv0,count);
7028 out:
7029 TALLOC_FREE(smb_fname_src);
7030 TALLOC_FREE(smb_fname_dst);
7031 TALLOC_FREE(fname_src);
7032 TALLOC_FREE(fname_dst);
7033 TALLOC_FREE(fname_src_mask);
7034 TALLOC_FREE(fname_src_dir);
7036 END_PROFILE(SMBcopy);
7037 return;
7040 #undef DBGC_CLASS
7041 #define DBGC_CLASS DBGC_LOCKING
7043 /****************************************************************************
7044 Get a lock pid, dealing with large count requests.
7045 ****************************************************************************/
7047 uint32 get_lock_pid(const uint8_t *data, int data_offset,
7048 bool large_file_format)
7050 if(!large_file_format)
7051 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
7052 else
7053 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7056 /****************************************************************************
7057 Get a lock count, dealing with large count requests.
7058 ****************************************************************************/
7060 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7061 bool large_file_format)
7063 uint64_t count = 0;
7065 if(!large_file_format) {
7066 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7067 } else {
7069 #if defined(HAVE_LONGLONG)
7070 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7071 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7072 #else /* HAVE_LONGLONG */
7075 * NT4.x seems to be broken in that it sends large file (64 bit)
7076 * lockingX calls even if the CAP_LARGE_FILES was *not*
7077 * negotiated. For boxes without large unsigned ints truncate the
7078 * lock count by dropping the top 32 bits.
7081 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7082 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7083 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7084 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7085 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7088 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7089 #endif /* HAVE_LONGLONG */
7092 return count;
7095 #if !defined(HAVE_LONGLONG)
7096 /****************************************************************************
7097 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7098 ****************************************************************************/
7100 static uint32 map_lock_offset(uint32 high, uint32 low)
7102 unsigned int i;
7103 uint32 mask = 0;
7104 uint32 highcopy = high;
7107 * Try and find out how many significant bits there are in high.
7110 for(i = 0; highcopy; i++)
7111 highcopy >>= 1;
7114 * We use 31 bits not 32 here as POSIX
7115 * lock offsets may not be negative.
7118 mask = (~0) << (31 - i);
7120 if(low & mask)
7121 return 0; /* Fail. */
7123 high <<= (31 - i);
7125 return (high|low);
7127 #endif /* !defined(HAVE_LONGLONG) */
7129 /****************************************************************************
7130 Get a lock offset, dealing with large offset requests.
7131 ****************************************************************************/
7133 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7134 bool large_file_format, bool *err)
7136 uint64_t offset = 0;
7138 *err = False;
7140 if(!large_file_format) {
7141 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7142 } else {
7144 #if defined(HAVE_LONGLONG)
7145 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7146 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7147 #else /* HAVE_LONGLONG */
7150 * NT4.x seems to be broken in that it sends large file (64 bit)
7151 * lockingX calls even if the CAP_LARGE_FILES was *not*
7152 * negotiated. For boxes without large unsigned ints mangle the
7153 * lock offset by mapping the top 32 bits onto the lower 32.
7156 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7157 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7158 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7159 uint32 new_low = 0;
7161 if((new_low = map_lock_offset(high, low)) == 0) {
7162 *err = True;
7163 return (uint64_t)-1;
7166 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7167 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7168 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7169 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7172 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7173 #endif /* HAVE_LONGLONG */
7176 return offset;
7179 NTSTATUS smbd_do_locking(struct smb_request *req,
7180 files_struct *fsp,
7181 uint8_t type,
7182 int32_t timeout,
7183 uint16_t num_ulocks,
7184 struct smbd_lock_element *ulocks,
7185 uint16_t num_locks,
7186 struct smbd_lock_element *locks,
7187 bool *async)
7189 connection_struct *conn = req->conn;
7190 int i;
7191 NTSTATUS status = NT_STATUS_OK;
7193 *async = false;
7195 /* Data now points at the beginning of the list
7196 of smb_unlkrng structs */
7197 for(i = 0; i < (int)num_ulocks; i++) {
7198 struct smbd_lock_element *e = &ulocks[i];
7200 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7201 "pid %u, file %s\n",
7202 (double)e->offset,
7203 (double)e->count,
7204 (unsigned int)e->smbpid,
7205 fsp_str_dbg(fsp)));
7207 if (e->brltype != UNLOCK_LOCK) {
7208 /* this can only happen with SMB2 */
7209 return NT_STATUS_INVALID_PARAMETER;
7212 status = do_unlock(smbd_messaging_context(),
7213 fsp,
7214 e->smbpid,
7215 e->count,
7216 e->offset,
7217 WINDOWS_LOCK);
7219 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7220 nt_errstr(status)));
7222 if (!NT_STATUS_IS_OK(status)) {
7223 return status;
7227 /* Setup the timeout in seconds. */
7229 if (!lp_blocking_locks(SNUM(conn))) {
7230 timeout = 0;
7233 /* Data now points at the beginning of the list
7234 of smb_lkrng structs */
7236 for(i = 0; i < (int)num_locks; i++) {
7237 struct smbd_lock_element *e = &locks[i];
7239 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
7240 "%u, file %s timeout = %d\n",
7241 (double)e->offset,
7242 (double)e->count,
7243 (unsigned int)e->smbpid,
7244 fsp_str_dbg(fsp),
7245 (int)timeout));
7247 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7248 struct blocking_lock_record *blr = NULL;
7250 if (lp_blocking_locks(SNUM(conn))) {
7252 /* Schedule a message to ourselves to
7253 remove the blocking lock record and
7254 return the right error. */
7256 blr = blocking_lock_cancel(fsp,
7257 e->smbpid,
7258 e->offset,
7259 e->count,
7260 WINDOWS_LOCK,
7261 type,
7262 NT_STATUS_FILE_LOCK_CONFLICT);
7263 if (blr == NULL) {
7264 return NT_STATUS_DOS(
7265 ERRDOS,
7266 ERRcancelviolation);
7269 /* Remove a matching pending lock. */
7270 status = do_lock_cancel(fsp,
7271 e->smbpid,
7272 e->count,
7273 e->offset,
7274 WINDOWS_LOCK,
7275 blr);
7276 } else {
7277 bool blocking_lock = timeout ? true : false;
7278 bool defer_lock = false;
7279 struct byte_range_lock *br_lck;
7280 uint32_t block_smbpid;
7282 br_lck = do_lock(smbd_messaging_context(),
7283 fsp,
7284 e->smbpid,
7285 e->count,
7286 e->offset,
7287 e->brltype,
7288 WINDOWS_LOCK,
7289 blocking_lock,
7290 &status,
7291 &block_smbpid,
7292 NULL);
7294 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7295 /* Windows internal resolution for blocking locks seems
7296 to be about 200ms... Don't wait for less than that. JRA. */
7297 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7298 timeout = lp_lock_spin_time();
7300 defer_lock = true;
7303 /* This heuristic seems to match W2K3 very well. If a
7304 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7305 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7306 far as I can tell. Replacement for do_lock_spin(). JRA. */
7308 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7309 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7310 defer_lock = true;
7311 timeout = lp_lock_spin_time();
7314 if (br_lck && defer_lock) {
7316 * A blocking lock was requested. Package up
7317 * this smb into a queued request and push it
7318 * onto the blocking lock queue.
7320 if(push_blocking_lock_request(br_lck,
7321 req,
7322 fsp,
7323 timeout,
7325 e->smbpid,
7326 e->brltype,
7327 WINDOWS_LOCK,
7328 e->offset,
7329 e->count,
7330 block_smbpid)) {
7331 TALLOC_FREE(br_lck);
7332 *async = true;
7333 return NT_STATUS_OK;
7337 TALLOC_FREE(br_lck);
7340 if (!NT_STATUS_IS_OK(status)) {
7341 break;
7345 /* If any of the above locks failed, then we must unlock
7346 all of the previous locks (X/Open spec). */
7348 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7350 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7351 i = -1; /* we want to skip the for loop */
7355 * Ensure we don't do a remove on the lock that just failed,
7356 * as under POSIX rules, if we have a lock already there, we
7357 * will delete it (and we shouldn't) .....
7359 for(i--; i >= 0; i--) {
7360 struct smbd_lock_element *e = &locks[i];
7362 do_unlock(smbd_messaging_context(),
7363 fsp,
7364 e->smbpid,
7365 e->count,
7366 e->offset,
7367 WINDOWS_LOCK);
7369 return status;
7372 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7373 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7375 return NT_STATUS_OK;
7378 /****************************************************************************
7379 Reply to a lockingX request.
7380 ****************************************************************************/
7382 void reply_lockingX(struct smb_request *req)
7384 connection_struct *conn = req->conn;
7385 files_struct *fsp;
7386 unsigned char locktype;
7387 unsigned char oplocklevel;
7388 uint16 num_ulocks;
7389 uint16 num_locks;
7390 int32 lock_timeout;
7391 int i;
7392 const uint8_t *data;
7393 bool large_file_format;
7394 bool err;
7395 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7396 struct smbd_lock_element *ulocks;
7397 struct smbd_lock_element *locks;
7398 bool async = false;
7400 START_PROFILE(SMBlockingX);
7402 if (req->wct < 8) {
7403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7404 END_PROFILE(SMBlockingX);
7405 return;
7408 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7409 locktype = CVAL(req->vwv+3, 0);
7410 oplocklevel = CVAL(req->vwv+3, 1);
7411 num_ulocks = SVAL(req->vwv+6, 0);
7412 num_locks = SVAL(req->vwv+7, 0);
7413 lock_timeout = IVAL(req->vwv+4, 0);
7414 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7416 if (!check_fsp(conn, req, fsp)) {
7417 END_PROFILE(SMBlockingX);
7418 return;
7421 data = req->buf;
7423 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7424 /* we don't support these - and CANCEL_LOCK makes w2k
7425 and XP reboot so I don't really want to be
7426 compatible! (tridge) */
7427 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7428 END_PROFILE(SMBlockingX);
7429 return;
7432 /* Check if this is an oplock break on a file
7433 we have granted an oplock on.
7435 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7436 /* Client can insist on breaking to none. */
7437 bool break_to_none = (oplocklevel == 0);
7438 bool result;
7440 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7441 "for fnum = %d\n", (unsigned int)oplocklevel,
7442 fsp->fnum ));
7445 * Make sure we have granted an exclusive or batch oplock on
7446 * this file.
7449 if (fsp->oplock_type == 0) {
7451 /* The Samba4 nbench simulator doesn't understand
7452 the difference between break to level2 and break
7453 to none from level2 - it sends oplock break
7454 replies in both cases. Don't keep logging an error
7455 message here - just ignore it. JRA. */
7457 DEBUG(5,("reply_lockingX: Error : oplock break from "
7458 "client for fnum = %d (oplock=%d) and no "
7459 "oplock granted on this file (%s).\n",
7460 fsp->fnum, fsp->oplock_type,
7461 fsp_str_dbg(fsp)));
7463 /* if this is a pure oplock break request then don't
7464 * send a reply */
7465 if (num_locks == 0 && num_ulocks == 0) {
7466 END_PROFILE(SMBlockingX);
7467 return;
7468 } else {
7469 END_PROFILE(SMBlockingX);
7470 reply_doserror(req, ERRDOS, ERRlock);
7471 return;
7475 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7476 (break_to_none)) {
7477 result = remove_oplock(fsp);
7478 } else {
7479 result = downgrade_oplock(fsp);
7482 if (!result) {
7483 DEBUG(0, ("reply_lockingX: error in removing "
7484 "oplock on file %s\n", fsp_str_dbg(fsp)));
7485 /* Hmmm. Is this panic justified? */
7486 smb_panic("internal tdb error");
7489 reply_to_oplock_break_requests(fsp);
7491 /* if this is a pure oplock break request then don't send a
7492 * reply */
7493 if (num_locks == 0 && num_ulocks == 0) {
7494 /* Sanity check - ensure a pure oplock break is not a
7495 chained request. */
7496 if(CVAL(req->vwv+0, 0) != 0xff)
7497 DEBUG(0,("reply_lockingX: Error : pure oplock "
7498 "break is a chained %d request !\n",
7499 (unsigned int)CVAL(req->vwv+0, 0)));
7500 END_PROFILE(SMBlockingX);
7501 return;
7505 if (req->buflen <
7506 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7508 END_PROFILE(SMBlockingX);
7509 return;
7512 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7513 if (ulocks == NULL) {
7514 reply_nterror(req, NT_STATUS_NO_MEMORY);
7515 END_PROFILE(SMBlockingX);
7516 return;
7519 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7520 if (locks == NULL) {
7521 reply_nterror(req, NT_STATUS_NO_MEMORY);
7522 END_PROFILE(SMBlockingX);
7523 return;
7526 /* Data now points at the beginning of the list
7527 of smb_unlkrng structs */
7528 for(i = 0; i < (int)num_ulocks; i++) {
7529 ulocks[i].smbpid = get_lock_pid(data, i, large_file_format);
7530 ulocks[i].count = get_lock_count(data, i, large_file_format);
7531 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7532 ulocks[i].brltype = UNLOCK_LOCK;
7535 * There is no error code marked "stupid client bug".... :-).
7537 if(err) {
7538 END_PROFILE(SMBlockingX);
7539 reply_doserror(req, ERRDOS, ERRnoaccess);
7540 return;
7544 /* Now do any requested locks */
7545 data += ((large_file_format ? 20 : 10)*num_ulocks);
7547 /* Data now points at the beginning of the list
7548 of smb_lkrng structs */
7550 for(i = 0; i < (int)num_locks; i++) {
7551 locks[i].smbpid = get_lock_pid(data, i, large_file_format);
7552 locks[i].count = get_lock_count(data, i, large_file_format);
7553 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7555 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7556 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7557 locks[i].brltype = PENDING_READ_LOCK;
7558 } else {
7559 locks[i].brltype = READ_LOCK;
7561 } else {
7562 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7563 locks[i].brltype = PENDING_WRITE_LOCK;
7564 } else {
7565 locks[i].brltype = WRITE_LOCK;
7570 * There is no error code marked "stupid client bug".... :-).
7572 if(err) {
7573 END_PROFILE(SMBlockingX);
7574 reply_doserror(req, ERRDOS, ERRnoaccess);
7575 return;
7579 status = smbd_do_locking(req, fsp,
7580 locktype, lock_timeout,
7581 num_ulocks, ulocks,
7582 num_locks, locks,
7583 &async);
7584 if (!NT_STATUS_IS_OK(status)) {
7585 END_PROFILE(SMBlockingX);
7586 reply_nterror(req, status);
7587 return;
7589 if (async) {
7590 END_PROFILE(SMBlockingX);
7591 return;
7594 reply_outbuf(req, 2, 0);
7596 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7597 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7599 END_PROFILE(SMBlockingX);
7600 chain_reply(req);
7603 #undef DBGC_CLASS
7604 #define DBGC_CLASS DBGC_ALL
7606 /****************************************************************************
7607 Reply to a SMBreadbmpx (read block multiplex) request.
7608 Always reply with an error, if someone has a platform really needs this,
7609 please contact vl@samba.org
7610 ****************************************************************************/
7612 void reply_readbmpx(struct smb_request *req)
7614 START_PROFILE(SMBreadBmpx);
7615 reply_doserror(req, ERRSRV, ERRuseSTD);
7616 END_PROFILE(SMBreadBmpx);
7617 return;
7620 /****************************************************************************
7621 Reply to a SMBreadbs (read block multiplex secondary) request.
7622 Always reply with an error, if someone has a platform really needs this,
7623 please contact vl@samba.org
7624 ****************************************************************************/
7626 void reply_readbs(struct smb_request *req)
7628 START_PROFILE(SMBreadBs);
7629 reply_doserror(req, ERRSRV, ERRuseSTD);
7630 END_PROFILE(SMBreadBs);
7631 return;
7634 /****************************************************************************
7635 Reply to a SMBsetattrE.
7636 ****************************************************************************/
7638 void reply_setattrE(struct smb_request *req)
7640 connection_struct *conn = req->conn;
7641 struct smb_file_time ft;
7642 files_struct *fsp;
7643 NTSTATUS status;
7645 START_PROFILE(SMBsetattrE);
7646 ZERO_STRUCT(ft);
7648 if (req->wct < 7) {
7649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7650 goto out;
7653 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7655 if(!fsp || (fsp->conn != conn)) {
7656 reply_doserror(req, ERRDOS, ERRbadfid);
7657 goto out;
7661 * Convert the DOS times into unix times.
7664 ft.atime = convert_time_t_to_timespec(
7665 srv_make_unix_date2(req->vwv+3));
7666 ft.mtime = convert_time_t_to_timespec(
7667 srv_make_unix_date2(req->vwv+5));
7668 ft.create_time = convert_time_t_to_timespec(
7669 srv_make_unix_date2(req->vwv+1));
7671 reply_outbuf(req, 0, 0);
7674 * Patch from Ray Frush <frush@engr.colostate.edu>
7675 * Sometimes times are sent as zero - ignore them.
7678 /* Ensure we have a valid stat struct for the source. */
7679 if (fsp->fh->fd != -1) {
7680 if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) == -1) {
7681 status = map_nt_error_from_unix(errno);
7682 reply_nterror(req, status);
7683 goto out;
7685 } else {
7686 int ret = -1;
7688 if (fsp->posix_open) {
7689 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name);
7690 } else {
7691 ret = SMB_VFS_STAT(conn, fsp->fsp_name);
7693 if (ret == -1) {
7694 status = map_nt_error_from_unix(errno);
7695 reply_nterror(req, status);
7696 goto out;
7700 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7701 if (!NT_STATUS_IS_OK(status)) {
7702 reply_doserror(req, ERRDOS, ERRnoaccess);
7703 goto out;
7706 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7707 " createtime=%u\n",
7708 fsp->fnum,
7709 (unsigned int)ft.atime.tv_sec,
7710 (unsigned int)ft.mtime.tv_sec,
7711 (unsigned int)ft.create_time.tv_sec
7713 out:
7714 END_PROFILE(SMBsetattrE);
7715 return;
7719 /* Back from the dead for OS/2..... JRA. */
7721 /****************************************************************************
7722 Reply to a SMBwritebmpx (write block multiplex primary) request.
7723 Always reply with an error, if someone has a platform really needs this,
7724 please contact vl@samba.org
7725 ****************************************************************************/
7727 void reply_writebmpx(struct smb_request *req)
7729 START_PROFILE(SMBwriteBmpx);
7730 reply_doserror(req, ERRSRV, ERRuseSTD);
7731 END_PROFILE(SMBwriteBmpx);
7732 return;
7735 /****************************************************************************
7736 Reply to a SMBwritebs (write block multiplex secondary) request.
7737 Always reply with an error, if someone has a platform really needs this,
7738 please contact vl@samba.org
7739 ****************************************************************************/
7741 void reply_writebs(struct smb_request *req)
7743 START_PROFILE(SMBwriteBs);
7744 reply_doserror(req, ERRSRV, ERRuseSTD);
7745 END_PROFILE(SMBwriteBs);
7746 return;
7749 /****************************************************************************
7750 Reply to a SMBgetattrE.
7751 ****************************************************************************/
7753 void reply_getattrE(struct smb_request *req)
7755 connection_struct *conn = req->conn;
7756 SMB_STRUCT_STAT sbuf;
7757 int mode;
7758 files_struct *fsp;
7759 struct timespec create_ts;
7761 START_PROFILE(SMBgetattrE);
7763 if (req->wct < 1) {
7764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7765 END_PROFILE(SMBgetattrE);
7766 return;
7769 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7771 if(!fsp || (fsp->conn != conn)) {
7772 reply_doserror(req, ERRDOS, ERRbadfid);
7773 END_PROFILE(SMBgetattrE);
7774 return;
7777 /* Do an fstat on this file */
7778 if(fsp_stat(fsp, &sbuf)) {
7779 reply_nterror(req, map_nt_error_from_unix(errno));
7780 END_PROFILE(SMBgetattrE);
7781 return;
7784 fsp->fsp_name->st = sbuf;
7786 mode = dos_mode(conn, fsp->fsp_name);
7789 * Convert the times into dos times. Set create
7790 * date to be last modify date as UNIX doesn't save
7791 * this.
7794 reply_outbuf(req, 11, 0);
7796 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7797 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7798 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7799 convert_timespec_to_time_t(sbuf.st_ex_atime));
7800 /* Should we check pending modtime here ? JRA */
7801 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7802 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7804 if (mode & aDIR) {
7805 SIVAL(req->outbuf, smb_vwv6, 0);
7806 SIVAL(req->outbuf, smb_vwv8, 0);
7807 } else {
7808 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7809 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7810 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7812 SSVAL(req->outbuf,smb_vwv10, mode);
7814 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7816 END_PROFILE(SMBgetattrE);
7817 return;