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 return srvstr_get_path_wcard(mem_ctx
, (const char *)req
->inbuf
, req
->flags2
,
322 pp_dest
, src
, smbreq_bufrem(req
, src
),
323 flags
, err
, contains_wcard
);
326 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
327 char **pp_dest
, const char *src
, int flags
,
331 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
332 flags
, err
, &ignore
);
335 /****************************************************************************
336 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
337 ****************************************************************************/
339 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
342 if ((fsp
== NULL
) || (conn
== NULL
)) {
343 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
346 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
347 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
353 /****************************************************************************
354 Check if we have a correct fsp pointing to a file.
355 ****************************************************************************/
357 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
360 if (!check_fsp_open(conn
, req
, fsp
)) {
363 if (fsp
->is_directory
) {
364 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
367 if (fsp
->fh
->fd
== -1) {
368 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
371 fsp
->num_smb_operations
++;
375 /****************************************************************************
376 Check if we have a correct fsp pointing to a quota fake file. Replacement for
377 the CHECK_NTQUOTA_HANDLE_OK macro.
378 ****************************************************************************/
380 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
383 if (!check_fsp_open(conn
, req
, fsp
)) {
387 if (fsp
->is_directory
) {
391 if (fsp
->fake_file_handle
== NULL
) {
395 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
399 if (fsp
->fake_file_handle
->private_data
== NULL
) {
406 static bool netbios_session_retarget(struct smbd_server_connection
*sconn
,
407 const char *name
, int name_type
)
410 char *trim_name_type
;
411 const char *retarget_parm
;
414 int retarget_type
= 0x20;
415 int retarget_port
= NBT_SMB_PORT
;
416 struct sockaddr_storage retarget_addr
;
417 struct sockaddr_in
*in_addr
;
421 if (get_socket_port(sconn
->sock
) != NBT_SMB_PORT
) {
425 trim_name
= talloc_strdup(talloc_tos(), name
);
426 if (trim_name
== NULL
) {
429 trim_char(trim_name
, ' ', ' ');
431 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
433 if (trim_name_type
== NULL
) {
437 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
438 trim_name_type
, NULL
);
439 if (retarget_parm
== NULL
) {
440 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
443 if (retarget_parm
== NULL
) {
447 retarget
= talloc_strdup(trim_name
, retarget_parm
);
448 if (retarget
== NULL
) {
452 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
454 p
= strchr(retarget
, ':');
457 retarget_port
= atoi(p
);
460 p
= strchr_m(retarget
, '#');
463 if (sscanf(p
, "%x", &retarget_type
) != 1) {
468 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
470 DEBUG(10, ("could not resolve %s\n", retarget
));
474 if (retarget_addr
.ss_family
!= AF_INET
) {
475 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
479 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
481 _smb_setlen(outbuf
, 6);
482 SCVAL(outbuf
, 0, 0x84);
483 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
484 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
486 if (!srv_send_smb(sconn
, (char *)outbuf
, false, 0, false,
488 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
494 TALLOC_FREE(trim_name
);
498 static void reply_called_name_not_present(char *outbuf
)
500 smb_setlen(outbuf
, 1);
501 SCVAL(outbuf
, 0, 0x83);
502 SCVAL(outbuf
, 4, 0x82);
505 /****************************************************************************
506 Reply to a (netbios-level) special message.
507 ****************************************************************************/
509 void reply_special(struct smbd_server_connection
*sconn
, char *inbuf
, size_t inbuf_size
)
511 int msg_type
= CVAL(inbuf
,0);
512 int msg_flags
= CVAL(inbuf
,1);
514 * We only really use 4 bytes of the outbuf, but for the smb_setlen
515 * calculation & friends (srv_send_smb uses that) we need the full smb
518 char outbuf
[smb_size
];
520 memset(outbuf
, '\0', sizeof(outbuf
));
522 smb_setlen(outbuf
,0);
525 case NBSSrequest
: /* session request */
527 /* inbuf_size is guarenteed to be at least 4. */
529 int name_type1
, name_type2
;
530 int name_len1
, name_len2
;
534 if (sconn
->nbt
.got_session
) {
535 exit_server_cleanly("multiple session request not permitted");
538 SCVAL(outbuf
,0,NBSSpositive
);
541 /* inbuf_size is guaranteed to be at least 4. */
542 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
543 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
544 DEBUG(0,("Invalid name length in session request\n"));
545 reply_called_name_not_present(outbuf
);
548 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
549 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
550 DEBUG(0,("Invalid name length in session request\n"));
551 reply_called_name_not_present(outbuf
);
555 name_type1
= name_extract((unsigned char *)inbuf
,
556 inbuf_size
,(unsigned int)4,name1
);
557 name_type2
= name_extract((unsigned char *)inbuf
,
558 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
560 if (name_type1
== -1 || name_type2
== -1) {
561 DEBUG(0,("Invalid name type in session request\n"));
562 reply_called_name_not_present(outbuf
);
566 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
567 name1
, name_type1
, name2
, name_type2
));
569 if (netbios_session_retarget(sconn
, name1
, name_type1
)) {
570 exit_server_cleanly("retargeted client");
574 * Windows NT/2k uses "*SMBSERVER" and XP uses
575 * "*SMBSERV" arrggg!!!
577 if (strequal(name1
, "*SMBSERVER ")
578 || strequal(name1
, "*SMBSERV ")) {
581 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
584 exit_server_cleanly("could not allocate raddr");
587 fstrcpy(name1
, raddr
);
590 set_local_machine_name(name1
, True
);
591 set_remote_machine_name(name2
, True
);
593 if (is_ipaddress(sconn
->remote_hostname
)) {
594 char *p
= discard_const_p(char, sconn
->remote_hostname
);
598 sconn
->remote_hostname
= talloc_strdup(sconn
,
599 get_remote_machine_name());
600 if (sconn
->remote_hostname
== NULL
) {
601 exit_server_cleanly("could not copy remote name");
603 sconn
->conn
->remote_hostname
= sconn
->remote_hostname
;
606 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
607 get_local_machine_name(), get_remote_machine_name(),
610 if (name_type2
== 'R') {
611 /* We are being asked for a pathworks session ---
613 reply_called_name_not_present(outbuf
);
617 reload_services(sconn
, conn_snum_used
, true);
620 sconn
->nbt
.got_session
= true;
624 case 0x89: /* session keepalive request
625 (some old clients produce this?) */
626 SCVAL(outbuf
,0,NBSSkeepalive
);
630 case NBSSpositive
: /* positive session response */
631 case NBSSnegative
: /* negative session response */
632 case NBSSretarget
: /* retarget session response */
633 DEBUG(0,("Unexpected session response\n"));
636 case NBSSkeepalive
: /* session keepalive */
641 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
642 msg_type
, msg_flags
));
644 srv_send_smb(sconn
, outbuf
, false, 0, false, NULL
);
646 if (CVAL(outbuf
, 0) != 0x82) {
647 exit_server_cleanly("invalid netbios session");
652 /****************************************************************************
654 conn POINTER CAN BE NULL HERE !
655 ****************************************************************************/
657 void reply_tcon(struct smb_request
*req
)
659 connection_struct
*conn
= req
->conn
;
661 char *service_buf
= NULL
;
662 char *password
= NULL
;
667 TALLOC_CTX
*ctx
= talloc_tos();
668 struct smbd_server_connection
*sconn
= req
->sconn
;
669 NTTIME now
= timeval_to_nttime(&req
->request_time
);
671 START_PROFILE(SMBtcon
);
673 if (req
->buflen
< 4) {
674 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
675 END_PROFILE(SMBtcon
);
679 p
= (const char *)req
->buf
+ 1;
680 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
682 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
684 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
687 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
688 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
689 END_PROFILE(SMBtcon
);
692 p
= strrchr_m(service_buf
,'\\');
696 service
= service_buf
;
699 conn
= make_connection(sconn
, now
, service
, dev
,
700 req
->vuid
,&nt_status
);
704 reply_nterror(req
, nt_status
);
705 END_PROFILE(SMBtcon
);
709 reply_outbuf(req
, 2, 0);
710 SSVAL(req
->outbuf
,smb_vwv0
,sconn
->smb1
.negprot
.max_recv
);
711 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
712 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
714 DEBUG(3,("tcon service=%s cnum=%d\n",
715 service
, conn
->cnum
));
717 END_PROFILE(SMBtcon
);
721 /****************************************************************************
722 Reply to a tcon and X.
723 conn POINTER CAN BE NULL HERE !
724 ****************************************************************************/
726 void reply_tcon_and_X(struct smb_request
*req
)
728 connection_struct
*conn
= req
->conn
;
729 const char *service
= NULL
;
730 TALLOC_CTX
*ctx
= talloc_tos();
731 /* what the cleint thinks the device is */
732 char *client_devicetype
= NULL
;
733 /* what the server tells the client the share represents */
734 const char *server_devicetype
;
740 struct smbXsrv_session
*session
= NULL
;
741 NTTIME now
= timeval_to_nttime(&req
->request_time
);
742 bool session_key_updated
= false;
743 uint16_t optional_support
= 0;
744 struct smbd_server_connection
*sconn
= req
->sconn
;
746 START_PROFILE(SMBtconX
);
749 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
750 END_PROFILE(SMBtconX
);
754 passlen
= SVAL(req
->vwv
+3, 0);
755 tcon_flags
= SVAL(req
->vwv
+2, 0);
757 /* we might have to close an old one */
758 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
759 struct smbXsrv_tcon
*tcon
;
767 * TODO: cancel all outstanding requests on the tcon
769 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
770 if (!NT_STATUS_IS_OK(status
)) {
771 DEBUG(0, ("reply_tcon_and_X: "
772 "smbXsrv_tcon_disconnect() failed: %s\n",
775 * If we hit this case, there is something completely
776 * wrong, so we better disconnect the transport connection.
778 END_PROFILE(SMBtconX
);
779 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
786 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
787 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
788 END_PROFILE(SMBtconX
);
792 if (sconn
->smb1
.negprot
.encrypted_passwords
) {
793 p
= (const char *)req
->buf
+ passlen
;
795 p
= (const char *)req
->buf
+ passlen
+ 1;
798 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
801 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
802 END_PROFILE(SMBtconX
);
807 * the service name can be either: \\server\share
808 * or share directly like on the DELL PowerVault 705
811 q
= strchr_m(path
+2,'\\');
813 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
814 END_PROFILE(SMBtconX
);
822 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
823 &client_devicetype
, p
,
824 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
826 if (client_devicetype
== NULL
) {
827 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
828 END_PROFILE(SMBtconX
);
832 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
834 nt_status
= smb1srv_session_lookup(req
->sconn
->conn
,
835 req
->vuid
, now
, &session
);
836 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
837 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
838 END_PROFILE(SMBtconX
);
841 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
842 reply_nterror(req
, nt_status
);
843 END_PROFILE(SMBtconX
);
846 if (!NT_STATUS_IS_OK(nt_status
)) {
847 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
848 END_PROFILE(SMBtconX
);
852 if (session
->global
->auth_session_info
== NULL
) {
853 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
854 END_PROFILE(SMBtconX
);
859 * If there is no application key defined yet
862 * This means we setup the application key on the
863 * first tcon that happens via the given session.
865 * Once the application key is defined, it does not
868 if (session
->global
->application_key
.length
== 0 &&
869 session
->global
->signing_key
.length
> 0)
871 struct smbXsrv_session
*x
= session
;
872 struct auth_session_info
*session_info
=
873 session
->global
->auth_session_info
;
874 uint8_t session_key
[16];
876 ZERO_STRUCT(session_key
);
877 memcpy(session_key
, x
->global
->signing_key
.data
,
878 MIN(x
->global
->signing_key
.length
, sizeof(session_key
)));
881 * The application key is truncated/padded to 16 bytes
883 x
->global
->application_key
= data_blob_talloc(x
->global
,
885 sizeof(session_key
));
886 ZERO_STRUCT(session_key
);
887 if (x
->global
->application_key
.data
== NULL
) {
888 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
889 END_PROFILE(SMBtconX
);
893 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
894 smb_key_derivation(x
->global
->application_key
.data
,
895 x
->global
->application_key
.length
,
896 x
->global
->application_key
.data
);
897 optional_support
|= SMB_EXTENDED_SIGNATURES
;
901 * Place the application key into the session_info
903 data_blob_clear_free(&session_info
->session_key
);
904 session_info
->session_key
= data_blob_dup_talloc(session_info
,
905 x
->global
->application_key
);
906 if (session_info
->session_key
.data
== NULL
) {
907 data_blob_clear_free(&x
->global
->application_key
);
908 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
909 END_PROFILE(SMBtconX
);
912 session_key_updated
= true;
915 conn
= make_connection(sconn
, now
, service
, client_devicetype
,
916 req
->vuid
, &nt_status
);
920 if (session_key_updated
) {
921 struct smbXsrv_session
*x
= session
;
922 struct auth_session_info
*session_info
=
923 session
->global
->auth_session_info
;
924 data_blob_clear_free(&x
->global
->application_key
);
925 data_blob_clear_free(&session_info
->session_key
);
927 reply_nterror(req
, nt_status
);
928 END_PROFILE(SMBtconX
);
933 server_devicetype
= "IPC";
934 else if ( IS_PRINT(conn
) )
935 server_devicetype
= "LPT1:";
937 server_devicetype
= "A:";
939 if (get_Protocol() < PROTOCOL_NT1
) {
940 reply_outbuf(req
, 2, 0);
941 if (message_push_string(&req
->outbuf
, server_devicetype
,
942 STR_TERMINATE
|STR_ASCII
) == -1) {
943 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
944 END_PROFILE(SMBtconX
);
948 /* NT sets the fstype of IPC$ to the null string */
949 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(ctx
, SNUM(conn
));
951 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
952 /* Return permissions. */
956 reply_outbuf(req
, 7, 0);
959 perm1
= FILE_ALL_ACCESS
;
960 perm2
= FILE_ALL_ACCESS
;
962 perm1
= conn
->share_access
;
965 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
966 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
968 reply_outbuf(req
, 3, 0);
971 if ((message_push_string(&req
->outbuf
, server_devicetype
,
972 STR_TERMINATE
|STR_ASCII
) == -1)
973 || (message_push_string(&req
->outbuf
, fstype
,
974 STR_TERMINATE
) == -1)) {
975 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
976 END_PROFILE(SMBtconX
);
980 /* what does setting this bit do? It is set by NT4 and
981 may affect the ability to autorun mounted cdroms */
982 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
984 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
986 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
987 DEBUG(2,("Serving %s as a Dfs root\n",
988 lp_servicename(ctx
, SNUM(conn
)) ));
989 optional_support
|= SMB_SHARE_IN_DFS
;
992 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
995 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
996 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
998 DEBUG(3,("tconX service=%s \n",
1001 /* set the incoming and outgoing tid to the just created one */
1002 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1003 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1005 END_PROFILE(SMBtconX
);
1007 req
->tid
= conn
->cnum
;
1010 /****************************************************************************
1011 Reply to an unknown type.
1012 ****************************************************************************/
1014 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
1016 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1017 smb_fn_name(type
), type
, type
));
1018 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1022 /****************************************************************************
1024 conn POINTER CAN BE NULL HERE !
1025 ****************************************************************************/
1027 void reply_ioctl(struct smb_request
*req
)
1029 connection_struct
*conn
= req
->conn
;
1036 START_PROFILE(SMBioctl
);
1039 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1040 END_PROFILE(SMBioctl
);
1044 device
= SVAL(req
->vwv
+1, 0);
1045 function
= SVAL(req
->vwv
+2, 0);
1046 ioctl_code
= (device
<< 16) + function
;
1048 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1050 switch (ioctl_code
) {
1051 case IOCTL_QUERY_JOB_INFO
:
1055 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1056 END_PROFILE(SMBioctl
);
1060 reply_outbuf(req
, 8, replysize
+1);
1061 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1062 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1063 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1064 p
= smb_buf(req
->outbuf
);
1065 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1066 p
+= 1; /* Allow for alignment */
1068 switch (ioctl_code
) {
1069 case IOCTL_QUERY_JOB_INFO
:
1071 files_struct
*fsp
= file_fsp(
1072 req
, SVAL(req
->vwv
+0, 0));
1074 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1075 END_PROFILE(SMBioctl
);
1079 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1081 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1082 lp_netbios_name(), 15,
1083 STR_TERMINATE
|STR_ASCII
);
1085 srvstr_push((char *)req
->outbuf
, req
->flags2
,
1087 lp_servicename(talloc_tos(),
1089 13, STR_TERMINATE
|STR_ASCII
);
1091 memset(p
+18, 0, 13);
1097 END_PROFILE(SMBioctl
);
1101 /****************************************************************************
1102 Strange checkpath NTSTATUS mapping.
1103 ****************************************************************************/
1105 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1107 /* Strange DOS error code semantics only for checkpath... */
1108 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1109 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1110 /* We need to map to ERRbadpath */
1111 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1117 /****************************************************************************
1118 Reply to a checkpath.
1119 ****************************************************************************/
1121 void reply_checkpath(struct smb_request
*req
)
1123 connection_struct
*conn
= req
->conn
;
1124 struct smb_filename
*smb_fname
= NULL
;
1127 TALLOC_CTX
*ctx
= talloc_tos();
1129 START_PROFILE(SMBcheckpath
);
1131 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1132 STR_TERMINATE
, &status
);
1134 if (!NT_STATUS_IS_OK(status
)) {
1135 status
= map_checkpath_error(req
->flags2
, status
);
1136 reply_nterror(req
, status
);
1137 END_PROFILE(SMBcheckpath
);
1141 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1143 status
= filename_convert(ctx
,
1145 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1151 if (!NT_STATUS_IS_OK(status
)) {
1152 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1153 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1154 ERRSRV
, ERRbadpath
);
1155 END_PROFILE(SMBcheckpath
);
1161 if (!VALID_STAT(smb_fname
->st
) &&
1162 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1163 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1164 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1165 status
= map_nt_error_from_unix(errno
);
1169 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1170 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1171 ERRDOS
, ERRbadpath
);
1175 reply_outbuf(req
, 0, 0);
1178 /* We special case this - as when a Windows machine
1179 is parsing a path is steps through the components
1180 one at a time - if a component fails it expects
1181 ERRbadpath, not ERRbadfile.
1183 status
= map_checkpath_error(req
->flags2
, status
);
1184 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1186 * Windows returns different error codes if
1187 * the parent directory is valid but not the
1188 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1189 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1190 * if the path is invalid.
1192 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1193 ERRDOS
, ERRbadpath
);
1197 reply_nterror(req
, status
);
1200 TALLOC_FREE(smb_fname
);
1201 END_PROFILE(SMBcheckpath
);
1205 /****************************************************************************
1207 ****************************************************************************/
1209 void reply_getatr(struct smb_request
*req
)
1211 connection_struct
*conn
= req
->conn
;
1212 struct smb_filename
*smb_fname
= NULL
;
1219 TALLOC_CTX
*ctx
= talloc_tos();
1220 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1222 START_PROFILE(SMBgetatr
);
1224 p
= (const char *)req
->buf
+ 1;
1225 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1226 if (!NT_STATUS_IS_OK(status
)) {
1227 reply_nterror(req
, status
);
1231 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1232 under WfWg - weird! */
1233 if (*fname
== '\0') {
1234 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1235 if (!CAN_WRITE(conn
)) {
1236 mode
|= FILE_ATTRIBUTE_READONLY
;
1241 status
= filename_convert(ctx
,
1243 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1248 if (!NT_STATUS_IS_OK(status
)) {
1249 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1250 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1251 ERRSRV
, ERRbadpath
);
1254 reply_nterror(req
, status
);
1257 if (!VALID_STAT(smb_fname
->st
) &&
1258 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1259 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1260 smb_fname_str_dbg(smb_fname
),
1262 reply_nterror(req
, map_nt_error_from_unix(errno
));
1266 mode
= dos_mode(conn
, smb_fname
);
1267 size
= smb_fname
->st
.st_ex_size
;
1269 if (ask_sharemode
) {
1270 struct timespec write_time_ts
;
1271 struct file_id fileid
;
1273 ZERO_STRUCT(write_time_ts
);
1274 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1275 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1276 if (!null_timespec(write_time_ts
)) {
1277 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1281 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1282 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1287 reply_outbuf(req
, 10, 0);
1289 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1290 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1291 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1293 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1295 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1297 if (get_Protocol() >= PROTOCOL_NT1
) {
1298 SSVAL(req
->outbuf
, smb_flg2
,
1299 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1302 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1303 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1306 TALLOC_FREE(smb_fname
);
1308 END_PROFILE(SMBgetatr
);
1312 /****************************************************************************
1314 ****************************************************************************/
1316 void reply_setatr(struct smb_request
*req
)
1318 struct smb_file_time ft
;
1319 connection_struct
*conn
= req
->conn
;
1320 struct smb_filename
*smb_fname
= NULL
;
1326 TALLOC_CTX
*ctx
= talloc_tos();
1328 START_PROFILE(SMBsetatr
);
1333 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1337 p
= (const char *)req
->buf
+ 1;
1338 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1339 if (!NT_STATUS_IS_OK(status
)) {
1340 reply_nterror(req
, status
);
1344 status
= filename_convert(ctx
,
1346 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1351 if (!NT_STATUS_IS_OK(status
)) {
1352 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1353 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1354 ERRSRV
, ERRbadpath
);
1357 reply_nterror(req
, status
);
1361 if (smb_fname
->base_name
[0] == '.' &&
1362 smb_fname
->base_name
[1] == '\0') {
1364 * Not sure here is the right place to catch this
1365 * condition. Might be moved to somewhere else later -- vl
1367 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1371 mode
= SVAL(req
->vwv
+0, 0);
1372 mtime
= srv_make_unix_date3(req
->vwv
+1);
1374 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1375 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1376 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1378 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1380 status
= check_access(conn
, NULL
, smb_fname
,
1381 FILE_WRITE_ATTRIBUTES
);
1382 if (!NT_STATUS_IS_OK(status
)) {
1383 reply_nterror(req
, status
);
1387 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1389 reply_nterror(req
, map_nt_error_from_unix(errno
));
1394 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1395 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1396 if (!NT_STATUS_IS_OK(status
)) {
1397 reply_nterror(req
, status
);
1401 reply_outbuf(req
, 0, 0);
1403 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1406 TALLOC_FREE(smb_fname
);
1407 END_PROFILE(SMBsetatr
);
1411 /****************************************************************************
1413 ****************************************************************************/
1415 void reply_dskattr(struct smb_request
*req
)
1417 connection_struct
*conn
= req
->conn
;
1418 uint64_t dfree
,dsize
,bsize
;
1419 START_PROFILE(SMBdskattr
);
1421 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1422 reply_nterror(req
, map_nt_error_from_unix(errno
));
1423 END_PROFILE(SMBdskattr
);
1427 reply_outbuf(req
, 5, 0);
1429 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1430 double total_space
, free_space
;
1431 /* we need to scale this to a number that DOS6 can handle. We
1432 use floating point so we can handle large drives on systems
1433 that don't have 64 bit integers
1435 we end up displaying a maximum of 2G to DOS systems
1437 total_space
= dsize
* (double)bsize
;
1438 free_space
= dfree
* (double)bsize
;
1440 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1441 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1443 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1444 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1446 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1447 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1448 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1449 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1451 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1452 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1453 SSVAL(req
->outbuf
,smb_vwv2
,512);
1454 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1457 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1459 END_PROFILE(SMBdskattr
);
1464 * Utility function to split the filename from the directory.
1466 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1467 char **fname_dir_out
,
1468 char **fname_mask_out
)
1470 const char *p
= NULL
;
1471 char *fname_dir
= NULL
;
1472 char *fname_mask
= NULL
;
1474 p
= strrchr_m(fname_in
, '/');
1476 fname_dir
= talloc_strdup(ctx
, ".");
1477 fname_mask
= talloc_strdup(ctx
, fname_in
);
1479 fname_dir
= talloc_strndup(ctx
, fname_in
,
1480 PTR_DIFF(p
, fname_in
));
1481 fname_mask
= talloc_strdup(ctx
, p
+1);
1484 if (!fname_dir
|| !fname_mask
) {
1485 TALLOC_FREE(fname_dir
);
1486 TALLOC_FREE(fname_mask
);
1487 return NT_STATUS_NO_MEMORY
;
1490 *fname_dir_out
= fname_dir
;
1491 *fname_mask_out
= fname_mask
;
1492 return NT_STATUS_OK
;
1495 /****************************************************************************
1497 Can be called from SMBsearch, SMBffirst or SMBfunique.
1498 ****************************************************************************/
1500 void reply_search(struct smb_request
*req
)
1502 connection_struct
*conn
= req
->conn
;
1504 const char *mask
= NULL
;
1505 char *directory
= NULL
;
1506 struct smb_filename
*smb_fname
= NULL
;
1510 struct timespec date
;
1512 unsigned int numentries
= 0;
1513 unsigned int maxentries
= 0;
1514 bool finished
= False
;
1519 bool check_descend
= False
;
1520 bool expect_close
= False
;
1522 bool mask_contains_wcard
= False
;
1523 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1524 TALLOC_CTX
*ctx
= talloc_tos();
1525 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1526 struct dptr_struct
*dirptr
= NULL
;
1527 struct smbd_server_connection
*sconn
= req
->sconn
;
1529 START_PROFILE(SMBsearch
);
1532 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1536 if (lp_posix_pathnames()) {
1537 reply_unknown_new(req
, req
->cmd
);
1541 /* If we were called as SMBffirst then we must expect close. */
1542 if(req
->cmd
== SMBffirst
) {
1543 expect_close
= True
;
1546 reply_outbuf(req
, 1, 3);
1547 maxentries
= SVAL(req
->vwv
+0, 0);
1548 dirtype
= SVAL(req
->vwv
+1, 0);
1549 p
= (const char *)req
->buf
+ 1;
1550 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1551 &nt_status
, &mask_contains_wcard
);
1552 if (!NT_STATUS_IS_OK(nt_status
)) {
1553 reply_nterror(req
, nt_status
);
1558 status_len
= SVAL(p
, 0);
1561 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1563 if (status_len
== 0) {
1564 nt_status
= filename_convert(ctx
, conn
,
1565 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1567 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1568 &mask_contains_wcard
,
1570 if (!NT_STATUS_IS_OK(nt_status
)) {
1571 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1572 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1573 ERRSRV
, ERRbadpath
);
1576 reply_nterror(req
, nt_status
);
1580 directory
= smb_fname
->base_name
;
1582 p
= strrchr_m(directory
,'/');
1583 if ((p
!= NULL
) && (*directory
!= '/')) {
1585 directory
= talloc_strndup(ctx
, directory
,
1586 PTR_DIFF(p
, directory
));
1589 directory
= talloc_strdup(ctx
,".");
1593 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1597 memset((char *)status
,'\0',21);
1598 SCVAL(status
,0,(dirtype
& 0x1F));
1600 nt_status
= dptr_create(conn
,
1608 mask_contains_wcard
,
1611 if (!NT_STATUS_IS_OK(nt_status
)) {
1612 reply_nterror(req
, nt_status
);
1615 dptr_num
= dptr_dnum(dirptr
);
1618 const char *dirpath
;
1620 memcpy(status
,p
,21);
1621 status_dirtype
= CVAL(status
,0) & 0x1F;
1622 if (status_dirtype
!= (dirtype
& 0x1F)) {
1623 dirtype
= status_dirtype
;
1626 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1630 dirpath
= dptr_path(sconn
, dptr_num
);
1631 directory
= talloc_strdup(ctx
, dirpath
);
1633 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1637 mask
= dptr_wcard(sconn
, dptr_num
);
1642 * For a 'continue' search we have no string. So
1643 * check from the initial saved string.
1645 mask_contains_wcard
= ms_has_wild(mask
);
1646 dirtype
= dptr_attr(sconn
, dptr_num
);
1649 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1651 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1652 dptr_init_search_op(dirptr
);
1654 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1655 char buf
[DIR_STRUCT_SIZE
];
1656 memcpy(buf
,status
,21);
1657 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1658 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1659 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1662 dptr_fill(sconn
, buf
+12,dptr_num
);
1663 if (dptr_zero(buf
+12) && (status_len
==0)) {
1668 if (message_push_blob(&req
->outbuf
,
1669 data_blob_const(buf
, sizeof(buf
)))
1671 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1679 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1682 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1683 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
1684 if (in_list(directory
, lp_dontdescend(ctx
, SNUM(conn
)),True
)) {
1685 check_descend
= True
;
1688 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1689 finished
= !get_dir_entry(ctx
,
1700 char buf
[DIR_STRUCT_SIZE
];
1701 memcpy(buf
,status
,21);
1702 if (!make_dir_struct(ctx
,
1708 convert_timespec_to_time_t(date
),
1709 !allow_long_path_components
)) {
1710 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1713 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1716 if (message_push_blob(&req
->outbuf
,
1717 data_blob_const(buf
, sizeof(buf
)))
1719 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1729 /* If we were called as SMBffirst with smb_search_id == NULL
1730 and no entries were found then return error and close dirptr
1733 if (numentries
== 0) {
1734 dptr_close(sconn
, &dptr_num
);
1735 } else if(expect_close
&& status_len
== 0) {
1736 /* Close the dptr - we know it's gone */
1737 dptr_close(sconn
, &dptr_num
);
1740 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1741 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1742 dptr_close(sconn
, &dptr_num
);
1745 if ((numentries
== 0) && !mask_contains_wcard
) {
1746 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1750 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1751 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1752 SCVAL(smb_buf(req
->outbuf
),0,5);
1753 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1755 /* The replies here are never long name. */
1756 SSVAL(req
->outbuf
, smb_flg2
,
1757 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1758 if (!allow_long_path_components
) {
1759 SSVAL(req
->outbuf
, smb_flg2
,
1760 SVAL(req
->outbuf
, smb_flg2
)
1761 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1764 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1765 SSVAL(req
->outbuf
, smb_flg2
,
1766 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1768 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1769 smb_fn_name(req
->cmd
),
1776 TALLOC_FREE(directory
);
1777 TALLOC_FREE(smb_fname
);
1778 END_PROFILE(SMBsearch
);
1782 /****************************************************************************
1783 Reply to a fclose (stop directory search).
1784 ****************************************************************************/
1786 void reply_fclose(struct smb_request
*req
)
1794 bool path_contains_wcard
= False
;
1795 TALLOC_CTX
*ctx
= talloc_tos();
1796 struct smbd_server_connection
*sconn
= req
->sconn
;
1798 START_PROFILE(SMBfclose
);
1800 if (lp_posix_pathnames()) {
1801 reply_unknown_new(req
, req
->cmd
);
1802 END_PROFILE(SMBfclose
);
1806 p
= (const char *)req
->buf
+ 1;
1807 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1808 &err
, &path_contains_wcard
);
1809 if (!NT_STATUS_IS_OK(err
)) {
1810 reply_nterror(req
, err
);
1811 END_PROFILE(SMBfclose
);
1815 status_len
= SVAL(p
,0);
1818 if (status_len
== 0) {
1819 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1820 END_PROFILE(SMBfclose
);
1824 memcpy(status
,p
,21);
1826 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1827 /* Close the dptr - we know it's gone */
1828 dptr_close(sconn
, &dptr_num
);
1831 reply_outbuf(req
, 1, 0);
1832 SSVAL(req
->outbuf
,smb_vwv0
,0);
1834 DEBUG(3,("search close\n"));
1836 END_PROFILE(SMBfclose
);
1840 /****************************************************************************
1842 ****************************************************************************/
1844 void reply_open(struct smb_request
*req
)
1846 connection_struct
*conn
= req
->conn
;
1847 struct smb_filename
*smb_fname
= NULL
;
1859 uint32 create_disposition
;
1860 uint32 create_options
= 0;
1861 uint32_t private_flags
= 0;
1863 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1864 TALLOC_CTX
*ctx
= talloc_tos();
1866 START_PROFILE(SMBopen
);
1869 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1873 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1874 deny_mode
= SVAL(req
->vwv
+0, 0);
1875 dos_attr
= SVAL(req
->vwv
+1, 0);
1877 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1878 STR_TERMINATE
, &status
);
1879 if (!NT_STATUS_IS_OK(status
)) {
1880 reply_nterror(req
, status
);
1884 status
= filename_convert(ctx
,
1886 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1891 if (!NT_STATUS_IS_OK(status
)) {
1892 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1893 reply_botherror(req
,
1894 NT_STATUS_PATH_NOT_COVERED
,
1895 ERRSRV
, ERRbadpath
);
1898 reply_nterror(req
, status
);
1902 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1903 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1904 &share_mode
, &create_disposition
,
1905 &create_options
, &private_flags
)) {
1906 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1910 status
= SMB_VFS_CREATE_FILE(
1913 0, /* root_dir_fid */
1914 smb_fname
, /* fname */
1915 access_mask
, /* access_mask */
1916 share_mode
, /* share_access */
1917 create_disposition
, /* create_disposition*/
1918 create_options
, /* create_options */
1919 dos_attr
, /* file_attributes */
1920 oplock_request
, /* oplock_request */
1921 0, /* allocation_size */
1928 if (!NT_STATUS_IS_OK(status
)) {
1929 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1930 /* We have re-scheduled this call. */
1933 reply_openerror(req
, status
);
1937 size
= smb_fname
->st
.st_ex_size
;
1938 fattr
= dos_mode(conn
, smb_fname
);
1940 /* Deal with other possible opens having a modified
1942 if (ask_sharemode
) {
1943 struct timespec write_time_ts
;
1945 ZERO_STRUCT(write_time_ts
);
1946 get_file_infos(fsp
->file_id
, 0, NULL
, &write_time_ts
);
1947 if (!null_timespec(write_time_ts
)) {
1948 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1952 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1954 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1955 DEBUG(3,("attempt to open a directory %s\n",
1957 close_file(req
, fsp
, ERROR_CLOSE
);
1958 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1959 ERRDOS
, ERRnoaccess
);
1963 reply_outbuf(req
, 7, 0);
1964 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1965 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1966 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1967 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1969 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1971 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1972 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1974 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1975 SCVAL(req
->outbuf
,smb_flg
,
1976 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1979 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1980 SCVAL(req
->outbuf
,smb_flg
,
1981 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1984 TALLOC_FREE(smb_fname
);
1985 END_PROFILE(SMBopen
);
1989 /****************************************************************************
1990 Reply to an open and X.
1991 ****************************************************************************/
1993 void reply_open_and_X(struct smb_request
*req
)
1995 connection_struct
*conn
= req
->conn
;
1996 struct smb_filename
*smb_fname
= NULL
;
2001 /* Breakout the oplock request bits so we can set the
2002 reply bits separately. */
2003 int ex_oplock_request
;
2004 int core_oplock_request
;
2007 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2008 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
2016 uint64_t allocation_size
;
2017 ssize_t retval
= -1;
2020 uint32 create_disposition
;
2021 uint32 create_options
= 0;
2022 uint32_t private_flags
= 0;
2023 TALLOC_CTX
*ctx
= talloc_tos();
2025 START_PROFILE(SMBopenX
);
2027 if (req
->wct
< 15) {
2028 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2032 open_flags
= SVAL(req
->vwv
+2, 0);
2033 deny_mode
= SVAL(req
->vwv
+3, 0);
2034 smb_attr
= SVAL(req
->vwv
+5, 0);
2035 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2036 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2037 oplock_request
= ex_oplock_request
| core_oplock_request
;
2038 smb_ofun
= SVAL(req
->vwv
+8, 0);
2039 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2041 /* If it's an IPC, pass off the pipe handler. */
2043 if (lp_nt_pipe_support()) {
2044 reply_open_pipe_and_X(conn
, req
);
2046 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2051 /* XXXX we need to handle passed times, sattr and flags */
2052 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2053 STR_TERMINATE
, &status
);
2054 if (!NT_STATUS_IS_OK(status
)) {
2055 reply_nterror(req
, status
);
2059 status
= filename_convert(ctx
,
2061 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2066 if (!NT_STATUS_IS_OK(status
)) {
2067 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2068 reply_botherror(req
,
2069 NT_STATUS_PATH_NOT_COVERED
,
2070 ERRSRV
, ERRbadpath
);
2073 reply_nterror(req
, status
);
2077 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
2079 &access_mask
, &share_mode
,
2080 &create_disposition
,
2083 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2087 status
= SMB_VFS_CREATE_FILE(
2090 0, /* root_dir_fid */
2091 smb_fname
, /* fname */
2092 access_mask
, /* access_mask */
2093 share_mode
, /* share_access */
2094 create_disposition
, /* create_disposition*/
2095 create_options
, /* create_options */
2096 smb_attr
, /* file_attributes */
2097 oplock_request
, /* oplock_request */
2098 0, /* allocation_size */
2103 &smb_action
); /* pinfo */
2105 if (!NT_STATUS_IS_OK(status
)) {
2106 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2107 /* We have re-scheduled this call. */
2110 reply_openerror(req
, status
);
2114 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2115 if the file is truncated or created. */
2116 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2117 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2118 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2119 close_file(req
, fsp
, ERROR_CLOSE
);
2120 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2123 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2125 close_file(req
, fsp
, ERROR_CLOSE
);
2126 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2129 status
= vfs_stat_fsp(fsp
);
2130 if (!NT_STATUS_IS_OK(status
)) {
2131 close_file(req
, fsp
, ERROR_CLOSE
);
2132 reply_nterror(req
, status
);
2137 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2138 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2139 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2140 close_file(req
, fsp
, ERROR_CLOSE
);
2141 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2145 /* If the caller set the extended oplock request bit
2146 and we granted one (by whatever means) - set the
2147 correct bit for extended oplock reply.
2150 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2151 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2154 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2155 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2158 /* If the caller set the core oplock request bit
2159 and we granted one (by whatever means) - set the
2160 correct bit for core oplock reply.
2163 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2164 reply_outbuf(req
, 19, 0);
2166 reply_outbuf(req
, 15, 0);
2169 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2170 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2172 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2173 SCVAL(req
->outbuf
, smb_flg
,
2174 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2177 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2178 SCVAL(req
->outbuf
, smb_flg
,
2179 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2182 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2183 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2184 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2185 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2187 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2189 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2190 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2191 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2193 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2194 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2198 TALLOC_FREE(smb_fname
);
2199 END_PROFILE(SMBopenX
);
2203 /****************************************************************************
2204 Reply to a SMBulogoffX.
2205 ****************************************************************************/
2207 void reply_ulogoffX(struct smb_request
*req
)
2209 struct smbd_server_connection
*sconn
= req
->sconn
;
2210 struct user_struct
*vuser
;
2211 struct smbXsrv_session
*session
= NULL
;
2214 START_PROFILE(SMBulogoffX
);
2216 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2219 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2220 (unsigned long long)req
->vuid
));
2222 req
->vuid
= UID_FIELD_INVALID
;
2223 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2224 END_PROFILE(SMBulogoffX
);
2228 session
= vuser
->session
;
2232 * TODO: cancel all outstanding requests on the session
2234 status
= smbXsrv_session_logoff(session
);
2235 if (!NT_STATUS_IS_OK(status
)) {
2236 DEBUG(0, ("reply_ulogoff: "
2237 "smbXsrv_session_logoff() failed: %s\n",
2238 nt_errstr(status
)));
2240 * If we hit this case, there is something completely
2241 * wrong, so we better disconnect the transport connection.
2243 END_PROFILE(SMBulogoffX
);
2244 exit_server(__location__
": smbXsrv_session_logoff failed");
2248 TALLOC_FREE(session
);
2250 reply_outbuf(req
, 2, 0);
2251 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2252 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2254 DEBUG(3, ("ulogoffX vuid=%llu\n",
2255 (unsigned long long)req
->vuid
));
2257 END_PROFILE(SMBulogoffX
);
2258 req
->vuid
= UID_FIELD_INVALID
;
2261 /****************************************************************************
2262 Reply to a mknew or a create.
2263 ****************************************************************************/
2265 void reply_mknew(struct smb_request
*req
)
2267 connection_struct
*conn
= req
->conn
;
2268 struct smb_filename
*smb_fname
= NULL
;
2271 struct smb_file_time ft
;
2273 int oplock_request
= 0;
2275 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2276 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2277 uint32 create_disposition
;
2278 uint32 create_options
= 0;
2279 TALLOC_CTX
*ctx
= talloc_tos();
2281 START_PROFILE(SMBcreate
);
2285 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2289 fattr
= SVAL(req
->vwv
+0, 0);
2290 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2293 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2295 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2296 STR_TERMINATE
, &status
);
2297 if (!NT_STATUS_IS_OK(status
)) {
2298 reply_nterror(req
, status
);
2302 status
= filename_convert(ctx
,
2304 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2309 if (!NT_STATUS_IS_OK(status
)) {
2310 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2311 reply_botherror(req
,
2312 NT_STATUS_PATH_NOT_COVERED
,
2313 ERRSRV
, ERRbadpath
);
2316 reply_nterror(req
, status
);
2320 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2321 DEBUG(0,("Attempt to create file (%s) with volid set - "
2322 "please report this\n",
2323 smb_fname_str_dbg(smb_fname
)));
2326 if(req
->cmd
== SMBmknew
) {
2327 /* We should fail if file exists. */
2328 create_disposition
= FILE_CREATE
;
2330 /* Create if file doesn't exist, truncate if it does. */
2331 create_disposition
= FILE_OVERWRITE_IF
;
2334 status
= SMB_VFS_CREATE_FILE(
2337 0, /* root_dir_fid */
2338 smb_fname
, /* fname */
2339 access_mask
, /* access_mask */
2340 share_mode
, /* share_access */
2341 create_disposition
, /* create_disposition*/
2342 create_options
, /* create_options */
2343 fattr
, /* file_attributes */
2344 oplock_request
, /* oplock_request */
2345 0, /* allocation_size */
2346 0, /* private_flags */
2352 if (!NT_STATUS_IS_OK(status
)) {
2353 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2354 /* We have re-scheduled this call. */
2357 reply_openerror(req
, status
);
2361 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2362 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2363 if (!NT_STATUS_IS_OK(status
)) {
2364 END_PROFILE(SMBcreate
);
2368 reply_outbuf(req
, 1, 0);
2369 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2371 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2372 SCVAL(req
->outbuf
,smb_flg
,
2373 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2376 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2377 SCVAL(req
->outbuf
,smb_flg
,
2378 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2381 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2382 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2383 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2384 (unsigned int)fattr
));
2387 TALLOC_FREE(smb_fname
);
2388 END_PROFILE(SMBcreate
);
2392 /****************************************************************************
2393 Reply to a create temporary file.
2394 ****************************************************************************/
2396 void reply_ctemp(struct smb_request
*req
)
2398 connection_struct
*conn
= req
->conn
;
2399 struct smb_filename
*smb_fname
= NULL
;
2407 TALLOC_CTX
*ctx
= talloc_tos();
2409 START_PROFILE(SMBctemp
);
2412 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2416 fattr
= SVAL(req
->vwv
+0, 0);
2417 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2419 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2420 STR_TERMINATE
, &status
);
2421 if (!NT_STATUS_IS_OK(status
)) {
2422 reply_nterror(req
, status
);
2426 fname
= talloc_asprintf(ctx
,
2430 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2434 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2438 status
= filename_convert(ctx
, conn
,
2439 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2444 if (!NT_STATUS_IS_OK(status
)) {
2445 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2446 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2447 ERRSRV
, ERRbadpath
);
2450 reply_nterror(req
, status
);
2454 tmpfd
= mkstemp(smb_fname
->base_name
);
2456 reply_nterror(req
, map_nt_error_from_unix(errno
));
2460 SMB_VFS_STAT(conn
, smb_fname
);
2462 /* We should fail if file does not exist. */
2463 status
= SMB_VFS_CREATE_FILE(
2466 0, /* root_dir_fid */
2467 smb_fname
, /* fname */
2468 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2469 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2470 FILE_OPEN
, /* create_disposition*/
2471 0, /* create_options */
2472 fattr
, /* file_attributes */
2473 oplock_request
, /* oplock_request */
2474 0, /* allocation_size */
2475 0, /* private_flags */
2481 /* close fd from mkstemp() */
2484 if (!NT_STATUS_IS_OK(status
)) {
2485 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2486 /* We have re-scheduled this call. */
2489 reply_openerror(req
, status
);
2493 reply_outbuf(req
, 1, 0);
2494 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2496 /* the returned filename is relative to the directory */
2497 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2499 s
= fsp
->fsp_name
->base_name
;
2505 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2506 thing in the byte section. JRA */
2507 SSVALS(p
, 0, -1); /* what is this? not in spec */
2509 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2511 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2515 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2516 SCVAL(req
->outbuf
, smb_flg
,
2517 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2520 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2521 SCVAL(req
->outbuf
, smb_flg
,
2522 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2525 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2526 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2527 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2529 TALLOC_FREE(smb_fname
);
2530 END_PROFILE(SMBctemp
);
2534 /*******************************************************************
2535 Check if a user is allowed to rename a file.
2536 ********************************************************************/
2538 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2541 if (!CAN_WRITE(conn
)) {
2542 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2545 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2546 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2547 /* Only bother to read the DOS attribute if we might deny the
2548 rename on the grounds of attribute missmatch. */
2549 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2550 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2551 return NT_STATUS_NO_SUCH_FILE
;
2555 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2556 if (fsp
->posix_open
) {
2557 return NT_STATUS_OK
;
2560 /* If no pathnames are open below this
2561 directory, allow the rename. */
2563 if (file_find_subpath(fsp
)) {
2564 return NT_STATUS_ACCESS_DENIED
;
2566 return NT_STATUS_OK
;
2569 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2570 return NT_STATUS_OK
;
2573 return NT_STATUS_ACCESS_DENIED
;
2576 /*******************************************************************
2577 * unlink a file with all relevant access checks
2578 *******************************************************************/
2580 static NTSTATUS
do_unlink(connection_struct
*conn
,
2581 struct smb_request
*req
,
2582 struct smb_filename
*smb_fname
,
2587 uint32 dirtype_orig
= dirtype
;
2590 bool posix_paths
= lp_posix_pathnames();
2592 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2593 smb_fname_str_dbg(smb_fname
),
2596 if (!CAN_WRITE(conn
)) {
2597 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2601 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2603 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2606 return map_nt_error_from_unix(errno
);
2609 fattr
= dos_mode(conn
, smb_fname
);
2611 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2612 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2615 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2617 return NT_STATUS_NO_SUCH_FILE
;
2620 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2621 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2622 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2624 return NT_STATUS_NO_SUCH_FILE
;
2627 if (dirtype_orig
& 0x8000) {
2628 /* These will never be set for POSIX. */
2629 return NT_STATUS_NO_SUCH_FILE
;
2633 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2634 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2637 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2638 return NT_STATUS_NO_SUCH_FILE
;
2641 if (dirtype
& 0xFF00) {
2642 /* These will never be set for POSIX. */
2643 return NT_STATUS_NO_SUCH_FILE
;
2648 return NT_STATUS_NO_SUCH_FILE
;
2651 /* Can't delete a directory. */
2652 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2653 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2658 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2659 return NT_STATUS_OBJECT_NAME_INVALID
;
2660 #endif /* JRATEST */
2662 /* On open checks the open itself will check the share mode, so
2663 don't do it here as we'll get it wrong. */
2665 status
= SMB_VFS_CREATE_FILE
2668 0, /* root_dir_fid */
2669 smb_fname
, /* fname */
2670 DELETE_ACCESS
, /* access_mask */
2671 FILE_SHARE_NONE
, /* share_access */
2672 FILE_OPEN
, /* create_disposition*/
2673 FILE_NON_DIRECTORY_FILE
, /* create_options */
2674 /* file_attributes */
2675 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2676 FILE_ATTRIBUTE_NORMAL
,
2677 0, /* oplock_request */
2678 0, /* allocation_size */
2679 0, /* private_flags */
2685 if (!NT_STATUS_IS_OK(status
)) {
2686 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2687 nt_errstr(status
)));
2691 status
= can_set_delete_on_close(fsp
, fattr
);
2692 if (!NT_STATUS_IS_OK(status
)) {
2693 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2695 smb_fname_str_dbg(smb_fname
),
2696 nt_errstr(status
)));
2697 close_file(req
, fsp
, NORMAL_CLOSE
);
2701 /* The set is across all open files on this dev/inode pair. */
2702 if (!set_delete_on_close(fsp
, True
,
2703 conn
->session_info
->security_token
,
2704 conn
->session_info
->unix_token
)) {
2705 close_file(req
, fsp
, NORMAL_CLOSE
);
2706 return NT_STATUS_ACCESS_DENIED
;
2709 return close_file(req
, fsp
, NORMAL_CLOSE
);
2712 /****************************************************************************
2713 The guts of the unlink command, split out so it may be called by the NT SMB
2715 ****************************************************************************/
2717 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2718 uint32 dirtype
, struct smb_filename
*smb_fname
,
2721 char *fname_dir
= NULL
;
2722 char *fname_mask
= NULL
;
2724 NTSTATUS status
= NT_STATUS_OK
;
2725 TALLOC_CTX
*ctx
= talloc_tos();
2727 /* Split up the directory from the filename/mask. */
2728 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2729 &fname_dir
, &fname_mask
);
2730 if (!NT_STATUS_IS_OK(status
)) {
2735 * We should only check the mangled cache
2736 * here if unix_convert failed. This means
2737 * that the path in 'mask' doesn't exist
2738 * on the file system and so we need to look
2739 * for a possible mangle. This patch from
2740 * Tine Smukavec <valentin.smukavec@hermes.si>.
2743 if (!VALID_STAT(smb_fname
->st
) &&
2744 mangle_is_mangled(fname_mask
, conn
->params
)) {
2745 char *new_mask
= NULL
;
2746 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2747 &new_mask
, conn
->params
);
2749 TALLOC_FREE(fname_mask
);
2750 fname_mask
= new_mask
;
2757 * Only one file needs to be unlinked. Append the mask back
2758 * onto the directory.
2760 TALLOC_FREE(smb_fname
->base_name
);
2761 if (ISDOT(fname_dir
)) {
2762 /* Ensure we use canonical names on open. */
2763 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2767 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2772 if (!smb_fname
->base_name
) {
2773 status
= NT_STATUS_NO_MEMORY
;
2777 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2780 status
= check_name(conn
, smb_fname
->base_name
);
2781 if (!NT_STATUS_IS_OK(status
)) {
2785 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2786 if (!NT_STATUS_IS_OK(status
)) {
2792 struct smb_Dir
*dir_hnd
= NULL
;
2794 const char *dname
= NULL
;
2795 char *talloced
= NULL
;
2797 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2798 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2802 if (strequal(fname_mask
,"????????.???")) {
2803 TALLOC_FREE(fname_mask
);
2804 fname_mask
= talloc_strdup(ctx
, "*");
2806 status
= NT_STATUS_NO_MEMORY
;
2811 status
= check_name(conn
, fname_dir
);
2812 if (!NT_STATUS_IS_OK(status
)) {
2816 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2818 if (dir_hnd
== NULL
) {
2819 status
= map_nt_error_from_unix(errno
);
2823 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2824 the pattern matches against the long name, otherwise the short name
2825 We don't implement this yet XXXX
2828 status
= NT_STATUS_NO_SUCH_FILE
;
2830 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2831 &smb_fname
->st
, &talloced
))) {
2832 TALLOC_CTX
*frame
= talloc_stackframe();
2834 if (!is_visible_file(conn
, fname_dir
, dname
,
2835 &smb_fname
->st
, true)) {
2837 TALLOC_FREE(talloced
);
2841 /* Quick check for "." and ".." */
2842 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2844 TALLOC_FREE(talloced
);
2848 if(!mask_match(dname
, fname_mask
,
2849 conn
->case_sensitive
)) {
2851 TALLOC_FREE(talloced
);
2855 TALLOC_FREE(smb_fname
->base_name
);
2856 if (ISDOT(fname_dir
)) {
2857 /* Ensure we use canonical names on open. */
2858 smb_fname
->base_name
=
2859 talloc_asprintf(smb_fname
, "%s",
2862 smb_fname
->base_name
=
2863 talloc_asprintf(smb_fname
, "%s/%s",
2867 if (!smb_fname
->base_name
) {
2868 TALLOC_FREE(dir_hnd
);
2869 status
= NT_STATUS_NO_MEMORY
;
2871 TALLOC_FREE(talloced
);
2875 status
= check_name(conn
, smb_fname
->base_name
);
2876 if (!NT_STATUS_IS_OK(status
)) {
2877 TALLOC_FREE(dir_hnd
);
2879 TALLOC_FREE(talloced
);
2883 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2884 if (!NT_STATUS_IS_OK(status
)) {
2886 TALLOC_FREE(talloced
);
2891 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2892 smb_fname
->base_name
));
2895 TALLOC_FREE(talloced
);
2897 TALLOC_FREE(dir_hnd
);
2900 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2901 status
= map_nt_error_from_unix(errno
);
2905 TALLOC_FREE(fname_dir
);
2906 TALLOC_FREE(fname_mask
);
2910 /****************************************************************************
2912 ****************************************************************************/
2914 void reply_unlink(struct smb_request
*req
)
2916 connection_struct
*conn
= req
->conn
;
2918 struct smb_filename
*smb_fname
= NULL
;
2921 bool path_contains_wcard
= False
;
2922 TALLOC_CTX
*ctx
= talloc_tos();
2924 START_PROFILE(SMBunlink
);
2927 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2931 dirtype
= SVAL(req
->vwv
+0, 0);
2933 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2934 STR_TERMINATE
, &status
,
2935 &path_contains_wcard
);
2936 if (!NT_STATUS_IS_OK(status
)) {
2937 reply_nterror(req
, status
);
2941 status
= filename_convert(ctx
, conn
,
2942 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2944 UCF_COND_ALLOW_WCARD_LCOMP
,
2945 &path_contains_wcard
,
2947 if (!NT_STATUS_IS_OK(status
)) {
2948 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2949 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2950 ERRSRV
, ERRbadpath
);
2953 reply_nterror(req
, status
);
2957 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2959 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2960 path_contains_wcard
);
2961 if (!NT_STATUS_IS_OK(status
)) {
2962 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2963 /* We have re-scheduled this call. */
2966 reply_nterror(req
, status
);
2970 reply_outbuf(req
, 0, 0);
2972 TALLOC_FREE(smb_fname
);
2973 END_PROFILE(SMBunlink
);
2977 /****************************************************************************
2979 ****************************************************************************/
2981 static void fail_readraw(void)
2983 const char *errstr
= talloc_asprintf(talloc_tos(),
2984 "FAIL ! reply_readbraw: socket write fail (%s)",
2989 exit_server_cleanly(errstr
);
2992 /****************************************************************************
2993 Fake (read/write) sendfile. Returns -1 on read or write fail.
2994 ****************************************************************************/
2996 ssize_t
fake_sendfile(files_struct
*fsp
, off_t startpos
, size_t nread
)
2999 size_t tosend
= nread
;
3006 bufsize
= MIN(nread
, 65536);
3008 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3012 while (tosend
> 0) {
3016 if (tosend
> bufsize
) {
3021 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3027 /* If we had a short read, fill with zeros. */
3028 if (ret
< cur_read
) {
3029 memset(buf
+ ret
, '\0', cur_read
- ret
);
3032 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
3034 char addr
[INET6_ADDRSTRLEN
];
3036 * Try and give an error message saying what
3039 DEBUG(0, ("write_data failed for client %s. "
3041 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3048 startpos
+= cur_read
;
3052 return (ssize_t
)nread
;
3055 /****************************************************************************
3056 Deal with the case of sendfile reading less bytes from the file than
3057 requested. Fill with zeros (all we can do).
3058 ****************************************************************************/
3060 void sendfile_short_send(files_struct
*fsp
,
3065 #define SHORT_SEND_BUFSIZE 1024
3066 if (nread
< headersize
) {
3067 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3068 "header for file %s (%s). Terminating\n",
3069 fsp_str_dbg(fsp
), strerror(errno
)));
3070 exit_server_cleanly("sendfile_short_send failed");
3073 nread
-= headersize
;
3075 if (nread
< smb_maxcnt
) {
3076 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3078 exit_server_cleanly("sendfile_short_send: "
3082 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3083 "with zeros !\n", fsp_str_dbg(fsp
)));
3085 while (nread
< smb_maxcnt
) {
3087 * We asked for the real file size and told sendfile
3088 * to not go beyond the end of the file. But it can
3089 * happen that in between our fstat call and the
3090 * sendfile call the file was truncated. This is very
3091 * bad because we have already announced the larger
3092 * number of bytes to the client.
3094 * The best we can do now is to send 0-bytes, just as
3095 * a read from a hole in a sparse file would do.
3097 * This should happen rarely enough that I don't care
3098 * about efficiency here :-)
3102 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3103 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
3105 char addr
[INET6_ADDRSTRLEN
];
3107 * Try and give an error message saying what
3110 DEBUG(0, ("write_data failed for client %s. "
3113 fsp
->conn
->sconn
->sock
, addr
,
3116 exit_server_cleanly("sendfile_short_send: "
3117 "write_data failed");
3125 /****************************************************************************
3126 Return a readbraw error (4 bytes of zero).
3127 ****************************************************************************/
3129 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
3135 smbd_lock_socket(sconn
);
3136 if (write_data(sconn
->sock
,header
,4) != 4) {
3137 char addr
[INET6_ADDRSTRLEN
];
3139 * Try and give an error message saying what
3142 DEBUG(0, ("write_data failed for client %s. "
3144 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
3149 smbd_unlock_socket(sconn
);
3152 /****************************************************************************
3153 Use sendfile in readbraw.
3154 ****************************************************************************/
3156 static void send_file_readbraw(connection_struct
*conn
,
3157 struct smb_request
*req
,
3163 struct smbd_server_connection
*sconn
= req
->sconn
;
3164 char *outbuf
= NULL
;
3168 * We can only use sendfile on a non-chained packet
3169 * but we can use on a non-oplocked file. tridge proved this
3170 * on a train in Germany :-). JRA.
3171 * reply_readbraw has already checked the length.
3174 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3175 (fsp
->wcp
== NULL
) &&
3176 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3177 ssize_t sendfile_read
= -1;
3179 DATA_BLOB header_blob
;
3181 _smb_setlen(header
,nread
);
3182 header_blob
= data_blob_const(header
, 4);
3184 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3185 &header_blob
, startpos
,
3187 if (sendfile_read
== -1) {
3188 /* Returning ENOSYS means no data at all was sent.
3189 * Do this as a normal read. */
3190 if (errno
== ENOSYS
) {
3191 goto normal_readbraw
;
3195 * Special hack for broken Linux with no working sendfile. If we
3196 * return EINTR we sent the header but not the rest of the data.
3197 * Fake this up by doing read/write calls.
3199 if (errno
== EINTR
) {
3200 /* Ensure we don't do this again. */
3201 set_use_sendfile(SNUM(conn
), False
);
3202 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3204 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3205 DEBUG(0,("send_file_readbraw: "
3206 "fake_sendfile failed for "
3210 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3215 DEBUG(0,("send_file_readbraw: sendfile failed for "
3216 "file %s (%s). Terminating\n",
3217 fsp_str_dbg(fsp
), strerror(errno
)));
3218 exit_server_cleanly("send_file_readbraw sendfile failed");
3219 } else if (sendfile_read
== 0) {
3221 * Some sendfile implementations return 0 to indicate
3222 * that there was a short read, but nothing was
3223 * actually written to the socket. In this case,
3224 * fallback to the normal read path so the header gets
3225 * the correct byte count.
3227 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3228 "bytes falling back to the normal read: "
3229 "%s\n", fsp_str_dbg(fsp
)));
3230 goto normal_readbraw
;
3233 /* Deal with possible short send. */
3234 if (sendfile_read
!= 4+nread
) {
3235 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3242 outbuf
= talloc_array(NULL
, char, nread
+4);
3244 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3245 (unsigned)(nread
+4)));
3246 reply_readbraw_error(sconn
);
3251 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3252 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3261 _smb_setlen(outbuf
,ret
);
3262 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3263 char addr
[INET6_ADDRSTRLEN
];
3265 * Try and give an error message saying what
3268 DEBUG(0, ("write_data failed for client %s. "
3270 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3277 TALLOC_FREE(outbuf
);
3280 /****************************************************************************
3281 Reply to a readbraw (core+ protocol).
3282 ****************************************************************************/
3284 void reply_readbraw(struct smb_request
*req
)
3286 connection_struct
*conn
= req
->conn
;
3287 struct smbd_server_connection
*sconn
= req
->sconn
;
3288 ssize_t maxcount
,mincount
;
3292 struct lock_struct lock
;
3295 START_PROFILE(SMBreadbraw
);
3297 if (srv_is_signing_active(sconn
) ||
3298 is_encrypted_packet(sconn
, req
->inbuf
)) {
3299 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3300 "raw reads/writes are disallowed.");
3304 reply_readbraw_error(sconn
);
3305 END_PROFILE(SMBreadbraw
);
3309 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3310 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3311 "'async smb echo handler = yes'\n"));
3312 reply_readbraw_error(sconn
);
3313 END_PROFILE(SMBreadbraw
);
3318 * Special check if an oplock break has been issued
3319 * and the readraw request croses on the wire, we must
3320 * return a zero length response here.
3323 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3326 * We have to do a check_fsp by hand here, as
3327 * we must always return 4 zero bytes on error,
3331 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3332 req
->vuid
!= fsp
->vuid
||
3333 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3335 * fsp could be NULL here so use the value from the packet. JRA.
3337 DEBUG(3,("reply_readbraw: fnum %d not valid "
3339 (int)SVAL(req
->vwv
+0, 0)));
3340 reply_readbraw_error(sconn
);
3341 END_PROFILE(SMBreadbraw
);
3345 /* Do a "by hand" version of CHECK_READ. */
3346 if (!(fsp
->can_read
||
3347 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3348 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3349 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3350 (int)SVAL(req
->vwv
+0, 0)));
3351 reply_readbraw_error(sconn
);
3352 END_PROFILE(SMBreadbraw
);
3356 flush_write_cache(fsp
, READRAW_FLUSH
);
3358 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3359 if(req
->wct
== 10) {
3361 * This is a large offset (64 bit) read.
3364 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3367 DEBUG(0,("reply_readbraw: negative 64 bit "
3368 "readraw offset (%.0f) !\n",
3369 (double)startpos
));
3370 reply_readbraw_error(sconn
);
3371 END_PROFILE(SMBreadbraw
);
3376 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3377 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3379 /* ensure we don't overrun the packet size */
3380 maxcount
= MIN(65535,maxcount
);
3382 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3383 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3386 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3387 reply_readbraw_error(sconn
);
3388 END_PROFILE(SMBreadbraw
);
3392 if (fsp_stat(fsp
) == 0) {
3393 size
= fsp
->fsp_name
->st
.st_ex_size
;
3396 if (startpos
>= size
) {
3399 nread
= MIN(maxcount
,(size
- startpos
));
3402 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3403 if (nread
< mincount
)
3407 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3408 "min=%lu nread=%lu\n",
3409 fsp_fnum_dbg(fsp
), (double)startpos
,
3410 (unsigned long)maxcount
,
3411 (unsigned long)mincount
,
3412 (unsigned long)nread
) );
3414 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3416 DEBUG(5,("reply_readbraw finished\n"));
3418 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3420 END_PROFILE(SMBreadbraw
);
3425 #define DBGC_CLASS DBGC_LOCKING
3427 /****************************************************************************
3428 Reply to a lockread (core+ protocol).
3429 ****************************************************************************/
3431 void reply_lockread(struct smb_request
*req
)
3433 connection_struct
*conn
= req
->conn
;
3440 struct byte_range_lock
*br_lck
= NULL
;
3442 struct smbd_server_connection
*sconn
= req
->sconn
;
3444 START_PROFILE(SMBlockread
);
3447 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3448 END_PROFILE(SMBlockread
);
3452 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3454 if (!check_fsp(conn
, req
, fsp
)) {
3455 END_PROFILE(SMBlockread
);
3459 if (!CHECK_READ(fsp
,req
)) {
3460 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3461 END_PROFILE(SMBlockread
);
3465 numtoread
= SVAL(req
->vwv
+1, 0);
3466 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3468 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3470 reply_outbuf(req
, 5, numtoread
+ 3);
3472 data
= smb_buf(req
->outbuf
) + 3;
3475 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3476 * protocol request that predates the read/write lock concept.
3477 * Thus instead of asking for a read lock here we need to ask
3478 * for a write lock. JRA.
3479 * Note that the requested lock size is unaffected by max_recv.
3482 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3484 (uint64_t)req
->smbpid
,
3485 (uint64_t)numtoread
,
3489 False
, /* Non-blocking lock. */
3493 TALLOC_FREE(br_lck
);
3495 if (NT_STATUS_V(status
)) {
3496 reply_nterror(req
, status
);
3497 END_PROFILE(SMBlockread
);
3502 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3505 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3506 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3507 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3508 (unsigned int)numtoread
,
3509 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3510 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3512 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3515 reply_nterror(req
, map_nt_error_from_unix(errno
));
3516 END_PROFILE(SMBlockread
);
3520 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3522 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3523 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3524 p
= smb_buf(req
->outbuf
);
3525 SCVAL(p
,0,0); /* pad byte. */
3528 DEBUG(3,("lockread %s num=%d nread=%d\n",
3529 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3531 END_PROFILE(SMBlockread
);
3536 #define DBGC_CLASS DBGC_ALL
3538 /****************************************************************************
3540 ****************************************************************************/
3542 void reply_read(struct smb_request
*req
)
3544 connection_struct
*conn
= req
->conn
;
3551 struct lock_struct lock
;
3552 struct smbd_server_connection
*sconn
= req
->sconn
;
3554 START_PROFILE(SMBread
);
3557 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3558 END_PROFILE(SMBread
);
3562 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3564 if (!check_fsp(conn
, req
, fsp
)) {
3565 END_PROFILE(SMBread
);
3569 if (!CHECK_READ(fsp
,req
)) {
3570 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3571 END_PROFILE(SMBread
);
3575 numtoread
= SVAL(req
->vwv
+1, 0);
3576 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3578 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3581 * The requested read size cannot be greater than max_recv. JRA.
3583 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3584 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3585 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3586 (unsigned int)numtoread
,
3587 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3588 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3591 reply_outbuf(req
, 5, numtoread
+3);
3593 data
= smb_buf(req
->outbuf
) + 3;
3595 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3596 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3599 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3600 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3601 END_PROFILE(SMBread
);
3606 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3609 reply_nterror(req
, map_nt_error_from_unix(errno
));
3613 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3615 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3616 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3617 SCVAL(smb_buf(req
->outbuf
),0,1);
3618 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3620 DEBUG(3, ("read %s num=%d nread=%d\n",
3621 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3624 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3626 END_PROFILE(SMBread
);
3630 /****************************************************************************
3632 ****************************************************************************/
3634 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3639 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3641 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3643 SCVAL(outbuf
,smb_vwv0
,0xFF);
3644 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3645 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3646 SSVAL(outbuf
,smb_vwv6
,
3647 (smb_wct
- 4) /* offset from smb header to wct */
3648 + 1 /* the wct field */
3649 + 12 * sizeof(uint16_t) /* vwv */
3650 + 2); /* the buflen field */
3651 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3652 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3653 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3654 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3658 /****************************************************************************
3659 Reply to a read and X - possibly using sendfile.
3660 ****************************************************************************/
3662 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3663 files_struct
*fsp
, off_t startpos
,
3667 struct lock_struct lock
;
3668 int saved_errno
= 0;
3670 if(fsp_stat(fsp
) == -1) {
3671 reply_nterror(req
, map_nt_error_from_unix(errno
));
3675 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3676 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3679 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3680 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3684 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3685 (startpos
> fsp
->fsp_name
->st
.st_ex_size
)
3686 || (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3688 * We already know that we would do a short read, so don't
3689 * try the sendfile() path.
3691 goto nosendfile_read
;
3695 * We can only use sendfile on a non-chained packet
3696 * but we can use on a non-oplocked file. tridge proved this
3697 * on a train in Germany :-). JRA.
3700 if (!req_is_in_chain(req
) &&
3701 !is_encrypted_packet(req
->sconn
, req
->inbuf
) &&
3702 (fsp
->base_fsp
== NULL
) &&
3703 (fsp
->wcp
== NULL
) &&
3704 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3705 uint8 headerbuf
[smb_size
+ 12 * 2];
3709 * Set up the packet header before send. We
3710 * assume here the sendfile will work (get the
3711 * correct amount of data).
3714 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3716 construct_reply_common_req(req
, (char *)headerbuf
);
3717 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3719 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3720 startpos
, smb_maxcnt
);
3722 /* Returning ENOSYS means no data at all was sent.
3723 Do this as a normal read. */
3724 if (errno
== ENOSYS
) {
3729 * Special hack for broken Linux with no working sendfile. If we
3730 * return EINTR we sent the header but not the rest of the data.
3731 * Fake this up by doing read/write calls.
3734 if (errno
== EINTR
) {
3735 /* Ensure we don't do this again. */
3736 set_use_sendfile(SNUM(conn
), False
);
3737 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3738 nread
= fake_sendfile(fsp
, startpos
,
3741 DEBUG(0,("send_file_readX: "
3742 "fake_sendfile failed for "
3746 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3748 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3749 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3750 /* No outbuf here means successful sendfile. */
3754 DEBUG(0,("send_file_readX: sendfile failed for file "
3755 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3757 exit_server_cleanly("send_file_readX sendfile failed");
3758 } else if (nread
== 0) {
3760 * Some sendfile implementations return 0 to indicate
3761 * that there was a short read, but nothing was
3762 * actually written to the socket. In this case,
3763 * fallback to the normal read path so the header gets
3764 * the correct byte count.
3766 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3767 "falling back to the normal read: %s\n",
3772 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3773 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3775 /* Deal with possible short send. */
3776 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3777 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3779 /* No outbuf here means successful sendfile. */
3780 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3781 SMB_PERFCOUNT_END(&req
->pcd
);
3787 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3788 uint8 headerbuf
[smb_size
+ 2*12];
3790 construct_reply_common_req(req
, (char *)headerbuf
);
3791 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3793 /* Send out the header. */
3794 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3795 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3797 char addr
[INET6_ADDRSTRLEN
];
3799 * Try and give an error message saying what
3802 DEBUG(0, ("write_data failed for client %s. "
3804 get_peer_addr(req
->sconn
->sock
, addr
,
3808 DEBUG(0,("send_file_readX: write_data failed for file "
3809 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3811 exit_server_cleanly("send_file_readX sendfile failed");
3813 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3815 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3816 "file %s (%s).\n", fsp_str_dbg(fsp
),
3818 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3825 reply_outbuf(req
, 12, smb_maxcnt
);
3826 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
3827 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
3829 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3830 saved_errno
= errno
;
3832 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3835 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3839 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3841 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3842 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3846 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3847 TALLOC_FREE(req
->outbuf
);
3851 /****************************************************************************
3852 MacOSX clients send large reads without telling us they are going to do that.
3853 Bug #9572 - File corruption during SMB1 read by Mac OSX 10.8.2 clients
3854 Allow this if we are talking to a Samba client, or if we told the client
3856 ****************************************************************************/
3858 static bool server_will_accept_large_read(void)
3860 /* Samba client ? No problem. */
3861 if (get_remote_arch() == RA_SAMBA
) {
3864 /* Need UNIX extensions. */
3865 if (!lp_unix_extensions()) {
3871 /****************************************************************************
3872 Reply to a read and X.
3873 ****************************************************************************/
3875 void reply_read_and_X(struct smb_request
*req
)
3877 connection_struct
*conn
= req
->conn
;
3882 bool big_readX
= False
;
3884 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3887 START_PROFILE(SMBreadX
);
3889 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3890 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3894 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3895 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3896 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3898 /* If it's an IPC, pass off the pipe handler. */
3900 reply_pipe_read_and_X(req
);
3901 END_PROFILE(SMBreadX
);
3905 if (!check_fsp(conn
, req
, fsp
)) {
3906 END_PROFILE(SMBreadX
);
3910 if (!CHECK_READ(fsp
,req
)) {
3911 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3912 END_PROFILE(SMBreadX
);
3916 upper_size
= SVAL(req
->vwv
+7, 0);
3917 if ((upper_size
!= 0) && server_will_accept_large_read()) {
3919 * This is Samba only behavior (up to Samba 3.6)!
3921 * Windows 2008 R2 ignores the upper_size,
3922 * so we do unless unix extentions are active
3923 * or "smbclient" is talking to us.
3925 smb_maxcnt
|= (upper_size
<<16);
3926 if (upper_size
> 1) {
3927 /* Can't do this on a chained packet. */
3928 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3929 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3930 END_PROFILE(SMBreadX
);
3933 /* We currently don't do this on signed or sealed data. */
3934 if (srv_is_signing_active(req
->sconn
) ||
3935 is_encrypted_packet(req
->sconn
, req
->inbuf
)) {
3936 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3937 END_PROFILE(SMBreadX
);
3940 /* Is there room in the reply for this data ? */
3941 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3943 NT_STATUS_INVALID_PARAMETER
);
3944 END_PROFILE(SMBreadX
);
3951 if (req
->wct
== 12) {
3953 * This is a large offset (64 bit) read.
3955 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
3960 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3965 if (NT_STATUS_IS_OK(status
)) {
3966 /* Read scheduled - we're done. */
3969 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3970 /* Real error - report to client. */
3971 END_PROFILE(SMBreadX
);
3972 reply_nterror(req
, status
);
3975 /* NT_STATUS_RETRY - fall back to sync read. */
3978 smbd_lock_socket(req
->sconn
);
3979 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3980 smbd_unlock_socket(req
->sconn
);
3983 END_PROFILE(SMBreadX
);
3987 /****************************************************************************
3988 Error replies to writebraw must have smb_wct == 1. Fix this up.
3989 ****************************************************************************/
3991 void error_to_writebrawerr(struct smb_request
*req
)
3993 uint8
*old_outbuf
= req
->outbuf
;
3995 reply_outbuf(req
, 1, 0);
3997 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3998 TALLOC_FREE(old_outbuf
);
4001 /****************************************************************************
4002 Read 4 bytes of a smb packet and return the smb length of the packet.
4003 Store the result in the buffer. This version of the function will
4004 never return a session keepalive (length of zero).
4005 Timeout is in milliseconds.
4006 ****************************************************************************/
4008 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4011 uint8_t msgtype
= NBSSkeepalive
;
4013 while (msgtype
== NBSSkeepalive
) {
4016 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4018 if (!NT_STATUS_IS_OK(status
)) {
4019 char addr
[INET6_ADDRSTRLEN
];
4020 /* Try and give an error message
4021 * saying what client failed. */
4022 DEBUG(0, ("read_fd_with_timeout failed for "
4023 "client %s read error = %s.\n",
4024 get_peer_addr(fd
,addr
,sizeof(addr
)),
4025 nt_errstr(status
)));
4029 msgtype
= CVAL(inbuf
, 0);
4032 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4033 (unsigned long)len
));
4035 return NT_STATUS_OK
;
4038 /****************************************************************************
4039 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4040 ****************************************************************************/
4042 void reply_writebraw(struct smb_request
*req
)
4044 connection_struct
*conn
= req
->conn
;
4047 ssize_t total_written
=0;
4048 size_t numtowrite
=0;
4051 const char *data
=NULL
;
4054 struct lock_struct lock
;
4057 START_PROFILE(SMBwritebraw
);
4060 * If we ever reply with an error, it must have the SMB command
4061 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4064 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4066 if (srv_is_signing_active(req
->sconn
)) {
4067 END_PROFILE(SMBwritebraw
);
4068 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4069 "raw reads/writes are disallowed.");
4072 if (req
->wct
< 12) {
4073 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4074 error_to_writebrawerr(req
);
4075 END_PROFILE(SMBwritebraw
);
4079 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
4080 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4081 "'async smb echo handler = yes'\n"));
4082 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4083 error_to_writebrawerr(req
);
4084 END_PROFILE(SMBwritebraw
);
4088 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4089 if (!check_fsp(conn
, req
, fsp
)) {
4090 error_to_writebrawerr(req
);
4091 END_PROFILE(SMBwritebraw
);
4095 if (!CHECK_WRITE(fsp
)) {
4096 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4097 error_to_writebrawerr(req
);
4098 END_PROFILE(SMBwritebraw
);
4102 tcount
= IVAL(req
->vwv
+1, 0);
4103 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4104 write_through
= BITSETW(req
->vwv
+7,0);
4106 /* We have to deal with slightly different formats depending
4107 on whether we are using the core+ or lanman1.0 protocol */
4109 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4110 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4111 data
= smb_buf_const(req
->inbuf
);
4113 numtowrite
= SVAL(req
->vwv
+10, 0);
4114 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4117 /* Ensure we don't write bytes past the end of this packet. */
4118 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4119 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4120 error_to_writebrawerr(req
);
4121 END_PROFILE(SMBwritebraw
);
4125 if (!fsp
->print_file
) {
4126 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4127 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4130 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4131 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4132 error_to_writebrawerr(req
);
4133 END_PROFILE(SMBwritebraw
);
4139 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4142 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4143 "wrote=%d sync=%d\n",
4144 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4145 (int)nwritten
, (int)write_through
));
4147 if (nwritten
< (ssize_t
)numtowrite
) {
4148 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4149 error_to_writebrawerr(req
);
4153 total_written
= nwritten
;
4155 /* Allocate a buffer of 64k + length. */
4156 buf
= talloc_array(NULL
, char, 65540);
4158 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4159 error_to_writebrawerr(req
);
4163 /* Return a SMBwritebraw message to the redirector to tell
4164 * it to send more bytes */
4166 memcpy(buf
, req
->inbuf
, smb_size
);
4167 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4168 SCVAL(buf
,smb_com
,SMBwritebraw
);
4169 SSVALS(buf
,smb_vwv0
,0xFFFF);
4171 if (!srv_send_smb(req
->sconn
,
4173 false, 0, /* no signing */
4174 IS_CONN_ENCRYPTED(conn
),
4176 exit_server_cleanly("reply_writebraw: srv_send_smb "
4180 /* Now read the raw data into the buffer and write it */
4181 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4183 if (!NT_STATUS_IS_OK(status
)) {
4184 exit_server_cleanly("secondary writebraw failed");
4187 /* Set up outbuf to return the correct size */
4188 reply_outbuf(req
, 1, 0);
4190 if (numtowrite
!= 0) {
4192 if (numtowrite
> 0xFFFF) {
4193 DEBUG(0,("reply_writebraw: Oversize secondary write "
4194 "raw requested (%u). Terminating\n",
4195 (unsigned int)numtowrite
));
4196 exit_server_cleanly("secondary writebraw failed");
4199 if (tcount
> nwritten
+numtowrite
) {
4200 DEBUG(3,("reply_writebraw: Client overestimated the "
4202 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4205 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4207 if (!NT_STATUS_IS_OK(status
)) {
4208 char addr
[INET6_ADDRSTRLEN
];
4209 /* Try and give an error message
4210 * saying what client failed. */
4211 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4212 "raw read failed (%s) for client %s. "
4213 "Terminating\n", nt_errstr(status
),
4214 get_peer_addr(req
->sconn
->sock
, addr
,
4216 exit_server_cleanly("secondary writebraw failed");
4219 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4220 if (nwritten
== -1) {
4222 reply_nterror(req
, map_nt_error_from_unix(errno
));
4223 error_to_writebrawerr(req
);
4227 if (nwritten
< (ssize_t
)numtowrite
) {
4228 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4229 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4233 total_written
+= nwritten
;
4238 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4240 status
= sync_file(conn
, fsp
, write_through
);
4241 if (!NT_STATUS_IS_OK(status
)) {
4242 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4243 fsp_str_dbg(fsp
), nt_errstr(status
)));
4244 reply_nterror(req
, status
);
4245 error_to_writebrawerr(req
);
4249 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4251 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4252 (int)total_written
));
4254 if (!fsp
->print_file
) {
4255 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4258 /* We won't return a status if write through is not selected - this
4259 * follows what WfWg does */
4260 END_PROFILE(SMBwritebraw
);
4262 if (!write_through
&& total_written
==tcount
) {
4264 #if RABBIT_PELLET_FIX
4266 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4267 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4270 if (!send_keepalive(req
->sconn
->sock
)) {
4271 exit_server_cleanly("reply_writebraw: send of "
4272 "keepalive failed");
4275 TALLOC_FREE(req
->outbuf
);
4280 if (!fsp
->print_file
) {
4281 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4284 END_PROFILE(SMBwritebraw
);
4289 #define DBGC_CLASS DBGC_LOCKING
4291 /****************************************************************************
4292 Reply to a writeunlock (core+).
4293 ****************************************************************************/
4295 void reply_writeunlock(struct smb_request
*req
)
4297 connection_struct
*conn
= req
->conn
;
4298 ssize_t nwritten
= -1;
4302 NTSTATUS status
= NT_STATUS_OK
;
4304 struct lock_struct lock
;
4305 int saved_errno
= 0;
4307 START_PROFILE(SMBwriteunlock
);
4310 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4311 END_PROFILE(SMBwriteunlock
);
4315 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4317 if (!check_fsp(conn
, req
, fsp
)) {
4318 END_PROFILE(SMBwriteunlock
);
4322 if (!CHECK_WRITE(fsp
)) {
4323 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4324 END_PROFILE(SMBwriteunlock
);
4328 numtowrite
= SVAL(req
->vwv
+1, 0);
4329 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4330 data
= (const char *)req
->buf
+ 3;
4332 if (!fsp
->print_file
&& numtowrite
> 0) {
4333 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4334 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4337 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4338 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4339 END_PROFILE(SMBwriteunlock
);
4344 /* The special X/Open SMB protocol handling of
4345 zero length writes is *NOT* done for
4347 if(numtowrite
== 0) {
4350 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4351 saved_errno
= errno
;
4354 status
= sync_file(conn
, fsp
, False
/* write through */);
4355 if (!NT_STATUS_IS_OK(status
)) {
4356 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4357 fsp_str_dbg(fsp
), nt_errstr(status
)));
4358 reply_nterror(req
, status
);
4363 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4367 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4368 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4372 if (numtowrite
&& !fsp
->print_file
) {
4373 status
= do_unlock(req
->sconn
->msg_ctx
,
4375 (uint64_t)req
->smbpid
,
4376 (uint64_t)numtowrite
,
4380 if (NT_STATUS_V(status
)) {
4381 reply_nterror(req
, status
);
4386 reply_outbuf(req
, 1, 0);
4388 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4390 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4391 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4394 if (numtowrite
&& !fsp
->print_file
) {
4395 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4398 END_PROFILE(SMBwriteunlock
);
4403 #define DBGC_CLASS DBGC_ALL
4405 /****************************************************************************
4407 ****************************************************************************/
4409 void reply_write(struct smb_request
*req
)
4411 connection_struct
*conn
= req
->conn
;
4413 ssize_t nwritten
= -1;
4417 struct lock_struct lock
;
4419 int saved_errno
= 0;
4421 START_PROFILE(SMBwrite
);
4424 END_PROFILE(SMBwrite
);
4425 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4429 /* If it's an IPC, pass off the pipe handler. */
4431 reply_pipe_write(req
);
4432 END_PROFILE(SMBwrite
);
4436 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4438 if (!check_fsp(conn
, req
, fsp
)) {
4439 END_PROFILE(SMBwrite
);
4443 if (!CHECK_WRITE(fsp
)) {
4444 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4445 END_PROFILE(SMBwrite
);
4449 numtowrite
= SVAL(req
->vwv
+1, 0);
4450 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4451 data
= (const char *)req
->buf
+ 3;
4453 if (!fsp
->print_file
) {
4454 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4455 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4458 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4459 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4460 END_PROFILE(SMBwrite
);
4466 * X/Open SMB protocol says that if smb_vwv1 is
4467 * zero then the file size should be extended or
4468 * truncated to the size given in smb_vwv[2-3].
4471 if(numtowrite
== 0) {
4473 * This is actually an allocate call, and set EOF. JRA.
4475 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4477 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4480 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4482 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4485 trigger_write_time_update_immediate(fsp
);
4487 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4490 status
= sync_file(conn
, fsp
, False
);
4491 if (!NT_STATUS_IS_OK(status
)) {
4492 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4493 fsp_str_dbg(fsp
), nt_errstr(status
)));
4494 reply_nterror(req
, status
);
4499 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4503 if((nwritten
== 0) && (numtowrite
!= 0)) {
4504 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4508 reply_outbuf(req
, 1, 0);
4510 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4512 if (nwritten
< (ssize_t
)numtowrite
) {
4513 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4514 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4517 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4520 if (!fsp
->print_file
) {
4521 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4524 END_PROFILE(SMBwrite
);
4528 /****************************************************************************
4529 Ensure a buffer is a valid writeX for recvfile purposes.
4530 ****************************************************************************/
4532 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4533 (2*14) + /* word count (including bcc) */ \
4536 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4537 const uint8_t *inbuf
)
4540 connection_struct
*conn
= NULL
;
4541 unsigned int doff
= 0;
4542 size_t len
= smb_len_large(inbuf
);
4543 struct smbXsrv_tcon
*tcon
;
4547 if (is_encrypted_packet(sconn
, inbuf
)) {
4548 /* Can't do this on encrypted
4553 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4557 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4558 CVAL(inbuf
,smb_wct
) != 14) {
4559 DEBUG(10,("is_valid_writeX_buffer: chained or "
4560 "invalid word length.\n"));
4564 status
= smb1srv_tcon_lookup(sconn
->conn
, SVAL(inbuf
, smb_tid
),
4566 if (!NT_STATUS_IS_OK(status
)) {
4567 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4570 conn
= tcon
->compat
;
4573 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4576 if (IS_PRINT(conn
)) {
4577 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4580 doff
= SVAL(inbuf
,smb_vwv11
);
4582 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4584 if (len
> doff
&& len
- doff
> 0xFFFF) {
4585 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4588 if (numtowrite
== 0) {
4589 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4593 /* Ensure the sizes match up. */
4594 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4595 /* no pad byte...old smbclient :-( */
4596 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4598 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4602 if (len
- doff
!= numtowrite
) {
4603 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4604 "len = %u, doff = %u, numtowrite = %u\n",
4607 (unsigned int)numtowrite
));
4611 DEBUG(10,("is_valid_writeX_buffer: true "
4612 "len = %u, doff = %u, numtowrite = %u\n",
4615 (unsigned int)numtowrite
));
4620 /****************************************************************************
4621 Reply to a write and X.
4622 ****************************************************************************/
4624 void reply_write_and_X(struct smb_request
*req
)
4626 connection_struct
*conn
= req
->conn
;
4628 struct lock_struct lock
;
4633 unsigned int smb_doff
;
4634 unsigned int smblen
;
4637 int saved_errno
= 0;
4639 START_PROFILE(SMBwriteX
);
4641 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4642 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4646 numtowrite
= SVAL(req
->vwv
+10, 0);
4647 smb_doff
= SVAL(req
->vwv
+11, 0);
4648 smblen
= smb_len(req
->inbuf
);
4650 if (req
->unread_bytes
> 0xFFFF ||
4651 (smblen
> smb_doff
&&
4652 smblen
- smb_doff
> 0xFFFF)) {
4653 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4656 if (req
->unread_bytes
) {
4657 /* Can't do a recvfile write on IPC$ */
4659 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4662 if (numtowrite
!= req
->unread_bytes
) {
4663 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4667 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4668 smb_doff
+ numtowrite
> smblen
) {
4669 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4674 /* If it's an IPC, pass off the pipe handler. */
4676 if (req
->unread_bytes
) {
4677 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4680 reply_pipe_write_and_X(req
);
4684 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4685 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4686 write_through
= BITSETW(req
->vwv
+7,0);
4688 if (!check_fsp(conn
, req
, fsp
)) {
4692 if (!CHECK_WRITE(fsp
)) {
4693 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4697 data
= smb_base(req
->inbuf
) + smb_doff
;
4699 if(req
->wct
== 14) {
4701 * This is a large offset (64 bit) write.
4703 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
4707 /* X/Open SMB protocol says that, unlike SMBwrite
4708 if the length is zero then NO truncation is
4709 done, just a write of zero. To truncate a file,
4712 if(numtowrite
== 0) {
4715 if (req
->unread_bytes
== 0) {
4716 status
= schedule_aio_write_and_X(conn
,
4723 if (NT_STATUS_IS_OK(status
)) {
4724 /* write scheduled - we're done. */
4727 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4728 /* Real error - report to client. */
4729 reply_nterror(req
, status
);
4732 /* NT_STATUS_RETRY - fall through to sync write. */
4735 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4736 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4739 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4740 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4744 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4745 saved_errno
= errno
;
4747 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4751 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4755 if((nwritten
== 0) && (numtowrite
!= 0)) {
4756 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4760 reply_outbuf(req
, 6, 0);
4761 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4762 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4763 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4764 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4766 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4767 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4769 status
= sync_file(conn
, fsp
, write_through
);
4770 if (!NT_STATUS_IS_OK(status
)) {
4771 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4772 fsp_str_dbg(fsp
), nt_errstr(status
)));
4773 reply_nterror(req
, status
);
4777 END_PROFILE(SMBwriteX
);
4781 if (req
->unread_bytes
) {
4782 /* writeX failed. drain socket. */
4783 if (drain_socket(req
->sconn
->sock
, req
->unread_bytes
) !=
4784 req
->unread_bytes
) {
4785 smb_panic("failed to drain pending bytes");
4787 req
->unread_bytes
= 0;
4790 END_PROFILE(SMBwriteX
);
4794 /****************************************************************************
4796 ****************************************************************************/
4798 void reply_lseek(struct smb_request
*req
)
4800 connection_struct
*conn
= req
->conn
;
4806 START_PROFILE(SMBlseek
);
4809 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4810 END_PROFILE(SMBlseek
);
4814 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4816 if (!check_fsp(conn
, req
, fsp
)) {
4820 flush_write_cache(fsp
, SEEK_FLUSH
);
4822 mode
= SVAL(req
->vwv
+1, 0) & 3;
4823 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4824 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
4833 res
= fsp
->fh
->pos
+ startpos
;
4844 if (umode
== SEEK_END
) {
4845 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4846 if(errno
== EINVAL
) {
4847 off_t current_pos
= startpos
;
4849 if(fsp_stat(fsp
) == -1) {
4851 map_nt_error_from_unix(errno
));
4852 END_PROFILE(SMBlseek
);
4856 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4858 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4863 reply_nterror(req
, map_nt_error_from_unix(errno
));
4864 END_PROFILE(SMBlseek
);
4871 reply_outbuf(req
, 2, 0);
4872 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4874 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4875 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
4877 END_PROFILE(SMBlseek
);
4881 /****************************************************************************
4883 ****************************************************************************/
4885 void reply_flush(struct smb_request
*req
)
4887 connection_struct
*conn
= req
->conn
;
4891 START_PROFILE(SMBflush
);
4894 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4898 fnum
= SVAL(req
->vwv
+0, 0);
4899 fsp
= file_fsp(req
, fnum
);
4901 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4906 file_sync_all(conn
);
4908 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4909 if (!NT_STATUS_IS_OK(status
)) {
4910 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4911 fsp_str_dbg(fsp
), nt_errstr(status
)));
4912 reply_nterror(req
, status
);
4913 END_PROFILE(SMBflush
);
4918 reply_outbuf(req
, 0, 0);
4920 DEBUG(3,("flush\n"));
4921 END_PROFILE(SMBflush
);
4925 /****************************************************************************
4927 conn POINTER CAN BE NULL HERE !
4928 ****************************************************************************/
4930 void reply_exit(struct smb_request
*req
)
4932 START_PROFILE(SMBexit
);
4934 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
4936 reply_outbuf(req
, 0, 0);
4938 DEBUG(3,("exit\n"));
4940 END_PROFILE(SMBexit
);
4944 struct reply_close_state
{
4946 struct smb_request
*smbreq
;
4949 static void do_smb1_close(struct tevent_req
*req
);
4951 void reply_close(struct smb_request
*req
)
4953 connection_struct
*conn
= req
->conn
;
4954 NTSTATUS status
= NT_STATUS_OK
;
4955 files_struct
*fsp
= NULL
;
4956 START_PROFILE(SMBclose
);
4959 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4960 END_PROFILE(SMBclose
);
4964 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4967 * We can only use check_fsp if we know it's not a directory.
4970 if (!check_fsp_open(conn
, req
, fsp
)) {
4971 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4972 END_PROFILE(SMBclose
);
4976 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
4977 fsp
->is_directory
? "directory" : "file",
4978 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
4979 conn
->num_files_open
));
4981 if (!fsp
->is_directory
) {
4985 * Take care of any time sent in the close.
4988 t
= srv_make_unix_date3(req
->vwv
+1);
4989 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4992 if (fsp
->num_aio_requests
!= 0) {
4994 struct reply_close_state
*state
;
4996 DEBUG(10, ("closing with aio %u requests pending\n",
4997 fsp
->num_aio_requests
));
5000 * We depend on the aio_extra destructor to take care of this
5001 * close request once fsp->num_aio_request drops to 0.
5004 fsp
->deferred_close
= tevent_wait_send(
5005 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5006 if (fsp
->deferred_close
== NULL
) {
5007 status
= NT_STATUS_NO_MEMORY
;
5011 state
= talloc(fsp
, struct reply_close_state
);
5012 if (state
== NULL
) {
5013 TALLOC_FREE(fsp
->deferred_close
);
5014 status
= NT_STATUS_NO_MEMORY
;
5018 state
->smbreq
= talloc_move(fsp
, &req
);
5019 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5021 END_PROFILE(SMBclose
);
5026 * close_file() returns the unix errno if an error was detected on
5027 * close - normally this is due to a disk full error. If not then it
5028 * was probably an I/O error.
5031 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5033 if (!NT_STATUS_IS_OK(status
)) {
5034 reply_nterror(req
, status
);
5035 END_PROFILE(SMBclose
);
5039 reply_outbuf(req
, 0, 0);
5040 END_PROFILE(SMBclose
);
5044 static void do_smb1_close(struct tevent_req
*req
)
5046 struct reply_close_state
*state
= tevent_req_callback_data(
5047 req
, struct reply_close_state
);
5048 struct smb_request
*smbreq
;
5052 ret
= tevent_wait_recv(req
);
5055 DEBUG(10, ("tevent_wait_recv returned %s\n",
5058 * Continue anyway, this should never happen
5063 * fsp->smb2_close_request right now is a talloc grandchild of
5064 * fsp. When we close_file(fsp), it would go with it. No chance to
5067 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5069 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5070 if (NT_STATUS_IS_OK(status
)) {
5071 reply_outbuf(smbreq
, 0, 0);
5073 reply_nterror(smbreq
, status
);
5075 if (!srv_send_smb(smbreq
->sconn
,
5076 (char *)smbreq
->outbuf
,
5079 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5081 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5084 TALLOC_FREE(smbreq
);
5087 /****************************************************************************
5088 Reply to a writeclose (Core+ protocol).
5089 ****************************************************************************/
5091 void reply_writeclose(struct smb_request
*req
)
5093 connection_struct
*conn
= req
->conn
;
5095 ssize_t nwritten
= -1;
5096 NTSTATUS close_status
= NT_STATUS_OK
;
5099 struct timespec mtime
;
5101 struct lock_struct lock
;
5103 START_PROFILE(SMBwriteclose
);
5106 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5107 END_PROFILE(SMBwriteclose
);
5111 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5113 if (!check_fsp(conn
, req
, fsp
)) {
5114 END_PROFILE(SMBwriteclose
);
5117 if (!CHECK_WRITE(fsp
)) {
5118 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5119 END_PROFILE(SMBwriteclose
);
5123 numtowrite
= SVAL(req
->vwv
+1, 0);
5124 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5125 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5126 data
= (const char *)req
->buf
+ 1;
5128 if (!fsp
->print_file
) {
5129 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5130 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5133 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5134 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5135 END_PROFILE(SMBwriteclose
);
5140 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5142 set_close_write_time(fsp
, mtime
);
5145 * More insanity. W2K only closes the file if writelen > 0.
5150 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5151 "file %s\n", fsp_str_dbg(fsp
)));
5152 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5155 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5156 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5157 conn
->num_files_open
));
5159 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5160 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5164 if(!NT_STATUS_IS_OK(close_status
)) {
5165 reply_nterror(req
, close_status
);
5169 reply_outbuf(req
, 1, 0);
5171 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5174 if (numtowrite
&& !fsp
->print_file
) {
5175 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5178 END_PROFILE(SMBwriteclose
);
5183 #define DBGC_CLASS DBGC_LOCKING
5185 /****************************************************************************
5187 ****************************************************************************/
5189 void reply_lock(struct smb_request
*req
)
5191 connection_struct
*conn
= req
->conn
;
5192 uint64_t count
,offset
;
5195 struct byte_range_lock
*br_lck
= NULL
;
5197 START_PROFILE(SMBlock
);
5200 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5201 END_PROFILE(SMBlock
);
5205 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5207 if (!check_fsp(conn
, req
, fsp
)) {
5208 END_PROFILE(SMBlock
);
5212 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5213 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5215 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5216 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5218 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5220 (uint64_t)req
->smbpid
,
5225 False
, /* Non-blocking lock. */
5230 TALLOC_FREE(br_lck
);
5232 if (NT_STATUS_V(status
)) {
5233 reply_nterror(req
, status
);
5234 END_PROFILE(SMBlock
);
5238 reply_outbuf(req
, 0, 0);
5240 END_PROFILE(SMBlock
);
5244 /****************************************************************************
5246 ****************************************************************************/
5248 void reply_unlock(struct smb_request
*req
)
5250 connection_struct
*conn
= req
->conn
;
5251 uint64_t count
,offset
;
5255 START_PROFILE(SMBunlock
);
5258 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5259 END_PROFILE(SMBunlock
);
5263 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5265 if (!check_fsp(conn
, req
, fsp
)) {
5266 END_PROFILE(SMBunlock
);
5270 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5271 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5273 status
= do_unlock(req
->sconn
->msg_ctx
,
5275 (uint64_t)req
->smbpid
,
5280 if (NT_STATUS_V(status
)) {
5281 reply_nterror(req
, status
);
5282 END_PROFILE(SMBunlock
);
5286 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5287 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5289 reply_outbuf(req
, 0, 0);
5291 END_PROFILE(SMBunlock
);
5296 #define DBGC_CLASS DBGC_ALL
5298 /****************************************************************************
5300 conn POINTER CAN BE NULL HERE !
5301 ****************************************************************************/
5303 void reply_tdis(struct smb_request
*req
)
5306 connection_struct
*conn
= req
->conn
;
5307 struct smbXsrv_tcon
*tcon
;
5309 START_PROFILE(SMBtdis
);
5312 DEBUG(4,("Invalid connection in tdis\n"));
5313 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5314 END_PROFILE(SMBtdis
);
5322 * TODO: cancel all outstanding requests on the tcon
5324 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5325 if (!NT_STATUS_IS_OK(status
)) {
5326 DEBUG(0, ("reply_tdis: "
5327 "smbXsrv_tcon_disconnect() failed: %s\n",
5328 nt_errstr(status
)));
5330 * If we hit this case, there is something completely
5331 * wrong, so we better disconnect the transport connection.
5333 END_PROFILE(SMBtdis
);
5334 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5340 reply_outbuf(req
, 0, 0);
5341 END_PROFILE(SMBtdis
);
5345 /****************************************************************************
5347 conn POINTER CAN BE NULL HERE !
5348 ****************************************************************************/
5350 void reply_echo(struct smb_request
*req
)
5352 connection_struct
*conn
= req
->conn
;
5353 struct smb_perfcount_data local_pcd
;
5354 struct smb_perfcount_data
*cur_pcd
;
5358 START_PROFILE(SMBecho
);
5360 smb_init_perfcount_data(&local_pcd
);
5363 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5364 END_PROFILE(SMBecho
);
5368 smb_reverb
= SVAL(req
->vwv
+0, 0);
5370 reply_outbuf(req
, 1, req
->buflen
);
5372 /* copy any incoming data back out */
5373 if (req
->buflen
> 0) {
5374 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5377 if (smb_reverb
> 100) {
5378 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5382 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5384 /* this makes sure we catch the request pcd */
5385 if (seq_num
== smb_reverb
) {
5386 cur_pcd
= &req
->pcd
;
5388 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5389 cur_pcd
= &local_pcd
;
5392 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5394 show_msg((char *)req
->outbuf
);
5395 if (!srv_send_smb(req
->sconn
,
5396 (char *)req
->outbuf
,
5397 true, req
->seqnum
+1,
5398 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5400 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5403 DEBUG(3,("echo %d times\n", smb_reverb
));
5405 TALLOC_FREE(req
->outbuf
);
5407 END_PROFILE(SMBecho
);
5411 /****************************************************************************
5412 Reply to a printopen.
5413 ****************************************************************************/
5415 void reply_printopen(struct smb_request
*req
)
5417 connection_struct
*conn
= req
->conn
;
5421 START_PROFILE(SMBsplopen
);
5424 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5425 END_PROFILE(SMBsplopen
);
5429 if (!CAN_PRINT(conn
)) {
5430 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5431 END_PROFILE(SMBsplopen
);
5435 status
= file_new(req
, conn
, &fsp
);
5436 if(!NT_STATUS_IS_OK(status
)) {
5437 reply_nterror(req
, status
);
5438 END_PROFILE(SMBsplopen
);
5442 /* Open for exclusive use, write only. */
5443 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5445 if (!NT_STATUS_IS_OK(status
)) {
5446 file_free(req
, fsp
);
5447 reply_nterror(req
, status
);
5448 END_PROFILE(SMBsplopen
);
5452 reply_outbuf(req
, 1, 0);
5453 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5455 DEBUG(3,("openprint fd=%d %s\n",
5456 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5458 END_PROFILE(SMBsplopen
);
5462 /****************************************************************************
5463 Reply to a printclose.
5464 ****************************************************************************/
5466 void reply_printclose(struct smb_request
*req
)
5468 connection_struct
*conn
= req
->conn
;
5472 START_PROFILE(SMBsplclose
);
5475 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5476 END_PROFILE(SMBsplclose
);
5480 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5482 if (!check_fsp(conn
, req
, fsp
)) {
5483 END_PROFILE(SMBsplclose
);
5487 if (!CAN_PRINT(conn
)) {
5488 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5489 END_PROFILE(SMBsplclose
);
5493 DEBUG(3,("printclose fd=%d %s\n",
5494 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5496 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5498 if(!NT_STATUS_IS_OK(status
)) {
5499 reply_nterror(req
, status
);
5500 END_PROFILE(SMBsplclose
);
5504 reply_outbuf(req
, 0, 0);
5506 END_PROFILE(SMBsplclose
);
5510 /****************************************************************************
5511 Reply to a printqueue.
5512 ****************************************************************************/
5514 void reply_printqueue(struct smb_request
*req
)
5516 connection_struct
*conn
= req
->conn
;
5520 START_PROFILE(SMBsplretq
);
5523 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5524 END_PROFILE(SMBsplretq
);
5528 max_count
= SVAL(req
->vwv
+0, 0);
5529 start_index
= SVAL(req
->vwv
+1, 0);
5531 /* we used to allow the client to get the cnum wrong, but that
5532 is really quite gross and only worked when there was only
5533 one printer - I think we should now only accept it if they
5534 get it right (tridge) */
5535 if (!CAN_PRINT(conn
)) {
5536 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5537 END_PROFILE(SMBsplretq
);
5541 reply_outbuf(req
, 2, 3);
5542 SSVAL(req
->outbuf
,smb_vwv0
,0);
5543 SSVAL(req
->outbuf
,smb_vwv1
,0);
5544 SCVAL(smb_buf(req
->outbuf
),0,1);
5545 SSVAL(smb_buf(req
->outbuf
),1,0);
5547 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5548 start_index
, max_count
));
5551 TALLOC_CTX
*mem_ctx
= talloc_tos();
5554 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5555 struct rpc_pipe_client
*cli
= NULL
;
5556 struct dcerpc_binding_handle
*b
= NULL
;
5557 struct policy_handle handle
;
5558 struct spoolss_DevmodeContainer devmode_ctr
;
5559 union spoolss_JobInfo
*info
;
5561 uint32_t num_to_get
;
5565 ZERO_STRUCT(handle
);
5567 status
= rpc_pipe_open_interface(conn
,
5568 &ndr_table_spoolss
.syntax_id
,
5570 conn
->sconn
->remote_address
,
5571 conn
->sconn
->msg_ctx
,
5573 if (!NT_STATUS_IS_OK(status
)) {
5574 DEBUG(0, ("reply_printqueue: "
5575 "could not connect to spoolss: %s\n",
5576 nt_errstr(status
)));
5577 reply_nterror(req
, status
);
5580 b
= cli
->binding_handle
;
5582 ZERO_STRUCT(devmode_ctr
);
5584 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5587 SEC_FLAG_MAXIMUM_ALLOWED
,
5590 if (!NT_STATUS_IS_OK(status
)) {
5591 reply_nterror(req
, status
);
5594 if (!W_ERROR_IS_OK(werr
)) {
5595 reply_nterror(req
, werror_to_ntstatus(werr
));
5599 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5607 if (!W_ERROR_IS_OK(werr
)) {
5608 reply_nterror(req
, werror_to_ntstatus(werr
));
5612 if (max_count
> 0) {
5613 first
= start_index
;
5615 first
= start_index
+ max_count
+ 1;
5618 if (first
>= count
) {
5621 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5624 for (i
= first
; i
< num_to_get
; i
++) {
5627 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5629 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5630 info
[i
].info2
.job_id
);
5632 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5638 srv_put_dos_date2(p
, 0, qtime
);
5639 SCVAL(p
, 4, qstatus
);
5640 SSVAL(p
, 5, qrapjobid
);
5641 SIVAL(p
, 7, info
[i
].info2
.size
);
5643 srvstr_push(blob
, req
->flags2
, p
+12,
5644 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5646 if (message_push_blob(
5649 blob
, sizeof(blob
))) == -1) {
5650 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5656 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5657 SSVAL(req
->outbuf
,smb_vwv1
,
5658 (max_count
>0?first
+count
:first
-1));
5659 SCVAL(smb_buf(req
->outbuf
),0,1);
5660 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5664 DEBUG(3, ("%u entries returned in queue\n",
5668 if (b
&& is_valid_policy_hnd(&handle
)) {
5669 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5674 END_PROFILE(SMBsplretq
);
5678 /****************************************************************************
5679 Reply to a printwrite.
5680 ****************************************************************************/
5682 void reply_printwrite(struct smb_request
*req
)
5684 connection_struct
*conn
= req
->conn
;
5689 START_PROFILE(SMBsplwr
);
5692 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5693 END_PROFILE(SMBsplwr
);
5697 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5699 if (!check_fsp(conn
, req
, fsp
)) {
5700 END_PROFILE(SMBsplwr
);
5704 if (!fsp
->print_file
) {
5705 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5706 END_PROFILE(SMBsplwr
);
5710 if (!CHECK_WRITE(fsp
)) {
5711 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5712 END_PROFILE(SMBsplwr
);
5716 numtowrite
= SVAL(req
->buf
, 1);
5718 if (req
->buflen
< numtowrite
+ 3) {
5719 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5720 END_PROFILE(SMBsplwr
);
5724 data
= (const char *)req
->buf
+ 3;
5726 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
5727 reply_nterror(req
, map_nt_error_from_unix(errno
));
5728 END_PROFILE(SMBsplwr
);
5732 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
5734 END_PROFILE(SMBsplwr
);
5738 /****************************************************************************
5740 ****************************************************************************/
5742 void reply_mkdir(struct smb_request
*req
)
5744 connection_struct
*conn
= req
->conn
;
5745 struct smb_filename
*smb_dname
= NULL
;
5746 char *directory
= NULL
;
5748 TALLOC_CTX
*ctx
= talloc_tos();
5750 START_PROFILE(SMBmkdir
);
5752 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5753 STR_TERMINATE
, &status
);
5754 if (!NT_STATUS_IS_OK(status
)) {
5755 reply_nterror(req
, status
);
5759 status
= filename_convert(ctx
, conn
,
5760 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5765 if (!NT_STATUS_IS_OK(status
)) {
5766 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5767 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5768 ERRSRV
, ERRbadpath
);
5771 reply_nterror(req
, status
);
5775 status
= create_directory(conn
, req
, smb_dname
);
5777 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5779 if (!NT_STATUS_IS_OK(status
)) {
5781 if (!use_nt_status()
5782 && NT_STATUS_EQUAL(status
,
5783 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5785 * Yes, in the DOS error code case we get a
5786 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5787 * samba4 torture test.
5789 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5792 reply_nterror(req
, status
);
5796 reply_outbuf(req
, 0, 0);
5798 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5800 TALLOC_FREE(smb_dname
);
5801 END_PROFILE(SMBmkdir
);
5805 /****************************************************************************
5807 ****************************************************************************/
5809 void reply_rmdir(struct smb_request
*req
)
5811 connection_struct
*conn
= req
->conn
;
5812 struct smb_filename
*smb_dname
= NULL
;
5813 char *directory
= NULL
;
5815 TALLOC_CTX
*ctx
= talloc_tos();
5816 files_struct
*fsp
= NULL
;
5818 struct smbd_server_connection
*sconn
= req
->sconn
;
5820 START_PROFILE(SMBrmdir
);
5822 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5823 STR_TERMINATE
, &status
);
5824 if (!NT_STATUS_IS_OK(status
)) {
5825 reply_nterror(req
, status
);
5829 status
= filename_convert(ctx
, conn
,
5830 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5835 if (!NT_STATUS_IS_OK(status
)) {
5836 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5837 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5838 ERRSRV
, ERRbadpath
);
5841 reply_nterror(req
, status
);
5845 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5846 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5850 status
= SMB_VFS_CREATE_FILE(
5853 0, /* root_dir_fid */
5854 smb_dname
, /* fname */
5855 DELETE_ACCESS
, /* access_mask */
5856 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5858 FILE_OPEN
, /* create_disposition*/
5859 FILE_DIRECTORY_FILE
, /* create_options */
5860 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5861 0, /* oplock_request */
5862 0, /* allocation_size */
5863 0, /* private_flags */
5869 if (!NT_STATUS_IS_OK(status
)) {
5870 if (open_was_deferred(req
->sconn
, req
->mid
)) {
5871 /* We have re-scheduled this call. */
5874 reply_nterror(req
, status
);
5878 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5879 if (!NT_STATUS_IS_OK(status
)) {
5880 close_file(req
, fsp
, ERROR_CLOSE
);
5881 reply_nterror(req
, status
);
5885 if (!set_delete_on_close(fsp
, true,
5886 conn
->session_info
->security_token
,
5887 conn
->session_info
->unix_token
)) {
5888 close_file(req
, fsp
, ERROR_CLOSE
);
5889 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5893 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5894 if (!NT_STATUS_IS_OK(status
)) {
5895 reply_nterror(req
, status
);
5897 reply_outbuf(req
, 0, 0);
5900 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5902 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5904 TALLOC_FREE(smb_dname
);
5905 END_PROFILE(SMBrmdir
);
5909 /*******************************************************************
5910 Resolve wildcards in a filename rename.
5911 ********************************************************************/
5913 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5918 char *name2_copy
= NULL
;
5923 char *p
,*p2
, *pname1
, *pname2
;
5925 name2_copy
= talloc_strdup(ctx
, name2
);
5930 pname1
= strrchr_m(name1
,'/');
5931 pname2
= strrchr_m(name2_copy
,'/');
5933 if (!pname1
|| !pname2
) {
5937 /* Truncate the copy of name2 at the last '/' */
5940 /* Now go past the '/' */
5944 root1
= talloc_strdup(ctx
, pname1
);
5945 root2
= talloc_strdup(ctx
, pname2
);
5947 if (!root1
|| !root2
) {
5951 p
= strrchr_m(root1
,'.');
5954 ext1
= talloc_strdup(ctx
, p
+1);
5956 ext1
= talloc_strdup(ctx
, "");
5958 p
= strrchr_m(root2
,'.');
5961 ext2
= talloc_strdup(ctx
, p
+1);
5963 ext2
= talloc_strdup(ctx
, "");
5966 if (!ext1
|| !ext2
) {
5974 /* Hmmm. Should this be mb-aware ? */
5977 } else if (*p2
== '*') {
5979 root2
= talloc_asprintf(ctx
, "%s%s",
5998 /* Hmmm. Should this be mb-aware ? */
6001 } else if (*p2
== '*') {
6003 ext2
= talloc_asprintf(ctx
, "%s%s",
6019 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6024 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6036 /****************************************************************************
6037 Ensure open files have their names updated. Updated to notify other smbd's
6039 ****************************************************************************/
6041 static void rename_open_files(connection_struct
*conn
,
6042 struct share_mode_lock
*lck
,
6043 uint32_t orig_name_hash
,
6044 const struct smb_filename
*smb_fname_dst
)
6047 bool did_rename
= False
;
6049 uint32_t new_name_hash
= 0;
6051 for(fsp
= file_find_di_first(conn
->sconn
, lck
->data
->id
); fsp
;
6052 fsp
= file_find_di_next(fsp
)) {
6053 /* fsp_name is a relative path under the fsp. To change this for other
6054 sharepaths we need to manipulate relative paths. */
6055 /* TODO - create the absolute path and manipulate the newname
6056 relative to the sharepath. */
6057 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6060 if (fsp
->name_hash
!= orig_name_hash
) {
6063 DEBUG(10, ("rename_open_files: renaming file %s "
6064 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6065 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6066 smb_fname_str_dbg(smb_fname_dst
)));
6068 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6069 if (NT_STATUS_IS_OK(status
)) {
6071 new_name_hash
= fsp
->name_hash
;
6076 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6077 "for %s\n", file_id_string_tos(&lck
->data
->id
),
6078 smb_fname_str_dbg(smb_fname_dst
)));
6081 /* Send messages to all smbd's (not ourself) that the name has changed. */
6082 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, conn
->connectpath
,
6083 orig_name_hash
, new_name_hash
,
6088 /****************************************************************************
6089 We need to check if the source path is a parent directory of the destination
6090 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6091 refuse the rename with a sharing violation. Under UNIX the above call can
6092 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6093 probably need to check that the client is a Windows one before disallowing
6094 this as a UNIX client (one with UNIX extensions) can know the source is a
6095 symlink and make this decision intelligently. Found by an excellent bug
6096 report from <AndyLiebman@aol.com>.
6097 ****************************************************************************/
6099 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6100 const struct smb_filename
*smb_fname_dst
)
6102 const char *psrc
= smb_fname_src
->base_name
;
6103 const char *pdst
= smb_fname_dst
->base_name
;
6106 if (psrc
[0] == '.' && psrc
[1] == '/') {
6109 if (pdst
[0] == '.' && pdst
[1] == '/') {
6112 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6115 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6119 * Do the notify calls from a rename
6122 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6123 const struct smb_filename
*smb_fname_src
,
6124 const struct smb_filename
*smb_fname_dst
)
6126 char *parent_dir_src
= NULL
;
6127 char *parent_dir_dst
= NULL
;
6130 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6131 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6133 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6134 &parent_dir_src
, NULL
) ||
6135 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6136 &parent_dir_dst
, NULL
)) {
6140 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6141 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6142 smb_fname_src
->base_name
);
6143 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6144 smb_fname_dst
->base_name
);
6147 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6148 smb_fname_src
->base_name
);
6149 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6150 smb_fname_dst
->base_name
);
6153 /* this is a strange one. w2k3 gives an additional event for
6154 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6155 files, but not directories */
6157 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6158 FILE_NOTIFY_CHANGE_ATTRIBUTES
6159 |FILE_NOTIFY_CHANGE_CREATION
,
6160 smb_fname_dst
->base_name
);
6163 TALLOC_FREE(parent_dir_src
);
6164 TALLOC_FREE(parent_dir_dst
);
6167 /****************************************************************************
6168 Returns an error if the parent directory for a filename is open in an
6170 ****************************************************************************/
6172 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6173 const struct smb_filename
*smb_fname_dst_in
)
6175 char *parent_dir
= NULL
;
6176 struct smb_filename smb_fname_parent
;
6178 files_struct
*fsp
= NULL
;
6181 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6182 &parent_dir
, NULL
)) {
6183 return NT_STATUS_NO_MEMORY
;
6185 ZERO_STRUCT(smb_fname_parent
);
6186 smb_fname_parent
.base_name
= parent_dir
;
6188 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6190 return map_nt_error_from_unix(errno
);
6194 * We're only checking on this smbd here, mostly good
6195 * enough.. and will pass tests.
6198 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6199 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6200 fsp
= file_find_di_next(fsp
)) {
6201 if (fsp
->access_mask
& DELETE_ACCESS
) {
6202 return NT_STATUS_SHARING_VIOLATION
;
6205 return NT_STATUS_OK
;
6208 /****************************************************************************
6209 Rename an open file - given an fsp.
6210 ****************************************************************************/
6212 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6214 const struct smb_filename
*smb_fname_dst_in
,
6216 bool replace_if_exists
)
6218 TALLOC_CTX
*ctx
= talloc_tos();
6219 struct smb_filename
*smb_fname_dst
= NULL
;
6220 NTSTATUS status
= NT_STATUS_OK
;
6221 struct share_mode_lock
*lck
= NULL
;
6222 bool dst_exists
, old_is_stream
, new_is_stream
;
6224 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6225 if (!NT_STATUS_IS_OK(status
)) {
6229 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6230 if (!NT_STATUS_IS_OK(status
)) {
6234 /* Make a copy of the dst smb_fname structs */
6236 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
6237 if (!NT_STATUS_IS_OK(status
)) {
6242 * Check for special case with case preserving and not
6243 * case sensitive. If the old last component differs from the original
6244 * last component only by case, then we should allow
6245 * the rename (user is trying to change the case of the
6248 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6249 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6250 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6252 char *fname_dst_lcomp_base_mod
= NULL
;
6253 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6256 * Get the last component of the destination name.
6258 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6260 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6262 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6264 if (!fname_dst_lcomp_base_mod
) {
6265 status
= NT_STATUS_NO_MEMORY
;
6270 * Create an smb_filename struct using the original last
6271 * component of the destination.
6273 status
= create_synthetic_smb_fname_split(ctx
,
6274 smb_fname_dst
->original_lcomp
, NULL
,
6275 &smb_fname_orig_lcomp
);
6276 if (!NT_STATUS_IS_OK(status
)) {
6277 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6281 /* If the base names only differ by case, use original. */
6282 if(!strcsequal(fname_dst_lcomp_base_mod
,
6283 smb_fname_orig_lcomp
->base_name
)) {
6286 * Replace the modified last component with the
6290 *last_slash
= '\0'; /* Truncate at the '/' */
6291 tmp
= talloc_asprintf(smb_fname_dst
,
6293 smb_fname_dst
->base_name
,
6294 smb_fname_orig_lcomp
->base_name
);
6296 tmp
= talloc_asprintf(smb_fname_dst
,
6298 smb_fname_orig_lcomp
->base_name
);
6301 status
= NT_STATUS_NO_MEMORY
;
6302 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6303 TALLOC_FREE(smb_fname_orig_lcomp
);
6306 TALLOC_FREE(smb_fname_dst
->base_name
);
6307 smb_fname_dst
->base_name
= tmp
;
6310 /* If the stream_names only differ by case, use original. */
6311 if(!strcsequal(smb_fname_dst
->stream_name
,
6312 smb_fname_orig_lcomp
->stream_name
)) {
6314 /* Use the original stream. */
6315 tmp
= talloc_strdup(smb_fname_dst
,
6316 smb_fname_orig_lcomp
->stream_name
);
6318 status
= NT_STATUS_NO_MEMORY
;
6319 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6320 TALLOC_FREE(smb_fname_orig_lcomp
);
6323 TALLOC_FREE(smb_fname_dst
->stream_name
);
6324 smb_fname_dst
->stream_name
= tmp
;
6326 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6327 TALLOC_FREE(smb_fname_orig_lcomp
);
6331 * If the src and dest names are identical - including case,
6332 * don't do the rename, just return success.
6335 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6336 strcsequal(fsp
->fsp_name
->stream_name
,
6337 smb_fname_dst
->stream_name
)) {
6338 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6339 "- returning success\n",
6340 smb_fname_str_dbg(smb_fname_dst
)));
6341 status
= NT_STATUS_OK
;
6345 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6346 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6348 /* Return the correct error code if both names aren't streams. */
6349 if (!old_is_stream
&& new_is_stream
) {
6350 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6354 if (old_is_stream
&& !new_is_stream
) {
6355 status
= NT_STATUS_INVALID_PARAMETER
;
6359 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6361 if(!replace_if_exists
&& dst_exists
) {
6362 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6363 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6364 smb_fname_str_dbg(smb_fname_dst
)));
6365 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6370 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6371 &smb_fname_dst
->st
);
6372 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6374 /* The file can be open when renaming a stream */
6375 if (dst_fsp
&& !new_is_stream
) {
6376 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6377 status
= NT_STATUS_ACCESS_DENIED
;
6382 /* Ensure we have a valid stat struct for the source. */
6383 status
= vfs_stat_fsp(fsp
);
6384 if (!NT_STATUS_IS_OK(status
)) {
6388 status
= can_rename(conn
, fsp
, attrs
);
6390 if (!NT_STATUS_IS_OK(status
)) {
6391 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6392 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6393 smb_fname_str_dbg(smb_fname_dst
)));
6394 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6395 status
= NT_STATUS_ACCESS_DENIED
;
6399 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6400 status
= NT_STATUS_ACCESS_DENIED
;
6403 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6406 * We have the file open ourselves, so not being able to get the
6407 * corresponding share mode lock is a fatal error.
6410 SMB_ASSERT(lck
!= NULL
);
6412 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6413 uint32 create_options
= fsp
->fh
->private_options
;
6415 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6416 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6417 smb_fname_str_dbg(smb_fname_dst
)));
6419 if (!fsp
->is_directory
&&
6420 !lp_posix_pathnames() &&
6421 (lp_map_archive(SNUM(conn
)) ||
6422 lp_store_dos_attributes(SNUM(conn
)))) {
6423 /* We must set the archive bit on the newly
6425 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6426 uint32_t old_dosmode
= dos_mode(conn
,
6428 file_set_dosmode(conn
,
6430 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6436 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6439 rename_open_files(conn
, lck
, fsp
->name_hash
, smb_fname_dst
);
6442 * A rename acts as a new file create w.r.t. allowing an initial delete
6443 * on close, probably because in Windows there is a new handle to the
6444 * new file. If initial delete on close was requested but not
6445 * originally set, we need to set it here. This is probably not 100% correct,
6446 * but will work for the CIFSFS client which in non-posix mode
6447 * depends on these semantics. JRA.
6450 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6451 status
= can_set_delete_on_close(fsp
, 0);
6453 if (NT_STATUS_IS_OK(status
)) {
6454 /* Note that here we set the *inital* delete on close flag,
6455 * not the regular one. The magic gets handled in close. */
6456 fsp
->initial_delete_on_close
= True
;
6460 status
= NT_STATUS_OK
;
6466 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6467 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6469 status
= map_nt_error_from_unix(errno
);
6472 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6473 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6474 smb_fname_str_dbg(smb_fname_dst
)));
6477 TALLOC_FREE(smb_fname_dst
);
6482 /****************************************************************************
6483 The guts of the rename command, split out so it may be called by the NT SMB
6485 ****************************************************************************/
6487 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6488 connection_struct
*conn
,
6489 struct smb_request
*req
,
6490 struct smb_filename
*smb_fname_src
,
6491 struct smb_filename
*smb_fname_dst
,
6493 bool replace_if_exists
,
6496 uint32_t access_mask
)
6498 char *fname_src_dir
= NULL
;
6499 char *fname_src_mask
= NULL
;
6501 NTSTATUS status
= NT_STATUS_OK
;
6502 struct smb_Dir
*dir_hnd
= NULL
;
6503 const char *dname
= NULL
;
6504 char *talloced
= NULL
;
6506 int create_options
= 0;
6507 bool posix_pathnames
= lp_posix_pathnames();
6511 * Split the old name into directory and last component
6512 * strings. Note that unix_convert may have stripped off a
6513 * leading ./ from both name and newname if the rename is
6514 * at the root of the share. We need to make sure either both
6515 * name and newname contain a / character or neither of them do
6516 * as this is checked in resolve_wildcards().
6519 /* Split up the directory from the filename/mask. */
6520 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6521 &fname_src_dir
, &fname_src_mask
);
6522 if (!NT_STATUS_IS_OK(status
)) {
6523 status
= NT_STATUS_NO_MEMORY
;
6528 * We should only check the mangled cache
6529 * here if unix_convert failed. This means
6530 * that the path in 'mask' doesn't exist
6531 * on the file system and so we need to look
6532 * for a possible mangle. This patch from
6533 * Tine Smukavec <valentin.smukavec@hermes.si>.
6536 if (!VALID_STAT(smb_fname_src
->st
) &&
6537 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6538 char *new_mask
= NULL
;
6539 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6542 TALLOC_FREE(fname_src_mask
);
6543 fname_src_mask
= new_mask
;
6547 if (!src_has_wild
) {
6551 * Only one file needs to be renamed. Append the mask back
6552 * onto the directory.
6554 TALLOC_FREE(smb_fname_src
->base_name
);
6555 if (ISDOT(fname_src_dir
)) {
6556 /* Ensure we use canonical names on open. */
6557 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6561 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6566 if (!smb_fname_src
->base_name
) {
6567 status
= NT_STATUS_NO_MEMORY
;
6571 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6572 "case_preserve = %d, short case preserve = %d, "
6573 "directory = %s, newname = %s, "
6574 "last_component_dest = %s\n",
6575 conn
->case_sensitive
, conn
->case_preserve
,
6576 conn
->short_case_preserve
,
6577 smb_fname_str_dbg(smb_fname_src
),
6578 smb_fname_str_dbg(smb_fname_dst
),
6579 smb_fname_dst
->original_lcomp
));
6581 /* The dest name still may have wildcards. */
6582 if (dest_has_wild
) {
6583 char *fname_dst_mod
= NULL
;
6584 if (!resolve_wildcards(smb_fname_dst
,
6585 smb_fname_src
->base_name
,
6586 smb_fname_dst
->base_name
,
6588 DEBUG(6, ("rename_internals: resolve_wildcards "
6590 smb_fname_src
->base_name
,
6591 smb_fname_dst
->base_name
));
6592 status
= NT_STATUS_NO_MEMORY
;
6595 TALLOC_FREE(smb_fname_dst
->base_name
);
6596 smb_fname_dst
->base_name
= fname_dst_mod
;
6599 ZERO_STRUCT(smb_fname_src
->st
);
6600 if (posix_pathnames
) {
6601 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
6603 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
6606 status
= map_nt_error_from_unix_common(errno
);
6610 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6611 create_options
|= FILE_DIRECTORY_FILE
;
6614 status
= SMB_VFS_CREATE_FILE(
6617 0, /* root_dir_fid */
6618 smb_fname_src
, /* fname */
6619 access_mask
, /* access_mask */
6620 (FILE_SHARE_READ
| /* share_access */
6622 FILE_OPEN
, /* create_disposition*/
6623 create_options
, /* create_options */
6624 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6625 0, /* oplock_request */
6626 0, /* allocation_size */
6627 0, /* private_flags */
6633 if (!NT_STATUS_IS_OK(status
)) {
6634 DEBUG(3, ("Could not open rename source %s: %s\n",
6635 smb_fname_str_dbg(smb_fname_src
),
6636 nt_errstr(status
)));
6640 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6641 attrs
, replace_if_exists
);
6643 close_file(req
, fsp
, NORMAL_CLOSE
);
6645 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6646 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6647 smb_fname_str_dbg(smb_fname_dst
)));
6653 * Wildcards - process each file that matches.
6655 if (strequal(fname_src_mask
, "????????.???")) {
6656 TALLOC_FREE(fname_src_mask
);
6657 fname_src_mask
= talloc_strdup(ctx
, "*");
6658 if (!fname_src_mask
) {
6659 status
= NT_STATUS_NO_MEMORY
;
6664 status
= check_name(conn
, fname_src_dir
);
6665 if (!NT_STATUS_IS_OK(status
)) {
6669 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6671 if (dir_hnd
== NULL
) {
6672 status
= map_nt_error_from_unix(errno
);
6676 status
= NT_STATUS_NO_SUCH_FILE
;
6678 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6679 * - gentest fix. JRA
6682 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6684 files_struct
*fsp
= NULL
;
6685 char *destname
= NULL
;
6686 bool sysdir_entry
= False
;
6688 /* Quick check for "." and ".." */
6689 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6690 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6691 sysdir_entry
= True
;
6693 TALLOC_FREE(talloced
);
6698 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6699 &smb_fname_src
->st
, false)) {
6700 TALLOC_FREE(talloced
);
6704 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6705 TALLOC_FREE(talloced
);
6710 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6714 TALLOC_FREE(smb_fname_src
->base_name
);
6715 if (ISDOT(fname_src_dir
)) {
6716 /* Ensure we use canonical names on open. */
6717 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6721 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6726 if (!smb_fname_src
->base_name
) {
6727 status
= NT_STATUS_NO_MEMORY
;
6731 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6732 smb_fname_dst
->base_name
,
6734 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6735 smb_fname_src
->base_name
, destname
));
6736 TALLOC_FREE(talloced
);
6740 status
= NT_STATUS_NO_MEMORY
;
6744 TALLOC_FREE(smb_fname_dst
->base_name
);
6745 smb_fname_dst
->base_name
= destname
;
6747 ZERO_STRUCT(smb_fname_src
->st
);
6748 if (posix_pathnames
) {
6749 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6751 SMB_VFS_STAT(conn
, smb_fname_src
);
6756 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6757 create_options
|= FILE_DIRECTORY_FILE
;
6760 status
= SMB_VFS_CREATE_FILE(
6763 0, /* root_dir_fid */
6764 smb_fname_src
, /* fname */
6765 access_mask
, /* access_mask */
6766 (FILE_SHARE_READ
| /* share_access */
6768 FILE_OPEN
, /* create_disposition*/
6769 create_options
, /* create_options */
6770 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6771 0, /* oplock_request */
6772 0, /* allocation_size */
6773 0, /* private_flags */
6779 if (!NT_STATUS_IS_OK(status
)) {
6780 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6781 "returned %s rename %s -> %s\n",
6783 smb_fname_str_dbg(smb_fname_src
),
6784 smb_fname_str_dbg(smb_fname_dst
)));
6788 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6790 if (!smb_fname_dst
->original_lcomp
) {
6791 status
= NT_STATUS_NO_MEMORY
;
6795 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6796 attrs
, replace_if_exists
);
6798 close_file(req
, fsp
, NORMAL_CLOSE
);
6800 if (!NT_STATUS_IS_OK(status
)) {
6801 DEBUG(3, ("rename_internals_fsp returned %s for "
6802 "rename %s -> %s\n", nt_errstr(status
),
6803 smb_fname_str_dbg(smb_fname_src
),
6804 smb_fname_str_dbg(smb_fname_dst
)));
6810 DEBUG(3,("rename_internals: doing rename on %s -> "
6811 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6812 smb_fname_str_dbg(smb_fname_src
)));
6813 TALLOC_FREE(talloced
);
6815 TALLOC_FREE(dir_hnd
);
6817 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6818 status
= map_nt_error_from_unix(errno
);
6822 TALLOC_FREE(talloced
);
6823 TALLOC_FREE(fname_src_dir
);
6824 TALLOC_FREE(fname_src_mask
);
6828 /****************************************************************************
6830 ****************************************************************************/
6832 void reply_mv(struct smb_request
*req
)
6834 connection_struct
*conn
= req
->conn
;
6836 char *newname
= NULL
;
6840 bool src_has_wcard
= False
;
6841 bool dest_has_wcard
= False
;
6842 TALLOC_CTX
*ctx
= talloc_tos();
6843 struct smb_filename
*smb_fname_src
= NULL
;
6844 struct smb_filename
*smb_fname_dst
= NULL
;
6845 uint32_t src_ucf_flags
= lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP
: UCF_COND_ALLOW_WCARD_LCOMP
;
6846 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
| (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP
);
6847 bool stream_rename
= false;
6849 START_PROFILE(SMBmv
);
6852 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6856 attrs
= SVAL(req
->vwv
+0, 0);
6858 p
= (const char *)req
->buf
+ 1;
6859 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6860 &status
, &src_has_wcard
);
6861 if (!NT_STATUS_IS_OK(status
)) {
6862 reply_nterror(req
, status
);
6866 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6867 &status
, &dest_has_wcard
);
6868 if (!NT_STATUS_IS_OK(status
)) {
6869 reply_nterror(req
, status
);
6873 if (!lp_posix_pathnames()) {
6874 /* The newname must begin with a ':' if the
6875 name contains a ':'. */
6876 if (strchr_m(name
, ':')) {
6877 if (newname
[0] != ':') {
6878 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6881 stream_rename
= true;
6885 status
= filename_convert(ctx
,
6887 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6893 if (!NT_STATUS_IS_OK(status
)) {
6894 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6895 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6896 ERRSRV
, ERRbadpath
);
6899 reply_nterror(req
, status
);
6903 status
= filename_convert(ctx
,
6905 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6911 if (!NT_STATUS_IS_OK(status
)) {
6912 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6913 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6914 ERRSRV
, ERRbadpath
);
6917 reply_nterror(req
, status
);
6921 if (stream_rename
) {
6922 /* smb_fname_dst->base_name must be the same as
6923 smb_fname_src->base_name. */
6924 TALLOC_FREE(smb_fname_dst
->base_name
);
6925 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6926 smb_fname_src
->base_name
);
6927 if (!smb_fname_dst
->base_name
) {
6928 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6933 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6934 smb_fname_str_dbg(smb_fname_dst
)));
6936 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
6937 attrs
, False
, src_has_wcard
, dest_has_wcard
,
6939 if (!NT_STATUS_IS_OK(status
)) {
6940 if (open_was_deferred(req
->sconn
, req
->mid
)) {
6941 /* We have re-scheduled this call. */
6944 reply_nterror(req
, status
);
6948 reply_outbuf(req
, 0, 0);
6950 TALLOC_FREE(smb_fname_src
);
6951 TALLOC_FREE(smb_fname_dst
);
6956 /*******************************************************************
6957 Copy a file as part of a reply_copy.
6958 ******************************************************************/
6961 * TODO: check error codes on all callers
6964 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6965 connection_struct
*conn
,
6966 struct smb_filename
*smb_fname_src
,
6967 struct smb_filename
*smb_fname_dst
,
6970 bool target_is_directory
)
6972 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
6974 files_struct
*fsp1
,*fsp2
;
6976 uint32 new_create_disposition
;
6980 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
6981 if (!NT_STATUS_IS_OK(status
)) {
6986 * If the target is a directory, extract the last component from the
6987 * src filename and append it to the dst filename
6989 if (target_is_directory
) {
6992 /* dest/target can't be a stream if it's a directory. */
6993 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
6995 p
= strrchr_m(smb_fname_src
->base_name
,'/');
6999 p
= smb_fname_src
->base_name
;
7001 smb_fname_dst_tmp
->base_name
=
7002 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7004 if (!smb_fname_dst_tmp
->base_name
) {
7005 status
= NT_STATUS_NO_MEMORY
;
7010 status
= vfs_file_exist(conn
, smb_fname_src
);
7011 if (!NT_STATUS_IS_OK(status
)) {
7015 if (!target_is_directory
&& count
) {
7016 new_create_disposition
= FILE_OPEN
;
7018 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7021 &new_create_disposition
,
7024 status
= NT_STATUS_INVALID_PARAMETER
;
7029 /* Open the src file for reading. */
7030 status
= SMB_VFS_CREATE_FILE(
7033 0, /* root_dir_fid */
7034 smb_fname_src
, /* fname */
7035 FILE_GENERIC_READ
, /* access_mask */
7036 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7037 FILE_OPEN
, /* create_disposition*/
7038 0, /* create_options */
7039 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7040 INTERNAL_OPEN_ONLY
, /* oplock_request */
7041 0, /* allocation_size */
7042 0, /* private_flags */
7048 if (!NT_STATUS_IS_OK(status
)) {
7052 dosattrs
= dos_mode(conn
, smb_fname_src
);
7054 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7055 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7058 /* Open the dst file for writing. */
7059 status
= SMB_VFS_CREATE_FILE(
7062 0, /* root_dir_fid */
7063 smb_fname_dst
, /* fname */
7064 FILE_GENERIC_WRITE
, /* access_mask */
7065 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7066 new_create_disposition
, /* create_disposition*/
7067 0, /* create_options */
7068 dosattrs
, /* file_attributes */
7069 INTERNAL_OPEN_ONLY
, /* oplock_request */
7070 0, /* allocation_size */
7071 0, /* private_flags */
7077 if (!NT_STATUS_IS_OK(status
)) {
7078 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7082 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7083 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7085 DEBUG(0, ("error - vfs lseek returned error %s\n",
7087 status
= map_nt_error_from_unix(errno
);
7088 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7089 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7094 /* Do the actual copy. */
7095 if (smb_fname_src
->st
.st_ex_size
) {
7096 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7101 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7103 /* Ensure the modtime is set correctly on the destination file. */
7104 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7107 * As we are opening fsp1 read-only we only expect
7108 * an error on close on fsp2 if we are out of space.
7109 * Thus we don't look at the error return from the
7112 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7114 if (!NT_STATUS_IS_OK(status
)) {
7118 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7119 status
= NT_STATUS_DISK_FULL
;
7123 status
= NT_STATUS_OK
;
7126 TALLOC_FREE(smb_fname_dst_tmp
);
7130 /****************************************************************************
7131 Reply to a file copy.
7132 ****************************************************************************/
7134 void reply_copy(struct smb_request
*req
)
7136 connection_struct
*conn
= req
->conn
;
7137 struct smb_filename
*smb_fname_src
= NULL
;
7138 struct smb_filename
*smb_fname_dst
= NULL
;
7139 char *fname_src
= NULL
;
7140 char *fname_dst
= NULL
;
7141 char *fname_src_mask
= NULL
;
7142 char *fname_src_dir
= NULL
;
7145 int error
= ERRnoaccess
;
7149 bool target_is_directory
=False
;
7150 bool source_has_wild
= False
;
7151 bool dest_has_wild
= False
;
7153 TALLOC_CTX
*ctx
= talloc_tos();
7155 START_PROFILE(SMBcopy
);
7158 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7162 tid2
= SVAL(req
->vwv
+0, 0);
7163 ofun
= SVAL(req
->vwv
+1, 0);
7164 flags
= SVAL(req
->vwv
+2, 0);
7166 p
= (const char *)req
->buf
;
7167 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7168 &status
, &source_has_wild
);
7169 if (!NT_STATUS_IS_OK(status
)) {
7170 reply_nterror(req
, status
);
7173 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7174 &status
, &dest_has_wild
);
7175 if (!NT_STATUS_IS_OK(status
)) {
7176 reply_nterror(req
, status
);
7180 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7182 if (tid2
!= conn
->cnum
) {
7183 /* can't currently handle inter share copies XXXX */
7184 DEBUG(3,("Rejecting inter-share copy\n"));
7185 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7189 status
= filename_convert(ctx
, conn
,
7190 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7192 UCF_COND_ALLOW_WCARD_LCOMP
,
7195 if (!NT_STATUS_IS_OK(status
)) {
7196 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7197 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7198 ERRSRV
, ERRbadpath
);
7201 reply_nterror(req
, status
);
7205 status
= filename_convert(ctx
, conn
,
7206 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7208 UCF_COND_ALLOW_WCARD_LCOMP
,
7211 if (!NT_STATUS_IS_OK(status
)) {
7212 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7213 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7214 ERRSRV
, ERRbadpath
);
7217 reply_nterror(req
, status
);
7221 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7223 if ((flags
&1) && target_is_directory
) {
7224 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7228 if ((flags
&2) && !target_is_directory
) {
7229 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7233 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7234 /* wants a tree copy! XXXX */
7235 DEBUG(3,("Rejecting tree copy\n"));
7236 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7240 /* Split up the directory from the filename/mask. */
7241 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7242 &fname_src_dir
, &fname_src_mask
);
7243 if (!NT_STATUS_IS_OK(status
)) {
7244 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7249 * We should only check the mangled cache
7250 * here if unix_convert failed. This means
7251 * that the path in 'mask' doesn't exist
7252 * on the file system and so we need to look
7253 * for a possible mangle. This patch from
7254 * Tine Smukavec <valentin.smukavec@hermes.si>.
7256 if (!VALID_STAT(smb_fname_src
->st
) &&
7257 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7258 char *new_mask
= NULL
;
7259 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7260 &new_mask
, conn
->params
);
7262 /* Use demangled name if one was successfully found. */
7264 TALLOC_FREE(fname_src_mask
);
7265 fname_src_mask
= new_mask
;
7269 if (!source_has_wild
) {
7272 * Only one file needs to be copied. Append the mask back onto
7275 TALLOC_FREE(smb_fname_src
->base_name
);
7276 if (ISDOT(fname_src_dir
)) {
7277 /* Ensure we use canonical names on open. */
7278 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7282 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7287 if (!smb_fname_src
->base_name
) {
7288 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7292 if (dest_has_wild
) {
7293 char *fname_dst_mod
= NULL
;
7294 if (!resolve_wildcards(smb_fname_dst
,
7295 smb_fname_src
->base_name
,
7296 smb_fname_dst
->base_name
,
7298 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7301 TALLOC_FREE(smb_fname_dst
->base_name
);
7302 smb_fname_dst
->base_name
= fname_dst_mod
;
7305 status
= check_name(conn
, smb_fname_src
->base_name
);
7306 if (!NT_STATUS_IS_OK(status
)) {
7307 reply_nterror(req
, status
);
7311 status
= check_name(conn
, smb_fname_dst
->base_name
);
7312 if (!NT_STATUS_IS_OK(status
)) {
7313 reply_nterror(req
, status
);
7317 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7318 ofun
, count
, target_is_directory
);
7320 if(!NT_STATUS_IS_OK(status
)) {
7321 reply_nterror(req
, status
);
7327 struct smb_Dir
*dir_hnd
= NULL
;
7328 const char *dname
= NULL
;
7329 char *talloced
= NULL
;
7333 * There is a wildcard that requires us to actually read the
7334 * src dir and copy each file matching the mask to the dst.
7335 * Right now streams won't be copied, but this could
7336 * presumably be added with a nested loop for reach dir entry.
7338 SMB_ASSERT(!smb_fname_src
->stream_name
);
7339 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7341 smb_fname_src
->stream_name
= NULL
;
7342 smb_fname_dst
->stream_name
= NULL
;
7344 if (strequal(fname_src_mask
,"????????.???")) {
7345 TALLOC_FREE(fname_src_mask
);
7346 fname_src_mask
= talloc_strdup(ctx
, "*");
7347 if (!fname_src_mask
) {
7348 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7353 status
= check_name(conn
, fname_src_dir
);
7354 if (!NT_STATUS_IS_OK(status
)) {
7355 reply_nterror(req
, status
);
7359 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7360 if (dir_hnd
== NULL
) {
7361 status
= map_nt_error_from_unix(errno
);
7362 reply_nterror(req
, status
);
7368 /* Iterate over the src dir copying each entry to the dst. */
7369 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7370 &smb_fname_src
->st
, &talloced
))) {
7371 char *destname
= NULL
;
7373 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7374 TALLOC_FREE(talloced
);
7378 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7379 &smb_fname_src
->st
, false)) {
7380 TALLOC_FREE(talloced
);
7384 if(!mask_match(dname
, fname_src_mask
,
7385 conn
->case_sensitive
)) {
7386 TALLOC_FREE(talloced
);
7390 error
= ERRnoaccess
;
7392 /* Get the src smb_fname struct setup. */
7393 TALLOC_FREE(smb_fname_src
->base_name
);
7394 if (ISDOT(fname_src_dir
)) {
7395 /* Ensure we use canonical names on open. */
7396 smb_fname_src
->base_name
=
7397 talloc_asprintf(smb_fname_src
, "%s",
7400 smb_fname_src
->base_name
=
7401 talloc_asprintf(smb_fname_src
, "%s/%s",
7402 fname_src_dir
, dname
);
7405 if (!smb_fname_src
->base_name
) {
7406 TALLOC_FREE(dir_hnd
);
7407 TALLOC_FREE(talloced
);
7408 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7412 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7413 smb_fname_dst
->base_name
,
7415 TALLOC_FREE(talloced
);
7419 TALLOC_FREE(dir_hnd
);
7420 TALLOC_FREE(talloced
);
7421 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7425 TALLOC_FREE(smb_fname_dst
->base_name
);
7426 smb_fname_dst
->base_name
= destname
;
7428 status
= check_name(conn
, smb_fname_src
->base_name
);
7429 if (!NT_STATUS_IS_OK(status
)) {
7430 TALLOC_FREE(dir_hnd
);
7431 TALLOC_FREE(talloced
);
7432 reply_nterror(req
, status
);
7436 status
= check_name(conn
, smb_fname_dst
->base_name
);
7437 if (!NT_STATUS_IS_OK(status
)) {
7438 TALLOC_FREE(dir_hnd
);
7439 TALLOC_FREE(talloced
);
7440 reply_nterror(req
, status
);
7444 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7445 smb_fname_src
->base_name
,
7446 smb_fname_dst
->base_name
));
7448 status
= copy_file(ctx
, conn
, smb_fname_src
,
7449 smb_fname_dst
, ofun
, count
,
7450 target_is_directory
);
7451 if (NT_STATUS_IS_OK(status
)) {
7455 TALLOC_FREE(talloced
);
7457 TALLOC_FREE(dir_hnd
);
7461 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7465 reply_outbuf(req
, 1, 0);
7466 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7468 TALLOC_FREE(smb_fname_src
);
7469 TALLOC_FREE(smb_fname_dst
);
7470 TALLOC_FREE(fname_src
);
7471 TALLOC_FREE(fname_dst
);
7472 TALLOC_FREE(fname_src_mask
);
7473 TALLOC_FREE(fname_src_dir
);
7475 END_PROFILE(SMBcopy
);
7480 #define DBGC_CLASS DBGC_LOCKING
7482 /****************************************************************************
7483 Get a lock pid, dealing with large count requests.
7484 ****************************************************************************/
7486 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7487 bool large_file_format
)
7489 if(!large_file_format
)
7490 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7492 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7495 /****************************************************************************
7496 Get a lock count, dealing with large count requests.
7497 ****************************************************************************/
7499 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7500 bool large_file_format
)
7504 if(!large_file_format
) {
7505 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7508 #if defined(HAVE_LONGLONG)
7509 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7510 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7511 #else /* HAVE_LONGLONG */
7514 * NT4.x seems to be broken in that it sends large file (64 bit)
7515 * lockingX calls even if the CAP_LARGE_FILES was *not*
7516 * negotiated. For boxes without large unsigned ints truncate the
7517 * lock count by dropping the top 32 bits.
7520 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7521 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7522 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7523 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7524 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7527 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7528 #endif /* HAVE_LONGLONG */
7534 #if !defined(HAVE_LONGLONG)
7535 /****************************************************************************
7536 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7537 ****************************************************************************/
7539 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7543 uint32 highcopy
= high
;
7546 * Try and find out how many significant bits there are in high.
7549 for(i
= 0; highcopy
; i
++)
7553 * We use 31 bits not 32 here as POSIX
7554 * lock offsets may not be negative.
7557 mask
= (~0) << (31 - i
);
7560 return 0; /* Fail. */
7566 #endif /* !defined(HAVE_LONGLONG) */
7568 /****************************************************************************
7569 Get a lock offset, dealing with large offset requests.
7570 ****************************************************************************/
7572 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7573 bool large_file_format
, bool *err
)
7575 uint64_t offset
= 0;
7579 if(!large_file_format
) {
7580 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7583 #if defined(HAVE_LONGLONG)
7584 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7585 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7586 #else /* HAVE_LONGLONG */
7589 * NT4.x seems to be broken in that it sends large file (64 bit)
7590 * lockingX calls even if the CAP_LARGE_FILES was *not*
7591 * negotiated. For boxes without large unsigned ints mangle the
7592 * lock offset by mapping the top 32 bits onto the lower 32.
7595 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7596 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7597 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7600 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7602 return (uint64_t)-1;
7605 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7606 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7607 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7608 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7611 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7612 #endif /* HAVE_LONGLONG */
7618 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7622 uint16_t num_ulocks
,
7623 struct smbd_lock_element
*ulocks
,
7625 struct smbd_lock_element
*locks
,
7628 connection_struct
*conn
= req
->conn
;
7630 NTSTATUS status
= NT_STATUS_OK
;
7634 /* Data now points at the beginning of the list
7635 of smb_unlkrng structs */
7636 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7637 struct smbd_lock_element
*e
= &ulocks
[i
];
7639 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7640 "pid %u, file %s\n",
7643 (unsigned int)e
->smblctx
,
7646 if (e
->brltype
!= UNLOCK_LOCK
) {
7647 /* this can only happen with SMB2 */
7648 return NT_STATUS_INVALID_PARAMETER
;
7651 status
= do_unlock(req
->sconn
->msg_ctx
,
7658 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7659 nt_errstr(status
)));
7661 if (!NT_STATUS_IS_OK(status
)) {
7666 /* Setup the timeout in seconds. */
7668 if (!lp_blocking_locks(SNUM(conn
))) {
7672 /* Data now points at the beginning of the list
7673 of smb_lkrng structs */
7675 for(i
= 0; i
< (int)num_locks
; i
++) {
7676 struct smbd_lock_element
*e
= &locks
[i
];
7678 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7679 "%llu, file %s timeout = %d\n",
7682 (unsigned long long)e
->smblctx
,
7686 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7687 struct blocking_lock_record
*blr
= NULL
;
7689 if (num_locks
> 1) {
7691 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7692 * if the lock vector contains one entry. When given mutliple cancel
7693 * requests in a single PDU we expect the server to return an
7694 * error. Windows servers seem to accept the request but only
7695 * cancel the first lock.
7696 * JRA - Do what Windows does (tm) :-).
7700 /* MS-CIFS (2.2.4.32.1) behavior. */
7701 return NT_STATUS_DOS(ERRDOS
,
7702 ERRcancelviolation
);
7704 /* Windows behavior. */
7706 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7707 "cancel request\n"));
7713 if (lp_blocking_locks(SNUM(conn
))) {
7715 /* Schedule a message to ourselves to
7716 remove the blocking lock record and
7717 return the right error. */
7719 blr
= blocking_lock_cancel_smb1(fsp
,
7725 NT_STATUS_FILE_LOCK_CONFLICT
);
7727 return NT_STATUS_DOS(
7729 ERRcancelviolation
);
7732 /* Remove a matching pending lock. */
7733 status
= do_lock_cancel(fsp
,
7740 bool blocking_lock
= timeout
? true : false;
7741 bool defer_lock
= false;
7742 struct byte_range_lock
*br_lck
;
7743 uint64_t block_smblctx
;
7745 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7757 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7758 /* Windows internal resolution for blocking locks seems
7759 to be about 200ms... Don't wait for less than that. JRA. */
7760 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7761 timeout
= lp_lock_spin_time();
7766 /* If a lock sent with timeout of zero would fail, and
7767 * this lock has been requested multiple times,
7768 * according to brl_lock_failed() we convert this
7769 * request to a blocking lock with a timeout of between
7770 * 150 - 300 milliseconds.
7772 * If lp_lock_spin_time() has been set to 0, we skip
7773 * this blocking retry and fail immediately.
7775 * Replacement for do_lock_spin(). JRA. */
7777 if (!req
->sconn
->using_smb2
&&
7778 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7779 lp_lock_spin_time() && !blocking_lock
&&
7780 NT_STATUS_EQUAL((status
),
7781 NT_STATUS_FILE_LOCK_CONFLICT
))
7784 timeout
= lp_lock_spin_time();
7787 if (br_lck
&& defer_lock
) {
7789 * A blocking lock was requested. Package up
7790 * this smb into a queued request and push it
7791 * onto the blocking lock queue.
7793 if(push_blocking_lock_request(br_lck
,
7804 TALLOC_FREE(br_lck
);
7806 return NT_STATUS_OK
;
7810 TALLOC_FREE(br_lck
);
7813 if (!NT_STATUS_IS_OK(status
)) {
7818 /* If any of the above locks failed, then we must unlock
7819 all of the previous locks (X/Open spec). */
7821 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7823 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7824 i
= -1; /* we want to skip the for loop */
7828 * Ensure we don't do a remove on the lock that just failed,
7829 * as under POSIX rules, if we have a lock already there, we
7830 * will delete it (and we shouldn't) .....
7832 for(i
--; i
>= 0; i
--) {
7833 struct smbd_lock_element
*e
= &locks
[i
];
7835 do_unlock(req
->sconn
->msg_ctx
,
7845 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d num_ulocks=%d\n",
7846 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
, num_ulocks
));
7848 return NT_STATUS_OK
;
7851 /****************************************************************************
7852 Reply to a lockingX request.
7853 ****************************************************************************/
7855 void reply_lockingX(struct smb_request
*req
)
7857 connection_struct
*conn
= req
->conn
;
7859 unsigned char locktype
;
7860 unsigned char oplocklevel
;
7865 const uint8_t *data
;
7866 bool large_file_format
;
7868 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7869 struct smbd_lock_element
*ulocks
;
7870 struct smbd_lock_element
*locks
;
7873 START_PROFILE(SMBlockingX
);
7876 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7877 END_PROFILE(SMBlockingX
);
7881 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7882 locktype
= CVAL(req
->vwv
+3, 0);
7883 oplocklevel
= CVAL(req
->vwv
+3, 1);
7884 num_ulocks
= SVAL(req
->vwv
+6, 0);
7885 num_locks
= SVAL(req
->vwv
+7, 0);
7886 lock_timeout
= IVAL(req
->vwv
+4, 0);
7887 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7889 if (!check_fsp(conn
, req
, fsp
)) {
7890 END_PROFILE(SMBlockingX
);
7896 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7897 /* we don't support these - and CANCEL_LOCK makes w2k
7898 and XP reboot so I don't really want to be
7899 compatible! (tridge) */
7900 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7901 END_PROFILE(SMBlockingX
);
7905 /* Check if this is an oplock break on a file
7906 we have granted an oplock on.
7908 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7909 /* Client can insist on breaking to none. */
7910 bool break_to_none
= (oplocklevel
== 0);
7913 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7914 "for %s\n", (unsigned int)oplocklevel
,
7915 fsp_fnum_dbg(fsp
)));
7918 * Make sure we have granted an exclusive or batch oplock on
7922 if (fsp
->oplock_type
== 0) {
7924 /* The Samba4 nbench simulator doesn't understand
7925 the difference between break to level2 and break
7926 to none from level2 - it sends oplock break
7927 replies in both cases. Don't keep logging an error
7928 message here - just ignore it. JRA. */
7930 DEBUG(5,("reply_lockingX: Error : oplock break from "
7931 "client for %s (oplock=%d) and no "
7932 "oplock granted on this file (%s).\n",
7933 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
7936 /* if this is a pure oplock break request then don't
7938 if (num_locks
== 0 && num_ulocks
== 0) {
7939 END_PROFILE(SMBlockingX
);
7942 END_PROFILE(SMBlockingX
);
7943 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
7948 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7950 result
= remove_oplock(fsp
);
7952 result
= downgrade_oplock(fsp
);
7956 DEBUG(0, ("reply_lockingX: error in removing "
7957 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7958 /* Hmmm. Is this panic justified? */
7959 smb_panic("internal tdb error");
7962 reply_to_oplock_break_requests(fsp
);
7964 /* if this is a pure oplock break request then don't send a
7966 if (num_locks
== 0 && num_ulocks
== 0) {
7967 /* Sanity check - ensure a pure oplock break is not a
7969 if(CVAL(req
->vwv
+0, 0) != 0xff)
7970 DEBUG(0,("reply_lockingX: Error : pure oplock "
7971 "break is a chained %d request !\n",
7972 (unsigned int)CVAL(req
->vwv
+0, 0)));
7973 END_PROFILE(SMBlockingX
);
7979 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7980 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7981 END_PROFILE(SMBlockingX
);
7985 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
7986 if (ulocks
== NULL
) {
7987 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7988 END_PROFILE(SMBlockingX
);
7992 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
7993 if (locks
== NULL
) {
7994 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7995 END_PROFILE(SMBlockingX
);
7999 /* Data now points at the beginning of the list
8000 of smb_unlkrng structs */
8001 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8002 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8003 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8004 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
8005 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8008 * There is no error code marked "stupid client bug".... :-).
8011 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8012 END_PROFILE(SMBlockingX
);
8017 /* Now do any requested locks */
8018 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8020 /* Data now points at the beginning of the list
8021 of smb_lkrng structs */
8023 for(i
= 0; i
< (int)num_locks
; i
++) {
8024 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8025 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8026 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
8028 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8029 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8030 locks
[i
].brltype
= PENDING_READ_LOCK
;
8032 locks
[i
].brltype
= READ_LOCK
;
8035 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8036 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8038 locks
[i
].brltype
= WRITE_LOCK
;
8043 * There is no error code marked "stupid client bug".... :-).
8046 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8047 END_PROFILE(SMBlockingX
);
8052 status
= smbd_do_locking(req
, fsp
,
8053 locktype
, lock_timeout
,
8057 if (!NT_STATUS_IS_OK(status
)) {
8058 END_PROFILE(SMBlockingX
);
8059 reply_nterror(req
, status
);
8063 END_PROFILE(SMBlockingX
);
8067 reply_outbuf(req
, 2, 0);
8068 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8069 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8071 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8072 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8074 END_PROFILE(SMBlockingX
);
8078 #define DBGC_CLASS DBGC_ALL
8080 /****************************************************************************
8081 Reply to a SMBreadbmpx (read block multiplex) request.
8082 Always reply with an error, if someone has a platform really needs this,
8083 please contact vl@samba.org
8084 ****************************************************************************/
8086 void reply_readbmpx(struct smb_request
*req
)
8088 START_PROFILE(SMBreadBmpx
);
8089 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8090 END_PROFILE(SMBreadBmpx
);
8094 /****************************************************************************
8095 Reply to a SMBreadbs (read block multiplex secondary) request.
8096 Always reply with an error, if someone has a platform really needs this,
8097 please contact vl@samba.org
8098 ****************************************************************************/
8100 void reply_readbs(struct smb_request
*req
)
8102 START_PROFILE(SMBreadBs
);
8103 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8104 END_PROFILE(SMBreadBs
);
8108 /****************************************************************************
8109 Reply to a SMBsetattrE.
8110 ****************************************************************************/
8112 void reply_setattrE(struct smb_request
*req
)
8114 connection_struct
*conn
= req
->conn
;
8115 struct smb_file_time ft
;
8119 START_PROFILE(SMBsetattrE
);
8123 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8127 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8129 if(!fsp
|| (fsp
->conn
!= conn
)) {
8130 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8135 * Convert the DOS times into unix times.
8138 ft
.atime
= convert_time_t_to_timespec(
8139 srv_make_unix_date2(req
->vwv
+3));
8140 ft
.mtime
= convert_time_t_to_timespec(
8141 srv_make_unix_date2(req
->vwv
+5));
8142 ft
.create_time
= convert_time_t_to_timespec(
8143 srv_make_unix_date2(req
->vwv
+1));
8145 reply_outbuf(req
, 0, 0);
8148 * Patch from Ray Frush <frush@engr.colostate.edu>
8149 * Sometimes times are sent as zero - ignore them.
8152 /* Ensure we have a valid stat struct for the source. */
8153 status
= vfs_stat_fsp(fsp
);
8154 if (!NT_STATUS_IS_OK(status
)) {
8155 reply_nterror(req
, status
);
8159 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8160 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8164 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8165 if (!NT_STATUS_IS_OK(status
)) {
8166 reply_nterror(req
, status
);
8170 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8173 (unsigned int)ft
.atime
.tv_sec
,
8174 (unsigned int)ft
.mtime
.tv_sec
,
8175 (unsigned int)ft
.create_time
.tv_sec
8178 END_PROFILE(SMBsetattrE
);
8183 /* Back from the dead for OS/2..... JRA. */
8185 /****************************************************************************
8186 Reply to a SMBwritebmpx (write block multiplex primary) request.
8187 Always reply with an error, if someone has a platform really needs this,
8188 please contact vl@samba.org
8189 ****************************************************************************/
8191 void reply_writebmpx(struct smb_request
*req
)
8193 START_PROFILE(SMBwriteBmpx
);
8194 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8195 END_PROFILE(SMBwriteBmpx
);
8199 /****************************************************************************
8200 Reply to a SMBwritebs (write block multiplex secondary) request.
8201 Always reply with an error, if someone has a platform really needs this,
8202 please contact vl@samba.org
8203 ****************************************************************************/
8205 void reply_writebs(struct smb_request
*req
)
8207 START_PROFILE(SMBwriteBs
);
8208 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8209 END_PROFILE(SMBwriteBs
);
8213 /****************************************************************************
8214 Reply to a SMBgetattrE.
8215 ****************************************************************************/
8217 void reply_getattrE(struct smb_request
*req
)
8219 connection_struct
*conn
= req
->conn
;
8222 struct timespec create_ts
;
8224 START_PROFILE(SMBgetattrE
);
8227 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8228 END_PROFILE(SMBgetattrE
);
8232 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8234 if(!fsp
|| (fsp
->conn
!= conn
)) {
8235 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8236 END_PROFILE(SMBgetattrE
);
8240 /* Do an fstat on this file */
8242 reply_nterror(req
, map_nt_error_from_unix(errno
));
8243 END_PROFILE(SMBgetattrE
);
8247 mode
= dos_mode(conn
, fsp
->fsp_name
);
8250 * Convert the times into dos times. Set create
8251 * date to be last modify date as UNIX doesn't save
8255 reply_outbuf(req
, 11, 0);
8257 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8258 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8259 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8260 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8261 /* Should we check pending modtime here ? JRA */
8262 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8263 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8265 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8266 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8267 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8269 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8270 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
8271 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8273 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8275 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8277 END_PROFILE(SMBgetattrE
);