Use new common function.
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blob080be5cc941f6b5b35950013dc16251be5a688a6
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 = NBT_SMB_PORT;
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) != NBT_SMB_PORT) {
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 reload_services(sconn, conn_snum_used, true);
603 reopen_logs();
605 sconn->nbt.got_session = true;
606 break;
609 case 0x89: /* session keepalive request
610 (some old clients produce this?) */
611 SCVAL(outbuf,0,NBSSkeepalive);
612 SCVAL(outbuf,3,0);
613 break;
615 case NBSSpositive: /* positive session response */
616 case NBSSnegative: /* negative session response */
617 case NBSSretarget: /* retarget session response */
618 DEBUG(0,("Unexpected session response\n"));
619 break;
621 case NBSSkeepalive: /* session keepalive */
622 default:
623 return;
626 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
627 msg_type, msg_flags));
629 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
631 if (CVAL(outbuf, 0) != 0x82) {
632 exit_server_cleanly("invalid netbios session");
634 return;
637 /****************************************************************************
638 Reply to a tcon.
639 conn POINTER CAN BE NULL HERE !
640 ****************************************************************************/
642 void reply_tcon(struct smb_request *req)
644 connection_struct *conn = req->conn;
645 const char *service;
646 char *service_buf = NULL;
647 char *password = NULL;
648 char *dev = NULL;
649 int pwlen=0;
650 NTSTATUS nt_status;
651 const char *p;
652 TALLOC_CTX *ctx = talloc_tos();
653 struct smbd_server_connection *sconn = req->sconn;
655 START_PROFILE(SMBtcon);
657 if (req->buflen < 4) {
658 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
659 END_PROFILE(SMBtcon);
660 return;
663 p = (const char *)req->buf + 1;
664 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
665 p += 1;
666 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
667 p += pwlen+1;
668 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
669 p += 1;
671 if (service_buf == NULL || password == NULL || dev == NULL) {
672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
673 END_PROFILE(SMBtcon);
674 return;
676 p = strrchr_m(service_buf,'\\');
677 if (p) {
678 service = p+1;
679 } else {
680 service = service_buf;
683 conn = make_connection(sconn,service,dev,
684 req->vuid,&nt_status);
685 req->conn = conn;
687 if (!conn) {
688 reply_nterror(req, nt_status);
689 END_PROFILE(SMBtcon);
690 return;
693 reply_outbuf(req, 2, 0);
694 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
695 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
696 SSVAL(req->outbuf,smb_tid,conn->cnum);
698 DEBUG(3,("tcon service=%s cnum=%d\n",
699 service, conn->cnum));
701 END_PROFILE(SMBtcon);
702 return;
705 /****************************************************************************
706 Reply to a tcon and X.
707 conn POINTER CAN BE NULL HERE !
708 ****************************************************************************/
710 void reply_tcon_and_X(struct smb_request *req)
712 connection_struct *conn = req->conn;
713 const char *service = NULL;
714 TALLOC_CTX *ctx = talloc_tos();
715 /* what the cleint thinks the device is */
716 char *client_devicetype = NULL;
717 /* what the server tells the client the share represents */
718 const char *server_devicetype;
719 NTSTATUS nt_status;
720 int passlen;
721 char *path = NULL;
722 const char *p, *q;
723 uint16 tcon_flags;
724 struct smbd_server_connection *sconn = req->sconn;
726 START_PROFILE(SMBtconX);
728 if (req->wct < 4) {
729 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
730 END_PROFILE(SMBtconX);
731 return;
734 passlen = SVAL(req->vwv+3, 0);
735 tcon_flags = SVAL(req->vwv+2, 0);
737 /* we might have to close an old one */
738 if ((tcon_flags & 0x1) && conn) {
739 struct smbXsrv_tcon *tcon;
740 NTSTATUS status;
742 tcon = conn->tcon;
743 req->conn = NULL;
744 conn = NULL;
747 * TODO: cancel all outstanding requests on the tcon
749 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
750 if (!NT_STATUS_IS_OK(status)) {
751 DEBUG(0, ("reply_tcon_and_X: "
752 "smbXsrv_tcon_disconnect() failed: %s\n",
753 nt_errstr(status)));
755 * If we hit this case, there is something completely
756 * wrong, so we better disconnect the transport connection.
758 END_PROFILE(SMBtconX);
759 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
760 return;
763 TALLOC_FREE(tcon);
766 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
767 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
768 END_PROFILE(SMBtconX);
769 return;
772 if (sconn->smb1.negprot.encrypted_passwords) {
773 p = (const char *)req->buf + passlen;
774 } else {
775 p = (const char *)req->buf + passlen + 1;
778 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
780 if (path == NULL) {
781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
782 END_PROFILE(SMBtconX);
783 return;
787 * the service name can be either: \\server\share
788 * or share directly like on the DELL PowerVault 705
790 if (*path=='\\') {
791 q = strchr_m(path+2,'\\');
792 if (!q) {
793 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
794 END_PROFILE(SMBtconX);
795 return;
797 service = q+1;
798 } else {
799 service = path;
802 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
803 &client_devicetype, p,
804 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
806 if (client_devicetype == NULL) {
807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
808 END_PROFILE(SMBtconX);
809 return;
812 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
814 conn = make_connection(sconn, service, client_devicetype,
815 req->vuid, &nt_status);
816 req->conn =conn;
818 if (!conn) {
819 reply_nterror(req, nt_status);
820 END_PROFILE(SMBtconX);
821 return;
824 if ( IS_IPC(conn) )
825 server_devicetype = "IPC";
826 else if ( IS_PRINT(conn) )
827 server_devicetype = "LPT1:";
828 else
829 server_devicetype = "A:";
831 if (get_Protocol() < PROTOCOL_NT1) {
832 reply_outbuf(req, 2, 0);
833 if (message_push_string(&req->outbuf, server_devicetype,
834 STR_TERMINATE|STR_ASCII) == -1) {
835 reply_nterror(req, NT_STATUS_NO_MEMORY);
836 END_PROFILE(SMBtconX);
837 return;
839 } else {
840 /* NT sets the fstype of IPC$ to the null string */
841 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
843 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
844 /* Return permissions. */
845 uint32 perm1 = 0;
846 uint32 perm2 = 0;
848 reply_outbuf(req, 7, 0);
850 if (IS_IPC(conn)) {
851 perm1 = FILE_ALL_ACCESS;
852 perm2 = FILE_ALL_ACCESS;
853 } else {
854 perm1 = conn->share_access;
857 SIVAL(req->outbuf, smb_vwv3, perm1);
858 SIVAL(req->outbuf, smb_vwv5, perm2);
859 } else {
860 reply_outbuf(req, 3, 0);
863 if ((message_push_string(&req->outbuf, server_devicetype,
864 STR_TERMINATE|STR_ASCII) == -1)
865 || (message_push_string(&req->outbuf, fstype,
866 STR_TERMINATE) == -1)) {
867 reply_nterror(req, NT_STATUS_NO_MEMORY);
868 END_PROFILE(SMBtconX);
869 return;
872 /* what does setting this bit do? It is set by NT4 and
873 may affect the ability to autorun mounted cdroms */
874 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
875 (lp_csc_policy(SNUM(conn)) << 2));
877 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
878 DEBUG(2,("Serving %s as a Dfs root\n",
879 lp_servicename(SNUM(conn)) ));
880 SSVAL(req->outbuf, smb_vwv2,
881 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
885 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
886 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
888 DEBUG(3,("tconX service=%s \n",
889 service));
891 /* set the incoming and outgoing tid to the just created one */
892 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
893 SSVAL(req->outbuf,smb_tid,conn->cnum);
895 END_PROFILE(SMBtconX);
897 req->tid = conn->cnum;
900 /****************************************************************************
901 Reply to an unknown type.
902 ****************************************************************************/
904 void reply_unknown_new(struct smb_request *req, uint8 type)
906 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
907 smb_fn_name(type), type, type));
908 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
909 return;
912 /****************************************************************************
913 Reply to an ioctl.
914 conn POINTER CAN BE NULL HERE !
915 ****************************************************************************/
917 void reply_ioctl(struct smb_request *req)
919 connection_struct *conn = req->conn;
920 uint16 device;
921 uint16 function;
922 uint32 ioctl_code;
923 int replysize;
924 char *p;
926 START_PROFILE(SMBioctl);
928 if (req->wct < 3) {
929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
930 END_PROFILE(SMBioctl);
931 return;
934 device = SVAL(req->vwv+1, 0);
935 function = SVAL(req->vwv+2, 0);
936 ioctl_code = (device << 16) + function;
938 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
940 switch (ioctl_code) {
941 case IOCTL_QUERY_JOB_INFO:
942 replysize = 32;
943 break;
944 default:
945 reply_force_doserror(req, ERRSRV, ERRnosupport);
946 END_PROFILE(SMBioctl);
947 return;
950 reply_outbuf(req, 8, replysize+1);
951 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
952 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
953 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
954 p = smb_buf(req->outbuf);
955 memset(p, '\0', replysize+1); /* valgrind-safe. */
956 p += 1; /* Allow for alignment */
958 switch (ioctl_code) {
959 case IOCTL_QUERY_JOB_INFO:
961 files_struct *fsp = file_fsp(
962 req, SVAL(req->vwv+0, 0));
963 if (!fsp) {
964 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
965 END_PROFILE(SMBioctl);
966 return;
968 /* Job number */
969 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
971 srvstr_push((char *)req->outbuf, req->flags2, p+2,
972 lp_netbios_name(), 15,
973 STR_TERMINATE|STR_ASCII);
974 if (conn) {
975 srvstr_push((char *)req->outbuf, req->flags2,
976 p+18, lp_servicename(SNUM(conn)),
977 13, STR_TERMINATE|STR_ASCII);
978 } else {
979 memset(p+18, 0, 13);
981 break;
985 END_PROFILE(SMBioctl);
986 return;
989 /****************************************************************************
990 Strange checkpath NTSTATUS mapping.
991 ****************************************************************************/
993 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
995 /* Strange DOS error code semantics only for checkpath... */
996 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
997 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
998 /* We need to map to ERRbadpath */
999 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1002 return status;
1005 /****************************************************************************
1006 Reply to a checkpath.
1007 ****************************************************************************/
1009 void reply_checkpath(struct smb_request *req)
1011 connection_struct *conn = req->conn;
1012 struct smb_filename *smb_fname = NULL;
1013 char *name = NULL;
1014 NTSTATUS status;
1015 TALLOC_CTX *ctx = talloc_tos();
1017 START_PROFILE(SMBcheckpath);
1019 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1020 STR_TERMINATE, &status);
1022 if (!NT_STATUS_IS_OK(status)) {
1023 status = map_checkpath_error(req->flags2, status);
1024 reply_nterror(req, status);
1025 END_PROFILE(SMBcheckpath);
1026 return;
1029 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1031 status = filename_convert(ctx,
1032 conn,
1033 req->flags2 & FLAGS2_DFS_PATHNAMES,
1034 name,
1036 NULL,
1037 &smb_fname);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1041 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1042 ERRSRV, ERRbadpath);
1043 END_PROFILE(SMBcheckpath);
1044 return;
1046 goto path_err;
1049 if (!VALID_STAT(smb_fname->st) &&
1050 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1051 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1052 smb_fname_str_dbg(smb_fname), strerror(errno)));
1053 status = map_nt_error_from_unix(errno);
1054 goto path_err;
1057 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1058 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1059 ERRDOS, ERRbadpath);
1060 goto out;
1063 reply_outbuf(req, 0, 0);
1065 path_err:
1066 /* We special case this - as when a Windows machine
1067 is parsing a path is steps through the components
1068 one at a time - if a component fails it expects
1069 ERRbadpath, not ERRbadfile.
1071 status = map_checkpath_error(req->flags2, status);
1072 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1074 * Windows returns different error codes if
1075 * the parent directory is valid but not the
1076 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1077 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1078 * if the path is invalid.
1080 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1081 ERRDOS, ERRbadpath);
1082 goto out;
1085 reply_nterror(req, status);
1087 out:
1088 TALLOC_FREE(smb_fname);
1089 END_PROFILE(SMBcheckpath);
1090 return;
1093 /****************************************************************************
1094 Reply to a getatr.
1095 ****************************************************************************/
1097 void reply_getatr(struct smb_request *req)
1099 connection_struct *conn = req->conn;
1100 struct smb_filename *smb_fname = NULL;
1101 char *fname = NULL;
1102 int mode=0;
1103 off_t size=0;
1104 time_t mtime=0;
1105 const char *p;
1106 NTSTATUS status;
1107 TALLOC_CTX *ctx = talloc_tos();
1108 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1110 START_PROFILE(SMBgetatr);
1112 p = (const char *)req->buf + 1;
1113 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1114 if (!NT_STATUS_IS_OK(status)) {
1115 reply_nterror(req, status);
1116 goto out;
1119 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1120 under WfWg - weird! */
1121 if (*fname == '\0') {
1122 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1123 if (!CAN_WRITE(conn)) {
1124 mode |= FILE_ATTRIBUTE_READONLY;
1126 size = 0;
1127 mtime = 0;
1128 } else {
1129 status = filename_convert(ctx,
1130 conn,
1131 req->flags2 & FLAGS2_DFS_PATHNAMES,
1132 fname,
1134 NULL,
1135 &smb_fname);
1136 if (!NT_STATUS_IS_OK(status)) {
1137 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1138 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1139 ERRSRV, ERRbadpath);
1140 goto out;
1142 reply_nterror(req, status);
1143 goto out;
1145 if (!VALID_STAT(smb_fname->st) &&
1146 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1147 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1148 smb_fname_str_dbg(smb_fname),
1149 strerror(errno)));
1150 reply_nterror(req, map_nt_error_from_unix(errno));
1151 goto out;
1154 mode = dos_mode(conn, smb_fname);
1155 size = smb_fname->st.st_ex_size;
1157 if (ask_sharemode) {
1158 struct timespec write_time_ts;
1159 struct file_id fileid;
1161 ZERO_STRUCT(write_time_ts);
1162 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1163 get_file_infos(fileid, 0, NULL, &write_time_ts);
1164 if (!null_timespec(write_time_ts)) {
1165 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1169 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1170 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1171 size = 0;
1175 reply_outbuf(req, 10, 0);
1177 SSVAL(req->outbuf,smb_vwv0,mode);
1178 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1179 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1180 } else {
1181 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1183 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1185 if (get_Protocol() >= PROTOCOL_NT1) {
1186 SSVAL(req->outbuf, smb_flg2,
1187 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1190 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1191 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1193 out:
1194 TALLOC_FREE(smb_fname);
1195 TALLOC_FREE(fname);
1196 END_PROFILE(SMBgetatr);
1197 return;
1200 /****************************************************************************
1201 Reply to a setatr.
1202 ****************************************************************************/
1204 void reply_setatr(struct smb_request *req)
1206 struct smb_file_time ft;
1207 connection_struct *conn = req->conn;
1208 struct smb_filename *smb_fname = NULL;
1209 char *fname = NULL;
1210 int mode;
1211 time_t mtime;
1212 const char *p;
1213 NTSTATUS status;
1214 TALLOC_CTX *ctx = talloc_tos();
1216 START_PROFILE(SMBsetatr);
1218 ZERO_STRUCT(ft);
1220 if (req->wct < 2) {
1221 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1222 goto out;
1225 p = (const char *)req->buf + 1;
1226 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1227 if (!NT_STATUS_IS_OK(status)) {
1228 reply_nterror(req, status);
1229 goto out;
1232 status = filename_convert(ctx,
1233 conn,
1234 req->flags2 & FLAGS2_DFS_PATHNAMES,
1235 fname,
1237 NULL,
1238 &smb_fname);
1239 if (!NT_STATUS_IS_OK(status)) {
1240 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1241 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1242 ERRSRV, ERRbadpath);
1243 goto out;
1245 reply_nterror(req, status);
1246 goto out;
1249 if (smb_fname->base_name[0] == '.' &&
1250 smb_fname->base_name[1] == '\0') {
1252 * Not sure here is the right place to catch this
1253 * condition. Might be moved to somewhere else later -- vl
1255 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1256 goto out;
1259 mode = SVAL(req->vwv+0, 0);
1260 mtime = srv_make_unix_date3(req->vwv+1);
1262 if (mode != FILE_ATTRIBUTE_NORMAL) {
1263 if (VALID_STAT_OF_DIR(smb_fname->st))
1264 mode |= FILE_ATTRIBUTE_DIRECTORY;
1265 else
1266 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1268 status = check_access(conn, NULL, smb_fname,
1269 FILE_WRITE_ATTRIBUTES);
1270 if (!NT_STATUS_IS_OK(status)) {
1271 reply_nterror(req, status);
1272 goto out;
1275 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1276 false) != 0) {
1277 reply_nterror(req, map_nt_error_from_unix(errno));
1278 goto out;
1282 ft.mtime = convert_time_t_to_timespec(mtime);
1283 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1284 if (!NT_STATUS_IS_OK(status)) {
1285 reply_nterror(req, status);
1286 goto out;
1289 reply_outbuf(req, 0, 0);
1291 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1292 mode));
1293 out:
1294 TALLOC_FREE(smb_fname);
1295 END_PROFILE(SMBsetatr);
1296 return;
1299 /****************************************************************************
1300 Reply to a dskattr.
1301 ****************************************************************************/
1303 void reply_dskattr(struct smb_request *req)
1305 connection_struct *conn = req->conn;
1306 uint64_t dfree,dsize,bsize;
1307 START_PROFILE(SMBdskattr);
1309 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1310 reply_nterror(req, map_nt_error_from_unix(errno));
1311 END_PROFILE(SMBdskattr);
1312 return;
1315 reply_outbuf(req, 5, 0);
1317 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1318 double total_space, free_space;
1319 /* we need to scale this to a number that DOS6 can handle. We
1320 use floating point so we can handle large drives on systems
1321 that don't have 64 bit integers
1323 we end up displaying a maximum of 2G to DOS systems
1325 total_space = dsize * (double)bsize;
1326 free_space = dfree * (double)bsize;
1328 dsize = (uint64_t)((total_space+63*512) / (64*512));
1329 dfree = (uint64_t)((free_space+63*512) / (64*512));
1331 if (dsize > 0xFFFF) dsize = 0xFFFF;
1332 if (dfree > 0xFFFF) dfree = 0xFFFF;
1334 SSVAL(req->outbuf,smb_vwv0,dsize);
1335 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1336 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1337 SSVAL(req->outbuf,smb_vwv3,dfree);
1338 } else {
1339 SSVAL(req->outbuf,smb_vwv0,dsize);
1340 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1341 SSVAL(req->outbuf,smb_vwv2,512);
1342 SSVAL(req->outbuf,smb_vwv3,dfree);
1345 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1347 END_PROFILE(SMBdskattr);
1348 return;
1352 * Utility function to split the filename from the directory.
1354 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1355 char **fname_dir_out,
1356 char **fname_mask_out)
1358 const char *p = NULL;
1359 char *fname_dir = NULL;
1360 char *fname_mask = NULL;
1362 p = strrchr_m(fname_in, '/');
1363 if (!p) {
1364 fname_dir = talloc_strdup(ctx, ".");
1365 fname_mask = talloc_strdup(ctx, fname_in);
1366 } else {
1367 fname_dir = talloc_strndup(ctx, fname_in,
1368 PTR_DIFF(p, fname_in));
1369 fname_mask = talloc_strdup(ctx, p+1);
1372 if (!fname_dir || !fname_mask) {
1373 TALLOC_FREE(fname_dir);
1374 TALLOC_FREE(fname_mask);
1375 return NT_STATUS_NO_MEMORY;
1378 *fname_dir_out = fname_dir;
1379 *fname_mask_out = fname_mask;
1380 return NT_STATUS_OK;
1383 /****************************************************************************
1384 Reply to a search.
1385 Can be called from SMBsearch, SMBffirst or SMBfunique.
1386 ****************************************************************************/
1388 void reply_search(struct smb_request *req)
1390 connection_struct *conn = req->conn;
1391 char *path = NULL;
1392 const char *mask = NULL;
1393 char *directory = NULL;
1394 struct smb_filename *smb_fname = NULL;
1395 char *fname = NULL;
1396 off_t size;
1397 uint32 mode;
1398 struct timespec date;
1399 uint32 dirtype;
1400 unsigned int numentries = 0;
1401 unsigned int maxentries = 0;
1402 bool finished = False;
1403 const char *p;
1404 int status_len;
1405 char status[21];
1406 int dptr_num= -1;
1407 bool check_descend = False;
1408 bool expect_close = False;
1409 NTSTATUS nt_status;
1410 bool mask_contains_wcard = False;
1411 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1412 TALLOC_CTX *ctx = talloc_tos();
1413 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1414 struct dptr_struct *dirptr = NULL;
1415 struct smbd_server_connection *sconn = req->sconn;
1417 START_PROFILE(SMBsearch);
1419 if (req->wct < 2) {
1420 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1421 goto out;
1424 if (lp_posix_pathnames()) {
1425 reply_unknown_new(req, req->cmd);
1426 goto out;
1429 /* If we were called as SMBffirst then we must expect close. */
1430 if(req->cmd == SMBffirst) {
1431 expect_close = True;
1434 reply_outbuf(req, 1, 3);
1435 maxentries = SVAL(req->vwv+0, 0);
1436 dirtype = SVAL(req->vwv+1, 0);
1437 p = (const char *)req->buf + 1;
1438 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1439 &nt_status, &mask_contains_wcard);
1440 if (!NT_STATUS_IS_OK(nt_status)) {
1441 reply_nterror(req, nt_status);
1442 goto out;
1445 p++;
1446 status_len = SVAL(p, 0);
1447 p += 2;
1449 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1451 if (status_len == 0) {
1452 nt_status = filename_convert(ctx, conn,
1453 req->flags2 & FLAGS2_DFS_PATHNAMES,
1454 path,
1455 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1456 &mask_contains_wcard,
1457 &smb_fname);
1458 if (!NT_STATUS_IS_OK(nt_status)) {
1459 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1460 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1461 ERRSRV, ERRbadpath);
1462 goto out;
1464 reply_nterror(req, nt_status);
1465 goto out;
1468 directory = smb_fname->base_name;
1470 p = strrchr_m(directory,'/');
1471 if ((p != NULL) && (*directory != '/')) {
1472 mask = p + 1;
1473 directory = talloc_strndup(ctx, directory,
1474 PTR_DIFF(p, directory));
1475 } else {
1476 mask = directory;
1477 directory = talloc_strdup(ctx,".");
1480 if (!directory) {
1481 reply_nterror(req, NT_STATUS_NO_MEMORY);
1482 goto out;
1485 memset((char *)status,'\0',21);
1486 SCVAL(status,0,(dirtype & 0x1F));
1488 nt_status = dptr_create(conn,
1489 NULL, /* req */
1490 NULL, /* fsp */
1491 directory,
1492 True,
1493 expect_close,
1494 req->smbpid,
1495 mask,
1496 mask_contains_wcard,
1497 dirtype,
1498 &dirptr);
1499 if (!NT_STATUS_IS_OK(nt_status)) {
1500 reply_nterror(req, nt_status);
1501 goto out;
1503 dptr_num = dptr_dnum(dirptr);
1504 } else {
1505 int status_dirtype;
1506 const char *dirpath;
1508 memcpy(status,p,21);
1509 status_dirtype = CVAL(status,0) & 0x1F;
1510 if (status_dirtype != (dirtype & 0x1F)) {
1511 dirtype = status_dirtype;
1514 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1515 if (!dirptr) {
1516 goto SearchEmpty;
1518 dirpath = dptr_path(sconn, dptr_num);
1519 directory = talloc_strdup(ctx, dirpath);
1520 if (!directory) {
1521 reply_nterror(req, NT_STATUS_NO_MEMORY);
1522 goto out;
1525 mask = dptr_wcard(sconn, dptr_num);
1526 if (!mask) {
1527 goto SearchEmpty;
1530 * For a 'continue' search we have no string. So
1531 * check from the initial saved string.
1533 mask_contains_wcard = ms_has_wild(mask);
1534 dirtype = dptr_attr(sconn, dptr_num);
1537 DEBUG(4,("dptr_num is %d\n",dptr_num));
1539 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1540 dptr_init_search_op(dirptr);
1542 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1543 char buf[DIR_STRUCT_SIZE];
1544 memcpy(buf,status,21);
1545 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1546 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1547 reply_nterror(req, NT_STATUS_NO_MEMORY);
1548 goto out;
1550 dptr_fill(sconn, buf+12,dptr_num);
1551 if (dptr_zero(buf+12) && (status_len==0)) {
1552 numentries = 1;
1553 } else {
1554 numentries = 0;
1556 if (message_push_blob(&req->outbuf,
1557 data_blob_const(buf, sizeof(buf)))
1558 == -1) {
1559 reply_nterror(req, NT_STATUS_NO_MEMORY);
1560 goto out;
1562 } else {
1563 unsigned int i;
1564 maxentries = MIN(
1565 maxentries,
1566 ((BUFFER_SIZE -
1567 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1568 /DIR_STRUCT_SIZE));
1570 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1571 directory,lp_dontdescend(SNUM(conn))));
1572 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1573 check_descend = True;
1576 for (i=numentries;(i<maxentries) && !finished;i++) {
1577 finished = !get_dir_entry(ctx,
1578 dirptr,
1579 mask,
1580 dirtype,
1581 &fname,
1582 &size,
1583 &mode,
1584 &date,
1585 check_descend,
1586 ask_sharemode);
1587 if (!finished) {
1588 char buf[DIR_STRUCT_SIZE];
1589 memcpy(buf,status,21);
1590 if (!make_dir_struct(ctx,
1591 buf,
1592 mask,
1593 fname,
1594 size,
1595 mode,
1596 convert_timespec_to_time_t(date),
1597 !allow_long_path_components)) {
1598 reply_nterror(req, NT_STATUS_NO_MEMORY);
1599 goto out;
1601 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1602 break;
1604 if (message_push_blob(&req->outbuf,
1605 data_blob_const(buf, sizeof(buf)))
1606 == -1) {
1607 reply_nterror(req, NT_STATUS_NO_MEMORY);
1608 goto out;
1610 numentries++;
1615 SearchEmpty:
1617 /* If we were called as SMBffirst with smb_search_id == NULL
1618 and no entries were found then return error and close dirptr
1619 (X/Open spec) */
1621 if (numentries == 0) {
1622 dptr_close(sconn, &dptr_num);
1623 } else if(expect_close && status_len == 0) {
1624 /* Close the dptr - we know it's gone */
1625 dptr_close(sconn, &dptr_num);
1628 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1629 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1630 dptr_close(sconn, &dptr_num);
1633 if ((numentries == 0) && !mask_contains_wcard) {
1634 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1635 goto out;
1638 SSVAL(req->outbuf,smb_vwv0,numentries);
1639 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1640 SCVAL(smb_buf(req->outbuf),0,5);
1641 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1643 /* The replies here are never long name. */
1644 SSVAL(req->outbuf, smb_flg2,
1645 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1646 if (!allow_long_path_components) {
1647 SSVAL(req->outbuf, smb_flg2,
1648 SVAL(req->outbuf, smb_flg2)
1649 & (~FLAGS2_LONG_PATH_COMPONENTS));
1652 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1653 SSVAL(req->outbuf, smb_flg2,
1654 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1656 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1657 smb_fn_name(req->cmd),
1658 mask,
1659 directory,
1660 dirtype,
1661 numentries,
1662 maxentries ));
1663 out:
1664 TALLOC_FREE(directory);
1665 TALLOC_FREE(smb_fname);
1666 END_PROFILE(SMBsearch);
1667 return;
1670 /****************************************************************************
1671 Reply to a fclose (stop directory search).
1672 ****************************************************************************/
1674 void reply_fclose(struct smb_request *req)
1676 int status_len;
1677 char status[21];
1678 int dptr_num= -2;
1679 const char *p;
1680 char *path = NULL;
1681 NTSTATUS err;
1682 bool path_contains_wcard = False;
1683 TALLOC_CTX *ctx = talloc_tos();
1684 struct smbd_server_connection *sconn = req->sconn;
1686 START_PROFILE(SMBfclose);
1688 if (lp_posix_pathnames()) {
1689 reply_unknown_new(req, req->cmd);
1690 END_PROFILE(SMBfclose);
1691 return;
1694 p = (const char *)req->buf + 1;
1695 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1696 &err, &path_contains_wcard);
1697 if (!NT_STATUS_IS_OK(err)) {
1698 reply_nterror(req, err);
1699 END_PROFILE(SMBfclose);
1700 return;
1702 p++;
1703 status_len = SVAL(p,0);
1704 p += 2;
1706 if (status_len == 0) {
1707 reply_force_doserror(req, ERRSRV, ERRsrverror);
1708 END_PROFILE(SMBfclose);
1709 return;
1712 memcpy(status,p,21);
1714 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1715 /* Close the dptr - we know it's gone */
1716 dptr_close(sconn, &dptr_num);
1719 reply_outbuf(req, 1, 0);
1720 SSVAL(req->outbuf,smb_vwv0,0);
1722 DEBUG(3,("search close\n"));
1724 END_PROFILE(SMBfclose);
1725 return;
1728 /****************************************************************************
1729 Reply to an open.
1730 ****************************************************************************/
1732 void reply_open(struct smb_request *req)
1734 connection_struct *conn = req->conn;
1735 struct smb_filename *smb_fname = NULL;
1736 char *fname = NULL;
1737 uint32 fattr=0;
1738 off_t size = 0;
1739 time_t mtime=0;
1740 int info;
1741 files_struct *fsp;
1742 int oplock_request;
1743 int deny_mode;
1744 uint32 dos_attr;
1745 uint32 access_mask;
1746 uint32 share_mode;
1747 uint32 create_disposition;
1748 uint32 create_options = 0;
1749 uint32_t private_flags = 0;
1750 NTSTATUS status;
1751 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1752 TALLOC_CTX *ctx = talloc_tos();
1754 START_PROFILE(SMBopen);
1756 if (req->wct < 2) {
1757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1758 goto out;
1761 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1762 deny_mode = SVAL(req->vwv+0, 0);
1763 dos_attr = SVAL(req->vwv+1, 0);
1765 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1766 STR_TERMINATE, &status);
1767 if (!NT_STATUS_IS_OK(status)) {
1768 reply_nterror(req, status);
1769 goto out;
1772 status = filename_convert(ctx,
1773 conn,
1774 req->flags2 & FLAGS2_DFS_PATHNAMES,
1775 fname,
1777 NULL,
1778 &smb_fname);
1779 if (!NT_STATUS_IS_OK(status)) {
1780 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1781 reply_botherror(req,
1782 NT_STATUS_PATH_NOT_COVERED,
1783 ERRSRV, ERRbadpath);
1784 goto out;
1786 reply_nterror(req, status);
1787 goto out;
1790 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1791 OPENX_FILE_EXISTS_OPEN, &access_mask,
1792 &share_mode, &create_disposition,
1793 &create_options, &private_flags)) {
1794 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1795 goto out;
1798 status = SMB_VFS_CREATE_FILE(
1799 conn, /* conn */
1800 req, /* req */
1801 0, /* root_dir_fid */
1802 smb_fname, /* fname */
1803 access_mask, /* access_mask */
1804 share_mode, /* share_access */
1805 create_disposition, /* create_disposition*/
1806 create_options, /* create_options */
1807 dos_attr, /* file_attributes */
1808 oplock_request, /* oplock_request */
1809 0, /* allocation_size */
1810 private_flags,
1811 NULL, /* sd */
1812 NULL, /* ea_list */
1813 &fsp, /* result */
1814 &info); /* pinfo */
1816 if (!NT_STATUS_IS_OK(status)) {
1817 if (open_was_deferred(req->sconn, req->mid)) {
1818 /* We have re-scheduled this call. */
1819 goto out;
1821 reply_openerror(req, status);
1822 goto out;
1825 size = smb_fname->st.st_ex_size;
1826 fattr = dos_mode(conn, smb_fname);
1828 /* Deal with other possible opens having a modified
1829 write time. JRA. */
1830 if (ask_sharemode) {
1831 struct timespec write_time_ts;
1833 ZERO_STRUCT(write_time_ts);
1834 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1835 if (!null_timespec(write_time_ts)) {
1836 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1840 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1842 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1843 DEBUG(3,("attempt to open a directory %s\n",
1844 fsp_str_dbg(fsp)));
1845 close_file(req, fsp, ERROR_CLOSE);
1846 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1847 ERRDOS, ERRnoaccess);
1848 goto out;
1851 reply_outbuf(req, 7, 0);
1852 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1853 SSVAL(req->outbuf,smb_vwv1,fattr);
1854 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1855 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1856 } else {
1857 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1859 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1860 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1862 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1863 SCVAL(req->outbuf,smb_flg,
1864 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1867 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1868 SCVAL(req->outbuf,smb_flg,
1869 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1871 out:
1872 TALLOC_FREE(smb_fname);
1873 END_PROFILE(SMBopen);
1874 return;
1877 /****************************************************************************
1878 Reply to an open and X.
1879 ****************************************************************************/
1881 void reply_open_and_X(struct smb_request *req)
1883 connection_struct *conn = req->conn;
1884 struct smb_filename *smb_fname = NULL;
1885 char *fname = NULL;
1886 uint16 open_flags;
1887 int deny_mode;
1888 uint32 smb_attr;
1889 /* Breakout the oplock request bits so we can set the
1890 reply bits separately. */
1891 int ex_oplock_request;
1892 int core_oplock_request;
1893 int oplock_request;
1894 #if 0
1895 int smb_sattr = SVAL(req->vwv+4, 0);
1896 uint32 smb_time = make_unix_date3(req->vwv+6);
1897 #endif
1898 int smb_ofun;
1899 uint32 fattr=0;
1900 int mtime=0;
1901 int smb_action = 0;
1902 files_struct *fsp;
1903 NTSTATUS status;
1904 uint64_t allocation_size;
1905 ssize_t retval = -1;
1906 uint32 access_mask;
1907 uint32 share_mode;
1908 uint32 create_disposition;
1909 uint32 create_options = 0;
1910 uint32_t private_flags = 0;
1911 TALLOC_CTX *ctx = talloc_tos();
1913 START_PROFILE(SMBopenX);
1915 if (req->wct < 15) {
1916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1917 goto out;
1920 open_flags = SVAL(req->vwv+2, 0);
1921 deny_mode = SVAL(req->vwv+3, 0);
1922 smb_attr = SVAL(req->vwv+5, 0);
1923 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1924 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1925 oplock_request = ex_oplock_request | core_oplock_request;
1926 smb_ofun = SVAL(req->vwv+8, 0);
1927 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1929 /* If it's an IPC, pass off the pipe handler. */
1930 if (IS_IPC(conn)) {
1931 if (lp_nt_pipe_support()) {
1932 reply_open_pipe_and_X(conn, req);
1933 } else {
1934 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1936 goto out;
1939 /* XXXX we need to handle passed times, sattr and flags */
1940 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1941 STR_TERMINATE, &status);
1942 if (!NT_STATUS_IS_OK(status)) {
1943 reply_nterror(req, status);
1944 goto out;
1947 status = filename_convert(ctx,
1948 conn,
1949 req->flags2 & FLAGS2_DFS_PATHNAMES,
1950 fname,
1952 NULL,
1953 &smb_fname);
1954 if (!NT_STATUS_IS_OK(status)) {
1955 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1956 reply_botherror(req,
1957 NT_STATUS_PATH_NOT_COVERED,
1958 ERRSRV, ERRbadpath);
1959 goto out;
1961 reply_nterror(req, status);
1962 goto out;
1965 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1966 smb_ofun,
1967 &access_mask, &share_mode,
1968 &create_disposition,
1969 &create_options,
1970 &private_flags)) {
1971 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1972 goto out;
1975 status = SMB_VFS_CREATE_FILE(
1976 conn, /* conn */
1977 req, /* req */
1978 0, /* root_dir_fid */
1979 smb_fname, /* fname */
1980 access_mask, /* access_mask */
1981 share_mode, /* share_access */
1982 create_disposition, /* create_disposition*/
1983 create_options, /* create_options */
1984 smb_attr, /* file_attributes */
1985 oplock_request, /* oplock_request */
1986 0, /* allocation_size */
1987 private_flags,
1988 NULL, /* sd */
1989 NULL, /* ea_list */
1990 &fsp, /* result */
1991 &smb_action); /* pinfo */
1993 if (!NT_STATUS_IS_OK(status)) {
1994 if (open_was_deferred(req->sconn, req->mid)) {
1995 /* We have re-scheduled this call. */
1996 goto out;
1998 reply_openerror(req, status);
1999 goto out;
2002 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2003 if the file is truncated or created. */
2004 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2005 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2006 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2007 close_file(req, fsp, ERROR_CLOSE);
2008 reply_nterror(req, NT_STATUS_DISK_FULL);
2009 goto out;
2011 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2012 if (retval < 0) {
2013 close_file(req, fsp, ERROR_CLOSE);
2014 reply_nterror(req, NT_STATUS_DISK_FULL);
2015 goto out;
2017 status = vfs_stat_fsp(fsp);
2018 if (!NT_STATUS_IS_OK(status)) {
2019 close_file(req, fsp, ERROR_CLOSE);
2020 reply_nterror(req, status);
2021 goto out;
2025 fattr = dos_mode(conn, fsp->fsp_name);
2026 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2027 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2028 close_file(req, fsp, ERROR_CLOSE);
2029 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2030 goto out;
2033 /* If the caller set the extended oplock request bit
2034 and we granted one (by whatever means) - set the
2035 correct bit for extended oplock reply.
2038 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2039 smb_action |= EXTENDED_OPLOCK_GRANTED;
2042 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2043 smb_action |= EXTENDED_OPLOCK_GRANTED;
2046 /* If the caller set the core oplock request bit
2047 and we granted one (by whatever means) - set the
2048 correct bit for core oplock reply.
2051 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2052 reply_outbuf(req, 19, 0);
2053 } else {
2054 reply_outbuf(req, 15, 0);
2057 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2058 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2060 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2061 SCVAL(req->outbuf, smb_flg,
2062 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2065 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2066 SCVAL(req->outbuf, smb_flg,
2067 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2070 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2071 SSVAL(req->outbuf,smb_vwv3,fattr);
2072 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2073 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2074 } else {
2075 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2077 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2078 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2079 SSVAL(req->outbuf,smb_vwv11,smb_action);
2081 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2082 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2085 out:
2086 TALLOC_FREE(smb_fname);
2087 END_PROFILE(SMBopenX);
2088 return;
2091 /****************************************************************************
2092 Reply to a SMBulogoffX.
2093 ****************************************************************************/
2095 void reply_ulogoffX(struct smb_request *req)
2097 struct smbd_server_connection *sconn = req->sconn;
2098 struct user_struct *vuser;
2099 struct smbXsrv_session *session = NULL;
2100 NTSTATUS status;
2102 START_PROFILE(SMBulogoffX);
2104 vuser = get_valid_user_struct(sconn, req->vuid);
2106 if(vuser == NULL) {
2107 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2108 (unsigned long long)req->vuid));
2110 req->vuid = UID_FIELD_INVALID;
2111 reply_force_doserror(req, ERRSRV, ERRbaduid);
2112 END_PROFILE(SMBulogoffX);
2113 return;
2116 session = vuser->session;
2117 vuser = NULL;
2120 * TODO: cancel all outstanding requests on the session
2122 status = smbXsrv_session_logoff(session);
2123 if (!NT_STATUS_IS_OK(status)) {
2124 DEBUG(0, ("reply_ulogoff: "
2125 "smbXsrv_session_logoff() failed: %s\n",
2126 nt_errstr(status)));
2128 * If we hit this case, there is something completely
2129 * wrong, so we better disconnect the transport connection.
2131 END_PROFILE(SMBulogoffX);
2132 exit_server(__location__ ": smbXsrv_session_logoff failed");
2133 return;
2136 TALLOC_FREE(session);
2138 reply_outbuf(req, 2, 0);
2139 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2140 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2142 DEBUG(3, ("ulogoffX vuid=%llu\n",
2143 (unsigned long long)req->vuid));
2145 END_PROFILE(SMBulogoffX);
2146 req->vuid = UID_FIELD_INVALID;
2149 /****************************************************************************
2150 Reply to a mknew or a create.
2151 ****************************************************************************/
2153 void reply_mknew(struct smb_request *req)
2155 connection_struct *conn = req->conn;
2156 struct smb_filename *smb_fname = NULL;
2157 char *fname = NULL;
2158 uint32 fattr = 0;
2159 struct smb_file_time ft;
2160 files_struct *fsp;
2161 int oplock_request = 0;
2162 NTSTATUS status;
2163 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2164 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2165 uint32 create_disposition;
2166 uint32 create_options = 0;
2167 TALLOC_CTX *ctx = talloc_tos();
2169 START_PROFILE(SMBcreate);
2170 ZERO_STRUCT(ft);
2172 if (req->wct < 3) {
2173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2174 goto out;
2177 fattr = SVAL(req->vwv+0, 0);
2178 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2180 /* mtime. */
2181 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2183 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2184 STR_TERMINATE, &status);
2185 if (!NT_STATUS_IS_OK(status)) {
2186 reply_nterror(req, status);
2187 goto out;
2190 status = filename_convert(ctx,
2191 conn,
2192 req->flags2 & FLAGS2_DFS_PATHNAMES,
2193 fname,
2195 NULL,
2196 &smb_fname);
2197 if (!NT_STATUS_IS_OK(status)) {
2198 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2199 reply_botherror(req,
2200 NT_STATUS_PATH_NOT_COVERED,
2201 ERRSRV, ERRbadpath);
2202 goto out;
2204 reply_nterror(req, status);
2205 goto out;
2208 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2209 DEBUG(0,("Attempt to create file (%s) with volid set - "
2210 "please report this\n",
2211 smb_fname_str_dbg(smb_fname)));
2214 if(req->cmd == SMBmknew) {
2215 /* We should fail if file exists. */
2216 create_disposition = FILE_CREATE;
2217 } else {
2218 /* Create if file doesn't exist, truncate if it does. */
2219 create_disposition = FILE_OVERWRITE_IF;
2222 status = SMB_VFS_CREATE_FILE(
2223 conn, /* conn */
2224 req, /* req */
2225 0, /* root_dir_fid */
2226 smb_fname, /* fname */
2227 access_mask, /* access_mask */
2228 share_mode, /* share_access */
2229 create_disposition, /* create_disposition*/
2230 create_options, /* create_options */
2231 fattr, /* file_attributes */
2232 oplock_request, /* oplock_request */
2233 0, /* allocation_size */
2234 0, /* private_flags */
2235 NULL, /* sd */
2236 NULL, /* ea_list */
2237 &fsp, /* result */
2238 NULL); /* pinfo */
2240 if (!NT_STATUS_IS_OK(status)) {
2241 if (open_was_deferred(req->sconn, req->mid)) {
2242 /* We have re-scheduled this call. */
2243 goto out;
2245 reply_openerror(req, status);
2246 goto out;
2249 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2250 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2251 if (!NT_STATUS_IS_OK(status)) {
2252 END_PROFILE(SMBcreate);
2253 goto out;
2256 reply_outbuf(req, 1, 0);
2257 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2259 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2260 SCVAL(req->outbuf,smb_flg,
2261 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2264 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2265 SCVAL(req->outbuf,smb_flg,
2266 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2269 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2270 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2271 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2272 (unsigned int)fattr));
2274 out:
2275 TALLOC_FREE(smb_fname);
2276 END_PROFILE(SMBcreate);
2277 return;
2280 /****************************************************************************
2281 Reply to a create temporary file.
2282 ****************************************************************************/
2284 void reply_ctemp(struct smb_request *req)
2286 connection_struct *conn = req->conn;
2287 struct smb_filename *smb_fname = NULL;
2288 char *fname = NULL;
2289 uint32 fattr;
2290 files_struct *fsp;
2291 int oplock_request;
2292 int tmpfd;
2293 char *s;
2294 NTSTATUS status;
2295 TALLOC_CTX *ctx = talloc_tos();
2297 START_PROFILE(SMBctemp);
2299 if (req->wct < 3) {
2300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2301 goto out;
2304 fattr = SVAL(req->vwv+0, 0);
2305 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2307 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2308 STR_TERMINATE, &status);
2309 if (!NT_STATUS_IS_OK(status)) {
2310 reply_nterror(req, status);
2311 goto out;
2313 if (*fname) {
2314 fname = talloc_asprintf(ctx,
2315 "%s/TMXXXXXX",
2316 fname);
2317 } else {
2318 fname = talloc_strdup(ctx, "TMXXXXXX");
2321 if (!fname) {
2322 reply_nterror(req, NT_STATUS_NO_MEMORY);
2323 goto out;
2326 status = filename_convert(ctx, conn,
2327 req->flags2 & FLAGS2_DFS_PATHNAMES,
2328 fname,
2330 NULL,
2331 &smb_fname);
2332 if (!NT_STATUS_IS_OK(status)) {
2333 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2334 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2335 ERRSRV, ERRbadpath);
2336 goto out;
2338 reply_nterror(req, status);
2339 goto out;
2342 tmpfd = mkstemp(smb_fname->base_name);
2343 if (tmpfd == -1) {
2344 reply_nterror(req, map_nt_error_from_unix(errno));
2345 goto out;
2348 SMB_VFS_STAT(conn, smb_fname);
2350 /* We should fail if file does not exist. */
2351 status = SMB_VFS_CREATE_FILE(
2352 conn, /* conn */
2353 req, /* req */
2354 0, /* root_dir_fid */
2355 smb_fname, /* fname */
2356 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2357 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2358 FILE_OPEN, /* create_disposition*/
2359 0, /* create_options */
2360 fattr, /* file_attributes */
2361 oplock_request, /* oplock_request */
2362 0, /* allocation_size */
2363 0, /* private_flags */
2364 NULL, /* sd */
2365 NULL, /* ea_list */
2366 &fsp, /* result */
2367 NULL); /* pinfo */
2369 /* close fd from mkstemp() */
2370 close(tmpfd);
2372 if (!NT_STATUS_IS_OK(status)) {
2373 if (open_was_deferred(req->sconn, req->mid)) {
2374 /* We have re-scheduled this call. */
2375 goto out;
2377 reply_openerror(req, status);
2378 goto out;
2381 reply_outbuf(req, 1, 0);
2382 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2384 /* the returned filename is relative to the directory */
2385 s = strrchr_m(fsp->fsp_name->base_name, '/');
2386 if (!s) {
2387 s = fsp->fsp_name->base_name;
2388 } else {
2389 s++;
2392 #if 0
2393 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2394 thing in the byte section. JRA */
2395 SSVALS(p, 0, -1); /* what is this? not in spec */
2396 #endif
2397 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2398 == -1) {
2399 reply_nterror(req, NT_STATUS_NO_MEMORY);
2400 goto out;
2403 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2404 SCVAL(req->outbuf, smb_flg,
2405 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2408 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2409 SCVAL(req->outbuf, smb_flg,
2410 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2413 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2414 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2415 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2416 out:
2417 TALLOC_FREE(smb_fname);
2418 END_PROFILE(SMBctemp);
2419 return;
2422 /*******************************************************************
2423 Check if a user is allowed to rename a file.
2424 ********************************************************************/
2426 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2427 uint16 dirtype)
2429 if (!CAN_WRITE(conn)) {
2430 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2433 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2434 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2435 /* Only bother to read the DOS attribute if we might deny the
2436 rename on the grounds of attribute missmatch. */
2437 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2438 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2439 return NT_STATUS_NO_SUCH_FILE;
2443 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2444 if (fsp->posix_open) {
2445 return NT_STATUS_OK;
2448 /* If no pathnames are open below this
2449 directory, allow the rename. */
2451 if (file_find_subpath(fsp)) {
2452 return NT_STATUS_ACCESS_DENIED;
2454 return NT_STATUS_OK;
2457 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2458 return NT_STATUS_OK;
2461 return NT_STATUS_ACCESS_DENIED;
2464 /*******************************************************************
2465 * unlink a file with all relevant access checks
2466 *******************************************************************/
2468 static NTSTATUS do_unlink(connection_struct *conn,
2469 struct smb_request *req,
2470 struct smb_filename *smb_fname,
2471 uint32 dirtype)
2473 uint32 fattr;
2474 files_struct *fsp;
2475 uint32 dirtype_orig = dirtype;
2476 NTSTATUS status;
2477 int ret;
2478 bool posix_paths = lp_posix_pathnames();
2480 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2481 smb_fname_str_dbg(smb_fname),
2482 dirtype));
2484 if (!CAN_WRITE(conn)) {
2485 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2488 if (posix_paths) {
2489 ret = SMB_VFS_LSTAT(conn, smb_fname);
2490 } else {
2491 ret = SMB_VFS_STAT(conn, smb_fname);
2493 if (ret != 0) {
2494 return map_nt_error_from_unix(errno);
2497 fattr = dos_mode(conn, smb_fname);
2499 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2500 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2503 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2504 if (!dirtype) {
2505 return NT_STATUS_NO_SUCH_FILE;
2508 if (!dir_check_ftype(conn, fattr, dirtype)) {
2509 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2510 return NT_STATUS_FILE_IS_A_DIRECTORY;
2512 return NT_STATUS_NO_SUCH_FILE;
2515 if (dirtype_orig & 0x8000) {
2516 /* These will never be set for POSIX. */
2517 return NT_STATUS_NO_SUCH_FILE;
2520 #if 0
2521 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2522 return NT_STATUS_FILE_IS_A_DIRECTORY;
2525 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2526 return NT_STATUS_NO_SUCH_FILE;
2529 if (dirtype & 0xFF00) {
2530 /* These will never be set for POSIX. */
2531 return NT_STATUS_NO_SUCH_FILE;
2534 dirtype &= 0xFF;
2535 if (!dirtype) {
2536 return NT_STATUS_NO_SUCH_FILE;
2539 /* Can't delete a directory. */
2540 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2541 return NT_STATUS_FILE_IS_A_DIRECTORY;
2543 #endif
2545 #if 0 /* JRATEST */
2546 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2547 return NT_STATUS_OBJECT_NAME_INVALID;
2548 #endif /* JRATEST */
2550 /* On open checks the open itself will check the share mode, so
2551 don't do it here as we'll get it wrong. */
2553 status = SMB_VFS_CREATE_FILE
2554 (conn, /* conn */
2555 req, /* req */
2556 0, /* root_dir_fid */
2557 smb_fname, /* fname */
2558 DELETE_ACCESS, /* access_mask */
2559 FILE_SHARE_NONE, /* share_access */
2560 FILE_OPEN, /* create_disposition*/
2561 FILE_NON_DIRECTORY_FILE, /* create_options */
2562 /* file_attributes */
2563 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2564 FILE_ATTRIBUTE_NORMAL,
2565 0, /* oplock_request */
2566 0, /* allocation_size */
2567 0, /* private_flags */
2568 NULL, /* sd */
2569 NULL, /* ea_list */
2570 &fsp, /* result */
2571 NULL); /* pinfo */
2573 if (!NT_STATUS_IS_OK(status)) {
2574 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2575 nt_errstr(status)));
2576 return status;
2579 status = can_set_delete_on_close(fsp, fattr);
2580 if (!NT_STATUS_IS_OK(status)) {
2581 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2582 "(%s)\n",
2583 smb_fname_str_dbg(smb_fname),
2584 nt_errstr(status)));
2585 close_file(req, fsp, NORMAL_CLOSE);
2586 return status;
2589 /* The set is across all open files on this dev/inode pair. */
2590 if (!set_delete_on_close(fsp, True,
2591 conn->session_info->security_token,
2592 conn->session_info->unix_token)) {
2593 close_file(req, fsp, NORMAL_CLOSE);
2594 return NT_STATUS_ACCESS_DENIED;
2597 return close_file(req, fsp, NORMAL_CLOSE);
2600 /****************************************************************************
2601 The guts of the unlink command, split out so it may be called by the NT SMB
2602 code.
2603 ****************************************************************************/
2605 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2606 uint32 dirtype, struct smb_filename *smb_fname,
2607 bool has_wild)
2609 char *fname_dir = NULL;
2610 char *fname_mask = NULL;
2611 int count=0;
2612 NTSTATUS status = NT_STATUS_OK;
2613 TALLOC_CTX *ctx = talloc_tos();
2615 /* Split up the directory from the filename/mask. */
2616 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2617 &fname_dir, &fname_mask);
2618 if (!NT_STATUS_IS_OK(status)) {
2619 goto out;
2623 * We should only check the mangled cache
2624 * here if unix_convert failed. This means
2625 * that the path in 'mask' doesn't exist
2626 * on the file system and so we need to look
2627 * for a possible mangle. This patch from
2628 * Tine Smukavec <valentin.smukavec@hermes.si>.
2631 if (!VALID_STAT(smb_fname->st) &&
2632 mangle_is_mangled(fname_mask, conn->params)) {
2633 char *new_mask = NULL;
2634 mangle_lookup_name_from_8_3(ctx, fname_mask,
2635 &new_mask, conn->params);
2636 if (new_mask) {
2637 TALLOC_FREE(fname_mask);
2638 fname_mask = new_mask;
2642 if (!has_wild) {
2645 * Only one file needs to be unlinked. Append the mask back
2646 * onto the directory.
2648 TALLOC_FREE(smb_fname->base_name);
2649 if (ISDOT(fname_dir)) {
2650 /* Ensure we use canonical names on open. */
2651 smb_fname->base_name = talloc_asprintf(smb_fname,
2652 "%s",
2653 fname_mask);
2654 } else {
2655 smb_fname->base_name = talloc_asprintf(smb_fname,
2656 "%s/%s",
2657 fname_dir,
2658 fname_mask);
2660 if (!smb_fname->base_name) {
2661 status = NT_STATUS_NO_MEMORY;
2662 goto out;
2664 if (dirtype == 0) {
2665 dirtype = FILE_ATTRIBUTE_NORMAL;
2668 status = check_name(conn, smb_fname->base_name);
2669 if (!NT_STATUS_IS_OK(status)) {
2670 goto out;
2673 status = do_unlink(conn, req, smb_fname, dirtype);
2674 if (!NT_STATUS_IS_OK(status)) {
2675 goto out;
2678 count++;
2679 } else {
2680 struct smb_Dir *dir_hnd = NULL;
2681 long offset = 0;
2682 const char *dname = NULL;
2683 char *talloced = NULL;
2685 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2686 status = NT_STATUS_OBJECT_NAME_INVALID;
2687 goto out;
2690 if (strequal(fname_mask,"????????.???")) {
2691 TALLOC_FREE(fname_mask);
2692 fname_mask = talloc_strdup(ctx, "*");
2693 if (!fname_mask) {
2694 status = NT_STATUS_NO_MEMORY;
2695 goto out;
2699 status = check_name(conn, fname_dir);
2700 if (!NT_STATUS_IS_OK(status)) {
2701 goto out;
2704 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2705 dirtype);
2706 if (dir_hnd == NULL) {
2707 status = map_nt_error_from_unix(errno);
2708 goto out;
2711 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2712 the pattern matches against the long name, otherwise the short name
2713 We don't implement this yet XXXX
2716 status = NT_STATUS_NO_SUCH_FILE;
2718 while ((dname = ReadDirName(dir_hnd, &offset,
2719 &smb_fname->st, &talloced))) {
2720 TALLOC_CTX *frame = talloc_stackframe();
2722 if (!is_visible_file(conn, fname_dir, dname,
2723 &smb_fname->st, true)) {
2724 TALLOC_FREE(frame);
2725 TALLOC_FREE(talloced);
2726 continue;
2729 /* Quick check for "." and ".." */
2730 if (ISDOT(dname) || ISDOTDOT(dname)) {
2731 TALLOC_FREE(frame);
2732 TALLOC_FREE(talloced);
2733 continue;
2736 if(!mask_match(dname, fname_mask,
2737 conn->case_sensitive)) {
2738 TALLOC_FREE(frame);
2739 TALLOC_FREE(talloced);
2740 continue;
2743 TALLOC_FREE(smb_fname->base_name);
2744 if (ISDOT(fname_dir)) {
2745 /* Ensure we use canonical names on open. */
2746 smb_fname->base_name =
2747 talloc_asprintf(smb_fname, "%s",
2748 dname);
2749 } else {
2750 smb_fname->base_name =
2751 talloc_asprintf(smb_fname, "%s/%s",
2752 fname_dir, dname);
2755 if (!smb_fname->base_name) {
2756 TALLOC_FREE(dir_hnd);
2757 status = NT_STATUS_NO_MEMORY;
2758 TALLOC_FREE(frame);
2759 TALLOC_FREE(talloced);
2760 goto out;
2763 status = check_name(conn, smb_fname->base_name);
2764 if (!NT_STATUS_IS_OK(status)) {
2765 TALLOC_FREE(dir_hnd);
2766 TALLOC_FREE(frame);
2767 TALLOC_FREE(talloced);
2768 goto out;
2771 status = do_unlink(conn, req, smb_fname, dirtype);
2772 if (!NT_STATUS_IS_OK(status)) {
2773 TALLOC_FREE(frame);
2774 TALLOC_FREE(talloced);
2775 continue;
2778 count++;
2779 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2780 smb_fname->base_name));
2782 TALLOC_FREE(frame);
2783 TALLOC_FREE(talloced);
2785 TALLOC_FREE(dir_hnd);
2788 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2789 status = map_nt_error_from_unix(errno);
2792 out:
2793 TALLOC_FREE(fname_dir);
2794 TALLOC_FREE(fname_mask);
2795 return status;
2798 /****************************************************************************
2799 Reply to a unlink
2800 ****************************************************************************/
2802 void reply_unlink(struct smb_request *req)
2804 connection_struct *conn = req->conn;
2805 char *name = NULL;
2806 struct smb_filename *smb_fname = NULL;
2807 uint32 dirtype;
2808 NTSTATUS status;
2809 bool path_contains_wcard = False;
2810 TALLOC_CTX *ctx = talloc_tos();
2812 START_PROFILE(SMBunlink);
2814 if (req->wct < 1) {
2815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2816 goto out;
2819 dirtype = SVAL(req->vwv+0, 0);
2821 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2822 STR_TERMINATE, &status,
2823 &path_contains_wcard);
2824 if (!NT_STATUS_IS_OK(status)) {
2825 reply_nterror(req, status);
2826 goto out;
2829 status = filename_convert(ctx, conn,
2830 req->flags2 & FLAGS2_DFS_PATHNAMES,
2831 name,
2832 UCF_COND_ALLOW_WCARD_LCOMP,
2833 &path_contains_wcard,
2834 &smb_fname);
2835 if (!NT_STATUS_IS_OK(status)) {
2836 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2837 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2838 ERRSRV, ERRbadpath);
2839 goto out;
2841 reply_nterror(req, status);
2842 goto out;
2845 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2847 status = unlink_internals(conn, req, dirtype, smb_fname,
2848 path_contains_wcard);
2849 if (!NT_STATUS_IS_OK(status)) {
2850 if (open_was_deferred(req->sconn, req->mid)) {
2851 /* We have re-scheduled this call. */
2852 goto out;
2854 reply_nterror(req, status);
2855 goto out;
2858 reply_outbuf(req, 0, 0);
2859 out:
2860 TALLOC_FREE(smb_fname);
2861 END_PROFILE(SMBunlink);
2862 return;
2865 /****************************************************************************
2866 Fail for readbraw.
2867 ****************************************************************************/
2869 static void fail_readraw(void)
2871 const char *errstr = talloc_asprintf(talloc_tos(),
2872 "FAIL ! reply_readbraw: socket write fail (%s)",
2873 strerror(errno));
2874 if (!errstr) {
2875 errstr = "";
2877 exit_server_cleanly(errstr);
2880 /****************************************************************************
2881 Fake (read/write) sendfile. Returns -1 on read or write fail.
2882 ****************************************************************************/
2884 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
2886 size_t bufsize;
2887 size_t tosend = nread;
2888 char *buf;
2890 if (nread == 0) {
2891 return 0;
2894 bufsize = MIN(nread, 65536);
2896 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2897 return -1;
2900 while (tosend > 0) {
2901 ssize_t ret;
2902 size_t cur_read;
2904 if (tosend > bufsize) {
2905 cur_read = bufsize;
2906 } else {
2907 cur_read = tosend;
2909 ret = read_file(fsp,buf,startpos,cur_read);
2910 if (ret == -1) {
2911 SAFE_FREE(buf);
2912 return -1;
2915 /* If we had a short read, fill with zeros. */
2916 if (ret < cur_read) {
2917 memset(buf + ret, '\0', cur_read - ret);
2920 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2921 != cur_read) {
2922 char addr[INET6_ADDRSTRLEN];
2924 * Try and give an error message saying what
2925 * client failed.
2927 DEBUG(0, ("write_data failed for client %s. "
2928 "Error %s\n",
2929 get_peer_addr(fsp->conn->sconn->sock, addr,
2930 sizeof(addr)),
2931 strerror(errno)));
2932 SAFE_FREE(buf);
2933 return -1;
2935 tosend -= cur_read;
2936 startpos += cur_read;
2939 SAFE_FREE(buf);
2940 return (ssize_t)nread;
2943 /****************************************************************************
2944 Deal with the case of sendfile reading less bytes from the file than
2945 requested. Fill with zeros (all we can do).
2946 ****************************************************************************/
2948 void sendfile_short_send(files_struct *fsp,
2949 ssize_t nread,
2950 size_t headersize,
2951 size_t smb_maxcnt)
2953 #define SHORT_SEND_BUFSIZE 1024
2954 if (nread < headersize) {
2955 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2956 "header for file %s (%s). Terminating\n",
2957 fsp_str_dbg(fsp), strerror(errno)));
2958 exit_server_cleanly("sendfile_short_send failed");
2961 nread -= headersize;
2963 if (nread < smb_maxcnt) {
2964 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2965 if (!buf) {
2966 exit_server_cleanly("sendfile_short_send: "
2967 "malloc failed");
2970 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2971 "with zeros !\n", fsp_str_dbg(fsp)));
2973 while (nread < smb_maxcnt) {
2975 * We asked for the real file size and told sendfile
2976 * to not go beyond the end of the file. But it can
2977 * happen that in between our fstat call and the
2978 * sendfile call the file was truncated. This is very
2979 * bad because we have already announced the larger
2980 * number of bytes to the client.
2982 * The best we can do now is to send 0-bytes, just as
2983 * a read from a hole in a sparse file would do.
2985 * This should happen rarely enough that I don't care
2986 * about efficiency here :-)
2988 size_t to_write;
2990 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2991 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2992 != to_write) {
2993 char addr[INET6_ADDRSTRLEN];
2995 * Try and give an error message saying what
2996 * client failed.
2998 DEBUG(0, ("write_data failed for client %s. "
2999 "Error %s\n",
3000 get_peer_addr(
3001 fsp->conn->sconn->sock, addr,
3002 sizeof(addr)),
3003 strerror(errno)));
3004 exit_server_cleanly("sendfile_short_send: "
3005 "write_data failed");
3007 nread += to_write;
3009 SAFE_FREE(buf);
3013 /****************************************************************************
3014 Return a readbraw error (4 bytes of zero).
3015 ****************************************************************************/
3017 static void reply_readbraw_error(struct smbd_server_connection *sconn)
3019 char header[4];
3021 SIVAL(header,0,0);
3023 smbd_lock_socket(sconn);
3024 if (write_data(sconn->sock,header,4) != 4) {
3025 char addr[INET6_ADDRSTRLEN];
3027 * Try and give an error message saying what
3028 * client failed.
3030 DEBUG(0, ("write_data failed for client %s. "
3031 "Error %s\n",
3032 get_peer_addr(sconn->sock, addr, sizeof(addr)),
3033 strerror(errno)));
3035 fail_readraw();
3037 smbd_unlock_socket(sconn);
3040 /****************************************************************************
3041 Use sendfile in readbraw.
3042 ****************************************************************************/
3044 static void send_file_readbraw(connection_struct *conn,
3045 struct smb_request *req,
3046 files_struct *fsp,
3047 off_t startpos,
3048 size_t nread,
3049 ssize_t mincount)
3051 struct smbd_server_connection *sconn = req->sconn;
3052 char *outbuf = NULL;
3053 ssize_t ret=0;
3056 * We can only use sendfile on a non-chained packet
3057 * but we can use on a non-oplocked file. tridge proved this
3058 * on a train in Germany :-). JRA.
3059 * reply_readbraw has already checked the length.
3062 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3063 (fsp->wcp == NULL) &&
3064 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3065 ssize_t sendfile_read = -1;
3066 char header[4];
3067 DATA_BLOB header_blob;
3069 _smb_setlen(header,nread);
3070 header_blob = data_blob_const(header, 4);
3072 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3073 &header_blob, startpos,
3074 nread);
3075 if (sendfile_read == -1) {
3076 /* Returning ENOSYS means no data at all was sent.
3077 * Do this as a normal read. */
3078 if (errno == ENOSYS) {
3079 goto normal_readbraw;
3083 * Special hack for broken Linux with no working sendfile. If we
3084 * return EINTR we sent the header but not the rest of the data.
3085 * Fake this up by doing read/write calls.
3087 if (errno == EINTR) {
3088 /* Ensure we don't do this again. */
3089 set_use_sendfile(SNUM(conn), False);
3090 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3092 if (fake_sendfile(fsp, startpos, nread) == -1) {
3093 DEBUG(0,("send_file_readbraw: "
3094 "fake_sendfile failed for "
3095 "file %s (%s).\n",
3096 fsp_str_dbg(fsp),
3097 strerror(errno)));
3098 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3100 return;
3103 DEBUG(0,("send_file_readbraw: sendfile failed for "
3104 "file %s (%s). Terminating\n",
3105 fsp_str_dbg(fsp), strerror(errno)));
3106 exit_server_cleanly("send_file_readbraw sendfile failed");
3107 } else if (sendfile_read == 0) {
3109 * Some sendfile implementations return 0 to indicate
3110 * that there was a short read, but nothing was
3111 * actually written to the socket. In this case,
3112 * fallback to the normal read path so the header gets
3113 * the correct byte count.
3115 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3116 "bytes falling back to the normal read: "
3117 "%s\n", fsp_str_dbg(fsp)));
3118 goto normal_readbraw;
3121 /* Deal with possible short send. */
3122 if (sendfile_read != 4+nread) {
3123 sendfile_short_send(fsp, sendfile_read, 4, nread);
3125 return;
3128 normal_readbraw:
3130 outbuf = talloc_array(NULL, char, nread+4);
3131 if (!outbuf) {
3132 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3133 (unsigned)(nread+4)));
3134 reply_readbraw_error(sconn);
3135 return;
3138 if (nread > 0) {
3139 ret = read_file(fsp,outbuf+4,startpos,nread);
3140 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3141 if (ret < mincount)
3142 ret = 0;
3143 #else
3144 if (ret < nread)
3145 ret = 0;
3146 #endif
3149 _smb_setlen(outbuf,ret);
3150 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3151 char addr[INET6_ADDRSTRLEN];
3153 * Try and give an error message saying what
3154 * client failed.
3156 DEBUG(0, ("write_data failed for client %s. "
3157 "Error %s\n",
3158 get_peer_addr(fsp->conn->sconn->sock, addr,
3159 sizeof(addr)),
3160 strerror(errno)));
3162 fail_readraw();
3165 TALLOC_FREE(outbuf);
3168 /****************************************************************************
3169 Reply to a readbraw (core+ protocol).
3170 ****************************************************************************/
3172 void reply_readbraw(struct smb_request *req)
3174 connection_struct *conn = req->conn;
3175 struct smbd_server_connection *sconn = req->sconn;
3176 ssize_t maxcount,mincount;
3177 size_t nread = 0;
3178 off_t startpos;
3179 files_struct *fsp;
3180 struct lock_struct lock;
3181 off_t size = 0;
3183 START_PROFILE(SMBreadbraw);
3185 if (srv_is_signing_active(sconn) ||
3186 is_encrypted_packet(sconn, req->inbuf)) {
3187 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3188 "raw reads/writes are disallowed.");
3191 if (req->wct < 8) {
3192 reply_readbraw_error(sconn);
3193 END_PROFILE(SMBreadbraw);
3194 return;
3197 if (sconn->smb1.echo_handler.trusted_fde) {
3198 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3199 "'async smb echo handler = yes'\n"));
3200 reply_readbraw_error(sconn);
3201 END_PROFILE(SMBreadbraw);
3202 return;
3206 * Special check if an oplock break has been issued
3207 * and the readraw request croses on the wire, we must
3208 * return a zero length response here.
3211 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3214 * We have to do a check_fsp by hand here, as
3215 * we must always return 4 zero bytes on error,
3216 * not a NTSTATUS.
3219 if (!fsp || !conn || conn != fsp->conn ||
3220 req->vuid != fsp->vuid ||
3221 fsp->is_directory || fsp->fh->fd == -1) {
3223 * fsp could be NULL here so use the value from the packet. JRA.
3225 DEBUG(3,("reply_readbraw: fnum %d not valid "
3226 "- cache prime?\n",
3227 (int)SVAL(req->vwv+0, 0)));
3228 reply_readbraw_error(sconn);
3229 END_PROFILE(SMBreadbraw);
3230 return;
3233 /* Do a "by hand" version of CHECK_READ. */
3234 if (!(fsp->can_read ||
3235 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3236 (fsp->access_mask & FILE_EXECUTE)))) {
3237 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3238 (int)SVAL(req->vwv+0, 0)));
3239 reply_readbraw_error(sconn);
3240 END_PROFILE(SMBreadbraw);
3241 return;
3244 flush_write_cache(fsp, READRAW_FLUSH);
3246 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3247 if(req->wct == 10) {
3249 * This is a large offset (64 bit) read.
3252 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3254 if(startpos < 0) {
3255 DEBUG(0,("reply_readbraw: negative 64 bit "
3256 "readraw offset (%.0f) !\n",
3257 (double)startpos ));
3258 reply_readbraw_error(sconn);
3259 END_PROFILE(SMBreadbraw);
3260 return;
3264 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3265 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3267 /* ensure we don't overrun the packet size */
3268 maxcount = MIN(65535,maxcount);
3270 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3271 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3272 &lock);
3274 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3275 reply_readbraw_error(sconn);
3276 END_PROFILE(SMBreadbraw);
3277 return;
3280 if (fsp_stat(fsp) == 0) {
3281 size = fsp->fsp_name->st.st_ex_size;
3284 if (startpos >= size) {
3285 nread = 0;
3286 } else {
3287 nread = MIN(maxcount,(size - startpos));
3290 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3291 if (nread < mincount)
3292 nread = 0;
3293 #endif
3295 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3296 "min=%lu nread=%lu\n",
3297 fsp_fnum_dbg(fsp), (double)startpos,
3298 (unsigned long)maxcount,
3299 (unsigned long)mincount,
3300 (unsigned long)nread ) );
3302 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3304 DEBUG(5,("reply_readbraw finished\n"));
3306 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3308 END_PROFILE(SMBreadbraw);
3309 return;
3312 #undef DBGC_CLASS
3313 #define DBGC_CLASS DBGC_LOCKING
3315 /****************************************************************************
3316 Reply to a lockread (core+ protocol).
3317 ****************************************************************************/
3319 void reply_lockread(struct smb_request *req)
3321 connection_struct *conn = req->conn;
3322 ssize_t nread = -1;
3323 char *data;
3324 off_t startpos;
3325 size_t numtoread;
3326 NTSTATUS status;
3327 files_struct *fsp;
3328 struct byte_range_lock *br_lck = NULL;
3329 char *p = NULL;
3330 struct smbd_server_connection *sconn = req->sconn;
3332 START_PROFILE(SMBlockread);
3334 if (req->wct < 5) {
3335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3336 END_PROFILE(SMBlockread);
3337 return;
3340 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3342 if (!check_fsp(conn, req, fsp)) {
3343 END_PROFILE(SMBlockread);
3344 return;
3347 if (!CHECK_READ(fsp,req)) {
3348 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3349 END_PROFILE(SMBlockread);
3350 return;
3353 numtoread = SVAL(req->vwv+1, 0);
3354 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3356 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3358 reply_outbuf(req, 5, numtoread + 3);
3360 data = smb_buf(req->outbuf) + 3;
3363 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3364 * protocol request that predates the read/write lock concept.
3365 * Thus instead of asking for a read lock here we need to ask
3366 * for a write lock. JRA.
3367 * Note that the requested lock size is unaffected by max_recv.
3370 br_lck = do_lock(req->sconn->msg_ctx,
3371 fsp,
3372 (uint64_t)req->smbpid,
3373 (uint64_t)numtoread,
3374 (uint64_t)startpos,
3375 WRITE_LOCK,
3376 WINDOWS_LOCK,
3377 False, /* Non-blocking lock. */
3378 &status,
3379 NULL,
3380 NULL);
3381 TALLOC_FREE(br_lck);
3383 if (NT_STATUS_V(status)) {
3384 reply_nterror(req, status);
3385 END_PROFILE(SMBlockread);
3386 return;
3390 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3393 if (numtoread > sconn->smb1.negprot.max_recv) {
3394 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3395 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3396 (unsigned int)numtoread,
3397 (unsigned int)sconn->smb1.negprot.max_recv));
3398 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3400 nread = read_file(fsp,data,startpos,numtoread);
3402 if (nread < 0) {
3403 reply_nterror(req, map_nt_error_from_unix(errno));
3404 END_PROFILE(SMBlockread);
3405 return;
3408 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3410 SSVAL(req->outbuf,smb_vwv0,nread);
3411 SSVAL(req->outbuf,smb_vwv5,nread+3);
3412 p = smb_buf(req->outbuf);
3413 SCVAL(p,0,0); /* pad byte. */
3414 SSVAL(p,1,nread);
3416 DEBUG(3,("lockread %s num=%d nread=%d\n",
3417 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3419 END_PROFILE(SMBlockread);
3420 return;
3423 #undef DBGC_CLASS
3424 #define DBGC_CLASS DBGC_ALL
3426 /****************************************************************************
3427 Reply to a read.
3428 ****************************************************************************/
3430 void reply_read(struct smb_request *req)
3432 connection_struct *conn = req->conn;
3433 size_t numtoread;
3434 ssize_t nread = 0;
3435 char *data;
3436 off_t startpos;
3437 int outsize = 0;
3438 files_struct *fsp;
3439 struct lock_struct lock;
3440 struct smbd_server_connection *sconn = req->sconn;
3442 START_PROFILE(SMBread);
3444 if (req->wct < 3) {
3445 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3446 END_PROFILE(SMBread);
3447 return;
3450 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3452 if (!check_fsp(conn, req, fsp)) {
3453 END_PROFILE(SMBread);
3454 return;
3457 if (!CHECK_READ(fsp,req)) {
3458 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3459 END_PROFILE(SMBread);
3460 return;
3463 numtoread = SVAL(req->vwv+1, 0);
3464 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3466 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3469 * The requested read size cannot be greater than max_recv. JRA.
3471 if (numtoread > sconn->smb1.negprot.max_recv) {
3472 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3473 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3474 (unsigned int)numtoread,
3475 (unsigned int)sconn->smb1.negprot.max_recv));
3476 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3479 reply_outbuf(req, 5, numtoread+3);
3481 data = smb_buf(req->outbuf) + 3;
3483 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3484 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3485 &lock);
3487 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3488 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3489 END_PROFILE(SMBread);
3490 return;
3493 if (numtoread > 0)
3494 nread = read_file(fsp,data,startpos,numtoread);
3496 if (nread < 0) {
3497 reply_nterror(req, map_nt_error_from_unix(errno));
3498 goto strict_unlock;
3501 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3503 SSVAL(req->outbuf,smb_vwv0,nread);
3504 SSVAL(req->outbuf,smb_vwv5,nread+3);
3505 SCVAL(smb_buf(req->outbuf),0,1);
3506 SSVAL(smb_buf(req->outbuf),1,nread);
3508 DEBUG(3, ("read %s num=%d nread=%d\n",
3509 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3511 strict_unlock:
3512 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3514 END_PROFILE(SMBread);
3515 return;
3518 /****************************************************************************
3519 Setup readX header.
3520 ****************************************************************************/
3522 static int setup_readX_header(struct smb_request *req, char *outbuf,
3523 size_t smb_maxcnt)
3525 int outsize;
3527 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3529 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3531 SCVAL(outbuf,smb_vwv0,0xFF);
3532 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3533 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3534 SSVAL(outbuf,smb_vwv6,
3535 (smb_wct - 4) /* offset from smb header to wct */
3536 + 1 /* the wct field */
3537 + 12 * sizeof(uint16_t) /* vwv */
3538 + 2); /* the buflen field */
3539 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3540 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3541 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3542 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3543 return outsize;
3546 /****************************************************************************
3547 Reply to a read and X - possibly using sendfile.
3548 ****************************************************************************/
3550 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3551 files_struct *fsp, off_t startpos,
3552 size_t smb_maxcnt)
3554 ssize_t nread = -1;
3555 struct lock_struct lock;
3556 int saved_errno = 0;
3558 if(fsp_stat(fsp) == -1) {
3559 reply_nterror(req, map_nt_error_from_unix(errno));
3560 return;
3563 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3564 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3565 &lock);
3567 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3568 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3569 return;
3572 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3573 (startpos > fsp->fsp_name->st.st_ex_size)
3574 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3576 * We already know that we would do a short read, so don't
3577 * try the sendfile() path.
3579 goto nosendfile_read;
3583 * We can only use sendfile on a non-chained packet
3584 * but we can use on a non-oplocked file. tridge proved this
3585 * on a train in Germany :-). JRA.
3588 if (!req_is_in_chain(req) &&
3589 !is_encrypted_packet(req->sconn, req->inbuf) &&
3590 (fsp->base_fsp == NULL) &&
3591 (fsp->wcp == NULL) &&
3592 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3593 uint8 headerbuf[smb_size + 12 * 2];
3594 DATA_BLOB header;
3597 * Set up the packet header before send. We
3598 * assume here the sendfile will work (get the
3599 * correct amount of data).
3602 header = data_blob_const(headerbuf, sizeof(headerbuf));
3604 construct_reply_common_req(req, (char *)headerbuf);
3605 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3607 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3608 startpos, smb_maxcnt);
3609 if (nread == -1) {
3610 /* Returning ENOSYS means no data at all was sent.
3611 Do this as a normal read. */
3612 if (errno == ENOSYS) {
3613 goto normal_read;
3617 * Special hack for broken Linux with no working sendfile. If we
3618 * return EINTR we sent the header but not the rest of the data.
3619 * Fake this up by doing read/write calls.
3622 if (errno == EINTR) {
3623 /* Ensure we don't do this again. */
3624 set_use_sendfile(SNUM(conn), False);
3625 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3626 nread = fake_sendfile(fsp, startpos,
3627 smb_maxcnt);
3628 if (nread == -1) {
3629 DEBUG(0,("send_file_readX: "
3630 "fake_sendfile failed for "
3631 "file %s (%s).\n",
3632 fsp_str_dbg(fsp),
3633 strerror(errno)));
3634 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3636 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3637 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3638 /* No outbuf here means successful sendfile. */
3639 goto strict_unlock;
3642 DEBUG(0,("send_file_readX: sendfile failed for file "
3643 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3644 strerror(errno)));
3645 exit_server_cleanly("send_file_readX sendfile failed");
3646 } else if (nread == 0) {
3648 * Some sendfile implementations return 0 to indicate
3649 * that there was a short read, but nothing was
3650 * actually written to the socket. In this case,
3651 * fallback to the normal read path so the header gets
3652 * the correct byte count.
3654 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3655 "falling back to the normal read: %s\n",
3656 fsp_str_dbg(fsp)));
3657 goto normal_read;
3660 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3661 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3663 /* Deal with possible short send. */
3664 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3665 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3667 /* No outbuf here means successful sendfile. */
3668 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3669 SMB_PERFCOUNT_END(&req->pcd);
3670 goto strict_unlock;
3673 normal_read:
3675 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3676 uint8 headerbuf[smb_size + 2*12];
3678 construct_reply_common_req(req, (char *)headerbuf);
3679 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3681 /* Send out the header. */
3682 if (write_data(req->sconn->sock, (char *)headerbuf,
3683 sizeof(headerbuf)) != sizeof(headerbuf)) {
3685 char addr[INET6_ADDRSTRLEN];
3687 * Try and give an error message saying what
3688 * client failed.
3690 DEBUG(0, ("write_data failed for client %s. "
3691 "Error %s\n",
3692 get_peer_addr(req->sconn->sock, addr,
3693 sizeof(addr)),
3694 strerror(errno)));
3696 DEBUG(0,("send_file_readX: write_data failed for file "
3697 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3698 strerror(errno)));
3699 exit_server_cleanly("send_file_readX sendfile failed");
3701 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3702 if (nread == -1) {
3703 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3704 "file %s (%s).\n", fsp_str_dbg(fsp),
3705 strerror(errno)));
3706 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3708 goto strict_unlock;
3711 nosendfile_read:
3713 reply_outbuf(req, 12, smb_maxcnt);
3714 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3715 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3717 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3718 saved_errno = errno;
3720 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3722 if (nread < 0) {
3723 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3724 return;
3727 setup_readX_header(req, (char *)req->outbuf, nread);
3729 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3730 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3731 return;
3733 strict_unlock:
3734 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3735 TALLOC_FREE(req->outbuf);
3736 return;
3739 /****************************************************************************
3740 Reply to a read and X.
3741 ****************************************************************************/
3743 void reply_read_and_X(struct smb_request *req)
3745 struct smbd_server_connection *sconn = req->sconn;
3746 connection_struct *conn = req->conn;
3747 files_struct *fsp;
3748 off_t startpos;
3749 size_t smb_maxcnt;
3750 bool big_readX = False;
3751 #if 0
3752 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3753 #endif
3755 START_PROFILE(SMBreadX);
3757 if ((req->wct != 10) && (req->wct != 12)) {
3758 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3759 return;
3762 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3763 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3764 smb_maxcnt = SVAL(req->vwv+5, 0);
3766 /* If it's an IPC, pass off the pipe handler. */
3767 if (IS_IPC(conn)) {
3768 reply_pipe_read_and_X(req);
3769 END_PROFILE(SMBreadX);
3770 return;
3773 if (!check_fsp(conn, req, fsp)) {
3774 END_PROFILE(SMBreadX);
3775 return;
3778 if (!CHECK_READ(fsp,req)) {
3779 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3780 END_PROFILE(SMBreadX);
3781 return;
3784 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3785 (get_remote_arch() == RA_SAMBA)) {
3787 * This is Samba only behavior (up to Samba 3.6)!
3789 * Windows 2008 R2 ignores the upper_size,
3790 * so we do unless unix extentions are active
3791 * or "smbclient" is talking to us.
3793 size_t upper_size = SVAL(req->vwv+7, 0);
3794 smb_maxcnt |= (upper_size<<16);
3795 if (upper_size > 1) {
3796 /* Can't do this on a chained packet. */
3797 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3798 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3799 END_PROFILE(SMBreadX);
3800 return;
3802 /* We currently don't do this on signed or sealed data. */
3803 if (srv_is_signing_active(req->sconn) ||
3804 is_encrypted_packet(req->sconn, req->inbuf)) {
3805 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3806 END_PROFILE(SMBreadX);
3807 return;
3809 /* Is there room in the reply for this data ? */
3810 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3811 reply_nterror(req,
3812 NT_STATUS_INVALID_PARAMETER);
3813 END_PROFILE(SMBreadX);
3814 return;
3816 big_readX = True;
3820 if (req->wct == 12) {
3822 * This is a large offset (64 bit) read.
3824 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3828 if (!big_readX) {
3829 NTSTATUS status = schedule_aio_read_and_X(conn,
3830 req,
3831 fsp,
3832 startpos,
3833 smb_maxcnt);
3834 if (NT_STATUS_IS_OK(status)) {
3835 /* Read scheduled - we're done. */
3836 goto out;
3838 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3839 /* Real error - report to client. */
3840 END_PROFILE(SMBreadX);
3841 reply_nterror(req, status);
3842 return;
3844 /* NT_STATUS_RETRY - fall back to sync read. */
3847 smbd_lock_socket(req->sconn);
3848 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3849 smbd_unlock_socket(req->sconn);
3851 out:
3852 END_PROFILE(SMBreadX);
3853 return;
3856 /****************************************************************************
3857 Error replies to writebraw must have smb_wct == 1. Fix this up.
3858 ****************************************************************************/
3860 void error_to_writebrawerr(struct smb_request *req)
3862 uint8 *old_outbuf = req->outbuf;
3864 reply_outbuf(req, 1, 0);
3866 memcpy(req->outbuf, old_outbuf, smb_size);
3867 TALLOC_FREE(old_outbuf);
3870 /****************************************************************************
3871 Read 4 bytes of a smb packet and return the smb length of the packet.
3872 Store the result in the buffer. This version of the function will
3873 never return a session keepalive (length of zero).
3874 Timeout is in milliseconds.
3875 ****************************************************************************/
3877 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3878 size_t *len)
3880 uint8_t msgtype = NBSSkeepalive;
3882 while (msgtype == NBSSkeepalive) {
3883 NTSTATUS status;
3885 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3886 len);
3887 if (!NT_STATUS_IS_OK(status)) {
3888 char addr[INET6_ADDRSTRLEN];
3889 /* Try and give an error message
3890 * saying what client failed. */
3891 DEBUG(0, ("read_fd_with_timeout failed for "
3892 "client %s read error = %s.\n",
3893 get_peer_addr(fd,addr,sizeof(addr)),
3894 nt_errstr(status)));
3895 return status;
3898 msgtype = CVAL(inbuf, 0);
3901 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3902 (unsigned long)len));
3904 return NT_STATUS_OK;
3907 /****************************************************************************
3908 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3909 ****************************************************************************/
3911 void reply_writebraw(struct smb_request *req)
3913 connection_struct *conn = req->conn;
3914 char *buf = NULL;
3915 ssize_t nwritten=0;
3916 ssize_t total_written=0;
3917 size_t numtowrite=0;
3918 size_t tcount;
3919 off_t startpos;
3920 const char *data=NULL;
3921 bool write_through;
3922 files_struct *fsp;
3923 struct lock_struct lock;
3924 NTSTATUS status;
3926 START_PROFILE(SMBwritebraw);
3929 * If we ever reply with an error, it must have the SMB command
3930 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3931 * we're finished.
3933 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3935 if (srv_is_signing_active(req->sconn)) {
3936 END_PROFILE(SMBwritebraw);
3937 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3938 "raw reads/writes are disallowed.");
3941 if (req->wct < 12) {
3942 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3943 error_to_writebrawerr(req);
3944 END_PROFILE(SMBwritebraw);
3945 return;
3948 if (req->sconn->smb1.echo_handler.trusted_fde) {
3949 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3950 "'async smb echo handler = yes'\n"));
3951 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3952 error_to_writebrawerr(req);
3953 END_PROFILE(SMBwritebraw);
3954 return;
3957 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3958 if (!check_fsp(conn, req, fsp)) {
3959 error_to_writebrawerr(req);
3960 END_PROFILE(SMBwritebraw);
3961 return;
3964 if (!CHECK_WRITE(fsp)) {
3965 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3966 error_to_writebrawerr(req);
3967 END_PROFILE(SMBwritebraw);
3968 return;
3971 tcount = IVAL(req->vwv+1, 0);
3972 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3973 write_through = BITSETW(req->vwv+7,0);
3975 /* We have to deal with slightly different formats depending
3976 on whether we are using the core+ or lanman1.0 protocol */
3978 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3979 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3980 data = smb_buf_const(req->inbuf);
3981 } else {
3982 numtowrite = SVAL(req->vwv+10, 0);
3983 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3986 /* Ensure we don't write bytes past the end of this packet. */
3987 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3989 error_to_writebrawerr(req);
3990 END_PROFILE(SMBwritebraw);
3991 return;
3994 if (!fsp->print_file) {
3995 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3996 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3997 &lock);
3999 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4000 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4001 error_to_writebrawerr(req);
4002 END_PROFILE(SMBwritebraw);
4003 return;
4007 if (numtowrite>0) {
4008 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4011 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4012 "wrote=%d sync=%d\n",
4013 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4014 (int)nwritten, (int)write_through));
4016 if (nwritten < (ssize_t)numtowrite) {
4017 reply_nterror(req, NT_STATUS_DISK_FULL);
4018 error_to_writebrawerr(req);
4019 goto strict_unlock;
4022 total_written = nwritten;
4024 /* Allocate a buffer of 64k + length. */
4025 buf = talloc_array(NULL, char, 65540);
4026 if (!buf) {
4027 reply_nterror(req, NT_STATUS_NO_MEMORY);
4028 error_to_writebrawerr(req);
4029 goto strict_unlock;
4032 /* Return a SMBwritebraw message to the redirector to tell
4033 * it to send more bytes */
4035 memcpy(buf, req->inbuf, smb_size);
4036 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4037 SCVAL(buf,smb_com,SMBwritebraw);
4038 SSVALS(buf,smb_vwv0,0xFFFF);
4039 show_msg(buf);
4040 if (!srv_send_smb(req->sconn,
4041 buf,
4042 false, 0, /* no signing */
4043 IS_CONN_ENCRYPTED(conn),
4044 &req->pcd)) {
4045 exit_server_cleanly("reply_writebraw: srv_send_smb "
4046 "failed.");
4049 /* Now read the raw data into the buffer and write it */
4050 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4051 &numtowrite);
4052 if (!NT_STATUS_IS_OK(status)) {
4053 exit_server_cleanly("secondary writebraw failed");
4056 /* Set up outbuf to return the correct size */
4057 reply_outbuf(req, 1, 0);
4059 if (numtowrite != 0) {
4061 if (numtowrite > 0xFFFF) {
4062 DEBUG(0,("reply_writebraw: Oversize secondary write "
4063 "raw requested (%u). Terminating\n",
4064 (unsigned int)numtowrite ));
4065 exit_server_cleanly("secondary writebraw failed");
4068 if (tcount > nwritten+numtowrite) {
4069 DEBUG(3,("reply_writebraw: Client overestimated the "
4070 "write %d %d %d\n",
4071 (int)tcount,(int)nwritten,(int)numtowrite));
4074 status = read_data(req->sconn->sock, buf+4, numtowrite);
4076 if (!NT_STATUS_IS_OK(status)) {
4077 char addr[INET6_ADDRSTRLEN];
4078 /* Try and give an error message
4079 * saying what client failed. */
4080 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4081 "raw read failed (%s) for client %s. "
4082 "Terminating\n", nt_errstr(status),
4083 get_peer_addr(req->sconn->sock, addr,
4084 sizeof(addr))));
4085 exit_server_cleanly("secondary writebraw failed");
4088 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4089 if (nwritten == -1) {
4090 TALLOC_FREE(buf);
4091 reply_nterror(req, map_nt_error_from_unix(errno));
4092 error_to_writebrawerr(req);
4093 goto strict_unlock;
4096 if (nwritten < (ssize_t)numtowrite) {
4097 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4098 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4101 if (nwritten > 0) {
4102 total_written += nwritten;
4106 TALLOC_FREE(buf);
4107 SSVAL(req->outbuf,smb_vwv0,total_written);
4109 status = sync_file(conn, fsp, write_through);
4110 if (!NT_STATUS_IS_OK(status)) {
4111 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4112 fsp_str_dbg(fsp), nt_errstr(status)));
4113 reply_nterror(req, status);
4114 error_to_writebrawerr(req);
4115 goto strict_unlock;
4118 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4119 "wrote=%d\n",
4120 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4121 (int)total_written));
4123 if (!fsp->print_file) {
4124 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4127 /* We won't return a status if write through is not selected - this
4128 * follows what WfWg does */
4129 END_PROFILE(SMBwritebraw);
4131 if (!write_through && total_written==tcount) {
4133 #if RABBIT_PELLET_FIX
4135 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4136 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4137 * JRA.
4139 if (!send_keepalive(req->sconn->sock)) {
4140 exit_server_cleanly("reply_writebraw: send of "
4141 "keepalive failed");
4143 #endif
4144 TALLOC_FREE(req->outbuf);
4146 return;
4148 strict_unlock:
4149 if (!fsp->print_file) {
4150 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4153 END_PROFILE(SMBwritebraw);
4154 return;
4157 #undef DBGC_CLASS
4158 #define DBGC_CLASS DBGC_LOCKING
4160 /****************************************************************************
4161 Reply to a writeunlock (core+).
4162 ****************************************************************************/
4164 void reply_writeunlock(struct smb_request *req)
4166 connection_struct *conn = req->conn;
4167 ssize_t nwritten = -1;
4168 size_t numtowrite;
4169 off_t startpos;
4170 const char *data;
4171 NTSTATUS status = NT_STATUS_OK;
4172 files_struct *fsp;
4173 struct lock_struct lock;
4174 int saved_errno = 0;
4176 START_PROFILE(SMBwriteunlock);
4178 if (req->wct < 5) {
4179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4180 END_PROFILE(SMBwriteunlock);
4181 return;
4184 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4186 if (!check_fsp(conn, req, fsp)) {
4187 END_PROFILE(SMBwriteunlock);
4188 return;
4191 if (!CHECK_WRITE(fsp)) {
4192 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4193 END_PROFILE(SMBwriteunlock);
4194 return;
4197 numtowrite = SVAL(req->vwv+1, 0);
4198 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4199 data = (const char *)req->buf + 3;
4201 if (!fsp->print_file && numtowrite > 0) {
4202 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4203 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4204 &lock);
4206 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4207 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4208 END_PROFILE(SMBwriteunlock);
4209 return;
4213 /* The special X/Open SMB protocol handling of
4214 zero length writes is *NOT* done for
4215 this call */
4216 if(numtowrite == 0) {
4217 nwritten = 0;
4218 } else {
4219 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4220 saved_errno = errno;
4223 status = sync_file(conn, fsp, False /* write through */);
4224 if (!NT_STATUS_IS_OK(status)) {
4225 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4226 fsp_str_dbg(fsp), nt_errstr(status)));
4227 reply_nterror(req, status);
4228 goto strict_unlock;
4231 if(nwritten < 0) {
4232 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4233 goto strict_unlock;
4236 if((nwritten < numtowrite) && (numtowrite != 0)) {
4237 reply_nterror(req, NT_STATUS_DISK_FULL);
4238 goto strict_unlock;
4241 if (numtowrite && !fsp->print_file) {
4242 status = do_unlock(req->sconn->msg_ctx,
4243 fsp,
4244 (uint64_t)req->smbpid,
4245 (uint64_t)numtowrite,
4246 (uint64_t)startpos,
4247 WINDOWS_LOCK);
4249 if (NT_STATUS_V(status)) {
4250 reply_nterror(req, status);
4251 goto strict_unlock;
4255 reply_outbuf(req, 1, 0);
4257 SSVAL(req->outbuf,smb_vwv0,nwritten);
4259 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4260 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4262 strict_unlock:
4263 if (numtowrite && !fsp->print_file) {
4264 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4267 END_PROFILE(SMBwriteunlock);
4268 return;
4271 #undef DBGC_CLASS
4272 #define DBGC_CLASS DBGC_ALL
4274 /****************************************************************************
4275 Reply to a write.
4276 ****************************************************************************/
4278 void reply_write(struct smb_request *req)
4280 connection_struct *conn = req->conn;
4281 size_t numtowrite;
4282 ssize_t nwritten = -1;
4283 off_t startpos;
4284 const char *data;
4285 files_struct *fsp;
4286 struct lock_struct lock;
4287 NTSTATUS status;
4288 int saved_errno = 0;
4290 START_PROFILE(SMBwrite);
4292 if (req->wct < 5) {
4293 END_PROFILE(SMBwrite);
4294 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4295 return;
4298 /* If it's an IPC, pass off the pipe handler. */
4299 if (IS_IPC(conn)) {
4300 reply_pipe_write(req);
4301 END_PROFILE(SMBwrite);
4302 return;
4305 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4307 if (!check_fsp(conn, req, fsp)) {
4308 END_PROFILE(SMBwrite);
4309 return;
4312 if (!CHECK_WRITE(fsp)) {
4313 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4314 END_PROFILE(SMBwrite);
4315 return;
4318 numtowrite = SVAL(req->vwv+1, 0);
4319 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4320 data = (const char *)req->buf + 3;
4322 if (!fsp->print_file) {
4323 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4324 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4325 &lock);
4327 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4328 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4329 END_PROFILE(SMBwrite);
4330 return;
4335 * X/Open SMB protocol says that if smb_vwv1 is
4336 * zero then the file size should be extended or
4337 * truncated to the size given in smb_vwv[2-3].
4340 if(numtowrite == 0) {
4342 * This is actually an allocate call, and set EOF. JRA.
4344 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4345 if (nwritten < 0) {
4346 reply_nterror(req, NT_STATUS_DISK_FULL);
4347 goto strict_unlock;
4349 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4350 if (nwritten < 0) {
4351 reply_nterror(req, NT_STATUS_DISK_FULL);
4352 goto strict_unlock;
4354 trigger_write_time_update_immediate(fsp);
4355 } else {
4356 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4359 status = sync_file(conn, fsp, False);
4360 if (!NT_STATUS_IS_OK(status)) {
4361 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4362 fsp_str_dbg(fsp), nt_errstr(status)));
4363 reply_nterror(req, status);
4364 goto strict_unlock;
4367 if(nwritten < 0) {
4368 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4369 goto strict_unlock;
4372 if((nwritten == 0) && (numtowrite != 0)) {
4373 reply_nterror(req, NT_STATUS_DISK_FULL);
4374 goto strict_unlock;
4377 reply_outbuf(req, 1, 0);
4379 SSVAL(req->outbuf,smb_vwv0,nwritten);
4381 if (nwritten < (ssize_t)numtowrite) {
4382 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4383 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4386 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4388 strict_unlock:
4389 if (!fsp->print_file) {
4390 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4393 END_PROFILE(SMBwrite);
4394 return;
4397 /****************************************************************************
4398 Ensure a buffer is a valid writeX for recvfile purposes.
4399 ****************************************************************************/
4401 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4402 (2*14) + /* word count (including bcc) */ \
4403 1 /* pad byte */)
4405 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4406 const uint8_t *inbuf)
4408 size_t numtowrite;
4409 connection_struct *conn = NULL;
4410 unsigned int doff = 0;
4411 size_t len = smb_len_large(inbuf);
4412 struct smbXsrv_tcon *tcon;
4413 NTSTATUS status;
4414 NTTIME now = 0;
4416 if (is_encrypted_packet(sconn, inbuf)) {
4417 /* Can't do this on encrypted
4418 * connections. */
4419 return false;
4422 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4423 return false;
4426 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4427 CVAL(inbuf,smb_wct) != 14) {
4428 DEBUG(10,("is_valid_writeX_buffer: chained or "
4429 "invalid word length.\n"));
4430 return false;
4433 status = smb1srv_tcon_lookup(sconn->conn, SVAL(inbuf, smb_tid),
4434 now, &tcon);
4435 if (!NT_STATUS_IS_OK(status)) {
4436 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4437 return false;
4439 conn = tcon->compat;
4441 if (IS_IPC(conn)) {
4442 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4443 return false;
4445 if (IS_PRINT(conn)) {
4446 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4447 return false;
4449 doff = SVAL(inbuf,smb_vwv11);
4451 numtowrite = SVAL(inbuf,smb_vwv10);
4453 if (len > doff && len - doff > 0xFFFF) {
4454 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4457 if (numtowrite == 0) {
4458 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4459 return false;
4462 /* Ensure the sizes match up. */
4463 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4464 /* no pad byte...old smbclient :-( */
4465 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4466 (unsigned int)doff,
4467 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4468 return false;
4471 if (len - doff != numtowrite) {
4472 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4473 "len = %u, doff = %u, numtowrite = %u\n",
4474 (unsigned int)len,
4475 (unsigned int)doff,
4476 (unsigned int)numtowrite ));
4477 return false;
4480 DEBUG(10,("is_valid_writeX_buffer: true "
4481 "len = %u, doff = %u, numtowrite = %u\n",
4482 (unsigned int)len,
4483 (unsigned int)doff,
4484 (unsigned int)numtowrite ));
4486 return true;
4489 /****************************************************************************
4490 Reply to a write and X.
4491 ****************************************************************************/
4493 void reply_write_and_X(struct smb_request *req)
4495 connection_struct *conn = req->conn;
4496 files_struct *fsp;
4497 struct lock_struct lock;
4498 off_t startpos;
4499 size_t numtowrite;
4500 bool write_through;
4501 ssize_t nwritten;
4502 unsigned int smb_doff;
4503 unsigned int smblen;
4504 const char *data;
4505 NTSTATUS status;
4506 int saved_errno = 0;
4508 START_PROFILE(SMBwriteX);
4510 if ((req->wct != 12) && (req->wct != 14)) {
4511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4512 goto out;
4515 numtowrite = SVAL(req->vwv+10, 0);
4516 smb_doff = SVAL(req->vwv+11, 0);
4517 smblen = smb_len(req->inbuf);
4519 if (req->unread_bytes > 0xFFFF ||
4520 (smblen > smb_doff &&
4521 smblen - smb_doff > 0xFFFF)) {
4522 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4525 if (req->unread_bytes) {
4526 /* Can't do a recvfile write on IPC$ */
4527 if (IS_IPC(conn)) {
4528 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4529 goto out;
4531 if (numtowrite != req->unread_bytes) {
4532 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4533 goto out;
4535 } else {
4536 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4537 smb_doff + numtowrite > smblen) {
4538 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4539 goto out;
4543 /* If it's an IPC, pass off the pipe handler. */
4544 if (IS_IPC(conn)) {
4545 if (req->unread_bytes) {
4546 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4547 goto out;
4549 reply_pipe_write_and_X(req);
4550 goto out;
4553 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4554 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4555 write_through = BITSETW(req->vwv+7,0);
4557 if (!check_fsp(conn, req, fsp)) {
4558 goto out;
4561 if (!CHECK_WRITE(fsp)) {
4562 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4563 goto out;
4566 data = smb_base(req->inbuf) + smb_doff;
4568 if(req->wct == 14) {
4570 * This is a large offset (64 bit) write.
4572 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4576 /* X/Open SMB protocol says that, unlike SMBwrite
4577 if the length is zero then NO truncation is
4578 done, just a write of zero. To truncate a file,
4579 use SMBwrite. */
4581 if(numtowrite == 0) {
4582 nwritten = 0;
4583 } else {
4584 if (req->unread_bytes == 0) {
4585 status = schedule_aio_write_and_X(conn,
4586 req,
4587 fsp,
4588 data,
4589 startpos,
4590 numtowrite);
4592 if (NT_STATUS_IS_OK(status)) {
4593 /* write scheduled - we're done. */
4594 goto out;
4596 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4597 /* Real error - report to client. */
4598 reply_nterror(req, status);
4599 goto out;
4601 /* NT_STATUS_RETRY - fall through to sync write. */
4604 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4605 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4606 &lock);
4608 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4609 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4610 goto out;
4613 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4614 saved_errno = errno;
4616 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4619 if(nwritten < 0) {
4620 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4621 goto out;
4624 if((nwritten == 0) && (numtowrite != 0)) {
4625 reply_nterror(req, NT_STATUS_DISK_FULL);
4626 goto out;
4629 reply_outbuf(req, 6, 0);
4630 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4631 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4632 SSVAL(req->outbuf,smb_vwv2,nwritten);
4633 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4635 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4636 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4638 status = sync_file(conn, fsp, write_through);
4639 if (!NT_STATUS_IS_OK(status)) {
4640 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4641 fsp_str_dbg(fsp), nt_errstr(status)));
4642 reply_nterror(req, status);
4643 goto out;
4646 END_PROFILE(SMBwriteX);
4647 return;
4649 out:
4650 if (req->unread_bytes) {
4651 /* writeX failed. drain socket. */
4652 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
4653 req->unread_bytes) {
4654 smb_panic("failed to drain pending bytes");
4656 req->unread_bytes = 0;
4659 END_PROFILE(SMBwriteX);
4660 return;
4663 /****************************************************************************
4664 Reply to a lseek.
4665 ****************************************************************************/
4667 void reply_lseek(struct smb_request *req)
4669 connection_struct *conn = req->conn;
4670 off_t startpos;
4671 off_t res= -1;
4672 int mode,umode;
4673 files_struct *fsp;
4675 START_PROFILE(SMBlseek);
4677 if (req->wct < 4) {
4678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4679 END_PROFILE(SMBlseek);
4680 return;
4683 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4685 if (!check_fsp(conn, req, fsp)) {
4686 return;
4689 flush_write_cache(fsp, SEEK_FLUSH);
4691 mode = SVAL(req->vwv+1, 0) & 3;
4692 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4693 startpos = (off_t)IVALS(req->vwv+2, 0);
4695 switch (mode) {
4696 case 0:
4697 umode = SEEK_SET;
4698 res = startpos;
4699 break;
4700 case 1:
4701 umode = SEEK_CUR;
4702 res = fsp->fh->pos + startpos;
4703 break;
4704 case 2:
4705 umode = SEEK_END;
4706 break;
4707 default:
4708 umode = SEEK_SET;
4709 res = startpos;
4710 break;
4713 if (umode == SEEK_END) {
4714 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4715 if(errno == EINVAL) {
4716 off_t current_pos = startpos;
4718 if(fsp_stat(fsp) == -1) {
4719 reply_nterror(req,
4720 map_nt_error_from_unix(errno));
4721 END_PROFILE(SMBlseek);
4722 return;
4725 current_pos += fsp->fsp_name->st.st_ex_size;
4726 if(current_pos < 0)
4727 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4731 if(res == -1) {
4732 reply_nterror(req, map_nt_error_from_unix(errno));
4733 END_PROFILE(SMBlseek);
4734 return;
4738 fsp->fh->pos = res;
4740 reply_outbuf(req, 2, 0);
4741 SIVAL(req->outbuf,smb_vwv0,res);
4743 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4744 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4746 END_PROFILE(SMBlseek);
4747 return;
4750 /****************************************************************************
4751 Reply to a flush.
4752 ****************************************************************************/
4754 void reply_flush(struct smb_request *req)
4756 connection_struct *conn = req->conn;
4757 uint16 fnum;
4758 files_struct *fsp;
4760 START_PROFILE(SMBflush);
4762 if (req->wct < 1) {
4763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4764 return;
4767 fnum = SVAL(req->vwv+0, 0);
4768 fsp = file_fsp(req, fnum);
4770 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4771 return;
4774 if (!fsp) {
4775 file_sync_all(conn);
4776 } else {
4777 NTSTATUS status = sync_file(conn, fsp, True);
4778 if (!NT_STATUS_IS_OK(status)) {
4779 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4780 fsp_str_dbg(fsp), nt_errstr(status)));
4781 reply_nterror(req, status);
4782 END_PROFILE(SMBflush);
4783 return;
4787 reply_outbuf(req, 0, 0);
4789 DEBUG(3,("flush\n"));
4790 END_PROFILE(SMBflush);
4791 return;
4794 /****************************************************************************
4795 Reply to a exit.
4796 conn POINTER CAN BE NULL HERE !
4797 ****************************************************************************/
4799 void reply_exit(struct smb_request *req)
4801 START_PROFILE(SMBexit);
4803 file_close_pid(req->sconn, req->smbpid, req->vuid);
4805 reply_outbuf(req, 0, 0);
4807 DEBUG(3,("exit\n"));
4809 END_PROFILE(SMBexit);
4810 return;
4813 /****************************************************************************
4814 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4815 ****************************************************************************/
4817 void reply_close(struct smb_request *req)
4819 connection_struct *conn = req->conn;
4820 NTSTATUS status = NT_STATUS_OK;
4821 files_struct *fsp = NULL;
4822 START_PROFILE(SMBclose);
4824 if (req->wct < 3) {
4825 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4826 END_PROFILE(SMBclose);
4827 return;
4830 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4833 * We can only use check_fsp if we know it's not a directory.
4836 if (!check_fsp_open(conn, req, fsp)) {
4837 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4838 END_PROFILE(SMBclose);
4839 return;
4842 if(fsp->is_directory) {
4844 * Special case - close NT SMB directory handle.
4846 DEBUG(3,("close directory %s\n", fsp_fnum_dbg(fsp)));
4847 status = close_file(req, fsp, NORMAL_CLOSE);
4848 } else {
4849 time_t t;
4851 * Close ordinary file.
4854 DEBUG(3,("close fd=%d %s (numopen=%d)\n",
4855 fsp->fh->fd, fsp_fnum_dbg(fsp),
4856 conn->num_files_open));
4859 * Take care of any time sent in the close.
4862 t = srv_make_unix_date3(req->vwv+1);
4863 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4866 * close_file() returns the unix errno if an error
4867 * was detected on close - normally this is due to
4868 * a disk full error. If not then it was probably an I/O error.
4871 status = close_file(req, fsp, NORMAL_CLOSE);
4874 if (!NT_STATUS_IS_OK(status)) {
4875 reply_nterror(req, status);
4876 END_PROFILE(SMBclose);
4877 return;
4880 reply_outbuf(req, 0, 0);
4881 END_PROFILE(SMBclose);
4882 return;
4885 /****************************************************************************
4886 Reply to a writeclose (Core+ protocol).
4887 ****************************************************************************/
4889 void reply_writeclose(struct smb_request *req)
4891 connection_struct *conn = req->conn;
4892 size_t numtowrite;
4893 ssize_t nwritten = -1;
4894 NTSTATUS close_status = NT_STATUS_OK;
4895 off_t startpos;
4896 const char *data;
4897 struct timespec mtime;
4898 files_struct *fsp;
4899 struct lock_struct lock;
4901 START_PROFILE(SMBwriteclose);
4903 if (req->wct < 6) {
4904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4905 END_PROFILE(SMBwriteclose);
4906 return;
4909 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4911 if (!check_fsp(conn, req, fsp)) {
4912 END_PROFILE(SMBwriteclose);
4913 return;
4915 if (!CHECK_WRITE(fsp)) {
4916 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4917 END_PROFILE(SMBwriteclose);
4918 return;
4921 numtowrite = SVAL(req->vwv+1, 0);
4922 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4923 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4924 data = (const char *)req->buf + 1;
4926 if (!fsp->print_file) {
4927 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4928 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4929 &lock);
4931 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4932 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4933 END_PROFILE(SMBwriteclose);
4934 return;
4938 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4940 set_close_write_time(fsp, mtime);
4943 * More insanity. W2K only closes the file if writelen > 0.
4944 * JRA.
4947 if (numtowrite) {
4948 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4949 "file %s\n", fsp_str_dbg(fsp)));
4950 close_status = close_file(req, fsp, NORMAL_CLOSE);
4953 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
4954 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
4955 conn->num_files_open));
4957 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4958 reply_nterror(req, NT_STATUS_DISK_FULL);
4959 goto strict_unlock;
4962 if(!NT_STATUS_IS_OK(close_status)) {
4963 reply_nterror(req, close_status);
4964 goto strict_unlock;
4967 reply_outbuf(req, 1, 0);
4969 SSVAL(req->outbuf,smb_vwv0,nwritten);
4971 strict_unlock:
4972 if (numtowrite && !fsp->print_file) {
4973 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4976 END_PROFILE(SMBwriteclose);
4977 return;
4980 #undef DBGC_CLASS
4981 #define DBGC_CLASS DBGC_LOCKING
4983 /****************************************************************************
4984 Reply to a lock.
4985 ****************************************************************************/
4987 void reply_lock(struct smb_request *req)
4989 connection_struct *conn = req->conn;
4990 uint64_t count,offset;
4991 NTSTATUS status;
4992 files_struct *fsp;
4993 struct byte_range_lock *br_lck = NULL;
4995 START_PROFILE(SMBlock);
4997 if (req->wct < 5) {
4998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4999 END_PROFILE(SMBlock);
5000 return;
5003 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5005 if (!check_fsp(conn, req, fsp)) {
5006 END_PROFILE(SMBlock);
5007 return;
5010 count = (uint64_t)IVAL(req->vwv+1, 0);
5011 offset = (uint64_t)IVAL(req->vwv+3, 0);
5013 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5014 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5016 br_lck = do_lock(req->sconn->msg_ctx,
5017 fsp,
5018 (uint64_t)req->smbpid,
5019 count,
5020 offset,
5021 WRITE_LOCK,
5022 WINDOWS_LOCK,
5023 False, /* Non-blocking lock. */
5024 &status,
5025 NULL,
5026 NULL);
5028 TALLOC_FREE(br_lck);
5030 if (NT_STATUS_V(status)) {
5031 reply_nterror(req, status);
5032 END_PROFILE(SMBlock);
5033 return;
5036 reply_outbuf(req, 0, 0);
5038 END_PROFILE(SMBlock);
5039 return;
5042 /****************************************************************************
5043 Reply to a unlock.
5044 ****************************************************************************/
5046 void reply_unlock(struct smb_request *req)
5048 connection_struct *conn = req->conn;
5049 uint64_t count,offset;
5050 NTSTATUS status;
5051 files_struct *fsp;
5053 START_PROFILE(SMBunlock);
5055 if (req->wct < 5) {
5056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5057 END_PROFILE(SMBunlock);
5058 return;
5061 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5063 if (!check_fsp(conn, req, fsp)) {
5064 END_PROFILE(SMBunlock);
5065 return;
5068 count = (uint64_t)IVAL(req->vwv+1, 0);
5069 offset = (uint64_t)IVAL(req->vwv+3, 0);
5071 status = do_unlock(req->sconn->msg_ctx,
5072 fsp,
5073 (uint64_t)req->smbpid,
5074 count,
5075 offset,
5076 WINDOWS_LOCK);
5078 if (NT_STATUS_V(status)) {
5079 reply_nterror(req, status);
5080 END_PROFILE(SMBunlock);
5081 return;
5084 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5085 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5087 reply_outbuf(req, 0, 0);
5089 END_PROFILE(SMBunlock);
5090 return;
5093 #undef DBGC_CLASS
5094 #define DBGC_CLASS DBGC_ALL
5096 /****************************************************************************
5097 Reply to a tdis.
5098 conn POINTER CAN BE NULL HERE !
5099 ****************************************************************************/
5101 void reply_tdis(struct smb_request *req)
5103 NTSTATUS status;
5104 connection_struct *conn = req->conn;
5105 struct smbXsrv_tcon *tcon;
5107 START_PROFILE(SMBtdis);
5109 if (!conn) {
5110 DEBUG(4,("Invalid connection in tdis\n"));
5111 reply_force_doserror(req, ERRSRV, ERRinvnid);
5112 END_PROFILE(SMBtdis);
5113 return;
5116 tcon = conn->tcon;
5117 req->conn = NULL;
5120 * TODO: cancel all outstanding requests on the tcon
5122 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5123 if (!NT_STATUS_IS_OK(status)) {
5124 DEBUG(0, ("reply_tdis: "
5125 "smbXsrv_tcon_disconnect() failed: %s\n",
5126 nt_errstr(status)));
5128 * If we hit this case, there is something completely
5129 * wrong, so we better disconnect the transport connection.
5131 END_PROFILE(SMBtdis);
5132 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5133 return;
5136 TALLOC_FREE(tcon);
5138 reply_outbuf(req, 0, 0);
5139 END_PROFILE(SMBtdis);
5140 return;
5143 /****************************************************************************
5144 Reply to a echo.
5145 conn POINTER CAN BE NULL HERE !
5146 ****************************************************************************/
5148 void reply_echo(struct smb_request *req)
5150 connection_struct *conn = req->conn;
5151 struct smb_perfcount_data local_pcd;
5152 struct smb_perfcount_data *cur_pcd;
5153 int smb_reverb;
5154 int seq_num;
5156 START_PROFILE(SMBecho);
5158 smb_init_perfcount_data(&local_pcd);
5160 if (req->wct < 1) {
5161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5162 END_PROFILE(SMBecho);
5163 return;
5166 smb_reverb = SVAL(req->vwv+0, 0);
5168 reply_outbuf(req, 1, req->buflen);
5170 /* copy any incoming data back out */
5171 if (req->buflen > 0) {
5172 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5175 if (smb_reverb > 100) {
5176 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5177 smb_reverb = 100;
5180 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5182 /* this makes sure we catch the request pcd */
5183 if (seq_num == smb_reverb) {
5184 cur_pcd = &req->pcd;
5185 } else {
5186 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5187 cur_pcd = &local_pcd;
5190 SSVAL(req->outbuf,smb_vwv0,seq_num);
5192 show_msg((char *)req->outbuf);
5193 if (!srv_send_smb(req->sconn,
5194 (char *)req->outbuf,
5195 true, req->seqnum+1,
5196 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5197 cur_pcd))
5198 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5201 DEBUG(3,("echo %d times\n", smb_reverb));
5203 TALLOC_FREE(req->outbuf);
5205 END_PROFILE(SMBecho);
5206 return;
5209 /****************************************************************************
5210 Reply to a printopen.
5211 ****************************************************************************/
5213 void reply_printopen(struct smb_request *req)
5215 connection_struct *conn = req->conn;
5216 files_struct *fsp;
5217 NTSTATUS status;
5219 START_PROFILE(SMBsplopen);
5221 if (req->wct < 2) {
5222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5223 END_PROFILE(SMBsplopen);
5224 return;
5227 if (!CAN_PRINT(conn)) {
5228 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5229 END_PROFILE(SMBsplopen);
5230 return;
5233 status = file_new(req, conn, &fsp);
5234 if(!NT_STATUS_IS_OK(status)) {
5235 reply_nterror(req, status);
5236 END_PROFILE(SMBsplopen);
5237 return;
5240 /* Open for exclusive use, write only. */
5241 status = print_spool_open(fsp, NULL, req->vuid);
5243 if (!NT_STATUS_IS_OK(status)) {
5244 file_free(req, fsp);
5245 reply_nterror(req, status);
5246 END_PROFILE(SMBsplopen);
5247 return;
5250 reply_outbuf(req, 1, 0);
5251 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5253 DEBUG(3,("openprint fd=%d %s\n",
5254 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5256 END_PROFILE(SMBsplopen);
5257 return;
5260 /****************************************************************************
5261 Reply to a printclose.
5262 ****************************************************************************/
5264 void reply_printclose(struct smb_request *req)
5266 connection_struct *conn = req->conn;
5267 files_struct *fsp;
5268 NTSTATUS status;
5270 START_PROFILE(SMBsplclose);
5272 if (req->wct < 1) {
5273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5274 END_PROFILE(SMBsplclose);
5275 return;
5278 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5280 if (!check_fsp(conn, req, fsp)) {
5281 END_PROFILE(SMBsplclose);
5282 return;
5285 if (!CAN_PRINT(conn)) {
5286 reply_force_doserror(req, ERRSRV, ERRerror);
5287 END_PROFILE(SMBsplclose);
5288 return;
5291 DEBUG(3,("printclose fd=%d %s\n",
5292 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5294 status = close_file(req, fsp, NORMAL_CLOSE);
5296 if(!NT_STATUS_IS_OK(status)) {
5297 reply_nterror(req, status);
5298 END_PROFILE(SMBsplclose);
5299 return;
5302 reply_outbuf(req, 0, 0);
5304 END_PROFILE(SMBsplclose);
5305 return;
5308 /****************************************************************************
5309 Reply to a printqueue.
5310 ****************************************************************************/
5312 void reply_printqueue(struct smb_request *req)
5314 connection_struct *conn = req->conn;
5315 int max_count;
5316 int start_index;
5318 START_PROFILE(SMBsplretq);
5320 if (req->wct < 2) {
5321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5322 END_PROFILE(SMBsplretq);
5323 return;
5326 max_count = SVAL(req->vwv+0, 0);
5327 start_index = SVAL(req->vwv+1, 0);
5329 /* we used to allow the client to get the cnum wrong, but that
5330 is really quite gross and only worked when there was only
5331 one printer - I think we should now only accept it if they
5332 get it right (tridge) */
5333 if (!CAN_PRINT(conn)) {
5334 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5335 END_PROFILE(SMBsplretq);
5336 return;
5339 reply_outbuf(req, 2, 3);
5340 SSVAL(req->outbuf,smb_vwv0,0);
5341 SSVAL(req->outbuf,smb_vwv1,0);
5342 SCVAL(smb_buf(req->outbuf),0,1);
5343 SSVAL(smb_buf(req->outbuf),1,0);
5345 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5346 start_index, max_count));
5349 TALLOC_CTX *mem_ctx = talloc_tos();
5350 NTSTATUS status;
5351 WERROR werr;
5352 const char *sharename = lp_servicename(SNUM(conn));
5353 struct rpc_pipe_client *cli = NULL;
5354 struct dcerpc_binding_handle *b = NULL;
5355 struct policy_handle handle;
5356 struct spoolss_DevmodeContainer devmode_ctr;
5357 union spoolss_JobInfo *info;
5358 uint32_t count;
5359 uint32_t num_to_get;
5360 uint32_t first;
5361 uint32_t i;
5363 ZERO_STRUCT(handle);
5365 status = rpc_pipe_open_interface(conn,
5366 &ndr_table_spoolss.syntax_id,
5367 conn->session_info,
5368 conn->sconn->remote_address,
5369 conn->sconn->msg_ctx,
5370 &cli);
5371 if (!NT_STATUS_IS_OK(status)) {
5372 DEBUG(0, ("reply_printqueue: "
5373 "could not connect to spoolss: %s\n",
5374 nt_errstr(status)));
5375 reply_nterror(req, status);
5376 goto out;
5378 b = cli->binding_handle;
5380 ZERO_STRUCT(devmode_ctr);
5382 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5383 sharename,
5384 NULL, devmode_ctr,
5385 SEC_FLAG_MAXIMUM_ALLOWED,
5386 &handle,
5387 &werr);
5388 if (!NT_STATUS_IS_OK(status)) {
5389 reply_nterror(req, status);
5390 goto out;
5392 if (!W_ERROR_IS_OK(werr)) {
5393 reply_nterror(req, werror_to_ntstatus(werr));
5394 goto out;
5397 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5398 &handle,
5399 0, /* firstjob */
5400 0xff, /* numjobs */
5401 2, /* level */
5402 0, /* offered */
5403 &count,
5404 &info);
5405 if (!W_ERROR_IS_OK(werr)) {
5406 reply_nterror(req, werror_to_ntstatus(werr));
5407 goto out;
5410 if (max_count > 0) {
5411 first = start_index;
5412 } else {
5413 first = start_index + max_count + 1;
5416 if (first >= count) {
5417 num_to_get = first;
5418 } else {
5419 num_to_get = first + MIN(ABS(max_count), count - first);
5422 for (i = first; i < num_to_get; i++) {
5423 char blob[28];
5424 char *p = blob;
5425 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5426 int qstatus;
5427 uint16_t qrapjobid = pjobid_to_rap(sharename,
5428 info[i].info2.job_id);
5430 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5431 qstatus = 2;
5432 } else {
5433 qstatus = 3;
5436 srv_put_dos_date2(p, 0, qtime);
5437 SCVAL(p, 4, qstatus);
5438 SSVAL(p, 5, qrapjobid);
5439 SIVAL(p, 7, info[i].info2.size);
5440 SCVAL(p, 11, 0);
5441 srvstr_push(blob, req->flags2, p+12,
5442 info[i].info2.notify_name, 16, STR_ASCII);
5444 if (message_push_blob(
5445 &req->outbuf,
5446 data_blob_const(
5447 blob, sizeof(blob))) == -1) {
5448 reply_nterror(req, NT_STATUS_NO_MEMORY);
5449 goto out;
5453 if (count > 0) {
5454 SSVAL(req->outbuf,smb_vwv0,count);
5455 SSVAL(req->outbuf,smb_vwv1,
5456 (max_count>0?first+count:first-1));
5457 SCVAL(smb_buf(req->outbuf),0,1);
5458 SSVAL(smb_buf(req->outbuf),1,28*count);
5462 DEBUG(3, ("%u entries returned in queue\n",
5463 (unsigned)count));
5465 out:
5466 if (b && is_valid_policy_hnd(&handle)) {
5467 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5472 END_PROFILE(SMBsplretq);
5473 return;
5476 /****************************************************************************
5477 Reply to a printwrite.
5478 ****************************************************************************/
5480 void reply_printwrite(struct smb_request *req)
5482 connection_struct *conn = req->conn;
5483 int numtowrite;
5484 const char *data;
5485 files_struct *fsp;
5487 START_PROFILE(SMBsplwr);
5489 if (req->wct < 1) {
5490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5491 END_PROFILE(SMBsplwr);
5492 return;
5495 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5497 if (!check_fsp(conn, req, fsp)) {
5498 END_PROFILE(SMBsplwr);
5499 return;
5502 if (!fsp->print_file) {
5503 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5504 END_PROFILE(SMBsplwr);
5505 return;
5508 if (!CHECK_WRITE(fsp)) {
5509 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5510 END_PROFILE(SMBsplwr);
5511 return;
5514 numtowrite = SVAL(req->buf, 1);
5516 if (req->buflen < numtowrite + 3) {
5517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5518 END_PROFILE(SMBsplwr);
5519 return;
5522 data = (const char *)req->buf + 3;
5524 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5525 reply_nterror(req, map_nt_error_from_unix(errno));
5526 END_PROFILE(SMBsplwr);
5527 return;
5530 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5532 END_PROFILE(SMBsplwr);
5533 return;
5536 /****************************************************************************
5537 Reply to a mkdir.
5538 ****************************************************************************/
5540 void reply_mkdir(struct smb_request *req)
5542 connection_struct *conn = req->conn;
5543 struct smb_filename *smb_dname = NULL;
5544 char *directory = NULL;
5545 NTSTATUS status;
5546 TALLOC_CTX *ctx = talloc_tos();
5548 START_PROFILE(SMBmkdir);
5550 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5551 STR_TERMINATE, &status);
5552 if (!NT_STATUS_IS_OK(status)) {
5553 reply_nterror(req, status);
5554 goto out;
5557 status = filename_convert(ctx, conn,
5558 req->flags2 & FLAGS2_DFS_PATHNAMES,
5559 directory,
5561 NULL,
5562 &smb_dname);
5563 if (!NT_STATUS_IS_OK(status)) {
5564 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5565 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5566 ERRSRV, ERRbadpath);
5567 goto out;
5569 reply_nterror(req, status);
5570 goto out;
5573 status = create_directory(conn, req, smb_dname);
5575 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5577 if (!NT_STATUS_IS_OK(status)) {
5579 if (!use_nt_status()
5580 && NT_STATUS_EQUAL(status,
5581 NT_STATUS_OBJECT_NAME_COLLISION)) {
5583 * Yes, in the DOS error code case we get a
5584 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5585 * samba4 torture test.
5587 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5590 reply_nterror(req, status);
5591 goto out;
5594 reply_outbuf(req, 0, 0);
5596 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5597 out:
5598 TALLOC_FREE(smb_dname);
5599 END_PROFILE(SMBmkdir);
5600 return;
5603 /****************************************************************************
5604 Reply to a rmdir.
5605 ****************************************************************************/
5607 void reply_rmdir(struct smb_request *req)
5609 connection_struct *conn = req->conn;
5610 struct smb_filename *smb_dname = NULL;
5611 char *directory = NULL;
5612 NTSTATUS status;
5613 TALLOC_CTX *ctx = talloc_tos();
5614 files_struct *fsp = NULL;
5615 int info = 0;
5616 struct smbd_server_connection *sconn = req->sconn;
5618 START_PROFILE(SMBrmdir);
5620 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5621 STR_TERMINATE, &status);
5622 if (!NT_STATUS_IS_OK(status)) {
5623 reply_nterror(req, status);
5624 goto out;
5627 status = filename_convert(ctx, conn,
5628 req->flags2 & FLAGS2_DFS_PATHNAMES,
5629 directory,
5631 NULL,
5632 &smb_dname);
5633 if (!NT_STATUS_IS_OK(status)) {
5634 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5635 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5636 ERRSRV, ERRbadpath);
5637 goto out;
5639 reply_nterror(req, status);
5640 goto out;
5643 if (is_ntfs_stream_smb_fname(smb_dname)) {
5644 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5645 goto out;
5648 status = SMB_VFS_CREATE_FILE(
5649 conn, /* conn */
5650 req, /* req */
5651 0, /* root_dir_fid */
5652 smb_dname, /* fname */
5653 DELETE_ACCESS, /* access_mask */
5654 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5655 FILE_SHARE_DELETE),
5656 FILE_OPEN, /* create_disposition*/
5657 FILE_DIRECTORY_FILE, /* create_options */
5658 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5659 0, /* oplock_request */
5660 0, /* allocation_size */
5661 0, /* private_flags */
5662 NULL, /* sd */
5663 NULL, /* ea_list */
5664 &fsp, /* result */
5665 &info); /* pinfo */
5667 if (!NT_STATUS_IS_OK(status)) {
5668 if (open_was_deferred(req->sconn, req->mid)) {
5669 /* We have re-scheduled this call. */
5670 goto out;
5672 reply_nterror(req, status);
5673 goto out;
5676 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5677 if (!NT_STATUS_IS_OK(status)) {
5678 close_file(req, fsp, ERROR_CLOSE);
5679 reply_nterror(req, status);
5680 goto out;
5683 if (!set_delete_on_close(fsp, true,
5684 conn->session_info->security_token,
5685 conn->session_info->unix_token)) {
5686 close_file(req, fsp, ERROR_CLOSE);
5687 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5688 goto out;
5691 status = close_file(req, fsp, NORMAL_CLOSE);
5692 if (!NT_STATUS_IS_OK(status)) {
5693 reply_nterror(req, status);
5694 } else {
5695 reply_outbuf(req, 0, 0);
5698 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5700 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5701 out:
5702 TALLOC_FREE(smb_dname);
5703 END_PROFILE(SMBrmdir);
5704 return;
5707 /*******************************************************************
5708 Resolve wildcards in a filename rename.
5709 ********************************************************************/
5711 static bool resolve_wildcards(TALLOC_CTX *ctx,
5712 const char *name1,
5713 const char *name2,
5714 char **pp_newname)
5716 char *name2_copy = NULL;
5717 char *root1 = NULL;
5718 char *root2 = NULL;
5719 char *ext1 = NULL;
5720 char *ext2 = NULL;
5721 char *p,*p2, *pname1, *pname2;
5723 name2_copy = talloc_strdup(ctx, name2);
5724 if (!name2_copy) {
5725 return False;
5728 pname1 = strrchr_m(name1,'/');
5729 pname2 = strrchr_m(name2_copy,'/');
5731 if (!pname1 || !pname2) {
5732 return False;
5735 /* Truncate the copy of name2 at the last '/' */
5736 *pname2 = '\0';
5738 /* Now go past the '/' */
5739 pname1++;
5740 pname2++;
5742 root1 = talloc_strdup(ctx, pname1);
5743 root2 = talloc_strdup(ctx, pname2);
5745 if (!root1 || !root2) {
5746 return False;
5749 p = strrchr_m(root1,'.');
5750 if (p) {
5751 *p = 0;
5752 ext1 = talloc_strdup(ctx, p+1);
5753 } else {
5754 ext1 = talloc_strdup(ctx, "");
5756 p = strrchr_m(root2,'.');
5757 if (p) {
5758 *p = 0;
5759 ext2 = talloc_strdup(ctx, p+1);
5760 } else {
5761 ext2 = talloc_strdup(ctx, "");
5764 if (!ext1 || !ext2) {
5765 return False;
5768 p = root1;
5769 p2 = root2;
5770 while (*p2) {
5771 if (*p2 == '?') {
5772 /* Hmmm. Should this be mb-aware ? */
5773 *p2 = *p;
5774 p2++;
5775 } else if (*p2 == '*') {
5776 *p2 = '\0';
5777 root2 = talloc_asprintf(ctx, "%s%s",
5778 root2,
5780 if (!root2) {
5781 return False;
5783 break;
5784 } else {
5785 p2++;
5787 if (*p) {
5788 p++;
5792 p = ext1;
5793 p2 = ext2;
5794 while (*p2) {
5795 if (*p2 == '?') {
5796 /* Hmmm. Should this be mb-aware ? */
5797 *p2 = *p;
5798 p2++;
5799 } else if (*p2 == '*') {
5800 *p2 = '\0';
5801 ext2 = talloc_asprintf(ctx, "%s%s",
5802 ext2,
5804 if (!ext2) {
5805 return False;
5807 break;
5808 } else {
5809 p2++;
5811 if (*p) {
5812 p++;
5816 if (*ext2) {
5817 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5818 name2_copy,
5819 root2,
5820 ext2);
5821 } else {
5822 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5823 name2_copy,
5824 root2);
5827 if (!*pp_newname) {
5828 return False;
5831 return True;
5834 /****************************************************************************
5835 Ensure open files have their names updated. Updated to notify other smbd's
5836 asynchronously.
5837 ****************************************************************************/
5839 static void rename_open_files(connection_struct *conn,
5840 struct share_mode_lock *lck,
5841 uint32_t orig_name_hash,
5842 const struct smb_filename *smb_fname_dst)
5844 files_struct *fsp;
5845 bool did_rename = False;
5846 NTSTATUS status;
5847 uint32_t new_name_hash = 0;
5849 for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
5850 fsp = file_find_di_next(fsp)) {
5851 /* fsp_name is a relative path under the fsp. To change this for other
5852 sharepaths we need to manipulate relative paths. */
5853 /* TODO - create the absolute path and manipulate the newname
5854 relative to the sharepath. */
5855 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5856 continue;
5858 if (fsp->name_hash != orig_name_hash) {
5859 continue;
5861 DEBUG(10, ("rename_open_files: renaming file %s "
5862 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
5863 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5864 smb_fname_str_dbg(smb_fname_dst)));
5866 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5867 if (NT_STATUS_IS_OK(status)) {
5868 did_rename = True;
5869 new_name_hash = fsp->name_hash;
5873 if (!did_rename) {
5874 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5875 "for %s\n", file_id_string_tos(&lck->data->id),
5876 smb_fname_str_dbg(smb_fname_dst)));
5879 /* Send messages to all smbd's (not ourself) that the name has changed. */
5880 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5881 orig_name_hash, new_name_hash,
5882 smb_fname_dst);
5886 /****************************************************************************
5887 We need to check if the source path is a parent directory of the destination
5888 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5889 refuse the rename with a sharing violation. Under UNIX the above call can
5890 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5891 probably need to check that the client is a Windows one before disallowing
5892 this as a UNIX client (one with UNIX extensions) can know the source is a
5893 symlink and make this decision intelligently. Found by an excellent bug
5894 report from <AndyLiebman@aol.com>.
5895 ****************************************************************************/
5897 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5898 const struct smb_filename *smb_fname_dst)
5900 const char *psrc = smb_fname_src->base_name;
5901 const char *pdst = smb_fname_dst->base_name;
5902 size_t slen;
5904 if (psrc[0] == '.' && psrc[1] == '/') {
5905 psrc += 2;
5907 if (pdst[0] == '.' && pdst[1] == '/') {
5908 pdst += 2;
5910 if ((slen = strlen(psrc)) > strlen(pdst)) {
5911 return False;
5913 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5917 * Do the notify calls from a rename
5920 static void notify_rename(connection_struct *conn, bool is_dir,
5921 const struct smb_filename *smb_fname_src,
5922 const struct smb_filename *smb_fname_dst)
5924 char *parent_dir_src = NULL;
5925 char *parent_dir_dst = NULL;
5926 uint32 mask;
5928 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5929 : FILE_NOTIFY_CHANGE_FILE_NAME;
5931 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5932 &parent_dir_src, NULL) ||
5933 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5934 &parent_dir_dst, NULL)) {
5935 goto out;
5938 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5939 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5940 smb_fname_src->base_name);
5941 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5942 smb_fname_dst->base_name);
5944 else {
5945 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5946 smb_fname_src->base_name);
5947 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5948 smb_fname_dst->base_name);
5951 /* this is a strange one. w2k3 gives an additional event for
5952 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5953 files, but not directories */
5954 if (!is_dir) {
5955 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5956 FILE_NOTIFY_CHANGE_ATTRIBUTES
5957 |FILE_NOTIFY_CHANGE_CREATION,
5958 smb_fname_dst->base_name);
5960 out:
5961 TALLOC_FREE(parent_dir_src);
5962 TALLOC_FREE(parent_dir_dst);
5965 /****************************************************************************
5966 Returns an error if the parent directory for a filename is open in an
5967 incompatible way.
5968 ****************************************************************************/
5970 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5971 const struct smb_filename *smb_fname_dst_in)
5973 char *parent_dir = NULL;
5974 struct smb_filename smb_fname_parent;
5975 struct file_id id;
5976 files_struct *fsp = NULL;
5977 int ret;
5979 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5980 &parent_dir, NULL)) {
5981 return NT_STATUS_NO_MEMORY;
5983 ZERO_STRUCT(smb_fname_parent);
5984 smb_fname_parent.base_name = parent_dir;
5986 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5987 if (ret == -1) {
5988 return map_nt_error_from_unix(errno);
5992 * We're only checking on this smbd here, mostly good
5993 * enough.. and will pass tests.
5996 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
5997 for (fsp = file_find_di_first(conn->sconn, id); fsp;
5998 fsp = file_find_di_next(fsp)) {
5999 if (fsp->access_mask & DELETE_ACCESS) {
6000 return NT_STATUS_SHARING_VIOLATION;
6003 return NT_STATUS_OK;
6006 /****************************************************************************
6007 Rename an open file - given an fsp.
6008 ****************************************************************************/
6010 NTSTATUS rename_internals_fsp(connection_struct *conn,
6011 files_struct *fsp,
6012 const struct smb_filename *smb_fname_dst_in,
6013 uint32 attrs,
6014 bool replace_if_exists)
6016 TALLOC_CTX *ctx = talloc_tos();
6017 struct smb_filename *smb_fname_dst = NULL;
6018 NTSTATUS status = NT_STATUS_OK;
6019 struct share_mode_lock *lck = NULL;
6020 bool dst_exists, old_is_stream, new_is_stream;
6022 status = check_name(conn, smb_fname_dst_in->base_name);
6023 if (!NT_STATUS_IS_OK(status)) {
6024 return status;
6027 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6028 if (!NT_STATUS_IS_OK(status)) {
6029 return status;
6032 /* Make a copy of the dst smb_fname structs */
6034 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6035 if (!NT_STATUS_IS_OK(status)) {
6036 goto out;
6040 * Check for special case with case preserving and not
6041 * case sensitive. If the old last component differs from the original
6042 * last component only by case, then we should allow
6043 * the rename (user is trying to change the case of the
6044 * filename).
6046 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6047 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6048 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6049 char *last_slash;
6050 char *fname_dst_lcomp_base_mod = NULL;
6051 struct smb_filename *smb_fname_orig_lcomp = NULL;
6054 * Get the last component of the destination name.
6056 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6057 if (last_slash) {
6058 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6059 } else {
6060 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6062 if (!fname_dst_lcomp_base_mod) {
6063 status = NT_STATUS_NO_MEMORY;
6064 goto out;
6068 * Create an smb_filename struct using the original last
6069 * component of the destination.
6071 status = create_synthetic_smb_fname_split(ctx,
6072 smb_fname_dst->original_lcomp, NULL,
6073 &smb_fname_orig_lcomp);
6074 if (!NT_STATUS_IS_OK(status)) {
6075 TALLOC_FREE(fname_dst_lcomp_base_mod);
6076 goto out;
6079 /* If the base names only differ by case, use original. */
6080 if(!strcsequal(fname_dst_lcomp_base_mod,
6081 smb_fname_orig_lcomp->base_name)) {
6082 char *tmp;
6084 * Replace the modified last component with the
6085 * original.
6087 if (last_slash) {
6088 *last_slash = '\0'; /* Truncate at the '/' */
6089 tmp = talloc_asprintf(smb_fname_dst,
6090 "%s/%s",
6091 smb_fname_dst->base_name,
6092 smb_fname_orig_lcomp->base_name);
6093 } else {
6094 tmp = talloc_asprintf(smb_fname_dst,
6095 "%s",
6096 smb_fname_orig_lcomp->base_name);
6098 if (tmp == NULL) {
6099 status = NT_STATUS_NO_MEMORY;
6100 TALLOC_FREE(fname_dst_lcomp_base_mod);
6101 TALLOC_FREE(smb_fname_orig_lcomp);
6102 goto out;
6104 TALLOC_FREE(smb_fname_dst->base_name);
6105 smb_fname_dst->base_name = tmp;
6108 /* If the stream_names only differ by case, use original. */
6109 if(!strcsequal(smb_fname_dst->stream_name,
6110 smb_fname_orig_lcomp->stream_name)) {
6111 char *tmp = NULL;
6112 /* Use the original stream. */
6113 tmp = talloc_strdup(smb_fname_dst,
6114 smb_fname_orig_lcomp->stream_name);
6115 if (tmp == NULL) {
6116 status = NT_STATUS_NO_MEMORY;
6117 TALLOC_FREE(fname_dst_lcomp_base_mod);
6118 TALLOC_FREE(smb_fname_orig_lcomp);
6119 goto out;
6121 TALLOC_FREE(smb_fname_dst->stream_name);
6122 smb_fname_dst->stream_name = tmp;
6124 TALLOC_FREE(fname_dst_lcomp_base_mod);
6125 TALLOC_FREE(smb_fname_orig_lcomp);
6129 * If the src and dest names are identical - including case,
6130 * don't do the rename, just return success.
6133 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6134 strcsequal(fsp->fsp_name->stream_name,
6135 smb_fname_dst->stream_name)) {
6136 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6137 "- returning success\n",
6138 smb_fname_str_dbg(smb_fname_dst)));
6139 status = NT_STATUS_OK;
6140 goto out;
6143 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6144 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6146 /* Return the correct error code if both names aren't streams. */
6147 if (!old_is_stream && new_is_stream) {
6148 status = NT_STATUS_OBJECT_NAME_INVALID;
6149 goto out;
6152 if (old_is_stream && !new_is_stream) {
6153 status = NT_STATUS_INVALID_PARAMETER;
6154 goto out;
6157 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6159 if(!replace_if_exists && dst_exists) {
6160 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6161 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6162 smb_fname_str_dbg(smb_fname_dst)));
6163 status = NT_STATUS_OBJECT_NAME_COLLISION;
6164 goto out;
6167 if (dst_exists) {
6168 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6169 &smb_fname_dst->st);
6170 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6171 fileid);
6172 /* The file can be open when renaming a stream */
6173 if (dst_fsp && !new_is_stream) {
6174 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6175 status = NT_STATUS_ACCESS_DENIED;
6176 goto out;
6180 /* Ensure we have a valid stat struct for the source. */
6181 status = vfs_stat_fsp(fsp);
6182 if (!NT_STATUS_IS_OK(status)) {
6183 goto out;
6186 status = can_rename(conn, fsp, attrs);
6188 if (!NT_STATUS_IS_OK(status)) {
6189 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6190 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6191 smb_fname_str_dbg(smb_fname_dst)));
6192 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6193 status = NT_STATUS_ACCESS_DENIED;
6194 goto out;
6197 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6198 status = NT_STATUS_ACCESS_DENIED;
6201 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6204 * We have the file open ourselves, so not being able to get the
6205 * corresponding share mode lock is a fatal error.
6208 SMB_ASSERT(lck != NULL);
6210 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6211 uint32 create_options = fsp->fh->private_options;
6213 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6214 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6215 smb_fname_str_dbg(smb_fname_dst)));
6217 if (!lp_posix_pathnames() &&
6218 (lp_map_archive(SNUM(conn)) ||
6219 lp_store_dos_attributes(SNUM(conn)))) {
6220 /* We must set the archive bit on the newly
6221 renamed file. */
6222 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6223 uint32_t old_dosmode = dos_mode(conn,
6224 smb_fname_dst);
6225 file_set_dosmode(conn,
6226 smb_fname_dst,
6227 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6228 NULL,
6229 true);
6233 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6234 smb_fname_dst);
6236 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6239 * A rename acts as a new file create w.r.t. allowing an initial delete
6240 * on close, probably because in Windows there is a new handle to the
6241 * new file. If initial delete on close was requested but not
6242 * originally set, we need to set it here. This is probably not 100% correct,
6243 * but will work for the CIFSFS client which in non-posix mode
6244 * depends on these semantics. JRA.
6247 if (create_options & FILE_DELETE_ON_CLOSE) {
6248 status = can_set_delete_on_close(fsp, 0);
6250 if (NT_STATUS_IS_OK(status)) {
6251 /* Note that here we set the *inital* delete on close flag,
6252 * not the regular one. The magic gets handled in close. */
6253 fsp->initial_delete_on_close = True;
6256 TALLOC_FREE(lck);
6257 status = NT_STATUS_OK;
6258 goto out;
6261 TALLOC_FREE(lck);
6263 if (errno == ENOTDIR || errno == EISDIR) {
6264 status = NT_STATUS_OBJECT_NAME_COLLISION;
6265 } else {
6266 status = map_nt_error_from_unix(errno);
6269 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6270 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6271 smb_fname_str_dbg(smb_fname_dst)));
6273 out:
6274 TALLOC_FREE(smb_fname_dst);
6276 return status;
6279 /****************************************************************************
6280 The guts of the rename command, split out so it may be called by the NT SMB
6281 code.
6282 ****************************************************************************/
6284 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6285 connection_struct *conn,
6286 struct smb_request *req,
6287 struct smb_filename *smb_fname_src,
6288 struct smb_filename *smb_fname_dst,
6289 uint32 attrs,
6290 bool replace_if_exists,
6291 bool src_has_wild,
6292 bool dest_has_wild,
6293 uint32_t access_mask)
6295 char *fname_src_dir = NULL;
6296 char *fname_src_mask = NULL;
6297 int count=0;
6298 NTSTATUS status = NT_STATUS_OK;
6299 struct smb_Dir *dir_hnd = NULL;
6300 const char *dname = NULL;
6301 char *talloced = NULL;
6302 long offset = 0;
6303 int create_options = 0;
6304 bool posix_pathnames = lp_posix_pathnames();
6307 * Split the old name into directory and last component
6308 * strings. Note that unix_convert may have stripped off a
6309 * leading ./ from both name and newname if the rename is
6310 * at the root of the share. We need to make sure either both
6311 * name and newname contain a / character or neither of them do
6312 * as this is checked in resolve_wildcards().
6315 /* Split up the directory from the filename/mask. */
6316 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6317 &fname_src_dir, &fname_src_mask);
6318 if (!NT_STATUS_IS_OK(status)) {
6319 status = NT_STATUS_NO_MEMORY;
6320 goto out;
6324 * We should only check the mangled cache
6325 * here if unix_convert failed. This means
6326 * that the path in 'mask' doesn't exist
6327 * on the file system and so we need to look
6328 * for a possible mangle. This patch from
6329 * Tine Smukavec <valentin.smukavec@hermes.si>.
6332 if (!VALID_STAT(smb_fname_src->st) &&
6333 mangle_is_mangled(fname_src_mask, conn->params)) {
6334 char *new_mask = NULL;
6335 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6336 conn->params);
6337 if (new_mask) {
6338 TALLOC_FREE(fname_src_mask);
6339 fname_src_mask = new_mask;
6343 if (!src_has_wild) {
6344 files_struct *fsp;
6347 * Only one file needs to be renamed. Append the mask back
6348 * onto the directory.
6350 TALLOC_FREE(smb_fname_src->base_name);
6351 if (ISDOT(fname_src_dir)) {
6352 /* Ensure we use canonical names on open. */
6353 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6354 "%s",
6355 fname_src_mask);
6356 } else {
6357 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6358 "%s/%s",
6359 fname_src_dir,
6360 fname_src_mask);
6362 if (!smb_fname_src->base_name) {
6363 status = NT_STATUS_NO_MEMORY;
6364 goto out;
6367 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6368 "case_preserve = %d, short case preserve = %d, "
6369 "directory = %s, newname = %s, "
6370 "last_component_dest = %s\n",
6371 conn->case_sensitive, conn->case_preserve,
6372 conn->short_case_preserve,
6373 smb_fname_str_dbg(smb_fname_src),
6374 smb_fname_str_dbg(smb_fname_dst),
6375 smb_fname_dst->original_lcomp));
6377 /* The dest name still may have wildcards. */
6378 if (dest_has_wild) {
6379 char *fname_dst_mod = NULL;
6380 if (!resolve_wildcards(smb_fname_dst,
6381 smb_fname_src->base_name,
6382 smb_fname_dst->base_name,
6383 &fname_dst_mod)) {
6384 DEBUG(6, ("rename_internals: resolve_wildcards "
6385 "%s %s failed\n",
6386 smb_fname_src->base_name,
6387 smb_fname_dst->base_name));
6388 status = NT_STATUS_NO_MEMORY;
6389 goto out;
6391 TALLOC_FREE(smb_fname_dst->base_name);
6392 smb_fname_dst->base_name = fname_dst_mod;
6395 ZERO_STRUCT(smb_fname_src->st);
6396 if (posix_pathnames) {
6397 SMB_VFS_LSTAT(conn, smb_fname_src);
6398 } else {
6399 SMB_VFS_STAT(conn, smb_fname_src);
6402 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6403 create_options |= FILE_DIRECTORY_FILE;
6406 status = SMB_VFS_CREATE_FILE(
6407 conn, /* conn */
6408 req, /* req */
6409 0, /* root_dir_fid */
6410 smb_fname_src, /* fname */
6411 access_mask, /* access_mask */
6412 (FILE_SHARE_READ | /* share_access */
6413 FILE_SHARE_WRITE),
6414 FILE_OPEN, /* create_disposition*/
6415 create_options, /* create_options */
6416 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6417 0, /* oplock_request */
6418 0, /* allocation_size */
6419 0, /* private_flags */
6420 NULL, /* sd */
6421 NULL, /* ea_list */
6422 &fsp, /* result */
6423 NULL); /* pinfo */
6425 if (!NT_STATUS_IS_OK(status)) {
6426 DEBUG(3, ("Could not open rename source %s: %s\n",
6427 smb_fname_str_dbg(smb_fname_src),
6428 nt_errstr(status)));
6429 goto out;
6432 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6433 attrs, replace_if_exists);
6435 close_file(req, fsp, NORMAL_CLOSE);
6437 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6438 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6439 smb_fname_str_dbg(smb_fname_dst)));
6441 goto out;
6445 * Wildcards - process each file that matches.
6447 if (strequal(fname_src_mask, "????????.???")) {
6448 TALLOC_FREE(fname_src_mask);
6449 fname_src_mask = talloc_strdup(ctx, "*");
6450 if (!fname_src_mask) {
6451 status = NT_STATUS_NO_MEMORY;
6452 goto out;
6456 status = check_name(conn, fname_src_dir);
6457 if (!NT_STATUS_IS_OK(status)) {
6458 goto out;
6461 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6462 attrs);
6463 if (dir_hnd == NULL) {
6464 status = map_nt_error_from_unix(errno);
6465 goto out;
6468 status = NT_STATUS_NO_SUCH_FILE;
6470 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6471 * - gentest fix. JRA
6474 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6475 &talloced))) {
6476 files_struct *fsp = NULL;
6477 char *destname = NULL;
6478 bool sysdir_entry = False;
6480 /* Quick check for "." and ".." */
6481 if (ISDOT(dname) || ISDOTDOT(dname)) {
6482 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6483 sysdir_entry = True;
6484 } else {
6485 TALLOC_FREE(talloced);
6486 continue;
6490 if (!is_visible_file(conn, fname_src_dir, dname,
6491 &smb_fname_src->st, false)) {
6492 TALLOC_FREE(talloced);
6493 continue;
6496 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6497 TALLOC_FREE(talloced);
6498 continue;
6501 if (sysdir_entry) {
6502 status = NT_STATUS_OBJECT_NAME_INVALID;
6503 break;
6506 TALLOC_FREE(smb_fname_src->base_name);
6507 if (ISDOT(fname_src_dir)) {
6508 /* Ensure we use canonical names on open. */
6509 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6510 "%s",
6511 dname);
6512 } else {
6513 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6514 "%s/%s",
6515 fname_src_dir,
6516 dname);
6518 if (!smb_fname_src->base_name) {
6519 status = NT_STATUS_NO_MEMORY;
6520 goto out;
6523 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6524 smb_fname_dst->base_name,
6525 &destname)) {
6526 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6527 smb_fname_src->base_name, destname));
6528 TALLOC_FREE(talloced);
6529 continue;
6531 if (!destname) {
6532 status = NT_STATUS_NO_MEMORY;
6533 goto out;
6536 TALLOC_FREE(smb_fname_dst->base_name);
6537 smb_fname_dst->base_name = destname;
6539 ZERO_STRUCT(smb_fname_src->st);
6540 if (posix_pathnames) {
6541 SMB_VFS_LSTAT(conn, smb_fname_src);
6542 } else {
6543 SMB_VFS_STAT(conn, smb_fname_src);
6546 create_options = 0;
6548 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6549 create_options |= FILE_DIRECTORY_FILE;
6552 status = SMB_VFS_CREATE_FILE(
6553 conn, /* conn */
6554 req, /* req */
6555 0, /* root_dir_fid */
6556 smb_fname_src, /* fname */
6557 access_mask, /* access_mask */
6558 (FILE_SHARE_READ | /* share_access */
6559 FILE_SHARE_WRITE),
6560 FILE_OPEN, /* create_disposition*/
6561 create_options, /* create_options */
6562 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6563 0, /* oplock_request */
6564 0, /* allocation_size */
6565 0, /* private_flags */
6566 NULL, /* sd */
6567 NULL, /* ea_list */
6568 &fsp, /* result */
6569 NULL); /* pinfo */
6571 if (!NT_STATUS_IS_OK(status)) {
6572 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6573 "returned %s rename %s -> %s\n",
6574 nt_errstr(status),
6575 smb_fname_str_dbg(smb_fname_src),
6576 smb_fname_str_dbg(smb_fname_dst)));
6577 break;
6580 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6581 dname);
6582 if (!smb_fname_dst->original_lcomp) {
6583 status = NT_STATUS_NO_MEMORY;
6584 goto out;
6587 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6588 attrs, replace_if_exists);
6590 close_file(req, fsp, NORMAL_CLOSE);
6592 if (!NT_STATUS_IS_OK(status)) {
6593 DEBUG(3, ("rename_internals_fsp returned %s for "
6594 "rename %s -> %s\n", nt_errstr(status),
6595 smb_fname_str_dbg(smb_fname_src),
6596 smb_fname_str_dbg(smb_fname_dst)));
6597 break;
6600 count++;
6602 DEBUG(3,("rename_internals: doing rename on %s -> "
6603 "%s\n", smb_fname_str_dbg(smb_fname_src),
6604 smb_fname_str_dbg(smb_fname_src)));
6605 TALLOC_FREE(talloced);
6607 TALLOC_FREE(dir_hnd);
6609 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6610 status = map_nt_error_from_unix(errno);
6613 out:
6614 TALLOC_FREE(talloced);
6615 TALLOC_FREE(fname_src_dir);
6616 TALLOC_FREE(fname_src_mask);
6617 return status;
6620 /****************************************************************************
6621 Reply to a mv.
6622 ****************************************************************************/
6624 void reply_mv(struct smb_request *req)
6626 connection_struct *conn = req->conn;
6627 char *name = NULL;
6628 char *newname = NULL;
6629 const char *p;
6630 uint32 attrs;
6631 NTSTATUS status;
6632 bool src_has_wcard = False;
6633 bool dest_has_wcard = False;
6634 TALLOC_CTX *ctx = talloc_tos();
6635 struct smb_filename *smb_fname_src = NULL;
6636 struct smb_filename *smb_fname_dst = NULL;
6637 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6638 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6639 bool stream_rename = false;
6641 START_PROFILE(SMBmv);
6643 if (req->wct < 1) {
6644 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6645 goto out;
6648 attrs = SVAL(req->vwv+0, 0);
6650 p = (const char *)req->buf + 1;
6651 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6652 &status, &src_has_wcard);
6653 if (!NT_STATUS_IS_OK(status)) {
6654 reply_nterror(req, status);
6655 goto out;
6657 p++;
6658 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6659 &status, &dest_has_wcard);
6660 if (!NT_STATUS_IS_OK(status)) {
6661 reply_nterror(req, status);
6662 goto out;
6665 if (!lp_posix_pathnames()) {
6666 /* The newname must begin with a ':' if the
6667 name contains a ':'. */
6668 if (strchr_m(name, ':')) {
6669 if (newname[0] != ':') {
6670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6671 goto out;
6673 stream_rename = true;
6677 status = filename_convert(ctx,
6678 conn,
6679 req->flags2 & FLAGS2_DFS_PATHNAMES,
6680 name,
6681 src_ucf_flags,
6682 &src_has_wcard,
6683 &smb_fname_src);
6685 if (!NT_STATUS_IS_OK(status)) {
6686 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6687 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6688 ERRSRV, ERRbadpath);
6689 goto out;
6691 reply_nterror(req, status);
6692 goto out;
6695 status = filename_convert(ctx,
6696 conn,
6697 req->flags2 & FLAGS2_DFS_PATHNAMES,
6698 newname,
6699 dst_ucf_flags,
6700 &dest_has_wcard,
6701 &smb_fname_dst);
6703 if (!NT_STATUS_IS_OK(status)) {
6704 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6705 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6706 ERRSRV, ERRbadpath);
6707 goto out;
6709 reply_nterror(req, status);
6710 goto out;
6713 if (stream_rename) {
6714 /* smb_fname_dst->base_name must be the same as
6715 smb_fname_src->base_name. */
6716 TALLOC_FREE(smb_fname_dst->base_name);
6717 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6718 smb_fname_src->base_name);
6719 if (!smb_fname_dst->base_name) {
6720 reply_nterror(req, NT_STATUS_NO_MEMORY);
6721 goto out;
6725 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6726 smb_fname_str_dbg(smb_fname_dst)));
6728 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6729 attrs, False, src_has_wcard, dest_has_wcard,
6730 DELETE_ACCESS);
6731 if (!NT_STATUS_IS_OK(status)) {
6732 if (open_was_deferred(req->sconn, req->mid)) {
6733 /* We have re-scheduled this call. */
6734 goto out;
6736 reply_nterror(req, status);
6737 goto out;
6740 reply_outbuf(req, 0, 0);
6741 out:
6742 TALLOC_FREE(smb_fname_src);
6743 TALLOC_FREE(smb_fname_dst);
6744 END_PROFILE(SMBmv);
6745 return;
6748 /*******************************************************************
6749 Copy a file as part of a reply_copy.
6750 ******************************************************************/
6753 * TODO: check error codes on all callers
6756 NTSTATUS copy_file(TALLOC_CTX *ctx,
6757 connection_struct *conn,
6758 struct smb_filename *smb_fname_src,
6759 struct smb_filename *smb_fname_dst,
6760 int ofun,
6761 int count,
6762 bool target_is_directory)
6764 struct smb_filename *smb_fname_dst_tmp = NULL;
6765 off_t ret=-1;
6766 files_struct *fsp1,*fsp2;
6767 uint32 dosattrs;
6768 uint32 new_create_disposition;
6769 NTSTATUS status;
6772 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6773 if (!NT_STATUS_IS_OK(status)) {
6774 return status;
6778 * If the target is a directory, extract the last component from the
6779 * src filename and append it to the dst filename
6781 if (target_is_directory) {
6782 const char *p;
6784 /* dest/target can't be a stream if it's a directory. */
6785 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6787 p = strrchr_m(smb_fname_src->base_name,'/');
6788 if (p) {
6789 p++;
6790 } else {
6791 p = smb_fname_src->base_name;
6793 smb_fname_dst_tmp->base_name =
6794 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6796 if (!smb_fname_dst_tmp->base_name) {
6797 status = NT_STATUS_NO_MEMORY;
6798 goto out;
6802 status = vfs_file_exist(conn, smb_fname_src);
6803 if (!NT_STATUS_IS_OK(status)) {
6804 goto out;
6807 if (!target_is_directory && count) {
6808 new_create_disposition = FILE_OPEN;
6809 } else {
6810 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6811 0, ofun,
6812 NULL, NULL,
6813 &new_create_disposition,
6814 NULL,
6815 NULL)) {
6816 status = NT_STATUS_INVALID_PARAMETER;
6817 goto out;
6821 /* Open the src file for reading. */
6822 status = SMB_VFS_CREATE_FILE(
6823 conn, /* conn */
6824 NULL, /* req */
6825 0, /* root_dir_fid */
6826 smb_fname_src, /* fname */
6827 FILE_GENERIC_READ, /* access_mask */
6828 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6829 FILE_OPEN, /* create_disposition*/
6830 0, /* create_options */
6831 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6832 INTERNAL_OPEN_ONLY, /* oplock_request */
6833 0, /* allocation_size */
6834 0, /* private_flags */
6835 NULL, /* sd */
6836 NULL, /* ea_list */
6837 &fsp1, /* result */
6838 NULL); /* psbuf */
6840 if (!NT_STATUS_IS_OK(status)) {
6841 goto out;
6844 dosattrs = dos_mode(conn, smb_fname_src);
6846 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6847 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6850 /* Open the dst file for writing. */
6851 status = SMB_VFS_CREATE_FILE(
6852 conn, /* conn */
6853 NULL, /* req */
6854 0, /* root_dir_fid */
6855 smb_fname_dst, /* fname */
6856 FILE_GENERIC_WRITE, /* access_mask */
6857 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6858 new_create_disposition, /* create_disposition*/
6859 0, /* create_options */
6860 dosattrs, /* file_attributes */
6861 INTERNAL_OPEN_ONLY, /* oplock_request */
6862 0, /* allocation_size */
6863 0, /* private_flags */
6864 NULL, /* sd */
6865 NULL, /* ea_list */
6866 &fsp2, /* result */
6867 NULL); /* psbuf */
6869 if (!NT_STATUS_IS_OK(status)) {
6870 close_file(NULL, fsp1, ERROR_CLOSE);
6871 goto out;
6874 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6875 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6876 if (ret == -1) {
6877 DEBUG(0, ("error - vfs lseek returned error %s\n",
6878 strerror(errno)));
6879 status = map_nt_error_from_unix(errno);
6880 close_file(NULL, fsp1, ERROR_CLOSE);
6881 close_file(NULL, fsp2, ERROR_CLOSE);
6882 goto out;
6886 /* Do the actual copy. */
6887 if (smb_fname_src->st.st_ex_size) {
6888 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6889 } else {
6890 ret = 0;
6893 close_file(NULL, fsp1, NORMAL_CLOSE);
6895 /* Ensure the modtime is set correctly on the destination file. */
6896 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6899 * As we are opening fsp1 read-only we only expect
6900 * an error on close on fsp2 if we are out of space.
6901 * Thus we don't look at the error return from the
6902 * close of fsp1.
6904 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6906 if (!NT_STATUS_IS_OK(status)) {
6907 goto out;
6910 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
6911 status = NT_STATUS_DISK_FULL;
6912 goto out;
6915 status = NT_STATUS_OK;
6917 out:
6918 TALLOC_FREE(smb_fname_dst_tmp);
6919 return status;
6922 /****************************************************************************
6923 Reply to a file copy.
6924 ****************************************************************************/
6926 void reply_copy(struct smb_request *req)
6928 connection_struct *conn = req->conn;
6929 struct smb_filename *smb_fname_src = NULL;
6930 struct smb_filename *smb_fname_dst = NULL;
6931 char *fname_src = NULL;
6932 char *fname_dst = NULL;
6933 char *fname_src_mask = NULL;
6934 char *fname_src_dir = NULL;
6935 const char *p;
6936 int count=0;
6937 int error = ERRnoaccess;
6938 int tid2;
6939 int ofun;
6940 int flags;
6941 bool target_is_directory=False;
6942 bool source_has_wild = False;
6943 bool dest_has_wild = False;
6944 NTSTATUS status;
6945 TALLOC_CTX *ctx = talloc_tos();
6947 START_PROFILE(SMBcopy);
6949 if (req->wct < 3) {
6950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6951 goto out;
6954 tid2 = SVAL(req->vwv+0, 0);
6955 ofun = SVAL(req->vwv+1, 0);
6956 flags = SVAL(req->vwv+2, 0);
6958 p = (const char *)req->buf;
6959 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6960 &status, &source_has_wild);
6961 if (!NT_STATUS_IS_OK(status)) {
6962 reply_nterror(req, status);
6963 goto out;
6965 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6966 &status, &dest_has_wild);
6967 if (!NT_STATUS_IS_OK(status)) {
6968 reply_nterror(req, status);
6969 goto out;
6972 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6974 if (tid2 != conn->cnum) {
6975 /* can't currently handle inter share copies XXXX */
6976 DEBUG(3,("Rejecting inter-share copy\n"));
6977 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6978 goto out;
6981 status = filename_convert(ctx, conn,
6982 req->flags2 & FLAGS2_DFS_PATHNAMES,
6983 fname_src,
6984 UCF_COND_ALLOW_WCARD_LCOMP,
6985 &source_has_wild,
6986 &smb_fname_src);
6987 if (!NT_STATUS_IS_OK(status)) {
6988 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6989 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6990 ERRSRV, ERRbadpath);
6991 goto out;
6993 reply_nterror(req, status);
6994 goto out;
6997 status = filename_convert(ctx, conn,
6998 req->flags2 & FLAGS2_DFS_PATHNAMES,
6999 fname_dst,
7000 UCF_COND_ALLOW_WCARD_LCOMP,
7001 &dest_has_wild,
7002 &smb_fname_dst);
7003 if (!NT_STATUS_IS_OK(status)) {
7004 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7005 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7006 ERRSRV, ERRbadpath);
7007 goto out;
7009 reply_nterror(req, status);
7010 goto out;
7013 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7015 if ((flags&1) && target_is_directory) {
7016 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7017 goto out;
7020 if ((flags&2) && !target_is_directory) {
7021 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7022 goto out;
7025 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7026 /* wants a tree copy! XXXX */
7027 DEBUG(3,("Rejecting tree copy\n"));
7028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7029 goto out;
7032 /* Split up the directory from the filename/mask. */
7033 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7034 &fname_src_dir, &fname_src_mask);
7035 if (!NT_STATUS_IS_OK(status)) {
7036 reply_nterror(req, NT_STATUS_NO_MEMORY);
7037 goto out;
7041 * We should only check the mangled cache
7042 * here if unix_convert failed. This means
7043 * that the path in 'mask' doesn't exist
7044 * on the file system and so we need to look
7045 * for a possible mangle. This patch from
7046 * Tine Smukavec <valentin.smukavec@hermes.si>.
7048 if (!VALID_STAT(smb_fname_src->st) &&
7049 mangle_is_mangled(fname_src_mask, conn->params)) {
7050 char *new_mask = NULL;
7051 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7052 &new_mask, conn->params);
7054 /* Use demangled name if one was successfully found. */
7055 if (new_mask) {
7056 TALLOC_FREE(fname_src_mask);
7057 fname_src_mask = new_mask;
7061 if (!source_has_wild) {
7064 * Only one file needs to be copied. Append the mask back onto
7065 * the directory.
7067 TALLOC_FREE(smb_fname_src->base_name);
7068 if (ISDOT(fname_src_dir)) {
7069 /* Ensure we use canonical names on open. */
7070 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7071 "%s",
7072 fname_src_mask);
7073 } else {
7074 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7075 "%s/%s",
7076 fname_src_dir,
7077 fname_src_mask);
7079 if (!smb_fname_src->base_name) {
7080 reply_nterror(req, NT_STATUS_NO_MEMORY);
7081 goto out;
7084 if (dest_has_wild) {
7085 char *fname_dst_mod = NULL;
7086 if (!resolve_wildcards(smb_fname_dst,
7087 smb_fname_src->base_name,
7088 smb_fname_dst->base_name,
7089 &fname_dst_mod)) {
7090 reply_nterror(req, NT_STATUS_NO_MEMORY);
7091 goto out;
7093 TALLOC_FREE(smb_fname_dst->base_name);
7094 smb_fname_dst->base_name = fname_dst_mod;
7097 status = check_name(conn, smb_fname_src->base_name);
7098 if (!NT_STATUS_IS_OK(status)) {
7099 reply_nterror(req, status);
7100 goto out;
7103 status = check_name(conn, smb_fname_dst->base_name);
7104 if (!NT_STATUS_IS_OK(status)) {
7105 reply_nterror(req, status);
7106 goto out;
7109 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7110 ofun, count, target_is_directory);
7112 if(!NT_STATUS_IS_OK(status)) {
7113 reply_nterror(req, status);
7114 goto out;
7115 } else {
7116 count++;
7118 } else {
7119 struct smb_Dir *dir_hnd = NULL;
7120 const char *dname = NULL;
7121 char *talloced = NULL;
7122 long offset = 0;
7125 * There is a wildcard that requires us to actually read the
7126 * src dir and copy each file matching the mask to the dst.
7127 * Right now streams won't be copied, but this could
7128 * presumably be added with a nested loop for reach dir entry.
7130 SMB_ASSERT(!smb_fname_src->stream_name);
7131 SMB_ASSERT(!smb_fname_dst->stream_name);
7133 smb_fname_src->stream_name = NULL;
7134 smb_fname_dst->stream_name = NULL;
7136 if (strequal(fname_src_mask,"????????.???")) {
7137 TALLOC_FREE(fname_src_mask);
7138 fname_src_mask = talloc_strdup(ctx, "*");
7139 if (!fname_src_mask) {
7140 reply_nterror(req, NT_STATUS_NO_MEMORY);
7141 goto out;
7145 status = check_name(conn, fname_src_dir);
7146 if (!NT_STATUS_IS_OK(status)) {
7147 reply_nterror(req, status);
7148 goto out;
7151 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7152 if (dir_hnd == NULL) {
7153 status = map_nt_error_from_unix(errno);
7154 reply_nterror(req, status);
7155 goto out;
7158 error = ERRbadfile;
7160 /* Iterate over the src dir copying each entry to the dst. */
7161 while ((dname = ReadDirName(dir_hnd, &offset,
7162 &smb_fname_src->st, &talloced))) {
7163 char *destname = NULL;
7165 if (ISDOT(dname) || ISDOTDOT(dname)) {
7166 TALLOC_FREE(talloced);
7167 continue;
7170 if (!is_visible_file(conn, fname_src_dir, dname,
7171 &smb_fname_src->st, false)) {
7172 TALLOC_FREE(talloced);
7173 continue;
7176 if(!mask_match(dname, fname_src_mask,
7177 conn->case_sensitive)) {
7178 TALLOC_FREE(talloced);
7179 continue;
7182 error = ERRnoaccess;
7184 /* Get the src smb_fname struct setup. */
7185 TALLOC_FREE(smb_fname_src->base_name);
7186 if (ISDOT(fname_src_dir)) {
7187 /* Ensure we use canonical names on open. */
7188 smb_fname_src->base_name =
7189 talloc_asprintf(smb_fname_src, "%s",
7190 dname);
7191 } else {
7192 smb_fname_src->base_name =
7193 talloc_asprintf(smb_fname_src, "%s/%s",
7194 fname_src_dir, dname);
7197 if (!smb_fname_src->base_name) {
7198 TALLOC_FREE(dir_hnd);
7199 TALLOC_FREE(talloced);
7200 reply_nterror(req, NT_STATUS_NO_MEMORY);
7201 goto out;
7204 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7205 smb_fname_dst->base_name,
7206 &destname)) {
7207 TALLOC_FREE(talloced);
7208 continue;
7210 if (!destname) {
7211 TALLOC_FREE(dir_hnd);
7212 TALLOC_FREE(talloced);
7213 reply_nterror(req, NT_STATUS_NO_MEMORY);
7214 goto out;
7217 TALLOC_FREE(smb_fname_dst->base_name);
7218 smb_fname_dst->base_name = destname;
7220 status = check_name(conn, smb_fname_src->base_name);
7221 if (!NT_STATUS_IS_OK(status)) {
7222 TALLOC_FREE(dir_hnd);
7223 TALLOC_FREE(talloced);
7224 reply_nterror(req, status);
7225 goto out;
7228 status = check_name(conn, smb_fname_dst->base_name);
7229 if (!NT_STATUS_IS_OK(status)) {
7230 TALLOC_FREE(dir_hnd);
7231 TALLOC_FREE(talloced);
7232 reply_nterror(req, status);
7233 goto out;
7236 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7237 smb_fname_src->base_name,
7238 smb_fname_dst->base_name));
7240 status = copy_file(ctx, conn, smb_fname_src,
7241 smb_fname_dst, ofun, count,
7242 target_is_directory);
7243 if (NT_STATUS_IS_OK(status)) {
7244 count++;
7247 TALLOC_FREE(talloced);
7249 TALLOC_FREE(dir_hnd);
7252 if (count == 0) {
7253 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7254 goto out;
7257 reply_outbuf(req, 1, 0);
7258 SSVAL(req->outbuf,smb_vwv0,count);
7259 out:
7260 TALLOC_FREE(smb_fname_src);
7261 TALLOC_FREE(smb_fname_dst);
7262 TALLOC_FREE(fname_src);
7263 TALLOC_FREE(fname_dst);
7264 TALLOC_FREE(fname_src_mask);
7265 TALLOC_FREE(fname_src_dir);
7267 END_PROFILE(SMBcopy);
7268 return;
7271 #undef DBGC_CLASS
7272 #define DBGC_CLASS DBGC_LOCKING
7274 /****************************************************************************
7275 Get a lock pid, dealing with large count requests.
7276 ****************************************************************************/
7278 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7279 bool large_file_format)
7281 if(!large_file_format)
7282 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7283 else
7284 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7287 /****************************************************************************
7288 Get a lock count, dealing with large count requests.
7289 ****************************************************************************/
7291 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7292 bool large_file_format)
7294 uint64_t count = 0;
7296 if(!large_file_format) {
7297 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7298 } else {
7300 #if defined(HAVE_LONGLONG)
7301 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7302 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7303 #else /* HAVE_LONGLONG */
7306 * NT4.x seems to be broken in that it sends large file (64 bit)
7307 * lockingX calls even if the CAP_LARGE_FILES was *not*
7308 * negotiated. For boxes without large unsigned ints truncate the
7309 * lock count by dropping the top 32 bits.
7312 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7313 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7314 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7315 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7316 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7319 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7320 #endif /* HAVE_LONGLONG */
7323 return count;
7326 #if !defined(HAVE_LONGLONG)
7327 /****************************************************************************
7328 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7329 ****************************************************************************/
7331 static uint32 map_lock_offset(uint32 high, uint32 low)
7333 unsigned int i;
7334 uint32 mask = 0;
7335 uint32 highcopy = high;
7338 * Try and find out how many significant bits there are in high.
7341 for(i = 0; highcopy; i++)
7342 highcopy >>= 1;
7345 * We use 31 bits not 32 here as POSIX
7346 * lock offsets may not be negative.
7349 mask = (~0) << (31 - i);
7351 if(low & mask)
7352 return 0; /* Fail. */
7354 high <<= (31 - i);
7356 return (high|low);
7358 #endif /* !defined(HAVE_LONGLONG) */
7360 /****************************************************************************
7361 Get a lock offset, dealing with large offset requests.
7362 ****************************************************************************/
7364 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7365 bool large_file_format, bool *err)
7367 uint64_t offset = 0;
7369 *err = False;
7371 if(!large_file_format) {
7372 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7373 } else {
7375 #if defined(HAVE_LONGLONG)
7376 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7377 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7378 #else /* HAVE_LONGLONG */
7381 * NT4.x seems to be broken in that it sends large file (64 bit)
7382 * lockingX calls even if the CAP_LARGE_FILES was *not*
7383 * negotiated. For boxes without large unsigned ints mangle the
7384 * lock offset by mapping the top 32 bits onto the lower 32.
7387 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7388 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7389 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7390 uint32 new_low = 0;
7392 if((new_low = map_lock_offset(high, low)) == 0) {
7393 *err = True;
7394 return (uint64_t)-1;
7397 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7398 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7399 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7400 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7403 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7404 #endif /* HAVE_LONGLONG */
7407 return offset;
7410 NTSTATUS smbd_do_locking(struct smb_request *req,
7411 files_struct *fsp,
7412 uint8_t type,
7413 int32_t timeout,
7414 uint16_t num_ulocks,
7415 struct smbd_lock_element *ulocks,
7416 uint16_t num_locks,
7417 struct smbd_lock_element *locks,
7418 bool *async)
7420 connection_struct *conn = req->conn;
7421 int i;
7422 NTSTATUS status = NT_STATUS_OK;
7424 *async = false;
7426 /* Data now points at the beginning of the list
7427 of smb_unlkrng structs */
7428 for(i = 0; i < (int)num_ulocks; i++) {
7429 struct smbd_lock_element *e = &ulocks[i];
7431 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7432 "pid %u, file %s\n",
7433 (double)e->offset,
7434 (double)e->count,
7435 (unsigned int)e->smblctx,
7436 fsp_str_dbg(fsp)));
7438 if (e->brltype != UNLOCK_LOCK) {
7439 /* this can only happen with SMB2 */
7440 return NT_STATUS_INVALID_PARAMETER;
7443 status = do_unlock(req->sconn->msg_ctx,
7444 fsp,
7445 e->smblctx,
7446 e->count,
7447 e->offset,
7448 WINDOWS_LOCK);
7450 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7451 nt_errstr(status)));
7453 if (!NT_STATUS_IS_OK(status)) {
7454 return status;
7458 /* Setup the timeout in seconds. */
7460 if (!lp_blocking_locks(SNUM(conn))) {
7461 timeout = 0;
7464 /* Data now points at the beginning of the list
7465 of smb_lkrng structs */
7467 for(i = 0; i < (int)num_locks; i++) {
7468 struct smbd_lock_element *e = &locks[i];
7470 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7471 "%llu, file %s timeout = %d\n",
7472 (double)e->offset,
7473 (double)e->count,
7474 (unsigned long long)e->smblctx,
7475 fsp_str_dbg(fsp),
7476 (int)timeout));
7478 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7479 struct blocking_lock_record *blr = NULL;
7481 if (num_locks > 1) {
7483 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7484 * if the lock vector contains one entry. When given mutliple cancel
7485 * requests in a single PDU we expect the server to return an
7486 * error. Windows servers seem to accept the request but only
7487 * cancel the first lock.
7488 * JRA - Do what Windows does (tm) :-).
7491 #if 0
7492 /* MS-CIFS (2.2.4.32.1) behavior. */
7493 return NT_STATUS_DOS(ERRDOS,
7494 ERRcancelviolation);
7495 #else
7496 /* Windows behavior. */
7497 if (i != 0) {
7498 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7499 "cancel request\n"));
7500 continue;
7502 #endif
7505 if (lp_blocking_locks(SNUM(conn))) {
7507 /* Schedule a message to ourselves to
7508 remove the blocking lock record and
7509 return the right error. */
7511 blr = blocking_lock_cancel_smb1(fsp,
7512 e->smblctx,
7513 e->offset,
7514 e->count,
7515 WINDOWS_LOCK,
7516 type,
7517 NT_STATUS_FILE_LOCK_CONFLICT);
7518 if (blr == NULL) {
7519 return NT_STATUS_DOS(
7520 ERRDOS,
7521 ERRcancelviolation);
7524 /* Remove a matching pending lock. */
7525 status = do_lock_cancel(fsp,
7526 e->smblctx,
7527 e->count,
7528 e->offset,
7529 WINDOWS_LOCK,
7530 blr);
7531 } else {
7532 bool blocking_lock = timeout ? true : false;
7533 bool defer_lock = false;
7534 struct byte_range_lock *br_lck;
7535 uint64_t block_smblctx;
7537 br_lck = do_lock(req->sconn->msg_ctx,
7538 fsp,
7539 e->smblctx,
7540 e->count,
7541 e->offset,
7542 e->brltype,
7543 WINDOWS_LOCK,
7544 blocking_lock,
7545 &status,
7546 &block_smblctx,
7547 NULL);
7549 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7550 /* Windows internal resolution for blocking locks seems
7551 to be about 200ms... Don't wait for less than that. JRA. */
7552 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7553 timeout = lp_lock_spin_time();
7555 defer_lock = true;
7558 /* If a lock sent with timeout of zero would fail, and
7559 * this lock has been requested multiple times,
7560 * according to brl_lock_failed() we convert this
7561 * request to a blocking lock with a timeout of between
7562 * 150 - 300 milliseconds.
7564 * If lp_lock_spin_time() has been set to 0, we skip
7565 * this blocking retry and fail immediately.
7567 * Replacement for do_lock_spin(). JRA. */
7569 if (!req->sconn->using_smb2 &&
7570 br_lck && lp_blocking_locks(SNUM(conn)) &&
7571 lp_lock_spin_time() && !blocking_lock &&
7572 NT_STATUS_EQUAL((status),
7573 NT_STATUS_FILE_LOCK_CONFLICT))
7575 defer_lock = true;
7576 timeout = lp_lock_spin_time();
7579 if (br_lck && defer_lock) {
7581 * A blocking lock was requested. Package up
7582 * this smb into a queued request and push it
7583 * onto the blocking lock queue.
7585 if(push_blocking_lock_request(br_lck,
7586 req,
7587 fsp,
7588 timeout,
7590 e->smblctx,
7591 e->brltype,
7592 WINDOWS_LOCK,
7593 e->offset,
7594 e->count,
7595 block_smblctx)) {
7596 TALLOC_FREE(br_lck);
7597 *async = true;
7598 return NT_STATUS_OK;
7602 TALLOC_FREE(br_lck);
7605 if (!NT_STATUS_IS_OK(status)) {
7606 break;
7610 /* If any of the above locks failed, then we must unlock
7611 all of the previous locks (X/Open spec). */
7613 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7615 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7616 i = -1; /* we want to skip the for loop */
7620 * Ensure we don't do a remove on the lock that just failed,
7621 * as under POSIX rules, if we have a lock already there, we
7622 * will delete it (and we shouldn't) .....
7624 for(i--; i >= 0; i--) {
7625 struct smbd_lock_element *e = &locks[i];
7627 do_unlock(req->sconn->msg_ctx,
7628 fsp,
7629 e->smblctx,
7630 e->count,
7631 e->offset,
7632 WINDOWS_LOCK);
7634 return status;
7637 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d num_ulocks=%d\n",
7638 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks, num_ulocks));
7640 return NT_STATUS_OK;
7643 /****************************************************************************
7644 Reply to a lockingX request.
7645 ****************************************************************************/
7647 void reply_lockingX(struct smb_request *req)
7649 connection_struct *conn = req->conn;
7650 files_struct *fsp;
7651 unsigned char locktype;
7652 unsigned char oplocklevel;
7653 uint16 num_ulocks;
7654 uint16 num_locks;
7655 int32 lock_timeout;
7656 int i;
7657 const uint8_t *data;
7658 bool large_file_format;
7659 bool err;
7660 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7661 struct smbd_lock_element *ulocks;
7662 struct smbd_lock_element *locks;
7663 bool async = false;
7665 START_PROFILE(SMBlockingX);
7667 if (req->wct < 8) {
7668 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7669 END_PROFILE(SMBlockingX);
7670 return;
7673 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7674 locktype = CVAL(req->vwv+3, 0);
7675 oplocklevel = CVAL(req->vwv+3, 1);
7676 num_ulocks = SVAL(req->vwv+6, 0);
7677 num_locks = SVAL(req->vwv+7, 0);
7678 lock_timeout = IVAL(req->vwv+4, 0);
7679 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7681 if (!check_fsp(conn, req, fsp)) {
7682 END_PROFILE(SMBlockingX);
7683 return;
7686 data = req->buf;
7688 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7689 /* we don't support these - and CANCEL_LOCK makes w2k
7690 and XP reboot so I don't really want to be
7691 compatible! (tridge) */
7692 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7693 END_PROFILE(SMBlockingX);
7694 return;
7697 /* Check if this is an oplock break on a file
7698 we have granted an oplock on.
7700 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7701 /* Client can insist on breaking to none. */
7702 bool break_to_none = (oplocklevel == 0);
7703 bool result;
7705 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7706 "for %s\n", (unsigned int)oplocklevel,
7707 fsp_fnum_dbg(fsp)));
7710 * Make sure we have granted an exclusive or batch oplock on
7711 * this file.
7714 if (fsp->oplock_type == 0) {
7716 /* The Samba4 nbench simulator doesn't understand
7717 the difference between break to level2 and break
7718 to none from level2 - it sends oplock break
7719 replies in both cases. Don't keep logging an error
7720 message here - just ignore it. JRA. */
7722 DEBUG(5,("reply_lockingX: Error : oplock break from "
7723 "client for %s (oplock=%d) and no "
7724 "oplock granted on this file (%s).\n",
7725 fsp_fnum_dbg(fsp), fsp->oplock_type,
7726 fsp_str_dbg(fsp)));
7728 /* if this is a pure oplock break request then don't
7729 * send a reply */
7730 if (num_locks == 0 && num_ulocks == 0) {
7731 END_PROFILE(SMBlockingX);
7732 return;
7733 } else {
7734 END_PROFILE(SMBlockingX);
7735 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7736 return;
7740 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7741 (break_to_none)) {
7742 result = remove_oplock(fsp);
7743 } else {
7744 result = downgrade_oplock(fsp);
7747 if (!result) {
7748 DEBUG(0, ("reply_lockingX: error in removing "
7749 "oplock on file %s\n", fsp_str_dbg(fsp)));
7750 /* Hmmm. Is this panic justified? */
7751 smb_panic("internal tdb error");
7754 reply_to_oplock_break_requests(fsp);
7756 /* if this is a pure oplock break request then don't send a
7757 * reply */
7758 if (num_locks == 0 && num_ulocks == 0) {
7759 /* Sanity check - ensure a pure oplock break is not a
7760 chained request. */
7761 if(CVAL(req->vwv+0, 0) != 0xff)
7762 DEBUG(0,("reply_lockingX: Error : pure oplock "
7763 "break is a chained %d request !\n",
7764 (unsigned int)CVAL(req->vwv+0, 0)));
7765 END_PROFILE(SMBlockingX);
7766 return;
7770 if (req->buflen <
7771 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7773 END_PROFILE(SMBlockingX);
7774 return;
7777 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7778 if (ulocks == NULL) {
7779 reply_nterror(req, NT_STATUS_NO_MEMORY);
7780 END_PROFILE(SMBlockingX);
7781 return;
7784 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7785 if (locks == NULL) {
7786 reply_nterror(req, NT_STATUS_NO_MEMORY);
7787 END_PROFILE(SMBlockingX);
7788 return;
7791 /* Data now points at the beginning of the list
7792 of smb_unlkrng structs */
7793 for(i = 0; i < (int)num_ulocks; i++) {
7794 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7795 ulocks[i].count = get_lock_count(data, i, large_file_format);
7796 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7797 ulocks[i].brltype = UNLOCK_LOCK;
7800 * There is no error code marked "stupid client bug".... :-).
7802 if(err) {
7803 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7804 END_PROFILE(SMBlockingX);
7805 return;
7809 /* Now do any requested locks */
7810 data += ((large_file_format ? 20 : 10)*num_ulocks);
7812 /* Data now points at the beginning of the list
7813 of smb_lkrng structs */
7815 for(i = 0; i < (int)num_locks; i++) {
7816 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7817 locks[i].count = get_lock_count(data, i, large_file_format);
7818 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7820 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7821 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7822 locks[i].brltype = PENDING_READ_LOCK;
7823 } else {
7824 locks[i].brltype = READ_LOCK;
7826 } else {
7827 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7828 locks[i].brltype = PENDING_WRITE_LOCK;
7829 } else {
7830 locks[i].brltype = WRITE_LOCK;
7835 * There is no error code marked "stupid client bug".... :-).
7837 if(err) {
7838 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7839 END_PROFILE(SMBlockingX);
7840 return;
7844 status = smbd_do_locking(req, fsp,
7845 locktype, lock_timeout,
7846 num_ulocks, ulocks,
7847 num_locks, locks,
7848 &async);
7849 if (!NT_STATUS_IS_OK(status)) {
7850 END_PROFILE(SMBlockingX);
7851 reply_nterror(req, status);
7852 return;
7854 if (async) {
7855 END_PROFILE(SMBlockingX);
7856 return;
7859 reply_outbuf(req, 2, 0);
7860 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
7861 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
7863 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
7864 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
7866 END_PROFILE(SMBlockingX);
7869 #undef DBGC_CLASS
7870 #define DBGC_CLASS DBGC_ALL
7872 /****************************************************************************
7873 Reply to a SMBreadbmpx (read block multiplex) request.
7874 Always reply with an error, if someone has a platform really needs this,
7875 please contact vl@samba.org
7876 ****************************************************************************/
7878 void reply_readbmpx(struct smb_request *req)
7880 START_PROFILE(SMBreadBmpx);
7881 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7882 END_PROFILE(SMBreadBmpx);
7883 return;
7886 /****************************************************************************
7887 Reply to a SMBreadbs (read block multiplex secondary) request.
7888 Always reply with an error, if someone has a platform really needs this,
7889 please contact vl@samba.org
7890 ****************************************************************************/
7892 void reply_readbs(struct smb_request *req)
7894 START_PROFILE(SMBreadBs);
7895 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7896 END_PROFILE(SMBreadBs);
7897 return;
7900 /****************************************************************************
7901 Reply to a SMBsetattrE.
7902 ****************************************************************************/
7904 void reply_setattrE(struct smb_request *req)
7906 connection_struct *conn = req->conn;
7907 struct smb_file_time ft;
7908 files_struct *fsp;
7909 NTSTATUS status;
7911 START_PROFILE(SMBsetattrE);
7912 ZERO_STRUCT(ft);
7914 if (req->wct < 7) {
7915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7916 goto out;
7919 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7921 if(!fsp || (fsp->conn != conn)) {
7922 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7923 goto out;
7927 * Convert the DOS times into unix times.
7930 ft.atime = convert_time_t_to_timespec(
7931 srv_make_unix_date2(req->vwv+3));
7932 ft.mtime = convert_time_t_to_timespec(
7933 srv_make_unix_date2(req->vwv+5));
7934 ft.create_time = convert_time_t_to_timespec(
7935 srv_make_unix_date2(req->vwv+1));
7937 reply_outbuf(req, 0, 0);
7940 * Patch from Ray Frush <frush@engr.colostate.edu>
7941 * Sometimes times are sent as zero - ignore them.
7944 /* Ensure we have a valid stat struct for the source. */
7945 status = vfs_stat_fsp(fsp);
7946 if (!NT_STATUS_IS_OK(status)) {
7947 reply_nterror(req, status);
7948 goto out;
7951 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7952 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7953 goto out;
7956 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7957 if (!NT_STATUS_IS_OK(status)) {
7958 reply_nterror(req, status);
7959 goto out;
7962 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
7963 " createtime=%u\n",
7964 fsp_fnum_dbg(fsp),
7965 (unsigned int)ft.atime.tv_sec,
7966 (unsigned int)ft.mtime.tv_sec,
7967 (unsigned int)ft.create_time.tv_sec
7969 out:
7970 END_PROFILE(SMBsetattrE);
7971 return;
7975 /* Back from the dead for OS/2..... JRA. */
7977 /****************************************************************************
7978 Reply to a SMBwritebmpx (write block multiplex primary) request.
7979 Always reply with an error, if someone has a platform really needs this,
7980 please contact vl@samba.org
7981 ****************************************************************************/
7983 void reply_writebmpx(struct smb_request *req)
7985 START_PROFILE(SMBwriteBmpx);
7986 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7987 END_PROFILE(SMBwriteBmpx);
7988 return;
7991 /****************************************************************************
7992 Reply to a SMBwritebs (write block multiplex secondary) request.
7993 Always reply with an error, if someone has a platform really needs this,
7994 please contact vl@samba.org
7995 ****************************************************************************/
7997 void reply_writebs(struct smb_request *req)
7999 START_PROFILE(SMBwriteBs);
8000 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8001 END_PROFILE(SMBwriteBs);
8002 return;
8005 /****************************************************************************
8006 Reply to a SMBgetattrE.
8007 ****************************************************************************/
8009 void reply_getattrE(struct smb_request *req)
8011 connection_struct *conn = req->conn;
8012 int mode;
8013 files_struct *fsp;
8014 struct timespec create_ts;
8016 START_PROFILE(SMBgetattrE);
8018 if (req->wct < 1) {
8019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8020 END_PROFILE(SMBgetattrE);
8021 return;
8024 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8026 if(!fsp || (fsp->conn != conn)) {
8027 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8028 END_PROFILE(SMBgetattrE);
8029 return;
8032 /* Do an fstat on this file */
8033 if(fsp_stat(fsp)) {
8034 reply_nterror(req, map_nt_error_from_unix(errno));
8035 END_PROFILE(SMBgetattrE);
8036 return;
8039 mode = dos_mode(conn, fsp->fsp_name);
8042 * Convert the times into dos times. Set create
8043 * date to be last modify date as UNIX doesn't save
8044 * this.
8047 reply_outbuf(req, 11, 0);
8049 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8050 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8051 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8052 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8053 /* Should we check pending modtime here ? JRA */
8054 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8055 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8057 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8058 SIVAL(req->outbuf, smb_vwv6, 0);
8059 SIVAL(req->outbuf, smb_vwv8, 0);
8060 } else {
8061 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8062 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8063 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8065 SSVAL(req->outbuf,smb_vwv10, mode);
8067 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8069 END_PROFILE(SMBgetattrE);
8070 return;