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"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
47 /****************************************************************************
48 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
49 path or anything including wildcards.
50 We're assuming here that '/' is not the second byte in any multibyte char
51 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
53 ****************************************************************************/
55 /* Custom version for processing POSIX paths. */
56 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
58 static NTSTATUS
check_path_syntax_internal(char *path
,
60 bool *p_last_component_contains_wcard
)
64 NTSTATUS ret
= NT_STATUS_OK
;
65 bool start_of_name_component
= True
;
66 bool stream_started
= false;
68 *p_last_component_contains_wcard
= False
;
75 return NT_STATUS_OBJECT_NAME_INVALID
;
78 return NT_STATUS_OBJECT_NAME_INVALID
;
80 if (strchr_m(&s
[1], ':')) {
81 return NT_STATUS_OBJECT_NAME_INVALID
;
87 if ((*s
== ':') && !posix_path
&& !stream_started
) {
88 if (*p_last_component_contains_wcard
) {
89 return NT_STATUS_OBJECT_NAME_INVALID
;
91 /* Stream names allow more characters than file names.
92 We're overloading posix_path here to allow a wider
93 range of characters. If stream_started is true this
94 is still a Windows path even if posix_path is true.
97 stream_started
= true;
98 start_of_name_component
= false;
102 return NT_STATUS_OBJECT_NAME_INVALID
;
106 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
108 * Safe to assume is not the second part of a mb char
109 * as this is handled below.
111 /* Eat multiple '/' or '\\' */
112 while (IS_PATH_SEP(*s
,posix_path
)) {
115 if ((d
!= path
) && (*s
!= '\0')) {
116 /* We only care about non-leading or trailing '/' or '\\' */
120 start_of_name_component
= True
;
122 *p_last_component_contains_wcard
= False
;
126 if (start_of_name_component
) {
127 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
128 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
131 * No mb char starts with '.' so we're safe checking the directory separator here.
134 /* If we just added a '/' - delete it */
135 if ((d
> path
) && (*(d
-1) == '/')) {
140 /* Are we at the start ? Can't go back further if so. */
142 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
145 /* Go back one level... */
146 /* We know this is safe as '/' cannot be part of a mb sequence. */
147 /* NOTE - if this assumption is invalid we are not in good shape... */
148 /* Decrement d first as d points to the *next* char to write into. */
149 for (d
--; d
> path
; d
--) {
153 s
+= 2; /* Else go past the .. */
154 /* We're still at the start of a name component, just the previous one. */
157 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
169 if (*s
<= 0x1f || *s
== '|') {
170 return NT_STATUS_OBJECT_NAME_INVALID
;
178 *p_last_component_contains_wcard
= True
;
187 /* Get the size of the next MB character. */
188 next_codepoint(s
,&siz
);
206 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
208 return NT_STATUS_INVALID_PARAMETER
;
211 start_of_name_component
= False
;
219 /****************************************************************************
220 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
221 No wildcards allowed.
222 ****************************************************************************/
224 NTSTATUS
check_path_syntax(char *path
)
227 return check_path_syntax_internal(path
, False
, &ignore
);
230 /****************************************************************************
231 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
232 Wildcards allowed - p_contains_wcard returns true if the last component contained
234 ****************************************************************************/
236 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
238 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
241 /****************************************************************************
242 Check the path for a POSIX client.
243 We're assuming here that '/' is not the second byte in any multibyte char
244 set (a safe assumption).
245 ****************************************************************************/
247 NTSTATUS
check_path_syntax_posix(char *path
)
250 return check_path_syntax_internal(path
, True
, &ignore
);
253 /****************************************************************************
254 Pull a string and check the path allowing a wilcard - provide for error return.
255 ****************************************************************************/
257 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
258 const char *base_ptr
,
265 bool *contains_wcard
)
271 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
275 *err
= NT_STATUS_INVALID_PARAMETER
;
279 *contains_wcard
= False
;
281 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
283 * For a DFS path the function parse_dfs_path()
284 * will do the path processing, just make a copy.
290 if (lp_posix_pathnames()) {
291 *err
= check_path_syntax_posix(*pp_dest
);
293 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
299 /****************************************************************************
300 Pull a string and check the path - provide for error return.
301 ****************************************************************************/
303 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
304 const char *base_ptr
,
313 return srvstr_get_path_wcard(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
314 src_len
, flags
, err
, &ignore
);
317 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
318 char **pp_dest
, const char *src
, int flags
,
319 NTSTATUS
*err
, bool *contains_wcard
)
321 ssize_t bufrem
= smbreq_bufrem(req
, src
);
324 *err
= NT_STATUS_INVALID_PARAMETER
;
328 return srvstr_get_path_wcard(mem_ctx
, (const char *)req
->inbuf
,
329 req
->flags2
, pp_dest
, src
, bufrem
, flags
,
330 err
, contains_wcard
);
333 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
334 char **pp_dest
, const char *src
, int flags
,
338 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
339 flags
, err
, &ignore
);
343 * pull a string from the smb_buf part of a packet. In this case the
344 * string can either be null terminated or it can be terminated by the
345 * end of the smbbuf area
347 size_t srvstr_pull_req_talloc(TALLOC_CTX
*ctx
, struct smb_request
*req
,
348 char **dest
, const uint8_t *src
, int flags
)
350 ssize_t bufrem
= smbreq_bufrem(req
, src
);
356 return pull_string_talloc(ctx
, req
->inbuf
, req
->flags2
, dest
, src
,
360 /****************************************************************************
361 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
362 ****************************************************************************/
364 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
367 if ((fsp
== NULL
) || (conn
== NULL
)) {
368 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
371 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
372 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
378 /****************************************************************************
379 Check if we have a correct fsp pointing to a file.
380 ****************************************************************************/
382 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
385 if (!check_fsp_open(conn
, req
, fsp
)) {
388 if (fsp
->is_directory
) {
389 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
392 if (fsp
->fh
->fd
== -1) {
393 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
396 fsp
->num_smb_operations
++;
400 /****************************************************************************
401 Check if we have a correct fsp pointing to a quota fake file. Replacement for
402 the CHECK_NTQUOTA_HANDLE_OK macro.
403 ****************************************************************************/
405 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
408 if (!check_fsp_open(conn
, req
, fsp
)) {
412 if (fsp
->is_directory
) {
416 if (fsp
->fake_file_handle
== NULL
) {
420 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
424 if (fsp
->fake_file_handle
->private_data
== NULL
) {
431 static bool netbios_session_retarget(struct smbd_server_connection
*sconn
,
432 const char *name
, int name_type
)
434 struct smbXsrv_connection
*xconn
= sconn
->conn
;
436 char *trim_name_type
;
437 const char *retarget_parm
;
440 int retarget_type
= 0x20;
441 int retarget_port
= NBT_SMB_PORT
;
442 struct sockaddr_storage retarget_addr
;
443 struct sockaddr_in
*in_addr
;
447 if (get_socket_port(xconn
->transport
.sock
) != NBT_SMB_PORT
) {
451 trim_name
= talloc_strdup(talloc_tos(), name
);
452 if (trim_name
== NULL
) {
455 trim_char(trim_name
, ' ', ' ');
457 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
459 if (trim_name_type
== NULL
) {
463 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
464 trim_name_type
, NULL
);
465 if (retarget_parm
== NULL
) {
466 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
469 if (retarget_parm
== NULL
) {
473 retarget
= talloc_strdup(trim_name
, retarget_parm
);
474 if (retarget
== NULL
) {
478 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
480 p
= strchr(retarget
, ':');
483 retarget_port
= atoi(p
);
486 p
= strchr_m(retarget
, '#');
489 if (sscanf(p
, "%x", &retarget_type
) != 1) {
494 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
496 DEBUG(10, ("could not resolve %s\n", retarget
));
500 if (retarget_addr
.ss_family
!= AF_INET
) {
501 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
505 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
507 _smb_setlen(outbuf
, 6);
508 SCVAL(outbuf
, 0, 0x84);
509 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
510 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
512 if (!srv_send_smb(sconn
, (char *)outbuf
, false, 0, false,
514 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
520 TALLOC_FREE(trim_name
);
524 static void reply_called_name_not_present(char *outbuf
)
526 smb_setlen(outbuf
, 1);
527 SCVAL(outbuf
, 0, 0x83);
528 SCVAL(outbuf
, 4, 0x82);
531 /****************************************************************************
532 Reply to a (netbios-level) special message.
533 ****************************************************************************/
535 void reply_special(struct smbd_server_connection
*sconn
, char *inbuf
, size_t inbuf_size
)
537 struct smbXsrv_connection
*xconn
= sconn
->conn
;
538 int msg_type
= CVAL(inbuf
,0);
539 int msg_flags
= CVAL(inbuf
,1);
541 * We only really use 4 bytes of the outbuf, but for the smb_setlen
542 * calculation & friends (srv_send_smb uses that) we need the full smb
545 char outbuf
[smb_size
];
547 memset(outbuf
, '\0', sizeof(outbuf
));
549 smb_setlen(outbuf
,0);
552 case NBSSrequest
: /* session request */
554 /* inbuf_size is guarenteed to be at least 4. */
556 int name_type1
, name_type2
;
557 int name_len1
, name_len2
;
561 if (xconn
->transport
.nbt
.got_session
) {
562 exit_server_cleanly("multiple session request not permitted");
565 SCVAL(outbuf
,0,NBSSpositive
);
568 /* inbuf_size is guaranteed to be at least 4. */
569 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
570 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
571 DEBUG(0,("Invalid name length in session request\n"));
572 reply_called_name_not_present(outbuf
);
575 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
576 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
577 DEBUG(0,("Invalid name length in session request\n"));
578 reply_called_name_not_present(outbuf
);
582 name_type1
= name_extract((unsigned char *)inbuf
,
583 inbuf_size
,(unsigned int)4,name1
);
584 name_type2
= name_extract((unsigned char *)inbuf
,
585 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
587 if (name_type1
== -1 || name_type2
== -1) {
588 DEBUG(0,("Invalid name type in session request\n"));
589 reply_called_name_not_present(outbuf
);
593 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
594 name1
, name_type1
, name2
, name_type2
));
596 if (netbios_session_retarget(sconn
, name1
, name_type1
)) {
597 exit_server_cleanly("retargeted client");
601 * Windows NT/2k uses "*SMBSERVER" and XP uses
602 * "*SMBSERV" arrggg!!!
604 if (strequal(name1
, "*SMBSERVER ")
605 || strequal(name1
, "*SMBSERV ")) {
608 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
611 exit_server_cleanly("could not allocate raddr");
614 fstrcpy(name1
, raddr
);
617 set_local_machine_name(name1
, True
);
618 set_remote_machine_name(name2
, True
);
620 if (is_ipaddress(sconn
->remote_hostname
)) {
621 char *p
= discard_const_p(char, sconn
->remote_hostname
);
625 sconn
->remote_hostname
= talloc_strdup(sconn
,
626 get_remote_machine_name());
627 if (sconn
->remote_hostname
== NULL
) {
628 exit_server_cleanly("could not copy remote name");
630 sconn
->conn
->remote_hostname
= sconn
->remote_hostname
;
633 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
634 get_local_machine_name(), get_remote_machine_name(),
637 if (name_type2
== 'R') {
638 /* We are being asked for a pathworks session ---
640 reply_called_name_not_present(outbuf
);
644 reload_services(sconn
, conn_snum_used
, true);
647 xconn
->transport
.nbt
.got_session
= true;
651 case 0x89: /* session keepalive request
652 (some old clients produce this?) */
653 SCVAL(outbuf
,0,NBSSkeepalive
);
657 case NBSSpositive
: /* positive session response */
658 case NBSSnegative
: /* negative session response */
659 case NBSSretarget
: /* retarget session response */
660 DEBUG(0,("Unexpected session response\n"));
663 case NBSSkeepalive
: /* session keepalive */
668 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
669 msg_type
, msg_flags
));
671 srv_send_smb(sconn
, outbuf
, false, 0, false, NULL
);
673 if (CVAL(outbuf
, 0) != 0x82) {
674 exit_server_cleanly("invalid netbios session");
679 /****************************************************************************
681 conn POINTER CAN BE NULL HERE !
682 ****************************************************************************/
684 void reply_tcon(struct smb_request
*req
)
686 connection_struct
*conn
= req
->conn
;
688 char *service_buf
= NULL
;
689 char *password
= NULL
;
695 TALLOC_CTX
*ctx
= talloc_tos();
696 struct smbd_server_connection
*sconn
= req
->sconn
;
697 struct smbXsrv_connection
*xconn
= sconn
->conn
;
698 NTTIME now
= timeval_to_nttime(&req
->request_time
);
700 START_PROFILE(SMBtcon
);
702 if (req
->buflen
< 4) {
703 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
704 END_PROFILE(SMBtcon
);
709 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
711 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
713 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
716 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
717 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
718 END_PROFILE(SMBtcon
);
721 p2
= strrchr_m(service_buf
,'\\');
725 service
= service_buf
;
728 conn
= make_connection(sconn
, now
, service
, dev
,
729 req
->vuid
,&nt_status
);
733 reply_nterror(req
, nt_status
);
734 END_PROFILE(SMBtcon
);
738 reply_outbuf(req
, 2, 0);
739 SSVAL(req
->outbuf
,smb_vwv0
,xconn
->smb1
.negprot
.max_recv
);
740 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
741 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
743 DEBUG(3,("tcon service=%s cnum=%d\n",
744 service
, conn
->cnum
));
746 END_PROFILE(SMBtcon
);
750 /****************************************************************************
751 Reply to a tcon and X.
752 conn POINTER CAN BE NULL HERE !
753 ****************************************************************************/
755 void reply_tcon_and_X(struct smb_request
*req
)
757 connection_struct
*conn
= req
->conn
;
758 const char *service
= NULL
;
759 TALLOC_CTX
*ctx
= talloc_tos();
760 /* what the cleint thinks the device is */
761 char *client_devicetype
= NULL
;
762 /* what the server tells the client the share represents */
763 const char *server_devicetype
;
770 struct smbXsrv_session
*session
= NULL
;
771 NTTIME now
= timeval_to_nttime(&req
->request_time
);
772 bool session_key_updated
= false;
773 uint16_t optional_support
= 0;
774 struct smbd_server_connection
*sconn
= req
->sconn
;
775 struct smbXsrv_connection
*xconn
= sconn
->conn
;
777 START_PROFILE(SMBtconX
);
780 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
781 END_PROFILE(SMBtconX
);
785 passlen
= SVAL(req
->vwv
+3, 0);
786 tcon_flags
= SVAL(req
->vwv
+2, 0);
788 /* we might have to close an old one */
789 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
790 struct smbXsrv_tcon
*tcon
;
798 * TODO: cancel all outstanding requests on the tcon
800 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
801 if (!NT_STATUS_IS_OK(status
)) {
802 DEBUG(0, ("reply_tcon_and_X: "
803 "smbXsrv_tcon_disconnect() failed: %s\n",
806 * If we hit this case, there is something completely
807 * wrong, so we better disconnect the transport connection.
809 END_PROFILE(SMBtconX
);
810 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
817 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
818 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
819 END_PROFILE(SMBtconX
);
823 if (xconn
->smb1
.negprot
.encrypted_passwords
) {
824 p
= req
->buf
+ passlen
;
826 p
= req
->buf
+ passlen
+ 1;
829 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
832 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
833 END_PROFILE(SMBtconX
);
838 * the service name can be either: \\server\share
839 * or share directly like on the DELL PowerVault 705
842 q
= strchr_m(path
+2,'\\');
844 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
845 END_PROFILE(SMBtconX
);
853 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
854 &client_devicetype
, p
,
855 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
857 if (client_devicetype
== NULL
) {
858 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
859 END_PROFILE(SMBtconX
);
863 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
865 nt_status
= smb1srv_session_lookup(req
->sconn
->conn
,
866 req
->vuid
, now
, &session
);
867 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
868 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
869 END_PROFILE(SMBtconX
);
872 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
873 reply_nterror(req
, nt_status
);
874 END_PROFILE(SMBtconX
);
877 if (!NT_STATUS_IS_OK(nt_status
)) {
878 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
879 END_PROFILE(SMBtconX
);
883 if (session
->global
->auth_session_info
== NULL
) {
884 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
885 END_PROFILE(SMBtconX
);
890 * If there is no application key defined yet
893 * This means we setup the application key on the
894 * first tcon that happens via the given session.
896 * Once the application key is defined, it does not
899 if (session
->global
->application_key
.length
== 0 &&
900 session
->global
->signing_key
.length
> 0)
902 struct smbXsrv_session
*x
= session
;
903 struct auth_session_info
*session_info
=
904 session
->global
->auth_session_info
;
905 uint8_t session_key
[16];
907 ZERO_STRUCT(session_key
);
908 memcpy(session_key
, x
->global
->signing_key
.data
,
909 MIN(x
->global
->signing_key
.length
, sizeof(session_key
)));
912 * The application key is truncated/padded to 16 bytes
914 x
->global
->application_key
= data_blob_talloc(x
->global
,
916 sizeof(session_key
));
917 ZERO_STRUCT(session_key
);
918 if (x
->global
->application_key
.data
== NULL
) {
919 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
920 END_PROFILE(SMBtconX
);
924 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
925 smb_key_derivation(x
->global
->application_key
.data
,
926 x
->global
->application_key
.length
,
927 x
->global
->application_key
.data
);
928 optional_support
|= SMB_EXTENDED_SIGNATURES
;
932 * Place the application key into the session_info
934 data_blob_clear_free(&session_info
->session_key
);
935 session_info
->session_key
= data_blob_dup_talloc(session_info
,
936 x
->global
->application_key
);
937 if (session_info
->session_key
.data
== NULL
) {
938 data_blob_clear_free(&x
->global
->application_key
);
939 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
940 END_PROFILE(SMBtconX
);
943 session_key_updated
= true;
946 conn
= make_connection(sconn
, now
, service
, client_devicetype
,
947 req
->vuid
, &nt_status
);
951 if (session_key_updated
) {
952 struct smbXsrv_session
*x
= session
;
953 struct auth_session_info
*session_info
=
954 session
->global
->auth_session_info
;
955 data_blob_clear_free(&x
->global
->application_key
);
956 data_blob_clear_free(&session_info
->session_key
);
958 reply_nterror(req
, nt_status
);
959 END_PROFILE(SMBtconX
);
964 server_devicetype
= "IPC";
965 else if ( IS_PRINT(conn
) )
966 server_devicetype
= "LPT1:";
968 server_devicetype
= "A:";
970 if (get_Protocol() < PROTOCOL_NT1
) {
971 reply_outbuf(req
, 2, 0);
972 if (message_push_string(&req
->outbuf
, server_devicetype
,
973 STR_TERMINATE
|STR_ASCII
) == -1) {
974 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
975 END_PROFILE(SMBtconX
);
979 /* NT sets the fstype of IPC$ to the null string */
980 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
982 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
983 /* Return permissions. */
987 reply_outbuf(req
, 7, 0);
990 perm1
= FILE_ALL_ACCESS
;
991 perm2
= FILE_ALL_ACCESS
;
993 perm1
= conn
->share_access
;
996 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
997 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
999 reply_outbuf(req
, 3, 0);
1002 if ((message_push_string(&req
->outbuf
, server_devicetype
,
1003 STR_TERMINATE
|STR_ASCII
) == -1)
1004 || (message_push_string(&req
->outbuf
, fstype
,
1005 STR_TERMINATE
) == -1)) {
1006 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1007 END_PROFILE(SMBtconX
);
1011 /* what does setting this bit do? It is set by NT4 and
1012 may affect the ability to autorun mounted cdroms */
1013 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
1015 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
1017 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
1018 DEBUG(2,("Serving %s as a Dfs root\n",
1019 lp_servicename(ctx
, SNUM(conn
)) ));
1020 optional_support
|= SMB_SHARE_IN_DFS
;
1023 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
1026 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1027 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1029 DEBUG(3,("tconX service=%s \n",
1032 /* set the incoming and outgoing tid to the just created one */
1033 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1034 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1036 END_PROFILE(SMBtconX
);
1038 req
->tid
= conn
->cnum
;
1041 /****************************************************************************
1042 Reply to an unknown type.
1043 ****************************************************************************/
1045 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
1047 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1048 smb_fn_name(type
), type
, type
));
1049 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1053 /****************************************************************************
1055 conn POINTER CAN BE NULL HERE !
1056 ****************************************************************************/
1058 void reply_ioctl(struct smb_request
*req
)
1060 connection_struct
*conn
= req
->conn
;
1067 START_PROFILE(SMBioctl
);
1070 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1071 END_PROFILE(SMBioctl
);
1075 device
= SVAL(req
->vwv
+1, 0);
1076 function
= SVAL(req
->vwv
+2, 0);
1077 ioctl_code
= (device
<< 16) + function
;
1079 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1081 switch (ioctl_code
) {
1082 case IOCTL_QUERY_JOB_INFO
:
1086 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1087 END_PROFILE(SMBioctl
);
1091 reply_outbuf(req
, 8, replysize
+1);
1092 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1093 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1094 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1095 p
= smb_buf(req
->outbuf
);
1096 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1097 p
+= 1; /* Allow for alignment */
1099 switch (ioctl_code
) {
1100 case IOCTL_QUERY_JOB_INFO
:
1102 files_struct
*fsp
= file_fsp(
1103 req
, SVAL(req
->vwv
+0, 0));
1105 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1106 END_PROFILE(SMBioctl
);
1110 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1112 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1113 lp_netbios_name(), 15,
1114 STR_TERMINATE
|STR_ASCII
);
1116 srvstr_push((char *)req
->outbuf
, req
->flags2
,
1118 lp_servicename(talloc_tos(),
1120 13, STR_TERMINATE
|STR_ASCII
);
1122 memset(p
+18, 0, 13);
1128 END_PROFILE(SMBioctl
);
1132 /****************************************************************************
1133 Strange checkpath NTSTATUS mapping.
1134 ****************************************************************************/
1136 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1138 /* Strange DOS error code semantics only for checkpath... */
1139 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1140 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1141 /* We need to map to ERRbadpath */
1142 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1148 /****************************************************************************
1149 Reply to a checkpath.
1150 ****************************************************************************/
1152 void reply_checkpath(struct smb_request
*req
)
1154 connection_struct
*conn
= req
->conn
;
1155 struct smb_filename
*smb_fname
= NULL
;
1158 TALLOC_CTX
*ctx
= talloc_tos();
1160 START_PROFILE(SMBcheckpath
);
1162 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1163 STR_TERMINATE
, &status
);
1165 if (!NT_STATUS_IS_OK(status
)) {
1166 status
= map_checkpath_error(req
->flags2
, status
);
1167 reply_nterror(req
, status
);
1168 END_PROFILE(SMBcheckpath
);
1172 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1174 status
= filename_convert(ctx
,
1176 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1182 if (!NT_STATUS_IS_OK(status
)) {
1183 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1184 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1185 ERRSRV
, ERRbadpath
);
1186 END_PROFILE(SMBcheckpath
);
1192 if (!VALID_STAT(smb_fname
->st
) &&
1193 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1194 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1195 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1196 status
= map_nt_error_from_unix(errno
);
1200 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1201 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1202 ERRDOS
, ERRbadpath
);
1206 reply_outbuf(req
, 0, 0);
1209 /* We special case this - as when a Windows machine
1210 is parsing a path is steps through the components
1211 one at a time - if a component fails it expects
1212 ERRbadpath, not ERRbadfile.
1214 status
= map_checkpath_error(req
->flags2
, status
);
1215 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1217 * Windows returns different error codes if
1218 * the parent directory is valid but not the
1219 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1220 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1221 * if the path is invalid.
1223 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1224 ERRDOS
, ERRbadpath
);
1228 reply_nterror(req
, status
);
1231 TALLOC_FREE(smb_fname
);
1232 END_PROFILE(SMBcheckpath
);
1236 /****************************************************************************
1238 ****************************************************************************/
1240 void reply_getatr(struct smb_request
*req
)
1242 connection_struct
*conn
= req
->conn
;
1243 struct smb_filename
*smb_fname
= NULL
;
1250 TALLOC_CTX
*ctx
= talloc_tos();
1251 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1253 START_PROFILE(SMBgetatr
);
1255 p
= (const char *)req
->buf
+ 1;
1256 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1257 if (!NT_STATUS_IS_OK(status
)) {
1258 reply_nterror(req
, status
);
1262 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1263 under WfWg - weird! */
1264 if (*fname
== '\0') {
1265 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1266 if (!CAN_WRITE(conn
)) {
1267 mode
|= FILE_ATTRIBUTE_READONLY
;
1272 status
= filename_convert(ctx
,
1274 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1279 if (!NT_STATUS_IS_OK(status
)) {
1280 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1281 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1282 ERRSRV
, ERRbadpath
);
1285 reply_nterror(req
, status
);
1288 if (!VALID_STAT(smb_fname
->st
) &&
1289 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1290 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1291 smb_fname_str_dbg(smb_fname
),
1293 reply_nterror(req
, map_nt_error_from_unix(errno
));
1297 mode
= dos_mode(conn
, smb_fname
);
1298 size
= smb_fname
->st
.st_ex_size
;
1300 if (ask_sharemode
) {
1301 struct timespec write_time_ts
;
1302 struct file_id fileid
;
1304 ZERO_STRUCT(write_time_ts
);
1305 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1306 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1307 if (!null_timespec(write_time_ts
)) {
1308 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1312 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1313 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1318 reply_outbuf(req
, 10, 0);
1320 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1321 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1322 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1324 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1326 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1328 if (get_Protocol() >= PROTOCOL_NT1
) {
1329 SSVAL(req
->outbuf
, smb_flg2
,
1330 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1333 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1334 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1337 TALLOC_FREE(smb_fname
);
1339 END_PROFILE(SMBgetatr
);
1343 /****************************************************************************
1345 ****************************************************************************/
1347 void reply_setatr(struct smb_request
*req
)
1349 struct smb_file_time ft
;
1350 connection_struct
*conn
= req
->conn
;
1351 struct smb_filename
*smb_fname
= NULL
;
1357 TALLOC_CTX
*ctx
= talloc_tos();
1359 START_PROFILE(SMBsetatr
);
1364 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1368 p
= (const char *)req
->buf
+ 1;
1369 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1370 if (!NT_STATUS_IS_OK(status
)) {
1371 reply_nterror(req
, status
);
1375 status
= filename_convert(ctx
,
1377 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1382 if (!NT_STATUS_IS_OK(status
)) {
1383 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1384 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1385 ERRSRV
, ERRbadpath
);
1388 reply_nterror(req
, status
);
1392 if (smb_fname
->base_name
[0] == '.' &&
1393 smb_fname
->base_name
[1] == '\0') {
1395 * Not sure here is the right place to catch this
1396 * condition. Might be moved to somewhere else later -- vl
1398 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1402 mode
= SVAL(req
->vwv
+0, 0);
1403 mtime
= srv_make_unix_date3(req
->vwv
+1);
1405 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1406 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1407 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1409 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1411 status
= check_access(conn
, NULL
, smb_fname
,
1412 FILE_WRITE_ATTRIBUTES
);
1413 if (!NT_STATUS_IS_OK(status
)) {
1414 reply_nterror(req
, status
);
1418 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1420 reply_nterror(req
, map_nt_error_from_unix(errno
));
1425 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1426 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1427 if (!NT_STATUS_IS_OK(status
)) {
1428 reply_nterror(req
, status
);
1432 reply_outbuf(req
, 0, 0);
1434 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1437 TALLOC_FREE(smb_fname
);
1438 END_PROFILE(SMBsetatr
);
1442 /****************************************************************************
1444 ****************************************************************************/
1446 void reply_dskattr(struct smb_request
*req
)
1448 connection_struct
*conn
= req
->conn
;
1449 uint64_t dfree
,dsize
,bsize
;
1450 START_PROFILE(SMBdskattr
);
1452 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1453 reply_nterror(req
, map_nt_error_from_unix(errno
));
1454 END_PROFILE(SMBdskattr
);
1458 reply_outbuf(req
, 5, 0);
1460 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1461 double total_space
, free_space
;
1462 /* we need to scale this to a number that DOS6 can handle. We
1463 use floating point so we can handle large drives on systems
1464 that don't have 64 bit integers
1466 we end up displaying a maximum of 2G to DOS systems
1468 total_space
= dsize
* (double)bsize
;
1469 free_space
= dfree
* (double)bsize
;
1471 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1472 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1474 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1475 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1477 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1478 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1479 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1480 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1482 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1483 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1484 SSVAL(req
->outbuf
,smb_vwv2
,512);
1485 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1488 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1490 END_PROFILE(SMBdskattr
);
1495 * Utility function to split the filename from the directory.
1497 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1498 char **fname_dir_out
,
1499 char **fname_mask_out
)
1501 const char *p
= NULL
;
1502 char *fname_dir
= NULL
;
1503 char *fname_mask
= NULL
;
1505 p
= strrchr_m(fname_in
, '/');
1507 fname_dir
= talloc_strdup(ctx
, ".");
1508 fname_mask
= talloc_strdup(ctx
, fname_in
);
1510 fname_dir
= talloc_strndup(ctx
, fname_in
,
1511 PTR_DIFF(p
, fname_in
));
1512 fname_mask
= talloc_strdup(ctx
, p
+1);
1515 if (!fname_dir
|| !fname_mask
) {
1516 TALLOC_FREE(fname_dir
);
1517 TALLOC_FREE(fname_mask
);
1518 return NT_STATUS_NO_MEMORY
;
1521 *fname_dir_out
= fname_dir
;
1522 *fname_mask_out
= fname_mask
;
1523 return NT_STATUS_OK
;
1526 /****************************************************************************
1528 Can be called from SMBsearch, SMBffirst or SMBfunique.
1529 ****************************************************************************/
1531 void reply_search(struct smb_request
*req
)
1533 connection_struct
*conn
= req
->conn
;
1535 const char *mask
= NULL
;
1536 char *directory
= NULL
;
1537 struct smb_filename
*smb_fname
= NULL
;
1541 struct timespec date
;
1543 unsigned int numentries
= 0;
1544 unsigned int maxentries
= 0;
1545 bool finished
= False
;
1550 bool check_descend
= False
;
1551 bool expect_close
= False
;
1553 bool mask_contains_wcard
= False
;
1554 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1555 TALLOC_CTX
*ctx
= talloc_tos();
1556 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1557 struct dptr_struct
*dirptr
= NULL
;
1558 struct smbd_server_connection
*sconn
= req
->sconn
;
1560 START_PROFILE(SMBsearch
);
1563 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1567 if (lp_posix_pathnames()) {
1568 reply_unknown_new(req
, req
->cmd
);
1572 /* If we were called as SMBffirst then we must expect close. */
1573 if(req
->cmd
== SMBffirst
) {
1574 expect_close
= True
;
1577 reply_outbuf(req
, 1, 3);
1578 maxentries
= SVAL(req
->vwv
+0, 0);
1579 dirtype
= SVAL(req
->vwv
+1, 0);
1580 p
= (const char *)req
->buf
+ 1;
1581 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1582 &nt_status
, &mask_contains_wcard
);
1583 if (!NT_STATUS_IS_OK(nt_status
)) {
1584 reply_nterror(req
, nt_status
);
1589 status_len
= SVAL(p
, 0);
1592 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1594 if (status_len
== 0) {
1595 nt_status
= filename_convert(ctx
, conn
,
1596 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1598 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1599 &mask_contains_wcard
,
1601 if (!NT_STATUS_IS_OK(nt_status
)) {
1602 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1603 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1604 ERRSRV
, ERRbadpath
);
1607 reply_nterror(req
, nt_status
);
1611 directory
= smb_fname
->base_name
;
1613 p
= strrchr_m(directory
,'/');
1614 if ((p
!= NULL
) && (*directory
!= '/')) {
1616 directory
= talloc_strndup(ctx
, directory
,
1617 PTR_DIFF(p
, directory
));
1620 directory
= talloc_strdup(ctx
,".");
1624 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1628 memset((char *)status
,'\0',21);
1629 SCVAL(status
,0,(dirtype
& 0x1F));
1631 nt_status
= dptr_create(conn
,
1639 mask_contains_wcard
,
1642 if (!NT_STATUS_IS_OK(nt_status
)) {
1643 reply_nterror(req
, nt_status
);
1646 dptr_num
= dptr_dnum(dirptr
);
1649 const char *dirpath
;
1651 memcpy(status
,p
,21);
1652 status_dirtype
= CVAL(status
,0) & 0x1F;
1653 if (status_dirtype
!= (dirtype
& 0x1F)) {
1654 dirtype
= status_dirtype
;
1657 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1661 dirpath
= dptr_path(sconn
, dptr_num
);
1662 directory
= talloc_strdup(ctx
, dirpath
);
1664 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1668 mask
= dptr_wcard(sconn
, dptr_num
);
1673 * For a 'continue' search we have no string. So
1674 * check from the initial saved string.
1676 mask_contains_wcard
= ms_has_wild(mask
);
1677 dirtype
= dptr_attr(sconn
, dptr_num
);
1680 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1682 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1683 dptr_init_search_op(dirptr
);
1685 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1686 char buf
[DIR_STRUCT_SIZE
];
1687 memcpy(buf
,status
,21);
1688 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1689 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1690 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1693 dptr_fill(sconn
, buf
+12,dptr_num
);
1694 if (dptr_zero(buf
+12) && (status_len
==0)) {
1699 if (message_push_blob(&req
->outbuf
,
1700 data_blob_const(buf
, sizeof(buf
)))
1702 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1707 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1708 size_t available_space
= sconn
->smb1
.sessions
.max_send
- hdr_size
;
1710 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1712 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1713 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
1714 if (in_list(directory
, lp_dont_descend(ctx
, SNUM(conn
)),True
)) {
1715 check_descend
= True
;
1718 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1719 finished
= !get_dir_entry(ctx
,
1730 char buf
[DIR_STRUCT_SIZE
];
1731 memcpy(buf
,status
,21);
1732 if (!make_dir_struct(ctx
,
1738 convert_timespec_to_time_t(date
),
1739 !allow_long_path_components
)) {
1740 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1743 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1746 if (message_push_blob(&req
->outbuf
,
1747 data_blob_const(buf
, sizeof(buf
)))
1749 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1759 /* If we were called as SMBffirst with smb_search_id == NULL
1760 and no entries were found then return error and close dirptr
1763 if (numentries
== 0) {
1764 dptr_close(sconn
, &dptr_num
);
1765 } else if(expect_close
&& status_len
== 0) {
1766 /* Close the dptr - we know it's gone */
1767 dptr_close(sconn
, &dptr_num
);
1770 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1771 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1772 dptr_close(sconn
, &dptr_num
);
1775 if ((numentries
== 0) && !mask_contains_wcard
) {
1776 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1780 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1781 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1782 SCVAL(smb_buf(req
->outbuf
),0,5);
1783 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1785 /* The replies here are never long name. */
1786 SSVAL(req
->outbuf
, smb_flg2
,
1787 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1788 if (!allow_long_path_components
) {
1789 SSVAL(req
->outbuf
, smb_flg2
,
1790 SVAL(req
->outbuf
, smb_flg2
)
1791 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1794 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1795 SSVAL(req
->outbuf
, smb_flg2
,
1796 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1798 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1799 smb_fn_name(req
->cmd
),
1806 TALLOC_FREE(directory
);
1807 TALLOC_FREE(smb_fname
);
1808 END_PROFILE(SMBsearch
);
1812 /****************************************************************************
1813 Reply to a fclose (stop directory search).
1814 ****************************************************************************/
1816 void reply_fclose(struct smb_request
*req
)
1824 bool path_contains_wcard
= False
;
1825 TALLOC_CTX
*ctx
= talloc_tos();
1826 struct smbd_server_connection
*sconn
= req
->sconn
;
1828 START_PROFILE(SMBfclose
);
1830 if (lp_posix_pathnames()) {
1831 reply_unknown_new(req
, req
->cmd
);
1832 END_PROFILE(SMBfclose
);
1836 p
= (const char *)req
->buf
+ 1;
1837 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1838 &err
, &path_contains_wcard
);
1839 if (!NT_STATUS_IS_OK(err
)) {
1840 reply_nterror(req
, err
);
1841 END_PROFILE(SMBfclose
);
1845 status_len
= SVAL(p
,0);
1848 if (status_len
== 0) {
1849 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1850 END_PROFILE(SMBfclose
);
1854 memcpy(status
,p
,21);
1856 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1857 /* Close the dptr - we know it's gone */
1858 dptr_close(sconn
, &dptr_num
);
1861 reply_outbuf(req
, 1, 0);
1862 SSVAL(req
->outbuf
,smb_vwv0
,0);
1864 DEBUG(3,("search close\n"));
1866 END_PROFILE(SMBfclose
);
1870 /****************************************************************************
1872 ****************************************************************************/
1874 void reply_open(struct smb_request
*req
)
1876 connection_struct
*conn
= req
->conn
;
1877 struct smb_filename
*smb_fname
= NULL
;
1889 uint32 create_disposition
;
1890 uint32 create_options
= 0;
1891 uint32_t private_flags
= 0;
1893 TALLOC_CTX
*ctx
= talloc_tos();
1895 START_PROFILE(SMBopen
);
1898 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1902 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1903 deny_mode
= SVAL(req
->vwv
+0, 0);
1904 dos_attr
= SVAL(req
->vwv
+1, 0);
1906 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1907 STR_TERMINATE
, &status
);
1908 if (!NT_STATUS_IS_OK(status
)) {
1909 reply_nterror(req
, status
);
1913 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1914 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1915 &share_mode
, &create_disposition
,
1916 &create_options
, &private_flags
)) {
1917 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1921 status
= filename_convert(ctx
,
1923 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1925 UCF_PREP_CREATEFILE
,
1928 if (!NT_STATUS_IS_OK(status
)) {
1929 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1930 reply_botherror(req
,
1931 NT_STATUS_PATH_NOT_COVERED
,
1932 ERRSRV
, ERRbadpath
);
1935 reply_nterror(req
, status
);
1939 status
= SMB_VFS_CREATE_FILE(
1942 0, /* root_dir_fid */
1943 smb_fname
, /* fname */
1944 access_mask
, /* access_mask */
1945 share_mode
, /* share_access */
1946 create_disposition
, /* create_disposition*/
1947 create_options
, /* create_options */
1948 dos_attr
, /* file_attributes */
1949 oplock_request
, /* oplock_request */
1950 0, /* allocation_size */
1957 if (!NT_STATUS_IS_OK(status
)) {
1958 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1959 /* We have re-scheduled this call. */
1962 reply_openerror(req
, status
);
1966 /* Ensure we're pointing at the correct stat struct. */
1967 TALLOC_FREE(smb_fname
);
1968 smb_fname
= fsp
->fsp_name
;
1970 size
= smb_fname
->st
.st_ex_size
;
1971 fattr
= dos_mode(conn
, smb_fname
);
1973 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1975 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1976 DEBUG(3,("attempt to open a directory %s\n",
1978 close_file(req
, fsp
, ERROR_CLOSE
);
1979 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1980 ERRDOS
, ERRnoaccess
);
1984 reply_outbuf(req
, 7, 0);
1985 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1986 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1987 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1988 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1990 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1992 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1993 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1995 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1996 SCVAL(req
->outbuf
,smb_flg
,
1997 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2000 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2001 SCVAL(req
->outbuf
,smb_flg
,
2002 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2005 END_PROFILE(SMBopen
);
2009 /****************************************************************************
2010 Reply to an open and X.
2011 ****************************************************************************/
2013 void reply_open_and_X(struct smb_request
*req
)
2015 connection_struct
*conn
= req
->conn
;
2016 struct smb_filename
*smb_fname
= NULL
;
2021 /* Breakout the oplock request bits so we can set the
2022 reply bits separately. */
2023 int ex_oplock_request
;
2024 int core_oplock_request
;
2027 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2028 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
2036 uint64_t allocation_size
;
2037 ssize_t retval
= -1;
2040 uint32 create_disposition
;
2041 uint32 create_options
= 0;
2042 uint32_t private_flags
= 0;
2043 TALLOC_CTX
*ctx
= talloc_tos();
2045 START_PROFILE(SMBopenX
);
2047 if (req
->wct
< 15) {
2048 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2052 open_flags
= SVAL(req
->vwv
+2, 0);
2053 deny_mode
= SVAL(req
->vwv
+3, 0);
2054 smb_attr
= SVAL(req
->vwv
+5, 0);
2055 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2056 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2057 oplock_request
= ex_oplock_request
| core_oplock_request
;
2058 smb_ofun
= SVAL(req
->vwv
+8, 0);
2059 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2061 /* If it's an IPC, pass off the pipe handler. */
2063 if (lp_nt_pipe_support()) {
2064 reply_open_pipe_and_X(conn
, req
);
2066 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2071 /* XXXX we need to handle passed times, sattr and flags */
2072 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2073 STR_TERMINATE
, &status
);
2074 if (!NT_STATUS_IS_OK(status
)) {
2075 reply_nterror(req
, status
);
2079 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2081 &access_mask
, &share_mode
,
2082 &create_disposition
,
2085 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2089 status
= filename_convert(ctx
,
2091 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2093 UCF_PREP_CREATEFILE
,
2096 if (!NT_STATUS_IS_OK(status
)) {
2097 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2098 reply_botherror(req
,
2099 NT_STATUS_PATH_NOT_COVERED
,
2100 ERRSRV
, ERRbadpath
);
2103 reply_nterror(req
, status
);
2107 status
= SMB_VFS_CREATE_FILE(
2110 0, /* root_dir_fid */
2111 smb_fname
, /* fname */
2112 access_mask
, /* access_mask */
2113 share_mode
, /* share_access */
2114 create_disposition
, /* create_disposition*/
2115 create_options
, /* create_options */
2116 smb_attr
, /* file_attributes */
2117 oplock_request
, /* oplock_request */
2118 0, /* allocation_size */
2123 &smb_action
); /* pinfo */
2125 if (!NT_STATUS_IS_OK(status
)) {
2126 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2127 /* We have re-scheduled this call. */
2130 reply_openerror(req
, status
);
2134 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2135 if the file is truncated or created. */
2136 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2137 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2138 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2139 close_file(req
, fsp
, ERROR_CLOSE
);
2140 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2143 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2145 close_file(req
, fsp
, ERROR_CLOSE
);
2146 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2149 status
= vfs_stat_fsp(fsp
);
2150 if (!NT_STATUS_IS_OK(status
)) {
2151 close_file(req
, fsp
, ERROR_CLOSE
);
2152 reply_nterror(req
, status
);
2157 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2158 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2159 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2160 close_file(req
, fsp
, ERROR_CLOSE
);
2161 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2165 /* If the caller set the extended oplock request bit
2166 and we granted one (by whatever means) - set the
2167 correct bit for extended oplock reply.
2170 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2171 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2174 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2175 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2178 /* If the caller set the core oplock request bit
2179 and we granted one (by whatever means) - set the
2180 correct bit for core oplock reply.
2183 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2184 reply_outbuf(req
, 19, 0);
2186 reply_outbuf(req
, 15, 0);
2189 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2190 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2192 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2193 SCVAL(req
->outbuf
, smb_flg
,
2194 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2197 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2198 SCVAL(req
->outbuf
, smb_flg
,
2199 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2202 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2203 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2204 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2205 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2207 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2209 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2210 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2211 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2213 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2214 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2218 TALLOC_FREE(smb_fname
);
2219 END_PROFILE(SMBopenX
);
2223 /****************************************************************************
2224 Reply to a SMBulogoffX.
2225 ****************************************************************************/
2227 void reply_ulogoffX(struct smb_request
*req
)
2229 struct smbd_server_connection
*sconn
= req
->sconn
;
2230 struct user_struct
*vuser
;
2231 struct smbXsrv_session
*session
= NULL
;
2234 START_PROFILE(SMBulogoffX
);
2236 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2239 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2240 (unsigned long long)req
->vuid
));
2242 req
->vuid
= UID_FIELD_INVALID
;
2243 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2244 END_PROFILE(SMBulogoffX
);
2248 session
= vuser
->session
;
2252 * TODO: cancel all outstanding requests on the session
2254 status
= smbXsrv_session_logoff(session
);
2255 if (!NT_STATUS_IS_OK(status
)) {
2256 DEBUG(0, ("reply_ulogoff: "
2257 "smbXsrv_session_logoff() failed: %s\n",
2258 nt_errstr(status
)));
2260 * If we hit this case, there is something completely
2261 * wrong, so we better disconnect the transport connection.
2263 END_PROFILE(SMBulogoffX
);
2264 exit_server(__location__
": smbXsrv_session_logoff failed");
2268 TALLOC_FREE(session
);
2270 reply_outbuf(req
, 2, 0);
2271 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2272 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2274 DEBUG(3, ("ulogoffX vuid=%llu\n",
2275 (unsigned long long)req
->vuid
));
2277 END_PROFILE(SMBulogoffX
);
2278 req
->vuid
= UID_FIELD_INVALID
;
2281 /****************************************************************************
2282 Reply to a mknew or a create.
2283 ****************************************************************************/
2285 void reply_mknew(struct smb_request
*req
)
2287 connection_struct
*conn
= req
->conn
;
2288 struct smb_filename
*smb_fname
= NULL
;
2291 struct smb_file_time ft
;
2293 int oplock_request
= 0;
2295 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2296 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2297 uint32 create_disposition
;
2298 uint32 create_options
= 0;
2299 TALLOC_CTX
*ctx
= talloc_tos();
2301 START_PROFILE(SMBcreate
);
2305 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2309 fattr
= SVAL(req
->vwv
+0, 0);
2310 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2313 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2315 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2316 STR_TERMINATE
, &status
);
2317 if (!NT_STATUS_IS_OK(status
)) {
2318 reply_nterror(req
, status
);
2322 status
= filename_convert(ctx
,
2324 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2326 UCF_PREP_CREATEFILE
,
2329 if (!NT_STATUS_IS_OK(status
)) {
2330 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2331 reply_botherror(req
,
2332 NT_STATUS_PATH_NOT_COVERED
,
2333 ERRSRV
, ERRbadpath
);
2336 reply_nterror(req
, status
);
2340 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2341 DEBUG(0,("Attempt to create file (%s) with volid set - "
2342 "please report this\n",
2343 smb_fname_str_dbg(smb_fname
)));
2346 if(req
->cmd
== SMBmknew
) {
2347 /* We should fail if file exists. */
2348 create_disposition
= FILE_CREATE
;
2350 /* Create if file doesn't exist, truncate if it does. */
2351 create_disposition
= FILE_OVERWRITE_IF
;
2354 status
= SMB_VFS_CREATE_FILE(
2357 0, /* root_dir_fid */
2358 smb_fname
, /* fname */
2359 access_mask
, /* access_mask */
2360 share_mode
, /* share_access */
2361 create_disposition
, /* create_disposition*/
2362 create_options
, /* create_options */
2363 fattr
, /* file_attributes */
2364 oplock_request
, /* oplock_request */
2365 0, /* allocation_size */
2366 0, /* private_flags */
2372 if (!NT_STATUS_IS_OK(status
)) {
2373 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2374 /* We have re-scheduled this call. */
2377 reply_openerror(req
, status
);
2381 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2382 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2383 if (!NT_STATUS_IS_OK(status
)) {
2384 END_PROFILE(SMBcreate
);
2388 reply_outbuf(req
, 1, 0);
2389 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2391 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2392 SCVAL(req
->outbuf
,smb_flg
,
2393 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2396 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2397 SCVAL(req
->outbuf
,smb_flg
,
2398 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2401 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2402 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2403 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2404 (unsigned int)fattr
));
2407 TALLOC_FREE(smb_fname
);
2408 END_PROFILE(SMBcreate
);
2412 /****************************************************************************
2413 Reply to a create temporary file.
2414 ****************************************************************************/
2416 void reply_ctemp(struct smb_request
*req
)
2418 connection_struct
*conn
= req
->conn
;
2419 struct smb_filename
*smb_fname
= NULL
;
2420 char *wire_name
= NULL
;
2428 TALLOC_CTX
*ctx
= talloc_tos();
2430 START_PROFILE(SMBctemp
);
2433 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2437 fattr
= SVAL(req
->vwv
+0, 0);
2438 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2440 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2441 STR_TERMINATE
, &status
);
2442 if (!NT_STATUS_IS_OK(status
)) {
2443 reply_nterror(req
, status
);
2447 for (i
= 0; i
< 10; i
++) {
2449 fname
= talloc_asprintf(ctx
,
2452 generate_random_str_list(ctx
, 5, "0123456789"));
2454 fname
= talloc_asprintf(ctx
,
2456 generate_random_str_list(ctx
, 5, "0123456789"));
2460 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2464 status
= filename_convert(ctx
, conn
,
2465 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2467 UCF_PREP_CREATEFILE
,
2470 if (!NT_STATUS_IS_OK(status
)) {
2471 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2472 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2473 ERRSRV
, ERRbadpath
);
2476 reply_nterror(req
, status
);
2480 /* Create the file. */
2481 status
= SMB_VFS_CREATE_FILE(
2484 0, /* root_dir_fid */
2485 smb_fname
, /* fname */
2486 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2487 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2488 FILE_CREATE
, /* create_disposition*/
2489 0, /* create_options */
2490 fattr
, /* file_attributes */
2491 oplock_request
, /* oplock_request */
2492 0, /* allocation_size */
2493 0, /* private_flags */
2499 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2501 TALLOC_FREE(smb_fname
);
2505 if (!NT_STATUS_IS_OK(status
)) {
2506 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2507 /* We have re-scheduled this call. */
2510 reply_openerror(req
, status
);
2518 /* Collision after 10 times... */
2519 reply_nterror(req
, status
);
2523 reply_outbuf(req
, 1, 0);
2524 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2526 /* the returned filename is relative to the directory */
2527 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2529 s
= fsp
->fsp_name
->base_name
;
2535 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2536 thing in the byte section. JRA */
2537 SSVALS(p
, 0, -1); /* what is this? not in spec */
2539 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2541 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2545 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2546 SCVAL(req
->outbuf
, smb_flg
,
2547 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2550 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2551 SCVAL(req
->outbuf
, smb_flg
,
2552 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2555 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2556 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2557 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2559 TALLOC_FREE(smb_fname
);
2560 TALLOC_FREE(wire_name
);
2561 END_PROFILE(SMBctemp
);
2565 /*******************************************************************
2566 Check if a user is allowed to rename a file.
2567 ********************************************************************/
2569 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2572 if (!CAN_WRITE(conn
)) {
2573 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2576 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2577 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2578 /* Only bother to read the DOS attribute if we might deny the
2579 rename on the grounds of attribute missmatch. */
2580 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2581 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2582 return NT_STATUS_NO_SUCH_FILE
;
2586 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2587 if (fsp
->posix_open
) {
2588 return NT_STATUS_OK
;
2591 /* If no pathnames are open below this
2592 directory, allow the rename. */
2594 if (file_find_subpath(fsp
)) {
2595 return NT_STATUS_ACCESS_DENIED
;
2597 return NT_STATUS_OK
;
2600 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2601 return NT_STATUS_OK
;
2604 return NT_STATUS_ACCESS_DENIED
;
2607 /*******************************************************************
2608 * unlink a file with all relevant access checks
2609 *******************************************************************/
2611 static NTSTATUS
do_unlink(connection_struct
*conn
,
2612 struct smb_request
*req
,
2613 struct smb_filename
*smb_fname
,
2618 uint32 dirtype_orig
= dirtype
;
2621 bool posix_paths
= lp_posix_pathnames();
2623 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2624 smb_fname_str_dbg(smb_fname
),
2627 if (!CAN_WRITE(conn
)) {
2628 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2632 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2634 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2637 return map_nt_error_from_unix(errno
);
2640 fattr
= dos_mode(conn
, smb_fname
);
2642 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2643 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2646 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2648 return NT_STATUS_NO_SUCH_FILE
;
2651 if (!dir_check_ftype(fattr
, dirtype
)) {
2652 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2653 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2655 return NT_STATUS_NO_SUCH_FILE
;
2658 if (dirtype_orig
& 0x8000) {
2659 /* These will never be set for POSIX. */
2660 return NT_STATUS_NO_SUCH_FILE
;
2664 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2665 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2668 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2669 return NT_STATUS_NO_SUCH_FILE
;
2672 if (dirtype
& 0xFF00) {
2673 /* These will never be set for POSIX. */
2674 return NT_STATUS_NO_SUCH_FILE
;
2679 return NT_STATUS_NO_SUCH_FILE
;
2682 /* Can't delete a directory. */
2683 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2684 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2689 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2690 return NT_STATUS_OBJECT_NAME_INVALID
;
2691 #endif /* JRATEST */
2693 /* On open checks the open itself will check the share mode, so
2694 don't do it here as we'll get it wrong. */
2696 status
= SMB_VFS_CREATE_FILE
2699 0, /* root_dir_fid */
2700 smb_fname
, /* fname */
2701 DELETE_ACCESS
, /* access_mask */
2702 FILE_SHARE_NONE
, /* share_access */
2703 FILE_OPEN
, /* create_disposition*/
2704 FILE_NON_DIRECTORY_FILE
, /* create_options */
2705 /* file_attributes */
2706 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2707 FILE_ATTRIBUTE_NORMAL
,
2708 0, /* oplock_request */
2709 0, /* allocation_size */
2710 0, /* private_flags */
2716 if (!NT_STATUS_IS_OK(status
)) {
2717 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2718 nt_errstr(status
)));
2722 status
= can_set_delete_on_close(fsp
, fattr
);
2723 if (!NT_STATUS_IS_OK(status
)) {
2724 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2726 smb_fname_str_dbg(smb_fname
),
2727 nt_errstr(status
)));
2728 close_file(req
, fsp
, NORMAL_CLOSE
);
2732 /* The set is across all open files on this dev/inode pair. */
2733 if (!set_delete_on_close(fsp
, True
,
2734 conn
->session_info
->security_token
,
2735 conn
->session_info
->unix_token
)) {
2736 close_file(req
, fsp
, NORMAL_CLOSE
);
2737 return NT_STATUS_ACCESS_DENIED
;
2740 return close_file(req
, fsp
, NORMAL_CLOSE
);
2743 /****************************************************************************
2744 The guts of the unlink command, split out so it may be called by the NT SMB
2746 ****************************************************************************/
2748 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2749 uint32 dirtype
, struct smb_filename
*smb_fname
,
2752 char *fname_dir
= NULL
;
2753 char *fname_mask
= NULL
;
2755 NTSTATUS status
= NT_STATUS_OK
;
2756 TALLOC_CTX
*ctx
= talloc_tos();
2758 /* Split up the directory from the filename/mask. */
2759 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2760 &fname_dir
, &fname_mask
);
2761 if (!NT_STATUS_IS_OK(status
)) {
2766 * We should only check the mangled cache
2767 * here if unix_convert failed. This means
2768 * that the path in 'mask' doesn't exist
2769 * on the file system and so we need to look
2770 * for a possible mangle. This patch from
2771 * Tine Smukavec <valentin.smukavec@hermes.si>.
2774 if (!VALID_STAT(smb_fname
->st
) &&
2775 mangle_is_mangled(fname_mask
, conn
->params
)) {
2776 char *new_mask
= NULL
;
2777 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2778 &new_mask
, conn
->params
);
2780 TALLOC_FREE(fname_mask
);
2781 fname_mask
= new_mask
;
2788 * Only one file needs to be unlinked. Append the mask back
2789 * onto the directory.
2791 TALLOC_FREE(smb_fname
->base_name
);
2792 if (ISDOT(fname_dir
)) {
2793 /* Ensure we use canonical names on open. */
2794 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2798 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2803 if (!smb_fname
->base_name
) {
2804 status
= NT_STATUS_NO_MEMORY
;
2808 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2811 status
= check_name(conn
, smb_fname
->base_name
);
2812 if (!NT_STATUS_IS_OK(status
)) {
2816 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2817 if (!NT_STATUS_IS_OK(status
)) {
2823 struct smb_Dir
*dir_hnd
= NULL
;
2825 const char *dname
= NULL
;
2826 char *talloced
= NULL
;
2828 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2829 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2833 if (strequal(fname_mask
,"????????.???")) {
2834 TALLOC_FREE(fname_mask
);
2835 fname_mask
= talloc_strdup(ctx
, "*");
2837 status
= NT_STATUS_NO_MEMORY
;
2842 status
= check_name(conn
, fname_dir
);
2843 if (!NT_STATUS_IS_OK(status
)) {
2847 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2849 if (dir_hnd
== NULL
) {
2850 status
= map_nt_error_from_unix(errno
);
2854 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2855 the pattern matches against the long name, otherwise the short name
2856 We don't implement this yet XXXX
2859 status
= NT_STATUS_NO_SUCH_FILE
;
2861 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2862 &smb_fname
->st
, &talloced
))) {
2863 TALLOC_CTX
*frame
= talloc_stackframe();
2865 if (!is_visible_file(conn
, fname_dir
, dname
,
2866 &smb_fname
->st
, true)) {
2868 TALLOC_FREE(talloced
);
2872 /* Quick check for "." and ".." */
2873 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2875 TALLOC_FREE(talloced
);
2879 if(!mask_match(dname
, fname_mask
,
2880 conn
->case_sensitive
)) {
2882 TALLOC_FREE(talloced
);
2886 TALLOC_FREE(smb_fname
->base_name
);
2887 if (ISDOT(fname_dir
)) {
2888 /* Ensure we use canonical names on open. */
2889 smb_fname
->base_name
=
2890 talloc_asprintf(smb_fname
, "%s",
2893 smb_fname
->base_name
=
2894 talloc_asprintf(smb_fname
, "%s/%s",
2898 if (!smb_fname
->base_name
) {
2899 TALLOC_FREE(dir_hnd
);
2900 status
= NT_STATUS_NO_MEMORY
;
2902 TALLOC_FREE(talloced
);
2906 status
= check_name(conn
, smb_fname
->base_name
);
2907 if (!NT_STATUS_IS_OK(status
)) {
2908 TALLOC_FREE(dir_hnd
);
2910 TALLOC_FREE(talloced
);
2914 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2915 if (!NT_STATUS_IS_OK(status
)) {
2916 TALLOC_FREE(dir_hnd
);
2918 TALLOC_FREE(talloced
);
2923 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2924 smb_fname
->base_name
));
2927 TALLOC_FREE(talloced
);
2929 TALLOC_FREE(dir_hnd
);
2932 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2933 status
= map_nt_error_from_unix(errno
);
2937 TALLOC_FREE(fname_dir
);
2938 TALLOC_FREE(fname_mask
);
2942 /****************************************************************************
2944 ****************************************************************************/
2946 void reply_unlink(struct smb_request
*req
)
2948 connection_struct
*conn
= req
->conn
;
2950 struct smb_filename
*smb_fname
= NULL
;
2953 bool path_contains_wcard
= False
;
2954 TALLOC_CTX
*ctx
= talloc_tos();
2956 START_PROFILE(SMBunlink
);
2959 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2963 dirtype
= SVAL(req
->vwv
+0, 0);
2965 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2966 STR_TERMINATE
, &status
,
2967 &path_contains_wcard
);
2968 if (!NT_STATUS_IS_OK(status
)) {
2969 reply_nterror(req
, status
);
2973 status
= filename_convert(ctx
, conn
,
2974 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2976 UCF_COND_ALLOW_WCARD_LCOMP
,
2977 &path_contains_wcard
,
2979 if (!NT_STATUS_IS_OK(status
)) {
2980 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2981 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2982 ERRSRV
, ERRbadpath
);
2985 reply_nterror(req
, status
);
2989 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2991 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2992 path_contains_wcard
);
2993 if (!NT_STATUS_IS_OK(status
)) {
2994 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2995 /* We have re-scheduled this call. */
2998 reply_nterror(req
, status
);
3002 reply_outbuf(req
, 0, 0);
3004 TALLOC_FREE(smb_fname
);
3005 END_PROFILE(SMBunlink
);
3009 /****************************************************************************
3011 ****************************************************************************/
3013 static void fail_readraw(void)
3015 const char *errstr
= talloc_asprintf(talloc_tos(),
3016 "FAIL ! reply_readbraw: socket write fail (%s)",
3021 exit_server_cleanly(errstr
);
3024 /****************************************************************************
3025 Fake (read/write) sendfile. Returns -1 on read or write fail.
3026 ****************************************************************************/
3028 ssize_t
fake_sendfile(files_struct
*fsp
, off_t startpos
, size_t nread
)
3030 struct smbXsrv_connection
*xconn
= fsp
->conn
->sconn
->conn
;
3032 size_t tosend
= nread
;
3039 bufsize
= MIN(nread
, 65536);
3041 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3045 while (tosend
> 0) {
3049 if (tosend
> bufsize
) {
3054 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3060 /* If we had a short read, fill with zeros. */
3061 if (ret
< cur_read
) {
3062 memset(buf
+ ret
, '\0', cur_read
- ret
);
3065 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3066 if (ret
!= cur_read
) {
3067 int saved_errno
= errno
;
3069 * Try and give an error message saying what
3072 DEBUG(0, ("write_data failed for client %s. "
3074 smbXsrv_connection_dbg(xconn
),
3075 strerror(saved_errno
)));
3077 errno
= saved_errno
;
3081 startpos
+= cur_read
;
3085 return (ssize_t
)nread
;
3088 /****************************************************************************
3089 Deal with the case of sendfile reading less bytes from the file than
3090 requested. Fill with zeros (all we can do).
3091 ****************************************************************************/
3093 void sendfile_short_send(files_struct
*fsp
,
3098 struct smbXsrv_connection
*xconn
= fsp
->conn
->sconn
->conn
;
3100 #define SHORT_SEND_BUFSIZE 1024
3101 if (nread
< headersize
) {
3102 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3103 "header for file %s (%s). Terminating\n",
3104 fsp_str_dbg(fsp
), strerror(errno
)));
3105 exit_server_cleanly("sendfile_short_send failed");
3108 nread
-= headersize
;
3110 if (nread
< smb_maxcnt
) {
3111 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3113 exit_server_cleanly("sendfile_short_send: "
3117 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3118 "with zeros !\n", fsp_str_dbg(fsp
)));
3120 while (nread
< smb_maxcnt
) {
3122 * We asked for the real file size and told sendfile
3123 * to not go beyond the end of the file. But it can
3124 * happen that in between our fstat call and the
3125 * sendfile call the file was truncated. This is very
3126 * bad because we have already announced the larger
3127 * number of bytes to the client.
3129 * The best we can do now is to send 0-bytes, just as
3130 * a read from a hole in a sparse file would do.
3132 * This should happen rarely enough that I don't care
3133 * about efficiency here :-)
3138 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3139 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3140 if (ret
!= to_write
) {
3141 int saved_errno
= errno
;
3143 * Try and give an error message saying what
3146 DEBUG(0, ("write_data failed for client %s. "
3148 smbXsrv_connection_dbg(xconn
),
3149 strerror(saved_errno
)));
3150 errno
= saved_errno
;
3151 exit_server_cleanly("sendfile_short_send: "
3152 "write_data failed");
3160 /****************************************************************************
3161 Return a readbraw error (4 bytes of zero).
3162 ****************************************************************************/
3164 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
3166 struct smbXsrv_connection
*xconn
= sconn
->conn
;
3171 smbd_lock_socket(sconn
);
3172 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3173 int saved_errno
= errno
;
3175 * Try and give an error message saying what
3178 DEBUG(0, ("write_data failed for client %s. "
3180 smbXsrv_connection_dbg(xconn
),
3181 strerror(saved_errno
)));
3182 errno
= saved_errno
;
3186 smbd_unlock_socket(sconn
);
3189 /****************************************************************************
3190 Use sendfile in readbraw.
3191 ****************************************************************************/
3193 static void send_file_readbraw(connection_struct
*conn
,
3194 struct smb_request
*req
,
3200 struct smbd_server_connection
*sconn
= req
->sconn
;
3201 struct smbXsrv_connection
*xconn
= sconn
->conn
;
3202 char *outbuf
= NULL
;
3206 * We can only use sendfile on a non-chained packet
3207 * but we can use on a non-oplocked file. tridge proved this
3208 * on a train in Germany :-). JRA.
3209 * reply_readbraw has already checked the length.
3212 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3213 (fsp
->wcp
== NULL
) &&
3214 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3215 ssize_t sendfile_read
= -1;
3217 DATA_BLOB header_blob
;
3219 _smb_setlen(header
,nread
);
3220 header_blob
= data_blob_const(header
, 4);
3222 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3223 &header_blob
, startpos
,
3225 if (sendfile_read
== -1) {
3226 /* Returning ENOSYS means no data at all was sent.
3227 * Do this as a normal read. */
3228 if (errno
== ENOSYS
) {
3229 goto normal_readbraw
;
3233 * Special hack for broken Linux with no working sendfile. If we
3234 * return EINTR we sent the header but not the rest of the data.
3235 * Fake this up by doing read/write calls.
3237 if (errno
== EINTR
) {
3238 /* Ensure we don't do this again. */
3239 set_use_sendfile(SNUM(conn
), False
);
3240 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3242 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3243 DEBUG(0,("send_file_readbraw: "
3244 "fake_sendfile failed for "
3248 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3253 DEBUG(0,("send_file_readbraw: sendfile failed for "
3254 "file %s (%s). Terminating\n",
3255 fsp_str_dbg(fsp
), strerror(errno
)));
3256 exit_server_cleanly("send_file_readbraw sendfile failed");
3257 } else if (sendfile_read
== 0) {
3259 * Some sendfile implementations return 0 to indicate
3260 * that there was a short read, but nothing was
3261 * actually written to the socket. In this case,
3262 * fallback to the normal read path so the header gets
3263 * the correct byte count.
3265 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3266 "bytes falling back to the normal read: "
3267 "%s\n", fsp_str_dbg(fsp
)));
3268 goto normal_readbraw
;
3271 /* Deal with possible short send. */
3272 if (sendfile_read
!= 4+nread
) {
3273 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3280 outbuf
= talloc_array(NULL
, char, nread
+4);
3282 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3283 (unsigned)(nread
+4)));
3284 reply_readbraw_error(sconn
);
3289 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3290 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3299 _smb_setlen(outbuf
,ret
);
3300 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3301 int saved_errno
= errno
;
3303 * Try and give an error message saying what
3306 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3307 smbXsrv_connection_dbg(xconn
),
3308 strerror(saved_errno
)));
3309 errno
= saved_errno
;
3314 TALLOC_FREE(outbuf
);
3317 /****************************************************************************
3318 Reply to a readbraw (core+ protocol).
3319 ****************************************************************************/
3321 void reply_readbraw(struct smb_request
*req
)
3323 connection_struct
*conn
= req
->conn
;
3324 struct smbd_server_connection
*sconn
= req
->sconn
;
3325 ssize_t maxcount
,mincount
;
3329 struct lock_struct lock
;
3332 START_PROFILE(SMBreadbraw
);
3334 if (srv_is_signing_active(sconn
) || req
->encrypted
) {
3335 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3336 "raw reads/writes are disallowed.");
3340 reply_readbraw_error(sconn
);
3341 END_PROFILE(SMBreadbraw
);
3345 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3346 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3347 "'async smb echo handler = yes'\n"));
3348 reply_readbraw_error(sconn
);
3349 END_PROFILE(SMBreadbraw
);
3354 * Special check if an oplock break has been issued
3355 * and the readraw request croses on the wire, we must
3356 * return a zero length response here.
3359 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3362 * We have to do a check_fsp by hand here, as
3363 * we must always return 4 zero bytes on error,
3367 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3368 req
->vuid
!= fsp
->vuid
||
3369 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3371 * fsp could be NULL here so use the value from the packet. JRA.
3373 DEBUG(3,("reply_readbraw: fnum %d not valid "
3375 (int)SVAL(req
->vwv
+0, 0)));
3376 reply_readbraw_error(sconn
);
3377 END_PROFILE(SMBreadbraw
);
3381 /* Do a "by hand" version of CHECK_READ. */
3382 if (!(fsp
->can_read
||
3383 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3384 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3385 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3386 (int)SVAL(req
->vwv
+0, 0)));
3387 reply_readbraw_error(sconn
);
3388 END_PROFILE(SMBreadbraw
);
3392 flush_write_cache(fsp
, SAMBA_READRAW_FLUSH
);
3394 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3395 if(req
->wct
== 10) {
3397 * This is a large offset (64 bit) read.
3400 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3403 DEBUG(0,("reply_readbraw: negative 64 bit "
3404 "readraw offset (%.0f) !\n",
3405 (double)startpos
));
3406 reply_readbraw_error(sconn
);
3407 END_PROFILE(SMBreadbraw
);
3412 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3413 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3415 /* ensure we don't overrun the packet size */
3416 maxcount
= MIN(65535,maxcount
);
3418 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3419 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3422 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3423 reply_readbraw_error(sconn
);
3424 END_PROFILE(SMBreadbraw
);
3428 if (fsp_stat(fsp
) == 0) {
3429 size
= fsp
->fsp_name
->st
.st_ex_size
;
3432 if (startpos
>= size
) {
3435 nread
= MIN(maxcount
,(size
- startpos
));
3438 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3439 if (nread
< mincount
)
3443 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3444 "min=%lu nread=%lu\n",
3445 fsp_fnum_dbg(fsp
), (double)startpos
,
3446 (unsigned long)maxcount
,
3447 (unsigned long)mincount
,
3448 (unsigned long)nread
) );
3450 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3452 DEBUG(5,("reply_readbraw finished\n"));
3454 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3456 END_PROFILE(SMBreadbraw
);
3461 #define DBGC_CLASS DBGC_LOCKING
3463 /****************************************************************************
3464 Reply to a lockread (core+ protocol).
3465 ****************************************************************************/
3467 void reply_lockread(struct smb_request
*req
)
3469 connection_struct
*conn
= req
->conn
;
3477 struct byte_range_lock
*br_lck
= NULL
;
3479 struct smbd_server_connection
*sconn
= req
->sconn
;
3481 START_PROFILE(SMBlockread
);
3484 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3485 END_PROFILE(SMBlockread
);
3489 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3491 if (!check_fsp(conn
, req
, fsp
)) {
3492 END_PROFILE(SMBlockread
);
3496 if (!CHECK_READ(fsp
,req
)) {
3497 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3498 END_PROFILE(SMBlockread
);
3502 numtoread
= SVAL(req
->vwv
+1, 0);
3503 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3506 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3507 * protocol request that predates the read/write lock concept.
3508 * Thus instead of asking for a read lock here we need to ask
3509 * for a write lock. JRA.
3510 * Note that the requested lock size is unaffected by max_send.
3513 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3515 (uint64_t)req
->smbpid
,
3516 (uint64_t)numtoread
,
3520 False
, /* Non-blocking lock. */
3523 TALLOC_FREE(br_lck
);
3525 if (NT_STATUS_V(status
)) {
3526 reply_nterror(req
, status
);
3527 END_PROFILE(SMBlockread
);
3532 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3534 maxtoread
= sconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3536 if (numtoread
> maxtoread
) {
3537 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3538 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3539 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3540 (unsigned int)sconn
->smb1
.sessions
.max_send
));
3541 numtoread
= maxtoread
;
3544 reply_outbuf(req
, 5, numtoread
+ 3);
3546 data
= smb_buf(req
->outbuf
) + 3;
3548 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3551 reply_nterror(req
, map_nt_error_from_unix(errno
));
3552 END_PROFILE(SMBlockread
);
3556 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3558 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3559 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3560 p
= smb_buf(req
->outbuf
);
3561 SCVAL(p
,0,0); /* pad byte. */
3564 DEBUG(3,("lockread %s num=%d nread=%d\n",
3565 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3567 END_PROFILE(SMBlockread
);
3572 #define DBGC_CLASS DBGC_ALL
3574 /****************************************************************************
3576 ****************************************************************************/
3578 void reply_read(struct smb_request
*req
)
3580 connection_struct
*conn
= req
->conn
;
3587 struct lock_struct lock
;
3588 struct smbd_server_connection
*sconn
= req
->sconn
;
3590 START_PROFILE(SMBread
);
3593 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3594 END_PROFILE(SMBread
);
3598 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3600 if (!check_fsp(conn
, req
, fsp
)) {
3601 END_PROFILE(SMBread
);
3605 if (!CHECK_READ(fsp
,req
)) {
3606 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3607 END_PROFILE(SMBread
);
3611 numtoread
= SVAL(req
->vwv
+1, 0);
3612 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3615 * The requested read size cannot be greater than max_send. JRA.
3617 maxtoread
= sconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3619 if (numtoread
> maxtoread
) {
3620 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3621 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3622 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3623 (unsigned int)sconn
->smb1
.sessions
.max_send
));
3624 numtoread
= maxtoread
;
3627 reply_outbuf(req
, 5, numtoread
+3);
3629 data
= smb_buf(req
->outbuf
) + 3;
3631 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3632 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3635 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3636 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3637 END_PROFILE(SMBread
);
3642 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3645 reply_nterror(req
, map_nt_error_from_unix(errno
));
3649 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3651 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3652 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3653 SCVAL(smb_buf(req
->outbuf
),0,1);
3654 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3656 DEBUG(3, ("read %s num=%d nread=%d\n",
3657 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3660 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3662 END_PROFILE(SMBread
);
3666 /****************************************************************************
3668 ****************************************************************************/
3670 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3675 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3677 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3679 SCVAL(outbuf
,smb_vwv0
,0xFF);
3680 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3681 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3682 SSVAL(outbuf
,smb_vwv6
,
3683 (smb_wct
- 4) /* offset from smb header to wct */
3684 + 1 /* the wct field */
3685 + 12 * sizeof(uint16_t) /* vwv */
3686 + 2); /* the buflen field */
3687 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3688 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3689 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3690 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3694 /****************************************************************************
3695 Reply to a read and X - possibly using sendfile.
3696 ****************************************************************************/
3698 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3699 files_struct
*fsp
, off_t startpos
,
3702 struct smbXsrv_connection
*xconn
= req
->sconn
->conn
;
3704 struct lock_struct lock
;
3705 int saved_errno
= 0;
3707 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3708 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3711 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3712 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3717 * We can only use sendfile on a non-chained packet
3718 * but we can use on a non-oplocked file. tridge proved this
3719 * on a train in Germany :-). JRA.
3722 if (!req_is_in_chain(req
) &&
3724 (fsp
->base_fsp
== NULL
) &&
3725 (fsp
->wcp
== NULL
) &&
3726 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3727 uint8 headerbuf
[smb_size
+ 12 * 2];
3730 if(fsp_stat(fsp
) == -1) {
3731 reply_nterror(req
, map_nt_error_from_unix(errno
));
3735 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3736 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3737 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3739 * We already know that we would do a short read, so don't
3740 * try the sendfile() path.
3742 goto nosendfile_read
;
3746 * Set up the packet header before send. We
3747 * assume here the sendfile will work (get the
3748 * correct amount of data).
3751 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3753 construct_reply_common_req(req
, (char *)headerbuf
);
3754 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3756 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
3757 startpos
, smb_maxcnt
);
3759 saved_errno
= errno
;
3761 /* Returning ENOSYS means no data at all was sent.
3762 Do this as a normal read. */
3763 if (errno
== ENOSYS
) {
3768 * Special hack for broken Linux with no working sendfile. If we
3769 * return EINTR we sent the header but not the rest of the data.
3770 * Fake this up by doing read/write calls.
3773 if (errno
== EINTR
) {
3774 /* Ensure we don't do this again. */
3775 set_use_sendfile(SNUM(conn
), False
);
3776 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3777 nread
= fake_sendfile(fsp
, startpos
,
3780 saved_errno
= errno
;
3781 DEBUG(0,("send_file_readX: "
3782 "fake_sendfile failed for "
3783 "file %s (%s) for client %s. "
3786 smbXsrv_connection_dbg(xconn
),
3787 strerror(saved_errno
)));
3788 errno
= saved_errno
;
3789 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3791 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3792 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3793 /* No outbuf here means successful sendfile. */
3797 DEBUG(0,("send_file_readX: sendfile failed for file "
3798 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3800 exit_server_cleanly("send_file_readX sendfile failed");
3801 } else if (nread
== 0) {
3803 * Some sendfile implementations return 0 to indicate
3804 * that there was a short read, but nothing was
3805 * actually written to the socket. In this case,
3806 * fallback to the normal read path so the header gets
3807 * the correct byte count.
3809 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3810 "falling back to the normal read: %s\n",
3815 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3816 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3818 /* Deal with possible short send. */
3819 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3820 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3822 /* No outbuf here means successful sendfile. */
3823 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3824 SMB_PERFCOUNT_END(&req
->pcd
);
3830 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3831 uint8 headerbuf
[smb_size
+ 2*12];
3834 construct_reply_common_req(req
, (char *)headerbuf
);
3835 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3837 /* Send out the header. */
3838 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
3840 if (ret
!= sizeof(headerbuf
)) {
3841 saved_errno
= errno
;
3843 * Try and give an error message saying what
3846 DEBUG(0,("send_file_readX: write_data failed for file "
3847 "%s (%s) for client %s. Terminating\n",
3849 smbXsrv_connection_dbg(xconn
),
3850 strerror(saved_errno
)));
3851 errno
= saved_errno
;
3852 exit_server_cleanly("send_file_readX sendfile failed");
3854 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3856 saved_errno
= errno
;
3857 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3858 "%s (%s) for client %s. Terminating\n",
3860 smbXsrv_connection_dbg(xconn
),
3861 strerror(saved_errno
)));
3862 errno
= saved_errno
;
3863 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3870 reply_outbuf(req
, 12, smb_maxcnt
);
3871 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
3872 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
3874 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3875 saved_errno
= errno
;
3877 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3880 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3884 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3886 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3887 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3891 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3892 TALLOC_FREE(req
->outbuf
);
3896 /****************************************************************************
3897 Work out how much space we have for a read return.
3898 ****************************************************************************/
3900 static size_t calc_max_read_pdu(const struct smb_request
*req
)
3902 if (req
->sconn
->conn
->protocol
< PROTOCOL_NT1
) {
3903 return req
->sconn
->smb1
.sessions
.max_send
;
3906 if (!lp_large_readwrite()) {
3907 return req
->sconn
->smb1
.sessions
.max_send
;
3910 if (req_is_in_chain(req
)) {
3911 return req
->sconn
->smb1
.sessions
.max_send
;
3914 if (req
->encrypted
) {
3916 * Don't take encrypted traffic up to the
3917 * limit. There are padding considerations
3918 * that make that tricky.
3920 return req
->sconn
->smb1
.sessions
.max_send
;
3923 if (srv_is_signing_active(req
->sconn
)) {
3927 if (!lp_unix_extensions()) {
3932 * We can do ultra-large POSIX reads.
3937 /****************************************************************************
3938 Calculate how big a read can be. Copes with all clients. It's always
3939 safe to return a short read - Windows does this.
3940 ****************************************************************************/
3942 static size_t calc_read_size(const struct smb_request
*req
,
3946 size_t max_pdu
= calc_max_read_pdu(req
);
3947 size_t total_size
= 0;
3948 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
3949 size_t max_len
= max_pdu
- hdr_len
;
3952 * Windows explicitly ignores upper size of 0xFFFF.
3953 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3954 * We must do the same as these will never fit even in
3955 * an extended size NetBIOS packet.
3957 if (upper_size
== 0xFFFF) {
3961 if (req
->sconn
->conn
->protocol
< PROTOCOL_NT1
) {
3965 total_size
= ((upper_size
<<16) | lower_size
);
3968 * LARGE_READX test shows it's always safe to return
3969 * a short read. Windows does so.
3971 return MIN(total_size
, max_len
);
3974 /****************************************************************************
3975 Reply to a read and X.
3976 ****************************************************************************/
3978 void reply_read_and_X(struct smb_request
*req
)
3980 connection_struct
*conn
= req
->conn
;
3985 bool big_readX
= False
;
3987 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3990 START_PROFILE(SMBreadX
);
3992 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3993 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3997 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3998 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3999 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4001 /* If it's an IPC, pass off the pipe handler. */
4003 reply_pipe_read_and_X(req
);
4004 END_PROFILE(SMBreadX
);
4008 if (!check_fsp(conn
, req
, fsp
)) {
4009 END_PROFILE(SMBreadX
);
4013 if (!CHECK_READ(fsp
,req
)) {
4014 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4015 END_PROFILE(SMBreadX
);
4019 upper_size
= SVAL(req
->vwv
+7, 0);
4020 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4021 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4023 * This is a heuristic to avoid keeping large
4024 * outgoing buffers around over long-lived aio
4030 if (req
->wct
== 12) {
4032 * This is a large offset (64 bit) read.
4034 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4039 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4044 if (NT_STATUS_IS_OK(status
)) {
4045 /* Read scheduled - we're done. */
4048 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4049 /* Real error - report to client. */
4050 END_PROFILE(SMBreadX
);
4051 reply_nterror(req
, status
);
4054 /* NT_STATUS_RETRY - fall back to sync read. */
4057 smbd_lock_socket(req
->sconn
);
4058 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4059 smbd_unlock_socket(req
->sconn
);
4062 END_PROFILE(SMBreadX
);
4066 /****************************************************************************
4067 Error replies to writebraw must have smb_wct == 1. Fix this up.
4068 ****************************************************************************/
4070 void error_to_writebrawerr(struct smb_request
*req
)
4072 uint8
*old_outbuf
= req
->outbuf
;
4074 reply_outbuf(req
, 1, 0);
4076 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4077 TALLOC_FREE(old_outbuf
);
4080 /****************************************************************************
4081 Read 4 bytes of a smb packet and return the smb length of the packet.
4082 Store the result in the buffer. This version of the function will
4083 never return a session keepalive (length of zero).
4084 Timeout is in milliseconds.
4085 ****************************************************************************/
4087 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4090 uint8_t msgtype
= NBSSkeepalive
;
4092 while (msgtype
== NBSSkeepalive
) {
4095 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4097 if (!NT_STATUS_IS_OK(status
)) {
4098 char addr
[INET6_ADDRSTRLEN
];
4099 /* Try and give an error message
4100 * saying what client failed. */
4101 DEBUG(0, ("read_fd_with_timeout failed for "
4102 "client %s read error = %s.\n",
4103 get_peer_addr(fd
,addr
,sizeof(addr
)),
4104 nt_errstr(status
)));
4108 msgtype
= CVAL(inbuf
, 0);
4111 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4112 (unsigned long)len
));
4114 return NT_STATUS_OK
;
4117 /****************************************************************************
4118 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4119 ****************************************************************************/
4121 void reply_writebraw(struct smb_request
*req
)
4123 connection_struct
*conn
= req
->conn
;
4124 struct smbXsrv_connection
*xconn
= req
->sconn
->conn
;
4127 ssize_t total_written
=0;
4128 size_t numtowrite
=0;
4131 const char *data
=NULL
;
4134 struct lock_struct lock
;
4137 START_PROFILE(SMBwritebraw
);
4140 * If we ever reply with an error, it must have the SMB command
4141 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4144 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4146 if (srv_is_signing_active(req
->sconn
)) {
4147 END_PROFILE(SMBwritebraw
);
4148 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4149 "raw reads/writes are disallowed.");
4152 if (req
->wct
< 12) {
4153 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4154 error_to_writebrawerr(req
);
4155 END_PROFILE(SMBwritebraw
);
4159 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
4160 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4161 "'async smb echo handler = yes'\n"));
4162 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4163 error_to_writebrawerr(req
);
4164 END_PROFILE(SMBwritebraw
);
4168 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4169 if (!check_fsp(conn
, req
, fsp
)) {
4170 error_to_writebrawerr(req
);
4171 END_PROFILE(SMBwritebraw
);
4175 if (!CHECK_WRITE(fsp
)) {
4176 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4177 error_to_writebrawerr(req
);
4178 END_PROFILE(SMBwritebraw
);
4182 tcount
= IVAL(req
->vwv
+1, 0);
4183 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4184 write_through
= BITSETW(req
->vwv
+7,0);
4186 /* We have to deal with slightly different formats depending
4187 on whether we are using the core+ or lanman1.0 protocol */
4189 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4190 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4191 data
= smb_buf_const(req
->inbuf
);
4193 numtowrite
= SVAL(req
->vwv
+10, 0);
4194 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4197 /* Ensure we don't write bytes past the end of this packet. */
4198 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4199 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4200 error_to_writebrawerr(req
);
4201 END_PROFILE(SMBwritebraw
);
4205 if (!fsp
->print_file
) {
4206 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4207 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4210 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4211 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4212 error_to_writebrawerr(req
);
4213 END_PROFILE(SMBwritebraw
);
4219 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4222 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4223 "wrote=%d sync=%d\n",
4224 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4225 (int)nwritten
, (int)write_through
));
4227 if (nwritten
< (ssize_t
)numtowrite
) {
4228 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4229 error_to_writebrawerr(req
);
4233 total_written
= nwritten
;
4235 /* Allocate a buffer of 64k + length. */
4236 buf
= talloc_array(NULL
, char, 65540);
4238 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4239 error_to_writebrawerr(req
);
4243 /* Return a SMBwritebraw message to the redirector to tell
4244 * it to send more bytes */
4246 memcpy(buf
, req
->inbuf
, smb_size
);
4247 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4248 SCVAL(buf
,smb_com
,SMBwritebraw
);
4249 SSVALS(buf
,smb_vwv0
,0xFFFF);
4251 if (!srv_send_smb(req
->sconn
,
4253 false, 0, /* no signing */
4254 IS_CONN_ENCRYPTED(conn
),
4256 exit_server_cleanly("reply_writebraw: srv_send_smb "
4260 /* Now read the raw data into the buffer and write it */
4261 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4263 if (!NT_STATUS_IS_OK(status
)) {
4264 exit_server_cleanly("secondary writebraw failed");
4267 /* Set up outbuf to return the correct size */
4268 reply_outbuf(req
, 1, 0);
4270 if (numtowrite
!= 0) {
4272 if (numtowrite
> 0xFFFF) {
4273 DEBUG(0,("reply_writebraw: Oversize secondary write "
4274 "raw requested (%u). Terminating\n",
4275 (unsigned int)numtowrite
));
4276 exit_server_cleanly("secondary writebraw failed");
4279 if (tcount
> nwritten
+numtowrite
) {
4280 DEBUG(3,("reply_writebraw: Client overestimated the "
4282 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4285 status
= read_data(xconn
->transport
.sock
, buf
+4, numtowrite
);
4287 if (!NT_STATUS_IS_OK(status
)) {
4288 /* Try and give an error message
4289 * saying what client failed. */
4290 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4291 "raw read failed (%s) for client %s. "
4292 "Terminating\n", nt_errstr(status
),
4293 smbXsrv_connection_dbg(xconn
)));
4294 exit_server_cleanly("secondary writebraw failed");
4297 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4298 if (nwritten
== -1) {
4300 reply_nterror(req
, map_nt_error_from_unix(errno
));
4301 error_to_writebrawerr(req
);
4305 if (nwritten
< (ssize_t
)numtowrite
) {
4306 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4307 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4311 total_written
+= nwritten
;
4316 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4318 status
= sync_file(conn
, fsp
, write_through
);
4319 if (!NT_STATUS_IS_OK(status
)) {
4320 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4321 fsp_str_dbg(fsp
), nt_errstr(status
)));
4322 reply_nterror(req
, status
);
4323 error_to_writebrawerr(req
);
4327 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4329 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4330 (int)total_written
));
4332 if (!fsp
->print_file
) {
4333 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4336 /* We won't return a status if write through is not selected - this
4337 * follows what WfWg does */
4338 END_PROFILE(SMBwritebraw
);
4340 if (!write_through
&& total_written
==tcount
) {
4342 #if RABBIT_PELLET_FIX
4344 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4345 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4348 if (!send_keepalive(xconn
->transport
.sock
)) {
4349 exit_server_cleanly("reply_writebraw: send of "
4350 "keepalive failed");
4353 TALLOC_FREE(req
->outbuf
);
4358 if (!fsp
->print_file
) {
4359 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4362 END_PROFILE(SMBwritebraw
);
4367 #define DBGC_CLASS DBGC_LOCKING
4369 /****************************************************************************
4370 Reply to a writeunlock (core+).
4371 ****************************************************************************/
4373 void reply_writeunlock(struct smb_request
*req
)
4375 connection_struct
*conn
= req
->conn
;
4376 ssize_t nwritten
= -1;
4380 NTSTATUS status
= NT_STATUS_OK
;
4382 struct lock_struct lock
;
4383 int saved_errno
= 0;
4385 START_PROFILE(SMBwriteunlock
);
4388 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4389 END_PROFILE(SMBwriteunlock
);
4393 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4395 if (!check_fsp(conn
, req
, fsp
)) {
4396 END_PROFILE(SMBwriteunlock
);
4400 if (!CHECK_WRITE(fsp
)) {
4401 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4402 END_PROFILE(SMBwriteunlock
);
4406 numtowrite
= SVAL(req
->vwv
+1, 0);
4407 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4408 data
= (const char *)req
->buf
+ 3;
4410 if (!fsp
->print_file
&& numtowrite
> 0) {
4411 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4412 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4415 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4416 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4417 END_PROFILE(SMBwriteunlock
);
4422 /* The special X/Open SMB protocol handling of
4423 zero length writes is *NOT* done for
4425 if(numtowrite
== 0) {
4428 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4429 saved_errno
= errno
;
4432 status
= sync_file(conn
, fsp
, False
/* write through */);
4433 if (!NT_STATUS_IS_OK(status
)) {
4434 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4435 fsp_str_dbg(fsp
), nt_errstr(status
)));
4436 reply_nterror(req
, status
);
4441 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4445 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4446 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4450 if (numtowrite
&& !fsp
->print_file
) {
4451 status
= do_unlock(req
->sconn
->msg_ctx
,
4453 (uint64_t)req
->smbpid
,
4454 (uint64_t)numtowrite
,
4458 if (NT_STATUS_V(status
)) {
4459 reply_nterror(req
, status
);
4464 reply_outbuf(req
, 1, 0);
4466 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4468 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4469 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4472 if (numtowrite
&& !fsp
->print_file
) {
4473 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4476 END_PROFILE(SMBwriteunlock
);
4481 #define DBGC_CLASS DBGC_ALL
4483 /****************************************************************************
4485 ****************************************************************************/
4487 void reply_write(struct smb_request
*req
)
4489 connection_struct
*conn
= req
->conn
;
4491 ssize_t nwritten
= -1;
4495 struct lock_struct lock
;
4497 int saved_errno
= 0;
4499 START_PROFILE(SMBwrite
);
4502 END_PROFILE(SMBwrite
);
4503 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4507 /* If it's an IPC, pass off the pipe handler. */
4509 reply_pipe_write(req
);
4510 END_PROFILE(SMBwrite
);
4514 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4516 if (!check_fsp(conn
, req
, fsp
)) {
4517 END_PROFILE(SMBwrite
);
4521 if (!CHECK_WRITE(fsp
)) {
4522 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4523 END_PROFILE(SMBwrite
);
4527 numtowrite
= SVAL(req
->vwv
+1, 0);
4528 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4529 data
= (const char *)req
->buf
+ 3;
4531 if (!fsp
->print_file
) {
4532 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4533 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4536 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4537 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4538 END_PROFILE(SMBwrite
);
4544 * X/Open SMB protocol says that if smb_vwv1 is
4545 * zero then the file size should be extended or
4546 * truncated to the size given in smb_vwv[2-3].
4549 if(numtowrite
== 0) {
4551 * This is actually an allocate call, and set EOF. JRA.
4553 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4555 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4558 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4560 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4563 trigger_write_time_update_immediate(fsp
);
4565 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4568 status
= sync_file(conn
, fsp
, False
);
4569 if (!NT_STATUS_IS_OK(status
)) {
4570 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4571 fsp_str_dbg(fsp
), nt_errstr(status
)));
4572 reply_nterror(req
, status
);
4577 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4581 if((nwritten
== 0) && (numtowrite
!= 0)) {
4582 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4586 reply_outbuf(req
, 1, 0);
4588 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4590 if (nwritten
< (ssize_t
)numtowrite
) {
4591 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4592 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4595 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4598 if (!fsp
->print_file
) {
4599 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4602 END_PROFILE(SMBwrite
);
4606 /****************************************************************************
4607 Ensure a buffer is a valid writeX for recvfile purposes.
4608 ****************************************************************************/
4610 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4611 (2*14) + /* word count (including bcc) */ \
4614 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4615 const uint8_t *inbuf
)
4618 unsigned int doff
= 0;
4619 size_t len
= smb_len_large(inbuf
);
4621 struct smbXsrv_open
*op
= NULL
;
4622 struct files_struct
*fsp
= NULL
;
4625 if (is_encrypted_packet(sconn
, inbuf
)) {
4626 /* Can't do this on encrypted
4631 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4635 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4636 CVAL(inbuf
,smb_wct
) != 14) {
4637 DEBUG(10,("is_valid_writeX_buffer: chained or "
4638 "invalid word length.\n"));
4642 fnum
= SVAL(inbuf
, smb_vwv2
);
4643 status
= smb1srv_open_lookup(sconn
->conn
,
4647 if (!NT_STATUS_IS_OK(status
)) {
4648 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4653 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4656 if (fsp
->conn
== NULL
) {
4657 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4661 if (IS_IPC(fsp
->conn
)) {
4662 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4665 if (IS_PRINT(fsp
->conn
)) {
4666 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4669 doff
= SVAL(inbuf
,smb_vwv11
);
4671 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4673 if (len
> doff
&& len
- doff
> 0xFFFF) {
4674 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4677 if (numtowrite
== 0) {
4678 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4682 /* Ensure the sizes match up. */
4683 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4684 /* no pad byte...old smbclient :-( */
4685 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4687 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4691 if (len
- doff
!= numtowrite
) {
4692 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4693 "len = %u, doff = %u, numtowrite = %u\n",
4696 (unsigned int)numtowrite
));
4700 DEBUG(10,("is_valid_writeX_buffer: true "
4701 "len = %u, doff = %u, numtowrite = %u\n",
4704 (unsigned int)numtowrite
));
4709 /****************************************************************************
4710 Reply to a write and X.
4711 ****************************************************************************/
4713 void reply_write_and_X(struct smb_request
*req
)
4715 connection_struct
*conn
= req
->conn
;
4716 struct smbXsrv_connection
*xconn
= req
->sconn
->conn
;
4718 struct lock_struct lock
;
4723 unsigned int smb_doff
;
4724 unsigned int smblen
;
4727 int saved_errno
= 0;
4729 START_PROFILE(SMBwriteX
);
4731 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4732 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4736 numtowrite
= SVAL(req
->vwv
+10, 0);
4737 smb_doff
= SVAL(req
->vwv
+11, 0);
4738 smblen
= smb_len(req
->inbuf
);
4740 if (req
->unread_bytes
> 0xFFFF ||
4741 (smblen
> smb_doff
&&
4742 smblen
- smb_doff
> 0xFFFF)) {
4743 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4746 if (req
->unread_bytes
) {
4747 /* Can't do a recvfile write on IPC$ */
4749 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4752 if (numtowrite
!= req
->unread_bytes
) {
4753 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4757 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4758 smb_doff
+ numtowrite
> smblen
) {
4759 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4764 /* If it's an IPC, pass off the pipe handler. */
4766 if (req
->unread_bytes
) {
4767 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4770 reply_pipe_write_and_X(req
);
4774 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4775 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4776 write_through
= BITSETW(req
->vwv
+7,0);
4778 if (!check_fsp(conn
, req
, fsp
)) {
4782 if (!CHECK_WRITE(fsp
)) {
4783 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4787 data
= smb_base(req
->inbuf
) + smb_doff
;
4789 if(req
->wct
== 14) {
4791 * This is a large offset (64 bit) write.
4793 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
4797 /* X/Open SMB protocol says that, unlike SMBwrite
4798 if the length is zero then NO truncation is
4799 done, just a write of zero. To truncate a file,
4802 if(numtowrite
== 0) {
4805 if (req
->unread_bytes
== 0) {
4806 status
= schedule_aio_write_and_X(conn
,
4813 if (NT_STATUS_IS_OK(status
)) {
4814 /* write scheduled - we're done. */
4817 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4818 /* Real error - report to client. */
4819 reply_nterror(req
, status
);
4822 /* NT_STATUS_RETRY - fall through to sync write. */
4825 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4826 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4829 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4830 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4834 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4835 saved_errno
= errno
;
4837 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4841 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4845 if((nwritten
== 0) && (numtowrite
!= 0)) {
4846 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4850 reply_outbuf(req
, 6, 0);
4851 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4852 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4853 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4854 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4856 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4857 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4859 status
= sync_file(conn
, fsp
, write_through
);
4860 if (!NT_STATUS_IS_OK(status
)) {
4861 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4862 fsp_str_dbg(fsp
), nt_errstr(status
)));
4863 reply_nterror(req
, status
);
4867 END_PROFILE(SMBwriteX
);
4871 if (req
->unread_bytes
) {
4872 /* writeX failed. drain socket. */
4873 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
4874 req
->unread_bytes
) {
4875 smb_panic("failed to drain pending bytes");
4877 req
->unread_bytes
= 0;
4880 END_PROFILE(SMBwriteX
);
4884 /****************************************************************************
4886 ****************************************************************************/
4888 void reply_lseek(struct smb_request
*req
)
4890 connection_struct
*conn
= req
->conn
;
4896 START_PROFILE(SMBlseek
);
4899 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4900 END_PROFILE(SMBlseek
);
4904 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4906 if (!check_fsp(conn
, req
, fsp
)) {
4910 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
4912 mode
= SVAL(req
->vwv
+1, 0) & 3;
4913 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4914 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
4923 res
= fsp
->fh
->pos
+ startpos
;
4934 if (umode
== SEEK_END
) {
4935 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4936 if(errno
== EINVAL
) {
4937 off_t current_pos
= startpos
;
4939 if(fsp_stat(fsp
) == -1) {
4941 map_nt_error_from_unix(errno
));
4942 END_PROFILE(SMBlseek
);
4946 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4948 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4953 reply_nterror(req
, map_nt_error_from_unix(errno
));
4954 END_PROFILE(SMBlseek
);
4961 reply_outbuf(req
, 2, 0);
4962 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4964 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4965 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
4967 END_PROFILE(SMBlseek
);
4971 /****************************************************************************
4973 ****************************************************************************/
4975 void reply_flush(struct smb_request
*req
)
4977 connection_struct
*conn
= req
->conn
;
4981 START_PROFILE(SMBflush
);
4984 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4988 fnum
= SVAL(req
->vwv
+0, 0);
4989 fsp
= file_fsp(req
, fnum
);
4991 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4996 file_sync_all(conn
);
4998 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4999 if (!NT_STATUS_IS_OK(status
)) {
5000 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5001 fsp_str_dbg(fsp
), nt_errstr(status
)));
5002 reply_nterror(req
, status
);
5003 END_PROFILE(SMBflush
);
5008 reply_outbuf(req
, 0, 0);
5010 DEBUG(3,("flush\n"));
5011 END_PROFILE(SMBflush
);
5015 /****************************************************************************
5017 conn POINTER CAN BE NULL HERE !
5018 ****************************************************************************/
5020 void reply_exit(struct smb_request
*req
)
5022 START_PROFILE(SMBexit
);
5024 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5026 reply_outbuf(req
, 0, 0);
5028 DEBUG(3,("exit\n"));
5030 END_PROFILE(SMBexit
);
5034 struct reply_close_state
{
5036 struct smb_request
*smbreq
;
5039 static void do_smb1_close(struct tevent_req
*req
);
5041 void reply_close(struct smb_request
*req
)
5043 connection_struct
*conn
= req
->conn
;
5044 NTSTATUS status
= NT_STATUS_OK
;
5045 files_struct
*fsp
= NULL
;
5046 START_PROFILE(SMBclose
);
5049 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5050 END_PROFILE(SMBclose
);
5054 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5057 * We can only use check_fsp if we know it's not a directory.
5060 if (!check_fsp_open(conn
, req
, fsp
)) {
5061 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5062 END_PROFILE(SMBclose
);
5066 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5067 fsp
->is_directory
? "directory" : "file",
5068 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5069 conn
->num_files_open
));
5071 if (!fsp
->is_directory
) {
5075 * Take care of any time sent in the close.
5078 t
= srv_make_unix_date3(req
->vwv
+1);
5079 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5082 if (fsp
->num_aio_requests
!= 0) {
5084 struct reply_close_state
*state
;
5086 DEBUG(10, ("closing with aio %u requests pending\n",
5087 fsp
->num_aio_requests
));
5090 * We depend on the aio_extra destructor to take care of this
5091 * close request once fsp->num_aio_request drops to 0.
5094 fsp
->deferred_close
= tevent_wait_send(
5095 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5096 if (fsp
->deferred_close
== NULL
) {
5097 status
= NT_STATUS_NO_MEMORY
;
5101 state
= talloc(fsp
, struct reply_close_state
);
5102 if (state
== NULL
) {
5103 TALLOC_FREE(fsp
->deferred_close
);
5104 status
= NT_STATUS_NO_MEMORY
;
5108 state
->smbreq
= talloc_move(fsp
, &req
);
5109 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5111 END_PROFILE(SMBclose
);
5116 * close_file() returns the unix errno if an error was detected on
5117 * close - normally this is due to a disk full error. If not then it
5118 * was probably an I/O error.
5121 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5123 if (!NT_STATUS_IS_OK(status
)) {
5124 reply_nterror(req
, status
);
5125 END_PROFILE(SMBclose
);
5129 reply_outbuf(req
, 0, 0);
5130 END_PROFILE(SMBclose
);
5134 static void do_smb1_close(struct tevent_req
*req
)
5136 struct reply_close_state
*state
= tevent_req_callback_data(
5137 req
, struct reply_close_state
);
5138 struct smb_request
*smbreq
;
5142 ret
= tevent_wait_recv(req
);
5145 DEBUG(10, ("tevent_wait_recv returned %s\n",
5148 * Continue anyway, this should never happen
5153 * fsp->smb2_close_request right now is a talloc grandchild of
5154 * fsp. When we close_file(fsp), it would go with it. No chance to
5157 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5159 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5160 if (NT_STATUS_IS_OK(status
)) {
5161 reply_outbuf(smbreq
, 0, 0);
5163 reply_nterror(smbreq
, status
);
5165 if (!srv_send_smb(smbreq
->sconn
,
5166 (char *)smbreq
->outbuf
,
5169 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5171 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5174 TALLOC_FREE(smbreq
);
5177 /****************************************************************************
5178 Reply to a writeclose (Core+ protocol).
5179 ****************************************************************************/
5181 void reply_writeclose(struct smb_request
*req
)
5183 connection_struct
*conn
= req
->conn
;
5185 ssize_t nwritten
= -1;
5186 NTSTATUS close_status
= NT_STATUS_OK
;
5189 struct timespec mtime
;
5191 struct lock_struct lock
;
5193 START_PROFILE(SMBwriteclose
);
5196 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5197 END_PROFILE(SMBwriteclose
);
5201 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5203 if (!check_fsp(conn
, req
, fsp
)) {
5204 END_PROFILE(SMBwriteclose
);
5207 if (!CHECK_WRITE(fsp
)) {
5208 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5209 END_PROFILE(SMBwriteclose
);
5213 numtowrite
= SVAL(req
->vwv
+1, 0);
5214 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5215 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5216 data
= (const char *)req
->buf
+ 1;
5218 if (fsp
->print_file
== NULL
) {
5219 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5220 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5223 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5224 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5225 END_PROFILE(SMBwriteclose
);
5230 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5232 if (fsp
->print_file
== NULL
) {
5233 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5236 set_close_write_time(fsp
, mtime
);
5239 * More insanity. W2K only closes the file if writelen > 0.
5243 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5244 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5245 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5248 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5249 "file %s\n", fsp_str_dbg(fsp
)));
5250 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5254 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5255 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5259 if(!NT_STATUS_IS_OK(close_status
)) {
5260 reply_nterror(req
, close_status
);
5264 reply_outbuf(req
, 1, 0);
5266 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5270 END_PROFILE(SMBwriteclose
);
5275 #define DBGC_CLASS DBGC_LOCKING
5277 /****************************************************************************
5279 ****************************************************************************/
5281 void reply_lock(struct smb_request
*req
)
5283 connection_struct
*conn
= req
->conn
;
5284 uint64_t count
,offset
;
5287 struct byte_range_lock
*br_lck
= NULL
;
5289 START_PROFILE(SMBlock
);
5292 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5293 END_PROFILE(SMBlock
);
5297 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5299 if (!check_fsp(conn
, req
, fsp
)) {
5300 END_PROFILE(SMBlock
);
5304 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5305 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5307 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5308 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5310 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5312 (uint64_t)req
->smbpid
,
5317 False
, /* Non-blocking lock. */
5321 TALLOC_FREE(br_lck
);
5323 if (NT_STATUS_V(status
)) {
5324 reply_nterror(req
, status
);
5325 END_PROFILE(SMBlock
);
5329 reply_outbuf(req
, 0, 0);
5331 END_PROFILE(SMBlock
);
5335 /****************************************************************************
5337 ****************************************************************************/
5339 void reply_unlock(struct smb_request
*req
)
5341 connection_struct
*conn
= req
->conn
;
5342 uint64_t count
,offset
;
5346 START_PROFILE(SMBunlock
);
5349 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5350 END_PROFILE(SMBunlock
);
5354 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5356 if (!check_fsp(conn
, req
, fsp
)) {
5357 END_PROFILE(SMBunlock
);
5361 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5362 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5364 status
= do_unlock(req
->sconn
->msg_ctx
,
5366 (uint64_t)req
->smbpid
,
5371 if (NT_STATUS_V(status
)) {
5372 reply_nterror(req
, status
);
5373 END_PROFILE(SMBunlock
);
5377 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5378 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5380 reply_outbuf(req
, 0, 0);
5382 END_PROFILE(SMBunlock
);
5387 #define DBGC_CLASS DBGC_ALL
5389 /****************************************************************************
5391 conn POINTER CAN BE NULL HERE !
5392 ****************************************************************************/
5394 void reply_tdis(struct smb_request
*req
)
5397 connection_struct
*conn
= req
->conn
;
5398 struct smbXsrv_tcon
*tcon
;
5400 START_PROFILE(SMBtdis
);
5403 DEBUG(4,("Invalid connection in tdis\n"));
5404 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5405 END_PROFILE(SMBtdis
);
5413 * TODO: cancel all outstanding requests on the tcon
5415 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5416 if (!NT_STATUS_IS_OK(status
)) {
5417 DEBUG(0, ("reply_tdis: "
5418 "smbXsrv_tcon_disconnect() failed: %s\n",
5419 nt_errstr(status
)));
5421 * If we hit this case, there is something completely
5422 * wrong, so we better disconnect the transport connection.
5424 END_PROFILE(SMBtdis
);
5425 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5431 reply_outbuf(req
, 0, 0);
5432 END_PROFILE(SMBtdis
);
5436 /****************************************************************************
5438 conn POINTER CAN BE NULL HERE !
5439 ****************************************************************************/
5441 void reply_echo(struct smb_request
*req
)
5443 connection_struct
*conn
= req
->conn
;
5444 struct smb_perfcount_data local_pcd
;
5445 struct smb_perfcount_data
*cur_pcd
;
5449 START_PROFILE(SMBecho
);
5451 smb_init_perfcount_data(&local_pcd
);
5454 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5455 END_PROFILE(SMBecho
);
5459 smb_reverb
= SVAL(req
->vwv
+0, 0);
5461 reply_outbuf(req
, 1, req
->buflen
);
5463 /* copy any incoming data back out */
5464 if (req
->buflen
> 0) {
5465 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5468 if (smb_reverb
> 100) {
5469 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5473 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5475 /* this makes sure we catch the request pcd */
5476 if (seq_num
== smb_reverb
) {
5477 cur_pcd
= &req
->pcd
;
5479 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5480 cur_pcd
= &local_pcd
;
5483 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5485 show_msg((char *)req
->outbuf
);
5486 if (!srv_send_smb(req
->sconn
,
5487 (char *)req
->outbuf
,
5488 true, req
->seqnum
+1,
5489 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5491 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5494 DEBUG(3,("echo %d times\n", smb_reverb
));
5496 TALLOC_FREE(req
->outbuf
);
5498 END_PROFILE(SMBecho
);
5502 /****************************************************************************
5503 Reply to a printopen.
5504 ****************************************************************************/
5506 void reply_printopen(struct smb_request
*req
)
5508 connection_struct
*conn
= req
->conn
;
5512 START_PROFILE(SMBsplopen
);
5515 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5516 END_PROFILE(SMBsplopen
);
5520 if (!CAN_PRINT(conn
)) {
5521 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5522 END_PROFILE(SMBsplopen
);
5526 status
= file_new(req
, conn
, &fsp
);
5527 if(!NT_STATUS_IS_OK(status
)) {
5528 reply_nterror(req
, status
);
5529 END_PROFILE(SMBsplopen
);
5533 /* Open for exclusive use, write only. */
5534 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5536 if (!NT_STATUS_IS_OK(status
)) {
5537 file_free(req
, fsp
);
5538 reply_nterror(req
, status
);
5539 END_PROFILE(SMBsplopen
);
5543 reply_outbuf(req
, 1, 0);
5544 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5546 DEBUG(3,("openprint fd=%d %s\n",
5547 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5549 END_PROFILE(SMBsplopen
);
5553 /****************************************************************************
5554 Reply to a printclose.
5555 ****************************************************************************/
5557 void reply_printclose(struct smb_request
*req
)
5559 connection_struct
*conn
= req
->conn
;
5563 START_PROFILE(SMBsplclose
);
5566 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5567 END_PROFILE(SMBsplclose
);
5571 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5573 if (!check_fsp(conn
, req
, fsp
)) {
5574 END_PROFILE(SMBsplclose
);
5578 if (!CAN_PRINT(conn
)) {
5579 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5580 END_PROFILE(SMBsplclose
);
5584 DEBUG(3,("printclose fd=%d %s\n",
5585 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5587 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5589 if(!NT_STATUS_IS_OK(status
)) {
5590 reply_nterror(req
, status
);
5591 END_PROFILE(SMBsplclose
);
5595 reply_outbuf(req
, 0, 0);
5597 END_PROFILE(SMBsplclose
);
5601 /****************************************************************************
5602 Reply to a printqueue.
5603 ****************************************************************************/
5605 void reply_printqueue(struct smb_request
*req
)
5607 connection_struct
*conn
= req
->conn
;
5611 START_PROFILE(SMBsplretq
);
5614 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5615 END_PROFILE(SMBsplretq
);
5619 max_count
= SVAL(req
->vwv
+0, 0);
5620 start_index
= SVAL(req
->vwv
+1, 0);
5622 /* we used to allow the client to get the cnum wrong, but that
5623 is really quite gross and only worked when there was only
5624 one printer - I think we should now only accept it if they
5625 get it right (tridge) */
5626 if (!CAN_PRINT(conn
)) {
5627 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5628 END_PROFILE(SMBsplretq
);
5632 reply_outbuf(req
, 2, 3);
5633 SSVAL(req
->outbuf
,smb_vwv0
,0);
5634 SSVAL(req
->outbuf
,smb_vwv1
,0);
5635 SCVAL(smb_buf(req
->outbuf
),0,1);
5636 SSVAL(smb_buf(req
->outbuf
),1,0);
5638 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5639 start_index
, max_count
));
5642 TALLOC_CTX
*mem_ctx
= talloc_tos();
5645 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5646 struct rpc_pipe_client
*cli
= NULL
;
5647 struct dcerpc_binding_handle
*b
= NULL
;
5648 struct policy_handle handle
;
5649 struct spoolss_DevmodeContainer devmode_ctr
;
5650 union spoolss_JobInfo
*info
;
5652 uint32_t num_to_get
;
5656 ZERO_STRUCT(handle
);
5658 status
= rpc_pipe_open_interface(conn
,
5661 conn
->sconn
->remote_address
,
5662 conn
->sconn
->msg_ctx
,
5664 if (!NT_STATUS_IS_OK(status
)) {
5665 DEBUG(0, ("reply_printqueue: "
5666 "could not connect to spoolss: %s\n",
5667 nt_errstr(status
)));
5668 reply_nterror(req
, status
);
5671 b
= cli
->binding_handle
;
5673 ZERO_STRUCT(devmode_ctr
);
5675 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5678 SEC_FLAG_MAXIMUM_ALLOWED
,
5681 if (!NT_STATUS_IS_OK(status
)) {
5682 reply_nterror(req
, status
);
5685 if (!W_ERROR_IS_OK(werr
)) {
5686 reply_nterror(req
, werror_to_ntstatus(werr
));
5690 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5698 if (!W_ERROR_IS_OK(werr
)) {
5699 reply_nterror(req
, werror_to_ntstatus(werr
));
5703 if (max_count
> 0) {
5704 first
= start_index
;
5706 first
= start_index
+ max_count
+ 1;
5709 if (first
>= count
) {
5712 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5715 for (i
= first
; i
< num_to_get
; i
++) {
5718 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5720 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5721 info
[i
].info2
.job_id
);
5723 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5729 srv_put_dos_date2(p
, 0, qtime
);
5730 SCVAL(p
, 4, qstatus
);
5731 SSVAL(p
, 5, qrapjobid
);
5732 SIVAL(p
, 7, info
[i
].info2
.size
);
5734 srvstr_push(blob
, req
->flags2
, p
+12,
5735 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5737 if (message_push_blob(
5740 blob
, sizeof(blob
))) == -1) {
5741 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5747 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5748 SSVAL(req
->outbuf
,smb_vwv1
,
5749 (max_count
>0?first
+count
:first
-1));
5750 SCVAL(smb_buf(req
->outbuf
),0,1);
5751 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5755 DEBUG(3, ("%u entries returned in queue\n",
5759 if (b
&& is_valid_policy_hnd(&handle
)) {
5760 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5765 END_PROFILE(SMBsplretq
);
5769 /****************************************************************************
5770 Reply to a printwrite.
5771 ****************************************************************************/
5773 void reply_printwrite(struct smb_request
*req
)
5775 connection_struct
*conn
= req
->conn
;
5780 START_PROFILE(SMBsplwr
);
5783 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5784 END_PROFILE(SMBsplwr
);
5788 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5790 if (!check_fsp(conn
, req
, fsp
)) {
5791 END_PROFILE(SMBsplwr
);
5795 if (!fsp
->print_file
) {
5796 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5797 END_PROFILE(SMBsplwr
);
5801 if (!CHECK_WRITE(fsp
)) {
5802 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5803 END_PROFILE(SMBsplwr
);
5807 numtowrite
= SVAL(req
->buf
, 1);
5809 if (req
->buflen
< numtowrite
+ 3) {
5810 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5811 END_PROFILE(SMBsplwr
);
5815 data
= (const char *)req
->buf
+ 3;
5817 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
5818 reply_nterror(req
, map_nt_error_from_unix(errno
));
5819 END_PROFILE(SMBsplwr
);
5823 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
5825 END_PROFILE(SMBsplwr
);
5829 /****************************************************************************
5831 ****************************************************************************/
5833 void reply_mkdir(struct smb_request
*req
)
5835 connection_struct
*conn
= req
->conn
;
5836 struct smb_filename
*smb_dname
= NULL
;
5837 char *directory
= NULL
;
5839 TALLOC_CTX
*ctx
= talloc_tos();
5841 START_PROFILE(SMBmkdir
);
5843 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5844 STR_TERMINATE
, &status
);
5845 if (!NT_STATUS_IS_OK(status
)) {
5846 reply_nterror(req
, status
);
5850 status
= filename_convert(ctx
, conn
,
5851 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5853 UCF_PREP_CREATEFILE
,
5856 if (!NT_STATUS_IS_OK(status
)) {
5857 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5858 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5859 ERRSRV
, ERRbadpath
);
5862 reply_nterror(req
, status
);
5866 status
= create_directory(conn
, req
, smb_dname
);
5868 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5870 if (!NT_STATUS_IS_OK(status
)) {
5872 if (!use_nt_status()
5873 && NT_STATUS_EQUAL(status
,
5874 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5876 * Yes, in the DOS error code case we get a
5877 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5878 * samba4 torture test.
5880 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5883 reply_nterror(req
, status
);
5887 reply_outbuf(req
, 0, 0);
5889 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5891 TALLOC_FREE(smb_dname
);
5892 END_PROFILE(SMBmkdir
);
5896 /****************************************************************************
5898 ****************************************************************************/
5900 void reply_rmdir(struct smb_request
*req
)
5902 connection_struct
*conn
= req
->conn
;
5903 struct smb_filename
*smb_dname
= NULL
;
5904 char *directory
= NULL
;
5906 TALLOC_CTX
*ctx
= talloc_tos();
5907 files_struct
*fsp
= NULL
;
5909 struct smbd_server_connection
*sconn
= req
->sconn
;
5911 START_PROFILE(SMBrmdir
);
5913 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5914 STR_TERMINATE
, &status
);
5915 if (!NT_STATUS_IS_OK(status
)) {
5916 reply_nterror(req
, status
);
5920 status
= filename_convert(ctx
, conn
,
5921 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5926 if (!NT_STATUS_IS_OK(status
)) {
5927 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5928 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5929 ERRSRV
, ERRbadpath
);
5932 reply_nterror(req
, status
);
5936 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5937 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5941 status
= SMB_VFS_CREATE_FILE(
5944 0, /* root_dir_fid */
5945 smb_dname
, /* fname */
5946 DELETE_ACCESS
, /* access_mask */
5947 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5949 FILE_OPEN
, /* create_disposition*/
5950 FILE_DIRECTORY_FILE
, /* create_options */
5951 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5952 0, /* oplock_request */
5953 0, /* allocation_size */
5954 0, /* private_flags */
5960 if (!NT_STATUS_IS_OK(status
)) {
5961 if (open_was_deferred(req
->sconn
, req
->mid
)) {
5962 /* We have re-scheduled this call. */
5965 reply_nterror(req
, status
);
5969 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5970 if (!NT_STATUS_IS_OK(status
)) {
5971 close_file(req
, fsp
, ERROR_CLOSE
);
5972 reply_nterror(req
, status
);
5976 if (!set_delete_on_close(fsp
, true,
5977 conn
->session_info
->security_token
,
5978 conn
->session_info
->unix_token
)) {
5979 close_file(req
, fsp
, ERROR_CLOSE
);
5980 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5984 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5985 if (!NT_STATUS_IS_OK(status
)) {
5986 reply_nterror(req
, status
);
5988 reply_outbuf(req
, 0, 0);
5991 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5993 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5995 TALLOC_FREE(smb_dname
);
5996 END_PROFILE(SMBrmdir
);
6000 /*******************************************************************
6001 Resolve wildcards in a filename rename.
6002 ********************************************************************/
6004 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6009 char *name2_copy
= NULL
;
6014 char *p
,*p2
, *pname1
, *pname2
;
6016 name2_copy
= talloc_strdup(ctx
, name2
);
6021 pname1
= strrchr_m(name1
,'/');
6022 pname2
= strrchr_m(name2_copy
,'/');
6024 if (!pname1
|| !pname2
) {
6028 /* Truncate the copy of name2 at the last '/' */
6031 /* Now go past the '/' */
6035 root1
= talloc_strdup(ctx
, pname1
);
6036 root2
= talloc_strdup(ctx
, pname2
);
6038 if (!root1
|| !root2
) {
6042 p
= strrchr_m(root1
,'.');
6045 ext1
= talloc_strdup(ctx
, p
+1);
6047 ext1
= talloc_strdup(ctx
, "");
6049 p
= strrchr_m(root2
,'.');
6052 ext2
= talloc_strdup(ctx
, p
+1);
6054 ext2
= talloc_strdup(ctx
, "");
6057 if (!ext1
|| !ext2
) {
6065 /* Hmmm. Should this be mb-aware ? */
6068 } else if (*p2
== '*') {
6070 root2
= talloc_asprintf(ctx
, "%s%s",
6089 /* Hmmm. Should this be mb-aware ? */
6092 } else if (*p2
== '*') {
6094 ext2
= talloc_asprintf(ctx
, "%s%s",
6110 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6115 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6127 /****************************************************************************
6128 Ensure open files have their names updated. Updated to notify other smbd's
6130 ****************************************************************************/
6132 static void rename_open_files(connection_struct
*conn
,
6133 struct share_mode_lock
*lck
,
6135 uint32_t orig_name_hash
,
6136 const struct smb_filename
*smb_fname_dst
)
6139 bool did_rename
= False
;
6141 uint32_t new_name_hash
= 0;
6143 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6144 fsp
= file_find_di_next(fsp
)) {
6145 /* fsp_name is a relative path under the fsp. To change this for other
6146 sharepaths we need to manipulate relative paths. */
6147 /* TODO - create the absolute path and manipulate the newname
6148 relative to the sharepath. */
6149 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6152 if (fsp
->name_hash
!= orig_name_hash
) {
6155 DEBUG(10, ("rename_open_files: renaming file %s "
6156 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6157 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6158 smb_fname_str_dbg(smb_fname_dst
)));
6160 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6161 if (NT_STATUS_IS_OK(status
)) {
6163 new_name_hash
= fsp
->name_hash
;
6168 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6169 "for %s\n", file_id_string_tos(&id
),
6170 smb_fname_str_dbg(smb_fname_dst
)));
6173 /* Send messages to all smbd's (not ourself) that the name has changed. */
6174 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6175 orig_name_hash
, new_name_hash
,
6180 /****************************************************************************
6181 We need to check if the source path is a parent directory of the destination
6182 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6183 refuse the rename with a sharing violation. Under UNIX the above call can
6184 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6185 probably need to check that the client is a Windows one before disallowing
6186 this as a UNIX client (one with UNIX extensions) can know the source is a
6187 symlink and make this decision intelligently. Found by an excellent bug
6188 report from <AndyLiebman@aol.com>.
6189 ****************************************************************************/
6191 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6192 const struct smb_filename
*smb_fname_dst
)
6194 const char *psrc
= smb_fname_src
->base_name
;
6195 const char *pdst
= smb_fname_dst
->base_name
;
6198 if (psrc
[0] == '.' && psrc
[1] == '/') {
6201 if (pdst
[0] == '.' && pdst
[1] == '/') {
6204 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6207 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6211 * Do the notify calls from a rename
6214 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6215 const struct smb_filename
*smb_fname_src
,
6216 const struct smb_filename
*smb_fname_dst
)
6218 char *parent_dir_src
= NULL
;
6219 char *parent_dir_dst
= NULL
;
6222 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6223 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6225 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6226 &parent_dir_src
, NULL
) ||
6227 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6228 &parent_dir_dst
, NULL
)) {
6232 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6233 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6234 smb_fname_src
->base_name
);
6235 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6236 smb_fname_dst
->base_name
);
6239 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6240 smb_fname_src
->base_name
);
6241 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6242 smb_fname_dst
->base_name
);
6245 /* this is a strange one. w2k3 gives an additional event for
6246 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6247 files, but not directories */
6249 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6250 FILE_NOTIFY_CHANGE_ATTRIBUTES
6251 |FILE_NOTIFY_CHANGE_CREATION
,
6252 smb_fname_dst
->base_name
);
6255 TALLOC_FREE(parent_dir_src
);
6256 TALLOC_FREE(parent_dir_dst
);
6259 /****************************************************************************
6260 Returns an error if the parent directory for a filename is open in an
6262 ****************************************************************************/
6264 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6265 const struct smb_filename
*smb_fname_dst_in
)
6267 char *parent_dir
= NULL
;
6268 struct smb_filename smb_fname_parent
;
6270 files_struct
*fsp
= NULL
;
6273 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6274 &parent_dir
, NULL
)) {
6275 return NT_STATUS_NO_MEMORY
;
6277 ZERO_STRUCT(smb_fname_parent
);
6278 smb_fname_parent
.base_name
= parent_dir
;
6280 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6282 return map_nt_error_from_unix(errno
);
6286 * We're only checking on this smbd here, mostly good
6287 * enough.. and will pass tests.
6290 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6291 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6292 fsp
= file_find_di_next(fsp
)) {
6293 if (fsp
->access_mask
& DELETE_ACCESS
) {
6294 return NT_STATUS_SHARING_VIOLATION
;
6297 return NT_STATUS_OK
;
6300 /****************************************************************************
6301 Rename an open file - given an fsp.
6302 ****************************************************************************/
6304 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6306 const struct smb_filename
*smb_fname_dst_in
,
6308 bool replace_if_exists
)
6310 TALLOC_CTX
*ctx
= talloc_tos();
6311 struct smb_filename
*smb_fname_dst
= NULL
;
6312 NTSTATUS status
= NT_STATUS_OK
;
6313 struct share_mode_lock
*lck
= NULL
;
6314 bool dst_exists
, old_is_stream
, new_is_stream
;
6316 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6317 if (!NT_STATUS_IS_OK(status
)) {
6321 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6322 if (!NT_STATUS_IS_OK(status
)) {
6326 /* Make a copy of the dst smb_fname structs */
6328 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6329 if (smb_fname_dst
== NULL
) {
6330 status
= NT_STATUS_NO_MEMORY
;
6335 * Check for special case with case preserving and not
6336 * case sensitive. If the old last component differs from the original
6337 * last component only by case, then we should allow
6338 * the rename (user is trying to change the case of the
6341 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6342 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6343 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6345 char *fname_dst_lcomp_base_mod
= NULL
;
6346 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6349 * Get the last component of the destination name.
6351 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6353 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6355 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6357 if (!fname_dst_lcomp_base_mod
) {
6358 status
= NT_STATUS_NO_MEMORY
;
6363 * Create an smb_filename struct using the original last
6364 * component of the destination.
6366 smb_fname_orig_lcomp
= synthetic_smb_fname_split(
6367 ctx
, smb_fname_dst
->original_lcomp
, NULL
);
6368 if (smb_fname_orig_lcomp
== NULL
) {
6369 status
= NT_STATUS_NO_MEMORY
;
6370 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6374 /* If the base names only differ by case, use original. */
6375 if(!strcsequal(fname_dst_lcomp_base_mod
,
6376 smb_fname_orig_lcomp
->base_name
)) {
6379 * Replace the modified last component with the
6383 *last_slash
= '\0'; /* Truncate at the '/' */
6384 tmp
= talloc_asprintf(smb_fname_dst
,
6386 smb_fname_dst
->base_name
,
6387 smb_fname_orig_lcomp
->base_name
);
6389 tmp
= talloc_asprintf(smb_fname_dst
,
6391 smb_fname_orig_lcomp
->base_name
);
6394 status
= NT_STATUS_NO_MEMORY
;
6395 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6396 TALLOC_FREE(smb_fname_orig_lcomp
);
6399 TALLOC_FREE(smb_fname_dst
->base_name
);
6400 smb_fname_dst
->base_name
= tmp
;
6403 /* If the stream_names only differ by case, use original. */
6404 if(!strcsequal(smb_fname_dst
->stream_name
,
6405 smb_fname_orig_lcomp
->stream_name
)) {
6407 /* Use the original stream. */
6408 tmp
= talloc_strdup(smb_fname_dst
,
6409 smb_fname_orig_lcomp
->stream_name
);
6411 status
= NT_STATUS_NO_MEMORY
;
6412 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6413 TALLOC_FREE(smb_fname_orig_lcomp
);
6416 TALLOC_FREE(smb_fname_dst
->stream_name
);
6417 smb_fname_dst
->stream_name
= tmp
;
6419 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6420 TALLOC_FREE(smb_fname_orig_lcomp
);
6424 * If the src and dest names are identical - including case,
6425 * don't do the rename, just return success.
6428 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6429 strcsequal(fsp
->fsp_name
->stream_name
,
6430 smb_fname_dst
->stream_name
)) {
6431 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6432 "- returning success\n",
6433 smb_fname_str_dbg(smb_fname_dst
)));
6434 status
= NT_STATUS_OK
;
6438 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6439 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6441 /* Return the correct error code if both names aren't streams. */
6442 if (!old_is_stream
&& new_is_stream
) {
6443 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6447 if (old_is_stream
&& !new_is_stream
) {
6448 status
= NT_STATUS_INVALID_PARAMETER
;
6452 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6454 if(!replace_if_exists
&& dst_exists
) {
6455 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6456 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6457 smb_fname_str_dbg(smb_fname_dst
)));
6458 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6463 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6464 &smb_fname_dst
->st
);
6465 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6467 /* The file can be open when renaming a stream */
6468 if (dst_fsp
&& !new_is_stream
) {
6469 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6470 status
= NT_STATUS_ACCESS_DENIED
;
6475 /* Ensure we have a valid stat struct for the source. */
6476 status
= vfs_stat_fsp(fsp
);
6477 if (!NT_STATUS_IS_OK(status
)) {
6481 status
= can_rename(conn
, fsp
, attrs
);
6483 if (!NT_STATUS_IS_OK(status
)) {
6484 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6485 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6486 smb_fname_str_dbg(smb_fname_dst
)));
6487 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6488 status
= NT_STATUS_ACCESS_DENIED
;
6492 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6493 status
= NT_STATUS_ACCESS_DENIED
;
6496 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6499 * We have the file open ourselves, so not being able to get the
6500 * corresponding share mode lock is a fatal error.
6503 SMB_ASSERT(lck
!= NULL
);
6505 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6506 uint32 create_options
= fsp
->fh
->private_options
;
6508 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6509 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6510 smb_fname_str_dbg(smb_fname_dst
)));
6512 if (!fsp
->is_directory
&&
6513 !lp_posix_pathnames() &&
6514 (lp_map_archive(SNUM(conn
)) ||
6515 lp_store_dos_attributes(SNUM(conn
)))) {
6516 /* We must set the archive bit on the newly
6518 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6519 uint32_t old_dosmode
= dos_mode(conn
,
6521 file_set_dosmode(conn
,
6523 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6529 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6532 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6536 * A rename acts as a new file create w.r.t. allowing an initial delete
6537 * on close, probably because in Windows there is a new handle to the
6538 * new file. If initial delete on close was requested but not
6539 * originally set, we need to set it here. This is probably not 100% correct,
6540 * but will work for the CIFSFS client which in non-posix mode
6541 * depends on these semantics. JRA.
6544 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6545 status
= can_set_delete_on_close(fsp
, 0);
6547 if (NT_STATUS_IS_OK(status
)) {
6548 /* Note that here we set the *inital* delete on close flag,
6549 * not the regular one. The magic gets handled in close. */
6550 fsp
->initial_delete_on_close
= True
;
6554 status
= NT_STATUS_OK
;
6560 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6561 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6563 status
= map_nt_error_from_unix(errno
);
6566 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6567 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6568 smb_fname_str_dbg(smb_fname_dst
)));
6571 TALLOC_FREE(smb_fname_dst
);
6576 /****************************************************************************
6577 The guts of the rename command, split out so it may be called by the NT SMB
6579 ****************************************************************************/
6581 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6582 connection_struct
*conn
,
6583 struct smb_request
*req
,
6584 struct smb_filename
*smb_fname_src
,
6585 struct smb_filename
*smb_fname_dst
,
6587 bool replace_if_exists
,
6590 uint32_t access_mask
)
6592 char *fname_src_dir
= NULL
;
6593 char *fname_src_mask
= NULL
;
6595 NTSTATUS status
= NT_STATUS_OK
;
6596 struct smb_Dir
*dir_hnd
= NULL
;
6597 const char *dname
= NULL
;
6598 char *talloced
= NULL
;
6600 int create_options
= 0;
6601 bool posix_pathnames
= lp_posix_pathnames();
6605 * Split the old name into directory and last component
6606 * strings. Note that unix_convert may have stripped off a
6607 * leading ./ from both name and newname if the rename is
6608 * at the root of the share. We need to make sure either both
6609 * name and newname contain a / character or neither of them do
6610 * as this is checked in resolve_wildcards().
6613 /* Split up the directory from the filename/mask. */
6614 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6615 &fname_src_dir
, &fname_src_mask
);
6616 if (!NT_STATUS_IS_OK(status
)) {
6617 status
= NT_STATUS_NO_MEMORY
;
6622 * We should only check the mangled cache
6623 * here if unix_convert failed. This means
6624 * that the path in 'mask' doesn't exist
6625 * on the file system and so we need to look
6626 * for a possible mangle. This patch from
6627 * Tine Smukavec <valentin.smukavec@hermes.si>.
6630 if (!VALID_STAT(smb_fname_src
->st
) &&
6631 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6632 char *new_mask
= NULL
;
6633 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6636 TALLOC_FREE(fname_src_mask
);
6637 fname_src_mask
= new_mask
;
6641 if (!src_has_wild
) {
6645 * Only one file needs to be renamed. Append the mask back
6646 * onto the directory.
6648 TALLOC_FREE(smb_fname_src
->base_name
);
6649 if (ISDOT(fname_src_dir
)) {
6650 /* Ensure we use canonical names on open. */
6651 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6655 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6660 if (!smb_fname_src
->base_name
) {
6661 status
= NT_STATUS_NO_MEMORY
;
6665 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6666 "case_preserve = %d, short case preserve = %d, "
6667 "directory = %s, newname = %s, "
6668 "last_component_dest = %s\n",
6669 conn
->case_sensitive
, conn
->case_preserve
,
6670 conn
->short_case_preserve
,
6671 smb_fname_str_dbg(smb_fname_src
),
6672 smb_fname_str_dbg(smb_fname_dst
),
6673 smb_fname_dst
->original_lcomp
));
6675 /* The dest name still may have wildcards. */
6676 if (dest_has_wild
) {
6677 char *fname_dst_mod
= NULL
;
6678 if (!resolve_wildcards(smb_fname_dst
,
6679 smb_fname_src
->base_name
,
6680 smb_fname_dst
->base_name
,
6682 DEBUG(6, ("rename_internals: resolve_wildcards "
6684 smb_fname_src
->base_name
,
6685 smb_fname_dst
->base_name
));
6686 status
= NT_STATUS_NO_MEMORY
;
6689 TALLOC_FREE(smb_fname_dst
->base_name
);
6690 smb_fname_dst
->base_name
= fname_dst_mod
;
6693 ZERO_STRUCT(smb_fname_src
->st
);
6694 if (posix_pathnames
) {
6695 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
6697 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
6700 status
= map_nt_error_from_unix_common(errno
);
6704 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6705 create_options
|= FILE_DIRECTORY_FILE
;
6708 status
= SMB_VFS_CREATE_FILE(
6711 0, /* root_dir_fid */
6712 smb_fname_src
, /* fname */
6713 access_mask
, /* access_mask */
6714 (FILE_SHARE_READ
| /* share_access */
6716 FILE_OPEN
, /* create_disposition*/
6717 create_options
, /* create_options */
6718 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6719 0, /* oplock_request */
6720 0, /* allocation_size */
6721 0, /* private_flags */
6727 if (!NT_STATUS_IS_OK(status
)) {
6728 DEBUG(3, ("Could not open rename source %s: %s\n",
6729 smb_fname_str_dbg(smb_fname_src
),
6730 nt_errstr(status
)));
6734 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6735 attrs
, replace_if_exists
);
6737 close_file(req
, fsp
, NORMAL_CLOSE
);
6739 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6740 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6741 smb_fname_str_dbg(smb_fname_dst
)));
6747 * Wildcards - process each file that matches.
6749 if (strequal(fname_src_mask
, "????????.???")) {
6750 TALLOC_FREE(fname_src_mask
);
6751 fname_src_mask
= talloc_strdup(ctx
, "*");
6752 if (!fname_src_mask
) {
6753 status
= NT_STATUS_NO_MEMORY
;
6758 status
= check_name(conn
, fname_src_dir
);
6759 if (!NT_STATUS_IS_OK(status
)) {
6763 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6765 if (dir_hnd
== NULL
) {
6766 status
= map_nt_error_from_unix(errno
);
6770 status
= NT_STATUS_NO_SUCH_FILE
;
6772 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6773 * - gentest fix. JRA
6776 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6778 files_struct
*fsp
= NULL
;
6779 char *destname
= NULL
;
6780 bool sysdir_entry
= False
;
6782 /* Quick check for "." and ".." */
6783 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6784 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6785 sysdir_entry
= True
;
6787 TALLOC_FREE(talloced
);
6792 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6793 &smb_fname_src
->st
, false)) {
6794 TALLOC_FREE(talloced
);
6798 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6799 TALLOC_FREE(talloced
);
6804 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6808 TALLOC_FREE(smb_fname_src
->base_name
);
6809 if (ISDOT(fname_src_dir
)) {
6810 /* Ensure we use canonical names on open. */
6811 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6815 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6820 if (!smb_fname_src
->base_name
) {
6821 status
= NT_STATUS_NO_MEMORY
;
6825 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6826 smb_fname_dst
->base_name
,
6828 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6829 smb_fname_src
->base_name
, destname
));
6830 TALLOC_FREE(talloced
);
6834 status
= NT_STATUS_NO_MEMORY
;
6838 TALLOC_FREE(smb_fname_dst
->base_name
);
6839 smb_fname_dst
->base_name
= destname
;
6841 ZERO_STRUCT(smb_fname_src
->st
);
6842 if (posix_pathnames
) {
6843 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6845 SMB_VFS_STAT(conn
, smb_fname_src
);
6850 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6851 create_options
|= FILE_DIRECTORY_FILE
;
6854 status
= SMB_VFS_CREATE_FILE(
6857 0, /* root_dir_fid */
6858 smb_fname_src
, /* fname */
6859 access_mask
, /* access_mask */
6860 (FILE_SHARE_READ
| /* share_access */
6862 FILE_OPEN
, /* create_disposition*/
6863 create_options
, /* create_options */
6864 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6865 0, /* oplock_request */
6866 0, /* allocation_size */
6867 0, /* private_flags */
6873 if (!NT_STATUS_IS_OK(status
)) {
6874 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6875 "returned %s rename %s -> %s\n",
6877 smb_fname_str_dbg(smb_fname_src
),
6878 smb_fname_str_dbg(smb_fname_dst
)));
6882 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6884 if (!smb_fname_dst
->original_lcomp
) {
6885 status
= NT_STATUS_NO_MEMORY
;
6889 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6890 attrs
, replace_if_exists
);
6892 close_file(req
, fsp
, NORMAL_CLOSE
);
6894 if (!NT_STATUS_IS_OK(status
)) {
6895 DEBUG(3, ("rename_internals_fsp returned %s for "
6896 "rename %s -> %s\n", nt_errstr(status
),
6897 smb_fname_str_dbg(smb_fname_src
),
6898 smb_fname_str_dbg(smb_fname_dst
)));
6904 DEBUG(3,("rename_internals: doing rename on %s -> "
6905 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6906 smb_fname_str_dbg(smb_fname_src
)));
6907 TALLOC_FREE(talloced
);
6909 TALLOC_FREE(dir_hnd
);
6911 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6912 status
= map_nt_error_from_unix(errno
);
6916 TALLOC_FREE(talloced
);
6917 TALLOC_FREE(fname_src_dir
);
6918 TALLOC_FREE(fname_src_mask
);
6922 /****************************************************************************
6924 ****************************************************************************/
6926 void reply_mv(struct smb_request
*req
)
6928 connection_struct
*conn
= req
->conn
;
6930 char *newname
= NULL
;
6934 bool src_has_wcard
= False
;
6935 bool dest_has_wcard
= False
;
6936 TALLOC_CTX
*ctx
= talloc_tos();
6937 struct smb_filename
*smb_fname_src
= NULL
;
6938 struct smb_filename
*smb_fname_dst
= NULL
;
6939 uint32_t src_ucf_flags
= lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP
: UCF_COND_ALLOW_WCARD_LCOMP
;
6940 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
| (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP
);
6941 bool stream_rename
= false;
6943 START_PROFILE(SMBmv
);
6946 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6950 attrs
= SVAL(req
->vwv
+0, 0);
6952 p
= (const char *)req
->buf
+ 1;
6953 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6954 &status
, &src_has_wcard
);
6955 if (!NT_STATUS_IS_OK(status
)) {
6956 reply_nterror(req
, status
);
6960 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6961 &status
, &dest_has_wcard
);
6962 if (!NT_STATUS_IS_OK(status
)) {
6963 reply_nterror(req
, status
);
6967 if (!lp_posix_pathnames()) {
6968 /* The newname must begin with a ':' if the
6969 name contains a ':'. */
6970 if (strchr_m(name
, ':')) {
6971 if (newname
[0] != ':') {
6972 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6975 stream_rename
= true;
6979 status
= filename_convert(ctx
,
6981 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6987 if (!NT_STATUS_IS_OK(status
)) {
6988 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6989 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6990 ERRSRV
, ERRbadpath
);
6993 reply_nterror(req
, status
);
6997 status
= filename_convert(ctx
,
6999 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7005 if (!NT_STATUS_IS_OK(status
)) {
7006 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7007 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7008 ERRSRV
, ERRbadpath
);
7011 reply_nterror(req
, status
);
7015 if (stream_rename
) {
7016 /* smb_fname_dst->base_name must be the same as
7017 smb_fname_src->base_name. */
7018 TALLOC_FREE(smb_fname_dst
->base_name
);
7019 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7020 smb_fname_src
->base_name
);
7021 if (!smb_fname_dst
->base_name
) {
7022 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7027 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7028 smb_fname_str_dbg(smb_fname_dst
)));
7030 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7031 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7033 if (!NT_STATUS_IS_OK(status
)) {
7034 if (open_was_deferred(req
->sconn
, req
->mid
)) {
7035 /* We have re-scheduled this call. */
7038 reply_nterror(req
, status
);
7042 reply_outbuf(req
, 0, 0);
7044 TALLOC_FREE(smb_fname_src
);
7045 TALLOC_FREE(smb_fname_dst
);
7050 /*******************************************************************
7051 Copy a file as part of a reply_copy.
7052 ******************************************************************/
7055 * TODO: check error codes on all callers
7058 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7059 connection_struct
*conn
,
7060 struct smb_filename
*smb_fname_src
,
7061 struct smb_filename
*smb_fname_dst
,
7064 bool target_is_directory
)
7066 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7068 files_struct
*fsp1
,*fsp2
;
7070 uint32 new_create_disposition
;
7074 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7075 if (smb_fname_dst_tmp
== NULL
) {
7076 return NT_STATUS_NO_MEMORY
;
7080 * If the target is a directory, extract the last component from the
7081 * src filename and append it to the dst filename
7083 if (target_is_directory
) {
7086 /* dest/target can't be a stream if it's a directory. */
7087 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7089 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7093 p
= smb_fname_src
->base_name
;
7095 smb_fname_dst_tmp
->base_name
=
7096 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7098 if (!smb_fname_dst_tmp
->base_name
) {
7099 status
= NT_STATUS_NO_MEMORY
;
7104 status
= vfs_file_exist(conn
, smb_fname_src
);
7105 if (!NT_STATUS_IS_OK(status
)) {
7109 if (!target_is_directory
&& count
) {
7110 new_create_disposition
= FILE_OPEN
;
7112 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7115 &new_create_disposition
,
7118 status
= NT_STATUS_INVALID_PARAMETER
;
7123 /* Open the src file for reading. */
7124 status
= SMB_VFS_CREATE_FILE(
7127 0, /* root_dir_fid */
7128 smb_fname_src
, /* fname */
7129 FILE_GENERIC_READ
, /* access_mask */
7130 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7131 FILE_OPEN
, /* create_disposition*/
7132 0, /* create_options */
7133 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7134 INTERNAL_OPEN_ONLY
, /* oplock_request */
7135 0, /* allocation_size */
7136 0, /* private_flags */
7142 if (!NT_STATUS_IS_OK(status
)) {
7146 dosattrs
= dos_mode(conn
, smb_fname_src
);
7148 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7149 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7152 /* Open the dst file for writing. */
7153 status
= SMB_VFS_CREATE_FILE(
7156 0, /* root_dir_fid */
7157 smb_fname_dst
, /* fname */
7158 FILE_GENERIC_WRITE
, /* access_mask */
7159 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7160 new_create_disposition
, /* create_disposition*/
7161 0, /* create_options */
7162 dosattrs
, /* file_attributes */
7163 INTERNAL_OPEN_ONLY
, /* oplock_request */
7164 0, /* allocation_size */
7165 0, /* private_flags */
7171 if (!NT_STATUS_IS_OK(status
)) {
7172 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7176 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7177 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7179 DEBUG(0, ("error - vfs lseek returned error %s\n",
7181 status
= map_nt_error_from_unix(errno
);
7182 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7183 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7188 /* Do the actual copy. */
7189 if (smb_fname_src
->st
.st_ex_size
) {
7190 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7195 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7197 /* Ensure the modtime is set correctly on the destination file. */
7198 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7201 * As we are opening fsp1 read-only we only expect
7202 * an error on close on fsp2 if we are out of space.
7203 * Thus we don't look at the error return from the
7206 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7208 if (!NT_STATUS_IS_OK(status
)) {
7212 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7213 status
= NT_STATUS_DISK_FULL
;
7217 status
= NT_STATUS_OK
;
7220 TALLOC_FREE(smb_fname_dst_tmp
);
7224 /****************************************************************************
7225 Reply to a file copy.
7226 ****************************************************************************/
7228 void reply_copy(struct smb_request
*req
)
7230 connection_struct
*conn
= req
->conn
;
7231 struct smb_filename
*smb_fname_src
= NULL
;
7232 struct smb_filename
*smb_fname_dst
= NULL
;
7233 char *fname_src
= NULL
;
7234 char *fname_dst
= NULL
;
7235 char *fname_src_mask
= NULL
;
7236 char *fname_src_dir
= NULL
;
7239 int error
= ERRnoaccess
;
7243 bool target_is_directory
=False
;
7244 bool source_has_wild
= False
;
7245 bool dest_has_wild
= False
;
7247 TALLOC_CTX
*ctx
= talloc_tos();
7249 START_PROFILE(SMBcopy
);
7252 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7256 tid2
= SVAL(req
->vwv
+0, 0);
7257 ofun
= SVAL(req
->vwv
+1, 0);
7258 flags
= SVAL(req
->vwv
+2, 0);
7260 p
= (const char *)req
->buf
;
7261 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7262 &status
, &source_has_wild
);
7263 if (!NT_STATUS_IS_OK(status
)) {
7264 reply_nterror(req
, status
);
7267 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7268 &status
, &dest_has_wild
);
7269 if (!NT_STATUS_IS_OK(status
)) {
7270 reply_nterror(req
, status
);
7274 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7276 if (tid2
!= conn
->cnum
) {
7277 /* can't currently handle inter share copies XXXX */
7278 DEBUG(3,("Rejecting inter-share copy\n"));
7279 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7283 status
= filename_convert(ctx
, conn
,
7284 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7286 UCF_COND_ALLOW_WCARD_LCOMP
,
7289 if (!NT_STATUS_IS_OK(status
)) {
7290 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7291 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7292 ERRSRV
, ERRbadpath
);
7295 reply_nterror(req
, status
);
7299 status
= filename_convert(ctx
, conn
,
7300 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7302 UCF_COND_ALLOW_WCARD_LCOMP
,
7305 if (!NT_STATUS_IS_OK(status
)) {
7306 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7307 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7308 ERRSRV
, ERRbadpath
);
7311 reply_nterror(req
, status
);
7315 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7317 if ((flags
&1) && target_is_directory
) {
7318 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7322 if ((flags
&2) && !target_is_directory
) {
7323 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7327 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7328 /* wants a tree copy! XXXX */
7329 DEBUG(3,("Rejecting tree copy\n"));
7330 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7334 /* Split up the directory from the filename/mask. */
7335 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7336 &fname_src_dir
, &fname_src_mask
);
7337 if (!NT_STATUS_IS_OK(status
)) {
7338 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7343 * We should only check the mangled cache
7344 * here if unix_convert failed. This means
7345 * that the path in 'mask' doesn't exist
7346 * on the file system and so we need to look
7347 * for a possible mangle. This patch from
7348 * Tine Smukavec <valentin.smukavec@hermes.si>.
7350 if (!VALID_STAT(smb_fname_src
->st
) &&
7351 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7352 char *new_mask
= NULL
;
7353 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7354 &new_mask
, conn
->params
);
7356 /* Use demangled name if one was successfully found. */
7358 TALLOC_FREE(fname_src_mask
);
7359 fname_src_mask
= new_mask
;
7363 if (!source_has_wild
) {
7366 * Only one file needs to be copied. Append the mask back onto
7369 TALLOC_FREE(smb_fname_src
->base_name
);
7370 if (ISDOT(fname_src_dir
)) {
7371 /* Ensure we use canonical names on open. */
7372 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7376 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7381 if (!smb_fname_src
->base_name
) {
7382 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7386 if (dest_has_wild
) {
7387 char *fname_dst_mod
= NULL
;
7388 if (!resolve_wildcards(smb_fname_dst
,
7389 smb_fname_src
->base_name
,
7390 smb_fname_dst
->base_name
,
7392 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7395 TALLOC_FREE(smb_fname_dst
->base_name
);
7396 smb_fname_dst
->base_name
= fname_dst_mod
;
7399 status
= check_name(conn
, smb_fname_src
->base_name
);
7400 if (!NT_STATUS_IS_OK(status
)) {
7401 reply_nterror(req
, status
);
7405 status
= check_name(conn
, smb_fname_dst
->base_name
);
7406 if (!NT_STATUS_IS_OK(status
)) {
7407 reply_nterror(req
, status
);
7411 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7412 ofun
, count
, target_is_directory
);
7414 if(!NT_STATUS_IS_OK(status
)) {
7415 reply_nterror(req
, status
);
7421 struct smb_Dir
*dir_hnd
= NULL
;
7422 const char *dname
= NULL
;
7423 char *talloced
= NULL
;
7427 * There is a wildcard that requires us to actually read the
7428 * src dir and copy each file matching the mask to the dst.
7429 * Right now streams won't be copied, but this could
7430 * presumably be added with a nested loop for reach dir entry.
7432 SMB_ASSERT(!smb_fname_src
->stream_name
);
7433 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7435 smb_fname_src
->stream_name
= NULL
;
7436 smb_fname_dst
->stream_name
= NULL
;
7438 if (strequal(fname_src_mask
,"????????.???")) {
7439 TALLOC_FREE(fname_src_mask
);
7440 fname_src_mask
= talloc_strdup(ctx
, "*");
7441 if (!fname_src_mask
) {
7442 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7447 status
= check_name(conn
, fname_src_dir
);
7448 if (!NT_STATUS_IS_OK(status
)) {
7449 reply_nterror(req
, status
);
7453 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7454 if (dir_hnd
== NULL
) {
7455 status
= map_nt_error_from_unix(errno
);
7456 reply_nterror(req
, status
);
7462 /* Iterate over the src dir copying each entry to the dst. */
7463 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7464 &smb_fname_src
->st
, &talloced
))) {
7465 char *destname
= NULL
;
7467 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7468 TALLOC_FREE(talloced
);
7472 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7473 &smb_fname_src
->st
, false)) {
7474 TALLOC_FREE(talloced
);
7478 if(!mask_match(dname
, fname_src_mask
,
7479 conn
->case_sensitive
)) {
7480 TALLOC_FREE(talloced
);
7484 error
= ERRnoaccess
;
7486 /* Get the src smb_fname struct setup. */
7487 TALLOC_FREE(smb_fname_src
->base_name
);
7488 if (ISDOT(fname_src_dir
)) {
7489 /* Ensure we use canonical names on open. */
7490 smb_fname_src
->base_name
=
7491 talloc_asprintf(smb_fname_src
, "%s",
7494 smb_fname_src
->base_name
=
7495 talloc_asprintf(smb_fname_src
, "%s/%s",
7496 fname_src_dir
, dname
);
7499 if (!smb_fname_src
->base_name
) {
7500 TALLOC_FREE(dir_hnd
);
7501 TALLOC_FREE(talloced
);
7502 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7506 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7507 smb_fname_dst
->base_name
,
7509 TALLOC_FREE(talloced
);
7513 TALLOC_FREE(dir_hnd
);
7514 TALLOC_FREE(talloced
);
7515 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7519 TALLOC_FREE(smb_fname_dst
->base_name
);
7520 smb_fname_dst
->base_name
= destname
;
7522 status
= check_name(conn
, smb_fname_src
->base_name
);
7523 if (!NT_STATUS_IS_OK(status
)) {
7524 TALLOC_FREE(dir_hnd
);
7525 TALLOC_FREE(talloced
);
7526 reply_nterror(req
, status
);
7530 status
= check_name(conn
, smb_fname_dst
->base_name
);
7531 if (!NT_STATUS_IS_OK(status
)) {
7532 TALLOC_FREE(dir_hnd
);
7533 TALLOC_FREE(talloced
);
7534 reply_nterror(req
, status
);
7538 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7539 smb_fname_src
->base_name
,
7540 smb_fname_dst
->base_name
));
7542 status
= copy_file(ctx
, conn
, smb_fname_src
,
7543 smb_fname_dst
, ofun
, count
,
7544 target_is_directory
);
7545 if (NT_STATUS_IS_OK(status
)) {
7549 TALLOC_FREE(talloced
);
7551 TALLOC_FREE(dir_hnd
);
7555 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7559 reply_outbuf(req
, 1, 0);
7560 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7562 TALLOC_FREE(smb_fname_src
);
7563 TALLOC_FREE(smb_fname_dst
);
7564 TALLOC_FREE(fname_src
);
7565 TALLOC_FREE(fname_dst
);
7566 TALLOC_FREE(fname_src_mask
);
7567 TALLOC_FREE(fname_src_dir
);
7569 END_PROFILE(SMBcopy
);
7574 #define DBGC_CLASS DBGC_LOCKING
7576 /****************************************************************************
7577 Get a lock pid, dealing with large count requests.
7578 ****************************************************************************/
7580 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7581 bool large_file_format
)
7583 if(!large_file_format
)
7584 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7586 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7589 /****************************************************************************
7590 Get a lock count, dealing with large count requests.
7591 ****************************************************************************/
7593 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7594 bool large_file_format
)
7598 if(!large_file_format
) {
7599 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7602 * No BVAL, this is reversed!
7604 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7605 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7611 /****************************************************************************
7612 Get a lock offset, dealing with large offset requests.
7613 ****************************************************************************/
7615 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7616 bool large_file_format
)
7618 uint64_t offset
= 0;
7620 if(!large_file_format
) {
7621 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7624 * No BVAL, this is reversed!
7626 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7627 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7633 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7638 struct smbd_lock_element
*locks
,
7641 connection_struct
*conn
= req
->conn
;
7643 NTSTATUS status
= NT_STATUS_OK
;
7647 /* Setup the timeout in seconds. */
7649 if (!lp_blocking_locks(SNUM(conn
))) {
7653 for(i
= 0; i
< (int)num_locks
; i
++) {
7654 struct smbd_lock_element
*e
= &locks
[i
];
7656 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7657 "%llu, file %s timeout = %d\n",
7660 (unsigned long long)e
->smblctx
,
7664 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7665 struct blocking_lock_record
*blr
= NULL
;
7667 if (num_locks
> 1) {
7669 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7670 * if the lock vector contains one entry. When given multiple cancel
7671 * requests in a single PDU we expect the server to return an
7672 * error. Windows servers seem to accept the request but only
7673 * cancel the first lock.
7674 * JRA - Do what Windows does (tm) :-).
7678 /* MS-CIFS (2.2.4.32.1) behavior. */
7679 return NT_STATUS_DOS(ERRDOS
,
7680 ERRcancelviolation
);
7682 /* Windows behavior. */
7684 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7685 "cancel request\n"));
7691 if (lp_blocking_locks(SNUM(conn
))) {
7693 /* Schedule a message to ourselves to
7694 remove the blocking lock record and
7695 return the right error. */
7697 blr
= blocking_lock_cancel_smb1(fsp
,
7703 NT_STATUS_FILE_LOCK_CONFLICT
);
7705 return NT_STATUS_DOS(
7707 ERRcancelviolation
);
7710 /* Remove a matching pending lock. */
7711 status
= do_lock_cancel(fsp
,
7717 bool blocking_lock
= timeout
? true : false;
7718 bool defer_lock
= false;
7719 struct byte_range_lock
*br_lck
;
7720 uint64_t block_smblctx
;
7722 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7733 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7734 /* Windows internal resolution for blocking locks seems
7735 to be about 200ms... Don't wait for less than that. JRA. */
7736 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7737 timeout
= lp_lock_spin_time();
7742 /* If a lock sent with timeout of zero would fail, and
7743 * this lock has been requested multiple times,
7744 * according to brl_lock_failed() we convert this
7745 * request to a blocking lock with a timeout of between
7746 * 150 - 300 milliseconds.
7748 * If lp_lock_spin_time() has been set to 0, we skip
7749 * this blocking retry and fail immediately.
7751 * Replacement for do_lock_spin(). JRA. */
7753 if (!req
->sconn
->using_smb2
&&
7754 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7755 lp_lock_spin_time() && !blocking_lock
&&
7756 NT_STATUS_EQUAL((status
),
7757 NT_STATUS_FILE_LOCK_CONFLICT
))
7760 timeout
= lp_lock_spin_time();
7763 if (br_lck
&& defer_lock
) {
7765 * A blocking lock was requested. Package up
7766 * this smb into a queued request and push it
7767 * onto the blocking lock queue.
7769 if(push_blocking_lock_request(br_lck
,
7780 TALLOC_FREE(br_lck
);
7782 return NT_STATUS_OK
;
7786 TALLOC_FREE(br_lck
);
7789 if (!NT_STATUS_IS_OK(status
)) {
7794 /* If any of the above locks failed, then we must unlock
7795 all of the previous locks (X/Open spec). */
7797 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7799 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7800 i
= -1; /* we want to skip the for loop */
7804 * Ensure we don't do a remove on the lock that just failed,
7805 * as under POSIX rules, if we have a lock already there, we
7806 * will delete it (and we shouldn't) .....
7808 for(i
--; i
>= 0; i
--) {
7809 struct smbd_lock_element
*e
= &locks
[i
];
7811 do_unlock(req
->sconn
->msg_ctx
,
7821 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7822 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
));
7824 return NT_STATUS_OK
;
7827 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
7829 uint16_t num_ulocks
,
7830 struct smbd_lock_element
*ulocks
)
7834 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7835 struct smbd_lock_element
*e
= &ulocks
[i
];
7838 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7839 "pid %u, file %s\n", __func__
,
7842 (unsigned int)e
->smblctx
,
7845 if (e
->brltype
!= UNLOCK_LOCK
) {
7846 /* this can only happen with SMB2 */
7847 return NT_STATUS_INVALID_PARAMETER
;
7850 status
= do_unlock(req
->sconn
->msg_ctx
,
7857 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
7858 nt_errstr(status
)));
7860 if (!NT_STATUS_IS_OK(status
)) {
7865 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
7868 return NT_STATUS_OK
;
7871 /****************************************************************************
7872 Reply to a lockingX request.
7873 ****************************************************************************/
7875 void reply_lockingX(struct smb_request
*req
)
7877 connection_struct
*conn
= req
->conn
;
7879 unsigned char locktype
;
7880 unsigned char oplocklevel
;
7885 const uint8_t *data
;
7886 bool large_file_format
;
7887 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7888 struct smbd_lock_element
*ulocks
;
7889 struct smbd_lock_element
*locks
;
7892 START_PROFILE(SMBlockingX
);
7895 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7896 END_PROFILE(SMBlockingX
);
7900 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7901 locktype
= CVAL(req
->vwv
+3, 0);
7902 oplocklevel
= CVAL(req
->vwv
+3, 1);
7903 num_ulocks
= SVAL(req
->vwv
+6, 0);
7904 num_locks
= SVAL(req
->vwv
+7, 0);
7905 lock_timeout
= IVAL(req
->vwv
+4, 0);
7906 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
7908 if (!check_fsp(conn
, req
, fsp
)) {
7909 END_PROFILE(SMBlockingX
);
7915 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7916 /* we don't support these - and CANCEL_LOCK makes w2k
7917 and XP reboot so I don't really want to be
7918 compatible! (tridge) */
7919 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7920 END_PROFILE(SMBlockingX
);
7924 /* Check if this is an oplock break on a file
7925 we have granted an oplock on.
7927 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
7928 /* Client can insist on breaking to none. */
7929 bool break_to_none
= (oplocklevel
== 0);
7932 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7933 "for %s\n", (unsigned int)oplocklevel
,
7934 fsp_fnum_dbg(fsp
)));
7937 * Make sure we have granted an exclusive or batch oplock on
7941 if (fsp
->oplock_type
== 0) {
7943 /* The Samba4 nbench simulator doesn't understand
7944 the difference between break to level2 and break
7945 to none from level2 - it sends oplock break
7946 replies in both cases. Don't keep logging an error
7947 message here - just ignore it. JRA. */
7949 DEBUG(5,("reply_lockingX: Error : oplock break from "
7950 "client for %s (oplock=%d) and no "
7951 "oplock granted on this file (%s).\n",
7952 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
7955 /* if this is a pure oplock break request then don't
7957 if (num_locks
== 0 && num_ulocks
== 0) {
7958 END_PROFILE(SMBlockingX
);
7961 END_PROFILE(SMBlockingX
);
7962 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
7967 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7969 result
= remove_oplock(fsp
);
7971 result
= downgrade_oplock(fsp
);
7975 DEBUG(0, ("reply_lockingX: error in removing "
7976 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7977 /* Hmmm. Is this panic justified? */
7978 smb_panic("internal tdb error");
7981 /* if this is a pure oplock break request then don't send a
7983 if (num_locks
== 0 && num_ulocks
== 0) {
7984 /* Sanity check - ensure a pure oplock break is not a
7986 if (CVAL(req
->vwv
+0, 0) != 0xff) {
7987 DEBUG(0,("reply_lockingX: Error : pure oplock "
7988 "break is a chained %d request !\n",
7989 (unsigned int)CVAL(req
->vwv
+0, 0)));
7991 END_PROFILE(SMBlockingX
);
7997 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7998 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7999 END_PROFILE(SMBlockingX
);
8003 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8004 if (ulocks
== NULL
) {
8005 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8006 END_PROFILE(SMBlockingX
);
8010 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8011 if (locks
== NULL
) {
8012 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8013 END_PROFILE(SMBlockingX
);
8017 /* Data now points at the beginning of the list
8018 of smb_unlkrng structs */
8019 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8020 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8021 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8022 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8023 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8026 /* Now do any requested locks */
8027 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8029 /* Data now points at the beginning of the list
8030 of smb_lkrng structs */
8032 for(i
= 0; i
< (int)num_locks
; i
++) {
8033 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8034 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8035 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8037 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8038 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8039 locks
[i
].brltype
= PENDING_READ_LOCK
;
8041 locks
[i
].brltype
= READ_LOCK
;
8044 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8045 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8047 locks
[i
].brltype
= WRITE_LOCK
;
8052 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
);
8053 if (!NT_STATUS_IS_OK(status
)) {
8054 END_PROFILE(SMBlockingX
);
8055 reply_nterror(req
, status
);
8059 status
= smbd_do_locking(req
, fsp
,
8060 locktype
, lock_timeout
,
8063 if (!NT_STATUS_IS_OK(status
)) {
8064 END_PROFILE(SMBlockingX
);
8065 reply_nterror(req
, status
);
8069 END_PROFILE(SMBlockingX
);
8073 reply_outbuf(req
, 2, 0);
8074 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8075 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8077 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8078 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8080 END_PROFILE(SMBlockingX
);
8084 #define DBGC_CLASS DBGC_ALL
8086 /****************************************************************************
8087 Reply to a SMBreadbmpx (read block multiplex) request.
8088 Always reply with an error, if someone has a platform really needs this,
8089 please contact vl@samba.org
8090 ****************************************************************************/
8092 void reply_readbmpx(struct smb_request
*req
)
8094 START_PROFILE(SMBreadBmpx
);
8095 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8096 END_PROFILE(SMBreadBmpx
);
8100 /****************************************************************************
8101 Reply to a SMBreadbs (read block multiplex secondary) request.
8102 Always reply with an error, if someone has a platform really needs this,
8103 please contact vl@samba.org
8104 ****************************************************************************/
8106 void reply_readbs(struct smb_request
*req
)
8108 START_PROFILE(SMBreadBs
);
8109 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8110 END_PROFILE(SMBreadBs
);
8114 /****************************************************************************
8115 Reply to a SMBsetattrE.
8116 ****************************************************************************/
8118 void reply_setattrE(struct smb_request
*req
)
8120 connection_struct
*conn
= req
->conn
;
8121 struct smb_file_time ft
;
8125 START_PROFILE(SMBsetattrE
);
8129 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8133 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8135 if(!fsp
|| (fsp
->conn
!= conn
)) {
8136 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8141 * Convert the DOS times into unix times.
8144 ft
.atime
= convert_time_t_to_timespec(
8145 srv_make_unix_date2(req
->vwv
+3));
8146 ft
.mtime
= convert_time_t_to_timespec(
8147 srv_make_unix_date2(req
->vwv
+5));
8148 ft
.create_time
= convert_time_t_to_timespec(
8149 srv_make_unix_date2(req
->vwv
+1));
8151 reply_outbuf(req
, 0, 0);
8154 * Patch from Ray Frush <frush@engr.colostate.edu>
8155 * Sometimes times are sent as zero - ignore them.
8158 /* Ensure we have a valid stat struct for the source. */
8159 status
= vfs_stat_fsp(fsp
);
8160 if (!NT_STATUS_IS_OK(status
)) {
8161 reply_nterror(req
, status
);
8165 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8166 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8170 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8171 if (!NT_STATUS_IS_OK(status
)) {
8172 reply_nterror(req
, status
);
8176 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8179 (unsigned int)ft
.atime
.tv_sec
,
8180 (unsigned int)ft
.mtime
.tv_sec
,
8181 (unsigned int)ft
.create_time
.tv_sec
8184 END_PROFILE(SMBsetattrE
);
8189 /* Back from the dead for OS/2..... JRA. */
8191 /****************************************************************************
8192 Reply to a SMBwritebmpx (write block multiplex primary) request.
8193 Always reply with an error, if someone has a platform really needs this,
8194 please contact vl@samba.org
8195 ****************************************************************************/
8197 void reply_writebmpx(struct smb_request
*req
)
8199 START_PROFILE(SMBwriteBmpx
);
8200 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8201 END_PROFILE(SMBwriteBmpx
);
8205 /****************************************************************************
8206 Reply to a SMBwritebs (write block multiplex secondary) request.
8207 Always reply with an error, if someone has a platform really needs this,
8208 please contact vl@samba.org
8209 ****************************************************************************/
8211 void reply_writebs(struct smb_request
*req
)
8213 START_PROFILE(SMBwriteBs
);
8214 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8215 END_PROFILE(SMBwriteBs
);
8219 /****************************************************************************
8220 Reply to a SMBgetattrE.
8221 ****************************************************************************/
8223 void reply_getattrE(struct smb_request
*req
)
8225 connection_struct
*conn
= req
->conn
;
8228 struct timespec create_ts
;
8230 START_PROFILE(SMBgetattrE
);
8233 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8234 END_PROFILE(SMBgetattrE
);
8238 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8240 if(!fsp
|| (fsp
->conn
!= conn
)) {
8241 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8242 END_PROFILE(SMBgetattrE
);
8246 /* Do an fstat on this file */
8248 reply_nterror(req
, map_nt_error_from_unix(errno
));
8249 END_PROFILE(SMBgetattrE
);
8253 mode
= dos_mode(conn
, fsp
->fsp_name
);
8256 * Convert the times into dos times. Set create
8257 * date to be last modify date as UNIX doesn't save
8261 reply_outbuf(req
, 11, 0);
8263 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8264 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8265 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8266 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8267 /* Should we check pending modtime here ? JRA */
8268 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8269 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8271 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8272 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8273 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8275 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8276 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
8277 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8279 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8281 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8283 END_PROFILE(SMBgetattrE
);