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
28 #include "system/filesys.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"
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
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
,
58 bool *p_last_component_contains_wcard
)
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
;
73 return NT_STATUS_OBJECT_NAME_INVALID
;
76 return NT_STATUS_OBJECT_NAME_INVALID
;
78 if (strchr_m(&s
[1], ':')) {
79 return NT_STATUS_OBJECT_NAME_INVALID
;
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.
95 stream_started
= true;
96 start_of_name_component
= false;
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
)) {
113 if ((d
!= path
) && (*s
!= '\0')) {
114 /* We only care about non-leading or trailing '/' or '\\' */
118 start_of_name_component
= True
;
120 *p_last_component_contains_wcard
= False
;
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) == '/')) {
138 /* Are we at the start ? Can't go back further if so. */
140 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
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
--) {
151 s
+= 2; /* Else go past the .. */
152 /* We're still at the start of a name component, just the previous one. */
155 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
167 if (*s
<= 0x1f || *s
== '|') {
168 return NT_STATUS_OBJECT_NAME_INVALID
;
176 *p_last_component_contains_wcard
= True
;
185 /* Get the size of the next MB character. */
186 next_codepoint(s
,&siz
);
204 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
206 return NT_STATUS_INVALID_PARAMETER
;
209 start_of_name_component
= False
;
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
)
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
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
)
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
,
263 bool *contains_wcard
)
269 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
273 *err
= NT_STATUS_INVALID_PARAMETER
;
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.
288 if (lp_posix_pathnames()) {
289 *err
= check_path_syntax_posix(*pp_dest
);
291 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
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
,
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
,
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
,
340 if ((fsp
== NULL
) || (conn
== NULL
)) {
341 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
344 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
345 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
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
,
358 if (!check_fsp_open(conn
, req
, fsp
)) {
361 if (fsp
->is_directory
) {
362 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
365 if (fsp
->fh
->fd
== -1) {
366 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
369 fsp
->num_smb_operations
++;
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
,
381 if (!check_fsp_open(conn
, req
, fsp
)) {
385 if (fsp
->is_directory
) {
389 if (fsp
->fake_file_handle
== NULL
) {
393 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
397 if (fsp
->fake_file_handle
->private_data
== NULL
) {
404 static bool netbios_session_retarget(struct smbd_server_connection
*sconn
,
405 const char *name
, int name_type
)
408 char *trim_name_type
;
409 const char *retarget_parm
;
412 int retarget_type
= 0x20;
413 int retarget_port
= NBT_SMB_PORT
;
414 struct sockaddr_storage retarget_addr
;
415 struct sockaddr_in
*in_addr
;
419 if (get_socket_port(sconn
->sock
) != NBT_SMB_PORT
) {
423 trim_name
= talloc_strdup(talloc_tos(), name
);
424 if (trim_name
== NULL
) {
427 trim_char(trim_name
, ' ', ' ');
429 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
431 if (trim_name_type
== NULL
) {
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",
441 if (retarget_parm
== NULL
) {
445 retarget
= talloc_strdup(trim_name
, retarget_parm
);
446 if (retarget
== NULL
) {
450 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
452 p
= strchr(retarget
, ':');
455 retarget_port
= atoi(p
);
458 p
= strchr_m(retarget
, '#');
461 if (sscanf(p
, "%x", &retarget_type
) != 1) {
466 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
468 DEBUG(10, ("could not resolve %s\n", retarget
));
472 if (retarget_addr
.ss_family
!= AF_INET
) {
473 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
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,
486 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
492 TALLOC_FREE(trim_name
);
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
516 char outbuf
[smb_size
];
518 memset(outbuf
, '\0', sizeof(outbuf
));
520 smb_setlen(outbuf
,0);
523 case NBSSrequest
: /* session request */
525 /* inbuf_size is guarenteed to be at least 4. */
527 int name_type1
, name_type2
;
528 int name_len1
, name_len2
;
532 if (sconn
->nbt
.got_session
) {
533 exit_server_cleanly("multiple session request not permitted");
536 SCVAL(outbuf
,0,NBSSpositive
);
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
);
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
);
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
);
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 ")) {
579 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
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(),
595 if (name_type2
== 'R') {
596 /* We are being asked for a pathworks session ---
598 reply_called_name_not_present(outbuf
);
602 reload_services(sconn
, conn_snum_used
, true);
605 sconn
->nbt
.got_session
= true;
609 case 0x89: /* session keepalive request
610 (some old clients produce this?) */
611 SCVAL(outbuf
,0,NBSSkeepalive
);
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"));
621 case NBSSkeepalive
: /* session keepalive */
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");
637 /****************************************************************************
639 conn POINTER CAN BE NULL HERE !
640 ****************************************************************************/
642 void reply_tcon(struct smb_request
*req
)
644 connection_struct
*conn
= req
->conn
;
646 char *service_buf
= NULL
;
647 char *password
= NULL
;
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
);
663 p
= (const char *)req
->buf
+ 1;
664 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
666 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
668 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
671 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
672 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
673 END_PROFILE(SMBtcon
);
676 p
= strrchr_m(service_buf
,'\\');
680 service
= service_buf
;
683 conn
= make_connection(sconn
,service
,dev
,
684 req
->vuid
,&nt_status
);
688 reply_nterror(req
, nt_status
);
689 END_PROFILE(SMBtcon
);
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
);
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
;
724 struct smbd_server_connection
*sconn
= req
->sconn
;
726 START_PROFILE(SMBtconX
);
729 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
730 END_PROFILE(SMBtconX
);
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
);
744 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
745 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
746 END_PROFILE(SMBtconX
);
750 if (sconn
->smb1
.negprot
.encrypted_passwords
) {
751 p
= (const char *)req
->buf
+ passlen
;
753 p
= (const char *)req
->buf
+ passlen
+ 1;
756 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
759 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
760 END_PROFILE(SMBtconX
);
765 * the service name can be either: \\server\share
766 * or share directly like on the DELL PowerVault 705
769 q
= strchr_m(path
+2,'\\');
771 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
772 END_PROFILE(SMBtconX
);
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
);
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
);
797 reply_nterror(req
, nt_status
);
798 END_PROFILE(SMBtconX
);
803 server_devicetype
= "IPC";
804 else if ( IS_PRINT(conn
) )
805 server_devicetype
= "LPT1:";
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
);
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. */
826 reply_outbuf(req
, 7, 0);
829 perm1
= FILE_ALL_ACCESS
;
830 perm2
= FILE_ALL_ACCESS
;
832 perm1
= conn
->share_access
;
835 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
836 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
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
);
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",
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
);
890 /****************************************************************************
892 conn POINTER CAN BE NULL HERE !
893 ****************************************************************************/
895 void reply_ioctl(struct smb_request
*req
)
897 connection_struct
*conn
= req
->conn
;
904 START_PROFILE(SMBioctl
);
907 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
908 END_PROFILE(SMBioctl
);
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
:
923 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
924 END_PROFILE(SMBioctl
);
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));
942 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
943 END_PROFILE(SMBioctl
);
947 if (fsp
->print_file
) {
948 SSVAL(p
, 0, fsp
->print_file
->rap_jobid
);
952 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
953 lp_netbios_name(), 15,
954 STR_TERMINATE
|STR_ASCII
);
956 srvstr_push((char *)req
->outbuf
, req
->flags2
,
957 p
+18, lp_servicename(SNUM(conn
)),
958 13, STR_TERMINATE
|STR_ASCII
);
966 END_PROFILE(SMBioctl
);
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
;
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
;
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
);
1010 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1012 status
= filename_convert(ctx
,
1014 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
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
);
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
);
1038 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1039 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1040 ERRDOS
, ERRbadpath
);
1044 reply_outbuf(req
, 0, 0);
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
);
1066 reply_nterror(req
, status
);
1069 TALLOC_FREE(smb_fname
);
1070 END_PROFILE(SMBcheckpath
);
1074 /****************************************************************************
1076 ****************************************************************************/
1078 void reply_getatr(struct smb_request
*req
)
1080 connection_struct
*conn
= req
->conn
;
1081 struct smb_filename
*smb_fname
= NULL
;
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
);
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
;
1110 status
= filename_convert(ctx
,
1112 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
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
);
1123 reply_nterror(req
, status
);
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
),
1131 reply_nterror(req
, map_nt_error_from_unix(errno
));
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
) {
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);
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
));
1175 TALLOC_FREE(smb_fname
);
1177 END_PROFILE(SMBgetatr
);
1181 /****************************************************************************
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
;
1195 TALLOC_CTX
*ctx
= talloc_tos();
1197 START_PROFILE(SMBsetatr
);
1202 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
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
);
1213 status
= filename_convert(ctx
,
1215 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
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
);
1226 reply_nterror(req
, status
);
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
);
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
;
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
);
1256 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1258 reply_nterror(req
, map_nt_error_from_unix(errno
));
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
);
1270 reply_outbuf(req
, 0, 0);
1272 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1275 TALLOC_FREE(smb_fname
);
1276 END_PROFILE(SMBsetatr
);
1280 /****************************************************************************
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
);
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
);
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
);
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
, '/');
1345 fname_dir
= talloc_strdup(ctx
, ".");
1346 fname_mask
= talloc_strdup(ctx
, fname_in
);
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 /****************************************************************************
1366 Can be called from SMBsearch, SMBffirst or SMBfunique.
1367 ****************************************************************************/
1369 void reply_search(struct smb_request
*req
)
1371 connection_struct
*conn
= req
->conn
;
1373 const char *mask
= NULL
;
1374 char *directory
= NULL
;
1375 struct smb_filename
*smb_fname
= NULL
;
1379 struct timespec date
;
1381 unsigned int numentries
= 0;
1382 unsigned int maxentries
= 0;
1383 bool finished
= False
;
1388 bool check_descend
= False
;
1389 bool expect_close
= False
;
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
);
1401 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1405 if (lp_posix_pathnames()) {
1406 reply_unknown_new(req
, req
->cmd
);
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
);
1427 status_len
= SVAL(p
, 0);
1430 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1432 if (status_len
== 0) {
1433 nt_status
= filename_convert(ctx
, conn
,
1434 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1436 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1437 &mask_contains_wcard
,
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
);
1445 reply_nterror(req
, nt_status
);
1449 directory
= smb_fname
->base_name
;
1451 p
= strrchr_m(directory
,'/');
1452 if ((p
!= NULL
) && (*directory
!= '/')) {
1454 directory
= talloc_strndup(ctx
, directory
,
1455 PTR_DIFF(p
, directory
));
1458 directory
= talloc_strdup(ctx
,".");
1462 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1466 memset((char *)status
,'\0',21);
1467 SCVAL(status
,0,(dirtype
& 0x1F));
1469 nt_status
= dptr_create(conn
,
1477 mask_contains_wcard
,
1480 if (!NT_STATUS_IS_OK(nt_status
)) {
1481 reply_nterror(req
, nt_status
);
1484 dptr_num
= dptr_dnum(dirptr
);
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
);
1499 dirpath
= dptr_path(sconn
, dptr_num
);
1500 directory
= talloc_strdup(ctx
, dirpath
);
1502 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1506 mask
= dptr_wcard(sconn
, dptr_num
);
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
);
1531 dptr_fill(sconn
, buf
+12,dptr_num
);
1532 if (dptr_zero(buf
+12) && (status_len
==0)) {
1537 if (message_push_blob(&req
->outbuf
,
1538 data_blob_const(buf
, sizeof(buf
)))
1540 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1548 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
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
,
1569 char buf
[DIR_STRUCT_SIZE
];
1570 memcpy(buf
,status
,21);
1571 if (!make_dir_struct(ctx
,
1577 convert_timespec_to_time_t(date
),
1578 !allow_long_path_components
)) {
1579 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1582 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1585 if (message_push_blob(&req
->outbuf
,
1586 data_blob_const(buf
, sizeof(buf
)))
1588 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1598 /* If we were called as SMBffirst with smb_search_id == NULL
1599 and no entries were found then return error and close dirptr
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
);
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
),
1645 TALLOC_FREE(directory
);
1646 TALLOC_FREE(smb_fname
);
1647 END_PROFILE(SMBsearch
);
1651 /****************************************************************************
1652 Reply to a fclose (stop directory search).
1653 ****************************************************************************/
1655 void reply_fclose(struct smb_request
*req
)
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
);
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
);
1684 status_len
= SVAL(p
,0);
1687 if (status_len
== 0) {
1688 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1689 END_PROFILE(SMBfclose
);
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
);
1709 /****************************************************************************
1711 ****************************************************************************/
1713 void reply_open(struct smb_request
*req
)
1715 connection_struct
*conn
= req
->conn
;
1716 struct smb_filename
*smb_fname
= NULL
;
1728 uint32 create_disposition
;
1729 uint32 create_options
= 0;
1730 uint32_t private_flags
= 0;
1732 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1733 TALLOC_CTX
*ctx
= talloc_tos();
1735 START_PROFILE(SMBopen
);
1738 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
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
);
1753 status
= filename_convert(ctx
,
1755 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
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
);
1767 reply_nterror(req
, status
);
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
);
1779 status
= SMB_VFS_CREATE_FILE(
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 */
1797 if (!NT_STATUS_IS_OK(status
)) {
1798 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1799 /* We have re-scheduled this call. */
1802 reply_openerror(req
, status
);
1806 size
= smb_fname
->st
.st_ex_size
;
1807 fattr
= dos_mode(conn
, smb_fname
);
1809 /* Deal with other possible opens having a modified
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",
1826 close_file(req
, fsp
, ERROR_CLOSE
);
1827 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1828 ERRDOS
, ERRnoaccess
);
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);
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
);
1853 TALLOC_FREE(smb_fname
);
1854 END_PROFILE(SMBopen
);
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
;
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
;
1876 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1877 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
1885 uint64_t allocation_size
;
1886 ssize_t retval
= -1;
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
);
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. */
1912 if (lp_nt_pipe_support()) {
1913 reply_open_pipe_and_X(conn
, req
);
1915 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
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
);
1928 status
= filename_convert(ctx
,
1930 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
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
);
1942 reply_nterror(req
, status
);
1946 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1948 &access_mask
, &share_mode
,
1949 &create_disposition
,
1952 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1956 status
= SMB_VFS_CREATE_FILE(
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 */
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. */
1979 reply_openerror(req
, status
);
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
);
1992 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
1994 close_file(req
, fsp
, ERROR_CLOSE
);
1995 reply_nterror(req
, NT_STATUS_DISK_FULL
);
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
);
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
);
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);
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);
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
);
2067 TALLOC_FREE(smb_fname
);
2068 END_PROFILE(SMBopenX
);
2072 /****************************************************************************
2073 Reply to a SMBulogoffX.
2074 ****************************************************************************/
2076 void reply_ulogoffX(struct smb_request
*req
)
2078 struct smbd_server_connection
*sconn
= req
->sconn
;
2081 START_PROFILE(SMBulogoffX
);
2083 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2086 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
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
;
2118 struct smb_file_time ft
;
2120 int oplock_request
= 0;
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
);
2132 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2136 fattr
= SVAL(req
->vwv
+0, 0);
2137 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
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
);
2149 status
= filename_convert(ctx
,
2151 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
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
);
2163 reply_nterror(req
, status
);
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
;
2177 /* Create if file doesn't exist, truncate if it does. */
2178 create_disposition
= FILE_OVERWRITE_IF
;
2181 status
= SMB_VFS_CREATE_FILE(
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 */
2199 if (!NT_STATUS_IS_OK(status
)) {
2200 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2201 /* We have re-scheduled this call. */
2204 reply_openerror(req
, status
);
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
);
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
));
2234 TALLOC_FREE(smb_fname
);
2235 END_PROFILE(SMBcreate
);
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
;
2254 TALLOC_CTX
*ctx
= talloc_tos();
2256 START_PROFILE(SMBctemp
);
2259 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
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
);
2273 fname
= talloc_asprintf(ctx
,
2277 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2281 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2285 status
= filename_convert(ctx
, conn
,
2286 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
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
);
2297 reply_nterror(req
, status
);
2301 tmpfd
= mkstemp(smb_fname
->base_name
);
2303 reply_nterror(req
, map_nt_error_from_unix(errno
));
2307 SMB_VFS_STAT(conn
, smb_fname
);
2309 /* We should fail if file does not exist. */
2310 status
= SMB_VFS_CREATE_FILE(
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 */
2328 /* close fd from mkstemp() */
2331 if (!NT_STATUS_IS_OK(status
)) {
2332 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2333 /* We have re-scheduled this call. */
2336 reply_openerror(req
, status
);
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
, '/');
2346 s
= fsp
->fsp_name
->base_name
;
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 */
2356 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2358 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
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
));
2376 TALLOC_FREE(smb_fname
);
2377 END_PROFILE(SMBctemp
);
2381 /*******************************************************************
2382 Check if a user is allowed to rename a file.
2383 ********************************************************************/
2385 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
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
,
2434 uint32 dirtype_orig
= dirtype
;
2437 bool posix_paths
= lp_posix_pathnames();
2439 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2440 smb_fname_str_dbg(smb_fname
),
2443 if (!CAN_WRITE(conn
)) {
2444 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2448 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2450 ret
= SMB_VFS_STAT(conn
, smb_fname
);
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
);
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
;
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
;
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
;
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
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 */
2532 if (!NT_STATUS_IS_OK(status
)) {
2533 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2534 nt_errstr(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 - "
2542 smb_fname_str_dbg(smb_fname
),
2543 nt_errstr(status
)));
2544 close_file(req
, fsp
, NORMAL_CLOSE
);
2548 /* The set is across all open files on this dev/inode pair. */
2549 if (!set_delete_on_close(fsp
, True
,
2550 conn
->session_info
->security_token
,
2551 conn
->session_info
->unix_token
)) {
2552 close_file(req
, fsp
, NORMAL_CLOSE
);
2553 return NT_STATUS_ACCESS_DENIED
;
2556 return close_file(req
, fsp
, NORMAL_CLOSE
);
2559 /****************************************************************************
2560 The guts of the unlink command, split out so it may be called by the NT SMB
2562 ****************************************************************************/
2564 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2565 uint32 dirtype
, struct smb_filename
*smb_fname
,
2568 char *fname_dir
= NULL
;
2569 char *fname_mask
= NULL
;
2571 NTSTATUS status
= NT_STATUS_OK
;
2572 TALLOC_CTX
*ctx
= talloc_tos();
2574 /* Split up the directory from the filename/mask. */
2575 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2576 &fname_dir
, &fname_mask
);
2577 if (!NT_STATUS_IS_OK(status
)) {
2582 * We should only check the mangled cache
2583 * here if unix_convert failed. This means
2584 * that the path in 'mask' doesn't exist
2585 * on the file system and so we need to look
2586 * for a possible mangle. This patch from
2587 * Tine Smukavec <valentin.smukavec@hermes.si>.
2590 if (!VALID_STAT(smb_fname
->st
) &&
2591 mangle_is_mangled(fname_mask
, conn
->params
)) {
2592 char *new_mask
= NULL
;
2593 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2594 &new_mask
, conn
->params
);
2596 TALLOC_FREE(fname_mask
);
2597 fname_mask
= new_mask
;
2604 * Only one file needs to be unlinked. Append the mask back
2605 * onto the directory.
2607 TALLOC_FREE(smb_fname
->base_name
);
2608 if (ISDOT(fname_dir
)) {
2609 /* Ensure we use canonical names on open. */
2610 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2614 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2619 if (!smb_fname
->base_name
) {
2620 status
= NT_STATUS_NO_MEMORY
;
2624 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2627 status
= check_name(conn
, smb_fname
->base_name
);
2628 if (!NT_STATUS_IS_OK(status
)) {
2632 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2633 if (!NT_STATUS_IS_OK(status
)) {
2639 struct smb_Dir
*dir_hnd
= NULL
;
2641 const char *dname
= NULL
;
2642 char *talloced
= NULL
;
2644 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2645 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2649 if (strequal(fname_mask
,"????????.???")) {
2650 TALLOC_FREE(fname_mask
);
2651 fname_mask
= talloc_strdup(ctx
, "*");
2653 status
= NT_STATUS_NO_MEMORY
;
2658 status
= check_name(conn
, fname_dir
);
2659 if (!NT_STATUS_IS_OK(status
)) {
2663 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2665 if (dir_hnd
== NULL
) {
2666 status
= map_nt_error_from_unix(errno
);
2670 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2671 the pattern matches against the long name, otherwise the short name
2672 We don't implement this yet XXXX
2675 status
= NT_STATUS_NO_SUCH_FILE
;
2677 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2678 &smb_fname
->st
, &talloced
))) {
2679 TALLOC_CTX
*frame
= talloc_stackframe();
2681 if (!is_visible_file(conn
, fname_dir
, dname
,
2682 &smb_fname
->st
, true)) {
2684 TALLOC_FREE(talloced
);
2688 /* Quick check for "." and ".." */
2689 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2691 TALLOC_FREE(talloced
);
2695 if(!mask_match(dname
, fname_mask
,
2696 conn
->case_sensitive
)) {
2698 TALLOC_FREE(talloced
);
2702 TALLOC_FREE(smb_fname
->base_name
);
2703 if (ISDOT(fname_dir
)) {
2704 /* Ensure we use canonical names on open. */
2705 smb_fname
->base_name
=
2706 talloc_asprintf(smb_fname
, "%s",
2709 smb_fname
->base_name
=
2710 talloc_asprintf(smb_fname
, "%s/%s",
2714 if (!smb_fname
->base_name
) {
2715 TALLOC_FREE(dir_hnd
);
2716 status
= NT_STATUS_NO_MEMORY
;
2718 TALLOC_FREE(talloced
);
2722 status
= check_name(conn
, smb_fname
->base_name
);
2723 if (!NT_STATUS_IS_OK(status
)) {
2724 TALLOC_FREE(dir_hnd
);
2726 TALLOC_FREE(talloced
);
2730 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2731 if (!NT_STATUS_IS_OK(status
)) {
2733 TALLOC_FREE(talloced
);
2738 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2739 smb_fname
->base_name
));
2742 TALLOC_FREE(talloced
);
2744 TALLOC_FREE(dir_hnd
);
2747 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2748 status
= map_nt_error_from_unix(errno
);
2752 TALLOC_FREE(fname_dir
);
2753 TALLOC_FREE(fname_mask
);
2757 /****************************************************************************
2759 ****************************************************************************/
2761 void reply_unlink(struct smb_request
*req
)
2763 connection_struct
*conn
= req
->conn
;
2765 struct smb_filename
*smb_fname
= NULL
;
2768 bool path_contains_wcard
= False
;
2769 TALLOC_CTX
*ctx
= talloc_tos();
2771 START_PROFILE(SMBunlink
);
2774 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2778 dirtype
= SVAL(req
->vwv
+0, 0);
2780 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2781 STR_TERMINATE
, &status
,
2782 &path_contains_wcard
);
2783 if (!NT_STATUS_IS_OK(status
)) {
2784 reply_nterror(req
, status
);
2788 status
= filename_convert(ctx
, conn
,
2789 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2791 UCF_COND_ALLOW_WCARD_LCOMP
,
2792 &path_contains_wcard
,
2794 if (!NT_STATUS_IS_OK(status
)) {
2795 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2796 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2797 ERRSRV
, ERRbadpath
);
2800 reply_nterror(req
, status
);
2804 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2806 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2807 path_contains_wcard
);
2808 if (!NT_STATUS_IS_OK(status
)) {
2809 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2810 /* We have re-scheduled this call. */
2813 reply_nterror(req
, status
);
2817 reply_outbuf(req
, 0, 0);
2819 TALLOC_FREE(smb_fname
);
2820 END_PROFILE(SMBunlink
);
2824 /****************************************************************************
2826 ****************************************************************************/
2828 static void fail_readraw(void)
2830 const char *errstr
= talloc_asprintf(talloc_tos(),
2831 "FAIL ! reply_readbraw: socket write fail (%s)",
2836 exit_server_cleanly(errstr
);
2839 /****************************************************************************
2840 Fake (read/write) sendfile. Returns -1 on read or write fail.
2841 ****************************************************************************/
2843 ssize_t
fake_sendfile(files_struct
*fsp
, off_t startpos
, size_t nread
)
2846 size_t tosend
= nread
;
2853 bufsize
= MIN(nread
, 65536);
2855 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2859 while (tosend
> 0) {
2863 if (tosend
> bufsize
) {
2868 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2874 /* If we had a short read, fill with zeros. */
2875 if (ret
< cur_read
) {
2876 memset(buf
+ ret
, '\0', cur_read
- ret
);
2879 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
2881 char addr
[INET6_ADDRSTRLEN
];
2883 * Try and give an error message saying what
2886 DEBUG(0, ("write_data failed for client %s. "
2888 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
2895 startpos
+= cur_read
;
2899 return (ssize_t
)nread
;
2902 /****************************************************************************
2903 Deal with the case of sendfile reading less bytes from the file than
2904 requested. Fill with zeros (all we can do).
2905 ****************************************************************************/
2907 void sendfile_short_send(files_struct
*fsp
,
2912 #define SHORT_SEND_BUFSIZE 1024
2913 if (nread
< headersize
) {
2914 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2915 "header for file %s (%s). Terminating\n",
2916 fsp_str_dbg(fsp
), strerror(errno
)));
2917 exit_server_cleanly("sendfile_short_send failed");
2920 nread
-= headersize
;
2922 if (nread
< smb_maxcnt
) {
2923 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
2925 exit_server_cleanly("sendfile_short_send: "
2929 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2930 "with zeros !\n", fsp_str_dbg(fsp
)));
2932 while (nread
< smb_maxcnt
) {
2934 * We asked for the real file size and told sendfile
2935 * to not go beyond the end of the file. But it can
2936 * happen that in between our fstat call and the
2937 * sendfile call the file was truncated. This is very
2938 * bad because we have already announced the larger
2939 * number of bytes to the client.
2941 * The best we can do now is to send 0-bytes, just as
2942 * a read from a hole in a sparse file would do.
2944 * This should happen rarely enough that I don't care
2945 * about efficiency here :-)
2949 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
2950 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
2952 char addr
[INET6_ADDRSTRLEN
];
2954 * Try and give an error message saying what
2957 DEBUG(0, ("write_data failed for client %s. "
2960 fsp
->conn
->sconn
->sock
, addr
,
2963 exit_server_cleanly("sendfile_short_send: "
2964 "write_data failed");
2972 /****************************************************************************
2973 Return a readbraw error (4 bytes of zero).
2974 ****************************************************************************/
2976 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
2982 smbd_lock_socket(sconn
);
2983 if (write_data(sconn
->sock
,header
,4) != 4) {
2984 char addr
[INET6_ADDRSTRLEN
];
2986 * Try and give an error message saying what
2989 DEBUG(0, ("write_data failed for client %s. "
2991 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
2996 smbd_unlock_socket(sconn
);
2999 /****************************************************************************
3000 Use sendfile in readbraw.
3001 ****************************************************************************/
3003 static void send_file_readbraw(connection_struct
*conn
,
3004 struct smb_request
*req
,
3010 struct smbd_server_connection
*sconn
= req
->sconn
;
3011 char *outbuf
= NULL
;
3015 * We can only use sendfile on a non-chained packet
3016 * but we can use on a non-oplocked file. tridge proved this
3017 * on a train in Germany :-). JRA.
3018 * reply_readbraw has already checked the length.
3021 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3022 (fsp
->wcp
== NULL
) &&
3023 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3024 ssize_t sendfile_read
= -1;
3026 DATA_BLOB header_blob
;
3028 _smb_setlen(header
,nread
);
3029 header_blob
= data_blob_const(header
, 4);
3031 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3032 &header_blob
, startpos
,
3034 if (sendfile_read
== -1) {
3035 /* Returning ENOSYS means no data at all was sent.
3036 * Do this as a normal read. */
3037 if (errno
== ENOSYS
) {
3038 goto normal_readbraw
;
3042 * Special hack for broken Linux with no working sendfile. If we
3043 * return EINTR we sent the header but not the rest of the data.
3044 * Fake this up by doing read/write calls.
3046 if (errno
== EINTR
) {
3047 /* Ensure we don't do this again. */
3048 set_use_sendfile(SNUM(conn
), False
);
3049 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3051 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3052 DEBUG(0,("send_file_readbraw: "
3053 "fake_sendfile failed for "
3057 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3062 DEBUG(0,("send_file_readbraw: sendfile failed for "
3063 "file %s (%s). Terminating\n",
3064 fsp_str_dbg(fsp
), strerror(errno
)));
3065 exit_server_cleanly("send_file_readbraw sendfile failed");
3066 } else if (sendfile_read
== 0) {
3068 * Some sendfile implementations return 0 to indicate
3069 * that there was a short read, but nothing was
3070 * actually written to the socket. In this case,
3071 * fallback to the normal read path so the header gets
3072 * the correct byte count.
3074 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3075 "bytes falling back to the normal read: "
3076 "%s\n", fsp_str_dbg(fsp
)));
3077 goto normal_readbraw
;
3080 /* Deal with possible short send. */
3081 if (sendfile_read
!= 4+nread
) {
3082 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3089 outbuf
= talloc_array(NULL
, char, nread
+4);
3091 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3092 (unsigned)(nread
+4)));
3093 reply_readbraw_error(sconn
);
3098 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3099 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3108 _smb_setlen(outbuf
,ret
);
3109 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3110 char addr
[INET6_ADDRSTRLEN
];
3112 * Try and give an error message saying what
3115 DEBUG(0, ("write_data failed for client %s. "
3117 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3124 TALLOC_FREE(outbuf
);
3127 /****************************************************************************
3128 Reply to a readbraw (core+ protocol).
3129 ****************************************************************************/
3131 void reply_readbraw(struct smb_request
*req
)
3133 connection_struct
*conn
= req
->conn
;
3134 struct smbd_server_connection
*sconn
= req
->sconn
;
3135 ssize_t maxcount
,mincount
;
3139 struct lock_struct lock
;
3142 START_PROFILE(SMBreadbraw
);
3144 if (srv_is_signing_active(sconn
) ||
3145 is_encrypted_packet(sconn
, req
->inbuf
)) {
3146 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3147 "raw reads/writes are disallowed.");
3151 reply_readbraw_error(sconn
);
3152 END_PROFILE(SMBreadbraw
);
3156 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3157 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3158 "'async smb echo handler = yes'\n"));
3159 reply_readbraw_error(sconn
);
3160 END_PROFILE(SMBreadbraw
);
3165 * Special check if an oplock break has been issued
3166 * and the readraw request croses on the wire, we must
3167 * return a zero length response here.
3170 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3173 * We have to do a check_fsp by hand here, as
3174 * we must always return 4 zero bytes on error,
3178 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3179 req
->vuid
!= fsp
->vuid
||
3180 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3182 * fsp could be NULL here so use the value from the packet. JRA.
3184 DEBUG(3,("reply_readbraw: fnum %d not valid "
3186 (int)SVAL(req
->vwv
+0, 0)));
3187 reply_readbraw_error(sconn
);
3188 END_PROFILE(SMBreadbraw
);
3192 /* Do a "by hand" version of CHECK_READ. */
3193 if (!(fsp
->can_read
||
3194 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3195 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3196 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3197 (int)SVAL(req
->vwv
+0, 0)));
3198 reply_readbraw_error(sconn
);
3199 END_PROFILE(SMBreadbraw
);
3203 flush_write_cache(fsp
, READRAW_FLUSH
);
3205 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3206 if(req
->wct
== 10) {
3208 * This is a large offset (64 bit) read.
3211 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3214 DEBUG(0,("reply_readbraw: negative 64 bit "
3215 "readraw offset (%.0f) !\n",
3216 (double)startpos
));
3217 reply_readbraw_error(sconn
);
3218 END_PROFILE(SMBreadbraw
);
3223 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3224 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3226 /* ensure we don't overrun the packet size */
3227 maxcount
= MIN(65535,maxcount
);
3229 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3230 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3233 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3234 reply_readbraw_error(sconn
);
3235 END_PROFILE(SMBreadbraw
);
3239 if (fsp_stat(fsp
) == 0) {
3240 size
= fsp
->fsp_name
->st
.st_ex_size
;
3243 if (startpos
>= size
) {
3246 nread
= MIN(maxcount
,(size
- startpos
));
3249 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3250 if (nread
< mincount
)
3254 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3255 "min=%lu nread=%lu\n",
3256 fsp
->fnum
, (double)startpos
,
3257 (unsigned long)maxcount
,
3258 (unsigned long)mincount
,
3259 (unsigned long)nread
) );
3261 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3263 DEBUG(5,("reply_readbraw finished\n"));
3265 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3267 END_PROFILE(SMBreadbraw
);
3272 #define DBGC_CLASS DBGC_LOCKING
3274 /****************************************************************************
3275 Reply to a lockread (core+ protocol).
3276 ****************************************************************************/
3278 void reply_lockread(struct smb_request
*req
)
3280 connection_struct
*conn
= req
->conn
;
3287 struct byte_range_lock
*br_lck
= NULL
;
3289 struct smbd_server_connection
*sconn
= req
->sconn
;
3291 START_PROFILE(SMBlockread
);
3294 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3295 END_PROFILE(SMBlockread
);
3299 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3301 if (!check_fsp(conn
, req
, fsp
)) {
3302 END_PROFILE(SMBlockread
);
3306 if (!CHECK_READ(fsp
,req
)) {
3307 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3308 END_PROFILE(SMBlockread
);
3312 numtoread
= SVAL(req
->vwv
+1, 0);
3313 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3315 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3317 reply_outbuf(req
, 5, numtoread
+ 3);
3319 data
= smb_buf(req
->outbuf
) + 3;
3322 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3323 * protocol request that predates the read/write lock concept.
3324 * Thus instead of asking for a read lock here we need to ask
3325 * for a write lock. JRA.
3326 * Note that the requested lock size is unaffected by max_recv.
3329 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3331 (uint64_t)req
->smbpid
,
3332 (uint64_t)numtoread
,
3336 False
, /* Non-blocking lock. */
3340 TALLOC_FREE(br_lck
);
3342 if (NT_STATUS_V(status
)) {
3343 reply_nterror(req
, status
);
3344 END_PROFILE(SMBlockread
);
3349 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3352 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3353 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3354 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3355 (unsigned int)numtoread
,
3356 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3357 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3359 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3362 reply_nterror(req
, map_nt_error_from_unix(errno
));
3363 END_PROFILE(SMBlockread
);
3367 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3369 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3370 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3371 p
= smb_buf(req
->outbuf
);
3372 SCVAL(p
,0,0); /* pad byte. */
3375 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3376 fsp
->fnum
, (int)numtoread
, (int)nread
));
3378 END_PROFILE(SMBlockread
);
3383 #define DBGC_CLASS DBGC_ALL
3385 /****************************************************************************
3387 ****************************************************************************/
3389 void reply_read(struct smb_request
*req
)
3391 connection_struct
*conn
= req
->conn
;
3398 struct lock_struct lock
;
3399 struct smbd_server_connection
*sconn
= req
->sconn
;
3401 START_PROFILE(SMBread
);
3404 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3405 END_PROFILE(SMBread
);
3409 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3411 if (!check_fsp(conn
, req
, fsp
)) {
3412 END_PROFILE(SMBread
);
3416 if (!CHECK_READ(fsp
,req
)) {
3417 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3418 END_PROFILE(SMBread
);
3422 numtoread
= SVAL(req
->vwv
+1, 0);
3423 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3425 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3428 * The requested read size cannot be greater than max_recv. JRA.
3430 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3431 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3432 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3433 (unsigned int)numtoread
,
3434 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3435 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3438 reply_outbuf(req
, 5, numtoread
+3);
3440 data
= smb_buf(req
->outbuf
) + 3;
3442 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3443 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3446 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3447 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3448 END_PROFILE(SMBread
);
3453 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3456 reply_nterror(req
, map_nt_error_from_unix(errno
));
3460 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3462 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3463 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3464 SCVAL(smb_buf(req
->outbuf
),0,1);
3465 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3467 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3468 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3471 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3473 END_PROFILE(SMBread
);
3477 /****************************************************************************
3479 ****************************************************************************/
3481 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3486 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3488 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3490 SCVAL(outbuf
,smb_vwv0
,0xFF);
3491 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3492 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3493 SSVAL(outbuf
,smb_vwv6
,
3494 (smb_wct
- 4) /* offset from smb header to wct */
3495 + 1 /* the wct field */
3496 + 12 * sizeof(uint16_t) /* vwv */
3497 + 2); /* the buflen field */
3498 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3499 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3500 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3501 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3505 /****************************************************************************
3506 Reply to a read and X - possibly using sendfile.
3507 ****************************************************************************/
3509 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3510 files_struct
*fsp
, off_t startpos
,
3514 struct lock_struct lock
;
3515 int saved_errno
= 0;
3517 if(fsp_stat(fsp
) == -1) {
3518 reply_nterror(req
, map_nt_error_from_unix(errno
));
3522 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3523 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3526 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3527 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3531 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3532 (startpos
> fsp
->fsp_name
->st
.st_ex_size
)
3533 || (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3535 * We already know that we would do a short read, so don't
3536 * try the sendfile() path.
3538 goto nosendfile_read
;
3542 * We can only use sendfile on a non-chained packet
3543 * but we can use on a non-oplocked file. tridge proved this
3544 * on a train in Germany :-). JRA.
3547 if (!req_is_in_chain(req
) &&
3548 !is_encrypted_packet(req
->sconn
, req
->inbuf
) &&
3549 (fsp
->base_fsp
== NULL
) &&
3550 (fsp
->wcp
== NULL
) &&
3551 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3552 uint8 headerbuf
[smb_size
+ 12 * 2];
3556 * Set up the packet header before send. We
3557 * assume here the sendfile will work (get the
3558 * correct amount of data).
3561 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3563 construct_reply_common_req(req
, (char *)headerbuf
);
3564 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3566 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3567 startpos
, smb_maxcnt
);
3569 /* Returning ENOSYS means no data at all was sent.
3570 Do this as a normal read. */
3571 if (errno
== ENOSYS
) {
3576 * Special hack for broken Linux with no working sendfile. If we
3577 * return EINTR we sent the header but not the rest of the data.
3578 * Fake this up by doing read/write calls.
3581 if (errno
== EINTR
) {
3582 /* Ensure we don't do this again. */
3583 set_use_sendfile(SNUM(conn
), False
);
3584 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3585 nread
= fake_sendfile(fsp
, startpos
,
3588 DEBUG(0,("send_file_readX: "
3589 "fake_sendfile failed for "
3593 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3595 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3596 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3597 /* No outbuf here means successful sendfile. */
3601 DEBUG(0,("send_file_readX: sendfile failed for file "
3602 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3604 exit_server_cleanly("send_file_readX sendfile failed");
3605 } else if (nread
== 0) {
3607 * Some sendfile implementations return 0 to indicate
3608 * that there was a short read, but nothing was
3609 * actually written to the socket. In this case,
3610 * fallback to the normal read path so the header gets
3611 * the correct byte count.
3613 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3614 "falling back to the normal read: %s\n",
3619 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3620 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3622 /* Deal with possible short send. */
3623 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3624 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3626 /* No outbuf here means successful sendfile. */
3627 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3628 SMB_PERFCOUNT_END(&req
->pcd
);
3634 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3635 uint8 headerbuf
[smb_size
+ 2*12];
3637 construct_reply_common_req(req
, (char *)headerbuf
);
3638 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3640 /* Send out the header. */
3641 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3642 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3644 char addr
[INET6_ADDRSTRLEN
];
3646 * Try and give an error message saying what
3649 DEBUG(0, ("write_data failed for client %s. "
3651 get_peer_addr(req
->sconn
->sock
, addr
,
3655 DEBUG(0,("send_file_readX: write_data failed for file "
3656 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3658 exit_server_cleanly("send_file_readX sendfile failed");
3660 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3662 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3663 "file %s (%s).\n", fsp_str_dbg(fsp
),
3665 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3672 reply_outbuf(req
, 12, smb_maxcnt
);
3673 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
3674 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
3676 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3677 saved_errno
= errno
;
3679 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3682 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3686 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3688 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3689 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3693 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3694 TALLOC_FREE(req
->outbuf
);
3698 /****************************************************************************
3699 Reply to a read and X.
3700 ****************************************************************************/
3702 void reply_read_and_X(struct smb_request
*req
)
3704 struct smbd_server_connection
*sconn
= req
->sconn
;
3705 connection_struct
*conn
= req
->conn
;
3709 bool big_readX
= False
;
3711 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3714 START_PROFILE(SMBreadX
);
3716 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3717 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3721 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3722 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3723 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3725 /* If it's an IPC, pass off the pipe handler. */
3727 reply_pipe_read_and_X(req
);
3728 END_PROFILE(SMBreadX
);
3732 if (!check_fsp(conn
, req
, fsp
)) {
3733 END_PROFILE(SMBreadX
);
3737 if (!CHECK_READ(fsp
,req
)) {
3738 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3739 END_PROFILE(SMBreadX
);
3743 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_LARGE_READ_CAP
) ||
3744 (get_remote_arch() == RA_SAMBA
)) {
3746 * This is Samba only behavior (up to Samba 3.6)!
3748 * Windows 2008 R2 ignores the upper_size,
3749 * so we do unless unix extentions are active
3750 * or "smbclient" is talking to us.
3752 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3753 smb_maxcnt
|= (upper_size
<<16);
3754 if (upper_size
> 1) {
3755 /* Can't do this on a chained packet. */
3756 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3757 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3758 END_PROFILE(SMBreadX
);
3761 /* We currently don't do this on signed or sealed data. */
3762 if (srv_is_signing_active(req
->sconn
) ||
3763 is_encrypted_packet(req
->sconn
, req
->inbuf
)) {
3764 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3765 END_PROFILE(SMBreadX
);
3768 /* Is there room in the reply for this data ? */
3769 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3771 NT_STATUS_INVALID_PARAMETER
);
3772 END_PROFILE(SMBreadX
);
3779 if (req
->wct
== 12) {
3781 * This is a large offset (64 bit) read.
3783 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
3788 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3793 if (NT_STATUS_IS_OK(status
)) {
3794 /* Read scheduled - we're done. */
3797 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3798 /* Real error - report to client. */
3799 END_PROFILE(SMBreadX
);
3800 reply_nterror(req
, status
);
3803 /* NT_STATUS_RETRY - fall back to sync read. */
3806 smbd_lock_socket(req
->sconn
);
3807 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3808 smbd_unlock_socket(req
->sconn
);
3811 END_PROFILE(SMBreadX
);
3815 /****************************************************************************
3816 Error replies to writebraw must have smb_wct == 1. Fix this up.
3817 ****************************************************************************/
3819 void error_to_writebrawerr(struct smb_request
*req
)
3821 uint8
*old_outbuf
= req
->outbuf
;
3823 reply_outbuf(req
, 1, 0);
3825 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3826 TALLOC_FREE(old_outbuf
);
3829 /****************************************************************************
3830 Read 4 bytes of a smb packet and return the smb length of the packet.
3831 Store the result in the buffer. This version of the function will
3832 never return a session keepalive (length of zero).
3833 Timeout is in milliseconds.
3834 ****************************************************************************/
3836 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3839 uint8_t msgtype
= NBSSkeepalive
;
3841 while (msgtype
== NBSSkeepalive
) {
3844 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3846 if (!NT_STATUS_IS_OK(status
)) {
3847 char addr
[INET6_ADDRSTRLEN
];
3848 /* Try and give an error message
3849 * saying what client failed. */
3850 DEBUG(0, ("read_fd_with_timeout failed for "
3851 "client %s read error = %s.\n",
3852 get_peer_addr(fd
,addr
,sizeof(addr
)),
3853 nt_errstr(status
)));
3857 msgtype
= CVAL(inbuf
, 0);
3860 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3861 (unsigned long)len
));
3863 return NT_STATUS_OK
;
3866 /****************************************************************************
3867 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3868 ****************************************************************************/
3870 void reply_writebraw(struct smb_request
*req
)
3872 connection_struct
*conn
= req
->conn
;
3875 ssize_t total_written
=0;
3876 size_t numtowrite
=0;
3879 const char *data
=NULL
;
3882 struct lock_struct lock
;
3885 START_PROFILE(SMBwritebraw
);
3888 * If we ever reply with an error, it must have the SMB command
3889 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3892 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
3894 if (srv_is_signing_active(req
->sconn
)) {
3895 END_PROFILE(SMBwritebraw
);
3896 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3897 "raw reads/writes are disallowed.");
3900 if (req
->wct
< 12) {
3901 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3902 error_to_writebrawerr(req
);
3903 END_PROFILE(SMBwritebraw
);
3907 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3908 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3909 "'async smb echo handler = yes'\n"));
3910 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3911 error_to_writebrawerr(req
);
3912 END_PROFILE(SMBwritebraw
);
3916 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3917 if (!check_fsp(conn
, req
, fsp
)) {
3918 error_to_writebrawerr(req
);
3919 END_PROFILE(SMBwritebraw
);
3923 if (!CHECK_WRITE(fsp
)) {
3924 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3925 error_to_writebrawerr(req
);
3926 END_PROFILE(SMBwritebraw
);
3930 tcount
= IVAL(req
->vwv
+1, 0);
3931 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3932 write_through
= BITSETW(req
->vwv
+7,0);
3934 /* We have to deal with slightly different formats depending
3935 on whether we are using the core+ or lanman1.0 protocol */
3937 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
3938 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
3939 data
= smb_buf_const(req
->inbuf
);
3941 numtowrite
= SVAL(req
->vwv
+10, 0);
3942 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3945 /* Ensure we don't write bytes past the end of this packet. */
3946 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3947 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3948 error_to_writebrawerr(req
);
3949 END_PROFILE(SMBwritebraw
);
3953 if (!fsp
->print_file
) {
3954 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3955 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
3958 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3959 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3960 error_to_writebrawerr(req
);
3961 END_PROFILE(SMBwritebraw
);
3967 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3970 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3971 "wrote=%d sync=%d\n",
3972 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3973 (int)nwritten
, (int)write_through
));
3975 if (nwritten
< (ssize_t
)numtowrite
) {
3976 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3977 error_to_writebrawerr(req
);
3981 total_written
= nwritten
;
3983 /* Allocate a buffer of 64k + length. */
3984 buf
= talloc_array(NULL
, char, 65540);
3986 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3987 error_to_writebrawerr(req
);
3991 /* Return a SMBwritebraw message to the redirector to tell
3992 * it to send more bytes */
3994 memcpy(buf
, req
->inbuf
, smb_size
);
3995 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
3996 SCVAL(buf
,smb_com
,SMBwritebraw
);
3997 SSVALS(buf
,smb_vwv0
,0xFFFF);
3999 if (!srv_send_smb(req
->sconn
,
4001 false, 0, /* no signing */
4002 IS_CONN_ENCRYPTED(conn
),
4004 exit_server_cleanly("reply_writebraw: srv_send_smb "
4008 /* Now read the raw data into the buffer and write it */
4009 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4011 if (!NT_STATUS_IS_OK(status
)) {
4012 exit_server_cleanly("secondary writebraw failed");
4015 /* Set up outbuf to return the correct size */
4016 reply_outbuf(req
, 1, 0);
4018 if (numtowrite
!= 0) {
4020 if (numtowrite
> 0xFFFF) {
4021 DEBUG(0,("reply_writebraw: Oversize secondary write "
4022 "raw requested (%u). Terminating\n",
4023 (unsigned int)numtowrite
));
4024 exit_server_cleanly("secondary writebraw failed");
4027 if (tcount
> nwritten
+numtowrite
) {
4028 DEBUG(3,("reply_writebraw: Client overestimated the "
4030 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4033 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4035 if (!NT_STATUS_IS_OK(status
)) {
4036 char addr
[INET6_ADDRSTRLEN
];
4037 /* Try and give an error message
4038 * saying what client failed. */
4039 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4040 "raw read failed (%s) for client %s. "
4041 "Terminating\n", nt_errstr(status
),
4042 get_peer_addr(req
->sconn
->sock
, addr
,
4044 exit_server_cleanly("secondary writebraw failed");
4047 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4048 if (nwritten
== -1) {
4050 reply_nterror(req
, map_nt_error_from_unix(errno
));
4051 error_to_writebrawerr(req
);
4055 if (nwritten
< (ssize_t
)numtowrite
) {
4056 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4057 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4061 total_written
+= nwritten
;
4066 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4068 status
= sync_file(conn
, fsp
, write_through
);
4069 if (!NT_STATUS_IS_OK(status
)) {
4070 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4071 fsp_str_dbg(fsp
), nt_errstr(status
)));
4072 reply_nterror(req
, status
);
4073 error_to_writebrawerr(req
);
4077 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4079 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4080 (int)total_written
));
4082 if (!fsp
->print_file
) {
4083 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4086 /* We won't return a status if write through is not selected - this
4087 * follows what WfWg does */
4088 END_PROFILE(SMBwritebraw
);
4090 if (!write_through
&& total_written
==tcount
) {
4092 #if RABBIT_PELLET_FIX
4094 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4095 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4098 if (!send_keepalive(req
->sconn
->sock
)) {
4099 exit_server_cleanly("reply_writebraw: send of "
4100 "keepalive failed");
4103 TALLOC_FREE(req
->outbuf
);
4108 if (!fsp
->print_file
) {
4109 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4112 END_PROFILE(SMBwritebraw
);
4117 #define DBGC_CLASS DBGC_LOCKING
4119 /****************************************************************************
4120 Reply to a writeunlock (core+).
4121 ****************************************************************************/
4123 void reply_writeunlock(struct smb_request
*req
)
4125 connection_struct
*conn
= req
->conn
;
4126 ssize_t nwritten
= -1;
4130 NTSTATUS status
= NT_STATUS_OK
;
4132 struct lock_struct lock
;
4133 int saved_errno
= 0;
4135 START_PROFILE(SMBwriteunlock
);
4138 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4139 END_PROFILE(SMBwriteunlock
);
4143 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4145 if (!check_fsp(conn
, req
, fsp
)) {
4146 END_PROFILE(SMBwriteunlock
);
4150 if (!CHECK_WRITE(fsp
)) {
4151 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4152 END_PROFILE(SMBwriteunlock
);
4156 numtowrite
= SVAL(req
->vwv
+1, 0);
4157 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4158 data
= (const char *)req
->buf
+ 3;
4160 if (!fsp
->print_file
&& numtowrite
> 0) {
4161 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4162 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4165 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4166 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4167 END_PROFILE(SMBwriteunlock
);
4172 /* The special X/Open SMB protocol handling of
4173 zero length writes is *NOT* done for
4175 if(numtowrite
== 0) {
4178 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4179 saved_errno
= errno
;
4182 status
= sync_file(conn
, fsp
, False
/* write through */);
4183 if (!NT_STATUS_IS_OK(status
)) {
4184 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4185 fsp_str_dbg(fsp
), nt_errstr(status
)));
4186 reply_nterror(req
, status
);
4191 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4195 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4196 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4200 if (numtowrite
&& !fsp
->print_file
) {
4201 status
= do_unlock(req
->sconn
->msg_ctx
,
4203 (uint64_t)req
->smbpid
,
4204 (uint64_t)numtowrite
,
4208 if (NT_STATUS_V(status
)) {
4209 reply_nterror(req
, status
);
4214 reply_outbuf(req
, 1, 0);
4216 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4218 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4219 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4222 if (numtowrite
&& !fsp
->print_file
) {
4223 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4226 END_PROFILE(SMBwriteunlock
);
4231 #define DBGC_CLASS DBGC_ALL
4233 /****************************************************************************
4235 ****************************************************************************/
4237 void reply_write(struct smb_request
*req
)
4239 connection_struct
*conn
= req
->conn
;
4241 ssize_t nwritten
= -1;
4245 struct lock_struct lock
;
4247 int saved_errno
= 0;
4249 START_PROFILE(SMBwrite
);
4252 END_PROFILE(SMBwrite
);
4253 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4257 /* If it's an IPC, pass off the pipe handler. */
4259 reply_pipe_write(req
);
4260 END_PROFILE(SMBwrite
);
4264 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4266 if (!check_fsp(conn
, req
, fsp
)) {
4267 END_PROFILE(SMBwrite
);
4271 if (!CHECK_WRITE(fsp
)) {
4272 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4273 END_PROFILE(SMBwrite
);
4277 numtowrite
= SVAL(req
->vwv
+1, 0);
4278 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4279 data
= (const char *)req
->buf
+ 3;
4281 if (!fsp
->print_file
) {
4282 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4283 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4286 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4287 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4288 END_PROFILE(SMBwrite
);
4294 * X/Open SMB protocol says that if smb_vwv1 is
4295 * zero then the file size should be extended or
4296 * truncated to the size given in smb_vwv[2-3].
4299 if(numtowrite
== 0) {
4301 * This is actually an allocate call, and set EOF. JRA.
4303 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4305 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4308 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4310 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4313 trigger_write_time_update_immediate(fsp
);
4315 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4318 status
= sync_file(conn
, fsp
, False
);
4319 if (!NT_STATUS_IS_OK(status
)) {
4320 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4321 fsp_str_dbg(fsp
), nt_errstr(status
)));
4322 reply_nterror(req
, status
);
4327 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4331 if((nwritten
== 0) && (numtowrite
!= 0)) {
4332 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4336 reply_outbuf(req
, 1, 0);
4338 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4340 if (nwritten
< (ssize_t
)numtowrite
) {
4341 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4342 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4345 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4348 if (!fsp
->print_file
) {
4349 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4352 END_PROFILE(SMBwrite
);
4356 /****************************************************************************
4357 Ensure a buffer is a valid writeX for recvfile purposes.
4358 ****************************************************************************/
4360 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4361 (2*14) + /* word count (including bcc) */ \
4364 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4365 const uint8_t *inbuf
)
4368 connection_struct
*conn
= NULL
;
4369 unsigned int doff
= 0;
4370 size_t len
= smb_len_large(inbuf
);
4372 if (is_encrypted_packet(sconn
, inbuf
)) {
4373 /* Can't do this on encrypted
4378 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4382 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4383 CVAL(inbuf
,smb_wct
) != 14) {
4384 DEBUG(10,("is_valid_writeX_buffer: chained or "
4385 "invalid word length.\n"));
4389 conn
= conn_find(sconn
, SVAL(inbuf
, smb_tid
));
4391 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4395 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4398 if (IS_PRINT(conn
)) {
4399 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4402 doff
= SVAL(inbuf
,smb_vwv11
);
4404 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4406 if (len
> doff
&& len
- doff
> 0xFFFF) {
4407 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4410 if (numtowrite
== 0) {
4411 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4415 /* Ensure the sizes match up. */
4416 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4417 /* no pad byte...old smbclient :-( */
4418 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4420 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4424 if (len
- doff
!= numtowrite
) {
4425 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4426 "len = %u, doff = %u, numtowrite = %u\n",
4429 (unsigned int)numtowrite
));
4433 DEBUG(10,("is_valid_writeX_buffer: true "
4434 "len = %u, doff = %u, numtowrite = %u\n",
4437 (unsigned int)numtowrite
));
4442 /****************************************************************************
4443 Reply to a write and X.
4444 ****************************************************************************/
4446 void reply_write_and_X(struct smb_request
*req
)
4448 connection_struct
*conn
= req
->conn
;
4450 struct lock_struct lock
;
4455 unsigned int smb_doff
;
4456 unsigned int smblen
;
4459 int saved_errno
= 0;
4461 START_PROFILE(SMBwriteX
);
4463 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4464 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4468 numtowrite
= SVAL(req
->vwv
+10, 0);
4469 smb_doff
= SVAL(req
->vwv
+11, 0);
4470 smblen
= smb_len(req
->inbuf
);
4472 if (req
->unread_bytes
> 0xFFFF ||
4473 (smblen
> smb_doff
&&
4474 smblen
- smb_doff
> 0xFFFF)) {
4475 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4478 if (req
->unread_bytes
) {
4479 /* Can't do a recvfile write on IPC$ */
4481 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4484 if (numtowrite
!= req
->unread_bytes
) {
4485 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4489 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4490 smb_doff
+ numtowrite
> smblen
) {
4491 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4496 /* If it's an IPC, pass off the pipe handler. */
4498 if (req
->unread_bytes
) {
4499 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4502 reply_pipe_write_and_X(req
);
4506 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4507 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4508 write_through
= BITSETW(req
->vwv
+7,0);
4510 if (!check_fsp(conn
, req
, fsp
)) {
4514 if (!CHECK_WRITE(fsp
)) {
4515 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4519 data
= smb_base(req
->inbuf
) + smb_doff
;
4521 if(req
->wct
== 14) {
4523 * This is a large offset (64 bit) write.
4525 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
4529 /* X/Open SMB protocol says that, unlike SMBwrite
4530 if the length is zero then NO truncation is
4531 done, just a write of zero. To truncate a file,
4534 if(numtowrite
== 0) {
4537 if (req
->unread_bytes
== 0) {
4538 status
= schedule_aio_write_and_X(conn
,
4545 if (NT_STATUS_IS_OK(status
)) {
4546 /* write scheduled - we're done. */
4549 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4550 /* Real error - report to client. */
4551 reply_nterror(req
, status
);
4554 /* NT_STATUS_RETRY - fall through to sync write. */
4557 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4558 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4561 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4562 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4566 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4567 saved_errno
= errno
;
4569 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4573 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4577 if((nwritten
== 0) && (numtowrite
!= 0)) {
4578 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4582 reply_outbuf(req
, 6, 0);
4583 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4584 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4585 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4586 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4588 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4589 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4591 status
= sync_file(conn
, fsp
, write_through
);
4592 if (!NT_STATUS_IS_OK(status
)) {
4593 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4594 fsp_str_dbg(fsp
), nt_errstr(status
)));
4595 reply_nterror(req
, status
);
4599 END_PROFILE(SMBwriteX
);
4603 if (req
->unread_bytes
) {
4604 /* writeX failed. drain socket. */
4605 if (drain_socket(req
->sconn
->sock
, req
->unread_bytes
) !=
4606 req
->unread_bytes
) {
4607 smb_panic("failed to drain pending bytes");
4609 req
->unread_bytes
= 0;
4612 END_PROFILE(SMBwriteX
);
4616 /****************************************************************************
4618 ****************************************************************************/
4620 void reply_lseek(struct smb_request
*req
)
4622 connection_struct
*conn
= req
->conn
;
4628 START_PROFILE(SMBlseek
);
4631 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4632 END_PROFILE(SMBlseek
);
4636 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4638 if (!check_fsp(conn
, req
, fsp
)) {
4642 flush_write_cache(fsp
, SEEK_FLUSH
);
4644 mode
= SVAL(req
->vwv
+1, 0) & 3;
4645 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4646 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
4655 res
= fsp
->fh
->pos
+ startpos
;
4666 if (umode
== SEEK_END
) {
4667 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4668 if(errno
== EINVAL
) {
4669 off_t current_pos
= startpos
;
4671 if(fsp_stat(fsp
) == -1) {
4673 map_nt_error_from_unix(errno
));
4674 END_PROFILE(SMBlseek
);
4678 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4680 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4685 reply_nterror(req
, map_nt_error_from_unix(errno
));
4686 END_PROFILE(SMBlseek
);
4693 reply_outbuf(req
, 2, 0);
4694 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4696 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4697 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4699 END_PROFILE(SMBlseek
);
4703 /****************************************************************************
4705 ****************************************************************************/
4707 void reply_flush(struct smb_request
*req
)
4709 connection_struct
*conn
= req
->conn
;
4713 START_PROFILE(SMBflush
);
4716 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4720 fnum
= SVAL(req
->vwv
+0, 0);
4721 fsp
= file_fsp(req
, fnum
);
4723 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4728 file_sync_all(conn
);
4730 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4731 if (!NT_STATUS_IS_OK(status
)) {
4732 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4733 fsp_str_dbg(fsp
), nt_errstr(status
)));
4734 reply_nterror(req
, status
);
4735 END_PROFILE(SMBflush
);
4740 reply_outbuf(req
, 0, 0);
4742 DEBUG(3,("flush\n"));
4743 END_PROFILE(SMBflush
);
4747 /****************************************************************************
4749 conn POINTER CAN BE NULL HERE !
4750 ****************************************************************************/
4752 void reply_exit(struct smb_request
*req
)
4754 START_PROFILE(SMBexit
);
4756 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
4758 reply_outbuf(req
, 0, 0);
4760 DEBUG(3,("exit\n"));
4762 END_PROFILE(SMBexit
);
4766 /****************************************************************************
4767 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4768 ****************************************************************************/
4770 void reply_close(struct smb_request
*req
)
4772 connection_struct
*conn
= req
->conn
;
4773 NTSTATUS status
= NT_STATUS_OK
;
4774 files_struct
*fsp
= NULL
;
4775 START_PROFILE(SMBclose
);
4778 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4779 END_PROFILE(SMBclose
);
4783 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4786 * We can only use check_fsp if we know it's not a directory.
4789 if (!check_fsp_open(conn
, req
, fsp
)) {
4790 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4791 END_PROFILE(SMBclose
);
4795 if(fsp
->is_directory
) {
4797 * Special case - close NT SMB directory handle.
4799 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4800 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4804 * Close ordinary file.
4807 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4808 fsp
->fh
->fd
, fsp
->fnum
,
4809 conn
->num_files_open
));
4812 * Take care of any time sent in the close.
4815 t
= srv_make_unix_date3(req
->vwv
+1);
4816 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4819 * close_file() returns the unix errno if an error
4820 * was detected on close - normally this is due to
4821 * a disk full error. If not then it was probably an I/O error.
4824 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4827 if (!NT_STATUS_IS_OK(status
)) {
4828 reply_nterror(req
, status
);
4829 END_PROFILE(SMBclose
);
4833 reply_outbuf(req
, 0, 0);
4834 END_PROFILE(SMBclose
);
4838 /****************************************************************************
4839 Reply to a writeclose (Core+ protocol).
4840 ****************************************************************************/
4842 void reply_writeclose(struct smb_request
*req
)
4844 connection_struct
*conn
= req
->conn
;
4846 ssize_t nwritten
= -1;
4847 NTSTATUS close_status
= NT_STATUS_OK
;
4850 struct timespec mtime
;
4852 struct lock_struct lock
;
4854 START_PROFILE(SMBwriteclose
);
4857 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4858 END_PROFILE(SMBwriteclose
);
4862 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4864 if (!check_fsp(conn
, req
, fsp
)) {
4865 END_PROFILE(SMBwriteclose
);
4868 if (!CHECK_WRITE(fsp
)) {
4869 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4870 END_PROFILE(SMBwriteclose
);
4874 numtowrite
= SVAL(req
->vwv
+1, 0);
4875 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4876 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4877 data
= (const char *)req
->buf
+ 1;
4879 if (!fsp
->print_file
) {
4880 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4881 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4884 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4885 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4886 END_PROFILE(SMBwriteclose
);
4891 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4893 set_close_write_time(fsp
, mtime
);
4896 * More insanity. W2K only closes the file if writelen > 0.
4901 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4902 "file %s\n", fsp_str_dbg(fsp
)));
4903 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4906 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4907 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4908 conn
->num_files_open
));
4910 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4911 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4915 if(!NT_STATUS_IS_OK(close_status
)) {
4916 reply_nterror(req
, close_status
);
4920 reply_outbuf(req
, 1, 0);
4922 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4925 if (numtowrite
&& !fsp
->print_file
) {
4926 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4929 END_PROFILE(SMBwriteclose
);
4934 #define DBGC_CLASS DBGC_LOCKING
4936 /****************************************************************************
4938 ****************************************************************************/
4940 void reply_lock(struct smb_request
*req
)
4942 connection_struct
*conn
= req
->conn
;
4943 uint64_t count
,offset
;
4946 struct byte_range_lock
*br_lck
= NULL
;
4948 START_PROFILE(SMBlock
);
4951 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4952 END_PROFILE(SMBlock
);
4956 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4958 if (!check_fsp(conn
, req
, fsp
)) {
4959 END_PROFILE(SMBlock
);
4963 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
4964 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
4966 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4967 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
4969 br_lck
= do_lock(req
->sconn
->msg_ctx
,
4971 (uint64_t)req
->smbpid
,
4976 False
, /* Non-blocking lock. */
4981 TALLOC_FREE(br_lck
);
4983 if (NT_STATUS_V(status
)) {
4984 reply_nterror(req
, status
);
4985 END_PROFILE(SMBlock
);
4989 reply_outbuf(req
, 0, 0);
4991 END_PROFILE(SMBlock
);
4995 /****************************************************************************
4997 ****************************************************************************/
4999 void reply_unlock(struct smb_request
*req
)
5001 connection_struct
*conn
= req
->conn
;
5002 uint64_t count
,offset
;
5006 START_PROFILE(SMBunlock
);
5009 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5010 END_PROFILE(SMBunlock
);
5014 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5016 if (!check_fsp(conn
, req
, fsp
)) {
5017 END_PROFILE(SMBunlock
);
5021 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5022 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5024 status
= do_unlock(req
->sconn
->msg_ctx
,
5026 (uint64_t)req
->smbpid
,
5031 if (NT_STATUS_V(status
)) {
5032 reply_nterror(req
, status
);
5033 END_PROFILE(SMBunlock
);
5037 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5038 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
5040 reply_outbuf(req
, 0, 0);
5042 END_PROFILE(SMBunlock
);
5047 #define DBGC_CLASS DBGC_ALL
5049 /****************************************************************************
5051 conn POINTER CAN BE NULL HERE !
5052 ****************************************************************************/
5054 void reply_tdis(struct smb_request
*req
)
5056 connection_struct
*conn
= req
->conn
;
5057 START_PROFILE(SMBtdis
);
5060 DEBUG(4,("Invalid connection in tdis\n"));
5061 reply_nterror(req
, NT_STATUS_NETWORK_NAME_DELETED
);
5062 END_PROFILE(SMBtdis
);
5068 close_cnum(conn
,req
->vuid
);
5071 reply_outbuf(req
, 0, 0);
5072 END_PROFILE(SMBtdis
);
5076 /****************************************************************************
5078 conn POINTER CAN BE NULL HERE !
5079 ****************************************************************************/
5081 void reply_echo(struct smb_request
*req
)
5083 connection_struct
*conn
= req
->conn
;
5084 struct smb_perfcount_data local_pcd
;
5085 struct smb_perfcount_data
*cur_pcd
;
5089 START_PROFILE(SMBecho
);
5091 smb_init_perfcount_data(&local_pcd
);
5094 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5095 END_PROFILE(SMBecho
);
5099 smb_reverb
= SVAL(req
->vwv
+0, 0);
5101 reply_outbuf(req
, 1, req
->buflen
);
5103 /* copy any incoming data back out */
5104 if (req
->buflen
> 0) {
5105 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5108 if (smb_reverb
> 100) {
5109 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5113 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5115 /* this makes sure we catch the request pcd */
5116 if (seq_num
== smb_reverb
) {
5117 cur_pcd
= &req
->pcd
;
5119 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5120 cur_pcd
= &local_pcd
;
5123 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5125 show_msg((char *)req
->outbuf
);
5126 if (!srv_send_smb(req
->sconn
,
5127 (char *)req
->outbuf
,
5128 true, req
->seqnum
+1,
5129 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5131 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5134 DEBUG(3,("echo %d times\n", smb_reverb
));
5136 TALLOC_FREE(req
->outbuf
);
5138 END_PROFILE(SMBecho
);
5142 /****************************************************************************
5143 Reply to a printopen.
5144 ****************************************************************************/
5146 void reply_printopen(struct smb_request
*req
)
5148 connection_struct
*conn
= req
->conn
;
5152 START_PROFILE(SMBsplopen
);
5155 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5156 END_PROFILE(SMBsplopen
);
5160 if (!CAN_PRINT(conn
)) {
5161 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5162 END_PROFILE(SMBsplopen
);
5166 status
= file_new(req
, conn
, &fsp
);
5167 if(!NT_STATUS_IS_OK(status
)) {
5168 reply_nterror(req
, status
);
5169 END_PROFILE(SMBsplopen
);
5173 /* Open for exclusive use, write only. */
5174 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5176 if (!NT_STATUS_IS_OK(status
)) {
5177 file_free(req
, fsp
);
5178 reply_nterror(req
, status
);
5179 END_PROFILE(SMBsplopen
);
5183 reply_outbuf(req
, 1, 0);
5184 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5186 DEBUG(3,("openprint fd=%d fnum=%d\n",
5187 fsp
->fh
->fd
, fsp
->fnum
));
5189 END_PROFILE(SMBsplopen
);
5193 /****************************************************************************
5194 Reply to a printclose.
5195 ****************************************************************************/
5197 void reply_printclose(struct smb_request
*req
)
5199 connection_struct
*conn
= req
->conn
;
5203 START_PROFILE(SMBsplclose
);
5206 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5207 END_PROFILE(SMBsplclose
);
5211 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5213 if (!check_fsp(conn
, req
, fsp
)) {
5214 END_PROFILE(SMBsplclose
);
5218 if (!CAN_PRINT(conn
)) {
5219 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5220 END_PROFILE(SMBsplclose
);
5224 DEBUG(3,("printclose fd=%d fnum=%d\n",
5225 fsp
->fh
->fd
,fsp
->fnum
));
5227 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5229 if(!NT_STATUS_IS_OK(status
)) {
5230 reply_nterror(req
, status
);
5231 END_PROFILE(SMBsplclose
);
5235 reply_outbuf(req
, 0, 0);
5237 END_PROFILE(SMBsplclose
);
5241 /****************************************************************************
5242 Reply to a printqueue.
5243 ****************************************************************************/
5245 void reply_printqueue(struct smb_request
*req
)
5247 connection_struct
*conn
= req
->conn
;
5251 START_PROFILE(SMBsplretq
);
5254 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5255 END_PROFILE(SMBsplretq
);
5259 max_count
= SVAL(req
->vwv
+0, 0);
5260 start_index
= SVAL(req
->vwv
+1, 0);
5262 /* we used to allow the client to get the cnum wrong, but that
5263 is really quite gross and only worked when there was only
5264 one printer - I think we should now only accept it if they
5265 get it right (tridge) */
5266 if (!CAN_PRINT(conn
)) {
5267 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5268 END_PROFILE(SMBsplretq
);
5272 reply_outbuf(req
, 2, 3);
5273 SSVAL(req
->outbuf
,smb_vwv0
,0);
5274 SSVAL(req
->outbuf
,smb_vwv1
,0);
5275 SCVAL(smb_buf(req
->outbuf
),0,1);
5276 SSVAL(smb_buf(req
->outbuf
),1,0);
5278 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5279 start_index
, max_count
));
5282 TALLOC_CTX
*mem_ctx
= talloc_tos();
5285 const char *sharename
= lp_servicename(SNUM(conn
));
5286 struct rpc_pipe_client
*cli
= NULL
;
5287 struct dcerpc_binding_handle
*b
= NULL
;
5288 struct policy_handle handle
;
5289 struct spoolss_DevmodeContainer devmode_ctr
;
5290 union spoolss_JobInfo
*info
;
5292 uint32_t num_to_get
;
5296 ZERO_STRUCT(handle
);
5298 status
= rpc_pipe_open_interface(conn
,
5299 &ndr_table_spoolss
.syntax_id
,
5301 conn
->sconn
->remote_address
,
5302 conn
->sconn
->msg_ctx
,
5304 if (!NT_STATUS_IS_OK(status
)) {
5305 DEBUG(0, ("reply_printqueue: "
5306 "could not connect to spoolss: %s\n",
5307 nt_errstr(status
)));
5308 reply_nterror(req
, status
);
5311 b
= cli
->binding_handle
;
5313 ZERO_STRUCT(devmode_ctr
);
5315 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5318 SEC_FLAG_MAXIMUM_ALLOWED
,
5321 if (!NT_STATUS_IS_OK(status
)) {
5322 reply_nterror(req
, status
);
5325 if (!W_ERROR_IS_OK(werr
)) {
5326 reply_nterror(req
, werror_to_ntstatus(werr
));
5330 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5338 if (!W_ERROR_IS_OK(werr
)) {
5339 reply_nterror(req
, werror_to_ntstatus(werr
));
5343 if (max_count
> 0) {
5344 first
= start_index
;
5346 first
= start_index
+ max_count
+ 1;
5349 if (first
>= count
) {
5352 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5355 for (i
= first
; i
< num_to_get
; i
++) {
5358 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5360 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5361 info
[i
].info2
.job_id
);
5363 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5369 srv_put_dos_date2(p
, 0, qtime
);
5370 SCVAL(p
, 4, qstatus
);
5371 SSVAL(p
, 5, qrapjobid
);
5372 SIVAL(p
, 7, info
[i
].info2
.size
);
5374 srvstr_push(blob
, req
->flags2
, p
+12,
5375 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5377 if (message_push_blob(
5380 blob
, sizeof(blob
))) == -1) {
5381 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5387 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5388 SSVAL(req
->outbuf
,smb_vwv1
,
5389 (max_count
>0?first
+count
:first
-1));
5390 SCVAL(smb_buf(req
->outbuf
),0,1);
5391 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5395 DEBUG(3, ("%u entries returned in queue\n",
5399 if (b
&& is_valid_policy_hnd(&handle
)) {
5400 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5405 END_PROFILE(SMBsplretq
);
5409 /****************************************************************************
5410 Reply to a printwrite.
5411 ****************************************************************************/
5413 void reply_printwrite(struct smb_request
*req
)
5415 connection_struct
*conn
= req
->conn
;
5420 START_PROFILE(SMBsplwr
);
5423 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5424 END_PROFILE(SMBsplwr
);
5428 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5430 if (!check_fsp(conn
, req
, fsp
)) {
5431 END_PROFILE(SMBsplwr
);
5435 if (!fsp
->print_file
) {
5436 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5437 END_PROFILE(SMBsplwr
);
5441 if (!CHECK_WRITE(fsp
)) {
5442 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5443 END_PROFILE(SMBsplwr
);
5447 numtowrite
= SVAL(req
->buf
, 1);
5449 if (req
->buflen
< numtowrite
+ 3) {
5450 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5451 END_PROFILE(SMBsplwr
);
5455 data
= (const char *)req
->buf
+ 3;
5457 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
5458 reply_nterror(req
, map_nt_error_from_unix(errno
));
5459 END_PROFILE(SMBsplwr
);
5463 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
5465 END_PROFILE(SMBsplwr
);
5469 /****************************************************************************
5471 ****************************************************************************/
5473 void reply_mkdir(struct smb_request
*req
)
5475 connection_struct
*conn
= req
->conn
;
5476 struct smb_filename
*smb_dname
= NULL
;
5477 char *directory
= NULL
;
5479 TALLOC_CTX
*ctx
= talloc_tos();
5481 START_PROFILE(SMBmkdir
);
5483 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5484 STR_TERMINATE
, &status
);
5485 if (!NT_STATUS_IS_OK(status
)) {
5486 reply_nterror(req
, status
);
5490 status
= filename_convert(ctx
, conn
,
5491 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5496 if (!NT_STATUS_IS_OK(status
)) {
5497 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5498 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5499 ERRSRV
, ERRbadpath
);
5502 reply_nterror(req
, status
);
5506 status
= create_directory(conn
, req
, smb_dname
);
5508 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5510 if (!NT_STATUS_IS_OK(status
)) {
5512 if (!use_nt_status()
5513 && NT_STATUS_EQUAL(status
,
5514 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5516 * Yes, in the DOS error code case we get a
5517 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5518 * samba4 torture test.
5520 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5523 reply_nterror(req
, status
);
5527 reply_outbuf(req
, 0, 0);
5529 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5531 TALLOC_FREE(smb_dname
);
5532 END_PROFILE(SMBmkdir
);
5536 /****************************************************************************
5538 ****************************************************************************/
5540 void reply_rmdir(struct smb_request
*req
)
5542 connection_struct
*conn
= req
->conn
;
5543 struct smb_filename
*smb_dname
= NULL
;
5544 char *directory
= NULL
;
5546 TALLOC_CTX
*ctx
= talloc_tos();
5547 files_struct
*fsp
= NULL
;
5549 struct smbd_server_connection
*sconn
= req
->sconn
;
5551 START_PROFILE(SMBrmdir
);
5553 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5554 STR_TERMINATE
, &status
);
5555 if (!NT_STATUS_IS_OK(status
)) {
5556 reply_nterror(req
, status
);
5560 status
= filename_convert(ctx
, conn
,
5561 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5566 if (!NT_STATUS_IS_OK(status
)) {
5567 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5568 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5569 ERRSRV
, ERRbadpath
);
5572 reply_nterror(req
, status
);
5576 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5577 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5581 status
= SMB_VFS_CREATE_FILE(
5584 0, /* root_dir_fid */
5585 smb_dname
, /* fname */
5586 DELETE_ACCESS
, /* access_mask */
5587 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5589 FILE_OPEN
, /* create_disposition*/
5590 FILE_DIRECTORY_FILE
, /* create_options */
5591 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5592 0, /* oplock_request */
5593 0, /* allocation_size */
5594 0, /* private_flags */
5600 if (!NT_STATUS_IS_OK(status
)) {
5601 if (open_was_deferred(req
->sconn
, req
->mid
)) {
5602 /* We have re-scheduled this call. */
5605 reply_nterror(req
, status
);
5609 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5610 if (!NT_STATUS_IS_OK(status
)) {
5611 close_file(req
, fsp
, ERROR_CLOSE
);
5612 reply_nterror(req
, status
);
5616 if (!set_delete_on_close(fsp
, true,
5617 conn
->session_info
->security_token
,
5618 conn
->session_info
->unix_token
)) {
5619 close_file(req
, fsp
, ERROR_CLOSE
);
5620 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5624 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5625 if (!NT_STATUS_IS_OK(status
)) {
5626 reply_nterror(req
, status
);
5628 reply_outbuf(req
, 0, 0);
5631 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5633 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5635 TALLOC_FREE(smb_dname
);
5636 END_PROFILE(SMBrmdir
);
5640 /*******************************************************************
5641 Resolve wildcards in a filename rename.
5642 ********************************************************************/
5644 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5649 char *name2_copy
= NULL
;
5654 char *p
,*p2
, *pname1
, *pname2
;
5656 name2_copy
= talloc_strdup(ctx
, name2
);
5661 pname1
= strrchr_m(name1
,'/');
5662 pname2
= strrchr_m(name2_copy
,'/');
5664 if (!pname1
|| !pname2
) {
5668 /* Truncate the copy of name2 at the last '/' */
5671 /* Now go past the '/' */
5675 root1
= talloc_strdup(ctx
, pname1
);
5676 root2
= talloc_strdup(ctx
, pname2
);
5678 if (!root1
|| !root2
) {
5682 p
= strrchr_m(root1
,'.');
5685 ext1
= talloc_strdup(ctx
, p
+1);
5687 ext1
= talloc_strdup(ctx
, "");
5689 p
= strrchr_m(root2
,'.');
5692 ext2
= talloc_strdup(ctx
, p
+1);
5694 ext2
= talloc_strdup(ctx
, "");
5697 if (!ext1
|| !ext2
) {
5705 /* Hmmm. Should this be mb-aware ? */
5708 } else if (*p2
== '*') {
5710 root2
= talloc_asprintf(ctx
, "%s%s",
5729 /* Hmmm. Should this be mb-aware ? */
5732 } else if (*p2
== '*') {
5734 ext2
= talloc_asprintf(ctx
, "%s%s",
5750 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5755 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5767 /****************************************************************************
5768 Ensure open files have their names updated. Updated to notify other smbd's
5770 ****************************************************************************/
5772 static void rename_open_files(connection_struct
*conn
,
5773 struct share_mode_lock
*lck
,
5774 uint32_t orig_name_hash
,
5775 const struct smb_filename
*smb_fname_dst
)
5778 bool did_rename
= False
;
5780 uint32_t new_name_hash
= 0;
5782 for(fsp
= file_find_di_first(conn
->sconn
, lck
->data
->id
); fsp
;
5783 fsp
= file_find_di_next(fsp
)) {
5784 /* fsp_name is a relative path under the fsp. To change this for other
5785 sharepaths we need to manipulate relative paths. */
5786 /* TODO - create the absolute path and manipulate the newname
5787 relative to the sharepath. */
5788 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5791 if (fsp
->name_hash
!= orig_name_hash
) {
5794 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5795 "(file_id %s) from %s -> %s\n", fsp
->fnum
,
5796 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
5797 smb_fname_str_dbg(smb_fname_dst
)));
5799 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
5800 if (NT_STATUS_IS_OK(status
)) {
5802 new_name_hash
= fsp
->name_hash
;
5807 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5808 "for %s\n", file_id_string_tos(&lck
->data
->id
),
5809 smb_fname_str_dbg(smb_fname_dst
)));
5812 /* Send messages to all smbd's (not ourself) that the name has changed. */
5813 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, conn
->connectpath
,
5814 orig_name_hash
, new_name_hash
,
5819 /****************************************************************************
5820 We need to check if the source path is a parent directory of the destination
5821 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5822 refuse the rename with a sharing violation. Under UNIX the above call can
5823 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5824 probably need to check that the client is a Windows one before disallowing
5825 this as a UNIX client (one with UNIX extensions) can know the source is a
5826 symlink and make this decision intelligently. Found by an excellent bug
5827 report from <AndyLiebman@aol.com>.
5828 ****************************************************************************/
5830 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
5831 const struct smb_filename
*smb_fname_dst
)
5833 const char *psrc
= smb_fname_src
->base_name
;
5834 const char *pdst
= smb_fname_dst
->base_name
;
5837 if (psrc
[0] == '.' && psrc
[1] == '/') {
5840 if (pdst
[0] == '.' && pdst
[1] == '/') {
5843 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5846 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5850 * Do the notify calls from a rename
5853 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5854 const struct smb_filename
*smb_fname_src
,
5855 const struct smb_filename
*smb_fname_dst
)
5857 char *parent_dir_src
= NULL
;
5858 char *parent_dir_dst
= NULL
;
5861 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5862 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5864 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
5865 &parent_dir_src
, NULL
) ||
5866 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
5867 &parent_dir_dst
, NULL
)) {
5871 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
5872 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
5873 smb_fname_src
->base_name
);
5874 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
5875 smb_fname_dst
->base_name
);
5878 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
5879 smb_fname_src
->base_name
);
5880 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
5881 smb_fname_dst
->base_name
);
5884 /* this is a strange one. w2k3 gives an additional event for
5885 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5886 files, but not directories */
5888 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5889 FILE_NOTIFY_CHANGE_ATTRIBUTES
5890 |FILE_NOTIFY_CHANGE_CREATION
,
5891 smb_fname_dst
->base_name
);
5894 TALLOC_FREE(parent_dir_src
);
5895 TALLOC_FREE(parent_dir_dst
);
5898 /****************************************************************************
5899 Returns an error if the parent directory for a filename is open in an
5901 ****************************************************************************/
5903 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
5904 const struct smb_filename
*smb_fname_dst_in
)
5906 char *parent_dir
= NULL
;
5907 struct smb_filename smb_fname_parent
;
5909 files_struct
*fsp
= NULL
;
5912 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
5913 &parent_dir
, NULL
)) {
5914 return NT_STATUS_NO_MEMORY
;
5916 ZERO_STRUCT(smb_fname_parent
);
5917 smb_fname_parent
.base_name
= parent_dir
;
5919 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
5921 return map_nt_error_from_unix(errno
);
5925 * We're only checking on this smbd here, mostly good
5926 * enough.. and will pass tests.
5929 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
5930 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
5931 fsp
= file_find_di_next(fsp
)) {
5932 if (fsp
->access_mask
& DELETE_ACCESS
) {
5933 return NT_STATUS_SHARING_VIOLATION
;
5936 return NT_STATUS_OK
;
5939 /****************************************************************************
5940 Rename an open file - given an fsp.
5941 ****************************************************************************/
5943 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
5945 const struct smb_filename
*smb_fname_dst_in
,
5947 bool replace_if_exists
)
5949 TALLOC_CTX
*ctx
= talloc_tos();
5950 struct smb_filename
*smb_fname_dst
= NULL
;
5951 NTSTATUS status
= NT_STATUS_OK
;
5952 struct share_mode_lock
*lck
= NULL
;
5953 bool dst_exists
, old_is_stream
, new_is_stream
;
5955 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
5956 if (!NT_STATUS_IS_OK(status
)) {
5960 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
5961 if (!NT_STATUS_IS_OK(status
)) {
5965 /* Make a copy of the dst smb_fname structs */
5967 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
5968 if (!NT_STATUS_IS_OK(status
)) {
5973 * Check for special case with case preserving and not
5974 * case sensitive. If the old last component differs from the original
5975 * last component only by case, then we should allow
5976 * the rename (user is trying to change the case of the
5979 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
5980 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
5981 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
5983 char *fname_dst_lcomp_base_mod
= NULL
;
5984 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
5987 * Get the last component of the destination name.
5989 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
5991 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
5993 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
5995 if (!fname_dst_lcomp_base_mod
) {
5996 status
= NT_STATUS_NO_MEMORY
;
6001 * Create an smb_filename struct using the original last
6002 * component of the destination.
6004 status
= create_synthetic_smb_fname_split(ctx
,
6005 smb_fname_dst
->original_lcomp
, NULL
,
6006 &smb_fname_orig_lcomp
);
6007 if (!NT_STATUS_IS_OK(status
)) {
6008 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6012 /* If the base names only differ by case, use original. */
6013 if(!strcsequal(fname_dst_lcomp_base_mod
,
6014 smb_fname_orig_lcomp
->base_name
)) {
6017 * Replace the modified last component with the
6021 *last_slash
= '\0'; /* Truncate at the '/' */
6022 tmp
= talloc_asprintf(smb_fname_dst
,
6024 smb_fname_dst
->base_name
,
6025 smb_fname_orig_lcomp
->base_name
);
6027 tmp
= talloc_asprintf(smb_fname_dst
,
6029 smb_fname_orig_lcomp
->base_name
);
6032 status
= NT_STATUS_NO_MEMORY
;
6033 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6034 TALLOC_FREE(smb_fname_orig_lcomp
);
6037 TALLOC_FREE(smb_fname_dst
->base_name
);
6038 smb_fname_dst
->base_name
= tmp
;
6041 /* If the stream_names only differ by case, use original. */
6042 if(!strcsequal(smb_fname_dst
->stream_name
,
6043 smb_fname_orig_lcomp
->stream_name
)) {
6045 /* Use the original stream. */
6046 tmp
= talloc_strdup(smb_fname_dst
,
6047 smb_fname_orig_lcomp
->stream_name
);
6049 status
= NT_STATUS_NO_MEMORY
;
6050 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6051 TALLOC_FREE(smb_fname_orig_lcomp
);
6054 TALLOC_FREE(smb_fname_dst
->stream_name
);
6055 smb_fname_dst
->stream_name
= tmp
;
6057 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6058 TALLOC_FREE(smb_fname_orig_lcomp
);
6062 * If the src and dest names are identical - including case,
6063 * don't do the rename, just return success.
6066 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6067 strcsequal(fsp
->fsp_name
->stream_name
,
6068 smb_fname_dst
->stream_name
)) {
6069 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6070 "- returning success\n",
6071 smb_fname_str_dbg(smb_fname_dst
)));
6072 status
= NT_STATUS_OK
;
6076 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6077 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6079 /* Return the correct error code if both names aren't streams. */
6080 if (!old_is_stream
&& new_is_stream
) {
6081 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6085 if (old_is_stream
&& !new_is_stream
) {
6086 status
= NT_STATUS_INVALID_PARAMETER
;
6090 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6092 if(!replace_if_exists
&& dst_exists
) {
6093 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6094 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6095 smb_fname_str_dbg(smb_fname_dst
)));
6096 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6101 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6102 &smb_fname_dst
->st
);
6103 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6105 /* The file can be open when renaming a stream */
6106 if (dst_fsp
&& !new_is_stream
) {
6107 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6108 status
= NT_STATUS_ACCESS_DENIED
;
6113 /* Ensure we have a valid stat struct for the source. */
6114 status
= vfs_stat_fsp(fsp
);
6115 if (!NT_STATUS_IS_OK(status
)) {
6119 status
= can_rename(conn
, fsp
, attrs
);
6121 if (!NT_STATUS_IS_OK(status
)) {
6122 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6123 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6124 smb_fname_str_dbg(smb_fname_dst
)));
6125 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6126 status
= NT_STATUS_ACCESS_DENIED
;
6130 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6131 status
= NT_STATUS_ACCESS_DENIED
;
6134 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6137 * We have the file open ourselves, so not being able to get the
6138 * corresponding share mode lock is a fatal error.
6141 SMB_ASSERT(lck
!= NULL
);
6143 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6144 uint32 create_options
= fsp
->fh
->private_options
;
6146 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6147 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6148 smb_fname_str_dbg(smb_fname_dst
)));
6150 if (!lp_posix_pathnames() &&
6151 (lp_map_archive(SNUM(conn
)) ||
6152 lp_store_dos_attributes(SNUM(conn
)))) {
6153 /* We must set the archive bit on the newly
6155 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6156 uint32_t old_dosmode
= dos_mode(conn
,
6158 file_set_dosmode(conn
,
6160 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6166 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6169 rename_open_files(conn
, lck
, fsp
->name_hash
, smb_fname_dst
);
6172 * A rename acts as a new file create w.r.t. allowing an initial delete
6173 * on close, probably because in Windows there is a new handle to the
6174 * new file. If initial delete on close was requested but not
6175 * originally set, we need to set it here. This is probably not 100% correct,
6176 * but will work for the CIFSFS client which in non-posix mode
6177 * depends on these semantics. JRA.
6180 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6181 status
= can_set_delete_on_close(fsp
, 0);
6183 if (NT_STATUS_IS_OK(status
)) {
6184 /* Note that here we set the *inital* delete on close flag,
6185 * not the regular one. The magic gets handled in close. */
6186 fsp
->initial_delete_on_close
= True
;
6190 status
= NT_STATUS_OK
;
6196 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6197 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6199 status
= map_nt_error_from_unix(errno
);
6202 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6203 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6204 smb_fname_str_dbg(smb_fname_dst
)));
6207 TALLOC_FREE(smb_fname_dst
);
6212 /****************************************************************************
6213 The guts of the rename command, split out so it may be called by the NT SMB
6215 ****************************************************************************/
6217 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6218 connection_struct
*conn
,
6219 struct smb_request
*req
,
6220 struct smb_filename
*smb_fname_src
,
6221 struct smb_filename
*smb_fname_dst
,
6223 bool replace_if_exists
,
6226 uint32_t access_mask
)
6228 char *fname_src_dir
= NULL
;
6229 char *fname_src_mask
= NULL
;
6231 NTSTATUS status
= NT_STATUS_OK
;
6232 struct smb_Dir
*dir_hnd
= NULL
;
6233 const char *dname
= NULL
;
6234 char *talloced
= NULL
;
6236 int create_options
= 0;
6237 bool posix_pathnames
= lp_posix_pathnames();
6240 * Split the old name into directory and last component
6241 * strings. Note that unix_convert may have stripped off a
6242 * leading ./ from both name and newname if the rename is
6243 * at the root of the share. We need to make sure either both
6244 * name and newname contain a / character or neither of them do
6245 * as this is checked in resolve_wildcards().
6248 /* Split up the directory from the filename/mask. */
6249 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6250 &fname_src_dir
, &fname_src_mask
);
6251 if (!NT_STATUS_IS_OK(status
)) {
6252 status
= NT_STATUS_NO_MEMORY
;
6257 * We should only check the mangled cache
6258 * here if unix_convert failed. This means
6259 * that the path in 'mask' doesn't exist
6260 * on the file system and so we need to look
6261 * for a possible mangle. This patch from
6262 * Tine Smukavec <valentin.smukavec@hermes.si>.
6265 if (!VALID_STAT(smb_fname_src
->st
) &&
6266 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6267 char *new_mask
= NULL
;
6268 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6271 TALLOC_FREE(fname_src_mask
);
6272 fname_src_mask
= new_mask
;
6276 if (!src_has_wild
) {
6280 * Only one file needs to be renamed. Append the mask back
6281 * onto the directory.
6283 TALLOC_FREE(smb_fname_src
->base_name
);
6284 if (ISDOT(fname_src_dir
)) {
6285 /* Ensure we use canonical names on open. */
6286 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6290 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6295 if (!smb_fname_src
->base_name
) {
6296 status
= NT_STATUS_NO_MEMORY
;
6300 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6301 "case_preserve = %d, short case preserve = %d, "
6302 "directory = %s, newname = %s, "
6303 "last_component_dest = %s\n",
6304 conn
->case_sensitive
, conn
->case_preserve
,
6305 conn
->short_case_preserve
,
6306 smb_fname_str_dbg(smb_fname_src
),
6307 smb_fname_str_dbg(smb_fname_dst
),
6308 smb_fname_dst
->original_lcomp
));
6310 /* The dest name still may have wildcards. */
6311 if (dest_has_wild
) {
6312 char *fname_dst_mod
= NULL
;
6313 if (!resolve_wildcards(smb_fname_dst
,
6314 smb_fname_src
->base_name
,
6315 smb_fname_dst
->base_name
,
6317 DEBUG(6, ("rename_internals: resolve_wildcards "
6319 smb_fname_src
->base_name
,
6320 smb_fname_dst
->base_name
));
6321 status
= NT_STATUS_NO_MEMORY
;
6324 TALLOC_FREE(smb_fname_dst
->base_name
);
6325 smb_fname_dst
->base_name
= fname_dst_mod
;
6328 ZERO_STRUCT(smb_fname_src
->st
);
6329 if (posix_pathnames
) {
6330 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6332 SMB_VFS_STAT(conn
, smb_fname_src
);
6335 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6336 create_options
|= FILE_DIRECTORY_FILE
;
6339 status
= SMB_VFS_CREATE_FILE(
6342 0, /* root_dir_fid */
6343 smb_fname_src
, /* fname */
6344 access_mask
, /* access_mask */
6345 (FILE_SHARE_READ
| /* share_access */
6347 FILE_OPEN
, /* create_disposition*/
6348 create_options
, /* create_options */
6349 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6350 0, /* oplock_request */
6351 0, /* allocation_size */
6352 0, /* private_flags */
6358 if (!NT_STATUS_IS_OK(status
)) {
6359 DEBUG(3, ("Could not open rename source %s: %s\n",
6360 smb_fname_str_dbg(smb_fname_src
),
6361 nt_errstr(status
)));
6365 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6366 attrs
, replace_if_exists
);
6368 close_file(req
, fsp
, NORMAL_CLOSE
);
6370 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6371 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6372 smb_fname_str_dbg(smb_fname_dst
)));
6378 * Wildcards - process each file that matches.
6380 if (strequal(fname_src_mask
, "????????.???")) {
6381 TALLOC_FREE(fname_src_mask
);
6382 fname_src_mask
= talloc_strdup(ctx
, "*");
6383 if (!fname_src_mask
) {
6384 status
= NT_STATUS_NO_MEMORY
;
6389 status
= check_name(conn
, fname_src_dir
);
6390 if (!NT_STATUS_IS_OK(status
)) {
6394 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6396 if (dir_hnd
== NULL
) {
6397 status
= map_nt_error_from_unix(errno
);
6401 status
= NT_STATUS_NO_SUCH_FILE
;
6403 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6404 * - gentest fix. JRA
6407 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6409 files_struct
*fsp
= NULL
;
6410 char *destname
= NULL
;
6411 bool sysdir_entry
= False
;
6413 /* Quick check for "." and ".." */
6414 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6415 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6416 sysdir_entry
= True
;
6418 TALLOC_FREE(talloced
);
6423 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6424 &smb_fname_src
->st
, false)) {
6425 TALLOC_FREE(talloced
);
6429 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6430 TALLOC_FREE(talloced
);
6435 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6439 TALLOC_FREE(smb_fname_src
->base_name
);
6440 if (ISDOT(fname_src_dir
)) {
6441 /* Ensure we use canonical names on open. */
6442 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6446 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6451 if (!smb_fname_src
->base_name
) {
6452 status
= NT_STATUS_NO_MEMORY
;
6456 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6457 smb_fname_dst
->base_name
,
6459 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6460 smb_fname_src
->base_name
, destname
));
6461 TALLOC_FREE(talloced
);
6465 status
= NT_STATUS_NO_MEMORY
;
6469 TALLOC_FREE(smb_fname_dst
->base_name
);
6470 smb_fname_dst
->base_name
= destname
;
6472 ZERO_STRUCT(smb_fname_src
->st
);
6473 if (posix_pathnames
) {
6474 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6476 SMB_VFS_STAT(conn
, smb_fname_src
);
6481 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6482 create_options
|= FILE_DIRECTORY_FILE
;
6485 status
= SMB_VFS_CREATE_FILE(
6488 0, /* root_dir_fid */
6489 smb_fname_src
, /* fname */
6490 access_mask
, /* access_mask */
6491 (FILE_SHARE_READ
| /* share_access */
6493 FILE_OPEN
, /* create_disposition*/
6494 create_options
, /* create_options */
6495 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6496 0, /* oplock_request */
6497 0, /* allocation_size */
6498 0, /* private_flags */
6504 if (!NT_STATUS_IS_OK(status
)) {
6505 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6506 "returned %s rename %s -> %s\n",
6508 smb_fname_str_dbg(smb_fname_src
),
6509 smb_fname_str_dbg(smb_fname_dst
)));
6513 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6515 if (!smb_fname_dst
->original_lcomp
) {
6516 status
= NT_STATUS_NO_MEMORY
;
6520 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6521 attrs
, replace_if_exists
);
6523 close_file(req
, fsp
, NORMAL_CLOSE
);
6525 if (!NT_STATUS_IS_OK(status
)) {
6526 DEBUG(3, ("rename_internals_fsp returned %s for "
6527 "rename %s -> %s\n", nt_errstr(status
),
6528 smb_fname_str_dbg(smb_fname_src
),
6529 smb_fname_str_dbg(smb_fname_dst
)));
6535 DEBUG(3,("rename_internals: doing rename on %s -> "
6536 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6537 smb_fname_str_dbg(smb_fname_src
)));
6538 TALLOC_FREE(talloced
);
6540 TALLOC_FREE(dir_hnd
);
6542 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6543 status
= map_nt_error_from_unix(errno
);
6547 TALLOC_FREE(talloced
);
6548 TALLOC_FREE(fname_src_dir
);
6549 TALLOC_FREE(fname_src_mask
);
6553 /****************************************************************************
6555 ****************************************************************************/
6557 void reply_mv(struct smb_request
*req
)
6559 connection_struct
*conn
= req
->conn
;
6561 char *newname
= NULL
;
6565 bool src_has_wcard
= False
;
6566 bool dest_has_wcard
= False
;
6567 TALLOC_CTX
*ctx
= talloc_tos();
6568 struct smb_filename
*smb_fname_src
= NULL
;
6569 struct smb_filename
*smb_fname_dst
= NULL
;
6570 uint32_t src_ucf_flags
= lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP
: UCF_COND_ALLOW_WCARD_LCOMP
;
6571 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
| (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP
);
6572 bool stream_rename
= false;
6574 START_PROFILE(SMBmv
);
6577 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6581 attrs
= SVAL(req
->vwv
+0, 0);
6583 p
= (const char *)req
->buf
+ 1;
6584 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6585 &status
, &src_has_wcard
);
6586 if (!NT_STATUS_IS_OK(status
)) {
6587 reply_nterror(req
, status
);
6591 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6592 &status
, &dest_has_wcard
);
6593 if (!NT_STATUS_IS_OK(status
)) {
6594 reply_nterror(req
, status
);
6598 if (!lp_posix_pathnames()) {
6599 /* The newname must begin with a ':' if the
6600 name contains a ':'. */
6601 if (strchr_m(name
, ':')) {
6602 if (newname
[0] != ':') {
6603 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6606 stream_rename
= true;
6610 status
= filename_convert(ctx
,
6612 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6618 if (!NT_STATUS_IS_OK(status
)) {
6619 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6620 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6621 ERRSRV
, ERRbadpath
);
6624 reply_nterror(req
, status
);
6628 status
= filename_convert(ctx
,
6630 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6636 if (!NT_STATUS_IS_OK(status
)) {
6637 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6638 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6639 ERRSRV
, ERRbadpath
);
6642 reply_nterror(req
, status
);
6646 if (stream_rename
) {
6647 /* smb_fname_dst->base_name must be the same as
6648 smb_fname_src->base_name. */
6649 TALLOC_FREE(smb_fname_dst
->base_name
);
6650 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6651 smb_fname_src
->base_name
);
6652 if (!smb_fname_dst
->base_name
) {
6653 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6658 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6659 smb_fname_str_dbg(smb_fname_dst
)));
6661 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
6662 attrs
, False
, src_has_wcard
, dest_has_wcard
,
6664 if (!NT_STATUS_IS_OK(status
)) {
6665 if (open_was_deferred(req
->sconn
, req
->mid
)) {
6666 /* We have re-scheduled this call. */
6669 reply_nterror(req
, status
);
6673 reply_outbuf(req
, 0, 0);
6675 TALLOC_FREE(smb_fname_src
);
6676 TALLOC_FREE(smb_fname_dst
);
6681 /*******************************************************************
6682 Copy a file as part of a reply_copy.
6683 ******************************************************************/
6686 * TODO: check error codes on all callers
6689 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6690 connection_struct
*conn
,
6691 struct smb_filename
*smb_fname_src
,
6692 struct smb_filename
*smb_fname_dst
,
6695 bool target_is_directory
)
6697 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
6699 files_struct
*fsp1
,*fsp2
;
6701 uint32 new_create_disposition
;
6705 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
6706 if (!NT_STATUS_IS_OK(status
)) {
6711 * If the target is a directory, extract the last component from the
6712 * src filename and append it to the dst filename
6714 if (target_is_directory
) {
6717 /* dest/target can't be a stream if it's a directory. */
6718 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
6720 p
= strrchr_m(smb_fname_src
->base_name
,'/');
6724 p
= smb_fname_src
->base_name
;
6726 smb_fname_dst_tmp
->base_name
=
6727 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
6729 if (!smb_fname_dst_tmp
->base_name
) {
6730 status
= NT_STATUS_NO_MEMORY
;
6735 status
= vfs_file_exist(conn
, smb_fname_src
);
6736 if (!NT_STATUS_IS_OK(status
)) {
6740 if (!target_is_directory
&& count
) {
6741 new_create_disposition
= FILE_OPEN
;
6743 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
6746 &new_create_disposition
,
6749 status
= NT_STATUS_INVALID_PARAMETER
;
6754 /* Open the src file for reading. */
6755 status
= SMB_VFS_CREATE_FILE(
6758 0, /* root_dir_fid */
6759 smb_fname_src
, /* fname */
6760 FILE_GENERIC_READ
, /* access_mask */
6761 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6762 FILE_OPEN
, /* create_disposition*/
6763 0, /* create_options */
6764 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6765 INTERNAL_OPEN_ONLY
, /* oplock_request */
6766 0, /* allocation_size */
6767 0, /* private_flags */
6773 if (!NT_STATUS_IS_OK(status
)) {
6777 dosattrs
= dos_mode(conn
, smb_fname_src
);
6779 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
6780 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
6783 /* Open the dst file for writing. */
6784 status
= SMB_VFS_CREATE_FILE(
6787 0, /* root_dir_fid */
6788 smb_fname_dst
, /* fname */
6789 FILE_GENERIC_WRITE
, /* access_mask */
6790 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6791 new_create_disposition
, /* create_disposition*/
6792 0, /* create_options */
6793 dosattrs
, /* file_attributes */
6794 INTERNAL_OPEN_ONLY
, /* oplock_request */
6795 0, /* allocation_size */
6796 0, /* private_flags */
6802 if (!NT_STATUS_IS_OK(status
)) {
6803 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6807 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
6808 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
6810 DEBUG(0, ("error - vfs lseek returned error %s\n",
6812 status
= map_nt_error_from_unix(errno
);
6813 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6814 close_file(NULL
, fsp2
, ERROR_CLOSE
);
6819 /* Do the actual copy. */
6820 if (smb_fname_src
->st
.st_ex_size
) {
6821 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
6826 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
6828 /* Ensure the modtime is set correctly on the destination file. */
6829 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
6832 * As we are opening fsp1 read-only we only expect
6833 * an error on close on fsp2 if we are out of space.
6834 * Thus we don't look at the error return from the
6837 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
6839 if (!NT_STATUS_IS_OK(status
)) {
6843 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
6844 status
= NT_STATUS_DISK_FULL
;
6848 status
= NT_STATUS_OK
;
6851 TALLOC_FREE(smb_fname_dst_tmp
);
6855 /****************************************************************************
6856 Reply to a file copy.
6857 ****************************************************************************/
6859 void reply_copy(struct smb_request
*req
)
6861 connection_struct
*conn
= req
->conn
;
6862 struct smb_filename
*smb_fname_src
= NULL
;
6863 struct smb_filename
*smb_fname_dst
= NULL
;
6864 char *fname_src
= NULL
;
6865 char *fname_dst
= NULL
;
6866 char *fname_src_mask
= NULL
;
6867 char *fname_src_dir
= NULL
;
6870 int error
= ERRnoaccess
;
6874 bool target_is_directory
=False
;
6875 bool source_has_wild
= False
;
6876 bool dest_has_wild
= False
;
6878 TALLOC_CTX
*ctx
= talloc_tos();
6880 START_PROFILE(SMBcopy
);
6883 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6887 tid2
= SVAL(req
->vwv
+0, 0);
6888 ofun
= SVAL(req
->vwv
+1, 0);
6889 flags
= SVAL(req
->vwv
+2, 0);
6891 p
= (const char *)req
->buf
;
6892 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
6893 &status
, &source_has_wild
);
6894 if (!NT_STATUS_IS_OK(status
)) {
6895 reply_nterror(req
, status
);
6898 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
6899 &status
, &dest_has_wild
);
6900 if (!NT_STATUS_IS_OK(status
)) {
6901 reply_nterror(req
, status
);
6905 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
6907 if (tid2
!= conn
->cnum
) {
6908 /* can't currently handle inter share copies XXXX */
6909 DEBUG(3,("Rejecting inter-share copy\n"));
6910 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
6914 status
= filename_convert(ctx
, conn
,
6915 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6917 UCF_COND_ALLOW_WCARD_LCOMP
,
6920 if (!NT_STATUS_IS_OK(status
)) {
6921 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6922 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6923 ERRSRV
, ERRbadpath
);
6926 reply_nterror(req
, status
);
6930 status
= filename_convert(ctx
, conn
,
6931 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6933 UCF_COND_ALLOW_WCARD_LCOMP
,
6936 if (!NT_STATUS_IS_OK(status
)) {
6937 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6938 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6939 ERRSRV
, ERRbadpath
);
6942 reply_nterror(req
, status
);
6946 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
6948 if ((flags
&1) && target_is_directory
) {
6949 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
6953 if ((flags
&2) && !target_is_directory
) {
6954 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
6958 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
6959 /* wants a tree copy! XXXX */
6960 DEBUG(3,("Rejecting tree copy\n"));
6961 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6965 /* Split up the directory from the filename/mask. */
6966 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6967 &fname_src_dir
, &fname_src_mask
);
6968 if (!NT_STATUS_IS_OK(status
)) {
6969 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6974 * We should only check the mangled cache
6975 * here if unix_convert failed. This means
6976 * that the path in 'mask' doesn't exist
6977 * on the file system and so we need to look
6978 * for a possible mangle. This patch from
6979 * Tine Smukavec <valentin.smukavec@hermes.si>.
6981 if (!VALID_STAT(smb_fname_src
->st
) &&
6982 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6983 char *new_mask
= NULL
;
6984 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
6985 &new_mask
, conn
->params
);
6987 /* Use demangled name if one was successfully found. */
6989 TALLOC_FREE(fname_src_mask
);
6990 fname_src_mask
= new_mask
;
6994 if (!source_has_wild
) {
6997 * Only one file needs to be copied. Append the mask back onto
7000 TALLOC_FREE(smb_fname_src
->base_name
);
7001 if (ISDOT(fname_src_dir
)) {
7002 /* Ensure we use canonical names on open. */
7003 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7007 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7012 if (!smb_fname_src
->base_name
) {
7013 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7017 if (dest_has_wild
) {
7018 char *fname_dst_mod
= NULL
;
7019 if (!resolve_wildcards(smb_fname_dst
,
7020 smb_fname_src
->base_name
,
7021 smb_fname_dst
->base_name
,
7023 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7026 TALLOC_FREE(smb_fname_dst
->base_name
);
7027 smb_fname_dst
->base_name
= fname_dst_mod
;
7030 status
= check_name(conn
, smb_fname_src
->base_name
);
7031 if (!NT_STATUS_IS_OK(status
)) {
7032 reply_nterror(req
, status
);
7036 status
= check_name(conn
, smb_fname_dst
->base_name
);
7037 if (!NT_STATUS_IS_OK(status
)) {
7038 reply_nterror(req
, status
);
7042 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7043 ofun
, count
, target_is_directory
);
7045 if(!NT_STATUS_IS_OK(status
)) {
7046 reply_nterror(req
, status
);
7052 struct smb_Dir
*dir_hnd
= NULL
;
7053 const char *dname
= NULL
;
7054 char *talloced
= NULL
;
7058 * There is a wildcard that requires us to actually read the
7059 * src dir and copy each file matching the mask to the dst.
7060 * Right now streams won't be copied, but this could
7061 * presumably be added with a nested loop for reach dir entry.
7063 SMB_ASSERT(!smb_fname_src
->stream_name
);
7064 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7066 smb_fname_src
->stream_name
= NULL
;
7067 smb_fname_dst
->stream_name
= NULL
;
7069 if (strequal(fname_src_mask
,"????????.???")) {
7070 TALLOC_FREE(fname_src_mask
);
7071 fname_src_mask
= talloc_strdup(ctx
, "*");
7072 if (!fname_src_mask
) {
7073 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7078 status
= check_name(conn
, fname_src_dir
);
7079 if (!NT_STATUS_IS_OK(status
)) {
7080 reply_nterror(req
, status
);
7084 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7085 if (dir_hnd
== NULL
) {
7086 status
= map_nt_error_from_unix(errno
);
7087 reply_nterror(req
, status
);
7093 /* Iterate over the src dir copying each entry to the dst. */
7094 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7095 &smb_fname_src
->st
, &talloced
))) {
7096 char *destname
= NULL
;
7098 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7099 TALLOC_FREE(talloced
);
7103 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7104 &smb_fname_src
->st
, false)) {
7105 TALLOC_FREE(talloced
);
7109 if(!mask_match(dname
, fname_src_mask
,
7110 conn
->case_sensitive
)) {
7111 TALLOC_FREE(talloced
);
7115 error
= ERRnoaccess
;
7117 /* Get the src smb_fname struct setup. */
7118 TALLOC_FREE(smb_fname_src
->base_name
);
7119 if (ISDOT(fname_src_dir
)) {
7120 /* Ensure we use canonical names on open. */
7121 smb_fname_src
->base_name
=
7122 talloc_asprintf(smb_fname_src
, "%s",
7125 smb_fname_src
->base_name
=
7126 talloc_asprintf(smb_fname_src
, "%s/%s",
7127 fname_src_dir
, dname
);
7130 if (!smb_fname_src
->base_name
) {
7131 TALLOC_FREE(dir_hnd
);
7132 TALLOC_FREE(talloced
);
7133 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7137 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7138 smb_fname_dst
->base_name
,
7140 TALLOC_FREE(talloced
);
7144 TALLOC_FREE(dir_hnd
);
7145 TALLOC_FREE(talloced
);
7146 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7150 TALLOC_FREE(smb_fname_dst
->base_name
);
7151 smb_fname_dst
->base_name
= destname
;
7153 status
= check_name(conn
, smb_fname_src
->base_name
);
7154 if (!NT_STATUS_IS_OK(status
)) {
7155 TALLOC_FREE(dir_hnd
);
7156 TALLOC_FREE(talloced
);
7157 reply_nterror(req
, status
);
7161 status
= check_name(conn
, smb_fname_dst
->base_name
);
7162 if (!NT_STATUS_IS_OK(status
)) {
7163 TALLOC_FREE(dir_hnd
);
7164 TALLOC_FREE(talloced
);
7165 reply_nterror(req
, status
);
7169 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7170 smb_fname_src
->base_name
,
7171 smb_fname_dst
->base_name
));
7173 status
= copy_file(ctx
, conn
, smb_fname_src
,
7174 smb_fname_dst
, ofun
, count
,
7175 target_is_directory
);
7176 if (NT_STATUS_IS_OK(status
)) {
7180 TALLOC_FREE(talloced
);
7182 TALLOC_FREE(dir_hnd
);
7186 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7190 reply_outbuf(req
, 1, 0);
7191 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7193 TALLOC_FREE(smb_fname_src
);
7194 TALLOC_FREE(smb_fname_dst
);
7195 TALLOC_FREE(fname_src
);
7196 TALLOC_FREE(fname_dst
);
7197 TALLOC_FREE(fname_src_mask
);
7198 TALLOC_FREE(fname_src_dir
);
7200 END_PROFILE(SMBcopy
);
7205 #define DBGC_CLASS DBGC_LOCKING
7207 /****************************************************************************
7208 Get a lock pid, dealing with large count requests.
7209 ****************************************************************************/
7211 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7212 bool large_file_format
)
7214 if(!large_file_format
)
7215 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7217 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7220 /****************************************************************************
7221 Get a lock count, dealing with large count requests.
7222 ****************************************************************************/
7224 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7225 bool large_file_format
)
7229 if(!large_file_format
) {
7230 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7233 #if defined(HAVE_LONGLONG)
7234 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7235 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7236 #else /* HAVE_LONGLONG */
7239 * NT4.x seems to be broken in that it sends large file (64 bit)
7240 * lockingX calls even if the CAP_LARGE_FILES was *not*
7241 * negotiated. For boxes without large unsigned ints truncate the
7242 * lock count by dropping the top 32 bits.
7245 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7246 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7247 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7248 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7249 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7252 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7253 #endif /* HAVE_LONGLONG */
7259 #if !defined(HAVE_LONGLONG)
7260 /****************************************************************************
7261 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7262 ****************************************************************************/
7264 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7268 uint32 highcopy
= high
;
7271 * Try and find out how many significant bits there are in high.
7274 for(i
= 0; highcopy
; i
++)
7278 * We use 31 bits not 32 here as POSIX
7279 * lock offsets may not be negative.
7282 mask
= (~0) << (31 - i
);
7285 return 0; /* Fail. */
7291 #endif /* !defined(HAVE_LONGLONG) */
7293 /****************************************************************************
7294 Get a lock offset, dealing with large offset requests.
7295 ****************************************************************************/
7297 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7298 bool large_file_format
, bool *err
)
7300 uint64_t offset
= 0;
7304 if(!large_file_format
) {
7305 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7308 #if defined(HAVE_LONGLONG)
7309 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7310 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7311 #else /* HAVE_LONGLONG */
7314 * NT4.x seems to be broken in that it sends large file (64 bit)
7315 * lockingX calls even if the CAP_LARGE_FILES was *not*
7316 * negotiated. For boxes without large unsigned ints mangle the
7317 * lock offset by mapping the top 32 bits onto the lower 32.
7320 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7321 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7322 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7325 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7327 return (uint64_t)-1;
7330 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7331 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7332 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7333 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7336 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7337 #endif /* HAVE_LONGLONG */
7343 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7347 uint16_t num_ulocks
,
7348 struct smbd_lock_element
*ulocks
,
7350 struct smbd_lock_element
*locks
,
7353 connection_struct
*conn
= req
->conn
;
7355 NTSTATUS status
= NT_STATUS_OK
;
7359 /* Data now points at the beginning of the list
7360 of smb_unlkrng structs */
7361 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7362 struct smbd_lock_element
*e
= &ulocks
[i
];
7364 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7365 "pid %u, file %s\n",
7368 (unsigned int)e
->smblctx
,
7371 if (e
->brltype
!= UNLOCK_LOCK
) {
7372 /* this can only happen with SMB2 */
7373 return NT_STATUS_INVALID_PARAMETER
;
7376 status
= do_unlock(req
->sconn
->msg_ctx
,
7383 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7384 nt_errstr(status
)));
7386 if (!NT_STATUS_IS_OK(status
)) {
7391 /* Setup the timeout in seconds. */
7393 if (!lp_blocking_locks(SNUM(conn
))) {
7397 /* Data now points at the beginning of the list
7398 of smb_lkrng structs */
7400 for(i
= 0; i
< (int)num_locks
; i
++) {
7401 struct smbd_lock_element
*e
= &locks
[i
];
7403 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7404 "%llu, file %s timeout = %d\n",
7407 (unsigned long long)e
->smblctx
,
7411 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7412 struct blocking_lock_record
*blr
= NULL
;
7414 if (num_locks
> 1) {
7416 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7417 * if the lock vector contains one entry. When given mutliple cancel
7418 * requests in a single PDU we expect the server to return an
7419 * error. Windows servers seem to accept the request but only
7420 * cancel the first lock.
7421 * JRA - Do what Windows does (tm) :-).
7425 /* MS-CIFS (2.2.4.32.1) behavior. */
7426 return NT_STATUS_DOS(ERRDOS
,
7427 ERRcancelviolation
);
7429 /* Windows behavior. */
7431 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7432 "cancel request\n"));
7438 if (lp_blocking_locks(SNUM(conn
))) {
7440 /* Schedule a message to ourselves to
7441 remove the blocking lock record and
7442 return the right error. */
7444 blr
= blocking_lock_cancel_smb1(fsp
,
7450 NT_STATUS_FILE_LOCK_CONFLICT
);
7452 return NT_STATUS_DOS(
7454 ERRcancelviolation
);
7457 /* Remove a matching pending lock. */
7458 status
= do_lock_cancel(fsp
,
7465 bool blocking_lock
= timeout
? true : false;
7466 bool defer_lock
= false;
7467 struct byte_range_lock
*br_lck
;
7468 uint64_t block_smblctx
;
7470 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7482 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7483 /* Windows internal resolution for blocking locks seems
7484 to be about 200ms... Don't wait for less than that. JRA. */
7485 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7486 timeout
= lp_lock_spin_time();
7491 /* If a lock sent with timeout of zero would fail, and
7492 * this lock has been requested multiple times,
7493 * according to brl_lock_failed() we convert this
7494 * request to a blocking lock with a timeout of between
7495 * 150 - 300 milliseconds.
7497 * If lp_lock_spin_time() has been set to 0, we skip
7498 * this blocking retry and fail immediately.
7500 * Replacement for do_lock_spin(). JRA. */
7502 if (!req
->sconn
->using_smb2
&&
7503 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7504 lp_lock_spin_time() && !blocking_lock
&&
7505 NT_STATUS_EQUAL((status
),
7506 NT_STATUS_FILE_LOCK_CONFLICT
))
7509 timeout
= lp_lock_spin_time();
7512 if (br_lck
&& defer_lock
) {
7514 * A blocking lock was requested. Package up
7515 * this smb into a queued request and push it
7516 * onto the blocking lock queue.
7518 if(push_blocking_lock_request(br_lck
,
7529 TALLOC_FREE(br_lck
);
7531 return NT_STATUS_OK
;
7535 TALLOC_FREE(br_lck
);
7538 if (!NT_STATUS_IS_OK(status
)) {
7543 /* If any of the above locks failed, then we must unlock
7544 all of the previous locks (X/Open spec). */
7546 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7548 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7549 i
= -1; /* we want to skip the for loop */
7553 * Ensure we don't do a remove on the lock that just failed,
7554 * as under POSIX rules, if we have a lock already there, we
7555 * will delete it (and we shouldn't) .....
7557 for(i
--; i
>= 0; i
--) {
7558 struct smbd_lock_element
*e
= &locks
[i
];
7560 do_unlock(req
->sconn
->msg_ctx
,
7570 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7571 fsp
->fnum
, (unsigned int)type
, num_locks
, num_ulocks
));
7573 return NT_STATUS_OK
;
7576 /****************************************************************************
7577 Reply to a lockingX request.
7578 ****************************************************************************/
7580 void reply_lockingX(struct smb_request
*req
)
7582 connection_struct
*conn
= req
->conn
;
7584 unsigned char locktype
;
7585 unsigned char oplocklevel
;
7590 const uint8_t *data
;
7591 bool large_file_format
;
7593 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7594 struct smbd_lock_element
*ulocks
;
7595 struct smbd_lock_element
*locks
;
7598 START_PROFILE(SMBlockingX
);
7601 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7602 END_PROFILE(SMBlockingX
);
7606 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7607 locktype
= CVAL(req
->vwv
+3, 0);
7608 oplocklevel
= CVAL(req
->vwv
+3, 1);
7609 num_ulocks
= SVAL(req
->vwv
+6, 0);
7610 num_locks
= SVAL(req
->vwv
+7, 0);
7611 lock_timeout
= IVAL(req
->vwv
+4, 0);
7612 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7614 if (!check_fsp(conn
, req
, fsp
)) {
7615 END_PROFILE(SMBlockingX
);
7621 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7622 /* we don't support these - and CANCEL_LOCK makes w2k
7623 and XP reboot so I don't really want to be
7624 compatible! (tridge) */
7625 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7626 END_PROFILE(SMBlockingX
);
7630 /* Check if this is an oplock break on a file
7631 we have granted an oplock on.
7633 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7634 /* Client can insist on breaking to none. */
7635 bool break_to_none
= (oplocklevel
== 0);
7638 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7639 "for fnum = %d\n", (unsigned int)oplocklevel
,
7643 * Make sure we have granted an exclusive or batch oplock on
7647 if (fsp
->oplock_type
== 0) {
7649 /* The Samba4 nbench simulator doesn't understand
7650 the difference between break to level2 and break
7651 to none from level2 - it sends oplock break
7652 replies in both cases. Don't keep logging an error
7653 message here - just ignore it. JRA. */
7655 DEBUG(5,("reply_lockingX: Error : oplock break from "
7656 "client for fnum = %d (oplock=%d) and no "
7657 "oplock granted on this file (%s).\n",
7658 fsp
->fnum
, fsp
->oplock_type
,
7661 /* if this is a pure oplock break request then don't
7663 if (num_locks
== 0 && num_ulocks
== 0) {
7664 END_PROFILE(SMBlockingX
);
7667 END_PROFILE(SMBlockingX
);
7668 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
7673 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7675 result
= remove_oplock(fsp
);
7677 result
= downgrade_oplock(fsp
);
7681 DEBUG(0, ("reply_lockingX: error in removing "
7682 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7683 /* Hmmm. Is this panic justified? */
7684 smb_panic("internal tdb error");
7687 reply_to_oplock_break_requests(fsp
);
7689 /* if this is a pure oplock break request then don't send a
7691 if (num_locks
== 0 && num_ulocks
== 0) {
7692 /* Sanity check - ensure a pure oplock break is not a
7694 if(CVAL(req
->vwv
+0, 0) != 0xff)
7695 DEBUG(0,("reply_lockingX: Error : pure oplock "
7696 "break is a chained %d request !\n",
7697 (unsigned int)CVAL(req
->vwv
+0, 0)));
7698 END_PROFILE(SMBlockingX
);
7704 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7705 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7706 END_PROFILE(SMBlockingX
);
7710 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
7711 if (ulocks
== NULL
) {
7712 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7713 END_PROFILE(SMBlockingX
);
7717 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
7718 if (locks
== NULL
) {
7719 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7720 END_PROFILE(SMBlockingX
);
7724 /* Data now points at the beginning of the list
7725 of smb_unlkrng structs */
7726 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7727 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7728 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7729 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7730 ulocks
[i
].brltype
= UNLOCK_LOCK
;
7733 * There is no error code marked "stupid client bug".... :-).
7736 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7737 END_PROFILE(SMBlockingX
);
7742 /* Now do any requested locks */
7743 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
7745 /* Data now points at the beginning of the list
7746 of smb_lkrng structs */
7748 for(i
= 0; i
< (int)num_locks
; i
++) {
7749 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7750 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7751 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7753 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
7754 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7755 locks
[i
].brltype
= PENDING_READ_LOCK
;
7757 locks
[i
].brltype
= READ_LOCK
;
7760 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7761 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
7763 locks
[i
].brltype
= WRITE_LOCK
;
7768 * There is no error code marked "stupid client bug".... :-).
7771 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7772 END_PROFILE(SMBlockingX
);
7777 status
= smbd_do_locking(req
, fsp
,
7778 locktype
, lock_timeout
,
7782 if (!NT_STATUS_IS_OK(status
)) {
7783 END_PROFILE(SMBlockingX
);
7784 reply_nterror(req
, status
);
7788 END_PROFILE(SMBlockingX
);
7792 reply_outbuf(req
, 2, 0);
7793 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
7794 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
7796 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7797 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7799 END_PROFILE(SMBlockingX
);
7803 #define DBGC_CLASS DBGC_ALL
7805 /****************************************************************************
7806 Reply to a SMBreadbmpx (read block multiplex) request.
7807 Always reply with an error, if someone has a platform really needs this,
7808 please contact vl@samba.org
7809 ****************************************************************************/
7811 void reply_readbmpx(struct smb_request
*req
)
7813 START_PROFILE(SMBreadBmpx
);
7814 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7815 END_PROFILE(SMBreadBmpx
);
7819 /****************************************************************************
7820 Reply to a SMBreadbs (read block multiplex secondary) request.
7821 Always reply with an error, if someone has a platform really needs this,
7822 please contact vl@samba.org
7823 ****************************************************************************/
7825 void reply_readbs(struct smb_request
*req
)
7827 START_PROFILE(SMBreadBs
);
7828 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7829 END_PROFILE(SMBreadBs
);
7833 /****************************************************************************
7834 Reply to a SMBsetattrE.
7835 ****************************************************************************/
7837 void reply_setattrE(struct smb_request
*req
)
7839 connection_struct
*conn
= req
->conn
;
7840 struct smb_file_time ft
;
7844 START_PROFILE(SMBsetattrE
);
7848 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7852 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7854 if(!fsp
|| (fsp
->conn
!= conn
)) {
7855 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7860 * Convert the DOS times into unix times.
7863 ft
.atime
= convert_time_t_to_timespec(
7864 srv_make_unix_date2(req
->vwv
+3));
7865 ft
.mtime
= convert_time_t_to_timespec(
7866 srv_make_unix_date2(req
->vwv
+5));
7867 ft
.create_time
= convert_time_t_to_timespec(
7868 srv_make_unix_date2(req
->vwv
+1));
7870 reply_outbuf(req
, 0, 0);
7873 * Patch from Ray Frush <frush@engr.colostate.edu>
7874 * Sometimes times are sent as zero - ignore them.
7877 /* Ensure we have a valid stat struct for the source. */
7878 status
= vfs_stat_fsp(fsp
);
7879 if (!NT_STATUS_IS_OK(status
)) {
7880 reply_nterror(req
, status
);
7884 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
7885 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7889 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
7890 if (!NT_STATUS_IS_OK(status
)) {
7891 reply_nterror(req
, status
);
7895 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7898 (unsigned int)ft
.atime
.tv_sec
,
7899 (unsigned int)ft
.mtime
.tv_sec
,
7900 (unsigned int)ft
.create_time
.tv_sec
7903 END_PROFILE(SMBsetattrE
);
7908 /* Back from the dead for OS/2..... JRA. */
7910 /****************************************************************************
7911 Reply to a SMBwritebmpx (write block multiplex primary) request.
7912 Always reply with an error, if someone has a platform really needs this,
7913 please contact vl@samba.org
7914 ****************************************************************************/
7916 void reply_writebmpx(struct smb_request
*req
)
7918 START_PROFILE(SMBwriteBmpx
);
7919 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7920 END_PROFILE(SMBwriteBmpx
);
7924 /****************************************************************************
7925 Reply to a SMBwritebs (write block multiplex secondary) request.
7926 Always reply with an error, if someone has a platform really needs this,
7927 please contact vl@samba.org
7928 ****************************************************************************/
7930 void reply_writebs(struct smb_request
*req
)
7932 START_PROFILE(SMBwriteBs
);
7933 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7934 END_PROFILE(SMBwriteBs
);
7938 /****************************************************************************
7939 Reply to a SMBgetattrE.
7940 ****************************************************************************/
7942 void reply_getattrE(struct smb_request
*req
)
7944 connection_struct
*conn
= req
->conn
;
7947 struct timespec create_ts
;
7949 START_PROFILE(SMBgetattrE
);
7952 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7953 END_PROFILE(SMBgetattrE
);
7957 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7959 if(!fsp
|| (fsp
->conn
!= conn
)) {
7960 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7961 END_PROFILE(SMBgetattrE
);
7965 /* Do an fstat on this file */
7967 reply_nterror(req
, map_nt_error_from_unix(errno
));
7968 END_PROFILE(SMBgetattrE
);
7972 mode
= dos_mode(conn
, fsp
->fsp_name
);
7975 * Convert the times into dos times. Set create
7976 * date to be last modify date as UNIX doesn't save
7980 reply_outbuf(req
, 11, 0);
7982 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
7983 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
7984 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
7985 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
7986 /* Should we check pending modtime here ? JRA */
7987 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
7988 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
7990 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
7991 SIVAL(req
->outbuf
, smb_vwv6
, 0);
7992 SIVAL(req
->outbuf
, smb_vwv8
, 0);
7994 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
7995 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
7996 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
7998 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8000 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
8002 END_PROFILE(SMBgetattrE
);