s3: Remove "req_wct_ofs()"
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blob6e4bcab7741e467770a8a911d994283db4af1c29
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 close_cnum(conn,req->vuid);
740 req->conn = NULL;
741 conn = NULL;
744 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
745 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
746 END_PROFILE(SMBtconX);
747 return;
750 if (sconn->smb1.negprot.encrypted_passwords) {
751 p = (const char *)req->buf + passlen;
752 } else {
753 p = (const char *)req->buf + passlen + 1;
756 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
758 if (path == NULL) {
759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
760 END_PROFILE(SMBtconX);
761 return;
765 * the service name can be either: \\server\share
766 * or share directly like on the DELL PowerVault 705
768 if (*path=='\\') {
769 q = strchr_m(path+2,'\\');
770 if (!q) {
771 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
772 END_PROFILE(SMBtconX);
773 return;
775 service = q+1;
776 } else {
777 service = path;
780 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
781 &client_devicetype, p,
782 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
784 if (client_devicetype == NULL) {
785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
786 END_PROFILE(SMBtconX);
787 return;
790 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
792 conn = make_connection(sconn, service, client_devicetype,
793 req->vuid, &nt_status);
794 req->conn =conn;
796 if (!conn) {
797 reply_nterror(req, nt_status);
798 END_PROFILE(SMBtconX);
799 return;
802 if ( IS_IPC(conn) )
803 server_devicetype = "IPC";
804 else if ( IS_PRINT(conn) )
805 server_devicetype = "LPT1:";
806 else
807 server_devicetype = "A:";
809 if (get_Protocol() < PROTOCOL_NT1) {
810 reply_outbuf(req, 2, 0);
811 if (message_push_string(&req->outbuf, server_devicetype,
812 STR_TERMINATE|STR_ASCII) == -1) {
813 reply_nterror(req, NT_STATUS_NO_MEMORY);
814 END_PROFILE(SMBtconX);
815 return;
817 } else {
818 /* NT sets the fstype of IPC$ to the null string */
819 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
821 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
822 /* Return permissions. */
823 uint32 perm1 = 0;
824 uint32 perm2 = 0;
826 reply_outbuf(req, 7, 0);
828 if (IS_IPC(conn)) {
829 perm1 = FILE_ALL_ACCESS;
830 perm2 = FILE_ALL_ACCESS;
831 } else {
832 perm1 = conn->share_access;
835 SIVAL(req->outbuf, smb_vwv3, perm1);
836 SIVAL(req->outbuf, smb_vwv5, perm2);
837 } else {
838 reply_outbuf(req, 3, 0);
841 if ((message_push_string(&req->outbuf, server_devicetype,
842 STR_TERMINATE|STR_ASCII) == -1)
843 || (message_push_string(&req->outbuf, fstype,
844 STR_TERMINATE) == -1)) {
845 reply_nterror(req, NT_STATUS_NO_MEMORY);
846 END_PROFILE(SMBtconX);
847 return;
850 /* what does setting this bit do? It is set by NT4 and
851 may affect the ability to autorun mounted cdroms */
852 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
853 (lp_csc_policy(SNUM(conn)) << 2));
855 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
856 DEBUG(2,("Serving %s as a Dfs root\n",
857 lp_servicename(SNUM(conn)) ));
858 SSVAL(req->outbuf, smb_vwv2,
859 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
863 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
864 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
866 DEBUG(3,("tconX service=%s \n",
867 service));
869 /* set the incoming and outgoing tid to the just created one */
870 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
871 SSVAL(req->outbuf,smb_tid,conn->cnum);
873 END_PROFILE(SMBtconX);
875 req->tid = conn->cnum;
878 /****************************************************************************
879 Reply to an unknown type.
880 ****************************************************************************/
882 void reply_unknown_new(struct smb_request *req, uint8 type)
884 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
885 smb_fn_name(type), type, type));
886 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
887 return;
890 /****************************************************************************
891 Reply to an ioctl.
892 conn POINTER CAN BE NULL HERE !
893 ****************************************************************************/
895 void reply_ioctl(struct smb_request *req)
897 connection_struct *conn = req->conn;
898 uint16 device;
899 uint16 function;
900 uint32 ioctl_code;
901 int replysize;
902 char *p;
904 START_PROFILE(SMBioctl);
906 if (req->wct < 3) {
907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
908 END_PROFILE(SMBioctl);
909 return;
912 device = SVAL(req->vwv+1, 0);
913 function = SVAL(req->vwv+2, 0);
914 ioctl_code = (device << 16) + function;
916 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
918 switch (ioctl_code) {
919 case IOCTL_QUERY_JOB_INFO:
920 replysize = 32;
921 break;
922 default:
923 reply_force_doserror(req, ERRSRV, ERRnosupport);
924 END_PROFILE(SMBioctl);
925 return;
928 reply_outbuf(req, 8, replysize+1);
929 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
930 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
931 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
932 p = smb_buf(req->outbuf);
933 memset(p, '\0', replysize+1); /* valgrind-safe. */
934 p += 1; /* Allow for alignment */
936 switch (ioctl_code) {
937 case IOCTL_QUERY_JOB_INFO:
939 files_struct *fsp = file_fsp(
940 req, SVAL(req->vwv+0, 0));
941 if (!fsp) {
942 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
943 END_PROFILE(SMBioctl);
944 return;
946 /* Job number */
947 if (fsp->print_file) {
948 SSVAL(p, 0, fsp->print_file->rap_jobid);
949 } else {
950 SSVAL(p, 0, 0);
952 srvstr_push((char *)req->outbuf, req->flags2, p+2,
953 lp_netbios_name(), 15,
954 STR_TERMINATE|STR_ASCII);
955 if (conn) {
956 srvstr_push((char *)req->outbuf, req->flags2,
957 p+18, lp_servicename(SNUM(conn)),
958 13, STR_TERMINATE|STR_ASCII);
959 } else {
960 memset(p+18, 0, 13);
962 break;
966 END_PROFILE(SMBioctl);
967 return;
970 /****************************************************************************
971 Strange checkpath NTSTATUS mapping.
972 ****************************************************************************/
974 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
976 /* Strange DOS error code semantics only for checkpath... */
977 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
978 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
979 /* We need to map to ERRbadpath */
980 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
983 return status;
986 /****************************************************************************
987 Reply to a checkpath.
988 ****************************************************************************/
990 void reply_checkpath(struct smb_request *req)
992 connection_struct *conn = req->conn;
993 struct smb_filename *smb_fname = NULL;
994 char *name = NULL;
995 NTSTATUS status;
996 TALLOC_CTX *ctx = talloc_tos();
998 START_PROFILE(SMBcheckpath);
1000 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1001 STR_TERMINATE, &status);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 status = map_checkpath_error(req->flags2, status);
1005 reply_nterror(req, status);
1006 END_PROFILE(SMBcheckpath);
1007 return;
1010 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1012 status = filename_convert(ctx,
1013 conn,
1014 req->flags2 & FLAGS2_DFS_PATHNAMES,
1015 name,
1017 NULL,
1018 &smb_fname);
1020 if (!NT_STATUS_IS_OK(status)) {
1021 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1022 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1023 ERRSRV, ERRbadpath);
1024 END_PROFILE(SMBcheckpath);
1025 return;
1027 goto path_err;
1030 if (!VALID_STAT(smb_fname->st) &&
1031 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1032 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1033 smb_fname_str_dbg(smb_fname), strerror(errno)));
1034 status = map_nt_error_from_unix(errno);
1035 goto path_err;
1038 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1039 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1040 ERRDOS, ERRbadpath);
1041 goto out;
1044 reply_outbuf(req, 0, 0);
1046 path_err:
1047 /* We special case this - as when a Windows machine
1048 is parsing a path is steps through the components
1049 one at a time - if a component fails it expects
1050 ERRbadpath, not ERRbadfile.
1052 status = map_checkpath_error(req->flags2, status);
1053 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1055 * Windows returns different error codes if
1056 * the parent directory is valid but not the
1057 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1058 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1059 * if the path is invalid.
1061 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1062 ERRDOS, ERRbadpath);
1063 goto out;
1066 reply_nterror(req, status);
1068 out:
1069 TALLOC_FREE(smb_fname);
1070 END_PROFILE(SMBcheckpath);
1071 return;
1074 /****************************************************************************
1075 Reply to a getatr.
1076 ****************************************************************************/
1078 void reply_getatr(struct smb_request *req)
1080 connection_struct *conn = req->conn;
1081 struct smb_filename *smb_fname = NULL;
1082 char *fname = NULL;
1083 int mode=0;
1084 SMB_OFF_T size=0;
1085 time_t mtime=0;
1086 const char *p;
1087 NTSTATUS status;
1088 TALLOC_CTX *ctx = talloc_tos();
1089 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1091 START_PROFILE(SMBgetatr);
1093 p = (const char *)req->buf + 1;
1094 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1095 if (!NT_STATUS_IS_OK(status)) {
1096 reply_nterror(req, status);
1097 goto out;
1100 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1101 under WfWg - weird! */
1102 if (*fname == '\0') {
1103 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1104 if (!CAN_WRITE(conn)) {
1105 mode |= FILE_ATTRIBUTE_READONLY;
1107 size = 0;
1108 mtime = 0;
1109 } else {
1110 status = filename_convert(ctx,
1111 conn,
1112 req->flags2 & FLAGS2_DFS_PATHNAMES,
1113 fname,
1115 NULL,
1116 &smb_fname);
1117 if (!NT_STATUS_IS_OK(status)) {
1118 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1119 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1120 ERRSRV, ERRbadpath);
1121 goto out;
1123 reply_nterror(req, status);
1124 goto out;
1126 if (!VALID_STAT(smb_fname->st) &&
1127 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1128 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1129 smb_fname_str_dbg(smb_fname),
1130 strerror(errno)));
1131 reply_nterror(req, map_nt_error_from_unix(errno));
1132 goto out;
1135 mode = dos_mode(conn, smb_fname);
1136 size = smb_fname->st.st_ex_size;
1138 if (ask_sharemode) {
1139 struct timespec write_time_ts;
1140 struct file_id fileid;
1142 ZERO_STRUCT(write_time_ts);
1143 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1144 get_file_infos(fileid, 0, NULL, &write_time_ts);
1145 if (!null_timespec(write_time_ts)) {
1146 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1150 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1151 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1152 size = 0;
1156 reply_outbuf(req, 10, 0);
1158 SSVAL(req->outbuf,smb_vwv0,mode);
1159 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1160 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1161 } else {
1162 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1164 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1166 if (get_Protocol() >= PROTOCOL_NT1) {
1167 SSVAL(req->outbuf, smb_flg2,
1168 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1171 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1172 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1174 out:
1175 TALLOC_FREE(smb_fname);
1176 TALLOC_FREE(fname);
1177 END_PROFILE(SMBgetatr);
1178 return;
1181 /****************************************************************************
1182 Reply to a setatr.
1183 ****************************************************************************/
1185 void reply_setatr(struct smb_request *req)
1187 struct smb_file_time ft;
1188 connection_struct *conn = req->conn;
1189 struct smb_filename *smb_fname = NULL;
1190 char *fname = NULL;
1191 int mode;
1192 time_t mtime;
1193 const char *p;
1194 NTSTATUS status;
1195 TALLOC_CTX *ctx = talloc_tos();
1197 START_PROFILE(SMBsetatr);
1199 ZERO_STRUCT(ft);
1201 if (req->wct < 2) {
1202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1203 goto out;
1206 p = (const char *)req->buf + 1;
1207 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 reply_nterror(req, status);
1210 goto out;
1213 status = filename_convert(ctx,
1214 conn,
1215 req->flags2 & FLAGS2_DFS_PATHNAMES,
1216 fname,
1218 NULL,
1219 &smb_fname);
1220 if (!NT_STATUS_IS_OK(status)) {
1221 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1222 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1223 ERRSRV, ERRbadpath);
1224 goto out;
1226 reply_nterror(req, status);
1227 goto out;
1230 if (smb_fname->base_name[0] == '.' &&
1231 smb_fname->base_name[1] == '\0') {
1233 * Not sure here is the right place to catch this
1234 * condition. Might be moved to somewhere else later -- vl
1236 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1237 goto out;
1240 mode = SVAL(req->vwv+0, 0);
1241 mtime = srv_make_unix_date3(req->vwv+1);
1243 if (mode != FILE_ATTRIBUTE_NORMAL) {
1244 if (VALID_STAT_OF_DIR(smb_fname->st))
1245 mode |= FILE_ATTRIBUTE_DIRECTORY;
1246 else
1247 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1249 status = check_access(conn, NULL, smb_fname,
1250 FILE_WRITE_ATTRIBUTES);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 reply_nterror(req, status);
1253 goto out;
1256 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1257 false) != 0) {
1258 reply_nterror(req, map_nt_error_from_unix(errno));
1259 goto out;
1263 ft.mtime = convert_time_t_to_timespec(mtime);
1264 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 reply_nterror(req, status);
1267 goto out;
1270 reply_outbuf(req, 0, 0);
1272 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1273 mode));
1274 out:
1275 TALLOC_FREE(smb_fname);
1276 END_PROFILE(SMBsetatr);
1277 return;
1280 /****************************************************************************
1281 Reply to a dskattr.
1282 ****************************************************************************/
1284 void reply_dskattr(struct smb_request *req)
1286 connection_struct *conn = req->conn;
1287 uint64_t dfree,dsize,bsize;
1288 START_PROFILE(SMBdskattr);
1290 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1291 reply_nterror(req, map_nt_error_from_unix(errno));
1292 END_PROFILE(SMBdskattr);
1293 return;
1296 reply_outbuf(req, 5, 0);
1298 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1299 double total_space, free_space;
1300 /* we need to scale this to a number that DOS6 can handle. We
1301 use floating point so we can handle large drives on systems
1302 that don't have 64 bit integers
1304 we end up displaying a maximum of 2G to DOS systems
1306 total_space = dsize * (double)bsize;
1307 free_space = dfree * (double)bsize;
1309 dsize = (uint64_t)((total_space+63*512) / (64*512));
1310 dfree = (uint64_t)((free_space+63*512) / (64*512));
1312 if (dsize > 0xFFFF) dsize = 0xFFFF;
1313 if (dfree > 0xFFFF) dfree = 0xFFFF;
1315 SSVAL(req->outbuf,smb_vwv0,dsize);
1316 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1317 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1318 SSVAL(req->outbuf,smb_vwv3,dfree);
1319 } else {
1320 SSVAL(req->outbuf,smb_vwv0,dsize);
1321 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1322 SSVAL(req->outbuf,smb_vwv2,512);
1323 SSVAL(req->outbuf,smb_vwv3,dfree);
1326 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1328 END_PROFILE(SMBdskattr);
1329 return;
1333 * Utility function to split the filename from the directory.
1335 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1336 char **fname_dir_out,
1337 char **fname_mask_out)
1339 const char *p = NULL;
1340 char *fname_dir = NULL;
1341 char *fname_mask = NULL;
1343 p = strrchr_m(fname_in, '/');
1344 if (!p) {
1345 fname_dir = talloc_strdup(ctx, ".");
1346 fname_mask = talloc_strdup(ctx, fname_in);
1347 } else {
1348 fname_dir = talloc_strndup(ctx, fname_in,
1349 PTR_DIFF(p, fname_in));
1350 fname_mask = talloc_strdup(ctx, p+1);
1353 if (!fname_dir || !fname_mask) {
1354 TALLOC_FREE(fname_dir);
1355 TALLOC_FREE(fname_mask);
1356 return NT_STATUS_NO_MEMORY;
1359 *fname_dir_out = fname_dir;
1360 *fname_mask_out = fname_mask;
1361 return NT_STATUS_OK;
1364 /****************************************************************************
1365 Reply to a search.
1366 Can be called from SMBsearch, SMBffirst or SMBfunique.
1367 ****************************************************************************/
1369 void reply_search(struct smb_request *req)
1371 connection_struct *conn = req->conn;
1372 char *path = NULL;
1373 const char *mask = NULL;
1374 char *directory = NULL;
1375 struct smb_filename *smb_fname = NULL;
1376 char *fname = NULL;
1377 SMB_OFF_T size;
1378 uint32 mode;
1379 struct timespec date;
1380 uint32 dirtype;
1381 unsigned int numentries = 0;
1382 unsigned int maxentries = 0;
1383 bool finished = False;
1384 const char *p;
1385 int status_len;
1386 char status[21];
1387 int dptr_num= -1;
1388 bool check_descend = False;
1389 bool expect_close = False;
1390 NTSTATUS nt_status;
1391 bool mask_contains_wcard = False;
1392 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1393 TALLOC_CTX *ctx = talloc_tos();
1394 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1395 struct dptr_struct *dirptr = NULL;
1396 struct smbd_server_connection *sconn = req->sconn;
1398 START_PROFILE(SMBsearch);
1400 if (req->wct < 2) {
1401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1402 goto out;
1405 if (lp_posix_pathnames()) {
1406 reply_unknown_new(req, req->cmd);
1407 goto out;
1410 /* If we were called as SMBffirst then we must expect close. */
1411 if(req->cmd == SMBffirst) {
1412 expect_close = True;
1415 reply_outbuf(req, 1, 3);
1416 maxentries = SVAL(req->vwv+0, 0);
1417 dirtype = SVAL(req->vwv+1, 0);
1418 p = (const char *)req->buf + 1;
1419 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1420 &nt_status, &mask_contains_wcard);
1421 if (!NT_STATUS_IS_OK(nt_status)) {
1422 reply_nterror(req, nt_status);
1423 goto out;
1426 p++;
1427 status_len = SVAL(p, 0);
1428 p += 2;
1430 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1432 if (status_len == 0) {
1433 nt_status = filename_convert(ctx, conn,
1434 req->flags2 & FLAGS2_DFS_PATHNAMES,
1435 path,
1436 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1437 &mask_contains_wcard,
1438 &smb_fname);
1439 if (!NT_STATUS_IS_OK(nt_status)) {
1440 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1441 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1442 ERRSRV, ERRbadpath);
1443 goto out;
1445 reply_nterror(req, nt_status);
1446 goto out;
1449 directory = smb_fname->base_name;
1451 p = strrchr_m(directory,'/');
1452 if ((p != NULL) && (*directory != '/')) {
1453 mask = p + 1;
1454 directory = talloc_strndup(ctx, directory,
1455 PTR_DIFF(p, directory));
1456 } else {
1457 mask = directory;
1458 directory = talloc_strdup(ctx,".");
1461 if (!directory) {
1462 reply_nterror(req, NT_STATUS_NO_MEMORY);
1463 goto out;
1466 memset((char *)status,'\0',21);
1467 SCVAL(status,0,(dirtype & 0x1F));
1469 nt_status = dptr_create(conn,
1470 NULL, /* req */
1471 NULL, /* fsp */
1472 directory,
1473 True,
1474 expect_close,
1475 req->smbpid,
1476 mask,
1477 mask_contains_wcard,
1478 dirtype,
1479 &dirptr);
1480 if (!NT_STATUS_IS_OK(nt_status)) {
1481 reply_nterror(req, nt_status);
1482 goto out;
1484 dptr_num = dptr_dnum(dirptr);
1485 } else {
1486 int status_dirtype;
1487 const char *dirpath;
1489 memcpy(status,p,21);
1490 status_dirtype = CVAL(status,0) & 0x1F;
1491 if (status_dirtype != (dirtype & 0x1F)) {
1492 dirtype = status_dirtype;
1495 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1496 if (!dirptr) {
1497 goto SearchEmpty;
1499 dirpath = dptr_path(sconn, dptr_num);
1500 directory = talloc_strdup(ctx, dirpath);
1501 if (!directory) {
1502 reply_nterror(req, NT_STATUS_NO_MEMORY);
1503 goto out;
1506 mask = dptr_wcard(sconn, dptr_num);
1507 if (!mask) {
1508 goto SearchEmpty;
1511 * For a 'continue' search we have no string. So
1512 * check from the initial saved string.
1514 mask_contains_wcard = ms_has_wild(mask);
1515 dirtype = dptr_attr(sconn, dptr_num);
1518 DEBUG(4,("dptr_num is %d\n",dptr_num));
1520 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1521 dptr_init_search_op(dirptr);
1523 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1524 char buf[DIR_STRUCT_SIZE];
1525 memcpy(buf,status,21);
1526 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1527 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1528 reply_nterror(req, NT_STATUS_NO_MEMORY);
1529 goto out;
1531 dptr_fill(sconn, buf+12,dptr_num);
1532 if (dptr_zero(buf+12) && (status_len==0)) {
1533 numentries = 1;
1534 } else {
1535 numentries = 0;
1537 if (message_push_blob(&req->outbuf,
1538 data_blob_const(buf, sizeof(buf)))
1539 == -1) {
1540 reply_nterror(req, NT_STATUS_NO_MEMORY);
1541 goto out;
1543 } else {
1544 unsigned int i;
1545 maxentries = MIN(
1546 maxentries,
1547 ((BUFFER_SIZE -
1548 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1549 /DIR_STRUCT_SIZE));
1551 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1552 directory,lp_dontdescend(SNUM(conn))));
1553 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1554 check_descend = True;
1557 for (i=numentries;(i<maxentries) && !finished;i++) {
1558 finished = !get_dir_entry(ctx,
1559 dirptr,
1560 mask,
1561 dirtype,
1562 &fname,
1563 &size,
1564 &mode,
1565 &date,
1566 check_descend,
1567 ask_sharemode);
1568 if (!finished) {
1569 char buf[DIR_STRUCT_SIZE];
1570 memcpy(buf,status,21);
1571 if (!make_dir_struct(ctx,
1572 buf,
1573 mask,
1574 fname,
1575 size,
1576 mode,
1577 convert_timespec_to_time_t(date),
1578 !allow_long_path_components)) {
1579 reply_nterror(req, NT_STATUS_NO_MEMORY);
1580 goto out;
1582 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1583 break;
1585 if (message_push_blob(&req->outbuf,
1586 data_blob_const(buf, sizeof(buf)))
1587 == -1) {
1588 reply_nterror(req, NT_STATUS_NO_MEMORY);
1589 goto out;
1591 numentries++;
1596 SearchEmpty:
1598 /* If we were called as SMBffirst with smb_search_id == NULL
1599 and no entries were found then return error and close dirptr
1600 (X/Open spec) */
1602 if (numentries == 0) {
1603 dptr_close(sconn, &dptr_num);
1604 } else if(expect_close && status_len == 0) {
1605 /* Close the dptr - we know it's gone */
1606 dptr_close(sconn, &dptr_num);
1609 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1610 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1611 dptr_close(sconn, &dptr_num);
1614 if ((numentries == 0) && !mask_contains_wcard) {
1615 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1616 goto out;
1619 SSVAL(req->outbuf,smb_vwv0,numentries);
1620 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1621 SCVAL(smb_buf(req->outbuf),0,5);
1622 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1624 /* The replies here are never long name. */
1625 SSVAL(req->outbuf, smb_flg2,
1626 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1627 if (!allow_long_path_components) {
1628 SSVAL(req->outbuf, smb_flg2,
1629 SVAL(req->outbuf, smb_flg2)
1630 & (~FLAGS2_LONG_PATH_COMPONENTS));
1633 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1634 SSVAL(req->outbuf, smb_flg2,
1635 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1637 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1638 smb_fn_name(req->cmd),
1639 mask,
1640 directory,
1641 dirtype,
1642 numentries,
1643 maxentries ));
1644 out:
1645 TALLOC_FREE(directory);
1646 TALLOC_FREE(smb_fname);
1647 END_PROFILE(SMBsearch);
1648 return;
1651 /****************************************************************************
1652 Reply to a fclose (stop directory search).
1653 ****************************************************************************/
1655 void reply_fclose(struct smb_request *req)
1657 int status_len;
1658 char status[21];
1659 int dptr_num= -2;
1660 const char *p;
1661 char *path = NULL;
1662 NTSTATUS err;
1663 bool path_contains_wcard = False;
1664 TALLOC_CTX *ctx = talloc_tos();
1665 struct smbd_server_connection *sconn = req->sconn;
1667 START_PROFILE(SMBfclose);
1669 if (lp_posix_pathnames()) {
1670 reply_unknown_new(req, req->cmd);
1671 END_PROFILE(SMBfclose);
1672 return;
1675 p = (const char *)req->buf + 1;
1676 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1677 &err, &path_contains_wcard);
1678 if (!NT_STATUS_IS_OK(err)) {
1679 reply_nterror(req, err);
1680 END_PROFILE(SMBfclose);
1681 return;
1683 p++;
1684 status_len = SVAL(p,0);
1685 p += 2;
1687 if (status_len == 0) {
1688 reply_force_doserror(req, ERRSRV, ERRsrverror);
1689 END_PROFILE(SMBfclose);
1690 return;
1693 memcpy(status,p,21);
1695 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1696 /* Close the dptr - we know it's gone */
1697 dptr_close(sconn, &dptr_num);
1700 reply_outbuf(req, 1, 0);
1701 SSVAL(req->outbuf,smb_vwv0,0);
1703 DEBUG(3,("search close\n"));
1705 END_PROFILE(SMBfclose);
1706 return;
1709 /****************************************************************************
1710 Reply to an open.
1711 ****************************************************************************/
1713 void reply_open(struct smb_request *req)
1715 connection_struct *conn = req->conn;
1716 struct smb_filename *smb_fname = NULL;
1717 char *fname = NULL;
1718 uint32 fattr=0;
1719 SMB_OFF_T size = 0;
1720 time_t mtime=0;
1721 int info;
1722 files_struct *fsp;
1723 int oplock_request;
1724 int deny_mode;
1725 uint32 dos_attr;
1726 uint32 access_mask;
1727 uint32 share_mode;
1728 uint32 create_disposition;
1729 uint32 create_options = 0;
1730 uint32_t private_flags = 0;
1731 NTSTATUS status;
1732 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1733 TALLOC_CTX *ctx = talloc_tos();
1735 START_PROFILE(SMBopen);
1737 if (req->wct < 2) {
1738 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1739 goto out;
1742 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1743 deny_mode = SVAL(req->vwv+0, 0);
1744 dos_attr = SVAL(req->vwv+1, 0);
1746 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1747 STR_TERMINATE, &status);
1748 if (!NT_STATUS_IS_OK(status)) {
1749 reply_nterror(req, status);
1750 goto out;
1753 status = filename_convert(ctx,
1754 conn,
1755 req->flags2 & FLAGS2_DFS_PATHNAMES,
1756 fname,
1758 NULL,
1759 &smb_fname);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1762 reply_botherror(req,
1763 NT_STATUS_PATH_NOT_COVERED,
1764 ERRSRV, ERRbadpath);
1765 goto out;
1767 reply_nterror(req, status);
1768 goto out;
1771 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1772 OPENX_FILE_EXISTS_OPEN, &access_mask,
1773 &share_mode, &create_disposition,
1774 &create_options, &private_flags)) {
1775 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1776 goto out;
1779 status = SMB_VFS_CREATE_FILE(
1780 conn, /* conn */
1781 req, /* req */
1782 0, /* root_dir_fid */
1783 smb_fname, /* fname */
1784 access_mask, /* access_mask */
1785 share_mode, /* share_access */
1786 create_disposition, /* create_disposition*/
1787 create_options, /* create_options */
1788 dos_attr, /* file_attributes */
1789 oplock_request, /* oplock_request */
1790 0, /* allocation_size */
1791 private_flags,
1792 NULL, /* sd */
1793 NULL, /* ea_list */
1794 &fsp, /* result */
1795 &info); /* pinfo */
1797 if (!NT_STATUS_IS_OK(status)) {
1798 if (open_was_deferred(req->sconn, req->mid)) {
1799 /* We have re-scheduled this call. */
1800 goto out;
1802 reply_openerror(req, status);
1803 goto out;
1806 size = smb_fname->st.st_ex_size;
1807 fattr = dos_mode(conn, smb_fname);
1809 /* Deal with other possible opens having a modified
1810 write time. JRA. */
1811 if (ask_sharemode) {
1812 struct timespec write_time_ts;
1814 ZERO_STRUCT(write_time_ts);
1815 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1816 if (!null_timespec(write_time_ts)) {
1817 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1821 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1823 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1824 DEBUG(3,("attempt to open a directory %s\n",
1825 fsp_str_dbg(fsp)));
1826 close_file(req, fsp, ERROR_CLOSE);
1827 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1828 ERRDOS, ERRnoaccess);
1829 goto out;
1832 reply_outbuf(req, 7, 0);
1833 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1834 SSVAL(req->outbuf,smb_vwv1,fattr);
1835 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1836 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1837 } else {
1838 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1840 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1841 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1843 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1844 SCVAL(req->outbuf,smb_flg,
1845 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1848 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1849 SCVAL(req->outbuf,smb_flg,
1850 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1852 out:
1853 TALLOC_FREE(smb_fname);
1854 END_PROFILE(SMBopen);
1855 return;
1858 /****************************************************************************
1859 Reply to an open and X.
1860 ****************************************************************************/
1862 void reply_open_and_X(struct smb_request *req)
1864 connection_struct *conn = req->conn;
1865 struct smb_filename *smb_fname = NULL;
1866 char *fname = NULL;
1867 uint16 open_flags;
1868 int deny_mode;
1869 uint32 smb_attr;
1870 /* Breakout the oplock request bits so we can set the
1871 reply bits separately. */
1872 int ex_oplock_request;
1873 int core_oplock_request;
1874 int oplock_request;
1875 #if 0
1876 int smb_sattr = SVAL(req->vwv+4, 0);
1877 uint32 smb_time = make_unix_date3(req->vwv+6);
1878 #endif
1879 int smb_ofun;
1880 uint32 fattr=0;
1881 int mtime=0;
1882 int smb_action = 0;
1883 files_struct *fsp;
1884 NTSTATUS status;
1885 uint64_t allocation_size;
1886 ssize_t retval = -1;
1887 uint32 access_mask;
1888 uint32 share_mode;
1889 uint32 create_disposition;
1890 uint32 create_options = 0;
1891 uint32_t private_flags = 0;
1892 TALLOC_CTX *ctx = talloc_tos();
1894 START_PROFILE(SMBopenX);
1896 if (req->wct < 15) {
1897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1898 goto out;
1901 open_flags = SVAL(req->vwv+2, 0);
1902 deny_mode = SVAL(req->vwv+3, 0);
1903 smb_attr = SVAL(req->vwv+5, 0);
1904 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1905 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1906 oplock_request = ex_oplock_request | core_oplock_request;
1907 smb_ofun = SVAL(req->vwv+8, 0);
1908 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1910 /* If it's an IPC, pass off the pipe handler. */
1911 if (IS_IPC(conn)) {
1912 if (lp_nt_pipe_support()) {
1913 reply_open_pipe_and_X(conn, req);
1914 } else {
1915 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1917 goto out;
1920 /* XXXX we need to handle passed times, sattr and flags */
1921 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1922 STR_TERMINATE, &status);
1923 if (!NT_STATUS_IS_OK(status)) {
1924 reply_nterror(req, status);
1925 goto out;
1928 status = filename_convert(ctx,
1929 conn,
1930 req->flags2 & FLAGS2_DFS_PATHNAMES,
1931 fname,
1933 NULL,
1934 &smb_fname);
1935 if (!NT_STATUS_IS_OK(status)) {
1936 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1937 reply_botherror(req,
1938 NT_STATUS_PATH_NOT_COVERED,
1939 ERRSRV, ERRbadpath);
1940 goto out;
1942 reply_nterror(req, status);
1943 goto out;
1946 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1947 smb_ofun,
1948 &access_mask, &share_mode,
1949 &create_disposition,
1950 &create_options,
1951 &private_flags)) {
1952 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1953 goto out;
1956 status = SMB_VFS_CREATE_FILE(
1957 conn, /* conn */
1958 req, /* req */
1959 0, /* root_dir_fid */
1960 smb_fname, /* fname */
1961 access_mask, /* access_mask */
1962 share_mode, /* share_access */
1963 create_disposition, /* create_disposition*/
1964 create_options, /* create_options */
1965 smb_attr, /* file_attributes */
1966 oplock_request, /* oplock_request */
1967 0, /* allocation_size */
1968 private_flags,
1969 NULL, /* sd */
1970 NULL, /* ea_list */
1971 &fsp, /* result */
1972 &smb_action); /* pinfo */
1974 if (!NT_STATUS_IS_OK(status)) {
1975 if (open_was_deferred(req->sconn, req->mid)) {
1976 /* We have re-scheduled this call. */
1977 goto out;
1979 reply_openerror(req, status);
1980 goto out;
1983 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1984 if the file is truncated or created. */
1985 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1986 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1987 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1988 close_file(req, fsp, ERROR_CLOSE);
1989 reply_nterror(req, NT_STATUS_DISK_FULL);
1990 goto out;
1992 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1993 if (retval < 0) {
1994 close_file(req, fsp, ERROR_CLOSE);
1995 reply_nterror(req, NT_STATUS_DISK_FULL);
1996 goto out;
1998 status = vfs_stat_fsp(fsp);
1999 if (!NT_STATUS_IS_OK(status)) {
2000 close_file(req, fsp, ERROR_CLOSE);
2001 reply_nterror(req, status);
2002 goto out;
2006 fattr = dos_mode(conn, fsp->fsp_name);
2007 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2008 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2009 close_file(req, fsp, ERROR_CLOSE);
2010 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2011 goto out;
2014 /* If the caller set the extended oplock request bit
2015 and we granted one (by whatever means) - set the
2016 correct bit for extended oplock reply.
2019 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2020 smb_action |= EXTENDED_OPLOCK_GRANTED;
2023 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2024 smb_action |= EXTENDED_OPLOCK_GRANTED;
2027 /* If the caller set the core oplock request bit
2028 and we granted one (by whatever means) - set the
2029 correct bit for core oplock reply.
2032 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2033 reply_outbuf(req, 19, 0);
2034 } else {
2035 reply_outbuf(req, 15, 0);
2038 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2039 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2041 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2042 SCVAL(req->outbuf, smb_flg,
2043 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2046 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2047 SCVAL(req->outbuf, smb_flg,
2048 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2051 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2052 SSVAL(req->outbuf,smb_vwv3,fattr);
2053 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2054 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2055 } else {
2056 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2058 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2059 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2060 SSVAL(req->outbuf,smb_vwv11,smb_action);
2062 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2063 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2066 out:
2067 TALLOC_FREE(smb_fname);
2068 END_PROFILE(SMBopenX);
2069 return;
2072 /****************************************************************************
2073 Reply to a SMBulogoffX.
2074 ****************************************************************************/
2076 void reply_ulogoffX(struct smb_request *req)
2078 struct smbd_server_connection *sconn = req->sconn;
2079 user_struct *vuser;
2081 START_PROFILE(SMBulogoffX);
2083 vuser = get_valid_user_struct(sconn, req->vuid);
2085 if(vuser == NULL) {
2086 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2087 req->vuid));
2090 /* in user level security we are supposed to close any files
2091 open by this user */
2092 if (vuser != NULL) {
2093 file_close_user(sconn, req->vuid);
2096 invalidate_vuid(sconn, req->vuid);
2098 reply_outbuf(req, 2, 0);
2099 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2100 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2102 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2104 END_PROFILE(SMBulogoffX);
2105 req->vuid = UID_FIELD_INVALID;
2108 /****************************************************************************
2109 Reply to a mknew or a create.
2110 ****************************************************************************/
2112 void reply_mknew(struct smb_request *req)
2114 connection_struct *conn = req->conn;
2115 struct smb_filename *smb_fname = NULL;
2116 char *fname = NULL;
2117 uint32 fattr = 0;
2118 struct smb_file_time ft;
2119 files_struct *fsp;
2120 int oplock_request = 0;
2121 NTSTATUS status;
2122 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2123 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2124 uint32 create_disposition;
2125 uint32 create_options = 0;
2126 TALLOC_CTX *ctx = talloc_tos();
2128 START_PROFILE(SMBcreate);
2129 ZERO_STRUCT(ft);
2131 if (req->wct < 3) {
2132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2133 goto out;
2136 fattr = SVAL(req->vwv+0, 0);
2137 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2139 /* mtime. */
2140 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2142 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2143 STR_TERMINATE, &status);
2144 if (!NT_STATUS_IS_OK(status)) {
2145 reply_nterror(req, status);
2146 goto out;
2149 status = filename_convert(ctx,
2150 conn,
2151 req->flags2 & FLAGS2_DFS_PATHNAMES,
2152 fname,
2154 NULL,
2155 &smb_fname);
2156 if (!NT_STATUS_IS_OK(status)) {
2157 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2158 reply_botherror(req,
2159 NT_STATUS_PATH_NOT_COVERED,
2160 ERRSRV, ERRbadpath);
2161 goto out;
2163 reply_nterror(req, status);
2164 goto out;
2167 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2168 DEBUG(0,("Attempt to create file (%s) with volid set - "
2169 "please report this\n",
2170 smb_fname_str_dbg(smb_fname)));
2173 if(req->cmd == SMBmknew) {
2174 /* We should fail if file exists. */
2175 create_disposition = FILE_CREATE;
2176 } else {
2177 /* Create if file doesn't exist, truncate if it does. */
2178 create_disposition = FILE_OVERWRITE_IF;
2181 status = SMB_VFS_CREATE_FILE(
2182 conn, /* conn */
2183 req, /* req */
2184 0, /* root_dir_fid */
2185 smb_fname, /* fname */
2186 access_mask, /* access_mask */
2187 share_mode, /* share_access */
2188 create_disposition, /* create_disposition*/
2189 create_options, /* create_options */
2190 fattr, /* file_attributes */
2191 oplock_request, /* oplock_request */
2192 0, /* allocation_size */
2193 0, /* private_flags */
2194 NULL, /* sd */
2195 NULL, /* ea_list */
2196 &fsp, /* result */
2197 NULL); /* pinfo */
2199 if (!NT_STATUS_IS_OK(status)) {
2200 if (open_was_deferred(req->sconn, req->mid)) {
2201 /* We have re-scheduled this call. */
2202 goto out;
2204 reply_openerror(req, status);
2205 goto out;
2208 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2209 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2210 if (!NT_STATUS_IS_OK(status)) {
2211 END_PROFILE(SMBcreate);
2212 goto out;
2215 reply_outbuf(req, 1, 0);
2216 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2218 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2219 SCVAL(req->outbuf,smb_flg,
2220 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2223 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2224 SCVAL(req->outbuf,smb_flg,
2225 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2228 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2229 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2230 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2231 (unsigned int)fattr));
2233 out:
2234 TALLOC_FREE(smb_fname);
2235 END_PROFILE(SMBcreate);
2236 return;
2239 /****************************************************************************
2240 Reply to a create temporary file.
2241 ****************************************************************************/
2243 void reply_ctemp(struct smb_request *req)
2245 connection_struct *conn = req->conn;
2246 struct smb_filename *smb_fname = NULL;
2247 char *fname = NULL;
2248 uint32 fattr;
2249 files_struct *fsp;
2250 int oplock_request;
2251 int tmpfd;
2252 char *s;
2253 NTSTATUS status;
2254 TALLOC_CTX *ctx = talloc_tos();
2256 START_PROFILE(SMBctemp);
2258 if (req->wct < 3) {
2259 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2260 goto out;
2263 fattr = SVAL(req->vwv+0, 0);
2264 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2266 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2267 STR_TERMINATE, &status);
2268 if (!NT_STATUS_IS_OK(status)) {
2269 reply_nterror(req, status);
2270 goto out;
2272 if (*fname) {
2273 fname = talloc_asprintf(ctx,
2274 "%s/TMXXXXXX",
2275 fname);
2276 } else {
2277 fname = talloc_strdup(ctx, "TMXXXXXX");
2280 if (!fname) {
2281 reply_nterror(req, NT_STATUS_NO_MEMORY);
2282 goto out;
2285 status = filename_convert(ctx, conn,
2286 req->flags2 & FLAGS2_DFS_PATHNAMES,
2287 fname,
2289 NULL,
2290 &smb_fname);
2291 if (!NT_STATUS_IS_OK(status)) {
2292 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2293 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2294 ERRSRV, ERRbadpath);
2295 goto out;
2297 reply_nterror(req, status);
2298 goto out;
2301 tmpfd = mkstemp(smb_fname->base_name);
2302 if (tmpfd == -1) {
2303 reply_nterror(req, map_nt_error_from_unix(errno));
2304 goto out;
2307 SMB_VFS_STAT(conn, smb_fname);
2309 /* We should fail if file does not exist. */
2310 status = SMB_VFS_CREATE_FILE(
2311 conn, /* conn */
2312 req, /* req */
2313 0, /* root_dir_fid */
2314 smb_fname, /* fname */
2315 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2316 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2317 FILE_OPEN, /* create_disposition*/
2318 0, /* create_options */
2319 fattr, /* file_attributes */
2320 oplock_request, /* oplock_request */
2321 0, /* allocation_size */
2322 0, /* private_flags */
2323 NULL, /* sd */
2324 NULL, /* ea_list */
2325 &fsp, /* result */
2326 NULL); /* pinfo */
2328 /* close fd from mkstemp() */
2329 close(tmpfd);
2331 if (!NT_STATUS_IS_OK(status)) {
2332 if (open_was_deferred(req->sconn, req->mid)) {
2333 /* We have re-scheduled this call. */
2334 goto out;
2336 reply_openerror(req, status);
2337 goto out;
2340 reply_outbuf(req, 1, 0);
2341 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2343 /* the returned filename is relative to the directory */
2344 s = strrchr_m(fsp->fsp_name->base_name, '/');
2345 if (!s) {
2346 s = fsp->fsp_name->base_name;
2347 } else {
2348 s++;
2351 #if 0
2352 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2353 thing in the byte section. JRA */
2354 SSVALS(p, 0, -1); /* what is this? not in spec */
2355 #endif
2356 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2357 == -1) {
2358 reply_nterror(req, NT_STATUS_NO_MEMORY);
2359 goto out;
2362 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2363 SCVAL(req->outbuf, smb_flg,
2364 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2367 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2368 SCVAL(req->outbuf, smb_flg,
2369 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2372 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2373 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2374 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2375 out:
2376 TALLOC_FREE(smb_fname);
2377 END_PROFILE(SMBctemp);
2378 return;
2381 /*******************************************************************
2382 Check if a user is allowed to rename a file.
2383 ********************************************************************/
2385 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2386 uint16 dirtype)
2388 if (!CAN_WRITE(conn)) {
2389 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2392 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2393 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2394 /* Only bother to read the DOS attribute if we might deny the
2395 rename on the grounds of attribute missmatch. */
2396 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2397 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2398 return NT_STATUS_NO_SUCH_FILE;
2402 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2403 if (fsp->posix_open) {
2404 return NT_STATUS_OK;
2407 /* If no pathnames are open below this
2408 directory, allow the rename. */
2410 if (file_find_subpath(fsp)) {
2411 return NT_STATUS_ACCESS_DENIED;
2413 return NT_STATUS_OK;
2416 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2417 return NT_STATUS_OK;
2420 return NT_STATUS_ACCESS_DENIED;
2423 /*******************************************************************
2424 * unlink a file with all relevant access checks
2425 *******************************************************************/
2427 static NTSTATUS do_unlink(connection_struct *conn,
2428 struct smb_request *req,
2429 struct smb_filename *smb_fname,
2430 uint32 dirtype)
2432 uint32 fattr;
2433 files_struct *fsp;
2434 uint32 dirtype_orig = dirtype;
2435 NTSTATUS status;
2436 int ret;
2437 bool posix_paths = lp_posix_pathnames();
2439 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2440 smb_fname_str_dbg(smb_fname),
2441 dirtype));
2443 if (!CAN_WRITE(conn)) {
2444 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2447 if (posix_paths) {
2448 ret = SMB_VFS_LSTAT(conn, smb_fname);
2449 } else {
2450 ret = SMB_VFS_STAT(conn, smb_fname);
2452 if (ret != 0) {
2453 return map_nt_error_from_unix(errno);
2456 fattr = dos_mode(conn, smb_fname);
2458 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2459 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2462 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2463 if (!dirtype) {
2464 return NT_STATUS_NO_SUCH_FILE;
2467 if (!dir_check_ftype(conn, fattr, dirtype)) {
2468 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2469 return NT_STATUS_FILE_IS_A_DIRECTORY;
2471 return NT_STATUS_NO_SUCH_FILE;
2474 if (dirtype_orig & 0x8000) {
2475 /* These will never be set for POSIX. */
2476 return NT_STATUS_NO_SUCH_FILE;
2479 #if 0
2480 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2481 return NT_STATUS_FILE_IS_A_DIRECTORY;
2484 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2485 return NT_STATUS_NO_SUCH_FILE;
2488 if (dirtype & 0xFF00) {
2489 /* These will never be set for POSIX. */
2490 return NT_STATUS_NO_SUCH_FILE;
2493 dirtype &= 0xFF;
2494 if (!dirtype) {
2495 return NT_STATUS_NO_SUCH_FILE;
2498 /* Can't delete a directory. */
2499 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2500 return NT_STATUS_FILE_IS_A_DIRECTORY;
2502 #endif
2504 #if 0 /* JRATEST */
2505 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2506 return NT_STATUS_OBJECT_NAME_INVALID;
2507 #endif /* JRATEST */
2509 /* On open checks the open itself will check the share mode, so
2510 don't do it here as we'll get it wrong. */
2512 status = SMB_VFS_CREATE_FILE
2513 (conn, /* conn */
2514 req, /* req */
2515 0, /* root_dir_fid */
2516 smb_fname, /* fname */
2517 DELETE_ACCESS, /* access_mask */
2518 FILE_SHARE_NONE, /* share_access */
2519 FILE_OPEN, /* create_disposition*/
2520 FILE_NON_DIRECTORY_FILE, /* create_options */
2521 /* file_attributes */
2522 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2523 FILE_ATTRIBUTE_NORMAL,
2524 0, /* oplock_request */
2525 0, /* allocation_size */
2526 0, /* private_flags */
2527 NULL, /* sd */
2528 NULL, /* ea_list */
2529 &fsp, /* result */
2530 NULL); /* pinfo */
2532 if (!NT_STATUS_IS_OK(status)) {
2533 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2534 nt_errstr(status)));
2535 return status;
2538 status = can_set_delete_on_close(fsp, fattr);
2539 if (!NT_STATUS_IS_OK(status)) {
2540 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2541 "(%s)\n",
2542 smb_fname_str_dbg(smb_fname),
2543 nt_errstr(status)));
2544 close_file(req, fsp, NORMAL_CLOSE);
2545 return status;
2548 /* The set is across all open files on this dev/inode pair. */
2549 if (!set_delete_on_close(fsp, True, conn->session_info->unix_token)) {
2550 close_file(req, fsp, NORMAL_CLOSE);
2551 return NT_STATUS_ACCESS_DENIED;
2554 return close_file(req, fsp, NORMAL_CLOSE);
2557 /****************************************************************************
2558 The guts of the unlink command, split out so it may be called by the NT SMB
2559 code.
2560 ****************************************************************************/
2562 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2563 uint32 dirtype, struct smb_filename *smb_fname,
2564 bool has_wild)
2566 char *fname_dir = NULL;
2567 char *fname_mask = NULL;
2568 int count=0;
2569 NTSTATUS status = NT_STATUS_OK;
2570 TALLOC_CTX *ctx = talloc_tos();
2572 /* Split up the directory from the filename/mask. */
2573 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2574 &fname_dir, &fname_mask);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 goto out;
2580 * We should only check the mangled cache
2581 * here if unix_convert failed. This means
2582 * that the path in 'mask' doesn't exist
2583 * on the file system and so we need to look
2584 * for a possible mangle. This patch from
2585 * Tine Smukavec <valentin.smukavec@hermes.si>.
2588 if (!VALID_STAT(smb_fname->st) &&
2589 mangle_is_mangled(fname_mask, conn->params)) {
2590 char *new_mask = NULL;
2591 mangle_lookup_name_from_8_3(ctx, fname_mask,
2592 &new_mask, conn->params);
2593 if (new_mask) {
2594 TALLOC_FREE(fname_mask);
2595 fname_mask = new_mask;
2599 if (!has_wild) {
2602 * Only one file needs to be unlinked. Append the mask back
2603 * onto the directory.
2605 TALLOC_FREE(smb_fname->base_name);
2606 if (ISDOT(fname_dir)) {
2607 /* Ensure we use canonical names on open. */
2608 smb_fname->base_name = talloc_asprintf(smb_fname,
2609 "%s",
2610 fname_mask);
2611 } else {
2612 smb_fname->base_name = talloc_asprintf(smb_fname,
2613 "%s/%s",
2614 fname_dir,
2615 fname_mask);
2617 if (!smb_fname->base_name) {
2618 status = NT_STATUS_NO_MEMORY;
2619 goto out;
2621 if (dirtype == 0) {
2622 dirtype = FILE_ATTRIBUTE_NORMAL;
2625 status = check_name(conn, smb_fname->base_name);
2626 if (!NT_STATUS_IS_OK(status)) {
2627 goto out;
2630 status = do_unlink(conn, req, smb_fname, dirtype);
2631 if (!NT_STATUS_IS_OK(status)) {
2632 goto out;
2635 count++;
2636 } else {
2637 struct smb_Dir *dir_hnd = NULL;
2638 long offset = 0;
2639 const char *dname = NULL;
2640 char *talloced = NULL;
2642 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2643 status = NT_STATUS_OBJECT_NAME_INVALID;
2644 goto out;
2647 if (strequal(fname_mask,"????????.???")) {
2648 TALLOC_FREE(fname_mask);
2649 fname_mask = talloc_strdup(ctx, "*");
2650 if (!fname_mask) {
2651 status = NT_STATUS_NO_MEMORY;
2652 goto out;
2656 status = check_name(conn, fname_dir);
2657 if (!NT_STATUS_IS_OK(status)) {
2658 goto out;
2661 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2662 dirtype);
2663 if (dir_hnd == NULL) {
2664 status = map_nt_error_from_unix(errno);
2665 goto out;
2668 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2669 the pattern matches against the long name, otherwise the short name
2670 We don't implement this yet XXXX
2673 status = NT_STATUS_NO_SUCH_FILE;
2675 while ((dname = ReadDirName(dir_hnd, &offset,
2676 &smb_fname->st, &talloced))) {
2677 TALLOC_CTX *frame = talloc_stackframe();
2679 if (!is_visible_file(conn, fname_dir, dname,
2680 &smb_fname->st, true)) {
2681 TALLOC_FREE(frame);
2682 TALLOC_FREE(talloced);
2683 continue;
2686 /* Quick check for "." and ".." */
2687 if (ISDOT(dname) || ISDOTDOT(dname)) {
2688 TALLOC_FREE(frame);
2689 TALLOC_FREE(talloced);
2690 continue;
2693 if(!mask_match(dname, fname_mask,
2694 conn->case_sensitive)) {
2695 TALLOC_FREE(frame);
2696 TALLOC_FREE(talloced);
2697 continue;
2700 TALLOC_FREE(smb_fname->base_name);
2701 if (ISDOT(fname_dir)) {
2702 /* Ensure we use canonical names on open. */
2703 smb_fname->base_name =
2704 talloc_asprintf(smb_fname, "%s",
2705 dname);
2706 } else {
2707 smb_fname->base_name =
2708 talloc_asprintf(smb_fname, "%s/%s",
2709 fname_dir, dname);
2712 if (!smb_fname->base_name) {
2713 TALLOC_FREE(dir_hnd);
2714 status = NT_STATUS_NO_MEMORY;
2715 TALLOC_FREE(frame);
2716 TALLOC_FREE(talloced);
2717 goto out;
2720 status = check_name(conn, smb_fname->base_name);
2721 if (!NT_STATUS_IS_OK(status)) {
2722 TALLOC_FREE(dir_hnd);
2723 TALLOC_FREE(frame);
2724 TALLOC_FREE(talloced);
2725 goto out;
2728 status = do_unlink(conn, req, smb_fname, dirtype);
2729 if (!NT_STATUS_IS_OK(status)) {
2730 TALLOC_FREE(frame);
2731 TALLOC_FREE(talloced);
2732 continue;
2735 count++;
2736 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2737 smb_fname->base_name));
2739 TALLOC_FREE(frame);
2740 TALLOC_FREE(talloced);
2742 TALLOC_FREE(dir_hnd);
2745 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2746 status = map_nt_error_from_unix(errno);
2749 out:
2750 TALLOC_FREE(fname_dir);
2751 TALLOC_FREE(fname_mask);
2752 return status;
2755 /****************************************************************************
2756 Reply to a unlink
2757 ****************************************************************************/
2759 void reply_unlink(struct smb_request *req)
2761 connection_struct *conn = req->conn;
2762 char *name = NULL;
2763 struct smb_filename *smb_fname = NULL;
2764 uint32 dirtype;
2765 NTSTATUS status;
2766 bool path_contains_wcard = False;
2767 TALLOC_CTX *ctx = talloc_tos();
2769 START_PROFILE(SMBunlink);
2771 if (req->wct < 1) {
2772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2773 goto out;
2776 dirtype = SVAL(req->vwv+0, 0);
2778 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2779 STR_TERMINATE, &status,
2780 &path_contains_wcard);
2781 if (!NT_STATUS_IS_OK(status)) {
2782 reply_nterror(req, status);
2783 goto out;
2786 status = filename_convert(ctx, conn,
2787 req->flags2 & FLAGS2_DFS_PATHNAMES,
2788 name,
2789 UCF_COND_ALLOW_WCARD_LCOMP,
2790 &path_contains_wcard,
2791 &smb_fname);
2792 if (!NT_STATUS_IS_OK(status)) {
2793 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2794 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2795 ERRSRV, ERRbadpath);
2796 goto out;
2798 reply_nterror(req, status);
2799 goto out;
2802 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2804 status = unlink_internals(conn, req, dirtype, smb_fname,
2805 path_contains_wcard);
2806 if (!NT_STATUS_IS_OK(status)) {
2807 if (open_was_deferred(req->sconn, req->mid)) {
2808 /* We have re-scheduled this call. */
2809 goto out;
2811 reply_nterror(req, status);
2812 goto out;
2815 reply_outbuf(req, 0, 0);
2816 out:
2817 TALLOC_FREE(smb_fname);
2818 END_PROFILE(SMBunlink);
2819 return;
2822 /****************************************************************************
2823 Fail for readbraw.
2824 ****************************************************************************/
2826 static void fail_readraw(void)
2828 const char *errstr = talloc_asprintf(talloc_tos(),
2829 "FAIL ! reply_readbraw: socket write fail (%s)",
2830 strerror(errno));
2831 if (!errstr) {
2832 errstr = "";
2834 exit_server_cleanly(errstr);
2837 /****************************************************************************
2838 Fake (read/write) sendfile. Returns -1 on read or write fail.
2839 ****************************************************************************/
2841 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2843 size_t bufsize;
2844 size_t tosend = nread;
2845 char *buf;
2847 if (nread == 0) {
2848 return 0;
2851 bufsize = MIN(nread, 65536);
2853 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2854 return -1;
2857 while (tosend > 0) {
2858 ssize_t ret;
2859 size_t cur_read;
2861 if (tosend > bufsize) {
2862 cur_read = bufsize;
2863 } else {
2864 cur_read = tosend;
2866 ret = read_file(fsp,buf,startpos,cur_read);
2867 if (ret == -1) {
2868 SAFE_FREE(buf);
2869 return -1;
2872 /* If we had a short read, fill with zeros. */
2873 if (ret < cur_read) {
2874 memset(buf + ret, '\0', cur_read - ret);
2877 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2878 != cur_read) {
2879 char addr[INET6_ADDRSTRLEN];
2881 * Try and give an error message saying what
2882 * client failed.
2884 DEBUG(0, ("write_data failed for client %s. "
2885 "Error %s\n",
2886 get_peer_addr(fsp->conn->sconn->sock, addr,
2887 sizeof(addr)),
2888 strerror(errno)));
2889 SAFE_FREE(buf);
2890 return -1;
2892 tosend -= cur_read;
2893 startpos += cur_read;
2896 SAFE_FREE(buf);
2897 return (ssize_t)nread;
2900 /****************************************************************************
2901 Deal with the case of sendfile reading less bytes from the file than
2902 requested. Fill with zeros (all we can do).
2903 ****************************************************************************/
2905 void sendfile_short_send(files_struct *fsp,
2906 ssize_t nread,
2907 size_t headersize,
2908 size_t smb_maxcnt)
2910 #define SHORT_SEND_BUFSIZE 1024
2911 if (nread < headersize) {
2912 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2913 "header for file %s (%s). Terminating\n",
2914 fsp_str_dbg(fsp), strerror(errno)));
2915 exit_server_cleanly("sendfile_short_send failed");
2918 nread -= headersize;
2920 if (nread < smb_maxcnt) {
2921 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2922 if (!buf) {
2923 exit_server_cleanly("sendfile_short_send: "
2924 "malloc failed");
2927 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2928 "with zeros !\n", fsp_str_dbg(fsp)));
2930 while (nread < smb_maxcnt) {
2932 * We asked for the real file size and told sendfile
2933 * to not go beyond the end of the file. But it can
2934 * happen that in between our fstat call and the
2935 * sendfile call the file was truncated. This is very
2936 * bad because we have already announced the larger
2937 * number of bytes to the client.
2939 * The best we can do now is to send 0-bytes, just as
2940 * a read from a hole in a sparse file would do.
2942 * This should happen rarely enough that I don't care
2943 * about efficiency here :-)
2945 size_t to_write;
2947 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2948 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2949 != to_write) {
2950 char addr[INET6_ADDRSTRLEN];
2952 * Try and give an error message saying what
2953 * client failed.
2955 DEBUG(0, ("write_data failed for client %s. "
2956 "Error %s\n",
2957 get_peer_addr(
2958 fsp->conn->sconn->sock, addr,
2959 sizeof(addr)),
2960 strerror(errno)));
2961 exit_server_cleanly("sendfile_short_send: "
2962 "write_data failed");
2964 nread += to_write;
2966 SAFE_FREE(buf);
2970 /****************************************************************************
2971 Return a readbraw error (4 bytes of zero).
2972 ****************************************************************************/
2974 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2976 char header[4];
2978 SIVAL(header,0,0);
2980 smbd_lock_socket(sconn);
2981 if (write_data(sconn->sock,header,4) != 4) {
2982 char addr[INET6_ADDRSTRLEN];
2984 * Try and give an error message saying what
2985 * client failed.
2987 DEBUG(0, ("write_data failed for client %s. "
2988 "Error %s\n",
2989 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2990 strerror(errno)));
2992 fail_readraw();
2994 smbd_unlock_socket(sconn);
2997 /****************************************************************************
2998 Use sendfile in readbraw.
2999 ****************************************************************************/
3001 static void send_file_readbraw(connection_struct *conn,
3002 struct smb_request *req,
3003 files_struct *fsp,
3004 SMB_OFF_T startpos,
3005 size_t nread,
3006 ssize_t mincount)
3008 struct smbd_server_connection *sconn = req->sconn;
3009 char *outbuf = NULL;
3010 ssize_t ret=0;
3013 * We can only use sendfile on a non-chained packet
3014 * but we can use on a non-oplocked file. tridge proved this
3015 * on a train in Germany :-). JRA.
3016 * reply_readbraw has already checked the length.
3019 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3020 (fsp->wcp == NULL) &&
3021 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3022 ssize_t sendfile_read = -1;
3023 char header[4];
3024 DATA_BLOB header_blob;
3026 _smb_setlen(header,nread);
3027 header_blob = data_blob_const(header, 4);
3029 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3030 &header_blob, startpos,
3031 nread);
3032 if (sendfile_read == -1) {
3033 /* Returning ENOSYS means no data at all was sent.
3034 * Do this as a normal read. */
3035 if (errno == ENOSYS) {
3036 goto normal_readbraw;
3040 * Special hack for broken Linux with no working sendfile. If we
3041 * return EINTR we sent the header but not the rest of the data.
3042 * Fake this up by doing read/write calls.
3044 if (errno == EINTR) {
3045 /* Ensure we don't do this again. */
3046 set_use_sendfile(SNUM(conn), False);
3047 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3049 if (fake_sendfile(fsp, startpos, nread) == -1) {
3050 DEBUG(0,("send_file_readbraw: "
3051 "fake_sendfile failed for "
3052 "file %s (%s).\n",
3053 fsp_str_dbg(fsp),
3054 strerror(errno)));
3055 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3057 return;
3060 DEBUG(0,("send_file_readbraw: sendfile failed for "
3061 "file %s (%s). Terminating\n",
3062 fsp_str_dbg(fsp), strerror(errno)));
3063 exit_server_cleanly("send_file_readbraw sendfile failed");
3064 } else if (sendfile_read == 0) {
3066 * Some sendfile implementations return 0 to indicate
3067 * that there was a short read, but nothing was
3068 * actually written to the socket. In this case,
3069 * fallback to the normal read path so the header gets
3070 * the correct byte count.
3072 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3073 "bytes falling back to the normal read: "
3074 "%s\n", fsp_str_dbg(fsp)));
3075 goto normal_readbraw;
3078 /* Deal with possible short send. */
3079 if (sendfile_read != 4+nread) {
3080 sendfile_short_send(fsp, sendfile_read, 4, nread);
3082 return;
3085 normal_readbraw:
3087 outbuf = talloc_array(NULL, char, nread+4);
3088 if (!outbuf) {
3089 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3090 (unsigned)(nread+4)));
3091 reply_readbraw_error(sconn);
3092 return;
3095 if (nread > 0) {
3096 ret = read_file(fsp,outbuf+4,startpos,nread);
3097 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3098 if (ret < mincount)
3099 ret = 0;
3100 #else
3101 if (ret < nread)
3102 ret = 0;
3103 #endif
3106 _smb_setlen(outbuf,ret);
3107 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3108 char addr[INET6_ADDRSTRLEN];
3110 * Try and give an error message saying what
3111 * client failed.
3113 DEBUG(0, ("write_data failed for client %s. "
3114 "Error %s\n",
3115 get_peer_addr(fsp->conn->sconn->sock, addr,
3116 sizeof(addr)),
3117 strerror(errno)));
3119 fail_readraw();
3122 TALLOC_FREE(outbuf);
3125 /****************************************************************************
3126 Reply to a readbraw (core+ protocol).
3127 ****************************************************************************/
3129 void reply_readbraw(struct smb_request *req)
3131 connection_struct *conn = req->conn;
3132 struct smbd_server_connection *sconn = req->sconn;
3133 ssize_t maxcount,mincount;
3134 size_t nread = 0;
3135 SMB_OFF_T startpos;
3136 files_struct *fsp;
3137 struct lock_struct lock;
3138 SMB_OFF_T size = 0;
3140 START_PROFILE(SMBreadbraw);
3142 if (srv_is_signing_active(sconn) ||
3143 is_encrypted_packet(sconn, req->inbuf)) {
3144 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3145 "raw reads/writes are disallowed.");
3148 if (req->wct < 8) {
3149 reply_readbraw_error(sconn);
3150 END_PROFILE(SMBreadbraw);
3151 return;
3154 if (sconn->smb1.echo_handler.trusted_fde) {
3155 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3156 "'async smb echo handler = yes'\n"));
3157 reply_readbraw_error(sconn);
3158 END_PROFILE(SMBreadbraw);
3159 return;
3163 * Special check if an oplock break has been issued
3164 * and the readraw request croses on the wire, we must
3165 * return a zero length response here.
3168 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3171 * We have to do a check_fsp by hand here, as
3172 * we must always return 4 zero bytes on error,
3173 * not a NTSTATUS.
3176 if (!fsp || !conn || conn != fsp->conn ||
3177 req->vuid != fsp->vuid ||
3178 fsp->is_directory || fsp->fh->fd == -1) {
3180 * fsp could be NULL here so use the value from the packet. JRA.
3182 DEBUG(3,("reply_readbraw: fnum %d not valid "
3183 "- cache prime?\n",
3184 (int)SVAL(req->vwv+0, 0)));
3185 reply_readbraw_error(sconn);
3186 END_PROFILE(SMBreadbraw);
3187 return;
3190 /* Do a "by hand" version of CHECK_READ. */
3191 if (!(fsp->can_read ||
3192 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3193 (fsp->access_mask & FILE_EXECUTE)))) {
3194 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3195 (int)SVAL(req->vwv+0, 0)));
3196 reply_readbraw_error(sconn);
3197 END_PROFILE(SMBreadbraw);
3198 return;
3201 flush_write_cache(fsp, READRAW_FLUSH);
3203 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3204 if(req->wct == 10) {
3206 * This is a large offset (64 bit) read.
3208 #ifdef LARGE_SMB_OFF_T
3210 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3212 #else /* !LARGE_SMB_OFF_T */
3215 * Ensure we haven't been sent a >32 bit offset.
3218 if(IVAL(req->vwv+8, 0) != 0) {
3219 DEBUG(0,("reply_readbraw: large offset "
3220 "(%x << 32) used and we don't support "
3221 "64 bit offsets.\n",
3222 (unsigned int)IVAL(req->vwv+8, 0) ));
3223 reply_readbraw_error(sconn);
3224 END_PROFILE(SMBreadbraw);
3225 return;
3228 #endif /* LARGE_SMB_OFF_T */
3230 if(startpos < 0) {
3231 DEBUG(0,("reply_readbraw: negative 64 bit "
3232 "readraw offset (%.0f) !\n",
3233 (double)startpos ));
3234 reply_readbraw_error(sconn);
3235 END_PROFILE(SMBreadbraw);
3236 return;
3240 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3241 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3243 /* ensure we don't overrun the packet size */
3244 maxcount = MIN(65535,maxcount);
3246 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3247 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3248 &lock);
3250 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3251 reply_readbraw_error(sconn);
3252 END_PROFILE(SMBreadbraw);
3253 return;
3256 if (fsp_stat(fsp) == 0) {
3257 size = fsp->fsp_name->st.st_ex_size;
3260 if (startpos >= size) {
3261 nread = 0;
3262 } else {
3263 nread = MIN(maxcount,(size - startpos));
3266 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3267 if (nread < mincount)
3268 nread = 0;
3269 #endif
3271 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3272 "min=%lu nread=%lu\n",
3273 fsp->fnum, (double)startpos,
3274 (unsigned long)maxcount,
3275 (unsigned long)mincount,
3276 (unsigned long)nread ) );
3278 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3280 DEBUG(5,("reply_readbraw finished\n"));
3282 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3284 END_PROFILE(SMBreadbraw);
3285 return;
3288 #undef DBGC_CLASS
3289 #define DBGC_CLASS DBGC_LOCKING
3291 /****************************************************************************
3292 Reply to a lockread (core+ protocol).
3293 ****************************************************************************/
3295 void reply_lockread(struct smb_request *req)
3297 connection_struct *conn = req->conn;
3298 ssize_t nread = -1;
3299 char *data;
3300 SMB_OFF_T startpos;
3301 size_t numtoread;
3302 NTSTATUS status;
3303 files_struct *fsp;
3304 struct byte_range_lock *br_lck = NULL;
3305 char *p = NULL;
3306 struct smbd_server_connection *sconn = req->sconn;
3308 START_PROFILE(SMBlockread);
3310 if (req->wct < 5) {
3311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3312 END_PROFILE(SMBlockread);
3313 return;
3316 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3318 if (!check_fsp(conn, req, fsp)) {
3319 END_PROFILE(SMBlockread);
3320 return;
3323 if (!CHECK_READ(fsp,req)) {
3324 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3325 END_PROFILE(SMBlockread);
3326 return;
3329 numtoread = SVAL(req->vwv+1, 0);
3330 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3332 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3334 reply_outbuf(req, 5, numtoread + 3);
3336 data = smb_buf(req->outbuf) + 3;
3339 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3340 * protocol request that predates the read/write lock concept.
3341 * Thus instead of asking for a read lock here we need to ask
3342 * for a write lock. JRA.
3343 * Note that the requested lock size is unaffected by max_recv.
3346 br_lck = do_lock(req->sconn->msg_ctx,
3347 fsp,
3348 (uint64_t)req->smbpid,
3349 (uint64_t)numtoread,
3350 (uint64_t)startpos,
3351 WRITE_LOCK,
3352 WINDOWS_LOCK,
3353 False, /* Non-blocking lock. */
3354 &status,
3355 NULL,
3356 NULL);
3357 TALLOC_FREE(br_lck);
3359 if (NT_STATUS_V(status)) {
3360 reply_nterror(req, status);
3361 END_PROFILE(SMBlockread);
3362 return;
3366 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3369 if (numtoread > sconn->smb1.negprot.max_recv) {
3370 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3371 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3372 (unsigned int)numtoread,
3373 (unsigned int)sconn->smb1.negprot.max_recv));
3374 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3376 nread = read_file(fsp,data,startpos,numtoread);
3378 if (nread < 0) {
3379 reply_nterror(req, map_nt_error_from_unix(errno));
3380 END_PROFILE(SMBlockread);
3381 return;
3384 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3386 SSVAL(req->outbuf,smb_vwv0,nread);
3387 SSVAL(req->outbuf,smb_vwv5,nread+3);
3388 p = smb_buf(req->outbuf);
3389 SCVAL(p,0,0); /* pad byte. */
3390 SSVAL(p,1,nread);
3392 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3393 fsp->fnum, (int)numtoread, (int)nread));
3395 END_PROFILE(SMBlockread);
3396 return;
3399 #undef DBGC_CLASS
3400 #define DBGC_CLASS DBGC_ALL
3402 /****************************************************************************
3403 Reply to a read.
3404 ****************************************************************************/
3406 void reply_read(struct smb_request *req)
3408 connection_struct *conn = req->conn;
3409 size_t numtoread;
3410 ssize_t nread = 0;
3411 char *data;
3412 SMB_OFF_T startpos;
3413 int outsize = 0;
3414 files_struct *fsp;
3415 struct lock_struct lock;
3416 struct smbd_server_connection *sconn = req->sconn;
3418 START_PROFILE(SMBread);
3420 if (req->wct < 3) {
3421 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3422 END_PROFILE(SMBread);
3423 return;
3426 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3428 if (!check_fsp(conn, req, fsp)) {
3429 END_PROFILE(SMBread);
3430 return;
3433 if (!CHECK_READ(fsp,req)) {
3434 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3435 END_PROFILE(SMBread);
3436 return;
3439 numtoread = SVAL(req->vwv+1, 0);
3440 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3442 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3445 * The requested read size cannot be greater than max_recv. JRA.
3447 if (numtoread > sconn->smb1.negprot.max_recv) {
3448 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3449 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3450 (unsigned int)numtoread,
3451 (unsigned int)sconn->smb1.negprot.max_recv));
3452 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3455 reply_outbuf(req, 5, numtoread+3);
3457 data = smb_buf(req->outbuf) + 3;
3459 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3460 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3461 &lock);
3463 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3464 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3465 END_PROFILE(SMBread);
3466 return;
3469 if (numtoread > 0)
3470 nread = read_file(fsp,data,startpos,numtoread);
3472 if (nread < 0) {
3473 reply_nterror(req, map_nt_error_from_unix(errno));
3474 goto strict_unlock;
3477 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3479 SSVAL(req->outbuf,smb_vwv0,nread);
3480 SSVAL(req->outbuf,smb_vwv5,nread+3);
3481 SCVAL(smb_buf(req->outbuf),0,1);
3482 SSVAL(smb_buf(req->outbuf),1,nread);
3484 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3485 fsp->fnum, (int)numtoread, (int)nread ) );
3487 strict_unlock:
3488 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3490 END_PROFILE(SMBread);
3491 return;
3494 /****************************************************************************
3495 Setup readX header.
3496 ****************************************************************************/
3498 static int setup_readX_header(struct smb_request *req, char *outbuf,
3499 size_t smb_maxcnt)
3501 int outsize;
3503 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3505 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3507 SCVAL(outbuf,smb_vwv0,0xFF);
3508 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3509 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3510 SSVAL(outbuf,smb_vwv6,
3511 (smb_wct - 4) /* offset from smb header to wct */
3512 + 1 /* the wct field */
3513 + 12 * sizeof(uint16_t) /* vwv */
3514 + 2); /* the buflen field */
3515 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3516 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3517 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3518 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3519 return outsize;
3522 /****************************************************************************
3523 Reply to a read and X - possibly using sendfile.
3524 ****************************************************************************/
3526 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3527 files_struct *fsp, SMB_OFF_T startpos,
3528 size_t smb_maxcnt)
3530 ssize_t nread = -1;
3531 struct lock_struct lock;
3532 int saved_errno = 0;
3534 if(fsp_stat(fsp) == -1) {
3535 reply_nterror(req, map_nt_error_from_unix(errno));
3536 return;
3539 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3540 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3541 &lock);
3543 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3544 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3545 return;
3548 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3549 (startpos > fsp->fsp_name->st.st_ex_size)
3550 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3552 * We already know that we would do a short read, so don't
3553 * try the sendfile() path.
3555 goto nosendfile_read;
3559 * We can only use sendfile on a non-chained packet
3560 * but we can use on a non-oplocked file. tridge proved this
3561 * on a train in Germany :-). JRA.
3564 if (!req_is_in_chain(req) &&
3565 !is_encrypted_packet(req->sconn, req->inbuf) &&
3566 (fsp->base_fsp == NULL) &&
3567 (fsp->wcp == NULL) &&
3568 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3569 uint8 headerbuf[smb_size + 12 * 2];
3570 DATA_BLOB header;
3573 * Set up the packet header before send. We
3574 * assume here the sendfile will work (get the
3575 * correct amount of data).
3578 header = data_blob_const(headerbuf, sizeof(headerbuf));
3580 construct_reply_common_req(req, (char *)headerbuf);
3581 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3583 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3584 startpos, smb_maxcnt);
3585 if (nread == -1) {
3586 /* Returning ENOSYS means no data at all was sent.
3587 Do this as a normal read. */
3588 if (errno == ENOSYS) {
3589 goto normal_read;
3593 * Special hack for broken Linux with no working sendfile. If we
3594 * return EINTR we sent the header but not the rest of the data.
3595 * Fake this up by doing read/write calls.
3598 if (errno == EINTR) {
3599 /* Ensure we don't do this again. */
3600 set_use_sendfile(SNUM(conn), False);
3601 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3602 nread = fake_sendfile(fsp, startpos,
3603 smb_maxcnt);
3604 if (nread == -1) {
3605 DEBUG(0,("send_file_readX: "
3606 "fake_sendfile failed for "
3607 "file %s (%s).\n",
3608 fsp_str_dbg(fsp),
3609 strerror(errno)));
3610 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3612 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3613 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3614 /* No outbuf here means successful sendfile. */
3615 goto strict_unlock;
3618 DEBUG(0,("send_file_readX: sendfile failed for file "
3619 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3620 strerror(errno)));
3621 exit_server_cleanly("send_file_readX sendfile failed");
3622 } else if (nread == 0) {
3624 * Some sendfile implementations return 0 to indicate
3625 * that there was a short read, but nothing was
3626 * actually written to the socket. In this case,
3627 * fallback to the normal read path so the header gets
3628 * the correct byte count.
3630 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3631 "falling back to the normal read: %s\n",
3632 fsp_str_dbg(fsp)));
3633 goto normal_read;
3636 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3637 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3639 /* Deal with possible short send. */
3640 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3641 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3643 /* No outbuf here means successful sendfile. */
3644 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3645 SMB_PERFCOUNT_END(&req->pcd);
3646 goto strict_unlock;
3649 normal_read:
3651 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3652 uint8 headerbuf[smb_size + 2*12];
3654 construct_reply_common_req(req, (char *)headerbuf);
3655 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3657 /* Send out the header. */
3658 if (write_data(req->sconn->sock, (char *)headerbuf,
3659 sizeof(headerbuf)) != sizeof(headerbuf)) {
3661 char addr[INET6_ADDRSTRLEN];
3663 * Try and give an error message saying what
3664 * client failed.
3666 DEBUG(0, ("write_data failed for client %s. "
3667 "Error %s\n",
3668 get_peer_addr(req->sconn->sock, addr,
3669 sizeof(addr)),
3670 strerror(errno)));
3672 DEBUG(0,("send_file_readX: write_data failed for file "
3673 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3674 strerror(errno)));
3675 exit_server_cleanly("send_file_readX sendfile failed");
3677 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3678 if (nread == -1) {
3679 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3680 "file %s (%s).\n", fsp_str_dbg(fsp),
3681 strerror(errno)));
3682 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3684 goto strict_unlock;
3687 nosendfile_read:
3689 reply_outbuf(req, 12, smb_maxcnt);
3690 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3691 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3693 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3694 saved_errno = errno;
3696 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3698 if (nread < 0) {
3699 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3700 return;
3703 setup_readX_header(req, (char *)req->outbuf, nread);
3705 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3706 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3707 return;
3709 strict_unlock:
3710 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3711 TALLOC_FREE(req->outbuf);
3712 return;
3715 /****************************************************************************
3716 Reply to a read and X.
3717 ****************************************************************************/
3719 void reply_read_and_X(struct smb_request *req)
3721 struct smbd_server_connection *sconn = req->sconn;
3722 connection_struct *conn = req->conn;
3723 files_struct *fsp;
3724 SMB_OFF_T startpos;
3725 size_t smb_maxcnt;
3726 bool big_readX = False;
3727 #if 0
3728 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3729 #endif
3731 START_PROFILE(SMBreadX);
3733 if ((req->wct != 10) && (req->wct != 12)) {
3734 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3735 return;
3738 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3739 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3740 smb_maxcnt = SVAL(req->vwv+5, 0);
3742 /* If it's an IPC, pass off the pipe handler. */
3743 if (IS_IPC(conn)) {
3744 reply_pipe_read_and_X(req);
3745 END_PROFILE(SMBreadX);
3746 return;
3749 if (!check_fsp(conn, req, fsp)) {
3750 END_PROFILE(SMBreadX);
3751 return;
3754 if (!CHECK_READ(fsp,req)) {
3755 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3756 END_PROFILE(SMBreadX);
3757 return;
3760 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3761 (get_remote_arch() == RA_SAMBA)) {
3763 * This is Samba only behavior (up to Samba 3.6)!
3765 * Windows 2008 R2 ignores the upper_size,
3766 * so we do unless unix extentions are active
3767 * or "smbclient" is talking to us.
3769 size_t upper_size = SVAL(req->vwv+7, 0);
3770 smb_maxcnt |= (upper_size<<16);
3771 if (upper_size > 1) {
3772 /* Can't do this on a chained packet. */
3773 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3774 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3775 END_PROFILE(SMBreadX);
3776 return;
3778 /* We currently don't do this on signed or sealed data. */
3779 if (srv_is_signing_active(req->sconn) ||
3780 is_encrypted_packet(req->sconn, req->inbuf)) {
3781 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3782 END_PROFILE(SMBreadX);
3783 return;
3785 /* Is there room in the reply for this data ? */
3786 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3787 reply_nterror(req,
3788 NT_STATUS_INVALID_PARAMETER);
3789 END_PROFILE(SMBreadX);
3790 return;
3792 big_readX = True;
3796 if (req->wct == 12) {
3797 #ifdef LARGE_SMB_OFF_T
3799 * This is a large offset (64 bit) read.
3801 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3803 #else /* !LARGE_SMB_OFF_T */
3806 * Ensure we haven't been sent a >32 bit offset.
3809 if(IVAL(req->vwv+10, 0) != 0) {
3810 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3811 "used and we don't support 64 bit offsets.\n",
3812 (unsigned int)IVAL(req->vwv+10, 0) ));
3813 END_PROFILE(SMBreadX);
3814 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3815 return;
3818 #endif /* LARGE_SMB_OFF_T */
3822 if (!big_readX) {
3823 NTSTATUS status = schedule_aio_read_and_X(conn,
3824 req,
3825 fsp,
3826 startpos,
3827 smb_maxcnt);
3828 if (NT_STATUS_IS_OK(status)) {
3829 /* Read scheduled - we're done. */
3830 goto out;
3832 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3833 /* Real error - report to client. */
3834 END_PROFILE(SMBreadX);
3835 reply_nterror(req, status);
3836 return;
3838 /* NT_STATUS_RETRY - fall back to sync read. */
3841 smbd_lock_socket(req->sconn);
3842 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3843 smbd_unlock_socket(req->sconn);
3845 out:
3846 END_PROFILE(SMBreadX);
3847 return;
3850 /****************************************************************************
3851 Error replies to writebraw must have smb_wct == 1. Fix this up.
3852 ****************************************************************************/
3854 void error_to_writebrawerr(struct smb_request *req)
3856 uint8 *old_outbuf = req->outbuf;
3858 reply_outbuf(req, 1, 0);
3860 memcpy(req->outbuf, old_outbuf, smb_size);
3861 TALLOC_FREE(old_outbuf);
3864 /****************************************************************************
3865 Read 4 bytes of a smb packet and return the smb length of the packet.
3866 Store the result in the buffer. This version of the function will
3867 never return a session keepalive (length of zero).
3868 Timeout is in milliseconds.
3869 ****************************************************************************/
3871 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3872 size_t *len)
3874 uint8_t msgtype = NBSSkeepalive;
3876 while (msgtype == NBSSkeepalive) {
3877 NTSTATUS status;
3879 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3880 len);
3881 if (!NT_STATUS_IS_OK(status)) {
3882 char addr[INET6_ADDRSTRLEN];
3883 /* Try and give an error message
3884 * saying what client failed. */
3885 DEBUG(0, ("read_fd_with_timeout failed for "
3886 "client %s read error = %s.\n",
3887 get_peer_addr(fd,addr,sizeof(addr)),
3888 nt_errstr(status)));
3889 return status;
3892 msgtype = CVAL(inbuf, 0);
3895 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3896 (unsigned long)len));
3898 return NT_STATUS_OK;
3901 /****************************************************************************
3902 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3903 ****************************************************************************/
3905 void reply_writebraw(struct smb_request *req)
3907 connection_struct *conn = req->conn;
3908 char *buf = NULL;
3909 ssize_t nwritten=0;
3910 ssize_t total_written=0;
3911 size_t numtowrite=0;
3912 size_t tcount;
3913 SMB_OFF_T startpos;
3914 const char *data=NULL;
3915 bool write_through;
3916 files_struct *fsp;
3917 struct lock_struct lock;
3918 NTSTATUS status;
3920 START_PROFILE(SMBwritebraw);
3923 * If we ever reply with an error, it must have the SMB command
3924 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3925 * we're finished.
3927 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3929 if (srv_is_signing_active(req->sconn)) {
3930 END_PROFILE(SMBwritebraw);
3931 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3932 "raw reads/writes are disallowed.");
3935 if (req->wct < 12) {
3936 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3937 error_to_writebrawerr(req);
3938 END_PROFILE(SMBwritebraw);
3939 return;
3942 if (req->sconn->smb1.echo_handler.trusted_fde) {
3943 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3944 "'async smb echo handler = yes'\n"));
3945 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3946 error_to_writebrawerr(req);
3947 END_PROFILE(SMBwritebraw);
3948 return;
3951 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3952 if (!check_fsp(conn, req, fsp)) {
3953 error_to_writebrawerr(req);
3954 END_PROFILE(SMBwritebraw);
3955 return;
3958 if (!CHECK_WRITE(fsp)) {
3959 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3960 error_to_writebrawerr(req);
3961 END_PROFILE(SMBwritebraw);
3962 return;
3965 tcount = IVAL(req->vwv+1, 0);
3966 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3967 write_through = BITSETW(req->vwv+7,0);
3969 /* We have to deal with slightly different formats depending
3970 on whether we are using the core+ or lanman1.0 protocol */
3972 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3973 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3974 data = smb_buf_const(req->inbuf);
3975 } else {
3976 numtowrite = SVAL(req->vwv+10, 0);
3977 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3980 /* Ensure we don't write bytes past the end of this packet. */
3981 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3983 error_to_writebrawerr(req);
3984 END_PROFILE(SMBwritebraw);
3985 return;
3988 if (!fsp->print_file) {
3989 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3990 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3991 &lock);
3993 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3994 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3995 error_to_writebrawerr(req);
3996 END_PROFILE(SMBwritebraw);
3997 return;
4001 if (numtowrite>0) {
4002 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4005 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4006 "wrote=%d sync=%d\n",
4007 fsp->fnum, (double)startpos, (int)numtowrite,
4008 (int)nwritten, (int)write_through));
4010 if (nwritten < (ssize_t)numtowrite) {
4011 reply_nterror(req, NT_STATUS_DISK_FULL);
4012 error_to_writebrawerr(req);
4013 goto strict_unlock;
4016 total_written = nwritten;
4018 /* Allocate a buffer of 64k + length. */
4019 buf = talloc_array(NULL, char, 65540);
4020 if (!buf) {
4021 reply_nterror(req, NT_STATUS_NO_MEMORY);
4022 error_to_writebrawerr(req);
4023 goto strict_unlock;
4026 /* Return a SMBwritebraw message to the redirector to tell
4027 * it to send more bytes */
4029 memcpy(buf, req->inbuf, smb_size);
4030 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4031 SCVAL(buf,smb_com,SMBwritebraw);
4032 SSVALS(buf,smb_vwv0,0xFFFF);
4033 show_msg(buf);
4034 if (!srv_send_smb(req->sconn,
4035 buf,
4036 false, 0, /* no signing */
4037 IS_CONN_ENCRYPTED(conn),
4038 &req->pcd)) {
4039 exit_server_cleanly("reply_writebraw: srv_send_smb "
4040 "failed.");
4043 /* Now read the raw data into the buffer and write it */
4044 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4045 &numtowrite);
4046 if (!NT_STATUS_IS_OK(status)) {
4047 exit_server_cleanly("secondary writebraw failed");
4050 /* Set up outbuf to return the correct size */
4051 reply_outbuf(req, 1, 0);
4053 if (numtowrite != 0) {
4055 if (numtowrite > 0xFFFF) {
4056 DEBUG(0,("reply_writebraw: Oversize secondary write "
4057 "raw requested (%u). Terminating\n",
4058 (unsigned int)numtowrite ));
4059 exit_server_cleanly("secondary writebraw failed");
4062 if (tcount > nwritten+numtowrite) {
4063 DEBUG(3,("reply_writebraw: Client overestimated the "
4064 "write %d %d %d\n",
4065 (int)tcount,(int)nwritten,(int)numtowrite));
4068 status = read_data(req->sconn->sock, buf+4, numtowrite);
4070 if (!NT_STATUS_IS_OK(status)) {
4071 char addr[INET6_ADDRSTRLEN];
4072 /* Try and give an error message
4073 * saying what client failed. */
4074 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4075 "raw read failed (%s) for client %s. "
4076 "Terminating\n", nt_errstr(status),
4077 get_peer_addr(req->sconn->sock, addr,
4078 sizeof(addr))));
4079 exit_server_cleanly("secondary writebraw failed");
4082 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4083 if (nwritten == -1) {
4084 TALLOC_FREE(buf);
4085 reply_nterror(req, map_nt_error_from_unix(errno));
4086 error_to_writebrawerr(req);
4087 goto strict_unlock;
4090 if (nwritten < (ssize_t)numtowrite) {
4091 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4092 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4095 if (nwritten > 0) {
4096 total_written += nwritten;
4100 TALLOC_FREE(buf);
4101 SSVAL(req->outbuf,smb_vwv0,total_written);
4103 status = sync_file(conn, fsp, write_through);
4104 if (!NT_STATUS_IS_OK(status)) {
4105 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4106 fsp_str_dbg(fsp), nt_errstr(status)));
4107 reply_nterror(req, status);
4108 error_to_writebrawerr(req);
4109 goto strict_unlock;
4112 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4113 "wrote=%d\n",
4114 fsp->fnum, (double)startpos, (int)numtowrite,
4115 (int)total_written));
4117 if (!fsp->print_file) {
4118 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4121 /* We won't return a status if write through is not selected - this
4122 * follows what WfWg does */
4123 END_PROFILE(SMBwritebraw);
4125 if (!write_through && total_written==tcount) {
4127 #if RABBIT_PELLET_FIX
4129 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4130 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4131 * JRA.
4133 if (!send_keepalive(req->sconn->sock)) {
4134 exit_server_cleanly("reply_writebraw: send of "
4135 "keepalive failed");
4137 #endif
4138 TALLOC_FREE(req->outbuf);
4140 return;
4142 strict_unlock:
4143 if (!fsp->print_file) {
4144 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4147 END_PROFILE(SMBwritebraw);
4148 return;
4151 #undef DBGC_CLASS
4152 #define DBGC_CLASS DBGC_LOCKING
4154 /****************************************************************************
4155 Reply to a writeunlock (core+).
4156 ****************************************************************************/
4158 void reply_writeunlock(struct smb_request *req)
4160 connection_struct *conn = req->conn;
4161 ssize_t nwritten = -1;
4162 size_t numtowrite;
4163 SMB_OFF_T startpos;
4164 const char *data;
4165 NTSTATUS status = NT_STATUS_OK;
4166 files_struct *fsp;
4167 struct lock_struct lock;
4168 int saved_errno = 0;
4170 START_PROFILE(SMBwriteunlock);
4172 if (req->wct < 5) {
4173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4174 END_PROFILE(SMBwriteunlock);
4175 return;
4178 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4180 if (!check_fsp(conn, req, fsp)) {
4181 END_PROFILE(SMBwriteunlock);
4182 return;
4185 if (!CHECK_WRITE(fsp)) {
4186 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4187 END_PROFILE(SMBwriteunlock);
4188 return;
4191 numtowrite = SVAL(req->vwv+1, 0);
4192 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4193 data = (const char *)req->buf + 3;
4195 if (!fsp->print_file && numtowrite > 0) {
4196 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4197 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4198 &lock);
4200 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4201 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4202 END_PROFILE(SMBwriteunlock);
4203 return;
4207 /* The special X/Open SMB protocol handling of
4208 zero length writes is *NOT* done for
4209 this call */
4210 if(numtowrite == 0) {
4211 nwritten = 0;
4212 } else {
4213 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4214 saved_errno = errno;
4217 status = sync_file(conn, fsp, False /* write through */);
4218 if (!NT_STATUS_IS_OK(status)) {
4219 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4220 fsp_str_dbg(fsp), nt_errstr(status)));
4221 reply_nterror(req, status);
4222 goto strict_unlock;
4225 if(nwritten < 0) {
4226 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4227 goto strict_unlock;
4230 if((nwritten < numtowrite) && (numtowrite != 0)) {
4231 reply_nterror(req, NT_STATUS_DISK_FULL);
4232 goto strict_unlock;
4235 if (numtowrite && !fsp->print_file) {
4236 status = do_unlock(req->sconn->msg_ctx,
4237 fsp,
4238 (uint64_t)req->smbpid,
4239 (uint64_t)numtowrite,
4240 (uint64_t)startpos,
4241 WINDOWS_LOCK);
4243 if (NT_STATUS_V(status)) {
4244 reply_nterror(req, status);
4245 goto strict_unlock;
4249 reply_outbuf(req, 1, 0);
4251 SSVAL(req->outbuf,smb_vwv0,nwritten);
4253 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4254 fsp->fnum, (int)numtowrite, (int)nwritten));
4256 strict_unlock:
4257 if (numtowrite && !fsp->print_file) {
4258 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4261 END_PROFILE(SMBwriteunlock);
4262 return;
4265 #undef DBGC_CLASS
4266 #define DBGC_CLASS DBGC_ALL
4268 /****************************************************************************
4269 Reply to a write.
4270 ****************************************************************************/
4272 void reply_write(struct smb_request *req)
4274 connection_struct *conn = req->conn;
4275 size_t numtowrite;
4276 ssize_t nwritten = -1;
4277 SMB_OFF_T startpos;
4278 const char *data;
4279 files_struct *fsp;
4280 struct lock_struct lock;
4281 NTSTATUS status;
4282 int saved_errno = 0;
4284 START_PROFILE(SMBwrite);
4286 if (req->wct < 5) {
4287 END_PROFILE(SMBwrite);
4288 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4289 return;
4292 /* If it's an IPC, pass off the pipe handler. */
4293 if (IS_IPC(conn)) {
4294 reply_pipe_write(req);
4295 END_PROFILE(SMBwrite);
4296 return;
4299 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4301 if (!check_fsp(conn, req, fsp)) {
4302 END_PROFILE(SMBwrite);
4303 return;
4306 if (!CHECK_WRITE(fsp)) {
4307 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4308 END_PROFILE(SMBwrite);
4309 return;
4312 numtowrite = SVAL(req->vwv+1, 0);
4313 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4314 data = (const char *)req->buf + 3;
4316 if (!fsp->print_file) {
4317 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4318 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4319 &lock);
4321 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4322 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4323 END_PROFILE(SMBwrite);
4324 return;
4329 * X/Open SMB protocol says that if smb_vwv1 is
4330 * zero then the file size should be extended or
4331 * truncated to the size given in smb_vwv[2-3].
4334 if(numtowrite == 0) {
4336 * This is actually an allocate call, and set EOF. JRA.
4338 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4339 if (nwritten < 0) {
4340 reply_nterror(req, NT_STATUS_DISK_FULL);
4341 goto strict_unlock;
4343 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4344 if (nwritten < 0) {
4345 reply_nterror(req, NT_STATUS_DISK_FULL);
4346 goto strict_unlock;
4348 trigger_write_time_update_immediate(fsp);
4349 } else {
4350 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4353 status = sync_file(conn, fsp, False);
4354 if (!NT_STATUS_IS_OK(status)) {
4355 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4356 fsp_str_dbg(fsp), nt_errstr(status)));
4357 reply_nterror(req, status);
4358 goto strict_unlock;
4361 if(nwritten < 0) {
4362 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4363 goto strict_unlock;
4366 if((nwritten == 0) && (numtowrite != 0)) {
4367 reply_nterror(req, NT_STATUS_DISK_FULL);
4368 goto strict_unlock;
4371 reply_outbuf(req, 1, 0);
4373 SSVAL(req->outbuf,smb_vwv0,nwritten);
4375 if (nwritten < (ssize_t)numtowrite) {
4376 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4377 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4380 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4382 strict_unlock:
4383 if (!fsp->print_file) {
4384 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4387 END_PROFILE(SMBwrite);
4388 return;
4391 /****************************************************************************
4392 Ensure a buffer is a valid writeX for recvfile purposes.
4393 ****************************************************************************/
4395 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4396 (2*14) + /* word count (including bcc) */ \
4397 1 /* pad byte */)
4399 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4400 const uint8_t *inbuf)
4402 size_t numtowrite;
4403 connection_struct *conn = NULL;
4404 unsigned int doff = 0;
4405 size_t len = smb_len_large(inbuf);
4407 if (is_encrypted_packet(sconn, inbuf)) {
4408 /* Can't do this on encrypted
4409 * connections. */
4410 return false;
4413 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4414 return false;
4417 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4418 CVAL(inbuf,smb_wct) != 14) {
4419 DEBUG(10,("is_valid_writeX_buffer: chained or "
4420 "invalid word length.\n"));
4421 return false;
4424 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4425 if (conn == NULL) {
4426 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4427 return false;
4429 if (IS_IPC(conn)) {
4430 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4431 return false;
4433 if (IS_PRINT(conn)) {
4434 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4435 return false;
4437 doff = SVAL(inbuf,smb_vwv11);
4439 numtowrite = SVAL(inbuf,smb_vwv10);
4441 if (len > doff && len - doff > 0xFFFF) {
4442 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4445 if (numtowrite == 0) {
4446 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4447 return false;
4450 /* Ensure the sizes match up. */
4451 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4452 /* no pad byte...old smbclient :-( */
4453 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4454 (unsigned int)doff,
4455 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4456 return false;
4459 if (len - doff != numtowrite) {
4460 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4461 "len = %u, doff = %u, numtowrite = %u\n",
4462 (unsigned int)len,
4463 (unsigned int)doff,
4464 (unsigned int)numtowrite ));
4465 return false;
4468 DEBUG(10,("is_valid_writeX_buffer: true "
4469 "len = %u, doff = %u, numtowrite = %u\n",
4470 (unsigned int)len,
4471 (unsigned int)doff,
4472 (unsigned int)numtowrite ));
4474 return true;
4477 /****************************************************************************
4478 Reply to a write and X.
4479 ****************************************************************************/
4481 void reply_write_and_X(struct smb_request *req)
4483 connection_struct *conn = req->conn;
4484 files_struct *fsp;
4485 struct lock_struct lock;
4486 SMB_OFF_T startpos;
4487 size_t numtowrite;
4488 bool write_through;
4489 ssize_t nwritten;
4490 unsigned int smb_doff;
4491 unsigned int smblen;
4492 const char *data;
4493 NTSTATUS status;
4494 int saved_errno = 0;
4496 START_PROFILE(SMBwriteX);
4498 if ((req->wct != 12) && (req->wct != 14)) {
4499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4500 goto out;
4503 numtowrite = SVAL(req->vwv+10, 0);
4504 smb_doff = SVAL(req->vwv+11, 0);
4505 smblen = smb_len(req->inbuf);
4507 if (req->unread_bytes > 0xFFFF ||
4508 (smblen > smb_doff &&
4509 smblen - smb_doff > 0xFFFF)) {
4510 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4513 if (req->unread_bytes) {
4514 /* Can't do a recvfile write on IPC$ */
4515 if (IS_IPC(conn)) {
4516 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4517 goto out;
4519 if (numtowrite != req->unread_bytes) {
4520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4521 goto out;
4523 } else {
4524 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4525 smb_doff + numtowrite > smblen) {
4526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4527 goto out;
4531 /* If it's an IPC, pass off the pipe handler. */
4532 if (IS_IPC(conn)) {
4533 if (req->unread_bytes) {
4534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4535 goto out;
4537 reply_pipe_write_and_X(req);
4538 goto out;
4541 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4542 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4543 write_through = BITSETW(req->vwv+7,0);
4545 if (!check_fsp(conn, req, fsp)) {
4546 goto out;
4549 if (!CHECK_WRITE(fsp)) {
4550 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4551 goto out;
4554 data = smb_base(req->inbuf) + smb_doff;
4556 if(req->wct == 14) {
4557 #ifdef LARGE_SMB_OFF_T
4559 * This is a large offset (64 bit) write.
4561 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4563 #else /* !LARGE_SMB_OFF_T */
4566 * Ensure we haven't been sent a >32 bit offset.
4569 if(IVAL(req->vwv+12, 0) != 0) {
4570 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4571 "used and we don't support 64 bit offsets.\n",
4572 (unsigned int)IVAL(req->vwv+12, 0) ));
4573 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4574 goto out;
4577 #endif /* LARGE_SMB_OFF_T */
4580 /* X/Open SMB protocol says that, unlike SMBwrite
4581 if the length is zero then NO truncation is
4582 done, just a write of zero. To truncate a file,
4583 use SMBwrite. */
4585 if(numtowrite == 0) {
4586 nwritten = 0;
4587 } else {
4588 if (req->unread_bytes == 0) {
4589 status = schedule_aio_write_and_X(conn,
4590 req,
4591 fsp,
4592 data,
4593 startpos,
4594 numtowrite);
4596 if (NT_STATUS_IS_OK(status)) {
4597 /* write scheduled - we're done. */
4598 goto out;
4600 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4601 /* Real error - report to client. */
4602 reply_nterror(req, status);
4603 goto out;
4605 /* NT_STATUS_RETRY - fall through to sync write. */
4608 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4609 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4610 &lock);
4612 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4613 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4614 goto out;
4617 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4618 saved_errno = errno;
4620 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4623 if(nwritten < 0) {
4624 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4625 goto out;
4628 if((nwritten == 0) && (numtowrite != 0)) {
4629 reply_nterror(req, NT_STATUS_DISK_FULL);
4630 goto out;
4633 reply_outbuf(req, 6, 0);
4634 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4635 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4636 SSVAL(req->outbuf,smb_vwv2,nwritten);
4637 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4639 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4640 fsp->fnum, (int)numtowrite, (int)nwritten));
4642 status = sync_file(conn, fsp, write_through);
4643 if (!NT_STATUS_IS_OK(status)) {
4644 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4645 fsp_str_dbg(fsp), nt_errstr(status)));
4646 reply_nterror(req, status);
4647 goto out;
4650 END_PROFILE(SMBwriteX);
4651 return;
4653 out:
4654 if (req->unread_bytes) {
4655 /* writeX failed. drain socket. */
4656 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
4657 req->unread_bytes) {
4658 smb_panic("failed to drain pending bytes");
4660 req->unread_bytes = 0;
4663 END_PROFILE(SMBwriteX);
4664 return;
4667 /****************************************************************************
4668 Reply to a lseek.
4669 ****************************************************************************/
4671 void reply_lseek(struct smb_request *req)
4673 connection_struct *conn = req->conn;
4674 SMB_OFF_T startpos;
4675 SMB_OFF_T res= -1;
4676 int mode,umode;
4677 files_struct *fsp;
4679 START_PROFILE(SMBlseek);
4681 if (req->wct < 4) {
4682 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4683 END_PROFILE(SMBlseek);
4684 return;
4687 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4689 if (!check_fsp(conn, req, fsp)) {
4690 return;
4693 flush_write_cache(fsp, SEEK_FLUSH);
4695 mode = SVAL(req->vwv+1, 0) & 3;
4696 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4697 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4699 switch (mode) {
4700 case 0:
4701 umode = SEEK_SET;
4702 res = startpos;
4703 break;
4704 case 1:
4705 umode = SEEK_CUR;
4706 res = fsp->fh->pos + startpos;
4707 break;
4708 case 2:
4709 umode = SEEK_END;
4710 break;
4711 default:
4712 umode = SEEK_SET;
4713 res = startpos;
4714 break;
4717 if (umode == SEEK_END) {
4718 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4719 if(errno == EINVAL) {
4720 SMB_OFF_T current_pos = startpos;
4722 if(fsp_stat(fsp) == -1) {
4723 reply_nterror(req,
4724 map_nt_error_from_unix(errno));
4725 END_PROFILE(SMBlseek);
4726 return;
4729 current_pos += fsp->fsp_name->st.st_ex_size;
4730 if(current_pos < 0)
4731 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4735 if(res == -1) {
4736 reply_nterror(req, map_nt_error_from_unix(errno));
4737 END_PROFILE(SMBlseek);
4738 return;
4742 fsp->fh->pos = res;
4744 reply_outbuf(req, 2, 0);
4745 SIVAL(req->outbuf,smb_vwv0,res);
4747 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4748 fsp->fnum, (double)startpos, (double)res, mode));
4750 END_PROFILE(SMBlseek);
4751 return;
4754 /****************************************************************************
4755 Reply to a flush.
4756 ****************************************************************************/
4758 void reply_flush(struct smb_request *req)
4760 connection_struct *conn = req->conn;
4761 uint16 fnum;
4762 files_struct *fsp;
4764 START_PROFILE(SMBflush);
4766 if (req->wct < 1) {
4767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4768 return;
4771 fnum = SVAL(req->vwv+0, 0);
4772 fsp = file_fsp(req, fnum);
4774 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4775 return;
4778 if (!fsp) {
4779 file_sync_all(conn);
4780 } else {
4781 NTSTATUS status = sync_file(conn, fsp, True);
4782 if (!NT_STATUS_IS_OK(status)) {
4783 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4784 fsp_str_dbg(fsp), nt_errstr(status)));
4785 reply_nterror(req, status);
4786 END_PROFILE(SMBflush);
4787 return;
4791 reply_outbuf(req, 0, 0);
4793 DEBUG(3,("flush\n"));
4794 END_PROFILE(SMBflush);
4795 return;
4798 /****************************************************************************
4799 Reply to a exit.
4800 conn POINTER CAN BE NULL HERE !
4801 ****************************************************************************/
4803 void reply_exit(struct smb_request *req)
4805 START_PROFILE(SMBexit);
4807 file_close_pid(req->sconn, req->smbpid, req->vuid);
4809 reply_outbuf(req, 0, 0);
4811 DEBUG(3,("exit\n"));
4813 END_PROFILE(SMBexit);
4814 return;
4817 /****************************************************************************
4818 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4819 ****************************************************************************/
4821 void reply_close(struct smb_request *req)
4823 connection_struct *conn = req->conn;
4824 NTSTATUS status = NT_STATUS_OK;
4825 files_struct *fsp = NULL;
4826 START_PROFILE(SMBclose);
4828 if (req->wct < 3) {
4829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4830 END_PROFILE(SMBclose);
4831 return;
4834 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4837 * We can only use check_fsp if we know it's not a directory.
4840 if (!check_fsp_open(conn, req, fsp)) {
4841 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4842 END_PROFILE(SMBclose);
4843 return;
4846 if(fsp->is_directory) {
4848 * Special case - close NT SMB directory handle.
4850 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4851 status = close_file(req, fsp, NORMAL_CLOSE);
4852 } else {
4853 time_t t;
4855 * Close ordinary file.
4858 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4859 fsp->fh->fd, fsp->fnum,
4860 conn->num_files_open));
4863 * Take care of any time sent in the close.
4866 t = srv_make_unix_date3(req->vwv+1);
4867 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4870 * close_file() returns the unix errno if an error
4871 * was detected on close - normally this is due to
4872 * a disk full error. If not then it was probably an I/O error.
4875 status = close_file(req, fsp, NORMAL_CLOSE);
4878 if (!NT_STATUS_IS_OK(status)) {
4879 reply_nterror(req, status);
4880 END_PROFILE(SMBclose);
4881 return;
4884 reply_outbuf(req, 0, 0);
4885 END_PROFILE(SMBclose);
4886 return;
4889 /****************************************************************************
4890 Reply to a writeclose (Core+ protocol).
4891 ****************************************************************************/
4893 void reply_writeclose(struct smb_request *req)
4895 connection_struct *conn = req->conn;
4896 size_t numtowrite;
4897 ssize_t nwritten = -1;
4898 NTSTATUS close_status = NT_STATUS_OK;
4899 SMB_OFF_T startpos;
4900 const char *data;
4901 struct timespec mtime;
4902 files_struct *fsp;
4903 struct lock_struct lock;
4905 START_PROFILE(SMBwriteclose);
4907 if (req->wct < 6) {
4908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4909 END_PROFILE(SMBwriteclose);
4910 return;
4913 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4915 if (!check_fsp(conn, req, fsp)) {
4916 END_PROFILE(SMBwriteclose);
4917 return;
4919 if (!CHECK_WRITE(fsp)) {
4920 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4921 END_PROFILE(SMBwriteclose);
4922 return;
4925 numtowrite = SVAL(req->vwv+1, 0);
4926 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4927 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4928 data = (const char *)req->buf + 1;
4930 if (!fsp->print_file) {
4931 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4932 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4933 &lock);
4935 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4936 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4937 END_PROFILE(SMBwriteclose);
4938 return;
4942 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4944 set_close_write_time(fsp, mtime);
4947 * More insanity. W2K only closes the file if writelen > 0.
4948 * JRA.
4951 if (numtowrite) {
4952 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4953 "file %s\n", fsp_str_dbg(fsp)));
4954 close_status = close_file(req, fsp, NORMAL_CLOSE);
4957 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4958 fsp->fnum, (int)numtowrite, (int)nwritten,
4959 conn->num_files_open));
4961 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4962 reply_nterror(req, NT_STATUS_DISK_FULL);
4963 goto strict_unlock;
4966 if(!NT_STATUS_IS_OK(close_status)) {
4967 reply_nterror(req, close_status);
4968 goto strict_unlock;
4971 reply_outbuf(req, 1, 0);
4973 SSVAL(req->outbuf,smb_vwv0,nwritten);
4975 strict_unlock:
4976 if (numtowrite && !fsp->print_file) {
4977 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4980 END_PROFILE(SMBwriteclose);
4981 return;
4984 #undef DBGC_CLASS
4985 #define DBGC_CLASS DBGC_LOCKING
4987 /****************************************************************************
4988 Reply to a lock.
4989 ****************************************************************************/
4991 void reply_lock(struct smb_request *req)
4993 connection_struct *conn = req->conn;
4994 uint64_t count,offset;
4995 NTSTATUS status;
4996 files_struct *fsp;
4997 struct byte_range_lock *br_lck = NULL;
4999 START_PROFILE(SMBlock);
5001 if (req->wct < 5) {
5002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5003 END_PROFILE(SMBlock);
5004 return;
5007 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5009 if (!check_fsp(conn, req, fsp)) {
5010 END_PROFILE(SMBlock);
5011 return;
5014 count = (uint64_t)IVAL(req->vwv+1, 0);
5015 offset = (uint64_t)IVAL(req->vwv+3, 0);
5017 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5018 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5020 br_lck = do_lock(req->sconn->msg_ctx,
5021 fsp,
5022 (uint64_t)req->smbpid,
5023 count,
5024 offset,
5025 WRITE_LOCK,
5026 WINDOWS_LOCK,
5027 False, /* Non-blocking lock. */
5028 &status,
5029 NULL,
5030 NULL);
5032 TALLOC_FREE(br_lck);
5034 if (NT_STATUS_V(status)) {
5035 reply_nterror(req, status);
5036 END_PROFILE(SMBlock);
5037 return;
5040 reply_outbuf(req, 0, 0);
5042 END_PROFILE(SMBlock);
5043 return;
5046 /****************************************************************************
5047 Reply to a unlock.
5048 ****************************************************************************/
5050 void reply_unlock(struct smb_request *req)
5052 connection_struct *conn = req->conn;
5053 uint64_t count,offset;
5054 NTSTATUS status;
5055 files_struct *fsp;
5057 START_PROFILE(SMBunlock);
5059 if (req->wct < 5) {
5060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5061 END_PROFILE(SMBunlock);
5062 return;
5065 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5067 if (!check_fsp(conn, req, fsp)) {
5068 END_PROFILE(SMBunlock);
5069 return;
5072 count = (uint64_t)IVAL(req->vwv+1, 0);
5073 offset = (uint64_t)IVAL(req->vwv+3, 0);
5075 status = do_unlock(req->sconn->msg_ctx,
5076 fsp,
5077 (uint64_t)req->smbpid,
5078 count,
5079 offset,
5080 WINDOWS_LOCK);
5082 if (NT_STATUS_V(status)) {
5083 reply_nterror(req, status);
5084 END_PROFILE(SMBunlock);
5085 return;
5088 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5089 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5091 reply_outbuf(req, 0, 0);
5093 END_PROFILE(SMBunlock);
5094 return;
5097 #undef DBGC_CLASS
5098 #define DBGC_CLASS DBGC_ALL
5100 /****************************************************************************
5101 Reply to a tdis.
5102 conn POINTER CAN BE NULL HERE !
5103 ****************************************************************************/
5105 void reply_tdis(struct smb_request *req)
5107 connection_struct *conn = req->conn;
5108 START_PROFILE(SMBtdis);
5110 if (!conn) {
5111 DEBUG(4,("Invalid connection in tdis\n"));
5112 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5113 END_PROFILE(SMBtdis);
5114 return;
5117 conn->used = False;
5119 close_cnum(conn,req->vuid);
5120 req->conn = NULL;
5122 reply_outbuf(req, 0, 0);
5123 END_PROFILE(SMBtdis);
5124 return;
5127 /****************************************************************************
5128 Reply to a echo.
5129 conn POINTER CAN BE NULL HERE !
5130 ****************************************************************************/
5132 void reply_echo(struct smb_request *req)
5134 connection_struct *conn = req->conn;
5135 struct smb_perfcount_data local_pcd;
5136 struct smb_perfcount_data *cur_pcd;
5137 int smb_reverb;
5138 int seq_num;
5140 START_PROFILE(SMBecho);
5142 smb_init_perfcount_data(&local_pcd);
5144 if (req->wct < 1) {
5145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5146 END_PROFILE(SMBecho);
5147 return;
5150 smb_reverb = SVAL(req->vwv+0, 0);
5152 reply_outbuf(req, 1, req->buflen);
5154 /* copy any incoming data back out */
5155 if (req->buflen > 0) {
5156 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5159 if (smb_reverb > 100) {
5160 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5161 smb_reverb = 100;
5164 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5166 /* this makes sure we catch the request pcd */
5167 if (seq_num == smb_reverb) {
5168 cur_pcd = &req->pcd;
5169 } else {
5170 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5171 cur_pcd = &local_pcd;
5174 SSVAL(req->outbuf,smb_vwv0,seq_num);
5176 show_msg((char *)req->outbuf);
5177 if (!srv_send_smb(req->sconn,
5178 (char *)req->outbuf,
5179 true, req->seqnum+1,
5180 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5181 cur_pcd))
5182 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5185 DEBUG(3,("echo %d times\n", smb_reverb));
5187 TALLOC_FREE(req->outbuf);
5189 END_PROFILE(SMBecho);
5190 return;
5193 /****************************************************************************
5194 Reply to a printopen.
5195 ****************************************************************************/
5197 void reply_printopen(struct smb_request *req)
5199 connection_struct *conn = req->conn;
5200 files_struct *fsp;
5201 NTSTATUS status;
5203 START_PROFILE(SMBsplopen);
5205 if (req->wct < 2) {
5206 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5207 END_PROFILE(SMBsplopen);
5208 return;
5211 if (!CAN_PRINT(conn)) {
5212 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5213 END_PROFILE(SMBsplopen);
5214 return;
5217 status = file_new(req, conn, &fsp);
5218 if(!NT_STATUS_IS_OK(status)) {
5219 reply_nterror(req, status);
5220 END_PROFILE(SMBsplopen);
5221 return;
5224 /* Open for exclusive use, write only. */
5225 status = print_spool_open(fsp, NULL, req->vuid);
5227 if (!NT_STATUS_IS_OK(status)) {
5228 file_free(req, fsp);
5229 reply_nterror(req, status);
5230 END_PROFILE(SMBsplopen);
5231 return;
5234 reply_outbuf(req, 1, 0);
5235 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5237 DEBUG(3,("openprint fd=%d fnum=%d\n",
5238 fsp->fh->fd, fsp->fnum));
5240 END_PROFILE(SMBsplopen);
5241 return;
5244 /****************************************************************************
5245 Reply to a printclose.
5246 ****************************************************************************/
5248 void reply_printclose(struct smb_request *req)
5250 connection_struct *conn = req->conn;
5251 files_struct *fsp;
5252 NTSTATUS status;
5254 START_PROFILE(SMBsplclose);
5256 if (req->wct < 1) {
5257 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5258 END_PROFILE(SMBsplclose);
5259 return;
5262 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5264 if (!check_fsp(conn, req, fsp)) {
5265 END_PROFILE(SMBsplclose);
5266 return;
5269 if (!CAN_PRINT(conn)) {
5270 reply_force_doserror(req, ERRSRV, ERRerror);
5271 END_PROFILE(SMBsplclose);
5272 return;
5275 DEBUG(3,("printclose fd=%d fnum=%d\n",
5276 fsp->fh->fd,fsp->fnum));
5278 status = close_file(req, fsp, NORMAL_CLOSE);
5280 if(!NT_STATUS_IS_OK(status)) {
5281 reply_nterror(req, status);
5282 END_PROFILE(SMBsplclose);
5283 return;
5286 reply_outbuf(req, 0, 0);
5288 END_PROFILE(SMBsplclose);
5289 return;
5292 /****************************************************************************
5293 Reply to a printqueue.
5294 ****************************************************************************/
5296 void reply_printqueue(struct smb_request *req)
5298 connection_struct *conn = req->conn;
5299 int max_count;
5300 int start_index;
5302 START_PROFILE(SMBsplretq);
5304 if (req->wct < 2) {
5305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5306 END_PROFILE(SMBsplretq);
5307 return;
5310 max_count = SVAL(req->vwv+0, 0);
5311 start_index = SVAL(req->vwv+1, 0);
5313 /* we used to allow the client to get the cnum wrong, but that
5314 is really quite gross and only worked when there was only
5315 one printer - I think we should now only accept it if they
5316 get it right (tridge) */
5317 if (!CAN_PRINT(conn)) {
5318 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5319 END_PROFILE(SMBsplretq);
5320 return;
5323 reply_outbuf(req, 2, 3);
5324 SSVAL(req->outbuf,smb_vwv0,0);
5325 SSVAL(req->outbuf,smb_vwv1,0);
5326 SCVAL(smb_buf(req->outbuf),0,1);
5327 SSVAL(smb_buf(req->outbuf),1,0);
5329 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5330 start_index, max_count));
5333 TALLOC_CTX *mem_ctx = talloc_tos();
5334 NTSTATUS status;
5335 WERROR werr;
5336 const char *sharename = lp_servicename(SNUM(conn));
5337 struct rpc_pipe_client *cli = NULL;
5338 struct dcerpc_binding_handle *b = NULL;
5339 struct policy_handle handle;
5340 struct spoolss_DevmodeContainer devmode_ctr;
5341 union spoolss_JobInfo *info;
5342 uint32_t count;
5343 uint32_t num_to_get;
5344 uint32_t first;
5345 uint32_t i;
5347 ZERO_STRUCT(handle);
5349 status = rpc_pipe_open_interface(conn,
5350 &ndr_table_spoolss.syntax_id,
5351 conn->session_info,
5352 conn->sconn->remote_address,
5353 conn->sconn->msg_ctx,
5354 &cli);
5355 if (!NT_STATUS_IS_OK(status)) {
5356 DEBUG(0, ("reply_printqueue: "
5357 "could not connect to spoolss: %s\n",
5358 nt_errstr(status)));
5359 reply_nterror(req, status);
5360 goto out;
5362 b = cli->binding_handle;
5364 ZERO_STRUCT(devmode_ctr);
5366 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5367 sharename,
5368 NULL, devmode_ctr,
5369 SEC_FLAG_MAXIMUM_ALLOWED,
5370 &handle,
5371 &werr);
5372 if (!NT_STATUS_IS_OK(status)) {
5373 reply_nterror(req, status);
5374 goto out;
5376 if (!W_ERROR_IS_OK(werr)) {
5377 reply_nterror(req, werror_to_ntstatus(werr));
5378 goto out;
5381 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5382 &handle,
5383 0, /* firstjob */
5384 0xff, /* numjobs */
5385 2, /* level */
5386 0, /* offered */
5387 &count,
5388 &info);
5389 if (!W_ERROR_IS_OK(werr)) {
5390 reply_nterror(req, werror_to_ntstatus(werr));
5391 goto out;
5394 if (max_count > 0) {
5395 first = start_index;
5396 } else {
5397 first = start_index + max_count + 1;
5400 if (first >= count) {
5401 num_to_get = first;
5402 } else {
5403 num_to_get = first + MIN(ABS(max_count), count - first);
5406 for (i = first; i < num_to_get; i++) {
5407 char blob[28];
5408 char *p = blob;
5409 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5410 int qstatus;
5411 uint16_t qrapjobid = pjobid_to_rap(sharename,
5412 info[i].info2.job_id);
5414 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5415 qstatus = 2;
5416 } else {
5417 qstatus = 3;
5420 srv_put_dos_date2(p, 0, qtime);
5421 SCVAL(p, 4, qstatus);
5422 SSVAL(p, 5, qrapjobid);
5423 SIVAL(p, 7, info[i].info2.size);
5424 SCVAL(p, 11, 0);
5425 srvstr_push(blob, req->flags2, p+12,
5426 info[i].info2.notify_name, 16, STR_ASCII);
5428 if (message_push_blob(
5429 &req->outbuf,
5430 data_blob_const(
5431 blob, sizeof(blob))) == -1) {
5432 reply_nterror(req, NT_STATUS_NO_MEMORY);
5433 goto out;
5437 if (count > 0) {
5438 SSVAL(req->outbuf,smb_vwv0,count);
5439 SSVAL(req->outbuf,smb_vwv1,
5440 (max_count>0?first+count:first-1));
5441 SCVAL(smb_buf(req->outbuf),0,1);
5442 SSVAL(smb_buf(req->outbuf),1,28*count);
5446 DEBUG(3, ("%u entries returned in queue\n",
5447 (unsigned)count));
5449 out:
5450 if (b && is_valid_policy_hnd(&handle)) {
5451 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5456 END_PROFILE(SMBsplretq);
5457 return;
5460 /****************************************************************************
5461 Reply to a printwrite.
5462 ****************************************************************************/
5464 void reply_printwrite(struct smb_request *req)
5466 connection_struct *conn = req->conn;
5467 int numtowrite;
5468 const char *data;
5469 files_struct *fsp;
5471 START_PROFILE(SMBsplwr);
5473 if (req->wct < 1) {
5474 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5475 END_PROFILE(SMBsplwr);
5476 return;
5479 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5481 if (!check_fsp(conn, req, fsp)) {
5482 END_PROFILE(SMBsplwr);
5483 return;
5486 if (!fsp->print_file) {
5487 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5488 END_PROFILE(SMBsplwr);
5489 return;
5492 if (!CHECK_WRITE(fsp)) {
5493 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5494 END_PROFILE(SMBsplwr);
5495 return;
5498 numtowrite = SVAL(req->buf, 1);
5500 if (req->buflen < numtowrite + 3) {
5501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5502 END_PROFILE(SMBsplwr);
5503 return;
5506 data = (const char *)req->buf + 3;
5508 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5509 reply_nterror(req, map_nt_error_from_unix(errno));
5510 END_PROFILE(SMBsplwr);
5511 return;
5514 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5516 END_PROFILE(SMBsplwr);
5517 return;
5520 /****************************************************************************
5521 Reply to a mkdir.
5522 ****************************************************************************/
5524 void reply_mkdir(struct smb_request *req)
5526 connection_struct *conn = req->conn;
5527 struct smb_filename *smb_dname = NULL;
5528 char *directory = NULL;
5529 NTSTATUS status;
5530 TALLOC_CTX *ctx = talloc_tos();
5532 START_PROFILE(SMBmkdir);
5534 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5535 STR_TERMINATE, &status);
5536 if (!NT_STATUS_IS_OK(status)) {
5537 reply_nterror(req, status);
5538 goto out;
5541 status = filename_convert(ctx, conn,
5542 req->flags2 & FLAGS2_DFS_PATHNAMES,
5543 directory,
5545 NULL,
5546 &smb_dname);
5547 if (!NT_STATUS_IS_OK(status)) {
5548 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5549 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5550 ERRSRV, ERRbadpath);
5551 goto out;
5553 reply_nterror(req, status);
5554 goto out;
5557 status = create_directory(conn, req, smb_dname);
5559 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5561 if (!NT_STATUS_IS_OK(status)) {
5563 if (!use_nt_status()
5564 && NT_STATUS_EQUAL(status,
5565 NT_STATUS_OBJECT_NAME_COLLISION)) {
5567 * Yes, in the DOS error code case we get a
5568 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5569 * samba4 torture test.
5571 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5574 reply_nterror(req, status);
5575 goto out;
5578 reply_outbuf(req, 0, 0);
5580 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5581 out:
5582 TALLOC_FREE(smb_dname);
5583 END_PROFILE(SMBmkdir);
5584 return;
5587 /****************************************************************************
5588 Reply to a rmdir.
5589 ****************************************************************************/
5591 void reply_rmdir(struct smb_request *req)
5593 connection_struct *conn = req->conn;
5594 struct smb_filename *smb_dname = NULL;
5595 char *directory = NULL;
5596 NTSTATUS status;
5597 TALLOC_CTX *ctx = talloc_tos();
5598 files_struct *fsp = NULL;
5599 int info = 0;
5600 struct smbd_server_connection *sconn = req->sconn;
5602 START_PROFILE(SMBrmdir);
5604 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5605 STR_TERMINATE, &status);
5606 if (!NT_STATUS_IS_OK(status)) {
5607 reply_nterror(req, status);
5608 goto out;
5611 status = filename_convert(ctx, conn,
5612 req->flags2 & FLAGS2_DFS_PATHNAMES,
5613 directory,
5615 NULL,
5616 &smb_dname);
5617 if (!NT_STATUS_IS_OK(status)) {
5618 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5619 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5620 ERRSRV, ERRbadpath);
5621 goto out;
5623 reply_nterror(req, status);
5624 goto out;
5627 if (is_ntfs_stream_smb_fname(smb_dname)) {
5628 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5629 goto out;
5632 status = SMB_VFS_CREATE_FILE(
5633 conn, /* conn */
5634 req, /* req */
5635 0, /* root_dir_fid */
5636 smb_dname, /* fname */
5637 DELETE_ACCESS, /* access_mask */
5638 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5639 FILE_SHARE_DELETE),
5640 FILE_OPEN, /* create_disposition*/
5641 FILE_DIRECTORY_FILE, /* create_options */
5642 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5643 0, /* oplock_request */
5644 0, /* allocation_size */
5645 0, /* private_flags */
5646 NULL, /* sd */
5647 NULL, /* ea_list */
5648 &fsp, /* result */
5649 &info); /* pinfo */
5651 if (!NT_STATUS_IS_OK(status)) {
5652 if (open_was_deferred(req->sconn, req->mid)) {
5653 /* We have re-scheduled this call. */
5654 goto out;
5656 reply_nterror(req, status);
5657 goto out;
5660 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5661 if (!NT_STATUS_IS_OK(status)) {
5662 close_file(req, fsp, ERROR_CLOSE);
5663 reply_nterror(req, status);
5664 goto out;
5667 if (!set_delete_on_close(fsp, true, conn->session_info->unix_token)) {
5668 close_file(req, fsp, ERROR_CLOSE);
5669 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5670 goto out;
5673 status = close_file(req, fsp, NORMAL_CLOSE);
5674 if (!NT_STATUS_IS_OK(status)) {
5675 reply_nterror(req, status);
5676 } else {
5677 reply_outbuf(req, 0, 0);
5680 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5682 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5683 out:
5684 TALLOC_FREE(smb_dname);
5685 END_PROFILE(SMBrmdir);
5686 return;
5689 /*******************************************************************
5690 Resolve wildcards in a filename rename.
5691 ********************************************************************/
5693 static bool resolve_wildcards(TALLOC_CTX *ctx,
5694 const char *name1,
5695 const char *name2,
5696 char **pp_newname)
5698 char *name2_copy = NULL;
5699 char *root1 = NULL;
5700 char *root2 = NULL;
5701 char *ext1 = NULL;
5702 char *ext2 = NULL;
5703 char *p,*p2, *pname1, *pname2;
5705 name2_copy = talloc_strdup(ctx, name2);
5706 if (!name2_copy) {
5707 return False;
5710 pname1 = strrchr_m(name1,'/');
5711 pname2 = strrchr_m(name2_copy,'/');
5713 if (!pname1 || !pname2) {
5714 return False;
5717 /* Truncate the copy of name2 at the last '/' */
5718 *pname2 = '\0';
5720 /* Now go past the '/' */
5721 pname1++;
5722 pname2++;
5724 root1 = talloc_strdup(ctx, pname1);
5725 root2 = talloc_strdup(ctx, pname2);
5727 if (!root1 || !root2) {
5728 return False;
5731 p = strrchr_m(root1,'.');
5732 if (p) {
5733 *p = 0;
5734 ext1 = talloc_strdup(ctx, p+1);
5735 } else {
5736 ext1 = talloc_strdup(ctx, "");
5738 p = strrchr_m(root2,'.');
5739 if (p) {
5740 *p = 0;
5741 ext2 = talloc_strdup(ctx, p+1);
5742 } else {
5743 ext2 = talloc_strdup(ctx, "");
5746 if (!ext1 || !ext2) {
5747 return False;
5750 p = root1;
5751 p2 = root2;
5752 while (*p2) {
5753 if (*p2 == '?') {
5754 /* Hmmm. Should this be mb-aware ? */
5755 *p2 = *p;
5756 p2++;
5757 } else if (*p2 == '*') {
5758 *p2 = '\0';
5759 root2 = talloc_asprintf(ctx, "%s%s",
5760 root2,
5762 if (!root2) {
5763 return False;
5765 break;
5766 } else {
5767 p2++;
5769 if (*p) {
5770 p++;
5774 p = ext1;
5775 p2 = ext2;
5776 while (*p2) {
5777 if (*p2 == '?') {
5778 /* Hmmm. Should this be mb-aware ? */
5779 *p2 = *p;
5780 p2++;
5781 } else if (*p2 == '*') {
5782 *p2 = '\0';
5783 ext2 = talloc_asprintf(ctx, "%s%s",
5784 ext2,
5786 if (!ext2) {
5787 return False;
5789 break;
5790 } else {
5791 p2++;
5793 if (*p) {
5794 p++;
5798 if (*ext2) {
5799 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5800 name2_copy,
5801 root2,
5802 ext2);
5803 } else {
5804 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5805 name2_copy,
5806 root2);
5809 if (!*pp_newname) {
5810 return False;
5813 return True;
5816 /****************************************************************************
5817 Ensure open files have their names updated. Updated to notify other smbd's
5818 asynchronously.
5819 ****************************************************************************/
5821 static void rename_open_files(connection_struct *conn,
5822 struct share_mode_lock *lck,
5823 uint32_t orig_name_hash,
5824 const struct smb_filename *smb_fname_dst)
5826 files_struct *fsp;
5827 bool did_rename = False;
5828 NTSTATUS status;
5829 uint32_t new_name_hash = 0;
5831 for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
5832 fsp = file_find_di_next(fsp)) {
5833 /* fsp_name is a relative path under the fsp. To change this for other
5834 sharepaths we need to manipulate relative paths. */
5835 /* TODO - create the absolute path and manipulate the newname
5836 relative to the sharepath. */
5837 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5838 continue;
5840 if (fsp->name_hash != orig_name_hash) {
5841 continue;
5843 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5844 "(file_id %s) from %s -> %s\n", fsp->fnum,
5845 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5846 smb_fname_str_dbg(smb_fname_dst)));
5848 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5849 if (NT_STATUS_IS_OK(status)) {
5850 did_rename = True;
5851 new_name_hash = fsp->name_hash;
5855 if (!did_rename) {
5856 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5857 "for %s\n", file_id_string_tos(&lck->data->id),
5858 smb_fname_str_dbg(smb_fname_dst)));
5861 /* Send messages to all smbd's (not ourself) that the name has changed. */
5862 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5863 orig_name_hash, new_name_hash,
5864 smb_fname_dst);
5868 /****************************************************************************
5869 We need to check if the source path is a parent directory of the destination
5870 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5871 refuse the rename with a sharing violation. Under UNIX the above call can
5872 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5873 probably need to check that the client is a Windows one before disallowing
5874 this as a UNIX client (one with UNIX extensions) can know the source is a
5875 symlink and make this decision intelligently. Found by an excellent bug
5876 report from <AndyLiebman@aol.com>.
5877 ****************************************************************************/
5879 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5880 const struct smb_filename *smb_fname_dst)
5882 const char *psrc = smb_fname_src->base_name;
5883 const char *pdst = smb_fname_dst->base_name;
5884 size_t slen;
5886 if (psrc[0] == '.' && psrc[1] == '/') {
5887 psrc += 2;
5889 if (pdst[0] == '.' && pdst[1] == '/') {
5890 pdst += 2;
5892 if ((slen = strlen(psrc)) > strlen(pdst)) {
5893 return False;
5895 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5899 * Do the notify calls from a rename
5902 static void notify_rename(connection_struct *conn, bool is_dir,
5903 const struct smb_filename *smb_fname_src,
5904 const struct smb_filename *smb_fname_dst)
5906 char *parent_dir_src = NULL;
5907 char *parent_dir_dst = NULL;
5908 uint32 mask;
5910 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5911 : FILE_NOTIFY_CHANGE_FILE_NAME;
5913 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5914 &parent_dir_src, NULL) ||
5915 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5916 &parent_dir_dst, NULL)) {
5917 goto out;
5920 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5921 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5922 smb_fname_src->base_name);
5923 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5924 smb_fname_dst->base_name);
5926 else {
5927 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5928 smb_fname_src->base_name);
5929 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5930 smb_fname_dst->base_name);
5933 /* this is a strange one. w2k3 gives an additional event for
5934 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5935 files, but not directories */
5936 if (!is_dir) {
5937 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5938 FILE_NOTIFY_CHANGE_ATTRIBUTES
5939 |FILE_NOTIFY_CHANGE_CREATION,
5940 smb_fname_dst->base_name);
5942 out:
5943 TALLOC_FREE(parent_dir_src);
5944 TALLOC_FREE(parent_dir_dst);
5947 /****************************************************************************
5948 Returns an error if the parent directory for a filename is open in an
5949 incompatible way.
5950 ****************************************************************************/
5952 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5953 const struct smb_filename *smb_fname_dst_in)
5955 char *parent_dir = NULL;
5956 struct smb_filename smb_fname_parent;
5957 struct file_id id;
5958 files_struct *fsp = NULL;
5959 int ret;
5961 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5962 &parent_dir, NULL)) {
5963 return NT_STATUS_NO_MEMORY;
5965 ZERO_STRUCT(smb_fname_parent);
5966 smb_fname_parent.base_name = parent_dir;
5968 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5969 if (ret == -1) {
5970 return map_nt_error_from_unix(errno);
5974 * We're only checking on this smbd here, mostly good
5975 * enough.. and will pass tests.
5978 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
5979 for (fsp = file_find_di_first(conn->sconn, id); fsp;
5980 fsp = file_find_di_next(fsp)) {
5981 if (fsp->access_mask & DELETE_ACCESS) {
5982 return NT_STATUS_SHARING_VIOLATION;
5985 return NT_STATUS_OK;
5988 /****************************************************************************
5989 Rename an open file - given an fsp.
5990 ****************************************************************************/
5992 NTSTATUS rename_internals_fsp(connection_struct *conn,
5993 files_struct *fsp,
5994 const struct smb_filename *smb_fname_dst_in,
5995 uint32 attrs,
5996 bool replace_if_exists)
5998 TALLOC_CTX *ctx = talloc_tos();
5999 struct smb_filename *smb_fname_dst = NULL;
6000 NTSTATUS status = NT_STATUS_OK;
6001 struct share_mode_lock *lck = NULL;
6002 bool dst_exists, old_is_stream, new_is_stream;
6004 status = check_name(conn, smb_fname_dst_in->base_name);
6005 if (!NT_STATUS_IS_OK(status)) {
6006 return status;
6009 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6010 if (!NT_STATUS_IS_OK(status)) {
6011 return status;
6014 /* Make a copy of the dst smb_fname structs */
6016 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6017 if (!NT_STATUS_IS_OK(status)) {
6018 goto out;
6022 * Check for special case with case preserving and not
6023 * case sensitive. If the old last component differs from the original
6024 * last component only by case, then we should allow
6025 * the rename (user is trying to change the case of the
6026 * filename).
6028 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6029 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6030 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6031 char *last_slash;
6032 char *fname_dst_lcomp_base_mod = NULL;
6033 struct smb_filename *smb_fname_orig_lcomp = NULL;
6036 * Get the last component of the destination name.
6038 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6039 if (last_slash) {
6040 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6041 } else {
6042 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6044 if (!fname_dst_lcomp_base_mod) {
6045 status = NT_STATUS_NO_MEMORY;
6046 goto out;
6050 * Create an smb_filename struct using the original last
6051 * component of the destination.
6053 status = create_synthetic_smb_fname_split(ctx,
6054 smb_fname_dst->original_lcomp, NULL,
6055 &smb_fname_orig_lcomp);
6056 if (!NT_STATUS_IS_OK(status)) {
6057 TALLOC_FREE(fname_dst_lcomp_base_mod);
6058 goto out;
6061 /* If the base names only differ by case, use original. */
6062 if(!strcsequal(fname_dst_lcomp_base_mod,
6063 smb_fname_orig_lcomp->base_name)) {
6064 char *tmp;
6066 * Replace the modified last component with the
6067 * original.
6069 if (last_slash) {
6070 *last_slash = '\0'; /* Truncate at the '/' */
6071 tmp = talloc_asprintf(smb_fname_dst,
6072 "%s/%s",
6073 smb_fname_dst->base_name,
6074 smb_fname_orig_lcomp->base_name);
6075 } else {
6076 tmp = talloc_asprintf(smb_fname_dst,
6077 "%s",
6078 smb_fname_orig_lcomp->base_name);
6080 if (tmp == NULL) {
6081 status = NT_STATUS_NO_MEMORY;
6082 TALLOC_FREE(fname_dst_lcomp_base_mod);
6083 TALLOC_FREE(smb_fname_orig_lcomp);
6084 goto out;
6086 TALLOC_FREE(smb_fname_dst->base_name);
6087 smb_fname_dst->base_name = tmp;
6090 /* If the stream_names only differ by case, use original. */
6091 if(!strcsequal(smb_fname_dst->stream_name,
6092 smb_fname_orig_lcomp->stream_name)) {
6093 char *tmp = NULL;
6094 /* Use the original stream. */
6095 tmp = talloc_strdup(smb_fname_dst,
6096 smb_fname_orig_lcomp->stream_name);
6097 if (tmp == NULL) {
6098 status = NT_STATUS_NO_MEMORY;
6099 TALLOC_FREE(fname_dst_lcomp_base_mod);
6100 TALLOC_FREE(smb_fname_orig_lcomp);
6101 goto out;
6103 TALLOC_FREE(smb_fname_dst->stream_name);
6104 smb_fname_dst->stream_name = tmp;
6106 TALLOC_FREE(fname_dst_lcomp_base_mod);
6107 TALLOC_FREE(smb_fname_orig_lcomp);
6111 * If the src and dest names are identical - including case,
6112 * don't do the rename, just return success.
6115 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6116 strcsequal(fsp->fsp_name->stream_name,
6117 smb_fname_dst->stream_name)) {
6118 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6119 "- returning success\n",
6120 smb_fname_str_dbg(smb_fname_dst)));
6121 status = NT_STATUS_OK;
6122 goto out;
6125 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6126 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6128 /* Return the correct error code if both names aren't streams. */
6129 if (!old_is_stream && new_is_stream) {
6130 status = NT_STATUS_OBJECT_NAME_INVALID;
6131 goto out;
6134 if (old_is_stream && !new_is_stream) {
6135 status = NT_STATUS_INVALID_PARAMETER;
6136 goto out;
6139 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6141 if(!replace_if_exists && dst_exists) {
6142 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6143 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6144 smb_fname_str_dbg(smb_fname_dst)));
6145 status = NT_STATUS_OBJECT_NAME_COLLISION;
6146 goto out;
6149 if (dst_exists) {
6150 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6151 &smb_fname_dst->st);
6152 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6153 fileid);
6154 /* The file can be open when renaming a stream */
6155 if (dst_fsp && !new_is_stream) {
6156 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6157 status = NT_STATUS_ACCESS_DENIED;
6158 goto out;
6162 /* Ensure we have a valid stat struct for the source. */
6163 status = vfs_stat_fsp(fsp);
6164 if (!NT_STATUS_IS_OK(status)) {
6165 goto out;
6168 status = can_rename(conn, fsp, attrs);
6170 if (!NT_STATUS_IS_OK(status)) {
6171 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6172 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6173 smb_fname_str_dbg(smb_fname_dst)));
6174 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6175 status = NT_STATUS_ACCESS_DENIED;
6176 goto out;
6179 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6180 status = NT_STATUS_ACCESS_DENIED;
6183 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6186 * We have the file open ourselves, so not being able to get the
6187 * corresponding share mode lock is a fatal error.
6190 SMB_ASSERT(lck != NULL);
6192 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6193 uint32 create_options = fsp->fh->private_options;
6195 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6196 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6197 smb_fname_str_dbg(smb_fname_dst)));
6199 if (!lp_posix_pathnames() &&
6200 (lp_map_archive(SNUM(conn)) ||
6201 lp_store_dos_attributes(SNUM(conn)))) {
6202 /* We must set the archive bit on the newly
6203 renamed file. */
6204 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6205 uint32_t old_dosmode = dos_mode(conn,
6206 smb_fname_dst);
6207 file_set_dosmode(conn,
6208 smb_fname_dst,
6209 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6210 NULL,
6211 true);
6215 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6216 smb_fname_dst);
6218 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6221 * A rename acts as a new file create w.r.t. allowing an initial delete
6222 * on close, probably because in Windows there is a new handle to the
6223 * new file. If initial delete on close was requested but not
6224 * originally set, we need to set it here. This is probably not 100% correct,
6225 * but will work for the CIFSFS client which in non-posix mode
6226 * depends on these semantics. JRA.
6229 if (create_options & FILE_DELETE_ON_CLOSE) {
6230 status = can_set_delete_on_close(fsp, 0);
6232 if (NT_STATUS_IS_OK(status)) {
6233 /* Note that here we set the *inital* delete on close flag,
6234 * not the regular one. The magic gets handled in close. */
6235 fsp->initial_delete_on_close = True;
6238 TALLOC_FREE(lck);
6239 status = NT_STATUS_OK;
6240 goto out;
6243 TALLOC_FREE(lck);
6245 if (errno == ENOTDIR || errno == EISDIR) {
6246 status = NT_STATUS_OBJECT_NAME_COLLISION;
6247 } else {
6248 status = map_nt_error_from_unix(errno);
6251 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6252 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6253 smb_fname_str_dbg(smb_fname_dst)));
6255 out:
6256 TALLOC_FREE(smb_fname_dst);
6258 return status;
6261 /****************************************************************************
6262 The guts of the rename command, split out so it may be called by the NT SMB
6263 code.
6264 ****************************************************************************/
6266 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6267 connection_struct *conn,
6268 struct smb_request *req,
6269 struct smb_filename *smb_fname_src,
6270 struct smb_filename *smb_fname_dst,
6271 uint32 attrs,
6272 bool replace_if_exists,
6273 bool src_has_wild,
6274 bool dest_has_wild,
6275 uint32_t access_mask)
6277 char *fname_src_dir = NULL;
6278 char *fname_src_mask = NULL;
6279 int count=0;
6280 NTSTATUS status = NT_STATUS_OK;
6281 struct smb_Dir *dir_hnd = NULL;
6282 const char *dname = NULL;
6283 char *talloced = NULL;
6284 long offset = 0;
6285 int create_options = 0;
6286 bool posix_pathnames = lp_posix_pathnames();
6289 * Split the old name into directory and last component
6290 * strings. Note that unix_convert may have stripped off a
6291 * leading ./ from both name and newname if the rename is
6292 * at the root of the share. We need to make sure either both
6293 * name and newname contain a / character or neither of them do
6294 * as this is checked in resolve_wildcards().
6297 /* Split up the directory from the filename/mask. */
6298 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6299 &fname_src_dir, &fname_src_mask);
6300 if (!NT_STATUS_IS_OK(status)) {
6301 status = NT_STATUS_NO_MEMORY;
6302 goto out;
6306 * We should only check the mangled cache
6307 * here if unix_convert failed. This means
6308 * that the path in 'mask' doesn't exist
6309 * on the file system and so we need to look
6310 * for a possible mangle. This patch from
6311 * Tine Smukavec <valentin.smukavec@hermes.si>.
6314 if (!VALID_STAT(smb_fname_src->st) &&
6315 mangle_is_mangled(fname_src_mask, conn->params)) {
6316 char *new_mask = NULL;
6317 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6318 conn->params);
6319 if (new_mask) {
6320 TALLOC_FREE(fname_src_mask);
6321 fname_src_mask = new_mask;
6325 if (!src_has_wild) {
6326 files_struct *fsp;
6329 * Only one file needs to be renamed. Append the mask back
6330 * onto the directory.
6332 TALLOC_FREE(smb_fname_src->base_name);
6333 if (ISDOT(fname_src_dir)) {
6334 /* Ensure we use canonical names on open. */
6335 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6336 "%s",
6337 fname_src_mask);
6338 } else {
6339 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6340 "%s/%s",
6341 fname_src_dir,
6342 fname_src_mask);
6344 if (!smb_fname_src->base_name) {
6345 status = NT_STATUS_NO_MEMORY;
6346 goto out;
6349 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6350 "case_preserve = %d, short case preserve = %d, "
6351 "directory = %s, newname = %s, "
6352 "last_component_dest = %s\n",
6353 conn->case_sensitive, conn->case_preserve,
6354 conn->short_case_preserve,
6355 smb_fname_str_dbg(smb_fname_src),
6356 smb_fname_str_dbg(smb_fname_dst),
6357 smb_fname_dst->original_lcomp));
6359 /* The dest name still may have wildcards. */
6360 if (dest_has_wild) {
6361 char *fname_dst_mod = NULL;
6362 if (!resolve_wildcards(smb_fname_dst,
6363 smb_fname_src->base_name,
6364 smb_fname_dst->base_name,
6365 &fname_dst_mod)) {
6366 DEBUG(6, ("rename_internals: resolve_wildcards "
6367 "%s %s failed\n",
6368 smb_fname_src->base_name,
6369 smb_fname_dst->base_name));
6370 status = NT_STATUS_NO_MEMORY;
6371 goto out;
6373 TALLOC_FREE(smb_fname_dst->base_name);
6374 smb_fname_dst->base_name = fname_dst_mod;
6377 ZERO_STRUCT(smb_fname_src->st);
6378 if (posix_pathnames) {
6379 SMB_VFS_LSTAT(conn, smb_fname_src);
6380 } else {
6381 SMB_VFS_STAT(conn, smb_fname_src);
6384 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6385 create_options |= FILE_DIRECTORY_FILE;
6388 status = SMB_VFS_CREATE_FILE(
6389 conn, /* conn */
6390 req, /* req */
6391 0, /* root_dir_fid */
6392 smb_fname_src, /* fname */
6393 access_mask, /* access_mask */
6394 (FILE_SHARE_READ | /* share_access */
6395 FILE_SHARE_WRITE),
6396 FILE_OPEN, /* create_disposition*/
6397 create_options, /* create_options */
6398 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6399 0, /* oplock_request */
6400 0, /* allocation_size */
6401 0, /* private_flags */
6402 NULL, /* sd */
6403 NULL, /* ea_list */
6404 &fsp, /* result */
6405 NULL); /* pinfo */
6407 if (!NT_STATUS_IS_OK(status)) {
6408 DEBUG(3, ("Could not open rename source %s: %s\n",
6409 smb_fname_str_dbg(smb_fname_src),
6410 nt_errstr(status)));
6411 goto out;
6414 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6415 attrs, replace_if_exists);
6417 close_file(req, fsp, NORMAL_CLOSE);
6419 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6420 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6421 smb_fname_str_dbg(smb_fname_dst)));
6423 goto out;
6427 * Wildcards - process each file that matches.
6429 if (strequal(fname_src_mask, "????????.???")) {
6430 TALLOC_FREE(fname_src_mask);
6431 fname_src_mask = talloc_strdup(ctx, "*");
6432 if (!fname_src_mask) {
6433 status = NT_STATUS_NO_MEMORY;
6434 goto out;
6438 status = check_name(conn, fname_src_dir);
6439 if (!NT_STATUS_IS_OK(status)) {
6440 goto out;
6443 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6444 attrs);
6445 if (dir_hnd == NULL) {
6446 status = map_nt_error_from_unix(errno);
6447 goto out;
6450 status = NT_STATUS_NO_SUCH_FILE;
6452 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6453 * - gentest fix. JRA
6456 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6457 &talloced))) {
6458 files_struct *fsp = NULL;
6459 char *destname = NULL;
6460 bool sysdir_entry = False;
6462 /* Quick check for "." and ".." */
6463 if (ISDOT(dname) || ISDOTDOT(dname)) {
6464 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6465 sysdir_entry = True;
6466 } else {
6467 TALLOC_FREE(talloced);
6468 continue;
6472 if (!is_visible_file(conn, fname_src_dir, dname,
6473 &smb_fname_src->st, false)) {
6474 TALLOC_FREE(talloced);
6475 continue;
6478 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6479 TALLOC_FREE(talloced);
6480 continue;
6483 if (sysdir_entry) {
6484 status = NT_STATUS_OBJECT_NAME_INVALID;
6485 break;
6488 TALLOC_FREE(smb_fname_src->base_name);
6489 if (ISDOT(fname_src_dir)) {
6490 /* Ensure we use canonical names on open. */
6491 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6492 "%s",
6493 dname);
6494 } else {
6495 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6496 "%s/%s",
6497 fname_src_dir,
6498 dname);
6500 if (!smb_fname_src->base_name) {
6501 status = NT_STATUS_NO_MEMORY;
6502 goto out;
6505 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6506 smb_fname_dst->base_name,
6507 &destname)) {
6508 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6509 smb_fname_src->base_name, destname));
6510 TALLOC_FREE(talloced);
6511 continue;
6513 if (!destname) {
6514 status = NT_STATUS_NO_MEMORY;
6515 goto out;
6518 TALLOC_FREE(smb_fname_dst->base_name);
6519 smb_fname_dst->base_name = destname;
6521 ZERO_STRUCT(smb_fname_src->st);
6522 if (posix_pathnames) {
6523 SMB_VFS_LSTAT(conn, smb_fname_src);
6524 } else {
6525 SMB_VFS_STAT(conn, smb_fname_src);
6528 create_options = 0;
6530 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6531 create_options |= FILE_DIRECTORY_FILE;
6534 status = SMB_VFS_CREATE_FILE(
6535 conn, /* conn */
6536 req, /* req */
6537 0, /* root_dir_fid */
6538 smb_fname_src, /* fname */
6539 access_mask, /* access_mask */
6540 (FILE_SHARE_READ | /* share_access */
6541 FILE_SHARE_WRITE),
6542 FILE_OPEN, /* create_disposition*/
6543 create_options, /* create_options */
6544 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6545 0, /* oplock_request */
6546 0, /* allocation_size */
6547 0, /* private_flags */
6548 NULL, /* sd */
6549 NULL, /* ea_list */
6550 &fsp, /* result */
6551 NULL); /* pinfo */
6553 if (!NT_STATUS_IS_OK(status)) {
6554 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6555 "returned %s rename %s -> %s\n",
6556 nt_errstr(status),
6557 smb_fname_str_dbg(smb_fname_src),
6558 smb_fname_str_dbg(smb_fname_dst)));
6559 break;
6562 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6563 dname);
6564 if (!smb_fname_dst->original_lcomp) {
6565 status = NT_STATUS_NO_MEMORY;
6566 goto out;
6569 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6570 attrs, replace_if_exists);
6572 close_file(req, fsp, NORMAL_CLOSE);
6574 if (!NT_STATUS_IS_OK(status)) {
6575 DEBUG(3, ("rename_internals_fsp returned %s for "
6576 "rename %s -> %s\n", nt_errstr(status),
6577 smb_fname_str_dbg(smb_fname_src),
6578 smb_fname_str_dbg(smb_fname_dst)));
6579 break;
6582 count++;
6584 DEBUG(3,("rename_internals: doing rename on %s -> "
6585 "%s\n", smb_fname_str_dbg(smb_fname_src),
6586 smb_fname_str_dbg(smb_fname_src)));
6587 TALLOC_FREE(talloced);
6589 TALLOC_FREE(dir_hnd);
6591 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6592 status = map_nt_error_from_unix(errno);
6595 out:
6596 TALLOC_FREE(talloced);
6597 TALLOC_FREE(fname_src_dir);
6598 TALLOC_FREE(fname_src_mask);
6599 return status;
6602 /****************************************************************************
6603 Reply to a mv.
6604 ****************************************************************************/
6606 void reply_mv(struct smb_request *req)
6608 connection_struct *conn = req->conn;
6609 char *name = NULL;
6610 char *newname = NULL;
6611 const char *p;
6612 uint32 attrs;
6613 NTSTATUS status;
6614 bool src_has_wcard = False;
6615 bool dest_has_wcard = False;
6616 TALLOC_CTX *ctx = talloc_tos();
6617 struct smb_filename *smb_fname_src = NULL;
6618 struct smb_filename *smb_fname_dst = NULL;
6619 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6620 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6621 bool stream_rename = false;
6623 START_PROFILE(SMBmv);
6625 if (req->wct < 1) {
6626 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6627 goto out;
6630 attrs = SVAL(req->vwv+0, 0);
6632 p = (const char *)req->buf + 1;
6633 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6634 &status, &src_has_wcard);
6635 if (!NT_STATUS_IS_OK(status)) {
6636 reply_nterror(req, status);
6637 goto out;
6639 p++;
6640 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6641 &status, &dest_has_wcard);
6642 if (!NT_STATUS_IS_OK(status)) {
6643 reply_nterror(req, status);
6644 goto out;
6647 if (!lp_posix_pathnames()) {
6648 /* The newname must begin with a ':' if the
6649 name contains a ':'. */
6650 if (strchr_m(name, ':')) {
6651 if (newname[0] != ':') {
6652 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6653 goto out;
6655 stream_rename = true;
6659 status = filename_convert(ctx,
6660 conn,
6661 req->flags2 & FLAGS2_DFS_PATHNAMES,
6662 name,
6663 src_ucf_flags,
6664 &src_has_wcard,
6665 &smb_fname_src);
6667 if (!NT_STATUS_IS_OK(status)) {
6668 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6669 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6670 ERRSRV, ERRbadpath);
6671 goto out;
6673 reply_nterror(req, status);
6674 goto out;
6677 status = filename_convert(ctx,
6678 conn,
6679 req->flags2 & FLAGS2_DFS_PATHNAMES,
6680 newname,
6681 dst_ucf_flags,
6682 &dest_has_wcard,
6683 &smb_fname_dst);
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 if (stream_rename) {
6696 /* smb_fname_dst->base_name must be the same as
6697 smb_fname_src->base_name. */
6698 TALLOC_FREE(smb_fname_dst->base_name);
6699 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6700 smb_fname_src->base_name);
6701 if (!smb_fname_dst->base_name) {
6702 reply_nterror(req, NT_STATUS_NO_MEMORY);
6703 goto out;
6707 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6708 smb_fname_str_dbg(smb_fname_dst)));
6710 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6711 attrs, False, src_has_wcard, dest_has_wcard,
6712 DELETE_ACCESS);
6713 if (!NT_STATUS_IS_OK(status)) {
6714 if (open_was_deferred(req->sconn, req->mid)) {
6715 /* We have re-scheduled this call. */
6716 goto out;
6718 reply_nterror(req, status);
6719 goto out;
6722 reply_outbuf(req, 0, 0);
6723 out:
6724 TALLOC_FREE(smb_fname_src);
6725 TALLOC_FREE(smb_fname_dst);
6726 END_PROFILE(SMBmv);
6727 return;
6730 /*******************************************************************
6731 Copy a file as part of a reply_copy.
6732 ******************************************************************/
6735 * TODO: check error codes on all callers
6738 NTSTATUS copy_file(TALLOC_CTX *ctx,
6739 connection_struct *conn,
6740 struct smb_filename *smb_fname_src,
6741 struct smb_filename *smb_fname_dst,
6742 int ofun,
6743 int count,
6744 bool target_is_directory)
6746 struct smb_filename *smb_fname_dst_tmp = NULL;
6747 SMB_OFF_T ret=-1;
6748 files_struct *fsp1,*fsp2;
6749 uint32 dosattrs;
6750 uint32 new_create_disposition;
6751 NTSTATUS status;
6754 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6755 if (!NT_STATUS_IS_OK(status)) {
6756 return status;
6760 * If the target is a directory, extract the last component from the
6761 * src filename and append it to the dst filename
6763 if (target_is_directory) {
6764 const char *p;
6766 /* dest/target can't be a stream if it's a directory. */
6767 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6769 p = strrchr_m(smb_fname_src->base_name,'/');
6770 if (p) {
6771 p++;
6772 } else {
6773 p = smb_fname_src->base_name;
6775 smb_fname_dst_tmp->base_name =
6776 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6778 if (!smb_fname_dst_tmp->base_name) {
6779 status = NT_STATUS_NO_MEMORY;
6780 goto out;
6784 status = vfs_file_exist(conn, smb_fname_src);
6785 if (!NT_STATUS_IS_OK(status)) {
6786 goto out;
6789 if (!target_is_directory && count) {
6790 new_create_disposition = FILE_OPEN;
6791 } else {
6792 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6793 0, ofun,
6794 NULL, NULL,
6795 &new_create_disposition,
6796 NULL,
6797 NULL)) {
6798 status = NT_STATUS_INVALID_PARAMETER;
6799 goto out;
6803 /* Open the src file for reading. */
6804 status = SMB_VFS_CREATE_FILE(
6805 conn, /* conn */
6806 NULL, /* req */
6807 0, /* root_dir_fid */
6808 smb_fname_src, /* fname */
6809 FILE_GENERIC_READ, /* access_mask */
6810 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6811 FILE_OPEN, /* create_disposition*/
6812 0, /* create_options */
6813 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6814 INTERNAL_OPEN_ONLY, /* oplock_request */
6815 0, /* allocation_size */
6816 0, /* private_flags */
6817 NULL, /* sd */
6818 NULL, /* ea_list */
6819 &fsp1, /* result */
6820 NULL); /* psbuf */
6822 if (!NT_STATUS_IS_OK(status)) {
6823 goto out;
6826 dosattrs = dos_mode(conn, smb_fname_src);
6828 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6829 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6832 /* Open the dst file for writing. */
6833 status = SMB_VFS_CREATE_FILE(
6834 conn, /* conn */
6835 NULL, /* req */
6836 0, /* root_dir_fid */
6837 smb_fname_dst, /* fname */
6838 FILE_GENERIC_WRITE, /* access_mask */
6839 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6840 new_create_disposition, /* create_disposition*/
6841 0, /* create_options */
6842 dosattrs, /* file_attributes */
6843 INTERNAL_OPEN_ONLY, /* oplock_request */
6844 0, /* allocation_size */
6845 0, /* private_flags */
6846 NULL, /* sd */
6847 NULL, /* ea_list */
6848 &fsp2, /* result */
6849 NULL); /* psbuf */
6851 if (!NT_STATUS_IS_OK(status)) {
6852 close_file(NULL, fsp1, ERROR_CLOSE);
6853 goto out;
6856 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6857 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6858 if (ret == -1) {
6859 DEBUG(0, ("error - vfs lseek returned error %s\n",
6860 strerror(errno)));
6861 status = map_nt_error_from_unix(errno);
6862 close_file(NULL, fsp1, ERROR_CLOSE);
6863 close_file(NULL, fsp2, ERROR_CLOSE);
6864 goto out;
6868 /* Do the actual copy. */
6869 if (smb_fname_src->st.st_ex_size) {
6870 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6871 } else {
6872 ret = 0;
6875 close_file(NULL, fsp1, NORMAL_CLOSE);
6877 /* Ensure the modtime is set correctly on the destination file. */
6878 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6881 * As we are opening fsp1 read-only we only expect
6882 * an error on close on fsp2 if we are out of space.
6883 * Thus we don't look at the error return from the
6884 * close of fsp1.
6886 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6888 if (!NT_STATUS_IS_OK(status)) {
6889 goto out;
6892 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6893 status = NT_STATUS_DISK_FULL;
6894 goto out;
6897 status = NT_STATUS_OK;
6899 out:
6900 TALLOC_FREE(smb_fname_dst_tmp);
6901 return status;
6904 /****************************************************************************
6905 Reply to a file copy.
6906 ****************************************************************************/
6908 void reply_copy(struct smb_request *req)
6910 connection_struct *conn = req->conn;
6911 struct smb_filename *smb_fname_src = NULL;
6912 struct smb_filename *smb_fname_dst = NULL;
6913 char *fname_src = NULL;
6914 char *fname_dst = NULL;
6915 char *fname_src_mask = NULL;
6916 char *fname_src_dir = NULL;
6917 const char *p;
6918 int count=0;
6919 int error = ERRnoaccess;
6920 int tid2;
6921 int ofun;
6922 int flags;
6923 bool target_is_directory=False;
6924 bool source_has_wild = False;
6925 bool dest_has_wild = False;
6926 NTSTATUS status;
6927 TALLOC_CTX *ctx = talloc_tos();
6929 START_PROFILE(SMBcopy);
6931 if (req->wct < 3) {
6932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6933 goto out;
6936 tid2 = SVAL(req->vwv+0, 0);
6937 ofun = SVAL(req->vwv+1, 0);
6938 flags = SVAL(req->vwv+2, 0);
6940 p = (const char *)req->buf;
6941 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6942 &status, &source_has_wild);
6943 if (!NT_STATUS_IS_OK(status)) {
6944 reply_nterror(req, status);
6945 goto out;
6947 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6948 &status, &dest_has_wild);
6949 if (!NT_STATUS_IS_OK(status)) {
6950 reply_nterror(req, status);
6951 goto out;
6954 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6956 if (tid2 != conn->cnum) {
6957 /* can't currently handle inter share copies XXXX */
6958 DEBUG(3,("Rejecting inter-share copy\n"));
6959 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6960 goto out;
6963 status = filename_convert(ctx, conn,
6964 req->flags2 & FLAGS2_DFS_PATHNAMES,
6965 fname_src,
6966 UCF_COND_ALLOW_WCARD_LCOMP,
6967 &source_has_wild,
6968 &smb_fname_src);
6969 if (!NT_STATUS_IS_OK(status)) {
6970 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6971 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6972 ERRSRV, ERRbadpath);
6973 goto out;
6975 reply_nterror(req, status);
6976 goto out;
6979 status = filename_convert(ctx, conn,
6980 req->flags2 & FLAGS2_DFS_PATHNAMES,
6981 fname_dst,
6982 UCF_COND_ALLOW_WCARD_LCOMP,
6983 &dest_has_wild,
6984 &smb_fname_dst);
6985 if (!NT_STATUS_IS_OK(status)) {
6986 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6987 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6988 ERRSRV, ERRbadpath);
6989 goto out;
6991 reply_nterror(req, status);
6992 goto out;
6995 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6997 if ((flags&1) && target_is_directory) {
6998 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6999 goto out;
7002 if ((flags&2) && !target_is_directory) {
7003 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7004 goto out;
7007 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7008 /* wants a tree copy! XXXX */
7009 DEBUG(3,("Rejecting tree copy\n"));
7010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7011 goto out;
7014 /* Split up the directory from the filename/mask. */
7015 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7016 &fname_src_dir, &fname_src_mask);
7017 if (!NT_STATUS_IS_OK(status)) {
7018 reply_nterror(req, NT_STATUS_NO_MEMORY);
7019 goto out;
7023 * We should only check the mangled cache
7024 * here if unix_convert failed. This means
7025 * that the path in 'mask' doesn't exist
7026 * on the file system and so we need to look
7027 * for a possible mangle. This patch from
7028 * Tine Smukavec <valentin.smukavec@hermes.si>.
7030 if (!VALID_STAT(smb_fname_src->st) &&
7031 mangle_is_mangled(fname_src_mask, conn->params)) {
7032 char *new_mask = NULL;
7033 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7034 &new_mask, conn->params);
7036 /* Use demangled name if one was successfully found. */
7037 if (new_mask) {
7038 TALLOC_FREE(fname_src_mask);
7039 fname_src_mask = new_mask;
7043 if (!source_has_wild) {
7046 * Only one file needs to be copied. Append the mask back onto
7047 * the directory.
7049 TALLOC_FREE(smb_fname_src->base_name);
7050 if (ISDOT(fname_src_dir)) {
7051 /* Ensure we use canonical names on open. */
7052 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7053 "%s",
7054 fname_src_mask);
7055 } else {
7056 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7057 "%s/%s",
7058 fname_src_dir,
7059 fname_src_mask);
7061 if (!smb_fname_src->base_name) {
7062 reply_nterror(req, NT_STATUS_NO_MEMORY);
7063 goto out;
7066 if (dest_has_wild) {
7067 char *fname_dst_mod = NULL;
7068 if (!resolve_wildcards(smb_fname_dst,
7069 smb_fname_src->base_name,
7070 smb_fname_dst->base_name,
7071 &fname_dst_mod)) {
7072 reply_nterror(req, NT_STATUS_NO_MEMORY);
7073 goto out;
7075 TALLOC_FREE(smb_fname_dst->base_name);
7076 smb_fname_dst->base_name = fname_dst_mod;
7079 status = check_name(conn, smb_fname_src->base_name);
7080 if (!NT_STATUS_IS_OK(status)) {
7081 reply_nterror(req, status);
7082 goto out;
7085 status = check_name(conn, smb_fname_dst->base_name);
7086 if (!NT_STATUS_IS_OK(status)) {
7087 reply_nterror(req, status);
7088 goto out;
7091 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7092 ofun, count, target_is_directory);
7094 if(!NT_STATUS_IS_OK(status)) {
7095 reply_nterror(req, status);
7096 goto out;
7097 } else {
7098 count++;
7100 } else {
7101 struct smb_Dir *dir_hnd = NULL;
7102 const char *dname = NULL;
7103 char *talloced = NULL;
7104 long offset = 0;
7107 * There is a wildcard that requires us to actually read the
7108 * src dir and copy each file matching the mask to the dst.
7109 * Right now streams won't be copied, but this could
7110 * presumably be added with a nested loop for reach dir entry.
7112 SMB_ASSERT(!smb_fname_src->stream_name);
7113 SMB_ASSERT(!smb_fname_dst->stream_name);
7115 smb_fname_src->stream_name = NULL;
7116 smb_fname_dst->stream_name = NULL;
7118 if (strequal(fname_src_mask,"????????.???")) {
7119 TALLOC_FREE(fname_src_mask);
7120 fname_src_mask = talloc_strdup(ctx, "*");
7121 if (!fname_src_mask) {
7122 reply_nterror(req, NT_STATUS_NO_MEMORY);
7123 goto out;
7127 status = check_name(conn, fname_src_dir);
7128 if (!NT_STATUS_IS_OK(status)) {
7129 reply_nterror(req, status);
7130 goto out;
7133 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7134 if (dir_hnd == NULL) {
7135 status = map_nt_error_from_unix(errno);
7136 reply_nterror(req, status);
7137 goto out;
7140 error = ERRbadfile;
7142 /* Iterate over the src dir copying each entry to the dst. */
7143 while ((dname = ReadDirName(dir_hnd, &offset,
7144 &smb_fname_src->st, &talloced))) {
7145 char *destname = NULL;
7147 if (ISDOT(dname) || ISDOTDOT(dname)) {
7148 TALLOC_FREE(talloced);
7149 continue;
7152 if (!is_visible_file(conn, fname_src_dir, dname,
7153 &smb_fname_src->st, false)) {
7154 TALLOC_FREE(talloced);
7155 continue;
7158 if(!mask_match(dname, fname_src_mask,
7159 conn->case_sensitive)) {
7160 TALLOC_FREE(talloced);
7161 continue;
7164 error = ERRnoaccess;
7166 /* Get the src smb_fname struct setup. */
7167 TALLOC_FREE(smb_fname_src->base_name);
7168 if (ISDOT(fname_src_dir)) {
7169 /* Ensure we use canonical names on open. */
7170 smb_fname_src->base_name =
7171 talloc_asprintf(smb_fname_src, "%s",
7172 dname);
7173 } else {
7174 smb_fname_src->base_name =
7175 talloc_asprintf(smb_fname_src, "%s/%s",
7176 fname_src_dir, dname);
7179 if (!smb_fname_src->base_name) {
7180 TALLOC_FREE(dir_hnd);
7181 TALLOC_FREE(talloced);
7182 reply_nterror(req, NT_STATUS_NO_MEMORY);
7183 goto out;
7186 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7187 smb_fname_dst->base_name,
7188 &destname)) {
7189 TALLOC_FREE(talloced);
7190 continue;
7192 if (!destname) {
7193 TALLOC_FREE(dir_hnd);
7194 TALLOC_FREE(talloced);
7195 reply_nterror(req, NT_STATUS_NO_MEMORY);
7196 goto out;
7199 TALLOC_FREE(smb_fname_dst->base_name);
7200 smb_fname_dst->base_name = destname;
7202 status = check_name(conn, smb_fname_src->base_name);
7203 if (!NT_STATUS_IS_OK(status)) {
7204 TALLOC_FREE(dir_hnd);
7205 TALLOC_FREE(talloced);
7206 reply_nterror(req, status);
7207 goto out;
7210 status = check_name(conn, smb_fname_dst->base_name);
7211 if (!NT_STATUS_IS_OK(status)) {
7212 TALLOC_FREE(dir_hnd);
7213 TALLOC_FREE(talloced);
7214 reply_nterror(req, status);
7215 goto out;
7218 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7219 smb_fname_src->base_name,
7220 smb_fname_dst->base_name));
7222 status = copy_file(ctx, conn, smb_fname_src,
7223 smb_fname_dst, ofun, count,
7224 target_is_directory);
7225 if (NT_STATUS_IS_OK(status)) {
7226 count++;
7229 TALLOC_FREE(talloced);
7231 TALLOC_FREE(dir_hnd);
7234 if (count == 0) {
7235 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7236 goto out;
7239 reply_outbuf(req, 1, 0);
7240 SSVAL(req->outbuf,smb_vwv0,count);
7241 out:
7242 TALLOC_FREE(smb_fname_src);
7243 TALLOC_FREE(smb_fname_dst);
7244 TALLOC_FREE(fname_src);
7245 TALLOC_FREE(fname_dst);
7246 TALLOC_FREE(fname_src_mask);
7247 TALLOC_FREE(fname_src_dir);
7249 END_PROFILE(SMBcopy);
7250 return;
7253 #undef DBGC_CLASS
7254 #define DBGC_CLASS DBGC_LOCKING
7256 /****************************************************************************
7257 Get a lock pid, dealing with large count requests.
7258 ****************************************************************************/
7260 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7261 bool large_file_format)
7263 if(!large_file_format)
7264 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7265 else
7266 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7269 /****************************************************************************
7270 Get a lock count, dealing with large count requests.
7271 ****************************************************************************/
7273 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7274 bool large_file_format)
7276 uint64_t count = 0;
7278 if(!large_file_format) {
7279 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7280 } else {
7282 #if defined(HAVE_LONGLONG)
7283 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7284 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7285 #else /* HAVE_LONGLONG */
7288 * NT4.x seems to be broken in that it sends large file (64 bit)
7289 * lockingX calls even if the CAP_LARGE_FILES was *not*
7290 * negotiated. For boxes without large unsigned ints truncate the
7291 * lock count by dropping the top 32 bits.
7294 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7295 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7296 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7297 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7298 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7301 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7302 #endif /* HAVE_LONGLONG */
7305 return count;
7308 #if !defined(HAVE_LONGLONG)
7309 /****************************************************************************
7310 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7311 ****************************************************************************/
7313 static uint32 map_lock_offset(uint32 high, uint32 low)
7315 unsigned int i;
7316 uint32 mask = 0;
7317 uint32 highcopy = high;
7320 * Try and find out how many significant bits there are in high.
7323 for(i = 0; highcopy; i++)
7324 highcopy >>= 1;
7327 * We use 31 bits not 32 here as POSIX
7328 * lock offsets may not be negative.
7331 mask = (~0) << (31 - i);
7333 if(low & mask)
7334 return 0; /* Fail. */
7336 high <<= (31 - i);
7338 return (high|low);
7340 #endif /* !defined(HAVE_LONGLONG) */
7342 /****************************************************************************
7343 Get a lock offset, dealing with large offset requests.
7344 ****************************************************************************/
7346 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7347 bool large_file_format, bool *err)
7349 uint64_t offset = 0;
7351 *err = False;
7353 if(!large_file_format) {
7354 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7355 } else {
7357 #if defined(HAVE_LONGLONG)
7358 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7359 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7360 #else /* HAVE_LONGLONG */
7363 * NT4.x seems to be broken in that it sends large file (64 bit)
7364 * lockingX calls even if the CAP_LARGE_FILES was *not*
7365 * negotiated. For boxes without large unsigned ints mangle the
7366 * lock offset by mapping the top 32 bits onto the lower 32.
7369 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7370 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7371 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7372 uint32 new_low = 0;
7374 if((new_low = map_lock_offset(high, low)) == 0) {
7375 *err = True;
7376 return (uint64_t)-1;
7379 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7380 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7381 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7382 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7385 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7386 #endif /* HAVE_LONGLONG */
7389 return offset;
7392 NTSTATUS smbd_do_locking(struct smb_request *req,
7393 files_struct *fsp,
7394 uint8_t type,
7395 int32_t timeout,
7396 uint16_t num_ulocks,
7397 struct smbd_lock_element *ulocks,
7398 uint16_t num_locks,
7399 struct smbd_lock_element *locks,
7400 bool *async)
7402 connection_struct *conn = req->conn;
7403 int i;
7404 NTSTATUS status = NT_STATUS_OK;
7406 *async = false;
7408 /* Data now points at the beginning of the list
7409 of smb_unlkrng structs */
7410 for(i = 0; i < (int)num_ulocks; i++) {
7411 struct smbd_lock_element *e = &ulocks[i];
7413 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7414 "pid %u, file %s\n",
7415 (double)e->offset,
7416 (double)e->count,
7417 (unsigned int)e->smblctx,
7418 fsp_str_dbg(fsp)));
7420 if (e->brltype != UNLOCK_LOCK) {
7421 /* this can only happen with SMB2 */
7422 return NT_STATUS_INVALID_PARAMETER;
7425 status = do_unlock(req->sconn->msg_ctx,
7426 fsp,
7427 e->smblctx,
7428 e->count,
7429 e->offset,
7430 WINDOWS_LOCK);
7432 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7433 nt_errstr(status)));
7435 if (!NT_STATUS_IS_OK(status)) {
7436 return status;
7440 /* Setup the timeout in seconds. */
7442 if (!lp_blocking_locks(SNUM(conn))) {
7443 timeout = 0;
7446 /* Data now points at the beginning of the list
7447 of smb_lkrng structs */
7449 for(i = 0; i < (int)num_locks; i++) {
7450 struct smbd_lock_element *e = &locks[i];
7452 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7453 "%llu, file %s timeout = %d\n",
7454 (double)e->offset,
7455 (double)e->count,
7456 (unsigned long long)e->smblctx,
7457 fsp_str_dbg(fsp),
7458 (int)timeout));
7460 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7461 struct blocking_lock_record *blr = NULL;
7463 if (num_locks > 1) {
7465 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7466 * if the lock vector contains one entry. When given mutliple cancel
7467 * requests in a single PDU we expect the server to return an
7468 * error. Windows servers seem to accept the request but only
7469 * cancel the first lock.
7470 * JRA - Do what Windows does (tm) :-).
7473 #if 0
7474 /* MS-CIFS (2.2.4.32.1) behavior. */
7475 return NT_STATUS_DOS(ERRDOS,
7476 ERRcancelviolation);
7477 #else
7478 /* Windows behavior. */
7479 if (i != 0) {
7480 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7481 "cancel request\n"));
7482 continue;
7484 #endif
7487 if (lp_blocking_locks(SNUM(conn))) {
7489 /* Schedule a message to ourselves to
7490 remove the blocking lock record and
7491 return the right error. */
7493 blr = blocking_lock_cancel_smb1(fsp,
7494 e->smblctx,
7495 e->offset,
7496 e->count,
7497 WINDOWS_LOCK,
7498 type,
7499 NT_STATUS_FILE_LOCK_CONFLICT);
7500 if (blr == NULL) {
7501 return NT_STATUS_DOS(
7502 ERRDOS,
7503 ERRcancelviolation);
7506 /* Remove a matching pending lock. */
7507 status = do_lock_cancel(fsp,
7508 e->smblctx,
7509 e->count,
7510 e->offset,
7511 WINDOWS_LOCK,
7512 blr);
7513 } else {
7514 bool blocking_lock = timeout ? true : false;
7515 bool defer_lock = false;
7516 struct byte_range_lock *br_lck;
7517 uint64_t block_smblctx;
7519 br_lck = do_lock(req->sconn->msg_ctx,
7520 fsp,
7521 e->smblctx,
7522 e->count,
7523 e->offset,
7524 e->brltype,
7525 WINDOWS_LOCK,
7526 blocking_lock,
7527 &status,
7528 &block_smblctx,
7529 NULL);
7531 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7532 /* Windows internal resolution for blocking locks seems
7533 to be about 200ms... Don't wait for less than that. JRA. */
7534 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7535 timeout = lp_lock_spin_time();
7537 defer_lock = true;
7540 /* If a lock sent with timeout of zero would fail, and
7541 * this lock has been requested multiple times,
7542 * according to brl_lock_failed() we convert this
7543 * request to a blocking lock with a timeout of between
7544 * 150 - 300 milliseconds.
7546 * If lp_lock_spin_time() has been set to 0, we skip
7547 * this blocking retry and fail immediately.
7549 * Replacement for do_lock_spin(). JRA. */
7551 if (!req->sconn->using_smb2 &&
7552 br_lck && lp_blocking_locks(SNUM(conn)) &&
7553 lp_lock_spin_time() && !blocking_lock &&
7554 NT_STATUS_EQUAL((status),
7555 NT_STATUS_FILE_LOCK_CONFLICT))
7557 defer_lock = true;
7558 timeout = lp_lock_spin_time();
7561 if (br_lck && defer_lock) {
7563 * A blocking lock was requested. Package up
7564 * this smb into a queued request and push it
7565 * onto the blocking lock queue.
7567 if(push_blocking_lock_request(br_lck,
7568 req,
7569 fsp,
7570 timeout,
7572 e->smblctx,
7573 e->brltype,
7574 WINDOWS_LOCK,
7575 e->offset,
7576 e->count,
7577 block_smblctx)) {
7578 TALLOC_FREE(br_lck);
7579 *async = true;
7580 return NT_STATUS_OK;
7584 TALLOC_FREE(br_lck);
7587 if (!NT_STATUS_IS_OK(status)) {
7588 break;
7592 /* If any of the above locks failed, then we must unlock
7593 all of the previous locks (X/Open spec). */
7595 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7597 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7598 i = -1; /* we want to skip the for loop */
7602 * Ensure we don't do a remove on the lock that just failed,
7603 * as under POSIX rules, if we have a lock already there, we
7604 * will delete it (and we shouldn't) .....
7606 for(i--; i >= 0; i--) {
7607 struct smbd_lock_element *e = &locks[i];
7609 do_unlock(req->sconn->msg_ctx,
7610 fsp,
7611 e->smblctx,
7612 e->count,
7613 e->offset,
7614 WINDOWS_LOCK);
7616 return status;
7619 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7620 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7622 return NT_STATUS_OK;
7625 /****************************************************************************
7626 Reply to a lockingX request.
7627 ****************************************************************************/
7629 void reply_lockingX(struct smb_request *req)
7631 connection_struct *conn = req->conn;
7632 files_struct *fsp;
7633 unsigned char locktype;
7634 unsigned char oplocklevel;
7635 uint16 num_ulocks;
7636 uint16 num_locks;
7637 int32 lock_timeout;
7638 int i;
7639 const uint8_t *data;
7640 bool large_file_format;
7641 bool err;
7642 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7643 struct smbd_lock_element *ulocks;
7644 struct smbd_lock_element *locks;
7645 bool async = false;
7647 START_PROFILE(SMBlockingX);
7649 if (req->wct < 8) {
7650 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7651 END_PROFILE(SMBlockingX);
7652 return;
7655 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7656 locktype = CVAL(req->vwv+3, 0);
7657 oplocklevel = CVAL(req->vwv+3, 1);
7658 num_ulocks = SVAL(req->vwv+6, 0);
7659 num_locks = SVAL(req->vwv+7, 0);
7660 lock_timeout = IVAL(req->vwv+4, 0);
7661 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7663 if (!check_fsp(conn, req, fsp)) {
7664 END_PROFILE(SMBlockingX);
7665 return;
7668 data = req->buf;
7670 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7671 /* we don't support these - and CANCEL_LOCK makes w2k
7672 and XP reboot so I don't really want to be
7673 compatible! (tridge) */
7674 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7675 END_PROFILE(SMBlockingX);
7676 return;
7679 /* Check if this is an oplock break on a file
7680 we have granted an oplock on.
7682 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7683 /* Client can insist on breaking to none. */
7684 bool break_to_none = (oplocklevel == 0);
7685 bool result;
7687 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7688 "for fnum = %d\n", (unsigned int)oplocklevel,
7689 fsp->fnum ));
7692 * Make sure we have granted an exclusive or batch oplock on
7693 * this file.
7696 if (fsp->oplock_type == 0) {
7698 /* The Samba4 nbench simulator doesn't understand
7699 the difference between break to level2 and break
7700 to none from level2 - it sends oplock break
7701 replies in both cases. Don't keep logging an error
7702 message here - just ignore it. JRA. */
7704 DEBUG(5,("reply_lockingX: Error : oplock break from "
7705 "client for fnum = %d (oplock=%d) and no "
7706 "oplock granted on this file (%s).\n",
7707 fsp->fnum, fsp->oplock_type,
7708 fsp_str_dbg(fsp)));
7710 /* if this is a pure oplock break request then don't
7711 * send a reply */
7712 if (num_locks == 0 && num_ulocks == 0) {
7713 END_PROFILE(SMBlockingX);
7714 return;
7715 } else {
7716 END_PROFILE(SMBlockingX);
7717 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7718 return;
7722 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7723 (break_to_none)) {
7724 result = remove_oplock(fsp);
7725 } else {
7726 result = downgrade_oplock(fsp);
7729 if (!result) {
7730 DEBUG(0, ("reply_lockingX: error in removing "
7731 "oplock on file %s\n", fsp_str_dbg(fsp)));
7732 /* Hmmm. Is this panic justified? */
7733 smb_panic("internal tdb error");
7736 reply_to_oplock_break_requests(fsp);
7738 /* if this is a pure oplock break request then don't send a
7739 * reply */
7740 if (num_locks == 0 && num_ulocks == 0) {
7741 /* Sanity check - ensure a pure oplock break is not a
7742 chained request. */
7743 if(CVAL(req->vwv+0, 0) != 0xff)
7744 DEBUG(0,("reply_lockingX: Error : pure oplock "
7745 "break is a chained %d request !\n",
7746 (unsigned int)CVAL(req->vwv+0, 0)));
7747 END_PROFILE(SMBlockingX);
7748 return;
7752 if (req->buflen <
7753 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7755 END_PROFILE(SMBlockingX);
7756 return;
7759 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7760 if (ulocks == NULL) {
7761 reply_nterror(req, NT_STATUS_NO_MEMORY);
7762 END_PROFILE(SMBlockingX);
7763 return;
7766 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7767 if (locks == NULL) {
7768 reply_nterror(req, NT_STATUS_NO_MEMORY);
7769 END_PROFILE(SMBlockingX);
7770 return;
7773 /* Data now points at the beginning of the list
7774 of smb_unlkrng structs */
7775 for(i = 0; i < (int)num_ulocks; i++) {
7776 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7777 ulocks[i].count = get_lock_count(data, i, large_file_format);
7778 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7779 ulocks[i].brltype = UNLOCK_LOCK;
7782 * There is no error code marked "stupid client bug".... :-).
7784 if(err) {
7785 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7786 END_PROFILE(SMBlockingX);
7787 return;
7791 /* Now do any requested locks */
7792 data += ((large_file_format ? 20 : 10)*num_ulocks);
7794 /* Data now points at the beginning of the list
7795 of smb_lkrng structs */
7797 for(i = 0; i < (int)num_locks; i++) {
7798 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7799 locks[i].count = get_lock_count(data, i, large_file_format);
7800 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7802 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7803 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7804 locks[i].brltype = PENDING_READ_LOCK;
7805 } else {
7806 locks[i].brltype = READ_LOCK;
7808 } else {
7809 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7810 locks[i].brltype = PENDING_WRITE_LOCK;
7811 } else {
7812 locks[i].brltype = WRITE_LOCK;
7817 * There is no error code marked "stupid client bug".... :-).
7819 if(err) {
7820 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7821 END_PROFILE(SMBlockingX);
7822 return;
7826 status = smbd_do_locking(req, fsp,
7827 locktype, lock_timeout,
7828 num_ulocks, ulocks,
7829 num_locks, locks,
7830 &async);
7831 if (!NT_STATUS_IS_OK(status)) {
7832 END_PROFILE(SMBlockingX);
7833 reply_nterror(req, status);
7834 return;
7836 if (async) {
7837 END_PROFILE(SMBlockingX);
7838 return;
7841 reply_outbuf(req, 2, 0);
7842 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
7843 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
7845 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7846 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7848 END_PROFILE(SMBlockingX);
7851 #undef DBGC_CLASS
7852 #define DBGC_CLASS DBGC_ALL
7854 /****************************************************************************
7855 Reply to a SMBreadbmpx (read block multiplex) request.
7856 Always reply with an error, if someone has a platform really needs this,
7857 please contact vl@samba.org
7858 ****************************************************************************/
7860 void reply_readbmpx(struct smb_request *req)
7862 START_PROFILE(SMBreadBmpx);
7863 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7864 END_PROFILE(SMBreadBmpx);
7865 return;
7868 /****************************************************************************
7869 Reply to a SMBreadbs (read block multiplex secondary) request.
7870 Always reply with an error, if someone has a platform really needs this,
7871 please contact vl@samba.org
7872 ****************************************************************************/
7874 void reply_readbs(struct smb_request *req)
7876 START_PROFILE(SMBreadBs);
7877 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7878 END_PROFILE(SMBreadBs);
7879 return;
7882 /****************************************************************************
7883 Reply to a SMBsetattrE.
7884 ****************************************************************************/
7886 void reply_setattrE(struct smb_request *req)
7888 connection_struct *conn = req->conn;
7889 struct smb_file_time ft;
7890 files_struct *fsp;
7891 NTSTATUS status;
7893 START_PROFILE(SMBsetattrE);
7894 ZERO_STRUCT(ft);
7896 if (req->wct < 7) {
7897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7898 goto out;
7901 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7903 if(!fsp || (fsp->conn != conn)) {
7904 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7905 goto out;
7909 * Convert the DOS times into unix times.
7912 ft.atime = convert_time_t_to_timespec(
7913 srv_make_unix_date2(req->vwv+3));
7914 ft.mtime = convert_time_t_to_timespec(
7915 srv_make_unix_date2(req->vwv+5));
7916 ft.create_time = convert_time_t_to_timespec(
7917 srv_make_unix_date2(req->vwv+1));
7919 reply_outbuf(req, 0, 0);
7922 * Patch from Ray Frush <frush@engr.colostate.edu>
7923 * Sometimes times are sent as zero - ignore them.
7926 /* Ensure we have a valid stat struct for the source. */
7927 status = vfs_stat_fsp(fsp);
7928 if (!NT_STATUS_IS_OK(status)) {
7929 reply_nterror(req, status);
7930 goto out;
7933 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7934 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7935 goto out;
7938 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7939 if (!NT_STATUS_IS_OK(status)) {
7940 reply_nterror(req, status);
7941 goto out;
7944 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7945 " createtime=%u\n",
7946 fsp->fnum,
7947 (unsigned int)ft.atime.tv_sec,
7948 (unsigned int)ft.mtime.tv_sec,
7949 (unsigned int)ft.create_time.tv_sec
7951 out:
7952 END_PROFILE(SMBsetattrE);
7953 return;
7957 /* Back from the dead for OS/2..... JRA. */
7959 /****************************************************************************
7960 Reply to a SMBwritebmpx (write block multiplex primary) request.
7961 Always reply with an error, if someone has a platform really needs this,
7962 please contact vl@samba.org
7963 ****************************************************************************/
7965 void reply_writebmpx(struct smb_request *req)
7967 START_PROFILE(SMBwriteBmpx);
7968 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7969 END_PROFILE(SMBwriteBmpx);
7970 return;
7973 /****************************************************************************
7974 Reply to a SMBwritebs (write block multiplex secondary) request.
7975 Always reply with an error, if someone has a platform really needs this,
7976 please contact vl@samba.org
7977 ****************************************************************************/
7979 void reply_writebs(struct smb_request *req)
7981 START_PROFILE(SMBwriteBs);
7982 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7983 END_PROFILE(SMBwriteBs);
7984 return;
7987 /****************************************************************************
7988 Reply to a SMBgetattrE.
7989 ****************************************************************************/
7991 void reply_getattrE(struct smb_request *req)
7993 connection_struct *conn = req->conn;
7994 int mode;
7995 files_struct *fsp;
7996 struct timespec create_ts;
7998 START_PROFILE(SMBgetattrE);
8000 if (req->wct < 1) {
8001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8002 END_PROFILE(SMBgetattrE);
8003 return;
8006 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8008 if(!fsp || (fsp->conn != conn)) {
8009 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8010 END_PROFILE(SMBgetattrE);
8011 return;
8014 /* Do an fstat on this file */
8015 if(fsp_stat(fsp)) {
8016 reply_nterror(req, map_nt_error_from_unix(errno));
8017 END_PROFILE(SMBgetattrE);
8018 return;
8021 mode = dos_mode(conn, fsp->fsp_name);
8024 * Convert the times into dos times. Set create
8025 * date to be last modify date as UNIX doesn't save
8026 * this.
8029 reply_outbuf(req, 11, 0);
8031 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8032 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8033 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8034 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8035 /* Should we check pending modtime here ? JRA */
8036 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8037 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8039 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8040 SIVAL(req->outbuf, smb_vwv6, 0);
8041 SIVAL(req->outbuf, smb_vwv8, 0);
8042 } else {
8043 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8044 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8045 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8047 SSVAL(req->outbuf,smb_vwv10, mode);
8049 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8051 END_PROFILE(SMBgetattrE);
8052 return;