s3:smbd/conn_msg: pass smbd_server_connection as private_data to msg_force_tdis()
[Samba/vl.git] / source3 / smbd / reply.c
bloba06e7b83391c0700fc192922450fb52898ebfa23
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 "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
41 #include "auth.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
45 /****************************************************************************
46 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
47 path or anything including wildcards.
48 We're assuming here that '/' is not the second byte in any multibyte char
49 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
50 set.
51 ****************************************************************************/
53 /* Custom version for processing POSIX paths. */
54 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
56 static NTSTATUS check_path_syntax_internal(char *path,
57 bool posix_path,
58 bool *p_last_component_contains_wcard)
60 char *d = path;
61 const char *s = path;
62 NTSTATUS ret = NT_STATUS_OK;
63 bool start_of_name_component = True;
64 bool stream_started = false;
66 *p_last_component_contains_wcard = False;
68 while (*s) {
69 if (stream_started) {
70 switch (*s) {
71 case '/':
72 case '\\':
73 return NT_STATUS_OBJECT_NAME_INVALID;
74 case ':':
75 if (s[1] == '\0') {
76 return NT_STATUS_OBJECT_NAME_INVALID;
78 if (strchr_m(&s[1], ':')) {
79 return NT_STATUS_OBJECT_NAME_INVALID;
81 break;
85 if ((*s == ':') && !posix_path && !stream_started) {
86 if (*p_last_component_contains_wcard) {
87 return NT_STATUS_OBJECT_NAME_INVALID;
89 /* Stream names allow more characters than file names.
90 We're overloading posix_path here to allow a wider
91 range of characters. If stream_started is true this
92 is still a Windows path even if posix_path is true.
93 JRA.
95 stream_started = true;
96 start_of_name_component = false;
97 posix_path = true;
99 if (s[1] == '\0') {
100 return NT_STATUS_OBJECT_NAME_INVALID;
104 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
106 * Safe to assume is not the second part of a mb char
107 * as this is handled below.
109 /* Eat multiple '/' or '\\' */
110 while (IS_PATH_SEP(*s,posix_path)) {
111 s++;
113 if ((d != path) && (*s != '\0')) {
114 /* We only care about non-leading or trailing '/' or '\\' */
115 *d++ = '/';
118 start_of_name_component = True;
119 /* New component. */
120 *p_last_component_contains_wcard = False;
121 continue;
124 if (start_of_name_component) {
125 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
126 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
129 * No mb char starts with '.' so we're safe checking the directory separator here.
132 /* If we just added a '/' - delete it */
133 if ((d > path) && (*(d-1) == '/')) {
134 *(d-1) = '\0';
135 d--;
138 /* Are we at the start ? Can't go back further if so. */
139 if (d <= path) {
140 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
141 break;
143 /* Go back one level... */
144 /* We know this is safe as '/' cannot be part of a mb sequence. */
145 /* NOTE - if this assumption is invalid we are not in good shape... */
146 /* Decrement d first as d points to the *next* char to write into. */
147 for (d--; d > path; d--) {
148 if (*d == '/')
149 break;
151 s += 2; /* Else go past the .. */
152 /* We're still at the start of a name component, just the previous one. */
153 continue;
155 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
156 if (posix_path) {
157 /* Eat the '.' */
158 s++;
159 continue;
165 if (!(*s & 0x80)) {
166 if (!posix_path) {
167 if (*s <= 0x1f || *s == '|') {
168 return NT_STATUS_OBJECT_NAME_INVALID;
170 switch (*s) {
171 case '*':
172 case '?':
173 case '<':
174 case '>':
175 case '"':
176 *p_last_component_contains_wcard = True;
177 break;
178 default:
179 break;
182 *d++ = *s++;
183 } else {
184 size_t siz;
185 /* Get the size of the next MB character. */
186 next_codepoint(s,&siz);
187 switch(siz) {
188 case 5:
189 *d++ = *s++;
190 /*fall through*/
191 case 4:
192 *d++ = *s++;
193 /*fall through*/
194 case 3:
195 *d++ = *s++;
196 /*fall through*/
197 case 2:
198 *d++ = *s++;
199 /*fall through*/
200 case 1:
201 *d++ = *s++;
202 break;
203 default:
204 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
205 *d = '\0';
206 return NT_STATUS_INVALID_PARAMETER;
209 start_of_name_component = False;
212 *d = '\0';
214 return ret;
217 /****************************************************************************
218 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219 No wildcards allowed.
220 ****************************************************************************/
222 NTSTATUS check_path_syntax(char *path)
224 bool ignore;
225 return check_path_syntax_internal(path, False, &ignore);
228 /****************************************************************************
229 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
230 Wildcards allowed - p_contains_wcard returns true if the last component contained
231 a wildcard.
232 ****************************************************************************/
234 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
236 return check_path_syntax_internal(path, False, p_contains_wcard);
239 /****************************************************************************
240 Check the path for a POSIX client.
241 We're assuming here that '/' is not the second byte in any multibyte char
242 set (a safe assumption).
243 ****************************************************************************/
245 NTSTATUS check_path_syntax_posix(char *path)
247 bool ignore;
248 return check_path_syntax_internal(path, True, &ignore);
251 /****************************************************************************
252 Pull a string and check the path allowing a wilcard - provide for error return.
253 ****************************************************************************/
255 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
256 const char *base_ptr,
257 uint16 smb_flags2,
258 char **pp_dest,
259 const char *src,
260 size_t src_len,
261 int flags,
262 NTSTATUS *err,
263 bool *contains_wcard)
265 size_t ret;
267 *pp_dest = NULL;
269 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
270 src_len, flags);
272 if (!*pp_dest) {
273 *err = NT_STATUS_INVALID_PARAMETER;
274 return ret;
277 *contains_wcard = False;
279 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
281 * For a DFS path the function parse_dfs_path()
282 * will do the path processing, just make a copy.
284 *err = NT_STATUS_OK;
285 return ret;
288 if (lp_posix_pathnames()) {
289 *err = check_path_syntax_posix(*pp_dest);
290 } else {
291 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
294 return ret;
297 /****************************************************************************
298 Pull a string and check the path - provide for error return.
299 ****************************************************************************/
301 size_t srvstr_get_path(TALLOC_CTX *ctx,
302 const char *base_ptr,
303 uint16 smb_flags2,
304 char **pp_dest,
305 const char *src,
306 size_t src_len,
307 int flags,
308 NTSTATUS *err)
310 bool ignore;
311 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
312 src_len, flags, err, &ignore);
315 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
316 char **pp_dest, const char *src, int flags,
317 NTSTATUS *err, bool *contains_wcard)
319 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
320 pp_dest, src, smbreq_bufrem(req, src),
321 flags, err, contains_wcard);
324 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
325 char **pp_dest, const char *src, int flags,
326 NTSTATUS *err)
328 bool ignore;
329 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
330 flags, err, &ignore);
333 /****************************************************************************
334 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
335 ****************************************************************************/
337 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
338 files_struct *fsp)
340 if ((fsp == NULL) || (conn == NULL)) {
341 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
342 return False;
344 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
345 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
346 return False;
348 return True;
351 /****************************************************************************
352 Check if we have a correct fsp pointing to a file.
353 ****************************************************************************/
355 bool check_fsp(connection_struct *conn, struct smb_request *req,
356 files_struct *fsp)
358 if (!check_fsp_open(conn, req, fsp)) {
359 return False;
361 if (fsp->is_directory) {
362 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
363 return False;
365 if (fsp->fh->fd == -1) {
366 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
367 return False;
369 fsp->num_smb_operations++;
370 return True;
373 /****************************************************************************
374 Check if we have a correct fsp pointing to a quota fake file. Replacement for
375 the CHECK_NTQUOTA_HANDLE_OK macro.
376 ****************************************************************************/
378 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
379 files_struct *fsp)
381 if (!check_fsp_open(conn, req, fsp)) {
382 return false;
385 if (fsp->is_directory) {
386 return false;
389 if (fsp->fake_file_handle == NULL) {
390 return false;
393 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
394 return false;
397 if (fsp->fake_file_handle->private_data == NULL) {
398 return false;
401 return true;
404 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
405 const char *name, int name_type)
407 char *trim_name;
408 char *trim_name_type;
409 const char *retarget_parm;
410 char *retarget;
411 char *p;
412 int retarget_type = 0x20;
413 int retarget_port = 139;
414 struct sockaddr_storage retarget_addr;
415 struct sockaddr_in *in_addr;
416 bool ret = false;
417 uint8_t outbuf[10];
419 if (get_socket_port(sconn->sock) != 139) {
420 return false;
423 trim_name = talloc_strdup(talloc_tos(), name);
424 if (trim_name == NULL) {
425 goto fail;
427 trim_char(trim_name, ' ', ' ');
429 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
430 name_type);
431 if (trim_name_type == NULL) {
432 goto fail;
435 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
436 trim_name_type, NULL);
437 if (retarget_parm == NULL) {
438 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
439 trim_name, NULL);
441 if (retarget_parm == NULL) {
442 goto fail;
445 retarget = talloc_strdup(trim_name, retarget_parm);
446 if (retarget == NULL) {
447 goto fail;
450 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
452 p = strchr(retarget, ':');
453 if (p != NULL) {
454 *p++ = '\0';
455 retarget_port = atoi(p);
458 p = strchr_m(retarget, '#');
459 if (p != NULL) {
460 *p++ = '\0';
461 if (sscanf(p, "%x", &retarget_type) != 1) {
462 goto fail;
466 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
467 if (!ret) {
468 DEBUG(10, ("could not resolve %s\n", retarget));
469 goto fail;
472 if (retarget_addr.ss_family != AF_INET) {
473 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
474 goto fail;
477 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
479 _smb_setlen(outbuf, 6);
480 SCVAL(outbuf, 0, 0x84);
481 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
482 *(uint16_t *)(outbuf+8) = htons(retarget_port);
484 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
485 NULL)) {
486 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
487 "failed.");
490 ret = true;
491 fail:
492 TALLOC_FREE(trim_name);
493 return ret;
496 static void reply_called_name_not_present(char *outbuf)
498 smb_setlen(outbuf, 1);
499 SCVAL(outbuf, 0, 0x83);
500 SCVAL(outbuf, 4, 0x82);
503 /****************************************************************************
504 Reply to a (netbios-level) special message.
505 ****************************************************************************/
507 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
509 int msg_type = CVAL(inbuf,0);
510 int msg_flags = CVAL(inbuf,1);
512 * We only really use 4 bytes of the outbuf, but for the smb_setlen
513 * calculation & friends (srv_send_smb uses that) we need the full smb
514 * header.
516 char outbuf[smb_size];
518 memset(outbuf, '\0', sizeof(outbuf));
520 smb_setlen(outbuf,0);
522 switch (msg_type) {
523 case NBSSrequest: /* session request */
525 /* inbuf_size is guarenteed to be at least 4. */
526 fstring name1,name2;
527 int name_type1, name_type2;
528 int name_len1, name_len2;
530 *name1 = *name2 = 0;
532 if (sconn->nbt.got_session) {
533 exit_server_cleanly("multiple session request not permitted");
536 SCVAL(outbuf,0,NBSSpositive);
537 SCVAL(outbuf,3,0);
539 /* inbuf_size is guaranteed to be at least 4. */
540 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
541 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
542 DEBUG(0,("Invalid name length in session request\n"));
543 reply_called_name_not_present(outbuf);
544 break;
546 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
547 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
548 DEBUG(0,("Invalid name length in session request\n"));
549 reply_called_name_not_present(outbuf);
550 break;
553 name_type1 = name_extract((unsigned char *)inbuf,
554 inbuf_size,(unsigned int)4,name1);
555 name_type2 = name_extract((unsigned char *)inbuf,
556 inbuf_size,(unsigned int)(4 + name_len1),name2);
558 if (name_type1 == -1 || name_type2 == -1) {
559 DEBUG(0,("Invalid name type in session request\n"));
560 reply_called_name_not_present(outbuf);
561 break;
564 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
565 name1, name_type1, name2, name_type2));
567 if (netbios_session_retarget(sconn, name1, name_type1)) {
568 exit_server_cleanly("retargeted client");
572 * Windows NT/2k uses "*SMBSERVER" and XP uses
573 * "*SMBSERV" arrggg!!!
575 if (strequal(name1, "*SMBSERVER ")
576 || strequal(name1, "*SMBSERV ")) {
577 char *raddr;
579 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
580 talloc_tos());
581 if (raddr == NULL) {
582 exit_server_cleanly("could not allocate raddr");
585 fstrcpy(name1, raddr);
588 set_local_machine_name(name1, True);
589 set_remote_machine_name(name2, True);
591 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
592 get_local_machine_name(), get_remote_machine_name(),
593 name_type2));
595 if (name_type2 == 'R') {
596 /* We are being asked for a pathworks session ---
597 no thanks! */
598 reply_called_name_not_present(outbuf);
599 break;
602 /* only add the client's machine name to the list
603 of possibly valid usernames if we are operating
604 in share mode security */
605 if (lp_security() == SEC_SHARE) {
606 add_session_user(sconn, get_remote_machine_name());
609 reload_services(sconn->msg_ctx, sconn->sock, True);
610 reopen_logs();
612 sconn->nbt.got_session = true;
613 break;
616 case 0x89: /* session keepalive request
617 (some old clients produce this?) */
618 SCVAL(outbuf,0,NBSSkeepalive);
619 SCVAL(outbuf,3,0);
620 break;
622 case NBSSpositive: /* positive session response */
623 case NBSSnegative: /* negative session response */
624 case NBSSretarget: /* retarget session response */
625 DEBUG(0,("Unexpected session response\n"));
626 break;
628 case NBSSkeepalive: /* session keepalive */
629 default:
630 return;
633 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
634 msg_type, msg_flags));
636 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
638 if (CVAL(outbuf, 0) != 0x82) {
639 exit_server_cleanly("invalid netbios session");
641 return;
644 /****************************************************************************
645 Reply to a tcon.
646 conn POINTER CAN BE NULL HERE !
647 ****************************************************************************/
649 void reply_tcon(struct smb_request *req)
651 connection_struct *conn = req->conn;
652 const char *service;
653 char *service_buf = NULL;
654 char *password = NULL;
655 char *dev = NULL;
656 int pwlen=0;
657 NTSTATUS nt_status;
658 const char *p;
659 DATA_BLOB password_blob;
660 TALLOC_CTX *ctx = talloc_tos();
661 struct smbd_server_connection *sconn = req->sconn;
663 START_PROFILE(SMBtcon);
665 if (req->buflen < 4) {
666 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
667 END_PROFILE(SMBtcon);
668 return;
671 p = (const char *)req->buf + 1;
672 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
673 p += 1;
674 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
675 p += pwlen+1;
676 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
677 p += 1;
679 if (service_buf == NULL || password == NULL || dev == NULL) {
680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
681 END_PROFILE(SMBtcon);
682 return;
684 p = strrchr_m(service_buf,'\\');
685 if (p) {
686 service = p+1;
687 } else {
688 service = service_buf;
691 password_blob = data_blob(password, pwlen+1);
693 conn = make_connection(sconn,service,password_blob,dev,
694 req->vuid,&nt_status);
695 req->conn = conn;
697 data_blob_clear_free(&password_blob);
699 if (!conn) {
700 reply_nterror(req, nt_status);
701 END_PROFILE(SMBtcon);
702 return;
705 reply_outbuf(req, 2, 0);
706 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
707 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
708 SSVAL(req->outbuf,smb_tid,conn->cnum);
710 DEBUG(3,("tcon service=%s cnum=%d\n",
711 service, conn->cnum));
713 END_PROFILE(SMBtcon);
714 return;
717 /****************************************************************************
718 Reply to a tcon and X.
719 conn POINTER CAN BE NULL HERE !
720 ****************************************************************************/
722 void reply_tcon_and_X(struct smb_request *req)
724 connection_struct *conn = req->conn;
725 const char *service = NULL;
726 DATA_BLOB password;
727 TALLOC_CTX *ctx = talloc_tos();
728 /* what the cleint thinks the device is */
729 char *client_devicetype = NULL;
730 /* what the server tells the client the share represents */
731 const char *server_devicetype;
732 NTSTATUS nt_status;
733 int passlen;
734 char *path = NULL;
735 const char *p, *q;
736 uint16 tcon_flags;
737 struct smbd_server_connection *sconn = req->sconn;
739 START_PROFILE(SMBtconX);
741 if (req->wct < 4) {
742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
743 END_PROFILE(SMBtconX);
744 return;
747 passlen = SVAL(req->vwv+3, 0);
748 tcon_flags = SVAL(req->vwv+2, 0);
750 /* we might have to close an old one */
751 if ((tcon_flags & 0x1) && conn) {
752 close_cnum(conn,req->vuid);
753 req->conn = NULL;
754 conn = NULL;
757 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
758 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
759 END_PROFILE(SMBtconX);
760 return;
763 if (sconn->smb1.negprot.encrypted_passwords) {
764 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
765 if (lp_security() == SEC_SHARE) {
767 * Security = share always has a pad byte
768 * after the password.
770 p = (const char *)req->buf + passlen + 1;
771 } else {
772 p = (const char *)req->buf + passlen;
774 } else {
775 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
776 /* Ensure correct termination */
777 password.data[passlen]=0;
778 p = (const char *)req->buf + passlen + 1;
781 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
783 if (path == NULL) {
784 data_blob_clear_free(&password);
785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
786 END_PROFILE(SMBtconX);
787 return;
791 * the service name can be either: \\server\share
792 * or share directly like on the DELL PowerVault 705
794 if (*path=='\\') {
795 q = strchr_m(path+2,'\\');
796 if (!q) {
797 data_blob_clear_free(&password);
798 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
799 END_PROFILE(SMBtconX);
800 return;
802 service = q+1;
803 } else {
804 service = path;
807 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
808 &client_devicetype, p,
809 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
811 if (client_devicetype == NULL) {
812 data_blob_clear_free(&password);
813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
814 END_PROFILE(SMBtconX);
815 return;
818 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
820 conn = make_connection(sconn, service, password, client_devicetype,
821 req->vuid, &nt_status);
822 req->conn =conn;
824 data_blob_clear_free(&password);
826 if (!conn) {
827 reply_nterror(req, nt_status);
828 END_PROFILE(SMBtconX);
829 return;
832 if ( IS_IPC(conn) )
833 server_devicetype = "IPC";
834 else if ( IS_PRINT(conn) )
835 server_devicetype = "LPT1:";
836 else
837 server_devicetype = "A:";
839 if (get_Protocol() < PROTOCOL_NT1) {
840 reply_outbuf(req, 2, 0);
841 if (message_push_string(&req->outbuf, server_devicetype,
842 STR_TERMINATE|STR_ASCII) == -1) {
843 reply_nterror(req, NT_STATUS_NO_MEMORY);
844 END_PROFILE(SMBtconX);
845 return;
847 } else {
848 /* NT sets the fstype of IPC$ to the null string */
849 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
851 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
852 /* Return permissions. */
853 uint32 perm1 = 0;
854 uint32 perm2 = 0;
856 reply_outbuf(req, 7, 0);
858 if (IS_IPC(conn)) {
859 perm1 = FILE_ALL_ACCESS;
860 perm2 = FILE_ALL_ACCESS;
861 } else {
862 perm1 = conn->share_access;
865 SIVAL(req->outbuf, smb_vwv3, perm1);
866 SIVAL(req->outbuf, smb_vwv5, perm2);
867 } else {
868 reply_outbuf(req, 3, 0);
871 if ((message_push_string(&req->outbuf, server_devicetype,
872 STR_TERMINATE|STR_ASCII) == -1)
873 || (message_push_string(&req->outbuf, fstype,
874 STR_TERMINATE) == -1)) {
875 reply_nterror(req, NT_STATUS_NO_MEMORY);
876 END_PROFILE(SMBtconX);
877 return;
880 /* what does setting this bit do? It is set by NT4 and
881 may affect the ability to autorun mounted cdroms */
882 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
883 (lp_csc_policy(SNUM(conn)) << 2));
885 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
886 DEBUG(2,("Serving %s as a Dfs root\n",
887 lp_servicename(SNUM(conn)) ));
888 SSVAL(req->outbuf, smb_vwv2,
889 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
894 DEBUG(3,("tconX service=%s \n",
895 service));
897 /* set the incoming and outgoing tid to the just created one */
898 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
899 SSVAL(req->outbuf,smb_tid,conn->cnum);
901 END_PROFILE(SMBtconX);
903 req->tid = conn->cnum;
904 chain_reply(req);
905 return;
908 /****************************************************************************
909 Reply to an unknown type.
910 ****************************************************************************/
912 void reply_unknown_new(struct smb_request *req, uint8 type)
914 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
915 smb_fn_name(type), type, type));
916 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
917 return;
920 /****************************************************************************
921 Reply to an ioctl.
922 conn POINTER CAN BE NULL HERE !
923 ****************************************************************************/
925 void reply_ioctl(struct smb_request *req)
927 connection_struct *conn = req->conn;
928 uint16 device;
929 uint16 function;
930 uint32 ioctl_code;
931 int replysize;
932 char *p;
934 START_PROFILE(SMBioctl);
936 if (req->wct < 3) {
937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
938 END_PROFILE(SMBioctl);
939 return;
942 device = SVAL(req->vwv+1, 0);
943 function = SVAL(req->vwv+2, 0);
944 ioctl_code = (device << 16) + function;
946 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
948 switch (ioctl_code) {
949 case IOCTL_QUERY_JOB_INFO:
950 replysize = 32;
951 break;
952 default:
953 reply_force_doserror(req, ERRSRV, ERRnosupport);
954 END_PROFILE(SMBioctl);
955 return;
958 reply_outbuf(req, 8, replysize+1);
959 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
960 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
961 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
962 p = smb_buf(req->outbuf);
963 memset(p, '\0', replysize+1); /* valgrind-safe. */
964 p += 1; /* Allow for alignment */
966 switch (ioctl_code) {
967 case IOCTL_QUERY_JOB_INFO:
969 files_struct *fsp = file_fsp(
970 req, SVAL(req->vwv+0, 0));
971 if (!fsp) {
972 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
973 END_PROFILE(SMBioctl);
974 return;
976 /* Job number */
977 if (fsp->print_file) {
978 SSVAL(p, 0, fsp->print_file->rap_jobid);
979 } else {
980 SSVAL(p, 0, 0);
982 srvstr_push((char *)req->outbuf, req->flags2, p+2,
983 lp_netbios_name(), 15,
984 STR_TERMINATE|STR_ASCII);
985 if (conn) {
986 srvstr_push((char *)req->outbuf, req->flags2,
987 p+18, lp_servicename(SNUM(conn)),
988 13, STR_TERMINATE|STR_ASCII);
989 } else {
990 memset(p+18, 0, 13);
992 break;
996 END_PROFILE(SMBioctl);
997 return;
1000 /****************************************************************************
1001 Strange checkpath NTSTATUS mapping.
1002 ****************************************************************************/
1004 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1006 /* Strange DOS error code semantics only for checkpath... */
1007 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1008 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1009 /* We need to map to ERRbadpath */
1010 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1013 return status;
1016 /****************************************************************************
1017 Reply to a checkpath.
1018 ****************************************************************************/
1020 void reply_checkpath(struct smb_request *req)
1022 connection_struct *conn = req->conn;
1023 struct smb_filename *smb_fname = NULL;
1024 char *name = NULL;
1025 NTSTATUS status;
1026 TALLOC_CTX *ctx = talloc_tos();
1028 START_PROFILE(SMBcheckpath);
1030 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1031 STR_TERMINATE, &status);
1033 if (!NT_STATUS_IS_OK(status)) {
1034 status = map_checkpath_error(req->flags2, status);
1035 reply_nterror(req, status);
1036 END_PROFILE(SMBcheckpath);
1037 return;
1040 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1042 status = filename_convert(ctx,
1043 conn,
1044 req->flags2 & FLAGS2_DFS_PATHNAMES,
1045 name,
1047 NULL,
1048 &smb_fname);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1052 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1053 ERRSRV, ERRbadpath);
1054 END_PROFILE(SMBcheckpath);
1055 return;
1057 goto path_err;
1060 if (!VALID_STAT(smb_fname->st) &&
1061 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1062 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1063 smb_fname_str_dbg(smb_fname), strerror(errno)));
1064 status = map_nt_error_from_unix(errno);
1065 goto path_err;
1068 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1069 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1070 ERRDOS, ERRbadpath);
1071 goto out;
1074 reply_outbuf(req, 0, 0);
1076 path_err:
1077 /* We special case this - as when a Windows machine
1078 is parsing a path is steps through the components
1079 one at a time - if a component fails it expects
1080 ERRbadpath, not ERRbadfile.
1082 status = map_checkpath_error(req->flags2, status);
1083 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1085 * Windows returns different error codes if
1086 * the parent directory is valid but not the
1087 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1088 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1089 * if the path is invalid.
1091 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1092 ERRDOS, ERRbadpath);
1093 goto out;
1096 reply_nterror(req, status);
1098 out:
1099 TALLOC_FREE(smb_fname);
1100 END_PROFILE(SMBcheckpath);
1101 return;
1104 /****************************************************************************
1105 Reply to a getatr.
1106 ****************************************************************************/
1108 void reply_getatr(struct smb_request *req)
1110 connection_struct *conn = req->conn;
1111 struct smb_filename *smb_fname = NULL;
1112 char *fname = NULL;
1113 int mode=0;
1114 SMB_OFF_T size=0;
1115 time_t mtime=0;
1116 const char *p;
1117 NTSTATUS status;
1118 TALLOC_CTX *ctx = talloc_tos();
1119 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1121 START_PROFILE(SMBgetatr);
1123 p = (const char *)req->buf + 1;
1124 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1125 if (!NT_STATUS_IS_OK(status)) {
1126 reply_nterror(req, status);
1127 goto out;
1130 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1131 under WfWg - weird! */
1132 if (*fname == '\0') {
1133 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1134 if (!CAN_WRITE(conn)) {
1135 mode |= FILE_ATTRIBUTE_READONLY;
1137 size = 0;
1138 mtime = 0;
1139 } else {
1140 status = filename_convert(ctx,
1141 conn,
1142 req->flags2 & FLAGS2_DFS_PATHNAMES,
1143 fname,
1145 NULL,
1146 &smb_fname);
1147 if (!NT_STATUS_IS_OK(status)) {
1148 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1149 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1150 ERRSRV, ERRbadpath);
1151 goto out;
1153 reply_nterror(req, status);
1154 goto out;
1156 if (!VALID_STAT(smb_fname->st) &&
1157 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1158 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1159 smb_fname_str_dbg(smb_fname),
1160 strerror(errno)));
1161 reply_nterror(req, map_nt_error_from_unix(errno));
1162 goto out;
1165 mode = dos_mode(conn, smb_fname);
1166 size = smb_fname->st.st_ex_size;
1168 if (ask_sharemode) {
1169 struct timespec write_time_ts;
1170 struct file_id fileid;
1172 ZERO_STRUCT(write_time_ts);
1173 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1174 get_file_infos(fileid, 0, NULL, &write_time_ts);
1175 if (!null_timespec(write_time_ts)) {
1176 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1180 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1181 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1182 size = 0;
1186 reply_outbuf(req, 10, 0);
1188 SSVAL(req->outbuf,smb_vwv0,mode);
1189 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1190 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1191 } else {
1192 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1194 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1196 if (get_Protocol() >= PROTOCOL_NT1) {
1197 SSVAL(req->outbuf, smb_flg2,
1198 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1201 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1202 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1204 out:
1205 TALLOC_FREE(smb_fname);
1206 TALLOC_FREE(fname);
1207 END_PROFILE(SMBgetatr);
1208 return;
1211 /****************************************************************************
1212 Reply to a setatr.
1213 ****************************************************************************/
1215 void reply_setatr(struct smb_request *req)
1217 struct smb_file_time ft;
1218 connection_struct *conn = req->conn;
1219 struct smb_filename *smb_fname = NULL;
1220 char *fname = NULL;
1221 int mode;
1222 time_t mtime;
1223 const char *p;
1224 NTSTATUS status;
1225 TALLOC_CTX *ctx = talloc_tos();
1227 START_PROFILE(SMBsetatr);
1229 ZERO_STRUCT(ft);
1231 if (req->wct < 2) {
1232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1233 goto out;
1236 p = (const char *)req->buf + 1;
1237 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1238 if (!NT_STATUS_IS_OK(status)) {
1239 reply_nterror(req, status);
1240 goto out;
1243 status = filename_convert(ctx,
1244 conn,
1245 req->flags2 & FLAGS2_DFS_PATHNAMES,
1246 fname,
1248 NULL,
1249 &smb_fname);
1250 if (!NT_STATUS_IS_OK(status)) {
1251 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1252 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1253 ERRSRV, ERRbadpath);
1254 goto out;
1256 reply_nterror(req, status);
1257 goto out;
1260 if (smb_fname->base_name[0] == '.' &&
1261 smb_fname->base_name[1] == '\0') {
1263 * Not sure here is the right place to catch this
1264 * condition. Might be moved to somewhere else later -- vl
1266 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1267 goto out;
1270 mode = SVAL(req->vwv+0, 0);
1271 mtime = srv_make_unix_date3(req->vwv+1);
1273 if (mode != FILE_ATTRIBUTE_NORMAL) {
1274 if (VALID_STAT_OF_DIR(smb_fname->st))
1275 mode |= FILE_ATTRIBUTE_DIRECTORY;
1276 else
1277 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1279 status = check_access(conn, NULL, smb_fname,
1280 FILE_WRITE_ATTRIBUTES);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 reply_nterror(req, status);
1283 goto out;
1286 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1287 false) != 0) {
1288 reply_nterror(req, map_nt_error_from_unix(errno));
1289 goto out;
1293 ft.mtime = convert_time_t_to_timespec(mtime);
1294 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 reply_nterror(req, status);
1297 goto out;
1300 reply_outbuf(req, 0, 0);
1302 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1303 mode));
1304 out:
1305 TALLOC_FREE(smb_fname);
1306 END_PROFILE(SMBsetatr);
1307 return;
1310 /****************************************************************************
1311 Reply to a dskattr.
1312 ****************************************************************************/
1314 void reply_dskattr(struct smb_request *req)
1316 connection_struct *conn = req->conn;
1317 uint64_t dfree,dsize,bsize;
1318 START_PROFILE(SMBdskattr);
1320 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1321 reply_nterror(req, map_nt_error_from_unix(errno));
1322 END_PROFILE(SMBdskattr);
1323 return;
1326 reply_outbuf(req, 5, 0);
1328 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1329 double total_space, free_space;
1330 /* we need to scale this to a number that DOS6 can handle. We
1331 use floating point so we can handle large drives on systems
1332 that don't have 64 bit integers
1334 we end up displaying a maximum of 2G to DOS systems
1336 total_space = dsize * (double)bsize;
1337 free_space = dfree * (double)bsize;
1339 dsize = (uint64_t)((total_space+63*512) / (64*512));
1340 dfree = (uint64_t)((free_space+63*512) / (64*512));
1342 if (dsize > 0xFFFF) dsize = 0xFFFF;
1343 if (dfree > 0xFFFF) dfree = 0xFFFF;
1345 SSVAL(req->outbuf,smb_vwv0,dsize);
1346 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1347 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1348 SSVAL(req->outbuf,smb_vwv3,dfree);
1349 } else {
1350 SSVAL(req->outbuf,smb_vwv0,dsize);
1351 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1352 SSVAL(req->outbuf,smb_vwv2,512);
1353 SSVAL(req->outbuf,smb_vwv3,dfree);
1356 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1358 END_PROFILE(SMBdskattr);
1359 return;
1363 * Utility function to split the filename from the directory.
1365 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1366 char **fname_dir_out,
1367 char **fname_mask_out)
1369 const char *p = NULL;
1370 char *fname_dir = NULL;
1371 char *fname_mask = NULL;
1373 p = strrchr_m(fname_in, '/');
1374 if (!p) {
1375 fname_dir = talloc_strdup(ctx, ".");
1376 fname_mask = talloc_strdup(ctx, fname_in);
1377 } else {
1378 fname_dir = talloc_strndup(ctx, fname_in,
1379 PTR_DIFF(p, fname_in));
1380 fname_mask = talloc_strdup(ctx, p+1);
1383 if (!fname_dir || !fname_mask) {
1384 TALLOC_FREE(fname_dir);
1385 TALLOC_FREE(fname_mask);
1386 return NT_STATUS_NO_MEMORY;
1389 *fname_dir_out = fname_dir;
1390 *fname_mask_out = fname_mask;
1391 return NT_STATUS_OK;
1394 /****************************************************************************
1395 Reply to a search.
1396 Can be called from SMBsearch, SMBffirst or SMBfunique.
1397 ****************************************************************************/
1399 void reply_search(struct smb_request *req)
1401 connection_struct *conn = req->conn;
1402 char *path = NULL;
1403 const char *mask = NULL;
1404 char *directory = NULL;
1405 struct smb_filename *smb_fname = NULL;
1406 char *fname = NULL;
1407 SMB_OFF_T size;
1408 uint32 mode;
1409 struct timespec date;
1410 uint32 dirtype;
1411 unsigned int numentries = 0;
1412 unsigned int maxentries = 0;
1413 bool finished = False;
1414 const char *p;
1415 int status_len;
1416 char status[21];
1417 int dptr_num= -1;
1418 bool check_descend = False;
1419 bool expect_close = False;
1420 NTSTATUS nt_status;
1421 bool mask_contains_wcard = False;
1422 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1423 TALLOC_CTX *ctx = talloc_tos();
1424 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1425 struct dptr_struct *dirptr = NULL;
1426 struct smbd_server_connection *sconn = req->sconn;
1428 START_PROFILE(SMBsearch);
1430 if (req->wct < 2) {
1431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1432 goto out;
1435 if (lp_posix_pathnames()) {
1436 reply_unknown_new(req, req->cmd);
1437 goto out;
1440 /* If we were called as SMBffirst then we must expect close. */
1441 if(req->cmd == SMBffirst) {
1442 expect_close = True;
1445 reply_outbuf(req, 1, 3);
1446 maxentries = SVAL(req->vwv+0, 0);
1447 dirtype = SVAL(req->vwv+1, 0);
1448 p = (const char *)req->buf + 1;
1449 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1450 &nt_status, &mask_contains_wcard);
1451 if (!NT_STATUS_IS_OK(nt_status)) {
1452 reply_nterror(req, nt_status);
1453 goto out;
1456 p++;
1457 status_len = SVAL(p, 0);
1458 p += 2;
1460 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1462 if (status_len == 0) {
1463 nt_status = filename_convert(ctx, conn,
1464 req->flags2 & FLAGS2_DFS_PATHNAMES,
1465 path,
1466 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1467 &mask_contains_wcard,
1468 &smb_fname);
1469 if (!NT_STATUS_IS_OK(nt_status)) {
1470 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1471 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1472 ERRSRV, ERRbadpath);
1473 goto out;
1475 reply_nterror(req, nt_status);
1476 goto out;
1479 directory = smb_fname->base_name;
1481 p = strrchr_m(directory,'/');
1482 if ((p != NULL) && (*directory != '/')) {
1483 mask = p + 1;
1484 directory = talloc_strndup(ctx, directory,
1485 PTR_DIFF(p, directory));
1486 } else {
1487 mask = directory;
1488 directory = talloc_strdup(ctx,".");
1491 if (!directory) {
1492 reply_nterror(req, NT_STATUS_NO_MEMORY);
1493 goto out;
1496 memset((char *)status,'\0',21);
1497 SCVAL(status,0,(dirtype & 0x1F));
1499 nt_status = dptr_create(conn,
1500 NULL, /* fsp */
1501 directory,
1502 True,
1503 expect_close,
1504 req->smbpid,
1505 mask,
1506 mask_contains_wcard,
1507 dirtype,
1508 &dirptr);
1509 if (!NT_STATUS_IS_OK(nt_status)) {
1510 reply_nterror(req, nt_status);
1511 goto out;
1513 dptr_num = dptr_dnum(dirptr);
1514 } else {
1515 int status_dirtype;
1516 const char *dirpath;
1518 memcpy(status,p,21);
1519 status_dirtype = CVAL(status,0) & 0x1F;
1520 if (status_dirtype != (dirtype & 0x1F)) {
1521 dirtype = status_dirtype;
1524 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1525 if (!dirptr) {
1526 goto SearchEmpty;
1528 dirpath = dptr_path(sconn, dptr_num);
1529 directory = talloc_strdup(ctx, dirpath);
1530 if (!directory) {
1531 reply_nterror(req, NT_STATUS_NO_MEMORY);
1532 goto out;
1535 mask = dptr_wcard(sconn, dptr_num);
1536 if (!mask) {
1537 goto SearchEmpty;
1540 * For a 'continue' search we have no string. So
1541 * check from the initial saved string.
1543 mask_contains_wcard = ms_has_wild(mask);
1544 dirtype = dptr_attr(sconn, dptr_num);
1547 DEBUG(4,("dptr_num is %d\n",dptr_num));
1549 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1550 dptr_init_search_op(dirptr);
1552 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1553 char buf[DIR_STRUCT_SIZE];
1554 memcpy(buf,status,21);
1555 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1556 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1557 reply_nterror(req, NT_STATUS_NO_MEMORY);
1558 goto out;
1560 dptr_fill(sconn, buf+12,dptr_num);
1561 if (dptr_zero(buf+12) && (status_len==0)) {
1562 numentries = 1;
1563 } else {
1564 numentries = 0;
1566 if (message_push_blob(&req->outbuf,
1567 data_blob_const(buf, sizeof(buf)))
1568 == -1) {
1569 reply_nterror(req, NT_STATUS_NO_MEMORY);
1570 goto out;
1572 } else {
1573 unsigned int i;
1574 maxentries = MIN(
1575 maxentries,
1576 ((BUFFER_SIZE -
1577 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1578 /DIR_STRUCT_SIZE));
1580 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1581 directory,lp_dontdescend(SNUM(conn))));
1582 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1583 check_descend = True;
1586 for (i=numentries;(i<maxentries) && !finished;i++) {
1587 finished = !get_dir_entry(ctx,
1588 dirptr,
1589 mask,
1590 dirtype,
1591 &fname,
1592 &size,
1593 &mode,
1594 &date,
1595 check_descend,
1596 ask_sharemode);
1597 if (!finished) {
1598 char buf[DIR_STRUCT_SIZE];
1599 memcpy(buf,status,21);
1600 if (!make_dir_struct(ctx,
1601 buf,
1602 mask,
1603 fname,
1604 size,
1605 mode,
1606 convert_timespec_to_time_t(date),
1607 !allow_long_path_components)) {
1608 reply_nterror(req, NT_STATUS_NO_MEMORY);
1609 goto out;
1611 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1612 break;
1614 if (message_push_blob(&req->outbuf,
1615 data_blob_const(buf, sizeof(buf)))
1616 == -1) {
1617 reply_nterror(req, NT_STATUS_NO_MEMORY);
1618 goto out;
1620 numentries++;
1625 SearchEmpty:
1627 /* If we were called as SMBffirst with smb_search_id == NULL
1628 and no entries were found then return error and close dirptr
1629 (X/Open spec) */
1631 if (numentries == 0) {
1632 dptr_close(sconn, &dptr_num);
1633 } else if(expect_close && status_len == 0) {
1634 /* Close the dptr - we know it's gone */
1635 dptr_close(sconn, &dptr_num);
1638 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1639 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1640 dptr_close(sconn, &dptr_num);
1643 if ((numentries == 0) && !mask_contains_wcard) {
1644 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1645 goto out;
1648 SSVAL(req->outbuf,smb_vwv0,numentries);
1649 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1650 SCVAL(smb_buf(req->outbuf),0,5);
1651 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1653 /* The replies here are never long name. */
1654 SSVAL(req->outbuf, smb_flg2,
1655 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1656 if (!allow_long_path_components) {
1657 SSVAL(req->outbuf, smb_flg2,
1658 SVAL(req->outbuf, smb_flg2)
1659 & (~FLAGS2_LONG_PATH_COMPONENTS));
1662 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1663 SSVAL(req->outbuf, smb_flg2,
1664 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1666 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1667 smb_fn_name(req->cmd),
1668 mask,
1669 directory,
1670 dirtype,
1671 numentries,
1672 maxentries ));
1673 out:
1674 TALLOC_FREE(directory);
1675 TALLOC_FREE(smb_fname);
1676 END_PROFILE(SMBsearch);
1677 return;
1680 /****************************************************************************
1681 Reply to a fclose (stop directory search).
1682 ****************************************************************************/
1684 void reply_fclose(struct smb_request *req)
1686 int status_len;
1687 char status[21];
1688 int dptr_num= -2;
1689 const char *p;
1690 char *path = NULL;
1691 NTSTATUS err;
1692 bool path_contains_wcard = False;
1693 TALLOC_CTX *ctx = talloc_tos();
1694 struct smbd_server_connection *sconn = req->sconn;
1696 START_PROFILE(SMBfclose);
1698 if (lp_posix_pathnames()) {
1699 reply_unknown_new(req, req->cmd);
1700 END_PROFILE(SMBfclose);
1701 return;
1704 p = (const char *)req->buf + 1;
1705 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1706 &err, &path_contains_wcard);
1707 if (!NT_STATUS_IS_OK(err)) {
1708 reply_nterror(req, err);
1709 END_PROFILE(SMBfclose);
1710 return;
1712 p++;
1713 status_len = SVAL(p,0);
1714 p += 2;
1716 if (status_len == 0) {
1717 reply_force_doserror(req, ERRSRV, ERRsrverror);
1718 END_PROFILE(SMBfclose);
1719 return;
1722 memcpy(status,p,21);
1724 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1725 /* Close the dptr - we know it's gone */
1726 dptr_close(sconn, &dptr_num);
1729 reply_outbuf(req, 1, 0);
1730 SSVAL(req->outbuf,smb_vwv0,0);
1732 DEBUG(3,("search close\n"));
1734 END_PROFILE(SMBfclose);
1735 return;
1738 /****************************************************************************
1739 Reply to an open.
1740 ****************************************************************************/
1742 void reply_open(struct smb_request *req)
1744 connection_struct *conn = req->conn;
1745 struct smb_filename *smb_fname = NULL;
1746 char *fname = NULL;
1747 uint32 fattr=0;
1748 SMB_OFF_T size = 0;
1749 time_t mtime=0;
1750 int info;
1751 files_struct *fsp;
1752 int oplock_request;
1753 int deny_mode;
1754 uint32 dos_attr;
1755 uint32 access_mask;
1756 uint32 share_mode;
1757 uint32 create_disposition;
1758 uint32 create_options = 0;
1759 uint32_t private_flags = 0;
1760 NTSTATUS status;
1761 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1762 TALLOC_CTX *ctx = talloc_tos();
1764 START_PROFILE(SMBopen);
1766 if (req->wct < 2) {
1767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1768 goto out;
1771 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1772 deny_mode = SVAL(req->vwv+0, 0);
1773 dos_attr = SVAL(req->vwv+1, 0);
1775 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1776 STR_TERMINATE, &status);
1777 if (!NT_STATUS_IS_OK(status)) {
1778 reply_nterror(req, status);
1779 goto out;
1782 status = filename_convert(ctx,
1783 conn,
1784 req->flags2 & FLAGS2_DFS_PATHNAMES,
1785 fname,
1787 NULL,
1788 &smb_fname);
1789 if (!NT_STATUS_IS_OK(status)) {
1790 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1791 reply_botherror(req,
1792 NT_STATUS_PATH_NOT_COVERED,
1793 ERRSRV, ERRbadpath);
1794 goto out;
1796 reply_nterror(req, status);
1797 goto out;
1800 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1801 OPENX_FILE_EXISTS_OPEN, &access_mask,
1802 &share_mode, &create_disposition,
1803 &create_options, &private_flags)) {
1804 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1805 goto out;
1808 status = SMB_VFS_CREATE_FILE(
1809 conn, /* conn */
1810 req, /* req */
1811 0, /* root_dir_fid */
1812 smb_fname, /* fname */
1813 access_mask, /* access_mask */
1814 share_mode, /* share_access */
1815 create_disposition, /* create_disposition*/
1816 create_options, /* create_options */
1817 dos_attr, /* file_attributes */
1818 oplock_request, /* oplock_request */
1819 0, /* allocation_size */
1820 private_flags,
1821 NULL, /* sd */
1822 NULL, /* ea_list */
1823 &fsp, /* result */
1824 &info); /* pinfo */
1826 if (!NT_STATUS_IS_OK(status)) {
1827 if (open_was_deferred(req->sconn, req->mid)) {
1828 /* We have re-scheduled this call. */
1829 goto out;
1831 reply_openerror(req, status);
1832 goto out;
1835 size = smb_fname->st.st_ex_size;
1836 fattr = dos_mode(conn, smb_fname);
1838 /* Deal with other possible opens having a modified
1839 write time. JRA. */
1840 if (ask_sharemode) {
1841 struct timespec write_time_ts;
1843 ZERO_STRUCT(write_time_ts);
1844 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1845 if (!null_timespec(write_time_ts)) {
1846 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1850 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1852 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1853 DEBUG(3,("attempt to open a directory %s\n",
1854 fsp_str_dbg(fsp)));
1855 close_file(req, fsp, ERROR_CLOSE);
1856 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1857 ERRDOS, ERRnoaccess);
1858 goto out;
1861 reply_outbuf(req, 7, 0);
1862 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1863 SSVAL(req->outbuf,smb_vwv1,fattr);
1864 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1865 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1866 } else {
1867 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1869 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1870 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1872 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1873 SCVAL(req->outbuf,smb_flg,
1874 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1877 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1878 SCVAL(req->outbuf,smb_flg,
1879 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1881 out:
1882 TALLOC_FREE(smb_fname);
1883 END_PROFILE(SMBopen);
1884 return;
1887 /****************************************************************************
1888 Reply to an open and X.
1889 ****************************************************************************/
1891 void reply_open_and_X(struct smb_request *req)
1893 connection_struct *conn = req->conn;
1894 struct smb_filename *smb_fname = NULL;
1895 char *fname = NULL;
1896 uint16 open_flags;
1897 int deny_mode;
1898 uint32 smb_attr;
1899 /* Breakout the oplock request bits so we can set the
1900 reply bits separately. */
1901 int ex_oplock_request;
1902 int core_oplock_request;
1903 int oplock_request;
1904 #if 0
1905 int smb_sattr = SVAL(req->vwv+4, 0);
1906 uint32 smb_time = make_unix_date3(req->vwv+6);
1907 #endif
1908 int smb_ofun;
1909 uint32 fattr=0;
1910 int mtime=0;
1911 int smb_action = 0;
1912 files_struct *fsp;
1913 NTSTATUS status;
1914 uint64_t allocation_size;
1915 ssize_t retval = -1;
1916 uint32 access_mask;
1917 uint32 share_mode;
1918 uint32 create_disposition;
1919 uint32 create_options = 0;
1920 uint32_t private_flags = 0;
1921 TALLOC_CTX *ctx = talloc_tos();
1923 START_PROFILE(SMBopenX);
1925 if (req->wct < 15) {
1926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1927 goto out;
1930 open_flags = SVAL(req->vwv+2, 0);
1931 deny_mode = SVAL(req->vwv+3, 0);
1932 smb_attr = SVAL(req->vwv+5, 0);
1933 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1934 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1935 oplock_request = ex_oplock_request | core_oplock_request;
1936 smb_ofun = SVAL(req->vwv+8, 0);
1937 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1939 /* If it's an IPC, pass off the pipe handler. */
1940 if (IS_IPC(conn)) {
1941 if (lp_nt_pipe_support()) {
1942 reply_open_pipe_and_X(conn, req);
1943 } else {
1944 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1946 goto out;
1949 /* XXXX we need to handle passed times, sattr and flags */
1950 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1951 STR_TERMINATE, &status);
1952 if (!NT_STATUS_IS_OK(status)) {
1953 reply_nterror(req, status);
1954 goto out;
1957 status = filename_convert(ctx,
1958 conn,
1959 req->flags2 & FLAGS2_DFS_PATHNAMES,
1960 fname,
1962 NULL,
1963 &smb_fname);
1964 if (!NT_STATUS_IS_OK(status)) {
1965 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1966 reply_botherror(req,
1967 NT_STATUS_PATH_NOT_COVERED,
1968 ERRSRV, ERRbadpath);
1969 goto out;
1971 reply_nterror(req, status);
1972 goto out;
1975 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1976 smb_ofun,
1977 &access_mask, &share_mode,
1978 &create_disposition,
1979 &create_options,
1980 &private_flags)) {
1981 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1982 goto out;
1985 status = SMB_VFS_CREATE_FILE(
1986 conn, /* conn */
1987 req, /* req */
1988 0, /* root_dir_fid */
1989 smb_fname, /* fname */
1990 access_mask, /* access_mask */
1991 share_mode, /* share_access */
1992 create_disposition, /* create_disposition*/
1993 create_options, /* create_options */
1994 smb_attr, /* file_attributes */
1995 oplock_request, /* oplock_request */
1996 0, /* allocation_size */
1997 private_flags,
1998 NULL, /* sd */
1999 NULL, /* ea_list */
2000 &fsp, /* result */
2001 &smb_action); /* pinfo */
2003 if (!NT_STATUS_IS_OK(status)) {
2004 if (open_was_deferred(req->sconn, req->mid)) {
2005 /* We have re-scheduled this call. */
2006 goto out;
2008 reply_openerror(req, status);
2009 goto out;
2012 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2013 if the file is truncated or created. */
2014 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2015 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2016 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2017 close_file(req, fsp, ERROR_CLOSE);
2018 reply_nterror(req, NT_STATUS_DISK_FULL);
2019 goto out;
2021 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
2022 if (retval < 0) {
2023 close_file(req, fsp, ERROR_CLOSE);
2024 reply_nterror(req, NT_STATUS_DISK_FULL);
2025 goto out;
2027 status = vfs_stat_fsp(fsp);
2028 if (!NT_STATUS_IS_OK(status)) {
2029 close_file(req, fsp, ERROR_CLOSE);
2030 reply_nterror(req, status);
2031 goto out;
2035 fattr = dos_mode(conn, fsp->fsp_name);
2036 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2037 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2038 close_file(req, fsp, ERROR_CLOSE);
2039 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2040 goto out;
2043 /* If the caller set the extended oplock request bit
2044 and we granted one (by whatever means) - set the
2045 correct bit for extended oplock reply.
2048 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2049 smb_action |= EXTENDED_OPLOCK_GRANTED;
2052 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2053 smb_action |= EXTENDED_OPLOCK_GRANTED;
2056 /* If the caller set the core oplock request bit
2057 and we granted one (by whatever means) - set the
2058 correct bit for core oplock reply.
2061 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2062 reply_outbuf(req, 19, 0);
2063 } else {
2064 reply_outbuf(req, 15, 0);
2067 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2068 SCVAL(req->outbuf, smb_flg,
2069 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2072 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2073 SCVAL(req->outbuf, smb_flg,
2074 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2077 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2078 SSVAL(req->outbuf,smb_vwv3,fattr);
2079 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2080 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2081 } else {
2082 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2084 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2085 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2086 SSVAL(req->outbuf,smb_vwv11,smb_action);
2088 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2089 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2092 chain_reply(req);
2093 out:
2094 TALLOC_FREE(smb_fname);
2095 END_PROFILE(SMBopenX);
2096 return;
2099 /****************************************************************************
2100 Reply to a SMBulogoffX.
2101 ****************************************************************************/
2103 void reply_ulogoffX(struct smb_request *req)
2105 struct smbd_server_connection *sconn = req->sconn;
2106 user_struct *vuser;
2108 START_PROFILE(SMBulogoffX);
2110 vuser = get_valid_user_struct(sconn, req->vuid);
2112 if(vuser == NULL) {
2113 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2114 req->vuid));
2117 /* in user level security we are supposed to close any files
2118 open by this user */
2119 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2120 file_close_user(sconn, req->vuid);
2123 invalidate_vuid(sconn, req->vuid);
2125 reply_outbuf(req, 2, 0);
2127 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2129 END_PROFILE(SMBulogoffX);
2130 req->vuid = UID_FIELD_INVALID;
2131 chain_reply(req);
2134 /****************************************************************************
2135 Reply to a mknew or a create.
2136 ****************************************************************************/
2138 void reply_mknew(struct smb_request *req)
2140 connection_struct *conn = req->conn;
2141 struct smb_filename *smb_fname = NULL;
2142 char *fname = NULL;
2143 uint32 fattr = 0;
2144 struct smb_file_time ft;
2145 files_struct *fsp;
2146 int oplock_request = 0;
2147 NTSTATUS status;
2148 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2149 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2150 uint32 create_disposition;
2151 uint32 create_options = 0;
2152 TALLOC_CTX *ctx = talloc_tos();
2154 START_PROFILE(SMBcreate);
2155 ZERO_STRUCT(ft);
2157 if (req->wct < 3) {
2158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2159 goto out;
2162 fattr = SVAL(req->vwv+0, 0);
2163 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2165 /* mtime. */
2166 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2168 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2169 STR_TERMINATE, &status);
2170 if (!NT_STATUS_IS_OK(status)) {
2171 reply_nterror(req, status);
2172 goto out;
2175 status = filename_convert(ctx,
2176 conn,
2177 req->flags2 & FLAGS2_DFS_PATHNAMES,
2178 fname,
2180 NULL,
2181 &smb_fname);
2182 if (!NT_STATUS_IS_OK(status)) {
2183 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2184 reply_botherror(req,
2185 NT_STATUS_PATH_NOT_COVERED,
2186 ERRSRV, ERRbadpath);
2187 goto out;
2189 reply_nterror(req, status);
2190 goto out;
2193 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2194 DEBUG(0,("Attempt to create file (%s) with volid set - "
2195 "please report this\n",
2196 smb_fname_str_dbg(smb_fname)));
2199 if(req->cmd == SMBmknew) {
2200 /* We should fail if file exists. */
2201 create_disposition = FILE_CREATE;
2202 } else {
2203 /* Create if file doesn't exist, truncate if it does. */
2204 create_disposition = FILE_OVERWRITE_IF;
2207 status = SMB_VFS_CREATE_FILE(
2208 conn, /* conn */
2209 req, /* req */
2210 0, /* root_dir_fid */
2211 smb_fname, /* fname */
2212 access_mask, /* access_mask */
2213 share_mode, /* share_access */
2214 create_disposition, /* create_disposition*/
2215 create_options, /* create_options */
2216 fattr, /* file_attributes */
2217 oplock_request, /* oplock_request */
2218 0, /* allocation_size */
2219 0, /* private_flags */
2220 NULL, /* sd */
2221 NULL, /* ea_list */
2222 &fsp, /* result */
2223 NULL); /* pinfo */
2225 if (!NT_STATUS_IS_OK(status)) {
2226 if (open_was_deferred(req->sconn, req->mid)) {
2227 /* We have re-scheduled this call. */
2228 goto out;
2230 reply_openerror(req, status);
2231 goto out;
2234 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2235 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2236 if (!NT_STATUS_IS_OK(status)) {
2237 END_PROFILE(SMBcreate);
2238 goto out;
2241 reply_outbuf(req, 1, 0);
2242 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2244 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2245 SCVAL(req->outbuf,smb_flg,
2246 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2249 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2250 SCVAL(req->outbuf,smb_flg,
2251 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2254 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2255 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2256 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2257 (unsigned int)fattr));
2259 out:
2260 TALLOC_FREE(smb_fname);
2261 END_PROFILE(SMBcreate);
2262 return;
2265 /****************************************************************************
2266 Reply to a create temporary file.
2267 ****************************************************************************/
2269 void reply_ctemp(struct smb_request *req)
2271 connection_struct *conn = req->conn;
2272 struct smb_filename *smb_fname = NULL;
2273 char *fname = NULL;
2274 uint32 fattr;
2275 files_struct *fsp;
2276 int oplock_request;
2277 int tmpfd;
2278 char *s;
2279 NTSTATUS status;
2280 TALLOC_CTX *ctx = talloc_tos();
2282 START_PROFILE(SMBctemp);
2284 if (req->wct < 3) {
2285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2286 goto out;
2289 fattr = SVAL(req->vwv+0, 0);
2290 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2292 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2293 STR_TERMINATE, &status);
2294 if (!NT_STATUS_IS_OK(status)) {
2295 reply_nterror(req, status);
2296 goto out;
2298 if (*fname) {
2299 fname = talloc_asprintf(ctx,
2300 "%s/TMXXXXXX",
2301 fname);
2302 } else {
2303 fname = talloc_strdup(ctx, "TMXXXXXX");
2306 if (!fname) {
2307 reply_nterror(req, NT_STATUS_NO_MEMORY);
2308 goto out;
2311 status = filename_convert(ctx, conn,
2312 req->flags2 & FLAGS2_DFS_PATHNAMES,
2313 fname,
2315 NULL,
2316 &smb_fname);
2317 if (!NT_STATUS_IS_OK(status)) {
2318 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2319 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2320 ERRSRV, ERRbadpath);
2321 goto out;
2323 reply_nterror(req, status);
2324 goto out;
2327 tmpfd = mkstemp(smb_fname->base_name);
2328 if (tmpfd == -1) {
2329 reply_nterror(req, map_nt_error_from_unix(errno));
2330 goto out;
2333 SMB_VFS_STAT(conn, smb_fname);
2335 /* We should fail if file does not exist. */
2336 status = SMB_VFS_CREATE_FILE(
2337 conn, /* conn */
2338 req, /* req */
2339 0, /* root_dir_fid */
2340 smb_fname, /* fname */
2341 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2342 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2343 FILE_OPEN, /* create_disposition*/
2344 0, /* create_options */
2345 fattr, /* file_attributes */
2346 oplock_request, /* oplock_request */
2347 0, /* allocation_size */
2348 0, /* private_flags */
2349 NULL, /* sd */
2350 NULL, /* ea_list */
2351 &fsp, /* result */
2352 NULL); /* pinfo */
2354 /* close fd from mkstemp() */
2355 close(tmpfd);
2357 if (!NT_STATUS_IS_OK(status)) {
2358 if (open_was_deferred(req->sconn, req->mid)) {
2359 /* We have re-scheduled this call. */
2360 goto out;
2362 reply_openerror(req, status);
2363 goto out;
2366 reply_outbuf(req, 1, 0);
2367 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2369 /* the returned filename is relative to the directory */
2370 s = strrchr_m(fsp->fsp_name->base_name, '/');
2371 if (!s) {
2372 s = fsp->fsp_name->base_name;
2373 } else {
2374 s++;
2377 #if 0
2378 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2379 thing in the byte section. JRA */
2380 SSVALS(p, 0, -1); /* what is this? not in spec */
2381 #endif
2382 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2383 == -1) {
2384 reply_nterror(req, NT_STATUS_NO_MEMORY);
2385 goto out;
2388 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2389 SCVAL(req->outbuf, smb_flg,
2390 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2393 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2394 SCVAL(req->outbuf, smb_flg,
2395 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2398 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2399 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2400 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2401 out:
2402 TALLOC_FREE(smb_fname);
2403 END_PROFILE(SMBctemp);
2404 return;
2407 /*******************************************************************
2408 Check if a user is allowed to rename a file.
2409 ********************************************************************/
2411 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2412 uint16 dirtype)
2414 if (!CAN_WRITE(conn)) {
2415 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2418 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2419 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2420 /* Only bother to read the DOS attribute if we might deny the
2421 rename on the grounds of attribute missmatch. */
2422 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2423 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2424 return NT_STATUS_NO_SUCH_FILE;
2428 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2429 if (fsp->posix_open) {
2430 return NT_STATUS_OK;
2433 /* If no pathnames are open below this
2434 directory, allow the rename. */
2436 if (file_find_subpath(fsp)) {
2437 return NT_STATUS_ACCESS_DENIED;
2439 return NT_STATUS_OK;
2442 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2443 return NT_STATUS_OK;
2446 return NT_STATUS_ACCESS_DENIED;
2449 /*******************************************************************
2450 * unlink a file with all relevant access checks
2451 *******************************************************************/
2453 static NTSTATUS do_unlink(connection_struct *conn,
2454 struct smb_request *req,
2455 struct smb_filename *smb_fname,
2456 uint32 dirtype)
2458 uint32 fattr;
2459 files_struct *fsp;
2460 uint32 dirtype_orig = dirtype;
2461 NTSTATUS status;
2462 int ret;
2463 bool posix_paths = lp_posix_pathnames();
2465 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2466 smb_fname_str_dbg(smb_fname),
2467 dirtype));
2469 if (!CAN_WRITE(conn)) {
2470 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2473 if (posix_paths) {
2474 ret = SMB_VFS_LSTAT(conn, smb_fname);
2475 } else {
2476 ret = SMB_VFS_STAT(conn, smb_fname);
2478 if (ret != 0) {
2479 return map_nt_error_from_unix(errno);
2482 fattr = dos_mode(conn, smb_fname);
2484 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2485 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2488 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2489 if (!dirtype) {
2490 return NT_STATUS_NO_SUCH_FILE;
2493 if (!dir_check_ftype(conn, fattr, dirtype)) {
2494 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2495 return NT_STATUS_FILE_IS_A_DIRECTORY;
2497 return NT_STATUS_NO_SUCH_FILE;
2500 if (dirtype_orig & 0x8000) {
2501 /* These will never be set for POSIX. */
2502 return NT_STATUS_NO_SUCH_FILE;
2505 #if 0
2506 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2507 return NT_STATUS_FILE_IS_A_DIRECTORY;
2510 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2511 return NT_STATUS_NO_SUCH_FILE;
2514 if (dirtype & 0xFF00) {
2515 /* These will never be set for POSIX. */
2516 return NT_STATUS_NO_SUCH_FILE;
2519 dirtype &= 0xFF;
2520 if (!dirtype) {
2521 return NT_STATUS_NO_SUCH_FILE;
2524 /* Can't delete a directory. */
2525 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2526 return NT_STATUS_FILE_IS_A_DIRECTORY;
2528 #endif
2530 #if 0 /* JRATEST */
2531 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2532 return NT_STATUS_OBJECT_NAME_INVALID;
2533 #endif /* JRATEST */
2535 /* On open checks the open itself will check the share mode, so
2536 don't do it here as we'll get it wrong. */
2538 status = SMB_VFS_CREATE_FILE
2539 (conn, /* conn */
2540 req, /* req */
2541 0, /* root_dir_fid */
2542 smb_fname, /* fname */
2543 DELETE_ACCESS, /* access_mask */
2544 FILE_SHARE_NONE, /* share_access */
2545 FILE_OPEN, /* create_disposition*/
2546 FILE_NON_DIRECTORY_FILE, /* create_options */
2547 /* file_attributes */
2548 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2549 FILE_ATTRIBUTE_NORMAL,
2550 0, /* oplock_request */
2551 0, /* allocation_size */
2552 0, /* private_flags */
2553 NULL, /* sd */
2554 NULL, /* ea_list */
2555 &fsp, /* result */
2556 NULL); /* pinfo */
2558 if (!NT_STATUS_IS_OK(status)) {
2559 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2560 nt_errstr(status)));
2561 return status;
2564 status = can_set_delete_on_close(fsp, fattr);
2565 if (!NT_STATUS_IS_OK(status)) {
2566 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2567 "(%s)\n",
2568 smb_fname_str_dbg(smb_fname),
2569 nt_errstr(status)));
2570 close_file(req, fsp, NORMAL_CLOSE);
2571 return status;
2574 /* The set is across all open files on this dev/inode pair. */
2575 if (!set_delete_on_close(fsp, True, conn->session_info->unix_token)) {
2576 close_file(req, fsp, NORMAL_CLOSE);
2577 return NT_STATUS_ACCESS_DENIED;
2580 return close_file(req, fsp, NORMAL_CLOSE);
2583 /****************************************************************************
2584 The guts of the unlink command, split out so it may be called by the NT SMB
2585 code.
2586 ****************************************************************************/
2588 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2589 uint32 dirtype, struct smb_filename *smb_fname,
2590 bool has_wild)
2592 char *fname_dir = NULL;
2593 char *fname_mask = NULL;
2594 int count=0;
2595 NTSTATUS status = NT_STATUS_OK;
2596 TALLOC_CTX *ctx = talloc_tos();
2598 /* Split up the directory from the filename/mask. */
2599 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2600 &fname_dir, &fname_mask);
2601 if (!NT_STATUS_IS_OK(status)) {
2602 goto out;
2606 * We should only check the mangled cache
2607 * here if unix_convert failed. This means
2608 * that the path in 'mask' doesn't exist
2609 * on the file system and so we need to look
2610 * for a possible mangle. This patch from
2611 * Tine Smukavec <valentin.smukavec@hermes.si>.
2614 if (!VALID_STAT(smb_fname->st) &&
2615 mangle_is_mangled(fname_mask, conn->params)) {
2616 char *new_mask = NULL;
2617 mangle_lookup_name_from_8_3(ctx, fname_mask,
2618 &new_mask, conn->params);
2619 if (new_mask) {
2620 TALLOC_FREE(fname_mask);
2621 fname_mask = new_mask;
2625 if (!has_wild) {
2628 * Only one file needs to be unlinked. Append the mask back
2629 * onto the directory.
2631 TALLOC_FREE(smb_fname->base_name);
2632 if (ISDOT(fname_dir)) {
2633 /* Ensure we use canonical names on open. */
2634 smb_fname->base_name = talloc_asprintf(smb_fname,
2635 "%s",
2636 fname_mask);
2637 } else {
2638 smb_fname->base_name = talloc_asprintf(smb_fname,
2639 "%s/%s",
2640 fname_dir,
2641 fname_mask);
2643 if (!smb_fname->base_name) {
2644 status = NT_STATUS_NO_MEMORY;
2645 goto out;
2647 if (dirtype == 0) {
2648 dirtype = FILE_ATTRIBUTE_NORMAL;
2651 status = check_name(conn, smb_fname->base_name);
2652 if (!NT_STATUS_IS_OK(status)) {
2653 goto out;
2656 status = do_unlink(conn, req, smb_fname, dirtype);
2657 if (!NT_STATUS_IS_OK(status)) {
2658 goto out;
2661 count++;
2662 } else {
2663 struct smb_Dir *dir_hnd = NULL;
2664 long offset = 0;
2665 const char *dname = NULL;
2666 char *talloced = NULL;
2668 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2669 status = NT_STATUS_OBJECT_NAME_INVALID;
2670 goto out;
2673 if (strequal(fname_mask,"????????.???")) {
2674 TALLOC_FREE(fname_mask);
2675 fname_mask = talloc_strdup(ctx, "*");
2676 if (!fname_mask) {
2677 status = NT_STATUS_NO_MEMORY;
2678 goto out;
2682 status = check_name(conn, fname_dir);
2683 if (!NT_STATUS_IS_OK(status)) {
2684 goto out;
2687 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2688 dirtype);
2689 if (dir_hnd == NULL) {
2690 status = map_nt_error_from_unix(errno);
2691 goto out;
2694 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2695 the pattern matches against the long name, otherwise the short name
2696 We don't implement this yet XXXX
2699 status = NT_STATUS_NO_SUCH_FILE;
2701 while ((dname = ReadDirName(dir_hnd, &offset,
2702 &smb_fname->st, &talloced))) {
2703 TALLOC_CTX *frame = talloc_stackframe();
2705 if (!is_visible_file(conn, fname_dir, dname,
2706 &smb_fname->st, true)) {
2707 TALLOC_FREE(frame);
2708 TALLOC_FREE(talloced);
2709 continue;
2712 /* Quick check for "." and ".." */
2713 if (ISDOT(dname) || ISDOTDOT(dname)) {
2714 TALLOC_FREE(frame);
2715 TALLOC_FREE(talloced);
2716 continue;
2719 if(!mask_match(dname, fname_mask,
2720 conn->case_sensitive)) {
2721 TALLOC_FREE(frame);
2722 TALLOC_FREE(talloced);
2723 continue;
2726 TALLOC_FREE(smb_fname->base_name);
2727 if (ISDOT(fname_dir)) {
2728 /* Ensure we use canonical names on open. */
2729 smb_fname->base_name =
2730 talloc_asprintf(smb_fname, "%s",
2731 dname);
2732 } else {
2733 smb_fname->base_name =
2734 talloc_asprintf(smb_fname, "%s/%s",
2735 fname_dir, dname);
2738 if (!smb_fname->base_name) {
2739 TALLOC_FREE(dir_hnd);
2740 status = NT_STATUS_NO_MEMORY;
2741 TALLOC_FREE(frame);
2742 TALLOC_FREE(talloced);
2743 goto out;
2746 status = check_name(conn, smb_fname->base_name);
2747 if (!NT_STATUS_IS_OK(status)) {
2748 TALLOC_FREE(dir_hnd);
2749 TALLOC_FREE(frame);
2750 TALLOC_FREE(talloced);
2751 goto out;
2754 status = do_unlink(conn, req, smb_fname, dirtype);
2755 if (!NT_STATUS_IS_OK(status)) {
2756 TALLOC_FREE(frame);
2757 TALLOC_FREE(talloced);
2758 continue;
2761 count++;
2762 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2763 smb_fname->base_name));
2765 TALLOC_FREE(frame);
2766 TALLOC_FREE(talloced);
2768 TALLOC_FREE(dir_hnd);
2771 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2772 status = map_nt_error_from_unix(errno);
2775 out:
2776 TALLOC_FREE(fname_dir);
2777 TALLOC_FREE(fname_mask);
2778 return status;
2781 /****************************************************************************
2782 Reply to a unlink
2783 ****************************************************************************/
2785 void reply_unlink(struct smb_request *req)
2787 connection_struct *conn = req->conn;
2788 char *name = NULL;
2789 struct smb_filename *smb_fname = NULL;
2790 uint32 dirtype;
2791 NTSTATUS status;
2792 bool path_contains_wcard = False;
2793 TALLOC_CTX *ctx = talloc_tos();
2795 START_PROFILE(SMBunlink);
2797 if (req->wct < 1) {
2798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2799 goto out;
2802 dirtype = SVAL(req->vwv+0, 0);
2804 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2805 STR_TERMINATE, &status,
2806 &path_contains_wcard);
2807 if (!NT_STATUS_IS_OK(status)) {
2808 reply_nterror(req, status);
2809 goto out;
2812 status = filename_convert(ctx, conn,
2813 req->flags2 & FLAGS2_DFS_PATHNAMES,
2814 name,
2815 UCF_COND_ALLOW_WCARD_LCOMP,
2816 &path_contains_wcard,
2817 &smb_fname);
2818 if (!NT_STATUS_IS_OK(status)) {
2819 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2820 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2821 ERRSRV, ERRbadpath);
2822 goto out;
2824 reply_nterror(req, status);
2825 goto out;
2828 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2830 status = unlink_internals(conn, req, dirtype, smb_fname,
2831 path_contains_wcard);
2832 if (!NT_STATUS_IS_OK(status)) {
2833 if (open_was_deferred(req->sconn, req->mid)) {
2834 /* We have re-scheduled this call. */
2835 goto out;
2837 reply_nterror(req, status);
2838 goto out;
2841 reply_outbuf(req, 0, 0);
2842 out:
2843 TALLOC_FREE(smb_fname);
2844 END_PROFILE(SMBunlink);
2845 return;
2848 /****************************************************************************
2849 Fail for readbraw.
2850 ****************************************************************************/
2852 static void fail_readraw(void)
2854 const char *errstr = talloc_asprintf(talloc_tos(),
2855 "FAIL ! reply_readbraw: socket write fail (%s)",
2856 strerror(errno));
2857 if (!errstr) {
2858 errstr = "";
2860 exit_server_cleanly(errstr);
2863 /****************************************************************************
2864 Fake (read/write) sendfile. Returns -1 on read or write fail.
2865 ****************************************************************************/
2867 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2869 size_t bufsize;
2870 size_t tosend = nread;
2871 char *buf;
2873 if (nread == 0) {
2874 return 0;
2877 bufsize = MIN(nread, 65536);
2879 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2880 return -1;
2883 while (tosend > 0) {
2884 ssize_t ret;
2885 size_t cur_read;
2887 if (tosend > bufsize) {
2888 cur_read = bufsize;
2889 } else {
2890 cur_read = tosend;
2892 ret = read_file(fsp,buf,startpos,cur_read);
2893 if (ret == -1) {
2894 SAFE_FREE(buf);
2895 return -1;
2898 /* If we had a short read, fill with zeros. */
2899 if (ret < cur_read) {
2900 memset(buf + ret, '\0', cur_read - ret);
2903 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2904 != cur_read) {
2905 char addr[INET6_ADDRSTRLEN];
2907 * Try and give an error message saying what
2908 * client failed.
2910 DEBUG(0, ("write_data failed for client %s. "
2911 "Error %s\n",
2912 get_peer_addr(fsp->conn->sconn->sock, addr,
2913 sizeof(addr)),
2914 strerror(errno)));
2915 SAFE_FREE(buf);
2916 return -1;
2918 tosend -= cur_read;
2919 startpos += cur_read;
2922 SAFE_FREE(buf);
2923 return (ssize_t)nread;
2926 /****************************************************************************
2927 Deal with the case of sendfile reading less bytes from the file than
2928 requested. Fill with zeros (all we can do).
2929 ****************************************************************************/
2931 void sendfile_short_send(files_struct *fsp,
2932 ssize_t nread,
2933 size_t headersize,
2934 size_t smb_maxcnt)
2936 #define SHORT_SEND_BUFSIZE 1024
2937 if (nread < headersize) {
2938 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2939 "header for file %s (%s). Terminating\n",
2940 fsp_str_dbg(fsp), strerror(errno)));
2941 exit_server_cleanly("sendfile_short_send failed");
2944 nread -= headersize;
2946 if (nread < smb_maxcnt) {
2947 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2948 if (!buf) {
2949 exit_server_cleanly("sendfile_short_send: "
2950 "malloc failed");
2953 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2954 "with zeros !\n", fsp_str_dbg(fsp)));
2956 while (nread < smb_maxcnt) {
2958 * We asked for the real file size and told sendfile
2959 * to not go beyond the end of the file. But it can
2960 * happen that in between our fstat call and the
2961 * sendfile call the file was truncated. This is very
2962 * bad because we have already announced the larger
2963 * number of bytes to the client.
2965 * The best we can do now is to send 0-bytes, just as
2966 * a read from a hole in a sparse file would do.
2968 * This should happen rarely enough that I don't care
2969 * about efficiency here :-)
2971 size_t to_write;
2973 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2974 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2975 != to_write) {
2976 char addr[INET6_ADDRSTRLEN];
2978 * Try and give an error message saying what
2979 * client failed.
2981 DEBUG(0, ("write_data failed for client %s. "
2982 "Error %s\n",
2983 get_peer_addr(
2984 fsp->conn->sconn->sock, addr,
2985 sizeof(addr)),
2986 strerror(errno)));
2987 exit_server_cleanly("sendfile_short_send: "
2988 "write_data failed");
2990 nread += to_write;
2992 SAFE_FREE(buf);
2996 /****************************************************************************
2997 Return a readbraw error (4 bytes of zero).
2998 ****************************************************************************/
3000 static void reply_readbraw_error(struct smbd_server_connection *sconn)
3002 char header[4];
3004 SIVAL(header,0,0);
3006 smbd_lock_socket(sconn);
3007 if (write_data(sconn->sock,header,4) != 4) {
3008 char addr[INET6_ADDRSTRLEN];
3010 * Try and give an error message saying what
3011 * client failed.
3013 DEBUG(0, ("write_data failed for client %s. "
3014 "Error %s\n",
3015 get_peer_addr(sconn->sock, addr, sizeof(addr)),
3016 strerror(errno)));
3018 fail_readraw();
3020 smbd_unlock_socket(sconn);
3023 /****************************************************************************
3024 Use sendfile in readbraw.
3025 ****************************************************************************/
3027 static void send_file_readbraw(connection_struct *conn,
3028 struct smb_request *req,
3029 files_struct *fsp,
3030 SMB_OFF_T startpos,
3031 size_t nread,
3032 ssize_t mincount)
3034 struct smbd_server_connection *sconn = req->sconn;
3035 char *outbuf = NULL;
3036 ssize_t ret=0;
3039 * We can only use sendfile on a non-chained packet
3040 * but we can use on a non-oplocked file. tridge proved this
3041 * on a train in Germany :-). JRA.
3042 * reply_readbraw has already checked the length.
3045 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3046 (fsp->wcp == NULL) &&
3047 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3048 ssize_t sendfile_read = -1;
3049 char header[4];
3050 DATA_BLOB header_blob;
3052 _smb_setlen(header,nread);
3053 header_blob = data_blob_const(header, 4);
3055 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3056 &header_blob, startpos,
3057 nread);
3058 if (sendfile_read == -1) {
3059 /* Returning ENOSYS means no data at all was sent.
3060 * Do this as a normal read. */
3061 if (errno == ENOSYS) {
3062 goto normal_readbraw;
3066 * Special hack for broken Linux with no working sendfile. If we
3067 * return EINTR we sent the header but not the rest of the data.
3068 * Fake this up by doing read/write calls.
3070 if (errno == EINTR) {
3071 /* Ensure we don't do this again. */
3072 set_use_sendfile(SNUM(conn), False);
3073 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3075 if (fake_sendfile(fsp, startpos, nread) == -1) {
3076 DEBUG(0,("send_file_readbraw: "
3077 "fake_sendfile failed for "
3078 "file %s (%s).\n",
3079 fsp_str_dbg(fsp),
3080 strerror(errno)));
3081 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3083 return;
3086 DEBUG(0,("send_file_readbraw: sendfile failed for "
3087 "file %s (%s). Terminating\n",
3088 fsp_str_dbg(fsp), strerror(errno)));
3089 exit_server_cleanly("send_file_readbraw sendfile failed");
3090 } else if (sendfile_read == 0) {
3092 * Some sendfile implementations return 0 to indicate
3093 * that there was a short read, but nothing was
3094 * actually written to the socket. In this case,
3095 * fallback to the normal read path so the header gets
3096 * the correct byte count.
3098 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3099 "bytes falling back to the normal read: "
3100 "%s\n", fsp_str_dbg(fsp)));
3101 goto normal_readbraw;
3104 /* Deal with possible short send. */
3105 if (sendfile_read != 4+nread) {
3106 sendfile_short_send(fsp, sendfile_read, 4, nread);
3108 return;
3111 normal_readbraw:
3113 outbuf = talloc_array(NULL, char, nread+4);
3114 if (!outbuf) {
3115 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3116 (unsigned)(nread+4)));
3117 reply_readbraw_error(sconn);
3118 return;
3121 if (nread > 0) {
3122 ret = read_file(fsp,outbuf+4,startpos,nread);
3123 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3124 if (ret < mincount)
3125 ret = 0;
3126 #else
3127 if (ret < nread)
3128 ret = 0;
3129 #endif
3132 _smb_setlen(outbuf,ret);
3133 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3134 char addr[INET6_ADDRSTRLEN];
3136 * Try and give an error message saying what
3137 * client failed.
3139 DEBUG(0, ("write_data failed for client %s. "
3140 "Error %s\n",
3141 get_peer_addr(fsp->conn->sconn->sock, addr,
3142 sizeof(addr)),
3143 strerror(errno)));
3145 fail_readraw();
3148 TALLOC_FREE(outbuf);
3151 /****************************************************************************
3152 Reply to a readbraw (core+ protocol).
3153 ****************************************************************************/
3155 void reply_readbraw(struct smb_request *req)
3157 connection_struct *conn = req->conn;
3158 struct smbd_server_connection *sconn = req->sconn;
3159 ssize_t maxcount,mincount;
3160 size_t nread = 0;
3161 SMB_OFF_T startpos;
3162 files_struct *fsp;
3163 struct lock_struct lock;
3164 SMB_OFF_T size = 0;
3166 START_PROFILE(SMBreadbraw);
3168 if (srv_is_signing_active(sconn) ||
3169 is_encrypted_packet(sconn, req->inbuf)) {
3170 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3171 "raw reads/writes are disallowed.");
3174 if (req->wct < 8) {
3175 reply_readbraw_error(sconn);
3176 END_PROFILE(SMBreadbraw);
3177 return;
3180 if (sconn->smb1.echo_handler.trusted_fde) {
3181 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3182 "'async smb echo handler = yes'\n"));
3183 reply_readbraw_error(sconn);
3184 END_PROFILE(SMBreadbraw);
3185 return;
3189 * Special check if an oplock break has been issued
3190 * and the readraw request croses on the wire, we must
3191 * return a zero length response here.
3194 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3197 * We have to do a check_fsp by hand here, as
3198 * we must always return 4 zero bytes on error,
3199 * not a NTSTATUS.
3202 if (!fsp || !conn || conn != fsp->conn ||
3203 req->vuid != fsp->vuid ||
3204 fsp->is_directory || fsp->fh->fd == -1) {
3206 * fsp could be NULL here so use the value from the packet. JRA.
3208 DEBUG(3,("reply_readbraw: fnum %d not valid "
3209 "- cache prime?\n",
3210 (int)SVAL(req->vwv+0, 0)));
3211 reply_readbraw_error(sconn);
3212 END_PROFILE(SMBreadbraw);
3213 return;
3216 /* Do a "by hand" version of CHECK_READ. */
3217 if (!(fsp->can_read ||
3218 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3219 (fsp->access_mask & FILE_EXECUTE)))) {
3220 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3221 (int)SVAL(req->vwv+0, 0)));
3222 reply_readbraw_error(sconn);
3223 END_PROFILE(SMBreadbraw);
3224 return;
3227 flush_write_cache(fsp, READRAW_FLUSH);
3229 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3230 if(req->wct == 10) {
3232 * This is a large offset (64 bit) read.
3234 #ifdef LARGE_SMB_OFF_T
3236 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3238 #else /* !LARGE_SMB_OFF_T */
3241 * Ensure we haven't been sent a >32 bit offset.
3244 if(IVAL(req->vwv+8, 0) != 0) {
3245 DEBUG(0,("reply_readbraw: large offset "
3246 "(%x << 32) used and we don't support "
3247 "64 bit offsets.\n",
3248 (unsigned int)IVAL(req->vwv+8, 0) ));
3249 reply_readbraw_error(sconn);
3250 END_PROFILE(SMBreadbraw);
3251 return;
3254 #endif /* LARGE_SMB_OFF_T */
3256 if(startpos < 0) {
3257 DEBUG(0,("reply_readbraw: negative 64 bit "
3258 "readraw offset (%.0f) !\n",
3259 (double)startpos ));
3260 reply_readbraw_error(sconn);
3261 END_PROFILE(SMBreadbraw);
3262 return;
3266 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3267 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3269 /* ensure we don't overrun the packet size */
3270 maxcount = MIN(65535,maxcount);
3272 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3273 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3274 &lock);
3276 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3277 reply_readbraw_error(sconn);
3278 END_PROFILE(SMBreadbraw);
3279 return;
3282 if (fsp_stat(fsp) == 0) {
3283 size = fsp->fsp_name->st.st_ex_size;
3286 if (startpos >= size) {
3287 nread = 0;
3288 } else {
3289 nread = MIN(maxcount,(size - startpos));
3292 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3293 if (nread < mincount)
3294 nread = 0;
3295 #endif
3297 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3298 "min=%lu nread=%lu\n",
3299 fsp->fnum, (double)startpos,
3300 (unsigned long)maxcount,
3301 (unsigned long)mincount,
3302 (unsigned long)nread ) );
3304 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3306 DEBUG(5,("reply_readbraw finished\n"));
3308 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3310 END_PROFILE(SMBreadbraw);
3311 return;
3314 #undef DBGC_CLASS
3315 #define DBGC_CLASS DBGC_LOCKING
3317 /****************************************************************************
3318 Reply to a lockread (core+ protocol).
3319 ****************************************************************************/
3321 void reply_lockread(struct smb_request *req)
3323 connection_struct *conn = req->conn;
3324 ssize_t nread = -1;
3325 char *data;
3326 SMB_OFF_T startpos;
3327 size_t numtoread;
3328 NTSTATUS status;
3329 files_struct *fsp;
3330 struct byte_range_lock *br_lck = NULL;
3331 char *p = NULL;
3332 struct smbd_server_connection *sconn = req->sconn;
3334 START_PROFILE(SMBlockread);
3336 if (req->wct < 5) {
3337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3338 END_PROFILE(SMBlockread);
3339 return;
3342 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3344 if (!check_fsp(conn, req, fsp)) {
3345 END_PROFILE(SMBlockread);
3346 return;
3349 if (!CHECK_READ(fsp,req)) {
3350 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3351 END_PROFILE(SMBlockread);
3352 return;
3355 numtoread = SVAL(req->vwv+1, 0);
3356 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3358 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3360 reply_outbuf(req, 5, numtoread + 3);
3362 data = smb_buf(req->outbuf) + 3;
3365 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3366 * protocol request that predates the read/write lock concept.
3367 * Thus instead of asking for a read lock here we need to ask
3368 * for a write lock. JRA.
3369 * Note that the requested lock size is unaffected by max_recv.
3372 br_lck = do_lock(req->sconn->msg_ctx,
3373 fsp,
3374 (uint64_t)req->smbpid,
3375 (uint64_t)numtoread,
3376 (uint64_t)startpos,
3377 WRITE_LOCK,
3378 WINDOWS_LOCK,
3379 False, /* Non-blocking lock. */
3380 &status,
3381 NULL,
3382 NULL);
3383 TALLOC_FREE(br_lck);
3385 if (NT_STATUS_V(status)) {
3386 reply_nterror(req, status);
3387 END_PROFILE(SMBlockread);
3388 return;
3392 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3395 if (numtoread > sconn->smb1.negprot.max_recv) {
3396 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3397 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3398 (unsigned int)numtoread,
3399 (unsigned int)sconn->smb1.negprot.max_recv));
3400 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3402 nread = read_file(fsp,data,startpos,numtoread);
3404 if (nread < 0) {
3405 reply_nterror(req, map_nt_error_from_unix(errno));
3406 END_PROFILE(SMBlockread);
3407 return;
3410 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3412 SSVAL(req->outbuf,smb_vwv0,nread);
3413 SSVAL(req->outbuf,smb_vwv5,nread+3);
3414 p = smb_buf(req->outbuf);
3415 SCVAL(p,0,0); /* pad byte. */
3416 SSVAL(p,1,nread);
3418 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3419 fsp->fnum, (int)numtoread, (int)nread));
3421 END_PROFILE(SMBlockread);
3422 return;
3425 #undef DBGC_CLASS
3426 #define DBGC_CLASS DBGC_ALL
3428 /****************************************************************************
3429 Reply to a read.
3430 ****************************************************************************/
3432 void reply_read(struct smb_request *req)
3434 connection_struct *conn = req->conn;
3435 size_t numtoread;
3436 ssize_t nread = 0;
3437 char *data;
3438 SMB_OFF_T startpos;
3439 int outsize = 0;
3440 files_struct *fsp;
3441 struct lock_struct lock;
3442 struct smbd_server_connection *sconn = req->sconn;
3444 START_PROFILE(SMBread);
3446 if (req->wct < 3) {
3447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3448 END_PROFILE(SMBread);
3449 return;
3452 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3454 if (!check_fsp(conn, req, fsp)) {
3455 END_PROFILE(SMBread);
3456 return;
3459 if (!CHECK_READ(fsp,req)) {
3460 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3461 END_PROFILE(SMBread);
3462 return;
3465 numtoread = SVAL(req->vwv+1, 0);
3466 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3468 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3471 * The requested read size cannot be greater than max_recv. JRA.
3473 if (numtoread > sconn->smb1.negprot.max_recv) {
3474 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3475 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3476 (unsigned int)numtoread,
3477 (unsigned int)sconn->smb1.negprot.max_recv));
3478 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3481 reply_outbuf(req, 5, numtoread+3);
3483 data = smb_buf(req->outbuf) + 3;
3485 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3486 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3487 &lock);
3489 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3490 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3491 END_PROFILE(SMBread);
3492 return;
3495 if (numtoread > 0)
3496 nread = read_file(fsp,data,startpos,numtoread);
3498 if (nread < 0) {
3499 reply_nterror(req, map_nt_error_from_unix(errno));
3500 goto strict_unlock;
3503 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3505 SSVAL(req->outbuf,smb_vwv0,nread);
3506 SSVAL(req->outbuf,smb_vwv5,nread+3);
3507 SCVAL(smb_buf(req->outbuf),0,1);
3508 SSVAL(smb_buf(req->outbuf),1,nread);
3510 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3511 fsp->fnum, (int)numtoread, (int)nread ) );
3513 strict_unlock:
3514 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3516 END_PROFILE(SMBread);
3517 return;
3520 /****************************************************************************
3521 Setup readX header.
3522 ****************************************************************************/
3524 static int setup_readX_header(struct smb_request *req, char *outbuf,
3525 size_t smb_maxcnt)
3527 int outsize;
3528 char *data;
3530 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3531 data = smb_buf(outbuf);
3533 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3535 SCVAL(outbuf,smb_vwv0,0xFF);
3536 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3537 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3538 SSVAL(outbuf,smb_vwv6,
3539 req_wct_ofs(req)
3540 + 1 /* the wct field */
3541 + 12 * sizeof(uint16_t) /* vwv */
3542 + 2); /* the buflen field */
3543 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3544 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3545 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3546 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3547 return outsize;
3550 /****************************************************************************
3551 Reply to a read and X - possibly using sendfile.
3552 ****************************************************************************/
3554 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3555 files_struct *fsp, SMB_OFF_T startpos,
3556 size_t smb_maxcnt)
3558 ssize_t nread = -1;
3559 struct lock_struct lock;
3560 int saved_errno = 0;
3562 if(fsp_stat(fsp) == -1) {
3563 reply_nterror(req, map_nt_error_from_unix(errno));
3564 return;
3567 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3568 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3569 &lock);
3571 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3572 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3573 return;
3576 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3577 (startpos > fsp->fsp_name->st.st_ex_size)
3578 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3580 * We already know that we would do a short read, so don't
3581 * try the sendfile() path.
3583 goto nosendfile_read;
3587 * We can only use sendfile on a non-chained packet
3588 * but we can use on a non-oplocked file. tridge proved this
3589 * on a train in Germany :-). JRA.
3592 if (!req_is_in_chain(req) &&
3593 !is_encrypted_packet(req->sconn, req->inbuf) &&
3594 (fsp->base_fsp == NULL) &&
3595 (fsp->wcp == NULL) &&
3596 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3597 uint8 headerbuf[smb_size + 12 * 2];
3598 DATA_BLOB header;
3601 * Set up the packet header before send. We
3602 * assume here the sendfile will work (get the
3603 * correct amount of data).
3606 header = data_blob_const(headerbuf, sizeof(headerbuf));
3608 construct_reply_common_req(req, (char *)headerbuf);
3609 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3611 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3612 startpos, smb_maxcnt);
3613 if (nread == -1) {
3614 /* Returning ENOSYS means no data at all was sent.
3615 Do this as a normal read. */
3616 if (errno == ENOSYS) {
3617 goto normal_read;
3621 * Special hack for broken Linux with no working sendfile. If we
3622 * return EINTR we sent the header but not the rest of the data.
3623 * Fake this up by doing read/write calls.
3626 if (errno == EINTR) {
3627 /* Ensure we don't do this again. */
3628 set_use_sendfile(SNUM(conn), False);
3629 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3630 nread = fake_sendfile(fsp, startpos,
3631 smb_maxcnt);
3632 if (nread == -1) {
3633 DEBUG(0,("send_file_readX: "
3634 "fake_sendfile failed for "
3635 "file %s (%s).\n",
3636 fsp_str_dbg(fsp),
3637 strerror(errno)));
3638 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3640 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3641 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3642 /* No outbuf here means successful sendfile. */
3643 goto strict_unlock;
3646 DEBUG(0,("send_file_readX: sendfile failed for file "
3647 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3648 strerror(errno)));
3649 exit_server_cleanly("send_file_readX sendfile failed");
3650 } else if (nread == 0) {
3652 * Some sendfile implementations return 0 to indicate
3653 * that there was a short read, but nothing was
3654 * actually written to the socket. In this case,
3655 * fallback to the normal read path so the header gets
3656 * the correct byte count.
3658 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3659 "falling back to the normal read: %s\n",
3660 fsp_str_dbg(fsp)));
3661 goto normal_read;
3664 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3665 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3667 /* Deal with possible short send. */
3668 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3669 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3671 /* No outbuf here means successful sendfile. */
3672 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3673 SMB_PERFCOUNT_END(&req->pcd);
3674 goto strict_unlock;
3677 normal_read:
3679 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3680 uint8 headerbuf[smb_size + 2*12];
3682 construct_reply_common_req(req, (char *)headerbuf);
3683 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3685 /* Send out the header. */
3686 if (write_data(req->sconn->sock, (char *)headerbuf,
3687 sizeof(headerbuf)) != sizeof(headerbuf)) {
3689 char addr[INET6_ADDRSTRLEN];
3691 * Try and give an error message saying what
3692 * client failed.
3694 DEBUG(0, ("write_data failed for client %s. "
3695 "Error %s\n",
3696 get_peer_addr(req->sconn->sock, addr,
3697 sizeof(addr)),
3698 strerror(errno)));
3700 DEBUG(0,("send_file_readX: write_data failed for file "
3701 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3702 strerror(errno)));
3703 exit_server_cleanly("send_file_readX sendfile failed");
3705 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3706 if (nread == -1) {
3707 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3708 "file %s (%s).\n", fsp_str_dbg(fsp),
3709 strerror(errno)));
3710 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3712 goto strict_unlock;
3715 nosendfile_read:
3717 reply_outbuf(req, 12, smb_maxcnt);
3719 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3720 saved_errno = errno;
3722 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3724 if (nread < 0) {
3725 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3726 return;
3729 setup_readX_header(req, (char *)req->outbuf, nread);
3731 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3732 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3734 chain_reply(req);
3735 return;
3737 strict_unlock:
3738 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3739 TALLOC_FREE(req->outbuf);
3740 return;
3743 /****************************************************************************
3744 Reply to a read and X.
3745 ****************************************************************************/
3747 void reply_read_and_X(struct smb_request *req)
3749 struct smbd_server_connection *sconn = req->sconn;
3750 connection_struct *conn = req->conn;
3751 files_struct *fsp;
3752 SMB_OFF_T startpos;
3753 size_t smb_maxcnt;
3754 bool big_readX = False;
3755 #if 0
3756 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3757 #endif
3759 START_PROFILE(SMBreadX);
3761 if ((req->wct != 10) && (req->wct != 12)) {
3762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3763 return;
3766 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3767 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3768 smb_maxcnt = SVAL(req->vwv+5, 0);
3770 /* If it's an IPC, pass off the pipe handler. */
3771 if (IS_IPC(conn)) {
3772 reply_pipe_read_and_X(req);
3773 END_PROFILE(SMBreadX);
3774 return;
3777 if (!check_fsp(conn, req, fsp)) {
3778 END_PROFILE(SMBreadX);
3779 return;
3782 if (!CHECK_READ(fsp,req)) {
3783 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3784 END_PROFILE(SMBreadX);
3785 return;
3788 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3789 (get_remote_arch() == RA_SAMBA)) {
3791 * This is Samba only behavior (up to Samba 3.6)!
3793 * Windows 2008 R2 ignores the upper_size,
3794 * so we do unless unix extentions are active
3795 * or "smbclient" is talking to us.
3797 size_t upper_size = SVAL(req->vwv+7, 0);
3798 smb_maxcnt |= (upper_size<<16);
3799 if (upper_size > 1) {
3800 /* Can't do this on a chained packet. */
3801 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3802 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3803 END_PROFILE(SMBreadX);
3804 return;
3806 /* We currently don't do this on signed or sealed data. */
3807 if (srv_is_signing_active(req->sconn) ||
3808 is_encrypted_packet(req->sconn, req->inbuf)) {
3809 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3810 END_PROFILE(SMBreadX);
3811 return;
3813 /* Is there room in the reply for this data ? */
3814 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3815 reply_nterror(req,
3816 NT_STATUS_INVALID_PARAMETER);
3817 END_PROFILE(SMBreadX);
3818 return;
3820 big_readX = True;
3824 if (req->wct == 12) {
3825 #ifdef LARGE_SMB_OFF_T
3827 * This is a large offset (64 bit) read.
3829 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3831 #else /* !LARGE_SMB_OFF_T */
3834 * Ensure we haven't been sent a >32 bit offset.
3837 if(IVAL(req->vwv+10, 0) != 0) {
3838 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3839 "used and we don't support 64 bit offsets.\n",
3840 (unsigned int)IVAL(req->vwv+10, 0) ));
3841 END_PROFILE(SMBreadX);
3842 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3843 return;
3846 #endif /* LARGE_SMB_OFF_T */
3850 if (!big_readX) {
3851 NTSTATUS status = schedule_aio_read_and_X(conn,
3852 req,
3853 fsp,
3854 startpos,
3855 smb_maxcnt);
3856 if (NT_STATUS_IS_OK(status)) {
3857 /* Read scheduled - we're done. */
3858 goto out;
3860 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3861 /* Real error - report to client. */
3862 END_PROFILE(SMBreadX);
3863 reply_nterror(req, status);
3864 return;
3866 /* NT_STATUS_RETRY - fall back to sync read. */
3869 smbd_lock_socket(req->sconn);
3870 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3871 smbd_unlock_socket(req->sconn);
3873 out:
3874 END_PROFILE(SMBreadX);
3875 return;
3878 /****************************************************************************
3879 Error replies to writebraw must have smb_wct == 1. Fix this up.
3880 ****************************************************************************/
3882 void error_to_writebrawerr(struct smb_request *req)
3884 uint8 *old_outbuf = req->outbuf;
3886 reply_outbuf(req, 1, 0);
3888 memcpy(req->outbuf, old_outbuf, smb_size);
3889 TALLOC_FREE(old_outbuf);
3892 /****************************************************************************
3893 Read 4 bytes of a smb packet and return the smb length of the packet.
3894 Store the result in the buffer. This version of the function will
3895 never return a session keepalive (length of zero).
3896 Timeout is in milliseconds.
3897 ****************************************************************************/
3899 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3900 size_t *len)
3902 uint8_t msgtype = NBSSkeepalive;
3904 while (msgtype == NBSSkeepalive) {
3905 NTSTATUS status;
3907 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3908 len);
3909 if (!NT_STATUS_IS_OK(status)) {
3910 char addr[INET6_ADDRSTRLEN];
3911 /* Try and give an error message
3912 * saying what client failed. */
3913 DEBUG(0, ("read_fd_with_timeout failed for "
3914 "client %s read error = %s.\n",
3915 get_peer_addr(fd,addr,sizeof(addr)),
3916 nt_errstr(status)));
3917 return status;
3920 msgtype = CVAL(inbuf, 0);
3923 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3924 (unsigned long)len));
3926 return NT_STATUS_OK;
3929 /****************************************************************************
3930 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3931 ****************************************************************************/
3933 void reply_writebraw(struct smb_request *req)
3935 connection_struct *conn = req->conn;
3936 char *buf = NULL;
3937 ssize_t nwritten=0;
3938 ssize_t total_written=0;
3939 size_t numtowrite=0;
3940 size_t tcount;
3941 SMB_OFF_T startpos;
3942 const char *data=NULL;
3943 bool write_through;
3944 files_struct *fsp;
3945 struct lock_struct lock;
3946 NTSTATUS status;
3948 START_PROFILE(SMBwritebraw);
3951 * If we ever reply with an error, it must have the SMB command
3952 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3953 * we're finished.
3955 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3957 if (srv_is_signing_active(req->sconn)) {
3958 END_PROFILE(SMBwritebraw);
3959 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3960 "raw reads/writes are disallowed.");
3963 if (req->wct < 12) {
3964 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3965 error_to_writebrawerr(req);
3966 END_PROFILE(SMBwritebraw);
3967 return;
3970 if (req->sconn->smb1.echo_handler.trusted_fde) {
3971 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3972 "'async smb echo handler = yes'\n"));
3973 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3974 error_to_writebrawerr(req);
3975 END_PROFILE(SMBwritebraw);
3976 return;
3979 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3980 if (!check_fsp(conn, req, fsp)) {
3981 error_to_writebrawerr(req);
3982 END_PROFILE(SMBwritebraw);
3983 return;
3986 if (!CHECK_WRITE(fsp)) {
3987 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3988 error_to_writebrawerr(req);
3989 END_PROFILE(SMBwritebraw);
3990 return;
3993 tcount = IVAL(req->vwv+1, 0);
3994 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3995 write_through = BITSETW(req->vwv+7,0);
3997 /* We have to deal with slightly different formats depending
3998 on whether we are using the core+ or lanman1.0 protocol */
4000 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4001 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4002 data = smb_buf_const(req->inbuf);
4003 } else {
4004 numtowrite = SVAL(req->vwv+10, 0);
4005 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4008 /* Ensure we don't write bytes past the end of this packet. */
4009 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4011 error_to_writebrawerr(req);
4012 END_PROFILE(SMBwritebraw);
4013 return;
4016 if (!fsp->print_file) {
4017 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4018 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4019 &lock);
4021 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4022 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4023 error_to_writebrawerr(req);
4024 END_PROFILE(SMBwritebraw);
4025 return;
4029 if (numtowrite>0) {
4030 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4033 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4034 "wrote=%d sync=%d\n",
4035 fsp->fnum, (double)startpos, (int)numtowrite,
4036 (int)nwritten, (int)write_through));
4038 if (nwritten < (ssize_t)numtowrite) {
4039 reply_nterror(req, NT_STATUS_DISK_FULL);
4040 error_to_writebrawerr(req);
4041 goto strict_unlock;
4044 total_written = nwritten;
4046 /* Allocate a buffer of 64k + length. */
4047 buf = talloc_array(NULL, char, 65540);
4048 if (!buf) {
4049 reply_nterror(req, NT_STATUS_NO_MEMORY);
4050 error_to_writebrawerr(req);
4051 goto strict_unlock;
4054 /* Return a SMBwritebraw message to the redirector to tell
4055 * it to send more bytes */
4057 memcpy(buf, req->inbuf, smb_size);
4058 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4059 SCVAL(buf,smb_com,SMBwritebraw);
4060 SSVALS(buf,smb_vwv0,0xFFFF);
4061 show_msg(buf);
4062 if (!srv_send_smb(req->sconn,
4063 buf,
4064 false, 0, /* no signing */
4065 IS_CONN_ENCRYPTED(conn),
4066 &req->pcd)) {
4067 exit_server_cleanly("reply_writebraw: srv_send_smb "
4068 "failed.");
4071 /* Now read the raw data into the buffer and write it */
4072 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4073 &numtowrite);
4074 if (!NT_STATUS_IS_OK(status)) {
4075 exit_server_cleanly("secondary writebraw failed");
4078 /* Set up outbuf to return the correct size */
4079 reply_outbuf(req, 1, 0);
4081 if (numtowrite != 0) {
4083 if (numtowrite > 0xFFFF) {
4084 DEBUG(0,("reply_writebraw: Oversize secondary write "
4085 "raw requested (%u). Terminating\n",
4086 (unsigned int)numtowrite ));
4087 exit_server_cleanly("secondary writebraw failed");
4090 if (tcount > nwritten+numtowrite) {
4091 DEBUG(3,("reply_writebraw: Client overestimated the "
4092 "write %d %d %d\n",
4093 (int)tcount,(int)nwritten,(int)numtowrite));
4096 status = read_data(req->sconn->sock, buf+4, numtowrite);
4098 if (!NT_STATUS_IS_OK(status)) {
4099 char addr[INET6_ADDRSTRLEN];
4100 /* Try and give an error message
4101 * saying what client failed. */
4102 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4103 "raw read failed (%s) for client %s. "
4104 "Terminating\n", nt_errstr(status),
4105 get_peer_addr(req->sconn->sock, addr,
4106 sizeof(addr))));
4107 exit_server_cleanly("secondary writebraw failed");
4110 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4111 if (nwritten == -1) {
4112 TALLOC_FREE(buf);
4113 reply_nterror(req, map_nt_error_from_unix(errno));
4114 error_to_writebrawerr(req);
4115 goto strict_unlock;
4118 if (nwritten < (ssize_t)numtowrite) {
4119 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4120 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4123 if (nwritten > 0) {
4124 total_written += nwritten;
4128 TALLOC_FREE(buf);
4129 SSVAL(req->outbuf,smb_vwv0,total_written);
4131 status = sync_file(conn, fsp, write_through);
4132 if (!NT_STATUS_IS_OK(status)) {
4133 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4134 fsp_str_dbg(fsp), nt_errstr(status)));
4135 reply_nterror(req, status);
4136 error_to_writebrawerr(req);
4137 goto strict_unlock;
4140 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4141 "wrote=%d\n",
4142 fsp->fnum, (double)startpos, (int)numtowrite,
4143 (int)total_written));
4145 if (!fsp->print_file) {
4146 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4149 /* We won't return a status if write through is not selected - this
4150 * follows what WfWg does */
4151 END_PROFILE(SMBwritebraw);
4153 if (!write_through && total_written==tcount) {
4155 #if RABBIT_PELLET_FIX
4157 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4158 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4159 * JRA.
4161 if (!send_keepalive(req->sconn->sock)) {
4162 exit_server_cleanly("reply_writebraw: send of "
4163 "keepalive failed");
4165 #endif
4166 TALLOC_FREE(req->outbuf);
4168 return;
4170 strict_unlock:
4171 if (!fsp->print_file) {
4172 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4175 END_PROFILE(SMBwritebraw);
4176 return;
4179 #undef DBGC_CLASS
4180 #define DBGC_CLASS DBGC_LOCKING
4182 /****************************************************************************
4183 Reply to a writeunlock (core+).
4184 ****************************************************************************/
4186 void reply_writeunlock(struct smb_request *req)
4188 connection_struct *conn = req->conn;
4189 ssize_t nwritten = -1;
4190 size_t numtowrite;
4191 SMB_OFF_T startpos;
4192 const char *data;
4193 NTSTATUS status = NT_STATUS_OK;
4194 files_struct *fsp;
4195 struct lock_struct lock;
4196 int saved_errno = 0;
4198 START_PROFILE(SMBwriteunlock);
4200 if (req->wct < 5) {
4201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4202 END_PROFILE(SMBwriteunlock);
4203 return;
4206 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4208 if (!check_fsp(conn, req, fsp)) {
4209 END_PROFILE(SMBwriteunlock);
4210 return;
4213 if (!CHECK_WRITE(fsp)) {
4214 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4215 END_PROFILE(SMBwriteunlock);
4216 return;
4219 numtowrite = SVAL(req->vwv+1, 0);
4220 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4221 data = (const char *)req->buf + 3;
4223 if (!fsp->print_file && numtowrite > 0) {
4224 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4225 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4226 &lock);
4228 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4229 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4230 END_PROFILE(SMBwriteunlock);
4231 return;
4235 /* The special X/Open SMB protocol handling of
4236 zero length writes is *NOT* done for
4237 this call */
4238 if(numtowrite == 0) {
4239 nwritten = 0;
4240 } else {
4241 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4242 saved_errno = errno;
4245 status = sync_file(conn, fsp, False /* write through */);
4246 if (!NT_STATUS_IS_OK(status)) {
4247 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4248 fsp_str_dbg(fsp), nt_errstr(status)));
4249 reply_nterror(req, status);
4250 goto strict_unlock;
4253 if(nwritten < 0) {
4254 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4255 goto strict_unlock;
4258 if((nwritten < numtowrite) && (numtowrite != 0)) {
4259 reply_nterror(req, NT_STATUS_DISK_FULL);
4260 goto strict_unlock;
4263 if (numtowrite && !fsp->print_file) {
4264 status = do_unlock(req->sconn->msg_ctx,
4265 fsp,
4266 (uint64_t)req->smbpid,
4267 (uint64_t)numtowrite,
4268 (uint64_t)startpos,
4269 WINDOWS_LOCK);
4271 if (NT_STATUS_V(status)) {
4272 reply_nterror(req, status);
4273 goto strict_unlock;
4277 reply_outbuf(req, 1, 0);
4279 SSVAL(req->outbuf,smb_vwv0,nwritten);
4281 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4282 fsp->fnum, (int)numtowrite, (int)nwritten));
4284 strict_unlock:
4285 if (numtowrite && !fsp->print_file) {
4286 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4289 END_PROFILE(SMBwriteunlock);
4290 return;
4293 #undef DBGC_CLASS
4294 #define DBGC_CLASS DBGC_ALL
4296 /****************************************************************************
4297 Reply to a write.
4298 ****************************************************************************/
4300 void reply_write(struct smb_request *req)
4302 connection_struct *conn = req->conn;
4303 size_t numtowrite;
4304 ssize_t nwritten = -1;
4305 SMB_OFF_T startpos;
4306 const char *data;
4307 files_struct *fsp;
4308 struct lock_struct lock;
4309 NTSTATUS status;
4310 int saved_errno = 0;
4312 START_PROFILE(SMBwrite);
4314 if (req->wct < 5) {
4315 END_PROFILE(SMBwrite);
4316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4317 return;
4320 /* If it's an IPC, pass off the pipe handler. */
4321 if (IS_IPC(conn)) {
4322 reply_pipe_write(req);
4323 END_PROFILE(SMBwrite);
4324 return;
4327 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4329 if (!check_fsp(conn, req, fsp)) {
4330 END_PROFILE(SMBwrite);
4331 return;
4334 if (!CHECK_WRITE(fsp)) {
4335 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4336 END_PROFILE(SMBwrite);
4337 return;
4340 numtowrite = SVAL(req->vwv+1, 0);
4341 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4342 data = (const char *)req->buf + 3;
4344 if (!fsp->print_file) {
4345 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4346 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4347 &lock);
4349 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4350 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4351 END_PROFILE(SMBwrite);
4352 return;
4357 * X/Open SMB protocol says that if smb_vwv1 is
4358 * zero then the file size should be extended or
4359 * truncated to the size given in smb_vwv[2-3].
4362 if(numtowrite == 0) {
4364 * This is actually an allocate call, and set EOF. JRA.
4366 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4367 if (nwritten < 0) {
4368 reply_nterror(req, NT_STATUS_DISK_FULL);
4369 goto strict_unlock;
4371 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4372 if (nwritten < 0) {
4373 reply_nterror(req, NT_STATUS_DISK_FULL);
4374 goto strict_unlock;
4376 trigger_write_time_update_immediate(fsp);
4377 } else {
4378 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4381 status = sync_file(conn, fsp, False);
4382 if (!NT_STATUS_IS_OK(status)) {
4383 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4384 fsp_str_dbg(fsp), nt_errstr(status)));
4385 reply_nterror(req, status);
4386 goto strict_unlock;
4389 if(nwritten < 0) {
4390 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4391 goto strict_unlock;
4394 if((nwritten == 0) && (numtowrite != 0)) {
4395 reply_nterror(req, NT_STATUS_DISK_FULL);
4396 goto strict_unlock;
4399 reply_outbuf(req, 1, 0);
4401 SSVAL(req->outbuf,smb_vwv0,nwritten);
4403 if (nwritten < (ssize_t)numtowrite) {
4404 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4405 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4408 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4410 strict_unlock:
4411 if (!fsp->print_file) {
4412 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4415 END_PROFILE(SMBwrite);
4416 return;
4419 /****************************************************************************
4420 Ensure a buffer is a valid writeX for recvfile purposes.
4421 ****************************************************************************/
4423 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4424 (2*14) + /* word count (including bcc) */ \
4425 1 /* pad byte */)
4427 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4428 const uint8_t *inbuf)
4430 size_t numtowrite;
4431 connection_struct *conn = NULL;
4432 unsigned int doff = 0;
4433 size_t len = smb_len_large(inbuf);
4435 if (is_encrypted_packet(sconn, inbuf)) {
4436 /* Can't do this on encrypted
4437 * connections. */
4438 return false;
4441 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4442 return false;
4445 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4446 CVAL(inbuf,smb_wct) != 14) {
4447 DEBUG(10,("is_valid_writeX_buffer: chained or "
4448 "invalid word length.\n"));
4449 return false;
4452 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4453 if (conn == NULL) {
4454 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4455 return false;
4457 if (IS_IPC(conn)) {
4458 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4459 return false;
4461 if (IS_PRINT(conn)) {
4462 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4463 return false;
4465 doff = SVAL(inbuf,smb_vwv11);
4467 numtowrite = SVAL(inbuf,smb_vwv10);
4469 if (len > doff && len - doff > 0xFFFF) {
4470 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4473 if (numtowrite == 0) {
4474 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4475 return false;
4478 /* Ensure the sizes match up. */
4479 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4480 /* no pad byte...old smbclient :-( */
4481 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4482 (unsigned int)doff,
4483 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4484 return false;
4487 if (len - doff != numtowrite) {
4488 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4489 "len = %u, doff = %u, numtowrite = %u\n",
4490 (unsigned int)len,
4491 (unsigned int)doff,
4492 (unsigned int)numtowrite ));
4493 return false;
4496 DEBUG(10,("is_valid_writeX_buffer: true "
4497 "len = %u, doff = %u, numtowrite = %u\n",
4498 (unsigned int)len,
4499 (unsigned int)doff,
4500 (unsigned int)numtowrite ));
4502 return true;
4505 /****************************************************************************
4506 Reply to a write and X.
4507 ****************************************************************************/
4509 void reply_write_and_X(struct smb_request *req)
4511 connection_struct *conn = req->conn;
4512 files_struct *fsp;
4513 struct lock_struct lock;
4514 SMB_OFF_T startpos;
4515 size_t numtowrite;
4516 bool write_through;
4517 ssize_t nwritten;
4518 unsigned int smb_doff;
4519 unsigned int smblen;
4520 const char *data;
4521 NTSTATUS status;
4522 int saved_errno = 0;
4524 START_PROFILE(SMBwriteX);
4526 if ((req->wct != 12) && (req->wct != 14)) {
4527 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4528 END_PROFILE(SMBwriteX);
4529 return;
4532 numtowrite = SVAL(req->vwv+10, 0);
4533 smb_doff = SVAL(req->vwv+11, 0);
4534 smblen = smb_len(req->inbuf);
4536 if (req->unread_bytes > 0xFFFF ||
4537 (smblen > smb_doff &&
4538 smblen - smb_doff > 0xFFFF)) {
4539 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4542 if (req->unread_bytes) {
4543 /* Can't do a recvfile write on IPC$ */
4544 if (IS_IPC(conn)) {
4545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4546 END_PROFILE(SMBwriteX);
4547 return;
4549 if (numtowrite != req->unread_bytes) {
4550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4551 END_PROFILE(SMBwriteX);
4552 return;
4554 } else {
4555 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4556 smb_doff + numtowrite > smblen) {
4557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4558 END_PROFILE(SMBwriteX);
4559 return;
4563 /* If it's an IPC, pass off the pipe handler. */
4564 if (IS_IPC(conn)) {
4565 if (req->unread_bytes) {
4566 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4567 END_PROFILE(SMBwriteX);
4568 return;
4570 reply_pipe_write_and_X(req);
4571 END_PROFILE(SMBwriteX);
4572 return;
4575 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4576 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4577 write_through = BITSETW(req->vwv+7,0);
4579 if (!check_fsp(conn, req, fsp)) {
4580 END_PROFILE(SMBwriteX);
4581 return;
4584 if (!CHECK_WRITE(fsp)) {
4585 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4586 END_PROFILE(SMBwriteX);
4587 return;
4590 data = smb_base(req->inbuf) + smb_doff;
4592 if(req->wct == 14) {
4593 #ifdef LARGE_SMB_OFF_T
4595 * This is a large offset (64 bit) write.
4597 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4599 #else /* !LARGE_SMB_OFF_T */
4602 * Ensure we haven't been sent a >32 bit offset.
4605 if(IVAL(req->vwv+12, 0) != 0) {
4606 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4607 "used and we don't support 64 bit offsets.\n",
4608 (unsigned int)IVAL(req->vwv+12, 0) ));
4609 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4610 END_PROFILE(SMBwriteX);
4611 return;
4614 #endif /* LARGE_SMB_OFF_T */
4617 /* X/Open SMB protocol says that, unlike SMBwrite
4618 if the length is zero then NO truncation is
4619 done, just a write of zero. To truncate a file,
4620 use SMBwrite. */
4622 if(numtowrite == 0) {
4623 nwritten = 0;
4624 } else {
4625 if (req->unread_bytes == 0) {
4626 status = schedule_aio_write_and_X(conn,
4627 req,
4628 fsp,
4629 data,
4630 startpos,
4631 numtowrite);
4633 if (NT_STATUS_IS_OK(status)) {
4634 /* write scheduled - we're done. */
4635 goto out;
4637 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4638 /* Real error - report to client. */
4639 reply_nterror(req, status);
4640 goto out;
4642 /* NT_STATUS_RETRY - fall through to sync write. */
4645 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4646 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4647 &lock);
4649 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4650 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4651 goto out;
4654 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4655 saved_errno = errno;
4657 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4660 if(nwritten < 0) {
4661 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4662 goto out;
4665 if((nwritten == 0) && (numtowrite != 0)) {
4666 reply_nterror(req, NT_STATUS_DISK_FULL);
4667 goto out;
4670 reply_outbuf(req, 6, 0);
4671 SSVAL(req->outbuf,smb_vwv2,nwritten);
4672 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4674 if (nwritten < (ssize_t)numtowrite) {
4675 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4676 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4679 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4680 fsp->fnum, (int)numtowrite, (int)nwritten));
4682 status = sync_file(conn, fsp, write_through);
4683 if (!NT_STATUS_IS_OK(status)) {
4684 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4685 fsp_str_dbg(fsp), nt_errstr(status)));
4686 reply_nterror(req, status);
4687 goto out;
4690 END_PROFILE(SMBwriteX);
4691 chain_reply(req);
4692 return;
4694 out:
4695 END_PROFILE(SMBwriteX);
4696 return;
4699 /****************************************************************************
4700 Reply to a lseek.
4701 ****************************************************************************/
4703 void reply_lseek(struct smb_request *req)
4705 connection_struct *conn = req->conn;
4706 SMB_OFF_T startpos;
4707 SMB_OFF_T res= -1;
4708 int mode,umode;
4709 files_struct *fsp;
4711 START_PROFILE(SMBlseek);
4713 if (req->wct < 4) {
4714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4715 END_PROFILE(SMBlseek);
4716 return;
4719 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4721 if (!check_fsp(conn, req, fsp)) {
4722 return;
4725 flush_write_cache(fsp, SEEK_FLUSH);
4727 mode = SVAL(req->vwv+1, 0) & 3;
4728 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4729 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4731 switch (mode) {
4732 case 0:
4733 umode = SEEK_SET;
4734 res = startpos;
4735 break;
4736 case 1:
4737 umode = SEEK_CUR;
4738 res = fsp->fh->pos + startpos;
4739 break;
4740 case 2:
4741 umode = SEEK_END;
4742 break;
4743 default:
4744 umode = SEEK_SET;
4745 res = startpos;
4746 break;
4749 if (umode == SEEK_END) {
4750 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4751 if(errno == EINVAL) {
4752 SMB_OFF_T current_pos = startpos;
4754 if(fsp_stat(fsp) == -1) {
4755 reply_nterror(req,
4756 map_nt_error_from_unix(errno));
4757 END_PROFILE(SMBlseek);
4758 return;
4761 current_pos += fsp->fsp_name->st.st_ex_size;
4762 if(current_pos < 0)
4763 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4767 if(res == -1) {
4768 reply_nterror(req, map_nt_error_from_unix(errno));
4769 END_PROFILE(SMBlseek);
4770 return;
4774 fsp->fh->pos = res;
4776 reply_outbuf(req, 2, 0);
4777 SIVAL(req->outbuf,smb_vwv0,res);
4779 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4780 fsp->fnum, (double)startpos, (double)res, mode));
4782 END_PROFILE(SMBlseek);
4783 return;
4786 /****************************************************************************
4787 Reply to a flush.
4788 ****************************************************************************/
4790 void reply_flush(struct smb_request *req)
4792 connection_struct *conn = req->conn;
4793 uint16 fnum;
4794 files_struct *fsp;
4796 START_PROFILE(SMBflush);
4798 if (req->wct < 1) {
4799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4800 return;
4803 fnum = SVAL(req->vwv+0, 0);
4804 fsp = file_fsp(req, fnum);
4806 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4807 return;
4810 if (!fsp) {
4811 file_sync_all(conn);
4812 } else {
4813 NTSTATUS status = sync_file(conn, fsp, True);
4814 if (!NT_STATUS_IS_OK(status)) {
4815 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4816 fsp_str_dbg(fsp), nt_errstr(status)));
4817 reply_nterror(req, status);
4818 END_PROFILE(SMBflush);
4819 return;
4823 reply_outbuf(req, 0, 0);
4825 DEBUG(3,("flush\n"));
4826 END_PROFILE(SMBflush);
4827 return;
4830 /****************************************************************************
4831 Reply to a exit.
4832 conn POINTER CAN BE NULL HERE !
4833 ****************************************************************************/
4835 void reply_exit(struct smb_request *req)
4837 START_PROFILE(SMBexit);
4839 file_close_pid(req->sconn, req->smbpid, req->vuid);
4841 reply_outbuf(req, 0, 0);
4843 DEBUG(3,("exit\n"));
4845 END_PROFILE(SMBexit);
4846 return;
4849 /****************************************************************************
4850 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4851 ****************************************************************************/
4853 void reply_close(struct smb_request *req)
4855 connection_struct *conn = req->conn;
4856 NTSTATUS status = NT_STATUS_OK;
4857 files_struct *fsp = NULL;
4858 START_PROFILE(SMBclose);
4860 if (req->wct < 3) {
4861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4862 END_PROFILE(SMBclose);
4863 return;
4866 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4869 * We can only use check_fsp if we know it's not a directory.
4872 if (!check_fsp_open(conn, req, fsp)) {
4873 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4874 END_PROFILE(SMBclose);
4875 return;
4878 if(fsp->is_directory) {
4880 * Special case - close NT SMB directory handle.
4882 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4883 status = close_file(req, fsp, NORMAL_CLOSE);
4884 } else {
4885 time_t t;
4887 * Close ordinary file.
4890 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4891 fsp->fh->fd, fsp->fnum,
4892 conn->num_files_open));
4895 * Take care of any time sent in the close.
4898 t = srv_make_unix_date3(req->vwv+1);
4899 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4902 * close_file() returns the unix errno if an error
4903 * was detected on close - normally this is due to
4904 * a disk full error. If not then it was probably an I/O error.
4907 status = close_file(req, fsp, NORMAL_CLOSE);
4910 if (!NT_STATUS_IS_OK(status)) {
4911 reply_nterror(req, status);
4912 END_PROFILE(SMBclose);
4913 return;
4916 reply_outbuf(req, 0, 0);
4917 END_PROFILE(SMBclose);
4918 return;
4921 /****************************************************************************
4922 Reply to a writeclose (Core+ protocol).
4923 ****************************************************************************/
4925 void reply_writeclose(struct smb_request *req)
4927 connection_struct *conn = req->conn;
4928 size_t numtowrite;
4929 ssize_t nwritten = -1;
4930 NTSTATUS close_status = NT_STATUS_OK;
4931 SMB_OFF_T startpos;
4932 const char *data;
4933 struct timespec mtime;
4934 files_struct *fsp;
4935 struct lock_struct lock;
4937 START_PROFILE(SMBwriteclose);
4939 if (req->wct < 6) {
4940 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4941 END_PROFILE(SMBwriteclose);
4942 return;
4945 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4947 if (!check_fsp(conn, req, fsp)) {
4948 END_PROFILE(SMBwriteclose);
4949 return;
4951 if (!CHECK_WRITE(fsp)) {
4952 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4953 END_PROFILE(SMBwriteclose);
4954 return;
4957 numtowrite = SVAL(req->vwv+1, 0);
4958 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4959 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4960 data = (const char *)req->buf + 1;
4962 if (!fsp->print_file) {
4963 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4964 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4965 &lock);
4967 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4968 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4969 END_PROFILE(SMBwriteclose);
4970 return;
4974 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4976 set_close_write_time(fsp, mtime);
4979 * More insanity. W2K only closes the file if writelen > 0.
4980 * JRA.
4983 if (numtowrite) {
4984 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4985 "file %s\n", fsp_str_dbg(fsp)));
4986 close_status = close_file(req, fsp, NORMAL_CLOSE);
4989 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4990 fsp->fnum, (int)numtowrite, (int)nwritten,
4991 conn->num_files_open));
4993 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4994 reply_nterror(req, NT_STATUS_DISK_FULL);
4995 goto strict_unlock;
4998 if(!NT_STATUS_IS_OK(close_status)) {
4999 reply_nterror(req, close_status);
5000 goto strict_unlock;
5003 reply_outbuf(req, 1, 0);
5005 SSVAL(req->outbuf,smb_vwv0,nwritten);
5007 strict_unlock:
5008 if (numtowrite && !fsp->print_file) {
5009 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5012 END_PROFILE(SMBwriteclose);
5013 return;
5016 #undef DBGC_CLASS
5017 #define DBGC_CLASS DBGC_LOCKING
5019 /****************************************************************************
5020 Reply to a lock.
5021 ****************************************************************************/
5023 void reply_lock(struct smb_request *req)
5025 connection_struct *conn = req->conn;
5026 uint64_t count,offset;
5027 NTSTATUS status;
5028 files_struct *fsp;
5029 struct byte_range_lock *br_lck = NULL;
5031 START_PROFILE(SMBlock);
5033 if (req->wct < 5) {
5034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5035 END_PROFILE(SMBlock);
5036 return;
5039 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5041 if (!check_fsp(conn, req, fsp)) {
5042 END_PROFILE(SMBlock);
5043 return;
5046 count = (uint64_t)IVAL(req->vwv+1, 0);
5047 offset = (uint64_t)IVAL(req->vwv+3, 0);
5049 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5050 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5052 br_lck = do_lock(req->sconn->msg_ctx,
5053 fsp,
5054 (uint64_t)req->smbpid,
5055 count,
5056 offset,
5057 WRITE_LOCK,
5058 WINDOWS_LOCK,
5059 False, /* Non-blocking lock. */
5060 &status,
5061 NULL,
5062 NULL);
5064 TALLOC_FREE(br_lck);
5066 if (NT_STATUS_V(status)) {
5067 reply_nterror(req, status);
5068 END_PROFILE(SMBlock);
5069 return;
5072 reply_outbuf(req, 0, 0);
5074 END_PROFILE(SMBlock);
5075 return;
5078 /****************************************************************************
5079 Reply to a unlock.
5080 ****************************************************************************/
5082 void reply_unlock(struct smb_request *req)
5084 connection_struct *conn = req->conn;
5085 uint64_t count,offset;
5086 NTSTATUS status;
5087 files_struct *fsp;
5089 START_PROFILE(SMBunlock);
5091 if (req->wct < 5) {
5092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5093 END_PROFILE(SMBunlock);
5094 return;
5097 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5099 if (!check_fsp(conn, req, fsp)) {
5100 END_PROFILE(SMBunlock);
5101 return;
5104 count = (uint64_t)IVAL(req->vwv+1, 0);
5105 offset = (uint64_t)IVAL(req->vwv+3, 0);
5107 status = do_unlock(req->sconn->msg_ctx,
5108 fsp,
5109 (uint64_t)req->smbpid,
5110 count,
5111 offset,
5112 WINDOWS_LOCK);
5114 if (NT_STATUS_V(status)) {
5115 reply_nterror(req, status);
5116 END_PROFILE(SMBunlock);
5117 return;
5120 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5121 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5123 reply_outbuf(req, 0, 0);
5125 END_PROFILE(SMBunlock);
5126 return;
5129 #undef DBGC_CLASS
5130 #define DBGC_CLASS DBGC_ALL
5132 /****************************************************************************
5133 Reply to a tdis.
5134 conn POINTER CAN BE NULL HERE !
5135 ****************************************************************************/
5137 void reply_tdis(struct smb_request *req)
5139 connection_struct *conn = req->conn;
5140 START_PROFILE(SMBtdis);
5142 if (!conn) {
5143 DEBUG(4,("Invalid connection in tdis\n"));
5144 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5145 END_PROFILE(SMBtdis);
5146 return;
5149 conn->used = False;
5151 close_cnum(conn,req->vuid);
5152 req->conn = NULL;
5154 reply_outbuf(req, 0, 0);
5155 END_PROFILE(SMBtdis);
5156 return;
5159 /****************************************************************************
5160 Reply to a echo.
5161 conn POINTER CAN BE NULL HERE !
5162 ****************************************************************************/
5164 void reply_echo(struct smb_request *req)
5166 connection_struct *conn = req->conn;
5167 struct smb_perfcount_data local_pcd;
5168 struct smb_perfcount_data *cur_pcd;
5169 int smb_reverb;
5170 int seq_num;
5172 START_PROFILE(SMBecho);
5174 smb_init_perfcount_data(&local_pcd);
5176 if (req->wct < 1) {
5177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5178 END_PROFILE(SMBecho);
5179 return;
5182 smb_reverb = SVAL(req->vwv+0, 0);
5184 reply_outbuf(req, 1, req->buflen);
5186 /* copy any incoming data back out */
5187 if (req->buflen > 0) {
5188 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5191 if (smb_reverb > 100) {
5192 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5193 smb_reverb = 100;
5196 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5198 /* this makes sure we catch the request pcd */
5199 if (seq_num == smb_reverb) {
5200 cur_pcd = &req->pcd;
5201 } else {
5202 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5203 cur_pcd = &local_pcd;
5206 SSVAL(req->outbuf,smb_vwv0,seq_num);
5208 show_msg((char *)req->outbuf);
5209 if (!srv_send_smb(req->sconn,
5210 (char *)req->outbuf,
5211 true, req->seqnum+1,
5212 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5213 cur_pcd))
5214 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5217 DEBUG(3,("echo %d times\n", smb_reverb));
5219 TALLOC_FREE(req->outbuf);
5221 END_PROFILE(SMBecho);
5222 return;
5225 /****************************************************************************
5226 Reply to a printopen.
5227 ****************************************************************************/
5229 void reply_printopen(struct smb_request *req)
5231 connection_struct *conn = req->conn;
5232 files_struct *fsp;
5233 NTSTATUS status;
5235 START_PROFILE(SMBsplopen);
5237 if (req->wct < 2) {
5238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5239 END_PROFILE(SMBsplopen);
5240 return;
5243 if (!CAN_PRINT(conn)) {
5244 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5245 END_PROFILE(SMBsplopen);
5246 return;
5249 status = file_new(req, conn, &fsp);
5250 if(!NT_STATUS_IS_OK(status)) {
5251 reply_nterror(req, status);
5252 END_PROFILE(SMBsplopen);
5253 return;
5256 /* Open for exclusive use, write only. */
5257 status = print_spool_open(fsp, NULL, req->vuid);
5259 if (!NT_STATUS_IS_OK(status)) {
5260 file_free(req, fsp);
5261 reply_nterror(req, status);
5262 END_PROFILE(SMBsplopen);
5263 return;
5266 reply_outbuf(req, 1, 0);
5267 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5269 DEBUG(3,("openprint fd=%d fnum=%d\n",
5270 fsp->fh->fd, fsp->fnum));
5272 END_PROFILE(SMBsplopen);
5273 return;
5276 /****************************************************************************
5277 Reply to a printclose.
5278 ****************************************************************************/
5280 void reply_printclose(struct smb_request *req)
5282 connection_struct *conn = req->conn;
5283 files_struct *fsp;
5284 NTSTATUS status;
5286 START_PROFILE(SMBsplclose);
5288 if (req->wct < 1) {
5289 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5290 END_PROFILE(SMBsplclose);
5291 return;
5294 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5296 if (!check_fsp(conn, req, fsp)) {
5297 END_PROFILE(SMBsplclose);
5298 return;
5301 if (!CAN_PRINT(conn)) {
5302 reply_force_doserror(req, ERRSRV, ERRerror);
5303 END_PROFILE(SMBsplclose);
5304 return;
5307 DEBUG(3,("printclose fd=%d fnum=%d\n",
5308 fsp->fh->fd,fsp->fnum));
5310 status = close_file(req, fsp, NORMAL_CLOSE);
5312 if(!NT_STATUS_IS_OK(status)) {
5313 reply_nterror(req, status);
5314 END_PROFILE(SMBsplclose);
5315 return;
5318 reply_outbuf(req, 0, 0);
5320 END_PROFILE(SMBsplclose);
5321 return;
5324 /****************************************************************************
5325 Reply to a printqueue.
5326 ****************************************************************************/
5328 void reply_printqueue(struct smb_request *req)
5330 connection_struct *conn = req->conn;
5331 int max_count;
5332 int start_index;
5334 START_PROFILE(SMBsplretq);
5336 if (req->wct < 2) {
5337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5338 END_PROFILE(SMBsplretq);
5339 return;
5342 max_count = SVAL(req->vwv+0, 0);
5343 start_index = SVAL(req->vwv+1, 0);
5345 /* we used to allow the client to get the cnum wrong, but that
5346 is really quite gross and only worked when there was only
5347 one printer - I think we should now only accept it if they
5348 get it right (tridge) */
5349 if (!CAN_PRINT(conn)) {
5350 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5351 END_PROFILE(SMBsplretq);
5352 return;
5355 reply_outbuf(req, 2, 3);
5356 SSVAL(req->outbuf,smb_vwv0,0);
5357 SSVAL(req->outbuf,smb_vwv1,0);
5358 SCVAL(smb_buf(req->outbuf),0,1);
5359 SSVAL(smb_buf(req->outbuf),1,0);
5361 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5362 start_index, max_count));
5365 TALLOC_CTX *mem_ctx = talloc_tos();
5366 NTSTATUS status;
5367 WERROR werr;
5368 const char *sharename = lp_servicename(SNUM(conn));
5369 struct rpc_pipe_client *cli = NULL;
5370 struct dcerpc_binding_handle *b = NULL;
5371 struct policy_handle handle;
5372 struct spoolss_DevmodeContainer devmode_ctr;
5373 union spoolss_JobInfo *info;
5374 uint32_t count;
5375 uint32_t num_to_get;
5376 uint32_t first;
5377 uint32_t i;
5379 ZERO_STRUCT(handle);
5381 status = rpc_pipe_open_interface(conn,
5382 &ndr_table_spoolss.syntax_id,
5383 conn->session_info,
5384 conn->sconn->remote_address,
5385 conn->sconn->msg_ctx,
5386 &cli);
5387 if (!NT_STATUS_IS_OK(status)) {
5388 DEBUG(0, ("reply_printqueue: "
5389 "could not connect to spoolss: %s\n",
5390 nt_errstr(status)));
5391 reply_nterror(req, status);
5392 goto out;
5394 b = cli->binding_handle;
5396 ZERO_STRUCT(devmode_ctr);
5398 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5399 sharename,
5400 NULL, devmode_ctr,
5401 SEC_FLAG_MAXIMUM_ALLOWED,
5402 &handle,
5403 &werr);
5404 if (!NT_STATUS_IS_OK(status)) {
5405 reply_nterror(req, status);
5406 goto out;
5408 if (!W_ERROR_IS_OK(werr)) {
5409 reply_nterror(req, werror_to_ntstatus(werr));
5410 goto out;
5413 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5414 &handle,
5415 0, /* firstjob */
5416 0xff, /* numjobs */
5417 2, /* level */
5418 0, /* offered */
5419 &count,
5420 &info);
5421 if (!W_ERROR_IS_OK(werr)) {
5422 reply_nterror(req, werror_to_ntstatus(werr));
5423 goto out;
5426 if (max_count > 0) {
5427 first = start_index;
5428 } else {
5429 first = start_index + max_count + 1;
5432 if (first >= count) {
5433 num_to_get = first;
5434 } else {
5435 num_to_get = first + MIN(ABS(max_count), count - first);
5438 for (i = first; i < num_to_get; i++) {
5439 char blob[28];
5440 char *p = blob;
5441 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5442 int qstatus;
5443 uint16_t qrapjobid = pjobid_to_rap(sharename,
5444 info[i].info2.job_id);
5446 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5447 qstatus = 2;
5448 } else {
5449 qstatus = 3;
5452 srv_put_dos_date2(p, 0, qtime);
5453 SCVAL(p, 4, qstatus);
5454 SSVAL(p, 5, qrapjobid);
5455 SIVAL(p, 7, info[i].info2.size);
5456 SCVAL(p, 11, 0);
5457 srvstr_push(blob, req->flags2, p+12,
5458 info[i].info2.notify_name, 16, STR_ASCII);
5460 if (message_push_blob(
5461 &req->outbuf,
5462 data_blob_const(
5463 blob, sizeof(blob))) == -1) {
5464 reply_nterror(req, NT_STATUS_NO_MEMORY);
5465 goto out;
5469 if (count > 0) {
5470 SSVAL(req->outbuf,smb_vwv0,count);
5471 SSVAL(req->outbuf,smb_vwv1,
5472 (max_count>0?first+count:first-1));
5473 SCVAL(smb_buf(req->outbuf),0,1);
5474 SSVAL(smb_buf(req->outbuf),1,28*count);
5478 DEBUG(3, ("%u entries returned in queue\n",
5479 (unsigned)count));
5481 out:
5482 if (b && is_valid_policy_hnd(&handle)) {
5483 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5488 END_PROFILE(SMBsplretq);
5489 return;
5492 /****************************************************************************
5493 Reply to a printwrite.
5494 ****************************************************************************/
5496 void reply_printwrite(struct smb_request *req)
5498 connection_struct *conn = req->conn;
5499 int numtowrite;
5500 const char *data;
5501 files_struct *fsp;
5503 START_PROFILE(SMBsplwr);
5505 if (req->wct < 1) {
5506 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5507 END_PROFILE(SMBsplwr);
5508 return;
5511 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5513 if (!check_fsp(conn, req, fsp)) {
5514 END_PROFILE(SMBsplwr);
5515 return;
5518 if (!fsp->print_file) {
5519 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5520 END_PROFILE(SMBsplwr);
5521 return;
5524 if (!CHECK_WRITE(fsp)) {
5525 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5526 END_PROFILE(SMBsplwr);
5527 return;
5530 numtowrite = SVAL(req->buf, 1);
5532 if (req->buflen < numtowrite + 3) {
5533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5534 END_PROFILE(SMBsplwr);
5535 return;
5538 data = (const char *)req->buf + 3;
5540 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5541 reply_nterror(req, map_nt_error_from_unix(errno));
5542 END_PROFILE(SMBsplwr);
5543 return;
5546 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5548 END_PROFILE(SMBsplwr);
5549 return;
5552 /****************************************************************************
5553 Reply to a mkdir.
5554 ****************************************************************************/
5556 void reply_mkdir(struct smb_request *req)
5558 connection_struct *conn = req->conn;
5559 struct smb_filename *smb_dname = NULL;
5560 char *directory = NULL;
5561 NTSTATUS status;
5562 TALLOC_CTX *ctx = talloc_tos();
5564 START_PROFILE(SMBmkdir);
5566 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5567 STR_TERMINATE, &status);
5568 if (!NT_STATUS_IS_OK(status)) {
5569 reply_nterror(req, status);
5570 goto out;
5573 status = filename_convert(ctx, conn,
5574 req->flags2 & FLAGS2_DFS_PATHNAMES,
5575 directory,
5577 NULL,
5578 &smb_dname);
5579 if (!NT_STATUS_IS_OK(status)) {
5580 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5581 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5582 ERRSRV, ERRbadpath);
5583 goto out;
5585 reply_nterror(req, status);
5586 goto out;
5589 status = create_directory(conn, req, smb_dname);
5591 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5593 if (!NT_STATUS_IS_OK(status)) {
5595 if (!use_nt_status()
5596 && NT_STATUS_EQUAL(status,
5597 NT_STATUS_OBJECT_NAME_COLLISION)) {
5599 * Yes, in the DOS error code case we get a
5600 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5601 * samba4 torture test.
5603 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5606 reply_nterror(req, status);
5607 goto out;
5610 reply_outbuf(req, 0, 0);
5612 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5613 out:
5614 TALLOC_FREE(smb_dname);
5615 END_PROFILE(SMBmkdir);
5616 return;
5619 /****************************************************************************
5620 Reply to a rmdir.
5621 ****************************************************************************/
5623 void reply_rmdir(struct smb_request *req)
5625 connection_struct *conn = req->conn;
5626 struct smb_filename *smb_dname = NULL;
5627 char *directory = NULL;
5628 NTSTATUS status;
5629 TALLOC_CTX *ctx = talloc_tos();
5630 files_struct *fsp = NULL;
5631 int info = 0;
5632 struct smbd_server_connection *sconn = req->sconn;
5634 START_PROFILE(SMBrmdir);
5636 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5637 STR_TERMINATE, &status);
5638 if (!NT_STATUS_IS_OK(status)) {
5639 reply_nterror(req, status);
5640 goto out;
5643 status = filename_convert(ctx, conn,
5644 req->flags2 & FLAGS2_DFS_PATHNAMES,
5645 directory,
5647 NULL,
5648 &smb_dname);
5649 if (!NT_STATUS_IS_OK(status)) {
5650 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5651 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5652 ERRSRV, ERRbadpath);
5653 goto out;
5655 reply_nterror(req, status);
5656 goto out;
5659 if (is_ntfs_stream_smb_fname(smb_dname)) {
5660 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5661 goto out;
5664 status = SMB_VFS_CREATE_FILE(
5665 conn, /* conn */
5666 req, /* req */
5667 0, /* root_dir_fid */
5668 smb_dname, /* fname */
5669 DELETE_ACCESS, /* access_mask */
5670 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5671 FILE_SHARE_DELETE),
5672 FILE_OPEN, /* create_disposition*/
5673 FILE_DIRECTORY_FILE, /* create_options */
5674 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5675 0, /* oplock_request */
5676 0, /* allocation_size */
5677 0, /* private_flags */
5678 NULL, /* sd */
5679 NULL, /* ea_list */
5680 &fsp, /* result */
5681 &info); /* pinfo */
5683 if (!NT_STATUS_IS_OK(status)) {
5684 if (open_was_deferred(req->sconn, req->mid)) {
5685 /* We have re-scheduled this call. */
5686 goto out;
5688 reply_nterror(req, status);
5689 goto out;
5692 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5693 if (!NT_STATUS_IS_OK(status)) {
5694 close_file(req, fsp, ERROR_CLOSE);
5695 reply_nterror(req, status);
5696 goto out;
5699 if (!set_delete_on_close(fsp, true, conn->session_info->unix_token)) {
5700 close_file(req, fsp, ERROR_CLOSE);
5701 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5702 goto out;
5705 status = close_file(req, fsp, NORMAL_CLOSE);
5706 if (!NT_STATUS_IS_OK(status)) {
5707 reply_nterror(req, status);
5708 } else {
5709 reply_outbuf(req, 0, 0);
5712 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5714 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5715 out:
5716 TALLOC_FREE(smb_dname);
5717 END_PROFILE(SMBrmdir);
5718 return;
5721 /*******************************************************************
5722 Resolve wildcards in a filename rename.
5723 ********************************************************************/
5725 static bool resolve_wildcards(TALLOC_CTX *ctx,
5726 const char *name1,
5727 const char *name2,
5728 char **pp_newname)
5730 char *name2_copy = NULL;
5731 char *root1 = NULL;
5732 char *root2 = NULL;
5733 char *ext1 = NULL;
5734 char *ext2 = NULL;
5735 char *p,*p2, *pname1, *pname2;
5737 name2_copy = talloc_strdup(ctx, name2);
5738 if (!name2_copy) {
5739 return False;
5742 pname1 = strrchr_m(name1,'/');
5743 pname2 = strrchr_m(name2_copy,'/');
5745 if (!pname1 || !pname2) {
5746 return False;
5749 /* Truncate the copy of name2 at the last '/' */
5750 *pname2 = '\0';
5752 /* Now go past the '/' */
5753 pname1++;
5754 pname2++;
5756 root1 = talloc_strdup(ctx, pname1);
5757 root2 = talloc_strdup(ctx, pname2);
5759 if (!root1 || !root2) {
5760 return False;
5763 p = strrchr_m(root1,'.');
5764 if (p) {
5765 *p = 0;
5766 ext1 = talloc_strdup(ctx, p+1);
5767 } else {
5768 ext1 = talloc_strdup(ctx, "");
5770 p = strrchr_m(root2,'.');
5771 if (p) {
5772 *p = 0;
5773 ext2 = talloc_strdup(ctx, p+1);
5774 } else {
5775 ext2 = talloc_strdup(ctx, "");
5778 if (!ext1 || !ext2) {
5779 return False;
5782 p = root1;
5783 p2 = root2;
5784 while (*p2) {
5785 if (*p2 == '?') {
5786 /* Hmmm. Should this be mb-aware ? */
5787 *p2 = *p;
5788 p2++;
5789 } else if (*p2 == '*') {
5790 *p2 = '\0';
5791 root2 = talloc_asprintf(ctx, "%s%s",
5792 root2,
5794 if (!root2) {
5795 return False;
5797 break;
5798 } else {
5799 p2++;
5801 if (*p) {
5802 p++;
5806 p = ext1;
5807 p2 = ext2;
5808 while (*p2) {
5809 if (*p2 == '?') {
5810 /* Hmmm. Should this be mb-aware ? */
5811 *p2 = *p;
5812 p2++;
5813 } else if (*p2 == '*') {
5814 *p2 = '\0';
5815 ext2 = talloc_asprintf(ctx, "%s%s",
5816 ext2,
5818 if (!ext2) {
5819 return False;
5821 break;
5822 } else {
5823 p2++;
5825 if (*p) {
5826 p++;
5830 if (*ext2) {
5831 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5832 name2_copy,
5833 root2,
5834 ext2);
5835 } else {
5836 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5837 name2_copy,
5838 root2);
5841 if (!*pp_newname) {
5842 return False;
5845 return True;
5848 /****************************************************************************
5849 Ensure open files have their names updated. Updated to notify other smbd's
5850 asynchronously.
5851 ****************************************************************************/
5853 static void rename_open_files(connection_struct *conn,
5854 struct share_mode_lock *lck,
5855 uint32_t orig_name_hash,
5856 const struct smb_filename *smb_fname_dst)
5858 files_struct *fsp;
5859 bool did_rename = False;
5860 NTSTATUS status;
5861 uint32_t new_name_hash = 0;
5863 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5864 fsp = file_find_di_next(fsp)) {
5865 /* fsp_name is a relative path under the fsp. To change this for other
5866 sharepaths we need to manipulate relative paths. */
5867 /* TODO - create the absolute path and manipulate the newname
5868 relative to the sharepath. */
5869 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5870 continue;
5872 if (fsp->name_hash != orig_name_hash) {
5873 continue;
5875 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5876 "(file_id %s) from %s -> %s\n", fsp->fnum,
5877 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5878 smb_fname_str_dbg(smb_fname_dst)));
5880 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5881 if (NT_STATUS_IS_OK(status)) {
5882 did_rename = True;
5883 new_name_hash = fsp->name_hash;
5887 if (!did_rename) {
5888 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5889 "for %s\n", file_id_string_tos(&lck->id),
5890 smb_fname_str_dbg(smb_fname_dst)));
5893 /* Send messages to all smbd's (not ourself) that the name has changed. */
5894 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5895 orig_name_hash, new_name_hash,
5896 smb_fname_dst);
5900 /****************************************************************************
5901 We need to check if the source path is a parent directory of the destination
5902 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5903 refuse the rename with a sharing violation. Under UNIX the above call can
5904 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5905 probably need to check that the client is a Windows one before disallowing
5906 this as a UNIX client (one with UNIX extensions) can know the source is a
5907 symlink and make this decision intelligently. Found by an excellent bug
5908 report from <AndyLiebman@aol.com>.
5909 ****************************************************************************/
5911 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5912 const struct smb_filename *smb_fname_dst)
5914 const char *psrc = smb_fname_src->base_name;
5915 const char *pdst = smb_fname_dst->base_name;
5916 size_t slen;
5918 if (psrc[0] == '.' && psrc[1] == '/') {
5919 psrc += 2;
5921 if (pdst[0] == '.' && pdst[1] == '/') {
5922 pdst += 2;
5924 if ((slen = strlen(psrc)) > strlen(pdst)) {
5925 return False;
5927 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5931 * Do the notify calls from a rename
5934 static void notify_rename(connection_struct *conn, bool is_dir,
5935 const struct smb_filename *smb_fname_src,
5936 const struct smb_filename *smb_fname_dst)
5938 char *parent_dir_src = NULL;
5939 char *parent_dir_dst = NULL;
5940 uint32 mask;
5942 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5943 : FILE_NOTIFY_CHANGE_FILE_NAME;
5945 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5946 &parent_dir_src, NULL) ||
5947 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5948 &parent_dir_dst, NULL)) {
5949 goto out;
5952 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5953 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5954 smb_fname_src->base_name);
5955 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5956 smb_fname_dst->base_name);
5958 else {
5959 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5960 smb_fname_src->base_name);
5961 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5962 smb_fname_dst->base_name);
5965 /* this is a strange one. w2k3 gives an additional event for
5966 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5967 files, but not directories */
5968 if (!is_dir) {
5969 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5970 FILE_NOTIFY_CHANGE_ATTRIBUTES
5971 |FILE_NOTIFY_CHANGE_CREATION,
5972 smb_fname_dst->base_name);
5974 out:
5975 TALLOC_FREE(parent_dir_src);
5976 TALLOC_FREE(parent_dir_dst);
5979 /****************************************************************************
5980 Returns an error if the parent directory for a filename is open in an
5981 incompatible way.
5982 ****************************************************************************/
5984 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5985 const struct smb_filename *smb_fname_dst_in)
5987 char *parent_dir = NULL;
5988 struct smb_filename smb_fname_parent;
5989 struct file_id id;
5990 files_struct *fsp = NULL;
5991 int ret;
5993 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5994 &parent_dir, NULL)) {
5995 return NT_STATUS_NO_MEMORY;
5997 ZERO_STRUCT(smb_fname_parent);
5998 smb_fname_parent.base_name = parent_dir;
6000 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6001 if (ret == -1) {
6002 return map_nt_error_from_unix(errno);
6006 * We're only checking on this smbd here, mostly good
6007 * enough.. and will pass tests.
6010 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6011 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6012 fsp = file_find_di_next(fsp)) {
6013 if (fsp->access_mask & DELETE_ACCESS) {
6014 return NT_STATUS_SHARING_VIOLATION;
6017 return NT_STATUS_OK;
6020 /****************************************************************************
6021 Rename an open file - given an fsp.
6022 ****************************************************************************/
6024 NTSTATUS rename_internals_fsp(connection_struct *conn,
6025 files_struct *fsp,
6026 const struct smb_filename *smb_fname_dst_in,
6027 uint32 attrs,
6028 bool replace_if_exists)
6030 TALLOC_CTX *ctx = talloc_tos();
6031 struct smb_filename *smb_fname_dst = NULL;
6032 NTSTATUS status = NT_STATUS_OK;
6033 struct share_mode_lock *lck = NULL;
6034 bool dst_exists, old_is_stream, new_is_stream;
6036 status = check_name(conn, smb_fname_dst_in->base_name);
6037 if (!NT_STATUS_IS_OK(status)) {
6038 return status;
6041 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6042 if (!NT_STATUS_IS_OK(status)) {
6043 return status;
6046 /* Make a copy of the dst smb_fname structs */
6048 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6049 if (!NT_STATUS_IS_OK(status)) {
6050 goto out;
6054 * Check for special case with case preserving and not
6055 * case sensitive. If the old last component differs from the original
6056 * last component only by case, then we should allow
6057 * the rename (user is trying to change the case of the
6058 * filename).
6060 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6061 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6062 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6063 char *last_slash;
6064 char *fname_dst_lcomp_base_mod = NULL;
6065 struct smb_filename *smb_fname_orig_lcomp = NULL;
6068 * Get the last component of the destination name.
6070 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6071 if (last_slash) {
6072 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6073 } else {
6074 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6076 if (!fname_dst_lcomp_base_mod) {
6077 status = NT_STATUS_NO_MEMORY;
6078 goto out;
6082 * Create an smb_filename struct using the original last
6083 * component of the destination.
6085 status = create_synthetic_smb_fname_split(ctx,
6086 smb_fname_dst->original_lcomp, NULL,
6087 &smb_fname_orig_lcomp);
6088 if (!NT_STATUS_IS_OK(status)) {
6089 TALLOC_FREE(fname_dst_lcomp_base_mod);
6090 goto out;
6093 /* If the base names only differ by case, use original. */
6094 if(!strcsequal(fname_dst_lcomp_base_mod,
6095 smb_fname_orig_lcomp->base_name)) {
6096 char *tmp;
6098 * Replace the modified last component with the
6099 * original.
6101 if (last_slash) {
6102 *last_slash = '\0'; /* Truncate at the '/' */
6103 tmp = talloc_asprintf(smb_fname_dst,
6104 "%s/%s",
6105 smb_fname_dst->base_name,
6106 smb_fname_orig_lcomp->base_name);
6107 } else {
6108 tmp = talloc_asprintf(smb_fname_dst,
6109 "%s",
6110 smb_fname_orig_lcomp->base_name);
6112 if (tmp == NULL) {
6113 status = NT_STATUS_NO_MEMORY;
6114 TALLOC_FREE(fname_dst_lcomp_base_mod);
6115 TALLOC_FREE(smb_fname_orig_lcomp);
6116 goto out;
6118 TALLOC_FREE(smb_fname_dst->base_name);
6119 smb_fname_dst->base_name = tmp;
6122 /* If the stream_names only differ by case, use original. */
6123 if(!strcsequal(smb_fname_dst->stream_name,
6124 smb_fname_orig_lcomp->stream_name)) {
6125 char *tmp = NULL;
6126 /* Use the original stream. */
6127 tmp = talloc_strdup(smb_fname_dst,
6128 smb_fname_orig_lcomp->stream_name);
6129 if (tmp == NULL) {
6130 status = NT_STATUS_NO_MEMORY;
6131 TALLOC_FREE(fname_dst_lcomp_base_mod);
6132 TALLOC_FREE(smb_fname_orig_lcomp);
6133 goto out;
6135 TALLOC_FREE(smb_fname_dst->stream_name);
6136 smb_fname_dst->stream_name = tmp;
6138 TALLOC_FREE(fname_dst_lcomp_base_mod);
6139 TALLOC_FREE(smb_fname_orig_lcomp);
6143 * If the src and dest names are identical - including case,
6144 * don't do the rename, just return success.
6147 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6148 strcsequal(fsp->fsp_name->stream_name,
6149 smb_fname_dst->stream_name)) {
6150 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6151 "- returning success\n",
6152 smb_fname_str_dbg(smb_fname_dst)));
6153 status = NT_STATUS_OK;
6154 goto out;
6157 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6158 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6160 /* Return the correct error code if both names aren't streams. */
6161 if (!old_is_stream && new_is_stream) {
6162 status = NT_STATUS_OBJECT_NAME_INVALID;
6163 goto out;
6166 if (old_is_stream && !new_is_stream) {
6167 status = NT_STATUS_INVALID_PARAMETER;
6168 goto out;
6171 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6173 if(!replace_if_exists && dst_exists) {
6174 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6175 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6176 smb_fname_str_dbg(smb_fname_dst)));
6177 status = NT_STATUS_OBJECT_NAME_COLLISION;
6178 goto out;
6181 if (dst_exists) {
6182 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6183 &smb_fname_dst->st);
6184 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6185 fileid);
6186 /* The file can be open when renaming a stream */
6187 if (dst_fsp && !new_is_stream) {
6188 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6189 status = NT_STATUS_ACCESS_DENIED;
6190 goto out;
6194 /* Ensure we have a valid stat struct for the source. */
6195 status = vfs_stat_fsp(fsp);
6196 if (!NT_STATUS_IS_OK(status)) {
6197 goto out;
6200 status = can_rename(conn, fsp, attrs);
6202 if (!NT_STATUS_IS_OK(status)) {
6203 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6204 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6205 smb_fname_str_dbg(smb_fname_dst)));
6206 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6207 status = NT_STATUS_ACCESS_DENIED;
6208 goto out;
6211 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6212 status = NT_STATUS_ACCESS_DENIED;
6215 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6216 NULL);
6219 * We have the file open ourselves, so not being able to get the
6220 * corresponding share mode lock is a fatal error.
6223 SMB_ASSERT(lck != NULL);
6225 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6226 uint32 create_options = fsp->fh->private_options;
6228 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6229 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6230 smb_fname_str_dbg(smb_fname_dst)));
6232 if (!lp_posix_pathnames() &&
6233 (lp_map_archive(SNUM(conn)) ||
6234 lp_store_dos_attributes(SNUM(conn)))) {
6235 /* We must set the archive bit on the newly
6236 renamed file. */
6237 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6238 uint32_t old_dosmode = dos_mode(conn,
6239 smb_fname_dst);
6240 file_set_dosmode(conn,
6241 smb_fname_dst,
6242 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6243 NULL,
6244 true);
6248 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6249 smb_fname_dst);
6251 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6254 * A rename acts as a new file create w.r.t. allowing an initial delete
6255 * on close, probably because in Windows there is a new handle to the
6256 * new file. If initial delete on close was requested but not
6257 * originally set, we need to set it here. This is probably not 100% correct,
6258 * but will work for the CIFSFS client which in non-posix mode
6259 * depends on these semantics. JRA.
6262 if (create_options & FILE_DELETE_ON_CLOSE) {
6263 status = can_set_delete_on_close(fsp, 0);
6265 if (NT_STATUS_IS_OK(status)) {
6266 /* Note that here we set the *inital* delete on close flag,
6267 * not the regular one. The magic gets handled in close. */
6268 fsp->initial_delete_on_close = True;
6271 TALLOC_FREE(lck);
6272 status = NT_STATUS_OK;
6273 goto out;
6276 TALLOC_FREE(lck);
6278 if (errno == ENOTDIR || errno == EISDIR) {
6279 status = NT_STATUS_OBJECT_NAME_COLLISION;
6280 } else {
6281 status = map_nt_error_from_unix(errno);
6284 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6285 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6286 smb_fname_str_dbg(smb_fname_dst)));
6288 out:
6289 TALLOC_FREE(smb_fname_dst);
6291 return status;
6294 /****************************************************************************
6295 The guts of the rename command, split out so it may be called by the NT SMB
6296 code.
6297 ****************************************************************************/
6299 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6300 connection_struct *conn,
6301 struct smb_request *req,
6302 struct smb_filename *smb_fname_src,
6303 struct smb_filename *smb_fname_dst,
6304 uint32 attrs,
6305 bool replace_if_exists,
6306 bool src_has_wild,
6307 bool dest_has_wild,
6308 uint32_t access_mask)
6310 char *fname_src_dir = NULL;
6311 char *fname_src_mask = NULL;
6312 int count=0;
6313 NTSTATUS status = NT_STATUS_OK;
6314 struct smb_Dir *dir_hnd = NULL;
6315 const char *dname = NULL;
6316 char *talloced = NULL;
6317 long offset = 0;
6318 int create_options = 0;
6319 bool posix_pathnames = lp_posix_pathnames();
6322 * Split the old name into directory and last component
6323 * strings. Note that unix_convert may have stripped off a
6324 * leading ./ from both name and newname if the rename is
6325 * at the root of the share. We need to make sure either both
6326 * name and newname contain a / character or neither of them do
6327 * as this is checked in resolve_wildcards().
6330 /* Split up the directory from the filename/mask. */
6331 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6332 &fname_src_dir, &fname_src_mask);
6333 if (!NT_STATUS_IS_OK(status)) {
6334 status = NT_STATUS_NO_MEMORY;
6335 goto out;
6339 * We should only check the mangled cache
6340 * here if unix_convert failed. This means
6341 * that the path in 'mask' doesn't exist
6342 * on the file system and so we need to look
6343 * for a possible mangle. This patch from
6344 * Tine Smukavec <valentin.smukavec@hermes.si>.
6347 if (!VALID_STAT(smb_fname_src->st) &&
6348 mangle_is_mangled(fname_src_mask, conn->params)) {
6349 char *new_mask = NULL;
6350 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6351 conn->params);
6352 if (new_mask) {
6353 TALLOC_FREE(fname_src_mask);
6354 fname_src_mask = new_mask;
6358 if (!src_has_wild) {
6359 files_struct *fsp;
6362 * Only one file needs to be renamed. Append the mask back
6363 * onto the directory.
6365 TALLOC_FREE(smb_fname_src->base_name);
6366 if (ISDOT(fname_src_dir)) {
6367 /* Ensure we use canonical names on open. */
6368 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6369 "%s",
6370 fname_src_mask);
6371 } else {
6372 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6373 "%s/%s",
6374 fname_src_dir,
6375 fname_src_mask);
6377 if (!smb_fname_src->base_name) {
6378 status = NT_STATUS_NO_MEMORY;
6379 goto out;
6382 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6383 "case_preserve = %d, short case preserve = %d, "
6384 "directory = %s, newname = %s, "
6385 "last_component_dest = %s\n",
6386 conn->case_sensitive, conn->case_preserve,
6387 conn->short_case_preserve,
6388 smb_fname_str_dbg(smb_fname_src),
6389 smb_fname_str_dbg(smb_fname_dst),
6390 smb_fname_dst->original_lcomp));
6392 /* The dest name still may have wildcards. */
6393 if (dest_has_wild) {
6394 char *fname_dst_mod = NULL;
6395 if (!resolve_wildcards(smb_fname_dst,
6396 smb_fname_src->base_name,
6397 smb_fname_dst->base_name,
6398 &fname_dst_mod)) {
6399 DEBUG(6, ("rename_internals: resolve_wildcards "
6400 "%s %s failed\n",
6401 smb_fname_src->base_name,
6402 smb_fname_dst->base_name));
6403 status = NT_STATUS_NO_MEMORY;
6404 goto out;
6406 TALLOC_FREE(smb_fname_dst->base_name);
6407 smb_fname_dst->base_name = fname_dst_mod;
6410 ZERO_STRUCT(smb_fname_src->st);
6411 if (posix_pathnames) {
6412 SMB_VFS_LSTAT(conn, smb_fname_src);
6413 } else {
6414 SMB_VFS_STAT(conn, smb_fname_src);
6417 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6418 create_options |= FILE_DIRECTORY_FILE;
6421 status = SMB_VFS_CREATE_FILE(
6422 conn, /* conn */
6423 req, /* req */
6424 0, /* root_dir_fid */
6425 smb_fname_src, /* fname */
6426 access_mask, /* access_mask */
6427 (FILE_SHARE_READ | /* share_access */
6428 FILE_SHARE_WRITE),
6429 FILE_OPEN, /* create_disposition*/
6430 create_options, /* create_options */
6431 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6432 0, /* oplock_request */
6433 0, /* allocation_size */
6434 0, /* private_flags */
6435 NULL, /* sd */
6436 NULL, /* ea_list */
6437 &fsp, /* result */
6438 NULL); /* pinfo */
6440 if (!NT_STATUS_IS_OK(status)) {
6441 DEBUG(3, ("Could not open rename source %s: %s\n",
6442 smb_fname_str_dbg(smb_fname_src),
6443 nt_errstr(status)));
6444 goto out;
6447 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6448 attrs, replace_if_exists);
6450 close_file(req, fsp, NORMAL_CLOSE);
6452 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6453 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6454 smb_fname_str_dbg(smb_fname_dst)));
6456 goto out;
6460 * Wildcards - process each file that matches.
6462 if (strequal(fname_src_mask, "????????.???")) {
6463 TALLOC_FREE(fname_src_mask);
6464 fname_src_mask = talloc_strdup(ctx, "*");
6465 if (!fname_src_mask) {
6466 status = NT_STATUS_NO_MEMORY;
6467 goto out;
6471 status = check_name(conn, fname_src_dir);
6472 if (!NT_STATUS_IS_OK(status)) {
6473 goto out;
6476 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6477 attrs);
6478 if (dir_hnd == NULL) {
6479 status = map_nt_error_from_unix(errno);
6480 goto out;
6483 status = NT_STATUS_NO_SUCH_FILE;
6485 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6486 * - gentest fix. JRA
6489 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6490 &talloced))) {
6491 files_struct *fsp = NULL;
6492 char *destname = NULL;
6493 bool sysdir_entry = False;
6495 /* Quick check for "." and ".." */
6496 if (ISDOT(dname) || ISDOTDOT(dname)) {
6497 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6498 sysdir_entry = True;
6499 } else {
6500 TALLOC_FREE(talloced);
6501 continue;
6505 if (!is_visible_file(conn, fname_src_dir, dname,
6506 &smb_fname_src->st, false)) {
6507 TALLOC_FREE(talloced);
6508 continue;
6511 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6512 TALLOC_FREE(talloced);
6513 continue;
6516 if (sysdir_entry) {
6517 status = NT_STATUS_OBJECT_NAME_INVALID;
6518 break;
6521 TALLOC_FREE(smb_fname_src->base_name);
6522 if (ISDOT(fname_src_dir)) {
6523 /* Ensure we use canonical names on open. */
6524 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6525 "%s",
6526 dname);
6527 } else {
6528 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6529 "%s/%s",
6530 fname_src_dir,
6531 dname);
6533 if (!smb_fname_src->base_name) {
6534 status = NT_STATUS_NO_MEMORY;
6535 goto out;
6538 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6539 smb_fname_dst->base_name,
6540 &destname)) {
6541 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6542 smb_fname_src->base_name, destname));
6543 TALLOC_FREE(talloced);
6544 continue;
6546 if (!destname) {
6547 status = NT_STATUS_NO_MEMORY;
6548 goto out;
6551 TALLOC_FREE(smb_fname_dst->base_name);
6552 smb_fname_dst->base_name = destname;
6554 ZERO_STRUCT(smb_fname_src->st);
6555 if (posix_pathnames) {
6556 SMB_VFS_LSTAT(conn, smb_fname_src);
6557 } else {
6558 SMB_VFS_STAT(conn, smb_fname_src);
6561 create_options = 0;
6563 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6564 create_options |= FILE_DIRECTORY_FILE;
6567 status = SMB_VFS_CREATE_FILE(
6568 conn, /* conn */
6569 req, /* req */
6570 0, /* root_dir_fid */
6571 smb_fname_src, /* fname */
6572 access_mask, /* access_mask */
6573 (FILE_SHARE_READ | /* share_access */
6574 FILE_SHARE_WRITE),
6575 FILE_OPEN, /* create_disposition*/
6576 create_options, /* create_options */
6577 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6578 0, /* oplock_request */
6579 0, /* allocation_size */
6580 0, /* private_flags */
6581 NULL, /* sd */
6582 NULL, /* ea_list */
6583 &fsp, /* result */
6584 NULL); /* pinfo */
6586 if (!NT_STATUS_IS_OK(status)) {
6587 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6588 "returned %s rename %s -> %s\n",
6589 nt_errstr(status),
6590 smb_fname_str_dbg(smb_fname_src),
6591 smb_fname_str_dbg(smb_fname_dst)));
6592 break;
6595 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6596 dname);
6597 if (!smb_fname_dst->original_lcomp) {
6598 status = NT_STATUS_NO_MEMORY;
6599 goto out;
6602 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6603 attrs, replace_if_exists);
6605 close_file(req, fsp, NORMAL_CLOSE);
6607 if (!NT_STATUS_IS_OK(status)) {
6608 DEBUG(3, ("rename_internals_fsp returned %s for "
6609 "rename %s -> %s\n", nt_errstr(status),
6610 smb_fname_str_dbg(smb_fname_src),
6611 smb_fname_str_dbg(smb_fname_dst)));
6612 break;
6615 count++;
6617 DEBUG(3,("rename_internals: doing rename on %s -> "
6618 "%s\n", smb_fname_str_dbg(smb_fname_src),
6619 smb_fname_str_dbg(smb_fname_src)));
6620 TALLOC_FREE(talloced);
6622 TALLOC_FREE(dir_hnd);
6624 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6625 status = map_nt_error_from_unix(errno);
6628 out:
6629 TALLOC_FREE(talloced);
6630 TALLOC_FREE(fname_src_dir);
6631 TALLOC_FREE(fname_src_mask);
6632 return status;
6635 /****************************************************************************
6636 Reply to a mv.
6637 ****************************************************************************/
6639 void reply_mv(struct smb_request *req)
6641 connection_struct *conn = req->conn;
6642 char *name = NULL;
6643 char *newname = NULL;
6644 const char *p;
6645 uint32 attrs;
6646 NTSTATUS status;
6647 bool src_has_wcard = False;
6648 bool dest_has_wcard = False;
6649 TALLOC_CTX *ctx = talloc_tos();
6650 struct smb_filename *smb_fname_src = NULL;
6651 struct smb_filename *smb_fname_dst = NULL;
6652 bool stream_rename = false;
6654 START_PROFILE(SMBmv);
6656 if (req->wct < 1) {
6657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6658 goto out;
6661 attrs = SVAL(req->vwv+0, 0);
6663 p = (const char *)req->buf + 1;
6664 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6665 &status, &src_has_wcard);
6666 if (!NT_STATUS_IS_OK(status)) {
6667 reply_nterror(req, status);
6668 goto out;
6670 p++;
6671 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6672 &status, &dest_has_wcard);
6673 if (!NT_STATUS_IS_OK(status)) {
6674 reply_nterror(req, status);
6675 goto out;
6678 if (!lp_posix_pathnames()) {
6679 /* The newname must begin with a ':' if the
6680 name contains a ':'. */
6681 if (strchr_m(name, ':')) {
6682 if (newname[0] != ':') {
6683 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6684 goto out;
6686 stream_rename = true;
6690 status = filename_convert(ctx,
6691 conn,
6692 req->flags2 & FLAGS2_DFS_PATHNAMES,
6693 name,
6694 UCF_COND_ALLOW_WCARD_LCOMP,
6695 &src_has_wcard,
6696 &smb_fname_src);
6698 if (!NT_STATUS_IS_OK(status)) {
6699 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6700 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6701 ERRSRV, ERRbadpath);
6702 goto out;
6704 reply_nterror(req, status);
6705 goto out;
6708 status = filename_convert(ctx,
6709 conn,
6710 req->flags2 & FLAGS2_DFS_PATHNAMES,
6711 newname,
6712 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6713 &dest_has_wcard,
6714 &smb_fname_dst);
6716 if (!NT_STATUS_IS_OK(status)) {
6717 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6718 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6719 ERRSRV, ERRbadpath);
6720 goto out;
6722 reply_nterror(req, status);
6723 goto out;
6726 if (stream_rename) {
6727 /* smb_fname_dst->base_name must be the same as
6728 smb_fname_src->base_name. */
6729 TALLOC_FREE(smb_fname_dst->base_name);
6730 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6731 smb_fname_src->base_name);
6732 if (!smb_fname_dst->base_name) {
6733 reply_nterror(req, NT_STATUS_NO_MEMORY);
6734 goto out;
6738 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6739 smb_fname_str_dbg(smb_fname_dst)));
6741 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6742 attrs, False, src_has_wcard, dest_has_wcard,
6743 DELETE_ACCESS);
6744 if (!NT_STATUS_IS_OK(status)) {
6745 if (open_was_deferred(req->sconn, req->mid)) {
6746 /* We have re-scheduled this call. */
6747 goto out;
6749 reply_nterror(req, status);
6750 goto out;
6753 reply_outbuf(req, 0, 0);
6754 out:
6755 TALLOC_FREE(smb_fname_src);
6756 TALLOC_FREE(smb_fname_dst);
6757 END_PROFILE(SMBmv);
6758 return;
6761 /*******************************************************************
6762 Copy a file as part of a reply_copy.
6763 ******************************************************************/
6766 * TODO: check error codes on all callers
6769 NTSTATUS copy_file(TALLOC_CTX *ctx,
6770 connection_struct *conn,
6771 struct smb_filename *smb_fname_src,
6772 struct smb_filename *smb_fname_dst,
6773 int ofun,
6774 int count,
6775 bool target_is_directory)
6777 struct smb_filename *smb_fname_dst_tmp = NULL;
6778 SMB_OFF_T ret=-1;
6779 files_struct *fsp1,*fsp2;
6780 uint32 dosattrs;
6781 uint32 new_create_disposition;
6782 NTSTATUS status;
6785 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6786 if (!NT_STATUS_IS_OK(status)) {
6787 return status;
6791 * If the target is a directory, extract the last component from the
6792 * src filename and append it to the dst filename
6794 if (target_is_directory) {
6795 const char *p;
6797 /* dest/target can't be a stream if it's a directory. */
6798 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6800 p = strrchr_m(smb_fname_src->base_name,'/');
6801 if (p) {
6802 p++;
6803 } else {
6804 p = smb_fname_src->base_name;
6806 smb_fname_dst_tmp->base_name =
6807 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6809 if (!smb_fname_dst_tmp->base_name) {
6810 status = NT_STATUS_NO_MEMORY;
6811 goto out;
6815 status = vfs_file_exist(conn, smb_fname_src);
6816 if (!NT_STATUS_IS_OK(status)) {
6817 goto out;
6820 if (!target_is_directory && count) {
6821 new_create_disposition = FILE_OPEN;
6822 } else {
6823 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6824 0, ofun,
6825 NULL, NULL,
6826 &new_create_disposition,
6827 NULL,
6828 NULL)) {
6829 status = NT_STATUS_INVALID_PARAMETER;
6830 goto out;
6834 /* Open the src file for reading. */
6835 status = SMB_VFS_CREATE_FILE(
6836 conn, /* conn */
6837 NULL, /* req */
6838 0, /* root_dir_fid */
6839 smb_fname_src, /* fname */
6840 FILE_GENERIC_READ, /* access_mask */
6841 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6842 FILE_OPEN, /* create_disposition*/
6843 0, /* create_options */
6844 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6845 INTERNAL_OPEN_ONLY, /* oplock_request */
6846 0, /* allocation_size */
6847 0, /* private_flags */
6848 NULL, /* sd */
6849 NULL, /* ea_list */
6850 &fsp1, /* result */
6851 NULL); /* psbuf */
6853 if (!NT_STATUS_IS_OK(status)) {
6854 goto out;
6857 dosattrs = dos_mode(conn, smb_fname_src);
6859 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6860 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6863 /* Open the dst file for writing. */
6864 status = SMB_VFS_CREATE_FILE(
6865 conn, /* conn */
6866 NULL, /* req */
6867 0, /* root_dir_fid */
6868 smb_fname_dst, /* fname */
6869 FILE_GENERIC_WRITE, /* access_mask */
6870 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6871 new_create_disposition, /* create_disposition*/
6872 0, /* create_options */
6873 dosattrs, /* file_attributes */
6874 INTERNAL_OPEN_ONLY, /* oplock_request */
6875 0, /* allocation_size */
6876 0, /* private_flags */
6877 NULL, /* sd */
6878 NULL, /* ea_list */
6879 &fsp2, /* result */
6880 NULL); /* psbuf */
6882 if (!NT_STATUS_IS_OK(status)) {
6883 close_file(NULL, fsp1, ERROR_CLOSE);
6884 goto out;
6887 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6888 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6889 if (ret == -1) {
6890 DEBUG(0, ("error - vfs lseek returned error %s\n",
6891 strerror(errno)));
6892 status = map_nt_error_from_unix(errno);
6893 close_file(NULL, fsp1, ERROR_CLOSE);
6894 close_file(NULL, fsp2, ERROR_CLOSE);
6895 goto out;
6899 /* Do the actual copy. */
6900 if (smb_fname_src->st.st_ex_size) {
6901 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6902 } else {
6903 ret = 0;
6906 close_file(NULL, fsp1, NORMAL_CLOSE);
6908 /* Ensure the modtime is set correctly on the destination file. */
6909 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6912 * As we are opening fsp1 read-only we only expect
6913 * an error on close on fsp2 if we are out of space.
6914 * Thus we don't look at the error return from the
6915 * close of fsp1.
6917 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6919 if (!NT_STATUS_IS_OK(status)) {
6920 goto out;
6923 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6924 status = NT_STATUS_DISK_FULL;
6925 goto out;
6928 status = NT_STATUS_OK;
6930 out:
6931 TALLOC_FREE(smb_fname_dst_tmp);
6932 return status;
6935 /****************************************************************************
6936 Reply to a file copy.
6937 ****************************************************************************/
6939 void reply_copy(struct smb_request *req)
6941 connection_struct *conn = req->conn;
6942 struct smb_filename *smb_fname_src = NULL;
6943 struct smb_filename *smb_fname_dst = NULL;
6944 char *fname_src = NULL;
6945 char *fname_dst = NULL;
6946 char *fname_src_mask = NULL;
6947 char *fname_src_dir = NULL;
6948 const char *p;
6949 int count=0;
6950 int error = ERRnoaccess;
6951 int tid2;
6952 int ofun;
6953 int flags;
6954 bool target_is_directory=False;
6955 bool source_has_wild = False;
6956 bool dest_has_wild = False;
6957 NTSTATUS status;
6958 TALLOC_CTX *ctx = talloc_tos();
6960 START_PROFILE(SMBcopy);
6962 if (req->wct < 3) {
6963 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6964 goto out;
6967 tid2 = SVAL(req->vwv+0, 0);
6968 ofun = SVAL(req->vwv+1, 0);
6969 flags = SVAL(req->vwv+2, 0);
6971 p = (const char *)req->buf;
6972 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6973 &status, &source_has_wild);
6974 if (!NT_STATUS_IS_OK(status)) {
6975 reply_nterror(req, status);
6976 goto out;
6978 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6979 &status, &dest_has_wild);
6980 if (!NT_STATUS_IS_OK(status)) {
6981 reply_nterror(req, status);
6982 goto out;
6985 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6987 if (tid2 != conn->cnum) {
6988 /* can't currently handle inter share copies XXXX */
6989 DEBUG(3,("Rejecting inter-share copy\n"));
6990 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6991 goto out;
6994 status = filename_convert(ctx, conn,
6995 req->flags2 & FLAGS2_DFS_PATHNAMES,
6996 fname_src,
6997 UCF_COND_ALLOW_WCARD_LCOMP,
6998 &source_has_wild,
6999 &smb_fname_src);
7000 if (!NT_STATUS_IS_OK(status)) {
7001 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7002 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7003 ERRSRV, ERRbadpath);
7004 goto out;
7006 reply_nterror(req, status);
7007 goto out;
7010 status = filename_convert(ctx, conn,
7011 req->flags2 & FLAGS2_DFS_PATHNAMES,
7012 fname_dst,
7013 UCF_COND_ALLOW_WCARD_LCOMP,
7014 &dest_has_wild,
7015 &smb_fname_dst);
7016 if (!NT_STATUS_IS_OK(status)) {
7017 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7018 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7019 ERRSRV, ERRbadpath);
7020 goto out;
7022 reply_nterror(req, status);
7023 goto out;
7026 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7028 if ((flags&1) && target_is_directory) {
7029 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7030 goto out;
7033 if ((flags&2) && !target_is_directory) {
7034 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7035 goto out;
7038 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7039 /* wants a tree copy! XXXX */
7040 DEBUG(3,("Rejecting tree copy\n"));
7041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7042 goto out;
7045 /* Split up the directory from the filename/mask. */
7046 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7047 &fname_src_dir, &fname_src_mask);
7048 if (!NT_STATUS_IS_OK(status)) {
7049 reply_nterror(req, NT_STATUS_NO_MEMORY);
7050 goto out;
7054 * We should only check the mangled cache
7055 * here if unix_convert failed. This means
7056 * that the path in 'mask' doesn't exist
7057 * on the file system and so we need to look
7058 * for a possible mangle. This patch from
7059 * Tine Smukavec <valentin.smukavec@hermes.si>.
7061 if (!VALID_STAT(smb_fname_src->st) &&
7062 mangle_is_mangled(fname_src_mask, conn->params)) {
7063 char *new_mask = NULL;
7064 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7065 &new_mask, conn->params);
7067 /* Use demangled name if one was successfully found. */
7068 if (new_mask) {
7069 TALLOC_FREE(fname_src_mask);
7070 fname_src_mask = new_mask;
7074 if (!source_has_wild) {
7077 * Only one file needs to be copied. Append the mask back onto
7078 * the directory.
7080 TALLOC_FREE(smb_fname_src->base_name);
7081 if (ISDOT(fname_src_dir)) {
7082 /* Ensure we use canonical names on open. */
7083 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7084 "%s",
7085 fname_src_mask);
7086 } else {
7087 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7088 "%s/%s",
7089 fname_src_dir,
7090 fname_src_mask);
7092 if (!smb_fname_src->base_name) {
7093 reply_nterror(req, NT_STATUS_NO_MEMORY);
7094 goto out;
7097 if (dest_has_wild) {
7098 char *fname_dst_mod = NULL;
7099 if (!resolve_wildcards(smb_fname_dst,
7100 smb_fname_src->base_name,
7101 smb_fname_dst->base_name,
7102 &fname_dst_mod)) {
7103 reply_nterror(req, NT_STATUS_NO_MEMORY);
7104 goto out;
7106 TALLOC_FREE(smb_fname_dst->base_name);
7107 smb_fname_dst->base_name = fname_dst_mod;
7110 status = check_name(conn, smb_fname_src->base_name);
7111 if (!NT_STATUS_IS_OK(status)) {
7112 reply_nterror(req, status);
7113 goto out;
7116 status = check_name(conn, smb_fname_dst->base_name);
7117 if (!NT_STATUS_IS_OK(status)) {
7118 reply_nterror(req, status);
7119 goto out;
7122 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7123 ofun, count, target_is_directory);
7125 if(!NT_STATUS_IS_OK(status)) {
7126 reply_nterror(req, status);
7127 goto out;
7128 } else {
7129 count++;
7131 } else {
7132 struct smb_Dir *dir_hnd = NULL;
7133 const char *dname = NULL;
7134 char *talloced = NULL;
7135 long offset = 0;
7138 * There is a wildcard that requires us to actually read the
7139 * src dir and copy each file matching the mask to the dst.
7140 * Right now streams won't be copied, but this could
7141 * presumably be added with a nested loop for reach dir entry.
7143 SMB_ASSERT(!smb_fname_src->stream_name);
7144 SMB_ASSERT(!smb_fname_dst->stream_name);
7146 smb_fname_src->stream_name = NULL;
7147 smb_fname_dst->stream_name = NULL;
7149 if (strequal(fname_src_mask,"????????.???")) {
7150 TALLOC_FREE(fname_src_mask);
7151 fname_src_mask = talloc_strdup(ctx, "*");
7152 if (!fname_src_mask) {
7153 reply_nterror(req, NT_STATUS_NO_MEMORY);
7154 goto out;
7158 status = check_name(conn, fname_src_dir);
7159 if (!NT_STATUS_IS_OK(status)) {
7160 reply_nterror(req, status);
7161 goto out;
7164 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7165 if (dir_hnd == NULL) {
7166 status = map_nt_error_from_unix(errno);
7167 reply_nterror(req, status);
7168 goto out;
7171 error = ERRbadfile;
7173 /* Iterate over the src dir copying each entry to the dst. */
7174 while ((dname = ReadDirName(dir_hnd, &offset,
7175 &smb_fname_src->st, &talloced))) {
7176 char *destname = NULL;
7178 if (ISDOT(dname) || ISDOTDOT(dname)) {
7179 TALLOC_FREE(talloced);
7180 continue;
7183 if (!is_visible_file(conn, fname_src_dir, dname,
7184 &smb_fname_src->st, false)) {
7185 TALLOC_FREE(talloced);
7186 continue;
7189 if(!mask_match(dname, fname_src_mask,
7190 conn->case_sensitive)) {
7191 TALLOC_FREE(talloced);
7192 continue;
7195 error = ERRnoaccess;
7197 /* Get the src smb_fname struct setup. */
7198 TALLOC_FREE(smb_fname_src->base_name);
7199 if (ISDOT(fname_src_dir)) {
7200 /* Ensure we use canonical names on open. */
7201 smb_fname_src->base_name =
7202 talloc_asprintf(smb_fname_src, "%s",
7203 dname);
7204 } else {
7205 smb_fname_src->base_name =
7206 talloc_asprintf(smb_fname_src, "%s/%s",
7207 fname_src_dir, dname);
7210 if (!smb_fname_src->base_name) {
7211 TALLOC_FREE(dir_hnd);
7212 TALLOC_FREE(talloced);
7213 reply_nterror(req, NT_STATUS_NO_MEMORY);
7214 goto out;
7217 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7218 smb_fname_dst->base_name,
7219 &destname)) {
7220 TALLOC_FREE(talloced);
7221 continue;
7223 if (!destname) {
7224 TALLOC_FREE(dir_hnd);
7225 TALLOC_FREE(talloced);
7226 reply_nterror(req, NT_STATUS_NO_MEMORY);
7227 goto out;
7230 TALLOC_FREE(smb_fname_dst->base_name);
7231 smb_fname_dst->base_name = destname;
7233 status = check_name(conn, smb_fname_src->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 status = check_name(conn, smb_fname_dst->base_name);
7242 if (!NT_STATUS_IS_OK(status)) {
7243 TALLOC_FREE(dir_hnd);
7244 TALLOC_FREE(talloced);
7245 reply_nterror(req, status);
7246 goto out;
7249 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7250 smb_fname_src->base_name,
7251 smb_fname_dst->base_name));
7253 status = copy_file(ctx, conn, smb_fname_src,
7254 smb_fname_dst, ofun, count,
7255 target_is_directory);
7256 if (NT_STATUS_IS_OK(status)) {
7257 count++;
7260 TALLOC_FREE(talloced);
7262 TALLOC_FREE(dir_hnd);
7265 if (count == 0) {
7266 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7267 goto out;
7270 reply_outbuf(req, 1, 0);
7271 SSVAL(req->outbuf,smb_vwv0,count);
7272 out:
7273 TALLOC_FREE(smb_fname_src);
7274 TALLOC_FREE(smb_fname_dst);
7275 TALLOC_FREE(fname_src);
7276 TALLOC_FREE(fname_dst);
7277 TALLOC_FREE(fname_src_mask);
7278 TALLOC_FREE(fname_src_dir);
7280 END_PROFILE(SMBcopy);
7281 return;
7284 #undef DBGC_CLASS
7285 #define DBGC_CLASS DBGC_LOCKING
7287 /****************************************************************************
7288 Get a lock pid, dealing with large count requests.
7289 ****************************************************************************/
7291 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7292 bool large_file_format)
7294 if(!large_file_format)
7295 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7296 else
7297 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7300 /****************************************************************************
7301 Get a lock count, dealing with large count requests.
7302 ****************************************************************************/
7304 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7305 bool large_file_format)
7307 uint64_t count = 0;
7309 if(!large_file_format) {
7310 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7311 } else {
7313 #if defined(HAVE_LONGLONG)
7314 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7315 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7316 #else /* HAVE_LONGLONG */
7319 * NT4.x seems to be broken in that it sends large file (64 bit)
7320 * lockingX calls even if the CAP_LARGE_FILES was *not*
7321 * negotiated. For boxes without large unsigned ints truncate the
7322 * lock count by dropping the top 32 bits.
7325 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7326 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7327 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7328 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7329 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7332 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7333 #endif /* HAVE_LONGLONG */
7336 return count;
7339 #if !defined(HAVE_LONGLONG)
7340 /****************************************************************************
7341 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7342 ****************************************************************************/
7344 static uint32 map_lock_offset(uint32 high, uint32 low)
7346 unsigned int i;
7347 uint32 mask = 0;
7348 uint32 highcopy = high;
7351 * Try and find out how many significant bits there are in high.
7354 for(i = 0; highcopy; i++)
7355 highcopy >>= 1;
7358 * We use 31 bits not 32 here as POSIX
7359 * lock offsets may not be negative.
7362 mask = (~0) << (31 - i);
7364 if(low & mask)
7365 return 0; /* Fail. */
7367 high <<= (31 - i);
7369 return (high|low);
7371 #endif /* !defined(HAVE_LONGLONG) */
7373 /****************************************************************************
7374 Get a lock offset, dealing with large offset requests.
7375 ****************************************************************************/
7377 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7378 bool large_file_format, bool *err)
7380 uint64_t offset = 0;
7382 *err = False;
7384 if(!large_file_format) {
7385 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7386 } else {
7388 #if defined(HAVE_LONGLONG)
7389 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7390 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7391 #else /* HAVE_LONGLONG */
7394 * NT4.x seems to be broken in that it sends large file (64 bit)
7395 * lockingX calls even if the CAP_LARGE_FILES was *not*
7396 * negotiated. For boxes without large unsigned ints mangle the
7397 * lock offset by mapping the top 32 bits onto the lower 32.
7400 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7401 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7402 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7403 uint32 new_low = 0;
7405 if((new_low = map_lock_offset(high, low)) == 0) {
7406 *err = True;
7407 return (uint64_t)-1;
7410 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7411 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7412 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7413 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7416 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7417 #endif /* HAVE_LONGLONG */
7420 return offset;
7423 NTSTATUS smbd_do_locking(struct smb_request *req,
7424 files_struct *fsp,
7425 uint8_t type,
7426 int32_t timeout,
7427 uint16_t num_ulocks,
7428 struct smbd_lock_element *ulocks,
7429 uint16_t num_locks,
7430 struct smbd_lock_element *locks,
7431 bool *async)
7433 connection_struct *conn = req->conn;
7434 int i;
7435 NTSTATUS status = NT_STATUS_OK;
7437 *async = false;
7439 /* Data now points at the beginning of the list
7440 of smb_unlkrng structs */
7441 for(i = 0; i < (int)num_ulocks; i++) {
7442 struct smbd_lock_element *e = &ulocks[i];
7444 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7445 "pid %u, file %s\n",
7446 (double)e->offset,
7447 (double)e->count,
7448 (unsigned int)e->smblctx,
7449 fsp_str_dbg(fsp)));
7451 if (e->brltype != UNLOCK_LOCK) {
7452 /* this can only happen with SMB2 */
7453 return NT_STATUS_INVALID_PARAMETER;
7456 status = do_unlock(req->sconn->msg_ctx,
7457 fsp,
7458 e->smblctx,
7459 e->count,
7460 e->offset,
7461 WINDOWS_LOCK);
7463 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7464 nt_errstr(status)));
7466 if (!NT_STATUS_IS_OK(status)) {
7467 return status;
7471 /* Setup the timeout in seconds. */
7473 if (!lp_blocking_locks(SNUM(conn))) {
7474 timeout = 0;
7477 /* Data now points at the beginning of the list
7478 of smb_lkrng structs */
7480 for(i = 0; i < (int)num_locks; i++) {
7481 struct smbd_lock_element *e = &locks[i];
7483 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7484 "%llu, file %s timeout = %d\n",
7485 (double)e->offset,
7486 (double)e->count,
7487 (unsigned long long)e->smblctx,
7488 fsp_str_dbg(fsp),
7489 (int)timeout));
7491 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7492 struct blocking_lock_record *blr = NULL;
7494 if (num_locks > 1) {
7496 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7497 * if the lock vector contains one entry. When given mutliple cancel
7498 * requests in a single PDU we expect the server to return an
7499 * error. Windows servers seem to accept the request but only
7500 * cancel the first lock.
7501 * JRA - Do what Windows does (tm) :-).
7504 #if 0
7505 /* MS-CIFS (2.2.4.32.1) behavior. */
7506 return NT_STATUS_DOS(ERRDOS,
7507 ERRcancelviolation);
7508 #else
7509 /* Windows behavior. */
7510 if (i != 0) {
7511 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7512 "cancel request\n"));
7513 continue;
7515 #endif
7518 if (lp_blocking_locks(SNUM(conn))) {
7520 /* Schedule a message to ourselves to
7521 remove the blocking lock record and
7522 return the right error. */
7524 blr = blocking_lock_cancel_smb1(fsp,
7525 e->smblctx,
7526 e->offset,
7527 e->count,
7528 WINDOWS_LOCK,
7529 type,
7530 NT_STATUS_FILE_LOCK_CONFLICT);
7531 if (blr == NULL) {
7532 return NT_STATUS_DOS(
7533 ERRDOS,
7534 ERRcancelviolation);
7537 /* Remove a matching pending lock. */
7538 status = do_lock_cancel(fsp,
7539 e->smblctx,
7540 e->count,
7541 e->offset,
7542 WINDOWS_LOCK,
7543 blr);
7544 } else {
7545 bool blocking_lock = timeout ? true : false;
7546 bool defer_lock = false;
7547 struct byte_range_lock *br_lck;
7548 uint64_t block_smblctx;
7550 br_lck = do_lock(req->sconn->msg_ctx,
7551 fsp,
7552 e->smblctx,
7553 e->count,
7554 e->offset,
7555 e->brltype,
7556 WINDOWS_LOCK,
7557 blocking_lock,
7558 &status,
7559 &block_smblctx,
7560 NULL);
7562 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7563 /* Windows internal resolution for blocking locks seems
7564 to be about 200ms... Don't wait for less than that. JRA. */
7565 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7566 timeout = lp_lock_spin_time();
7568 defer_lock = true;
7571 /* If a lock sent with timeout of zero would fail, and
7572 * this lock has been requested multiple times,
7573 * according to brl_lock_failed() we convert this
7574 * request to a blocking lock with a timeout of between
7575 * 150 - 300 milliseconds.
7577 * If lp_lock_spin_time() has been set to 0, we skip
7578 * this blocking retry and fail immediately.
7580 * Replacement for do_lock_spin(). JRA. */
7582 if (!req->sconn->using_smb2 &&
7583 br_lck && lp_blocking_locks(SNUM(conn)) &&
7584 lp_lock_spin_time() && !blocking_lock &&
7585 NT_STATUS_EQUAL((status),
7586 NT_STATUS_FILE_LOCK_CONFLICT))
7588 defer_lock = true;
7589 timeout = lp_lock_spin_time();
7592 if (br_lck && defer_lock) {
7594 * A blocking lock was requested. Package up
7595 * this smb into a queued request and push it
7596 * onto the blocking lock queue.
7598 if(push_blocking_lock_request(br_lck,
7599 req,
7600 fsp,
7601 timeout,
7603 e->smblctx,
7604 e->brltype,
7605 WINDOWS_LOCK,
7606 e->offset,
7607 e->count,
7608 block_smblctx)) {
7609 TALLOC_FREE(br_lck);
7610 *async = true;
7611 return NT_STATUS_OK;
7615 TALLOC_FREE(br_lck);
7618 if (!NT_STATUS_IS_OK(status)) {
7619 break;
7623 /* If any of the above locks failed, then we must unlock
7624 all of the previous locks (X/Open spec). */
7626 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7628 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7629 i = -1; /* we want to skip the for loop */
7633 * Ensure we don't do a remove on the lock that just failed,
7634 * as under POSIX rules, if we have a lock already there, we
7635 * will delete it (and we shouldn't) .....
7637 for(i--; i >= 0; i--) {
7638 struct smbd_lock_element *e = &locks[i];
7640 do_unlock(req->sconn->msg_ctx,
7641 fsp,
7642 e->smblctx,
7643 e->count,
7644 e->offset,
7645 WINDOWS_LOCK);
7647 return status;
7650 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7651 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7653 return NT_STATUS_OK;
7656 /****************************************************************************
7657 Reply to a lockingX request.
7658 ****************************************************************************/
7660 void reply_lockingX(struct smb_request *req)
7662 connection_struct *conn = req->conn;
7663 files_struct *fsp;
7664 unsigned char locktype;
7665 unsigned char oplocklevel;
7666 uint16 num_ulocks;
7667 uint16 num_locks;
7668 int32 lock_timeout;
7669 int i;
7670 const uint8_t *data;
7671 bool large_file_format;
7672 bool err;
7673 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7674 struct smbd_lock_element *ulocks;
7675 struct smbd_lock_element *locks;
7676 bool async = false;
7678 START_PROFILE(SMBlockingX);
7680 if (req->wct < 8) {
7681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7682 END_PROFILE(SMBlockingX);
7683 return;
7686 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7687 locktype = CVAL(req->vwv+3, 0);
7688 oplocklevel = CVAL(req->vwv+3, 1);
7689 num_ulocks = SVAL(req->vwv+6, 0);
7690 num_locks = SVAL(req->vwv+7, 0);
7691 lock_timeout = IVAL(req->vwv+4, 0);
7692 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7694 if (!check_fsp(conn, req, fsp)) {
7695 END_PROFILE(SMBlockingX);
7696 return;
7699 data = req->buf;
7701 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7702 /* we don't support these - and CANCEL_LOCK makes w2k
7703 and XP reboot so I don't really want to be
7704 compatible! (tridge) */
7705 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7706 END_PROFILE(SMBlockingX);
7707 return;
7710 /* Check if this is an oplock break on a file
7711 we have granted an oplock on.
7713 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7714 /* Client can insist on breaking to none. */
7715 bool break_to_none = (oplocklevel == 0);
7716 bool result;
7718 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7719 "for fnum = %d\n", (unsigned int)oplocklevel,
7720 fsp->fnum ));
7723 * Make sure we have granted an exclusive or batch oplock on
7724 * this file.
7727 if (fsp->oplock_type == 0) {
7729 /* The Samba4 nbench simulator doesn't understand
7730 the difference between break to level2 and break
7731 to none from level2 - it sends oplock break
7732 replies in both cases. Don't keep logging an error
7733 message here - just ignore it. JRA. */
7735 DEBUG(5,("reply_lockingX: Error : oplock break from "
7736 "client for fnum = %d (oplock=%d) and no "
7737 "oplock granted on this file (%s).\n",
7738 fsp->fnum, fsp->oplock_type,
7739 fsp_str_dbg(fsp)));
7741 /* if this is a pure oplock break request then don't
7742 * send a reply */
7743 if (num_locks == 0 && num_ulocks == 0) {
7744 END_PROFILE(SMBlockingX);
7745 return;
7746 } else {
7747 END_PROFILE(SMBlockingX);
7748 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7749 return;
7753 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7754 (break_to_none)) {
7755 result = remove_oplock(fsp);
7756 } else {
7757 result = downgrade_oplock(fsp);
7760 if (!result) {
7761 DEBUG(0, ("reply_lockingX: error in removing "
7762 "oplock on file %s\n", fsp_str_dbg(fsp)));
7763 /* Hmmm. Is this panic justified? */
7764 smb_panic("internal tdb error");
7767 reply_to_oplock_break_requests(fsp);
7769 /* if this is a pure oplock break request then don't send a
7770 * reply */
7771 if (num_locks == 0 && num_ulocks == 0) {
7772 /* Sanity check - ensure a pure oplock break is not a
7773 chained request. */
7774 if(CVAL(req->vwv+0, 0) != 0xff)
7775 DEBUG(0,("reply_lockingX: Error : pure oplock "
7776 "break is a chained %d request !\n",
7777 (unsigned int)CVAL(req->vwv+0, 0)));
7778 END_PROFILE(SMBlockingX);
7779 return;
7783 if (req->buflen <
7784 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7786 END_PROFILE(SMBlockingX);
7787 return;
7790 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7791 if (ulocks == NULL) {
7792 reply_nterror(req, NT_STATUS_NO_MEMORY);
7793 END_PROFILE(SMBlockingX);
7794 return;
7797 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7798 if (locks == NULL) {
7799 reply_nterror(req, NT_STATUS_NO_MEMORY);
7800 END_PROFILE(SMBlockingX);
7801 return;
7804 /* Data now points at the beginning of the list
7805 of smb_unlkrng structs */
7806 for(i = 0; i < (int)num_ulocks; i++) {
7807 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7808 ulocks[i].count = get_lock_count(data, i, large_file_format);
7809 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7810 ulocks[i].brltype = UNLOCK_LOCK;
7813 * There is no error code marked "stupid client bug".... :-).
7815 if(err) {
7816 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7817 END_PROFILE(SMBlockingX);
7818 return;
7822 /* Now do any requested locks */
7823 data += ((large_file_format ? 20 : 10)*num_ulocks);
7825 /* Data now points at the beginning of the list
7826 of smb_lkrng structs */
7828 for(i = 0; i < (int)num_locks; i++) {
7829 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7830 locks[i].count = get_lock_count(data, i, large_file_format);
7831 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7833 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7834 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7835 locks[i].brltype = PENDING_READ_LOCK;
7836 } else {
7837 locks[i].brltype = READ_LOCK;
7839 } else {
7840 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7841 locks[i].brltype = PENDING_WRITE_LOCK;
7842 } else {
7843 locks[i].brltype = WRITE_LOCK;
7848 * There is no error code marked "stupid client bug".... :-).
7850 if(err) {
7851 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7852 END_PROFILE(SMBlockingX);
7853 return;
7857 status = smbd_do_locking(req, fsp,
7858 locktype, lock_timeout,
7859 num_ulocks, ulocks,
7860 num_locks, locks,
7861 &async);
7862 if (!NT_STATUS_IS_OK(status)) {
7863 END_PROFILE(SMBlockingX);
7864 reply_nterror(req, status);
7865 return;
7867 if (async) {
7868 END_PROFILE(SMBlockingX);
7869 return;
7872 reply_outbuf(req, 2, 0);
7874 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7875 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7877 END_PROFILE(SMBlockingX);
7878 chain_reply(req);
7881 #undef DBGC_CLASS
7882 #define DBGC_CLASS DBGC_ALL
7884 /****************************************************************************
7885 Reply to a SMBreadbmpx (read block multiplex) request.
7886 Always reply with an error, if someone has a platform really needs this,
7887 please contact vl@samba.org
7888 ****************************************************************************/
7890 void reply_readbmpx(struct smb_request *req)
7892 START_PROFILE(SMBreadBmpx);
7893 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7894 END_PROFILE(SMBreadBmpx);
7895 return;
7898 /****************************************************************************
7899 Reply to a SMBreadbs (read block multiplex secondary) request.
7900 Always reply with an error, if someone has a platform really needs this,
7901 please contact vl@samba.org
7902 ****************************************************************************/
7904 void reply_readbs(struct smb_request *req)
7906 START_PROFILE(SMBreadBs);
7907 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7908 END_PROFILE(SMBreadBs);
7909 return;
7912 /****************************************************************************
7913 Reply to a SMBsetattrE.
7914 ****************************************************************************/
7916 void reply_setattrE(struct smb_request *req)
7918 connection_struct *conn = req->conn;
7919 struct smb_file_time ft;
7920 files_struct *fsp;
7921 NTSTATUS status;
7923 START_PROFILE(SMBsetattrE);
7924 ZERO_STRUCT(ft);
7926 if (req->wct < 7) {
7927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7928 goto out;
7931 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7933 if(!fsp || (fsp->conn != conn)) {
7934 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7935 goto out;
7939 * Convert the DOS times into unix times.
7942 ft.atime = convert_time_t_to_timespec(
7943 srv_make_unix_date2(req->vwv+3));
7944 ft.mtime = convert_time_t_to_timespec(
7945 srv_make_unix_date2(req->vwv+5));
7946 ft.create_time = convert_time_t_to_timespec(
7947 srv_make_unix_date2(req->vwv+1));
7949 reply_outbuf(req, 0, 0);
7952 * Patch from Ray Frush <frush@engr.colostate.edu>
7953 * Sometimes times are sent as zero - ignore them.
7956 /* Ensure we have a valid stat struct for the source. */
7957 status = vfs_stat_fsp(fsp);
7958 if (!NT_STATUS_IS_OK(status)) {
7959 reply_nterror(req, status);
7960 goto out;
7963 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7964 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7965 goto out;
7968 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7969 if (!NT_STATUS_IS_OK(status)) {
7970 reply_nterror(req, status);
7971 goto out;
7974 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7975 " createtime=%u\n",
7976 fsp->fnum,
7977 (unsigned int)ft.atime.tv_sec,
7978 (unsigned int)ft.mtime.tv_sec,
7979 (unsigned int)ft.create_time.tv_sec
7981 out:
7982 END_PROFILE(SMBsetattrE);
7983 return;
7987 /* Back from the dead for OS/2..... JRA. */
7989 /****************************************************************************
7990 Reply to a SMBwritebmpx (write block multiplex primary) request.
7991 Always reply with an error, if someone has a platform really needs this,
7992 please contact vl@samba.org
7993 ****************************************************************************/
7995 void reply_writebmpx(struct smb_request *req)
7997 START_PROFILE(SMBwriteBmpx);
7998 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7999 END_PROFILE(SMBwriteBmpx);
8000 return;
8003 /****************************************************************************
8004 Reply to a SMBwritebs (write block multiplex secondary) request.
8005 Always reply with an error, if someone has a platform really needs this,
8006 please contact vl@samba.org
8007 ****************************************************************************/
8009 void reply_writebs(struct smb_request *req)
8011 START_PROFILE(SMBwriteBs);
8012 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8013 END_PROFILE(SMBwriteBs);
8014 return;
8017 /****************************************************************************
8018 Reply to a SMBgetattrE.
8019 ****************************************************************************/
8021 void reply_getattrE(struct smb_request *req)
8023 connection_struct *conn = req->conn;
8024 int mode;
8025 files_struct *fsp;
8026 struct timespec create_ts;
8028 START_PROFILE(SMBgetattrE);
8030 if (req->wct < 1) {
8031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8032 END_PROFILE(SMBgetattrE);
8033 return;
8036 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8038 if(!fsp || (fsp->conn != conn)) {
8039 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8040 END_PROFILE(SMBgetattrE);
8041 return;
8044 /* Do an fstat on this file */
8045 if(fsp_stat(fsp)) {
8046 reply_nterror(req, map_nt_error_from_unix(errno));
8047 END_PROFILE(SMBgetattrE);
8048 return;
8051 mode = dos_mode(conn, fsp->fsp_name);
8054 * Convert the times into dos times. Set create
8055 * date to be last modify date as UNIX doesn't save
8056 * this.
8059 reply_outbuf(req, 11, 0);
8061 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8062 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8063 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8064 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8065 /* Should we check pending modtime here ? JRA */
8066 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8067 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8069 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8070 SIVAL(req->outbuf, smb_vwv6, 0);
8071 SIVAL(req->outbuf, smb_vwv8, 0);
8072 } else {
8073 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8074 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8075 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8077 SSVAL(req->outbuf,smb_vwv10, mode);
8079 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8081 END_PROFILE(SMBgetattrE);
8082 return;