samba-tool/testparm: Fix traceback when checking client name/ip against hosts allowed.
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blob0adc4e80f69ef654932f1f8d519390546e51b7a0
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"
42 #include "../lib/tsocket/tsocket.h"
44 /****************************************************************************
45 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
46 path or anything including wildcards.
47 We're assuming here that '/' is not the second byte in any multibyte char
48 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
49 set.
50 ****************************************************************************/
52 /* Custom version for processing POSIX paths. */
53 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
55 static NTSTATUS check_path_syntax_internal(char *path,
56 bool posix_path,
57 bool *p_last_component_contains_wcard)
59 char *d = path;
60 const char *s = path;
61 NTSTATUS ret = NT_STATUS_OK;
62 bool start_of_name_component = True;
63 bool stream_started = false;
65 *p_last_component_contains_wcard = False;
67 while (*s) {
68 if (stream_started) {
69 switch (*s) {
70 case '/':
71 case '\\':
72 return NT_STATUS_OBJECT_NAME_INVALID;
73 case ':':
74 if (s[1] == '\0') {
75 return NT_STATUS_OBJECT_NAME_INVALID;
77 if (strchr_m(&s[1], ':')) {
78 return NT_STATUS_OBJECT_NAME_INVALID;
80 break;
84 if ((*s == ':') && !posix_path && !stream_started) {
85 if (*p_last_component_contains_wcard) {
86 return NT_STATUS_OBJECT_NAME_INVALID;
88 /* Stream names allow more characters than file names.
89 We're overloading posix_path here to allow a wider
90 range of characters. If stream_started is true this
91 is still a Windows path even if posix_path is true.
92 JRA.
94 stream_started = true;
95 start_of_name_component = false;
96 posix_path = true;
98 if (s[1] == '\0') {
99 return NT_STATUS_OBJECT_NAME_INVALID;
103 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
105 * Safe to assume is not the second part of a mb char
106 * as this is handled below.
108 /* Eat multiple '/' or '\\' */
109 while (IS_PATH_SEP(*s,posix_path)) {
110 s++;
112 if ((d != path) && (*s != '\0')) {
113 /* We only care about non-leading or trailing '/' or '\\' */
114 *d++ = '/';
117 start_of_name_component = True;
118 /* New component. */
119 *p_last_component_contains_wcard = False;
120 continue;
123 if (start_of_name_component) {
124 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
125 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
128 * No mb char starts with '.' so we're safe checking the directory separator here.
131 /* If we just added a '/' - delete it */
132 if ((d > path) && (*(d-1) == '/')) {
133 *(d-1) = '\0';
134 d--;
137 /* Are we at the start ? Can't go back further if so. */
138 if (d <= path) {
139 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
140 break;
142 /* Go back one level... */
143 /* We know this is safe as '/' cannot be part of a mb sequence. */
144 /* NOTE - if this assumption is invalid we are not in good shape... */
145 /* Decrement d first as d points to the *next* char to write into. */
146 for (d--; d > path; d--) {
147 if (*d == '/')
148 break;
150 s += 2; /* Else go past the .. */
151 /* We're still at the start of a name component, just the previous one. */
152 continue;
154 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
155 if (posix_path) {
156 /* Eat the '.' */
157 s++;
158 continue;
164 if (!(*s & 0x80)) {
165 if (!posix_path) {
166 if (*s <= 0x1f || *s == '|') {
167 return NT_STATUS_OBJECT_NAME_INVALID;
169 switch (*s) {
170 case '*':
171 case '?':
172 case '<':
173 case '>':
174 case '"':
175 *p_last_component_contains_wcard = True;
176 break;
177 default:
178 break;
181 *d++ = *s++;
182 } else {
183 size_t siz;
184 /* Get the size of the next MB character. */
185 next_codepoint(s,&siz);
186 switch(siz) {
187 case 5:
188 *d++ = *s++;
189 /*fall through*/
190 case 4:
191 *d++ = *s++;
192 /*fall through*/
193 case 3:
194 *d++ = *s++;
195 /*fall through*/
196 case 2:
197 *d++ = *s++;
198 /*fall through*/
199 case 1:
200 *d++ = *s++;
201 break;
202 default:
203 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
204 *d = '\0';
205 return NT_STATUS_INVALID_PARAMETER;
208 start_of_name_component = False;
211 *d = '\0';
213 return ret;
216 /****************************************************************************
217 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
218 No wildcards allowed.
219 ****************************************************************************/
221 NTSTATUS check_path_syntax(char *path)
223 bool ignore;
224 return check_path_syntax_internal(path, False, &ignore);
227 /****************************************************************************
228 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
229 Wildcards allowed - p_contains_wcard returns true if the last component contained
230 a wildcard.
231 ****************************************************************************/
233 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
235 return check_path_syntax_internal(path, False, p_contains_wcard);
238 /****************************************************************************
239 Check the path for a POSIX client.
240 We're assuming here that '/' is not the second byte in any multibyte char
241 set (a safe assumption).
242 ****************************************************************************/
244 NTSTATUS check_path_syntax_posix(char *path)
246 bool ignore;
247 return check_path_syntax_internal(path, True, &ignore);
250 /****************************************************************************
251 Pull a string and check the path allowing a wilcard - provide for error return.
252 ****************************************************************************/
254 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
255 const char *base_ptr,
256 uint16 smb_flags2,
257 char **pp_dest,
258 const char *src,
259 size_t src_len,
260 int flags,
261 NTSTATUS *err,
262 bool *contains_wcard)
264 size_t ret;
266 *pp_dest = NULL;
268 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
269 src_len, flags);
271 if (!*pp_dest) {
272 *err = NT_STATUS_INVALID_PARAMETER;
273 return ret;
276 *contains_wcard = False;
278 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
280 * For a DFS path the function parse_dfs_path()
281 * will do the path processing, just make a copy.
283 *err = NT_STATUS_OK;
284 return ret;
287 if (lp_posix_pathnames()) {
288 *err = check_path_syntax_posix(*pp_dest);
289 } else {
290 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
293 return ret;
296 /****************************************************************************
297 Pull a string and check the path - provide for error return.
298 ****************************************************************************/
300 size_t srvstr_get_path(TALLOC_CTX *ctx,
301 const char *base_ptr,
302 uint16 smb_flags2,
303 char **pp_dest,
304 const char *src,
305 size_t src_len,
306 int flags,
307 NTSTATUS *err)
309 bool ignore;
310 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
311 src_len, flags, err, &ignore);
314 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
315 char **pp_dest, const char *src, int flags,
316 NTSTATUS *err, bool *contains_wcard)
318 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
319 pp_dest, src, smbreq_bufrem(req, src),
320 flags, err, contains_wcard);
323 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
324 char **pp_dest, const char *src, int flags,
325 NTSTATUS *err)
327 bool ignore;
328 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
329 flags, err, &ignore);
332 /****************************************************************************
333 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
334 ****************************************************************************/
336 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
337 files_struct *fsp)
339 if ((fsp == NULL) || (conn == NULL)) {
340 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
341 return False;
343 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
344 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
345 return False;
347 return True;
350 /****************************************************************************
351 Check if we have a correct fsp pointing to a file.
352 ****************************************************************************/
354 bool check_fsp(connection_struct *conn, struct smb_request *req,
355 files_struct *fsp)
357 if (!check_fsp_open(conn, req, fsp)) {
358 return False;
360 if (fsp->is_directory) {
361 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
362 return False;
364 if (fsp->fh->fd == -1) {
365 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
366 return False;
368 fsp->num_smb_operations++;
369 return True;
372 /****************************************************************************
373 Check if we have a correct fsp pointing to a quota fake file. Replacement for
374 the CHECK_NTQUOTA_HANDLE_OK macro.
375 ****************************************************************************/
377 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
378 files_struct *fsp)
380 if (!check_fsp_open(conn, req, fsp)) {
381 return false;
384 if (fsp->is_directory) {
385 return false;
388 if (fsp->fake_file_handle == NULL) {
389 return false;
392 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
393 return false;
396 if (fsp->fake_file_handle->private_data == NULL) {
397 return false;
400 return true;
403 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
404 const char *name, int name_type)
406 char *trim_name;
407 char *trim_name_type;
408 const char *retarget_parm;
409 char *retarget;
410 char *p;
411 int retarget_type = 0x20;
412 int retarget_port = 139;
413 struct sockaddr_storage retarget_addr;
414 struct sockaddr_in *in_addr;
415 bool ret = false;
416 uint8_t outbuf[10];
418 if (get_socket_port(sconn->sock) != 139) {
419 return false;
422 trim_name = talloc_strdup(talloc_tos(), name);
423 if (trim_name == NULL) {
424 goto fail;
426 trim_char(trim_name, ' ', ' ');
428 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
429 name_type);
430 if (trim_name_type == NULL) {
431 goto fail;
434 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
435 trim_name_type, NULL);
436 if (retarget_parm == NULL) {
437 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
438 trim_name, NULL);
440 if (retarget_parm == NULL) {
441 goto fail;
444 retarget = talloc_strdup(trim_name, retarget_parm);
445 if (retarget == NULL) {
446 goto fail;
449 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
451 p = strchr(retarget, ':');
452 if (p != NULL) {
453 *p++ = '\0';
454 retarget_port = atoi(p);
457 p = strchr_m(retarget, '#');
458 if (p != NULL) {
459 *p++ = '\0';
460 if (sscanf(p, "%x", &retarget_type) != 1) {
461 goto fail;
465 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
466 if (!ret) {
467 DEBUG(10, ("could not resolve %s\n", retarget));
468 goto fail;
471 if (retarget_addr.ss_family != AF_INET) {
472 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
473 goto fail;
476 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
478 _smb_setlen(outbuf, 6);
479 SCVAL(outbuf, 0, 0x84);
480 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
481 *(uint16_t *)(outbuf+8) = htons(retarget_port);
483 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
484 NULL)) {
485 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
486 "failed.");
489 ret = true;
490 fail:
491 TALLOC_FREE(trim_name);
492 return ret;
495 static void reply_called_name_not_present(char *outbuf)
497 smb_setlen(outbuf, 1);
498 SCVAL(outbuf, 0, 0x83);
499 SCVAL(outbuf, 4, 0x82);
502 /****************************************************************************
503 Reply to a (netbios-level) special message.
504 ****************************************************************************/
506 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
508 int msg_type = CVAL(inbuf,0);
509 int msg_flags = CVAL(inbuf,1);
511 * We only really use 4 bytes of the outbuf, but for the smb_setlen
512 * calculation & friends (srv_send_smb uses that) we need the full smb
513 * header.
515 char outbuf[smb_size];
517 memset(outbuf, '\0', sizeof(outbuf));
519 smb_setlen(outbuf,0);
521 switch (msg_type) {
522 case NBSSrequest: /* session request */
524 /* inbuf_size is guarenteed to be at least 4. */
525 fstring name1,name2;
526 int name_type1, name_type2;
527 int name_len1, name_len2;
529 *name1 = *name2 = 0;
531 if (sconn->nbt.got_session) {
532 exit_server_cleanly("multiple session request not permitted");
535 SCVAL(outbuf,0,NBSSpositive);
536 SCVAL(outbuf,3,0);
538 /* inbuf_size is guaranteed to be at least 4. */
539 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
540 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
541 DEBUG(0,("Invalid name length in session request\n"));
542 reply_called_name_not_present(outbuf);
543 break;
545 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
546 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
547 DEBUG(0,("Invalid name length in session request\n"));
548 reply_called_name_not_present(outbuf);
549 break;
552 name_type1 = name_extract((unsigned char *)inbuf,
553 inbuf_size,(unsigned int)4,name1);
554 name_type2 = name_extract((unsigned char *)inbuf,
555 inbuf_size,(unsigned int)(4 + name_len1),name2);
557 if (name_type1 == -1 || name_type2 == -1) {
558 DEBUG(0,("Invalid name type in session request\n"));
559 reply_called_name_not_present(outbuf);
560 break;
563 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
564 name1, name_type1, name2, name_type2));
566 if (netbios_session_retarget(sconn, name1, name_type1)) {
567 exit_server_cleanly("retargeted client");
571 * Windows NT/2k uses "*SMBSERVER" and XP uses
572 * "*SMBSERV" arrggg!!!
574 if (strequal(name1, "*SMBSERVER ")
575 || strequal(name1, "*SMBSERV ")) {
576 char *raddr;
578 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
579 talloc_tos());
580 if (raddr == NULL) {
581 exit_server_cleanly("could not allocate raddr");
584 fstrcpy(name1, raddr);
587 set_local_machine_name(name1, True);
588 set_remote_machine_name(name2, True);
590 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
591 get_local_machine_name(), get_remote_machine_name(),
592 name_type2));
594 if (name_type2 == 'R') {
595 /* We are being asked for a pathworks session ---
596 no thanks! */
597 reply_called_name_not_present(outbuf);
598 break;
601 /* only add the client's machine name to the list
602 of possibly valid usernames if we are operating
603 in share mode security */
604 if (lp_security() == SEC_SHARE) {
605 add_session_user(sconn, get_remote_machine_name());
608 reload_services(sconn->msg_ctx, sconn->sock, True);
609 reopen_logs();
611 sconn->nbt.got_session = true;
612 break;
615 case 0x89: /* session keepalive request
616 (some old clients produce this?) */
617 SCVAL(outbuf,0,NBSSkeepalive);
618 SCVAL(outbuf,3,0);
619 break;
621 case NBSSpositive: /* positive session response */
622 case NBSSnegative: /* negative session response */
623 case NBSSretarget: /* retarget session response */
624 DEBUG(0,("Unexpected session response\n"));
625 break;
627 case NBSSkeepalive: /* session keepalive */
628 default:
629 return;
632 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
633 msg_type, msg_flags));
635 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
637 if (CVAL(outbuf, 0) != 0x82) {
638 exit_server_cleanly("invalid netbios session");
640 return;
643 /****************************************************************************
644 Reply to a tcon.
645 conn POINTER CAN BE NULL HERE !
646 ****************************************************************************/
648 void reply_tcon(struct smb_request *req)
650 connection_struct *conn = req->conn;
651 const char *service;
652 char *service_buf = NULL;
653 char *password = NULL;
654 char *dev = NULL;
655 int pwlen=0;
656 NTSTATUS nt_status;
657 const char *p;
658 DATA_BLOB password_blob;
659 TALLOC_CTX *ctx = talloc_tos();
660 struct smbd_server_connection *sconn = req->sconn;
662 START_PROFILE(SMBtcon);
664 if (req->buflen < 4) {
665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
666 END_PROFILE(SMBtcon);
667 return;
670 p = (const char *)req->buf + 1;
671 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
672 p += 1;
673 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
674 p += pwlen+1;
675 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
676 p += 1;
678 if (service_buf == NULL || password == NULL || dev == NULL) {
679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
680 END_PROFILE(SMBtcon);
681 return;
683 p = strrchr_m(service_buf,'\\');
684 if (p) {
685 service = p+1;
686 } else {
687 service = service_buf;
690 password_blob = data_blob(password, pwlen+1);
692 conn = make_connection(sconn,service,password_blob,dev,
693 req->vuid,&nt_status);
694 req->conn = conn;
696 data_blob_clear_free(&password_blob);
698 if (!conn) {
699 reply_nterror(req, nt_status);
700 END_PROFILE(SMBtcon);
701 return;
704 reply_outbuf(req, 2, 0);
705 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
706 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
707 SSVAL(req->outbuf,smb_tid,conn->cnum);
709 DEBUG(3,("tcon service=%s cnum=%d\n",
710 service, conn->cnum));
712 END_PROFILE(SMBtcon);
713 return;
716 /****************************************************************************
717 Reply to a tcon and X.
718 conn POINTER CAN BE NULL HERE !
719 ****************************************************************************/
721 void reply_tcon_and_X(struct smb_request *req)
723 connection_struct *conn = req->conn;
724 const char *service = NULL;
725 DATA_BLOB password;
726 TALLOC_CTX *ctx = talloc_tos();
727 /* what the cleint thinks the device is */
728 char *client_devicetype = NULL;
729 /* what the server tells the client the share represents */
730 const char *server_devicetype;
731 NTSTATUS nt_status;
732 int passlen;
733 char *path = NULL;
734 const char *p, *q;
735 uint16 tcon_flags;
736 struct smbd_server_connection *sconn = req->sconn;
738 START_PROFILE(SMBtconX);
740 if (req->wct < 4) {
741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
742 END_PROFILE(SMBtconX);
743 return;
746 passlen = SVAL(req->vwv+3, 0);
747 tcon_flags = SVAL(req->vwv+2, 0);
749 /* we might have to close an old one */
750 if ((tcon_flags & 0x1) && conn) {
751 close_cnum(conn,req->vuid);
752 req->conn = NULL;
753 conn = NULL;
756 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
757 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
758 END_PROFILE(SMBtconX);
759 return;
762 if (sconn->smb1.negprot.encrypted_passwords) {
763 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
764 if (lp_security() == SEC_SHARE) {
766 * Security = share always has a pad byte
767 * after the password.
769 p = (const char *)req->buf + passlen + 1;
770 } else {
771 p = (const char *)req->buf + passlen;
773 } else {
774 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
775 /* Ensure correct termination */
776 password.data[passlen]=0;
777 p = (const char *)req->buf + passlen + 1;
780 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
782 if (path == NULL) {
783 data_blob_clear_free(&password);
784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
785 END_PROFILE(SMBtconX);
786 return;
790 * the service name can be either: \\server\share
791 * or share directly like on the DELL PowerVault 705
793 if (*path=='\\') {
794 q = strchr_m(path+2,'\\');
795 if (!q) {
796 data_blob_clear_free(&password);
797 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
798 END_PROFILE(SMBtconX);
799 return;
801 service = q+1;
802 } else {
803 service = path;
806 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
807 &client_devicetype, p,
808 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
810 if (client_devicetype == NULL) {
811 data_blob_clear_free(&password);
812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
813 END_PROFILE(SMBtconX);
814 return;
817 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
819 conn = make_connection(sconn, service, password, client_devicetype,
820 req->vuid, &nt_status);
821 req->conn =conn;
823 data_blob_clear_free(&password);
825 if (!conn) {
826 reply_nterror(req, nt_status);
827 END_PROFILE(SMBtconX);
828 return;
831 if ( IS_IPC(conn) )
832 server_devicetype = "IPC";
833 else if ( IS_PRINT(conn) )
834 server_devicetype = "LPT1:";
835 else
836 server_devicetype = "A:";
838 if (get_Protocol() < PROTOCOL_NT1) {
839 reply_outbuf(req, 2, 0);
840 if (message_push_string(&req->outbuf, server_devicetype,
841 STR_TERMINATE|STR_ASCII) == -1) {
842 reply_nterror(req, NT_STATUS_NO_MEMORY);
843 END_PROFILE(SMBtconX);
844 return;
846 } else {
847 /* NT sets the fstype of IPC$ to the null string */
848 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
850 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
851 /* Return permissions. */
852 uint32 perm1 = 0;
853 uint32 perm2 = 0;
855 reply_outbuf(req, 7, 0);
857 if (IS_IPC(conn)) {
858 perm1 = FILE_ALL_ACCESS;
859 perm2 = FILE_ALL_ACCESS;
860 } else {
861 perm1 = conn->share_access;
864 SIVAL(req->outbuf, smb_vwv3, perm1);
865 SIVAL(req->outbuf, smb_vwv5, perm2);
866 } else {
867 reply_outbuf(req, 3, 0);
870 if ((message_push_string(&req->outbuf, server_devicetype,
871 STR_TERMINATE|STR_ASCII) == -1)
872 || (message_push_string(&req->outbuf, fstype,
873 STR_TERMINATE) == -1)) {
874 reply_nterror(req, NT_STATUS_NO_MEMORY);
875 END_PROFILE(SMBtconX);
876 return;
879 /* what does setting this bit do? It is set by NT4 and
880 may affect the ability to autorun mounted cdroms */
881 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
882 (lp_csc_policy(SNUM(conn)) << 2));
884 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
885 DEBUG(2,("Serving %s as a Dfs root\n",
886 lp_servicename(SNUM(conn)) ));
887 SSVAL(req->outbuf, smb_vwv2,
888 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
893 DEBUG(3,("tconX service=%s \n",
894 service));
896 /* set the incoming and outgoing tid to the just created one */
897 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
898 SSVAL(req->outbuf,smb_tid,conn->cnum);
900 END_PROFILE(SMBtconX);
902 req->tid = conn->cnum;
903 chain_reply(req);
904 return;
907 /****************************************************************************
908 Reply to an unknown type.
909 ****************************************************************************/
911 void reply_unknown_new(struct smb_request *req, uint8 type)
913 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
914 smb_fn_name(type), type, type));
915 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
916 return;
919 /****************************************************************************
920 Reply to an ioctl.
921 conn POINTER CAN BE NULL HERE !
922 ****************************************************************************/
924 void reply_ioctl(struct smb_request *req)
926 connection_struct *conn = req->conn;
927 uint16 device;
928 uint16 function;
929 uint32 ioctl_code;
930 int replysize;
931 char *p;
933 START_PROFILE(SMBioctl);
935 if (req->wct < 3) {
936 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
937 END_PROFILE(SMBioctl);
938 return;
941 device = SVAL(req->vwv+1, 0);
942 function = SVAL(req->vwv+2, 0);
943 ioctl_code = (device << 16) + function;
945 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
947 switch (ioctl_code) {
948 case IOCTL_QUERY_JOB_INFO:
949 replysize = 32;
950 break;
951 default:
952 reply_force_doserror(req, ERRSRV, ERRnosupport);
953 END_PROFILE(SMBioctl);
954 return;
957 reply_outbuf(req, 8, replysize+1);
958 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
959 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
960 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
961 p = smb_buf(req->outbuf);
962 memset(p, '\0', replysize+1); /* valgrind-safe. */
963 p += 1; /* Allow for alignment */
965 switch (ioctl_code) {
966 case IOCTL_QUERY_JOB_INFO:
968 files_struct *fsp = file_fsp(
969 req, SVAL(req->vwv+0, 0));
970 if (!fsp) {
971 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
972 END_PROFILE(SMBioctl);
973 return;
975 /* Job number */
976 if (fsp->print_file) {
977 SSVAL(p, 0, fsp->print_file->rap_jobid);
978 } else {
979 SSVAL(p, 0, 0);
981 srvstr_push((char *)req->outbuf, req->flags2, p+2,
982 lp_netbios_name(), 15,
983 STR_TERMINATE|STR_ASCII);
984 if (conn) {
985 srvstr_push((char *)req->outbuf, req->flags2,
986 p+18, lp_servicename(SNUM(conn)),
987 13, STR_TERMINATE|STR_ASCII);
988 } else {
989 memset(p+18, 0, 13);
991 break;
995 END_PROFILE(SMBioctl);
996 return;
999 /****************************************************************************
1000 Strange checkpath NTSTATUS mapping.
1001 ****************************************************************************/
1003 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1005 /* Strange DOS error code semantics only for checkpath... */
1006 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1007 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1008 /* We need to map to ERRbadpath */
1009 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1012 return status;
1015 /****************************************************************************
1016 Reply to a checkpath.
1017 ****************************************************************************/
1019 void reply_checkpath(struct smb_request *req)
1021 connection_struct *conn = req->conn;
1022 struct smb_filename *smb_fname = NULL;
1023 char *name = NULL;
1024 NTSTATUS status;
1025 TALLOC_CTX *ctx = talloc_tos();
1027 START_PROFILE(SMBcheckpath);
1029 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1030 STR_TERMINATE, &status);
1032 if (!NT_STATUS_IS_OK(status)) {
1033 status = map_checkpath_error(req->flags2, status);
1034 reply_nterror(req, status);
1035 END_PROFILE(SMBcheckpath);
1036 return;
1039 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1041 status = filename_convert(ctx,
1042 conn,
1043 req->flags2 & FLAGS2_DFS_PATHNAMES,
1044 name,
1046 NULL,
1047 &smb_fname);
1049 if (!NT_STATUS_IS_OK(status)) {
1050 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1051 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1052 ERRSRV, ERRbadpath);
1053 END_PROFILE(SMBcheckpath);
1054 return;
1056 goto path_err;
1059 if (!VALID_STAT(smb_fname->st) &&
1060 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1061 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1062 smb_fname_str_dbg(smb_fname), strerror(errno)));
1063 status = map_nt_error_from_unix(errno);
1064 goto path_err;
1067 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1068 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1069 ERRDOS, ERRbadpath);
1070 goto out;
1073 reply_outbuf(req, 0, 0);
1075 path_err:
1076 /* We special case this - as when a Windows machine
1077 is parsing a path is steps through the components
1078 one at a time - if a component fails it expects
1079 ERRbadpath, not ERRbadfile.
1081 status = map_checkpath_error(req->flags2, status);
1082 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1084 * Windows returns different error codes if
1085 * the parent directory is valid but not the
1086 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1087 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1088 * if the path is invalid.
1090 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1091 ERRDOS, ERRbadpath);
1092 goto out;
1095 reply_nterror(req, status);
1097 out:
1098 TALLOC_FREE(smb_fname);
1099 END_PROFILE(SMBcheckpath);
1100 return;
1103 /****************************************************************************
1104 Reply to a getatr.
1105 ****************************************************************************/
1107 void reply_getatr(struct smb_request *req)
1109 connection_struct *conn = req->conn;
1110 struct smb_filename *smb_fname = NULL;
1111 char *fname = NULL;
1112 int mode=0;
1113 SMB_OFF_T size=0;
1114 time_t mtime=0;
1115 const char *p;
1116 NTSTATUS status;
1117 TALLOC_CTX *ctx = talloc_tos();
1118 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1120 START_PROFILE(SMBgetatr);
1122 p = (const char *)req->buf + 1;
1123 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1124 if (!NT_STATUS_IS_OK(status)) {
1125 reply_nterror(req, status);
1126 goto out;
1129 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1130 under WfWg - weird! */
1131 if (*fname == '\0') {
1132 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1133 if (!CAN_WRITE(conn)) {
1134 mode |= FILE_ATTRIBUTE_READONLY;
1136 size = 0;
1137 mtime = 0;
1138 } else {
1139 status = filename_convert(ctx,
1140 conn,
1141 req->flags2 & FLAGS2_DFS_PATHNAMES,
1142 fname,
1144 NULL,
1145 &smb_fname);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1148 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1149 ERRSRV, ERRbadpath);
1150 goto out;
1152 reply_nterror(req, status);
1153 goto out;
1155 if (!VALID_STAT(smb_fname->st) &&
1156 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1157 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1158 smb_fname_str_dbg(smb_fname),
1159 strerror(errno)));
1160 reply_nterror(req, map_nt_error_from_unix(errno));
1161 goto out;
1164 mode = dos_mode(conn, smb_fname);
1165 size = smb_fname->st.st_ex_size;
1167 if (ask_sharemode) {
1168 struct timespec write_time_ts;
1169 struct file_id fileid;
1171 ZERO_STRUCT(write_time_ts);
1172 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1173 get_file_infos(fileid, 0, NULL, &write_time_ts);
1174 if (!null_timespec(write_time_ts)) {
1175 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1179 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1180 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1181 size = 0;
1185 reply_outbuf(req, 10, 0);
1187 SSVAL(req->outbuf,smb_vwv0,mode);
1188 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1189 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1190 } else {
1191 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1193 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1195 if (get_Protocol() >= PROTOCOL_NT1) {
1196 SSVAL(req->outbuf, smb_flg2,
1197 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1200 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1201 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1203 out:
1204 TALLOC_FREE(smb_fname);
1205 TALLOC_FREE(fname);
1206 END_PROFILE(SMBgetatr);
1207 return;
1210 /****************************************************************************
1211 Reply to a setatr.
1212 ****************************************************************************/
1214 void reply_setatr(struct smb_request *req)
1216 struct smb_file_time ft;
1217 connection_struct *conn = req->conn;
1218 struct smb_filename *smb_fname = NULL;
1219 char *fname = NULL;
1220 int mode;
1221 time_t mtime;
1222 const char *p;
1223 NTSTATUS status;
1224 TALLOC_CTX *ctx = talloc_tos();
1226 START_PROFILE(SMBsetatr);
1228 ZERO_STRUCT(ft);
1230 if (req->wct < 2) {
1231 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1232 goto out;
1235 p = (const char *)req->buf + 1;
1236 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1237 if (!NT_STATUS_IS_OK(status)) {
1238 reply_nterror(req, status);
1239 goto out;
1242 status = filename_convert(ctx,
1243 conn,
1244 req->flags2 & FLAGS2_DFS_PATHNAMES,
1245 fname,
1247 NULL,
1248 &smb_fname);
1249 if (!NT_STATUS_IS_OK(status)) {
1250 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1251 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1252 ERRSRV, ERRbadpath);
1253 goto out;
1255 reply_nterror(req, status);
1256 goto out;
1259 if (smb_fname->base_name[0] == '.' &&
1260 smb_fname->base_name[1] == '\0') {
1262 * Not sure here is the right place to catch this
1263 * condition. Might be moved to somewhere else later -- vl
1265 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1266 goto out;
1269 mode = SVAL(req->vwv+0, 0);
1270 mtime = srv_make_unix_date3(req->vwv+1);
1272 ft.mtime = convert_time_t_to_timespec(mtime);
1273 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 reply_nterror(req, status);
1276 goto out;
1279 if (mode != FILE_ATTRIBUTE_NORMAL) {
1280 if (VALID_STAT_OF_DIR(smb_fname->st))
1281 mode |= FILE_ATTRIBUTE_DIRECTORY;
1282 else
1283 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1285 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1286 false) != 0) {
1287 reply_nterror(req, map_nt_error_from_unix(errno));
1288 goto out;
1292 reply_outbuf(req, 0, 0);
1294 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1295 mode));
1296 out:
1297 TALLOC_FREE(smb_fname);
1298 END_PROFILE(SMBsetatr);
1299 return;
1302 /****************************************************************************
1303 Reply to a dskattr.
1304 ****************************************************************************/
1306 void reply_dskattr(struct smb_request *req)
1308 connection_struct *conn = req->conn;
1309 uint64_t dfree,dsize,bsize;
1310 START_PROFILE(SMBdskattr);
1312 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1313 reply_nterror(req, map_nt_error_from_unix(errno));
1314 END_PROFILE(SMBdskattr);
1315 return;
1318 reply_outbuf(req, 5, 0);
1320 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1321 double total_space, free_space;
1322 /* we need to scale this to a number that DOS6 can handle. We
1323 use floating point so we can handle large drives on systems
1324 that don't have 64 bit integers
1326 we end up displaying a maximum of 2G to DOS systems
1328 total_space = dsize * (double)bsize;
1329 free_space = dfree * (double)bsize;
1331 dsize = (uint64_t)((total_space+63*512) / (64*512));
1332 dfree = (uint64_t)((free_space+63*512) / (64*512));
1334 if (dsize > 0xFFFF) dsize = 0xFFFF;
1335 if (dfree > 0xFFFF) dfree = 0xFFFF;
1337 SSVAL(req->outbuf,smb_vwv0,dsize);
1338 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1339 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1340 SSVAL(req->outbuf,smb_vwv3,dfree);
1341 } else {
1342 SSVAL(req->outbuf,smb_vwv0,dsize);
1343 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1344 SSVAL(req->outbuf,smb_vwv2,512);
1345 SSVAL(req->outbuf,smb_vwv3,dfree);
1348 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1350 END_PROFILE(SMBdskattr);
1351 return;
1355 * Utility function to split the filename from the directory.
1357 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1358 char **fname_dir_out,
1359 char **fname_mask_out)
1361 const char *p = NULL;
1362 char *fname_dir = NULL;
1363 char *fname_mask = NULL;
1365 p = strrchr_m(fname_in, '/');
1366 if (!p) {
1367 fname_dir = talloc_strdup(ctx, ".");
1368 fname_mask = talloc_strdup(ctx, fname_in);
1369 } else {
1370 fname_dir = talloc_strndup(ctx, fname_in,
1371 PTR_DIFF(p, fname_in));
1372 fname_mask = talloc_strdup(ctx, p+1);
1375 if (!fname_dir || !fname_mask) {
1376 TALLOC_FREE(fname_dir);
1377 TALLOC_FREE(fname_mask);
1378 return NT_STATUS_NO_MEMORY;
1381 *fname_dir_out = fname_dir;
1382 *fname_mask_out = fname_mask;
1383 return NT_STATUS_OK;
1386 /****************************************************************************
1387 Reply to a search.
1388 Can be called from SMBsearch, SMBffirst or SMBfunique.
1389 ****************************************************************************/
1391 void reply_search(struct smb_request *req)
1393 connection_struct *conn = req->conn;
1394 char *path = NULL;
1395 const char *mask = NULL;
1396 char *directory = NULL;
1397 struct smb_filename *smb_fname = NULL;
1398 char *fname = NULL;
1399 SMB_OFF_T size;
1400 uint32 mode;
1401 struct timespec date;
1402 uint32 dirtype;
1403 unsigned int numentries = 0;
1404 unsigned int maxentries = 0;
1405 bool finished = False;
1406 const char *p;
1407 int status_len;
1408 char status[21];
1409 int dptr_num= -1;
1410 bool check_descend = False;
1411 bool expect_close = False;
1412 NTSTATUS nt_status;
1413 bool mask_contains_wcard = False;
1414 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1415 TALLOC_CTX *ctx = talloc_tos();
1416 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1417 struct dptr_struct *dirptr = NULL;
1418 struct smbd_server_connection *sconn = req->sconn;
1420 START_PROFILE(SMBsearch);
1422 if (req->wct < 2) {
1423 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1424 goto out;
1427 if (lp_posix_pathnames()) {
1428 reply_unknown_new(req, req->cmd);
1429 goto out;
1432 /* If we were called as SMBffirst then we must expect close. */
1433 if(req->cmd == SMBffirst) {
1434 expect_close = True;
1437 reply_outbuf(req, 1, 3);
1438 maxentries = SVAL(req->vwv+0, 0);
1439 dirtype = SVAL(req->vwv+1, 0);
1440 p = (const char *)req->buf + 1;
1441 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1442 &nt_status, &mask_contains_wcard);
1443 if (!NT_STATUS_IS_OK(nt_status)) {
1444 reply_nterror(req, nt_status);
1445 goto out;
1448 p++;
1449 status_len = SVAL(p, 0);
1450 p += 2;
1452 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1454 if (status_len == 0) {
1455 nt_status = filename_convert(ctx, conn,
1456 req->flags2 & FLAGS2_DFS_PATHNAMES,
1457 path,
1458 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1459 &mask_contains_wcard,
1460 &smb_fname);
1461 if (!NT_STATUS_IS_OK(nt_status)) {
1462 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1463 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1464 ERRSRV, ERRbadpath);
1465 goto out;
1467 reply_nterror(req, nt_status);
1468 goto out;
1471 directory = smb_fname->base_name;
1473 p = strrchr_m(directory,'/');
1474 if ((p != NULL) && (*directory != '/')) {
1475 mask = p + 1;
1476 directory = talloc_strndup(ctx, directory,
1477 PTR_DIFF(p, directory));
1478 } else {
1479 mask = directory;
1480 directory = talloc_strdup(ctx,".");
1483 if (!directory) {
1484 reply_nterror(req, NT_STATUS_NO_MEMORY);
1485 goto out;
1488 memset((char *)status,'\0',21);
1489 SCVAL(status,0,(dirtype & 0x1F));
1491 nt_status = dptr_create(conn,
1492 NULL, /* fsp */
1493 directory,
1494 True,
1495 expect_close,
1496 req->smbpid,
1497 mask,
1498 mask_contains_wcard,
1499 dirtype,
1500 &dirptr);
1501 if (!NT_STATUS_IS_OK(nt_status)) {
1502 reply_nterror(req, nt_status);
1503 goto out;
1505 dptr_num = dptr_dnum(dirptr);
1506 } else {
1507 int status_dirtype;
1508 const char *dirpath;
1510 memcpy(status,p,21);
1511 status_dirtype = CVAL(status,0) & 0x1F;
1512 if (status_dirtype != (dirtype & 0x1F)) {
1513 dirtype = status_dirtype;
1516 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1517 if (!dirptr) {
1518 goto SearchEmpty;
1520 dirpath = dptr_path(sconn, dptr_num);
1521 directory = talloc_strdup(ctx, dirpath);
1522 if (!directory) {
1523 reply_nterror(req, NT_STATUS_NO_MEMORY);
1524 goto out;
1527 mask = dptr_wcard(sconn, dptr_num);
1528 if (!mask) {
1529 goto SearchEmpty;
1532 * For a 'continue' search we have no string. So
1533 * check from the initial saved string.
1535 mask_contains_wcard = ms_has_wild(mask);
1536 dirtype = dptr_attr(sconn, dptr_num);
1539 DEBUG(4,("dptr_num is %d\n",dptr_num));
1541 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1542 dptr_init_search_op(dirptr);
1544 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1545 char buf[DIR_STRUCT_SIZE];
1546 memcpy(buf,status,21);
1547 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1548 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1549 reply_nterror(req, NT_STATUS_NO_MEMORY);
1550 goto out;
1552 dptr_fill(sconn, buf+12,dptr_num);
1553 if (dptr_zero(buf+12) && (status_len==0)) {
1554 numentries = 1;
1555 } else {
1556 numentries = 0;
1558 if (message_push_blob(&req->outbuf,
1559 data_blob_const(buf, sizeof(buf)))
1560 == -1) {
1561 reply_nterror(req, NT_STATUS_NO_MEMORY);
1562 goto out;
1564 } else {
1565 unsigned int i;
1566 maxentries = MIN(
1567 maxentries,
1568 ((BUFFER_SIZE -
1569 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1570 /DIR_STRUCT_SIZE));
1572 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1573 directory,lp_dontdescend(SNUM(conn))));
1574 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1575 check_descend = True;
1578 for (i=numentries;(i<maxentries) && !finished;i++) {
1579 finished = !get_dir_entry(ctx,
1580 dirptr,
1581 mask,
1582 dirtype,
1583 &fname,
1584 &size,
1585 &mode,
1586 &date,
1587 check_descend,
1588 ask_sharemode);
1589 if (!finished) {
1590 char buf[DIR_STRUCT_SIZE];
1591 memcpy(buf,status,21);
1592 if (!make_dir_struct(ctx,
1593 buf,
1594 mask,
1595 fname,
1596 size,
1597 mode,
1598 convert_timespec_to_time_t(date),
1599 !allow_long_path_components)) {
1600 reply_nterror(req, NT_STATUS_NO_MEMORY);
1601 goto out;
1603 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1604 break;
1606 if (message_push_blob(&req->outbuf,
1607 data_blob_const(buf, sizeof(buf)))
1608 == -1) {
1609 reply_nterror(req, NT_STATUS_NO_MEMORY);
1610 goto out;
1612 numentries++;
1617 SearchEmpty:
1619 /* If we were called as SMBffirst with smb_search_id == NULL
1620 and no entries were found then return error and close dirptr
1621 (X/Open spec) */
1623 if (numentries == 0) {
1624 dptr_close(sconn, &dptr_num);
1625 } else if(expect_close && status_len == 0) {
1626 /* Close the dptr - we know it's gone */
1627 dptr_close(sconn, &dptr_num);
1630 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1631 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1632 dptr_close(sconn, &dptr_num);
1635 if ((numentries == 0) && !mask_contains_wcard) {
1636 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1637 goto out;
1640 SSVAL(req->outbuf,smb_vwv0,numentries);
1641 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1642 SCVAL(smb_buf(req->outbuf),0,5);
1643 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1645 /* The replies here are never long name. */
1646 SSVAL(req->outbuf, smb_flg2,
1647 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1648 if (!allow_long_path_components) {
1649 SSVAL(req->outbuf, smb_flg2,
1650 SVAL(req->outbuf, smb_flg2)
1651 & (~FLAGS2_LONG_PATH_COMPONENTS));
1654 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1655 SSVAL(req->outbuf, smb_flg2,
1656 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1658 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1659 smb_fn_name(req->cmd),
1660 mask,
1661 directory,
1662 dirtype,
1663 numentries,
1664 maxentries ));
1665 out:
1666 TALLOC_FREE(directory);
1667 TALLOC_FREE(smb_fname);
1668 END_PROFILE(SMBsearch);
1669 return;
1672 /****************************************************************************
1673 Reply to a fclose (stop directory search).
1674 ****************************************************************************/
1676 void reply_fclose(struct smb_request *req)
1678 int status_len;
1679 char status[21];
1680 int dptr_num= -2;
1681 const char *p;
1682 char *path = NULL;
1683 NTSTATUS err;
1684 bool path_contains_wcard = False;
1685 TALLOC_CTX *ctx = talloc_tos();
1686 struct smbd_server_connection *sconn = req->sconn;
1688 START_PROFILE(SMBfclose);
1690 if (lp_posix_pathnames()) {
1691 reply_unknown_new(req, req->cmd);
1692 END_PROFILE(SMBfclose);
1693 return;
1696 p = (const char *)req->buf + 1;
1697 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1698 &err, &path_contains_wcard);
1699 if (!NT_STATUS_IS_OK(err)) {
1700 reply_nterror(req, err);
1701 END_PROFILE(SMBfclose);
1702 return;
1704 p++;
1705 status_len = SVAL(p,0);
1706 p += 2;
1708 if (status_len == 0) {
1709 reply_force_doserror(req, ERRSRV, ERRsrverror);
1710 END_PROFILE(SMBfclose);
1711 return;
1714 memcpy(status,p,21);
1716 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1717 /* Close the dptr - we know it's gone */
1718 dptr_close(sconn, &dptr_num);
1721 reply_outbuf(req, 1, 0);
1722 SSVAL(req->outbuf,smb_vwv0,0);
1724 DEBUG(3,("search close\n"));
1726 END_PROFILE(SMBfclose);
1727 return;
1730 /****************************************************************************
1731 Reply to an open.
1732 ****************************************************************************/
1734 void reply_open(struct smb_request *req)
1736 connection_struct *conn = req->conn;
1737 struct smb_filename *smb_fname = NULL;
1738 char *fname = NULL;
1739 uint32 fattr=0;
1740 SMB_OFF_T size = 0;
1741 time_t mtime=0;
1742 int info;
1743 files_struct *fsp;
1744 int oplock_request;
1745 int deny_mode;
1746 uint32 dos_attr;
1747 uint32 access_mask;
1748 uint32 share_mode;
1749 uint32 create_disposition;
1750 uint32 create_options = 0;
1751 uint32_t private_flags = 0;
1752 NTSTATUS status;
1753 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1754 TALLOC_CTX *ctx = talloc_tos();
1756 START_PROFILE(SMBopen);
1758 if (req->wct < 2) {
1759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1760 goto out;
1763 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1764 deny_mode = SVAL(req->vwv+0, 0);
1765 dos_attr = SVAL(req->vwv+1, 0);
1767 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1768 STR_TERMINATE, &status);
1769 if (!NT_STATUS_IS_OK(status)) {
1770 reply_nterror(req, status);
1771 goto out;
1774 status = filename_convert(ctx,
1775 conn,
1776 req->flags2 & FLAGS2_DFS_PATHNAMES,
1777 fname,
1779 NULL,
1780 &smb_fname);
1781 if (!NT_STATUS_IS_OK(status)) {
1782 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1783 reply_botherror(req,
1784 NT_STATUS_PATH_NOT_COVERED,
1785 ERRSRV, ERRbadpath);
1786 goto out;
1788 reply_nterror(req, status);
1789 goto out;
1792 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1793 OPENX_FILE_EXISTS_OPEN, &access_mask,
1794 &share_mode, &create_disposition,
1795 &create_options, &private_flags)) {
1796 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1797 goto out;
1800 status = SMB_VFS_CREATE_FILE(
1801 conn, /* conn */
1802 req, /* req */
1803 0, /* root_dir_fid */
1804 smb_fname, /* fname */
1805 access_mask, /* access_mask */
1806 share_mode, /* share_access */
1807 create_disposition, /* create_disposition*/
1808 create_options, /* create_options */
1809 dos_attr, /* file_attributes */
1810 oplock_request, /* oplock_request */
1811 0, /* allocation_size */
1812 private_flags,
1813 NULL, /* sd */
1814 NULL, /* ea_list */
1815 &fsp, /* result */
1816 &info); /* pinfo */
1818 if (!NT_STATUS_IS_OK(status)) {
1819 if (open_was_deferred(req->sconn, req->mid)) {
1820 /* We have re-scheduled this call. */
1821 goto out;
1823 reply_openerror(req, status);
1824 goto out;
1827 size = smb_fname->st.st_ex_size;
1828 fattr = dos_mode(conn, smb_fname);
1830 /* Deal with other possible opens having a modified
1831 write time. JRA. */
1832 if (ask_sharemode) {
1833 struct timespec write_time_ts;
1835 ZERO_STRUCT(write_time_ts);
1836 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1837 if (!null_timespec(write_time_ts)) {
1838 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1842 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1844 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1845 DEBUG(3,("attempt to open a directory %s\n",
1846 fsp_str_dbg(fsp)));
1847 close_file(req, fsp, ERROR_CLOSE);
1848 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1849 ERRDOS, ERRnoaccess);
1850 goto out;
1853 reply_outbuf(req, 7, 0);
1854 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1855 SSVAL(req->outbuf,smb_vwv1,fattr);
1856 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1857 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1858 } else {
1859 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1861 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1862 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1864 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1865 SCVAL(req->outbuf,smb_flg,
1866 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1869 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1870 SCVAL(req->outbuf,smb_flg,
1871 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1873 out:
1874 TALLOC_FREE(smb_fname);
1875 END_PROFILE(SMBopen);
1876 return;
1879 /****************************************************************************
1880 Reply to an open and X.
1881 ****************************************************************************/
1883 void reply_open_and_X(struct smb_request *req)
1885 connection_struct *conn = req->conn;
1886 struct smb_filename *smb_fname = NULL;
1887 char *fname = NULL;
1888 uint16 open_flags;
1889 int deny_mode;
1890 uint32 smb_attr;
1891 /* Breakout the oplock request bits so we can set the
1892 reply bits separately. */
1893 int ex_oplock_request;
1894 int core_oplock_request;
1895 int oplock_request;
1896 #if 0
1897 int smb_sattr = SVAL(req->vwv+4, 0);
1898 uint32 smb_time = make_unix_date3(req->vwv+6);
1899 #endif
1900 int smb_ofun;
1901 uint32 fattr=0;
1902 int mtime=0;
1903 int smb_action = 0;
1904 files_struct *fsp;
1905 NTSTATUS status;
1906 uint64_t allocation_size;
1907 ssize_t retval = -1;
1908 uint32 access_mask;
1909 uint32 share_mode;
1910 uint32 create_disposition;
1911 uint32 create_options = 0;
1912 uint32_t private_flags = 0;
1913 TALLOC_CTX *ctx = talloc_tos();
1915 START_PROFILE(SMBopenX);
1917 if (req->wct < 15) {
1918 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1919 goto out;
1922 open_flags = SVAL(req->vwv+2, 0);
1923 deny_mode = SVAL(req->vwv+3, 0);
1924 smb_attr = SVAL(req->vwv+5, 0);
1925 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1926 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1927 oplock_request = ex_oplock_request | core_oplock_request;
1928 smb_ofun = SVAL(req->vwv+8, 0);
1929 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1931 /* If it's an IPC, pass off the pipe handler. */
1932 if (IS_IPC(conn)) {
1933 if (lp_nt_pipe_support()) {
1934 reply_open_pipe_and_X(conn, req);
1935 } else {
1936 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1938 goto out;
1941 /* XXXX we need to handle passed times, sattr and flags */
1942 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1943 STR_TERMINATE, &status);
1944 if (!NT_STATUS_IS_OK(status)) {
1945 reply_nterror(req, status);
1946 goto out;
1949 status = filename_convert(ctx,
1950 conn,
1951 req->flags2 & FLAGS2_DFS_PATHNAMES,
1952 fname,
1954 NULL,
1955 &smb_fname);
1956 if (!NT_STATUS_IS_OK(status)) {
1957 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1958 reply_botherror(req,
1959 NT_STATUS_PATH_NOT_COVERED,
1960 ERRSRV, ERRbadpath);
1961 goto out;
1963 reply_nterror(req, status);
1964 goto out;
1967 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1968 smb_ofun,
1969 &access_mask, &share_mode,
1970 &create_disposition,
1971 &create_options,
1972 &private_flags)) {
1973 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1974 goto out;
1977 status = SMB_VFS_CREATE_FILE(
1978 conn, /* conn */
1979 req, /* req */
1980 0, /* root_dir_fid */
1981 smb_fname, /* fname */
1982 access_mask, /* access_mask */
1983 share_mode, /* share_access */
1984 create_disposition, /* create_disposition*/
1985 create_options, /* create_options */
1986 smb_attr, /* file_attributes */
1987 oplock_request, /* oplock_request */
1988 0, /* allocation_size */
1989 private_flags,
1990 NULL, /* sd */
1991 NULL, /* ea_list */
1992 &fsp, /* result */
1993 &smb_action); /* pinfo */
1995 if (!NT_STATUS_IS_OK(status)) {
1996 if (open_was_deferred(req->sconn, req->mid)) {
1997 /* We have re-scheduled this call. */
1998 goto out;
2000 reply_openerror(req, status);
2001 goto out;
2004 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2005 if the file is truncated or created. */
2006 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2007 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2008 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2009 close_file(req, fsp, ERROR_CLOSE);
2010 reply_nterror(req, NT_STATUS_DISK_FULL);
2011 goto out;
2013 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
2014 if (retval < 0) {
2015 close_file(req, fsp, ERROR_CLOSE);
2016 reply_nterror(req, NT_STATUS_DISK_FULL);
2017 goto out;
2019 status = vfs_stat_fsp(fsp);
2020 if (!NT_STATUS_IS_OK(status)) {
2021 close_file(req, fsp, ERROR_CLOSE);
2022 reply_nterror(req, status);
2023 goto out;
2027 fattr = dos_mode(conn, fsp->fsp_name);
2028 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2029 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2030 close_file(req, fsp, ERROR_CLOSE);
2031 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2032 goto out;
2035 /* If the caller set the extended oplock request bit
2036 and we granted one (by whatever means) - set the
2037 correct bit for extended oplock reply.
2040 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2041 smb_action |= EXTENDED_OPLOCK_GRANTED;
2044 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2045 smb_action |= EXTENDED_OPLOCK_GRANTED;
2048 /* If the caller set the core oplock request bit
2049 and we granted one (by whatever means) - set the
2050 correct bit for core oplock reply.
2053 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2054 reply_outbuf(req, 19, 0);
2055 } else {
2056 reply_outbuf(req, 15, 0);
2059 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2060 SCVAL(req->outbuf, smb_flg,
2061 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2064 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2065 SCVAL(req->outbuf, smb_flg,
2066 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2069 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2070 SSVAL(req->outbuf,smb_vwv3,fattr);
2071 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2072 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2073 } else {
2074 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2076 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2077 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2078 SSVAL(req->outbuf,smb_vwv11,smb_action);
2080 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2081 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2084 chain_reply(req);
2085 out:
2086 TALLOC_FREE(smb_fname);
2087 END_PROFILE(SMBopenX);
2088 return;
2091 /****************************************************************************
2092 Reply to a SMBulogoffX.
2093 ****************************************************************************/
2095 void reply_ulogoffX(struct smb_request *req)
2097 struct smbd_server_connection *sconn = req->sconn;
2098 user_struct *vuser;
2100 START_PROFILE(SMBulogoffX);
2102 vuser = get_valid_user_struct(sconn, req->vuid);
2104 if(vuser == NULL) {
2105 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2106 req->vuid));
2109 /* in user level security we are supposed to close any files
2110 open by this user */
2111 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2112 file_close_user(sconn, req->vuid);
2115 invalidate_vuid(sconn, req->vuid);
2117 reply_outbuf(req, 2, 0);
2119 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2121 END_PROFILE(SMBulogoffX);
2122 req->vuid = UID_FIELD_INVALID;
2123 chain_reply(req);
2126 /****************************************************************************
2127 Reply to a mknew or a create.
2128 ****************************************************************************/
2130 void reply_mknew(struct smb_request *req)
2132 connection_struct *conn = req->conn;
2133 struct smb_filename *smb_fname = NULL;
2134 char *fname = NULL;
2135 uint32 fattr = 0;
2136 struct smb_file_time ft;
2137 files_struct *fsp;
2138 int oplock_request = 0;
2139 NTSTATUS status;
2140 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2141 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2142 uint32 create_disposition;
2143 uint32 create_options = 0;
2144 TALLOC_CTX *ctx = talloc_tos();
2146 START_PROFILE(SMBcreate);
2147 ZERO_STRUCT(ft);
2149 if (req->wct < 3) {
2150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2151 goto out;
2154 fattr = SVAL(req->vwv+0, 0);
2155 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2157 /* mtime. */
2158 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2160 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2161 STR_TERMINATE, &status);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 reply_nterror(req, status);
2164 goto out;
2167 status = filename_convert(ctx,
2168 conn,
2169 req->flags2 & FLAGS2_DFS_PATHNAMES,
2170 fname,
2172 NULL,
2173 &smb_fname);
2174 if (!NT_STATUS_IS_OK(status)) {
2175 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2176 reply_botherror(req,
2177 NT_STATUS_PATH_NOT_COVERED,
2178 ERRSRV, ERRbadpath);
2179 goto out;
2181 reply_nterror(req, status);
2182 goto out;
2185 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2186 DEBUG(0,("Attempt to create file (%s) with volid set - "
2187 "please report this\n",
2188 smb_fname_str_dbg(smb_fname)));
2191 if(req->cmd == SMBmknew) {
2192 /* We should fail if file exists. */
2193 create_disposition = FILE_CREATE;
2194 } else {
2195 /* Create if file doesn't exist, truncate if it does. */
2196 create_disposition = FILE_OVERWRITE_IF;
2199 status = SMB_VFS_CREATE_FILE(
2200 conn, /* conn */
2201 req, /* req */
2202 0, /* root_dir_fid */
2203 smb_fname, /* fname */
2204 access_mask, /* access_mask */
2205 share_mode, /* share_access */
2206 create_disposition, /* create_disposition*/
2207 create_options, /* create_options */
2208 fattr, /* file_attributes */
2209 oplock_request, /* oplock_request */
2210 0, /* allocation_size */
2211 0, /* private_flags */
2212 NULL, /* sd */
2213 NULL, /* ea_list */
2214 &fsp, /* result */
2215 NULL); /* pinfo */
2217 if (!NT_STATUS_IS_OK(status)) {
2218 if (open_was_deferred(req->sconn, req->mid)) {
2219 /* We have re-scheduled this call. */
2220 goto out;
2222 reply_openerror(req, status);
2223 goto out;
2226 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2227 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2228 if (!NT_STATUS_IS_OK(status)) {
2229 END_PROFILE(SMBcreate);
2230 goto out;
2233 reply_outbuf(req, 1, 0);
2234 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2236 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2237 SCVAL(req->outbuf,smb_flg,
2238 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2241 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2242 SCVAL(req->outbuf,smb_flg,
2243 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2246 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2247 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2248 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2249 (unsigned int)fattr));
2251 out:
2252 TALLOC_FREE(smb_fname);
2253 END_PROFILE(SMBcreate);
2254 return;
2257 /****************************************************************************
2258 Reply to a create temporary file.
2259 ****************************************************************************/
2261 void reply_ctemp(struct smb_request *req)
2263 connection_struct *conn = req->conn;
2264 struct smb_filename *smb_fname = NULL;
2265 char *fname = NULL;
2266 uint32 fattr;
2267 files_struct *fsp;
2268 int oplock_request;
2269 int tmpfd;
2270 char *s;
2271 NTSTATUS status;
2272 TALLOC_CTX *ctx = talloc_tos();
2274 START_PROFILE(SMBctemp);
2276 if (req->wct < 3) {
2277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2278 goto out;
2281 fattr = SVAL(req->vwv+0, 0);
2282 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2284 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2285 STR_TERMINATE, &status);
2286 if (!NT_STATUS_IS_OK(status)) {
2287 reply_nterror(req, status);
2288 goto out;
2290 if (*fname) {
2291 fname = talloc_asprintf(ctx,
2292 "%s/TMXXXXXX",
2293 fname);
2294 } else {
2295 fname = talloc_strdup(ctx, "TMXXXXXX");
2298 if (!fname) {
2299 reply_nterror(req, NT_STATUS_NO_MEMORY);
2300 goto out;
2303 status = filename_convert(ctx, conn,
2304 req->flags2 & FLAGS2_DFS_PATHNAMES,
2305 fname,
2307 NULL,
2308 &smb_fname);
2309 if (!NT_STATUS_IS_OK(status)) {
2310 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2311 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2312 ERRSRV, ERRbadpath);
2313 goto out;
2315 reply_nterror(req, status);
2316 goto out;
2319 tmpfd = mkstemp(smb_fname->base_name);
2320 if (tmpfd == -1) {
2321 reply_nterror(req, map_nt_error_from_unix(errno));
2322 goto out;
2325 SMB_VFS_STAT(conn, smb_fname);
2327 /* We should fail if file does not exist. */
2328 status = SMB_VFS_CREATE_FILE(
2329 conn, /* conn */
2330 req, /* req */
2331 0, /* root_dir_fid */
2332 smb_fname, /* fname */
2333 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2334 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2335 FILE_OPEN, /* create_disposition*/
2336 0, /* create_options */
2337 fattr, /* file_attributes */
2338 oplock_request, /* oplock_request */
2339 0, /* allocation_size */
2340 0, /* private_flags */
2341 NULL, /* sd */
2342 NULL, /* ea_list */
2343 &fsp, /* result */
2344 NULL); /* pinfo */
2346 /* close fd from mkstemp() */
2347 close(tmpfd);
2349 if (!NT_STATUS_IS_OK(status)) {
2350 if (open_was_deferred(req->sconn, req->mid)) {
2351 /* We have re-scheduled this call. */
2352 goto out;
2354 reply_openerror(req, status);
2355 goto out;
2358 reply_outbuf(req, 1, 0);
2359 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2361 /* the returned filename is relative to the directory */
2362 s = strrchr_m(fsp->fsp_name->base_name, '/');
2363 if (!s) {
2364 s = fsp->fsp_name->base_name;
2365 } else {
2366 s++;
2369 #if 0
2370 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2371 thing in the byte section. JRA */
2372 SSVALS(p, 0, -1); /* what is this? not in spec */
2373 #endif
2374 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2375 == -1) {
2376 reply_nterror(req, NT_STATUS_NO_MEMORY);
2377 goto out;
2380 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2381 SCVAL(req->outbuf, smb_flg,
2382 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2385 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2386 SCVAL(req->outbuf, smb_flg,
2387 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2390 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2391 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2392 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2393 out:
2394 TALLOC_FREE(smb_fname);
2395 END_PROFILE(SMBctemp);
2396 return;
2399 /*******************************************************************
2400 Check if a user is allowed to rename a file.
2401 ********************************************************************/
2403 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2404 uint16 dirtype)
2406 if (!CAN_WRITE(conn)) {
2407 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2410 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2411 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2412 /* Only bother to read the DOS attribute if we might deny the
2413 rename on the grounds of attribute missmatch. */
2414 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2415 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2416 return NT_STATUS_NO_SUCH_FILE;
2420 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2421 if (fsp->posix_open) {
2422 return NT_STATUS_OK;
2425 /* If no pathnames are open below this
2426 directory, allow the rename. */
2428 if (file_find_subpath(fsp)) {
2429 return NT_STATUS_ACCESS_DENIED;
2431 return NT_STATUS_OK;
2434 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2435 return NT_STATUS_OK;
2438 return NT_STATUS_ACCESS_DENIED;
2441 /*******************************************************************
2442 * unlink a file with all relevant access checks
2443 *******************************************************************/
2445 static NTSTATUS do_unlink(connection_struct *conn,
2446 struct smb_request *req,
2447 struct smb_filename *smb_fname,
2448 uint32 dirtype)
2450 uint32 fattr;
2451 files_struct *fsp;
2452 uint32 dirtype_orig = dirtype;
2453 NTSTATUS status;
2454 int ret;
2455 bool posix_paths = lp_posix_pathnames();
2457 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2458 smb_fname_str_dbg(smb_fname),
2459 dirtype));
2461 if (!CAN_WRITE(conn)) {
2462 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2465 if (posix_paths) {
2466 ret = SMB_VFS_LSTAT(conn, smb_fname);
2467 } else {
2468 ret = SMB_VFS_STAT(conn, smb_fname);
2470 if (ret != 0) {
2471 return map_nt_error_from_unix(errno);
2474 fattr = dos_mode(conn, smb_fname);
2476 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2477 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2480 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2481 if (!dirtype) {
2482 return NT_STATUS_NO_SUCH_FILE;
2485 if (!dir_check_ftype(conn, fattr, dirtype)) {
2486 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2487 return NT_STATUS_FILE_IS_A_DIRECTORY;
2489 return NT_STATUS_NO_SUCH_FILE;
2492 if (dirtype_orig & 0x8000) {
2493 /* These will never be set for POSIX. */
2494 return NT_STATUS_NO_SUCH_FILE;
2497 #if 0
2498 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2499 return NT_STATUS_FILE_IS_A_DIRECTORY;
2502 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2503 return NT_STATUS_NO_SUCH_FILE;
2506 if (dirtype & 0xFF00) {
2507 /* These will never be set for POSIX. */
2508 return NT_STATUS_NO_SUCH_FILE;
2511 dirtype &= 0xFF;
2512 if (!dirtype) {
2513 return NT_STATUS_NO_SUCH_FILE;
2516 /* Can't delete a directory. */
2517 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2518 return NT_STATUS_FILE_IS_A_DIRECTORY;
2520 #endif
2522 #if 0 /* JRATEST */
2523 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2524 return NT_STATUS_OBJECT_NAME_INVALID;
2525 #endif /* JRATEST */
2527 /* On open checks the open itself will check the share mode, so
2528 don't do it here as we'll get it wrong. */
2530 status = SMB_VFS_CREATE_FILE
2531 (conn, /* conn */
2532 req, /* req */
2533 0, /* root_dir_fid */
2534 smb_fname, /* fname */
2535 DELETE_ACCESS, /* access_mask */
2536 FILE_SHARE_NONE, /* share_access */
2537 FILE_OPEN, /* create_disposition*/
2538 FILE_NON_DIRECTORY_FILE, /* create_options */
2539 /* file_attributes */
2540 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2541 FILE_ATTRIBUTE_NORMAL,
2542 0, /* oplock_request */
2543 0, /* allocation_size */
2544 0, /* private_flags */
2545 NULL, /* sd */
2546 NULL, /* ea_list */
2547 &fsp, /* result */
2548 NULL); /* pinfo */
2550 if (!NT_STATUS_IS_OK(status)) {
2551 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2552 nt_errstr(status)));
2553 return status;
2556 status = can_set_delete_on_close(fsp, fattr);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2559 "(%s)\n",
2560 smb_fname_str_dbg(smb_fname),
2561 nt_errstr(status)));
2562 close_file(req, fsp, NORMAL_CLOSE);
2563 return status;
2566 /* The set is across all open files on this dev/inode pair. */
2567 if (!set_delete_on_close(fsp, True, conn->session_info->unix_token)) {
2568 close_file(req, fsp, NORMAL_CLOSE);
2569 return NT_STATUS_ACCESS_DENIED;
2572 return close_file(req, fsp, NORMAL_CLOSE);
2575 /****************************************************************************
2576 The guts of the unlink command, split out so it may be called by the NT SMB
2577 code.
2578 ****************************************************************************/
2580 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2581 uint32 dirtype, struct smb_filename *smb_fname,
2582 bool has_wild)
2584 char *fname_dir = NULL;
2585 char *fname_mask = NULL;
2586 int count=0;
2587 NTSTATUS status = NT_STATUS_OK;
2588 TALLOC_CTX *ctx = talloc_tos();
2590 /* Split up the directory from the filename/mask. */
2591 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2592 &fname_dir, &fname_mask);
2593 if (!NT_STATUS_IS_OK(status)) {
2594 goto out;
2598 * We should only check the mangled cache
2599 * here if unix_convert failed. This means
2600 * that the path in 'mask' doesn't exist
2601 * on the file system and so we need to look
2602 * for a possible mangle. This patch from
2603 * Tine Smukavec <valentin.smukavec@hermes.si>.
2606 if (!VALID_STAT(smb_fname->st) &&
2607 mangle_is_mangled(fname_mask, conn->params)) {
2608 char *new_mask = NULL;
2609 mangle_lookup_name_from_8_3(ctx, fname_mask,
2610 &new_mask, conn->params);
2611 if (new_mask) {
2612 TALLOC_FREE(fname_mask);
2613 fname_mask = new_mask;
2617 if (!has_wild) {
2620 * Only one file needs to be unlinked. Append the mask back
2621 * onto the directory.
2623 TALLOC_FREE(smb_fname->base_name);
2624 if (ISDOT(fname_dir)) {
2625 /* Ensure we use canonical names on open. */
2626 smb_fname->base_name = talloc_asprintf(smb_fname,
2627 "%s",
2628 fname_mask);
2629 } else {
2630 smb_fname->base_name = talloc_asprintf(smb_fname,
2631 "%s/%s",
2632 fname_dir,
2633 fname_mask);
2635 if (!smb_fname->base_name) {
2636 status = NT_STATUS_NO_MEMORY;
2637 goto out;
2639 if (dirtype == 0) {
2640 dirtype = FILE_ATTRIBUTE_NORMAL;
2643 status = check_name(conn, smb_fname->base_name);
2644 if (!NT_STATUS_IS_OK(status)) {
2645 goto out;
2648 status = do_unlink(conn, req, smb_fname, dirtype);
2649 if (!NT_STATUS_IS_OK(status)) {
2650 goto out;
2653 count++;
2654 } else {
2655 struct smb_Dir *dir_hnd = NULL;
2656 long offset = 0;
2657 const char *dname = NULL;
2658 char *talloced = NULL;
2660 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2661 status = NT_STATUS_OBJECT_NAME_INVALID;
2662 goto out;
2665 if (strequal(fname_mask,"????????.???")) {
2666 TALLOC_FREE(fname_mask);
2667 fname_mask = talloc_strdup(ctx, "*");
2668 if (!fname_mask) {
2669 status = NT_STATUS_NO_MEMORY;
2670 goto out;
2674 status = check_name(conn, fname_dir);
2675 if (!NT_STATUS_IS_OK(status)) {
2676 goto out;
2679 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2680 dirtype);
2681 if (dir_hnd == NULL) {
2682 status = map_nt_error_from_unix(errno);
2683 goto out;
2686 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2687 the pattern matches against the long name, otherwise the short name
2688 We don't implement this yet XXXX
2691 status = NT_STATUS_NO_SUCH_FILE;
2693 while ((dname = ReadDirName(dir_hnd, &offset,
2694 &smb_fname->st, &talloced))) {
2695 TALLOC_CTX *frame = talloc_stackframe();
2697 if (!is_visible_file(conn, fname_dir, dname,
2698 &smb_fname->st, true)) {
2699 TALLOC_FREE(frame);
2700 TALLOC_FREE(talloced);
2701 continue;
2704 /* Quick check for "." and ".." */
2705 if (ISDOT(dname) || ISDOTDOT(dname)) {
2706 TALLOC_FREE(frame);
2707 TALLOC_FREE(talloced);
2708 continue;
2711 if(!mask_match(dname, fname_mask,
2712 conn->case_sensitive)) {
2713 TALLOC_FREE(frame);
2714 TALLOC_FREE(talloced);
2715 continue;
2718 TALLOC_FREE(smb_fname->base_name);
2719 if (ISDOT(fname_dir)) {
2720 /* Ensure we use canonical names on open. */
2721 smb_fname->base_name =
2722 talloc_asprintf(smb_fname, "%s",
2723 dname);
2724 } else {
2725 smb_fname->base_name =
2726 talloc_asprintf(smb_fname, "%s/%s",
2727 fname_dir, dname);
2730 if (!smb_fname->base_name) {
2731 TALLOC_FREE(dir_hnd);
2732 status = NT_STATUS_NO_MEMORY;
2733 TALLOC_FREE(frame);
2734 TALLOC_FREE(talloced);
2735 goto out;
2738 status = check_name(conn, smb_fname->base_name);
2739 if (!NT_STATUS_IS_OK(status)) {
2740 TALLOC_FREE(dir_hnd);
2741 TALLOC_FREE(frame);
2742 TALLOC_FREE(talloced);
2743 goto out;
2746 status = do_unlink(conn, req, smb_fname, dirtype);
2747 if (!NT_STATUS_IS_OK(status)) {
2748 TALLOC_FREE(frame);
2749 TALLOC_FREE(talloced);
2750 continue;
2753 count++;
2754 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2755 smb_fname->base_name));
2757 TALLOC_FREE(frame);
2758 TALLOC_FREE(talloced);
2760 TALLOC_FREE(dir_hnd);
2763 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2764 status = map_nt_error_from_unix(errno);
2767 out:
2768 TALLOC_FREE(fname_dir);
2769 TALLOC_FREE(fname_mask);
2770 return status;
2773 /****************************************************************************
2774 Reply to a unlink
2775 ****************************************************************************/
2777 void reply_unlink(struct smb_request *req)
2779 connection_struct *conn = req->conn;
2780 char *name = NULL;
2781 struct smb_filename *smb_fname = NULL;
2782 uint32 dirtype;
2783 NTSTATUS status;
2784 bool path_contains_wcard = False;
2785 TALLOC_CTX *ctx = talloc_tos();
2787 START_PROFILE(SMBunlink);
2789 if (req->wct < 1) {
2790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2791 goto out;
2794 dirtype = SVAL(req->vwv+0, 0);
2796 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2797 STR_TERMINATE, &status,
2798 &path_contains_wcard);
2799 if (!NT_STATUS_IS_OK(status)) {
2800 reply_nterror(req, status);
2801 goto out;
2804 status = filename_convert(ctx, conn,
2805 req->flags2 & FLAGS2_DFS_PATHNAMES,
2806 name,
2807 UCF_COND_ALLOW_WCARD_LCOMP,
2808 &path_contains_wcard,
2809 &smb_fname);
2810 if (!NT_STATUS_IS_OK(status)) {
2811 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2812 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2813 ERRSRV, ERRbadpath);
2814 goto out;
2816 reply_nterror(req, status);
2817 goto out;
2820 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2822 status = unlink_internals(conn, req, dirtype, smb_fname,
2823 path_contains_wcard);
2824 if (!NT_STATUS_IS_OK(status)) {
2825 if (open_was_deferred(req->sconn, req->mid)) {
2826 /* We have re-scheduled this call. */
2827 goto out;
2829 reply_nterror(req, status);
2830 goto out;
2833 reply_outbuf(req, 0, 0);
2834 out:
2835 TALLOC_FREE(smb_fname);
2836 END_PROFILE(SMBunlink);
2837 return;
2840 /****************************************************************************
2841 Fail for readbraw.
2842 ****************************************************************************/
2844 static void fail_readraw(void)
2846 const char *errstr = talloc_asprintf(talloc_tos(),
2847 "FAIL ! reply_readbraw: socket write fail (%s)",
2848 strerror(errno));
2849 if (!errstr) {
2850 errstr = "";
2852 exit_server_cleanly(errstr);
2855 /****************************************************************************
2856 Fake (read/write) sendfile. Returns -1 on read or write fail.
2857 ****************************************************************************/
2859 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2861 size_t bufsize;
2862 size_t tosend = nread;
2863 char *buf;
2865 if (nread == 0) {
2866 return 0;
2869 bufsize = MIN(nread, 65536);
2871 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2872 return -1;
2875 while (tosend > 0) {
2876 ssize_t ret;
2877 size_t cur_read;
2879 if (tosend > bufsize) {
2880 cur_read = bufsize;
2881 } else {
2882 cur_read = tosend;
2884 ret = read_file(fsp,buf,startpos,cur_read);
2885 if (ret == -1) {
2886 SAFE_FREE(buf);
2887 return -1;
2890 /* If we had a short read, fill with zeros. */
2891 if (ret < cur_read) {
2892 memset(buf + ret, '\0', cur_read - ret);
2895 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2896 != cur_read) {
2897 char addr[INET6_ADDRSTRLEN];
2899 * Try and give an error message saying what
2900 * client failed.
2902 DEBUG(0, ("write_data failed for client %s. "
2903 "Error %s\n",
2904 get_peer_addr(fsp->conn->sconn->sock, addr,
2905 sizeof(addr)),
2906 strerror(errno)));
2907 SAFE_FREE(buf);
2908 return -1;
2910 tosend -= cur_read;
2911 startpos += cur_read;
2914 SAFE_FREE(buf);
2915 return (ssize_t)nread;
2918 /****************************************************************************
2919 Deal with the case of sendfile reading less bytes from the file than
2920 requested. Fill with zeros (all we can do).
2921 ****************************************************************************/
2923 void sendfile_short_send(files_struct *fsp,
2924 ssize_t nread,
2925 size_t headersize,
2926 size_t smb_maxcnt)
2928 #define SHORT_SEND_BUFSIZE 1024
2929 if (nread < headersize) {
2930 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2931 "header for file %s (%s). Terminating\n",
2932 fsp_str_dbg(fsp), strerror(errno)));
2933 exit_server_cleanly("sendfile_short_send failed");
2936 nread -= headersize;
2938 if (nread < smb_maxcnt) {
2939 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2940 if (!buf) {
2941 exit_server_cleanly("sendfile_short_send: "
2942 "malloc failed");
2945 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2946 "with zeros !\n", fsp_str_dbg(fsp)));
2948 while (nread < smb_maxcnt) {
2950 * We asked for the real file size and told sendfile
2951 * to not go beyond the end of the file. But it can
2952 * happen that in between our fstat call and the
2953 * sendfile call the file was truncated. This is very
2954 * bad because we have already announced the larger
2955 * number of bytes to the client.
2957 * The best we can do now is to send 0-bytes, just as
2958 * a read from a hole in a sparse file would do.
2960 * This should happen rarely enough that I don't care
2961 * about efficiency here :-)
2963 size_t to_write;
2965 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2966 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2967 != to_write) {
2968 char addr[INET6_ADDRSTRLEN];
2970 * Try and give an error message saying what
2971 * client failed.
2973 DEBUG(0, ("write_data failed for client %s. "
2974 "Error %s\n",
2975 get_peer_addr(
2976 fsp->conn->sconn->sock, addr,
2977 sizeof(addr)),
2978 strerror(errno)));
2979 exit_server_cleanly("sendfile_short_send: "
2980 "write_data failed");
2982 nread += to_write;
2984 SAFE_FREE(buf);
2988 /****************************************************************************
2989 Return a readbraw error (4 bytes of zero).
2990 ****************************************************************************/
2992 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2994 char header[4];
2996 SIVAL(header,0,0);
2998 smbd_lock_socket(sconn);
2999 if (write_data(sconn->sock,header,4) != 4) {
3000 char addr[INET6_ADDRSTRLEN];
3002 * Try and give an error message saying what
3003 * client failed.
3005 DEBUG(0, ("write_data failed for client %s. "
3006 "Error %s\n",
3007 get_peer_addr(sconn->sock, addr, sizeof(addr)),
3008 strerror(errno)));
3010 fail_readraw();
3012 smbd_unlock_socket(sconn);
3015 /****************************************************************************
3016 Use sendfile in readbraw.
3017 ****************************************************************************/
3019 static void send_file_readbraw(connection_struct *conn,
3020 struct smb_request *req,
3021 files_struct *fsp,
3022 SMB_OFF_T startpos,
3023 size_t nread,
3024 ssize_t mincount)
3026 struct smbd_server_connection *sconn = req->sconn;
3027 char *outbuf = NULL;
3028 ssize_t ret=0;
3031 * We can only use sendfile on a non-chained packet
3032 * but we can use on a non-oplocked file. tridge proved this
3033 * on a train in Germany :-). JRA.
3034 * reply_readbraw has already checked the length.
3037 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3038 (fsp->wcp == NULL) &&
3039 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3040 ssize_t sendfile_read = -1;
3041 char header[4];
3042 DATA_BLOB header_blob;
3044 _smb_setlen(header,nread);
3045 header_blob = data_blob_const(header, 4);
3047 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3048 &header_blob, startpos,
3049 nread);
3050 if (sendfile_read == -1) {
3051 /* Returning ENOSYS means no data at all was sent.
3052 * Do this as a normal read. */
3053 if (errno == ENOSYS) {
3054 goto normal_readbraw;
3058 * Special hack for broken Linux with no working sendfile. If we
3059 * return EINTR we sent the header but not the rest of the data.
3060 * Fake this up by doing read/write calls.
3062 if (errno == EINTR) {
3063 /* Ensure we don't do this again. */
3064 set_use_sendfile(SNUM(conn), False);
3065 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3067 if (fake_sendfile(fsp, startpos, nread) == -1) {
3068 DEBUG(0,("send_file_readbraw: "
3069 "fake_sendfile failed for "
3070 "file %s (%s).\n",
3071 fsp_str_dbg(fsp),
3072 strerror(errno)));
3073 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3075 return;
3078 DEBUG(0,("send_file_readbraw: sendfile failed for "
3079 "file %s (%s). Terminating\n",
3080 fsp_str_dbg(fsp), strerror(errno)));
3081 exit_server_cleanly("send_file_readbraw sendfile failed");
3082 } else if (sendfile_read == 0) {
3084 * Some sendfile implementations return 0 to indicate
3085 * that there was a short read, but nothing was
3086 * actually written to the socket. In this case,
3087 * fallback to the normal read path so the header gets
3088 * the correct byte count.
3090 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3091 "bytes falling back to the normal read: "
3092 "%s\n", fsp_str_dbg(fsp)));
3093 goto normal_readbraw;
3096 /* Deal with possible short send. */
3097 if (sendfile_read != 4+nread) {
3098 sendfile_short_send(fsp, sendfile_read, 4, nread);
3100 return;
3103 normal_readbraw:
3105 outbuf = talloc_array(NULL, char, nread+4);
3106 if (!outbuf) {
3107 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3108 (unsigned)(nread+4)));
3109 reply_readbraw_error(sconn);
3110 return;
3113 if (nread > 0) {
3114 ret = read_file(fsp,outbuf+4,startpos,nread);
3115 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3116 if (ret < mincount)
3117 ret = 0;
3118 #else
3119 if (ret < nread)
3120 ret = 0;
3121 #endif
3124 _smb_setlen(outbuf,ret);
3125 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3126 char addr[INET6_ADDRSTRLEN];
3128 * Try and give an error message saying what
3129 * client failed.
3131 DEBUG(0, ("write_data failed for client %s. "
3132 "Error %s\n",
3133 get_peer_addr(fsp->conn->sconn->sock, addr,
3134 sizeof(addr)),
3135 strerror(errno)));
3137 fail_readraw();
3140 TALLOC_FREE(outbuf);
3143 /****************************************************************************
3144 Reply to a readbraw (core+ protocol).
3145 ****************************************************************************/
3147 void reply_readbraw(struct smb_request *req)
3149 connection_struct *conn = req->conn;
3150 struct smbd_server_connection *sconn = req->sconn;
3151 ssize_t maxcount,mincount;
3152 size_t nread = 0;
3153 SMB_OFF_T startpos;
3154 files_struct *fsp;
3155 struct lock_struct lock;
3156 SMB_OFF_T size = 0;
3158 START_PROFILE(SMBreadbraw);
3160 if (srv_is_signing_active(sconn) ||
3161 is_encrypted_packet(sconn, req->inbuf)) {
3162 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3163 "raw reads/writes are disallowed.");
3166 if (req->wct < 8) {
3167 reply_readbraw_error(sconn);
3168 END_PROFILE(SMBreadbraw);
3169 return;
3172 if (sconn->smb1.echo_handler.trusted_fde) {
3173 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3174 "'async smb echo handler = yes'\n"));
3175 reply_readbraw_error(sconn);
3176 END_PROFILE(SMBreadbraw);
3177 return;
3181 * Special check if an oplock break has been issued
3182 * and the readraw request croses on the wire, we must
3183 * return a zero length response here.
3186 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3189 * We have to do a check_fsp by hand here, as
3190 * we must always return 4 zero bytes on error,
3191 * not a NTSTATUS.
3194 if (!fsp || !conn || conn != fsp->conn ||
3195 req->vuid != fsp->vuid ||
3196 fsp->is_directory || fsp->fh->fd == -1) {
3198 * fsp could be NULL here so use the value from the packet. JRA.
3200 DEBUG(3,("reply_readbraw: fnum %d not valid "
3201 "- cache prime?\n",
3202 (int)SVAL(req->vwv+0, 0)));
3203 reply_readbraw_error(sconn);
3204 END_PROFILE(SMBreadbraw);
3205 return;
3208 /* Do a "by hand" version of CHECK_READ. */
3209 if (!(fsp->can_read ||
3210 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3211 (fsp->access_mask & FILE_EXECUTE)))) {
3212 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3213 (int)SVAL(req->vwv+0, 0)));
3214 reply_readbraw_error(sconn);
3215 END_PROFILE(SMBreadbraw);
3216 return;
3219 flush_write_cache(fsp, READRAW_FLUSH);
3221 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3222 if(req->wct == 10) {
3224 * This is a large offset (64 bit) read.
3226 #ifdef LARGE_SMB_OFF_T
3228 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3230 #else /* !LARGE_SMB_OFF_T */
3233 * Ensure we haven't been sent a >32 bit offset.
3236 if(IVAL(req->vwv+8, 0) != 0) {
3237 DEBUG(0,("reply_readbraw: large offset "
3238 "(%x << 32) used and we don't support "
3239 "64 bit offsets.\n",
3240 (unsigned int)IVAL(req->vwv+8, 0) ));
3241 reply_readbraw_error(sconn);
3242 END_PROFILE(SMBreadbraw);
3243 return;
3246 #endif /* LARGE_SMB_OFF_T */
3248 if(startpos < 0) {
3249 DEBUG(0,("reply_readbraw: negative 64 bit "
3250 "readraw offset (%.0f) !\n",
3251 (double)startpos ));
3252 reply_readbraw_error(sconn);
3253 END_PROFILE(SMBreadbraw);
3254 return;
3258 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3259 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3261 /* ensure we don't overrun the packet size */
3262 maxcount = MIN(65535,maxcount);
3264 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3265 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3266 &lock);
3268 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3269 reply_readbraw_error(sconn);
3270 END_PROFILE(SMBreadbraw);
3271 return;
3274 if (fsp_stat(fsp) == 0) {
3275 size = fsp->fsp_name->st.st_ex_size;
3278 if (startpos >= size) {
3279 nread = 0;
3280 } else {
3281 nread = MIN(maxcount,(size - startpos));
3284 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3285 if (nread < mincount)
3286 nread = 0;
3287 #endif
3289 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3290 "min=%lu nread=%lu\n",
3291 fsp->fnum, (double)startpos,
3292 (unsigned long)maxcount,
3293 (unsigned long)mincount,
3294 (unsigned long)nread ) );
3296 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3298 DEBUG(5,("reply_readbraw finished\n"));
3300 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3302 END_PROFILE(SMBreadbraw);
3303 return;
3306 #undef DBGC_CLASS
3307 #define DBGC_CLASS DBGC_LOCKING
3309 /****************************************************************************
3310 Reply to a lockread (core+ protocol).
3311 ****************************************************************************/
3313 void reply_lockread(struct smb_request *req)
3315 connection_struct *conn = req->conn;
3316 ssize_t nread = -1;
3317 char *data;
3318 SMB_OFF_T startpos;
3319 size_t numtoread;
3320 NTSTATUS status;
3321 files_struct *fsp;
3322 struct byte_range_lock *br_lck = NULL;
3323 char *p = NULL;
3324 struct smbd_server_connection *sconn = req->sconn;
3326 START_PROFILE(SMBlockread);
3328 if (req->wct < 5) {
3329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3330 END_PROFILE(SMBlockread);
3331 return;
3334 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3336 if (!check_fsp(conn, req, fsp)) {
3337 END_PROFILE(SMBlockread);
3338 return;
3341 if (!CHECK_READ(fsp,req)) {
3342 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3343 END_PROFILE(SMBlockread);
3344 return;
3347 numtoread = SVAL(req->vwv+1, 0);
3348 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3350 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3352 reply_outbuf(req, 5, numtoread + 3);
3354 data = smb_buf(req->outbuf) + 3;
3357 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3358 * protocol request that predates the read/write lock concept.
3359 * Thus instead of asking for a read lock here we need to ask
3360 * for a write lock. JRA.
3361 * Note that the requested lock size is unaffected by max_recv.
3364 br_lck = do_lock(req->sconn->msg_ctx,
3365 fsp,
3366 (uint64_t)req->smbpid,
3367 (uint64_t)numtoread,
3368 (uint64_t)startpos,
3369 WRITE_LOCK,
3370 WINDOWS_LOCK,
3371 False, /* Non-blocking lock. */
3372 &status,
3373 NULL,
3374 NULL);
3375 TALLOC_FREE(br_lck);
3377 if (NT_STATUS_V(status)) {
3378 reply_nterror(req, status);
3379 END_PROFILE(SMBlockread);
3380 return;
3384 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3387 if (numtoread > sconn->smb1.negprot.max_recv) {
3388 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3389 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3390 (unsigned int)numtoread,
3391 (unsigned int)sconn->smb1.negprot.max_recv));
3392 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3394 nread = read_file(fsp,data,startpos,numtoread);
3396 if (nread < 0) {
3397 reply_nterror(req, map_nt_error_from_unix(errno));
3398 END_PROFILE(SMBlockread);
3399 return;
3402 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3404 SSVAL(req->outbuf,smb_vwv0,nread);
3405 SSVAL(req->outbuf,smb_vwv5,nread+3);
3406 p = smb_buf(req->outbuf);
3407 SCVAL(p,0,0); /* pad byte. */
3408 SSVAL(p,1,nread);
3410 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3411 fsp->fnum, (int)numtoread, (int)nread));
3413 END_PROFILE(SMBlockread);
3414 return;
3417 #undef DBGC_CLASS
3418 #define DBGC_CLASS DBGC_ALL
3420 /****************************************************************************
3421 Reply to a read.
3422 ****************************************************************************/
3424 void reply_read(struct smb_request *req)
3426 connection_struct *conn = req->conn;
3427 size_t numtoread;
3428 ssize_t nread = 0;
3429 char *data;
3430 SMB_OFF_T startpos;
3431 int outsize = 0;
3432 files_struct *fsp;
3433 struct lock_struct lock;
3434 struct smbd_server_connection *sconn = req->sconn;
3436 START_PROFILE(SMBread);
3438 if (req->wct < 3) {
3439 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3440 END_PROFILE(SMBread);
3441 return;
3444 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3446 if (!check_fsp(conn, req, fsp)) {
3447 END_PROFILE(SMBread);
3448 return;
3451 if (!CHECK_READ(fsp,req)) {
3452 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3453 END_PROFILE(SMBread);
3454 return;
3457 numtoread = SVAL(req->vwv+1, 0);
3458 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3460 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3463 * The requested read size cannot be greater than max_recv. JRA.
3465 if (numtoread > sconn->smb1.negprot.max_recv) {
3466 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3467 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3468 (unsigned int)numtoread,
3469 (unsigned int)sconn->smb1.negprot.max_recv));
3470 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3473 reply_outbuf(req, 5, numtoread+3);
3475 data = smb_buf(req->outbuf) + 3;
3477 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3478 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3479 &lock);
3481 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3482 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3483 END_PROFILE(SMBread);
3484 return;
3487 if (numtoread > 0)
3488 nread = read_file(fsp,data,startpos,numtoread);
3490 if (nread < 0) {
3491 reply_nterror(req, map_nt_error_from_unix(errno));
3492 goto strict_unlock;
3495 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3497 SSVAL(req->outbuf,smb_vwv0,nread);
3498 SSVAL(req->outbuf,smb_vwv5,nread+3);
3499 SCVAL(smb_buf(req->outbuf),0,1);
3500 SSVAL(smb_buf(req->outbuf),1,nread);
3502 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3503 fsp->fnum, (int)numtoread, (int)nread ) );
3505 strict_unlock:
3506 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3508 END_PROFILE(SMBread);
3509 return;
3512 /****************************************************************************
3513 Setup readX header.
3514 ****************************************************************************/
3516 static int setup_readX_header(struct smb_request *req, char *outbuf,
3517 size_t smb_maxcnt)
3519 int outsize;
3520 char *data;
3522 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3523 data = smb_buf(outbuf);
3525 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3527 SCVAL(outbuf,smb_vwv0,0xFF);
3528 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3529 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3530 SSVAL(outbuf,smb_vwv6,
3531 req_wct_ofs(req)
3532 + 1 /* the wct field */
3533 + 12 * sizeof(uint16_t) /* vwv */
3534 + 2); /* the buflen field */
3535 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3536 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3537 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3538 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3539 return outsize;
3542 /****************************************************************************
3543 Reply to a read and X - possibly using sendfile.
3544 ****************************************************************************/
3546 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3547 files_struct *fsp, SMB_OFF_T startpos,
3548 size_t smb_maxcnt)
3550 ssize_t nread = -1;
3551 struct lock_struct lock;
3552 int saved_errno = 0;
3554 if(fsp_stat(fsp) == -1) {
3555 reply_nterror(req, map_nt_error_from_unix(errno));
3556 return;
3559 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3560 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3561 &lock);
3563 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3564 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3565 return;
3568 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3569 (startpos > fsp->fsp_name->st.st_ex_size)
3570 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3572 * We already know that we would do a short read, so don't
3573 * try the sendfile() path.
3575 goto nosendfile_read;
3579 * We can only use sendfile on a non-chained packet
3580 * but we can use on a non-oplocked file. tridge proved this
3581 * on a train in Germany :-). JRA.
3584 if (!req_is_in_chain(req) &&
3585 !is_encrypted_packet(req->sconn, req->inbuf) &&
3586 (fsp->base_fsp == NULL) &&
3587 (fsp->wcp == NULL) &&
3588 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3589 uint8 headerbuf[smb_size + 12 * 2];
3590 DATA_BLOB header;
3593 * Set up the packet header before send. We
3594 * assume here the sendfile will work (get the
3595 * correct amount of data).
3598 header = data_blob_const(headerbuf, sizeof(headerbuf));
3600 construct_reply_common_req(req, (char *)headerbuf);
3601 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3603 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3604 startpos, smb_maxcnt);
3605 if (nread == -1) {
3606 /* Returning ENOSYS means no data at all was sent.
3607 Do this as a normal read. */
3608 if (errno == ENOSYS) {
3609 goto normal_read;
3613 * Special hack for broken Linux with no working sendfile. If we
3614 * return EINTR we sent the header but not the rest of the data.
3615 * Fake this up by doing read/write calls.
3618 if (errno == EINTR) {
3619 /* Ensure we don't do this again. */
3620 set_use_sendfile(SNUM(conn), False);
3621 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3622 nread = fake_sendfile(fsp, startpos,
3623 smb_maxcnt);
3624 if (nread == -1) {
3625 DEBUG(0,("send_file_readX: "
3626 "fake_sendfile failed for "
3627 "file %s (%s).\n",
3628 fsp_str_dbg(fsp),
3629 strerror(errno)));
3630 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3632 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3633 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3634 /* No outbuf here means successful sendfile. */
3635 goto strict_unlock;
3638 DEBUG(0,("send_file_readX: sendfile failed for file "
3639 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3640 strerror(errno)));
3641 exit_server_cleanly("send_file_readX sendfile failed");
3642 } else if (nread == 0) {
3644 * Some sendfile implementations return 0 to indicate
3645 * that there was a short read, but nothing was
3646 * actually written to the socket. In this case,
3647 * fallback to the normal read path so the header gets
3648 * the correct byte count.
3650 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3651 "falling back to the normal read: %s\n",
3652 fsp_str_dbg(fsp)));
3653 goto normal_read;
3656 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3657 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3659 /* Deal with possible short send. */
3660 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3661 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3663 /* No outbuf here means successful sendfile. */
3664 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3665 SMB_PERFCOUNT_END(&req->pcd);
3666 goto strict_unlock;
3669 normal_read:
3671 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3672 uint8 headerbuf[smb_size + 2*12];
3674 construct_reply_common_req(req, (char *)headerbuf);
3675 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3677 /* Send out the header. */
3678 if (write_data(req->sconn->sock, (char *)headerbuf,
3679 sizeof(headerbuf)) != sizeof(headerbuf)) {
3681 char addr[INET6_ADDRSTRLEN];
3683 * Try and give an error message saying what
3684 * client failed.
3686 DEBUG(0, ("write_data failed for client %s. "
3687 "Error %s\n",
3688 get_peer_addr(req->sconn->sock, addr,
3689 sizeof(addr)),
3690 strerror(errno)));
3692 DEBUG(0,("send_file_readX: write_data failed for file "
3693 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3694 strerror(errno)));
3695 exit_server_cleanly("send_file_readX sendfile failed");
3697 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3698 if (nread == -1) {
3699 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3700 "file %s (%s).\n", fsp_str_dbg(fsp),
3701 strerror(errno)));
3702 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3704 goto strict_unlock;
3707 nosendfile_read:
3709 reply_outbuf(req, 12, smb_maxcnt);
3711 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3712 saved_errno = errno;
3714 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3716 if (nread < 0) {
3717 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3718 return;
3721 setup_readX_header(req, (char *)req->outbuf, nread);
3723 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3724 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3726 chain_reply(req);
3727 return;
3729 strict_unlock:
3730 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3731 TALLOC_FREE(req->outbuf);
3732 return;
3735 /****************************************************************************
3736 Reply to a read and X.
3737 ****************************************************************************/
3739 void reply_read_and_X(struct smb_request *req)
3741 struct smbd_server_connection *sconn = req->sconn;
3742 connection_struct *conn = req->conn;
3743 files_struct *fsp;
3744 SMB_OFF_T startpos;
3745 size_t smb_maxcnt;
3746 bool big_readX = False;
3747 #if 0
3748 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3749 #endif
3751 START_PROFILE(SMBreadX);
3753 if ((req->wct != 10) && (req->wct != 12)) {
3754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3755 return;
3758 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3759 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3760 smb_maxcnt = SVAL(req->vwv+5, 0);
3762 /* If it's an IPC, pass off the pipe handler. */
3763 if (IS_IPC(conn)) {
3764 reply_pipe_read_and_X(req);
3765 END_PROFILE(SMBreadX);
3766 return;
3769 if (!check_fsp(conn, req, fsp)) {
3770 END_PROFILE(SMBreadX);
3771 return;
3774 if (!CHECK_READ(fsp,req)) {
3775 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3776 END_PROFILE(SMBreadX);
3777 return;
3780 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3781 (get_remote_arch() == RA_SAMBA)) {
3783 * This is Samba only behavior (up to Samba 3.6)!
3785 * Windows 2008 R2 ignores the upper_size,
3786 * so we do unless unix extentions are active
3787 * or "smbclient" is talking to us.
3789 size_t upper_size = SVAL(req->vwv+7, 0);
3790 smb_maxcnt |= (upper_size<<16);
3791 if (upper_size > 1) {
3792 /* Can't do this on a chained packet. */
3793 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3794 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3795 END_PROFILE(SMBreadX);
3796 return;
3798 /* We currently don't do this on signed or sealed data. */
3799 if (srv_is_signing_active(req->sconn) ||
3800 is_encrypted_packet(req->sconn, req->inbuf)) {
3801 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3802 END_PROFILE(SMBreadX);
3803 return;
3805 /* Is there room in the reply for this data ? */
3806 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3807 reply_nterror(req,
3808 NT_STATUS_INVALID_PARAMETER);
3809 END_PROFILE(SMBreadX);
3810 return;
3812 big_readX = True;
3816 if (req->wct == 12) {
3817 #ifdef LARGE_SMB_OFF_T
3819 * This is a large offset (64 bit) read.
3821 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3823 #else /* !LARGE_SMB_OFF_T */
3826 * Ensure we haven't been sent a >32 bit offset.
3829 if(IVAL(req->vwv+10, 0) != 0) {
3830 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3831 "used and we don't support 64 bit offsets.\n",
3832 (unsigned int)IVAL(req->vwv+10, 0) ));
3833 END_PROFILE(SMBreadX);
3834 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3835 return;
3838 #endif /* LARGE_SMB_OFF_T */
3842 if (!big_readX) {
3843 NTSTATUS status = schedule_aio_read_and_X(conn,
3844 req,
3845 fsp,
3846 startpos,
3847 smb_maxcnt);
3848 if (NT_STATUS_IS_OK(status)) {
3849 /* Read scheduled - we're done. */
3850 goto out;
3852 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3853 /* Real error - report to client. */
3854 END_PROFILE(SMBreadX);
3855 reply_nterror(req, status);
3856 return;
3858 /* NT_STATUS_RETRY - fall back to sync read. */
3861 smbd_lock_socket(req->sconn);
3862 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3863 smbd_unlock_socket(req->sconn);
3865 out:
3866 END_PROFILE(SMBreadX);
3867 return;
3870 /****************************************************************************
3871 Error replies to writebraw must have smb_wct == 1. Fix this up.
3872 ****************************************************************************/
3874 void error_to_writebrawerr(struct smb_request *req)
3876 uint8 *old_outbuf = req->outbuf;
3878 reply_outbuf(req, 1, 0);
3880 memcpy(req->outbuf, old_outbuf, smb_size);
3881 TALLOC_FREE(old_outbuf);
3884 /****************************************************************************
3885 Read 4 bytes of a smb packet and return the smb length of the packet.
3886 Store the result in the buffer. This version of the function will
3887 never return a session keepalive (length of zero).
3888 Timeout is in milliseconds.
3889 ****************************************************************************/
3891 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3892 size_t *len)
3894 uint8_t msgtype = NBSSkeepalive;
3896 while (msgtype == NBSSkeepalive) {
3897 NTSTATUS status;
3899 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3900 len);
3901 if (!NT_STATUS_IS_OK(status)) {
3902 char addr[INET6_ADDRSTRLEN];
3903 /* Try and give an error message
3904 * saying what client failed. */
3905 DEBUG(0, ("read_fd_with_timeout failed for "
3906 "client %s read error = %s.\n",
3907 get_peer_addr(fd,addr,sizeof(addr)),
3908 nt_errstr(status)));
3909 return status;
3912 msgtype = CVAL(inbuf, 0);
3915 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3916 (unsigned long)len));
3918 return NT_STATUS_OK;
3921 /****************************************************************************
3922 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3923 ****************************************************************************/
3925 void reply_writebraw(struct smb_request *req)
3927 connection_struct *conn = req->conn;
3928 char *buf = NULL;
3929 ssize_t nwritten=0;
3930 ssize_t total_written=0;
3931 size_t numtowrite=0;
3932 size_t tcount;
3933 SMB_OFF_T startpos;
3934 const char *data=NULL;
3935 bool write_through;
3936 files_struct *fsp;
3937 struct lock_struct lock;
3938 NTSTATUS status;
3940 START_PROFILE(SMBwritebraw);
3943 * If we ever reply with an error, it must have the SMB command
3944 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3945 * we're finished.
3947 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3949 if (srv_is_signing_active(req->sconn)) {
3950 END_PROFILE(SMBwritebraw);
3951 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3952 "raw reads/writes are disallowed.");
3955 if (req->wct < 12) {
3956 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3957 error_to_writebrawerr(req);
3958 END_PROFILE(SMBwritebraw);
3959 return;
3962 if (req->sconn->smb1.echo_handler.trusted_fde) {
3963 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3964 "'async smb echo handler = yes'\n"));
3965 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3966 error_to_writebrawerr(req);
3967 END_PROFILE(SMBwritebraw);
3968 return;
3971 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3972 if (!check_fsp(conn, req, fsp)) {
3973 error_to_writebrawerr(req);
3974 END_PROFILE(SMBwritebraw);
3975 return;
3978 if (!CHECK_WRITE(fsp)) {
3979 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3980 error_to_writebrawerr(req);
3981 END_PROFILE(SMBwritebraw);
3982 return;
3985 tcount = IVAL(req->vwv+1, 0);
3986 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3987 write_through = BITSETW(req->vwv+7,0);
3989 /* We have to deal with slightly different formats depending
3990 on whether we are using the core+ or lanman1.0 protocol */
3992 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3993 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3994 data = smb_buf_const(req->inbuf);
3995 } else {
3996 numtowrite = SVAL(req->vwv+10, 0);
3997 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4000 /* Ensure we don't write bytes past the end of this packet. */
4001 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4003 error_to_writebrawerr(req);
4004 END_PROFILE(SMBwritebraw);
4005 return;
4008 if (!fsp->print_file) {
4009 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4010 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4011 &lock);
4013 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4014 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4015 error_to_writebrawerr(req);
4016 END_PROFILE(SMBwritebraw);
4017 return;
4021 if (numtowrite>0) {
4022 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4025 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4026 "wrote=%d sync=%d\n",
4027 fsp->fnum, (double)startpos, (int)numtowrite,
4028 (int)nwritten, (int)write_through));
4030 if (nwritten < (ssize_t)numtowrite) {
4031 reply_nterror(req, NT_STATUS_DISK_FULL);
4032 error_to_writebrawerr(req);
4033 goto strict_unlock;
4036 total_written = nwritten;
4038 /* Allocate a buffer of 64k + length. */
4039 buf = talloc_array(NULL, char, 65540);
4040 if (!buf) {
4041 reply_nterror(req, NT_STATUS_NO_MEMORY);
4042 error_to_writebrawerr(req);
4043 goto strict_unlock;
4046 /* Return a SMBwritebraw message to the redirector to tell
4047 * it to send more bytes */
4049 memcpy(buf, req->inbuf, smb_size);
4050 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4051 SCVAL(buf,smb_com,SMBwritebraw);
4052 SSVALS(buf,smb_vwv0,0xFFFF);
4053 show_msg(buf);
4054 if (!srv_send_smb(req->sconn,
4055 buf,
4056 false, 0, /* no signing */
4057 IS_CONN_ENCRYPTED(conn),
4058 &req->pcd)) {
4059 exit_server_cleanly("reply_writebraw: srv_send_smb "
4060 "failed.");
4063 /* Now read the raw data into the buffer and write it */
4064 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4065 &numtowrite);
4066 if (!NT_STATUS_IS_OK(status)) {
4067 exit_server_cleanly("secondary writebraw failed");
4070 /* Set up outbuf to return the correct size */
4071 reply_outbuf(req, 1, 0);
4073 if (numtowrite != 0) {
4075 if (numtowrite > 0xFFFF) {
4076 DEBUG(0,("reply_writebraw: Oversize secondary write "
4077 "raw requested (%u). Terminating\n",
4078 (unsigned int)numtowrite ));
4079 exit_server_cleanly("secondary writebraw failed");
4082 if (tcount > nwritten+numtowrite) {
4083 DEBUG(3,("reply_writebraw: Client overestimated the "
4084 "write %d %d %d\n",
4085 (int)tcount,(int)nwritten,(int)numtowrite));
4088 status = read_data(req->sconn->sock, buf+4, numtowrite);
4090 if (!NT_STATUS_IS_OK(status)) {
4091 char addr[INET6_ADDRSTRLEN];
4092 /* Try and give an error message
4093 * saying what client failed. */
4094 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4095 "raw read failed (%s) for client %s. "
4096 "Terminating\n", nt_errstr(status),
4097 get_peer_addr(req->sconn->sock, addr,
4098 sizeof(addr))));
4099 exit_server_cleanly("secondary writebraw failed");
4102 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4103 if (nwritten == -1) {
4104 TALLOC_FREE(buf);
4105 reply_nterror(req, map_nt_error_from_unix(errno));
4106 error_to_writebrawerr(req);
4107 goto strict_unlock;
4110 if (nwritten < (ssize_t)numtowrite) {
4111 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4112 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4115 if (nwritten > 0) {
4116 total_written += nwritten;
4120 TALLOC_FREE(buf);
4121 SSVAL(req->outbuf,smb_vwv0,total_written);
4123 status = sync_file(conn, fsp, write_through);
4124 if (!NT_STATUS_IS_OK(status)) {
4125 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4126 fsp_str_dbg(fsp), nt_errstr(status)));
4127 reply_nterror(req, status);
4128 error_to_writebrawerr(req);
4129 goto strict_unlock;
4132 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4133 "wrote=%d\n",
4134 fsp->fnum, (double)startpos, (int)numtowrite,
4135 (int)total_written));
4137 if (!fsp->print_file) {
4138 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4141 /* We won't return a status if write through is not selected - this
4142 * follows what WfWg does */
4143 END_PROFILE(SMBwritebraw);
4145 if (!write_through && total_written==tcount) {
4147 #if RABBIT_PELLET_FIX
4149 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4150 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4151 * JRA.
4153 if (!send_keepalive(req->sconn->sock)) {
4154 exit_server_cleanly("reply_writebraw: send of "
4155 "keepalive failed");
4157 #endif
4158 TALLOC_FREE(req->outbuf);
4160 return;
4162 strict_unlock:
4163 if (!fsp->print_file) {
4164 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4167 END_PROFILE(SMBwritebraw);
4168 return;
4171 #undef DBGC_CLASS
4172 #define DBGC_CLASS DBGC_LOCKING
4174 /****************************************************************************
4175 Reply to a writeunlock (core+).
4176 ****************************************************************************/
4178 void reply_writeunlock(struct smb_request *req)
4180 connection_struct *conn = req->conn;
4181 ssize_t nwritten = -1;
4182 size_t numtowrite;
4183 SMB_OFF_T startpos;
4184 const char *data;
4185 NTSTATUS status = NT_STATUS_OK;
4186 files_struct *fsp;
4187 struct lock_struct lock;
4188 int saved_errno = 0;
4190 START_PROFILE(SMBwriteunlock);
4192 if (req->wct < 5) {
4193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4194 END_PROFILE(SMBwriteunlock);
4195 return;
4198 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4200 if (!check_fsp(conn, req, fsp)) {
4201 END_PROFILE(SMBwriteunlock);
4202 return;
4205 if (!CHECK_WRITE(fsp)) {
4206 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4207 END_PROFILE(SMBwriteunlock);
4208 return;
4211 numtowrite = SVAL(req->vwv+1, 0);
4212 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4213 data = (const char *)req->buf + 3;
4215 if (!fsp->print_file && numtowrite > 0) {
4216 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4217 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4218 &lock);
4220 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4221 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4222 END_PROFILE(SMBwriteunlock);
4223 return;
4227 /* The special X/Open SMB protocol handling of
4228 zero length writes is *NOT* done for
4229 this call */
4230 if(numtowrite == 0) {
4231 nwritten = 0;
4232 } else {
4233 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4234 saved_errno = errno;
4237 status = sync_file(conn, fsp, False /* write through */);
4238 if (!NT_STATUS_IS_OK(status)) {
4239 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4240 fsp_str_dbg(fsp), nt_errstr(status)));
4241 reply_nterror(req, status);
4242 goto strict_unlock;
4245 if(nwritten < 0) {
4246 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4247 goto strict_unlock;
4250 if((nwritten < numtowrite) && (numtowrite != 0)) {
4251 reply_nterror(req, NT_STATUS_DISK_FULL);
4252 goto strict_unlock;
4255 if (numtowrite && !fsp->print_file) {
4256 status = do_unlock(req->sconn->msg_ctx,
4257 fsp,
4258 (uint64_t)req->smbpid,
4259 (uint64_t)numtowrite,
4260 (uint64_t)startpos,
4261 WINDOWS_LOCK);
4263 if (NT_STATUS_V(status)) {
4264 reply_nterror(req, status);
4265 goto strict_unlock;
4269 reply_outbuf(req, 1, 0);
4271 SSVAL(req->outbuf,smb_vwv0,nwritten);
4273 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4274 fsp->fnum, (int)numtowrite, (int)nwritten));
4276 strict_unlock:
4277 if (numtowrite && !fsp->print_file) {
4278 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4281 END_PROFILE(SMBwriteunlock);
4282 return;
4285 #undef DBGC_CLASS
4286 #define DBGC_CLASS DBGC_ALL
4288 /****************************************************************************
4289 Reply to a write.
4290 ****************************************************************************/
4292 void reply_write(struct smb_request *req)
4294 connection_struct *conn = req->conn;
4295 size_t numtowrite;
4296 ssize_t nwritten = -1;
4297 SMB_OFF_T startpos;
4298 const char *data;
4299 files_struct *fsp;
4300 struct lock_struct lock;
4301 NTSTATUS status;
4302 int saved_errno = 0;
4304 START_PROFILE(SMBwrite);
4306 if (req->wct < 5) {
4307 END_PROFILE(SMBwrite);
4308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4309 return;
4312 /* If it's an IPC, pass off the pipe handler. */
4313 if (IS_IPC(conn)) {
4314 reply_pipe_write(req);
4315 END_PROFILE(SMBwrite);
4316 return;
4319 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4321 if (!check_fsp(conn, req, fsp)) {
4322 END_PROFILE(SMBwrite);
4323 return;
4326 if (!CHECK_WRITE(fsp)) {
4327 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4328 END_PROFILE(SMBwrite);
4329 return;
4332 numtowrite = SVAL(req->vwv+1, 0);
4333 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4334 data = (const char *)req->buf + 3;
4336 if (!fsp->print_file) {
4337 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4338 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4339 &lock);
4341 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4342 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4343 END_PROFILE(SMBwrite);
4344 return;
4349 * X/Open SMB protocol says that if smb_vwv1 is
4350 * zero then the file size should be extended or
4351 * truncated to the size given in smb_vwv[2-3].
4354 if(numtowrite == 0) {
4356 * This is actually an allocate call, and set EOF. JRA.
4358 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4359 if (nwritten < 0) {
4360 reply_nterror(req, NT_STATUS_DISK_FULL);
4361 goto strict_unlock;
4363 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4364 if (nwritten < 0) {
4365 reply_nterror(req, NT_STATUS_DISK_FULL);
4366 goto strict_unlock;
4368 trigger_write_time_update_immediate(fsp);
4369 } else {
4370 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4373 status = sync_file(conn, fsp, False);
4374 if (!NT_STATUS_IS_OK(status)) {
4375 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4376 fsp_str_dbg(fsp), nt_errstr(status)));
4377 reply_nterror(req, status);
4378 goto strict_unlock;
4381 if(nwritten < 0) {
4382 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4383 goto strict_unlock;
4386 if((nwritten == 0) && (numtowrite != 0)) {
4387 reply_nterror(req, NT_STATUS_DISK_FULL);
4388 goto strict_unlock;
4391 reply_outbuf(req, 1, 0);
4393 SSVAL(req->outbuf,smb_vwv0,nwritten);
4395 if (nwritten < (ssize_t)numtowrite) {
4396 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4397 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4400 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4402 strict_unlock:
4403 if (!fsp->print_file) {
4404 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4407 END_PROFILE(SMBwrite);
4408 return;
4411 /****************************************************************************
4412 Ensure a buffer is a valid writeX for recvfile purposes.
4413 ****************************************************************************/
4415 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4416 (2*14) + /* word count (including bcc) */ \
4417 1 /* pad byte */)
4419 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4420 const uint8_t *inbuf)
4422 size_t numtowrite;
4423 connection_struct *conn = NULL;
4424 unsigned int doff = 0;
4425 size_t len = smb_len_large(inbuf);
4427 if (is_encrypted_packet(sconn, inbuf)) {
4428 /* Can't do this on encrypted
4429 * connections. */
4430 return false;
4433 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4434 return false;
4437 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4438 CVAL(inbuf,smb_wct) != 14) {
4439 DEBUG(10,("is_valid_writeX_buffer: chained or "
4440 "invalid word length.\n"));
4441 return false;
4444 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4445 if (conn == NULL) {
4446 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4447 return false;
4449 if (IS_IPC(conn)) {
4450 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4451 return false;
4453 if (IS_PRINT(conn)) {
4454 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4455 return false;
4457 doff = SVAL(inbuf,smb_vwv11);
4459 numtowrite = SVAL(inbuf,smb_vwv10);
4461 if (len > doff && len - doff > 0xFFFF) {
4462 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4465 if (numtowrite == 0) {
4466 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4467 return false;
4470 /* Ensure the sizes match up. */
4471 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4472 /* no pad byte...old smbclient :-( */
4473 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4474 (unsigned int)doff,
4475 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4476 return false;
4479 if (len - doff != numtowrite) {
4480 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4481 "len = %u, doff = %u, numtowrite = %u\n",
4482 (unsigned int)len,
4483 (unsigned int)doff,
4484 (unsigned int)numtowrite ));
4485 return false;
4488 DEBUG(10,("is_valid_writeX_buffer: true "
4489 "len = %u, doff = %u, numtowrite = %u\n",
4490 (unsigned int)len,
4491 (unsigned int)doff,
4492 (unsigned int)numtowrite ));
4494 return true;
4497 /****************************************************************************
4498 Reply to a write and X.
4499 ****************************************************************************/
4501 void reply_write_and_X(struct smb_request *req)
4503 connection_struct *conn = req->conn;
4504 files_struct *fsp;
4505 struct lock_struct lock;
4506 SMB_OFF_T startpos;
4507 size_t numtowrite;
4508 bool write_through;
4509 ssize_t nwritten;
4510 unsigned int smb_doff;
4511 unsigned int smblen;
4512 const char *data;
4513 NTSTATUS status;
4514 int saved_errno = 0;
4516 START_PROFILE(SMBwriteX);
4518 if ((req->wct != 12) && (req->wct != 14)) {
4519 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4520 END_PROFILE(SMBwriteX);
4521 return;
4524 numtowrite = SVAL(req->vwv+10, 0);
4525 smb_doff = SVAL(req->vwv+11, 0);
4526 smblen = smb_len(req->inbuf);
4528 if (req->unread_bytes > 0xFFFF ||
4529 (smblen > smb_doff &&
4530 smblen - smb_doff > 0xFFFF)) {
4531 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4534 if (req->unread_bytes) {
4535 /* Can't do a recvfile write on IPC$ */
4536 if (IS_IPC(conn)) {
4537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4538 END_PROFILE(SMBwriteX);
4539 return;
4541 if (numtowrite != req->unread_bytes) {
4542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4543 END_PROFILE(SMBwriteX);
4544 return;
4546 } else {
4547 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4548 smb_doff + numtowrite > smblen) {
4549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4550 END_PROFILE(SMBwriteX);
4551 return;
4555 /* If it's an IPC, pass off the pipe handler. */
4556 if (IS_IPC(conn)) {
4557 if (req->unread_bytes) {
4558 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4559 END_PROFILE(SMBwriteX);
4560 return;
4562 reply_pipe_write_and_X(req);
4563 END_PROFILE(SMBwriteX);
4564 return;
4567 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4568 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4569 write_through = BITSETW(req->vwv+7,0);
4571 if (!check_fsp(conn, req, fsp)) {
4572 END_PROFILE(SMBwriteX);
4573 return;
4576 if (!CHECK_WRITE(fsp)) {
4577 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4578 END_PROFILE(SMBwriteX);
4579 return;
4582 data = smb_base(req->inbuf) + smb_doff;
4584 if(req->wct == 14) {
4585 #ifdef LARGE_SMB_OFF_T
4587 * This is a large offset (64 bit) write.
4589 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4591 #else /* !LARGE_SMB_OFF_T */
4594 * Ensure we haven't been sent a >32 bit offset.
4597 if(IVAL(req->vwv+12, 0) != 0) {
4598 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4599 "used and we don't support 64 bit offsets.\n",
4600 (unsigned int)IVAL(req->vwv+12, 0) ));
4601 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4602 END_PROFILE(SMBwriteX);
4603 return;
4606 #endif /* LARGE_SMB_OFF_T */
4609 /* X/Open SMB protocol says that, unlike SMBwrite
4610 if the length is zero then NO truncation is
4611 done, just a write of zero. To truncate a file,
4612 use SMBwrite. */
4614 if(numtowrite == 0) {
4615 nwritten = 0;
4616 } else {
4617 if (req->unread_bytes == 0) {
4618 status = schedule_aio_write_and_X(conn,
4619 req,
4620 fsp,
4621 data,
4622 startpos,
4623 numtowrite);
4625 if (NT_STATUS_IS_OK(status)) {
4626 /* write scheduled - we're done. */
4627 goto out;
4629 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4630 /* Real error - report to client. */
4631 reply_nterror(req, status);
4632 goto out;
4634 /* NT_STATUS_RETRY - fall through to sync write. */
4637 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4638 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4639 &lock);
4641 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4642 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4643 goto out;
4646 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4647 saved_errno = errno;
4649 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4652 if(nwritten < 0) {
4653 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4654 goto out;
4657 if((nwritten == 0) && (numtowrite != 0)) {
4658 reply_nterror(req, NT_STATUS_DISK_FULL);
4659 goto out;
4662 reply_outbuf(req, 6, 0);
4663 SSVAL(req->outbuf,smb_vwv2,nwritten);
4664 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4666 if (nwritten < (ssize_t)numtowrite) {
4667 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4668 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4671 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4672 fsp->fnum, (int)numtowrite, (int)nwritten));
4674 status = sync_file(conn, fsp, write_through);
4675 if (!NT_STATUS_IS_OK(status)) {
4676 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4677 fsp_str_dbg(fsp), nt_errstr(status)));
4678 reply_nterror(req, status);
4679 goto out;
4682 END_PROFILE(SMBwriteX);
4683 chain_reply(req);
4684 return;
4686 out:
4687 END_PROFILE(SMBwriteX);
4688 return;
4691 /****************************************************************************
4692 Reply to a lseek.
4693 ****************************************************************************/
4695 void reply_lseek(struct smb_request *req)
4697 connection_struct *conn = req->conn;
4698 SMB_OFF_T startpos;
4699 SMB_OFF_T res= -1;
4700 int mode,umode;
4701 files_struct *fsp;
4703 START_PROFILE(SMBlseek);
4705 if (req->wct < 4) {
4706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4707 END_PROFILE(SMBlseek);
4708 return;
4711 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4713 if (!check_fsp(conn, req, fsp)) {
4714 return;
4717 flush_write_cache(fsp, SEEK_FLUSH);
4719 mode = SVAL(req->vwv+1, 0) & 3;
4720 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4721 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4723 switch (mode) {
4724 case 0:
4725 umode = SEEK_SET;
4726 res = startpos;
4727 break;
4728 case 1:
4729 umode = SEEK_CUR;
4730 res = fsp->fh->pos + startpos;
4731 break;
4732 case 2:
4733 umode = SEEK_END;
4734 break;
4735 default:
4736 umode = SEEK_SET;
4737 res = startpos;
4738 break;
4741 if (umode == SEEK_END) {
4742 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4743 if(errno == EINVAL) {
4744 SMB_OFF_T current_pos = startpos;
4746 if(fsp_stat(fsp) == -1) {
4747 reply_nterror(req,
4748 map_nt_error_from_unix(errno));
4749 END_PROFILE(SMBlseek);
4750 return;
4753 current_pos += fsp->fsp_name->st.st_ex_size;
4754 if(current_pos < 0)
4755 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4759 if(res == -1) {
4760 reply_nterror(req, map_nt_error_from_unix(errno));
4761 END_PROFILE(SMBlseek);
4762 return;
4766 fsp->fh->pos = res;
4768 reply_outbuf(req, 2, 0);
4769 SIVAL(req->outbuf,smb_vwv0,res);
4771 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4772 fsp->fnum, (double)startpos, (double)res, mode));
4774 END_PROFILE(SMBlseek);
4775 return;
4778 /****************************************************************************
4779 Reply to a flush.
4780 ****************************************************************************/
4782 void reply_flush(struct smb_request *req)
4784 connection_struct *conn = req->conn;
4785 uint16 fnum;
4786 files_struct *fsp;
4788 START_PROFILE(SMBflush);
4790 if (req->wct < 1) {
4791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4792 return;
4795 fnum = SVAL(req->vwv+0, 0);
4796 fsp = file_fsp(req, fnum);
4798 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4799 return;
4802 if (!fsp) {
4803 file_sync_all(conn);
4804 } else {
4805 NTSTATUS status = sync_file(conn, fsp, True);
4806 if (!NT_STATUS_IS_OK(status)) {
4807 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4808 fsp_str_dbg(fsp), nt_errstr(status)));
4809 reply_nterror(req, status);
4810 END_PROFILE(SMBflush);
4811 return;
4815 reply_outbuf(req, 0, 0);
4817 DEBUG(3,("flush\n"));
4818 END_PROFILE(SMBflush);
4819 return;
4822 /****************************************************************************
4823 Reply to a exit.
4824 conn POINTER CAN BE NULL HERE !
4825 ****************************************************************************/
4827 void reply_exit(struct smb_request *req)
4829 START_PROFILE(SMBexit);
4831 file_close_pid(req->sconn, req->smbpid, req->vuid);
4833 reply_outbuf(req, 0, 0);
4835 DEBUG(3,("exit\n"));
4837 END_PROFILE(SMBexit);
4838 return;
4841 /****************************************************************************
4842 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4843 ****************************************************************************/
4845 void reply_close(struct smb_request *req)
4847 connection_struct *conn = req->conn;
4848 NTSTATUS status = NT_STATUS_OK;
4849 files_struct *fsp = NULL;
4850 START_PROFILE(SMBclose);
4852 if (req->wct < 3) {
4853 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4854 END_PROFILE(SMBclose);
4855 return;
4858 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4861 * We can only use check_fsp if we know it's not a directory.
4864 if (!check_fsp_open(conn, req, fsp)) {
4865 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4866 END_PROFILE(SMBclose);
4867 return;
4870 if(fsp->is_directory) {
4872 * Special case - close NT SMB directory handle.
4874 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4875 status = close_file(req, fsp, NORMAL_CLOSE);
4876 } else {
4877 time_t t;
4879 * Close ordinary file.
4882 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4883 fsp->fh->fd, fsp->fnum,
4884 conn->num_files_open));
4887 * Take care of any time sent in the close.
4890 t = srv_make_unix_date3(req->vwv+1);
4891 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4894 * close_file() returns the unix errno if an error
4895 * was detected on close - normally this is due to
4896 * a disk full error. If not then it was probably an I/O error.
4899 status = close_file(req, fsp, NORMAL_CLOSE);
4902 if (!NT_STATUS_IS_OK(status)) {
4903 reply_nterror(req, status);
4904 END_PROFILE(SMBclose);
4905 return;
4908 reply_outbuf(req, 0, 0);
4909 END_PROFILE(SMBclose);
4910 return;
4913 /****************************************************************************
4914 Reply to a writeclose (Core+ protocol).
4915 ****************************************************************************/
4917 void reply_writeclose(struct smb_request *req)
4919 connection_struct *conn = req->conn;
4920 size_t numtowrite;
4921 ssize_t nwritten = -1;
4922 NTSTATUS close_status = NT_STATUS_OK;
4923 SMB_OFF_T startpos;
4924 const char *data;
4925 struct timespec mtime;
4926 files_struct *fsp;
4927 struct lock_struct lock;
4929 START_PROFILE(SMBwriteclose);
4931 if (req->wct < 6) {
4932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4933 END_PROFILE(SMBwriteclose);
4934 return;
4937 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4939 if (!check_fsp(conn, req, fsp)) {
4940 END_PROFILE(SMBwriteclose);
4941 return;
4943 if (!CHECK_WRITE(fsp)) {
4944 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4945 END_PROFILE(SMBwriteclose);
4946 return;
4949 numtowrite = SVAL(req->vwv+1, 0);
4950 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4951 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4952 data = (const char *)req->buf + 1;
4954 if (!fsp->print_file) {
4955 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4956 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4957 &lock);
4959 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4960 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4961 END_PROFILE(SMBwriteclose);
4962 return;
4966 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4968 set_close_write_time(fsp, mtime);
4971 * More insanity. W2K only closes the file if writelen > 0.
4972 * JRA.
4975 if (numtowrite) {
4976 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4977 "file %s\n", fsp_str_dbg(fsp)));
4978 close_status = close_file(req, fsp, NORMAL_CLOSE);
4981 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4982 fsp->fnum, (int)numtowrite, (int)nwritten,
4983 conn->num_files_open));
4985 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4986 reply_nterror(req, NT_STATUS_DISK_FULL);
4987 goto strict_unlock;
4990 if(!NT_STATUS_IS_OK(close_status)) {
4991 reply_nterror(req, close_status);
4992 goto strict_unlock;
4995 reply_outbuf(req, 1, 0);
4997 SSVAL(req->outbuf,smb_vwv0,nwritten);
4999 strict_unlock:
5000 if (numtowrite && !fsp->print_file) {
5001 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5004 END_PROFILE(SMBwriteclose);
5005 return;
5008 #undef DBGC_CLASS
5009 #define DBGC_CLASS DBGC_LOCKING
5011 /****************************************************************************
5012 Reply to a lock.
5013 ****************************************************************************/
5015 void reply_lock(struct smb_request *req)
5017 connection_struct *conn = req->conn;
5018 uint64_t count,offset;
5019 NTSTATUS status;
5020 files_struct *fsp;
5021 struct byte_range_lock *br_lck = NULL;
5023 START_PROFILE(SMBlock);
5025 if (req->wct < 5) {
5026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5027 END_PROFILE(SMBlock);
5028 return;
5031 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5033 if (!check_fsp(conn, req, fsp)) {
5034 END_PROFILE(SMBlock);
5035 return;
5038 count = (uint64_t)IVAL(req->vwv+1, 0);
5039 offset = (uint64_t)IVAL(req->vwv+3, 0);
5041 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5042 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5044 br_lck = do_lock(req->sconn->msg_ctx,
5045 fsp,
5046 (uint64_t)req->smbpid,
5047 count,
5048 offset,
5049 WRITE_LOCK,
5050 WINDOWS_LOCK,
5051 False, /* Non-blocking lock. */
5052 &status,
5053 NULL,
5054 NULL);
5056 TALLOC_FREE(br_lck);
5058 if (NT_STATUS_V(status)) {
5059 reply_nterror(req, status);
5060 END_PROFILE(SMBlock);
5061 return;
5064 reply_outbuf(req, 0, 0);
5066 END_PROFILE(SMBlock);
5067 return;
5070 /****************************************************************************
5071 Reply to a unlock.
5072 ****************************************************************************/
5074 void reply_unlock(struct smb_request *req)
5076 connection_struct *conn = req->conn;
5077 uint64_t count,offset;
5078 NTSTATUS status;
5079 files_struct *fsp;
5081 START_PROFILE(SMBunlock);
5083 if (req->wct < 5) {
5084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5085 END_PROFILE(SMBunlock);
5086 return;
5089 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5091 if (!check_fsp(conn, req, fsp)) {
5092 END_PROFILE(SMBunlock);
5093 return;
5096 count = (uint64_t)IVAL(req->vwv+1, 0);
5097 offset = (uint64_t)IVAL(req->vwv+3, 0);
5099 status = do_unlock(req->sconn->msg_ctx,
5100 fsp,
5101 (uint64_t)req->smbpid,
5102 count,
5103 offset,
5104 WINDOWS_LOCK);
5106 if (NT_STATUS_V(status)) {
5107 reply_nterror(req, status);
5108 END_PROFILE(SMBunlock);
5109 return;
5112 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5113 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5115 reply_outbuf(req, 0, 0);
5117 END_PROFILE(SMBunlock);
5118 return;
5121 #undef DBGC_CLASS
5122 #define DBGC_CLASS DBGC_ALL
5124 /****************************************************************************
5125 Reply to a tdis.
5126 conn POINTER CAN BE NULL HERE !
5127 ****************************************************************************/
5129 void reply_tdis(struct smb_request *req)
5131 connection_struct *conn = req->conn;
5132 START_PROFILE(SMBtdis);
5134 if (!conn) {
5135 DEBUG(4,("Invalid connection in tdis\n"));
5136 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5137 END_PROFILE(SMBtdis);
5138 return;
5141 conn->used = False;
5143 close_cnum(conn,req->vuid);
5144 req->conn = NULL;
5146 reply_outbuf(req, 0, 0);
5147 END_PROFILE(SMBtdis);
5148 return;
5151 /****************************************************************************
5152 Reply to a echo.
5153 conn POINTER CAN BE NULL HERE !
5154 ****************************************************************************/
5156 void reply_echo(struct smb_request *req)
5158 connection_struct *conn = req->conn;
5159 struct smb_perfcount_data local_pcd;
5160 struct smb_perfcount_data *cur_pcd;
5161 int smb_reverb;
5162 int seq_num;
5164 START_PROFILE(SMBecho);
5166 smb_init_perfcount_data(&local_pcd);
5168 if (req->wct < 1) {
5169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5170 END_PROFILE(SMBecho);
5171 return;
5174 smb_reverb = SVAL(req->vwv+0, 0);
5176 reply_outbuf(req, 1, req->buflen);
5178 /* copy any incoming data back out */
5179 if (req->buflen > 0) {
5180 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5183 if (smb_reverb > 100) {
5184 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5185 smb_reverb = 100;
5188 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5190 /* this makes sure we catch the request pcd */
5191 if (seq_num == smb_reverb) {
5192 cur_pcd = &req->pcd;
5193 } else {
5194 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5195 cur_pcd = &local_pcd;
5198 SSVAL(req->outbuf,smb_vwv0,seq_num);
5200 show_msg((char *)req->outbuf);
5201 if (!srv_send_smb(req->sconn,
5202 (char *)req->outbuf,
5203 true, req->seqnum+1,
5204 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5205 cur_pcd))
5206 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5209 DEBUG(3,("echo %d times\n", smb_reverb));
5211 TALLOC_FREE(req->outbuf);
5213 END_PROFILE(SMBecho);
5214 return;
5217 /****************************************************************************
5218 Reply to a printopen.
5219 ****************************************************************************/
5221 void reply_printopen(struct smb_request *req)
5223 connection_struct *conn = req->conn;
5224 files_struct *fsp;
5225 NTSTATUS status;
5227 START_PROFILE(SMBsplopen);
5229 if (req->wct < 2) {
5230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5231 END_PROFILE(SMBsplopen);
5232 return;
5235 if (!CAN_PRINT(conn)) {
5236 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5237 END_PROFILE(SMBsplopen);
5238 return;
5241 status = file_new(req, conn, &fsp);
5242 if(!NT_STATUS_IS_OK(status)) {
5243 reply_nterror(req, status);
5244 END_PROFILE(SMBsplopen);
5245 return;
5248 /* Open for exclusive use, write only. */
5249 status = print_spool_open(fsp, NULL, req->vuid);
5251 if (!NT_STATUS_IS_OK(status)) {
5252 file_free(req, fsp);
5253 reply_nterror(req, status);
5254 END_PROFILE(SMBsplopen);
5255 return;
5258 reply_outbuf(req, 1, 0);
5259 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5261 DEBUG(3,("openprint fd=%d fnum=%d\n",
5262 fsp->fh->fd, fsp->fnum));
5264 END_PROFILE(SMBsplopen);
5265 return;
5268 /****************************************************************************
5269 Reply to a printclose.
5270 ****************************************************************************/
5272 void reply_printclose(struct smb_request *req)
5274 connection_struct *conn = req->conn;
5275 files_struct *fsp;
5276 NTSTATUS status;
5278 START_PROFILE(SMBsplclose);
5280 if (req->wct < 1) {
5281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5282 END_PROFILE(SMBsplclose);
5283 return;
5286 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5288 if (!check_fsp(conn, req, fsp)) {
5289 END_PROFILE(SMBsplclose);
5290 return;
5293 if (!CAN_PRINT(conn)) {
5294 reply_force_doserror(req, ERRSRV, ERRerror);
5295 END_PROFILE(SMBsplclose);
5296 return;
5299 DEBUG(3,("printclose fd=%d fnum=%d\n",
5300 fsp->fh->fd,fsp->fnum));
5302 status = close_file(req, fsp, NORMAL_CLOSE);
5304 if(!NT_STATUS_IS_OK(status)) {
5305 reply_nterror(req, status);
5306 END_PROFILE(SMBsplclose);
5307 return;
5310 reply_outbuf(req, 0, 0);
5312 END_PROFILE(SMBsplclose);
5313 return;
5316 /****************************************************************************
5317 Reply to a printqueue.
5318 ****************************************************************************/
5320 void reply_printqueue(struct smb_request *req)
5322 connection_struct *conn = req->conn;
5323 int max_count;
5324 int start_index;
5326 START_PROFILE(SMBsplretq);
5328 if (req->wct < 2) {
5329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5330 END_PROFILE(SMBsplretq);
5331 return;
5334 max_count = SVAL(req->vwv+0, 0);
5335 start_index = SVAL(req->vwv+1, 0);
5337 /* we used to allow the client to get the cnum wrong, but that
5338 is really quite gross and only worked when there was only
5339 one printer - I think we should now only accept it if they
5340 get it right (tridge) */
5341 if (!CAN_PRINT(conn)) {
5342 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5343 END_PROFILE(SMBsplretq);
5344 return;
5347 reply_outbuf(req, 2, 3);
5348 SSVAL(req->outbuf,smb_vwv0,0);
5349 SSVAL(req->outbuf,smb_vwv1,0);
5350 SCVAL(smb_buf(req->outbuf),0,1);
5351 SSVAL(smb_buf(req->outbuf),1,0);
5353 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5354 start_index, max_count));
5357 TALLOC_CTX *mem_ctx = talloc_tos();
5358 NTSTATUS status;
5359 WERROR werr;
5360 const char *sharename = lp_servicename(SNUM(conn));
5361 struct rpc_pipe_client *cli = NULL;
5362 struct dcerpc_binding_handle *b = NULL;
5363 struct policy_handle handle;
5364 struct spoolss_DevmodeContainer devmode_ctr;
5365 union spoolss_JobInfo *info;
5366 uint32_t count;
5367 uint32_t num_to_get;
5368 uint32_t first;
5369 uint32_t i;
5371 ZERO_STRUCT(handle);
5373 status = rpc_pipe_open_interface(conn,
5374 &ndr_table_spoolss.syntax_id,
5375 conn->session_info,
5376 conn->sconn->remote_address,
5377 conn->sconn->msg_ctx,
5378 &cli);
5379 if (!NT_STATUS_IS_OK(status)) {
5380 DEBUG(0, ("reply_printqueue: "
5381 "could not connect to spoolss: %s\n",
5382 nt_errstr(status)));
5383 reply_nterror(req, status);
5384 goto out;
5386 b = cli->binding_handle;
5388 ZERO_STRUCT(devmode_ctr);
5390 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5391 sharename,
5392 NULL, devmode_ctr,
5393 SEC_FLAG_MAXIMUM_ALLOWED,
5394 &handle,
5395 &werr);
5396 if (!NT_STATUS_IS_OK(status)) {
5397 reply_nterror(req, status);
5398 goto out;
5400 if (!W_ERROR_IS_OK(werr)) {
5401 reply_nterror(req, werror_to_ntstatus(werr));
5402 goto out;
5405 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5406 &handle,
5407 0, /* firstjob */
5408 0xff, /* numjobs */
5409 2, /* level */
5410 0, /* offered */
5411 &count,
5412 &info);
5413 if (!W_ERROR_IS_OK(werr)) {
5414 reply_nterror(req, werror_to_ntstatus(werr));
5415 goto out;
5418 if (max_count > 0) {
5419 first = start_index;
5420 } else {
5421 first = start_index + max_count + 1;
5424 if (first >= count) {
5425 num_to_get = first;
5426 } else {
5427 num_to_get = first + MIN(ABS(max_count), count - first);
5430 for (i = first; i < num_to_get; i++) {
5431 char blob[28];
5432 char *p = blob;
5433 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5434 int qstatus;
5435 uint16_t qrapjobid = pjobid_to_rap(sharename,
5436 info[i].info2.job_id);
5438 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5439 qstatus = 2;
5440 } else {
5441 qstatus = 3;
5444 srv_put_dos_date2(p, 0, qtime);
5445 SCVAL(p, 4, qstatus);
5446 SSVAL(p, 5, qrapjobid);
5447 SIVAL(p, 7, info[i].info2.size);
5448 SCVAL(p, 11, 0);
5449 srvstr_push(blob, req->flags2, p+12,
5450 info[i].info2.notify_name, 16, STR_ASCII);
5452 if (message_push_blob(
5453 &req->outbuf,
5454 data_blob_const(
5455 blob, sizeof(blob))) == -1) {
5456 reply_nterror(req, NT_STATUS_NO_MEMORY);
5457 goto out;
5461 if (count > 0) {
5462 SSVAL(req->outbuf,smb_vwv0,count);
5463 SSVAL(req->outbuf,smb_vwv1,
5464 (max_count>0?first+count:first-1));
5465 SCVAL(smb_buf(req->outbuf),0,1);
5466 SSVAL(smb_buf(req->outbuf),1,28*count);
5470 DEBUG(3, ("%u entries returned in queue\n",
5471 (unsigned)count));
5473 out:
5474 if (b && is_valid_policy_hnd(&handle)) {
5475 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5480 END_PROFILE(SMBsplretq);
5481 return;
5484 /****************************************************************************
5485 Reply to a printwrite.
5486 ****************************************************************************/
5488 void reply_printwrite(struct smb_request *req)
5490 connection_struct *conn = req->conn;
5491 int numtowrite;
5492 const char *data;
5493 files_struct *fsp;
5495 START_PROFILE(SMBsplwr);
5497 if (req->wct < 1) {
5498 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5499 END_PROFILE(SMBsplwr);
5500 return;
5503 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5505 if (!check_fsp(conn, req, fsp)) {
5506 END_PROFILE(SMBsplwr);
5507 return;
5510 if (!fsp->print_file) {
5511 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5512 END_PROFILE(SMBsplwr);
5513 return;
5516 if (!CHECK_WRITE(fsp)) {
5517 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5518 END_PROFILE(SMBsplwr);
5519 return;
5522 numtowrite = SVAL(req->buf, 1);
5524 if (req->buflen < numtowrite + 3) {
5525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5526 END_PROFILE(SMBsplwr);
5527 return;
5530 data = (const char *)req->buf + 3;
5532 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5533 reply_nterror(req, map_nt_error_from_unix(errno));
5534 END_PROFILE(SMBsplwr);
5535 return;
5538 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5540 END_PROFILE(SMBsplwr);
5541 return;
5544 /****************************************************************************
5545 Reply to a mkdir.
5546 ****************************************************************************/
5548 void reply_mkdir(struct smb_request *req)
5550 connection_struct *conn = req->conn;
5551 struct smb_filename *smb_dname = NULL;
5552 char *directory = NULL;
5553 NTSTATUS status;
5554 TALLOC_CTX *ctx = talloc_tos();
5556 START_PROFILE(SMBmkdir);
5558 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5559 STR_TERMINATE, &status);
5560 if (!NT_STATUS_IS_OK(status)) {
5561 reply_nterror(req, status);
5562 goto out;
5565 status = filename_convert(ctx, conn,
5566 req->flags2 & FLAGS2_DFS_PATHNAMES,
5567 directory,
5569 NULL,
5570 &smb_dname);
5571 if (!NT_STATUS_IS_OK(status)) {
5572 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5573 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5574 ERRSRV, ERRbadpath);
5575 goto out;
5577 reply_nterror(req, status);
5578 goto out;
5581 status = create_directory(conn, req, smb_dname);
5583 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5585 if (!NT_STATUS_IS_OK(status)) {
5587 if (!use_nt_status()
5588 && NT_STATUS_EQUAL(status,
5589 NT_STATUS_OBJECT_NAME_COLLISION)) {
5591 * Yes, in the DOS error code case we get a
5592 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5593 * samba4 torture test.
5595 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5598 reply_nterror(req, status);
5599 goto out;
5602 reply_outbuf(req, 0, 0);
5604 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5605 out:
5606 TALLOC_FREE(smb_dname);
5607 END_PROFILE(SMBmkdir);
5608 return;
5611 /****************************************************************************
5612 Reply to a rmdir.
5613 ****************************************************************************/
5615 void reply_rmdir(struct smb_request *req)
5617 connection_struct *conn = req->conn;
5618 struct smb_filename *smb_dname = NULL;
5619 char *directory = NULL;
5620 NTSTATUS status;
5621 TALLOC_CTX *ctx = talloc_tos();
5622 files_struct *fsp = NULL;
5623 int info = 0;
5624 struct smbd_server_connection *sconn = req->sconn;
5626 START_PROFILE(SMBrmdir);
5628 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5629 STR_TERMINATE, &status);
5630 if (!NT_STATUS_IS_OK(status)) {
5631 reply_nterror(req, status);
5632 goto out;
5635 status = filename_convert(ctx, conn,
5636 req->flags2 & FLAGS2_DFS_PATHNAMES,
5637 directory,
5639 NULL,
5640 &smb_dname);
5641 if (!NT_STATUS_IS_OK(status)) {
5642 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5643 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5644 ERRSRV, ERRbadpath);
5645 goto out;
5647 reply_nterror(req, status);
5648 goto out;
5651 if (is_ntfs_stream_smb_fname(smb_dname)) {
5652 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5653 goto out;
5656 status = SMB_VFS_CREATE_FILE(
5657 conn, /* conn */
5658 req, /* req */
5659 0, /* root_dir_fid */
5660 smb_dname, /* fname */
5661 DELETE_ACCESS, /* access_mask */
5662 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5663 FILE_SHARE_DELETE),
5664 FILE_OPEN, /* create_disposition*/
5665 FILE_DIRECTORY_FILE, /* create_options */
5666 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5667 0, /* oplock_request */
5668 0, /* allocation_size */
5669 0, /* private_flags */
5670 NULL, /* sd */
5671 NULL, /* ea_list */
5672 &fsp, /* result */
5673 &info); /* pinfo */
5675 if (!NT_STATUS_IS_OK(status)) {
5676 if (open_was_deferred(req->sconn, req->mid)) {
5677 /* We have re-scheduled this call. */
5678 goto out;
5680 reply_nterror(req, status);
5681 goto out;
5684 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5685 if (!NT_STATUS_IS_OK(status)) {
5686 close_file(req, fsp, ERROR_CLOSE);
5687 reply_nterror(req, status);
5688 goto out;
5691 if (!set_delete_on_close(fsp, true, conn->session_info->unix_token)) {
5692 close_file(req, fsp, ERROR_CLOSE);
5693 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5694 goto out;
5697 status = close_file(req, fsp, NORMAL_CLOSE);
5698 if (!NT_STATUS_IS_OK(status)) {
5699 reply_nterror(req, status);
5700 } else {
5701 reply_outbuf(req, 0, 0);
5704 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5706 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5707 out:
5708 TALLOC_FREE(smb_dname);
5709 END_PROFILE(SMBrmdir);
5710 return;
5713 /*******************************************************************
5714 Resolve wildcards in a filename rename.
5715 ********************************************************************/
5717 static bool resolve_wildcards(TALLOC_CTX *ctx,
5718 const char *name1,
5719 const char *name2,
5720 char **pp_newname)
5722 char *name2_copy = NULL;
5723 char *root1 = NULL;
5724 char *root2 = NULL;
5725 char *ext1 = NULL;
5726 char *ext2 = NULL;
5727 char *p,*p2, *pname1, *pname2;
5729 name2_copy = talloc_strdup(ctx, name2);
5730 if (!name2_copy) {
5731 return False;
5734 pname1 = strrchr_m(name1,'/');
5735 pname2 = strrchr_m(name2_copy,'/');
5737 if (!pname1 || !pname2) {
5738 return False;
5741 /* Truncate the copy of name2 at the last '/' */
5742 *pname2 = '\0';
5744 /* Now go past the '/' */
5745 pname1++;
5746 pname2++;
5748 root1 = talloc_strdup(ctx, pname1);
5749 root2 = talloc_strdup(ctx, pname2);
5751 if (!root1 || !root2) {
5752 return False;
5755 p = strrchr_m(root1,'.');
5756 if (p) {
5757 *p = 0;
5758 ext1 = talloc_strdup(ctx, p+1);
5759 } else {
5760 ext1 = talloc_strdup(ctx, "");
5762 p = strrchr_m(root2,'.');
5763 if (p) {
5764 *p = 0;
5765 ext2 = talloc_strdup(ctx, p+1);
5766 } else {
5767 ext2 = talloc_strdup(ctx, "");
5770 if (!ext1 || !ext2) {
5771 return False;
5774 p = root1;
5775 p2 = root2;
5776 while (*p2) {
5777 if (*p2 == '?') {
5778 /* Hmmm. Should this be mb-aware ? */
5779 *p2 = *p;
5780 p2++;
5781 } else if (*p2 == '*') {
5782 *p2 = '\0';
5783 root2 = talloc_asprintf(ctx, "%s%s",
5784 root2,
5786 if (!root2) {
5787 return False;
5789 break;
5790 } else {
5791 p2++;
5793 if (*p) {
5794 p++;
5798 p = ext1;
5799 p2 = ext2;
5800 while (*p2) {
5801 if (*p2 == '?') {
5802 /* Hmmm. Should this be mb-aware ? */
5803 *p2 = *p;
5804 p2++;
5805 } else if (*p2 == '*') {
5806 *p2 = '\0';
5807 ext2 = talloc_asprintf(ctx, "%s%s",
5808 ext2,
5810 if (!ext2) {
5811 return False;
5813 break;
5814 } else {
5815 p2++;
5817 if (*p) {
5818 p++;
5822 if (*ext2) {
5823 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5824 name2_copy,
5825 root2,
5826 ext2);
5827 } else {
5828 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5829 name2_copy,
5830 root2);
5833 if (!*pp_newname) {
5834 return False;
5837 return True;
5840 /****************************************************************************
5841 Ensure open files have their names updated. Updated to notify other smbd's
5842 asynchronously.
5843 ****************************************************************************/
5845 static void rename_open_files(connection_struct *conn,
5846 struct share_mode_lock *lck,
5847 uint32_t orig_name_hash,
5848 const struct smb_filename *smb_fname_dst)
5850 files_struct *fsp;
5851 bool did_rename = False;
5852 NTSTATUS status;
5853 uint32_t new_name_hash = 0;
5855 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5856 fsp = file_find_di_next(fsp)) {
5857 /* fsp_name is a relative path under the fsp. To change this for other
5858 sharepaths we need to manipulate relative paths. */
5859 /* TODO - create the absolute path and manipulate the newname
5860 relative to the sharepath. */
5861 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5862 continue;
5864 if (fsp->name_hash != orig_name_hash) {
5865 continue;
5867 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5868 "(file_id %s) from %s -> %s\n", fsp->fnum,
5869 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5870 smb_fname_str_dbg(smb_fname_dst)));
5872 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5873 if (NT_STATUS_IS_OK(status)) {
5874 did_rename = True;
5875 new_name_hash = fsp->name_hash;
5879 if (!did_rename) {
5880 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5881 "for %s\n", file_id_string_tos(&lck->id),
5882 smb_fname_str_dbg(smb_fname_dst)));
5885 /* Send messages to all smbd's (not ourself) that the name has changed. */
5886 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5887 orig_name_hash, new_name_hash,
5888 smb_fname_dst);
5892 /****************************************************************************
5893 We need to check if the source path is a parent directory of the destination
5894 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5895 refuse the rename with a sharing violation. Under UNIX the above call can
5896 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5897 probably need to check that the client is a Windows one before disallowing
5898 this as a UNIX client (one with UNIX extensions) can know the source is a
5899 symlink and make this decision intelligently. Found by an excellent bug
5900 report from <AndyLiebman@aol.com>.
5901 ****************************************************************************/
5903 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5904 const struct smb_filename *smb_fname_dst)
5906 const char *psrc = smb_fname_src->base_name;
5907 const char *pdst = smb_fname_dst->base_name;
5908 size_t slen;
5910 if (psrc[0] == '.' && psrc[1] == '/') {
5911 psrc += 2;
5913 if (pdst[0] == '.' && pdst[1] == '/') {
5914 pdst += 2;
5916 if ((slen = strlen(psrc)) > strlen(pdst)) {
5917 return False;
5919 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5923 * Do the notify calls from a rename
5926 static void notify_rename(connection_struct *conn, bool is_dir,
5927 const struct smb_filename *smb_fname_src,
5928 const struct smb_filename *smb_fname_dst)
5930 char *parent_dir_src = NULL;
5931 char *parent_dir_dst = NULL;
5932 uint32 mask;
5934 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5935 : FILE_NOTIFY_CHANGE_FILE_NAME;
5937 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5938 &parent_dir_src, NULL) ||
5939 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5940 &parent_dir_dst, NULL)) {
5941 goto out;
5944 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5945 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5946 smb_fname_src->base_name);
5947 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5948 smb_fname_dst->base_name);
5950 else {
5951 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5952 smb_fname_src->base_name);
5953 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5954 smb_fname_dst->base_name);
5957 /* this is a strange one. w2k3 gives an additional event for
5958 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5959 files, but not directories */
5960 if (!is_dir) {
5961 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5962 FILE_NOTIFY_CHANGE_ATTRIBUTES
5963 |FILE_NOTIFY_CHANGE_CREATION,
5964 smb_fname_dst->base_name);
5966 out:
5967 TALLOC_FREE(parent_dir_src);
5968 TALLOC_FREE(parent_dir_dst);
5971 /****************************************************************************
5972 Returns an error if the parent directory for a filename is open in an
5973 incompatible way.
5974 ****************************************************************************/
5976 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5977 const struct smb_filename *smb_fname_dst_in)
5979 char *parent_dir = NULL;
5980 struct smb_filename smb_fname_parent;
5981 struct file_id id;
5982 files_struct *fsp = NULL;
5983 int ret;
5985 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5986 &parent_dir, NULL)) {
5987 return NT_STATUS_NO_MEMORY;
5989 ZERO_STRUCT(smb_fname_parent);
5990 smb_fname_parent.base_name = parent_dir;
5992 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5993 if (ret == -1) {
5994 return map_nt_error_from_unix(errno);
5998 * We're only checking on this smbd here, mostly good
5999 * enough.. and will pass tests.
6002 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6003 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6004 fsp = file_find_di_next(fsp)) {
6005 if (fsp->access_mask & DELETE_ACCESS) {
6006 return NT_STATUS_SHARING_VIOLATION;
6009 return NT_STATUS_OK;
6012 /****************************************************************************
6013 Rename an open file - given an fsp.
6014 ****************************************************************************/
6016 NTSTATUS rename_internals_fsp(connection_struct *conn,
6017 files_struct *fsp,
6018 const struct smb_filename *smb_fname_dst_in,
6019 uint32 attrs,
6020 bool replace_if_exists)
6022 TALLOC_CTX *ctx = talloc_tos();
6023 struct smb_filename *smb_fname_dst = NULL;
6024 NTSTATUS status = NT_STATUS_OK;
6025 struct share_mode_lock *lck = NULL;
6026 bool dst_exists, old_is_stream, new_is_stream;
6028 status = check_name(conn, smb_fname_dst_in->base_name);
6029 if (!NT_STATUS_IS_OK(status)) {
6030 return status;
6033 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6034 if (!NT_STATUS_IS_OK(status)) {
6035 return status;
6038 /* Make a copy of the dst smb_fname structs */
6040 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6041 if (!NT_STATUS_IS_OK(status)) {
6042 goto out;
6046 * Check for special case with case preserving and not
6047 * case sensitive. If the old last component differs from the original
6048 * last component only by case, then we should allow
6049 * the rename (user is trying to change the case of the
6050 * filename).
6052 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6053 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6054 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6055 char *last_slash;
6056 char *fname_dst_lcomp_base_mod = NULL;
6057 struct smb_filename *smb_fname_orig_lcomp = NULL;
6060 * Get the last component of the destination name.
6062 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6063 if (last_slash) {
6064 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6065 } else {
6066 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6068 if (!fname_dst_lcomp_base_mod) {
6069 status = NT_STATUS_NO_MEMORY;
6070 goto out;
6074 * Create an smb_filename struct using the original last
6075 * component of the destination.
6077 status = create_synthetic_smb_fname_split(ctx,
6078 smb_fname_dst->original_lcomp, NULL,
6079 &smb_fname_orig_lcomp);
6080 if (!NT_STATUS_IS_OK(status)) {
6081 TALLOC_FREE(fname_dst_lcomp_base_mod);
6082 goto out;
6085 /* If the base names only differ by case, use original. */
6086 if(!strcsequal(fname_dst_lcomp_base_mod,
6087 smb_fname_orig_lcomp->base_name)) {
6088 char *tmp;
6090 * Replace the modified last component with the
6091 * original.
6093 if (last_slash) {
6094 *last_slash = '\0'; /* Truncate at the '/' */
6095 tmp = talloc_asprintf(smb_fname_dst,
6096 "%s/%s",
6097 smb_fname_dst->base_name,
6098 smb_fname_orig_lcomp->base_name);
6099 } else {
6100 tmp = talloc_asprintf(smb_fname_dst,
6101 "%s",
6102 smb_fname_orig_lcomp->base_name);
6104 if (tmp == NULL) {
6105 status = NT_STATUS_NO_MEMORY;
6106 TALLOC_FREE(fname_dst_lcomp_base_mod);
6107 TALLOC_FREE(smb_fname_orig_lcomp);
6108 goto out;
6110 TALLOC_FREE(smb_fname_dst->base_name);
6111 smb_fname_dst->base_name = tmp;
6114 /* If the stream_names only differ by case, use original. */
6115 if(!strcsequal(smb_fname_dst->stream_name,
6116 smb_fname_orig_lcomp->stream_name)) {
6117 char *tmp = NULL;
6118 /* Use the original stream. */
6119 tmp = talloc_strdup(smb_fname_dst,
6120 smb_fname_orig_lcomp->stream_name);
6121 if (tmp == NULL) {
6122 status = NT_STATUS_NO_MEMORY;
6123 TALLOC_FREE(fname_dst_lcomp_base_mod);
6124 TALLOC_FREE(smb_fname_orig_lcomp);
6125 goto out;
6127 TALLOC_FREE(smb_fname_dst->stream_name);
6128 smb_fname_dst->stream_name = tmp;
6130 TALLOC_FREE(fname_dst_lcomp_base_mod);
6131 TALLOC_FREE(smb_fname_orig_lcomp);
6135 * If the src and dest names are identical - including case,
6136 * don't do the rename, just return success.
6139 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6140 strcsequal(fsp->fsp_name->stream_name,
6141 smb_fname_dst->stream_name)) {
6142 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6143 "- returning success\n",
6144 smb_fname_str_dbg(smb_fname_dst)));
6145 status = NT_STATUS_OK;
6146 goto out;
6149 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6150 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6152 /* Return the correct error code if both names aren't streams. */
6153 if (!old_is_stream && new_is_stream) {
6154 status = NT_STATUS_OBJECT_NAME_INVALID;
6155 goto out;
6158 if (old_is_stream && !new_is_stream) {
6159 status = NT_STATUS_INVALID_PARAMETER;
6160 goto out;
6163 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6165 if(!replace_if_exists && dst_exists) {
6166 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6167 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6168 smb_fname_str_dbg(smb_fname_dst)));
6169 status = NT_STATUS_OBJECT_NAME_COLLISION;
6170 goto out;
6173 if (dst_exists) {
6174 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6175 &smb_fname_dst->st);
6176 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6177 fileid);
6178 /* The file can be open when renaming a stream */
6179 if (dst_fsp && !new_is_stream) {
6180 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6181 status = NT_STATUS_ACCESS_DENIED;
6182 goto out;
6186 /* Ensure we have a valid stat struct for the source. */
6187 status = vfs_stat_fsp(fsp);
6188 if (!NT_STATUS_IS_OK(status)) {
6189 goto out;
6192 status = can_rename(conn, fsp, attrs);
6194 if (!NT_STATUS_IS_OK(status)) {
6195 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6196 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6197 smb_fname_str_dbg(smb_fname_dst)));
6198 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6199 status = NT_STATUS_ACCESS_DENIED;
6200 goto out;
6203 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6204 status = NT_STATUS_ACCESS_DENIED;
6207 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6208 NULL);
6211 * We have the file open ourselves, so not being able to get the
6212 * corresponding share mode lock is a fatal error.
6215 SMB_ASSERT(lck != NULL);
6217 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6218 uint32 create_options = fsp->fh->private_options;
6220 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6221 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6222 smb_fname_str_dbg(smb_fname_dst)));
6224 if (!lp_posix_pathnames() &&
6225 (lp_map_archive(SNUM(conn)) ||
6226 lp_store_dos_attributes(SNUM(conn)))) {
6227 /* We must set the archive bit on the newly
6228 renamed file. */
6229 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6230 uint32_t old_dosmode = dos_mode(conn,
6231 smb_fname_dst);
6232 file_set_dosmode(conn,
6233 smb_fname_dst,
6234 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6235 NULL,
6236 true);
6240 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6241 smb_fname_dst);
6243 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6246 * A rename acts as a new file create w.r.t. allowing an initial delete
6247 * on close, probably because in Windows there is a new handle to the
6248 * new file. If initial delete on close was requested but not
6249 * originally set, we need to set it here. This is probably not 100% correct,
6250 * but will work for the CIFSFS client which in non-posix mode
6251 * depends on these semantics. JRA.
6254 if (create_options & FILE_DELETE_ON_CLOSE) {
6255 status = can_set_delete_on_close(fsp, 0);
6257 if (NT_STATUS_IS_OK(status)) {
6258 /* Note that here we set the *inital* delete on close flag,
6259 * not the regular one. The magic gets handled in close. */
6260 fsp->initial_delete_on_close = True;
6263 TALLOC_FREE(lck);
6264 status = NT_STATUS_OK;
6265 goto out;
6268 TALLOC_FREE(lck);
6270 if (errno == ENOTDIR || errno == EISDIR) {
6271 status = NT_STATUS_OBJECT_NAME_COLLISION;
6272 } else {
6273 status = map_nt_error_from_unix(errno);
6276 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6277 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6278 smb_fname_str_dbg(smb_fname_dst)));
6280 out:
6281 TALLOC_FREE(smb_fname_dst);
6283 return status;
6286 /****************************************************************************
6287 The guts of the rename command, split out so it may be called by the NT SMB
6288 code.
6289 ****************************************************************************/
6291 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6292 connection_struct *conn,
6293 struct smb_request *req,
6294 struct smb_filename *smb_fname_src,
6295 struct smb_filename *smb_fname_dst,
6296 uint32 attrs,
6297 bool replace_if_exists,
6298 bool src_has_wild,
6299 bool dest_has_wild,
6300 uint32_t access_mask)
6302 char *fname_src_dir = NULL;
6303 char *fname_src_mask = NULL;
6304 int count=0;
6305 NTSTATUS status = NT_STATUS_OK;
6306 struct smb_Dir *dir_hnd = NULL;
6307 const char *dname = NULL;
6308 char *talloced = NULL;
6309 long offset = 0;
6310 int create_options = 0;
6311 bool posix_pathnames = lp_posix_pathnames();
6314 * Split the old name into directory and last component
6315 * strings. Note that unix_convert may have stripped off a
6316 * leading ./ from both name and newname if the rename is
6317 * at the root of the share. We need to make sure either both
6318 * name and newname contain a / character or neither of them do
6319 * as this is checked in resolve_wildcards().
6322 /* Split up the directory from the filename/mask. */
6323 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6324 &fname_src_dir, &fname_src_mask);
6325 if (!NT_STATUS_IS_OK(status)) {
6326 status = NT_STATUS_NO_MEMORY;
6327 goto out;
6331 * We should only check the mangled cache
6332 * here if unix_convert failed. This means
6333 * that the path in 'mask' doesn't exist
6334 * on the file system and so we need to look
6335 * for a possible mangle. This patch from
6336 * Tine Smukavec <valentin.smukavec@hermes.si>.
6339 if (!VALID_STAT(smb_fname_src->st) &&
6340 mangle_is_mangled(fname_src_mask, conn->params)) {
6341 char *new_mask = NULL;
6342 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6343 conn->params);
6344 if (new_mask) {
6345 TALLOC_FREE(fname_src_mask);
6346 fname_src_mask = new_mask;
6350 if (!src_has_wild) {
6351 files_struct *fsp;
6354 * Only one file needs to be renamed. Append the mask back
6355 * onto the directory.
6357 TALLOC_FREE(smb_fname_src->base_name);
6358 if (ISDOT(fname_src_dir)) {
6359 /* Ensure we use canonical names on open. */
6360 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6361 "%s",
6362 fname_src_mask);
6363 } else {
6364 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6365 "%s/%s",
6366 fname_src_dir,
6367 fname_src_mask);
6369 if (!smb_fname_src->base_name) {
6370 status = NT_STATUS_NO_MEMORY;
6371 goto out;
6374 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6375 "case_preserve = %d, short case preserve = %d, "
6376 "directory = %s, newname = %s, "
6377 "last_component_dest = %s\n",
6378 conn->case_sensitive, conn->case_preserve,
6379 conn->short_case_preserve,
6380 smb_fname_str_dbg(smb_fname_src),
6381 smb_fname_str_dbg(smb_fname_dst),
6382 smb_fname_dst->original_lcomp));
6384 /* The dest name still may have wildcards. */
6385 if (dest_has_wild) {
6386 char *fname_dst_mod = NULL;
6387 if (!resolve_wildcards(smb_fname_dst,
6388 smb_fname_src->base_name,
6389 smb_fname_dst->base_name,
6390 &fname_dst_mod)) {
6391 DEBUG(6, ("rename_internals: resolve_wildcards "
6392 "%s %s failed\n",
6393 smb_fname_src->base_name,
6394 smb_fname_dst->base_name));
6395 status = NT_STATUS_NO_MEMORY;
6396 goto out;
6398 TALLOC_FREE(smb_fname_dst->base_name);
6399 smb_fname_dst->base_name = fname_dst_mod;
6402 ZERO_STRUCT(smb_fname_src->st);
6403 if (posix_pathnames) {
6404 SMB_VFS_LSTAT(conn, smb_fname_src);
6405 } else {
6406 SMB_VFS_STAT(conn, smb_fname_src);
6409 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6410 create_options |= FILE_DIRECTORY_FILE;
6413 status = SMB_VFS_CREATE_FILE(
6414 conn, /* conn */
6415 req, /* req */
6416 0, /* root_dir_fid */
6417 smb_fname_src, /* fname */
6418 access_mask, /* access_mask */
6419 (FILE_SHARE_READ | /* share_access */
6420 FILE_SHARE_WRITE),
6421 FILE_OPEN, /* create_disposition*/
6422 create_options, /* create_options */
6423 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6424 0, /* oplock_request */
6425 0, /* allocation_size */
6426 0, /* private_flags */
6427 NULL, /* sd */
6428 NULL, /* ea_list */
6429 &fsp, /* result */
6430 NULL); /* pinfo */
6432 if (!NT_STATUS_IS_OK(status)) {
6433 DEBUG(3, ("Could not open rename source %s: %s\n",
6434 smb_fname_str_dbg(smb_fname_src),
6435 nt_errstr(status)));
6436 goto out;
6439 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6440 attrs, replace_if_exists);
6442 close_file(req, fsp, NORMAL_CLOSE);
6444 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6445 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6446 smb_fname_str_dbg(smb_fname_dst)));
6448 goto out;
6452 * Wildcards - process each file that matches.
6454 if (strequal(fname_src_mask, "????????.???")) {
6455 TALLOC_FREE(fname_src_mask);
6456 fname_src_mask = talloc_strdup(ctx, "*");
6457 if (!fname_src_mask) {
6458 status = NT_STATUS_NO_MEMORY;
6459 goto out;
6463 status = check_name(conn, fname_src_dir);
6464 if (!NT_STATUS_IS_OK(status)) {
6465 goto out;
6468 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6469 attrs);
6470 if (dir_hnd == NULL) {
6471 status = map_nt_error_from_unix(errno);
6472 goto out;
6475 status = NT_STATUS_NO_SUCH_FILE;
6477 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6478 * - gentest fix. JRA
6481 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6482 &talloced))) {
6483 files_struct *fsp = NULL;
6484 char *destname = NULL;
6485 bool sysdir_entry = False;
6487 /* Quick check for "." and ".." */
6488 if (ISDOT(dname) || ISDOTDOT(dname)) {
6489 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6490 sysdir_entry = True;
6491 } else {
6492 TALLOC_FREE(talloced);
6493 continue;
6497 if (!is_visible_file(conn, fname_src_dir, dname,
6498 &smb_fname_src->st, false)) {
6499 TALLOC_FREE(talloced);
6500 continue;
6503 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6504 TALLOC_FREE(talloced);
6505 continue;
6508 if (sysdir_entry) {
6509 status = NT_STATUS_OBJECT_NAME_INVALID;
6510 break;
6513 TALLOC_FREE(smb_fname_src->base_name);
6514 if (ISDOT(fname_src_dir)) {
6515 /* Ensure we use canonical names on open. */
6516 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6517 "%s",
6518 dname);
6519 } else {
6520 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6521 "%s/%s",
6522 fname_src_dir,
6523 dname);
6525 if (!smb_fname_src->base_name) {
6526 status = NT_STATUS_NO_MEMORY;
6527 goto out;
6530 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6531 smb_fname_dst->base_name,
6532 &destname)) {
6533 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6534 smb_fname_src->base_name, destname));
6535 TALLOC_FREE(talloced);
6536 continue;
6538 if (!destname) {
6539 status = NT_STATUS_NO_MEMORY;
6540 goto out;
6543 TALLOC_FREE(smb_fname_dst->base_name);
6544 smb_fname_dst->base_name = destname;
6546 ZERO_STRUCT(smb_fname_src->st);
6547 if (posix_pathnames) {
6548 SMB_VFS_LSTAT(conn, smb_fname_src);
6549 } else {
6550 SMB_VFS_STAT(conn, smb_fname_src);
6553 create_options = 0;
6555 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6556 create_options |= FILE_DIRECTORY_FILE;
6559 status = SMB_VFS_CREATE_FILE(
6560 conn, /* conn */
6561 req, /* req */
6562 0, /* root_dir_fid */
6563 smb_fname_src, /* fname */
6564 access_mask, /* access_mask */
6565 (FILE_SHARE_READ | /* share_access */
6566 FILE_SHARE_WRITE),
6567 FILE_OPEN, /* create_disposition*/
6568 create_options, /* create_options */
6569 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6570 0, /* oplock_request */
6571 0, /* allocation_size */
6572 0, /* private_flags */
6573 NULL, /* sd */
6574 NULL, /* ea_list */
6575 &fsp, /* result */
6576 NULL); /* pinfo */
6578 if (!NT_STATUS_IS_OK(status)) {
6579 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6580 "returned %s rename %s -> %s\n",
6581 nt_errstr(status),
6582 smb_fname_str_dbg(smb_fname_src),
6583 smb_fname_str_dbg(smb_fname_dst)));
6584 break;
6587 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6588 dname);
6589 if (!smb_fname_dst->original_lcomp) {
6590 status = NT_STATUS_NO_MEMORY;
6591 goto out;
6594 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6595 attrs, replace_if_exists);
6597 close_file(req, fsp, NORMAL_CLOSE);
6599 if (!NT_STATUS_IS_OK(status)) {
6600 DEBUG(3, ("rename_internals_fsp returned %s for "
6601 "rename %s -> %s\n", nt_errstr(status),
6602 smb_fname_str_dbg(smb_fname_src),
6603 smb_fname_str_dbg(smb_fname_dst)));
6604 break;
6607 count++;
6609 DEBUG(3,("rename_internals: doing rename on %s -> "
6610 "%s\n", smb_fname_str_dbg(smb_fname_src),
6611 smb_fname_str_dbg(smb_fname_src)));
6612 TALLOC_FREE(talloced);
6614 TALLOC_FREE(dir_hnd);
6616 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6617 status = map_nt_error_from_unix(errno);
6620 out:
6621 TALLOC_FREE(talloced);
6622 TALLOC_FREE(fname_src_dir);
6623 TALLOC_FREE(fname_src_mask);
6624 return status;
6627 /****************************************************************************
6628 Reply to a mv.
6629 ****************************************************************************/
6631 void reply_mv(struct smb_request *req)
6633 connection_struct *conn = req->conn;
6634 char *name = NULL;
6635 char *newname = NULL;
6636 const char *p;
6637 uint32 attrs;
6638 NTSTATUS status;
6639 bool src_has_wcard = False;
6640 bool dest_has_wcard = False;
6641 TALLOC_CTX *ctx = talloc_tos();
6642 struct smb_filename *smb_fname_src = NULL;
6643 struct smb_filename *smb_fname_dst = NULL;
6644 bool stream_rename = false;
6646 START_PROFILE(SMBmv);
6648 if (req->wct < 1) {
6649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6650 goto out;
6653 attrs = SVAL(req->vwv+0, 0);
6655 p = (const char *)req->buf + 1;
6656 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6657 &status, &src_has_wcard);
6658 if (!NT_STATUS_IS_OK(status)) {
6659 reply_nterror(req, status);
6660 goto out;
6662 p++;
6663 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6664 &status, &dest_has_wcard);
6665 if (!NT_STATUS_IS_OK(status)) {
6666 reply_nterror(req, status);
6667 goto out;
6670 if (!lp_posix_pathnames()) {
6671 /* The newname must begin with a ':' if the
6672 name contains a ':'. */
6673 if (strchr_m(name, ':')) {
6674 if (newname[0] != ':') {
6675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6676 goto out;
6678 stream_rename = true;
6682 status = filename_convert(ctx,
6683 conn,
6684 req->flags2 & FLAGS2_DFS_PATHNAMES,
6685 name,
6686 UCF_COND_ALLOW_WCARD_LCOMP,
6687 &src_has_wcard,
6688 &smb_fname_src);
6690 if (!NT_STATUS_IS_OK(status)) {
6691 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6692 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6693 ERRSRV, ERRbadpath);
6694 goto out;
6696 reply_nterror(req, status);
6697 goto out;
6700 status = filename_convert(ctx,
6701 conn,
6702 req->flags2 & FLAGS2_DFS_PATHNAMES,
6703 newname,
6704 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6705 &dest_has_wcard,
6706 &smb_fname_dst);
6708 if (!NT_STATUS_IS_OK(status)) {
6709 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6710 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6711 ERRSRV, ERRbadpath);
6712 goto out;
6714 reply_nterror(req, status);
6715 goto out;
6718 if (stream_rename) {
6719 /* smb_fname_dst->base_name must be the same as
6720 smb_fname_src->base_name. */
6721 TALLOC_FREE(smb_fname_dst->base_name);
6722 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6723 smb_fname_src->base_name);
6724 if (!smb_fname_dst->base_name) {
6725 reply_nterror(req, NT_STATUS_NO_MEMORY);
6726 goto out;
6730 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6731 smb_fname_str_dbg(smb_fname_dst)));
6733 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6734 attrs, False, src_has_wcard, dest_has_wcard,
6735 DELETE_ACCESS);
6736 if (!NT_STATUS_IS_OK(status)) {
6737 if (open_was_deferred(req->sconn, req->mid)) {
6738 /* We have re-scheduled this call. */
6739 goto out;
6741 reply_nterror(req, status);
6742 goto out;
6745 reply_outbuf(req, 0, 0);
6746 out:
6747 TALLOC_FREE(smb_fname_src);
6748 TALLOC_FREE(smb_fname_dst);
6749 END_PROFILE(SMBmv);
6750 return;
6753 /*******************************************************************
6754 Copy a file as part of a reply_copy.
6755 ******************************************************************/
6758 * TODO: check error codes on all callers
6761 NTSTATUS copy_file(TALLOC_CTX *ctx,
6762 connection_struct *conn,
6763 struct smb_filename *smb_fname_src,
6764 struct smb_filename *smb_fname_dst,
6765 int ofun,
6766 int count,
6767 bool target_is_directory)
6769 struct smb_filename *smb_fname_dst_tmp = NULL;
6770 SMB_OFF_T ret=-1;
6771 files_struct *fsp1,*fsp2;
6772 uint32 dosattrs;
6773 uint32 new_create_disposition;
6774 NTSTATUS status;
6777 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6778 if (!NT_STATUS_IS_OK(status)) {
6779 return status;
6783 * If the target is a directory, extract the last component from the
6784 * src filename and append it to the dst filename
6786 if (target_is_directory) {
6787 const char *p;
6789 /* dest/target can't be a stream if it's a directory. */
6790 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6792 p = strrchr_m(smb_fname_src->base_name,'/');
6793 if (p) {
6794 p++;
6795 } else {
6796 p = smb_fname_src->base_name;
6798 smb_fname_dst_tmp->base_name =
6799 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6801 if (!smb_fname_dst_tmp->base_name) {
6802 status = NT_STATUS_NO_MEMORY;
6803 goto out;
6807 status = vfs_file_exist(conn, smb_fname_src);
6808 if (!NT_STATUS_IS_OK(status)) {
6809 goto out;
6812 if (!target_is_directory && count) {
6813 new_create_disposition = FILE_OPEN;
6814 } else {
6815 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6816 0, ofun,
6817 NULL, NULL,
6818 &new_create_disposition,
6819 NULL,
6820 NULL)) {
6821 status = NT_STATUS_INVALID_PARAMETER;
6822 goto out;
6826 /* Open the src file for reading. */
6827 status = SMB_VFS_CREATE_FILE(
6828 conn, /* conn */
6829 NULL, /* req */
6830 0, /* root_dir_fid */
6831 smb_fname_src, /* fname */
6832 FILE_GENERIC_READ, /* access_mask */
6833 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6834 FILE_OPEN, /* create_disposition*/
6835 0, /* create_options */
6836 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6837 INTERNAL_OPEN_ONLY, /* oplock_request */
6838 0, /* allocation_size */
6839 0, /* private_flags */
6840 NULL, /* sd */
6841 NULL, /* ea_list */
6842 &fsp1, /* result */
6843 NULL); /* psbuf */
6845 if (!NT_STATUS_IS_OK(status)) {
6846 goto out;
6849 dosattrs = dos_mode(conn, smb_fname_src);
6851 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6852 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6855 /* Open the dst file for writing. */
6856 status = SMB_VFS_CREATE_FILE(
6857 conn, /* conn */
6858 NULL, /* req */
6859 0, /* root_dir_fid */
6860 smb_fname_dst, /* fname */
6861 FILE_GENERIC_WRITE, /* access_mask */
6862 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6863 new_create_disposition, /* create_disposition*/
6864 0, /* create_options */
6865 dosattrs, /* file_attributes */
6866 INTERNAL_OPEN_ONLY, /* oplock_request */
6867 0, /* allocation_size */
6868 0, /* private_flags */
6869 NULL, /* sd */
6870 NULL, /* ea_list */
6871 &fsp2, /* result */
6872 NULL); /* psbuf */
6874 if (!NT_STATUS_IS_OK(status)) {
6875 close_file(NULL, fsp1, ERROR_CLOSE);
6876 goto out;
6879 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6880 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6881 if (ret == -1) {
6882 DEBUG(0, ("error - vfs lseek returned error %s\n",
6883 strerror(errno)));
6884 status = map_nt_error_from_unix(errno);
6885 close_file(NULL, fsp1, ERROR_CLOSE);
6886 close_file(NULL, fsp2, ERROR_CLOSE);
6887 goto out;
6891 /* Do the actual copy. */
6892 if (smb_fname_src->st.st_ex_size) {
6893 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6894 } else {
6895 ret = 0;
6898 close_file(NULL, fsp1, NORMAL_CLOSE);
6900 /* Ensure the modtime is set correctly on the destination file. */
6901 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6904 * As we are opening fsp1 read-only we only expect
6905 * an error on close on fsp2 if we are out of space.
6906 * Thus we don't look at the error return from the
6907 * close of fsp1.
6909 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6911 if (!NT_STATUS_IS_OK(status)) {
6912 goto out;
6915 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6916 status = NT_STATUS_DISK_FULL;
6917 goto out;
6920 status = NT_STATUS_OK;
6922 out:
6923 TALLOC_FREE(smb_fname_dst_tmp);
6924 return status;
6927 /****************************************************************************
6928 Reply to a file copy.
6929 ****************************************************************************/
6931 void reply_copy(struct smb_request *req)
6933 connection_struct *conn = req->conn;
6934 struct smb_filename *smb_fname_src = NULL;
6935 struct smb_filename *smb_fname_dst = NULL;
6936 char *fname_src = NULL;
6937 char *fname_dst = NULL;
6938 char *fname_src_mask = NULL;
6939 char *fname_src_dir = NULL;
6940 const char *p;
6941 int count=0;
6942 int error = ERRnoaccess;
6943 int tid2;
6944 int ofun;
6945 int flags;
6946 bool target_is_directory=False;
6947 bool source_has_wild = False;
6948 bool dest_has_wild = False;
6949 NTSTATUS status;
6950 TALLOC_CTX *ctx = talloc_tos();
6952 START_PROFILE(SMBcopy);
6954 if (req->wct < 3) {
6955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6956 goto out;
6959 tid2 = SVAL(req->vwv+0, 0);
6960 ofun = SVAL(req->vwv+1, 0);
6961 flags = SVAL(req->vwv+2, 0);
6963 p = (const char *)req->buf;
6964 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6965 &status, &source_has_wild);
6966 if (!NT_STATUS_IS_OK(status)) {
6967 reply_nterror(req, status);
6968 goto out;
6970 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6971 &status, &dest_has_wild);
6972 if (!NT_STATUS_IS_OK(status)) {
6973 reply_nterror(req, status);
6974 goto out;
6977 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6979 if (tid2 != conn->cnum) {
6980 /* can't currently handle inter share copies XXXX */
6981 DEBUG(3,("Rejecting inter-share copy\n"));
6982 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6983 goto out;
6986 status = filename_convert(ctx, conn,
6987 req->flags2 & FLAGS2_DFS_PATHNAMES,
6988 fname_src,
6989 UCF_COND_ALLOW_WCARD_LCOMP,
6990 &source_has_wild,
6991 &smb_fname_src);
6992 if (!NT_STATUS_IS_OK(status)) {
6993 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6994 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6995 ERRSRV, ERRbadpath);
6996 goto out;
6998 reply_nterror(req, status);
6999 goto out;
7002 status = filename_convert(ctx, conn,
7003 req->flags2 & FLAGS2_DFS_PATHNAMES,
7004 fname_dst,
7005 UCF_COND_ALLOW_WCARD_LCOMP,
7006 &dest_has_wild,
7007 &smb_fname_dst);
7008 if (!NT_STATUS_IS_OK(status)) {
7009 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7010 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7011 ERRSRV, ERRbadpath);
7012 goto out;
7014 reply_nterror(req, status);
7015 goto out;
7018 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7020 if ((flags&1) && target_is_directory) {
7021 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7022 goto out;
7025 if ((flags&2) && !target_is_directory) {
7026 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7027 goto out;
7030 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7031 /* wants a tree copy! XXXX */
7032 DEBUG(3,("Rejecting tree copy\n"));
7033 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7034 goto out;
7037 /* Split up the directory from the filename/mask. */
7038 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7039 &fname_src_dir, &fname_src_mask);
7040 if (!NT_STATUS_IS_OK(status)) {
7041 reply_nterror(req, NT_STATUS_NO_MEMORY);
7042 goto out;
7046 * We should only check the mangled cache
7047 * here if unix_convert failed. This means
7048 * that the path in 'mask' doesn't exist
7049 * on the file system and so we need to look
7050 * for a possible mangle. This patch from
7051 * Tine Smukavec <valentin.smukavec@hermes.si>.
7053 if (!VALID_STAT(smb_fname_src->st) &&
7054 mangle_is_mangled(fname_src_mask, conn->params)) {
7055 char *new_mask = NULL;
7056 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7057 &new_mask, conn->params);
7059 /* Use demangled name if one was successfully found. */
7060 if (new_mask) {
7061 TALLOC_FREE(fname_src_mask);
7062 fname_src_mask = new_mask;
7066 if (!source_has_wild) {
7069 * Only one file needs to be copied. Append the mask back onto
7070 * the directory.
7072 TALLOC_FREE(smb_fname_src->base_name);
7073 if (ISDOT(fname_src_dir)) {
7074 /* Ensure we use canonical names on open. */
7075 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7076 "%s",
7077 fname_src_mask);
7078 } else {
7079 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7080 "%s/%s",
7081 fname_src_dir,
7082 fname_src_mask);
7084 if (!smb_fname_src->base_name) {
7085 reply_nterror(req, NT_STATUS_NO_MEMORY);
7086 goto out;
7089 if (dest_has_wild) {
7090 char *fname_dst_mod = NULL;
7091 if (!resolve_wildcards(smb_fname_dst,
7092 smb_fname_src->base_name,
7093 smb_fname_dst->base_name,
7094 &fname_dst_mod)) {
7095 reply_nterror(req, NT_STATUS_NO_MEMORY);
7096 goto out;
7098 TALLOC_FREE(smb_fname_dst->base_name);
7099 smb_fname_dst->base_name = fname_dst_mod;
7102 status = check_name(conn, smb_fname_src->base_name);
7103 if (!NT_STATUS_IS_OK(status)) {
7104 reply_nterror(req, status);
7105 goto out;
7108 status = check_name(conn, smb_fname_dst->base_name);
7109 if (!NT_STATUS_IS_OK(status)) {
7110 reply_nterror(req, status);
7111 goto out;
7114 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7115 ofun, count, target_is_directory);
7117 if(!NT_STATUS_IS_OK(status)) {
7118 reply_nterror(req, status);
7119 goto out;
7120 } else {
7121 count++;
7123 } else {
7124 struct smb_Dir *dir_hnd = NULL;
7125 const char *dname = NULL;
7126 char *talloced = NULL;
7127 long offset = 0;
7130 * There is a wildcard that requires us to actually read the
7131 * src dir and copy each file matching the mask to the dst.
7132 * Right now streams won't be copied, but this could
7133 * presumably be added with a nested loop for reach dir entry.
7135 SMB_ASSERT(!smb_fname_src->stream_name);
7136 SMB_ASSERT(!smb_fname_dst->stream_name);
7138 smb_fname_src->stream_name = NULL;
7139 smb_fname_dst->stream_name = NULL;
7141 if (strequal(fname_src_mask,"????????.???")) {
7142 TALLOC_FREE(fname_src_mask);
7143 fname_src_mask = talloc_strdup(ctx, "*");
7144 if (!fname_src_mask) {
7145 reply_nterror(req, NT_STATUS_NO_MEMORY);
7146 goto out;
7150 status = check_name(conn, fname_src_dir);
7151 if (!NT_STATUS_IS_OK(status)) {
7152 reply_nterror(req, status);
7153 goto out;
7156 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7157 if (dir_hnd == NULL) {
7158 status = map_nt_error_from_unix(errno);
7159 reply_nterror(req, status);
7160 goto out;
7163 error = ERRbadfile;
7165 /* Iterate over the src dir copying each entry to the dst. */
7166 while ((dname = ReadDirName(dir_hnd, &offset,
7167 &smb_fname_src->st, &talloced))) {
7168 char *destname = NULL;
7170 if (ISDOT(dname) || ISDOTDOT(dname)) {
7171 TALLOC_FREE(talloced);
7172 continue;
7175 if (!is_visible_file(conn, fname_src_dir, dname,
7176 &smb_fname_src->st, false)) {
7177 TALLOC_FREE(talloced);
7178 continue;
7181 if(!mask_match(dname, fname_src_mask,
7182 conn->case_sensitive)) {
7183 TALLOC_FREE(talloced);
7184 continue;
7187 error = ERRnoaccess;
7189 /* Get the src smb_fname struct setup. */
7190 TALLOC_FREE(smb_fname_src->base_name);
7191 if (ISDOT(fname_src_dir)) {
7192 /* Ensure we use canonical names on open. */
7193 smb_fname_src->base_name =
7194 talloc_asprintf(smb_fname_src, "%s",
7195 dname);
7196 } else {
7197 smb_fname_src->base_name =
7198 talloc_asprintf(smb_fname_src, "%s/%s",
7199 fname_src_dir, dname);
7202 if (!smb_fname_src->base_name) {
7203 TALLOC_FREE(dir_hnd);
7204 TALLOC_FREE(talloced);
7205 reply_nterror(req, NT_STATUS_NO_MEMORY);
7206 goto out;
7209 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7210 smb_fname_dst->base_name,
7211 &destname)) {
7212 TALLOC_FREE(talloced);
7213 continue;
7215 if (!destname) {
7216 TALLOC_FREE(dir_hnd);
7217 TALLOC_FREE(talloced);
7218 reply_nterror(req, NT_STATUS_NO_MEMORY);
7219 goto out;
7222 TALLOC_FREE(smb_fname_dst->base_name);
7223 smb_fname_dst->base_name = destname;
7225 status = check_name(conn, smb_fname_src->base_name);
7226 if (!NT_STATUS_IS_OK(status)) {
7227 TALLOC_FREE(dir_hnd);
7228 TALLOC_FREE(talloced);
7229 reply_nterror(req, status);
7230 goto out;
7233 status = check_name(conn, smb_fname_dst->base_name);
7234 if (!NT_STATUS_IS_OK(status)) {
7235 TALLOC_FREE(dir_hnd);
7236 TALLOC_FREE(talloced);
7237 reply_nterror(req, status);
7238 goto out;
7241 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7242 smb_fname_src->base_name,
7243 smb_fname_dst->base_name));
7245 status = copy_file(ctx, conn, smb_fname_src,
7246 smb_fname_dst, ofun, count,
7247 target_is_directory);
7248 if (NT_STATUS_IS_OK(status)) {
7249 count++;
7252 TALLOC_FREE(talloced);
7254 TALLOC_FREE(dir_hnd);
7257 if (count == 0) {
7258 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7259 goto out;
7262 reply_outbuf(req, 1, 0);
7263 SSVAL(req->outbuf,smb_vwv0,count);
7264 out:
7265 TALLOC_FREE(smb_fname_src);
7266 TALLOC_FREE(smb_fname_dst);
7267 TALLOC_FREE(fname_src);
7268 TALLOC_FREE(fname_dst);
7269 TALLOC_FREE(fname_src_mask);
7270 TALLOC_FREE(fname_src_dir);
7272 END_PROFILE(SMBcopy);
7273 return;
7276 #undef DBGC_CLASS
7277 #define DBGC_CLASS DBGC_LOCKING
7279 /****************************************************************************
7280 Get a lock pid, dealing with large count requests.
7281 ****************************************************************************/
7283 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7284 bool large_file_format)
7286 if(!large_file_format)
7287 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7288 else
7289 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7292 /****************************************************************************
7293 Get a lock count, dealing with large count requests.
7294 ****************************************************************************/
7296 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7297 bool large_file_format)
7299 uint64_t count = 0;
7301 if(!large_file_format) {
7302 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7303 } else {
7305 #if defined(HAVE_LONGLONG)
7306 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7307 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7308 #else /* HAVE_LONGLONG */
7311 * NT4.x seems to be broken in that it sends large file (64 bit)
7312 * lockingX calls even if the CAP_LARGE_FILES was *not*
7313 * negotiated. For boxes without large unsigned ints truncate the
7314 * lock count by dropping the top 32 bits.
7317 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7318 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7319 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7320 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7321 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7324 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7325 #endif /* HAVE_LONGLONG */
7328 return count;
7331 #if !defined(HAVE_LONGLONG)
7332 /****************************************************************************
7333 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7334 ****************************************************************************/
7336 static uint32 map_lock_offset(uint32 high, uint32 low)
7338 unsigned int i;
7339 uint32 mask = 0;
7340 uint32 highcopy = high;
7343 * Try and find out how many significant bits there are in high.
7346 for(i = 0; highcopy; i++)
7347 highcopy >>= 1;
7350 * We use 31 bits not 32 here as POSIX
7351 * lock offsets may not be negative.
7354 mask = (~0) << (31 - i);
7356 if(low & mask)
7357 return 0; /* Fail. */
7359 high <<= (31 - i);
7361 return (high|low);
7363 #endif /* !defined(HAVE_LONGLONG) */
7365 /****************************************************************************
7366 Get a lock offset, dealing with large offset requests.
7367 ****************************************************************************/
7369 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7370 bool large_file_format, bool *err)
7372 uint64_t offset = 0;
7374 *err = False;
7376 if(!large_file_format) {
7377 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7378 } else {
7380 #if defined(HAVE_LONGLONG)
7381 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7382 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7383 #else /* HAVE_LONGLONG */
7386 * NT4.x seems to be broken in that it sends large file (64 bit)
7387 * lockingX calls even if the CAP_LARGE_FILES was *not*
7388 * negotiated. For boxes without large unsigned ints mangle the
7389 * lock offset by mapping the top 32 bits onto the lower 32.
7392 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7393 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7394 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7395 uint32 new_low = 0;
7397 if((new_low = map_lock_offset(high, low)) == 0) {
7398 *err = True;
7399 return (uint64_t)-1;
7402 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7403 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7404 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7405 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7408 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7409 #endif /* HAVE_LONGLONG */
7412 return offset;
7415 NTSTATUS smbd_do_locking(struct smb_request *req,
7416 files_struct *fsp,
7417 uint8_t type,
7418 int32_t timeout,
7419 uint16_t num_ulocks,
7420 struct smbd_lock_element *ulocks,
7421 uint16_t num_locks,
7422 struct smbd_lock_element *locks,
7423 bool *async)
7425 connection_struct *conn = req->conn;
7426 int i;
7427 NTSTATUS status = NT_STATUS_OK;
7429 *async = false;
7431 /* Data now points at the beginning of the list
7432 of smb_unlkrng structs */
7433 for(i = 0; i < (int)num_ulocks; i++) {
7434 struct smbd_lock_element *e = &ulocks[i];
7436 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7437 "pid %u, file %s\n",
7438 (double)e->offset,
7439 (double)e->count,
7440 (unsigned int)e->smblctx,
7441 fsp_str_dbg(fsp)));
7443 if (e->brltype != UNLOCK_LOCK) {
7444 /* this can only happen with SMB2 */
7445 return NT_STATUS_INVALID_PARAMETER;
7448 status = do_unlock(req->sconn->msg_ctx,
7449 fsp,
7450 e->smblctx,
7451 e->count,
7452 e->offset,
7453 WINDOWS_LOCK);
7455 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7456 nt_errstr(status)));
7458 if (!NT_STATUS_IS_OK(status)) {
7459 return status;
7463 /* Setup the timeout in seconds. */
7465 if (!lp_blocking_locks(SNUM(conn))) {
7466 timeout = 0;
7469 /* Data now points at the beginning of the list
7470 of smb_lkrng structs */
7472 for(i = 0; i < (int)num_locks; i++) {
7473 struct smbd_lock_element *e = &locks[i];
7475 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7476 "%llu, file %s timeout = %d\n",
7477 (double)e->offset,
7478 (double)e->count,
7479 (unsigned long long)e->smblctx,
7480 fsp_str_dbg(fsp),
7481 (int)timeout));
7483 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7484 struct blocking_lock_record *blr = NULL;
7486 if (num_locks > 1) {
7488 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7489 * if the lock vector contains one entry. When given mutliple cancel
7490 * requests in a single PDU we expect the server to return an
7491 * error. Windows servers seem to accept the request but only
7492 * cancel the first lock.
7493 * JRA - Do what Windows does (tm) :-).
7496 #if 0
7497 /* MS-CIFS (2.2.4.32.1) behavior. */
7498 return NT_STATUS_DOS(ERRDOS,
7499 ERRcancelviolation);
7500 #else
7501 /* Windows behavior. */
7502 if (i != 0) {
7503 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7504 "cancel request\n"));
7505 continue;
7507 #endif
7510 if (lp_blocking_locks(SNUM(conn))) {
7512 /* Schedule a message to ourselves to
7513 remove the blocking lock record and
7514 return the right error. */
7516 blr = blocking_lock_cancel_smb1(fsp,
7517 e->smblctx,
7518 e->offset,
7519 e->count,
7520 WINDOWS_LOCK,
7521 type,
7522 NT_STATUS_FILE_LOCK_CONFLICT);
7523 if (blr == NULL) {
7524 return NT_STATUS_DOS(
7525 ERRDOS,
7526 ERRcancelviolation);
7529 /* Remove a matching pending lock. */
7530 status = do_lock_cancel(fsp,
7531 e->smblctx,
7532 e->count,
7533 e->offset,
7534 WINDOWS_LOCK,
7535 blr);
7536 } else {
7537 bool blocking_lock = timeout ? true : false;
7538 bool defer_lock = false;
7539 struct byte_range_lock *br_lck;
7540 uint64_t block_smblctx;
7542 br_lck = do_lock(req->sconn->msg_ctx,
7543 fsp,
7544 e->smblctx,
7545 e->count,
7546 e->offset,
7547 e->brltype,
7548 WINDOWS_LOCK,
7549 blocking_lock,
7550 &status,
7551 &block_smblctx,
7552 NULL);
7554 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7555 /* Windows internal resolution for blocking locks seems
7556 to be about 200ms... Don't wait for less than that. JRA. */
7557 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7558 timeout = lp_lock_spin_time();
7560 defer_lock = true;
7563 /* If a lock sent with timeout of zero would fail, and
7564 * this lock has been requested multiple times,
7565 * according to brl_lock_failed() we convert this
7566 * request to a blocking lock with a timeout of between
7567 * 150 - 300 milliseconds.
7569 * If lp_lock_spin_time() has been set to 0, we skip
7570 * this blocking retry and fail immediately.
7572 * Replacement for do_lock_spin(). JRA. */
7574 if (!req->sconn->using_smb2 &&
7575 br_lck && lp_blocking_locks(SNUM(conn)) &&
7576 lp_lock_spin_time() && !blocking_lock &&
7577 NT_STATUS_EQUAL((status),
7578 NT_STATUS_FILE_LOCK_CONFLICT))
7580 defer_lock = true;
7581 timeout = lp_lock_spin_time();
7584 if (br_lck && defer_lock) {
7586 * A blocking lock was requested. Package up
7587 * this smb into a queued request and push it
7588 * onto the blocking lock queue.
7590 if(push_blocking_lock_request(br_lck,
7591 req,
7592 fsp,
7593 timeout,
7595 e->smblctx,
7596 e->brltype,
7597 WINDOWS_LOCK,
7598 e->offset,
7599 e->count,
7600 block_smblctx)) {
7601 TALLOC_FREE(br_lck);
7602 *async = true;
7603 return NT_STATUS_OK;
7607 TALLOC_FREE(br_lck);
7610 if (!NT_STATUS_IS_OK(status)) {
7611 break;
7615 /* If any of the above locks failed, then we must unlock
7616 all of the previous locks (X/Open spec). */
7618 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7620 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7621 i = -1; /* we want to skip the for loop */
7625 * Ensure we don't do a remove on the lock that just failed,
7626 * as under POSIX rules, if we have a lock already there, we
7627 * will delete it (and we shouldn't) .....
7629 for(i--; i >= 0; i--) {
7630 struct smbd_lock_element *e = &locks[i];
7632 do_unlock(req->sconn->msg_ctx,
7633 fsp,
7634 e->smblctx,
7635 e->count,
7636 e->offset,
7637 WINDOWS_LOCK);
7639 return status;
7642 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7643 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7645 return NT_STATUS_OK;
7648 /****************************************************************************
7649 Reply to a lockingX request.
7650 ****************************************************************************/
7652 void reply_lockingX(struct smb_request *req)
7654 connection_struct *conn = req->conn;
7655 files_struct *fsp;
7656 unsigned char locktype;
7657 unsigned char oplocklevel;
7658 uint16 num_ulocks;
7659 uint16 num_locks;
7660 int32 lock_timeout;
7661 int i;
7662 const uint8_t *data;
7663 bool large_file_format;
7664 bool err;
7665 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7666 struct smbd_lock_element *ulocks;
7667 struct smbd_lock_element *locks;
7668 bool async = false;
7670 START_PROFILE(SMBlockingX);
7672 if (req->wct < 8) {
7673 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7674 END_PROFILE(SMBlockingX);
7675 return;
7678 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7679 locktype = CVAL(req->vwv+3, 0);
7680 oplocklevel = CVAL(req->vwv+3, 1);
7681 num_ulocks = SVAL(req->vwv+6, 0);
7682 num_locks = SVAL(req->vwv+7, 0);
7683 lock_timeout = IVAL(req->vwv+4, 0);
7684 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7686 if (!check_fsp(conn, req, fsp)) {
7687 END_PROFILE(SMBlockingX);
7688 return;
7691 data = req->buf;
7693 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7694 /* we don't support these - and CANCEL_LOCK makes w2k
7695 and XP reboot so I don't really want to be
7696 compatible! (tridge) */
7697 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7698 END_PROFILE(SMBlockingX);
7699 return;
7702 /* Check if this is an oplock break on a file
7703 we have granted an oplock on.
7705 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7706 /* Client can insist on breaking to none. */
7707 bool break_to_none = (oplocklevel == 0);
7708 bool result;
7710 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7711 "for fnum = %d\n", (unsigned int)oplocklevel,
7712 fsp->fnum ));
7715 * Make sure we have granted an exclusive or batch oplock on
7716 * this file.
7719 if (fsp->oplock_type == 0) {
7721 /* The Samba4 nbench simulator doesn't understand
7722 the difference between break to level2 and break
7723 to none from level2 - it sends oplock break
7724 replies in both cases. Don't keep logging an error
7725 message here - just ignore it. JRA. */
7727 DEBUG(5,("reply_lockingX: Error : oplock break from "
7728 "client for fnum = %d (oplock=%d) and no "
7729 "oplock granted on this file (%s).\n",
7730 fsp->fnum, fsp->oplock_type,
7731 fsp_str_dbg(fsp)));
7733 /* if this is a pure oplock break request then don't
7734 * send a reply */
7735 if (num_locks == 0 && num_ulocks == 0) {
7736 END_PROFILE(SMBlockingX);
7737 return;
7738 } else {
7739 END_PROFILE(SMBlockingX);
7740 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7741 return;
7745 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7746 (break_to_none)) {
7747 result = remove_oplock(fsp);
7748 } else {
7749 result = downgrade_oplock(fsp);
7752 if (!result) {
7753 DEBUG(0, ("reply_lockingX: error in removing "
7754 "oplock on file %s\n", fsp_str_dbg(fsp)));
7755 /* Hmmm. Is this panic justified? */
7756 smb_panic("internal tdb error");
7759 reply_to_oplock_break_requests(fsp);
7761 /* if this is a pure oplock break request then don't send a
7762 * reply */
7763 if (num_locks == 0 && num_ulocks == 0) {
7764 /* Sanity check - ensure a pure oplock break is not a
7765 chained request. */
7766 if(CVAL(req->vwv+0, 0) != 0xff)
7767 DEBUG(0,("reply_lockingX: Error : pure oplock "
7768 "break is a chained %d request !\n",
7769 (unsigned int)CVAL(req->vwv+0, 0)));
7770 END_PROFILE(SMBlockingX);
7771 return;
7775 if (req->buflen <
7776 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7777 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7778 END_PROFILE(SMBlockingX);
7779 return;
7782 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7783 if (ulocks == NULL) {
7784 reply_nterror(req, NT_STATUS_NO_MEMORY);
7785 END_PROFILE(SMBlockingX);
7786 return;
7789 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7790 if (locks == NULL) {
7791 reply_nterror(req, NT_STATUS_NO_MEMORY);
7792 END_PROFILE(SMBlockingX);
7793 return;
7796 /* Data now points at the beginning of the list
7797 of smb_unlkrng structs */
7798 for(i = 0; i < (int)num_ulocks; i++) {
7799 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7800 ulocks[i].count = get_lock_count(data, i, large_file_format);
7801 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7802 ulocks[i].brltype = UNLOCK_LOCK;
7805 * There is no error code marked "stupid client bug".... :-).
7807 if(err) {
7808 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7809 END_PROFILE(SMBlockingX);
7810 return;
7814 /* Now do any requested locks */
7815 data += ((large_file_format ? 20 : 10)*num_ulocks);
7817 /* Data now points at the beginning of the list
7818 of smb_lkrng structs */
7820 for(i = 0; i < (int)num_locks; i++) {
7821 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7822 locks[i].count = get_lock_count(data, i, large_file_format);
7823 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7825 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7826 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7827 locks[i].brltype = PENDING_READ_LOCK;
7828 } else {
7829 locks[i].brltype = READ_LOCK;
7831 } else {
7832 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7833 locks[i].brltype = PENDING_WRITE_LOCK;
7834 } else {
7835 locks[i].brltype = WRITE_LOCK;
7840 * There is no error code marked "stupid client bug".... :-).
7842 if(err) {
7843 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7844 END_PROFILE(SMBlockingX);
7845 return;
7849 status = smbd_do_locking(req, fsp,
7850 locktype, lock_timeout,
7851 num_ulocks, ulocks,
7852 num_locks, locks,
7853 &async);
7854 if (!NT_STATUS_IS_OK(status)) {
7855 END_PROFILE(SMBlockingX);
7856 reply_nterror(req, status);
7857 return;
7859 if (async) {
7860 END_PROFILE(SMBlockingX);
7861 return;
7864 reply_outbuf(req, 2, 0);
7866 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7867 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7869 END_PROFILE(SMBlockingX);
7870 chain_reply(req);
7873 #undef DBGC_CLASS
7874 #define DBGC_CLASS DBGC_ALL
7876 /****************************************************************************
7877 Reply to a SMBreadbmpx (read block multiplex) request.
7878 Always reply with an error, if someone has a platform really needs this,
7879 please contact vl@samba.org
7880 ****************************************************************************/
7882 void reply_readbmpx(struct smb_request *req)
7884 START_PROFILE(SMBreadBmpx);
7885 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7886 END_PROFILE(SMBreadBmpx);
7887 return;
7890 /****************************************************************************
7891 Reply to a SMBreadbs (read block multiplex secondary) request.
7892 Always reply with an error, if someone has a platform really needs this,
7893 please contact vl@samba.org
7894 ****************************************************************************/
7896 void reply_readbs(struct smb_request *req)
7898 START_PROFILE(SMBreadBs);
7899 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7900 END_PROFILE(SMBreadBs);
7901 return;
7904 /****************************************************************************
7905 Reply to a SMBsetattrE.
7906 ****************************************************************************/
7908 void reply_setattrE(struct smb_request *req)
7910 connection_struct *conn = req->conn;
7911 struct smb_file_time ft;
7912 files_struct *fsp;
7913 NTSTATUS status;
7915 START_PROFILE(SMBsetattrE);
7916 ZERO_STRUCT(ft);
7918 if (req->wct < 7) {
7919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7920 goto out;
7923 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7925 if(!fsp || (fsp->conn != conn)) {
7926 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7927 goto out;
7931 * Convert the DOS times into unix times.
7934 ft.atime = convert_time_t_to_timespec(
7935 srv_make_unix_date2(req->vwv+3));
7936 ft.mtime = convert_time_t_to_timespec(
7937 srv_make_unix_date2(req->vwv+5));
7938 ft.create_time = convert_time_t_to_timespec(
7939 srv_make_unix_date2(req->vwv+1));
7941 reply_outbuf(req, 0, 0);
7944 * Patch from Ray Frush <frush@engr.colostate.edu>
7945 * Sometimes times are sent as zero - ignore them.
7948 /* Ensure we have a valid stat struct for the source. */
7949 status = vfs_stat_fsp(fsp);
7950 if (!NT_STATUS_IS_OK(status)) {
7951 reply_nterror(req, status);
7952 goto out;
7955 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7956 if (!NT_STATUS_IS_OK(status)) {
7957 reply_nterror(req, status);
7958 goto out;
7961 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7962 " createtime=%u\n",
7963 fsp->fnum,
7964 (unsigned int)ft.atime.tv_sec,
7965 (unsigned int)ft.mtime.tv_sec,
7966 (unsigned int)ft.create_time.tv_sec
7968 out:
7969 END_PROFILE(SMBsetattrE);
7970 return;
7974 /* Back from the dead for OS/2..... JRA. */
7976 /****************************************************************************
7977 Reply to a SMBwritebmpx (write block multiplex primary) request.
7978 Always reply with an error, if someone has a platform really needs this,
7979 please contact vl@samba.org
7980 ****************************************************************************/
7982 void reply_writebmpx(struct smb_request *req)
7984 START_PROFILE(SMBwriteBmpx);
7985 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7986 END_PROFILE(SMBwriteBmpx);
7987 return;
7990 /****************************************************************************
7991 Reply to a SMBwritebs (write block multiplex secondary) request.
7992 Always reply with an error, if someone has a platform really needs this,
7993 please contact vl@samba.org
7994 ****************************************************************************/
7996 void reply_writebs(struct smb_request *req)
7998 START_PROFILE(SMBwriteBs);
7999 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8000 END_PROFILE(SMBwriteBs);
8001 return;
8004 /****************************************************************************
8005 Reply to a SMBgetattrE.
8006 ****************************************************************************/
8008 void reply_getattrE(struct smb_request *req)
8010 connection_struct *conn = req->conn;
8011 int mode;
8012 files_struct *fsp;
8013 struct timespec create_ts;
8015 START_PROFILE(SMBgetattrE);
8017 if (req->wct < 1) {
8018 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8019 END_PROFILE(SMBgetattrE);
8020 return;
8023 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8025 if(!fsp || (fsp->conn != conn)) {
8026 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8027 END_PROFILE(SMBgetattrE);
8028 return;
8031 /* Do an fstat on this file */
8032 if(fsp_stat(fsp)) {
8033 reply_nterror(req, map_nt_error_from_unix(errno));
8034 END_PROFILE(SMBgetattrE);
8035 return;
8038 mode = dos_mode(conn, fsp->fsp_name);
8041 * Convert the times into dos times. Set create
8042 * date to be last modify date as UNIX doesn't save
8043 * this.
8046 reply_outbuf(req, 11, 0);
8048 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8049 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8050 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8051 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8052 /* Should we check pending modtime here ? JRA */
8053 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8054 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8056 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8057 SIVAL(req->outbuf, smb_vwv6, 0);
8058 SIVAL(req->outbuf, smb_vwv8, 0);
8059 } else {
8060 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8061 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8062 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8064 SSVAL(req->outbuf,smb_vwv10, mode);
8066 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8068 END_PROFILE(SMBgetattrE);
8069 return;