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 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
949 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
950 lp_netbios_name(), 15,
951 STR_TERMINATE
|STR_ASCII
);
953 srvstr_push((char *)req
->outbuf
, req
->flags2
,
954 p
+18, lp_servicename(SNUM(conn
)),
955 13, STR_TERMINATE
|STR_ASCII
);
963 END_PROFILE(SMBioctl
);
967 /****************************************************************************
968 Strange checkpath NTSTATUS mapping.
969 ****************************************************************************/
971 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
973 /* Strange DOS error code semantics only for checkpath... */
974 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
975 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
976 /* We need to map to ERRbadpath */
977 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
983 /****************************************************************************
984 Reply to a checkpath.
985 ****************************************************************************/
987 void reply_checkpath(struct smb_request
*req
)
989 connection_struct
*conn
= req
->conn
;
990 struct smb_filename
*smb_fname
= NULL
;
993 TALLOC_CTX
*ctx
= talloc_tos();
995 START_PROFILE(SMBcheckpath
);
997 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
998 STR_TERMINATE
, &status
);
1000 if (!NT_STATUS_IS_OK(status
)) {
1001 status
= map_checkpath_error(req
->flags2
, status
);
1002 reply_nterror(req
, status
);
1003 END_PROFILE(SMBcheckpath
);
1007 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1009 status
= filename_convert(ctx
,
1011 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1017 if (!NT_STATUS_IS_OK(status
)) {
1018 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1019 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1020 ERRSRV
, ERRbadpath
);
1021 END_PROFILE(SMBcheckpath
);
1027 if (!VALID_STAT(smb_fname
->st
) &&
1028 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1029 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1030 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1031 status
= map_nt_error_from_unix(errno
);
1035 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1036 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1037 ERRDOS
, ERRbadpath
);
1041 reply_outbuf(req
, 0, 0);
1044 /* We special case this - as when a Windows machine
1045 is parsing a path is steps through the components
1046 one at a time - if a component fails it expects
1047 ERRbadpath, not ERRbadfile.
1049 status
= map_checkpath_error(req
->flags2
, status
);
1050 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1052 * Windows returns different error codes if
1053 * the parent directory is valid but not the
1054 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1055 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1056 * if the path is invalid.
1058 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1059 ERRDOS
, ERRbadpath
);
1063 reply_nterror(req
, status
);
1066 TALLOC_FREE(smb_fname
);
1067 END_PROFILE(SMBcheckpath
);
1071 /****************************************************************************
1073 ****************************************************************************/
1075 void reply_getatr(struct smb_request
*req
)
1077 connection_struct
*conn
= req
->conn
;
1078 struct smb_filename
*smb_fname
= NULL
;
1085 TALLOC_CTX
*ctx
= talloc_tos();
1086 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1088 START_PROFILE(SMBgetatr
);
1090 p
= (const char *)req
->buf
+ 1;
1091 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1092 if (!NT_STATUS_IS_OK(status
)) {
1093 reply_nterror(req
, status
);
1097 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1098 under WfWg - weird! */
1099 if (*fname
== '\0') {
1100 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1101 if (!CAN_WRITE(conn
)) {
1102 mode
|= FILE_ATTRIBUTE_READONLY
;
1107 status
= filename_convert(ctx
,
1109 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1114 if (!NT_STATUS_IS_OK(status
)) {
1115 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1116 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1117 ERRSRV
, ERRbadpath
);
1120 reply_nterror(req
, status
);
1123 if (!VALID_STAT(smb_fname
->st
) &&
1124 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1125 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1126 smb_fname_str_dbg(smb_fname
),
1128 reply_nterror(req
, map_nt_error_from_unix(errno
));
1132 mode
= dos_mode(conn
, smb_fname
);
1133 size
= smb_fname
->st
.st_ex_size
;
1135 if (ask_sharemode
) {
1136 struct timespec write_time_ts
;
1137 struct file_id fileid
;
1139 ZERO_STRUCT(write_time_ts
);
1140 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1141 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1142 if (!null_timespec(write_time_ts
)) {
1143 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1147 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1148 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1153 reply_outbuf(req
, 10, 0);
1155 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1156 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1157 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1159 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1161 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1163 if (get_Protocol() >= PROTOCOL_NT1
) {
1164 SSVAL(req
->outbuf
, smb_flg2
,
1165 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1168 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1169 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1172 TALLOC_FREE(smb_fname
);
1174 END_PROFILE(SMBgetatr
);
1178 /****************************************************************************
1180 ****************************************************************************/
1182 void reply_setatr(struct smb_request
*req
)
1184 struct smb_file_time ft
;
1185 connection_struct
*conn
= req
->conn
;
1186 struct smb_filename
*smb_fname
= NULL
;
1192 TALLOC_CTX
*ctx
= talloc_tos();
1194 START_PROFILE(SMBsetatr
);
1199 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1203 p
= (const char *)req
->buf
+ 1;
1204 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1205 if (!NT_STATUS_IS_OK(status
)) {
1206 reply_nterror(req
, status
);
1210 status
= filename_convert(ctx
,
1212 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1217 if (!NT_STATUS_IS_OK(status
)) {
1218 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1219 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1220 ERRSRV
, ERRbadpath
);
1223 reply_nterror(req
, status
);
1227 if (smb_fname
->base_name
[0] == '.' &&
1228 smb_fname
->base_name
[1] == '\0') {
1230 * Not sure here is the right place to catch this
1231 * condition. Might be moved to somewhere else later -- vl
1233 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1237 mode
= SVAL(req
->vwv
+0, 0);
1238 mtime
= srv_make_unix_date3(req
->vwv
+1);
1240 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1241 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1242 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1244 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1246 status
= check_access(conn
, NULL
, smb_fname
,
1247 FILE_WRITE_ATTRIBUTES
);
1248 if (!NT_STATUS_IS_OK(status
)) {
1249 reply_nterror(req
, status
);
1253 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1255 reply_nterror(req
, map_nt_error_from_unix(errno
));
1260 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1261 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1262 if (!NT_STATUS_IS_OK(status
)) {
1263 reply_nterror(req
, status
);
1267 reply_outbuf(req
, 0, 0);
1269 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1272 TALLOC_FREE(smb_fname
);
1273 END_PROFILE(SMBsetatr
);
1277 /****************************************************************************
1279 ****************************************************************************/
1281 void reply_dskattr(struct smb_request
*req
)
1283 connection_struct
*conn
= req
->conn
;
1284 uint64_t dfree
,dsize
,bsize
;
1285 START_PROFILE(SMBdskattr
);
1287 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1288 reply_nterror(req
, map_nt_error_from_unix(errno
));
1289 END_PROFILE(SMBdskattr
);
1293 reply_outbuf(req
, 5, 0);
1295 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1296 double total_space
, free_space
;
1297 /* we need to scale this to a number that DOS6 can handle. We
1298 use floating point so we can handle large drives on systems
1299 that don't have 64 bit integers
1301 we end up displaying a maximum of 2G to DOS systems
1303 total_space
= dsize
* (double)bsize
;
1304 free_space
= dfree
* (double)bsize
;
1306 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1307 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1309 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1310 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1312 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1313 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1314 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1315 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1317 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1318 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1319 SSVAL(req
->outbuf
,smb_vwv2
,512);
1320 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1323 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1325 END_PROFILE(SMBdskattr
);
1330 * Utility function to split the filename from the directory.
1332 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1333 char **fname_dir_out
,
1334 char **fname_mask_out
)
1336 const char *p
= NULL
;
1337 char *fname_dir
= NULL
;
1338 char *fname_mask
= NULL
;
1340 p
= strrchr_m(fname_in
, '/');
1342 fname_dir
= talloc_strdup(ctx
, ".");
1343 fname_mask
= talloc_strdup(ctx
, fname_in
);
1345 fname_dir
= talloc_strndup(ctx
, fname_in
,
1346 PTR_DIFF(p
, fname_in
));
1347 fname_mask
= talloc_strdup(ctx
, p
+1);
1350 if (!fname_dir
|| !fname_mask
) {
1351 TALLOC_FREE(fname_dir
);
1352 TALLOC_FREE(fname_mask
);
1353 return NT_STATUS_NO_MEMORY
;
1356 *fname_dir_out
= fname_dir
;
1357 *fname_mask_out
= fname_mask
;
1358 return NT_STATUS_OK
;
1361 /****************************************************************************
1363 Can be called from SMBsearch, SMBffirst or SMBfunique.
1364 ****************************************************************************/
1366 void reply_search(struct smb_request
*req
)
1368 connection_struct
*conn
= req
->conn
;
1370 const char *mask
= NULL
;
1371 char *directory
= NULL
;
1372 struct smb_filename
*smb_fname
= NULL
;
1376 struct timespec date
;
1378 unsigned int numentries
= 0;
1379 unsigned int maxentries
= 0;
1380 bool finished
= False
;
1385 bool check_descend
= False
;
1386 bool expect_close
= False
;
1388 bool mask_contains_wcard
= False
;
1389 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1390 TALLOC_CTX
*ctx
= talloc_tos();
1391 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1392 struct dptr_struct
*dirptr
= NULL
;
1393 struct smbd_server_connection
*sconn
= req
->sconn
;
1395 START_PROFILE(SMBsearch
);
1398 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1402 if (lp_posix_pathnames()) {
1403 reply_unknown_new(req
, req
->cmd
);
1407 /* If we were called as SMBffirst then we must expect close. */
1408 if(req
->cmd
== SMBffirst
) {
1409 expect_close
= True
;
1412 reply_outbuf(req
, 1, 3);
1413 maxentries
= SVAL(req
->vwv
+0, 0);
1414 dirtype
= SVAL(req
->vwv
+1, 0);
1415 p
= (const char *)req
->buf
+ 1;
1416 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1417 &nt_status
, &mask_contains_wcard
);
1418 if (!NT_STATUS_IS_OK(nt_status
)) {
1419 reply_nterror(req
, nt_status
);
1424 status_len
= SVAL(p
, 0);
1427 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1429 if (status_len
== 0) {
1430 nt_status
= filename_convert(ctx
, conn
,
1431 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1433 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1434 &mask_contains_wcard
,
1436 if (!NT_STATUS_IS_OK(nt_status
)) {
1437 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1438 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1439 ERRSRV
, ERRbadpath
);
1442 reply_nterror(req
, nt_status
);
1446 directory
= smb_fname
->base_name
;
1448 p
= strrchr_m(directory
,'/');
1449 if ((p
!= NULL
) && (*directory
!= '/')) {
1451 directory
= talloc_strndup(ctx
, directory
,
1452 PTR_DIFF(p
, directory
));
1455 directory
= talloc_strdup(ctx
,".");
1459 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1463 memset((char *)status
,'\0',21);
1464 SCVAL(status
,0,(dirtype
& 0x1F));
1466 nt_status
= dptr_create(conn
,
1474 mask_contains_wcard
,
1477 if (!NT_STATUS_IS_OK(nt_status
)) {
1478 reply_nterror(req
, nt_status
);
1481 dptr_num
= dptr_dnum(dirptr
);
1484 const char *dirpath
;
1486 memcpy(status
,p
,21);
1487 status_dirtype
= CVAL(status
,0) & 0x1F;
1488 if (status_dirtype
!= (dirtype
& 0x1F)) {
1489 dirtype
= status_dirtype
;
1492 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1496 dirpath
= dptr_path(sconn
, dptr_num
);
1497 directory
= talloc_strdup(ctx
, dirpath
);
1499 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1503 mask
= dptr_wcard(sconn
, dptr_num
);
1508 * For a 'continue' search we have no string. So
1509 * check from the initial saved string.
1511 mask_contains_wcard
= ms_has_wild(mask
);
1512 dirtype
= dptr_attr(sconn
, dptr_num
);
1515 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1517 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1518 dptr_init_search_op(dirptr
);
1520 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1521 char buf
[DIR_STRUCT_SIZE
];
1522 memcpy(buf
,status
,21);
1523 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1524 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1525 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1528 dptr_fill(sconn
, buf
+12,dptr_num
);
1529 if (dptr_zero(buf
+12) && (status_len
==0)) {
1534 if (message_push_blob(&req
->outbuf
,
1535 data_blob_const(buf
, sizeof(buf
)))
1537 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1545 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1548 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1549 directory
,lp_dontdescend(SNUM(conn
))));
1550 if (in_list(directory
, lp_dontdescend(SNUM(conn
)),True
)) {
1551 check_descend
= True
;
1554 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1555 finished
= !get_dir_entry(ctx
,
1566 char buf
[DIR_STRUCT_SIZE
];
1567 memcpy(buf
,status
,21);
1568 if (!make_dir_struct(ctx
,
1574 convert_timespec_to_time_t(date
),
1575 !allow_long_path_components
)) {
1576 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1579 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1582 if (message_push_blob(&req
->outbuf
,
1583 data_blob_const(buf
, sizeof(buf
)))
1585 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1595 /* If we were called as SMBffirst with smb_search_id == NULL
1596 and no entries were found then return error and close dirptr
1599 if (numentries
== 0) {
1600 dptr_close(sconn
, &dptr_num
);
1601 } else if(expect_close
&& status_len
== 0) {
1602 /* Close the dptr - we know it's gone */
1603 dptr_close(sconn
, &dptr_num
);
1606 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1607 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1608 dptr_close(sconn
, &dptr_num
);
1611 if ((numentries
== 0) && !mask_contains_wcard
) {
1612 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1616 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1617 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1618 SCVAL(smb_buf(req
->outbuf
),0,5);
1619 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1621 /* The replies here are never long name. */
1622 SSVAL(req
->outbuf
, smb_flg2
,
1623 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1624 if (!allow_long_path_components
) {
1625 SSVAL(req
->outbuf
, smb_flg2
,
1626 SVAL(req
->outbuf
, smb_flg2
)
1627 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1630 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1631 SSVAL(req
->outbuf
, smb_flg2
,
1632 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1634 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1635 smb_fn_name(req
->cmd
),
1642 TALLOC_FREE(directory
);
1643 TALLOC_FREE(smb_fname
);
1644 END_PROFILE(SMBsearch
);
1648 /****************************************************************************
1649 Reply to a fclose (stop directory search).
1650 ****************************************************************************/
1652 void reply_fclose(struct smb_request
*req
)
1660 bool path_contains_wcard
= False
;
1661 TALLOC_CTX
*ctx
= talloc_tos();
1662 struct smbd_server_connection
*sconn
= req
->sconn
;
1664 START_PROFILE(SMBfclose
);
1666 if (lp_posix_pathnames()) {
1667 reply_unknown_new(req
, req
->cmd
);
1668 END_PROFILE(SMBfclose
);
1672 p
= (const char *)req
->buf
+ 1;
1673 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1674 &err
, &path_contains_wcard
);
1675 if (!NT_STATUS_IS_OK(err
)) {
1676 reply_nterror(req
, err
);
1677 END_PROFILE(SMBfclose
);
1681 status_len
= SVAL(p
,0);
1684 if (status_len
== 0) {
1685 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1686 END_PROFILE(SMBfclose
);
1690 memcpy(status
,p
,21);
1692 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1693 /* Close the dptr - we know it's gone */
1694 dptr_close(sconn
, &dptr_num
);
1697 reply_outbuf(req
, 1, 0);
1698 SSVAL(req
->outbuf
,smb_vwv0
,0);
1700 DEBUG(3,("search close\n"));
1702 END_PROFILE(SMBfclose
);
1706 /****************************************************************************
1708 ****************************************************************************/
1710 void reply_open(struct smb_request
*req
)
1712 connection_struct
*conn
= req
->conn
;
1713 struct smb_filename
*smb_fname
= NULL
;
1725 uint32 create_disposition
;
1726 uint32 create_options
= 0;
1727 uint32_t private_flags
= 0;
1729 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1730 TALLOC_CTX
*ctx
= talloc_tos();
1732 START_PROFILE(SMBopen
);
1735 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1739 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1740 deny_mode
= SVAL(req
->vwv
+0, 0);
1741 dos_attr
= SVAL(req
->vwv
+1, 0);
1743 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1744 STR_TERMINATE
, &status
);
1745 if (!NT_STATUS_IS_OK(status
)) {
1746 reply_nterror(req
, status
);
1750 status
= filename_convert(ctx
,
1752 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1757 if (!NT_STATUS_IS_OK(status
)) {
1758 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1759 reply_botherror(req
,
1760 NT_STATUS_PATH_NOT_COVERED
,
1761 ERRSRV
, ERRbadpath
);
1764 reply_nterror(req
, status
);
1768 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1769 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1770 &share_mode
, &create_disposition
,
1771 &create_options
, &private_flags
)) {
1772 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1776 status
= SMB_VFS_CREATE_FILE(
1779 0, /* root_dir_fid */
1780 smb_fname
, /* fname */
1781 access_mask
, /* access_mask */
1782 share_mode
, /* share_access */
1783 create_disposition
, /* create_disposition*/
1784 create_options
, /* create_options */
1785 dos_attr
, /* file_attributes */
1786 oplock_request
, /* oplock_request */
1787 0, /* allocation_size */
1794 if (!NT_STATUS_IS_OK(status
)) {
1795 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1796 /* We have re-scheduled this call. */
1799 reply_openerror(req
, status
);
1803 size
= smb_fname
->st
.st_ex_size
;
1804 fattr
= dos_mode(conn
, smb_fname
);
1806 /* Deal with other possible opens having a modified
1808 if (ask_sharemode
) {
1809 struct timespec write_time_ts
;
1811 ZERO_STRUCT(write_time_ts
);
1812 get_file_infos(fsp
->file_id
, 0, NULL
, &write_time_ts
);
1813 if (!null_timespec(write_time_ts
)) {
1814 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1818 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1820 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1821 DEBUG(3,("attempt to open a directory %s\n",
1823 close_file(req
, fsp
, ERROR_CLOSE
);
1824 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1825 ERRDOS
, ERRnoaccess
);
1829 reply_outbuf(req
, 7, 0);
1830 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1831 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1832 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1833 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1835 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1837 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1838 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1840 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1841 SCVAL(req
->outbuf
,smb_flg
,
1842 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1845 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1846 SCVAL(req
->outbuf
,smb_flg
,
1847 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1850 TALLOC_FREE(smb_fname
);
1851 END_PROFILE(SMBopen
);
1855 /****************************************************************************
1856 Reply to an open and X.
1857 ****************************************************************************/
1859 void reply_open_and_X(struct smb_request
*req
)
1861 connection_struct
*conn
= req
->conn
;
1862 struct smb_filename
*smb_fname
= NULL
;
1867 /* Breakout the oplock request bits so we can set the
1868 reply bits separately. */
1869 int ex_oplock_request
;
1870 int core_oplock_request
;
1873 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1874 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
1882 uint64_t allocation_size
;
1883 ssize_t retval
= -1;
1886 uint32 create_disposition
;
1887 uint32 create_options
= 0;
1888 uint32_t private_flags
= 0;
1889 TALLOC_CTX
*ctx
= talloc_tos();
1891 START_PROFILE(SMBopenX
);
1893 if (req
->wct
< 15) {
1894 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1898 open_flags
= SVAL(req
->vwv
+2, 0);
1899 deny_mode
= SVAL(req
->vwv
+3, 0);
1900 smb_attr
= SVAL(req
->vwv
+5, 0);
1901 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1902 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1903 oplock_request
= ex_oplock_request
| core_oplock_request
;
1904 smb_ofun
= SVAL(req
->vwv
+8, 0);
1905 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1907 /* If it's an IPC, pass off the pipe handler. */
1909 if (lp_nt_pipe_support()) {
1910 reply_open_pipe_and_X(conn
, req
);
1912 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1917 /* XXXX we need to handle passed times, sattr and flags */
1918 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1919 STR_TERMINATE
, &status
);
1920 if (!NT_STATUS_IS_OK(status
)) {
1921 reply_nterror(req
, status
);
1925 status
= filename_convert(ctx
,
1927 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1932 if (!NT_STATUS_IS_OK(status
)) {
1933 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1934 reply_botherror(req
,
1935 NT_STATUS_PATH_NOT_COVERED
,
1936 ERRSRV
, ERRbadpath
);
1939 reply_nterror(req
, status
);
1943 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1945 &access_mask
, &share_mode
,
1946 &create_disposition
,
1949 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1953 status
= SMB_VFS_CREATE_FILE(
1956 0, /* root_dir_fid */
1957 smb_fname
, /* fname */
1958 access_mask
, /* access_mask */
1959 share_mode
, /* share_access */
1960 create_disposition
, /* create_disposition*/
1961 create_options
, /* create_options */
1962 smb_attr
, /* file_attributes */
1963 oplock_request
, /* oplock_request */
1964 0, /* allocation_size */
1969 &smb_action
); /* pinfo */
1971 if (!NT_STATUS_IS_OK(status
)) {
1972 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1973 /* We have re-scheduled this call. */
1976 reply_openerror(req
, status
);
1980 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1981 if the file is truncated or created. */
1982 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1983 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1984 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1985 close_file(req
, fsp
, ERROR_CLOSE
);
1986 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1989 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
1991 close_file(req
, fsp
, ERROR_CLOSE
);
1992 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1995 status
= vfs_stat_fsp(fsp
);
1996 if (!NT_STATUS_IS_OK(status
)) {
1997 close_file(req
, fsp
, ERROR_CLOSE
);
1998 reply_nterror(req
, status
);
2003 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2004 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2005 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2006 close_file(req
, fsp
, ERROR_CLOSE
);
2007 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2011 /* If the caller set the extended oplock request bit
2012 and we granted one (by whatever means) - set the
2013 correct bit for extended oplock reply.
2016 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2017 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2020 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2021 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2024 /* If the caller set the core oplock request bit
2025 and we granted one (by whatever means) - set the
2026 correct bit for core oplock reply.
2029 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2030 reply_outbuf(req
, 19, 0);
2032 reply_outbuf(req
, 15, 0);
2035 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2036 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2038 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2039 SCVAL(req
->outbuf
, smb_flg
,
2040 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2043 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2044 SCVAL(req
->outbuf
, smb_flg
,
2045 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2048 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2049 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2050 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2051 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2053 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2055 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2056 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2057 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2059 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2060 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2064 TALLOC_FREE(smb_fname
);
2065 END_PROFILE(SMBopenX
);
2069 /****************************************************************************
2070 Reply to a SMBulogoffX.
2071 ****************************************************************************/
2073 void reply_ulogoffX(struct smb_request
*req
)
2075 struct smbd_server_connection
*sconn
= req
->sconn
;
2076 struct user_struct
*vuser
;
2078 START_PROFILE(SMBulogoffX
);
2080 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2083 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2086 req
->vuid
= UID_FIELD_INVALID
;
2087 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2088 END_PROFILE(SMBulogoffX
);
2092 /* in user level security we are supposed to close any files
2093 open by this user */
2094 if (vuser
!= NULL
) {
2095 file_close_user(sconn
, req
->vuid
);
2098 invalidate_vuid(sconn
, req
->vuid
);
2100 reply_outbuf(req
, 2, 0);
2101 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2102 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2104 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
2106 END_PROFILE(SMBulogoffX
);
2107 req
->vuid
= UID_FIELD_INVALID
;
2110 /****************************************************************************
2111 Reply to a mknew or a create.
2112 ****************************************************************************/
2114 void reply_mknew(struct smb_request
*req
)
2116 connection_struct
*conn
= req
->conn
;
2117 struct smb_filename
*smb_fname
= NULL
;
2120 struct smb_file_time ft
;
2122 int oplock_request
= 0;
2124 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2125 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2126 uint32 create_disposition
;
2127 uint32 create_options
= 0;
2128 TALLOC_CTX
*ctx
= talloc_tos();
2130 START_PROFILE(SMBcreate
);
2134 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2138 fattr
= SVAL(req
->vwv
+0, 0);
2139 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2142 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2144 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2145 STR_TERMINATE
, &status
);
2146 if (!NT_STATUS_IS_OK(status
)) {
2147 reply_nterror(req
, status
);
2151 status
= filename_convert(ctx
,
2153 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2158 if (!NT_STATUS_IS_OK(status
)) {
2159 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2160 reply_botherror(req
,
2161 NT_STATUS_PATH_NOT_COVERED
,
2162 ERRSRV
, ERRbadpath
);
2165 reply_nterror(req
, status
);
2169 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2170 DEBUG(0,("Attempt to create file (%s) with volid set - "
2171 "please report this\n",
2172 smb_fname_str_dbg(smb_fname
)));
2175 if(req
->cmd
== SMBmknew
) {
2176 /* We should fail if file exists. */
2177 create_disposition
= FILE_CREATE
;
2179 /* Create if file doesn't exist, truncate if it does. */
2180 create_disposition
= FILE_OVERWRITE_IF
;
2183 status
= SMB_VFS_CREATE_FILE(
2186 0, /* root_dir_fid */
2187 smb_fname
, /* fname */
2188 access_mask
, /* access_mask */
2189 share_mode
, /* share_access */
2190 create_disposition
, /* create_disposition*/
2191 create_options
, /* create_options */
2192 fattr
, /* file_attributes */
2193 oplock_request
, /* oplock_request */
2194 0, /* allocation_size */
2195 0, /* private_flags */
2201 if (!NT_STATUS_IS_OK(status
)) {
2202 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2203 /* We have re-scheduled this call. */
2206 reply_openerror(req
, status
);
2210 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2211 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2212 if (!NT_STATUS_IS_OK(status
)) {
2213 END_PROFILE(SMBcreate
);
2217 reply_outbuf(req
, 1, 0);
2218 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2220 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2221 SCVAL(req
->outbuf
,smb_flg
,
2222 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2225 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2226 SCVAL(req
->outbuf
,smb_flg
,
2227 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2230 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2231 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2232 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2233 (unsigned int)fattr
));
2236 TALLOC_FREE(smb_fname
);
2237 END_PROFILE(SMBcreate
);
2241 /****************************************************************************
2242 Reply to a create temporary file.
2243 ****************************************************************************/
2245 void reply_ctemp(struct smb_request
*req
)
2247 connection_struct
*conn
= req
->conn
;
2248 struct smb_filename
*smb_fname
= NULL
;
2256 TALLOC_CTX
*ctx
= talloc_tos();
2258 START_PROFILE(SMBctemp
);
2261 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2265 fattr
= SVAL(req
->vwv
+0, 0);
2266 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2268 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2269 STR_TERMINATE
, &status
);
2270 if (!NT_STATUS_IS_OK(status
)) {
2271 reply_nterror(req
, status
);
2275 fname
= talloc_asprintf(ctx
,
2279 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2283 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2287 status
= filename_convert(ctx
, conn
,
2288 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2293 if (!NT_STATUS_IS_OK(status
)) {
2294 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2295 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2296 ERRSRV
, ERRbadpath
);
2299 reply_nterror(req
, status
);
2303 tmpfd
= mkstemp(smb_fname
->base_name
);
2305 reply_nterror(req
, map_nt_error_from_unix(errno
));
2309 SMB_VFS_STAT(conn
, smb_fname
);
2311 /* We should fail if file does not exist. */
2312 status
= SMB_VFS_CREATE_FILE(
2315 0, /* root_dir_fid */
2316 smb_fname
, /* fname */
2317 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2318 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2319 FILE_OPEN
, /* create_disposition*/
2320 0, /* create_options */
2321 fattr
, /* file_attributes */
2322 oplock_request
, /* oplock_request */
2323 0, /* allocation_size */
2324 0, /* private_flags */
2330 /* close fd from mkstemp() */
2333 if (!NT_STATUS_IS_OK(status
)) {
2334 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2335 /* We have re-scheduled this call. */
2338 reply_openerror(req
, status
);
2342 reply_outbuf(req
, 1, 0);
2343 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2345 /* the returned filename is relative to the directory */
2346 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2348 s
= fsp
->fsp_name
->base_name
;
2354 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2355 thing in the byte section. JRA */
2356 SSVALS(p
, 0, -1); /* what is this? not in spec */
2358 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2360 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2364 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2365 SCVAL(req
->outbuf
, smb_flg
,
2366 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2369 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2370 SCVAL(req
->outbuf
, smb_flg
,
2371 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2374 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2375 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2376 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2378 TALLOC_FREE(smb_fname
);
2379 END_PROFILE(SMBctemp
);
2383 /*******************************************************************
2384 Check if a user is allowed to rename a file.
2385 ********************************************************************/
2387 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2390 if (!CAN_WRITE(conn
)) {
2391 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2394 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2395 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2396 /* Only bother to read the DOS attribute if we might deny the
2397 rename on the grounds of attribute missmatch. */
2398 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2399 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2400 return NT_STATUS_NO_SUCH_FILE
;
2404 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2405 if (fsp
->posix_open
) {
2406 return NT_STATUS_OK
;
2409 /* If no pathnames are open below this
2410 directory, allow the rename. */
2412 if (file_find_subpath(fsp
)) {
2413 return NT_STATUS_ACCESS_DENIED
;
2415 return NT_STATUS_OK
;
2418 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2419 return NT_STATUS_OK
;
2422 return NT_STATUS_ACCESS_DENIED
;
2425 /*******************************************************************
2426 * unlink a file with all relevant access checks
2427 *******************************************************************/
2429 static NTSTATUS
do_unlink(connection_struct
*conn
,
2430 struct smb_request
*req
,
2431 struct smb_filename
*smb_fname
,
2436 uint32 dirtype_orig
= dirtype
;
2439 bool posix_paths
= lp_posix_pathnames();
2441 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2442 smb_fname_str_dbg(smb_fname
),
2445 if (!CAN_WRITE(conn
)) {
2446 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2450 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2452 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2455 return map_nt_error_from_unix(errno
);
2458 fattr
= dos_mode(conn
, smb_fname
);
2460 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2461 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2464 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2466 return NT_STATUS_NO_SUCH_FILE
;
2469 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2470 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2471 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2473 return NT_STATUS_NO_SUCH_FILE
;
2476 if (dirtype_orig
& 0x8000) {
2477 /* These will never be set for POSIX. */
2478 return NT_STATUS_NO_SUCH_FILE
;
2482 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2483 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2486 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2487 return NT_STATUS_NO_SUCH_FILE
;
2490 if (dirtype
& 0xFF00) {
2491 /* These will never be set for POSIX. */
2492 return NT_STATUS_NO_SUCH_FILE
;
2497 return NT_STATUS_NO_SUCH_FILE
;
2500 /* Can't delete a directory. */
2501 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2502 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2507 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2508 return NT_STATUS_OBJECT_NAME_INVALID
;
2509 #endif /* JRATEST */
2511 /* On open checks the open itself will check the share mode, so
2512 don't do it here as we'll get it wrong. */
2514 status
= SMB_VFS_CREATE_FILE
2517 0, /* root_dir_fid */
2518 smb_fname
, /* fname */
2519 DELETE_ACCESS
, /* access_mask */
2520 FILE_SHARE_NONE
, /* share_access */
2521 FILE_OPEN
, /* create_disposition*/
2522 FILE_NON_DIRECTORY_FILE
, /* create_options */
2523 /* file_attributes */
2524 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2525 FILE_ATTRIBUTE_NORMAL
,
2526 0, /* oplock_request */
2527 0, /* allocation_size */
2528 0, /* private_flags */
2534 if (!NT_STATUS_IS_OK(status
)) {
2535 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2536 nt_errstr(status
)));
2540 status
= can_set_delete_on_close(fsp
, fattr
);
2541 if (!NT_STATUS_IS_OK(status
)) {
2542 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2544 smb_fname_str_dbg(smb_fname
),
2545 nt_errstr(status
)));
2546 close_file(req
, fsp
, NORMAL_CLOSE
);
2550 /* The set is across all open files on this dev/inode pair. */
2551 if (!set_delete_on_close(fsp
, True
,
2552 conn
->session_info
->security_token
,
2553 conn
->session_info
->unix_token
)) {
2554 close_file(req
, fsp
, NORMAL_CLOSE
);
2555 return NT_STATUS_ACCESS_DENIED
;
2558 return close_file(req
, fsp
, NORMAL_CLOSE
);
2561 /****************************************************************************
2562 The guts of the unlink command, split out so it may be called by the NT SMB
2564 ****************************************************************************/
2566 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2567 uint32 dirtype
, struct smb_filename
*smb_fname
,
2570 char *fname_dir
= NULL
;
2571 char *fname_mask
= NULL
;
2573 NTSTATUS status
= NT_STATUS_OK
;
2574 TALLOC_CTX
*ctx
= talloc_tos();
2576 /* Split up the directory from the filename/mask. */
2577 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2578 &fname_dir
, &fname_mask
);
2579 if (!NT_STATUS_IS_OK(status
)) {
2584 * We should only check the mangled cache
2585 * here if unix_convert failed. This means
2586 * that the path in 'mask' doesn't exist
2587 * on the file system and so we need to look
2588 * for a possible mangle. This patch from
2589 * Tine Smukavec <valentin.smukavec@hermes.si>.
2592 if (!VALID_STAT(smb_fname
->st
) &&
2593 mangle_is_mangled(fname_mask
, conn
->params
)) {
2594 char *new_mask
= NULL
;
2595 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2596 &new_mask
, conn
->params
);
2598 TALLOC_FREE(fname_mask
);
2599 fname_mask
= new_mask
;
2606 * Only one file needs to be unlinked. Append the mask back
2607 * onto the directory.
2609 TALLOC_FREE(smb_fname
->base_name
);
2610 if (ISDOT(fname_dir
)) {
2611 /* Ensure we use canonical names on open. */
2612 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2616 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2621 if (!smb_fname
->base_name
) {
2622 status
= NT_STATUS_NO_MEMORY
;
2626 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2629 status
= check_name(conn
, smb_fname
->base_name
);
2630 if (!NT_STATUS_IS_OK(status
)) {
2634 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2635 if (!NT_STATUS_IS_OK(status
)) {
2641 struct smb_Dir
*dir_hnd
= NULL
;
2643 const char *dname
= NULL
;
2644 char *talloced
= NULL
;
2646 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2647 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2651 if (strequal(fname_mask
,"????????.???")) {
2652 TALLOC_FREE(fname_mask
);
2653 fname_mask
= talloc_strdup(ctx
, "*");
2655 status
= NT_STATUS_NO_MEMORY
;
2660 status
= check_name(conn
, fname_dir
);
2661 if (!NT_STATUS_IS_OK(status
)) {
2665 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2667 if (dir_hnd
== NULL
) {
2668 status
= map_nt_error_from_unix(errno
);
2672 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2673 the pattern matches against the long name, otherwise the short name
2674 We don't implement this yet XXXX
2677 status
= NT_STATUS_NO_SUCH_FILE
;
2679 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2680 &smb_fname
->st
, &talloced
))) {
2681 TALLOC_CTX
*frame
= talloc_stackframe();
2683 if (!is_visible_file(conn
, fname_dir
, dname
,
2684 &smb_fname
->st
, true)) {
2686 TALLOC_FREE(talloced
);
2690 /* Quick check for "." and ".." */
2691 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2693 TALLOC_FREE(talloced
);
2697 if(!mask_match(dname
, fname_mask
,
2698 conn
->case_sensitive
)) {
2700 TALLOC_FREE(talloced
);
2704 TALLOC_FREE(smb_fname
->base_name
);
2705 if (ISDOT(fname_dir
)) {
2706 /* Ensure we use canonical names on open. */
2707 smb_fname
->base_name
=
2708 talloc_asprintf(smb_fname
, "%s",
2711 smb_fname
->base_name
=
2712 talloc_asprintf(smb_fname
, "%s/%s",
2716 if (!smb_fname
->base_name
) {
2717 TALLOC_FREE(dir_hnd
);
2718 status
= NT_STATUS_NO_MEMORY
;
2720 TALLOC_FREE(talloced
);
2724 status
= check_name(conn
, smb_fname
->base_name
);
2725 if (!NT_STATUS_IS_OK(status
)) {
2726 TALLOC_FREE(dir_hnd
);
2728 TALLOC_FREE(talloced
);
2732 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2733 if (!NT_STATUS_IS_OK(status
)) {
2735 TALLOC_FREE(talloced
);
2740 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2741 smb_fname
->base_name
));
2744 TALLOC_FREE(talloced
);
2746 TALLOC_FREE(dir_hnd
);
2749 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2750 status
= map_nt_error_from_unix(errno
);
2754 TALLOC_FREE(fname_dir
);
2755 TALLOC_FREE(fname_mask
);
2759 /****************************************************************************
2761 ****************************************************************************/
2763 void reply_unlink(struct smb_request
*req
)
2765 connection_struct
*conn
= req
->conn
;
2767 struct smb_filename
*smb_fname
= NULL
;
2770 bool path_contains_wcard
= False
;
2771 TALLOC_CTX
*ctx
= talloc_tos();
2773 START_PROFILE(SMBunlink
);
2776 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2780 dirtype
= SVAL(req
->vwv
+0, 0);
2782 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2783 STR_TERMINATE
, &status
,
2784 &path_contains_wcard
);
2785 if (!NT_STATUS_IS_OK(status
)) {
2786 reply_nterror(req
, status
);
2790 status
= filename_convert(ctx
, conn
,
2791 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2793 UCF_COND_ALLOW_WCARD_LCOMP
,
2794 &path_contains_wcard
,
2796 if (!NT_STATUS_IS_OK(status
)) {
2797 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2798 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2799 ERRSRV
, ERRbadpath
);
2802 reply_nterror(req
, status
);
2806 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2808 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2809 path_contains_wcard
);
2810 if (!NT_STATUS_IS_OK(status
)) {
2811 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2812 /* We have re-scheduled this call. */
2815 reply_nterror(req
, status
);
2819 reply_outbuf(req
, 0, 0);
2821 TALLOC_FREE(smb_fname
);
2822 END_PROFILE(SMBunlink
);
2826 /****************************************************************************
2828 ****************************************************************************/
2830 static void fail_readraw(void)
2832 const char *errstr
= talloc_asprintf(talloc_tos(),
2833 "FAIL ! reply_readbraw: socket write fail (%s)",
2838 exit_server_cleanly(errstr
);
2841 /****************************************************************************
2842 Fake (read/write) sendfile. Returns -1 on read or write fail.
2843 ****************************************************************************/
2845 ssize_t
fake_sendfile(files_struct
*fsp
, off_t startpos
, size_t nread
)
2848 size_t tosend
= nread
;
2855 bufsize
= MIN(nread
, 65536);
2857 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2861 while (tosend
> 0) {
2865 if (tosend
> bufsize
) {
2870 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2876 /* If we had a short read, fill with zeros. */
2877 if (ret
< cur_read
) {
2878 memset(buf
+ ret
, '\0', cur_read
- ret
);
2881 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
2883 char addr
[INET6_ADDRSTRLEN
];
2885 * Try and give an error message saying what
2888 DEBUG(0, ("write_data failed for client %s. "
2890 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
2897 startpos
+= cur_read
;
2901 return (ssize_t
)nread
;
2904 /****************************************************************************
2905 Deal with the case of sendfile reading less bytes from the file than
2906 requested. Fill with zeros (all we can do).
2907 ****************************************************************************/
2909 void sendfile_short_send(files_struct
*fsp
,
2914 #define SHORT_SEND_BUFSIZE 1024
2915 if (nread
< headersize
) {
2916 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2917 "header for file %s (%s). Terminating\n",
2918 fsp_str_dbg(fsp
), strerror(errno
)));
2919 exit_server_cleanly("sendfile_short_send failed");
2922 nread
-= headersize
;
2924 if (nread
< smb_maxcnt
) {
2925 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
2927 exit_server_cleanly("sendfile_short_send: "
2931 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2932 "with zeros !\n", fsp_str_dbg(fsp
)));
2934 while (nread
< smb_maxcnt
) {
2936 * We asked for the real file size and told sendfile
2937 * to not go beyond the end of the file. But it can
2938 * happen that in between our fstat call and the
2939 * sendfile call the file was truncated. This is very
2940 * bad because we have already announced the larger
2941 * number of bytes to the client.
2943 * The best we can do now is to send 0-bytes, just as
2944 * a read from a hole in a sparse file would do.
2946 * This should happen rarely enough that I don't care
2947 * about efficiency here :-)
2951 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
2952 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
2954 char addr
[INET6_ADDRSTRLEN
];
2956 * Try and give an error message saying what
2959 DEBUG(0, ("write_data failed for client %s. "
2962 fsp
->conn
->sconn
->sock
, addr
,
2965 exit_server_cleanly("sendfile_short_send: "
2966 "write_data failed");
2974 /****************************************************************************
2975 Return a readbraw error (4 bytes of zero).
2976 ****************************************************************************/
2978 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
2984 smbd_lock_socket(sconn
);
2985 if (write_data(sconn
->sock
,header
,4) != 4) {
2986 char addr
[INET6_ADDRSTRLEN
];
2988 * Try and give an error message saying what
2991 DEBUG(0, ("write_data failed for client %s. "
2993 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
2998 smbd_unlock_socket(sconn
);
3001 /****************************************************************************
3002 Use sendfile in readbraw.
3003 ****************************************************************************/
3005 static void send_file_readbraw(connection_struct
*conn
,
3006 struct smb_request
*req
,
3012 struct smbd_server_connection
*sconn
= req
->sconn
;
3013 char *outbuf
= NULL
;
3017 * We can only use sendfile on a non-chained packet
3018 * but we can use on a non-oplocked file. tridge proved this
3019 * on a train in Germany :-). JRA.
3020 * reply_readbraw has already checked the length.
3023 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3024 (fsp
->wcp
== NULL
) &&
3025 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3026 ssize_t sendfile_read
= -1;
3028 DATA_BLOB header_blob
;
3030 _smb_setlen(header
,nread
);
3031 header_blob
= data_blob_const(header
, 4);
3033 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3034 &header_blob
, startpos
,
3036 if (sendfile_read
== -1) {
3037 /* Returning ENOSYS means no data at all was sent.
3038 * Do this as a normal read. */
3039 if (errno
== ENOSYS
) {
3040 goto normal_readbraw
;
3044 * Special hack for broken Linux with no working sendfile. If we
3045 * return EINTR we sent the header but not the rest of the data.
3046 * Fake this up by doing read/write calls.
3048 if (errno
== EINTR
) {
3049 /* Ensure we don't do this again. */
3050 set_use_sendfile(SNUM(conn
), False
);
3051 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3053 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3054 DEBUG(0,("send_file_readbraw: "
3055 "fake_sendfile failed for "
3059 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3064 DEBUG(0,("send_file_readbraw: sendfile failed for "
3065 "file %s (%s). Terminating\n",
3066 fsp_str_dbg(fsp
), strerror(errno
)));
3067 exit_server_cleanly("send_file_readbraw sendfile failed");
3068 } else if (sendfile_read
== 0) {
3070 * Some sendfile implementations return 0 to indicate
3071 * that there was a short read, but nothing was
3072 * actually written to the socket. In this case,
3073 * fallback to the normal read path so the header gets
3074 * the correct byte count.
3076 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3077 "bytes falling back to the normal read: "
3078 "%s\n", fsp_str_dbg(fsp
)));
3079 goto normal_readbraw
;
3082 /* Deal with possible short send. */
3083 if (sendfile_read
!= 4+nread
) {
3084 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3091 outbuf
= talloc_array(NULL
, char, nread
+4);
3093 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3094 (unsigned)(nread
+4)));
3095 reply_readbraw_error(sconn
);
3100 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3101 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3110 _smb_setlen(outbuf
,ret
);
3111 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3112 char addr
[INET6_ADDRSTRLEN
];
3114 * Try and give an error message saying what
3117 DEBUG(0, ("write_data failed for client %s. "
3119 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3126 TALLOC_FREE(outbuf
);
3129 /****************************************************************************
3130 Reply to a readbraw (core+ protocol).
3131 ****************************************************************************/
3133 void reply_readbraw(struct smb_request
*req
)
3135 connection_struct
*conn
= req
->conn
;
3136 struct smbd_server_connection
*sconn
= req
->sconn
;
3137 ssize_t maxcount
,mincount
;
3141 struct lock_struct lock
;
3144 START_PROFILE(SMBreadbraw
);
3146 if (srv_is_signing_active(sconn
) ||
3147 is_encrypted_packet(sconn
, req
->inbuf
)) {
3148 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3149 "raw reads/writes are disallowed.");
3153 reply_readbraw_error(sconn
);
3154 END_PROFILE(SMBreadbraw
);
3158 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3159 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3160 "'async smb echo handler = yes'\n"));
3161 reply_readbraw_error(sconn
);
3162 END_PROFILE(SMBreadbraw
);
3167 * Special check if an oplock break has been issued
3168 * and the readraw request croses on the wire, we must
3169 * return a zero length response here.
3172 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3175 * We have to do a check_fsp by hand here, as
3176 * we must always return 4 zero bytes on error,
3180 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3181 req
->vuid
!= fsp
->vuid
||
3182 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3184 * fsp could be NULL here so use the value from the packet. JRA.
3186 DEBUG(3,("reply_readbraw: fnum %d not valid "
3188 (int)SVAL(req
->vwv
+0, 0)));
3189 reply_readbraw_error(sconn
);
3190 END_PROFILE(SMBreadbraw
);
3194 /* Do a "by hand" version of CHECK_READ. */
3195 if (!(fsp
->can_read
||
3196 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3197 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3198 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3199 (int)SVAL(req
->vwv
+0, 0)));
3200 reply_readbraw_error(sconn
);
3201 END_PROFILE(SMBreadbraw
);
3205 flush_write_cache(fsp
, READRAW_FLUSH
);
3207 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3208 if(req
->wct
== 10) {
3210 * This is a large offset (64 bit) read.
3213 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3216 DEBUG(0,("reply_readbraw: negative 64 bit "
3217 "readraw offset (%.0f) !\n",
3218 (double)startpos
));
3219 reply_readbraw_error(sconn
);
3220 END_PROFILE(SMBreadbraw
);
3225 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3226 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3228 /* ensure we don't overrun the packet size */
3229 maxcount
= MIN(65535,maxcount
);
3231 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3232 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3235 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3236 reply_readbraw_error(sconn
);
3237 END_PROFILE(SMBreadbraw
);
3241 if (fsp_stat(fsp
) == 0) {
3242 size
= fsp
->fsp_name
->st
.st_ex_size
;
3245 if (startpos
>= size
) {
3248 nread
= MIN(maxcount
,(size
- startpos
));
3251 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3252 if (nread
< mincount
)
3256 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3257 "min=%lu nread=%lu\n",
3258 fsp
->fnum
, (double)startpos
,
3259 (unsigned long)maxcount
,
3260 (unsigned long)mincount
,
3261 (unsigned long)nread
) );
3263 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3265 DEBUG(5,("reply_readbraw finished\n"));
3267 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3269 END_PROFILE(SMBreadbraw
);
3274 #define DBGC_CLASS DBGC_LOCKING
3276 /****************************************************************************
3277 Reply to a lockread (core+ protocol).
3278 ****************************************************************************/
3280 void reply_lockread(struct smb_request
*req
)
3282 connection_struct
*conn
= req
->conn
;
3289 struct byte_range_lock
*br_lck
= NULL
;
3291 struct smbd_server_connection
*sconn
= req
->sconn
;
3293 START_PROFILE(SMBlockread
);
3296 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3297 END_PROFILE(SMBlockread
);
3301 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3303 if (!check_fsp(conn
, req
, fsp
)) {
3304 END_PROFILE(SMBlockread
);
3308 if (!CHECK_READ(fsp
,req
)) {
3309 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3310 END_PROFILE(SMBlockread
);
3314 numtoread
= SVAL(req
->vwv
+1, 0);
3315 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3317 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3319 reply_outbuf(req
, 5, numtoread
+ 3);
3321 data
= smb_buf(req
->outbuf
) + 3;
3324 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3325 * protocol request that predates the read/write lock concept.
3326 * Thus instead of asking for a read lock here we need to ask
3327 * for a write lock. JRA.
3328 * Note that the requested lock size is unaffected by max_recv.
3331 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3333 (uint64_t)req
->smbpid
,
3334 (uint64_t)numtoread
,
3338 False
, /* Non-blocking lock. */
3342 TALLOC_FREE(br_lck
);
3344 if (NT_STATUS_V(status
)) {
3345 reply_nterror(req
, status
);
3346 END_PROFILE(SMBlockread
);
3351 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3354 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3355 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3356 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3357 (unsigned int)numtoread
,
3358 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3359 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3361 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3364 reply_nterror(req
, map_nt_error_from_unix(errno
));
3365 END_PROFILE(SMBlockread
);
3369 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3371 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3372 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3373 p
= smb_buf(req
->outbuf
);
3374 SCVAL(p
,0,0); /* pad byte. */
3377 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3378 fsp
->fnum
, (int)numtoread
, (int)nread
));
3380 END_PROFILE(SMBlockread
);
3385 #define DBGC_CLASS DBGC_ALL
3387 /****************************************************************************
3389 ****************************************************************************/
3391 void reply_read(struct smb_request
*req
)
3393 connection_struct
*conn
= req
->conn
;
3400 struct lock_struct lock
;
3401 struct smbd_server_connection
*sconn
= req
->sconn
;
3403 START_PROFILE(SMBread
);
3406 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3407 END_PROFILE(SMBread
);
3411 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3413 if (!check_fsp(conn
, req
, fsp
)) {
3414 END_PROFILE(SMBread
);
3418 if (!CHECK_READ(fsp
,req
)) {
3419 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3420 END_PROFILE(SMBread
);
3424 numtoread
= SVAL(req
->vwv
+1, 0);
3425 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3427 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3430 * The requested read size cannot be greater than max_recv. JRA.
3432 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3433 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3434 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3435 (unsigned int)numtoread
,
3436 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3437 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3440 reply_outbuf(req
, 5, numtoread
+3);
3442 data
= smb_buf(req
->outbuf
) + 3;
3444 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3445 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3448 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3449 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3450 END_PROFILE(SMBread
);
3455 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3458 reply_nterror(req
, map_nt_error_from_unix(errno
));
3462 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3464 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3465 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3466 SCVAL(smb_buf(req
->outbuf
),0,1);
3467 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3469 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3470 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3473 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3475 END_PROFILE(SMBread
);
3479 /****************************************************************************
3481 ****************************************************************************/
3483 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3488 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3490 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3492 SCVAL(outbuf
,smb_vwv0
,0xFF);
3493 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3494 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3495 SSVAL(outbuf
,smb_vwv6
,
3496 (smb_wct
- 4) /* offset from smb header to wct */
3497 + 1 /* the wct field */
3498 + 12 * sizeof(uint16_t) /* vwv */
3499 + 2); /* the buflen field */
3500 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3501 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3502 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3503 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3507 /****************************************************************************
3508 Reply to a read and X - possibly using sendfile.
3509 ****************************************************************************/
3511 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3512 files_struct
*fsp
, off_t startpos
,
3516 struct lock_struct lock
;
3517 int saved_errno
= 0;
3519 if(fsp_stat(fsp
) == -1) {
3520 reply_nterror(req
, map_nt_error_from_unix(errno
));
3524 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3525 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3528 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3529 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3533 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3534 (startpos
> fsp
->fsp_name
->st
.st_ex_size
)
3535 || (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3537 * We already know that we would do a short read, so don't
3538 * try the sendfile() path.
3540 goto nosendfile_read
;
3544 * We can only use sendfile on a non-chained packet
3545 * but we can use on a non-oplocked file. tridge proved this
3546 * on a train in Germany :-). JRA.
3549 if (!req_is_in_chain(req
) &&
3550 !is_encrypted_packet(req
->sconn
, req
->inbuf
) &&
3551 (fsp
->base_fsp
== NULL
) &&
3552 (fsp
->wcp
== NULL
) &&
3553 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3554 uint8 headerbuf
[smb_size
+ 12 * 2];
3558 * Set up the packet header before send. We
3559 * assume here the sendfile will work (get the
3560 * correct amount of data).
3563 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3565 construct_reply_common_req(req
, (char *)headerbuf
);
3566 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3568 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3569 startpos
, smb_maxcnt
);
3571 /* Returning ENOSYS means no data at all was sent.
3572 Do this as a normal read. */
3573 if (errno
== ENOSYS
) {
3578 * Special hack for broken Linux with no working sendfile. If we
3579 * return EINTR we sent the header but not the rest of the data.
3580 * Fake this up by doing read/write calls.
3583 if (errno
== EINTR
) {
3584 /* Ensure we don't do this again. */
3585 set_use_sendfile(SNUM(conn
), False
);
3586 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3587 nread
= fake_sendfile(fsp
, startpos
,
3590 DEBUG(0,("send_file_readX: "
3591 "fake_sendfile failed for "
3595 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3597 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3598 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3599 /* No outbuf here means successful sendfile. */
3603 DEBUG(0,("send_file_readX: sendfile failed for file "
3604 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3606 exit_server_cleanly("send_file_readX sendfile failed");
3607 } else if (nread
== 0) {
3609 * Some sendfile implementations return 0 to indicate
3610 * that there was a short read, but nothing was
3611 * actually written to the socket. In this case,
3612 * fallback to the normal read path so the header gets
3613 * the correct byte count.
3615 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3616 "falling back to the normal read: %s\n",
3621 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3622 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3624 /* Deal with possible short send. */
3625 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3626 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3628 /* No outbuf here means successful sendfile. */
3629 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3630 SMB_PERFCOUNT_END(&req
->pcd
);
3636 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3637 uint8 headerbuf
[smb_size
+ 2*12];
3639 construct_reply_common_req(req
, (char *)headerbuf
);
3640 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3642 /* Send out the header. */
3643 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3644 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3646 char addr
[INET6_ADDRSTRLEN
];
3648 * Try and give an error message saying what
3651 DEBUG(0, ("write_data failed for client %s. "
3653 get_peer_addr(req
->sconn
->sock
, addr
,
3657 DEBUG(0,("send_file_readX: write_data failed for file "
3658 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3660 exit_server_cleanly("send_file_readX sendfile failed");
3662 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3664 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3665 "file %s (%s).\n", fsp_str_dbg(fsp
),
3667 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3674 reply_outbuf(req
, 12, smb_maxcnt
);
3675 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
3676 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
3678 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3679 saved_errno
= errno
;
3681 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3684 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3688 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3690 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3691 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3695 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3696 TALLOC_FREE(req
->outbuf
);
3700 /****************************************************************************
3701 Reply to a read and X.
3702 ****************************************************************************/
3704 void reply_read_and_X(struct smb_request
*req
)
3706 struct smbd_server_connection
*sconn
= req
->sconn
;
3707 connection_struct
*conn
= req
->conn
;
3711 bool big_readX
= False
;
3713 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3716 START_PROFILE(SMBreadX
);
3718 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3719 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3723 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3724 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3725 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3727 /* If it's an IPC, pass off the pipe handler. */
3729 reply_pipe_read_and_X(req
);
3730 END_PROFILE(SMBreadX
);
3734 if (!check_fsp(conn
, req
, fsp
)) {
3735 END_PROFILE(SMBreadX
);
3739 if (!CHECK_READ(fsp
,req
)) {
3740 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3741 END_PROFILE(SMBreadX
);
3745 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_LARGE_READ_CAP
) ||
3746 (get_remote_arch() == RA_SAMBA
)) {
3748 * This is Samba only behavior (up to Samba 3.6)!
3750 * Windows 2008 R2 ignores the upper_size,
3751 * so we do unless unix extentions are active
3752 * or "smbclient" is talking to us.
3754 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3755 smb_maxcnt
|= (upper_size
<<16);
3756 if (upper_size
> 1) {
3757 /* Can't do this on a chained packet. */
3758 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3759 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3760 END_PROFILE(SMBreadX
);
3763 /* We currently don't do this on signed or sealed data. */
3764 if (srv_is_signing_active(req
->sconn
) ||
3765 is_encrypted_packet(req
->sconn
, req
->inbuf
)) {
3766 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3767 END_PROFILE(SMBreadX
);
3770 /* Is there room in the reply for this data ? */
3771 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3773 NT_STATUS_INVALID_PARAMETER
);
3774 END_PROFILE(SMBreadX
);
3781 if (req
->wct
== 12) {
3783 * This is a large offset (64 bit) read.
3785 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
3790 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3795 if (NT_STATUS_IS_OK(status
)) {
3796 /* Read scheduled - we're done. */
3799 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3800 /* Real error - report to client. */
3801 END_PROFILE(SMBreadX
);
3802 reply_nterror(req
, status
);
3805 /* NT_STATUS_RETRY - fall back to sync read. */
3808 smbd_lock_socket(req
->sconn
);
3809 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3810 smbd_unlock_socket(req
->sconn
);
3813 END_PROFILE(SMBreadX
);
3817 /****************************************************************************
3818 Error replies to writebraw must have smb_wct == 1. Fix this up.
3819 ****************************************************************************/
3821 void error_to_writebrawerr(struct smb_request
*req
)
3823 uint8
*old_outbuf
= req
->outbuf
;
3825 reply_outbuf(req
, 1, 0);
3827 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3828 TALLOC_FREE(old_outbuf
);
3831 /****************************************************************************
3832 Read 4 bytes of a smb packet and return the smb length of the packet.
3833 Store the result in the buffer. This version of the function will
3834 never return a session keepalive (length of zero).
3835 Timeout is in milliseconds.
3836 ****************************************************************************/
3838 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3841 uint8_t msgtype
= NBSSkeepalive
;
3843 while (msgtype
== NBSSkeepalive
) {
3846 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3848 if (!NT_STATUS_IS_OK(status
)) {
3849 char addr
[INET6_ADDRSTRLEN
];
3850 /* Try and give an error message
3851 * saying what client failed. */
3852 DEBUG(0, ("read_fd_with_timeout failed for "
3853 "client %s read error = %s.\n",
3854 get_peer_addr(fd
,addr
,sizeof(addr
)),
3855 nt_errstr(status
)));
3859 msgtype
= CVAL(inbuf
, 0);
3862 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3863 (unsigned long)len
));
3865 return NT_STATUS_OK
;
3868 /****************************************************************************
3869 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3870 ****************************************************************************/
3872 void reply_writebraw(struct smb_request
*req
)
3874 connection_struct
*conn
= req
->conn
;
3877 ssize_t total_written
=0;
3878 size_t numtowrite
=0;
3881 const char *data
=NULL
;
3884 struct lock_struct lock
;
3887 START_PROFILE(SMBwritebraw
);
3890 * If we ever reply with an error, it must have the SMB command
3891 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3894 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
3896 if (srv_is_signing_active(req
->sconn
)) {
3897 END_PROFILE(SMBwritebraw
);
3898 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3899 "raw reads/writes are disallowed.");
3902 if (req
->wct
< 12) {
3903 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3904 error_to_writebrawerr(req
);
3905 END_PROFILE(SMBwritebraw
);
3909 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3910 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3911 "'async smb echo handler = yes'\n"));
3912 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3913 error_to_writebrawerr(req
);
3914 END_PROFILE(SMBwritebraw
);
3918 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3919 if (!check_fsp(conn
, req
, fsp
)) {
3920 error_to_writebrawerr(req
);
3921 END_PROFILE(SMBwritebraw
);
3925 if (!CHECK_WRITE(fsp
)) {
3926 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3927 error_to_writebrawerr(req
);
3928 END_PROFILE(SMBwritebraw
);
3932 tcount
= IVAL(req
->vwv
+1, 0);
3933 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3934 write_through
= BITSETW(req
->vwv
+7,0);
3936 /* We have to deal with slightly different formats depending
3937 on whether we are using the core+ or lanman1.0 protocol */
3939 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
3940 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
3941 data
= smb_buf_const(req
->inbuf
);
3943 numtowrite
= SVAL(req
->vwv
+10, 0);
3944 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3947 /* Ensure we don't write bytes past the end of this packet. */
3948 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3949 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3950 error_to_writebrawerr(req
);
3951 END_PROFILE(SMBwritebraw
);
3955 if (!fsp
->print_file
) {
3956 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3957 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
3960 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3961 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3962 error_to_writebrawerr(req
);
3963 END_PROFILE(SMBwritebraw
);
3969 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3972 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3973 "wrote=%d sync=%d\n",
3974 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3975 (int)nwritten
, (int)write_through
));
3977 if (nwritten
< (ssize_t
)numtowrite
) {
3978 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3979 error_to_writebrawerr(req
);
3983 total_written
= nwritten
;
3985 /* Allocate a buffer of 64k + length. */
3986 buf
= talloc_array(NULL
, char, 65540);
3988 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3989 error_to_writebrawerr(req
);
3993 /* Return a SMBwritebraw message to the redirector to tell
3994 * it to send more bytes */
3996 memcpy(buf
, req
->inbuf
, smb_size
);
3997 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
3998 SCVAL(buf
,smb_com
,SMBwritebraw
);
3999 SSVALS(buf
,smb_vwv0
,0xFFFF);
4001 if (!srv_send_smb(req
->sconn
,
4003 false, 0, /* no signing */
4004 IS_CONN_ENCRYPTED(conn
),
4006 exit_server_cleanly("reply_writebraw: srv_send_smb "
4010 /* Now read the raw data into the buffer and write it */
4011 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4013 if (!NT_STATUS_IS_OK(status
)) {
4014 exit_server_cleanly("secondary writebraw failed");
4017 /* Set up outbuf to return the correct size */
4018 reply_outbuf(req
, 1, 0);
4020 if (numtowrite
!= 0) {
4022 if (numtowrite
> 0xFFFF) {
4023 DEBUG(0,("reply_writebraw: Oversize secondary write "
4024 "raw requested (%u). Terminating\n",
4025 (unsigned int)numtowrite
));
4026 exit_server_cleanly("secondary writebraw failed");
4029 if (tcount
> nwritten
+numtowrite
) {
4030 DEBUG(3,("reply_writebraw: Client overestimated the "
4032 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4035 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4037 if (!NT_STATUS_IS_OK(status
)) {
4038 char addr
[INET6_ADDRSTRLEN
];
4039 /* Try and give an error message
4040 * saying what client failed. */
4041 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4042 "raw read failed (%s) for client %s. "
4043 "Terminating\n", nt_errstr(status
),
4044 get_peer_addr(req
->sconn
->sock
, addr
,
4046 exit_server_cleanly("secondary writebraw failed");
4049 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4050 if (nwritten
== -1) {
4052 reply_nterror(req
, map_nt_error_from_unix(errno
));
4053 error_to_writebrawerr(req
);
4057 if (nwritten
< (ssize_t
)numtowrite
) {
4058 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4059 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4063 total_written
+= nwritten
;
4068 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4070 status
= sync_file(conn
, fsp
, write_through
);
4071 if (!NT_STATUS_IS_OK(status
)) {
4072 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4073 fsp_str_dbg(fsp
), nt_errstr(status
)));
4074 reply_nterror(req
, status
);
4075 error_to_writebrawerr(req
);
4079 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4081 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4082 (int)total_written
));
4084 if (!fsp
->print_file
) {
4085 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4088 /* We won't return a status if write through is not selected - this
4089 * follows what WfWg does */
4090 END_PROFILE(SMBwritebraw
);
4092 if (!write_through
&& total_written
==tcount
) {
4094 #if RABBIT_PELLET_FIX
4096 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4097 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4100 if (!send_keepalive(req
->sconn
->sock
)) {
4101 exit_server_cleanly("reply_writebraw: send of "
4102 "keepalive failed");
4105 TALLOC_FREE(req
->outbuf
);
4110 if (!fsp
->print_file
) {
4111 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4114 END_PROFILE(SMBwritebraw
);
4119 #define DBGC_CLASS DBGC_LOCKING
4121 /****************************************************************************
4122 Reply to a writeunlock (core+).
4123 ****************************************************************************/
4125 void reply_writeunlock(struct smb_request
*req
)
4127 connection_struct
*conn
= req
->conn
;
4128 ssize_t nwritten
= -1;
4132 NTSTATUS status
= NT_STATUS_OK
;
4134 struct lock_struct lock
;
4135 int saved_errno
= 0;
4137 START_PROFILE(SMBwriteunlock
);
4140 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4141 END_PROFILE(SMBwriteunlock
);
4145 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4147 if (!check_fsp(conn
, req
, fsp
)) {
4148 END_PROFILE(SMBwriteunlock
);
4152 if (!CHECK_WRITE(fsp
)) {
4153 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4154 END_PROFILE(SMBwriteunlock
);
4158 numtowrite
= SVAL(req
->vwv
+1, 0);
4159 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4160 data
= (const char *)req
->buf
+ 3;
4162 if (!fsp
->print_file
&& numtowrite
> 0) {
4163 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4164 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4167 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4168 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4169 END_PROFILE(SMBwriteunlock
);
4174 /* The special X/Open SMB protocol handling of
4175 zero length writes is *NOT* done for
4177 if(numtowrite
== 0) {
4180 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4181 saved_errno
= errno
;
4184 status
= sync_file(conn
, fsp
, False
/* write through */);
4185 if (!NT_STATUS_IS_OK(status
)) {
4186 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4187 fsp_str_dbg(fsp
), nt_errstr(status
)));
4188 reply_nterror(req
, status
);
4193 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4197 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4198 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4202 if (numtowrite
&& !fsp
->print_file
) {
4203 status
= do_unlock(req
->sconn
->msg_ctx
,
4205 (uint64_t)req
->smbpid
,
4206 (uint64_t)numtowrite
,
4210 if (NT_STATUS_V(status
)) {
4211 reply_nterror(req
, status
);
4216 reply_outbuf(req
, 1, 0);
4218 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4220 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4221 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4224 if (numtowrite
&& !fsp
->print_file
) {
4225 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4228 END_PROFILE(SMBwriteunlock
);
4233 #define DBGC_CLASS DBGC_ALL
4235 /****************************************************************************
4237 ****************************************************************************/
4239 void reply_write(struct smb_request
*req
)
4241 connection_struct
*conn
= req
->conn
;
4243 ssize_t nwritten
= -1;
4247 struct lock_struct lock
;
4249 int saved_errno
= 0;
4251 START_PROFILE(SMBwrite
);
4254 END_PROFILE(SMBwrite
);
4255 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4259 /* If it's an IPC, pass off the pipe handler. */
4261 reply_pipe_write(req
);
4262 END_PROFILE(SMBwrite
);
4266 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4268 if (!check_fsp(conn
, req
, fsp
)) {
4269 END_PROFILE(SMBwrite
);
4273 if (!CHECK_WRITE(fsp
)) {
4274 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4275 END_PROFILE(SMBwrite
);
4279 numtowrite
= SVAL(req
->vwv
+1, 0);
4280 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4281 data
= (const char *)req
->buf
+ 3;
4283 if (!fsp
->print_file
) {
4284 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4285 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4288 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4289 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4290 END_PROFILE(SMBwrite
);
4296 * X/Open SMB protocol says that if smb_vwv1 is
4297 * zero then the file size should be extended or
4298 * truncated to the size given in smb_vwv[2-3].
4301 if(numtowrite
== 0) {
4303 * This is actually an allocate call, and set EOF. JRA.
4305 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4307 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4310 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4312 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4315 trigger_write_time_update_immediate(fsp
);
4317 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4320 status
= sync_file(conn
, fsp
, False
);
4321 if (!NT_STATUS_IS_OK(status
)) {
4322 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4323 fsp_str_dbg(fsp
), nt_errstr(status
)));
4324 reply_nterror(req
, status
);
4329 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4333 if((nwritten
== 0) && (numtowrite
!= 0)) {
4334 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4338 reply_outbuf(req
, 1, 0);
4340 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4342 if (nwritten
< (ssize_t
)numtowrite
) {
4343 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4344 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4347 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4350 if (!fsp
->print_file
) {
4351 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4354 END_PROFILE(SMBwrite
);
4358 /****************************************************************************
4359 Ensure a buffer is a valid writeX for recvfile purposes.
4360 ****************************************************************************/
4362 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4363 (2*14) + /* word count (including bcc) */ \
4366 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4367 const uint8_t *inbuf
)
4370 connection_struct
*conn
= NULL
;
4371 unsigned int doff
= 0;
4372 size_t len
= smb_len_large(inbuf
);
4374 if (is_encrypted_packet(sconn
, inbuf
)) {
4375 /* Can't do this on encrypted
4380 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4384 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4385 CVAL(inbuf
,smb_wct
) != 14) {
4386 DEBUG(10,("is_valid_writeX_buffer: chained or "
4387 "invalid word length.\n"));
4391 conn
= conn_find(sconn
, SVAL(inbuf
, smb_tid
));
4393 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4397 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4400 if (IS_PRINT(conn
)) {
4401 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4404 doff
= SVAL(inbuf
,smb_vwv11
);
4406 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4408 if (len
> doff
&& len
- doff
> 0xFFFF) {
4409 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4412 if (numtowrite
== 0) {
4413 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4417 /* Ensure the sizes match up. */
4418 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4419 /* no pad byte...old smbclient :-( */
4420 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4422 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4426 if (len
- doff
!= numtowrite
) {
4427 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4428 "len = %u, doff = %u, numtowrite = %u\n",
4431 (unsigned int)numtowrite
));
4435 DEBUG(10,("is_valid_writeX_buffer: true "
4436 "len = %u, doff = %u, numtowrite = %u\n",
4439 (unsigned int)numtowrite
));
4444 /****************************************************************************
4445 Reply to a write and X.
4446 ****************************************************************************/
4448 void reply_write_and_X(struct smb_request
*req
)
4450 connection_struct
*conn
= req
->conn
;
4452 struct lock_struct lock
;
4457 unsigned int smb_doff
;
4458 unsigned int smblen
;
4461 int saved_errno
= 0;
4463 START_PROFILE(SMBwriteX
);
4465 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4466 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4470 numtowrite
= SVAL(req
->vwv
+10, 0);
4471 smb_doff
= SVAL(req
->vwv
+11, 0);
4472 smblen
= smb_len(req
->inbuf
);
4474 if (req
->unread_bytes
> 0xFFFF ||
4475 (smblen
> smb_doff
&&
4476 smblen
- smb_doff
> 0xFFFF)) {
4477 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4480 if (req
->unread_bytes
) {
4481 /* Can't do a recvfile write on IPC$ */
4483 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4486 if (numtowrite
!= req
->unread_bytes
) {
4487 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4491 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4492 smb_doff
+ numtowrite
> smblen
) {
4493 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4498 /* If it's an IPC, pass off the pipe handler. */
4500 if (req
->unread_bytes
) {
4501 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4504 reply_pipe_write_and_X(req
);
4508 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4509 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4510 write_through
= BITSETW(req
->vwv
+7,0);
4512 if (!check_fsp(conn
, req
, fsp
)) {
4516 if (!CHECK_WRITE(fsp
)) {
4517 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4521 data
= smb_base(req
->inbuf
) + smb_doff
;
4523 if(req
->wct
== 14) {
4525 * This is a large offset (64 bit) write.
4527 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
4531 /* X/Open SMB protocol says that, unlike SMBwrite
4532 if the length is zero then NO truncation is
4533 done, just a write of zero. To truncate a file,
4536 if(numtowrite
== 0) {
4539 if (req
->unread_bytes
== 0) {
4540 status
= schedule_aio_write_and_X(conn
,
4547 if (NT_STATUS_IS_OK(status
)) {
4548 /* write scheduled - we're done. */
4551 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4552 /* Real error - report to client. */
4553 reply_nterror(req
, status
);
4556 /* NT_STATUS_RETRY - fall through to sync write. */
4559 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4560 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4563 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4564 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4568 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4569 saved_errno
= errno
;
4571 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4575 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4579 if((nwritten
== 0) && (numtowrite
!= 0)) {
4580 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4584 reply_outbuf(req
, 6, 0);
4585 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4586 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4587 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4588 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4590 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4591 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4593 status
= sync_file(conn
, fsp
, write_through
);
4594 if (!NT_STATUS_IS_OK(status
)) {
4595 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4596 fsp_str_dbg(fsp
), nt_errstr(status
)));
4597 reply_nterror(req
, status
);
4601 END_PROFILE(SMBwriteX
);
4605 if (req
->unread_bytes
) {
4606 /* writeX failed. drain socket. */
4607 if (drain_socket(req
->sconn
->sock
, req
->unread_bytes
) !=
4608 req
->unread_bytes
) {
4609 smb_panic("failed to drain pending bytes");
4611 req
->unread_bytes
= 0;
4614 END_PROFILE(SMBwriteX
);
4618 /****************************************************************************
4620 ****************************************************************************/
4622 void reply_lseek(struct smb_request
*req
)
4624 connection_struct
*conn
= req
->conn
;
4630 START_PROFILE(SMBlseek
);
4633 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4634 END_PROFILE(SMBlseek
);
4638 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4640 if (!check_fsp(conn
, req
, fsp
)) {
4644 flush_write_cache(fsp
, SEEK_FLUSH
);
4646 mode
= SVAL(req
->vwv
+1, 0) & 3;
4647 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4648 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
4657 res
= fsp
->fh
->pos
+ startpos
;
4668 if (umode
== SEEK_END
) {
4669 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4670 if(errno
== EINVAL
) {
4671 off_t current_pos
= startpos
;
4673 if(fsp_stat(fsp
) == -1) {
4675 map_nt_error_from_unix(errno
));
4676 END_PROFILE(SMBlseek
);
4680 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4682 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4687 reply_nterror(req
, map_nt_error_from_unix(errno
));
4688 END_PROFILE(SMBlseek
);
4695 reply_outbuf(req
, 2, 0);
4696 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4698 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4699 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4701 END_PROFILE(SMBlseek
);
4705 /****************************************************************************
4707 ****************************************************************************/
4709 void reply_flush(struct smb_request
*req
)
4711 connection_struct
*conn
= req
->conn
;
4715 START_PROFILE(SMBflush
);
4718 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4722 fnum
= SVAL(req
->vwv
+0, 0);
4723 fsp
= file_fsp(req
, fnum
);
4725 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4730 file_sync_all(conn
);
4732 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4733 if (!NT_STATUS_IS_OK(status
)) {
4734 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4735 fsp_str_dbg(fsp
), nt_errstr(status
)));
4736 reply_nterror(req
, status
);
4737 END_PROFILE(SMBflush
);
4742 reply_outbuf(req
, 0, 0);
4744 DEBUG(3,("flush\n"));
4745 END_PROFILE(SMBflush
);
4749 /****************************************************************************
4751 conn POINTER CAN BE NULL HERE !
4752 ****************************************************************************/
4754 void reply_exit(struct smb_request
*req
)
4756 START_PROFILE(SMBexit
);
4758 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
4760 reply_outbuf(req
, 0, 0);
4762 DEBUG(3,("exit\n"));
4764 END_PROFILE(SMBexit
);
4768 /****************************************************************************
4769 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4770 ****************************************************************************/
4772 void reply_close(struct smb_request
*req
)
4774 connection_struct
*conn
= req
->conn
;
4775 NTSTATUS status
= NT_STATUS_OK
;
4776 files_struct
*fsp
= NULL
;
4777 START_PROFILE(SMBclose
);
4780 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4781 END_PROFILE(SMBclose
);
4785 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4788 * We can only use check_fsp if we know it's not a directory.
4791 if (!check_fsp_open(conn
, req
, fsp
)) {
4792 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4793 END_PROFILE(SMBclose
);
4797 if(fsp
->is_directory
) {
4799 * Special case - close NT SMB directory handle.
4801 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4802 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4806 * Close ordinary file.
4809 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4810 fsp
->fh
->fd
, fsp
->fnum
,
4811 conn
->num_files_open
));
4814 * Take care of any time sent in the close.
4817 t
= srv_make_unix_date3(req
->vwv
+1);
4818 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4821 * close_file() returns the unix errno if an error
4822 * was detected on close - normally this is due to
4823 * a disk full error. If not then it was probably an I/O error.
4826 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4829 if (!NT_STATUS_IS_OK(status
)) {
4830 reply_nterror(req
, status
);
4831 END_PROFILE(SMBclose
);
4835 reply_outbuf(req
, 0, 0);
4836 END_PROFILE(SMBclose
);
4840 /****************************************************************************
4841 Reply to a writeclose (Core+ protocol).
4842 ****************************************************************************/
4844 void reply_writeclose(struct smb_request
*req
)
4846 connection_struct
*conn
= req
->conn
;
4848 ssize_t nwritten
= -1;
4849 NTSTATUS close_status
= NT_STATUS_OK
;
4852 struct timespec mtime
;
4854 struct lock_struct lock
;
4856 START_PROFILE(SMBwriteclose
);
4859 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4860 END_PROFILE(SMBwriteclose
);
4864 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4866 if (!check_fsp(conn
, req
, fsp
)) {
4867 END_PROFILE(SMBwriteclose
);
4870 if (!CHECK_WRITE(fsp
)) {
4871 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4872 END_PROFILE(SMBwriteclose
);
4876 numtowrite
= SVAL(req
->vwv
+1, 0);
4877 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4878 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4879 data
= (const char *)req
->buf
+ 1;
4881 if (!fsp
->print_file
) {
4882 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4883 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4886 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4887 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4888 END_PROFILE(SMBwriteclose
);
4893 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4895 set_close_write_time(fsp
, mtime
);
4898 * More insanity. W2K only closes the file if writelen > 0.
4903 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4904 "file %s\n", fsp_str_dbg(fsp
)));
4905 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4908 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4909 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4910 conn
->num_files_open
));
4912 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4913 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4917 if(!NT_STATUS_IS_OK(close_status
)) {
4918 reply_nterror(req
, close_status
);
4922 reply_outbuf(req
, 1, 0);
4924 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4927 if (numtowrite
&& !fsp
->print_file
) {
4928 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4931 END_PROFILE(SMBwriteclose
);
4936 #define DBGC_CLASS DBGC_LOCKING
4938 /****************************************************************************
4940 ****************************************************************************/
4942 void reply_lock(struct smb_request
*req
)
4944 connection_struct
*conn
= req
->conn
;
4945 uint64_t count
,offset
;
4948 struct byte_range_lock
*br_lck
= NULL
;
4950 START_PROFILE(SMBlock
);
4953 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4954 END_PROFILE(SMBlock
);
4958 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4960 if (!check_fsp(conn
, req
, fsp
)) {
4961 END_PROFILE(SMBlock
);
4965 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
4966 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
4968 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4969 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
4971 br_lck
= do_lock(req
->sconn
->msg_ctx
,
4973 (uint64_t)req
->smbpid
,
4978 False
, /* Non-blocking lock. */
4983 TALLOC_FREE(br_lck
);
4985 if (NT_STATUS_V(status
)) {
4986 reply_nterror(req
, status
);
4987 END_PROFILE(SMBlock
);
4991 reply_outbuf(req
, 0, 0);
4993 END_PROFILE(SMBlock
);
4997 /****************************************************************************
4999 ****************************************************************************/
5001 void reply_unlock(struct smb_request
*req
)
5003 connection_struct
*conn
= req
->conn
;
5004 uint64_t count
,offset
;
5008 START_PROFILE(SMBunlock
);
5011 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5012 END_PROFILE(SMBunlock
);
5016 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5018 if (!check_fsp(conn
, req
, fsp
)) {
5019 END_PROFILE(SMBunlock
);
5023 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5024 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5026 status
= do_unlock(req
->sconn
->msg_ctx
,
5028 (uint64_t)req
->smbpid
,
5033 if (NT_STATUS_V(status
)) {
5034 reply_nterror(req
, status
);
5035 END_PROFILE(SMBunlock
);
5039 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5040 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
5042 reply_outbuf(req
, 0, 0);
5044 END_PROFILE(SMBunlock
);
5049 #define DBGC_CLASS DBGC_ALL
5051 /****************************************************************************
5053 conn POINTER CAN BE NULL HERE !
5054 ****************************************************************************/
5056 void reply_tdis(struct smb_request
*req
)
5058 connection_struct
*conn
= req
->conn
;
5059 START_PROFILE(SMBtdis
);
5062 DEBUG(4,("Invalid connection in tdis\n"));
5063 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5064 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
);