s3: Support shadow copy display over SMB2
[Samba.git] / source3 / smbd / reply.c
blob61e3a7e2d0e2a00562dea6e215a86ff3bcc0bb8f
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 "system/filesys.h"
29 #include "printing.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/cli_spoolss.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_server/rpc_ncacn_np.h"
38 #include "libcli/security/security.h"
39 #include "libsmb/nmblib.h"
40 #include "auth.h"
41 #include "smbprofile.h"
43 /****************************************************************************
44 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
45 path or anything including wildcards.
46 We're assuming here that '/' is not the second byte in any multibyte char
47 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
48 set.
49 ****************************************************************************/
51 /* Custom version for processing POSIX paths. */
52 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
54 static NTSTATUS check_path_syntax_internal(char *path,
55 bool posix_path,
56 bool *p_last_component_contains_wcard)
58 char *d = path;
59 const char *s = path;
60 NTSTATUS ret = NT_STATUS_OK;
61 bool start_of_name_component = True;
62 bool stream_started = false;
64 *p_last_component_contains_wcard = False;
66 while (*s) {
67 if (stream_started) {
68 switch (*s) {
69 case '/':
70 case '\\':
71 return NT_STATUS_OBJECT_NAME_INVALID;
72 case ':':
73 if (s[1] == '\0') {
74 return NT_STATUS_OBJECT_NAME_INVALID;
76 if (strchr_m(&s[1], ':')) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 break;
83 if ((*s == ':') && !posix_path && !stream_started) {
84 if (*p_last_component_contains_wcard) {
85 return NT_STATUS_OBJECT_NAME_INVALID;
87 /* Stream names allow more characters than file names.
88 We're overloading posix_path here to allow a wider
89 range of characters. If stream_started is true this
90 is still a Windows path even if posix_path is true.
91 JRA.
93 stream_started = true;
94 start_of_name_component = false;
95 posix_path = true;
97 if (s[1] == '\0') {
98 return NT_STATUS_OBJECT_NAME_INVALID;
102 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
104 * Safe to assume is not the second part of a mb char
105 * as this is handled below.
107 /* Eat multiple '/' or '\\' */
108 while (IS_PATH_SEP(*s,posix_path)) {
109 s++;
111 if ((d != path) && (*s != '\0')) {
112 /* We only care about non-leading or trailing '/' or '\\' */
113 *d++ = '/';
116 start_of_name_component = True;
117 /* New component. */
118 *p_last_component_contains_wcard = False;
119 continue;
122 if (start_of_name_component) {
123 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
124 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
127 * No mb char starts with '.' so we're safe checking the directory separator here.
130 /* If we just added a '/' - delete it */
131 if ((d > path) && (*(d-1) == '/')) {
132 *(d-1) = '\0';
133 d--;
136 /* Are we at the start ? Can't go back further if so. */
137 if (d <= path) {
138 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
139 break;
141 /* Go back one level... */
142 /* We know this is safe as '/' cannot be part of a mb sequence. */
143 /* NOTE - if this assumption is invalid we are not in good shape... */
144 /* Decrement d first as d points to the *next* char to write into. */
145 for (d--; d > path; d--) {
146 if (*d == '/')
147 break;
149 s += 2; /* Else go past the .. */
150 /* We're still at the start of a name component, just the previous one. */
151 continue;
153 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
154 if (posix_path) {
155 /* Eat the '.' */
156 s++;
157 continue;
163 if (!(*s & 0x80)) {
164 if (!posix_path) {
165 if (*s <= 0x1f || *s == '|') {
166 return NT_STATUS_OBJECT_NAME_INVALID;
168 switch (*s) {
169 case '*':
170 case '?':
171 case '<':
172 case '>':
173 case '"':
174 *p_last_component_contains_wcard = True;
175 break;
176 default:
177 break;
180 *d++ = *s++;
181 } else {
182 size_t siz;
183 /* Get the size of the next MB character. */
184 next_codepoint(s,&siz);
185 switch(siz) {
186 case 5:
187 *d++ = *s++;
188 /*fall through*/
189 case 4:
190 *d++ = *s++;
191 /*fall through*/
192 case 3:
193 *d++ = *s++;
194 /*fall through*/
195 case 2:
196 *d++ = *s++;
197 /*fall through*/
198 case 1:
199 *d++ = *s++;
200 break;
201 default:
202 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
203 *d = '\0';
204 return NT_STATUS_INVALID_PARAMETER;
207 start_of_name_component = False;
210 *d = '\0';
212 return ret;
215 /****************************************************************************
216 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
217 No wildcards allowed.
218 ****************************************************************************/
220 NTSTATUS check_path_syntax(char *path)
222 bool ignore;
223 return check_path_syntax_internal(path, False, &ignore);
226 /****************************************************************************
227 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
228 Wildcards allowed - p_contains_wcard returns true if the last component contained
229 a wildcard.
230 ****************************************************************************/
232 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
234 return check_path_syntax_internal(path, False, p_contains_wcard);
237 /****************************************************************************
238 Check the path for a POSIX client.
239 We're assuming here that '/' is not the second byte in any multibyte char
240 set (a safe assumption).
241 ****************************************************************************/
243 NTSTATUS check_path_syntax_posix(char *path)
245 bool ignore;
246 return check_path_syntax_internal(path, True, &ignore);
249 /****************************************************************************
250 Pull a string and check the path allowing a wilcard - provide for error return.
251 ****************************************************************************/
253 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
254 const char *base_ptr,
255 uint16 smb_flags2,
256 char **pp_dest,
257 const char *src,
258 size_t src_len,
259 int flags,
260 NTSTATUS *err,
261 bool *contains_wcard)
263 size_t ret;
265 *pp_dest = NULL;
267 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
268 src_len, flags);
270 if (!*pp_dest) {
271 *err = NT_STATUS_INVALID_PARAMETER;
272 return ret;
275 *contains_wcard = False;
277 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
279 * For a DFS path the function parse_dfs_path()
280 * will do the path processing, just make a copy.
282 *err = NT_STATUS_OK;
283 return ret;
286 if (lp_posix_pathnames()) {
287 *err = check_path_syntax_posix(*pp_dest);
288 } else {
289 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
292 return ret;
295 /****************************************************************************
296 Pull a string and check the path - provide for error return.
297 ****************************************************************************/
299 size_t srvstr_get_path(TALLOC_CTX *ctx,
300 const char *base_ptr,
301 uint16 smb_flags2,
302 char **pp_dest,
303 const char *src,
304 size_t src_len,
305 int flags,
306 NTSTATUS *err)
308 bool ignore;
309 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
310 src_len, flags, err, &ignore);
313 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
314 char **pp_dest, const char *src, int flags,
315 NTSTATUS *err, bool *contains_wcard)
317 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
318 pp_dest, src, smbreq_bufrem(req, src),
319 flags, err, contains_wcard);
322 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
323 char **pp_dest, const char *src, int flags,
324 NTSTATUS *err)
326 bool ignore;
327 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
328 flags, err, &ignore);
331 /****************************************************************************
332 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
333 ****************************************************************************/
335 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
336 files_struct *fsp)
338 if ((fsp == NULL) || (conn == NULL)) {
339 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
340 return False;
342 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
343 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
344 return False;
346 return True;
349 /****************************************************************************
350 Check if we have a correct fsp pointing to a file.
351 ****************************************************************************/
353 bool check_fsp(connection_struct *conn, struct smb_request *req,
354 files_struct *fsp)
356 if (!check_fsp_open(conn, req, fsp)) {
357 return False;
359 if (fsp->is_directory) {
360 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
361 return False;
363 if (fsp->fh->fd == -1) {
364 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
365 return False;
367 fsp->num_smb_operations++;
368 return True;
371 /****************************************************************************
372 Check if we have a correct fsp pointing to a quota fake file. Replacement for
373 the CHECK_NTQUOTA_HANDLE_OK macro.
374 ****************************************************************************/
376 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
377 files_struct *fsp)
379 if (!check_fsp_open(conn, req, fsp)) {
380 return false;
383 if (fsp->is_directory) {
384 return false;
387 if (fsp->fake_file_handle == NULL) {
388 return false;
391 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
392 return false;
395 if (fsp->fake_file_handle->private_data == NULL) {
396 return false;
399 return true;
402 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
403 const char *name, int name_type)
405 char *trim_name;
406 char *trim_name_type;
407 const char *retarget_parm;
408 char *retarget;
409 char *p;
410 int retarget_type = 0x20;
411 int retarget_port = 139;
412 struct sockaddr_storage retarget_addr;
413 struct sockaddr_in *in_addr;
414 bool ret = false;
415 uint8_t outbuf[10];
417 if (get_socket_port(sconn->sock) != 139) {
418 return false;
421 trim_name = talloc_strdup(talloc_tos(), name);
422 if (trim_name == NULL) {
423 goto fail;
425 trim_char(trim_name, ' ', ' ');
427 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
428 name_type);
429 if (trim_name_type == NULL) {
430 goto fail;
433 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
434 trim_name_type, NULL);
435 if (retarget_parm == NULL) {
436 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
437 trim_name, NULL);
439 if (retarget_parm == NULL) {
440 goto fail;
443 retarget = talloc_strdup(trim_name, retarget_parm);
444 if (retarget == NULL) {
445 goto fail;
448 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
450 p = strchr(retarget, ':');
451 if (p != NULL) {
452 *p++ = '\0';
453 retarget_port = atoi(p);
456 p = strchr_m(retarget, '#');
457 if (p != NULL) {
458 *p++ = '\0';
459 if (sscanf(p, "%x", &retarget_type) != 1) {
460 goto fail;
464 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
465 if (!ret) {
466 DEBUG(10, ("could not resolve %s\n", retarget));
467 goto fail;
470 if (retarget_addr.ss_family != AF_INET) {
471 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
472 goto fail;
475 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
477 _smb_setlen(outbuf, 6);
478 SCVAL(outbuf, 0, 0x84);
479 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
480 *(uint16_t *)(outbuf+8) = htons(retarget_port);
482 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
483 NULL)) {
484 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
485 "failed.");
488 ret = true;
489 fail:
490 TALLOC_FREE(trim_name);
491 return ret;
494 static void reply_called_name_not_present(char *outbuf)
496 smb_setlen(outbuf, 1);
497 SCVAL(outbuf, 0, 0x83);
498 SCVAL(outbuf, 4, 0x82);
501 /****************************************************************************
502 Reply to a (netbios-level) special message.
503 ****************************************************************************/
505 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
507 int msg_type = CVAL(inbuf,0);
508 int msg_flags = CVAL(inbuf,1);
510 * We only really use 4 bytes of the outbuf, but for the smb_setlen
511 * calculation & friends (srv_send_smb uses that) we need the full smb
512 * header.
514 char outbuf[smb_size];
516 memset(outbuf, '\0', sizeof(outbuf));
518 smb_setlen(outbuf,0);
520 switch (msg_type) {
521 case 0x81: /* session request */
523 /* inbuf_size is guarenteed to be at least 4. */
524 fstring name1,name2;
525 int name_type1, name_type2;
526 int name_len1, name_len2;
528 *name1 = *name2 = 0;
530 if (sconn->nbt.got_session) {
531 exit_server_cleanly("multiple session request not permitted");
534 SCVAL(outbuf,0,0x82);
535 SCVAL(outbuf,3,0);
537 /* inbuf_size is guaranteed to be at least 4. */
538 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
539 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
540 DEBUG(0,("Invalid name length in session request\n"));
541 reply_called_name_not_present(outbuf);
542 break;
544 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
545 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
546 DEBUG(0,("Invalid name length in session request\n"));
547 reply_called_name_not_present(outbuf);
548 break;
551 name_type1 = name_extract((unsigned char *)inbuf,
552 inbuf_size,(unsigned int)4,name1);
553 name_type2 = name_extract((unsigned char *)inbuf,
554 inbuf_size,(unsigned int)(4 + name_len1),name2);
556 if (name_type1 == -1 || name_type2 == -1) {
557 DEBUG(0,("Invalid name type in session request\n"));
558 reply_called_name_not_present(outbuf);
559 break;
562 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
563 name1, name_type1, name2, name_type2));
565 if (netbios_session_retarget(sconn, name1, name_type1)) {
566 exit_server_cleanly("retargeted client");
570 * Windows NT/2k uses "*SMBSERVER" and XP uses
571 * "*SMBSERV" arrggg!!!
573 if (strequal(name1, "*SMBSERVER ")
574 || strequal(name1, "*SMBSERV ")) {
575 fstrcpy(name1, sconn->client_id.addr);
578 set_local_machine_name(name1, True);
579 set_remote_machine_name(name2, True);
581 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
582 get_local_machine_name(), get_remote_machine_name(),
583 name_type2));
585 if (name_type2 == 'R') {
586 /* We are being asked for a pathworks session ---
587 no thanks! */
588 reply_called_name_not_present(outbuf);
589 break;
592 /* only add the client's machine name to the list
593 of possibly valid usernames if we are operating
594 in share mode security */
595 if (lp_security() == SEC_SHARE) {
596 add_session_user(sconn, get_remote_machine_name());
599 reload_services(sconn->msg_ctx, sconn->sock, True);
600 reopen_logs();
602 sconn->nbt.got_session = true;
603 break;
606 case 0x89: /* session keepalive request
607 (some old clients produce this?) */
608 SCVAL(outbuf,0,SMBkeepalive);
609 SCVAL(outbuf,3,0);
610 break;
612 case 0x82: /* positive session response */
613 case 0x83: /* negative session response */
614 case 0x84: /* retarget session response */
615 DEBUG(0,("Unexpected session response\n"));
616 break;
618 case SMBkeepalive: /* session keepalive */
619 default:
620 return;
623 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
624 msg_type, msg_flags));
626 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
628 if (CVAL(outbuf, 0) != 0x82) {
629 exit_server_cleanly("invalid netbios session");
631 return;
634 /****************************************************************************
635 Reply to a tcon.
636 conn POINTER CAN BE NULL HERE !
637 ****************************************************************************/
639 void reply_tcon(struct smb_request *req)
641 connection_struct *conn = req->conn;
642 const char *service;
643 char *service_buf = NULL;
644 char *password = NULL;
645 char *dev = NULL;
646 int pwlen=0;
647 NTSTATUS nt_status;
648 const char *p;
649 DATA_BLOB password_blob;
650 TALLOC_CTX *ctx = talloc_tos();
651 struct smbd_server_connection *sconn = req->sconn;
653 START_PROFILE(SMBtcon);
655 if (req->buflen < 4) {
656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
657 END_PROFILE(SMBtcon);
658 return;
661 p = (const char *)req->buf + 1;
662 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
663 p += 1;
664 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
665 p += pwlen+1;
666 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
667 p += 1;
669 if (service_buf == NULL || password == NULL || dev == NULL) {
670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
671 END_PROFILE(SMBtcon);
672 return;
674 p = strrchr_m(service_buf,'\\');
675 if (p) {
676 service = p+1;
677 } else {
678 service = service_buf;
681 password_blob = data_blob(password, pwlen+1);
683 conn = make_connection(sconn,service,password_blob,dev,
684 req->vuid,&nt_status);
685 req->conn = conn;
687 data_blob_clear_free(&password_blob);
689 if (!conn) {
690 reply_nterror(req, nt_status);
691 END_PROFILE(SMBtcon);
692 return;
695 reply_outbuf(req, 2, 0);
696 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
697 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
698 SSVAL(req->outbuf,smb_tid,conn->cnum);
700 DEBUG(3,("tcon service=%s cnum=%d\n",
701 service, conn->cnum));
703 END_PROFILE(SMBtcon);
704 return;
707 /****************************************************************************
708 Reply to a tcon and X.
709 conn POINTER CAN BE NULL HERE !
710 ****************************************************************************/
712 void reply_tcon_and_X(struct smb_request *req)
714 connection_struct *conn = req->conn;
715 const char *service = NULL;
716 DATA_BLOB password;
717 TALLOC_CTX *ctx = talloc_tos();
718 /* what the cleint thinks the device is */
719 char *client_devicetype = NULL;
720 /* what the server tells the client the share represents */
721 const char *server_devicetype;
722 NTSTATUS nt_status;
723 int passlen;
724 char *path = NULL;
725 const char *p, *q;
726 uint16 tcon_flags;
727 struct smbd_server_connection *sconn = req->sconn;
729 START_PROFILE(SMBtconX);
731 if (req->wct < 4) {
732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
733 END_PROFILE(SMBtconX);
734 return;
737 passlen = SVAL(req->vwv+3, 0);
738 tcon_flags = SVAL(req->vwv+2, 0);
740 /* we might have to close an old one */
741 if ((tcon_flags & 0x1) && conn) {
742 close_cnum(conn,req->vuid);
743 req->conn = NULL;
744 conn = NULL;
747 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
748 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
749 END_PROFILE(SMBtconX);
750 return;
753 if (sconn->smb1.negprot.encrypted_passwords) {
754 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
755 if (lp_security() == SEC_SHARE) {
757 * Security = share always has a pad byte
758 * after the password.
760 p = (const char *)req->buf + passlen + 1;
761 } else {
762 p = (const char *)req->buf + passlen;
764 } else {
765 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
766 /* Ensure correct termination */
767 password.data[passlen]=0;
768 p = (const char *)req->buf + passlen + 1;
771 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
773 if (path == NULL) {
774 data_blob_clear_free(&password);
775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
776 END_PROFILE(SMBtconX);
777 return;
781 * the service name can be either: \\server\share
782 * or share directly like on the DELL PowerVault 705
784 if (*path=='\\') {
785 q = strchr_m(path+2,'\\');
786 if (!q) {
787 data_blob_clear_free(&password);
788 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
789 END_PROFILE(SMBtconX);
790 return;
792 service = q+1;
793 } else {
794 service = path;
797 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
798 &client_devicetype, p,
799 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
801 if (client_devicetype == NULL) {
802 data_blob_clear_free(&password);
803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
804 END_PROFILE(SMBtconX);
805 return;
808 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
810 conn = make_connection(sconn, service, password, client_devicetype,
811 req->vuid, &nt_status);
812 req->conn =conn;
814 data_blob_clear_free(&password);
816 if (!conn) {
817 reply_nterror(req, nt_status);
818 END_PROFILE(SMBtconX);
819 return;
822 if ( IS_IPC(conn) )
823 server_devicetype = "IPC";
824 else if ( IS_PRINT(conn) )
825 server_devicetype = "LPT1:";
826 else
827 server_devicetype = "A:";
829 if (get_Protocol() < PROTOCOL_NT1) {
830 reply_outbuf(req, 2, 0);
831 if (message_push_string(&req->outbuf, server_devicetype,
832 STR_TERMINATE|STR_ASCII) == -1) {
833 reply_nterror(req, NT_STATUS_NO_MEMORY);
834 END_PROFILE(SMBtconX);
835 return;
837 } else {
838 /* NT sets the fstype of IPC$ to the null string */
839 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
841 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
842 /* Return permissions. */
843 uint32 perm1 = 0;
844 uint32 perm2 = 0;
846 reply_outbuf(req, 7, 0);
848 if (IS_IPC(conn)) {
849 perm1 = FILE_ALL_ACCESS;
850 perm2 = FILE_ALL_ACCESS;
851 } else {
852 perm1 = CAN_WRITE(conn) ?
853 SHARE_ALL_ACCESS :
854 SHARE_READ_ONLY;
857 SIVAL(req->outbuf, smb_vwv3, perm1);
858 SIVAL(req->outbuf, smb_vwv5, perm2);
859 } else {
860 reply_outbuf(req, 3, 0);
863 if ((message_push_string(&req->outbuf, server_devicetype,
864 STR_TERMINATE|STR_ASCII) == -1)
865 || (message_push_string(&req->outbuf, fstype,
866 STR_TERMINATE) == -1)) {
867 reply_nterror(req, NT_STATUS_NO_MEMORY);
868 END_PROFILE(SMBtconX);
869 return;
872 /* what does setting this bit do? It is set by NT4 and
873 may affect the ability to autorun mounted cdroms */
874 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
875 (lp_csc_policy(SNUM(conn)) << 2));
877 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
878 DEBUG(2,("Serving %s as a Dfs root\n",
879 lp_servicename(SNUM(conn)) ));
880 SSVAL(req->outbuf, smb_vwv2,
881 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
886 DEBUG(3,("tconX service=%s \n",
887 service));
889 /* set the incoming and outgoing tid to the just created one */
890 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
891 SSVAL(req->outbuf,smb_tid,conn->cnum);
893 END_PROFILE(SMBtconX);
895 req->tid = conn->cnum;
896 chain_reply(req);
897 return;
900 /****************************************************************************
901 Reply to an unknown type.
902 ****************************************************************************/
904 void reply_unknown_new(struct smb_request *req, uint8 type)
906 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
907 smb_fn_name(type), type, type));
908 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
909 return;
912 /****************************************************************************
913 Reply to an ioctl.
914 conn POINTER CAN BE NULL HERE !
915 ****************************************************************************/
917 void reply_ioctl(struct smb_request *req)
919 connection_struct *conn = req->conn;
920 uint16 device;
921 uint16 function;
922 uint32 ioctl_code;
923 int replysize;
924 char *p;
926 START_PROFILE(SMBioctl);
928 if (req->wct < 3) {
929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
930 END_PROFILE(SMBioctl);
931 return;
934 device = SVAL(req->vwv+1, 0);
935 function = SVAL(req->vwv+2, 0);
936 ioctl_code = (device << 16) + function;
938 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
940 switch (ioctl_code) {
941 case IOCTL_QUERY_JOB_INFO:
942 replysize = 32;
943 break;
944 default:
945 reply_force_doserror(req, ERRSRV, ERRnosupport);
946 END_PROFILE(SMBioctl);
947 return;
950 reply_outbuf(req, 8, replysize+1);
951 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
952 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
953 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
954 p = smb_buf(req->outbuf);
955 memset(p, '\0', replysize+1); /* valgrind-safe. */
956 p += 1; /* Allow for alignment */
958 switch (ioctl_code) {
959 case IOCTL_QUERY_JOB_INFO:
961 files_struct *fsp = file_fsp(
962 req, SVAL(req->vwv+0, 0));
963 if (!fsp) {
964 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
965 END_PROFILE(SMBioctl);
966 return;
968 /* Job number */
969 if (fsp->print_file) {
970 SSVAL(p, 0, fsp->print_file->rap_jobid);
971 } else {
972 SSVAL(p, 0, 0);
974 srvstr_push((char *)req->outbuf, req->flags2, p+2,
975 global_myname(), 15,
976 STR_TERMINATE|STR_ASCII);
977 if (conn) {
978 srvstr_push((char *)req->outbuf, req->flags2,
979 p+18, lp_servicename(SNUM(conn)),
980 13, STR_TERMINATE|STR_ASCII);
981 } else {
982 memset(p+18, 0, 13);
984 break;
988 END_PROFILE(SMBioctl);
989 return;
992 /****************************************************************************
993 Strange checkpath NTSTATUS mapping.
994 ****************************************************************************/
996 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
998 /* Strange DOS error code semantics only for checkpath... */
999 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1000 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1001 /* We need to map to ERRbadpath */
1002 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1005 return status;
1008 /****************************************************************************
1009 Reply to a checkpath.
1010 ****************************************************************************/
1012 void reply_checkpath(struct smb_request *req)
1014 connection_struct *conn = req->conn;
1015 struct smb_filename *smb_fname = NULL;
1016 char *name = NULL;
1017 NTSTATUS status;
1018 TALLOC_CTX *ctx = talloc_tos();
1020 START_PROFILE(SMBcheckpath);
1022 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1023 STR_TERMINATE, &status);
1025 if (!NT_STATUS_IS_OK(status)) {
1026 status = map_checkpath_error(req->flags2, status);
1027 reply_nterror(req, status);
1028 END_PROFILE(SMBcheckpath);
1029 return;
1032 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1034 status = filename_convert(ctx,
1035 conn,
1036 req->flags2 & FLAGS2_DFS_PATHNAMES,
1037 name,
1039 NULL,
1040 &smb_fname);
1042 if (!NT_STATUS_IS_OK(status)) {
1043 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1044 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1045 ERRSRV, ERRbadpath);
1046 END_PROFILE(SMBcheckpath);
1047 return;
1049 goto path_err;
1052 if (!VALID_STAT(smb_fname->st) &&
1053 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1054 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1055 smb_fname_str_dbg(smb_fname), strerror(errno)));
1056 status = map_nt_error_from_unix(errno);
1057 goto path_err;
1060 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1061 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1062 ERRDOS, ERRbadpath);
1063 goto out;
1066 reply_outbuf(req, 0, 0);
1068 path_err:
1069 /* We special case this - as when a Windows machine
1070 is parsing a path is steps through the components
1071 one at a time - if a component fails it expects
1072 ERRbadpath, not ERRbadfile.
1074 status = map_checkpath_error(req->flags2, status);
1075 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1077 * Windows returns different error codes if
1078 * the parent directory is valid but not the
1079 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1080 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1081 * if the path is invalid.
1083 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1084 ERRDOS, ERRbadpath);
1085 goto out;
1088 reply_nterror(req, status);
1090 out:
1091 TALLOC_FREE(smb_fname);
1092 END_PROFILE(SMBcheckpath);
1093 return;
1096 /****************************************************************************
1097 Reply to a getatr.
1098 ****************************************************************************/
1100 void reply_getatr(struct smb_request *req)
1102 connection_struct *conn = req->conn;
1103 struct smb_filename *smb_fname = NULL;
1104 char *fname = NULL;
1105 int mode=0;
1106 SMB_OFF_T size=0;
1107 time_t mtime=0;
1108 const char *p;
1109 NTSTATUS status;
1110 TALLOC_CTX *ctx = talloc_tos();
1111 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1113 START_PROFILE(SMBgetatr);
1115 p = (const char *)req->buf + 1;
1116 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1117 if (!NT_STATUS_IS_OK(status)) {
1118 reply_nterror(req, status);
1119 goto out;
1122 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1123 under WfWg - weird! */
1124 if (*fname == '\0') {
1125 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1126 if (!CAN_WRITE(conn)) {
1127 mode |= FILE_ATTRIBUTE_READONLY;
1129 size = 0;
1130 mtime = 0;
1131 } else {
1132 status = filename_convert(ctx,
1133 conn,
1134 req->flags2 & FLAGS2_DFS_PATHNAMES,
1135 fname,
1137 NULL,
1138 &smb_fname);
1139 if (!NT_STATUS_IS_OK(status)) {
1140 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1141 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1142 ERRSRV, ERRbadpath);
1143 goto out;
1145 reply_nterror(req, status);
1146 goto out;
1148 if (!VALID_STAT(smb_fname->st) &&
1149 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1150 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1151 smb_fname_str_dbg(smb_fname),
1152 strerror(errno)));
1153 reply_nterror(req, map_nt_error_from_unix(errno));
1154 goto out;
1157 mode = dos_mode(conn, smb_fname);
1158 size = smb_fname->st.st_ex_size;
1160 if (ask_sharemode) {
1161 struct timespec write_time_ts;
1162 struct file_id fileid;
1164 ZERO_STRUCT(write_time_ts);
1165 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1166 get_file_infos(fileid, 0, NULL, &write_time_ts);
1167 if (!null_timespec(write_time_ts)) {
1168 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1172 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1173 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1174 size = 0;
1178 reply_outbuf(req, 10, 0);
1180 SSVAL(req->outbuf,smb_vwv0,mode);
1181 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1182 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1183 } else {
1184 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1186 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1188 if (get_Protocol() >= PROTOCOL_NT1) {
1189 SSVAL(req->outbuf, smb_flg2,
1190 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1193 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1194 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1196 out:
1197 TALLOC_FREE(smb_fname);
1198 TALLOC_FREE(fname);
1199 END_PROFILE(SMBgetatr);
1200 return;
1203 /****************************************************************************
1204 Reply to a setatr.
1205 ****************************************************************************/
1207 void reply_setatr(struct smb_request *req)
1209 struct smb_file_time ft;
1210 connection_struct *conn = req->conn;
1211 struct smb_filename *smb_fname = NULL;
1212 char *fname = NULL;
1213 int mode;
1214 time_t mtime;
1215 const char *p;
1216 NTSTATUS status;
1217 TALLOC_CTX *ctx = talloc_tos();
1219 START_PROFILE(SMBsetatr);
1221 ZERO_STRUCT(ft);
1223 if (req->wct < 2) {
1224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1225 goto out;
1228 p = (const char *)req->buf + 1;
1229 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1230 if (!NT_STATUS_IS_OK(status)) {
1231 reply_nterror(req, status);
1232 goto out;
1235 status = filename_convert(ctx,
1236 conn,
1237 req->flags2 & FLAGS2_DFS_PATHNAMES,
1238 fname,
1240 NULL,
1241 &smb_fname);
1242 if (!NT_STATUS_IS_OK(status)) {
1243 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1244 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1245 ERRSRV, ERRbadpath);
1246 goto out;
1248 reply_nterror(req, status);
1249 goto out;
1252 if (smb_fname->base_name[0] == '.' &&
1253 smb_fname->base_name[1] == '\0') {
1255 * Not sure here is the right place to catch this
1256 * condition. Might be moved to somewhere else later -- vl
1258 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1259 goto out;
1262 mode = SVAL(req->vwv+0, 0);
1263 mtime = srv_make_unix_date3(req->vwv+1);
1265 ft.mtime = convert_time_t_to_timespec(mtime);
1266 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1267 if (!NT_STATUS_IS_OK(status)) {
1268 reply_nterror(req, status);
1269 goto out;
1272 if (mode != FILE_ATTRIBUTE_NORMAL) {
1273 if (VALID_STAT_OF_DIR(smb_fname->st))
1274 mode |= FILE_ATTRIBUTE_DIRECTORY;
1275 else
1276 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1278 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1279 false) != 0) {
1280 reply_nterror(req, map_nt_error_from_unix(errno));
1281 goto out;
1285 reply_outbuf(req, 0, 0);
1287 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1288 mode));
1289 out:
1290 TALLOC_FREE(smb_fname);
1291 END_PROFILE(SMBsetatr);
1292 return;
1295 /****************************************************************************
1296 Reply to a dskattr.
1297 ****************************************************************************/
1299 void reply_dskattr(struct smb_request *req)
1301 connection_struct *conn = req->conn;
1302 uint64_t dfree,dsize,bsize;
1303 START_PROFILE(SMBdskattr);
1305 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1306 reply_nterror(req, map_nt_error_from_unix(errno));
1307 END_PROFILE(SMBdskattr);
1308 return;
1311 reply_outbuf(req, 5, 0);
1313 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1314 double total_space, free_space;
1315 /* we need to scale this to a number that DOS6 can handle. We
1316 use floating point so we can handle large drives on systems
1317 that don't have 64 bit integers
1319 we end up displaying a maximum of 2G to DOS systems
1321 total_space = dsize * (double)bsize;
1322 free_space = dfree * (double)bsize;
1324 dsize = (uint64_t)((total_space+63*512) / (64*512));
1325 dfree = (uint64_t)((free_space+63*512) / (64*512));
1327 if (dsize > 0xFFFF) dsize = 0xFFFF;
1328 if (dfree > 0xFFFF) dfree = 0xFFFF;
1330 SSVAL(req->outbuf,smb_vwv0,dsize);
1331 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1332 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1333 SSVAL(req->outbuf,smb_vwv3,dfree);
1334 } else {
1335 SSVAL(req->outbuf,smb_vwv0,dsize);
1336 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1337 SSVAL(req->outbuf,smb_vwv2,512);
1338 SSVAL(req->outbuf,smb_vwv3,dfree);
1341 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1343 END_PROFILE(SMBdskattr);
1344 return;
1348 * Utility function to split the filename from the directory.
1350 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1351 char **fname_dir_out,
1352 char **fname_mask_out)
1354 const char *p = NULL;
1355 char *fname_dir = NULL;
1356 char *fname_mask = NULL;
1358 p = strrchr_m(fname_in, '/');
1359 if (!p) {
1360 fname_dir = talloc_strdup(ctx, ".");
1361 fname_mask = talloc_strdup(ctx, fname_in);
1362 } else {
1363 fname_dir = talloc_strndup(ctx, fname_in,
1364 PTR_DIFF(p, fname_in));
1365 fname_mask = talloc_strdup(ctx, p+1);
1368 if (!fname_dir || !fname_mask) {
1369 TALLOC_FREE(fname_dir);
1370 TALLOC_FREE(fname_mask);
1371 return NT_STATUS_NO_MEMORY;
1374 *fname_dir_out = fname_dir;
1375 *fname_mask_out = fname_mask;
1376 return NT_STATUS_OK;
1379 /****************************************************************************
1380 Reply to a search.
1381 Can be called from SMBsearch, SMBffirst or SMBfunique.
1382 ****************************************************************************/
1384 void reply_search(struct smb_request *req)
1386 connection_struct *conn = req->conn;
1387 char *path = NULL;
1388 const char *mask = NULL;
1389 char *directory = NULL;
1390 struct smb_filename *smb_fname = NULL;
1391 char *fname = NULL;
1392 SMB_OFF_T size;
1393 uint32 mode;
1394 struct timespec date;
1395 uint32 dirtype;
1396 unsigned int numentries = 0;
1397 unsigned int maxentries = 0;
1398 bool finished = False;
1399 const char *p;
1400 int status_len;
1401 char status[21];
1402 int dptr_num= -1;
1403 bool check_descend = False;
1404 bool expect_close = False;
1405 NTSTATUS nt_status;
1406 bool mask_contains_wcard = False;
1407 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1408 TALLOC_CTX *ctx = talloc_tos();
1409 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1410 struct dptr_struct *dirptr = NULL;
1411 struct smbd_server_connection *sconn = req->sconn;
1413 START_PROFILE(SMBsearch);
1415 if (req->wct < 2) {
1416 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1417 goto out;
1420 if (lp_posix_pathnames()) {
1421 reply_unknown_new(req, req->cmd);
1422 goto out;
1425 /* If we were called as SMBffirst then we must expect close. */
1426 if(req->cmd == SMBffirst) {
1427 expect_close = True;
1430 reply_outbuf(req, 1, 3);
1431 maxentries = SVAL(req->vwv+0, 0);
1432 dirtype = SVAL(req->vwv+1, 0);
1433 p = (const char *)req->buf + 1;
1434 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1435 &nt_status, &mask_contains_wcard);
1436 if (!NT_STATUS_IS_OK(nt_status)) {
1437 reply_nterror(req, nt_status);
1438 goto out;
1441 p++;
1442 status_len = SVAL(p, 0);
1443 p += 2;
1445 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1447 if (status_len == 0) {
1448 nt_status = filename_convert(ctx, conn,
1449 req->flags2 & FLAGS2_DFS_PATHNAMES,
1450 path,
1451 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1452 &mask_contains_wcard,
1453 &smb_fname);
1454 if (!NT_STATUS_IS_OK(nt_status)) {
1455 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1456 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1457 ERRSRV, ERRbadpath);
1458 goto out;
1460 reply_nterror(req, nt_status);
1461 goto out;
1464 directory = smb_fname->base_name;
1466 p = strrchr_m(directory,'/');
1467 if ((p != NULL) && (*directory != '/')) {
1468 mask = p + 1;
1469 directory = talloc_strndup(ctx, directory,
1470 PTR_DIFF(p, directory));
1471 } else {
1472 mask = directory;
1473 directory = talloc_strdup(ctx,".");
1476 if (!directory) {
1477 reply_nterror(req, NT_STATUS_NO_MEMORY);
1478 goto out;
1481 memset((char *)status,'\0',21);
1482 SCVAL(status,0,(dirtype & 0x1F));
1484 nt_status = dptr_create(conn,
1485 NULL, /* fsp */
1486 directory,
1487 True,
1488 expect_close,
1489 req->smbpid,
1490 mask,
1491 mask_contains_wcard,
1492 dirtype,
1493 &dirptr);
1494 if (!NT_STATUS_IS_OK(nt_status)) {
1495 reply_nterror(req, nt_status);
1496 goto out;
1498 dptr_num = dptr_dnum(dirptr);
1499 } else {
1500 int status_dirtype;
1501 const char *dirpath;
1503 memcpy(status,p,21);
1504 status_dirtype = CVAL(status,0) & 0x1F;
1505 if (status_dirtype != (dirtype & 0x1F)) {
1506 dirtype = status_dirtype;
1509 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1510 if (!dirptr) {
1511 goto SearchEmpty;
1513 dirpath = dptr_path(sconn, dptr_num);
1514 directory = talloc_strdup(ctx, dirpath);
1515 if (!directory) {
1516 reply_nterror(req, NT_STATUS_NO_MEMORY);
1517 goto out;
1520 mask = dptr_wcard(sconn, dptr_num);
1521 if (!mask) {
1522 goto SearchEmpty;
1525 * For a 'continue' search we have no string. So
1526 * check from the initial saved string.
1528 mask_contains_wcard = ms_has_wild(mask);
1529 dirtype = dptr_attr(sconn, dptr_num);
1532 DEBUG(4,("dptr_num is %d\n",dptr_num));
1534 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1535 dptr_init_search_op(dirptr);
1537 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1538 char buf[DIR_STRUCT_SIZE];
1539 memcpy(buf,status,21);
1540 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1541 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1542 reply_nterror(req, NT_STATUS_NO_MEMORY);
1543 goto out;
1545 dptr_fill(sconn, buf+12,dptr_num);
1546 if (dptr_zero(buf+12) && (status_len==0)) {
1547 numentries = 1;
1548 } else {
1549 numentries = 0;
1551 if (message_push_blob(&req->outbuf,
1552 data_blob_const(buf, sizeof(buf)))
1553 == -1) {
1554 reply_nterror(req, NT_STATUS_NO_MEMORY);
1555 goto out;
1557 } else {
1558 unsigned int i;
1559 maxentries = MIN(
1560 maxentries,
1561 ((BUFFER_SIZE -
1562 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1563 /DIR_STRUCT_SIZE));
1565 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1566 directory,lp_dontdescend(SNUM(conn))));
1567 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1568 check_descend = True;
1571 for (i=numentries;(i<maxentries) && !finished;i++) {
1572 finished = !get_dir_entry(ctx,
1573 dirptr,
1574 mask,
1575 dirtype,
1576 &fname,
1577 &size,
1578 &mode,
1579 &date,
1580 check_descend,
1581 ask_sharemode);
1582 if (!finished) {
1583 char buf[DIR_STRUCT_SIZE];
1584 memcpy(buf,status,21);
1585 if (!make_dir_struct(ctx,
1586 buf,
1587 mask,
1588 fname,
1589 size,
1590 mode,
1591 convert_timespec_to_time_t(date),
1592 !allow_long_path_components)) {
1593 reply_nterror(req, NT_STATUS_NO_MEMORY);
1594 goto out;
1596 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1597 break;
1599 if (message_push_blob(&req->outbuf,
1600 data_blob_const(buf, sizeof(buf)))
1601 == -1) {
1602 reply_nterror(req, NT_STATUS_NO_MEMORY);
1603 goto out;
1605 numentries++;
1610 SearchEmpty:
1612 /* If we were called as SMBffirst with smb_search_id == NULL
1613 and no entries were found then return error and close dirptr
1614 (X/Open spec) */
1616 if (numentries == 0) {
1617 dptr_close(sconn, &dptr_num);
1618 } else if(expect_close && status_len == 0) {
1619 /* Close the dptr - we know it's gone */
1620 dptr_close(sconn, &dptr_num);
1623 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1624 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1625 dptr_close(sconn, &dptr_num);
1628 if ((numentries == 0) && !mask_contains_wcard) {
1629 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1630 goto out;
1633 SSVAL(req->outbuf,smb_vwv0,numentries);
1634 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1635 SCVAL(smb_buf(req->outbuf),0,5);
1636 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1638 /* The replies here are never long name. */
1639 SSVAL(req->outbuf, smb_flg2,
1640 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1641 if (!allow_long_path_components) {
1642 SSVAL(req->outbuf, smb_flg2,
1643 SVAL(req->outbuf, smb_flg2)
1644 & (~FLAGS2_LONG_PATH_COMPONENTS));
1647 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1648 SSVAL(req->outbuf, smb_flg2,
1649 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1651 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1652 smb_fn_name(req->cmd),
1653 mask,
1654 directory,
1655 dirtype,
1656 numentries,
1657 maxentries ));
1658 out:
1659 TALLOC_FREE(directory);
1660 TALLOC_FREE(smb_fname);
1661 END_PROFILE(SMBsearch);
1662 return;
1665 /****************************************************************************
1666 Reply to a fclose (stop directory search).
1667 ****************************************************************************/
1669 void reply_fclose(struct smb_request *req)
1671 int status_len;
1672 char status[21];
1673 int dptr_num= -2;
1674 const char *p;
1675 char *path = NULL;
1676 NTSTATUS err;
1677 bool path_contains_wcard = False;
1678 TALLOC_CTX *ctx = talloc_tos();
1679 struct smbd_server_connection *sconn = req->sconn;
1681 START_PROFILE(SMBfclose);
1683 if (lp_posix_pathnames()) {
1684 reply_unknown_new(req, req->cmd);
1685 END_PROFILE(SMBfclose);
1686 return;
1689 p = (const char *)req->buf + 1;
1690 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1691 &err, &path_contains_wcard);
1692 if (!NT_STATUS_IS_OK(err)) {
1693 reply_nterror(req, err);
1694 END_PROFILE(SMBfclose);
1695 return;
1697 p++;
1698 status_len = SVAL(p,0);
1699 p += 2;
1701 if (status_len == 0) {
1702 reply_force_doserror(req, ERRSRV, ERRsrverror);
1703 END_PROFILE(SMBfclose);
1704 return;
1707 memcpy(status,p,21);
1709 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1710 /* Close the dptr - we know it's gone */
1711 dptr_close(sconn, &dptr_num);
1714 reply_outbuf(req, 1, 0);
1715 SSVAL(req->outbuf,smb_vwv0,0);
1717 DEBUG(3,("search close\n"));
1719 END_PROFILE(SMBfclose);
1720 return;
1723 /****************************************************************************
1724 Reply to an open.
1725 ****************************************************************************/
1727 void reply_open(struct smb_request *req)
1729 connection_struct *conn = req->conn;
1730 struct smb_filename *smb_fname = NULL;
1731 char *fname = NULL;
1732 uint32 fattr=0;
1733 SMB_OFF_T size = 0;
1734 time_t mtime=0;
1735 int info;
1736 files_struct *fsp;
1737 int oplock_request;
1738 int deny_mode;
1739 uint32 dos_attr;
1740 uint32 access_mask;
1741 uint32 share_mode;
1742 uint32 create_disposition;
1743 uint32 create_options = 0;
1744 uint32_t private_flags = 0;
1745 NTSTATUS status;
1746 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1747 TALLOC_CTX *ctx = talloc_tos();
1749 START_PROFILE(SMBopen);
1751 if (req->wct < 2) {
1752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1753 goto out;
1756 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1757 deny_mode = SVAL(req->vwv+0, 0);
1758 dos_attr = SVAL(req->vwv+1, 0);
1760 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1761 STR_TERMINATE, &status);
1762 if (!NT_STATUS_IS_OK(status)) {
1763 reply_nterror(req, status);
1764 goto out;
1767 status = filename_convert(ctx,
1768 conn,
1769 req->flags2 & FLAGS2_DFS_PATHNAMES,
1770 fname,
1772 NULL,
1773 &smb_fname);
1774 if (!NT_STATUS_IS_OK(status)) {
1775 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1776 reply_botherror(req,
1777 NT_STATUS_PATH_NOT_COVERED,
1778 ERRSRV, ERRbadpath);
1779 goto out;
1781 reply_nterror(req, status);
1782 goto out;
1785 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1786 OPENX_FILE_EXISTS_OPEN, &access_mask,
1787 &share_mode, &create_disposition,
1788 &create_options, &private_flags)) {
1789 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1790 goto out;
1793 status = SMB_VFS_CREATE_FILE(
1794 conn, /* conn */
1795 req, /* req */
1796 0, /* root_dir_fid */
1797 smb_fname, /* fname */
1798 access_mask, /* access_mask */
1799 share_mode, /* share_access */
1800 create_disposition, /* create_disposition*/
1801 create_options, /* create_options */
1802 dos_attr, /* file_attributes */
1803 oplock_request, /* oplock_request */
1804 0, /* allocation_size */
1805 private_flags,
1806 NULL, /* sd */
1807 NULL, /* ea_list */
1808 &fsp, /* result */
1809 &info); /* pinfo */
1811 if (!NT_STATUS_IS_OK(status)) {
1812 if (open_was_deferred(req->mid)) {
1813 /* We have re-scheduled this call. */
1814 goto out;
1816 reply_openerror(req, status);
1817 goto out;
1820 size = smb_fname->st.st_ex_size;
1821 fattr = dos_mode(conn, smb_fname);
1823 /* Deal with other possible opens having a modified
1824 write time. JRA. */
1825 if (ask_sharemode) {
1826 struct timespec write_time_ts;
1828 ZERO_STRUCT(write_time_ts);
1829 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1830 if (!null_timespec(write_time_ts)) {
1831 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1835 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1837 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1838 DEBUG(3,("attempt to open a directory %s\n",
1839 fsp_str_dbg(fsp)));
1840 close_file(req, fsp, ERROR_CLOSE);
1841 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1842 ERRDOS, ERRnoaccess);
1843 goto out;
1846 reply_outbuf(req, 7, 0);
1847 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1848 SSVAL(req->outbuf,smb_vwv1,fattr);
1849 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1850 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1851 } else {
1852 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1854 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1855 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1857 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1858 SCVAL(req->outbuf,smb_flg,
1859 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1862 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1863 SCVAL(req->outbuf,smb_flg,
1864 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1866 out:
1867 TALLOC_FREE(smb_fname);
1868 END_PROFILE(SMBopen);
1869 return;
1872 /****************************************************************************
1873 Reply to an open and X.
1874 ****************************************************************************/
1876 void reply_open_and_X(struct smb_request *req)
1878 connection_struct *conn = req->conn;
1879 struct smb_filename *smb_fname = NULL;
1880 char *fname = NULL;
1881 uint16 open_flags;
1882 int deny_mode;
1883 uint32 smb_attr;
1884 /* Breakout the oplock request bits so we can set the
1885 reply bits separately. */
1886 int ex_oplock_request;
1887 int core_oplock_request;
1888 int oplock_request;
1889 #if 0
1890 int smb_sattr = SVAL(req->vwv+4, 0);
1891 uint32 smb_time = make_unix_date3(req->vwv+6);
1892 #endif
1893 int smb_ofun;
1894 uint32 fattr=0;
1895 int mtime=0;
1896 int smb_action = 0;
1897 files_struct *fsp;
1898 NTSTATUS status;
1899 uint64_t allocation_size;
1900 ssize_t retval = -1;
1901 uint32 access_mask;
1902 uint32 share_mode;
1903 uint32 create_disposition;
1904 uint32 create_options = 0;
1905 uint32_t private_flags = 0;
1906 TALLOC_CTX *ctx = talloc_tos();
1908 START_PROFILE(SMBopenX);
1910 if (req->wct < 15) {
1911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1912 goto out;
1915 open_flags = SVAL(req->vwv+2, 0);
1916 deny_mode = SVAL(req->vwv+3, 0);
1917 smb_attr = SVAL(req->vwv+5, 0);
1918 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1919 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1920 oplock_request = ex_oplock_request | core_oplock_request;
1921 smb_ofun = SVAL(req->vwv+8, 0);
1922 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1924 /* If it's an IPC, pass off the pipe handler. */
1925 if (IS_IPC(conn)) {
1926 if (lp_nt_pipe_support()) {
1927 reply_open_pipe_and_X(conn, req);
1928 } else {
1929 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1931 goto out;
1934 /* XXXX we need to handle passed times, sattr and flags */
1935 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1936 STR_TERMINATE, &status);
1937 if (!NT_STATUS_IS_OK(status)) {
1938 reply_nterror(req, status);
1939 goto out;
1942 status = filename_convert(ctx,
1943 conn,
1944 req->flags2 & FLAGS2_DFS_PATHNAMES,
1945 fname,
1947 NULL,
1948 &smb_fname);
1949 if (!NT_STATUS_IS_OK(status)) {
1950 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1951 reply_botherror(req,
1952 NT_STATUS_PATH_NOT_COVERED,
1953 ERRSRV, ERRbadpath);
1954 goto out;
1956 reply_nterror(req, status);
1957 goto out;
1960 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1961 &access_mask, &share_mode,
1962 &create_disposition,
1963 &create_options,
1964 &private_flags)) {
1965 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1966 goto out;
1969 status = SMB_VFS_CREATE_FILE(
1970 conn, /* conn */
1971 req, /* req */
1972 0, /* root_dir_fid */
1973 smb_fname, /* fname */
1974 access_mask, /* access_mask */
1975 share_mode, /* share_access */
1976 create_disposition, /* create_disposition*/
1977 create_options, /* create_options */
1978 smb_attr, /* file_attributes */
1979 oplock_request, /* oplock_request */
1980 0, /* allocation_size */
1981 private_flags,
1982 NULL, /* sd */
1983 NULL, /* ea_list */
1984 &fsp, /* result */
1985 &smb_action); /* pinfo */
1987 if (!NT_STATUS_IS_OK(status)) {
1988 if (open_was_deferred(req->mid)) {
1989 /* We have re-scheduled this call. */
1990 goto out;
1992 reply_openerror(req, status);
1993 goto out;
1996 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1997 if the file is truncated or created. */
1998 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1999 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2000 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2001 close_file(req, fsp, ERROR_CLOSE);
2002 reply_nterror(req, NT_STATUS_DISK_FULL);
2003 goto out;
2005 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
2006 if (retval < 0) {
2007 close_file(req, fsp, ERROR_CLOSE);
2008 reply_nterror(req, NT_STATUS_DISK_FULL);
2009 goto out;
2011 status = vfs_stat_fsp(fsp);
2012 if (!NT_STATUS_IS_OK(status)) {
2013 close_file(req, fsp, ERROR_CLOSE);
2014 reply_nterror(req, status);
2015 goto out;
2019 fattr = dos_mode(conn, fsp->fsp_name);
2020 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2021 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2022 close_file(req, fsp, ERROR_CLOSE);
2023 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2024 goto out;
2027 /* If the caller set the extended oplock request bit
2028 and we granted one (by whatever means) - set the
2029 correct bit for extended oplock reply.
2032 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2033 smb_action |= EXTENDED_OPLOCK_GRANTED;
2036 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2037 smb_action |= EXTENDED_OPLOCK_GRANTED;
2040 /* If the caller set the core oplock request bit
2041 and we granted one (by whatever means) - set the
2042 correct bit for core oplock reply.
2045 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2046 reply_outbuf(req, 19, 0);
2047 } else {
2048 reply_outbuf(req, 15, 0);
2051 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2052 SCVAL(req->outbuf, smb_flg,
2053 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2056 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2057 SCVAL(req->outbuf, smb_flg,
2058 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2061 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2062 SSVAL(req->outbuf,smb_vwv3,fattr);
2063 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2064 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2065 } else {
2066 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2068 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2069 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2070 SSVAL(req->outbuf,smb_vwv11,smb_action);
2072 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2073 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2076 chain_reply(req);
2077 out:
2078 TALLOC_FREE(smb_fname);
2079 END_PROFILE(SMBopenX);
2080 return;
2083 /****************************************************************************
2084 Reply to a SMBulogoffX.
2085 ****************************************************************************/
2087 void reply_ulogoffX(struct smb_request *req)
2089 struct smbd_server_connection *sconn = req->sconn;
2090 user_struct *vuser;
2092 START_PROFILE(SMBulogoffX);
2094 vuser = get_valid_user_struct(sconn, req->vuid);
2096 if(vuser == NULL) {
2097 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2098 req->vuid));
2101 /* in user level security we are supposed to close any files
2102 open by this user */
2103 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2104 file_close_user(sconn, req->vuid);
2107 invalidate_vuid(sconn, req->vuid);
2109 reply_outbuf(req, 2, 0);
2111 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2113 END_PROFILE(SMBulogoffX);
2114 req->vuid = UID_FIELD_INVALID;
2115 chain_reply(req);
2118 /****************************************************************************
2119 Reply to a mknew or a create.
2120 ****************************************************************************/
2122 void reply_mknew(struct smb_request *req)
2124 connection_struct *conn = req->conn;
2125 struct smb_filename *smb_fname = NULL;
2126 char *fname = NULL;
2127 uint32 fattr = 0;
2128 struct smb_file_time ft;
2129 files_struct *fsp;
2130 int oplock_request = 0;
2131 NTSTATUS status;
2132 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2133 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2134 uint32 create_disposition;
2135 uint32 create_options = 0;
2136 TALLOC_CTX *ctx = talloc_tos();
2138 START_PROFILE(SMBcreate);
2139 ZERO_STRUCT(ft);
2141 if (req->wct < 3) {
2142 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2143 goto out;
2146 fattr = SVAL(req->vwv+0, 0);
2147 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2149 /* mtime. */
2150 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2152 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2153 STR_TERMINATE, &status);
2154 if (!NT_STATUS_IS_OK(status)) {
2155 reply_nterror(req, status);
2156 goto out;
2159 status = filename_convert(ctx,
2160 conn,
2161 req->flags2 & FLAGS2_DFS_PATHNAMES,
2162 fname,
2164 NULL,
2165 &smb_fname);
2166 if (!NT_STATUS_IS_OK(status)) {
2167 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2168 reply_botherror(req,
2169 NT_STATUS_PATH_NOT_COVERED,
2170 ERRSRV, ERRbadpath);
2171 goto out;
2173 reply_nterror(req, status);
2174 goto out;
2177 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2178 DEBUG(0,("Attempt to create file (%s) with volid set - "
2179 "please report this\n",
2180 smb_fname_str_dbg(smb_fname)));
2183 if(req->cmd == SMBmknew) {
2184 /* We should fail if file exists. */
2185 create_disposition = FILE_CREATE;
2186 } else {
2187 /* Create if file doesn't exist, truncate if it does. */
2188 create_disposition = FILE_OVERWRITE_IF;
2191 status = SMB_VFS_CREATE_FILE(
2192 conn, /* conn */
2193 req, /* req */
2194 0, /* root_dir_fid */
2195 smb_fname, /* fname */
2196 access_mask, /* access_mask */
2197 share_mode, /* share_access */
2198 create_disposition, /* create_disposition*/
2199 create_options, /* create_options */
2200 fattr, /* file_attributes */
2201 oplock_request, /* oplock_request */
2202 0, /* allocation_size */
2203 0, /* private_flags */
2204 NULL, /* sd */
2205 NULL, /* ea_list */
2206 &fsp, /* result */
2207 NULL); /* pinfo */
2209 if (!NT_STATUS_IS_OK(status)) {
2210 if (open_was_deferred(req->mid)) {
2211 /* We have re-scheduled this call. */
2212 goto out;
2214 reply_openerror(req, status);
2215 goto out;
2218 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2219 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2220 if (!NT_STATUS_IS_OK(status)) {
2221 END_PROFILE(SMBcreate);
2222 goto out;
2225 reply_outbuf(req, 1, 0);
2226 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2228 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2229 SCVAL(req->outbuf,smb_flg,
2230 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2233 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2234 SCVAL(req->outbuf,smb_flg,
2235 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2238 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2239 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2240 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2241 (unsigned int)fattr));
2243 out:
2244 TALLOC_FREE(smb_fname);
2245 END_PROFILE(SMBcreate);
2246 return;
2249 /****************************************************************************
2250 Reply to a create temporary file.
2251 ****************************************************************************/
2253 void reply_ctemp(struct smb_request *req)
2255 connection_struct *conn = req->conn;
2256 struct smb_filename *smb_fname = NULL;
2257 char *fname = NULL;
2258 uint32 fattr;
2259 files_struct *fsp;
2260 int oplock_request;
2261 int tmpfd;
2262 char *s;
2263 NTSTATUS status;
2264 TALLOC_CTX *ctx = talloc_tos();
2266 START_PROFILE(SMBctemp);
2268 if (req->wct < 3) {
2269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2270 goto out;
2273 fattr = SVAL(req->vwv+0, 0);
2274 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2276 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2277 STR_TERMINATE, &status);
2278 if (!NT_STATUS_IS_OK(status)) {
2279 reply_nterror(req, status);
2280 goto out;
2282 if (*fname) {
2283 fname = talloc_asprintf(ctx,
2284 "%s/TMXXXXXX",
2285 fname);
2286 } else {
2287 fname = talloc_strdup(ctx, "TMXXXXXX");
2290 if (!fname) {
2291 reply_nterror(req, NT_STATUS_NO_MEMORY);
2292 goto out;
2295 status = filename_convert(ctx, conn,
2296 req->flags2 & FLAGS2_DFS_PATHNAMES,
2297 fname,
2299 NULL,
2300 &smb_fname);
2301 if (!NT_STATUS_IS_OK(status)) {
2302 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2303 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2304 ERRSRV, ERRbadpath);
2305 goto out;
2307 reply_nterror(req, status);
2308 goto out;
2311 tmpfd = mkstemp(smb_fname->base_name);
2312 if (tmpfd == -1) {
2313 reply_nterror(req, map_nt_error_from_unix(errno));
2314 goto out;
2317 SMB_VFS_STAT(conn, smb_fname);
2319 /* We should fail if file does not exist. */
2320 status = SMB_VFS_CREATE_FILE(
2321 conn, /* conn */
2322 req, /* req */
2323 0, /* root_dir_fid */
2324 smb_fname, /* fname */
2325 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2326 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2327 FILE_OPEN, /* create_disposition*/
2328 0, /* create_options */
2329 fattr, /* file_attributes */
2330 oplock_request, /* oplock_request */
2331 0, /* allocation_size */
2332 0, /* private_flags */
2333 NULL, /* sd */
2334 NULL, /* ea_list */
2335 &fsp, /* result */
2336 NULL); /* pinfo */
2338 /* close fd from mkstemp() */
2339 close(tmpfd);
2341 if (!NT_STATUS_IS_OK(status)) {
2342 if (open_was_deferred(req->mid)) {
2343 /* We have re-scheduled this call. */
2344 goto out;
2346 reply_openerror(req, status);
2347 goto out;
2350 reply_outbuf(req, 1, 0);
2351 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2353 /* the returned filename is relative to the directory */
2354 s = strrchr_m(fsp->fsp_name->base_name, '/');
2355 if (!s) {
2356 s = fsp->fsp_name->base_name;
2357 } else {
2358 s++;
2361 #if 0
2362 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2363 thing in the byte section. JRA */
2364 SSVALS(p, 0, -1); /* what is this? not in spec */
2365 #endif
2366 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2367 == -1) {
2368 reply_nterror(req, NT_STATUS_NO_MEMORY);
2369 goto out;
2372 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2373 SCVAL(req->outbuf, smb_flg,
2374 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2377 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2378 SCVAL(req->outbuf, smb_flg,
2379 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2382 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2383 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2384 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2385 out:
2386 TALLOC_FREE(smb_fname);
2387 END_PROFILE(SMBctemp);
2388 return;
2391 /*******************************************************************
2392 Check if a user is allowed to rename a file.
2393 ********************************************************************/
2395 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2396 uint16 dirtype)
2398 if (!CAN_WRITE(conn)) {
2399 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2402 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2403 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2404 /* Only bother to read the DOS attribute if we might deny the
2405 rename on the grounds of attribute missmatch. */
2406 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2407 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2408 return NT_STATUS_NO_SUCH_FILE;
2412 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2413 if (fsp->posix_open) {
2414 return NT_STATUS_OK;
2417 /* If no pathnames are open below this
2418 directory, allow the rename. */
2420 if (file_find_subpath(fsp)) {
2421 return NT_STATUS_ACCESS_DENIED;
2423 return NT_STATUS_OK;
2426 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2427 return NT_STATUS_OK;
2430 return NT_STATUS_ACCESS_DENIED;
2433 /*******************************************************************
2434 * unlink a file with all relevant access checks
2435 *******************************************************************/
2437 static NTSTATUS do_unlink(connection_struct *conn,
2438 struct smb_request *req,
2439 struct smb_filename *smb_fname,
2440 uint32 dirtype)
2442 uint32 fattr;
2443 files_struct *fsp;
2444 uint32 dirtype_orig = dirtype;
2445 NTSTATUS status;
2446 int ret;
2447 bool posix_paths = lp_posix_pathnames();
2449 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2450 smb_fname_str_dbg(smb_fname),
2451 dirtype));
2453 if (!CAN_WRITE(conn)) {
2454 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2457 if (posix_paths) {
2458 ret = SMB_VFS_LSTAT(conn, smb_fname);
2459 } else {
2460 ret = SMB_VFS_STAT(conn, smb_fname);
2462 if (ret != 0) {
2463 return map_nt_error_from_unix(errno);
2466 fattr = dos_mode(conn, smb_fname);
2468 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2469 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2472 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2473 if (!dirtype) {
2474 return NT_STATUS_NO_SUCH_FILE;
2477 if (!dir_check_ftype(conn, fattr, dirtype)) {
2478 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2479 return NT_STATUS_FILE_IS_A_DIRECTORY;
2481 return NT_STATUS_NO_SUCH_FILE;
2484 if (dirtype_orig & 0x8000) {
2485 /* These will never be set for POSIX. */
2486 return NT_STATUS_NO_SUCH_FILE;
2489 #if 0
2490 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2491 return NT_STATUS_FILE_IS_A_DIRECTORY;
2494 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2495 return NT_STATUS_NO_SUCH_FILE;
2498 if (dirtype & 0xFF00) {
2499 /* These will never be set for POSIX. */
2500 return NT_STATUS_NO_SUCH_FILE;
2503 dirtype &= 0xFF;
2504 if (!dirtype) {
2505 return NT_STATUS_NO_SUCH_FILE;
2508 /* Can't delete a directory. */
2509 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2510 return NT_STATUS_FILE_IS_A_DIRECTORY;
2512 #endif
2514 #if 0 /* JRATEST */
2515 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2516 return NT_STATUS_OBJECT_NAME_INVALID;
2517 #endif /* JRATEST */
2519 /* On open checks the open itself will check the share mode, so
2520 don't do it here as we'll get it wrong. */
2522 status = SMB_VFS_CREATE_FILE
2523 (conn, /* conn */
2524 req, /* req */
2525 0, /* root_dir_fid */
2526 smb_fname, /* fname */
2527 DELETE_ACCESS, /* access_mask */
2528 FILE_SHARE_NONE, /* share_access */
2529 FILE_OPEN, /* create_disposition*/
2530 FILE_NON_DIRECTORY_FILE, /* create_options */
2531 /* file_attributes */
2532 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2533 FILE_ATTRIBUTE_NORMAL,
2534 0, /* oplock_request */
2535 0, /* allocation_size */
2536 0, /* private_flags */
2537 NULL, /* sd */
2538 NULL, /* ea_list */
2539 &fsp, /* result */
2540 NULL); /* pinfo */
2542 if (!NT_STATUS_IS_OK(status)) {
2543 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2544 nt_errstr(status)));
2545 return status;
2548 status = can_set_delete_on_close(fsp, fattr);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2551 "(%s)\n",
2552 smb_fname_str_dbg(smb_fname),
2553 nt_errstr(status)));
2554 close_file(req, fsp, NORMAL_CLOSE);
2555 return status;
2558 /* The set is across all open files on this dev/inode pair. */
2559 if (!set_delete_on_close(fsp, True, &conn->session_info->utok)) {
2560 close_file(req, fsp, NORMAL_CLOSE);
2561 return NT_STATUS_ACCESS_DENIED;
2564 return close_file(req, fsp, NORMAL_CLOSE);
2567 /****************************************************************************
2568 The guts of the unlink command, split out so it may be called by the NT SMB
2569 code.
2570 ****************************************************************************/
2572 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2573 uint32 dirtype, struct smb_filename *smb_fname,
2574 bool has_wild)
2576 char *fname_dir = NULL;
2577 char *fname_mask = NULL;
2578 int count=0;
2579 NTSTATUS status = NT_STATUS_OK;
2580 TALLOC_CTX *ctx = talloc_tos();
2582 /* Split up the directory from the filename/mask. */
2583 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2584 &fname_dir, &fname_mask);
2585 if (!NT_STATUS_IS_OK(status)) {
2586 goto out;
2590 * We should only check the mangled cache
2591 * here if unix_convert failed. This means
2592 * that the path in 'mask' doesn't exist
2593 * on the file system and so we need to look
2594 * for a possible mangle. This patch from
2595 * Tine Smukavec <valentin.smukavec@hermes.si>.
2598 if (!VALID_STAT(smb_fname->st) &&
2599 mangle_is_mangled(fname_mask, conn->params)) {
2600 char *new_mask = NULL;
2601 mangle_lookup_name_from_8_3(ctx, fname_mask,
2602 &new_mask, conn->params);
2603 if (new_mask) {
2604 TALLOC_FREE(fname_mask);
2605 fname_mask = new_mask;
2609 if (!has_wild) {
2612 * Only one file needs to be unlinked. Append the mask back
2613 * onto the directory.
2615 TALLOC_FREE(smb_fname->base_name);
2616 if (ISDOT(fname_dir)) {
2617 /* Ensure we use canonical names on open. */
2618 smb_fname->base_name = talloc_asprintf(smb_fname,
2619 "%s",
2620 fname_mask);
2621 } else {
2622 smb_fname->base_name = talloc_asprintf(smb_fname,
2623 "%s/%s",
2624 fname_dir,
2625 fname_mask);
2627 if (!smb_fname->base_name) {
2628 status = NT_STATUS_NO_MEMORY;
2629 goto out;
2631 if (dirtype == 0) {
2632 dirtype = FILE_ATTRIBUTE_NORMAL;
2635 status = check_name(conn, smb_fname->base_name);
2636 if (!NT_STATUS_IS_OK(status)) {
2637 goto out;
2640 status = do_unlink(conn, req, smb_fname, dirtype);
2641 if (!NT_STATUS_IS_OK(status)) {
2642 goto out;
2645 count++;
2646 } else {
2647 struct smb_Dir *dir_hnd = NULL;
2648 long offset = 0;
2649 const char *dname = NULL;
2650 char *talloced = NULL;
2652 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2653 status = NT_STATUS_OBJECT_NAME_INVALID;
2654 goto out;
2657 if (strequal(fname_mask,"????????.???")) {
2658 TALLOC_FREE(fname_mask);
2659 fname_mask = talloc_strdup(ctx, "*");
2660 if (!fname_mask) {
2661 status = NT_STATUS_NO_MEMORY;
2662 goto out;
2666 status = check_name(conn, fname_dir);
2667 if (!NT_STATUS_IS_OK(status)) {
2668 goto out;
2671 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2672 dirtype);
2673 if (dir_hnd == NULL) {
2674 status = map_nt_error_from_unix(errno);
2675 goto out;
2678 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2679 the pattern matches against the long name, otherwise the short name
2680 We don't implement this yet XXXX
2683 status = NT_STATUS_NO_SUCH_FILE;
2685 while ((dname = ReadDirName(dir_hnd, &offset,
2686 &smb_fname->st, &talloced))) {
2687 TALLOC_CTX *frame = talloc_stackframe();
2689 if (!is_visible_file(conn, fname_dir, dname,
2690 &smb_fname->st, true)) {
2691 TALLOC_FREE(frame);
2692 TALLOC_FREE(talloced);
2693 continue;
2696 /* Quick check for "." and ".." */
2697 if (ISDOT(dname) || ISDOTDOT(dname)) {
2698 TALLOC_FREE(frame);
2699 TALLOC_FREE(talloced);
2700 continue;
2703 if(!mask_match(dname, fname_mask,
2704 conn->case_sensitive)) {
2705 TALLOC_FREE(frame);
2706 TALLOC_FREE(talloced);
2707 continue;
2710 TALLOC_FREE(smb_fname->base_name);
2711 if (ISDOT(fname_dir)) {
2712 /* Ensure we use canonical names on open. */
2713 smb_fname->base_name =
2714 talloc_asprintf(smb_fname, "%s",
2715 dname);
2716 } else {
2717 smb_fname->base_name =
2718 talloc_asprintf(smb_fname, "%s/%s",
2719 fname_dir, dname);
2722 if (!smb_fname->base_name) {
2723 TALLOC_FREE(dir_hnd);
2724 status = NT_STATUS_NO_MEMORY;
2725 TALLOC_FREE(frame);
2726 TALLOC_FREE(talloced);
2727 goto out;
2730 status = check_name(conn, smb_fname->base_name);
2731 if (!NT_STATUS_IS_OK(status)) {
2732 TALLOC_FREE(dir_hnd);
2733 TALLOC_FREE(frame);
2734 TALLOC_FREE(talloced);
2735 goto out;
2738 status = do_unlink(conn, req, smb_fname, dirtype);
2739 if (!NT_STATUS_IS_OK(status)) {
2740 TALLOC_FREE(frame);
2741 TALLOC_FREE(talloced);
2742 continue;
2745 count++;
2746 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2747 smb_fname->base_name));
2749 TALLOC_FREE(frame);
2750 TALLOC_FREE(talloced);
2752 TALLOC_FREE(dir_hnd);
2755 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2756 status = map_nt_error_from_unix(errno);
2759 out:
2760 TALLOC_FREE(fname_dir);
2761 TALLOC_FREE(fname_mask);
2762 return status;
2765 /****************************************************************************
2766 Reply to a unlink
2767 ****************************************************************************/
2769 void reply_unlink(struct smb_request *req)
2771 connection_struct *conn = req->conn;
2772 char *name = NULL;
2773 struct smb_filename *smb_fname = NULL;
2774 uint32 dirtype;
2775 NTSTATUS status;
2776 bool path_contains_wcard = False;
2777 TALLOC_CTX *ctx = talloc_tos();
2779 START_PROFILE(SMBunlink);
2781 if (req->wct < 1) {
2782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2783 goto out;
2786 dirtype = SVAL(req->vwv+0, 0);
2788 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2789 STR_TERMINATE, &status,
2790 &path_contains_wcard);
2791 if (!NT_STATUS_IS_OK(status)) {
2792 reply_nterror(req, status);
2793 goto out;
2796 status = filename_convert(ctx, conn,
2797 req->flags2 & FLAGS2_DFS_PATHNAMES,
2798 name,
2799 UCF_COND_ALLOW_WCARD_LCOMP,
2800 &path_contains_wcard,
2801 &smb_fname);
2802 if (!NT_STATUS_IS_OK(status)) {
2803 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2804 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2805 ERRSRV, ERRbadpath);
2806 goto out;
2808 reply_nterror(req, status);
2809 goto out;
2812 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2814 status = unlink_internals(conn, req, dirtype, smb_fname,
2815 path_contains_wcard);
2816 if (!NT_STATUS_IS_OK(status)) {
2817 if (open_was_deferred(req->mid)) {
2818 /* We have re-scheduled this call. */
2819 goto out;
2821 reply_nterror(req, status);
2822 goto out;
2825 reply_outbuf(req, 0, 0);
2826 out:
2827 TALLOC_FREE(smb_fname);
2828 END_PROFILE(SMBunlink);
2829 return;
2832 /****************************************************************************
2833 Fail for readbraw.
2834 ****************************************************************************/
2836 static void fail_readraw(void)
2838 const char *errstr = talloc_asprintf(talloc_tos(),
2839 "FAIL ! reply_readbraw: socket write fail (%s)",
2840 strerror(errno));
2841 if (!errstr) {
2842 errstr = "";
2844 exit_server_cleanly(errstr);
2847 /****************************************************************************
2848 Fake (read/write) sendfile. Returns -1 on read or write fail.
2849 ****************************************************************************/
2851 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2853 size_t bufsize;
2854 size_t tosend = nread;
2855 char *buf;
2857 if (nread == 0) {
2858 return 0;
2861 bufsize = MIN(nread, 65536);
2863 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2864 return -1;
2867 while (tosend > 0) {
2868 ssize_t ret;
2869 size_t cur_read;
2871 if (tosend > bufsize) {
2872 cur_read = bufsize;
2873 } else {
2874 cur_read = tosend;
2876 ret = read_file(fsp,buf,startpos,cur_read);
2877 if (ret == -1) {
2878 SAFE_FREE(buf);
2879 return -1;
2882 /* If we had a short read, fill with zeros. */
2883 if (ret < cur_read) {
2884 memset(buf + ret, '\0', cur_read - ret);
2887 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2888 != cur_read) {
2889 char addr[INET6_ADDRSTRLEN];
2891 * Try and give an error message saying what
2892 * client failed.
2894 DEBUG(0, ("write_data failed for client %s. "
2895 "Error %s\n",
2896 get_peer_addr(fsp->conn->sconn->sock, addr,
2897 sizeof(addr)),
2898 strerror(errno)));
2899 SAFE_FREE(buf);
2900 return -1;
2902 tosend -= cur_read;
2903 startpos += cur_read;
2906 SAFE_FREE(buf);
2907 return (ssize_t)nread;
2910 /****************************************************************************
2911 Deal with the case of sendfile reading less bytes from the file than
2912 requested. Fill with zeros (all we can do).
2913 ****************************************************************************/
2915 void sendfile_short_send(files_struct *fsp,
2916 ssize_t nread,
2917 size_t headersize,
2918 size_t smb_maxcnt)
2920 #define SHORT_SEND_BUFSIZE 1024
2921 if (nread < headersize) {
2922 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2923 "header for file %s (%s). Terminating\n",
2924 fsp_str_dbg(fsp), strerror(errno)));
2925 exit_server_cleanly("sendfile_short_send failed");
2928 nread -= headersize;
2930 if (nread < smb_maxcnt) {
2931 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2932 if (!buf) {
2933 exit_server_cleanly("sendfile_short_send: "
2934 "malloc failed");
2937 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2938 "with zeros !\n", fsp_str_dbg(fsp)));
2940 while (nread < smb_maxcnt) {
2942 * We asked for the real file size and told sendfile
2943 * to not go beyond the end of the file. But it can
2944 * happen that in between our fstat call and the
2945 * sendfile call the file was truncated. This is very
2946 * bad because we have already announced the larger
2947 * number of bytes to the client.
2949 * The best we can do now is to send 0-bytes, just as
2950 * a read from a hole in a sparse file would do.
2952 * This should happen rarely enough that I don't care
2953 * about efficiency here :-)
2955 size_t to_write;
2957 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2958 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2959 != to_write) {
2960 char addr[INET6_ADDRSTRLEN];
2962 * Try and give an error message saying what
2963 * client failed.
2965 DEBUG(0, ("write_data failed for client %s. "
2966 "Error %s\n",
2967 get_peer_addr(
2968 fsp->conn->sconn->sock, addr,
2969 sizeof(addr)),
2970 strerror(errno)));
2971 exit_server_cleanly("sendfile_short_send: "
2972 "write_data failed");
2974 nread += to_write;
2976 SAFE_FREE(buf);
2980 /****************************************************************************
2981 Return a readbraw error (4 bytes of zero).
2982 ****************************************************************************/
2984 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2986 char header[4];
2988 SIVAL(header,0,0);
2990 smbd_lock_socket(sconn);
2991 if (write_data(sconn->sock,header,4) != 4) {
2992 char addr[INET6_ADDRSTRLEN];
2994 * Try and give an error message saying what
2995 * client failed.
2997 DEBUG(0, ("write_data failed for client %s. "
2998 "Error %s\n",
2999 get_peer_addr(sconn->sock, addr, sizeof(addr)),
3000 strerror(errno)));
3002 fail_readraw();
3004 smbd_unlock_socket(sconn);
3007 /****************************************************************************
3008 Use sendfile in readbraw.
3009 ****************************************************************************/
3011 static void send_file_readbraw(connection_struct *conn,
3012 struct smb_request *req,
3013 files_struct *fsp,
3014 SMB_OFF_T startpos,
3015 size_t nread,
3016 ssize_t mincount)
3018 struct smbd_server_connection *sconn = req->sconn;
3019 char *outbuf = NULL;
3020 ssize_t ret=0;
3023 * We can only use sendfile on a non-chained packet
3024 * but we can use on a non-oplocked file. tridge proved this
3025 * on a train in Germany :-). JRA.
3026 * reply_readbraw has already checked the length.
3029 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3030 (fsp->wcp == NULL) &&
3031 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3032 ssize_t sendfile_read = -1;
3033 char header[4];
3034 DATA_BLOB header_blob;
3036 _smb_setlen(header,nread);
3037 header_blob = data_blob_const(header, 4);
3039 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3040 &header_blob, startpos,
3041 nread);
3042 if (sendfile_read == -1) {
3043 /* Returning ENOSYS means no data at all was sent.
3044 * Do this as a normal read. */
3045 if (errno == ENOSYS) {
3046 goto normal_readbraw;
3050 * Special hack for broken Linux with no working sendfile. If we
3051 * return EINTR we sent the header but not the rest of the data.
3052 * Fake this up by doing read/write calls.
3054 if (errno == EINTR) {
3055 /* Ensure we don't do this again. */
3056 set_use_sendfile(SNUM(conn), False);
3057 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3059 if (fake_sendfile(fsp, startpos, nread) == -1) {
3060 DEBUG(0,("send_file_readbraw: "
3061 "fake_sendfile failed for "
3062 "file %s (%s).\n",
3063 fsp_str_dbg(fsp),
3064 strerror(errno)));
3065 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3067 return;
3070 DEBUG(0,("send_file_readbraw: sendfile failed for "
3071 "file %s (%s). Terminating\n",
3072 fsp_str_dbg(fsp), strerror(errno)));
3073 exit_server_cleanly("send_file_readbraw sendfile failed");
3074 } else if (sendfile_read == 0) {
3076 * Some sendfile implementations return 0 to indicate
3077 * that there was a short read, but nothing was
3078 * actually written to the socket. In this case,
3079 * fallback to the normal read path so the header gets
3080 * the correct byte count.
3082 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3083 "bytes falling back to the normal read: "
3084 "%s\n", fsp_str_dbg(fsp)));
3085 goto normal_readbraw;
3088 /* Deal with possible short send. */
3089 if (sendfile_read != 4+nread) {
3090 sendfile_short_send(fsp, sendfile_read, 4, nread);
3092 return;
3095 normal_readbraw:
3097 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3098 if (!outbuf) {
3099 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3100 (unsigned)(nread+4)));
3101 reply_readbraw_error(sconn);
3102 return;
3105 if (nread > 0) {
3106 ret = read_file(fsp,outbuf+4,startpos,nread);
3107 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3108 if (ret < mincount)
3109 ret = 0;
3110 #else
3111 if (ret < nread)
3112 ret = 0;
3113 #endif
3116 _smb_setlen(outbuf,ret);
3117 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3118 char addr[INET6_ADDRSTRLEN];
3120 * Try and give an error message saying what
3121 * client failed.
3123 DEBUG(0, ("write_data failed for client %s. "
3124 "Error %s\n",
3125 get_peer_addr(fsp->conn->sconn->sock, addr,
3126 sizeof(addr)),
3127 strerror(errno)));
3129 fail_readraw();
3132 TALLOC_FREE(outbuf);
3135 /****************************************************************************
3136 Reply to a readbraw (core+ protocol).
3137 ****************************************************************************/
3139 void reply_readbraw(struct smb_request *req)
3141 connection_struct *conn = req->conn;
3142 struct smbd_server_connection *sconn = req->sconn;
3143 ssize_t maxcount,mincount;
3144 size_t nread = 0;
3145 SMB_OFF_T startpos;
3146 files_struct *fsp;
3147 struct lock_struct lock;
3148 SMB_OFF_T size = 0;
3150 START_PROFILE(SMBreadbraw);
3152 if (srv_is_signing_active(sconn) ||
3153 is_encrypted_packet(req->inbuf)) {
3154 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3155 "raw reads/writes are disallowed.");
3158 if (req->wct < 8) {
3159 reply_readbraw_error(sconn);
3160 END_PROFILE(SMBreadbraw);
3161 return;
3164 if (sconn->smb1.echo_handler.trusted_fde) {
3165 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3166 "'async smb echo handler = yes'\n"));
3167 reply_readbraw_error(sconn);
3168 END_PROFILE(SMBreadbraw);
3169 return;
3173 * Special check if an oplock break has been issued
3174 * and the readraw request croses on the wire, we must
3175 * return a zero length response here.
3178 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3181 * We have to do a check_fsp by hand here, as
3182 * we must always return 4 zero bytes on error,
3183 * not a NTSTATUS.
3186 if (!fsp || !conn || conn != fsp->conn ||
3187 req->vuid != fsp->vuid ||
3188 fsp->is_directory || fsp->fh->fd == -1) {
3190 * fsp could be NULL here so use the value from the packet. JRA.
3192 DEBUG(3,("reply_readbraw: fnum %d not valid "
3193 "- cache prime?\n",
3194 (int)SVAL(req->vwv+0, 0)));
3195 reply_readbraw_error(sconn);
3196 END_PROFILE(SMBreadbraw);
3197 return;
3200 /* Do a "by hand" version of CHECK_READ. */
3201 if (!(fsp->can_read ||
3202 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3203 (fsp->access_mask & FILE_EXECUTE)))) {
3204 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3205 (int)SVAL(req->vwv+0, 0)));
3206 reply_readbraw_error(sconn);
3207 END_PROFILE(SMBreadbraw);
3208 return;
3211 flush_write_cache(fsp, READRAW_FLUSH);
3213 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3214 if(req->wct == 10) {
3216 * This is a large offset (64 bit) read.
3218 #ifdef LARGE_SMB_OFF_T
3220 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3222 #else /* !LARGE_SMB_OFF_T */
3225 * Ensure we haven't been sent a >32 bit offset.
3228 if(IVAL(req->vwv+8, 0) != 0) {
3229 DEBUG(0,("reply_readbraw: large offset "
3230 "(%x << 32) used and we don't support "
3231 "64 bit offsets.\n",
3232 (unsigned int)IVAL(req->vwv+8, 0) ));
3233 reply_readbraw_error(sconn);
3234 END_PROFILE(SMBreadbraw);
3235 return;
3238 #endif /* LARGE_SMB_OFF_T */
3240 if(startpos < 0) {
3241 DEBUG(0,("reply_readbraw: negative 64 bit "
3242 "readraw offset (%.0f) !\n",
3243 (double)startpos ));
3244 reply_readbraw_error(sconn);
3245 END_PROFILE(SMBreadbraw);
3246 return;
3250 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3251 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3253 /* ensure we don't overrun the packet size */
3254 maxcount = MIN(65535,maxcount);
3256 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3257 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3258 &lock);
3260 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3261 reply_readbraw_error(sconn);
3262 END_PROFILE(SMBreadbraw);
3263 return;
3266 if (fsp_stat(fsp) == 0) {
3267 size = fsp->fsp_name->st.st_ex_size;
3270 if (startpos >= size) {
3271 nread = 0;
3272 } else {
3273 nread = MIN(maxcount,(size - startpos));
3276 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3277 if (nread < mincount)
3278 nread = 0;
3279 #endif
3281 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3282 "min=%lu nread=%lu\n",
3283 fsp->fnum, (double)startpos,
3284 (unsigned long)maxcount,
3285 (unsigned long)mincount,
3286 (unsigned long)nread ) );
3288 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3290 DEBUG(5,("reply_readbraw finished\n"));
3292 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3294 END_PROFILE(SMBreadbraw);
3295 return;
3298 #undef DBGC_CLASS
3299 #define DBGC_CLASS DBGC_LOCKING
3301 /****************************************************************************
3302 Reply to a lockread (core+ protocol).
3303 ****************************************************************************/
3305 void reply_lockread(struct smb_request *req)
3307 connection_struct *conn = req->conn;
3308 ssize_t nread = -1;
3309 char *data;
3310 SMB_OFF_T startpos;
3311 size_t numtoread;
3312 NTSTATUS status;
3313 files_struct *fsp;
3314 struct byte_range_lock *br_lck = NULL;
3315 char *p = NULL;
3316 struct smbd_server_connection *sconn = req->sconn;
3318 START_PROFILE(SMBlockread);
3320 if (req->wct < 5) {
3321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3322 END_PROFILE(SMBlockread);
3323 return;
3326 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3328 if (!check_fsp(conn, req, fsp)) {
3329 END_PROFILE(SMBlockread);
3330 return;
3333 if (!CHECK_READ(fsp,req)) {
3334 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3335 END_PROFILE(SMBlockread);
3336 return;
3339 numtoread = SVAL(req->vwv+1, 0);
3340 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3342 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3344 reply_outbuf(req, 5, numtoread + 3);
3346 data = smb_buf(req->outbuf) + 3;
3349 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3350 * protocol request that predates the read/write lock concept.
3351 * Thus instead of asking for a read lock here we need to ask
3352 * for a write lock. JRA.
3353 * Note that the requested lock size is unaffected by max_recv.
3356 br_lck = do_lock(req->sconn->msg_ctx,
3357 fsp,
3358 (uint64_t)req->smbpid,
3359 (uint64_t)numtoread,
3360 (uint64_t)startpos,
3361 WRITE_LOCK,
3362 WINDOWS_LOCK,
3363 False, /* Non-blocking lock. */
3364 &status,
3365 NULL,
3366 NULL);
3367 TALLOC_FREE(br_lck);
3369 if (NT_STATUS_V(status)) {
3370 reply_nterror(req, status);
3371 END_PROFILE(SMBlockread);
3372 return;
3376 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3379 if (numtoread > sconn->smb1.negprot.max_recv) {
3380 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3381 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3382 (unsigned int)numtoread,
3383 (unsigned int)sconn->smb1.negprot.max_recv));
3384 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3386 nread = read_file(fsp,data,startpos,numtoread);
3388 if (nread < 0) {
3389 reply_nterror(req, map_nt_error_from_unix(errno));
3390 END_PROFILE(SMBlockread);
3391 return;
3394 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3396 SSVAL(req->outbuf,smb_vwv0,nread);
3397 SSVAL(req->outbuf,smb_vwv5,nread+3);
3398 p = smb_buf(req->outbuf);
3399 SCVAL(p,0,0); /* pad byte. */
3400 SSVAL(p,1,nread);
3402 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3403 fsp->fnum, (int)numtoread, (int)nread));
3405 END_PROFILE(SMBlockread);
3406 return;
3409 #undef DBGC_CLASS
3410 #define DBGC_CLASS DBGC_ALL
3412 /****************************************************************************
3413 Reply to a read.
3414 ****************************************************************************/
3416 void reply_read(struct smb_request *req)
3418 connection_struct *conn = req->conn;
3419 size_t numtoread;
3420 ssize_t nread = 0;
3421 char *data;
3422 SMB_OFF_T startpos;
3423 int outsize = 0;
3424 files_struct *fsp;
3425 struct lock_struct lock;
3426 struct smbd_server_connection *sconn = req->sconn;
3428 START_PROFILE(SMBread);
3430 if (req->wct < 3) {
3431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3432 END_PROFILE(SMBread);
3433 return;
3436 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3438 if (!check_fsp(conn, req, fsp)) {
3439 END_PROFILE(SMBread);
3440 return;
3443 if (!CHECK_READ(fsp,req)) {
3444 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3445 END_PROFILE(SMBread);
3446 return;
3449 numtoread = SVAL(req->vwv+1, 0);
3450 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3452 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3455 * The requested read size cannot be greater than max_recv. JRA.
3457 if (numtoread > sconn->smb1.negprot.max_recv) {
3458 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3459 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3460 (unsigned int)numtoread,
3461 (unsigned int)sconn->smb1.negprot.max_recv));
3462 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3465 reply_outbuf(req, 5, numtoread+3);
3467 data = smb_buf(req->outbuf) + 3;
3469 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3470 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3471 &lock);
3473 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3474 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3475 END_PROFILE(SMBread);
3476 return;
3479 if (numtoread > 0)
3480 nread = read_file(fsp,data,startpos,numtoread);
3482 if (nread < 0) {
3483 reply_nterror(req, map_nt_error_from_unix(errno));
3484 goto strict_unlock;
3487 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3489 SSVAL(req->outbuf,smb_vwv0,nread);
3490 SSVAL(req->outbuf,smb_vwv5,nread+3);
3491 SCVAL(smb_buf(req->outbuf),0,1);
3492 SSVAL(smb_buf(req->outbuf),1,nread);
3494 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3495 fsp->fnum, (int)numtoread, (int)nread ) );
3497 strict_unlock:
3498 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3500 END_PROFILE(SMBread);
3501 return;
3504 /****************************************************************************
3505 Setup readX header.
3506 ****************************************************************************/
3508 static int setup_readX_header(struct smb_request *req, char *outbuf,
3509 size_t smb_maxcnt)
3511 int outsize;
3512 char *data;
3514 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3515 data = smb_buf(outbuf);
3517 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3519 SCVAL(outbuf,smb_vwv0,0xFF);
3520 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3521 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3522 SSVAL(outbuf,smb_vwv6,
3523 req_wct_ofs(req)
3524 + 1 /* the wct field */
3525 + 12 * sizeof(uint16_t) /* vwv */
3526 + 2); /* the buflen field */
3527 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3528 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3529 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3530 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3531 return outsize;
3534 /****************************************************************************
3535 Reply to a read and X - possibly using sendfile.
3536 ****************************************************************************/
3538 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3539 files_struct *fsp, SMB_OFF_T startpos,
3540 size_t smb_maxcnt)
3542 ssize_t nread = -1;
3543 struct lock_struct lock;
3544 int saved_errno = 0;
3546 if(fsp_stat(fsp) == -1) {
3547 reply_nterror(req, map_nt_error_from_unix(errno));
3548 return;
3551 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3552 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3553 &lock);
3555 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3556 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3557 return;
3560 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3561 (startpos > fsp->fsp_name->st.st_ex_size)
3562 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3564 * We already know that we would do a short read, so don't
3565 * try the sendfile() path.
3567 goto nosendfile_read;
3571 * We can only use sendfile on a non-chained packet
3572 * but we can use on a non-oplocked file. tridge proved this
3573 * on a train in Germany :-). JRA.
3576 if (!req_is_in_chain(req) &&
3577 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3578 (fsp->wcp == NULL) &&
3579 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3580 uint8 headerbuf[smb_size + 12 * 2];
3581 DATA_BLOB header;
3584 * Set up the packet header before send. We
3585 * assume here the sendfile will work (get the
3586 * correct amount of data).
3589 header = data_blob_const(headerbuf, sizeof(headerbuf));
3591 construct_reply_common_req(req, (char *)headerbuf);
3592 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3594 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3595 startpos, smb_maxcnt);
3596 if (nread == -1) {
3597 /* Returning ENOSYS means no data at all was sent.
3598 Do this as a normal read. */
3599 if (errno == ENOSYS) {
3600 goto normal_read;
3604 * Special hack for broken Linux with no working sendfile. If we
3605 * return EINTR we sent the header but not the rest of the data.
3606 * Fake this up by doing read/write calls.
3609 if (errno == EINTR) {
3610 /* Ensure we don't do this again. */
3611 set_use_sendfile(SNUM(conn), False);
3612 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3613 nread = fake_sendfile(fsp, startpos,
3614 smb_maxcnt);
3615 if (nread == -1) {
3616 DEBUG(0,("send_file_readX: "
3617 "fake_sendfile failed for "
3618 "file %s (%s).\n",
3619 fsp_str_dbg(fsp),
3620 strerror(errno)));
3621 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3623 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3624 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3625 /* No outbuf here means successful sendfile. */
3626 goto strict_unlock;
3629 DEBUG(0,("send_file_readX: sendfile failed for file "
3630 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3631 strerror(errno)));
3632 exit_server_cleanly("send_file_readX sendfile failed");
3633 } else if (nread == 0) {
3635 * Some sendfile implementations return 0 to indicate
3636 * that there was a short read, but nothing was
3637 * actually written to the socket. In this case,
3638 * fallback to the normal read path so the header gets
3639 * the correct byte count.
3641 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3642 "falling back to the normal read: %s\n",
3643 fsp_str_dbg(fsp)));
3644 goto normal_read;
3647 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3648 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3650 /* Deal with possible short send. */
3651 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3652 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3654 /* No outbuf here means successful sendfile. */
3655 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3656 SMB_PERFCOUNT_END(&req->pcd);
3657 goto strict_unlock;
3660 normal_read:
3662 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3663 uint8 headerbuf[smb_size + 2*12];
3665 construct_reply_common_req(req, (char *)headerbuf);
3666 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3668 /* Send out the header. */
3669 if (write_data(req->sconn->sock, (char *)headerbuf,
3670 sizeof(headerbuf)) != sizeof(headerbuf)) {
3672 char addr[INET6_ADDRSTRLEN];
3674 * Try and give an error message saying what
3675 * client failed.
3677 DEBUG(0, ("write_data failed for client %s. "
3678 "Error %s\n",
3679 get_peer_addr(req->sconn->sock, addr,
3680 sizeof(addr)),
3681 strerror(errno)));
3683 DEBUG(0,("send_file_readX: write_data failed for file "
3684 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3685 strerror(errno)));
3686 exit_server_cleanly("send_file_readX sendfile failed");
3688 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3689 if (nread == -1) {
3690 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3691 "file %s (%s).\n", fsp_str_dbg(fsp),
3692 strerror(errno)));
3693 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3695 goto strict_unlock;
3698 nosendfile_read:
3700 reply_outbuf(req, 12, smb_maxcnt);
3702 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3703 saved_errno = errno;
3705 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3707 if (nread < 0) {
3708 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3709 return;
3712 setup_readX_header(req, (char *)req->outbuf, nread);
3714 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3715 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3717 chain_reply(req);
3718 return;
3720 strict_unlock:
3721 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3722 TALLOC_FREE(req->outbuf);
3723 return;
3726 /****************************************************************************
3727 Reply to a read and X.
3728 ****************************************************************************/
3730 void reply_read_and_X(struct smb_request *req)
3732 connection_struct *conn = req->conn;
3733 files_struct *fsp;
3734 SMB_OFF_T startpos;
3735 size_t smb_maxcnt;
3736 bool big_readX = False;
3737 #if 0
3738 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3739 #endif
3741 START_PROFILE(SMBreadX);
3743 if ((req->wct != 10) && (req->wct != 12)) {
3744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3745 return;
3748 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3749 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3750 smb_maxcnt = SVAL(req->vwv+5, 0);
3752 /* If it's an IPC, pass off the pipe handler. */
3753 if (IS_IPC(conn)) {
3754 reply_pipe_read_and_X(req);
3755 END_PROFILE(SMBreadX);
3756 return;
3759 if (!check_fsp(conn, req, fsp)) {
3760 END_PROFILE(SMBreadX);
3761 return;
3764 if (!CHECK_READ(fsp,req)) {
3765 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3766 END_PROFILE(SMBreadX);
3767 return;
3770 if (global_client_caps & CAP_LARGE_READX) {
3771 size_t upper_size = SVAL(req->vwv+7, 0);
3772 smb_maxcnt |= (upper_size<<16);
3773 if (upper_size > 1) {
3774 /* Can't do this on a chained packet. */
3775 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3776 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3777 END_PROFILE(SMBreadX);
3778 return;
3780 /* We currently don't do this on signed or sealed data. */
3781 if (srv_is_signing_active(req->sconn) ||
3782 is_encrypted_packet(req->inbuf)) {
3783 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3784 END_PROFILE(SMBreadX);
3785 return;
3787 /* Is there room in the reply for this data ? */
3788 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3789 reply_nterror(req,
3790 NT_STATUS_INVALID_PARAMETER);
3791 END_PROFILE(SMBreadX);
3792 return;
3794 big_readX = True;
3798 if (req->wct == 12) {
3799 #ifdef LARGE_SMB_OFF_T
3801 * This is a large offset (64 bit) read.
3803 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3805 #else /* !LARGE_SMB_OFF_T */
3808 * Ensure we haven't been sent a >32 bit offset.
3811 if(IVAL(req->vwv+10, 0) != 0) {
3812 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3813 "used and we don't support 64 bit offsets.\n",
3814 (unsigned int)IVAL(req->vwv+10, 0) ));
3815 END_PROFILE(SMBreadX);
3816 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3817 return;
3820 #endif /* LARGE_SMB_OFF_T */
3824 if (!big_readX) {
3825 NTSTATUS status = schedule_aio_read_and_X(conn,
3826 req,
3827 fsp,
3828 startpos,
3829 smb_maxcnt);
3830 if (NT_STATUS_IS_OK(status)) {
3831 /* Read scheduled - we're done. */
3832 goto out;
3834 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3835 /* Real error - report to client. */
3836 END_PROFILE(SMBreadX);
3837 reply_nterror(req, status);
3838 return;
3840 /* NT_STATUS_RETRY - fall back to sync read. */
3843 smbd_lock_socket(req->sconn);
3844 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3845 smbd_unlock_socket(req->sconn);
3847 out:
3848 END_PROFILE(SMBreadX);
3849 return;
3852 /****************************************************************************
3853 Error replies to writebraw must have smb_wct == 1. Fix this up.
3854 ****************************************************************************/
3856 void error_to_writebrawerr(struct smb_request *req)
3858 uint8 *old_outbuf = req->outbuf;
3860 reply_outbuf(req, 1, 0);
3862 memcpy(req->outbuf, old_outbuf, smb_size);
3863 TALLOC_FREE(old_outbuf);
3866 /****************************************************************************
3867 Read 4 bytes of a smb packet and return the smb length of the packet.
3868 Store the result in the buffer. This version of the function will
3869 never return a session keepalive (length of zero).
3870 Timeout is in milliseconds.
3871 ****************************************************************************/
3873 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3874 size_t *len)
3876 uint8_t msgtype = SMBkeepalive;
3878 while (msgtype == SMBkeepalive) {
3879 NTSTATUS status;
3881 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3882 len);
3883 if (!NT_STATUS_IS_OK(status)) {
3884 char addr[INET6_ADDRSTRLEN];
3885 /* Try and give an error message
3886 * saying what client failed. */
3887 DEBUG(0, ("read_fd_with_timeout failed for "
3888 "client %s read error = %s.\n",
3889 get_peer_addr(fd,addr,sizeof(addr)),
3890 nt_errstr(status)));
3891 return status;
3894 msgtype = CVAL(inbuf, 0);
3897 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3898 (unsigned long)len));
3900 return NT_STATUS_OK;
3903 /****************************************************************************
3904 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3905 ****************************************************************************/
3907 void reply_writebraw(struct smb_request *req)
3909 connection_struct *conn = req->conn;
3910 char *buf = NULL;
3911 ssize_t nwritten=0;
3912 ssize_t total_written=0;
3913 size_t numtowrite=0;
3914 size_t tcount;
3915 SMB_OFF_T startpos;
3916 const char *data=NULL;
3917 bool write_through;
3918 files_struct *fsp;
3919 struct lock_struct lock;
3920 NTSTATUS status;
3922 START_PROFILE(SMBwritebraw);
3925 * If we ever reply with an error, it must have the SMB command
3926 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3927 * we're finished.
3929 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3931 if (srv_is_signing_active(req->sconn)) {
3932 END_PROFILE(SMBwritebraw);
3933 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3934 "raw reads/writes are disallowed.");
3937 if (req->wct < 12) {
3938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3939 error_to_writebrawerr(req);
3940 END_PROFILE(SMBwritebraw);
3941 return;
3944 if (req->sconn->smb1.echo_handler.trusted_fde) {
3945 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3946 "'async smb echo handler = yes'\n"));
3947 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3948 error_to_writebrawerr(req);
3949 END_PROFILE(SMBwritebraw);
3950 return;
3953 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3954 if (!check_fsp(conn, req, fsp)) {
3955 error_to_writebrawerr(req);
3956 END_PROFILE(SMBwritebraw);
3957 return;
3960 if (!CHECK_WRITE(fsp)) {
3961 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3962 error_to_writebrawerr(req);
3963 END_PROFILE(SMBwritebraw);
3964 return;
3967 tcount = IVAL(req->vwv+1, 0);
3968 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3969 write_through = BITSETW(req->vwv+7,0);
3971 /* We have to deal with slightly different formats depending
3972 on whether we are using the core+ or lanman1.0 protocol */
3974 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3975 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3976 data = smb_buf_const(req->inbuf);
3977 } else {
3978 numtowrite = SVAL(req->vwv+10, 0);
3979 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3982 /* Ensure we don't write bytes past the end of this packet. */
3983 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3985 error_to_writebrawerr(req);
3986 END_PROFILE(SMBwritebraw);
3987 return;
3990 if (!fsp->print_file) {
3991 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3992 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3993 &lock);
3995 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3996 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3997 error_to_writebrawerr(req);
3998 END_PROFILE(SMBwritebraw);
3999 return;
4003 if (numtowrite>0) {
4004 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4007 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4008 "wrote=%d sync=%d\n",
4009 fsp->fnum, (double)startpos, (int)numtowrite,
4010 (int)nwritten, (int)write_through));
4012 if (nwritten < (ssize_t)numtowrite) {
4013 reply_nterror(req, NT_STATUS_DISK_FULL);
4014 error_to_writebrawerr(req);
4015 goto strict_unlock;
4018 total_written = nwritten;
4020 /* Allocate a buffer of 64k + length. */
4021 buf = TALLOC_ARRAY(NULL, char, 65540);
4022 if (!buf) {
4023 reply_nterror(req, NT_STATUS_NO_MEMORY);
4024 error_to_writebrawerr(req);
4025 goto strict_unlock;
4028 /* Return a SMBwritebraw message to the redirector to tell
4029 * it to send more bytes */
4031 memcpy(buf, req->inbuf, smb_size);
4032 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4033 SCVAL(buf,smb_com,SMBwritebraw);
4034 SSVALS(buf,smb_vwv0,0xFFFF);
4035 show_msg(buf);
4036 if (!srv_send_smb(req->sconn,
4037 buf,
4038 false, 0, /* no signing */
4039 IS_CONN_ENCRYPTED(conn),
4040 &req->pcd)) {
4041 exit_server_cleanly("reply_writebraw: srv_send_smb "
4042 "failed.");
4045 /* Now read the raw data into the buffer and write it */
4046 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4047 &numtowrite);
4048 if (!NT_STATUS_IS_OK(status)) {
4049 exit_server_cleanly("secondary writebraw failed");
4052 /* Set up outbuf to return the correct size */
4053 reply_outbuf(req, 1, 0);
4055 if (numtowrite != 0) {
4057 if (numtowrite > 0xFFFF) {
4058 DEBUG(0,("reply_writebraw: Oversize secondary write "
4059 "raw requested (%u). Terminating\n",
4060 (unsigned int)numtowrite ));
4061 exit_server_cleanly("secondary writebraw failed");
4064 if (tcount > nwritten+numtowrite) {
4065 DEBUG(3,("reply_writebraw: Client overestimated the "
4066 "write %d %d %d\n",
4067 (int)tcount,(int)nwritten,(int)numtowrite));
4070 status = read_data(req->sconn->sock, buf+4, numtowrite);
4072 if (!NT_STATUS_IS_OK(status)) {
4073 char addr[INET6_ADDRSTRLEN];
4074 /* Try and give an error message
4075 * saying what client failed. */
4076 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4077 "raw read failed (%s) for client %s. "
4078 "Terminating\n", nt_errstr(status),
4079 get_peer_addr(req->sconn->sock, addr,
4080 sizeof(addr))));
4081 exit_server_cleanly("secondary writebraw failed");
4084 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4085 if (nwritten == -1) {
4086 TALLOC_FREE(buf);
4087 reply_nterror(req, map_nt_error_from_unix(errno));
4088 error_to_writebrawerr(req);
4089 goto strict_unlock;
4092 if (nwritten < (ssize_t)numtowrite) {
4093 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4094 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4097 if (nwritten > 0) {
4098 total_written += nwritten;
4102 TALLOC_FREE(buf);
4103 SSVAL(req->outbuf,smb_vwv0,total_written);
4105 status = sync_file(conn, fsp, write_through);
4106 if (!NT_STATUS_IS_OK(status)) {
4107 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4108 fsp_str_dbg(fsp), nt_errstr(status)));
4109 reply_nterror(req, status);
4110 error_to_writebrawerr(req);
4111 goto strict_unlock;
4114 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4115 "wrote=%d\n",
4116 fsp->fnum, (double)startpos, (int)numtowrite,
4117 (int)total_written));
4119 if (!fsp->print_file) {
4120 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4123 /* We won't return a status if write through is not selected - this
4124 * follows what WfWg does */
4125 END_PROFILE(SMBwritebraw);
4127 if (!write_through && total_written==tcount) {
4129 #if RABBIT_PELLET_FIX
4131 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4132 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4133 * JRA.
4135 if (!send_keepalive(req->sconn->sock)) {
4136 exit_server_cleanly("reply_writebraw: send of "
4137 "keepalive failed");
4139 #endif
4140 TALLOC_FREE(req->outbuf);
4142 return;
4144 strict_unlock:
4145 if (!fsp->print_file) {
4146 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4149 END_PROFILE(SMBwritebraw);
4150 return;
4153 #undef DBGC_CLASS
4154 #define DBGC_CLASS DBGC_LOCKING
4156 /****************************************************************************
4157 Reply to a writeunlock (core+).
4158 ****************************************************************************/
4160 void reply_writeunlock(struct smb_request *req)
4162 connection_struct *conn = req->conn;
4163 ssize_t nwritten = -1;
4164 size_t numtowrite;
4165 SMB_OFF_T startpos;
4166 const char *data;
4167 NTSTATUS status = NT_STATUS_OK;
4168 files_struct *fsp;
4169 struct lock_struct lock;
4170 int saved_errno = 0;
4172 START_PROFILE(SMBwriteunlock);
4174 if (req->wct < 5) {
4175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4176 END_PROFILE(SMBwriteunlock);
4177 return;
4180 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4182 if (!check_fsp(conn, req, fsp)) {
4183 END_PROFILE(SMBwriteunlock);
4184 return;
4187 if (!CHECK_WRITE(fsp)) {
4188 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4189 END_PROFILE(SMBwriteunlock);
4190 return;
4193 numtowrite = SVAL(req->vwv+1, 0);
4194 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4195 data = (const char *)req->buf + 3;
4197 if (!fsp->print_file && numtowrite > 0) {
4198 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4199 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4200 &lock);
4202 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4203 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4204 END_PROFILE(SMBwriteunlock);
4205 return;
4209 /* The special X/Open SMB protocol handling of
4210 zero length writes is *NOT* done for
4211 this call */
4212 if(numtowrite == 0) {
4213 nwritten = 0;
4214 } else {
4215 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4216 saved_errno = errno;
4219 status = sync_file(conn, fsp, False /* write through */);
4220 if (!NT_STATUS_IS_OK(status)) {
4221 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4222 fsp_str_dbg(fsp), nt_errstr(status)));
4223 reply_nterror(req, status);
4224 goto strict_unlock;
4227 if(nwritten < 0) {
4228 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4229 goto strict_unlock;
4232 if((nwritten < numtowrite) && (numtowrite != 0)) {
4233 reply_nterror(req, NT_STATUS_DISK_FULL);
4234 goto strict_unlock;
4237 if (numtowrite && !fsp->print_file) {
4238 status = do_unlock(req->sconn->msg_ctx,
4239 fsp,
4240 (uint64_t)req->smbpid,
4241 (uint64_t)numtowrite,
4242 (uint64_t)startpos,
4243 WINDOWS_LOCK);
4245 if (NT_STATUS_V(status)) {
4246 reply_nterror(req, status);
4247 goto strict_unlock;
4251 reply_outbuf(req, 1, 0);
4253 SSVAL(req->outbuf,smb_vwv0,nwritten);
4255 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4256 fsp->fnum, (int)numtowrite, (int)nwritten));
4258 strict_unlock:
4259 if (numtowrite && !fsp->print_file) {
4260 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4263 END_PROFILE(SMBwriteunlock);
4264 return;
4267 #undef DBGC_CLASS
4268 #define DBGC_CLASS DBGC_ALL
4270 /****************************************************************************
4271 Reply to a write.
4272 ****************************************************************************/
4274 void reply_write(struct smb_request *req)
4276 connection_struct *conn = req->conn;
4277 size_t numtowrite;
4278 ssize_t nwritten = -1;
4279 SMB_OFF_T startpos;
4280 const char *data;
4281 files_struct *fsp;
4282 struct lock_struct lock;
4283 NTSTATUS status;
4284 int saved_errno = 0;
4286 START_PROFILE(SMBwrite);
4288 if (req->wct < 5) {
4289 END_PROFILE(SMBwrite);
4290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4291 return;
4294 /* If it's an IPC, pass off the pipe handler. */
4295 if (IS_IPC(conn)) {
4296 reply_pipe_write(req);
4297 END_PROFILE(SMBwrite);
4298 return;
4301 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4303 if (!check_fsp(conn, req, fsp)) {
4304 END_PROFILE(SMBwrite);
4305 return;
4308 if (!CHECK_WRITE(fsp)) {
4309 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4310 END_PROFILE(SMBwrite);
4311 return;
4314 numtowrite = SVAL(req->vwv+1, 0);
4315 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4316 data = (const char *)req->buf + 3;
4318 if (!fsp->print_file) {
4319 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4320 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4321 &lock);
4323 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4324 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4325 END_PROFILE(SMBwrite);
4326 return;
4331 * X/Open SMB protocol says that if smb_vwv1 is
4332 * zero then the file size should be extended or
4333 * truncated to the size given in smb_vwv[2-3].
4336 if(numtowrite == 0) {
4338 * This is actually an allocate call, and set EOF. JRA.
4340 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4341 if (nwritten < 0) {
4342 reply_nterror(req, NT_STATUS_DISK_FULL);
4343 goto strict_unlock;
4345 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4346 if (nwritten < 0) {
4347 reply_nterror(req, NT_STATUS_DISK_FULL);
4348 goto strict_unlock;
4350 trigger_write_time_update_immediate(fsp);
4351 } else {
4352 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4355 status = sync_file(conn, fsp, False);
4356 if (!NT_STATUS_IS_OK(status)) {
4357 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4358 fsp_str_dbg(fsp), nt_errstr(status)));
4359 reply_nterror(req, status);
4360 goto strict_unlock;
4363 if(nwritten < 0) {
4364 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4365 goto strict_unlock;
4368 if((nwritten == 0) && (numtowrite != 0)) {
4369 reply_nterror(req, NT_STATUS_DISK_FULL);
4370 goto strict_unlock;
4373 reply_outbuf(req, 1, 0);
4375 SSVAL(req->outbuf,smb_vwv0,nwritten);
4377 if (nwritten < (ssize_t)numtowrite) {
4378 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4379 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4382 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4384 strict_unlock:
4385 if (!fsp->print_file) {
4386 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4389 END_PROFILE(SMBwrite);
4390 return;
4393 /****************************************************************************
4394 Ensure a buffer is a valid writeX for recvfile purposes.
4395 ****************************************************************************/
4397 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4398 (2*14) + /* word count (including bcc) */ \
4399 1 /* pad byte */)
4401 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4402 const uint8_t *inbuf)
4404 size_t numtowrite;
4405 connection_struct *conn = NULL;
4406 unsigned int doff = 0;
4407 size_t len = smb_len_large(inbuf);
4409 if (is_encrypted_packet(inbuf)) {
4410 /* Can't do this on encrypted
4411 * connections. */
4412 return false;
4415 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4416 return false;
4419 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4420 CVAL(inbuf,smb_wct) != 14) {
4421 DEBUG(10,("is_valid_writeX_buffer: chained or "
4422 "invalid word length.\n"));
4423 return false;
4426 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4427 if (conn == NULL) {
4428 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4429 return false;
4431 if (IS_IPC(conn)) {
4432 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4433 return false;
4435 if (IS_PRINT(conn)) {
4436 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4437 return false;
4439 doff = SVAL(inbuf,smb_vwv11);
4441 numtowrite = SVAL(inbuf,smb_vwv10);
4443 if (len > doff && len - doff > 0xFFFF) {
4444 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4447 if (numtowrite == 0) {
4448 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4449 return false;
4452 /* Ensure the sizes match up. */
4453 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4454 /* no pad byte...old smbclient :-( */
4455 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4456 (unsigned int)doff,
4457 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4458 return false;
4461 if (len - doff != numtowrite) {
4462 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4463 "len = %u, doff = %u, numtowrite = %u\n",
4464 (unsigned int)len,
4465 (unsigned int)doff,
4466 (unsigned int)numtowrite ));
4467 return false;
4470 DEBUG(10,("is_valid_writeX_buffer: true "
4471 "len = %u, doff = %u, numtowrite = %u\n",
4472 (unsigned int)len,
4473 (unsigned int)doff,
4474 (unsigned int)numtowrite ));
4476 return true;
4479 /****************************************************************************
4480 Reply to a write and X.
4481 ****************************************************************************/
4483 void reply_write_and_X(struct smb_request *req)
4485 connection_struct *conn = req->conn;
4486 files_struct *fsp;
4487 struct lock_struct lock;
4488 SMB_OFF_T startpos;
4489 size_t numtowrite;
4490 bool write_through;
4491 ssize_t nwritten;
4492 unsigned int smb_doff;
4493 unsigned int smblen;
4494 const char *data;
4495 NTSTATUS status;
4496 int saved_errno = 0;
4498 START_PROFILE(SMBwriteX);
4500 if ((req->wct != 12) && (req->wct != 14)) {
4501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4502 END_PROFILE(SMBwriteX);
4503 return;
4506 numtowrite = SVAL(req->vwv+10, 0);
4507 smb_doff = SVAL(req->vwv+11, 0);
4508 smblen = smb_len(req->inbuf);
4510 if (req->unread_bytes > 0xFFFF ||
4511 (smblen > smb_doff &&
4512 smblen - smb_doff > 0xFFFF)) {
4513 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4516 if (req->unread_bytes) {
4517 /* Can't do a recvfile write on IPC$ */
4518 if (IS_IPC(conn)) {
4519 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4520 END_PROFILE(SMBwriteX);
4521 return;
4523 if (numtowrite != req->unread_bytes) {
4524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4525 END_PROFILE(SMBwriteX);
4526 return;
4528 } else {
4529 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4530 smb_doff + numtowrite > smblen) {
4531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4532 END_PROFILE(SMBwriteX);
4533 return;
4537 /* If it's an IPC, pass off the pipe handler. */
4538 if (IS_IPC(conn)) {
4539 if (req->unread_bytes) {
4540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4541 END_PROFILE(SMBwriteX);
4542 return;
4544 reply_pipe_write_and_X(req);
4545 END_PROFILE(SMBwriteX);
4546 return;
4549 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4550 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4551 write_through = BITSETW(req->vwv+7,0);
4553 if (!check_fsp(conn, req, fsp)) {
4554 END_PROFILE(SMBwriteX);
4555 return;
4558 if (!CHECK_WRITE(fsp)) {
4559 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4560 END_PROFILE(SMBwriteX);
4561 return;
4564 data = smb_base(req->inbuf) + smb_doff;
4566 if(req->wct == 14) {
4567 #ifdef LARGE_SMB_OFF_T
4569 * This is a large offset (64 bit) write.
4571 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4573 #else /* !LARGE_SMB_OFF_T */
4576 * Ensure we haven't been sent a >32 bit offset.
4579 if(IVAL(req->vwv+12, 0) != 0) {
4580 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4581 "used and we don't support 64 bit offsets.\n",
4582 (unsigned int)IVAL(req->vwv+12, 0) ));
4583 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4584 END_PROFILE(SMBwriteX);
4585 return;
4588 #endif /* LARGE_SMB_OFF_T */
4591 /* X/Open SMB protocol says that, unlike SMBwrite
4592 if the length is zero then NO truncation is
4593 done, just a write of zero. To truncate a file,
4594 use SMBwrite. */
4596 if(numtowrite == 0) {
4597 nwritten = 0;
4598 } else {
4599 if (req->unread_bytes == 0) {
4600 status = schedule_aio_write_and_X(conn,
4601 req,
4602 fsp,
4603 data,
4604 startpos,
4605 numtowrite);
4607 if (NT_STATUS_IS_OK(status)) {
4608 /* write scheduled - we're done. */
4609 goto out;
4611 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4612 /* Real error - report to client. */
4613 reply_nterror(req, status);
4614 goto out;
4616 /* NT_STATUS_RETRY - fall through to sync write. */
4619 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4620 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4621 &lock);
4623 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4624 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4625 goto out;
4628 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4629 saved_errno = errno;
4631 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4634 if(nwritten < 0) {
4635 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4636 goto out;
4639 if((nwritten == 0) && (numtowrite != 0)) {
4640 reply_nterror(req, NT_STATUS_DISK_FULL);
4641 goto out;
4644 reply_outbuf(req, 6, 0);
4645 SSVAL(req->outbuf,smb_vwv2,nwritten);
4646 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4648 if (nwritten < (ssize_t)numtowrite) {
4649 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4650 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4653 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4654 fsp->fnum, (int)numtowrite, (int)nwritten));
4656 status = sync_file(conn, fsp, write_through);
4657 if (!NT_STATUS_IS_OK(status)) {
4658 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4659 fsp_str_dbg(fsp), nt_errstr(status)));
4660 reply_nterror(req, status);
4661 goto out;
4664 END_PROFILE(SMBwriteX);
4665 chain_reply(req);
4666 return;
4668 out:
4669 END_PROFILE(SMBwriteX);
4670 return;
4673 /****************************************************************************
4674 Reply to a lseek.
4675 ****************************************************************************/
4677 void reply_lseek(struct smb_request *req)
4679 connection_struct *conn = req->conn;
4680 SMB_OFF_T startpos;
4681 SMB_OFF_T res= -1;
4682 int mode,umode;
4683 files_struct *fsp;
4685 START_PROFILE(SMBlseek);
4687 if (req->wct < 4) {
4688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4689 END_PROFILE(SMBlseek);
4690 return;
4693 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4695 if (!check_fsp(conn, req, fsp)) {
4696 return;
4699 flush_write_cache(fsp, SEEK_FLUSH);
4701 mode = SVAL(req->vwv+1, 0) & 3;
4702 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4703 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4705 switch (mode) {
4706 case 0:
4707 umode = SEEK_SET;
4708 res = startpos;
4709 break;
4710 case 1:
4711 umode = SEEK_CUR;
4712 res = fsp->fh->pos + startpos;
4713 break;
4714 case 2:
4715 umode = SEEK_END;
4716 break;
4717 default:
4718 umode = SEEK_SET;
4719 res = startpos;
4720 break;
4723 if (umode == SEEK_END) {
4724 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4725 if(errno == EINVAL) {
4726 SMB_OFF_T current_pos = startpos;
4728 if(fsp_stat(fsp) == -1) {
4729 reply_nterror(req,
4730 map_nt_error_from_unix(errno));
4731 END_PROFILE(SMBlseek);
4732 return;
4735 current_pos += fsp->fsp_name->st.st_ex_size;
4736 if(current_pos < 0)
4737 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4741 if(res == -1) {
4742 reply_nterror(req, map_nt_error_from_unix(errno));
4743 END_PROFILE(SMBlseek);
4744 return;
4748 fsp->fh->pos = res;
4750 reply_outbuf(req, 2, 0);
4751 SIVAL(req->outbuf,smb_vwv0,res);
4753 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4754 fsp->fnum, (double)startpos, (double)res, mode));
4756 END_PROFILE(SMBlseek);
4757 return;
4760 /****************************************************************************
4761 Reply to a flush.
4762 ****************************************************************************/
4764 void reply_flush(struct smb_request *req)
4766 connection_struct *conn = req->conn;
4767 uint16 fnum;
4768 files_struct *fsp;
4770 START_PROFILE(SMBflush);
4772 if (req->wct < 1) {
4773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4774 return;
4777 fnum = SVAL(req->vwv+0, 0);
4778 fsp = file_fsp(req, fnum);
4780 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4781 return;
4784 if (!fsp) {
4785 file_sync_all(conn);
4786 } else {
4787 NTSTATUS status = sync_file(conn, fsp, True);
4788 if (!NT_STATUS_IS_OK(status)) {
4789 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4790 fsp_str_dbg(fsp), nt_errstr(status)));
4791 reply_nterror(req, status);
4792 END_PROFILE(SMBflush);
4793 return;
4797 reply_outbuf(req, 0, 0);
4799 DEBUG(3,("flush\n"));
4800 END_PROFILE(SMBflush);
4801 return;
4804 /****************************************************************************
4805 Reply to a exit.
4806 conn POINTER CAN BE NULL HERE !
4807 ****************************************************************************/
4809 void reply_exit(struct smb_request *req)
4811 START_PROFILE(SMBexit);
4813 file_close_pid(req->sconn, req->smbpid, req->vuid);
4815 reply_outbuf(req, 0, 0);
4817 DEBUG(3,("exit\n"));
4819 END_PROFILE(SMBexit);
4820 return;
4823 /****************************************************************************
4824 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4825 ****************************************************************************/
4827 void reply_close(struct smb_request *req)
4829 connection_struct *conn = req->conn;
4830 NTSTATUS status = NT_STATUS_OK;
4831 files_struct *fsp = NULL;
4832 START_PROFILE(SMBclose);
4834 if (req->wct < 3) {
4835 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4836 END_PROFILE(SMBclose);
4837 return;
4840 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4843 * We can only use check_fsp if we know it's not a directory.
4846 if (!check_fsp_open(conn, req, fsp)) {
4847 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4848 END_PROFILE(SMBclose);
4849 return;
4852 if(fsp->is_directory) {
4854 * Special case - close NT SMB directory handle.
4856 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4857 status = close_file(req, fsp, NORMAL_CLOSE);
4858 } else {
4859 time_t t;
4861 * Close ordinary file.
4864 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4865 fsp->fh->fd, fsp->fnum,
4866 conn->num_files_open));
4869 * Take care of any time sent in the close.
4872 t = srv_make_unix_date3(req->vwv+1);
4873 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4876 * close_file() returns the unix errno if an error
4877 * was detected on close - normally this is due to
4878 * a disk full error. If not then it was probably an I/O error.
4881 status = close_file(req, fsp, NORMAL_CLOSE);
4884 if (!NT_STATUS_IS_OK(status)) {
4885 reply_nterror(req, status);
4886 END_PROFILE(SMBclose);
4887 return;
4890 reply_outbuf(req, 0, 0);
4891 END_PROFILE(SMBclose);
4892 return;
4895 /****************************************************************************
4896 Reply to a writeclose (Core+ protocol).
4897 ****************************************************************************/
4899 void reply_writeclose(struct smb_request *req)
4901 connection_struct *conn = req->conn;
4902 size_t numtowrite;
4903 ssize_t nwritten = -1;
4904 NTSTATUS close_status = NT_STATUS_OK;
4905 SMB_OFF_T startpos;
4906 const char *data;
4907 struct timespec mtime;
4908 files_struct *fsp;
4909 struct lock_struct lock;
4911 START_PROFILE(SMBwriteclose);
4913 if (req->wct < 6) {
4914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4915 END_PROFILE(SMBwriteclose);
4916 return;
4919 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4921 if (!check_fsp(conn, req, fsp)) {
4922 END_PROFILE(SMBwriteclose);
4923 return;
4925 if (!CHECK_WRITE(fsp)) {
4926 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4927 END_PROFILE(SMBwriteclose);
4928 return;
4931 numtowrite = SVAL(req->vwv+1, 0);
4932 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4933 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4934 data = (const char *)req->buf + 1;
4936 if (!fsp->print_file) {
4937 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4938 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4939 &lock);
4941 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4942 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4943 END_PROFILE(SMBwriteclose);
4944 return;
4948 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4950 set_close_write_time(fsp, mtime);
4953 * More insanity. W2K only closes the file if writelen > 0.
4954 * JRA.
4957 if (numtowrite) {
4958 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4959 "file %s\n", fsp_str_dbg(fsp)));
4960 close_status = close_file(req, fsp, NORMAL_CLOSE);
4963 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4964 fsp->fnum, (int)numtowrite, (int)nwritten,
4965 conn->num_files_open));
4967 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4968 reply_nterror(req, NT_STATUS_DISK_FULL);
4969 goto strict_unlock;
4972 if(!NT_STATUS_IS_OK(close_status)) {
4973 reply_nterror(req, close_status);
4974 goto strict_unlock;
4977 reply_outbuf(req, 1, 0);
4979 SSVAL(req->outbuf,smb_vwv0,nwritten);
4981 strict_unlock:
4982 if (numtowrite && !fsp->print_file) {
4983 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4986 END_PROFILE(SMBwriteclose);
4987 return;
4990 #undef DBGC_CLASS
4991 #define DBGC_CLASS DBGC_LOCKING
4993 /****************************************************************************
4994 Reply to a lock.
4995 ****************************************************************************/
4997 void reply_lock(struct smb_request *req)
4999 connection_struct *conn = req->conn;
5000 uint64_t count,offset;
5001 NTSTATUS status;
5002 files_struct *fsp;
5003 struct byte_range_lock *br_lck = NULL;
5005 START_PROFILE(SMBlock);
5007 if (req->wct < 5) {
5008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5009 END_PROFILE(SMBlock);
5010 return;
5013 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5015 if (!check_fsp(conn, req, fsp)) {
5016 END_PROFILE(SMBlock);
5017 return;
5020 count = (uint64_t)IVAL(req->vwv+1, 0);
5021 offset = (uint64_t)IVAL(req->vwv+3, 0);
5023 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5024 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5026 br_lck = do_lock(req->sconn->msg_ctx,
5027 fsp,
5028 (uint64_t)req->smbpid,
5029 count,
5030 offset,
5031 WRITE_LOCK,
5032 WINDOWS_LOCK,
5033 False, /* Non-blocking lock. */
5034 &status,
5035 NULL,
5036 NULL);
5038 TALLOC_FREE(br_lck);
5040 if (NT_STATUS_V(status)) {
5041 reply_nterror(req, status);
5042 END_PROFILE(SMBlock);
5043 return;
5046 reply_outbuf(req, 0, 0);
5048 END_PROFILE(SMBlock);
5049 return;
5052 /****************************************************************************
5053 Reply to a unlock.
5054 ****************************************************************************/
5056 void reply_unlock(struct smb_request *req)
5058 connection_struct *conn = req->conn;
5059 uint64_t count,offset;
5060 NTSTATUS status;
5061 files_struct *fsp;
5063 START_PROFILE(SMBunlock);
5065 if (req->wct < 5) {
5066 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5067 END_PROFILE(SMBunlock);
5068 return;
5071 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5073 if (!check_fsp(conn, req, fsp)) {
5074 END_PROFILE(SMBunlock);
5075 return;
5078 count = (uint64_t)IVAL(req->vwv+1, 0);
5079 offset = (uint64_t)IVAL(req->vwv+3, 0);
5081 status = do_unlock(req->sconn->msg_ctx,
5082 fsp,
5083 (uint64_t)req->smbpid,
5084 count,
5085 offset,
5086 WINDOWS_LOCK);
5088 if (NT_STATUS_V(status)) {
5089 reply_nterror(req, status);
5090 END_PROFILE(SMBunlock);
5091 return;
5094 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5095 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5097 reply_outbuf(req, 0, 0);
5099 END_PROFILE(SMBunlock);
5100 return;
5103 #undef DBGC_CLASS
5104 #define DBGC_CLASS DBGC_ALL
5106 /****************************************************************************
5107 Reply to a tdis.
5108 conn POINTER CAN BE NULL HERE !
5109 ****************************************************************************/
5111 void reply_tdis(struct smb_request *req)
5113 connection_struct *conn = req->conn;
5114 START_PROFILE(SMBtdis);
5116 if (!conn) {
5117 DEBUG(4,("Invalid connection in tdis\n"));
5118 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5119 END_PROFILE(SMBtdis);
5120 return;
5123 conn->used = False;
5125 close_cnum(conn,req->vuid);
5126 req->conn = NULL;
5128 reply_outbuf(req, 0, 0);
5129 END_PROFILE(SMBtdis);
5130 return;
5133 /****************************************************************************
5134 Reply to a echo.
5135 conn POINTER CAN BE NULL HERE !
5136 ****************************************************************************/
5138 void reply_echo(struct smb_request *req)
5140 connection_struct *conn = req->conn;
5141 struct smb_perfcount_data local_pcd;
5142 struct smb_perfcount_data *cur_pcd;
5143 int smb_reverb;
5144 int seq_num;
5146 START_PROFILE(SMBecho);
5148 smb_init_perfcount_data(&local_pcd);
5150 if (req->wct < 1) {
5151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5152 END_PROFILE(SMBecho);
5153 return;
5156 smb_reverb = SVAL(req->vwv+0, 0);
5158 reply_outbuf(req, 1, req->buflen);
5160 /* copy any incoming data back out */
5161 if (req->buflen > 0) {
5162 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5165 if (smb_reverb > 100) {
5166 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5167 smb_reverb = 100;
5170 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5172 /* this makes sure we catch the request pcd */
5173 if (seq_num == smb_reverb) {
5174 cur_pcd = &req->pcd;
5175 } else {
5176 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5177 cur_pcd = &local_pcd;
5180 SSVAL(req->outbuf,smb_vwv0,seq_num);
5182 show_msg((char *)req->outbuf);
5183 if (!srv_send_smb(req->sconn,
5184 (char *)req->outbuf,
5185 true, req->seqnum+1,
5186 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5187 cur_pcd))
5188 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5191 DEBUG(3,("echo %d times\n", smb_reverb));
5193 TALLOC_FREE(req->outbuf);
5195 END_PROFILE(SMBecho);
5196 return;
5199 /****************************************************************************
5200 Reply to a printopen.
5201 ****************************************************************************/
5203 void reply_printopen(struct smb_request *req)
5205 connection_struct *conn = req->conn;
5206 files_struct *fsp;
5207 NTSTATUS status;
5209 START_PROFILE(SMBsplopen);
5211 if (req->wct < 2) {
5212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5213 END_PROFILE(SMBsplopen);
5214 return;
5217 if (!CAN_PRINT(conn)) {
5218 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5219 END_PROFILE(SMBsplopen);
5220 return;
5223 status = file_new(req, conn, &fsp);
5224 if(!NT_STATUS_IS_OK(status)) {
5225 reply_nterror(req, status);
5226 END_PROFILE(SMBsplopen);
5227 return;
5230 /* Open for exclusive use, write only. */
5231 status = print_spool_open(fsp, NULL, req->vuid);
5233 if (!NT_STATUS_IS_OK(status)) {
5234 file_free(req, fsp);
5235 reply_nterror(req, status);
5236 END_PROFILE(SMBsplopen);
5237 return;
5240 reply_outbuf(req, 1, 0);
5241 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5243 DEBUG(3,("openprint fd=%d fnum=%d\n",
5244 fsp->fh->fd, fsp->fnum));
5246 END_PROFILE(SMBsplopen);
5247 return;
5250 /****************************************************************************
5251 Reply to a printclose.
5252 ****************************************************************************/
5254 void reply_printclose(struct smb_request *req)
5256 connection_struct *conn = req->conn;
5257 files_struct *fsp;
5258 NTSTATUS status;
5260 START_PROFILE(SMBsplclose);
5262 if (req->wct < 1) {
5263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5264 END_PROFILE(SMBsplclose);
5265 return;
5268 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5270 if (!check_fsp(conn, req, fsp)) {
5271 END_PROFILE(SMBsplclose);
5272 return;
5275 if (!CAN_PRINT(conn)) {
5276 reply_force_doserror(req, ERRSRV, ERRerror);
5277 END_PROFILE(SMBsplclose);
5278 return;
5281 DEBUG(3,("printclose fd=%d fnum=%d\n",
5282 fsp->fh->fd,fsp->fnum));
5284 status = close_file(req, fsp, NORMAL_CLOSE);
5286 if(!NT_STATUS_IS_OK(status)) {
5287 reply_nterror(req, status);
5288 END_PROFILE(SMBsplclose);
5289 return;
5292 reply_outbuf(req, 0, 0);
5294 END_PROFILE(SMBsplclose);
5295 return;
5298 /****************************************************************************
5299 Reply to a printqueue.
5300 ****************************************************************************/
5302 void reply_printqueue(struct smb_request *req)
5304 connection_struct *conn = req->conn;
5305 int max_count;
5306 int start_index;
5308 START_PROFILE(SMBsplretq);
5310 if (req->wct < 2) {
5311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5312 END_PROFILE(SMBsplretq);
5313 return;
5316 max_count = SVAL(req->vwv+0, 0);
5317 start_index = SVAL(req->vwv+1, 0);
5319 /* we used to allow the client to get the cnum wrong, but that
5320 is really quite gross and only worked when there was only
5321 one printer - I think we should now only accept it if they
5322 get it right (tridge) */
5323 if (!CAN_PRINT(conn)) {
5324 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5325 END_PROFILE(SMBsplretq);
5326 return;
5329 reply_outbuf(req, 2, 3);
5330 SSVAL(req->outbuf,smb_vwv0,0);
5331 SSVAL(req->outbuf,smb_vwv1,0);
5332 SCVAL(smb_buf(req->outbuf),0,1);
5333 SSVAL(smb_buf(req->outbuf),1,0);
5335 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5336 start_index, max_count));
5339 TALLOC_CTX *mem_ctx = talloc_tos();
5340 NTSTATUS status;
5341 WERROR werr;
5342 const char *sharename = lp_servicename(SNUM(conn));
5343 struct rpc_pipe_client *cli = NULL;
5344 struct dcerpc_binding_handle *b = NULL;
5345 struct policy_handle handle;
5346 struct spoolss_DevmodeContainer devmode_ctr;
5347 union spoolss_JobInfo *info;
5348 uint32_t count;
5349 uint32_t num_to_get;
5350 uint32_t first;
5351 uint32_t i;
5353 ZERO_STRUCT(handle);
5355 status = rpc_pipe_open_interface(conn,
5356 &ndr_table_spoolss.syntax_id,
5357 conn->session_info,
5358 &conn->sconn->client_id,
5359 conn->sconn->msg_ctx,
5360 &cli);
5361 if (!NT_STATUS_IS_OK(status)) {
5362 DEBUG(0, ("reply_printqueue: "
5363 "could not connect to spoolss: %s\n",
5364 nt_errstr(status)));
5365 reply_nterror(req, status);
5366 goto out;
5368 b = cli->binding_handle;
5370 ZERO_STRUCT(devmode_ctr);
5372 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5373 sharename,
5374 NULL, devmode_ctr,
5375 SEC_FLAG_MAXIMUM_ALLOWED,
5376 &handle,
5377 &werr);
5378 if (!NT_STATUS_IS_OK(status)) {
5379 reply_nterror(req, status);
5380 goto out;
5382 if (!W_ERROR_IS_OK(werr)) {
5383 reply_nterror(req, werror_to_ntstatus(werr));
5384 goto out;
5387 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5388 &handle,
5389 0, /* firstjob */
5390 0xff, /* numjobs */
5391 2, /* level */
5392 0, /* offered */
5393 &count,
5394 &info);
5395 if (!W_ERROR_IS_OK(werr)) {
5396 reply_nterror(req, werror_to_ntstatus(werr));
5397 goto out;
5400 if (max_count > 0) {
5401 first = start_index;
5402 } else {
5403 first = start_index + max_count + 1;
5406 if (first >= count) {
5407 num_to_get = first;
5408 } else {
5409 num_to_get = first + MIN(ABS(max_count), count - first);
5412 for (i = first; i < num_to_get; i++) {
5413 char blob[28];
5414 char *p = blob;
5415 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5416 int qstatus;
5417 uint16_t qrapjobid = pjobid_to_rap(sharename,
5418 info[i].info2.job_id);
5420 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5421 qstatus = 2;
5422 } else {
5423 qstatus = 3;
5426 srv_put_dos_date2(p, 0, qtime);
5427 SCVAL(p, 4, qstatus);
5428 SSVAL(p, 5, qrapjobid);
5429 SIVAL(p, 7, info[i].info2.size);
5430 SCVAL(p, 11, 0);
5431 srvstr_push(blob, req->flags2, p+12,
5432 info[i].info2.notify_name, 16, STR_ASCII);
5434 if (message_push_blob(
5435 &req->outbuf,
5436 data_blob_const(
5437 blob, sizeof(blob))) == -1) {
5438 reply_nterror(req, NT_STATUS_NO_MEMORY);
5439 goto out;
5443 if (count > 0) {
5444 SSVAL(req->outbuf,smb_vwv0,count);
5445 SSVAL(req->outbuf,smb_vwv1,
5446 (max_count>0?first+count:first-1));
5447 SCVAL(smb_buf(req->outbuf),0,1);
5448 SSVAL(smb_buf(req->outbuf),1,28*count);
5452 DEBUG(3, ("%u entries returned in queue\n",
5453 (unsigned)count));
5455 out:
5456 if (b && is_valid_policy_hnd(&handle)) {
5457 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5462 END_PROFILE(SMBsplretq);
5463 return;
5466 /****************************************************************************
5467 Reply to a printwrite.
5468 ****************************************************************************/
5470 void reply_printwrite(struct smb_request *req)
5472 connection_struct *conn = req->conn;
5473 int numtowrite;
5474 const char *data;
5475 files_struct *fsp;
5477 START_PROFILE(SMBsplwr);
5479 if (req->wct < 1) {
5480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5481 END_PROFILE(SMBsplwr);
5482 return;
5485 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5487 if (!check_fsp(conn, req, fsp)) {
5488 END_PROFILE(SMBsplwr);
5489 return;
5492 if (!fsp->print_file) {
5493 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5494 END_PROFILE(SMBsplwr);
5495 return;
5498 if (!CHECK_WRITE(fsp)) {
5499 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5500 END_PROFILE(SMBsplwr);
5501 return;
5504 numtowrite = SVAL(req->buf, 1);
5506 if (req->buflen < numtowrite + 3) {
5507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5508 END_PROFILE(SMBsplwr);
5509 return;
5512 data = (const char *)req->buf + 3;
5514 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5515 reply_nterror(req, map_nt_error_from_unix(errno));
5516 END_PROFILE(SMBsplwr);
5517 return;
5520 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5522 END_PROFILE(SMBsplwr);
5523 return;
5526 /****************************************************************************
5527 Reply to a mkdir.
5528 ****************************************************************************/
5530 void reply_mkdir(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();
5538 START_PROFILE(SMBmkdir);
5540 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5541 STR_TERMINATE, &status);
5542 if (!NT_STATUS_IS_OK(status)) {
5543 reply_nterror(req, status);
5544 goto out;
5547 status = filename_convert(ctx, conn,
5548 req->flags2 & FLAGS2_DFS_PATHNAMES,
5549 directory,
5551 NULL,
5552 &smb_dname);
5553 if (!NT_STATUS_IS_OK(status)) {
5554 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5555 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5556 ERRSRV, ERRbadpath);
5557 goto out;
5559 reply_nterror(req, status);
5560 goto out;
5563 status = create_directory(conn, req, smb_dname);
5565 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5567 if (!NT_STATUS_IS_OK(status)) {
5569 if (!use_nt_status()
5570 && NT_STATUS_EQUAL(status,
5571 NT_STATUS_OBJECT_NAME_COLLISION)) {
5573 * Yes, in the DOS error code case we get a
5574 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5575 * samba4 torture test.
5577 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5580 reply_nterror(req, status);
5581 goto out;
5584 reply_outbuf(req, 0, 0);
5586 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5587 out:
5588 TALLOC_FREE(smb_dname);
5589 END_PROFILE(SMBmkdir);
5590 return;
5593 /****************************************************************************
5594 Reply to a rmdir.
5595 ****************************************************************************/
5597 void reply_rmdir(struct smb_request *req)
5599 connection_struct *conn = req->conn;
5600 struct smb_filename *smb_dname = NULL;
5601 char *directory = NULL;
5602 NTSTATUS status;
5603 TALLOC_CTX *ctx = talloc_tos();
5604 files_struct *fsp = NULL;
5605 int info = 0;
5606 struct smbd_server_connection *sconn = req->sconn;
5608 START_PROFILE(SMBrmdir);
5610 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5611 STR_TERMINATE, &status);
5612 if (!NT_STATUS_IS_OK(status)) {
5613 reply_nterror(req, status);
5614 goto out;
5617 status = filename_convert(ctx, conn,
5618 req->flags2 & FLAGS2_DFS_PATHNAMES,
5619 directory,
5621 NULL,
5622 &smb_dname);
5623 if (!NT_STATUS_IS_OK(status)) {
5624 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5625 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5626 ERRSRV, ERRbadpath);
5627 goto out;
5629 reply_nterror(req, status);
5630 goto out;
5633 if (is_ntfs_stream_smb_fname(smb_dname)) {
5634 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5635 goto out;
5638 status = SMB_VFS_CREATE_FILE(
5639 conn, /* conn */
5640 req, /* req */
5641 0, /* root_dir_fid */
5642 smb_dname, /* fname */
5643 DELETE_ACCESS, /* access_mask */
5644 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5645 FILE_SHARE_DELETE),
5646 FILE_OPEN, /* create_disposition*/
5647 FILE_DIRECTORY_FILE, /* create_options */
5648 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5649 0, /* oplock_request */
5650 0, /* allocation_size */
5651 0, /* private_flags */
5652 NULL, /* sd */
5653 NULL, /* ea_list */
5654 &fsp, /* result */
5655 &info); /* pinfo */
5657 if (!NT_STATUS_IS_OK(status)) {
5658 if (open_was_deferred(req->mid)) {
5659 /* We have re-scheduled this call. */
5660 goto out;
5662 reply_nterror(req, status);
5663 goto out;
5666 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5667 if (!NT_STATUS_IS_OK(status)) {
5668 close_file(req, fsp, ERROR_CLOSE);
5669 reply_nterror(req, status);
5670 goto out;
5673 if (!set_delete_on_close(fsp, true, &conn->session_info->utok)) {
5674 close_file(req, fsp, ERROR_CLOSE);
5675 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5676 goto out;
5679 status = close_file(req, fsp, NORMAL_CLOSE);
5680 if (!NT_STATUS_IS_OK(status)) {
5681 reply_nterror(req, status);
5682 } else {
5683 reply_outbuf(req, 0, 0);
5686 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5688 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5689 out:
5690 TALLOC_FREE(smb_dname);
5691 END_PROFILE(SMBrmdir);
5692 return;
5695 /*******************************************************************
5696 Resolve wildcards in a filename rename.
5697 ********************************************************************/
5699 static bool resolve_wildcards(TALLOC_CTX *ctx,
5700 const char *name1,
5701 const char *name2,
5702 char **pp_newname)
5704 char *name2_copy = NULL;
5705 char *root1 = NULL;
5706 char *root2 = NULL;
5707 char *ext1 = NULL;
5708 char *ext2 = NULL;
5709 char *p,*p2, *pname1, *pname2;
5711 name2_copy = talloc_strdup(ctx, name2);
5712 if (!name2_copy) {
5713 return False;
5716 pname1 = strrchr_m(name1,'/');
5717 pname2 = strrchr_m(name2_copy,'/');
5719 if (!pname1 || !pname2) {
5720 return False;
5723 /* Truncate the copy of name2 at the last '/' */
5724 *pname2 = '\0';
5726 /* Now go past the '/' */
5727 pname1++;
5728 pname2++;
5730 root1 = talloc_strdup(ctx, pname1);
5731 root2 = talloc_strdup(ctx, pname2);
5733 if (!root1 || !root2) {
5734 return False;
5737 p = strrchr_m(root1,'.');
5738 if (p) {
5739 *p = 0;
5740 ext1 = talloc_strdup(ctx, p+1);
5741 } else {
5742 ext1 = talloc_strdup(ctx, "");
5744 p = strrchr_m(root2,'.');
5745 if (p) {
5746 *p = 0;
5747 ext2 = talloc_strdup(ctx, p+1);
5748 } else {
5749 ext2 = talloc_strdup(ctx, "");
5752 if (!ext1 || !ext2) {
5753 return False;
5756 p = root1;
5757 p2 = root2;
5758 while (*p2) {
5759 if (*p2 == '?') {
5760 /* Hmmm. Should this be mb-aware ? */
5761 *p2 = *p;
5762 p2++;
5763 } else if (*p2 == '*') {
5764 *p2 = '\0';
5765 root2 = talloc_asprintf(ctx, "%s%s",
5766 root2,
5768 if (!root2) {
5769 return False;
5771 break;
5772 } else {
5773 p2++;
5775 if (*p) {
5776 p++;
5780 p = ext1;
5781 p2 = ext2;
5782 while (*p2) {
5783 if (*p2 == '?') {
5784 /* Hmmm. Should this be mb-aware ? */
5785 *p2 = *p;
5786 p2++;
5787 } else if (*p2 == '*') {
5788 *p2 = '\0';
5789 ext2 = talloc_asprintf(ctx, "%s%s",
5790 ext2,
5792 if (!ext2) {
5793 return False;
5795 break;
5796 } else {
5797 p2++;
5799 if (*p) {
5800 p++;
5804 if (*ext2) {
5805 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5806 name2_copy,
5807 root2,
5808 ext2);
5809 } else {
5810 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5811 name2_copy,
5812 root2);
5815 if (!*pp_newname) {
5816 return False;
5819 return True;
5822 /****************************************************************************
5823 Ensure open files have their names updated. Updated to notify other smbd's
5824 asynchronously.
5825 ****************************************************************************/
5827 static void rename_open_files(connection_struct *conn,
5828 struct share_mode_lock *lck,
5829 uint32_t orig_name_hash,
5830 const struct smb_filename *smb_fname_dst)
5832 files_struct *fsp;
5833 bool did_rename = False;
5834 NTSTATUS status;
5835 uint32_t new_name_hash = 0;
5837 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5838 fsp = file_find_di_next(fsp)) {
5839 /* fsp_name is a relative path under the fsp. To change this for other
5840 sharepaths we need to manipulate relative paths. */
5841 /* TODO - create the absolute path and manipulate the newname
5842 relative to the sharepath. */
5843 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5844 continue;
5846 if (fsp->name_hash != orig_name_hash) {
5847 continue;
5849 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5850 "(file_id %s) from %s -> %s\n", fsp->fnum,
5851 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5852 smb_fname_str_dbg(smb_fname_dst)));
5854 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5855 if (NT_STATUS_IS_OK(status)) {
5856 did_rename = True;
5857 new_name_hash = fsp->name_hash;
5861 if (!did_rename) {
5862 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5863 "for %s\n", file_id_string_tos(&lck->id),
5864 smb_fname_str_dbg(smb_fname_dst)));
5867 /* Send messages to all smbd's (not ourself) that the name has changed. */
5868 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5869 orig_name_hash, new_name_hash,
5870 smb_fname_dst);
5874 /****************************************************************************
5875 We need to check if the source path is a parent directory of the destination
5876 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5877 refuse the rename with a sharing violation. Under UNIX the above call can
5878 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5879 probably need to check that the client is a Windows one before disallowing
5880 this as a UNIX client (one with UNIX extensions) can know the source is a
5881 symlink and make this decision intelligently. Found by an excellent bug
5882 report from <AndyLiebman@aol.com>.
5883 ****************************************************************************/
5885 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5886 const struct smb_filename *smb_fname_dst)
5888 const char *psrc = smb_fname_src->base_name;
5889 const char *pdst = smb_fname_dst->base_name;
5890 size_t slen;
5892 if (psrc[0] == '.' && psrc[1] == '/') {
5893 psrc += 2;
5895 if (pdst[0] == '.' && pdst[1] == '/') {
5896 pdst += 2;
5898 if ((slen = strlen(psrc)) > strlen(pdst)) {
5899 return False;
5901 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5905 * Do the notify calls from a rename
5908 static void notify_rename(connection_struct *conn, bool is_dir,
5909 const struct smb_filename *smb_fname_src,
5910 const struct smb_filename *smb_fname_dst)
5912 char *parent_dir_src = NULL;
5913 char *parent_dir_dst = NULL;
5914 uint32 mask;
5916 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5917 : FILE_NOTIFY_CHANGE_FILE_NAME;
5919 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5920 &parent_dir_src, NULL) ||
5921 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5922 &parent_dir_dst, NULL)) {
5923 goto out;
5926 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5927 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5928 smb_fname_src->base_name);
5929 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5930 smb_fname_dst->base_name);
5932 else {
5933 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5934 smb_fname_src->base_name);
5935 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5936 smb_fname_dst->base_name);
5939 /* this is a strange one. w2k3 gives an additional event for
5940 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5941 files, but not directories */
5942 if (!is_dir) {
5943 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5944 FILE_NOTIFY_CHANGE_ATTRIBUTES
5945 |FILE_NOTIFY_CHANGE_CREATION,
5946 smb_fname_dst->base_name);
5948 out:
5949 TALLOC_FREE(parent_dir_src);
5950 TALLOC_FREE(parent_dir_dst);
5953 /****************************************************************************
5954 Rename an open file - given an fsp.
5955 ****************************************************************************/
5957 NTSTATUS rename_internals_fsp(connection_struct *conn,
5958 files_struct *fsp,
5959 const struct smb_filename *smb_fname_dst_in,
5960 uint32 attrs,
5961 bool replace_if_exists)
5963 TALLOC_CTX *ctx = talloc_tos();
5964 struct smb_filename *smb_fname_dst = NULL;
5965 NTSTATUS status = NT_STATUS_OK;
5966 struct share_mode_lock *lck = NULL;
5967 bool dst_exists, old_is_stream, new_is_stream;
5969 status = check_name(conn, smb_fname_dst_in->base_name);
5970 if (!NT_STATUS_IS_OK(status)) {
5971 return status;
5974 /* Make a copy of the dst smb_fname structs */
5976 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5977 if (!NT_STATUS_IS_OK(status)) {
5978 goto out;
5982 * Check for special case with case preserving and not
5983 * case sensitive. If the old last component differs from the original
5984 * last component only by case, then we should allow
5985 * the rename (user is trying to change the case of the
5986 * filename).
5988 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5989 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5990 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5991 char *last_slash;
5992 char *fname_dst_lcomp_base_mod = NULL;
5993 struct smb_filename *smb_fname_orig_lcomp = NULL;
5996 * Get the last component of the destination name.
5998 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5999 if (last_slash) {
6000 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6001 } else {
6002 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6004 if (!fname_dst_lcomp_base_mod) {
6005 status = NT_STATUS_NO_MEMORY;
6006 goto out;
6010 * Create an smb_filename struct using the original last
6011 * component of the destination.
6013 status = create_synthetic_smb_fname_split(ctx,
6014 smb_fname_dst->original_lcomp, NULL,
6015 &smb_fname_orig_lcomp);
6016 if (!NT_STATUS_IS_OK(status)) {
6017 TALLOC_FREE(fname_dst_lcomp_base_mod);
6018 goto out;
6021 /* If the base names only differ by case, use original. */
6022 if(!strcsequal(fname_dst_lcomp_base_mod,
6023 smb_fname_orig_lcomp->base_name)) {
6024 char *tmp;
6026 * Replace the modified last component with the
6027 * original.
6029 if (last_slash) {
6030 *last_slash = '\0'; /* Truncate at the '/' */
6031 tmp = talloc_asprintf(smb_fname_dst,
6032 "%s/%s",
6033 smb_fname_dst->base_name,
6034 smb_fname_orig_lcomp->base_name);
6035 } else {
6036 tmp = talloc_asprintf(smb_fname_dst,
6037 "%s",
6038 smb_fname_orig_lcomp->base_name);
6040 if (tmp == NULL) {
6041 status = NT_STATUS_NO_MEMORY;
6042 TALLOC_FREE(fname_dst_lcomp_base_mod);
6043 TALLOC_FREE(smb_fname_orig_lcomp);
6044 goto out;
6046 TALLOC_FREE(smb_fname_dst->base_name);
6047 smb_fname_dst->base_name = tmp;
6050 /* If the stream_names only differ by case, use original. */
6051 if(!strcsequal(smb_fname_dst->stream_name,
6052 smb_fname_orig_lcomp->stream_name)) {
6053 char *tmp = NULL;
6054 /* Use the original stream. */
6055 tmp = talloc_strdup(smb_fname_dst,
6056 smb_fname_orig_lcomp->stream_name);
6057 if (tmp == NULL) {
6058 status = NT_STATUS_NO_MEMORY;
6059 TALLOC_FREE(fname_dst_lcomp_base_mod);
6060 TALLOC_FREE(smb_fname_orig_lcomp);
6061 goto out;
6063 TALLOC_FREE(smb_fname_dst->stream_name);
6064 smb_fname_dst->stream_name = tmp;
6066 TALLOC_FREE(fname_dst_lcomp_base_mod);
6067 TALLOC_FREE(smb_fname_orig_lcomp);
6071 * If the src and dest names are identical - including case,
6072 * don't do the rename, just return success.
6075 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6076 strcsequal(fsp->fsp_name->stream_name,
6077 smb_fname_dst->stream_name)) {
6078 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6079 "- returning success\n",
6080 smb_fname_str_dbg(smb_fname_dst)));
6081 status = NT_STATUS_OK;
6082 goto out;
6085 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6086 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6088 /* Return the correct error code if both names aren't streams. */
6089 if (!old_is_stream && new_is_stream) {
6090 status = NT_STATUS_OBJECT_NAME_INVALID;
6091 goto out;
6094 if (old_is_stream && !new_is_stream) {
6095 status = NT_STATUS_INVALID_PARAMETER;
6096 goto out;
6099 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6101 if(!replace_if_exists && dst_exists) {
6102 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6103 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6104 smb_fname_str_dbg(smb_fname_dst)));
6105 status = NT_STATUS_OBJECT_NAME_COLLISION;
6106 goto out;
6109 if (dst_exists) {
6110 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6111 &smb_fname_dst->st);
6112 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6113 fileid);
6114 /* The file can be open when renaming a stream */
6115 if (dst_fsp && !new_is_stream) {
6116 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6117 status = NT_STATUS_ACCESS_DENIED;
6118 goto out;
6122 /* Ensure we have a valid stat struct for the source. */
6123 status = vfs_stat_fsp(fsp);
6124 if (!NT_STATUS_IS_OK(status)) {
6125 goto out;
6128 status = can_rename(conn, fsp, attrs);
6130 if (!NT_STATUS_IS_OK(status)) {
6131 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6132 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6133 smb_fname_str_dbg(smb_fname_dst)));
6134 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6135 status = NT_STATUS_ACCESS_DENIED;
6136 goto out;
6139 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6140 status = NT_STATUS_ACCESS_DENIED;
6143 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6144 NULL);
6147 * We have the file open ourselves, so not being able to get the
6148 * corresponding share mode lock is a fatal error.
6151 SMB_ASSERT(lck != NULL);
6153 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6154 uint32 create_options = fsp->fh->private_options;
6156 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6157 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6158 smb_fname_str_dbg(smb_fname_dst)));
6160 if (!lp_posix_pathnames() &&
6161 (lp_map_archive(SNUM(conn)) ||
6162 lp_store_dos_attributes(SNUM(conn)))) {
6163 /* We must set the archive bit on the newly
6164 renamed file. */
6165 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6166 uint32_t old_dosmode = dos_mode(conn,
6167 smb_fname_dst);
6168 file_set_dosmode(conn,
6169 smb_fname_dst,
6170 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6171 NULL,
6172 true);
6176 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6177 smb_fname_dst);
6179 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6182 * A rename acts as a new file create w.r.t. allowing an initial delete
6183 * on close, probably because in Windows there is a new handle to the
6184 * new file. If initial delete on close was requested but not
6185 * originally set, we need to set it here. This is probably not 100% correct,
6186 * but will work for the CIFSFS client which in non-posix mode
6187 * depends on these semantics. JRA.
6190 if (create_options & FILE_DELETE_ON_CLOSE) {
6191 status = can_set_delete_on_close(fsp, 0);
6193 if (NT_STATUS_IS_OK(status)) {
6194 /* Note that here we set the *inital* delete on close flag,
6195 * not the regular one. The magic gets handled in close. */
6196 fsp->initial_delete_on_close = True;
6199 TALLOC_FREE(lck);
6200 status = NT_STATUS_OK;
6201 goto out;
6204 TALLOC_FREE(lck);
6206 if (errno == ENOTDIR || errno == EISDIR) {
6207 status = NT_STATUS_OBJECT_NAME_COLLISION;
6208 } else {
6209 status = map_nt_error_from_unix(errno);
6212 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6213 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6214 smb_fname_str_dbg(smb_fname_dst)));
6216 out:
6217 TALLOC_FREE(smb_fname_dst);
6219 return status;
6222 /****************************************************************************
6223 The guts of the rename command, split out so it may be called by the NT SMB
6224 code.
6225 ****************************************************************************/
6227 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6228 connection_struct *conn,
6229 struct smb_request *req,
6230 struct smb_filename *smb_fname_src,
6231 struct smb_filename *smb_fname_dst,
6232 uint32 attrs,
6233 bool replace_if_exists,
6234 bool src_has_wild,
6235 bool dest_has_wild,
6236 uint32_t access_mask)
6238 char *fname_src_dir = NULL;
6239 char *fname_src_mask = NULL;
6240 int count=0;
6241 NTSTATUS status = NT_STATUS_OK;
6242 struct smb_Dir *dir_hnd = NULL;
6243 const char *dname = NULL;
6244 char *talloced = NULL;
6245 long offset = 0;
6246 int create_options = 0;
6247 bool posix_pathnames = lp_posix_pathnames();
6250 * Split the old name into directory and last component
6251 * strings. Note that unix_convert may have stripped off a
6252 * leading ./ from both name and newname if the rename is
6253 * at the root of the share. We need to make sure either both
6254 * name and newname contain a / character or neither of them do
6255 * as this is checked in resolve_wildcards().
6258 /* Split up the directory from the filename/mask. */
6259 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6260 &fname_src_dir, &fname_src_mask);
6261 if (!NT_STATUS_IS_OK(status)) {
6262 status = NT_STATUS_NO_MEMORY;
6263 goto out;
6267 * We should only check the mangled cache
6268 * here if unix_convert failed. This means
6269 * that the path in 'mask' doesn't exist
6270 * on the file system and so we need to look
6271 * for a possible mangle. This patch from
6272 * Tine Smukavec <valentin.smukavec@hermes.si>.
6275 if (!VALID_STAT(smb_fname_src->st) &&
6276 mangle_is_mangled(fname_src_mask, conn->params)) {
6277 char *new_mask = NULL;
6278 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6279 conn->params);
6280 if (new_mask) {
6281 TALLOC_FREE(fname_src_mask);
6282 fname_src_mask = new_mask;
6286 if (!src_has_wild) {
6287 files_struct *fsp;
6290 * Only one file needs to be renamed. Append the mask back
6291 * onto the directory.
6293 TALLOC_FREE(smb_fname_src->base_name);
6294 if (ISDOT(fname_src_dir)) {
6295 /* Ensure we use canonical names on open. */
6296 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6297 "%s",
6298 fname_src_mask);
6299 } else {
6300 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6301 "%s/%s",
6302 fname_src_dir,
6303 fname_src_mask);
6305 if (!smb_fname_src->base_name) {
6306 status = NT_STATUS_NO_MEMORY;
6307 goto out;
6310 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6311 "case_preserve = %d, short case preserve = %d, "
6312 "directory = %s, newname = %s, "
6313 "last_component_dest = %s\n",
6314 conn->case_sensitive, conn->case_preserve,
6315 conn->short_case_preserve,
6316 smb_fname_str_dbg(smb_fname_src),
6317 smb_fname_str_dbg(smb_fname_dst),
6318 smb_fname_dst->original_lcomp));
6320 /* The dest name still may have wildcards. */
6321 if (dest_has_wild) {
6322 char *fname_dst_mod = NULL;
6323 if (!resolve_wildcards(smb_fname_dst,
6324 smb_fname_src->base_name,
6325 smb_fname_dst->base_name,
6326 &fname_dst_mod)) {
6327 DEBUG(6, ("rename_internals: resolve_wildcards "
6328 "%s %s failed\n",
6329 smb_fname_src->base_name,
6330 smb_fname_dst->base_name));
6331 status = NT_STATUS_NO_MEMORY;
6332 goto out;
6334 TALLOC_FREE(smb_fname_dst->base_name);
6335 smb_fname_dst->base_name = fname_dst_mod;
6338 ZERO_STRUCT(smb_fname_src->st);
6339 if (posix_pathnames) {
6340 SMB_VFS_LSTAT(conn, smb_fname_src);
6341 } else {
6342 SMB_VFS_STAT(conn, smb_fname_src);
6345 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6346 create_options |= FILE_DIRECTORY_FILE;
6349 status = SMB_VFS_CREATE_FILE(
6350 conn, /* conn */
6351 req, /* req */
6352 0, /* root_dir_fid */
6353 smb_fname_src, /* fname */
6354 access_mask, /* access_mask */
6355 (FILE_SHARE_READ | /* share_access */
6356 FILE_SHARE_WRITE),
6357 FILE_OPEN, /* create_disposition*/
6358 create_options, /* create_options */
6359 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6360 0, /* oplock_request */
6361 0, /* allocation_size */
6362 0, /* private_flags */
6363 NULL, /* sd */
6364 NULL, /* ea_list */
6365 &fsp, /* result */
6366 NULL); /* pinfo */
6368 if (!NT_STATUS_IS_OK(status)) {
6369 DEBUG(3, ("Could not open rename source %s: %s\n",
6370 smb_fname_str_dbg(smb_fname_src),
6371 nt_errstr(status)));
6372 goto out;
6375 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6376 attrs, replace_if_exists);
6378 close_file(req, fsp, NORMAL_CLOSE);
6380 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6381 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6382 smb_fname_str_dbg(smb_fname_dst)));
6384 goto out;
6388 * Wildcards - process each file that matches.
6390 if (strequal(fname_src_mask, "????????.???")) {
6391 TALLOC_FREE(fname_src_mask);
6392 fname_src_mask = talloc_strdup(ctx, "*");
6393 if (!fname_src_mask) {
6394 status = NT_STATUS_NO_MEMORY;
6395 goto out;
6399 status = check_name(conn, fname_src_dir);
6400 if (!NT_STATUS_IS_OK(status)) {
6401 goto out;
6404 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6405 attrs);
6406 if (dir_hnd == NULL) {
6407 status = map_nt_error_from_unix(errno);
6408 goto out;
6411 status = NT_STATUS_NO_SUCH_FILE;
6413 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6414 * - gentest fix. JRA
6417 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6418 &talloced))) {
6419 files_struct *fsp = NULL;
6420 char *destname = NULL;
6421 bool sysdir_entry = False;
6423 /* Quick check for "." and ".." */
6424 if (ISDOT(dname) || ISDOTDOT(dname)) {
6425 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6426 sysdir_entry = True;
6427 } else {
6428 TALLOC_FREE(talloced);
6429 continue;
6433 if (!is_visible_file(conn, fname_src_dir, dname,
6434 &smb_fname_src->st, false)) {
6435 TALLOC_FREE(talloced);
6436 continue;
6439 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6440 TALLOC_FREE(talloced);
6441 continue;
6444 if (sysdir_entry) {
6445 status = NT_STATUS_OBJECT_NAME_INVALID;
6446 break;
6449 TALLOC_FREE(smb_fname_src->base_name);
6450 if (ISDOT(fname_src_dir)) {
6451 /* Ensure we use canonical names on open. */
6452 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6453 "%s",
6454 dname);
6455 } else {
6456 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6457 "%s/%s",
6458 fname_src_dir,
6459 dname);
6461 if (!smb_fname_src->base_name) {
6462 status = NT_STATUS_NO_MEMORY;
6463 goto out;
6466 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6467 smb_fname_dst->base_name,
6468 &destname)) {
6469 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6470 smb_fname_src->base_name, destname));
6471 TALLOC_FREE(talloced);
6472 continue;
6474 if (!destname) {
6475 status = NT_STATUS_NO_MEMORY;
6476 goto out;
6479 TALLOC_FREE(smb_fname_dst->base_name);
6480 smb_fname_dst->base_name = destname;
6482 ZERO_STRUCT(smb_fname_src->st);
6483 if (posix_pathnames) {
6484 SMB_VFS_LSTAT(conn, smb_fname_src);
6485 } else {
6486 SMB_VFS_STAT(conn, smb_fname_src);
6489 create_options = 0;
6491 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6492 create_options |= FILE_DIRECTORY_FILE;
6495 status = SMB_VFS_CREATE_FILE(
6496 conn, /* conn */
6497 req, /* req */
6498 0, /* root_dir_fid */
6499 smb_fname_src, /* fname */
6500 access_mask, /* access_mask */
6501 (FILE_SHARE_READ | /* share_access */
6502 FILE_SHARE_WRITE),
6503 FILE_OPEN, /* create_disposition*/
6504 create_options, /* create_options */
6505 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6506 0, /* oplock_request */
6507 0, /* allocation_size */
6508 0, /* private_flags */
6509 NULL, /* sd */
6510 NULL, /* ea_list */
6511 &fsp, /* result */
6512 NULL); /* pinfo */
6514 if (!NT_STATUS_IS_OK(status)) {
6515 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6516 "returned %s rename %s -> %s\n",
6517 nt_errstr(status),
6518 smb_fname_str_dbg(smb_fname_src),
6519 smb_fname_str_dbg(smb_fname_dst)));
6520 break;
6523 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6524 dname);
6525 if (!smb_fname_dst->original_lcomp) {
6526 status = NT_STATUS_NO_MEMORY;
6527 goto out;
6530 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6531 attrs, replace_if_exists);
6533 close_file(req, fsp, NORMAL_CLOSE);
6535 if (!NT_STATUS_IS_OK(status)) {
6536 DEBUG(3, ("rename_internals_fsp returned %s for "
6537 "rename %s -> %s\n", nt_errstr(status),
6538 smb_fname_str_dbg(smb_fname_src),
6539 smb_fname_str_dbg(smb_fname_dst)));
6540 break;
6543 count++;
6545 DEBUG(3,("rename_internals: doing rename on %s -> "
6546 "%s\n", smb_fname_str_dbg(smb_fname_src),
6547 smb_fname_str_dbg(smb_fname_src)));
6548 TALLOC_FREE(talloced);
6550 TALLOC_FREE(dir_hnd);
6552 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6553 status = map_nt_error_from_unix(errno);
6556 out:
6557 TALLOC_FREE(talloced);
6558 TALLOC_FREE(fname_src_dir);
6559 TALLOC_FREE(fname_src_mask);
6560 return status;
6563 /****************************************************************************
6564 Reply to a mv.
6565 ****************************************************************************/
6567 void reply_mv(struct smb_request *req)
6569 connection_struct *conn = req->conn;
6570 char *name = NULL;
6571 char *newname = NULL;
6572 const char *p;
6573 uint32 attrs;
6574 NTSTATUS status;
6575 bool src_has_wcard = False;
6576 bool dest_has_wcard = False;
6577 TALLOC_CTX *ctx = talloc_tos();
6578 struct smb_filename *smb_fname_src = NULL;
6579 struct smb_filename *smb_fname_dst = NULL;
6580 bool stream_rename = false;
6582 START_PROFILE(SMBmv);
6584 if (req->wct < 1) {
6585 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6586 goto out;
6589 attrs = SVAL(req->vwv+0, 0);
6591 p = (const char *)req->buf + 1;
6592 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6593 &status, &src_has_wcard);
6594 if (!NT_STATUS_IS_OK(status)) {
6595 reply_nterror(req, status);
6596 goto out;
6598 p++;
6599 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6600 &status, &dest_has_wcard);
6601 if (!NT_STATUS_IS_OK(status)) {
6602 reply_nterror(req, status);
6603 goto out;
6606 if (!lp_posix_pathnames()) {
6607 /* The newname must begin with a ':' if the
6608 name contains a ':'. */
6609 if (strchr_m(name, ':')) {
6610 if (newname[0] != ':') {
6611 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6612 goto out;
6614 stream_rename = true;
6618 status = filename_convert(ctx,
6619 conn,
6620 req->flags2 & FLAGS2_DFS_PATHNAMES,
6621 name,
6622 UCF_COND_ALLOW_WCARD_LCOMP,
6623 &src_has_wcard,
6624 &smb_fname_src);
6626 if (!NT_STATUS_IS_OK(status)) {
6627 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6628 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6629 ERRSRV, ERRbadpath);
6630 goto out;
6632 reply_nterror(req, status);
6633 goto out;
6636 status = filename_convert(ctx,
6637 conn,
6638 req->flags2 & FLAGS2_DFS_PATHNAMES,
6639 newname,
6640 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6641 &dest_has_wcard,
6642 &smb_fname_dst);
6644 if (!NT_STATUS_IS_OK(status)) {
6645 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6646 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6647 ERRSRV, ERRbadpath);
6648 goto out;
6650 reply_nterror(req, status);
6651 goto out;
6654 if (stream_rename) {
6655 /* smb_fname_dst->base_name must be the same as
6656 smb_fname_src->base_name. */
6657 TALLOC_FREE(smb_fname_dst->base_name);
6658 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6659 smb_fname_src->base_name);
6660 if (!smb_fname_dst->base_name) {
6661 reply_nterror(req, NT_STATUS_NO_MEMORY);
6662 goto out;
6666 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6667 smb_fname_str_dbg(smb_fname_dst)));
6669 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6670 attrs, False, src_has_wcard, dest_has_wcard,
6671 DELETE_ACCESS);
6672 if (!NT_STATUS_IS_OK(status)) {
6673 if (open_was_deferred(req->mid)) {
6674 /* We have re-scheduled this call. */
6675 goto out;
6677 reply_nterror(req, status);
6678 goto out;
6681 reply_outbuf(req, 0, 0);
6682 out:
6683 TALLOC_FREE(smb_fname_src);
6684 TALLOC_FREE(smb_fname_dst);
6685 END_PROFILE(SMBmv);
6686 return;
6689 /*******************************************************************
6690 Copy a file as part of a reply_copy.
6691 ******************************************************************/
6694 * TODO: check error codes on all callers
6697 NTSTATUS copy_file(TALLOC_CTX *ctx,
6698 connection_struct *conn,
6699 struct smb_filename *smb_fname_src,
6700 struct smb_filename *smb_fname_dst,
6701 int ofun,
6702 int count,
6703 bool target_is_directory)
6705 struct smb_filename *smb_fname_dst_tmp = NULL;
6706 SMB_OFF_T ret=-1;
6707 files_struct *fsp1,*fsp2;
6708 uint32 dosattrs;
6709 uint32 new_create_disposition;
6710 NTSTATUS status;
6713 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6714 if (!NT_STATUS_IS_OK(status)) {
6715 return status;
6719 * If the target is a directory, extract the last component from the
6720 * src filename and append it to the dst filename
6722 if (target_is_directory) {
6723 const char *p;
6725 /* dest/target can't be a stream if it's a directory. */
6726 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6728 p = strrchr_m(smb_fname_src->base_name,'/');
6729 if (p) {
6730 p++;
6731 } else {
6732 p = smb_fname_src->base_name;
6734 smb_fname_dst_tmp->base_name =
6735 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6737 if (!smb_fname_dst_tmp->base_name) {
6738 status = NT_STATUS_NO_MEMORY;
6739 goto out;
6743 status = vfs_file_exist(conn, smb_fname_src);
6744 if (!NT_STATUS_IS_OK(status)) {
6745 goto out;
6748 if (!target_is_directory && count) {
6749 new_create_disposition = FILE_OPEN;
6750 } else {
6751 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6752 NULL, NULL,
6753 &new_create_disposition,
6754 NULL,
6755 NULL)) {
6756 status = NT_STATUS_INVALID_PARAMETER;
6757 goto out;
6761 /* Open the src file for reading. */
6762 status = SMB_VFS_CREATE_FILE(
6763 conn, /* conn */
6764 NULL, /* req */
6765 0, /* root_dir_fid */
6766 smb_fname_src, /* fname */
6767 FILE_GENERIC_READ, /* access_mask */
6768 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6769 FILE_OPEN, /* create_disposition*/
6770 0, /* create_options */
6771 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6772 INTERNAL_OPEN_ONLY, /* oplock_request */
6773 0, /* allocation_size */
6774 0, /* private_flags */
6775 NULL, /* sd */
6776 NULL, /* ea_list */
6777 &fsp1, /* result */
6778 NULL); /* psbuf */
6780 if (!NT_STATUS_IS_OK(status)) {
6781 goto out;
6784 dosattrs = dos_mode(conn, smb_fname_src);
6786 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6787 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6790 /* Open the dst file for writing. */
6791 status = SMB_VFS_CREATE_FILE(
6792 conn, /* conn */
6793 NULL, /* req */
6794 0, /* root_dir_fid */
6795 smb_fname_dst, /* fname */
6796 FILE_GENERIC_WRITE, /* access_mask */
6797 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6798 new_create_disposition, /* create_disposition*/
6799 0, /* create_options */
6800 dosattrs, /* file_attributes */
6801 INTERNAL_OPEN_ONLY, /* oplock_request */
6802 0, /* allocation_size */
6803 0, /* private_flags */
6804 NULL, /* sd */
6805 NULL, /* ea_list */
6806 &fsp2, /* result */
6807 NULL); /* psbuf */
6809 if (!NT_STATUS_IS_OK(status)) {
6810 close_file(NULL, fsp1, ERROR_CLOSE);
6811 goto out;
6814 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6815 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6816 if (ret == -1) {
6817 DEBUG(0, ("error - vfs lseek returned error %s\n",
6818 strerror(errno)));
6819 status = map_nt_error_from_unix(errno);
6820 close_file(NULL, fsp1, ERROR_CLOSE);
6821 close_file(NULL, fsp2, ERROR_CLOSE);
6822 goto out;
6826 /* Do the actual copy. */
6827 if (smb_fname_src->st.st_ex_size) {
6828 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6829 } else {
6830 ret = 0;
6833 close_file(NULL, fsp1, NORMAL_CLOSE);
6835 /* Ensure the modtime is set correctly on the destination file. */
6836 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6839 * As we are opening fsp1 read-only we only expect
6840 * an error on close on fsp2 if we are out of space.
6841 * Thus we don't look at the error return from the
6842 * close of fsp1.
6844 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6846 if (!NT_STATUS_IS_OK(status)) {
6847 goto out;
6850 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6851 status = NT_STATUS_DISK_FULL;
6852 goto out;
6855 status = NT_STATUS_OK;
6857 out:
6858 TALLOC_FREE(smb_fname_dst_tmp);
6859 return status;
6862 /****************************************************************************
6863 Reply to a file copy.
6864 ****************************************************************************/
6866 void reply_copy(struct smb_request *req)
6868 connection_struct *conn = req->conn;
6869 struct smb_filename *smb_fname_src = NULL;
6870 struct smb_filename *smb_fname_dst = NULL;
6871 char *fname_src = NULL;
6872 char *fname_dst = NULL;
6873 char *fname_src_mask = NULL;
6874 char *fname_src_dir = NULL;
6875 const char *p;
6876 int count=0;
6877 int error = ERRnoaccess;
6878 int tid2;
6879 int ofun;
6880 int flags;
6881 bool target_is_directory=False;
6882 bool source_has_wild = False;
6883 bool dest_has_wild = False;
6884 NTSTATUS status;
6885 TALLOC_CTX *ctx = talloc_tos();
6887 START_PROFILE(SMBcopy);
6889 if (req->wct < 3) {
6890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6891 goto out;
6894 tid2 = SVAL(req->vwv+0, 0);
6895 ofun = SVAL(req->vwv+1, 0);
6896 flags = SVAL(req->vwv+2, 0);
6898 p = (const char *)req->buf;
6899 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6900 &status, &source_has_wild);
6901 if (!NT_STATUS_IS_OK(status)) {
6902 reply_nterror(req, status);
6903 goto out;
6905 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6906 &status, &dest_has_wild);
6907 if (!NT_STATUS_IS_OK(status)) {
6908 reply_nterror(req, status);
6909 goto out;
6912 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6914 if (tid2 != conn->cnum) {
6915 /* can't currently handle inter share copies XXXX */
6916 DEBUG(3,("Rejecting inter-share copy\n"));
6917 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6918 goto out;
6921 status = filename_convert(ctx, conn,
6922 req->flags2 & FLAGS2_DFS_PATHNAMES,
6923 fname_src,
6924 UCF_COND_ALLOW_WCARD_LCOMP,
6925 &source_has_wild,
6926 &smb_fname_src);
6927 if (!NT_STATUS_IS_OK(status)) {
6928 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6929 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6930 ERRSRV, ERRbadpath);
6931 goto out;
6933 reply_nterror(req, status);
6934 goto out;
6937 status = filename_convert(ctx, conn,
6938 req->flags2 & FLAGS2_DFS_PATHNAMES,
6939 fname_dst,
6940 UCF_COND_ALLOW_WCARD_LCOMP,
6941 &dest_has_wild,
6942 &smb_fname_dst);
6943 if (!NT_STATUS_IS_OK(status)) {
6944 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6945 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6946 ERRSRV, ERRbadpath);
6947 goto out;
6949 reply_nterror(req, status);
6950 goto out;
6953 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6955 if ((flags&1) && target_is_directory) {
6956 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6957 goto out;
6960 if ((flags&2) && !target_is_directory) {
6961 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6962 goto out;
6965 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6966 /* wants a tree copy! XXXX */
6967 DEBUG(3,("Rejecting tree copy\n"));
6968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6969 goto out;
6972 /* Split up the directory from the filename/mask. */
6973 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6974 &fname_src_dir, &fname_src_mask);
6975 if (!NT_STATUS_IS_OK(status)) {
6976 reply_nterror(req, NT_STATUS_NO_MEMORY);
6977 goto out;
6981 * We should only check the mangled cache
6982 * here if unix_convert failed. This means
6983 * that the path in 'mask' doesn't exist
6984 * on the file system and so we need to look
6985 * for a possible mangle. This patch from
6986 * Tine Smukavec <valentin.smukavec@hermes.si>.
6988 if (!VALID_STAT(smb_fname_src->st) &&
6989 mangle_is_mangled(fname_src_mask, conn->params)) {
6990 char *new_mask = NULL;
6991 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6992 &new_mask, conn->params);
6994 /* Use demangled name if one was successfully found. */
6995 if (new_mask) {
6996 TALLOC_FREE(fname_src_mask);
6997 fname_src_mask = new_mask;
7001 if (!source_has_wild) {
7004 * Only one file needs to be copied. Append the mask back onto
7005 * the directory.
7007 TALLOC_FREE(smb_fname_src->base_name);
7008 if (ISDOT(fname_src_dir)) {
7009 /* Ensure we use canonical names on open. */
7010 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7011 "%s",
7012 fname_src_mask);
7013 } else {
7014 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7015 "%s/%s",
7016 fname_src_dir,
7017 fname_src_mask);
7019 if (!smb_fname_src->base_name) {
7020 reply_nterror(req, NT_STATUS_NO_MEMORY);
7021 goto out;
7024 if (dest_has_wild) {
7025 char *fname_dst_mod = NULL;
7026 if (!resolve_wildcards(smb_fname_dst,
7027 smb_fname_src->base_name,
7028 smb_fname_dst->base_name,
7029 &fname_dst_mod)) {
7030 reply_nterror(req, NT_STATUS_NO_MEMORY);
7031 goto out;
7033 TALLOC_FREE(smb_fname_dst->base_name);
7034 smb_fname_dst->base_name = fname_dst_mod;
7037 status = check_name(conn, smb_fname_src->base_name);
7038 if (!NT_STATUS_IS_OK(status)) {
7039 reply_nterror(req, status);
7040 goto out;
7043 status = check_name(conn, smb_fname_dst->base_name);
7044 if (!NT_STATUS_IS_OK(status)) {
7045 reply_nterror(req, status);
7046 goto out;
7049 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7050 ofun, count, target_is_directory);
7052 if(!NT_STATUS_IS_OK(status)) {
7053 reply_nterror(req, status);
7054 goto out;
7055 } else {
7056 count++;
7058 } else {
7059 struct smb_Dir *dir_hnd = NULL;
7060 const char *dname = NULL;
7061 char *talloced = NULL;
7062 long offset = 0;
7065 * There is a wildcard that requires us to actually read the
7066 * src dir and copy each file matching the mask to the dst.
7067 * Right now streams won't be copied, but this could
7068 * presumably be added with a nested loop for reach dir entry.
7070 SMB_ASSERT(!smb_fname_src->stream_name);
7071 SMB_ASSERT(!smb_fname_dst->stream_name);
7073 smb_fname_src->stream_name = NULL;
7074 smb_fname_dst->stream_name = NULL;
7076 if (strequal(fname_src_mask,"????????.???")) {
7077 TALLOC_FREE(fname_src_mask);
7078 fname_src_mask = talloc_strdup(ctx, "*");
7079 if (!fname_src_mask) {
7080 reply_nterror(req, NT_STATUS_NO_MEMORY);
7081 goto out;
7085 status = check_name(conn, fname_src_dir);
7086 if (!NT_STATUS_IS_OK(status)) {
7087 reply_nterror(req, status);
7088 goto out;
7091 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7092 if (dir_hnd == NULL) {
7093 status = map_nt_error_from_unix(errno);
7094 reply_nterror(req, status);
7095 goto out;
7098 error = ERRbadfile;
7100 /* Iterate over the src dir copying each entry to the dst. */
7101 while ((dname = ReadDirName(dir_hnd, &offset,
7102 &smb_fname_src->st, &talloced))) {
7103 char *destname = NULL;
7105 if (ISDOT(dname) || ISDOTDOT(dname)) {
7106 TALLOC_FREE(talloced);
7107 continue;
7110 if (!is_visible_file(conn, fname_src_dir, dname,
7111 &smb_fname_src->st, false)) {
7112 TALLOC_FREE(talloced);
7113 continue;
7116 if(!mask_match(dname, fname_src_mask,
7117 conn->case_sensitive)) {
7118 TALLOC_FREE(talloced);
7119 continue;
7122 error = ERRnoaccess;
7124 /* Get the src smb_fname struct setup. */
7125 TALLOC_FREE(smb_fname_src->base_name);
7126 if (ISDOT(fname_src_dir)) {
7127 /* Ensure we use canonical names on open. */
7128 smb_fname_src->base_name =
7129 talloc_asprintf(smb_fname_src, "%s",
7130 dname);
7131 } else {
7132 smb_fname_src->base_name =
7133 talloc_asprintf(smb_fname_src, "%s/%s",
7134 fname_src_dir, dname);
7137 if (!smb_fname_src->base_name) {
7138 TALLOC_FREE(dir_hnd);
7139 TALLOC_FREE(talloced);
7140 reply_nterror(req, NT_STATUS_NO_MEMORY);
7141 goto out;
7144 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7145 smb_fname_dst->base_name,
7146 &destname)) {
7147 TALLOC_FREE(talloced);
7148 continue;
7150 if (!destname) {
7151 TALLOC_FREE(dir_hnd);
7152 TALLOC_FREE(talloced);
7153 reply_nterror(req, NT_STATUS_NO_MEMORY);
7154 goto out;
7157 TALLOC_FREE(smb_fname_dst->base_name);
7158 smb_fname_dst->base_name = destname;
7160 status = check_name(conn, smb_fname_src->base_name);
7161 if (!NT_STATUS_IS_OK(status)) {
7162 TALLOC_FREE(dir_hnd);
7163 TALLOC_FREE(talloced);
7164 reply_nterror(req, status);
7165 goto out;
7168 status = check_name(conn, smb_fname_dst->base_name);
7169 if (!NT_STATUS_IS_OK(status)) {
7170 TALLOC_FREE(dir_hnd);
7171 TALLOC_FREE(talloced);
7172 reply_nterror(req, status);
7173 goto out;
7176 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7177 smb_fname_src->base_name,
7178 smb_fname_dst->base_name));
7180 status = copy_file(ctx, conn, smb_fname_src,
7181 smb_fname_dst, ofun, count,
7182 target_is_directory);
7183 if (NT_STATUS_IS_OK(status)) {
7184 count++;
7187 TALLOC_FREE(talloced);
7189 TALLOC_FREE(dir_hnd);
7192 if (count == 0) {
7193 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7194 goto out;
7197 reply_outbuf(req, 1, 0);
7198 SSVAL(req->outbuf,smb_vwv0,count);
7199 out:
7200 TALLOC_FREE(smb_fname_src);
7201 TALLOC_FREE(smb_fname_dst);
7202 TALLOC_FREE(fname_src);
7203 TALLOC_FREE(fname_dst);
7204 TALLOC_FREE(fname_src_mask);
7205 TALLOC_FREE(fname_src_dir);
7207 END_PROFILE(SMBcopy);
7208 return;
7211 #undef DBGC_CLASS
7212 #define DBGC_CLASS DBGC_LOCKING
7214 /****************************************************************************
7215 Get a lock pid, dealing with large count requests.
7216 ****************************************************************************/
7218 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7219 bool large_file_format)
7221 if(!large_file_format)
7222 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7223 else
7224 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7227 /****************************************************************************
7228 Get a lock count, dealing with large count requests.
7229 ****************************************************************************/
7231 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7232 bool large_file_format)
7234 uint64_t count = 0;
7236 if(!large_file_format) {
7237 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7238 } else {
7240 #if defined(HAVE_LONGLONG)
7241 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7242 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7243 #else /* HAVE_LONGLONG */
7246 * NT4.x seems to be broken in that it sends large file (64 bit)
7247 * lockingX calls even if the CAP_LARGE_FILES was *not*
7248 * negotiated. For boxes without large unsigned ints truncate the
7249 * lock count by dropping the top 32 bits.
7252 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7253 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7254 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7255 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7256 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7259 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7260 #endif /* HAVE_LONGLONG */
7263 return count;
7266 #if !defined(HAVE_LONGLONG)
7267 /****************************************************************************
7268 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7269 ****************************************************************************/
7271 static uint32 map_lock_offset(uint32 high, uint32 low)
7273 unsigned int i;
7274 uint32 mask = 0;
7275 uint32 highcopy = high;
7278 * Try and find out how many significant bits there are in high.
7281 for(i = 0; highcopy; i++)
7282 highcopy >>= 1;
7285 * We use 31 bits not 32 here as POSIX
7286 * lock offsets may not be negative.
7289 mask = (~0) << (31 - i);
7291 if(low & mask)
7292 return 0; /* Fail. */
7294 high <<= (31 - i);
7296 return (high|low);
7298 #endif /* !defined(HAVE_LONGLONG) */
7300 /****************************************************************************
7301 Get a lock offset, dealing with large offset requests.
7302 ****************************************************************************/
7304 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7305 bool large_file_format, bool *err)
7307 uint64_t offset = 0;
7309 *err = False;
7311 if(!large_file_format) {
7312 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7313 } else {
7315 #if defined(HAVE_LONGLONG)
7316 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7317 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7318 #else /* HAVE_LONGLONG */
7321 * NT4.x seems to be broken in that it sends large file (64 bit)
7322 * lockingX calls even if the CAP_LARGE_FILES was *not*
7323 * negotiated. For boxes without large unsigned ints mangle the
7324 * lock offset by mapping the top 32 bits onto the lower 32.
7327 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7328 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7329 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7330 uint32 new_low = 0;
7332 if((new_low = map_lock_offset(high, low)) == 0) {
7333 *err = True;
7334 return (uint64_t)-1;
7337 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7338 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7339 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7340 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7343 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7344 #endif /* HAVE_LONGLONG */
7347 return offset;
7350 NTSTATUS smbd_do_locking(struct smb_request *req,
7351 files_struct *fsp,
7352 uint8_t type,
7353 int32_t timeout,
7354 uint16_t num_ulocks,
7355 struct smbd_lock_element *ulocks,
7356 uint16_t num_locks,
7357 struct smbd_lock_element *locks,
7358 bool *async)
7360 connection_struct *conn = req->conn;
7361 int i;
7362 NTSTATUS status = NT_STATUS_OK;
7364 *async = false;
7366 /* Data now points at the beginning of the list
7367 of smb_unlkrng structs */
7368 for(i = 0; i < (int)num_ulocks; i++) {
7369 struct smbd_lock_element *e = &ulocks[i];
7371 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7372 "pid %u, file %s\n",
7373 (double)e->offset,
7374 (double)e->count,
7375 (unsigned int)e->smblctx,
7376 fsp_str_dbg(fsp)));
7378 if (e->brltype != UNLOCK_LOCK) {
7379 /* this can only happen with SMB2 */
7380 return NT_STATUS_INVALID_PARAMETER;
7383 status = do_unlock(req->sconn->msg_ctx,
7384 fsp,
7385 e->smblctx,
7386 e->count,
7387 e->offset,
7388 WINDOWS_LOCK);
7390 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7391 nt_errstr(status)));
7393 if (!NT_STATUS_IS_OK(status)) {
7394 return status;
7398 /* Setup the timeout in seconds. */
7400 if (!lp_blocking_locks(SNUM(conn))) {
7401 timeout = 0;
7404 /* Data now points at the beginning of the list
7405 of smb_lkrng structs */
7407 for(i = 0; i < (int)num_locks; i++) {
7408 struct smbd_lock_element *e = &locks[i];
7410 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7411 "%llu, file %s timeout = %d\n",
7412 (double)e->offset,
7413 (double)e->count,
7414 (unsigned long long)e->smblctx,
7415 fsp_str_dbg(fsp),
7416 (int)timeout));
7418 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7419 struct blocking_lock_record *blr = NULL;
7421 if (num_locks > 1) {
7423 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7424 * if the lock vector contains one entry. When given mutliple cancel
7425 * requests in a single PDU we expect the server to return an
7426 * error. Windows servers seem to accept the request but only
7427 * cancel the first lock.
7428 * JRA - Do what Windows does (tm) :-).
7431 #if 0
7432 /* MS-CIFS (2.2.4.32.1) behavior. */
7433 return NT_STATUS_DOS(ERRDOS,
7434 ERRcancelviolation);
7435 #else
7436 /* Windows behavior. */
7437 if (i != 0) {
7438 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7439 "cancel request\n"));
7440 continue;
7442 #endif
7445 if (lp_blocking_locks(SNUM(conn))) {
7447 /* Schedule a message to ourselves to
7448 remove the blocking lock record and
7449 return the right error. */
7451 blr = blocking_lock_cancel_smb1(fsp,
7452 e->smblctx,
7453 e->offset,
7454 e->count,
7455 WINDOWS_LOCK,
7456 type,
7457 NT_STATUS_FILE_LOCK_CONFLICT);
7458 if (blr == NULL) {
7459 return NT_STATUS_DOS(
7460 ERRDOS,
7461 ERRcancelviolation);
7464 /* Remove a matching pending lock. */
7465 status = do_lock_cancel(fsp,
7466 e->smblctx,
7467 e->count,
7468 e->offset,
7469 WINDOWS_LOCK,
7470 blr);
7471 } else {
7472 bool blocking_lock = timeout ? true : false;
7473 bool defer_lock = false;
7474 struct byte_range_lock *br_lck;
7475 uint64_t block_smblctx;
7477 br_lck = do_lock(req->sconn->msg_ctx,
7478 fsp,
7479 e->smblctx,
7480 e->count,
7481 e->offset,
7482 e->brltype,
7483 WINDOWS_LOCK,
7484 blocking_lock,
7485 &status,
7486 &block_smblctx,
7487 NULL);
7489 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7490 /* Windows internal resolution for blocking locks seems
7491 to be about 200ms... Don't wait for less than that. JRA. */
7492 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7493 timeout = lp_lock_spin_time();
7495 defer_lock = true;
7498 /* If a lock sent with timeout of zero would fail, and
7499 * this lock has been requested multiple times,
7500 * according to brl_lock_failed() we convert this
7501 * request to a blocking lock with a timeout of between
7502 * 150 - 300 milliseconds.
7504 * If lp_lock_spin_time() has been set to 0, we skip
7505 * this blocking retry and fail immediately.
7507 * Replacement for do_lock_spin(). JRA. */
7509 if (!req->sconn->using_smb2 &&
7510 br_lck && lp_blocking_locks(SNUM(conn)) &&
7511 lp_lock_spin_time() && !blocking_lock &&
7512 NT_STATUS_EQUAL((status),
7513 NT_STATUS_FILE_LOCK_CONFLICT))
7515 defer_lock = true;
7516 timeout = lp_lock_spin_time();
7519 if (br_lck && defer_lock) {
7521 * A blocking lock was requested. Package up
7522 * this smb into a queued request and push it
7523 * onto the blocking lock queue.
7525 if(push_blocking_lock_request(br_lck,
7526 req,
7527 fsp,
7528 timeout,
7530 e->smblctx,
7531 e->brltype,
7532 WINDOWS_LOCK,
7533 e->offset,
7534 e->count,
7535 block_smblctx)) {
7536 TALLOC_FREE(br_lck);
7537 *async = true;
7538 return NT_STATUS_OK;
7542 TALLOC_FREE(br_lck);
7545 if (!NT_STATUS_IS_OK(status)) {
7546 break;
7550 /* If any of the above locks failed, then we must unlock
7551 all of the previous locks (X/Open spec). */
7553 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7555 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7556 i = -1; /* we want to skip the for loop */
7560 * Ensure we don't do a remove on the lock that just failed,
7561 * as under POSIX rules, if we have a lock already there, we
7562 * will delete it (and we shouldn't) .....
7564 for(i--; i >= 0; i--) {
7565 struct smbd_lock_element *e = &locks[i];
7567 do_unlock(req->sconn->msg_ctx,
7568 fsp,
7569 e->smblctx,
7570 e->count,
7571 e->offset,
7572 WINDOWS_LOCK);
7574 return status;
7577 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7578 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7580 return NT_STATUS_OK;
7583 /****************************************************************************
7584 Reply to a lockingX request.
7585 ****************************************************************************/
7587 void reply_lockingX(struct smb_request *req)
7589 connection_struct *conn = req->conn;
7590 files_struct *fsp;
7591 unsigned char locktype;
7592 unsigned char oplocklevel;
7593 uint16 num_ulocks;
7594 uint16 num_locks;
7595 int32 lock_timeout;
7596 int i;
7597 const uint8_t *data;
7598 bool large_file_format;
7599 bool err;
7600 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7601 struct smbd_lock_element *ulocks;
7602 struct smbd_lock_element *locks;
7603 bool async = false;
7605 START_PROFILE(SMBlockingX);
7607 if (req->wct < 8) {
7608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7609 END_PROFILE(SMBlockingX);
7610 return;
7613 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7614 locktype = CVAL(req->vwv+3, 0);
7615 oplocklevel = CVAL(req->vwv+3, 1);
7616 num_ulocks = SVAL(req->vwv+6, 0);
7617 num_locks = SVAL(req->vwv+7, 0);
7618 lock_timeout = IVAL(req->vwv+4, 0);
7619 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7621 if (!check_fsp(conn, req, fsp)) {
7622 END_PROFILE(SMBlockingX);
7623 return;
7626 data = req->buf;
7628 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7629 /* we don't support these - and CANCEL_LOCK makes w2k
7630 and XP reboot so I don't really want to be
7631 compatible! (tridge) */
7632 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7633 END_PROFILE(SMBlockingX);
7634 return;
7637 /* Check if this is an oplock break on a file
7638 we have granted an oplock on.
7640 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7641 /* Client can insist on breaking to none. */
7642 bool break_to_none = (oplocklevel == 0);
7643 bool result;
7645 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7646 "for fnum = %d\n", (unsigned int)oplocklevel,
7647 fsp->fnum ));
7650 * Make sure we have granted an exclusive or batch oplock on
7651 * this file.
7654 if (fsp->oplock_type == 0) {
7656 /* The Samba4 nbench simulator doesn't understand
7657 the difference between break to level2 and break
7658 to none from level2 - it sends oplock break
7659 replies in both cases. Don't keep logging an error
7660 message here - just ignore it. JRA. */
7662 DEBUG(5,("reply_lockingX: Error : oplock break from "
7663 "client for fnum = %d (oplock=%d) and no "
7664 "oplock granted on this file (%s).\n",
7665 fsp->fnum, fsp->oplock_type,
7666 fsp_str_dbg(fsp)));
7668 /* if this is a pure oplock break request then don't
7669 * send a reply */
7670 if (num_locks == 0 && num_ulocks == 0) {
7671 END_PROFILE(SMBlockingX);
7672 return;
7673 } else {
7674 END_PROFILE(SMBlockingX);
7675 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7676 return;
7680 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7681 (break_to_none)) {
7682 result = remove_oplock(fsp);
7683 } else {
7684 result = downgrade_oplock(fsp);
7687 if (!result) {
7688 DEBUG(0, ("reply_lockingX: error in removing "
7689 "oplock on file %s\n", fsp_str_dbg(fsp)));
7690 /* Hmmm. Is this panic justified? */
7691 smb_panic("internal tdb error");
7694 reply_to_oplock_break_requests(fsp);
7696 /* if this is a pure oplock break request then don't send a
7697 * reply */
7698 if (num_locks == 0 && num_ulocks == 0) {
7699 /* Sanity check - ensure a pure oplock break is not a
7700 chained request. */
7701 if(CVAL(req->vwv+0, 0) != 0xff)
7702 DEBUG(0,("reply_lockingX: Error : pure oplock "
7703 "break is a chained %d request !\n",
7704 (unsigned int)CVAL(req->vwv+0, 0)));
7705 END_PROFILE(SMBlockingX);
7706 return;
7710 if (req->buflen <
7711 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7713 END_PROFILE(SMBlockingX);
7714 return;
7717 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7718 if (ulocks == NULL) {
7719 reply_nterror(req, NT_STATUS_NO_MEMORY);
7720 END_PROFILE(SMBlockingX);
7721 return;
7724 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7725 if (locks == NULL) {
7726 reply_nterror(req, NT_STATUS_NO_MEMORY);
7727 END_PROFILE(SMBlockingX);
7728 return;
7731 /* Data now points at the beginning of the list
7732 of smb_unlkrng structs */
7733 for(i = 0; i < (int)num_ulocks; i++) {
7734 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7735 ulocks[i].count = get_lock_count(data, i, large_file_format);
7736 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7737 ulocks[i].brltype = UNLOCK_LOCK;
7740 * There is no error code marked "stupid client bug".... :-).
7742 if(err) {
7743 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7744 END_PROFILE(SMBlockingX);
7745 return;
7749 /* Now do any requested locks */
7750 data += ((large_file_format ? 20 : 10)*num_ulocks);
7752 /* Data now points at the beginning of the list
7753 of smb_lkrng structs */
7755 for(i = 0; i < (int)num_locks; i++) {
7756 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7757 locks[i].count = get_lock_count(data, i, large_file_format);
7758 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7760 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7761 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7762 locks[i].brltype = PENDING_READ_LOCK;
7763 } else {
7764 locks[i].brltype = READ_LOCK;
7766 } else {
7767 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7768 locks[i].brltype = PENDING_WRITE_LOCK;
7769 } else {
7770 locks[i].brltype = WRITE_LOCK;
7775 * There is no error code marked "stupid client bug".... :-).
7777 if(err) {
7778 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7779 END_PROFILE(SMBlockingX);
7780 return;
7784 status = smbd_do_locking(req, fsp,
7785 locktype, lock_timeout,
7786 num_ulocks, ulocks,
7787 num_locks, locks,
7788 &async);
7789 if (!NT_STATUS_IS_OK(status)) {
7790 END_PROFILE(SMBlockingX);
7791 reply_nterror(req, status);
7792 return;
7794 if (async) {
7795 END_PROFILE(SMBlockingX);
7796 return;
7799 reply_outbuf(req, 2, 0);
7801 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7802 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7804 END_PROFILE(SMBlockingX);
7805 chain_reply(req);
7808 #undef DBGC_CLASS
7809 #define DBGC_CLASS DBGC_ALL
7811 /****************************************************************************
7812 Reply to a SMBreadbmpx (read block multiplex) request.
7813 Always reply with an error, if someone has a platform really needs this,
7814 please contact vl@samba.org
7815 ****************************************************************************/
7817 void reply_readbmpx(struct smb_request *req)
7819 START_PROFILE(SMBreadBmpx);
7820 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7821 END_PROFILE(SMBreadBmpx);
7822 return;
7825 /****************************************************************************
7826 Reply to a SMBreadbs (read block multiplex secondary) request.
7827 Always reply with an error, if someone has a platform really needs this,
7828 please contact vl@samba.org
7829 ****************************************************************************/
7831 void reply_readbs(struct smb_request *req)
7833 START_PROFILE(SMBreadBs);
7834 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7835 END_PROFILE(SMBreadBs);
7836 return;
7839 /****************************************************************************
7840 Reply to a SMBsetattrE.
7841 ****************************************************************************/
7843 void reply_setattrE(struct smb_request *req)
7845 connection_struct *conn = req->conn;
7846 struct smb_file_time ft;
7847 files_struct *fsp;
7848 NTSTATUS status;
7850 START_PROFILE(SMBsetattrE);
7851 ZERO_STRUCT(ft);
7853 if (req->wct < 7) {
7854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7855 goto out;
7858 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7860 if(!fsp || (fsp->conn != conn)) {
7861 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7862 goto out;
7866 * Convert the DOS times into unix times.
7869 ft.atime = convert_time_t_to_timespec(
7870 srv_make_unix_date2(req->vwv+3));
7871 ft.mtime = convert_time_t_to_timespec(
7872 srv_make_unix_date2(req->vwv+5));
7873 ft.create_time = convert_time_t_to_timespec(
7874 srv_make_unix_date2(req->vwv+1));
7876 reply_outbuf(req, 0, 0);
7879 * Patch from Ray Frush <frush@engr.colostate.edu>
7880 * Sometimes times are sent as zero - ignore them.
7883 /* Ensure we have a valid stat struct for the source. */
7884 status = vfs_stat_fsp(fsp);
7885 if (!NT_STATUS_IS_OK(status)) {
7886 reply_nterror(req, status);
7887 goto out;
7890 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7891 if (!NT_STATUS_IS_OK(status)) {
7892 reply_nterror(req, status);
7893 goto out;
7896 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7897 " createtime=%u\n",
7898 fsp->fnum,
7899 (unsigned int)ft.atime.tv_sec,
7900 (unsigned int)ft.mtime.tv_sec,
7901 (unsigned int)ft.create_time.tv_sec
7903 out:
7904 END_PROFILE(SMBsetattrE);
7905 return;
7909 /* Back from the dead for OS/2..... JRA. */
7911 /****************************************************************************
7912 Reply to a SMBwritebmpx (write block multiplex primary) request.
7913 Always reply with an error, if someone has a platform really needs this,
7914 please contact vl@samba.org
7915 ****************************************************************************/
7917 void reply_writebmpx(struct smb_request *req)
7919 START_PROFILE(SMBwriteBmpx);
7920 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7921 END_PROFILE(SMBwriteBmpx);
7922 return;
7925 /****************************************************************************
7926 Reply to a SMBwritebs (write block multiplex secondary) request.
7927 Always reply with an error, if someone has a platform really needs this,
7928 please contact vl@samba.org
7929 ****************************************************************************/
7931 void reply_writebs(struct smb_request *req)
7933 START_PROFILE(SMBwriteBs);
7934 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7935 END_PROFILE(SMBwriteBs);
7936 return;
7939 /****************************************************************************
7940 Reply to a SMBgetattrE.
7941 ****************************************************************************/
7943 void reply_getattrE(struct smb_request *req)
7945 connection_struct *conn = req->conn;
7946 int mode;
7947 files_struct *fsp;
7948 struct timespec create_ts;
7950 START_PROFILE(SMBgetattrE);
7952 if (req->wct < 1) {
7953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7954 END_PROFILE(SMBgetattrE);
7955 return;
7958 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7960 if(!fsp || (fsp->conn != conn)) {
7961 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7962 END_PROFILE(SMBgetattrE);
7963 return;
7966 /* Do an fstat on this file */
7967 if(fsp_stat(fsp)) {
7968 reply_nterror(req, map_nt_error_from_unix(errno));
7969 END_PROFILE(SMBgetattrE);
7970 return;
7973 mode = dos_mode(conn, fsp->fsp_name);
7976 * Convert the times into dos times. Set create
7977 * date to be last modify date as UNIX doesn't save
7978 * this.
7981 reply_outbuf(req, 11, 0);
7983 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7984 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7985 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7986 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7987 /* Should we check pending modtime here ? JRA */
7988 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7989 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7991 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7992 SIVAL(req->outbuf, smb_vwv6, 0);
7993 SIVAL(req->outbuf, smb_vwv8, 0);
7994 } else {
7995 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7996 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7997 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7999 SSVAL(req->outbuf,smb_vwv10, mode);
8001 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8003 END_PROFILE(SMBgetattrE);
8004 return;