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"
46 #include "lib/sys_rw_data.h"
48 /****************************************************************************
49 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50 path or anything including wildcards.
51 We're assuming here that '/' is not the second byte in any multibyte char
52 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
54 ****************************************************************************/
56 /* Custom version for processing POSIX paths. */
57 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
59 static NTSTATUS
check_path_syntax_internal(char *path
,
61 bool *p_last_component_contains_wcard
)
65 NTSTATUS ret
= NT_STATUS_OK
;
66 bool start_of_name_component
= True
;
67 bool stream_started
= false;
69 *p_last_component_contains_wcard
= False
;
76 return NT_STATUS_OBJECT_NAME_INVALID
;
79 return NT_STATUS_OBJECT_NAME_INVALID
;
81 if (strchr_m(&s
[1], ':')) {
82 return NT_STATUS_OBJECT_NAME_INVALID
;
88 if ((*s
== ':') && !posix_path
&& !stream_started
) {
89 if (*p_last_component_contains_wcard
) {
90 return NT_STATUS_OBJECT_NAME_INVALID
;
92 /* Stream names allow more characters than file names.
93 We're overloading posix_path here to allow a wider
94 range of characters. If stream_started is true this
95 is still a Windows path even if posix_path is true.
98 stream_started
= true;
99 start_of_name_component
= false;
103 return NT_STATUS_OBJECT_NAME_INVALID
;
107 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
109 * Safe to assume is not the second part of a mb char
110 * as this is handled below.
112 /* Eat multiple '/' or '\\' */
113 while (IS_PATH_SEP(*s
,posix_path
)) {
116 if ((d
!= path
) && (*s
!= '\0')) {
117 /* We only care about non-leading or trailing '/' or '\\' */
121 start_of_name_component
= True
;
123 *p_last_component_contains_wcard
= False
;
127 if (start_of_name_component
) {
128 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
129 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
132 * No mb char starts with '.' so we're safe checking the directory separator here.
135 /* If we just added a '/' - delete it */
136 if ((d
> path
) && (*(d
-1) == '/')) {
141 /* Are we at the start ? Can't go back further if so. */
143 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
146 /* Go back one level... */
147 /* We know this is safe as '/' cannot be part of a mb sequence. */
148 /* NOTE - if this assumption is invalid we are not in good shape... */
149 /* Decrement d first as d points to the *next* char to write into. */
150 for (d
--; d
> path
; d
--) {
154 s
+= 2; /* Else go past the .. */
155 /* We're still at the start of a name component, just the previous one. */
158 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
170 if (*s
<= 0x1f || *s
== '|') {
171 return NT_STATUS_OBJECT_NAME_INVALID
;
179 *p_last_component_contains_wcard
= True
;
188 /* Get the size of the next MB character. */
189 next_codepoint(s
,&siz
);
207 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
209 return NT_STATUS_INVALID_PARAMETER
;
212 start_of_name_component
= False
;
220 /****************************************************************************
221 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222 No wildcards allowed.
223 ****************************************************************************/
225 NTSTATUS
check_path_syntax(char *path
)
228 return check_path_syntax_internal(path
, False
, &ignore
);
231 /****************************************************************************
232 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233 Wildcards allowed - p_contains_wcard returns true if the last component contained
235 ****************************************************************************/
237 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
239 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
242 /****************************************************************************
243 Check the path for a POSIX client.
244 We're assuming here that '/' is not the second byte in any multibyte char
245 set (a safe assumption).
246 ****************************************************************************/
248 NTSTATUS
check_path_syntax_posix(char *path
)
251 return check_path_syntax_internal(path
, True
, &ignore
);
254 /****************************************************************************
255 Pull a string and check the path allowing a wilcard - provide for error return.
256 ****************************************************************************/
258 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
259 const char *base_ptr
,
266 bool *contains_wcard
)
272 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
276 *err
= NT_STATUS_INVALID_PARAMETER
;
280 *contains_wcard
= False
;
282 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
284 * For a DFS path the function parse_dfs_path()
285 * will do the path processing, just make a copy.
291 if (lp_posix_pathnames()) {
292 *err
= check_path_syntax_posix(*pp_dest
);
294 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
300 /****************************************************************************
301 Pull a string and check the path - provide for error return.
302 ****************************************************************************/
304 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
305 const char *base_ptr
,
314 return srvstr_get_path_wcard(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
315 src_len
, flags
, err
, &ignore
);
318 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
319 char **pp_dest
, const char *src
, int flags
,
320 NTSTATUS
*err
, bool *contains_wcard
)
322 ssize_t bufrem
= smbreq_bufrem(req
, src
);
325 *err
= NT_STATUS_INVALID_PARAMETER
;
329 return srvstr_get_path_wcard(mem_ctx
, (const char *)req
->inbuf
,
330 req
->flags2
, pp_dest
, src
, bufrem
, flags
,
331 err
, contains_wcard
);
334 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
335 char **pp_dest
, const char *src
, int flags
,
339 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
340 flags
, err
, &ignore
);
344 * pull a string from the smb_buf part of a packet. In this case the
345 * string can either be null terminated or it can be terminated by the
346 * end of the smbbuf area
348 size_t srvstr_pull_req_talloc(TALLOC_CTX
*ctx
, struct smb_request
*req
,
349 char **dest
, const uint8_t *src
, int flags
)
351 ssize_t bufrem
= smbreq_bufrem(req
, src
);
357 return pull_string_talloc(ctx
, req
->inbuf
, req
->flags2
, dest
, src
,
361 /****************************************************************************
362 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
363 ****************************************************************************/
365 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
368 if ((fsp
== NULL
) || (conn
== NULL
)) {
369 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
372 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
373 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
379 /****************************************************************************
380 Check if we have a correct fsp pointing to a file.
381 ****************************************************************************/
383 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
386 if (!check_fsp_open(conn
, req
, fsp
)) {
389 if (fsp
->is_directory
) {
390 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
393 if (fsp
->fh
->fd
== -1) {
394 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
397 fsp
->num_smb_operations
++;
401 /****************************************************************************
402 Check if we have a correct fsp pointing to a quota fake file. Replacement for
403 the CHECK_NTQUOTA_HANDLE_OK macro.
404 ****************************************************************************/
406 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
409 if (!check_fsp_open(conn
, req
, fsp
)) {
413 if (fsp
->is_directory
) {
417 if (fsp
->fake_file_handle
== NULL
) {
421 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
425 if (fsp
->fake_file_handle
->private_data
== NULL
) {
432 static bool netbios_session_retarget(struct smbXsrv_connection
*xconn
,
433 const char *name
, int name_type
)
436 char *trim_name_type
;
437 const char *retarget_parm
;
440 int retarget_type
= 0x20;
441 int retarget_port
= NBT_SMB_PORT
;
442 struct sockaddr_storage retarget_addr
;
443 struct sockaddr_in
*in_addr
;
447 if (get_socket_port(xconn
->transport
.sock
) != NBT_SMB_PORT
) {
451 trim_name
= talloc_strdup(talloc_tos(), name
);
452 if (trim_name
== NULL
) {
455 trim_char(trim_name
, ' ', ' ');
457 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
459 if (trim_name_type
== NULL
) {
463 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
464 trim_name_type
, NULL
);
465 if (retarget_parm
== NULL
) {
466 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
469 if (retarget_parm
== NULL
) {
473 retarget
= talloc_strdup(trim_name
, retarget_parm
);
474 if (retarget
== NULL
) {
478 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
480 p
= strchr(retarget
, ':');
483 retarget_port
= atoi(p
);
486 p
= strchr_m(retarget
, '#');
489 if (sscanf(p
, "%x", &retarget_type
) != 1) {
494 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
496 DEBUG(10, ("could not resolve %s\n", retarget
));
500 if (retarget_addr
.ss_family
!= AF_INET
) {
501 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
505 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
507 _smb_setlen(outbuf
, 6);
508 SCVAL(outbuf
, 0, 0x84);
509 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
510 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
512 if (!srv_send_smb(xconn
, (char *)outbuf
, false, 0, false,
514 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
520 TALLOC_FREE(trim_name
);
524 static void reply_called_name_not_present(char *outbuf
)
526 smb_setlen(outbuf
, 1);
527 SCVAL(outbuf
, 0, 0x83);
528 SCVAL(outbuf
, 4, 0x82);
531 /****************************************************************************
532 Reply to a (netbios-level) special message.
533 ****************************************************************************/
535 void reply_special(struct smbXsrv_connection
*xconn
, char *inbuf
, size_t inbuf_size
)
537 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
538 int msg_type
= CVAL(inbuf
,0);
539 int msg_flags
= CVAL(inbuf
,1);
541 * We only really use 4 bytes of the outbuf, but for the smb_setlen
542 * calculation & friends (srv_send_smb uses that) we need the full smb
545 char outbuf
[smb_size
];
547 memset(outbuf
, '\0', sizeof(outbuf
));
549 smb_setlen(outbuf
,0);
552 case NBSSrequest
: /* session request */
554 /* inbuf_size is guarenteed to be at least 4. */
556 int name_type1
, name_type2
;
557 int name_len1
, name_len2
;
561 if (xconn
->transport
.nbt
.got_session
) {
562 exit_server_cleanly("multiple session request not permitted");
565 SCVAL(outbuf
,0,NBSSpositive
);
568 /* inbuf_size is guaranteed to be at least 4. */
569 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
570 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
571 DEBUG(0,("Invalid name length in session request\n"));
572 reply_called_name_not_present(outbuf
);
575 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
576 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
577 DEBUG(0,("Invalid name length in session request\n"));
578 reply_called_name_not_present(outbuf
);
582 name_type1
= name_extract((unsigned char *)inbuf
,
583 inbuf_size
,(unsigned int)4,name1
);
584 name_type2
= name_extract((unsigned char *)inbuf
,
585 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
587 if (name_type1
== -1 || name_type2
== -1) {
588 DEBUG(0,("Invalid name type in session request\n"));
589 reply_called_name_not_present(outbuf
);
593 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
594 name1
, name_type1
, name2
, name_type2
));
596 if (netbios_session_retarget(xconn
, name1
, name_type1
)) {
597 exit_server_cleanly("retargeted client");
601 * Windows NT/2k uses "*SMBSERVER" and XP uses
602 * "*SMBSERV" arrggg!!!
604 if (strequal(name1
, "*SMBSERVER ")
605 || strequal(name1
, "*SMBSERV ")) {
608 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
611 exit_server_cleanly("could not allocate raddr");
614 fstrcpy(name1
, raddr
);
617 set_local_machine_name(name1
, True
);
618 set_remote_machine_name(name2
, True
);
620 if (is_ipaddress(sconn
->remote_hostname
)) {
621 char *p
= discard_const_p(char, sconn
->remote_hostname
);
625 sconn
->remote_hostname
= talloc_strdup(sconn
,
626 get_remote_machine_name());
627 if (sconn
->remote_hostname
== NULL
) {
628 exit_server_cleanly("could not copy remote name");
630 xconn
->remote_hostname
= sconn
->remote_hostname
;
633 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
634 get_local_machine_name(), get_remote_machine_name(),
637 if (name_type2
== 'R') {
638 /* We are being asked for a pathworks session ---
640 reply_called_name_not_present(outbuf
);
644 reload_services(sconn
, conn_snum_used
, true);
647 xconn
->transport
.nbt
.got_session
= true;
651 case 0x89: /* session keepalive request
652 (some old clients produce this?) */
653 SCVAL(outbuf
,0,NBSSkeepalive
);
657 case NBSSpositive
: /* positive session response */
658 case NBSSnegative
: /* negative session response */
659 case NBSSretarget
: /* retarget session response */
660 DEBUG(0,("Unexpected session response\n"));
663 case NBSSkeepalive
: /* session keepalive */
668 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
669 msg_type
, msg_flags
));
671 srv_send_smb(xconn
, outbuf
, false, 0, false, NULL
);
673 if (CVAL(outbuf
, 0) != 0x82) {
674 exit_server_cleanly("invalid netbios session");
679 /****************************************************************************
681 conn POINTER CAN BE NULL HERE !
682 ****************************************************************************/
684 void reply_tcon(struct smb_request
*req
)
686 connection_struct
*conn
= req
->conn
;
688 char *service_buf
= NULL
;
689 char *password
= NULL
;
695 TALLOC_CTX
*ctx
= talloc_tos();
696 struct smbXsrv_connection
*xconn
= req
->xconn
;
697 NTTIME now
= timeval_to_nttime(&req
->request_time
);
699 START_PROFILE(SMBtcon
);
701 if (req
->buflen
< 4) {
702 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
703 END_PROFILE(SMBtcon
);
708 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
710 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
712 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
715 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
716 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
717 END_PROFILE(SMBtcon
);
720 p2
= strrchr_m(service_buf
,'\\');
724 service
= service_buf
;
727 conn
= make_connection(req
, now
, service
, dev
,
728 req
->vuid
,&nt_status
);
732 reply_nterror(req
, nt_status
);
733 END_PROFILE(SMBtcon
);
737 reply_outbuf(req
, 2, 0);
738 SSVAL(req
->outbuf
,smb_vwv0
,xconn
->smb1
.negprot
.max_recv
);
739 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
740 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
742 DEBUG(3,("tcon service=%s cnum=%d\n",
743 service
, conn
->cnum
));
745 END_PROFILE(SMBtcon
);
749 /****************************************************************************
750 Reply to a tcon and X.
751 conn POINTER CAN BE NULL HERE !
752 ****************************************************************************/
754 void reply_tcon_and_X(struct smb_request
*req
)
756 connection_struct
*conn
= req
->conn
;
757 const char *service
= NULL
;
758 TALLOC_CTX
*ctx
= talloc_tos();
759 /* what the cleint thinks the device is */
760 char *client_devicetype
= NULL
;
761 /* what the server tells the client the share represents */
762 const char *server_devicetype
;
769 struct smbXsrv_session
*session
= NULL
;
770 NTTIME now
= timeval_to_nttime(&req
->request_time
);
771 bool session_key_updated
= false;
772 uint16_t optional_support
= 0;
773 struct smbXsrv_connection
*xconn
= req
->xconn
;
775 START_PROFILE(SMBtconX
);
778 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
779 END_PROFILE(SMBtconX
);
783 passlen
= SVAL(req
->vwv
+3, 0);
784 tcon_flags
= SVAL(req
->vwv
+2, 0);
786 /* we might have to close an old one */
787 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
788 struct smbXsrv_tcon
*tcon
;
796 * TODO: cancel all outstanding requests on the tcon
798 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
799 if (!NT_STATUS_IS_OK(status
)) {
800 DEBUG(0, ("reply_tcon_and_X: "
801 "smbXsrv_tcon_disconnect() failed: %s\n",
804 * If we hit this case, there is something completely
805 * wrong, so we better disconnect the transport connection.
807 END_PROFILE(SMBtconX
);
808 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
815 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
816 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
817 END_PROFILE(SMBtconX
);
821 if (xconn
->smb1
.negprot
.encrypted_passwords
) {
822 p
= req
->buf
+ passlen
;
824 p
= req
->buf
+ passlen
+ 1;
827 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
830 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
831 END_PROFILE(SMBtconX
);
836 * the service name can be either: \\server\share
837 * or share directly like on the DELL PowerVault 705
840 q
= strchr_m(path
+2,'\\');
842 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
843 END_PROFILE(SMBtconX
);
851 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
852 &client_devicetype
, p
,
853 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
855 if (client_devicetype
== NULL
) {
856 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
857 END_PROFILE(SMBtconX
);
861 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
863 nt_status
= smb1srv_session_lookup(xconn
,
864 req
->vuid
, now
, &session
);
865 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
866 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
867 END_PROFILE(SMBtconX
);
870 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
871 reply_nterror(req
, nt_status
);
872 END_PROFILE(SMBtconX
);
875 if (!NT_STATUS_IS_OK(nt_status
)) {
876 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
877 END_PROFILE(SMBtconX
);
881 if (session
->global
->auth_session_info
== NULL
) {
882 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
883 END_PROFILE(SMBtconX
);
888 * If there is no application key defined yet
891 * This means we setup the application key on the
892 * first tcon that happens via the given session.
894 * Once the application key is defined, it does not
897 if (session
->global
->application_key
.length
== 0 &&
898 session
->global
->signing_key
.length
> 0)
900 struct smbXsrv_session
*x
= session
;
901 struct auth_session_info
*session_info
=
902 session
->global
->auth_session_info
;
903 uint8_t session_key
[16];
905 ZERO_STRUCT(session_key
);
906 memcpy(session_key
, x
->global
->signing_key
.data
,
907 MIN(x
->global
->signing_key
.length
, sizeof(session_key
)));
910 * The application key is truncated/padded to 16 bytes
912 x
->global
->application_key
= data_blob_talloc(x
->global
,
914 sizeof(session_key
));
915 ZERO_STRUCT(session_key
);
916 if (x
->global
->application_key
.data
== NULL
) {
917 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
918 END_PROFILE(SMBtconX
);
922 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
923 smb_key_derivation(x
->global
->application_key
.data
,
924 x
->global
->application_key
.length
,
925 x
->global
->application_key
.data
);
926 optional_support
|= SMB_EXTENDED_SIGNATURES
;
930 * Place the application key into the session_info
932 data_blob_clear_free(&session_info
->session_key
);
933 session_info
->session_key
= data_blob_dup_talloc(session_info
,
934 x
->global
->application_key
);
935 if (session_info
->session_key
.data
== NULL
) {
936 data_blob_clear_free(&x
->global
->application_key
);
937 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
938 END_PROFILE(SMBtconX
);
941 session_key_updated
= true;
944 conn
= make_connection(req
, now
, service
, client_devicetype
,
945 req
->vuid
, &nt_status
);
949 if (session_key_updated
) {
950 struct smbXsrv_session
*x
= session
;
951 struct auth_session_info
*session_info
=
952 session
->global
->auth_session_info
;
953 data_blob_clear_free(&x
->global
->application_key
);
954 data_blob_clear_free(&session_info
->session_key
);
956 reply_nterror(req
, nt_status
);
957 END_PROFILE(SMBtconX
);
962 server_devicetype
= "IPC";
963 else if ( IS_PRINT(conn
) )
964 server_devicetype
= "LPT1:";
966 server_devicetype
= "A:";
968 if (get_Protocol() < PROTOCOL_NT1
) {
969 reply_outbuf(req
, 2, 0);
970 if (message_push_string(&req
->outbuf
, server_devicetype
,
971 STR_TERMINATE
|STR_ASCII
) == -1) {
972 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
973 END_PROFILE(SMBtconX
);
977 /* NT sets the fstype of IPC$ to the null string */
978 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
980 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
981 /* Return permissions. */
985 reply_outbuf(req
, 7, 0);
988 perm1
= FILE_ALL_ACCESS
;
989 perm2
= FILE_ALL_ACCESS
;
991 perm1
= conn
->share_access
;
994 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
995 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
997 reply_outbuf(req
, 3, 0);
1000 if ((message_push_string(&req
->outbuf
, server_devicetype
,
1001 STR_TERMINATE
|STR_ASCII
) == -1)
1002 || (message_push_string(&req
->outbuf
, fstype
,
1003 STR_TERMINATE
) == -1)) {
1004 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1005 END_PROFILE(SMBtconX
);
1009 /* what does setting this bit do? It is set by NT4 and
1010 may affect the ability to autorun mounted cdroms */
1011 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
1013 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
1015 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
1016 DEBUG(2,("Serving %s as a Dfs root\n",
1017 lp_servicename(ctx
, SNUM(conn
)) ));
1018 optional_support
|= SMB_SHARE_IN_DFS
;
1021 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
1024 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1025 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1027 DEBUG(3,("tconX service=%s \n",
1030 /* set the incoming and outgoing tid to the just created one */
1031 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1032 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1034 END_PROFILE(SMBtconX
);
1036 req
->tid
= conn
->cnum
;
1039 /****************************************************************************
1040 Reply to an unknown type.
1041 ****************************************************************************/
1043 void reply_unknown_new(struct smb_request
*req
, uint8_t type
)
1045 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1046 smb_fn_name(type
), type
, type
));
1047 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1051 /****************************************************************************
1053 conn POINTER CAN BE NULL HERE !
1054 ****************************************************************************/
1056 void reply_ioctl(struct smb_request
*req
)
1058 connection_struct
*conn
= req
->conn
;
1061 uint32_t ioctl_code
;
1065 START_PROFILE(SMBioctl
);
1068 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1069 END_PROFILE(SMBioctl
);
1073 device
= SVAL(req
->vwv
+1, 0);
1074 function
= SVAL(req
->vwv
+2, 0);
1075 ioctl_code
= (device
<< 16) + function
;
1077 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1079 switch (ioctl_code
) {
1080 case IOCTL_QUERY_JOB_INFO
:
1084 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1085 END_PROFILE(SMBioctl
);
1089 reply_outbuf(req
, 8, replysize
+1);
1090 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1091 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1092 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1093 p
= smb_buf(req
->outbuf
);
1094 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1095 p
+= 1; /* Allow for alignment */
1097 switch (ioctl_code
) {
1098 case IOCTL_QUERY_JOB_INFO
:
1102 files_struct
*fsp
= file_fsp(
1103 req
, SVAL(req
->vwv
+0, 0));
1105 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1106 END_PROFILE(SMBioctl
);
1110 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1112 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1113 lp_netbios_name(), 15,
1114 STR_TERMINATE
|STR_ASCII
, &len
);
1115 if (!NT_STATUS_IS_OK(status
)) {
1116 reply_nterror(req
, status
);
1117 END_PROFILE(SMBioctl
);
1121 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
,
1123 lp_servicename(talloc_tos(),
1125 13, STR_TERMINATE
|STR_ASCII
, &len
);
1126 if (!NT_STATUS_IS_OK(status
)) {
1127 reply_nterror(req
, status
);
1128 END_PROFILE(SMBioctl
);
1132 memset(p
+18, 0, 13);
1138 END_PROFILE(SMBioctl
);
1142 /****************************************************************************
1143 Strange checkpath NTSTATUS mapping.
1144 ****************************************************************************/
1146 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1148 /* Strange DOS error code semantics only for checkpath... */
1149 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1150 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1151 /* We need to map to ERRbadpath */
1152 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1158 /****************************************************************************
1159 Reply to a checkpath.
1160 ****************************************************************************/
1162 void reply_checkpath(struct smb_request
*req
)
1164 connection_struct
*conn
= req
->conn
;
1165 struct smb_filename
*smb_fname
= NULL
;
1168 TALLOC_CTX
*ctx
= talloc_tos();
1170 START_PROFILE(SMBcheckpath
);
1172 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1173 STR_TERMINATE
, &status
);
1175 if (!NT_STATUS_IS_OK(status
)) {
1176 status
= map_checkpath_error(req
->flags2
, status
);
1177 reply_nterror(req
, status
);
1178 END_PROFILE(SMBcheckpath
);
1182 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1184 status
= filename_convert(ctx
,
1186 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1192 if (!NT_STATUS_IS_OK(status
)) {
1193 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1194 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1195 ERRSRV
, ERRbadpath
);
1196 END_PROFILE(SMBcheckpath
);
1202 if (!VALID_STAT(smb_fname
->st
) &&
1203 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1204 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1205 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1206 status
= map_nt_error_from_unix(errno
);
1210 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1211 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1212 ERRDOS
, ERRbadpath
);
1216 reply_outbuf(req
, 0, 0);
1219 /* We special case this - as when a Windows machine
1220 is parsing a path is steps through the components
1221 one at a time - if a component fails it expects
1222 ERRbadpath, not ERRbadfile.
1224 status
= map_checkpath_error(req
->flags2
, status
);
1225 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1227 * Windows returns different error codes if
1228 * the parent directory is valid but not the
1229 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1230 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1231 * if the path is invalid.
1233 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1234 ERRDOS
, ERRbadpath
);
1238 reply_nterror(req
, status
);
1241 TALLOC_FREE(smb_fname
);
1242 END_PROFILE(SMBcheckpath
);
1246 /****************************************************************************
1248 ****************************************************************************/
1250 void reply_getatr(struct smb_request
*req
)
1252 connection_struct
*conn
= req
->conn
;
1253 struct smb_filename
*smb_fname
= NULL
;
1260 TALLOC_CTX
*ctx
= talloc_tos();
1261 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1263 START_PROFILE(SMBgetatr
);
1265 p
= (const char *)req
->buf
+ 1;
1266 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1267 if (!NT_STATUS_IS_OK(status
)) {
1268 reply_nterror(req
, status
);
1272 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1273 under WfWg - weird! */
1274 if (*fname
== '\0') {
1275 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1276 if (!CAN_WRITE(conn
)) {
1277 mode
|= FILE_ATTRIBUTE_READONLY
;
1282 status
= filename_convert(ctx
,
1284 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1289 if (!NT_STATUS_IS_OK(status
)) {
1290 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1291 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1292 ERRSRV
, ERRbadpath
);
1295 reply_nterror(req
, status
);
1298 if (!VALID_STAT(smb_fname
->st
) &&
1299 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1300 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1301 smb_fname_str_dbg(smb_fname
),
1303 reply_nterror(req
, map_nt_error_from_unix(errno
));
1307 mode
= dos_mode(conn
, smb_fname
);
1308 size
= smb_fname
->st
.st_ex_size
;
1310 if (ask_sharemode
) {
1311 struct timespec write_time_ts
;
1312 struct file_id fileid
;
1314 ZERO_STRUCT(write_time_ts
);
1315 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1316 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1317 if (!null_timespec(write_time_ts
)) {
1318 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1322 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1323 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1328 reply_outbuf(req
, 10, 0);
1330 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1331 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1332 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1334 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1336 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
1338 if (get_Protocol() >= PROTOCOL_NT1
) {
1339 SSVAL(req
->outbuf
, smb_flg2
,
1340 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1343 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1344 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1347 TALLOC_FREE(smb_fname
);
1349 END_PROFILE(SMBgetatr
);
1353 /****************************************************************************
1355 ****************************************************************************/
1357 void reply_setatr(struct smb_request
*req
)
1359 struct smb_file_time ft
;
1360 connection_struct
*conn
= req
->conn
;
1361 struct smb_filename
*smb_fname
= NULL
;
1367 TALLOC_CTX
*ctx
= talloc_tos();
1369 START_PROFILE(SMBsetatr
);
1374 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1378 p
= (const char *)req
->buf
+ 1;
1379 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1380 if (!NT_STATUS_IS_OK(status
)) {
1381 reply_nterror(req
, status
);
1385 status
= filename_convert(ctx
,
1387 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1392 if (!NT_STATUS_IS_OK(status
)) {
1393 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1394 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1395 ERRSRV
, ERRbadpath
);
1398 reply_nterror(req
, status
);
1402 if (smb_fname
->base_name
[0] == '.' &&
1403 smb_fname
->base_name
[1] == '\0') {
1405 * Not sure here is the right place to catch this
1406 * condition. Might be moved to somewhere else later -- vl
1408 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1412 mode
= SVAL(req
->vwv
+0, 0);
1413 mtime
= srv_make_unix_date3(req
->vwv
+1);
1415 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1416 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1417 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1419 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1421 status
= check_access(conn
, NULL
, smb_fname
,
1422 FILE_WRITE_ATTRIBUTES
);
1423 if (!NT_STATUS_IS_OK(status
)) {
1424 reply_nterror(req
, status
);
1428 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1430 reply_nterror(req
, map_nt_error_from_unix(errno
));
1435 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1436 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1437 if (!NT_STATUS_IS_OK(status
)) {
1438 reply_nterror(req
, status
);
1442 reply_outbuf(req
, 0, 0);
1444 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1447 TALLOC_FREE(smb_fname
);
1448 END_PROFILE(SMBsetatr
);
1452 /****************************************************************************
1454 ****************************************************************************/
1456 void reply_dskattr(struct smb_request
*req
)
1458 connection_struct
*conn
= req
->conn
;
1460 uint64_t dfree
,dsize
,bsize
;
1461 START_PROFILE(SMBdskattr
);
1463 ret
= get_dfree_info(conn
, ".", &bsize
, &dfree
, &dsize
);
1464 if (ret
== (uint64_t)-1) {
1465 reply_nterror(req
, map_nt_error_from_unix(errno
));
1466 END_PROFILE(SMBdskattr
);
1471 * Force max to fit in 16 bit fields.
1473 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1477 if (bsize
> (WORDMAX
*512)) {
1478 bsize
= (WORDMAX
*512);
1479 if (dsize
> WORDMAX
)
1481 if (dfree
> WORDMAX
)
1487 reply_outbuf(req
, 5, 0);
1489 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1490 double total_space
, free_space
;
1491 /* we need to scale this to a number that DOS6 can handle. We
1492 use floating point so we can handle large drives on systems
1493 that don't have 64 bit integers
1495 we end up displaying a maximum of 2G to DOS systems
1497 total_space
= dsize
* (double)bsize
;
1498 free_space
= dfree
* (double)bsize
;
1500 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1501 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1503 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1504 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1506 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1507 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1508 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1509 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1511 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1512 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1513 SSVAL(req
->outbuf
,smb_vwv2
,512);
1514 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1517 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1519 END_PROFILE(SMBdskattr
);
1524 * Utility function to split the filename from the directory.
1526 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1527 char **fname_dir_out
,
1528 char **fname_mask_out
)
1530 const char *p
= NULL
;
1531 char *fname_dir
= NULL
;
1532 char *fname_mask
= NULL
;
1534 p
= strrchr_m(fname_in
, '/');
1536 fname_dir
= talloc_strdup(ctx
, ".");
1537 fname_mask
= talloc_strdup(ctx
, fname_in
);
1539 fname_dir
= talloc_strndup(ctx
, fname_in
,
1540 PTR_DIFF(p
, fname_in
));
1541 fname_mask
= talloc_strdup(ctx
, p
+1);
1544 if (!fname_dir
|| !fname_mask
) {
1545 TALLOC_FREE(fname_dir
);
1546 TALLOC_FREE(fname_mask
);
1547 return NT_STATUS_NO_MEMORY
;
1550 *fname_dir_out
= fname_dir
;
1551 *fname_mask_out
= fname_mask
;
1552 return NT_STATUS_OK
;
1555 /****************************************************************************
1557 ****************************************************************************/
1559 static bool make_dir_struct(TALLOC_CTX
*ctx
,
1569 char *mask2
= talloc_strdup(ctx
, mask
);
1575 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1579 memset(buf
+1,' ',11);
1580 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
1582 push_ascii(buf
+1,mask2
,8, 0);
1583 push_ascii(buf
+9,p
+1,3, 0);
1586 push_ascii(buf
+1,mask2
,11, 0);
1589 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1591 srv_put_dos_date(buf
,22,date
);
1592 SSVAL(buf
,26,size
& 0xFFFF);
1593 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1594 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1595 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1596 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1597 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1601 /****************************************************************************
1603 Can be called from SMBsearch, SMBffirst or SMBfunique.
1604 ****************************************************************************/
1606 void reply_search(struct smb_request
*req
)
1608 connection_struct
*conn
= req
->conn
;
1610 const char *mask
= NULL
;
1611 char *directory
= NULL
;
1612 struct smb_filename
*smb_fname
= NULL
;
1616 struct timespec date
;
1618 unsigned int numentries
= 0;
1619 unsigned int maxentries
= 0;
1620 bool finished
= False
;
1625 bool check_descend
= False
;
1626 bool expect_close
= False
;
1628 bool mask_contains_wcard
= False
;
1629 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1630 TALLOC_CTX
*ctx
= talloc_tos();
1631 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1632 struct dptr_struct
*dirptr
= NULL
;
1633 struct smbXsrv_connection
*xconn
= req
->xconn
;
1634 struct smbd_server_connection
*sconn
= req
->sconn
;
1636 START_PROFILE(SMBsearch
);
1639 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1643 if (lp_posix_pathnames()) {
1644 reply_unknown_new(req
, req
->cmd
);
1648 /* If we were called as SMBffirst then we must expect close. */
1649 if(req
->cmd
== SMBffirst
) {
1650 expect_close
= True
;
1653 reply_outbuf(req
, 1, 3);
1654 maxentries
= SVAL(req
->vwv
+0, 0);
1655 dirtype
= SVAL(req
->vwv
+1, 0);
1656 p
= (const char *)req
->buf
+ 1;
1657 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1658 &nt_status
, &mask_contains_wcard
);
1659 if (!NT_STATUS_IS_OK(nt_status
)) {
1660 reply_nterror(req
, nt_status
);
1665 status_len
= SVAL(p
, 0);
1668 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1670 if (status_len
== 0) {
1671 nt_status
= filename_convert(ctx
, conn
,
1672 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1674 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1675 &mask_contains_wcard
,
1677 if (!NT_STATUS_IS_OK(nt_status
)) {
1678 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1679 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1680 ERRSRV
, ERRbadpath
);
1683 reply_nterror(req
, nt_status
);
1687 directory
= smb_fname
->base_name
;
1689 p
= strrchr_m(directory
,'/');
1690 if ((p
!= NULL
) && (*directory
!= '/')) {
1692 directory
= talloc_strndup(ctx
, directory
,
1693 PTR_DIFF(p
, directory
));
1696 directory
= talloc_strdup(ctx
,".");
1700 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1704 memset((char *)status
,'\0',21);
1705 SCVAL(status
,0,(dirtype
& 0x1F));
1707 nt_status
= dptr_create(conn
,
1715 mask_contains_wcard
,
1718 if (!NT_STATUS_IS_OK(nt_status
)) {
1719 reply_nterror(req
, nt_status
);
1722 dptr_num
= dptr_dnum(dirptr
);
1725 const char *dirpath
;
1727 memcpy(status
,p
,21);
1728 status_dirtype
= CVAL(status
,0) & 0x1F;
1729 if (status_dirtype
!= (dirtype
& 0x1F)) {
1730 dirtype
= status_dirtype
;
1733 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1737 dirpath
= dptr_path(sconn
, dptr_num
);
1738 directory
= talloc_strdup(ctx
, dirpath
);
1740 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1744 mask
= dptr_wcard(sconn
, dptr_num
);
1749 * For a 'continue' search we have no string. So
1750 * check from the initial saved string.
1752 mask_contains_wcard
= ms_has_wild(mask
);
1753 dirtype
= dptr_attr(sconn
, dptr_num
);
1756 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1758 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1759 dptr_init_search_op(dirptr
);
1761 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1762 char buf
[DIR_STRUCT_SIZE
];
1763 memcpy(buf
,status
,21);
1764 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1765 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1766 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1769 dptr_fill(sconn
, buf
+12,dptr_num
);
1770 if (dptr_zero(buf
+12) && (status_len
==0)) {
1775 if (message_push_blob(&req
->outbuf
,
1776 data_blob_const(buf
, sizeof(buf
)))
1778 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1783 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1784 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1786 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1788 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1789 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
1790 if (in_list(directory
, lp_dont_descend(ctx
, SNUM(conn
)),True
)) {
1791 check_descend
= True
;
1794 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1795 finished
= !get_dir_entry(ctx
,
1806 char buf
[DIR_STRUCT_SIZE
];
1807 memcpy(buf
,status
,21);
1808 if (!make_dir_struct(ctx
,
1814 convert_timespec_to_time_t(date
),
1815 !allow_long_path_components
)) {
1816 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1819 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1822 if (message_push_blob(&req
->outbuf
,
1823 data_blob_const(buf
, sizeof(buf
)))
1825 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1835 /* If we were called as SMBffirst with smb_search_id == NULL
1836 and no entries were found then return error and close dirptr
1839 if (numentries
== 0) {
1840 dptr_close(sconn
, &dptr_num
);
1841 } else if(expect_close
&& status_len
== 0) {
1842 /* Close the dptr - we know it's gone */
1843 dptr_close(sconn
, &dptr_num
);
1846 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1847 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1848 dptr_close(sconn
, &dptr_num
);
1851 if ((numentries
== 0) && !mask_contains_wcard
) {
1852 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1856 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1857 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1858 SCVAL(smb_buf(req
->outbuf
),0,5);
1859 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1861 /* The replies here are never long name. */
1862 SSVAL(req
->outbuf
, smb_flg2
,
1863 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1864 if (!allow_long_path_components
) {
1865 SSVAL(req
->outbuf
, smb_flg2
,
1866 SVAL(req
->outbuf
, smb_flg2
)
1867 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1870 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1871 SSVAL(req
->outbuf
, smb_flg2
,
1872 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1874 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1875 smb_fn_name(req
->cmd
),
1882 TALLOC_FREE(directory
);
1883 TALLOC_FREE(smb_fname
);
1884 END_PROFILE(SMBsearch
);
1888 /****************************************************************************
1889 Reply to a fclose (stop directory search).
1890 ****************************************************************************/
1892 void reply_fclose(struct smb_request
*req
)
1900 bool path_contains_wcard
= False
;
1901 TALLOC_CTX
*ctx
= talloc_tos();
1902 struct smbd_server_connection
*sconn
= req
->sconn
;
1904 START_PROFILE(SMBfclose
);
1906 if (lp_posix_pathnames()) {
1907 reply_unknown_new(req
, req
->cmd
);
1908 END_PROFILE(SMBfclose
);
1912 p
= (const char *)req
->buf
+ 1;
1913 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1914 &err
, &path_contains_wcard
);
1915 if (!NT_STATUS_IS_OK(err
)) {
1916 reply_nterror(req
, err
);
1917 END_PROFILE(SMBfclose
);
1921 status_len
= SVAL(p
,0);
1924 if (status_len
== 0) {
1925 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1926 END_PROFILE(SMBfclose
);
1930 memcpy(status
,p
,21);
1932 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1933 /* Close the dptr - we know it's gone */
1934 dptr_close(sconn
, &dptr_num
);
1937 reply_outbuf(req
, 1, 0);
1938 SSVAL(req
->outbuf
,smb_vwv0
,0);
1940 DEBUG(3,("search close\n"));
1942 END_PROFILE(SMBfclose
);
1946 /****************************************************************************
1948 ****************************************************************************/
1950 void reply_open(struct smb_request
*req
)
1952 connection_struct
*conn
= req
->conn
;
1953 struct smb_filename
*smb_fname
= NULL
;
1963 uint32_t access_mask
;
1964 uint32_t share_mode
;
1965 uint32_t create_disposition
;
1966 uint32_t create_options
= 0;
1967 uint32_t private_flags
= 0;
1969 TALLOC_CTX
*ctx
= talloc_tos();
1971 START_PROFILE(SMBopen
);
1974 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1978 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1979 deny_mode
= SVAL(req
->vwv
+0, 0);
1980 dos_attr
= SVAL(req
->vwv
+1, 0);
1982 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1983 STR_TERMINATE
, &status
);
1984 if (!NT_STATUS_IS_OK(status
)) {
1985 reply_nterror(req
, status
);
1989 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1990 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1991 &share_mode
, &create_disposition
,
1992 &create_options
, &private_flags
)) {
1993 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1997 status
= filename_convert(ctx
,
1999 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2001 UCF_PREP_CREATEFILE
,
2004 if (!NT_STATUS_IS_OK(status
)) {
2005 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2006 reply_botherror(req
,
2007 NT_STATUS_PATH_NOT_COVERED
,
2008 ERRSRV
, ERRbadpath
);
2011 reply_nterror(req
, status
);
2015 status
= SMB_VFS_CREATE_FILE(
2018 0, /* root_dir_fid */
2019 smb_fname
, /* fname */
2020 access_mask
, /* access_mask */
2021 share_mode
, /* share_access */
2022 create_disposition
, /* create_disposition*/
2023 create_options
, /* create_options */
2024 dos_attr
, /* file_attributes */
2025 oplock_request
, /* oplock_request */
2027 0, /* allocation_size */
2033 NULL
, NULL
); /* create context */
2035 if (!NT_STATUS_IS_OK(status
)) {
2036 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2037 /* We have re-scheduled this call. */
2040 reply_openerror(req
, status
);
2044 /* Ensure we're pointing at the correct stat struct. */
2045 TALLOC_FREE(smb_fname
);
2046 smb_fname
= fsp
->fsp_name
;
2048 size
= smb_fname
->st
.st_ex_size
;
2049 fattr
= dos_mode(conn
, smb_fname
);
2051 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2053 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2054 DEBUG(3,("attempt to open a directory %s\n",
2056 close_file(req
, fsp
, ERROR_CLOSE
);
2057 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2058 ERRDOS
, ERRnoaccess
);
2062 reply_outbuf(req
, 7, 0);
2063 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2064 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2065 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2066 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2068 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2070 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
2071 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2073 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2074 SCVAL(req
->outbuf
,smb_flg
,
2075 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2078 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2079 SCVAL(req
->outbuf
,smb_flg
,
2080 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2083 END_PROFILE(SMBopen
);
2087 /****************************************************************************
2088 Reply to an open and X.
2089 ****************************************************************************/
2091 void reply_open_and_X(struct smb_request
*req
)
2093 connection_struct
*conn
= req
->conn
;
2094 struct smb_filename
*smb_fname
= NULL
;
2096 uint16_t open_flags
;
2099 /* Breakout the oplock request bits so we can set the
2100 reply bits separately. */
2101 int ex_oplock_request
;
2102 int core_oplock_request
;
2105 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2106 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
2114 uint64_t allocation_size
;
2115 ssize_t retval
= -1;
2116 uint32_t access_mask
;
2117 uint32_t share_mode
;
2118 uint32_t create_disposition
;
2119 uint32_t create_options
= 0;
2120 uint32_t private_flags
= 0;
2121 TALLOC_CTX
*ctx
= talloc_tos();
2123 START_PROFILE(SMBopenX
);
2125 if (req
->wct
< 15) {
2126 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2130 open_flags
= SVAL(req
->vwv
+2, 0);
2131 deny_mode
= SVAL(req
->vwv
+3, 0);
2132 smb_attr
= SVAL(req
->vwv
+5, 0);
2133 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2134 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2135 oplock_request
= ex_oplock_request
| core_oplock_request
;
2136 smb_ofun
= SVAL(req
->vwv
+8, 0);
2137 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2139 /* If it's an IPC, pass off the pipe handler. */
2141 if (lp_nt_pipe_support()) {
2142 reply_open_pipe_and_X(conn
, req
);
2144 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2149 /* XXXX we need to handle passed times, sattr and flags */
2150 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2151 STR_TERMINATE
, &status
);
2152 if (!NT_STATUS_IS_OK(status
)) {
2153 reply_nterror(req
, status
);
2157 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2159 &access_mask
, &share_mode
,
2160 &create_disposition
,
2163 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2167 status
= filename_convert(ctx
,
2169 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2171 UCF_PREP_CREATEFILE
,
2174 if (!NT_STATUS_IS_OK(status
)) {
2175 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2176 reply_botherror(req
,
2177 NT_STATUS_PATH_NOT_COVERED
,
2178 ERRSRV
, ERRbadpath
);
2181 reply_nterror(req
, status
);
2185 status
= SMB_VFS_CREATE_FILE(
2188 0, /* root_dir_fid */
2189 smb_fname
, /* fname */
2190 access_mask
, /* access_mask */
2191 share_mode
, /* share_access */
2192 create_disposition
, /* create_disposition*/
2193 create_options
, /* create_options */
2194 smb_attr
, /* file_attributes */
2195 oplock_request
, /* oplock_request */
2197 0, /* allocation_size */
2202 &smb_action
, /* pinfo */
2203 NULL
, NULL
); /* create context */
2205 if (!NT_STATUS_IS_OK(status
)) {
2206 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2207 /* We have re-scheduled this call. */
2210 reply_openerror(req
, status
);
2214 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2215 if the file is truncated or created. */
2216 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2217 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2218 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2219 close_file(req
, fsp
, ERROR_CLOSE
);
2220 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2223 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2225 close_file(req
, fsp
, ERROR_CLOSE
);
2226 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2229 status
= vfs_stat_fsp(fsp
);
2230 if (!NT_STATUS_IS_OK(status
)) {
2231 close_file(req
, fsp
, ERROR_CLOSE
);
2232 reply_nterror(req
, status
);
2237 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2238 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2239 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2240 close_file(req
, fsp
, ERROR_CLOSE
);
2241 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2245 /* If the caller set the extended oplock request bit
2246 and we granted one (by whatever means) - set the
2247 correct bit for extended oplock reply.
2250 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2251 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2254 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2255 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2258 /* If the caller set the core oplock request bit
2259 and we granted one (by whatever means) - set the
2260 correct bit for core oplock reply.
2263 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2264 reply_outbuf(req
, 19, 0);
2266 reply_outbuf(req
, 15, 0);
2269 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2270 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2272 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2273 SCVAL(req
->outbuf
, smb_flg
,
2274 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2277 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2278 SCVAL(req
->outbuf
, smb_flg
,
2279 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2282 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2283 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2284 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2285 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2287 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2289 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2290 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2291 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2293 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2294 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2298 TALLOC_FREE(smb_fname
);
2299 END_PROFILE(SMBopenX
);
2303 /****************************************************************************
2304 Reply to a SMBulogoffX.
2305 ****************************************************************************/
2307 void reply_ulogoffX(struct smb_request
*req
)
2309 struct smbd_server_connection
*sconn
= req
->sconn
;
2310 struct user_struct
*vuser
;
2311 struct smbXsrv_session
*session
= NULL
;
2314 START_PROFILE(SMBulogoffX
);
2316 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2319 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2320 (unsigned long long)req
->vuid
));
2322 req
->vuid
= UID_FIELD_INVALID
;
2323 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2324 END_PROFILE(SMBulogoffX
);
2328 session
= vuser
->session
;
2332 * TODO: cancel all outstanding requests on the session
2334 status
= smbXsrv_session_logoff(session
);
2335 if (!NT_STATUS_IS_OK(status
)) {
2336 DEBUG(0, ("reply_ulogoff: "
2337 "smbXsrv_session_logoff() failed: %s\n",
2338 nt_errstr(status
)));
2340 * If we hit this case, there is something completely
2341 * wrong, so we better disconnect the transport connection.
2343 END_PROFILE(SMBulogoffX
);
2344 exit_server(__location__
": smbXsrv_session_logoff failed");
2348 TALLOC_FREE(session
);
2350 reply_outbuf(req
, 2, 0);
2351 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2352 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2354 DEBUG(3, ("ulogoffX vuid=%llu\n",
2355 (unsigned long long)req
->vuid
));
2357 END_PROFILE(SMBulogoffX
);
2358 req
->vuid
= UID_FIELD_INVALID
;
2361 /****************************************************************************
2362 Reply to a mknew or a create.
2363 ****************************************************************************/
2365 void reply_mknew(struct smb_request
*req
)
2367 connection_struct
*conn
= req
->conn
;
2368 struct smb_filename
*smb_fname
= NULL
;
2371 struct smb_file_time ft
;
2373 int oplock_request
= 0;
2375 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2376 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2377 uint32_t create_disposition
;
2378 uint32_t create_options
= 0;
2379 TALLOC_CTX
*ctx
= talloc_tos();
2381 START_PROFILE(SMBcreate
);
2385 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2389 fattr
= SVAL(req
->vwv
+0, 0);
2390 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2393 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2395 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2396 STR_TERMINATE
, &status
);
2397 if (!NT_STATUS_IS_OK(status
)) {
2398 reply_nterror(req
, status
);
2402 status
= filename_convert(ctx
,
2404 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2406 UCF_PREP_CREATEFILE
,
2409 if (!NT_STATUS_IS_OK(status
)) {
2410 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2411 reply_botherror(req
,
2412 NT_STATUS_PATH_NOT_COVERED
,
2413 ERRSRV
, ERRbadpath
);
2416 reply_nterror(req
, status
);
2420 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2421 DEBUG(0,("Attempt to create file (%s) with volid set - "
2422 "please report this\n",
2423 smb_fname_str_dbg(smb_fname
)));
2426 if(req
->cmd
== SMBmknew
) {
2427 /* We should fail if file exists. */
2428 create_disposition
= FILE_CREATE
;
2430 /* Create if file doesn't exist, truncate if it does. */
2431 create_disposition
= FILE_OVERWRITE_IF
;
2434 status
= SMB_VFS_CREATE_FILE(
2437 0, /* root_dir_fid */
2438 smb_fname
, /* fname */
2439 access_mask
, /* access_mask */
2440 share_mode
, /* share_access */
2441 create_disposition
, /* create_disposition*/
2442 create_options
, /* create_options */
2443 fattr
, /* file_attributes */
2444 oplock_request
, /* oplock_request */
2446 0, /* allocation_size */
2447 0, /* private_flags */
2452 NULL
, NULL
); /* create context */
2454 if (!NT_STATUS_IS_OK(status
)) {
2455 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2456 /* We have re-scheduled this call. */
2459 reply_openerror(req
, status
);
2463 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2464 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2465 if (!NT_STATUS_IS_OK(status
)) {
2466 END_PROFILE(SMBcreate
);
2470 reply_outbuf(req
, 1, 0);
2471 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2473 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2474 SCVAL(req
->outbuf
,smb_flg
,
2475 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2478 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2479 SCVAL(req
->outbuf
,smb_flg
,
2480 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2483 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2484 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2485 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2486 (unsigned int)fattr
));
2489 TALLOC_FREE(smb_fname
);
2490 END_PROFILE(SMBcreate
);
2494 /****************************************************************************
2495 Reply to a create temporary file.
2496 ****************************************************************************/
2498 void reply_ctemp(struct smb_request
*req
)
2500 connection_struct
*conn
= req
->conn
;
2501 struct smb_filename
*smb_fname
= NULL
;
2502 char *wire_name
= NULL
;
2510 TALLOC_CTX
*ctx
= talloc_tos();
2512 START_PROFILE(SMBctemp
);
2515 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2519 fattr
= SVAL(req
->vwv
+0, 0);
2520 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2522 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2523 STR_TERMINATE
, &status
);
2524 if (!NT_STATUS_IS_OK(status
)) {
2525 reply_nterror(req
, status
);
2529 for (i
= 0; i
< 10; i
++) {
2531 fname
= talloc_asprintf(ctx
,
2534 generate_random_str_list(ctx
, 5, "0123456789"));
2536 fname
= talloc_asprintf(ctx
,
2538 generate_random_str_list(ctx
, 5, "0123456789"));
2542 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2546 status
= filename_convert(ctx
, conn
,
2547 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2549 UCF_PREP_CREATEFILE
,
2552 if (!NT_STATUS_IS_OK(status
)) {
2553 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2554 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2555 ERRSRV
, ERRbadpath
);
2558 reply_nterror(req
, status
);
2562 /* Create the file. */
2563 status
= SMB_VFS_CREATE_FILE(
2566 0, /* root_dir_fid */
2567 smb_fname
, /* fname */
2568 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2569 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2570 FILE_CREATE
, /* create_disposition*/
2571 0, /* create_options */
2572 fattr
, /* file_attributes */
2573 oplock_request
, /* oplock_request */
2575 0, /* allocation_size */
2576 0, /* private_flags */
2581 NULL
, NULL
); /* create context */
2583 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2585 TALLOC_FREE(smb_fname
);
2589 if (!NT_STATUS_IS_OK(status
)) {
2590 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2591 /* We have re-scheduled this call. */
2594 reply_openerror(req
, status
);
2602 /* Collision after 10 times... */
2603 reply_nterror(req
, status
);
2607 reply_outbuf(req
, 1, 0);
2608 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2610 /* the returned filename is relative to the directory */
2611 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2613 s
= fsp
->fsp_name
->base_name
;
2619 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2620 thing in the byte section. JRA */
2621 SSVALS(p
, 0, -1); /* what is this? not in spec */
2623 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2625 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2629 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2630 SCVAL(req
->outbuf
, smb_flg
,
2631 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2634 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2635 SCVAL(req
->outbuf
, smb_flg
,
2636 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2639 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2640 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2641 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2643 TALLOC_FREE(smb_fname
);
2644 TALLOC_FREE(wire_name
);
2645 END_PROFILE(SMBctemp
);
2649 /*******************************************************************
2650 Check if a user is allowed to rename a file.
2651 ********************************************************************/
2653 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2656 if (!CAN_WRITE(conn
)) {
2657 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2660 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2661 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2662 /* Only bother to read the DOS attribute if we might deny the
2663 rename on the grounds of attribute missmatch. */
2664 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2665 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2666 return NT_STATUS_NO_SUCH_FILE
;
2670 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2671 if (fsp
->posix_open
) {
2672 return NT_STATUS_OK
;
2675 /* If no pathnames are open below this
2676 directory, allow the rename. */
2678 if (file_find_subpath(fsp
)) {
2679 return NT_STATUS_ACCESS_DENIED
;
2681 return NT_STATUS_OK
;
2684 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2685 return NT_STATUS_OK
;
2688 return NT_STATUS_ACCESS_DENIED
;
2691 /*******************************************************************
2692 * unlink a file with all relevant access checks
2693 *******************************************************************/
2695 static NTSTATUS
do_unlink(connection_struct
*conn
,
2696 struct smb_request
*req
,
2697 struct smb_filename
*smb_fname
,
2702 uint32_t dirtype_orig
= dirtype
;
2705 bool posix_paths
= lp_posix_pathnames();
2707 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2708 smb_fname_str_dbg(smb_fname
),
2711 if (!CAN_WRITE(conn
)) {
2712 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2716 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2718 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2721 return map_nt_error_from_unix(errno
);
2724 fattr
= dos_mode(conn
, smb_fname
);
2726 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2727 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2730 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2732 return NT_STATUS_NO_SUCH_FILE
;
2735 if (!dir_check_ftype(fattr
, dirtype
)) {
2736 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2737 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2739 return NT_STATUS_NO_SUCH_FILE
;
2742 if (dirtype_orig
& 0x8000) {
2743 /* These will never be set for POSIX. */
2744 return NT_STATUS_NO_SUCH_FILE
;
2748 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2749 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2752 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2753 return NT_STATUS_NO_SUCH_FILE
;
2756 if (dirtype
& 0xFF00) {
2757 /* These will never be set for POSIX. */
2758 return NT_STATUS_NO_SUCH_FILE
;
2763 return NT_STATUS_NO_SUCH_FILE
;
2766 /* Can't delete a directory. */
2767 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2768 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2773 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2774 return NT_STATUS_OBJECT_NAME_INVALID
;
2775 #endif /* JRATEST */
2777 /* On open checks the open itself will check the share mode, so
2778 don't do it here as we'll get it wrong. */
2780 status
= SMB_VFS_CREATE_FILE
2783 0, /* root_dir_fid */
2784 smb_fname
, /* fname */
2785 DELETE_ACCESS
, /* access_mask */
2786 FILE_SHARE_NONE
, /* share_access */
2787 FILE_OPEN
, /* create_disposition*/
2788 FILE_NON_DIRECTORY_FILE
, /* create_options */
2789 /* file_attributes */
2790 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2791 FILE_ATTRIBUTE_NORMAL
,
2792 0, /* oplock_request */
2794 0, /* allocation_size */
2795 0, /* private_flags */
2800 NULL
, NULL
); /* create context */
2802 if (!NT_STATUS_IS_OK(status
)) {
2803 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2804 nt_errstr(status
)));
2808 status
= can_set_delete_on_close(fsp
, fattr
);
2809 if (!NT_STATUS_IS_OK(status
)) {
2810 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2812 smb_fname_str_dbg(smb_fname
),
2813 nt_errstr(status
)));
2814 close_file(req
, fsp
, NORMAL_CLOSE
);
2818 /* The set is across all open files on this dev/inode pair. */
2819 if (!set_delete_on_close(fsp
, True
,
2820 conn
->session_info
->security_token
,
2821 conn
->session_info
->unix_token
)) {
2822 close_file(req
, fsp
, NORMAL_CLOSE
);
2823 return NT_STATUS_ACCESS_DENIED
;
2826 return close_file(req
, fsp
, NORMAL_CLOSE
);
2829 /****************************************************************************
2830 The guts of the unlink command, split out so it may be called by the NT SMB
2832 ****************************************************************************/
2834 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2835 uint32_t dirtype
, struct smb_filename
*smb_fname
,
2838 char *fname_dir
= NULL
;
2839 char *fname_mask
= NULL
;
2841 NTSTATUS status
= NT_STATUS_OK
;
2842 TALLOC_CTX
*ctx
= talloc_tos();
2844 /* Split up the directory from the filename/mask. */
2845 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2846 &fname_dir
, &fname_mask
);
2847 if (!NT_STATUS_IS_OK(status
)) {
2852 * We should only check the mangled cache
2853 * here if unix_convert failed. This means
2854 * that the path in 'mask' doesn't exist
2855 * on the file system and so we need to look
2856 * for a possible mangle. This patch from
2857 * Tine Smukavec <valentin.smukavec@hermes.si>.
2860 if (!VALID_STAT(smb_fname
->st
) &&
2861 mangle_is_mangled(fname_mask
, conn
->params
)) {
2862 char *new_mask
= NULL
;
2863 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2864 &new_mask
, conn
->params
);
2866 TALLOC_FREE(fname_mask
);
2867 fname_mask
= new_mask
;
2874 * Only one file needs to be unlinked. Append the mask back
2875 * onto the directory.
2877 TALLOC_FREE(smb_fname
->base_name
);
2878 if (ISDOT(fname_dir
)) {
2879 /* Ensure we use canonical names on open. */
2880 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2884 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2889 if (!smb_fname
->base_name
) {
2890 status
= NT_STATUS_NO_MEMORY
;
2894 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2897 status
= check_name(conn
, smb_fname
->base_name
);
2898 if (!NT_STATUS_IS_OK(status
)) {
2902 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2903 if (!NT_STATUS_IS_OK(status
)) {
2909 struct smb_Dir
*dir_hnd
= NULL
;
2911 const char *dname
= NULL
;
2912 char *talloced
= NULL
;
2914 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2915 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2919 if (strequal(fname_mask
,"????????.???")) {
2920 TALLOC_FREE(fname_mask
);
2921 fname_mask
= talloc_strdup(ctx
, "*");
2923 status
= NT_STATUS_NO_MEMORY
;
2928 status
= check_name(conn
, fname_dir
);
2929 if (!NT_STATUS_IS_OK(status
)) {
2933 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2935 if (dir_hnd
== NULL
) {
2936 status
= map_nt_error_from_unix(errno
);
2940 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2941 the pattern matches against the long name, otherwise the short name
2942 We don't implement this yet XXXX
2945 status
= NT_STATUS_NO_SUCH_FILE
;
2947 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2948 &smb_fname
->st
, &talloced
))) {
2949 TALLOC_CTX
*frame
= talloc_stackframe();
2951 if (!is_visible_file(conn
, fname_dir
, dname
,
2952 &smb_fname
->st
, true)) {
2954 TALLOC_FREE(talloced
);
2958 /* Quick check for "." and ".." */
2959 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2961 TALLOC_FREE(talloced
);
2965 if(!mask_match(dname
, fname_mask
,
2966 conn
->case_sensitive
)) {
2968 TALLOC_FREE(talloced
);
2972 TALLOC_FREE(smb_fname
->base_name
);
2973 if (ISDOT(fname_dir
)) {
2974 /* Ensure we use canonical names on open. */
2975 smb_fname
->base_name
=
2976 talloc_asprintf(smb_fname
, "%s",
2979 smb_fname
->base_name
=
2980 talloc_asprintf(smb_fname
, "%s/%s",
2984 if (!smb_fname
->base_name
) {
2985 TALLOC_FREE(dir_hnd
);
2986 status
= NT_STATUS_NO_MEMORY
;
2988 TALLOC_FREE(talloced
);
2992 status
= check_name(conn
, smb_fname
->base_name
);
2993 if (!NT_STATUS_IS_OK(status
)) {
2994 TALLOC_FREE(dir_hnd
);
2996 TALLOC_FREE(talloced
);
3000 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3001 if (!NT_STATUS_IS_OK(status
)) {
3002 TALLOC_FREE(dir_hnd
);
3004 TALLOC_FREE(talloced
);
3009 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3010 smb_fname
->base_name
));
3013 TALLOC_FREE(talloced
);
3015 TALLOC_FREE(dir_hnd
);
3018 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3019 status
= map_nt_error_from_unix(errno
);
3023 TALLOC_FREE(fname_dir
);
3024 TALLOC_FREE(fname_mask
);
3028 /****************************************************************************
3030 ****************************************************************************/
3032 void reply_unlink(struct smb_request
*req
)
3034 connection_struct
*conn
= req
->conn
;
3036 struct smb_filename
*smb_fname
= NULL
;
3039 bool path_contains_wcard
= False
;
3040 TALLOC_CTX
*ctx
= talloc_tos();
3042 START_PROFILE(SMBunlink
);
3045 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3049 dirtype
= SVAL(req
->vwv
+0, 0);
3051 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3052 STR_TERMINATE
, &status
,
3053 &path_contains_wcard
);
3054 if (!NT_STATUS_IS_OK(status
)) {
3055 reply_nterror(req
, status
);
3059 status
= filename_convert(ctx
, conn
,
3060 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3062 UCF_COND_ALLOW_WCARD_LCOMP
,
3063 &path_contains_wcard
,
3065 if (!NT_STATUS_IS_OK(status
)) {
3066 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3067 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3068 ERRSRV
, ERRbadpath
);
3071 reply_nterror(req
, status
);
3075 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3077 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
3078 path_contains_wcard
);
3079 if (!NT_STATUS_IS_OK(status
)) {
3080 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3081 /* We have re-scheduled this call. */
3084 reply_nterror(req
, status
);
3088 reply_outbuf(req
, 0, 0);
3090 TALLOC_FREE(smb_fname
);
3091 END_PROFILE(SMBunlink
);
3095 /****************************************************************************
3097 ****************************************************************************/
3099 static void fail_readraw(void)
3101 const char *errstr
= talloc_asprintf(talloc_tos(),
3102 "FAIL ! reply_readbraw: socket write fail (%s)",
3107 exit_server_cleanly(errstr
);
3110 /****************************************************************************
3111 Fake (read/write) sendfile. Returns -1 on read or write fail.
3112 ****************************************************************************/
3114 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3115 off_t startpos
, size_t nread
)
3118 size_t tosend
= nread
;
3125 bufsize
= MIN(nread
, 65536);
3127 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3131 while (tosend
> 0) {
3135 cur_read
= MIN(tosend
, bufsize
);
3136 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3142 /* If we had a short read, fill with zeros. */
3143 if (ret
< cur_read
) {
3144 memset(buf
+ ret
, '\0', cur_read
- ret
);
3147 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3148 if (ret
!= cur_read
) {
3149 int saved_errno
= errno
;
3151 * Try and give an error message saying what
3154 DEBUG(0, ("write_data failed for client %s. "
3156 smbXsrv_connection_dbg(xconn
),
3157 strerror(saved_errno
)));
3159 errno
= saved_errno
;
3163 startpos
+= cur_read
;
3167 return (ssize_t
)nread
;
3170 /****************************************************************************
3171 Deal with the case of sendfile reading less bytes from the file than
3172 requested. Fill with zeros (all we can do). Returns 0 on success
3173 ****************************************************************************/
3175 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3181 #define SHORT_SEND_BUFSIZE 1024
3182 if (nread
< headersize
) {
3183 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3184 "header for file %s (%s). Terminating\n",
3185 fsp_str_dbg(fsp
), strerror(errno
)));
3189 nread
-= headersize
;
3191 if (nread
< smb_maxcnt
) {
3192 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3194 DEBUG(0,("sendfile_short_send: malloc failed "
3195 "for file %s (%s). Terminating\n",
3196 fsp_str_dbg(fsp
), strerror(errno
)));
3200 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3201 "with zeros !\n", fsp_str_dbg(fsp
)));
3203 while (nread
< smb_maxcnt
) {
3205 * We asked for the real file size and told sendfile
3206 * to not go beyond the end of the file. But it can
3207 * happen that in between our fstat call and the
3208 * sendfile call the file was truncated. This is very
3209 * bad because we have already announced the larger
3210 * number of bytes to the client.
3212 * The best we can do now is to send 0-bytes, just as
3213 * a read from a hole in a sparse file would do.
3215 * This should happen rarely enough that I don't care
3216 * about efficiency here :-)
3221 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3222 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3223 if (ret
!= to_write
) {
3224 int saved_errno
= errno
;
3226 * Try and give an error message saying what
3229 DEBUG(0, ("write_data failed for client %s. "
3231 smbXsrv_connection_dbg(xconn
),
3232 strerror(saved_errno
)));
3233 errno
= saved_errno
;
3244 /****************************************************************************
3245 Return a readbraw error (4 bytes of zero).
3246 ****************************************************************************/
3248 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3254 smbd_lock_socket(xconn
);
3255 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3256 int saved_errno
= errno
;
3258 * Try and give an error message saying what
3261 DEBUG(0, ("write_data failed for client %s. "
3263 smbXsrv_connection_dbg(xconn
),
3264 strerror(saved_errno
)));
3265 errno
= saved_errno
;
3269 smbd_unlock_socket(xconn
);
3272 /****************************************************************************
3273 Use sendfile in readbraw.
3274 ****************************************************************************/
3276 static void send_file_readbraw(connection_struct
*conn
,
3277 struct smb_request
*req
,
3283 struct smbXsrv_connection
*xconn
= req
->xconn
;
3284 char *outbuf
= NULL
;
3288 * We can only use sendfile on a non-chained packet
3289 * but we can use on a non-oplocked file. tridge proved this
3290 * on a train in Germany :-). JRA.
3291 * reply_readbraw has already checked the length.
3294 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3295 (fsp
->wcp
== NULL
) &&
3296 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3297 ssize_t sendfile_read
= -1;
3299 DATA_BLOB header_blob
;
3301 _smb_setlen(header
,nread
);
3302 header_blob
= data_blob_const(header
, 4);
3304 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3305 &header_blob
, startpos
,
3307 if (sendfile_read
== -1) {
3308 /* Returning ENOSYS means no data at all was sent.
3309 * Do this as a normal read. */
3310 if (errno
== ENOSYS
) {
3311 goto normal_readbraw
;
3315 * Special hack for broken Linux with no working sendfile. If we
3316 * return EINTR we sent the header but not the rest of the data.
3317 * Fake this up by doing read/write calls.
3319 if (errno
== EINTR
) {
3320 /* Ensure we don't do this again. */
3321 set_use_sendfile(SNUM(conn
), False
);
3322 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3324 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3325 DEBUG(0,("send_file_readbraw: "
3326 "fake_sendfile failed for "
3330 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3335 DEBUG(0,("send_file_readbraw: sendfile failed for "
3336 "file %s (%s). Terminating\n",
3337 fsp_str_dbg(fsp
), strerror(errno
)));
3338 exit_server_cleanly("send_file_readbraw sendfile failed");
3339 } else if (sendfile_read
== 0) {
3341 * Some sendfile implementations return 0 to indicate
3342 * that there was a short read, but nothing was
3343 * actually written to the socket. In this case,
3344 * fallback to the normal read path so the header gets
3345 * the correct byte count.
3347 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3348 "bytes falling back to the normal read: "
3349 "%s\n", fsp_str_dbg(fsp
)));
3350 goto normal_readbraw
;
3353 /* Deal with possible short send. */
3354 if (sendfile_read
!= 4+nread
) {
3355 ret
= sendfile_short_send(xconn
, fsp
,
3356 sendfile_read
, 4, nread
);
3366 outbuf
= talloc_array(NULL
, char, nread
+4);
3368 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3369 (unsigned)(nread
+4)));
3370 reply_readbraw_error(xconn
);
3375 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3376 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3385 _smb_setlen(outbuf
,ret
);
3386 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3387 int saved_errno
= errno
;
3389 * Try and give an error message saying what
3392 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3393 smbXsrv_connection_dbg(xconn
),
3394 strerror(saved_errno
)));
3395 errno
= saved_errno
;
3400 TALLOC_FREE(outbuf
);
3403 /****************************************************************************
3404 Reply to a readbraw (core+ protocol).
3405 ****************************************************************************/
3407 void reply_readbraw(struct smb_request
*req
)
3409 connection_struct
*conn
= req
->conn
;
3410 struct smbXsrv_connection
*xconn
= req
->xconn
;
3411 ssize_t maxcount
,mincount
;
3415 struct lock_struct lock
;
3418 START_PROFILE(SMBreadbraw
);
3420 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3421 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3422 "raw reads/writes are disallowed.");
3426 reply_readbraw_error(xconn
);
3427 END_PROFILE(SMBreadbraw
);
3431 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3432 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3433 "'async smb echo handler = yes'\n"));
3434 reply_readbraw_error(xconn
);
3435 END_PROFILE(SMBreadbraw
);
3440 * Special check if an oplock break has been issued
3441 * and the readraw request croses on the wire, we must
3442 * return a zero length response here.
3445 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3448 * We have to do a check_fsp by hand here, as
3449 * we must always return 4 zero bytes on error,
3453 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3454 req
->vuid
!= fsp
->vuid
||
3455 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3457 * fsp could be NULL here so use the value from the packet. JRA.
3459 DEBUG(3,("reply_readbraw: fnum %d not valid "
3461 (int)SVAL(req
->vwv
+0, 0)));
3462 reply_readbraw_error(xconn
);
3463 END_PROFILE(SMBreadbraw
);
3467 /* Do a "by hand" version of CHECK_READ. */
3468 if (!(fsp
->can_read
||
3469 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3470 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3471 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3472 (int)SVAL(req
->vwv
+0, 0)));
3473 reply_readbraw_error(xconn
);
3474 END_PROFILE(SMBreadbraw
);
3478 flush_write_cache(fsp
, SAMBA_READRAW_FLUSH
);
3480 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3481 if(req
->wct
== 10) {
3483 * This is a large offset (64 bit) read.
3486 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3489 DEBUG(0,("reply_readbraw: negative 64 bit "
3490 "readraw offset (%.0f) !\n",
3491 (double)startpos
));
3492 reply_readbraw_error(xconn
);
3493 END_PROFILE(SMBreadbraw
);
3498 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3499 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3501 /* ensure we don't overrun the packet size */
3502 maxcount
= MIN(65535,maxcount
);
3504 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3505 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3508 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3509 reply_readbraw_error(xconn
);
3510 END_PROFILE(SMBreadbraw
);
3514 if (fsp_stat(fsp
) == 0) {
3515 size
= fsp
->fsp_name
->st
.st_ex_size
;
3518 if (startpos
>= size
) {
3521 nread
= MIN(maxcount
,(size
- startpos
));
3524 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3525 if (nread
< mincount
)
3529 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3530 "min=%lu nread=%lu\n",
3531 fsp_fnum_dbg(fsp
), (double)startpos
,
3532 (unsigned long)maxcount
,
3533 (unsigned long)mincount
,
3534 (unsigned long)nread
) );
3536 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3538 DEBUG(5,("reply_readbraw finished\n"));
3540 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3542 END_PROFILE(SMBreadbraw
);
3547 #define DBGC_CLASS DBGC_LOCKING
3549 /****************************************************************************
3550 Reply to a lockread (core+ protocol).
3551 ****************************************************************************/
3553 void reply_lockread(struct smb_request
*req
)
3555 connection_struct
*conn
= req
->conn
;
3563 struct byte_range_lock
*br_lck
= NULL
;
3565 struct smbXsrv_connection
*xconn
= req
->xconn
;
3567 START_PROFILE(SMBlockread
);
3570 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3571 END_PROFILE(SMBlockread
);
3575 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3577 if (!check_fsp(conn
, req
, fsp
)) {
3578 END_PROFILE(SMBlockread
);
3582 if (!CHECK_READ(fsp
,req
)) {
3583 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3584 END_PROFILE(SMBlockread
);
3588 numtoread
= SVAL(req
->vwv
+1, 0);
3589 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3592 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3593 * protocol request that predates the read/write lock concept.
3594 * Thus instead of asking for a read lock here we need to ask
3595 * for a write lock. JRA.
3596 * Note that the requested lock size is unaffected by max_send.
3599 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3601 (uint64_t)req
->smbpid
,
3602 (uint64_t)numtoread
,
3606 False
, /* Non-blocking lock. */
3609 TALLOC_FREE(br_lck
);
3611 if (NT_STATUS_V(status
)) {
3612 reply_nterror(req
, status
);
3613 END_PROFILE(SMBlockread
);
3618 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3620 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3622 if (numtoread
> maxtoread
) {
3623 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3624 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3625 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3626 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3627 numtoread
= maxtoread
;
3630 reply_outbuf(req
, 5, numtoread
+ 3);
3632 data
= smb_buf(req
->outbuf
) + 3;
3634 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3637 reply_nterror(req
, map_nt_error_from_unix(errno
));
3638 END_PROFILE(SMBlockread
);
3642 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3644 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3645 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3646 p
= smb_buf(req
->outbuf
);
3647 SCVAL(p
,0,0); /* pad byte. */
3650 DEBUG(3,("lockread %s num=%d nread=%d\n",
3651 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3653 END_PROFILE(SMBlockread
);
3658 #define DBGC_CLASS DBGC_ALL
3660 /****************************************************************************
3662 ****************************************************************************/
3664 void reply_read(struct smb_request
*req
)
3666 connection_struct
*conn
= req
->conn
;
3673 struct lock_struct lock
;
3674 struct smbXsrv_connection
*xconn
= req
->xconn
;
3676 START_PROFILE(SMBread
);
3679 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3680 END_PROFILE(SMBread
);
3684 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3686 if (!check_fsp(conn
, req
, fsp
)) {
3687 END_PROFILE(SMBread
);
3691 if (!CHECK_READ(fsp
,req
)) {
3692 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3693 END_PROFILE(SMBread
);
3697 numtoread
= SVAL(req
->vwv
+1, 0);
3698 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3701 * The requested read size cannot be greater than max_send. JRA.
3703 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3705 if (numtoread
> maxtoread
) {
3706 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3707 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3708 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3709 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3710 numtoread
= maxtoread
;
3713 reply_outbuf(req
, 5, numtoread
+3);
3715 data
= smb_buf(req
->outbuf
) + 3;
3717 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3718 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3721 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3722 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3723 END_PROFILE(SMBread
);
3728 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3731 reply_nterror(req
, map_nt_error_from_unix(errno
));
3735 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3737 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3738 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3739 SCVAL(smb_buf(req
->outbuf
),0,1);
3740 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3742 DEBUG(3, ("read %s num=%d nread=%d\n",
3743 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3746 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3748 END_PROFILE(SMBread
);
3752 /****************************************************************************
3754 ****************************************************************************/
3756 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3761 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3764 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3766 SCVAL(outbuf
,smb_vwv0
,0xFF);
3767 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3768 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3769 SSVAL(outbuf
,smb_vwv6
,
3770 (smb_wct
- 4) /* offset from smb header to wct */
3771 + 1 /* the wct field */
3772 + 12 * sizeof(uint16_t) /* vwv */
3773 + 2 /* the buflen field */
3774 + 1); /* padding byte */
3775 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3776 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3777 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3778 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3779 _smb_setlen_large(outbuf
,
3780 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3784 /****************************************************************************
3785 Reply to a read and X - possibly using sendfile.
3786 ****************************************************************************/
3788 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3789 files_struct
*fsp
, off_t startpos
,
3792 struct smbXsrv_connection
*xconn
= req
->xconn
;
3794 struct lock_struct lock
;
3795 int saved_errno
= 0;
3797 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3798 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3801 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3802 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3807 * We can only use sendfile on a non-chained packet
3808 * but we can use on a non-oplocked file. tridge proved this
3809 * on a train in Germany :-). JRA.
3812 if (!req_is_in_chain(req
) &&
3814 (fsp
->base_fsp
== NULL
) &&
3815 (fsp
->wcp
== NULL
) &&
3816 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3817 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
3820 if(fsp_stat(fsp
) == -1) {
3821 reply_nterror(req
, map_nt_error_from_unix(errno
));
3825 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3826 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3827 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3829 * We already know that we would do a short read, so don't
3830 * try the sendfile() path.
3832 goto nosendfile_read
;
3836 * Set up the packet header before send. We
3837 * assume here the sendfile will work (get the
3838 * correct amount of data).
3841 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3843 construct_reply_common_req(req
, (char *)headerbuf
);
3844 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3846 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
3847 startpos
, smb_maxcnt
);
3849 saved_errno
= errno
;
3851 /* Returning ENOSYS means no data at all was sent.
3852 Do this as a normal read. */
3853 if (errno
== ENOSYS
) {
3858 * Special hack for broken Linux with no working sendfile. If we
3859 * return EINTR we sent the header but not the rest of the data.
3860 * Fake this up by doing read/write calls.
3863 if (errno
== EINTR
) {
3864 /* Ensure we don't do this again. */
3865 set_use_sendfile(SNUM(conn
), False
);
3866 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3867 nread
= fake_sendfile(xconn
, fsp
, startpos
,
3870 saved_errno
= errno
;
3871 DEBUG(0,("send_file_readX: "
3872 "fake_sendfile failed for "
3873 "file %s (%s) for client %s. "
3876 smbXsrv_connection_dbg(xconn
),
3877 strerror(saved_errno
)));
3878 errno
= saved_errno
;
3879 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3881 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3882 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3883 /* No outbuf here means successful sendfile. */
3887 DEBUG(0,("send_file_readX: sendfile failed for file "
3888 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3890 exit_server_cleanly("send_file_readX sendfile failed");
3891 } else if (nread
== 0) {
3893 * Some sendfile implementations return 0 to indicate
3894 * that there was a short read, but nothing was
3895 * actually written to the socket. In this case,
3896 * fallback to the normal read path so the header gets
3897 * the correct byte count.
3899 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3900 "falling back to the normal read: %s\n",
3905 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3906 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3908 /* Deal with possible short send. */
3909 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3912 ret
= sendfile_short_send(xconn
, fsp
, nread
,
3913 sizeof(headerbuf
), smb_maxcnt
);
3916 r
= "send_file_readX: sendfile_short_send failed";
3917 DEBUG(0,("%s for file %s (%s).\n",
3918 r
, fsp_str_dbg(fsp
), strerror(errno
)));
3919 exit_server_cleanly(r
);
3922 /* No outbuf here means successful sendfile. */
3923 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3924 SMB_PERFCOUNT_END(&req
->pcd
);
3930 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3931 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
3934 construct_reply_common_req(req
, (char *)headerbuf
);
3935 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3937 /* Send out the header. */
3938 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
3940 if (ret
!= sizeof(headerbuf
)) {
3941 saved_errno
= errno
;
3943 * Try and give an error message saying what
3946 DEBUG(0,("send_file_readX: write_data failed for file "
3947 "%s (%s) for client %s. Terminating\n",
3949 smbXsrv_connection_dbg(xconn
),
3950 strerror(saved_errno
)));
3951 errno
= saved_errno
;
3952 exit_server_cleanly("send_file_readX sendfile failed");
3954 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
3956 saved_errno
= errno
;
3957 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3958 "%s (%s) for client %s. Terminating\n",
3960 smbXsrv_connection_dbg(xconn
),
3961 strerror(saved_errno
)));
3962 errno
= saved_errno
;
3963 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3970 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
3971 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
3972 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
3974 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
3975 startpos
, smb_maxcnt
);
3976 saved_errno
= errno
;
3978 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3981 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3985 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3987 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3988 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3992 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3993 TALLOC_FREE(req
->outbuf
);
3997 /****************************************************************************
3998 Work out how much space we have for a read return.
3999 ****************************************************************************/
4001 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4003 struct smbXsrv_connection
*xconn
= req
->xconn
;
4005 if (xconn
->protocol
< PROTOCOL_NT1
) {
4006 return xconn
->smb1
.sessions
.max_send
;
4009 if (!lp_large_readwrite()) {
4010 return xconn
->smb1
.sessions
.max_send
;
4013 if (req_is_in_chain(req
)) {
4014 return xconn
->smb1
.sessions
.max_send
;
4017 if (req
->encrypted
) {
4019 * Don't take encrypted traffic up to the
4020 * limit. There are padding considerations
4021 * that make that tricky.
4023 return xconn
->smb1
.sessions
.max_send
;
4026 if (srv_is_signing_active(xconn
)) {
4030 if (!lp_unix_extensions()) {
4035 * We can do ultra-large POSIX reads.
4040 /****************************************************************************
4041 Calculate how big a read can be. Copes with all clients. It's always
4042 safe to return a short read - Windows does this.
4043 ****************************************************************************/
4045 static size_t calc_read_size(const struct smb_request
*req
,
4049 struct smbXsrv_connection
*xconn
= req
->xconn
;
4050 size_t max_pdu
= calc_max_read_pdu(req
);
4051 size_t total_size
= 0;
4052 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4053 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4056 * Windows explicitly ignores upper size of 0xFFFF.
4057 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4058 * We must do the same as these will never fit even in
4059 * an extended size NetBIOS packet.
4061 if (upper_size
== 0xFFFF) {
4065 if (xconn
->protocol
< PROTOCOL_NT1
) {
4069 total_size
= ((upper_size
<<16) | lower_size
);
4072 * LARGE_READX test shows it's always safe to return
4073 * a short read. Windows does so.
4075 return MIN(total_size
, max_len
);
4078 /****************************************************************************
4079 Reply to a read and X.
4080 ****************************************************************************/
4082 void reply_read_and_X(struct smb_request
*req
)
4084 connection_struct
*conn
= req
->conn
;
4089 bool big_readX
= False
;
4091 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4094 START_PROFILE(SMBreadX
);
4096 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4097 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4101 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4102 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4103 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4105 /* If it's an IPC, pass off the pipe handler. */
4107 reply_pipe_read_and_X(req
);
4108 END_PROFILE(SMBreadX
);
4112 if (!check_fsp(conn
, req
, fsp
)) {
4113 END_PROFILE(SMBreadX
);
4117 if (!CHECK_READ(fsp
,req
)) {
4118 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4119 END_PROFILE(SMBreadX
);
4123 upper_size
= SVAL(req
->vwv
+7, 0);
4124 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4125 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4127 * This is a heuristic to avoid keeping large
4128 * outgoing buffers around over long-lived aio
4134 if (req
->wct
== 12) {
4136 * This is a large offset (64 bit) read.
4138 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4143 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4148 if (NT_STATUS_IS_OK(status
)) {
4149 /* Read scheduled - we're done. */
4152 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4153 /* Real error - report to client. */
4154 END_PROFILE(SMBreadX
);
4155 reply_nterror(req
, status
);
4158 /* NT_STATUS_RETRY - fall back to sync read. */
4161 smbd_lock_socket(req
->xconn
);
4162 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4163 smbd_unlock_socket(req
->xconn
);
4166 END_PROFILE(SMBreadX
);
4170 /****************************************************************************
4171 Error replies to writebraw must have smb_wct == 1. Fix this up.
4172 ****************************************************************************/
4174 void error_to_writebrawerr(struct smb_request
*req
)
4176 uint8_t *old_outbuf
= req
->outbuf
;
4178 reply_outbuf(req
, 1, 0);
4180 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4181 TALLOC_FREE(old_outbuf
);
4184 /****************************************************************************
4185 Read 4 bytes of a smb packet and return the smb length of the packet.
4186 Store the result in the buffer. This version of the function will
4187 never return a session keepalive (length of zero).
4188 Timeout is in milliseconds.
4189 ****************************************************************************/
4191 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4194 uint8_t msgtype
= NBSSkeepalive
;
4196 while (msgtype
== NBSSkeepalive
) {
4199 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4201 if (!NT_STATUS_IS_OK(status
)) {
4202 char addr
[INET6_ADDRSTRLEN
];
4203 /* Try and give an error message
4204 * saying what client failed. */
4205 DEBUG(0, ("read_fd_with_timeout failed for "
4206 "client %s read error = %s.\n",
4207 get_peer_addr(fd
,addr
,sizeof(addr
)),
4208 nt_errstr(status
)));
4212 msgtype
= CVAL(inbuf
, 0);
4215 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4216 (unsigned long)len
));
4218 return NT_STATUS_OK
;
4221 /****************************************************************************
4222 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4223 ****************************************************************************/
4225 void reply_writebraw(struct smb_request
*req
)
4227 connection_struct
*conn
= req
->conn
;
4228 struct smbXsrv_connection
*xconn
= req
->xconn
;
4231 ssize_t total_written
=0;
4232 size_t numtowrite
=0;
4235 const char *data
=NULL
;
4238 struct lock_struct lock
;
4241 START_PROFILE(SMBwritebraw
);
4244 * If we ever reply with an error, it must have the SMB command
4245 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4248 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4250 if (srv_is_signing_active(xconn
)) {
4251 END_PROFILE(SMBwritebraw
);
4252 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4253 "raw reads/writes are disallowed.");
4256 if (req
->wct
< 12) {
4257 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4258 error_to_writebrawerr(req
);
4259 END_PROFILE(SMBwritebraw
);
4263 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4264 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4265 "'async smb echo handler = yes'\n"));
4266 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4267 error_to_writebrawerr(req
);
4268 END_PROFILE(SMBwritebraw
);
4272 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4273 if (!check_fsp(conn
, req
, fsp
)) {
4274 error_to_writebrawerr(req
);
4275 END_PROFILE(SMBwritebraw
);
4279 if (!CHECK_WRITE(fsp
)) {
4280 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4281 error_to_writebrawerr(req
);
4282 END_PROFILE(SMBwritebraw
);
4286 tcount
= IVAL(req
->vwv
+1, 0);
4287 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4288 write_through
= BITSETW(req
->vwv
+7,0);
4290 /* We have to deal with slightly different formats depending
4291 on whether we are using the core+ or lanman1.0 protocol */
4293 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4294 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4295 data
= smb_buf_const(req
->inbuf
);
4297 numtowrite
= SVAL(req
->vwv
+10, 0);
4298 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4301 /* Ensure we don't write bytes past the end of this packet. */
4302 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4303 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4304 error_to_writebrawerr(req
);
4305 END_PROFILE(SMBwritebraw
);
4309 if (!fsp
->print_file
) {
4310 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4311 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4314 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4315 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4316 error_to_writebrawerr(req
);
4317 END_PROFILE(SMBwritebraw
);
4323 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4326 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4327 "wrote=%d sync=%d\n",
4328 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4329 (int)nwritten
, (int)write_through
));
4331 if (nwritten
< (ssize_t
)numtowrite
) {
4332 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4333 error_to_writebrawerr(req
);
4337 total_written
= nwritten
;
4339 /* Allocate a buffer of 64k + length. */
4340 buf
= talloc_array(NULL
, char, 65540);
4342 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4343 error_to_writebrawerr(req
);
4347 /* Return a SMBwritebraw message to the redirector to tell
4348 * it to send more bytes */
4350 memcpy(buf
, req
->inbuf
, smb_size
);
4351 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4352 SCVAL(buf
,smb_com
,SMBwritebraw
);
4353 SSVALS(buf
,smb_vwv0
,0xFFFF);
4355 if (!srv_send_smb(req
->xconn
,
4357 false, 0, /* no signing */
4358 IS_CONN_ENCRYPTED(conn
),
4360 exit_server_cleanly("reply_writebraw: srv_send_smb "
4364 /* Now read the raw data into the buffer and write it */
4365 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4367 if (!NT_STATUS_IS_OK(status
)) {
4368 exit_server_cleanly("secondary writebraw failed");
4371 /* Set up outbuf to return the correct size */
4372 reply_outbuf(req
, 1, 0);
4374 if (numtowrite
!= 0) {
4376 if (numtowrite
> 0xFFFF) {
4377 DEBUG(0,("reply_writebraw: Oversize secondary write "
4378 "raw requested (%u). Terminating\n",
4379 (unsigned int)numtowrite
));
4380 exit_server_cleanly("secondary writebraw failed");
4383 if (tcount
> nwritten
+numtowrite
) {
4384 DEBUG(3,("reply_writebraw: Client overestimated the "
4386 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4389 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4392 if (!NT_STATUS_IS_OK(status
)) {
4393 /* Try and give an error message
4394 * saying what client failed. */
4395 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4396 "raw read failed (%s) for client %s. "
4397 "Terminating\n", nt_errstr(status
),
4398 smbXsrv_connection_dbg(xconn
)));
4399 exit_server_cleanly("secondary writebraw failed");
4402 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4403 if (nwritten
== -1) {
4405 reply_nterror(req
, map_nt_error_from_unix(errno
));
4406 error_to_writebrawerr(req
);
4410 if (nwritten
< (ssize_t
)numtowrite
) {
4411 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4412 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4416 total_written
+= nwritten
;
4421 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4423 status
= sync_file(conn
, fsp
, write_through
);
4424 if (!NT_STATUS_IS_OK(status
)) {
4425 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4426 fsp_str_dbg(fsp
), nt_errstr(status
)));
4427 reply_nterror(req
, status
);
4428 error_to_writebrawerr(req
);
4432 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4434 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4435 (int)total_written
));
4437 if (!fsp
->print_file
) {
4438 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4441 /* We won't return a status if write through is not selected - this
4442 * follows what WfWg does */
4443 END_PROFILE(SMBwritebraw
);
4445 if (!write_through
&& total_written
==tcount
) {
4447 #if RABBIT_PELLET_FIX
4449 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4450 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4453 if (!send_keepalive(xconn
->transport
.sock
)) {
4454 exit_server_cleanly("reply_writebraw: send of "
4455 "keepalive failed");
4458 TALLOC_FREE(req
->outbuf
);
4463 if (!fsp
->print_file
) {
4464 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4467 END_PROFILE(SMBwritebraw
);
4472 #define DBGC_CLASS DBGC_LOCKING
4474 /****************************************************************************
4475 Reply to a writeunlock (core+).
4476 ****************************************************************************/
4478 void reply_writeunlock(struct smb_request
*req
)
4480 connection_struct
*conn
= req
->conn
;
4481 ssize_t nwritten
= -1;
4485 NTSTATUS status
= NT_STATUS_OK
;
4487 struct lock_struct lock
;
4488 int saved_errno
= 0;
4490 START_PROFILE(SMBwriteunlock
);
4493 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4494 END_PROFILE(SMBwriteunlock
);
4498 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4500 if (!check_fsp(conn
, req
, fsp
)) {
4501 END_PROFILE(SMBwriteunlock
);
4505 if (!CHECK_WRITE(fsp
)) {
4506 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4507 END_PROFILE(SMBwriteunlock
);
4511 numtowrite
= SVAL(req
->vwv
+1, 0);
4512 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4513 data
= (const char *)req
->buf
+ 3;
4515 if (!fsp
->print_file
&& numtowrite
> 0) {
4516 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4517 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4520 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4521 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4522 END_PROFILE(SMBwriteunlock
);
4527 /* The special X/Open SMB protocol handling of
4528 zero length writes is *NOT* done for
4530 if(numtowrite
== 0) {
4533 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4534 saved_errno
= errno
;
4537 status
= sync_file(conn
, fsp
, False
/* write through */);
4538 if (!NT_STATUS_IS_OK(status
)) {
4539 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4540 fsp_str_dbg(fsp
), nt_errstr(status
)));
4541 reply_nterror(req
, status
);
4546 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4550 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4551 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4555 if (numtowrite
&& !fsp
->print_file
) {
4556 status
= do_unlock(req
->sconn
->msg_ctx
,
4558 (uint64_t)req
->smbpid
,
4559 (uint64_t)numtowrite
,
4563 if (NT_STATUS_V(status
)) {
4564 reply_nterror(req
, status
);
4569 reply_outbuf(req
, 1, 0);
4571 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4573 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4574 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4577 if (numtowrite
&& !fsp
->print_file
) {
4578 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4581 END_PROFILE(SMBwriteunlock
);
4586 #define DBGC_CLASS DBGC_ALL
4588 /****************************************************************************
4590 ****************************************************************************/
4592 void reply_write(struct smb_request
*req
)
4594 connection_struct
*conn
= req
->conn
;
4596 ssize_t nwritten
= -1;
4600 struct lock_struct lock
;
4602 int saved_errno
= 0;
4604 START_PROFILE(SMBwrite
);
4607 END_PROFILE(SMBwrite
);
4608 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4612 /* If it's an IPC, pass off the pipe handler. */
4614 reply_pipe_write(req
);
4615 END_PROFILE(SMBwrite
);
4619 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4621 if (!check_fsp(conn
, req
, fsp
)) {
4622 END_PROFILE(SMBwrite
);
4626 if (!CHECK_WRITE(fsp
)) {
4627 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4628 END_PROFILE(SMBwrite
);
4632 numtowrite
= SVAL(req
->vwv
+1, 0);
4633 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4634 data
= (const char *)req
->buf
+ 3;
4636 if (!fsp
->print_file
) {
4637 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4638 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4641 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4642 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4643 END_PROFILE(SMBwrite
);
4649 * X/Open SMB protocol says that if smb_vwv1 is
4650 * zero then the file size should be extended or
4651 * truncated to the size given in smb_vwv[2-3].
4654 if(numtowrite
== 0) {
4656 * This is actually an allocate call, and set EOF. JRA.
4658 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4660 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4663 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4665 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4668 trigger_write_time_update_immediate(fsp
);
4670 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4673 status
= sync_file(conn
, fsp
, False
);
4674 if (!NT_STATUS_IS_OK(status
)) {
4675 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4676 fsp_str_dbg(fsp
), nt_errstr(status
)));
4677 reply_nterror(req
, status
);
4682 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4686 if((nwritten
== 0) && (numtowrite
!= 0)) {
4687 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4691 reply_outbuf(req
, 1, 0);
4693 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4695 if (nwritten
< (ssize_t
)numtowrite
) {
4696 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4697 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4700 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4703 if (!fsp
->print_file
) {
4704 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4707 END_PROFILE(SMBwrite
);
4711 /****************************************************************************
4712 Ensure a buffer is a valid writeX for recvfile purposes.
4713 ****************************************************************************/
4715 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4716 (2*14) + /* word count (including bcc) */ \
4719 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4720 const uint8_t *inbuf
)
4723 unsigned int doff
= 0;
4724 size_t len
= smb_len_large(inbuf
);
4726 struct smbXsrv_open
*op
= NULL
;
4727 struct files_struct
*fsp
= NULL
;
4730 if (is_encrypted_packet(inbuf
)) {
4731 /* Can't do this on encrypted
4736 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4740 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4741 CVAL(inbuf
,smb_wct
) != 14) {
4742 DEBUG(10,("is_valid_writeX_buffer: chained or "
4743 "invalid word length.\n"));
4747 fnum
= SVAL(inbuf
, smb_vwv2
);
4748 status
= smb1srv_open_lookup(xconn
,
4752 if (!NT_STATUS_IS_OK(status
)) {
4753 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4758 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4761 if (fsp
->conn
== NULL
) {
4762 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4766 if (IS_IPC(fsp
->conn
)) {
4767 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4770 if (IS_PRINT(fsp
->conn
)) {
4771 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4774 doff
= SVAL(inbuf
,smb_vwv11
);
4776 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4778 if (len
> doff
&& len
- doff
> 0xFFFF) {
4779 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4782 if (numtowrite
== 0) {
4783 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4787 /* Ensure the sizes match up. */
4788 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4789 /* no pad byte...old smbclient :-( */
4790 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4792 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4796 if (len
- doff
!= numtowrite
) {
4797 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4798 "len = %u, doff = %u, numtowrite = %u\n",
4801 (unsigned int)numtowrite
));
4805 DEBUG(10,("is_valid_writeX_buffer: true "
4806 "len = %u, doff = %u, numtowrite = %u\n",
4809 (unsigned int)numtowrite
));
4814 /****************************************************************************
4815 Reply to a write and X.
4816 ****************************************************************************/
4818 void reply_write_and_X(struct smb_request
*req
)
4820 connection_struct
*conn
= req
->conn
;
4821 struct smbXsrv_connection
*xconn
= req
->xconn
;
4823 struct lock_struct lock
;
4828 unsigned int smb_doff
;
4829 unsigned int smblen
;
4832 int saved_errno
= 0;
4834 START_PROFILE(SMBwriteX
);
4836 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4837 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4841 numtowrite
= SVAL(req
->vwv
+10, 0);
4842 smb_doff
= SVAL(req
->vwv
+11, 0);
4843 smblen
= smb_len(req
->inbuf
);
4845 if (req
->unread_bytes
> 0xFFFF ||
4846 (smblen
> smb_doff
&&
4847 smblen
- smb_doff
> 0xFFFF)) {
4848 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4851 if (req
->unread_bytes
) {
4852 /* Can't do a recvfile write on IPC$ */
4854 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4857 if (numtowrite
!= req
->unread_bytes
) {
4858 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4862 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4863 smb_doff
+ numtowrite
> smblen
) {
4864 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4869 /* If it's an IPC, pass off the pipe handler. */
4871 if (req
->unread_bytes
) {
4872 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4875 reply_pipe_write_and_X(req
);
4879 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4880 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4881 write_through
= BITSETW(req
->vwv
+7,0);
4883 if (!check_fsp(conn
, req
, fsp
)) {
4887 if (!CHECK_WRITE(fsp
)) {
4888 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4892 data
= smb_base(req
->inbuf
) + smb_doff
;
4894 if(req
->wct
== 14) {
4896 * This is a large offset (64 bit) write.
4898 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
4902 /* X/Open SMB protocol says that, unlike SMBwrite
4903 if the length is zero then NO truncation is
4904 done, just a write of zero. To truncate a file,
4907 if(numtowrite
== 0) {
4910 if (req
->unread_bytes
== 0) {
4911 status
= schedule_aio_write_and_X(conn
,
4918 if (NT_STATUS_IS_OK(status
)) {
4919 /* write scheduled - we're done. */
4922 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4923 /* Real error - report to client. */
4924 reply_nterror(req
, status
);
4927 /* NT_STATUS_RETRY - fall through to sync write. */
4930 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4931 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4934 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4935 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4939 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4940 saved_errno
= errno
;
4942 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4946 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4950 if((nwritten
== 0) && (numtowrite
!= 0)) {
4951 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4955 reply_outbuf(req
, 6, 0);
4956 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4957 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4958 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4959 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4961 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4962 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4964 status
= sync_file(conn
, fsp
, write_through
);
4965 if (!NT_STATUS_IS_OK(status
)) {
4966 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4967 fsp_str_dbg(fsp
), nt_errstr(status
)));
4968 reply_nterror(req
, status
);
4972 END_PROFILE(SMBwriteX
);
4976 if (req
->unread_bytes
) {
4977 /* writeX failed. drain socket. */
4978 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
4979 req
->unread_bytes
) {
4980 smb_panic("failed to drain pending bytes");
4982 req
->unread_bytes
= 0;
4985 END_PROFILE(SMBwriteX
);
4989 /****************************************************************************
4991 ****************************************************************************/
4993 void reply_lseek(struct smb_request
*req
)
4995 connection_struct
*conn
= req
->conn
;
5001 START_PROFILE(SMBlseek
);
5004 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5005 END_PROFILE(SMBlseek
);
5009 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5011 if (!check_fsp(conn
, req
, fsp
)) {
5015 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
5017 mode
= SVAL(req
->vwv
+1, 0) & 3;
5018 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5019 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5028 res
= fsp
->fh
->pos
+ startpos
;
5039 if (umode
== SEEK_END
) {
5040 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5041 if(errno
== EINVAL
) {
5042 off_t current_pos
= startpos
;
5044 if(fsp_stat(fsp
) == -1) {
5046 map_nt_error_from_unix(errno
));
5047 END_PROFILE(SMBlseek
);
5051 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5053 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5058 reply_nterror(req
, map_nt_error_from_unix(errno
));
5059 END_PROFILE(SMBlseek
);
5066 reply_outbuf(req
, 2, 0);
5067 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5069 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5070 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5072 END_PROFILE(SMBlseek
);
5076 /****************************************************************************
5078 ****************************************************************************/
5080 void reply_flush(struct smb_request
*req
)
5082 connection_struct
*conn
= req
->conn
;
5086 START_PROFILE(SMBflush
);
5089 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5093 fnum
= SVAL(req
->vwv
+0, 0);
5094 fsp
= file_fsp(req
, fnum
);
5096 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5101 file_sync_all(conn
);
5103 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5104 if (!NT_STATUS_IS_OK(status
)) {
5105 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5106 fsp_str_dbg(fsp
), nt_errstr(status
)));
5107 reply_nterror(req
, status
);
5108 END_PROFILE(SMBflush
);
5113 reply_outbuf(req
, 0, 0);
5115 DEBUG(3,("flush\n"));
5116 END_PROFILE(SMBflush
);
5120 /****************************************************************************
5122 conn POINTER CAN BE NULL HERE !
5123 ****************************************************************************/
5125 void reply_exit(struct smb_request
*req
)
5127 START_PROFILE(SMBexit
);
5129 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5131 reply_outbuf(req
, 0, 0);
5133 DEBUG(3,("exit\n"));
5135 END_PROFILE(SMBexit
);
5139 struct reply_close_state
{
5141 struct smb_request
*smbreq
;
5144 static void do_smb1_close(struct tevent_req
*req
);
5146 void reply_close(struct smb_request
*req
)
5148 connection_struct
*conn
= req
->conn
;
5149 NTSTATUS status
= NT_STATUS_OK
;
5150 files_struct
*fsp
= NULL
;
5151 START_PROFILE(SMBclose
);
5154 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5155 END_PROFILE(SMBclose
);
5159 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5162 * We can only use check_fsp if we know it's not a directory.
5165 if (!check_fsp_open(conn
, req
, fsp
)) {
5166 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5167 END_PROFILE(SMBclose
);
5171 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5172 fsp
->is_directory
? "directory" : "file",
5173 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5174 conn
->num_files_open
));
5176 if (!fsp
->is_directory
) {
5180 * Take care of any time sent in the close.
5183 t
= srv_make_unix_date3(req
->vwv
+1);
5184 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5187 if (fsp
->num_aio_requests
!= 0) {
5189 struct reply_close_state
*state
;
5191 DEBUG(10, ("closing with aio %u requests pending\n",
5192 fsp
->num_aio_requests
));
5195 * We depend on the aio_extra destructor to take care of this
5196 * close request once fsp->num_aio_request drops to 0.
5199 fsp
->deferred_close
= tevent_wait_send(
5200 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5201 if (fsp
->deferred_close
== NULL
) {
5202 status
= NT_STATUS_NO_MEMORY
;
5206 state
= talloc(fsp
, struct reply_close_state
);
5207 if (state
== NULL
) {
5208 TALLOC_FREE(fsp
->deferred_close
);
5209 status
= NT_STATUS_NO_MEMORY
;
5213 state
->smbreq
= talloc_move(fsp
, &req
);
5214 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5216 END_PROFILE(SMBclose
);
5221 * close_file() returns the unix errno if an error was detected on
5222 * close - normally this is due to a disk full error. If not then it
5223 * was probably an I/O error.
5226 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5228 if (!NT_STATUS_IS_OK(status
)) {
5229 reply_nterror(req
, status
);
5230 END_PROFILE(SMBclose
);
5234 reply_outbuf(req
, 0, 0);
5235 END_PROFILE(SMBclose
);
5239 static void do_smb1_close(struct tevent_req
*req
)
5241 struct reply_close_state
*state
= tevent_req_callback_data(
5242 req
, struct reply_close_state
);
5243 struct smb_request
*smbreq
;
5247 ret
= tevent_wait_recv(req
);
5250 DEBUG(10, ("tevent_wait_recv returned %s\n",
5253 * Continue anyway, this should never happen
5258 * fsp->smb2_close_request right now is a talloc grandchild of
5259 * fsp. When we close_file(fsp), it would go with it. No chance to
5262 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5264 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5265 if (NT_STATUS_IS_OK(status
)) {
5266 reply_outbuf(smbreq
, 0, 0);
5268 reply_nterror(smbreq
, status
);
5270 if (!srv_send_smb(smbreq
->xconn
,
5271 (char *)smbreq
->outbuf
,
5274 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5276 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5279 TALLOC_FREE(smbreq
);
5282 /****************************************************************************
5283 Reply to a writeclose (Core+ protocol).
5284 ****************************************************************************/
5286 void reply_writeclose(struct smb_request
*req
)
5288 connection_struct
*conn
= req
->conn
;
5290 ssize_t nwritten
= -1;
5291 NTSTATUS close_status
= NT_STATUS_OK
;
5294 struct timespec mtime
;
5296 struct lock_struct lock
;
5298 START_PROFILE(SMBwriteclose
);
5301 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5302 END_PROFILE(SMBwriteclose
);
5306 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5308 if (!check_fsp(conn
, req
, fsp
)) {
5309 END_PROFILE(SMBwriteclose
);
5312 if (!CHECK_WRITE(fsp
)) {
5313 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5314 END_PROFILE(SMBwriteclose
);
5318 numtowrite
= SVAL(req
->vwv
+1, 0);
5319 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5320 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5321 data
= (const char *)req
->buf
+ 1;
5323 if (fsp
->print_file
== NULL
) {
5324 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5325 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5328 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5329 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5330 END_PROFILE(SMBwriteclose
);
5335 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5337 if (fsp
->print_file
== NULL
) {
5338 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5341 set_close_write_time(fsp
, mtime
);
5344 * More insanity. W2K only closes the file if writelen > 0.
5348 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5349 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5350 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5353 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5354 "file %s\n", fsp_str_dbg(fsp
)));
5355 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5359 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5360 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5364 if(!NT_STATUS_IS_OK(close_status
)) {
5365 reply_nterror(req
, close_status
);
5369 reply_outbuf(req
, 1, 0);
5371 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5375 END_PROFILE(SMBwriteclose
);
5380 #define DBGC_CLASS DBGC_LOCKING
5382 /****************************************************************************
5384 ****************************************************************************/
5386 void reply_lock(struct smb_request
*req
)
5388 connection_struct
*conn
= req
->conn
;
5389 uint64_t count
,offset
;
5392 struct byte_range_lock
*br_lck
= NULL
;
5394 START_PROFILE(SMBlock
);
5397 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5398 END_PROFILE(SMBlock
);
5402 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5404 if (!check_fsp(conn
, req
, fsp
)) {
5405 END_PROFILE(SMBlock
);
5409 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5410 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5412 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5413 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5415 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5417 (uint64_t)req
->smbpid
,
5422 False
, /* Non-blocking lock. */
5426 TALLOC_FREE(br_lck
);
5428 if (NT_STATUS_V(status
)) {
5429 reply_nterror(req
, status
);
5430 END_PROFILE(SMBlock
);
5434 reply_outbuf(req
, 0, 0);
5436 END_PROFILE(SMBlock
);
5440 /****************************************************************************
5442 ****************************************************************************/
5444 void reply_unlock(struct smb_request
*req
)
5446 connection_struct
*conn
= req
->conn
;
5447 uint64_t count
,offset
;
5451 START_PROFILE(SMBunlock
);
5454 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5455 END_PROFILE(SMBunlock
);
5459 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5461 if (!check_fsp(conn
, req
, fsp
)) {
5462 END_PROFILE(SMBunlock
);
5466 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5467 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5469 status
= do_unlock(req
->sconn
->msg_ctx
,
5471 (uint64_t)req
->smbpid
,
5476 if (NT_STATUS_V(status
)) {
5477 reply_nterror(req
, status
);
5478 END_PROFILE(SMBunlock
);
5482 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5483 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5485 reply_outbuf(req
, 0, 0);
5487 END_PROFILE(SMBunlock
);
5492 #define DBGC_CLASS DBGC_ALL
5494 /****************************************************************************
5496 conn POINTER CAN BE NULL HERE !
5497 ****************************************************************************/
5499 void reply_tdis(struct smb_request
*req
)
5502 connection_struct
*conn
= req
->conn
;
5503 struct smbXsrv_tcon
*tcon
;
5505 START_PROFILE(SMBtdis
);
5508 DEBUG(4,("Invalid connection in tdis\n"));
5509 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5510 END_PROFILE(SMBtdis
);
5518 * TODO: cancel all outstanding requests on the tcon
5520 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5521 if (!NT_STATUS_IS_OK(status
)) {
5522 DEBUG(0, ("reply_tdis: "
5523 "smbXsrv_tcon_disconnect() failed: %s\n",
5524 nt_errstr(status
)));
5526 * If we hit this case, there is something completely
5527 * wrong, so we better disconnect the transport connection.
5529 END_PROFILE(SMBtdis
);
5530 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5536 reply_outbuf(req
, 0, 0);
5537 END_PROFILE(SMBtdis
);
5541 /****************************************************************************
5543 conn POINTER CAN BE NULL HERE !
5544 ****************************************************************************/
5546 void reply_echo(struct smb_request
*req
)
5548 connection_struct
*conn
= req
->conn
;
5549 struct smb_perfcount_data local_pcd
;
5550 struct smb_perfcount_data
*cur_pcd
;
5554 START_PROFILE(SMBecho
);
5556 smb_init_perfcount_data(&local_pcd
);
5559 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5560 END_PROFILE(SMBecho
);
5564 smb_reverb
= SVAL(req
->vwv
+0, 0);
5566 reply_outbuf(req
, 1, req
->buflen
);
5568 /* copy any incoming data back out */
5569 if (req
->buflen
> 0) {
5570 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5573 if (smb_reverb
> 100) {
5574 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5578 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5580 /* this makes sure we catch the request pcd */
5581 if (seq_num
== smb_reverb
) {
5582 cur_pcd
= &req
->pcd
;
5584 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5585 cur_pcd
= &local_pcd
;
5588 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5590 show_msg((char *)req
->outbuf
);
5591 if (!srv_send_smb(req
->xconn
,
5592 (char *)req
->outbuf
,
5593 true, req
->seqnum
+1,
5594 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5596 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5599 DEBUG(3,("echo %d times\n", smb_reverb
));
5601 TALLOC_FREE(req
->outbuf
);
5603 END_PROFILE(SMBecho
);
5607 /****************************************************************************
5608 Reply to a printopen.
5609 ****************************************************************************/
5611 void reply_printopen(struct smb_request
*req
)
5613 connection_struct
*conn
= req
->conn
;
5617 START_PROFILE(SMBsplopen
);
5620 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5621 END_PROFILE(SMBsplopen
);
5625 if (!CAN_PRINT(conn
)) {
5626 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5627 END_PROFILE(SMBsplopen
);
5631 status
= file_new(req
, conn
, &fsp
);
5632 if(!NT_STATUS_IS_OK(status
)) {
5633 reply_nterror(req
, status
);
5634 END_PROFILE(SMBsplopen
);
5638 /* Open for exclusive use, write only. */
5639 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5641 if (!NT_STATUS_IS_OK(status
)) {
5642 file_free(req
, fsp
);
5643 reply_nterror(req
, status
);
5644 END_PROFILE(SMBsplopen
);
5648 reply_outbuf(req
, 1, 0);
5649 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5651 DEBUG(3,("openprint fd=%d %s\n",
5652 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5654 END_PROFILE(SMBsplopen
);
5658 /****************************************************************************
5659 Reply to a printclose.
5660 ****************************************************************************/
5662 void reply_printclose(struct smb_request
*req
)
5664 connection_struct
*conn
= req
->conn
;
5668 START_PROFILE(SMBsplclose
);
5671 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5672 END_PROFILE(SMBsplclose
);
5676 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5678 if (!check_fsp(conn
, req
, fsp
)) {
5679 END_PROFILE(SMBsplclose
);
5683 if (!CAN_PRINT(conn
)) {
5684 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5685 END_PROFILE(SMBsplclose
);
5689 DEBUG(3,("printclose fd=%d %s\n",
5690 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5692 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5694 if(!NT_STATUS_IS_OK(status
)) {
5695 reply_nterror(req
, status
);
5696 END_PROFILE(SMBsplclose
);
5700 reply_outbuf(req
, 0, 0);
5702 END_PROFILE(SMBsplclose
);
5706 /****************************************************************************
5707 Reply to a printqueue.
5708 ****************************************************************************/
5710 void reply_printqueue(struct smb_request
*req
)
5712 connection_struct
*conn
= req
->conn
;
5716 START_PROFILE(SMBsplretq
);
5719 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5720 END_PROFILE(SMBsplretq
);
5724 max_count
= SVAL(req
->vwv
+0, 0);
5725 start_index
= SVAL(req
->vwv
+1, 0);
5727 /* we used to allow the client to get the cnum wrong, but that
5728 is really quite gross and only worked when there was only
5729 one printer - I think we should now only accept it if they
5730 get it right (tridge) */
5731 if (!CAN_PRINT(conn
)) {
5732 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5733 END_PROFILE(SMBsplretq
);
5737 reply_outbuf(req
, 2, 3);
5738 SSVAL(req
->outbuf
,smb_vwv0
,0);
5739 SSVAL(req
->outbuf
,smb_vwv1
,0);
5740 SCVAL(smb_buf(req
->outbuf
),0,1);
5741 SSVAL(smb_buf(req
->outbuf
),1,0);
5743 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5744 start_index
, max_count
));
5747 TALLOC_CTX
*mem_ctx
= talloc_tos();
5750 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5751 struct rpc_pipe_client
*cli
= NULL
;
5752 struct dcerpc_binding_handle
*b
= NULL
;
5753 struct policy_handle handle
;
5754 struct spoolss_DevmodeContainer devmode_ctr
;
5755 union spoolss_JobInfo
*info
;
5757 uint32_t num_to_get
;
5761 ZERO_STRUCT(handle
);
5763 status
= rpc_pipe_open_interface(conn
,
5766 conn
->sconn
->remote_address
,
5767 conn
->sconn
->msg_ctx
,
5769 if (!NT_STATUS_IS_OK(status
)) {
5770 DEBUG(0, ("reply_printqueue: "
5771 "could not connect to spoolss: %s\n",
5772 nt_errstr(status
)));
5773 reply_nterror(req
, status
);
5776 b
= cli
->binding_handle
;
5778 ZERO_STRUCT(devmode_ctr
);
5780 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5783 SEC_FLAG_MAXIMUM_ALLOWED
,
5786 if (!NT_STATUS_IS_OK(status
)) {
5787 reply_nterror(req
, status
);
5790 if (!W_ERROR_IS_OK(werr
)) {
5791 reply_nterror(req
, werror_to_ntstatus(werr
));
5795 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5803 if (!W_ERROR_IS_OK(werr
)) {
5804 reply_nterror(req
, werror_to_ntstatus(werr
));
5808 if (max_count
> 0) {
5809 first
= start_index
;
5811 first
= start_index
+ max_count
+ 1;
5814 if (first
>= count
) {
5817 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5820 for (i
= first
; i
< num_to_get
; i
++) {
5823 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5826 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5827 info
[i
].info2
.job_id
);
5829 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5835 srv_put_dos_date2(p
, 0, qtime
);
5836 SCVAL(p
, 4, qstatus
);
5837 SSVAL(p
, 5, qrapjobid
);
5838 SIVAL(p
, 7, info
[i
].info2
.size
);
5840 status
= srvstr_push(blob
, req
->flags2
, p
+12,
5841 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
5842 if (!NT_STATUS_IS_OK(status
)) {
5843 reply_nterror(req
, status
);
5846 if (message_push_blob(
5849 blob
, sizeof(blob
))) == -1) {
5850 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5856 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5857 SSVAL(req
->outbuf
,smb_vwv1
,
5858 (max_count
>0?first
+count
:first
-1));
5859 SCVAL(smb_buf(req
->outbuf
),0,1);
5860 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5864 DEBUG(3, ("%u entries returned in queue\n",
5868 if (b
&& is_valid_policy_hnd(&handle
)) {
5869 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5874 END_PROFILE(SMBsplretq
);
5878 /****************************************************************************
5879 Reply to a printwrite.
5880 ****************************************************************************/
5882 void reply_printwrite(struct smb_request
*req
)
5884 connection_struct
*conn
= req
->conn
;
5889 START_PROFILE(SMBsplwr
);
5892 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5893 END_PROFILE(SMBsplwr
);
5897 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5899 if (!check_fsp(conn
, req
, fsp
)) {
5900 END_PROFILE(SMBsplwr
);
5904 if (!fsp
->print_file
) {
5905 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5906 END_PROFILE(SMBsplwr
);
5910 if (!CHECK_WRITE(fsp
)) {
5911 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5912 END_PROFILE(SMBsplwr
);
5916 numtowrite
= SVAL(req
->buf
, 1);
5918 if (req
->buflen
< numtowrite
+ 3) {
5919 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5920 END_PROFILE(SMBsplwr
);
5924 data
= (const char *)req
->buf
+ 3;
5926 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
5927 reply_nterror(req
, map_nt_error_from_unix(errno
));
5928 END_PROFILE(SMBsplwr
);
5932 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
5934 END_PROFILE(SMBsplwr
);
5938 /****************************************************************************
5940 ****************************************************************************/
5942 void reply_mkdir(struct smb_request
*req
)
5944 connection_struct
*conn
= req
->conn
;
5945 struct smb_filename
*smb_dname
= NULL
;
5946 char *directory
= NULL
;
5948 TALLOC_CTX
*ctx
= talloc_tos();
5950 START_PROFILE(SMBmkdir
);
5952 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5953 STR_TERMINATE
, &status
);
5954 if (!NT_STATUS_IS_OK(status
)) {
5955 reply_nterror(req
, status
);
5959 status
= filename_convert(ctx
, conn
,
5960 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5962 UCF_PREP_CREATEFILE
,
5965 if (!NT_STATUS_IS_OK(status
)) {
5966 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5967 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5968 ERRSRV
, ERRbadpath
);
5971 reply_nterror(req
, status
);
5975 status
= create_directory(conn
, req
, smb_dname
);
5977 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5979 if (!NT_STATUS_IS_OK(status
)) {
5981 if (!use_nt_status()
5982 && NT_STATUS_EQUAL(status
,
5983 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5985 * Yes, in the DOS error code case we get a
5986 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5987 * samba4 torture test.
5989 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5992 reply_nterror(req
, status
);
5996 reply_outbuf(req
, 0, 0);
5998 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6000 TALLOC_FREE(smb_dname
);
6001 END_PROFILE(SMBmkdir
);
6005 /****************************************************************************
6007 ****************************************************************************/
6009 void reply_rmdir(struct smb_request
*req
)
6011 connection_struct
*conn
= req
->conn
;
6012 struct smb_filename
*smb_dname
= NULL
;
6013 char *directory
= NULL
;
6015 TALLOC_CTX
*ctx
= talloc_tos();
6016 files_struct
*fsp
= NULL
;
6018 struct smbd_server_connection
*sconn
= req
->sconn
;
6020 START_PROFILE(SMBrmdir
);
6022 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6023 STR_TERMINATE
, &status
);
6024 if (!NT_STATUS_IS_OK(status
)) {
6025 reply_nterror(req
, status
);
6029 status
= filename_convert(ctx
, conn
,
6030 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6035 if (!NT_STATUS_IS_OK(status
)) {
6036 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6037 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6038 ERRSRV
, ERRbadpath
);
6041 reply_nterror(req
, status
);
6045 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6046 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6050 status
= SMB_VFS_CREATE_FILE(
6053 0, /* root_dir_fid */
6054 smb_dname
, /* fname */
6055 DELETE_ACCESS
, /* access_mask */
6056 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6058 FILE_OPEN
, /* create_disposition*/
6059 FILE_DIRECTORY_FILE
, /* create_options */
6060 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6061 0, /* oplock_request */
6063 0, /* allocation_size */
6064 0, /* private_flags */
6069 NULL
, NULL
); /* create context */
6071 if (!NT_STATUS_IS_OK(status
)) {
6072 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6073 /* We have re-scheduled this call. */
6076 reply_nterror(req
, status
);
6080 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6081 if (!NT_STATUS_IS_OK(status
)) {
6082 close_file(req
, fsp
, ERROR_CLOSE
);
6083 reply_nterror(req
, status
);
6087 if (!set_delete_on_close(fsp
, true,
6088 conn
->session_info
->security_token
,
6089 conn
->session_info
->unix_token
)) {
6090 close_file(req
, fsp
, ERROR_CLOSE
);
6091 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6095 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6096 if (!NT_STATUS_IS_OK(status
)) {
6097 reply_nterror(req
, status
);
6099 reply_outbuf(req
, 0, 0);
6102 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
6104 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6106 TALLOC_FREE(smb_dname
);
6107 END_PROFILE(SMBrmdir
);
6111 /*******************************************************************
6112 Resolve wildcards in a filename rename.
6113 ********************************************************************/
6115 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6120 char *name2_copy
= NULL
;
6125 char *p
,*p2
, *pname1
, *pname2
;
6127 name2_copy
= talloc_strdup(ctx
, name2
);
6132 pname1
= strrchr_m(name1
,'/');
6133 pname2
= strrchr_m(name2_copy
,'/');
6135 if (!pname1
|| !pname2
) {
6139 /* Truncate the copy of name2 at the last '/' */
6142 /* Now go past the '/' */
6146 root1
= talloc_strdup(ctx
, pname1
);
6147 root2
= talloc_strdup(ctx
, pname2
);
6149 if (!root1
|| !root2
) {
6153 p
= strrchr_m(root1
,'.');
6156 ext1
= talloc_strdup(ctx
, p
+1);
6158 ext1
= talloc_strdup(ctx
, "");
6160 p
= strrchr_m(root2
,'.');
6163 ext2
= talloc_strdup(ctx
, p
+1);
6165 ext2
= talloc_strdup(ctx
, "");
6168 if (!ext1
|| !ext2
) {
6176 /* Hmmm. Should this be mb-aware ? */
6179 } else if (*p2
== '*') {
6181 root2
= talloc_asprintf(ctx
, "%s%s",
6200 /* Hmmm. Should this be mb-aware ? */
6203 } else if (*p2
== '*') {
6205 ext2
= talloc_asprintf(ctx
, "%s%s",
6221 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6226 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6238 /****************************************************************************
6239 Ensure open files have their names updated. Updated to notify other smbd's
6241 ****************************************************************************/
6243 static void rename_open_files(connection_struct
*conn
,
6244 struct share_mode_lock
*lck
,
6246 uint32_t orig_name_hash
,
6247 const struct smb_filename
*smb_fname_dst
)
6250 bool did_rename
= False
;
6252 uint32_t new_name_hash
= 0;
6254 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6255 fsp
= file_find_di_next(fsp
)) {
6256 /* fsp_name is a relative path under the fsp. To change this for other
6257 sharepaths we need to manipulate relative paths. */
6258 /* TODO - create the absolute path and manipulate the newname
6259 relative to the sharepath. */
6260 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6263 if (fsp
->name_hash
!= orig_name_hash
) {
6266 DEBUG(10, ("rename_open_files: renaming file %s "
6267 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6268 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6269 smb_fname_str_dbg(smb_fname_dst
)));
6271 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6272 if (NT_STATUS_IS_OK(status
)) {
6274 new_name_hash
= fsp
->name_hash
;
6279 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6280 "for %s\n", file_id_string_tos(&id
),
6281 smb_fname_str_dbg(smb_fname_dst
)));
6284 /* Send messages to all smbd's (not ourself) that the name has changed. */
6285 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6286 orig_name_hash
, new_name_hash
,
6291 /****************************************************************************
6292 We need to check if the source path is a parent directory of the destination
6293 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6294 refuse the rename with a sharing violation. Under UNIX the above call can
6295 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6296 probably need to check that the client is a Windows one before disallowing
6297 this as a UNIX client (one with UNIX extensions) can know the source is a
6298 symlink and make this decision intelligently. Found by an excellent bug
6299 report from <AndyLiebman@aol.com>.
6300 ****************************************************************************/
6302 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6303 const struct smb_filename
*smb_fname_dst
)
6305 const char *psrc
= smb_fname_src
->base_name
;
6306 const char *pdst
= smb_fname_dst
->base_name
;
6309 if (psrc
[0] == '.' && psrc
[1] == '/') {
6312 if (pdst
[0] == '.' && pdst
[1] == '/') {
6315 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6318 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6322 * Do the notify calls from a rename
6325 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6326 const struct smb_filename
*smb_fname_src
,
6327 const struct smb_filename
*smb_fname_dst
)
6329 char *parent_dir_src
= NULL
;
6330 char *parent_dir_dst
= NULL
;
6333 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6334 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6336 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6337 &parent_dir_src
, NULL
) ||
6338 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6339 &parent_dir_dst
, NULL
)) {
6343 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6344 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6345 smb_fname_src
->base_name
);
6346 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6347 smb_fname_dst
->base_name
);
6350 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6351 smb_fname_src
->base_name
);
6352 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6353 smb_fname_dst
->base_name
);
6356 /* this is a strange one. w2k3 gives an additional event for
6357 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6358 files, but not directories */
6360 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6361 FILE_NOTIFY_CHANGE_ATTRIBUTES
6362 |FILE_NOTIFY_CHANGE_CREATION
,
6363 smb_fname_dst
->base_name
);
6366 TALLOC_FREE(parent_dir_src
);
6367 TALLOC_FREE(parent_dir_dst
);
6370 /****************************************************************************
6371 Returns an error if the parent directory for a filename is open in an
6373 ****************************************************************************/
6375 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6376 const struct smb_filename
*smb_fname_dst_in
)
6378 char *parent_dir
= NULL
;
6379 struct smb_filename smb_fname_parent
;
6381 files_struct
*fsp
= NULL
;
6384 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6385 &parent_dir
, NULL
)) {
6386 return NT_STATUS_NO_MEMORY
;
6388 ZERO_STRUCT(smb_fname_parent
);
6389 smb_fname_parent
.base_name
= parent_dir
;
6391 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6393 return map_nt_error_from_unix(errno
);
6397 * We're only checking on this smbd here, mostly good
6398 * enough.. and will pass tests.
6401 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6402 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6403 fsp
= file_find_di_next(fsp
)) {
6404 if (fsp
->access_mask
& DELETE_ACCESS
) {
6405 return NT_STATUS_SHARING_VIOLATION
;
6408 return NT_STATUS_OK
;
6411 /****************************************************************************
6412 Rename an open file - given an fsp.
6413 ****************************************************************************/
6415 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6417 const struct smb_filename
*smb_fname_dst_in
,
6419 bool replace_if_exists
)
6421 TALLOC_CTX
*ctx
= talloc_tos();
6422 struct smb_filename
*smb_fname_dst
= NULL
;
6423 NTSTATUS status
= NT_STATUS_OK
;
6424 struct share_mode_lock
*lck
= NULL
;
6425 bool dst_exists
, old_is_stream
, new_is_stream
;
6427 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6428 if (!NT_STATUS_IS_OK(status
)) {
6432 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6433 if (!NT_STATUS_IS_OK(status
)) {
6437 /* Make a copy of the dst smb_fname structs */
6439 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6440 if (smb_fname_dst
== NULL
) {
6441 status
= NT_STATUS_NO_MEMORY
;
6446 * Check for special case with case preserving and not
6447 * case sensitive. If the old last component differs from the original
6448 * last component only by case, then we should allow
6449 * the rename (user is trying to change the case of the
6452 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6453 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6454 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6456 char *fname_dst_lcomp_base_mod
= NULL
;
6457 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6460 * Get the last component of the destination name.
6462 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6464 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6466 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6468 if (!fname_dst_lcomp_base_mod
) {
6469 status
= NT_STATUS_NO_MEMORY
;
6474 * Create an smb_filename struct using the original last
6475 * component of the destination.
6477 smb_fname_orig_lcomp
= synthetic_smb_fname_split(
6478 ctx
, smb_fname_dst
->original_lcomp
, NULL
);
6479 if (smb_fname_orig_lcomp
== NULL
) {
6480 status
= NT_STATUS_NO_MEMORY
;
6481 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6485 /* If the base names only differ by case, use original. */
6486 if(!strcsequal(fname_dst_lcomp_base_mod
,
6487 smb_fname_orig_lcomp
->base_name
)) {
6490 * Replace the modified last component with the
6494 *last_slash
= '\0'; /* Truncate at the '/' */
6495 tmp
= talloc_asprintf(smb_fname_dst
,
6497 smb_fname_dst
->base_name
,
6498 smb_fname_orig_lcomp
->base_name
);
6500 tmp
= talloc_asprintf(smb_fname_dst
,
6502 smb_fname_orig_lcomp
->base_name
);
6505 status
= NT_STATUS_NO_MEMORY
;
6506 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6507 TALLOC_FREE(smb_fname_orig_lcomp
);
6510 TALLOC_FREE(smb_fname_dst
->base_name
);
6511 smb_fname_dst
->base_name
= tmp
;
6514 /* If the stream_names only differ by case, use original. */
6515 if(!strcsequal(smb_fname_dst
->stream_name
,
6516 smb_fname_orig_lcomp
->stream_name
)) {
6518 /* Use the original stream. */
6519 tmp
= talloc_strdup(smb_fname_dst
,
6520 smb_fname_orig_lcomp
->stream_name
);
6522 status
= NT_STATUS_NO_MEMORY
;
6523 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6524 TALLOC_FREE(smb_fname_orig_lcomp
);
6527 TALLOC_FREE(smb_fname_dst
->stream_name
);
6528 smb_fname_dst
->stream_name
= tmp
;
6530 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6531 TALLOC_FREE(smb_fname_orig_lcomp
);
6535 * If the src and dest names are identical - including case,
6536 * don't do the rename, just return success.
6539 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6540 strcsequal(fsp
->fsp_name
->stream_name
,
6541 smb_fname_dst
->stream_name
)) {
6542 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6543 "- returning success\n",
6544 smb_fname_str_dbg(smb_fname_dst
)));
6545 status
= NT_STATUS_OK
;
6549 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6550 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6552 /* Return the correct error code if both names aren't streams. */
6553 if (!old_is_stream
&& new_is_stream
) {
6554 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6558 if (old_is_stream
&& !new_is_stream
) {
6559 status
= NT_STATUS_INVALID_PARAMETER
;
6563 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6565 if(!replace_if_exists
&& dst_exists
) {
6566 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6567 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6568 smb_fname_str_dbg(smb_fname_dst
)));
6569 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6574 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6575 &smb_fname_dst
->st
);
6576 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6578 /* The file can be open when renaming a stream */
6579 if (dst_fsp
&& !new_is_stream
) {
6580 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6581 status
= NT_STATUS_ACCESS_DENIED
;
6586 /* Ensure we have a valid stat struct for the source. */
6587 status
= vfs_stat_fsp(fsp
);
6588 if (!NT_STATUS_IS_OK(status
)) {
6592 status
= can_rename(conn
, fsp
, attrs
);
6594 if (!NT_STATUS_IS_OK(status
)) {
6595 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6596 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6597 smb_fname_str_dbg(smb_fname_dst
)));
6598 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6599 status
= NT_STATUS_ACCESS_DENIED
;
6603 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6604 status
= NT_STATUS_ACCESS_DENIED
;
6607 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6610 * We have the file open ourselves, so not being able to get the
6611 * corresponding share mode lock is a fatal error.
6614 SMB_ASSERT(lck
!= NULL
);
6616 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6617 uint32_t create_options
= fsp
->fh
->private_options
;
6619 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6620 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6621 smb_fname_str_dbg(smb_fname_dst
)));
6623 if (!fsp
->is_directory
&&
6624 !lp_posix_pathnames() &&
6625 (lp_map_archive(SNUM(conn
)) ||
6626 lp_store_dos_attributes(SNUM(conn
)))) {
6627 /* We must set the archive bit on the newly
6629 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6630 uint32_t old_dosmode
= dos_mode(conn
,
6632 file_set_dosmode(conn
,
6634 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6640 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6643 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6647 * A rename acts as a new file create w.r.t. allowing an initial delete
6648 * on close, probably because in Windows there is a new handle to the
6649 * new file. If initial delete on close was requested but not
6650 * originally set, we need to set it here. This is probably not 100% correct,
6651 * but will work for the CIFSFS client which in non-posix mode
6652 * depends on these semantics. JRA.
6655 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6656 status
= can_set_delete_on_close(fsp
, 0);
6658 if (NT_STATUS_IS_OK(status
)) {
6659 /* Note that here we set the *inital* delete on close flag,
6660 * not the regular one. The magic gets handled in close. */
6661 fsp
->initial_delete_on_close
= True
;
6665 status
= NT_STATUS_OK
;
6671 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6672 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6674 status
= map_nt_error_from_unix(errno
);
6677 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6678 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6679 smb_fname_str_dbg(smb_fname_dst
)));
6682 TALLOC_FREE(smb_fname_dst
);
6687 /****************************************************************************
6688 The guts of the rename command, split out so it may be called by the NT SMB
6690 ****************************************************************************/
6692 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6693 connection_struct
*conn
,
6694 struct smb_request
*req
,
6695 struct smb_filename
*smb_fname_src
,
6696 struct smb_filename
*smb_fname_dst
,
6698 bool replace_if_exists
,
6701 uint32_t access_mask
)
6703 char *fname_src_dir
= NULL
;
6704 char *fname_src_mask
= NULL
;
6706 NTSTATUS status
= NT_STATUS_OK
;
6707 struct smb_Dir
*dir_hnd
= NULL
;
6708 const char *dname
= NULL
;
6709 char *talloced
= NULL
;
6711 int create_options
= 0;
6712 bool posix_pathnames
= lp_posix_pathnames();
6716 * Split the old name into directory and last component
6717 * strings. Note that unix_convert may have stripped off a
6718 * leading ./ from both name and newname if the rename is
6719 * at the root of the share. We need to make sure either both
6720 * name and newname contain a / character or neither of them do
6721 * as this is checked in resolve_wildcards().
6724 /* Split up the directory from the filename/mask. */
6725 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6726 &fname_src_dir
, &fname_src_mask
);
6727 if (!NT_STATUS_IS_OK(status
)) {
6728 status
= NT_STATUS_NO_MEMORY
;
6733 * We should only check the mangled cache
6734 * here if unix_convert failed. This means
6735 * that the path in 'mask' doesn't exist
6736 * on the file system and so we need to look
6737 * for a possible mangle. This patch from
6738 * Tine Smukavec <valentin.smukavec@hermes.si>.
6741 if (!VALID_STAT(smb_fname_src
->st
) &&
6742 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6743 char *new_mask
= NULL
;
6744 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6747 TALLOC_FREE(fname_src_mask
);
6748 fname_src_mask
= new_mask
;
6752 if (!src_has_wild
) {
6756 * Only one file needs to be renamed. Append the mask back
6757 * onto the directory.
6759 TALLOC_FREE(smb_fname_src
->base_name
);
6760 if (ISDOT(fname_src_dir
)) {
6761 /* Ensure we use canonical names on open. */
6762 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6766 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6771 if (!smb_fname_src
->base_name
) {
6772 status
= NT_STATUS_NO_MEMORY
;
6776 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6777 "case_preserve = %d, short case preserve = %d, "
6778 "directory = %s, newname = %s, "
6779 "last_component_dest = %s\n",
6780 conn
->case_sensitive
, conn
->case_preserve
,
6781 conn
->short_case_preserve
,
6782 smb_fname_str_dbg(smb_fname_src
),
6783 smb_fname_str_dbg(smb_fname_dst
),
6784 smb_fname_dst
->original_lcomp
));
6786 /* The dest name still may have wildcards. */
6787 if (dest_has_wild
) {
6788 char *fname_dst_mod
= NULL
;
6789 if (!resolve_wildcards(smb_fname_dst
,
6790 smb_fname_src
->base_name
,
6791 smb_fname_dst
->base_name
,
6793 DEBUG(6, ("rename_internals: resolve_wildcards "
6795 smb_fname_src
->base_name
,
6796 smb_fname_dst
->base_name
));
6797 status
= NT_STATUS_NO_MEMORY
;
6800 TALLOC_FREE(smb_fname_dst
->base_name
);
6801 smb_fname_dst
->base_name
= fname_dst_mod
;
6804 ZERO_STRUCT(smb_fname_src
->st
);
6805 if (posix_pathnames
) {
6806 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
6808 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
6811 status
= map_nt_error_from_unix_common(errno
);
6815 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6816 create_options
|= FILE_DIRECTORY_FILE
;
6819 status
= SMB_VFS_CREATE_FILE(
6822 0, /* root_dir_fid */
6823 smb_fname_src
, /* fname */
6824 access_mask
, /* access_mask */
6825 (FILE_SHARE_READ
| /* share_access */
6827 FILE_OPEN
, /* create_disposition*/
6828 create_options
, /* create_options */
6829 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6830 0, /* oplock_request */
6832 0, /* allocation_size */
6833 0, /* private_flags */
6838 NULL
, NULL
); /* create context */
6840 if (!NT_STATUS_IS_OK(status
)) {
6841 DEBUG(3, ("Could not open rename source %s: %s\n",
6842 smb_fname_str_dbg(smb_fname_src
),
6843 nt_errstr(status
)));
6847 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6848 attrs
, replace_if_exists
);
6850 close_file(req
, fsp
, NORMAL_CLOSE
);
6852 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6853 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6854 smb_fname_str_dbg(smb_fname_dst
)));
6860 * Wildcards - process each file that matches.
6862 if (strequal(fname_src_mask
, "????????.???")) {
6863 TALLOC_FREE(fname_src_mask
);
6864 fname_src_mask
= talloc_strdup(ctx
, "*");
6865 if (!fname_src_mask
) {
6866 status
= NT_STATUS_NO_MEMORY
;
6871 status
= check_name(conn
, fname_src_dir
);
6872 if (!NT_STATUS_IS_OK(status
)) {
6876 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6878 if (dir_hnd
== NULL
) {
6879 status
= map_nt_error_from_unix(errno
);
6883 status
= NT_STATUS_NO_SUCH_FILE
;
6885 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6886 * - gentest fix. JRA
6889 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6891 files_struct
*fsp
= NULL
;
6892 char *destname
= NULL
;
6893 bool sysdir_entry
= False
;
6895 /* Quick check for "." and ".." */
6896 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6897 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6898 sysdir_entry
= True
;
6900 TALLOC_FREE(talloced
);
6905 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6906 &smb_fname_src
->st
, false)) {
6907 TALLOC_FREE(talloced
);
6911 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6912 TALLOC_FREE(talloced
);
6917 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6921 TALLOC_FREE(smb_fname_src
->base_name
);
6922 if (ISDOT(fname_src_dir
)) {
6923 /* Ensure we use canonical names on open. */
6924 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6928 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6933 if (!smb_fname_src
->base_name
) {
6934 status
= NT_STATUS_NO_MEMORY
;
6938 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6939 smb_fname_dst
->base_name
,
6941 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6942 smb_fname_src
->base_name
, destname
));
6943 TALLOC_FREE(talloced
);
6947 status
= NT_STATUS_NO_MEMORY
;
6951 TALLOC_FREE(smb_fname_dst
->base_name
);
6952 smb_fname_dst
->base_name
= destname
;
6954 ZERO_STRUCT(smb_fname_src
->st
);
6955 if (posix_pathnames
) {
6956 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6958 SMB_VFS_STAT(conn
, smb_fname_src
);
6963 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6964 create_options
|= FILE_DIRECTORY_FILE
;
6967 status
= SMB_VFS_CREATE_FILE(
6970 0, /* root_dir_fid */
6971 smb_fname_src
, /* fname */
6972 access_mask
, /* access_mask */
6973 (FILE_SHARE_READ
| /* share_access */
6975 FILE_OPEN
, /* create_disposition*/
6976 create_options
, /* create_options */
6977 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6978 0, /* oplock_request */
6980 0, /* allocation_size */
6981 0, /* private_flags */
6986 NULL
, NULL
); /* create context */
6988 if (!NT_STATUS_IS_OK(status
)) {
6989 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6990 "returned %s rename %s -> %s\n",
6992 smb_fname_str_dbg(smb_fname_src
),
6993 smb_fname_str_dbg(smb_fname_dst
)));
6997 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6999 if (!smb_fname_dst
->original_lcomp
) {
7000 status
= NT_STATUS_NO_MEMORY
;
7004 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7005 attrs
, replace_if_exists
);
7007 close_file(req
, fsp
, NORMAL_CLOSE
);
7009 if (!NT_STATUS_IS_OK(status
)) {
7010 DEBUG(3, ("rename_internals_fsp returned %s for "
7011 "rename %s -> %s\n", nt_errstr(status
),
7012 smb_fname_str_dbg(smb_fname_src
),
7013 smb_fname_str_dbg(smb_fname_dst
)));
7019 DEBUG(3,("rename_internals: doing rename on %s -> "
7020 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7021 smb_fname_str_dbg(smb_fname_src
)));
7022 TALLOC_FREE(talloced
);
7024 TALLOC_FREE(dir_hnd
);
7026 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7027 status
= map_nt_error_from_unix(errno
);
7031 TALLOC_FREE(talloced
);
7032 TALLOC_FREE(fname_src_dir
);
7033 TALLOC_FREE(fname_src_mask
);
7037 /****************************************************************************
7039 ****************************************************************************/
7041 void reply_mv(struct smb_request
*req
)
7043 connection_struct
*conn
= req
->conn
;
7045 char *newname
= NULL
;
7049 bool src_has_wcard
= False
;
7050 bool dest_has_wcard
= False
;
7051 TALLOC_CTX
*ctx
= talloc_tos();
7052 struct smb_filename
*smb_fname_src
= NULL
;
7053 struct smb_filename
*smb_fname_dst
= NULL
;
7054 uint32_t src_ucf_flags
= lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP
: UCF_COND_ALLOW_WCARD_LCOMP
;
7055 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
| (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP
);
7056 bool stream_rename
= false;
7058 START_PROFILE(SMBmv
);
7061 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7065 attrs
= SVAL(req
->vwv
+0, 0);
7067 p
= (const char *)req
->buf
+ 1;
7068 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7069 &status
, &src_has_wcard
);
7070 if (!NT_STATUS_IS_OK(status
)) {
7071 reply_nterror(req
, status
);
7075 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7076 &status
, &dest_has_wcard
);
7077 if (!NT_STATUS_IS_OK(status
)) {
7078 reply_nterror(req
, status
);
7082 if (!lp_posix_pathnames()) {
7083 /* The newname must begin with a ':' if the
7084 name contains a ':'. */
7085 if (strchr_m(name
, ':')) {
7086 if (newname
[0] != ':') {
7087 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7090 stream_rename
= true;
7094 status
= filename_convert(ctx
,
7096 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7102 if (!NT_STATUS_IS_OK(status
)) {
7103 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7104 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7105 ERRSRV
, ERRbadpath
);
7108 reply_nterror(req
, status
);
7112 status
= filename_convert(ctx
,
7114 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7120 if (!NT_STATUS_IS_OK(status
)) {
7121 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7122 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7123 ERRSRV
, ERRbadpath
);
7126 reply_nterror(req
, status
);
7130 if (stream_rename
) {
7131 /* smb_fname_dst->base_name must be the same as
7132 smb_fname_src->base_name. */
7133 TALLOC_FREE(smb_fname_dst
->base_name
);
7134 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7135 smb_fname_src
->base_name
);
7136 if (!smb_fname_dst
->base_name
) {
7137 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7142 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7143 smb_fname_str_dbg(smb_fname_dst
)));
7145 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7146 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7148 if (!NT_STATUS_IS_OK(status
)) {
7149 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7150 /* We have re-scheduled this call. */
7153 reply_nterror(req
, status
);
7157 reply_outbuf(req
, 0, 0);
7159 TALLOC_FREE(smb_fname_src
);
7160 TALLOC_FREE(smb_fname_dst
);
7165 /*******************************************************************
7166 Copy a file as part of a reply_copy.
7167 ******************************************************************/
7170 * TODO: check error codes on all callers
7173 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7174 connection_struct
*conn
,
7175 struct smb_filename
*smb_fname_src
,
7176 struct smb_filename
*smb_fname_dst
,
7179 bool target_is_directory
)
7181 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7183 files_struct
*fsp1
,*fsp2
;
7185 uint32_t new_create_disposition
;
7189 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7190 if (smb_fname_dst_tmp
== NULL
) {
7191 return NT_STATUS_NO_MEMORY
;
7195 * If the target is a directory, extract the last component from the
7196 * src filename and append it to the dst filename
7198 if (target_is_directory
) {
7201 /* dest/target can't be a stream if it's a directory. */
7202 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7204 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7208 p
= smb_fname_src
->base_name
;
7210 smb_fname_dst_tmp
->base_name
=
7211 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7213 if (!smb_fname_dst_tmp
->base_name
) {
7214 status
= NT_STATUS_NO_MEMORY
;
7219 status
= vfs_file_exist(conn
, smb_fname_src
);
7220 if (!NT_STATUS_IS_OK(status
)) {
7224 if (!target_is_directory
&& count
) {
7225 new_create_disposition
= FILE_OPEN
;
7227 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7230 &new_create_disposition
,
7233 status
= NT_STATUS_INVALID_PARAMETER
;
7238 /* Open the src file for reading. */
7239 status
= SMB_VFS_CREATE_FILE(
7242 0, /* root_dir_fid */
7243 smb_fname_src
, /* fname */
7244 FILE_GENERIC_READ
, /* access_mask */
7245 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7246 FILE_OPEN
, /* create_disposition*/
7247 0, /* create_options */
7248 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7249 INTERNAL_OPEN_ONLY
, /* oplock_request */
7251 0, /* allocation_size */
7252 0, /* private_flags */
7257 NULL
, NULL
); /* create context */
7259 if (!NT_STATUS_IS_OK(status
)) {
7263 dosattrs
= dos_mode(conn
, smb_fname_src
);
7265 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7266 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7269 /* Open the dst file for writing. */
7270 status
= SMB_VFS_CREATE_FILE(
7273 0, /* root_dir_fid */
7274 smb_fname_dst
, /* fname */
7275 FILE_GENERIC_WRITE
, /* access_mask */
7276 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7277 new_create_disposition
, /* create_disposition*/
7278 0, /* create_options */
7279 dosattrs
, /* file_attributes */
7280 INTERNAL_OPEN_ONLY
, /* oplock_request */
7282 0, /* allocation_size */
7283 0, /* private_flags */
7288 NULL
, NULL
); /* create context */
7290 if (!NT_STATUS_IS_OK(status
)) {
7291 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7295 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7296 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7298 DEBUG(0, ("error - vfs lseek returned error %s\n",
7300 status
= map_nt_error_from_unix(errno
);
7301 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7302 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7307 /* Do the actual copy. */
7308 if (smb_fname_src
->st
.st_ex_size
) {
7309 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7314 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7316 /* Ensure the modtime is set correctly on the destination file. */
7317 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7320 * As we are opening fsp1 read-only we only expect
7321 * an error on close on fsp2 if we are out of space.
7322 * Thus we don't look at the error return from the
7325 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7327 if (!NT_STATUS_IS_OK(status
)) {
7331 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7332 status
= NT_STATUS_DISK_FULL
;
7336 status
= NT_STATUS_OK
;
7339 TALLOC_FREE(smb_fname_dst_tmp
);
7343 /****************************************************************************
7344 Reply to a file copy.
7345 ****************************************************************************/
7347 void reply_copy(struct smb_request
*req
)
7349 connection_struct
*conn
= req
->conn
;
7350 struct smb_filename
*smb_fname_src
= NULL
;
7351 struct smb_filename
*smb_fname_dst
= NULL
;
7352 char *fname_src
= NULL
;
7353 char *fname_dst
= NULL
;
7354 char *fname_src_mask
= NULL
;
7355 char *fname_src_dir
= NULL
;
7358 int error
= ERRnoaccess
;
7362 bool target_is_directory
=False
;
7363 bool source_has_wild
= False
;
7364 bool dest_has_wild
= False
;
7366 TALLOC_CTX
*ctx
= talloc_tos();
7368 START_PROFILE(SMBcopy
);
7371 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7375 tid2
= SVAL(req
->vwv
+0, 0);
7376 ofun
= SVAL(req
->vwv
+1, 0);
7377 flags
= SVAL(req
->vwv
+2, 0);
7379 p
= (const char *)req
->buf
;
7380 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7381 &status
, &source_has_wild
);
7382 if (!NT_STATUS_IS_OK(status
)) {
7383 reply_nterror(req
, status
);
7386 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7387 &status
, &dest_has_wild
);
7388 if (!NT_STATUS_IS_OK(status
)) {
7389 reply_nterror(req
, status
);
7393 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7395 if (tid2
!= conn
->cnum
) {
7396 /* can't currently handle inter share copies XXXX */
7397 DEBUG(3,("Rejecting inter-share copy\n"));
7398 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7402 status
= filename_convert(ctx
, conn
,
7403 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7405 UCF_COND_ALLOW_WCARD_LCOMP
,
7408 if (!NT_STATUS_IS_OK(status
)) {
7409 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7410 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7411 ERRSRV
, ERRbadpath
);
7414 reply_nterror(req
, status
);
7418 status
= filename_convert(ctx
, conn
,
7419 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7421 UCF_COND_ALLOW_WCARD_LCOMP
,
7424 if (!NT_STATUS_IS_OK(status
)) {
7425 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7426 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7427 ERRSRV
, ERRbadpath
);
7430 reply_nterror(req
, status
);
7434 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7436 if ((flags
&1) && target_is_directory
) {
7437 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7441 if ((flags
&2) && !target_is_directory
) {
7442 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7446 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7447 /* wants a tree copy! XXXX */
7448 DEBUG(3,("Rejecting tree copy\n"));
7449 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7453 /* Split up the directory from the filename/mask. */
7454 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7455 &fname_src_dir
, &fname_src_mask
);
7456 if (!NT_STATUS_IS_OK(status
)) {
7457 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7462 * We should only check the mangled cache
7463 * here if unix_convert failed. This means
7464 * that the path in 'mask' doesn't exist
7465 * on the file system and so we need to look
7466 * for a possible mangle. This patch from
7467 * Tine Smukavec <valentin.smukavec@hermes.si>.
7469 if (!VALID_STAT(smb_fname_src
->st
) &&
7470 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7471 char *new_mask
= NULL
;
7472 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7473 &new_mask
, conn
->params
);
7475 /* Use demangled name if one was successfully found. */
7477 TALLOC_FREE(fname_src_mask
);
7478 fname_src_mask
= new_mask
;
7482 if (!source_has_wild
) {
7485 * Only one file needs to be copied. Append the mask back onto
7488 TALLOC_FREE(smb_fname_src
->base_name
);
7489 if (ISDOT(fname_src_dir
)) {
7490 /* Ensure we use canonical names on open. */
7491 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7495 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7500 if (!smb_fname_src
->base_name
) {
7501 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7505 if (dest_has_wild
) {
7506 char *fname_dst_mod
= NULL
;
7507 if (!resolve_wildcards(smb_fname_dst
,
7508 smb_fname_src
->base_name
,
7509 smb_fname_dst
->base_name
,
7511 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7514 TALLOC_FREE(smb_fname_dst
->base_name
);
7515 smb_fname_dst
->base_name
= fname_dst_mod
;
7518 status
= check_name(conn
, smb_fname_src
->base_name
);
7519 if (!NT_STATUS_IS_OK(status
)) {
7520 reply_nterror(req
, status
);
7524 status
= check_name(conn
, smb_fname_dst
->base_name
);
7525 if (!NT_STATUS_IS_OK(status
)) {
7526 reply_nterror(req
, status
);
7530 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7531 ofun
, count
, target_is_directory
);
7533 if(!NT_STATUS_IS_OK(status
)) {
7534 reply_nterror(req
, status
);
7540 struct smb_Dir
*dir_hnd
= NULL
;
7541 const char *dname
= NULL
;
7542 char *talloced
= NULL
;
7546 * There is a wildcard that requires us to actually read the
7547 * src dir and copy each file matching the mask to the dst.
7548 * Right now streams won't be copied, but this could
7549 * presumably be added with a nested loop for reach dir entry.
7551 SMB_ASSERT(!smb_fname_src
->stream_name
);
7552 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7554 smb_fname_src
->stream_name
= NULL
;
7555 smb_fname_dst
->stream_name
= NULL
;
7557 if (strequal(fname_src_mask
,"????????.???")) {
7558 TALLOC_FREE(fname_src_mask
);
7559 fname_src_mask
= talloc_strdup(ctx
, "*");
7560 if (!fname_src_mask
) {
7561 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7566 status
= check_name(conn
, fname_src_dir
);
7567 if (!NT_STATUS_IS_OK(status
)) {
7568 reply_nterror(req
, status
);
7572 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7573 if (dir_hnd
== NULL
) {
7574 status
= map_nt_error_from_unix(errno
);
7575 reply_nterror(req
, status
);
7581 /* Iterate over the src dir copying each entry to the dst. */
7582 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7583 &smb_fname_src
->st
, &talloced
))) {
7584 char *destname
= NULL
;
7586 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7587 TALLOC_FREE(talloced
);
7591 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7592 &smb_fname_src
->st
, false)) {
7593 TALLOC_FREE(talloced
);
7597 if(!mask_match(dname
, fname_src_mask
,
7598 conn
->case_sensitive
)) {
7599 TALLOC_FREE(talloced
);
7603 error
= ERRnoaccess
;
7605 /* Get the src smb_fname struct setup. */
7606 TALLOC_FREE(smb_fname_src
->base_name
);
7607 if (ISDOT(fname_src_dir
)) {
7608 /* Ensure we use canonical names on open. */
7609 smb_fname_src
->base_name
=
7610 talloc_asprintf(smb_fname_src
, "%s",
7613 smb_fname_src
->base_name
=
7614 talloc_asprintf(smb_fname_src
, "%s/%s",
7615 fname_src_dir
, dname
);
7618 if (!smb_fname_src
->base_name
) {
7619 TALLOC_FREE(dir_hnd
);
7620 TALLOC_FREE(talloced
);
7621 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7625 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7626 smb_fname_dst
->base_name
,
7628 TALLOC_FREE(talloced
);
7632 TALLOC_FREE(dir_hnd
);
7633 TALLOC_FREE(talloced
);
7634 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7638 TALLOC_FREE(smb_fname_dst
->base_name
);
7639 smb_fname_dst
->base_name
= destname
;
7641 status
= check_name(conn
, smb_fname_src
->base_name
);
7642 if (!NT_STATUS_IS_OK(status
)) {
7643 TALLOC_FREE(dir_hnd
);
7644 TALLOC_FREE(talloced
);
7645 reply_nterror(req
, status
);
7649 status
= check_name(conn
, smb_fname_dst
->base_name
);
7650 if (!NT_STATUS_IS_OK(status
)) {
7651 TALLOC_FREE(dir_hnd
);
7652 TALLOC_FREE(talloced
);
7653 reply_nterror(req
, status
);
7657 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7658 smb_fname_src
->base_name
,
7659 smb_fname_dst
->base_name
));
7661 status
= copy_file(ctx
, conn
, smb_fname_src
,
7662 smb_fname_dst
, ofun
, count
,
7663 target_is_directory
);
7664 if (NT_STATUS_IS_OK(status
)) {
7668 TALLOC_FREE(talloced
);
7670 TALLOC_FREE(dir_hnd
);
7674 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7678 reply_outbuf(req
, 1, 0);
7679 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7681 TALLOC_FREE(smb_fname_src
);
7682 TALLOC_FREE(smb_fname_dst
);
7683 TALLOC_FREE(fname_src
);
7684 TALLOC_FREE(fname_dst
);
7685 TALLOC_FREE(fname_src_mask
);
7686 TALLOC_FREE(fname_src_dir
);
7688 END_PROFILE(SMBcopy
);
7693 #define DBGC_CLASS DBGC_LOCKING
7695 /****************************************************************************
7696 Get a lock pid, dealing with large count requests.
7697 ****************************************************************************/
7699 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7700 bool large_file_format
)
7702 if(!large_file_format
)
7703 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7705 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7708 /****************************************************************************
7709 Get a lock count, dealing with large count requests.
7710 ****************************************************************************/
7712 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7713 bool large_file_format
)
7717 if(!large_file_format
) {
7718 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7721 * No BVAL, this is reversed!
7723 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7724 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7730 /****************************************************************************
7731 Get a lock offset, dealing with large offset requests.
7732 ****************************************************************************/
7734 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7735 bool large_file_format
)
7737 uint64_t offset
= 0;
7739 if(!large_file_format
) {
7740 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7743 * No BVAL, this is reversed!
7745 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7746 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7752 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7757 struct smbd_lock_element
*locks
,
7760 connection_struct
*conn
= req
->conn
;
7762 NTSTATUS status
= NT_STATUS_OK
;
7766 /* Setup the timeout in seconds. */
7768 if (!lp_blocking_locks(SNUM(conn
))) {
7772 for(i
= 0; i
< (int)num_locks
; i
++) {
7773 struct smbd_lock_element
*e
= &locks
[i
];
7775 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7776 "%llu, file %s timeout = %d\n",
7779 (unsigned long long)e
->smblctx
,
7783 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7784 struct blocking_lock_record
*blr
= NULL
;
7786 if (num_locks
> 1) {
7788 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7789 * if the lock vector contains one entry. When given multiple cancel
7790 * requests in a single PDU we expect the server to return an
7791 * error. Windows servers seem to accept the request but only
7792 * cancel the first lock.
7793 * JRA - Do what Windows does (tm) :-).
7797 /* MS-CIFS (2.2.4.32.1) behavior. */
7798 return NT_STATUS_DOS(ERRDOS
,
7799 ERRcancelviolation
);
7801 /* Windows behavior. */
7803 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7804 "cancel request\n"));
7810 if (lp_blocking_locks(SNUM(conn
))) {
7812 /* Schedule a message to ourselves to
7813 remove the blocking lock record and
7814 return the right error. */
7816 blr
= blocking_lock_cancel_smb1(fsp
,
7822 NT_STATUS_FILE_LOCK_CONFLICT
);
7824 return NT_STATUS_DOS(
7826 ERRcancelviolation
);
7829 /* Remove a matching pending lock. */
7830 status
= do_lock_cancel(fsp
,
7836 bool blocking_lock
= timeout
? true : false;
7837 bool defer_lock
= false;
7838 struct byte_range_lock
*br_lck
;
7839 uint64_t block_smblctx
;
7841 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7852 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7853 /* Windows internal resolution for blocking locks seems
7854 to be about 200ms... Don't wait for less than that. JRA. */
7855 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7856 timeout
= lp_lock_spin_time();
7861 /* If a lock sent with timeout of zero would fail, and
7862 * this lock has been requested multiple times,
7863 * according to brl_lock_failed() we convert this
7864 * request to a blocking lock with a timeout of between
7865 * 150 - 300 milliseconds.
7867 * If lp_lock_spin_time() has been set to 0, we skip
7868 * this blocking retry and fail immediately.
7870 * Replacement for do_lock_spin(). JRA. */
7872 if (!req
->sconn
->using_smb2
&&
7873 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7874 lp_lock_spin_time() && !blocking_lock
&&
7875 NT_STATUS_EQUAL((status
),
7876 NT_STATUS_FILE_LOCK_CONFLICT
))
7879 timeout
= lp_lock_spin_time();
7882 if (br_lck
&& defer_lock
) {
7884 * A blocking lock was requested. Package up
7885 * this smb into a queued request and push it
7886 * onto the blocking lock queue.
7888 if(push_blocking_lock_request(br_lck
,
7899 TALLOC_FREE(br_lck
);
7901 return NT_STATUS_OK
;
7905 TALLOC_FREE(br_lck
);
7908 if (!NT_STATUS_IS_OK(status
)) {
7913 /* If any of the above locks failed, then we must unlock
7914 all of the previous locks (X/Open spec). */
7916 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7918 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7919 i
= -1; /* we want to skip the for loop */
7923 * Ensure we don't do a remove on the lock that just failed,
7924 * as under POSIX rules, if we have a lock already there, we
7925 * will delete it (and we shouldn't) .....
7927 for(i
--; i
>= 0; i
--) {
7928 struct smbd_lock_element
*e
= &locks
[i
];
7930 do_unlock(req
->sconn
->msg_ctx
,
7940 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7941 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
));
7943 return NT_STATUS_OK
;
7946 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
7948 uint16_t num_ulocks
,
7949 struct smbd_lock_element
*ulocks
)
7953 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7954 struct smbd_lock_element
*e
= &ulocks
[i
];
7957 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7958 "pid %u, file %s\n", __func__
,
7961 (unsigned int)e
->smblctx
,
7964 if (e
->brltype
!= UNLOCK_LOCK
) {
7965 /* this can only happen with SMB2 */
7966 return NT_STATUS_INVALID_PARAMETER
;
7969 status
= do_unlock(req
->sconn
->msg_ctx
,
7976 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
7977 nt_errstr(status
)));
7979 if (!NT_STATUS_IS_OK(status
)) {
7984 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
7987 return NT_STATUS_OK
;
7990 /****************************************************************************
7991 Reply to a lockingX request.
7992 ****************************************************************************/
7994 void reply_lockingX(struct smb_request
*req
)
7996 connection_struct
*conn
= req
->conn
;
7998 unsigned char locktype
;
7999 unsigned char oplocklevel
;
8000 uint16_t num_ulocks
;
8002 int32_t lock_timeout
;
8004 const uint8_t *data
;
8005 bool large_file_format
;
8006 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8007 struct smbd_lock_element
*ulocks
;
8008 struct smbd_lock_element
*locks
;
8011 START_PROFILE(SMBlockingX
);
8014 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8015 END_PROFILE(SMBlockingX
);
8019 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8020 locktype
= CVAL(req
->vwv
+3, 0);
8021 oplocklevel
= CVAL(req
->vwv
+3, 1);
8022 num_ulocks
= SVAL(req
->vwv
+6, 0);
8023 num_locks
= SVAL(req
->vwv
+7, 0);
8024 lock_timeout
= IVAL(req
->vwv
+4, 0);
8025 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8027 if (!check_fsp(conn
, req
, fsp
)) {
8028 END_PROFILE(SMBlockingX
);
8034 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8035 /* we don't support these - and CANCEL_LOCK makes w2k
8036 and XP reboot so I don't really want to be
8037 compatible! (tridge) */
8038 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8039 END_PROFILE(SMBlockingX
);
8043 /* Check if this is an oplock break on a file
8044 we have granted an oplock on.
8046 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8047 /* Client can insist on breaking to none. */
8048 bool break_to_none
= (oplocklevel
== 0);
8051 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8052 "for %s\n", (unsigned int)oplocklevel
,
8053 fsp_fnum_dbg(fsp
)));
8056 * Make sure we have granted an exclusive or batch oplock on
8060 if (fsp
->oplock_type
== 0) {
8062 /* The Samba4 nbench simulator doesn't understand
8063 the difference between break to level2 and break
8064 to none from level2 - it sends oplock break
8065 replies in both cases. Don't keep logging an error
8066 message here - just ignore it. JRA. */
8068 DEBUG(5,("reply_lockingX: Error : oplock break from "
8069 "client for %s (oplock=%d) and no "
8070 "oplock granted on this file (%s).\n",
8071 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8074 /* if this is a pure oplock break request then don't
8076 if (num_locks
== 0 && num_ulocks
== 0) {
8077 END_PROFILE(SMBlockingX
);
8080 END_PROFILE(SMBlockingX
);
8081 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8086 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8088 result
= remove_oplock(fsp
);
8090 result
= downgrade_oplock(fsp
);
8094 DEBUG(0, ("reply_lockingX: error in removing "
8095 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8096 /* Hmmm. Is this panic justified? */
8097 smb_panic("internal tdb error");
8100 /* if this is a pure oplock break request then don't send a
8102 if (num_locks
== 0 && num_ulocks
== 0) {
8103 /* Sanity check - ensure a pure oplock break is not a
8105 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8106 DEBUG(0,("reply_lockingX: Error : pure oplock "
8107 "break is a chained %d request !\n",
8108 (unsigned int)CVAL(req
->vwv
+0, 0)));
8110 END_PROFILE(SMBlockingX
);
8116 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8117 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8118 END_PROFILE(SMBlockingX
);
8122 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8123 if (ulocks
== NULL
) {
8124 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8125 END_PROFILE(SMBlockingX
);
8129 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8130 if (locks
== NULL
) {
8131 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8132 END_PROFILE(SMBlockingX
);
8136 /* Data now points at the beginning of the list
8137 of smb_unlkrng structs */
8138 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8139 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8140 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8141 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8142 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8145 /* Now do any requested locks */
8146 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8148 /* Data now points at the beginning of the list
8149 of smb_lkrng structs */
8151 for(i
= 0; i
< (int)num_locks
; i
++) {
8152 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8153 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8154 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8156 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8157 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8158 locks
[i
].brltype
= PENDING_READ_LOCK
;
8160 locks
[i
].brltype
= READ_LOCK
;
8163 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8164 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8166 locks
[i
].brltype
= WRITE_LOCK
;
8171 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
);
8172 if (!NT_STATUS_IS_OK(status
)) {
8173 END_PROFILE(SMBlockingX
);
8174 reply_nterror(req
, status
);
8178 status
= smbd_do_locking(req
, fsp
,
8179 locktype
, lock_timeout
,
8182 if (!NT_STATUS_IS_OK(status
)) {
8183 END_PROFILE(SMBlockingX
);
8184 reply_nterror(req
, status
);
8188 END_PROFILE(SMBlockingX
);
8192 reply_outbuf(req
, 2, 0);
8193 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8194 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8196 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8197 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8199 END_PROFILE(SMBlockingX
);
8203 #define DBGC_CLASS DBGC_ALL
8205 /****************************************************************************
8206 Reply to a SMBreadbmpx (read block multiplex) request.
8207 Always reply with an error, if someone has a platform really needs this,
8208 please contact vl@samba.org
8209 ****************************************************************************/
8211 void reply_readbmpx(struct smb_request
*req
)
8213 START_PROFILE(SMBreadBmpx
);
8214 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8215 END_PROFILE(SMBreadBmpx
);
8219 /****************************************************************************
8220 Reply to a SMBreadbs (read block multiplex secondary) request.
8221 Always reply with an error, if someone has a platform really needs this,
8222 please contact vl@samba.org
8223 ****************************************************************************/
8225 void reply_readbs(struct smb_request
*req
)
8227 START_PROFILE(SMBreadBs
);
8228 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8229 END_PROFILE(SMBreadBs
);
8233 /****************************************************************************
8234 Reply to a SMBsetattrE.
8235 ****************************************************************************/
8237 void reply_setattrE(struct smb_request
*req
)
8239 connection_struct
*conn
= req
->conn
;
8240 struct smb_file_time ft
;
8244 START_PROFILE(SMBsetattrE
);
8248 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8252 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8254 if(!fsp
|| (fsp
->conn
!= conn
)) {
8255 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8260 * Convert the DOS times into unix times.
8263 ft
.atime
= convert_time_t_to_timespec(
8264 srv_make_unix_date2(req
->vwv
+3));
8265 ft
.mtime
= convert_time_t_to_timespec(
8266 srv_make_unix_date2(req
->vwv
+5));
8267 ft
.create_time
= convert_time_t_to_timespec(
8268 srv_make_unix_date2(req
->vwv
+1));
8270 reply_outbuf(req
, 0, 0);
8273 * Patch from Ray Frush <frush@engr.colostate.edu>
8274 * Sometimes times are sent as zero - ignore them.
8277 /* Ensure we have a valid stat struct for the source. */
8278 status
= vfs_stat_fsp(fsp
);
8279 if (!NT_STATUS_IS_OK(status
)) {
8280 reply_nterror(req
, status
);
8284 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8285 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8289 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8290 if (!NT_STATUS_IS_OK(status
)) {
8291 reply_nterror(req
, status
);
8295 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8298 (unsigned int)ft
.atime
.tv_sec
,
8299 (unsigned int)ft
.mtime
.tv_sec
,
8300 (unsigned int)ft
.create_time
.tv_sec
8303 END_PROFILE(SMBsetattrE
);
8308 /* Back from the dead for OS/2..... JRA. */
8310 /****************************************************************************
8311 Reply to a SMBwritebmpx (write block multiplex primary) request.
8312 Always reply with an error, if someone has a platform really needs this,
8313 please contact vl@samba.org
8314 ****************************************************************************/
8316 void reply_writebmpx(struct smb_request
*req
)
8318 START_PROFILE(SMBwriteBmpx
);
8319 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8320 END_PROFILE(SMBwriteBmpx
);
8324 /****************************************************************************
8325 Reply to a SMBwritebs (write block multiplex secondary) request.
8326 Always reply with an error, if someone has a platform really needs this,
8327 please contact vl@samba.org
8328 ****************************************************************************/
8330 void reply_writebs(struct smb_request
*req
)
8332 START_PROFILE(SMBwriteBs
);
8333 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8334 END_PROFILE(SMBwriteBs
);
8338 /****************************************************************************
8339 Reply to a SMBgetattrE.
8340 ****************************************************************************/
8342 void reply_getattrE(struct smb_request
*req
)
8344 connection_struct
*conn
= req
->conn
;
8347 struct timespec create_ts
;
8349 START_PROFILE(SMBgetattrE
);
8352 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8353 END_PROFILE(SMBgetattrE
);
8357 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8359 if(!fsp
|| (fsp
->conn
!= conn
)) {
8360 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8361 END_PROFILE(SMBgetattrE
);
8365 /* Do an fstat on this file */
8367 reply_nterror(req
, map_nt_error_from_unix(errno
));
8368 END_PROFILE(SMBgetattrE
);
8372 mode
= dos_mode(conn
, fsp
->fsp_name
);
8375 * Convert the times into dos times. Set create
8376 * date to be last modify date as UNIX doesn't save
8380 reply_outbuf(req
, 11, 0);
8382 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8383 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8384 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8385 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8386 /* Should we check pending modtime here ? JRA */
8387 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8388 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8390 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8391 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8392 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8394 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8395 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
8396 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8398 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8400 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8402 END_PROFILE(SMBgetattrE
);