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 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
;
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
)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
;
1459 uint64_t dfree
,dsize
,bsize
;
1460 START_PROFILE(SMBdskattr
);
1462 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1463 reply_nterror(req
, map_nt_error_from_unix(errno
));
1464 END_PROFILE(SMBdskattr
);
1468 reply_outbuf(req
, 5, 0);
1470 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1471 double total_space
, free_space
;
1472 /* we need to scale this to a number that DOS6 can handle. We
1473 use floating point so we can handle large drives on systems
1474 that don't have 64 bit integers
1476 we end up displaying a maximum of 2G to DOS systems
1478 total_space
= dsize
* (double)bsize
;
1479 free_space
= dfree
* (double)bsize
;
1481 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1482 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1484 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1485 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1487 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1488 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1489 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1490 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1492 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1493 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1494 SSVAL(req
->outbuf
,smb_vwv2
,512);
1495 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1498 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1500 END_PROFILE(SMBdskattr
);
1505 * Utility function to split the filename from the directory.
1507 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1508 char **fname_dir_out
,
1509 char **fname_mask_out
)
1511 const char *p
= NULL
;
1512 char *fname_dir
= NULL
;
1513 char *fname_mask
= NULL
;
1515 p
= strrchr_m(fname_in
, '/');
1517 fname_dir
= talloc_strdup(ctx
, ".");
1518 fname_mask
= talloc_strdup(ctx
, fname_in
);
1520 fname_dir
= talloc_strndup(ctx
, fname_in
,
1521 PTR_DIFF(p
, fname_in
));
1522 fname_mask
= talloc_strdup(ctx
, p
+1);
1525 if (!fname_dir
|| !fname_mask
) {
1526 TALLOC_FREE(fname_dir
);
1527 TALLOC_FREE(fname_mask
);
1528 return NT_STATUS_NO_MEMORY
;
1531 *fname_dir_out
= fname_dir
;
1532 *fname_mask_out
= fname_mask
;
1533 return NT_STATUS_OK
;
1536 /****************************************************************************
1538 ****************************************************************************/
1540 static bool make_dir_struct(TALLOC_CTX
*ctx
,
1550 char *mask2
= talloc_strdup(ctx
, mask
);
1556 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1560 memset(buf
+1,' ',11);
1561 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
1563 push_ascii(buf
+1,mask2
,8, 0);
1564 push_ascii(buf
+9,p
+1,3, 0);
1567 push_ascii(buf
+1,mask2
,11, 0);
1570 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1572 srv_put_dos_date(buf
,22,date
);
1573 SSVAL(buf
,26,size
& 0xFFFF);
1574 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1575 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1576 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1577 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1578 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1582 /****************************************************************************
1584 Can be called from SMBsearch, SMBffirst or SMBfunique.
1585 ****************************************************************************/
1587 void reply_search(struct smb_request
*req
)
1589 connection_struct
*conn
= req
->conn
;
1591 const char *mask
= NULL
;
1592 char *directory
= NULL
;
1593 struct smb_filename
*smb_fname
= NULL
;
1597 struct timespec date
;
1599 unsigned int numentries
= 0;
1600 unsigned int maxentries
= 0;
1601 bool finished
= False
;
1606 bool check_descend
= False
;
1607 bool expect_close
= False
;
1609 bool mask_contains_wcard
= False
;
1610 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1611 TALLOC_CTX
*ctx
= talloc_tos();
1612 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1613 struct dptr_struct
*dirptr
= NULL
;
1614 struct smbXsrv_connection
*xconn
= req
->xconn
;
1615 struct smbd_server_connection
*sconn
= req
->sconn
;
1617 START_PROFILE(SMBsearch
);
1620 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1624 if (lp_posix_pathnames()) {
1625 reply_unknown_new(req
, req
->cmd
);
1629 /* If we were called as SMBffirst then we must expect close. */
1630 if(req
->cmd
== SMBffirst
) {
1631 expect_close
= True
;
1634 reply_outbuf(req
, 1, 3);
1635 maxentries
= SVAL(req
->vwv
+0, 0);
1636 dirtype
= SVAL(req
->vwv
+1, 0);
1637 p
= (const char *)req
->buf
+ 1;
1638 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1639 &nt_status
, &mask_contains_wcard
);
1640 if (!NT_STATUS_IS_OK(nt_status
)) {
1641 reply_nterror(req
, nt_status
);
1646 status_len
= SVAL(p
, 0);
1649 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1651 if (status_len
== 0) {
1652 nt_status
= filename_convert(ctx
, conn
,
1653 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1655 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1656 &mask_contains_wcard
,
1658 if (!NT_STATUS_IS_OK(nt_status
)) {
1659 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1660 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1661 ERRSRV
, ERRbadpath
);
1664 reply_nterror(req
, nt_status
);
1668 directory
= smb_fname
->base_name
;
1670 p
= strrchr_m(directory
,'/');
1671 if ((p
!= NULL
) && (*directory
!= '/')) {
1673 directory
= talloc_strndup(ctx
, directory
,
1674 PTR_DIFF(p
, directory
));
1677 directory
= talloc_strdup(ctx
,".");
1681 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1685 memset((char *)status
,'\0',21);
1686 SCVAL(status
,0,(dirtype
& 0x1F));
1688 nt_status
= dptr_create(conn
,
1696 mask_contains_wcard
,
1699 if (!NT_STATUS_IS_OK(nt_status
)) {
1700 reply_nterror(req
, nt_status
);
1703 dptr_num
= dptr_dnum(dirptr
);
1706 const char *dirpath
;
1708 memcpy(status
,p
,21);
1709 status_dirtype
= CVAL(status
,0) & 0x1F;
1710 if (status_dirtype
!= (dirtype
& 0x1F)) {
1711 dirtype
= status_dirtype
;
1714 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1718 dirpath
= dptr_path(sconn
, dptr_num
);
1719 directory
= talloc_strdup(ctx
, dirpath
);
1721 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1725 mask
= dptr_wcard(sconn
, dptr_num
);
1730 * For a 'continue' search we have no string. So
1731 * check from the initial saved string.
1733 mask_contains_wcard
= ms_has_wild(mask
);
1734 dirtype
= dptr_attr(sconn
, dptr_num
);
1737 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1739 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1740 dptr_init_search_op(dirptr
);
1742 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1743 char buf
[DIR_STRUCT_SIZE
];
1744 memcpy(buf
,status
,21);
1745 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1746 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1747 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1750 dptr_fill(sconn
, buf
+12,dptr_num
);
1751 if (dptr_zero(buf
+12) && (status_len
==0)) {
1756 if (message_push_blob(&req
->outbuf
,
1757 data_blob_const(buf
, sizeof(buf
)))
1759 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1764 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1765 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1767 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1769 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1770 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
1771 if (in_list(directory
, lp_dont_descend(ctx
, SNUM(conn
)),True
)) {
1772 check_descend
= True
;
1775 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1776 finished
= !get_dir_entry(ctx
,
1787 char buf
[DIR_STRUCT_SIZE
];
1788 memcpy(buf
,status
,21);
1789 if (!make_dir_struct(ctx
,
1795 convert_timespec_to_time_t(date
),
1796 !allow_long_path_components
)) {
1797 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1800 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1803 if (message_push_blob(&req
->outbuf
,
1804 data_blob_const(buf
, sizeof(buf
)))
1806 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1816 /* If we were called as SMBffirst with smb_search_id == NULL
1817 and no entries were found then return error and close dirptr
1820 if (numentries
== 0) {
1821 dptr_close(sconn
, &dptr_num
);
1822 } else if(expect_close
&& status_len
== 0) {
1823 /* Close the dptr - we know it's gone */
1824 dptr_close(sconn
, &dptr_num
);
1827 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1828 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1829 dptr_close(sconn
, &dptr_num
);
1832 if ((numentries
== 0) && !mask_contains_wcard
) {
1833 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1837 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1838 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1839 SCVAL(smb_buf(req
->outbuf
),0,5);
1840 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1842 /* The replies here are never long name. */
1843 SSVAL(req
->outbuf
, smb_flg2
,
1844 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1845 if (!allow_long_path_components
) {
1846 SSVAL(req
->outbuf
, smb_flg2
,
1847 SVAL(req
->outbuf
, smb_flg2
)
1848 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1851 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1852 SSVAL(req
->outbuf
, smb_flg2
,
1853 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1855 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1856 smb_fn_name(req
->cmd
),
1863 TALLOC_FREE(directory
);
1864 TALLOC_FREE(smb_fname
);
1865 END_PROFILE(SMBsearch
);
1869 /****************************************************************************
1870 Reply to a fclose (stop directory search).
1871 ****************************************************************************/
1873 void reply_fclose(struct smb_request
*req
)
1881 bool path_contains_wcard
= False
;
1882 TALLOC_CTX
*ctx
= talloc_tos();
1883 struct smbd_server_connection
*sconn
= req
->sconn
;
1885 START_PROFILE(SMBfclose
);
1887 if (lp_posix_pathnames()) {
1888 reply_unknown_new(req
, req
->cmd
);
1889 END_PROFILE(SMBfclose
);
1893 p
= (const char *)req
->buf
+ 1;
1894 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1895 &err
, &path_contains_wcard
);
1896 if (!NT_STATUS_IS_OK(err
)) {
1897 reply_nterror(req
, err
);
1898 END_PROFILE(SMBfclose
);
1902 status_len
= SVAL(p
,0);
1905 if (status_len
== 0) {
1906 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1907 END_PROFILE(SMBfclose
);
1911 memcpy(status
,p
,21);
1913 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1914 /* Close the dptr - we know it's gone */
1915 dptr_close(sconn
, &dptr_num
);
1918 reply_outbuf(req
, 1, 0);
1919 SSVAL(req
->outbuf
,smb_vwv0
,0);
1921 DEBUG(3,("search close\n"));
1923 END_PROFILE(SMBfclose
);
1927 /****************************************************************************
1929 ****************************************************************************/
1931 void reply_open(struct smb_request
*req
)
1933 connection_struct
*conn
= req
->conn
;
1934 struct smb_filename
*smb_fname
= NULL
;
1946 uint32 create_disposition
;
1947 uint32 create_options
= 0;
1948 uint32_t private_flags
= 0;
1950 TALLOC_CTX
*ctx
= talloc_tos();
1952 START_PROFILE(SMBopen
);
1955 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1959 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1960 deny_mode
= SVAL(req
->vwv
+0, 0);
1961 dos_attr
= SVAL(req
->vwv
+1, 0);
1963 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1964 STR_TERMINATE
, &status
);
1965 if (!NT_STATUS_IS_OK(status
)) {
1966 reply_nterror(req
, status
);
1970 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1971 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1972 &share_mode
, &create_disposition
,
1973 &create_options
, &private_flags
)) {
1974 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1978 status
= filename_convert(ctx
,
1980 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1982 UCF_PREP_CREATEFILE
,
1985 if (!NT_STATUS_IS_OK(status
)) {
1986 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1987 reply_botherror(req
,
1988 NT_STATUS_PATH_NOT_COVERED
,
1989 ERRSRV
, ERRbadpath
);
1992 reply_nterror(req
, status
);
1996 status
= SMB_VFS_CREATE_FILE(
1999 0, /* root_dir_fid */
2000 smb_fname
, /* fname */
2001 access_mask
, /* access_mask */
2002 share_mode
, /* share_access */
2003 create_disposition
, /* create_disposition*/
2004 create_options
, /* create_options */
2005 dos_attr
, /* file_attributes */
2006 oplock_request
, /* oplock_request */
2008 0, /* allocation_size */
2014 NULL
, NULL
); /* create context */
2016 if (!NT_STATUS_IS_OK(status
)) {
2017 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2018 /* We have re-scheduled this call. */
2021 reply_openerror(req
, status
);
2025 /* Ensure we're pointing at the correct stat struct. */
2026 TALLOC_FREE(smb_fname
);
2027 smb_fname
= fsp
->fsp_name
;
2029 size
= smb_fname
->st
.st_ex_size
;
2030 fattr
= dos_mode(conn
, smb_fname
);
2032 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2034 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2035 DEBUG(3,("attempt to open a directory %s\n",
2037 close_file(req
, fsp
, ERROR_CLOSE
);
2038 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2039 ERRDOS
, ERRnoaccess
);
2043 reply_outbuf(req
, 7, 0);
2044 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2045 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2046 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2047 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2049 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2051 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
2052 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2054 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2055 SCVAL(req
->outbuf
,smb_flg
,
2056 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2059 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2060 SCVAL(req
->outbuf
,smb_flg
,
2061 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2064 END_PROFILE(SMBopen
);
2068 /****************************************************************************
2069 Reply to an open and X.
2070 ****************************************************************************/
2072 void reply_open_and_X(struct smb_request
*req
)
2074 connection_struct
*conn
= req
->conn
;
2075 struct smb_filename
*smb_fname
= NULL
;
2080 /* Breakout the oplock request bits so we can set the
2081 reply bits separately. */
2082 int ex_oplock_request
;
2083 int core_oplock_request
;
2086 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2087 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
2095 uint64_t allocation_size
;
2096 ssize_t retval
= -1;
2099 uint32 create_disposition
;
2100 uint32 create_options
= 0;
2101 uint32_t private_flags
= 0;
2102 TALLOC_CTX
*ctx
= talloc_tos();
2104 START_PROFILE(SMBopenX
);
2106 if (req
->wct
< 15) {
2107 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2111 open_flags
= SVAL(req
->vwv
+2, 0);
2112 deny_mode
= SVAL(req
->vwv
+3, 0);
2113 smb_attr
= SVAL(req
->vwv
+5, 0);
2114 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2115 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2116 oplock_request
= ex_oplock_request
| core_oplock_request
;
2117 smb_ofun
= SVAL(req
->vwv
+8, 0);
2118 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2120 /* If it's an IPC, pass off the pipe handler. */
2122 if (lp_nt_pipe_support()) {
2123 reply_open_pipe_and_X(conn
, req
);
2125 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2130 /* XXXX we need to handle passed times, sattr and flags */
2131 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2132 STR_TERMINATE
, &status
);
2133 if (!NT_STATUS_IS_OK(status
)) {
2134 reply_nterror(req
, status
);
2138 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2140 &access_mask
, &share_mode
,
2141 &create_disposition
,
2144 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2148 status
= filename_convert(ctx
,
2150 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2152 UCF_PREP_CREATEFILE
,
2155 if (!NT_STATUS_IS_OK(status
)) {
2156 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2157 reply_botherror(req
,
2158 NT_STATUS_PATH_NOT_COVERED
,
2159 ERRSRV
, ERRbadpath
);
2162 reply_nterror(req
, status
);
2166 status
= SMB_VFS_CREATE_FILE(
2169 0, /* root_dir_fid */
2170 smb_fname
, /* fname */
2171 access_mask
, /* access_mask */
2172 share_mode
, /* share_access */
2173 create_disposition
, /* create_disposition*/
2174 create_options
, /* create_options */
2175 smb_attr
, /* file_attributes */
2176 oplock_request
, /* oplock_request */
2178 0, /* allocation_size */
2183 &smb_action
, /* pinfo */
2184 NULL
, NULL
); /* create context */
2186 if (!NT_STATUS_IS_OK(status
)) {
2187 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2188 /* We have re-scheduled this call. */
2191 reply_openerror(req
, status
);
2195 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2196 if the file is truncated or created. */
2197 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2198 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2199 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2200 close_file(req
, fsp
, ERROR_CLOSE
);
2201 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2204 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2206 close_file(req
, fsp
, ERROR_CLOSE
);
2207 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2210 status
= vfs_stat_fsp(fsp
);
2211 if (!NT_STATUS_IS_OK(status
)) {
2212 close_file(req
, fsp
, ERROR_CLOSE
);
2213 reply_nterror(req
, status
);
2218 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2219 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2220 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2221 close_file(req
, fsp
, ERROR_CLOSE
);
2222 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2226 /* If the caller set the extended oplock request bit
2227 and we granted one (by whatever means) - set the
2228 correct bit for extended oplock reply.
2231 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2232 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2235 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2236 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2239 /* If the caller set the core oplock request bit
2240 and we granted one (by whatever means) - set the
2241 correct bit for core oplock reply.
2244 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2245 reply_outbuf(req
, 19, 0);
2247 reply_outbuf(req
, 15, 0);
2250 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2251 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2253 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2254 SCVAL(req
->outbuf
, smb_flg
,
2255 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2258 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2259 SCVAL(req
->outbuf
, smb_flg
,
2260 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2263 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2264 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2265 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2266 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2268 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2270 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2271 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2272 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2274 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2275 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2279 TALLOC_FREE(smb_fname
);
2280 END_PROFILE(SMBopenX
);
2284 /****************************************************************************
2285 Reply to a SMBulogoffX.
2286 ****************************************************************************/
2288 void reply_ulogoffX(struct smb_request
*req
)
2290 struct smbd_server_connection
*sconn
= req
->sconn
;
2291 struct user_struct
*vuser
;
2292 struct smbXsrv_session
*session
= NULL
;
2295 START_PROFILE(SMBulogoffX
);
2297 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2300 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2301 (unsigned long long)req
->vuid
));
2303 req
->vuid
= UID_FIELD_INVALID
;
2304 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2305 END_PROFILE(SMBulogoffX
);
2309 session
= vuser
->session
;
2313 * TODO: cancel all outstanding requests on the session
2315 status
= smbXsrv_session_logoff(session
);
2316 if (!NT_STATUS_IS_OK(status
)) {
2317 DEBUG(0, ("reply_ulogoff: "
2318 "smbXsrv_session_logoff() failed: %s\n",
2319 nt_errstr(status
)));
2321 * If we hit this case, there is something completely
2322 * wrong, so we better disconnect the transport connection.
2324 END_PROFILE(SMBulogoffX
);
2325 exit_server(__location__
": smbXsrv_session_logoff failed");
2329 TALLOC_FREE(session
);
2331 reply_outbuf(req
, 2, 0);
2332 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2333 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2335 DEBUG(3, ("ulogoffX vuid=%llu\n",
2336 (unsigned long long)req
->vuid
));
2338 END_PROFILE(SMBulogoffX
);
2339 req
->vuid
= UID_FIELD_INVALID
;
2342 /****************************************************************************
2343 Reply to a mknew or a create.
2344 ****************************************************************************/
2346 void reply_mknew(struct smb_request
*req
)
2348 connection_struct
*conn
= req
->conn
;
2349 struct smb_filename
*smb_fname
= NULL
;
2352 struct smb_file_time ft
;
2354 int oplock_request
= 0;
2356 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2357 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2358 uint32 create_disposition
;
2359 uint32 create_options
= 0;
2360 TALLOC_CTX
*ctx
= talloc_tos();
2362 START_PROFILE(SMBcreate
);
2366 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2370 fattr
= SVAL(req
->vwv
+0, 0);
2371 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2374 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2376 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2377 STR_TERMINATE
, &status
);
2378 if (!NT_STATUS_IS_OK(status
)) {
2379 reply_nterror(req
, status
);
2383 status
= filename_convert(ctx
,
2385 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2387 UCF_PREP_CREATEFILE
,
2390 if (!NT_STATUS_IS_OK(status
)) {
2391 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2392 reply_botherror(req
,
2393 NT_STATUS_PATH_NOT_COVERED
,
2394 ERRSRV
, ERRbadpath
);
2397 reply_nterror(req
, status
);
2401 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2402 DEBUG(0,("Attempt to create file (%s) with volid set - "
2403 "please report this\n",
2404 smb_fname_str_dbg(smb_fname
)));
2407 if(req
->cmd
== SMBmknew
) {
2408 /* We should fail if file exists. */
2409 create_disposition
= FILE_CREATE
;
2411 /* Create if file doesn't exist, truncate if it does. */
2412 create_disposition
= FILE_OVERWRITE_IF
;
2415 status
= SMB_VFS_CREATE_FILE(
2418 0, /* root_dir_fid */
2419 smb_fname
, /* fname */
2420 access_mask
, /* access_mask */
2421 share_mode
, /* share_access */
2422 create_disposition
, /* create_disposition*/
2423 create_options
, /* create_options */
2424 fattr
, /* file_attributes */
2425 oplock_request
, /* oplock_request */
2427 0, /* allocation_size */
2428 0, /* private_flags */
2433 NULL
, NULL
); /* create context */
2435 if (!NT_STATUS_IS_OK(status
)) {
2436 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2437 /* We have re-scheduled this call. */
2440 reply_openerror(req
, status
);
2444 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2445 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2446 if (!NT_STATUS_IS_OK(status
)) {
2447 END_PROFILE(SMBcreate
);
2451 reply_outbuf(req
, 1, 0);
2452 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2454 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2455 SCVAL(req
->outbuf
,smb_flg
,
2456 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2459 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2460 SCVAL(req
->outbuf
,smb_flg
,
2461 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2464 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2465 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2466 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2467 (unsigned int)fattr
));
2470 TALLOC_FREE(smb_fname
);
2471 END_PROFILE(SMBcreate
);
2475 /****************************************************************************
2476 Reply to a create temporary file.
2477 ****************************************************************************/
2479 void reply_ctemp(struct smb_request
*req
)
2481 connection_struct
*conn
= req
->conn
;
2482 struct smb_filename
*smb_fname
= NULL
;
2483 char *wire_name
= NULL
;
2491 TALLOC_CTX
*ctx
= talloc_tos();
2493 START_PROFILE(SMBctemp
);
2496 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2500 fattr
= SVAL(req
->vwv
+0, 0);
2501 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2503 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2504 STR_TERMINATE
, &status
);
2505 if (!NT_STATUS_IS_OK(status
)) {
2506 reply_nterror(req
, status
);
2510 for (i
= 0; i
< 10; i
++) {
2512 fname
= talloc_asprintf(ctx
,
2515 generate_random_str_list(ctx
, 5, "0123456789"));
2517 fname
= talloc_asprintf(ctx
,
2519 generate_random_str_list(ctx
, 5, "0123456789"));
2523 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2527 status
= filename_convert(ctx
, conn
,
2528 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2530 UCF_PREP_CREATEFILE
,
2533 if (!NT_STATUS_IS_OK(status
)) {
2534 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2535 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2536 ERRSRV
, ERRbadpath
);
2539 reply_nterror(req
, status
);
2543 /* Create the file. */
2544 status
= SMB_VFS_CREATE_FILE(
2547 0, /* root_dir_fid */
2548 smb_fname
, /* fname */
2549 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2550 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2551 FILE_CREATE
, /* create_disposition*/
2552 0, /* create_options */
2553 fattr
, /* file_attributes */
2554 oplock_request
, /* oplock_request */
2556 0, /* allocation_size */
2557 0, /* private_flags */
2562 NULL
, NULL
); /* create context */
2564 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2566 TALLOC_FREE(smb_fname
);
2570 if (!NT_STATUS_IS_OK(status
)) {
2571 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2572 /* We have re-scheduled this call. */
2575 reply_openerror(req
, status
);
2583 /* Collision after 10 times... */
2584 reply_nterror(req
, status
);
2588 reply_outbuf(req
, 1, 0);
2589 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2591 /* the returned filename is relative to the directory */
2592 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2594 s
= fsp
->fsp_name
->base_name
;
2600 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2601 thing in the byte section. JRA */
2602 SSVALS(p
, 0, -1); /* what is this? not in spec */
2604 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2606 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2610 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2611 SCVAL(req
->outbuf
, smb_flg
,
2612 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2615 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2616 SCVAL(req
->outbuf
, smb_flg
,
2617 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2620 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2621 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2622 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2624 TALLOC_FREE(smb_fname
);
2625 TALLOC_FREE(wire_name
);
2626 END_PROFILE(SMBctemp
);
2630 /*******************************************************************
2631 Check if a user is allowed to rename a file.
2632 ********************************************************************/
2634 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2637 if (!CAN_WRITE(conn
)) {
2638 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2641 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2642 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2643 /* Only bother to read the DOS attribute if we might deny the
2644 rename on the grounds of attribute missmatch. */
2645 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2646 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2647 return NT_STATUS_NO_SUCH_FILE
;
2651 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2652 if (fsp
->posix_open
) {
2653 return NT_STATUS_OK
;
2656 /* If no pathnames are open below this
2657 directory, allow the rename. */
2659 if (file_find_subpath(fsp
)) {
2660 return NT_STATUS_ACCESS_DENIED
;
2662 return NT_STATUS_OK
;
2665 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2666 return NT_STATUS_OK
;
2669 return NT_STATUS_ACCESS_DENIED
;
2672 /*******************************************************************
2673 * unlink a file with all relevant access checks
2674 *******************************************************************/
2676 static NTSTATUS
do_unlink(connection_struct
*conn
,
2677 struct smb_request
*req
,
2678 struct smb_filename
*smb_fname
,
2683 uint32 dirtype_orig
= dirtype
;
2686 bool posix_paths
= lp_posix_pathnames();
2688 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2689 smb_fname_str_dbg(smb_fname
),
2692 if (!CAN_WRITE(conn
)) {
2693 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2697 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2699 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2702 return map_nt_error_from_unix(errno
);
2705 fattr
= dos_mode(conn
, smb_fname
);
2707 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2708 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2711 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2713 return NT_STATUS_NO_SUCH_FILE
;
2716 if (!dir_check_ftype(fattr
, dirtype
)) {
2717 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2718 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2720 return NT_STATUS_NO_SUCH_FILE
;
2723 if (dirtype_orig
& 0x8000) {
2724 /* These will never be set for POSIX. */
2725 return NT_STATUS_NO_SUCH_FILE
;
2729 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2730 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2733 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2734 return NT_STATUS_NO_SUCH_FILE
;
2737 if (dirtype
& 0xFF00) {
2738 /* These will never be set for POSIX. */
2739 return NT_STATUS_NO_SUCH_FILE
;
2744 return NT_STATUS_NO_SUCH_FILE
;
2747 /* Can't delete a directory. */
2748 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2749 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2754 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2755 return NT_STATUS_OBJECT_NAME_INVALID
;
2756 #endif /* JRATEST */
2758 /* On open checks the open itself will check the share mode, so
2759 don't do it here as we'll get it wrong. */
2761 status
= SMB_VFS_CREATE_FILE
2764 0, /* root_dir_fid */
2765 smb_fname
, /* fname */
2766 DELETE_ACCESS
, /* access_mask */
2767 FILE_SHARE_NONE
, /* share_access */
2768 FILE_OPEN
, /* create_disposition*/
2769 FILE_NON_DIRECTORY_FILE
, /* create_options */
2770 /* file_attributes */
2771 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2772 FILE_ATTRIBUTE_NORMAL
,
2773 0, /* oplock_request */
2775 0, /* allocation_size */
2776 0, /* private_flags */
2781 NULL
, NULL
); /* create context */
2783 if (!NT_STATUS_IS_OK(status
)) {
2784 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2785 nt_errstr(status
)));
2789 status
= can_set_delete_on_close(fsp
, fattr
);
2790 if (!NT_STATUS_IS_OK(status
)) {
2791 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2793 smb_fname_str_dbg(smb_fname
),
2794 nt_errstr(status
)));
2795 close_file(req
, fsp
, NORMAL_CLOSE
);
2799 /* The set is across all open files on this dev/inode pair. */
2800 if (!set_delete_on_close(fsp
, True
,
2801 conn
->session_info
->security_token
,
2802 conn
->session_info
->unix_token
)) {
2803 close_file(req
, fsp
, NORMAL_CLOSE
);
2804 return NT_STATUS_ACCESS_DENIED
;
2807 return close_file(req
, fsp
, NORMAL_CLOSE
);
2810 /****************************************************************************
2811 The guts of the unlink command, split out so it may be called by the NT SMB
2813 ****************************************************************************/
2815 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2816 uint32 dirtype
, struct smb_filename
*smb_fname
,
2819 char *fname_dir
= NULL
;
2820 char *fname_mask
= NULL
;
2822 NTSTATUS status
= NT_STATUS_OK
;
2823 TALLOC_CTX
*ctx
= talloc_tos();
2825 /* Split up the directory from the filename/mask. */
2826 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2827 &fname_dir
, &fname_mask
);
2828 if (!NT_STATUS_IS_OK(status
)) {
2833 * We should only check the mangled cache
2834 * here if unix_convert failed. This means
2835 * that the path in 'mask' doesn't exist
2836 * on the file system and so we need to look
2837 * for a possible mangle. This patch from
2838 * Tine Smukavec <valentin.smukavec@hermes.si>.
2841 if (!VALID_STAT(smb_fname
->st
) &&
2842 mangle_is_mangled(fname_mask
, conn
->params
)) {
2843 char *new_mask
= NULL
;
2844 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2845 &new_mask
, conn
->params
);
2847 TALLOC_FREE(fname_mask
);
2848 fname_mask
= new_mask
;
2855 * Only one file needs to be unlinked. Append the mask back
2856 * onto the directory.
2858 TALLOC_FREE(smb_fname
->base_name
);
2859 if (ISDOT(fname_dir
)) {
2860 /* Ensure we use canonical names on open. */
2861 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2865 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2870 if (!smb_fname
->base_name
) {
2871 status
= NT_STATUS_NO_MEMORY
;
2875 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2878 status
= check_name(conn
, smb_fname
->base_name
);
2879 if (!NT_STATUS_IS_OK(status
)) {
2883 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2884 if (!NT_STATUS_IS_OK(status
)) {
2890 struct smb_Dir
*dir_hnd
= NULL
;
2892 const char *dname
= NULL
;
2893 char *talloced
= NULL
;
2895 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2896 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2900 if (strequal(fname_mask
,"????????.???")) {
2901 TALLOC_FREE(fname_mask
);
2902 fname_mask
= talloc_strdup(ctx
, "*");
2904 status
= NT_STATUS_NO_MEMORY
;
2909 status
= check_name(conn
, fname_dir
);
2910 if (!NT_STATUS_IS_OK(status
)) {
2914 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2916 if (dir_hnd
== NULL
) {
2917 status
= map_nt_error_from_unix(errno
);
2921 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2922 the pattern matches against the long name, otherwise the short name
2923 We don't implement this yet XXXX
2926 status
= NT_STATUS_NO_SUCH_FILE
;
2928 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2929 &smb_fname
->st
, &talloced
))) {
2930 TALLOC_CTX
*frame
= talloc_stackframe();
2932 if (!is_visible_file(conn
, fname_dir
, dname
,
2933 &smb_fname
->st
, true)) {
2935 TALLOC_FREE(talloced
);
2939 /* Quick check for "." and ".." */
2940 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2942 TALLOC_FREE(talloced
);
2946 if(!mask_match(dname
, fname_mask
,
2947 conn
->case_sensitive
)) {
2949 TALLOC_FREE(talloced
);
2953 TALLOC_FREE(smb_fname
->base_name
);
2954 if (ISDOT(fname_dir
)) {
2955 /* Ensure we use canonical names on open. */
2956 smb_fname
->base_name
=
2957 talloc_asprintf(smb_fname
, "%s",
2960 smb_fname
->base_name
=
2961 talloc_asprintf(smb_fname
, "%s/%s",
2965 if (!smb_fname
->base_name
) {
2966 TALLOC_FREE(dir_hnd
);
2967 status
= NT_STATUS_NO_MEMORY
;
2969 TALLOC_FREE(talloced
);
2973 status
= check_name(conn
, smb_fname
->base_name
);
2974 if (!NT_STATUS_IS_OK(status
)) {
2975 TALLOC_FREE(dir_hnd
);
2977 TALLOC_FREE(talloced
);
2981 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2982 if (!NT_STATUS_IS_OK(status
)) {
2983 TALLOC_FREE(dir_hnd
);
2985 TALLOC_FREE(talloced
);
2990 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2991 smb_fname
->base_name
));
2994 TALLOC_FREE(talloced
);
2996 TALLOC_FREE(dir_hnd
);
2999 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3000 status
= map_nt_error_from_unix(errno
);
3004 TALLOC_FREE(fname_dir
);
3005 TALLOC_FREE(fname_mask
);
3009 /****************************************************************************
3011 ****************************************************************************/
3013 void reply_unlink(struct smb_request
*req
)
3015 connection_struct
*conn
= req
->conn
;
3017 struct smb_filename
*smb_fname
= NULL
;
3020 bool path_contains_wcard
= False
;
3021 TALLOC_CTX
*ctx
= talloc_tos();
3023 START_PROFILE(SMBunlink
);
3026 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3030 dirtype
= SVAL(req
->vwv
+0, 0);
3032 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3033 STR_TERMINATE
, &status
,
3034 &path_contains_wcard
);
3035 if (!NT_STATUS_IS_OK(status
)) {
3036 reply_nterror(req
, status
);
3040 status
= filename_convert(ctx
, conn
,
3041 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3043 UCF_COND_ALLOW_WCARD_LCOMP
,
3044 &path_contains_wcard
,
3046 if (!NT_STATUS_IS_OK(status
)) {
3047 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3048 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3049 ERRSRV
, ERRbadpath
);
3052 reply_nterror(req
, status
);
3056 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3058 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
3059 path_contains_wcard
);
3060 if (!NT_STATUS_IS_OK(status
)) {
3061 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3062 /* We have re-scheduled this call. */
3065 reply_nterror(req
, status
);
3069 reply_outbuf(req
, 0, 0);
3071 TALLOC_FREE(smb_fname
);
3072 END_PROFILE(SMBunlink
);
3076 /****************************************************************************
3078 ****************************************************************************/
3080 static void fail_readraw(void)
3082 const char *errstr
= talloc_asprintf(talloc_tos(),
3083 "FAIL ! reply_readbraw: socket write fail (%s)",
3088 exit_server_cleanly(errstr
);
3091 /****************************************************************************
3092 Fake (read/write) sendfile. Returns -1 on read or write fail.
3093 ****************************************************************************/
3095 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3096 off_t startpos
, size_t nread
)
3099 size_t tosend
= nread
;
3106 bufsize
= MIN(nread
, 65536);
3108 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3112 while (tosend
> 0) {
3116 cur_read
= MIN(tosend
, bufsize
);
3117 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3123 /* If we had a short read, fill with zeros. */
3124 if (ret
< cur_read
) {
3125 memset(buf
+ ret
, '\0', cur_read
- ret
);
3128 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3129 if (ret
!= cur_read
) {
3130 int saved_errno
= errno
;
3132 * Try and give an error message saying what
3135 DEBUG(0, ("write_data failed for client %s. "
3137 smbXsrv_connection_dbg(xconn
),
3138 strerror(saved_errno
)));
3140 errno
= saved_errno
;
3144 startpos
+= cur_read
;
3148 return (ssize_t
)nread
;
3151 /****************************************************************************
3152 Deal with the case of sendfile reading less bytes from the file than
3153 requested. Fill with zeros (all we can do). Returns 0 on success
3154 ****************************************************************************/
3156 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3162 #define SHORT_SEND_BUFSIZE 1024
3163 if (nread
< headersize
) {
3164 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3165 "header for file %s (%s). Terminating\n",
3166 fsp_str_dbg(fsp
), strerror(errno
)));
3170 nread
-= headersize
;
3172 if (nread
< smb_maxcnt
) {
3173 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3175 DEBUG(0,("sendfile_short_send: malloc failed "
3176 "for file %s (%s). Terminating\n",
3177 fsp_str_dbg(fsp
), strerror(errno
)));
3181 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3182 "with zeros !\n", fsp_str_dbg(fsp
)));
3184 while (nread
< smb_maxcnt
) {
3186 * We asked for the real file size and told sendfile
3187 * to not go beyond the end of the file. But it can
3188 * happen that in between our fstat call and the
3189 * sendfile call the file was truncated. This is very
3190 * bad because we have already announced the larger
3191 * number of bytes to the client.
3193 * The best we can do now is to send 0-bytes, just as
3194 * a read from a hole in a sparse file would do.
3196 * This should happen rarely enough that I don't care
3197 * about efficiency here :-)
3202 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3203 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3204 if (ret
!= to_write
) {
3205 int saved_errno
= errno
;
3207 * Try and give an error message saying what
3210 DEBUG(0, ("write_data failed for client %s. "
3212 smbXsrv_connection_dbg(xconn
),
3213 strerror(saved_errno
)));
3214 errno
= saved_errno
;
3225 /****************************************************************************
3226 Return a readbraw error (4 bytes of zero).
3227 ****************************************************************************/
3229 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3235 smbd_lock_socket(xconn
);
3236 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3237 int saved_errno
= errno
;
3239 * Try and give an error message saying what
3242 DEBUG(0, ("write_data failed for client %s. "
3244 smbXsrv_connection_dbg(xconn
),
3245 strerror(saved_errno
)));
3246 errno
= saved_errno
;
3250 smbd_unlock_socket(xconn
);
3253 /****************************************************************************
3254 Use sendfile in readbraw.
3255 ****************************************************************************/
3257 static void send_file_readbraw(connection_struct
*conn
,
3258 struct smb_request
*req
,
3264 struct smbXsrv_connection
*xconn
= req
->xconn
;
3265 char *outbuf
= NULL
;
3269 * We can only use sendfile on a non-chained packet
3270 * but we can use on a non-oplocked file. tridge proved this
3271 * on a train in Germany :-). JRA.
3272 * reply_readbraw has already checked the length.
3275 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3276 (fsp
->wcp
== NULL
) &&
3277 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3278 ssize_t sendfile_read
= -1;
3280 DATA_BLOB header_blob
;
3282 _smb_setlen(header
,nread
);
3283 header_blob
= data_blob_const(header
, 4);
3285 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3286 &header_blob
, startpos
,
3288 if (sendfile_read
== -1) {
3289 /* Returning ENOSYS means no data at all was sent.
3290 * Do this as a normal read. */
3291 if (errno
== ENOSYS
) {
3292 goto normal_readbraw
;
3296 * Special hack for broken Linux with no working sendfile. If we
3297 * return EINTR we sent the header but not the rest of the data.
3298 * Fake this up by doing read/write calls.
3300 if (errno
== EINTR
) {
3301 /* Ensure we don't do this again. */
3302 set_use_sendfile(SNUM(conn
), False
);
3303 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3305 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3306 DEBUG(0,("send_file_readbraw: "
3307 "fake_sendfile failed for "
3311 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3316 DEBUG(0,("send_file_readbraw: sendfile failed for "
3317 "file %s (%s). Terminating\n",
3318 fsp_str_dbg(fsp
), strerror(errno
)));
3319 exit_server_cleanly("send_file_readbraw sendfile failed");
3320 } else if (sendfile_read
== 0) {
3322 * Some sendfile implementations return 0 to indicate
3323 * that there was a short read, but nothing was
3324 * actually written to the socket. In this case,
3325 * fallback to the normal read path so the header gets
3326 * the correct byte count.
3328 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3329 "bytes falling back to the normal read: "
3330 "%s\n", fsp_str_dbg(fsp
)));
3331 goto normal_readbraw
;
3334 /* Deal with possible short send. */
3335 if (sendfile_read
!= 4+nread
) {
3336 ret
= sendfile_short_send(xconn
, fsp
,
3337 sendfile_read
, 4, nread
);
3347 outbuf
= talloc_array(NULL
, char, nread
+4);
3349 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3350 (unsigned)(nread
+4)));
3351 reply_readbraw_error(xconn
);
3356 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3357 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3366 _smb_setlen(outbuf
,ret
);
3367 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3368 int saved_errno
= errno
;
3370 * Try and give an error message saying what
3373 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3374 smbXsrv_connection_dbg(xconn
),
3375 strerror(saved_errno
)));
3376 errno
= saved_errno
;
3381 TALLOC_FREE(outbuf
);
3384 /****************************************************************************
3385 Reply to a readbraw (core+ protocol).
3386 ****************************************************************************/
3388 void reply_readbraw(struct smb_request
*req
)
3390 connection_struct
*conn
= req
->conn
;
3391 struct smbXsrv_connection
*xconn
= req
->xconn
;
3392 ssize_t maxcount
,mincount
;
3396 struct lock_struct lock
;
3399 START_PROFILE(SMBreadbraw
);
3401 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3402 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3403 "raw reads/writes are disallowed.");
3407 reply_readbraw_error(xconn
);
3408 END_PROFILE(SMBreadbraw
);
3412 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3413 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3414 "'async smb echo handler = yes'\n"));
3415 reply_readbraw_error(xconn
);
3416 END_PROFILE(SMBreadbraw
);
3421 * Special check if an oplock break has been issued
3422 * and the readraw request croses on the wire, we must
3423 * return a zero length response here.
3426 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3429 * We have to do a check_fsp by hand here, as
3430 * we must always return 4 zero bytes on error,
3434 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3435 req
->vuid
!= fsp
->vuid
||
3436 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3438 * fsp could be NULL here so use the value from the packet. JRA.
3440 DEBUG(3,("reply_readbraw: fnum %d not valid "
3442 (int)SVAL(req
->vwv
+0, 0)));
3443 reply_readbraw_error(xconn
);
3444 END_PROFILE(SMBreadbraw
);
3448 /* Do a "by hand" version of CHECK_READ. */
3449 if (!(fsp
->can_read
||
3450 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3451 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3452 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3453 (int)SVAL(req
->vwv
+0, 0)));
3454 reply_readbraw_error(xconn
);
3455 END_PROFILE(SMBreadbraw
);
3459 flush_write_cache(fsp
, SAMBA_READRAW_FLUSH
);
3461 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3462 if(req
->wct
== 10) {
3464 * This is a large offset (64 bit) read.
3467 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3470 DEBUG(0,("reply_readbraw: negative 64 bit "
3471 "readraw offset (%.0f) !\n",
3472 (double)startpos
));
3473 reply_readbraw_error(xconn
);
3474 END_PROFILE(SMBreadbraw
);
3479 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3480 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3482 /* ensure we don't overrun the packet size */
3483 maxcount
= MIN(65535,maxcount
);
3485 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3486 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3489 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3490 reply_readbraw_error(xconn
);
3491 END_PROFILE(SMBreadbraw
);
3495 if (fsp_stat(fsp
) == 0) {
3496 size
= fsp
->fsp_name
->st
.st_ex_size
;
3499 if (startpos
>= size
) {
3502 nread
= MIN(maxcount
,(size
- startpos
));
3505 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3506 if (nread
< mincount
)
3510 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3511 "min=%lu nread=%lu\n",
3512 fsp_fnum_dbg(fsp
), (double)startpos
,
3513 (unsigned long)maxcount
,
3514 (unsigned long)mincount
,
3515 (unsigned long)nread
) );
3517 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3519 DEBUG(5,("reply_readbraw finished\n"));
3521 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3523 END_PROFILE(SMBreadbraw
);
3528 #define DBGC_CLASS DBGC_LOCKING
3530 /****************************************************************************
3531 Reply to a lockread (core+ protocol).
3532 ****************************************************************************/
3534 void reply_lockread(struct smb_request
*req
)
3536 connection_struct
*conn
= req
->conn
;
3544 struct byte_range_lock
*br_lck
= NULL
;
3546 struct smbXsrv_connection
*xconn
= req
->xconn
;
3548 START_PROFILE(SMBlockread
);
3551 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3552 END_PROFILE(SMBlockread
);
3556 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3558 if (!check_fsp(conn
, req
, fsp
)) {
3559 END_PROFILE(SMBlockread
);
3563 if (!CHECK_READ(fsp
,req
)) {
3564 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3565 END_PROFILE(SMBlockread
);
3569 numtoread
= SVAL(req
->vwv
+1, 0);
3570 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3573 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3574 * protocol request that predates the read/write lock concept.
3575 * Thus instead of asking for a read lock here we need to ask
3576 * for a write lock. JRA.
3577 * Note that the requested lock size is unaffected by max_send.
3580 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3582 (uint64_t)req
->smbpid
,
3583 (uint64_t)numtoread
,
3587 False
, /* Non-blocking lock. */
3590 TALLOC_FREE(br_lck
);
3592 if (NT_STATUS_V(status
)) {
3593 reply_nterror(req
, status
);
3594 END_PROFILE(SMBlockread
);
3599 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3601 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3603 if (numtoread
> maxtoread
) {
3604 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3605 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3606 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3607 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3608 numtoread
= maxtoread
;
3611 reply_outbuf(req
, 5, numtoread
+ 3);
3613 data
= smb_buf(req
->outbuf
) + 3;
3615 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3618 reply_nterror(req
, map_nt_error_from_unix(errno
));
3619 END_PROFILE(SMBlockread
);
3623 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3625 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3626 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3627 p
= smb_buf(req
->outbuf
);
3628 SCVAL(p
,0,0); /* pad byte. */
3631 DEBUG(3,("lockread %s num=%d nread=%d\n",
3632 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3634 END_PROFILE(SMBlockread
);
3639 #define DBGC_CLASS DBGC_ALL
3641 /****************************************************************************
3643 ****************************************************************************/
3645 void reply_read(struct smb_request
*req
)
3647 connection_struct
*conn
= req
->conn
;
3654 struct lock_struct lock
;
3655 struct smbXsrv_connection
*xconn
= req
->xconn
;
3657 START_PROFILE(SMBread
);
3660 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3661 END_PROFILE(SMBread
);
3665 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3667 if (!check_fsp(conn
, req
, fsp
)) {
3668 END_PROFILE(SMBread
);
3672 if (!CHECK_READ(fsp
,req
)) {
3673 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3674 END_PROFILE(SMBread
);
3678 numtoread
= SVAL(req
->vwv
+1, 0);
3679 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3682 * The requested read size cannot be greater than max_send. JRA.
3684 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3686 if (numtoread
> maxtoread
) {
3687 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3688 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3689 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3690 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3691 numtoread
= maxtoread
;
3694 reply_outbuf(req
, 5, numtoread
+3);
3696 data
= smb_buf(req
->outbuf
) + 3;
3698 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3699 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3702 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3703 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3704 END_PROFILE(SMBread
);
3709 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3712 reply_nterror(req
, map_nt_error_from_unix(errno
));
3716 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3718 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3719 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3720 SCVAL(smb_buf(req
->outbuf
),0,1);
3721 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3723 DEBUG(3, ("read %s num=%d nread=%d\n",
3724 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3727 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3729 END_PROFILE(SMBread
);
3733 /****************************************************************************
3735 ****************************************************************************/
3737 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3742 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3745 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3747 SCVAL(outbuf
,smb_vwv0
,0xFF);
3748 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3749 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3750 SSVAL(outbuf
,smb_vwv6
,
3751 (smb_wct
- 4) /* offset from smb header to wct */
3752 + 1 /* the wct field */
3753 + 12 * sizeof(uint16_t) /* vwv */
3754 + 2 /* the buflen field */
3755 + 1); /* padding byte */
3756 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3757 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3758 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3759 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3760 _smb_setlen_large(outbuf
,
3761 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3765 /****************************************************************************
3766 Reply to a read and X - possibly using sendfile.
3767 ****************************************************************************/
3769 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3770 files_struct
*fsp
, off_t startpos
,
3773 struct smbXsrv_connection
*xconn
= req
->xconn
;
3775 struct lock_struct lock
;
3776 int saved_errno
= 0;
3778 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3779 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3782 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3783 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3788 * We can only use sendfile on a non-chained packet
3789 * but we can use on a non-oplocked file. tridge proved this
3790 * on a train in Germany :-). JRA.
3793 if (!req_is_in_chain(req
) &&
3795 (fsp
->base_fsp
== NULL
) &&
3796 (fsp
->wcp
== NULL
) &&
3797 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3798 uint8 headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
3801 if(fsp_stat(fsp
) == -1) {
3802 reply_nterror(req
, map_nt_error_from_unix(errno
));
3806 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3807 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3808 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3810 * We already know that we would do a short read, so don't
3811 * try the sendfile() path.
3813 goto nosendfile_read
;
3817 * Set up the packet header before send. We
3818 * assume here the sendfile will work (get the
3819 * correct amount of data).
3822 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3824 construct_reply_common_req(req
, (char *)headerbuf
);
3825 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3827 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
3828 startpos
, smb_maxcnt
);
3830 saved_errno
= errno
;
3832 /* Returning ENOSYS means no data at all was sent.
3833 Do this as a normal read. */
3834 if (errno
== ENOSYS
) {
3839 * Special hack for broken Linux with no working sendfile. If we
3840 * return EINTR we sent the header but not the rest of the data.
3841 * Fake this up by doing read/write calls.
3844 if (errno
== EINTR
) {
3845 /* Ensure we don't do this again. */
3846 set_use_sendfile(SNUM(conn
), False
);
3847 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3848 nread
= fake_sendfile(xconn
, fsp
, startpos
,
3851 saved_errno
= errno
;
3852 DEBUG(0,("send_file_readX: "
3853 "fake_sendfile failed for "
3854 "file %s (%s) for client %s. "
3857 smbXsrv_connection_dbg(xconn
),
3858 strerror(saved_errno
)));
3859 errno
= saved_errno
;
3860 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3862 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3863 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3864 /* No outbuf here means successful sendfile. */
3868 DEBUG(0,("send_file_readX: sendfile failed for file "
3869 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3871 exit_server_cleanly("send_file_readX sendfile failed");
3872 } else if (nread
== 0) {
3874 * Some sendfile implementations return 0 to indicate
3875 * that there was a short read, but nothing was
3876 * actually written to the socket. In this case,
3877 * fallback to the normal read path so the header gets
3878 * the correct byte count.
3880 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3881 "falling back to the normal read: %s\n",
3886 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3887 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3889 /* Deal with possible short send. */
3890 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3893 ret
= sendfile_short_send(xconn
, fsp
, nread
,
3894 sizeof(headerbuf
), smb_maxcnt
);
3897 r
= "send_file_readX: sendfile_short_send failed";
3898 DEBUG(0,("%s for file %s (%s).\n",
3899 r
, fsp_str_dbg(fsp
), strerror(errno
)));
3900 exit_server_cleanly(r
);
3903 /* No outbuf here means successful sendfile. */
3904 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3905 SMB_PERFCOUNT_END(&req
->pcd
);
3911 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3912 uint8 headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
3915 construct_reply_common_req(req
, (char *)headerbuf
);
3916 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3918 /* Send out the header. */
3919 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
3921 if (ret
!= sizeof(headerbuf
)) {
3922 saved_errno
= errno
;
3924 * Try and give an error message saying what
3927 DEBUG(0,("send_file_readX: write_data failed for file "
3928 "%s (%s) for client %s. Terminating\n",
3930 smbXsrv_connection_dbg(xconn
),
3931 strerror(saved_errno
)));
3932 errno
= saved_errno
;
3933 exit_server_cleanly("send_file_readX sendfile failed");
3935 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
3937 saved_errno
= errno
;
3938 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3939 "%s (%s) for client %s. Terminating\n",
3941 smbXsrv_connection_dbg(xconn
),
3942 strerror(saved_errno
)));
3943 errno
= saved_errno
;
3944 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3951 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
3952 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
3953 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
3955 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
3956 startpos
, smb_maxcnt
);
3957 saved_errno
= errno
;
3959 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3962 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3966 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3968 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3969 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3973 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3974 TALLOC_FREE(req
->outbuf
);
3978 /****************************************************************************
3979 Work out how much space we have for a read return.
3980 ****************************************************************************/
3982 static size_t calc_max_read_pdu(const struct smb_request
*req
)
3984 struct smbXsrv_connection
*xconn
= req
->xconn
;
3986 if (xconn
->protocol
< PROTOCOL_NT1
) {
3987 return xconn
->smb1
.sessions
.max_send
;
3990 if (!lp_large_readwrite()) {
3991 return xconn
->smb1
.sessions
.max_send
;
3994 if (req_is_in_chain(req
)) {
3995 return xconn
->smb1
.sessions
.max_send
;
3998 if (req
->encrypted
) {
4000 * Don't take encrypted traffic up to the
4001 * limit. There are padding considerations
4002 * that make that tricky.
4004 return xconn
->smb1
.sessions
.max_send
;
4007 if (srv_is_signing_active(xconn
)) {
4011 if (!lp_unix_extensions()) {
4016 * We can do ultra-large POSIX reads.
4021 /****************************************************************************
4022 Calculate how big a read can be. Copes with all clients. It's always
4023 safe to return a short read - Windows does this.
4024 ****************************************************************************/
4026 static size_t calc_read_size(const struct smb_request
*req
,
4030 struct smbXsrv_connection
*xconn
= req
->xconn
;
4031 size_t max_pdu
= calc_max_read_pdu(req
);
4032 size_t total_size
= 0;
4033 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4034 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4037 * Windows explicitly ignores upper size of 0xFFFF.
4038 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4039 * We must do the same as these will never fit even in
4040 * an extended size NetBIOS packet.
4042 if (upper_size
== 0xFFFF) {
4046 if (xconn
->protocol
< PROTOCOL_NT1
) {
4050 total_size
= ((upper_size
<<16) | lower_size
);
4053 * LARGE_READX test shows it's always safe to return
4054 * a short read. Windows does so.
4056 return MIN(total_size
, max_len
);
4059 /****************************************************************************
4060 Reply to a read and X.
4061 ****************************************************************************/
4063 void reply_read_and_X(struct smb_request
*req
)
4065 connection_struct
*conn
= req
->conn
;
4070 bool big_readX
= False
;
4072 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4075 START_PROFILE(SMBreadX
);
4077 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4078 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4082 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4083 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4084 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4086 /* If it's an IPC, pass off the pipe handler. */
4088 reply_pipe_read_and_X(req
);
4089 END_PROFILE(SMBreadX
);
4093 if (!check_fsp(conn
, req
, fsp
)) {
4094 END_PROFILE(SMBreadX
);
4098 if (!CHECK_READ(fsp
,req
)) {
4099 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4100 END_PROFILE(SMBreadX
);
4104 upper_size
= SVAL(req
->vwv
+7, 0);
4105 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4106 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4108 * This is a heuristic to avoid keeping large
4109 * outgoing buffers around over long-lived aio
4115 if (req
->wct
== 12) {
4117 * This is a large offset (64 bit) read.
4119 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4124 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4129 if (NT_STATUS_IS_OK(status
)) {
4130 /* Read scheduled - we're done. */
4133 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4134 /* Real error - report to client. */
4135 END_PROFILE(SMBreadX
);
4136 reply_nterror(req
, status
);
4139 /* NT_STATUS_RETRY - fall back to sync read. */
4142 smbd_lock_socket(req
->xconn
);
4143 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4144 smbd_unlock_socket(req
->xconn
);
4147 END_PROFILE(SMBreadX
);
4151 /****************************************************************************
4152 Error replies to writebraw must have smb_wct == 1. Fix this up.
4153 ****************************************************************************/
4155 void error_to_writebrawerr(struct smb_request
*req
)
4157 uint8
*old_outbuf
= req
->outbuf
;
4159 reply_outbuf(req
, 1, 0);
4161 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4162 TALLOC_FREE(old_outbuf
);
4165 /****************************************************************************
4166 Read 4 bytes of a smb packet and return the smb length of the packet.
4167 Store the result in the buffer. This version of the function will
4168 never return a session keepalive (length of zero).
4169 Timeout is in milliseconds.
4170 ****************************************************************************/
4172 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4175 uint8_t msgtype
= NBSSkeepalive
;
4177 while (msgtype
== NBSSkeepalive
) {
4180 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4182 if (!NT_STATUS_IS_OK(status
)) {
4183 char addr
[INET6_ADDRSTRLEN
];
4184 /* Try and give an error message
4185 * saying what client failed. */
4186 DEBUG(0, ("read_fd_with_timeout failed for "
4187 "client %s read error = %s.\n",
4188 get_peer_addr(fd
,addr
,sizeof(addr
)),
4189 nt_errstr(status
)));
4193 msgtype
= CVAL(inbuf
, 0);
4196 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4197 (unsigned long)len
));
4199 return NT_STATUS_OK
;
4202 /****************************************************************************
4203 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4204 ****************************************************************************/
4206 void reply_writebraw(struct smb_request
*req
)
4208 connection_struct
*conn
= req
->conn
;
4209 struct smbXsrv_connection
*xconn
= req
->xconn
;
4212 ssize_t total_written
=0;
4213 size_t numtowrite
=0;
4216 const char *data
=NULL
;
4219 struct lock_struct lock
;
4222 START_PROFILE(SMBwritebraw
);
4225 * If we ever reply with an error, it must have the SMB command
4226 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4229 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4231 if (srv_is_signing_active(xconn
)) {
4232 END_PROFILE(SMBwritebraw
);
4233 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4234 "raw reads/writes are disallowed.");
4237 if (req
->wct
< 12) {
4238 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4239 error_to_writebrawerr(req
);
4240 END_PROFILE(SMBwritebraw
);
4244 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4245 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4246 "'async smb echo handler = yes'\n"));
4247 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4248 error_to_writebrawerr(req
);
4249 END_PROFILE(SMBwritebraw
);
4253 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4254 if (!check_fsp(conn
, req
, fsp
)) {
4255 error_to_writebrawerr(req
);
4256 END_PROFILE(SMBwritebraw
);
4260 if (!CHECK_WRITE(fsp
)) {
4261 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4262 error_to_writebrawerr(req
);
4263 END_PROFILE(SMBwritebraw
);
4267 tcount
= IVAL(req
->vwv
+1, 0);
4268 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4269 write_through
= BITSETW(req
->vwv
+7,0);
4271 /* We have to deal with slightly different formats depending
4272 on whether we are using the core+ or lanman1.0 protocol */
4274 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4275 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4276 data
= smb_buf_const(req
->inbuf
);
4278 numtowrite
= SVAL(req
->vwv
+10, 0);
4279 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4282 /* Ensure we don't write bytes past the end of this packet. */
4283 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4284 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4285 error_to_writebrawerr(req
);
4286 END_PROFILE(SMBwritebraw
);
4290 if (!fsp
->print_file
) {
4291 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4292 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4295 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4296 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4297 error_to_writebrawerr(req
);
4298 END_PROFILE(SMBwritebraw
);
4304 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4307 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4308 "wrote=%d sync=%d\n",
4309 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4310 (int)nwritten
, (int)write_through
));
4312 if (nwritten
< (ssize_t
)numtowrite
) {
4313 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4314 error_to_writebrawerr(req
);
4318 total_written
= nwritten
;
4320 /* Allocate a buffer of 64k + length. */
4321 buf
= talloc_array(NULL
, char, 65540);
4323 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4324 error_to_writebrawerr(req
);
4328 /* Return a SMBwritebraw message to the redirector to tell
4329 * it to send more bytes */
4331 memcpy(buf
, req
->inbuf
, smb_size
);
4332 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4333 SCVAL(buf
,smb_com
,SMBwritebraw
);
4334 SSVALS(buf
,smb_vwv0
,0xFFFF);
4336 if (!srv_send_smb(req
->xconn
,
4338 false, 0, /* no signing */
4339 IS_CONN_ENCRYPTED(conn
),
4341 exit_server_cleanly("reply_writebraw: srv_send_smb "
4345 /* Now read the raw data into the buffer and write it */
4346 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4348 if (!NT_STATUS_IS_OK(status
)) {
4349 exit_server_cleanly("secondary writebraw failed");
4352 /* Set up outbuf to return the correct size */
4353 reply_outbuf(req
, 1, 0);
4355 if (numtowrite
!= 0) {
4357 if (numtowrite
> 0xFFFF) {
4358 DEBUG(0,("reply_writebraw: Oversize secondary write "
4359 "raw requested (%u). Terminating\n",
4360 (unsigned int)numtowrite
));
4361 exit_server_cleanly("secondary writebraw failed");
4364 if (tcount
> nwritten
+numtowrite
) {
4365 DEBUG(3,("reply_writebraw: Client overestimated the "
4367 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4370 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4373 if (!NT_STATUS_IS_OK(status
)) {
4374 /* Try and give an error message
4375 * saying what client failed. */
4376 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4377 "raw read failed (%s) for client %s. "
4378 "Terminating\n", nt_errstr(status
),
4379 smbXsrv_connection_dbg(xconn
)));
4380 exit_server_cleanly("secondary writebraw failed");
4383 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4384 if (nwritten
== -1) {
4386 reply_nterror(req
, map_nt_error_from_unix(errno
));
4387 error_to_writebrawerr(req
);
4391 if (nwritten
< (ssize_t
)numtowrite
) {
4392 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4393 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4397 total_written
+= nwritten
;
4402 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4404 status
= sync_file(conn
, fsp
, write_through
);
4405 if (!NT_STATUS_IS_OK(status
)) {
4406 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4407 fsp_str_dbg(fsp
), nt_errstr(status
)));
4408 reply_nterror(req
, status
);
4409 error_to_writebrawerr(req
);
4413 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4415 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4416 (int)total_written
));
4418 if (!fsp
->print_file
) {
4419 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4422 /* We won't return a status if write through is not selected - this
4423 * follows what WfWg does */
4424 END_PROFILE(SMBwritebraw
);
4426 if (!write_through
&& total_written
==tcount
) {
4428 #if RABBIT_PELLET_FIX
4430 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4431 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4434 if (!send_keepalive(xconn
->transport
.sock
)) {
4435 exit_server_cleanly("reply_writebraw: send of "
4436 "keepalive failed");
4439 TALLOC_FREE(req
->outbuf
);
4444 if (!fsp
->print_file
) {
4445 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4448 END_PROFILE(SMBwritebraw
);
4453 #define DBGC_CLASS DBGC_LOCKING
4455 /****************************************************************************
4456 Reply to a writeunlock (core+).
4457 ****************************************************************************/
4459 void reply_writeunlock(struct smb_request
*req
)
4461 connection_struct
*conn
= req
->conn
;
4462 ssize_t nwritten
= -1;
4466 NTSTATUS status
= NT_STATUS_OK
;
4468 struct lock_struct lock
;
4469 int saved_errno
= 0;
4471 START_PROFILE(SMBwriteunlock
);
4474 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4475 END_PROFILE(SMBwriteunlock
);
4479 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4481 if (!check_fsp(conn
, req
, fsp
)) {
4482 END_PROFILE(SMBwriteunlock
);
4486 if (!CHECK_WRITE(fsp
)) {
4487 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4488 END_PROFILE(SMBwriteunlock
);
4492 numtowrite
= SVAL(req
->vwv
+1, 0);
4493 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4494 data
= (const char *)req
->buf
+ 3;
4496 if (!fsp
->print_file
&& numtowrite
> 0) {
4497 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4498 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4501 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4502 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4503 END_PROFILE(SMBwriteunlock
);
4508 /* The special X/Open SMB protocol handling of
4509 zero length writes is *NOT* done for
4511 if(numtowrite
== 0) {
4514 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4515 saved_errno
= errno
;
4518 status
= sync_file(conn
, fsp
, False
/* write through */);
4519 if (!NT_STATUS_IS_OK(status
)) {
4520 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4521 fsp_str_dbg(fsp
), nt_errstr(status
)));
4522 reply_nterror(req
, status
);
4527 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4531 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4532 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4536 if (numtowrite
&& !fsp
->print_file
) {
4537 status
= do_unlock(req
->sconn
->msg_ctx
,
4539 (uint64_t)req
->smbpid
,
4540 (uint64_t)numtowrite
,
4544 if (NT_STATUS_V(status
)) {
4545 reply_nterror(req
, status
);
4550 reply_outbuf(req
, 1, 0);
4552 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4554 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4555 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4558 if (numtowrite
&& !fsp
->print_file
) {
4559 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4562 END_PROFILE(SMBwriteunlock
);
4567 #define DBGC_CLASS DBGC_ALL
4569 /****************************************************************************
4571 ****************************************************************************/
4573 void reply_write(struct smb_request
*req
)
4575 connection_struct
*conn
= req
->conn
;
4577 ssize_t nwritten
= -1;
4581 struct lock_struct lock
;
4583 int saved_errno
= 0;
4585 START_PROFILE(SMBwrite
);
4588 END_PROFILE(SMBwrite
);
4589 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4593 /* If it's an IPC, pass off the pipe handler. */
4595 reply_pipe_write(req
);
4596 END_PROFILE(SMBwrite
);
4600 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4602 if (!check_fsp(conn
, req
, fsp
)) {
4603 END_PROFILE(SMBwrite
);
4607 if (!CHECK_WRITE(fsp
)) {
4608 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4609 END_PROFILE(SMBwrite
);
4613 numtowrite
= SVAL(req
->vwv
+1, 0);
4614 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4615 data
= (const char *)req
->buf
+ 3;
4617 if (!fsp
->print_file
) {
4618 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4619 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4622 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4623 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4624 END_PROFILE(SMBwrite
);
4630 * X/Open SMB protocol says that if smb_vwv1 is
4631 * zero then the file size should be extended or
4632 * truncated to the size given in smb_vwv[2-3].
4635 if(numtowrite
== 0) {
4637 * This is actually an allocate call, and set EOF. JRA.
4639 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4641 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4644 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4646 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4649 trigger_write_time_update_immediate(fsp
);
4651 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4654 status
= sync_file(conn
, fsp
, False
);
4655 if (!NT_STATUS_IS_OK(status
)) {
4656 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4657 fsp_str_dbg(fsp
), nt_errstr(status
)));
4658 reply_nterror(req
, status
);
4663 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4667 if((nwritten
== 0) && (numtowrite
!= 0)) {
4668 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4672 reply_outbuf(req
, 1, 0);
4674 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4676 if (nwritten
< (ssize_t
)numtowrite
) {
4677 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4678 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4681 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4684 if (!fsp
->print_file
) {
4685 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4688 END_PROFILE(SMBwrite
);
4692 /****************************************************************************
4693 Ensure a buffer is a valid writeX for recvfile purposes.
4694 ****************************************************************************/
4696 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4697 (2*14) + /* word count (including bcc) */ \
4700 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4701 const uint8_t *inbuf
)
4704 unsigned int doff
= 0;
4705 size_t len
= smb_len_large(inbuf
);
4707 struct smbXsrv_open
*op
= NULL
;
4708 struct files_struct
*fsp
= NULL
;
4711 if (is_encrypted_packet(inbuf
)) {
4712 /* Can't do this on encrypted
4717 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4721 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4722 CVAL(inbuf
,smb_wct
) != 14) {
4723 DEBUG(10,("is_valid_writeX_buffer: chained or "
4724 "invalid word length.\n"));
4728 fnum
= SVAL(inbuf
, smb_vwv2
);
4729 status
= smb1srv_open_lookup(xconn
,
4733 if (!NT_STATUS_IS_OK(status
)) {
4734 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4739 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4742 if (fsp
->conn
== NULL
) {
4743 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4747 if (IS_IPC(fsp
->conn
)) {
4748 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4751 if (IS_PRINT(fsp
->conn
)) {
4752 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4755 doff
= SVAL(inbuf
,smb_vwv11
);
4757 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4759 if (len
> doff
&& len
- doff
> 0xFFFF) {
4760 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4763 if (numtowrite
== 0) {
4764 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4768 /* Ensure the sizes match up. */
4769 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4770 /* no pad byte...old smbclient :-( */
4771 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4773 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4777 if (len
- doff
!= numtowrite
) {
4778 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4779 "len = %u, doff = %u, numtowrite = %u\n",
4782 (unsigned int)numtowrite
));
4786 DEBUG(10,("is_valid_writeX_buffer: true "
4787 "len = %u, doff = %u, numtowrite = %u\n",
4790 (unsigned int)numtowrite
));
4795 /****************************************************************************
4796 Reply to a write and X.
4797 ****************************************************************************/
4799 void reply_write_and_X(struct smb_request
*req
)
4801 connection_struct
*conn
= req
->conn
;
4802 struct smbXsrv_connection
*xconn
= req
->xconn
;
4804 struct lock_struct lock
;
4809 unsigned int smb_doff
;
4810 unsigned int smblen
;
4813 int saved_errno
= 0;
4815 START_PROFILE(SMBwriteX
);
4817 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4818 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4822 numtowrite
= SVAL(req
->vwv
+10, 0);
4823 smb_doff
= SVAL(req
->vwv
+11, 0);
4824 smblen
= smb_len(req
->inbuf
);
4826 if (req
->unread_bytes
> 0xFFFF ||
4827 (smblen
> smb_doff
&&
4828 smblen
- smb_doff
> 0xFFFF)) {
4829 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4832 if (req
->unread_bytes
) {
4833 /* Can't do a recvfile write on IPC$ */
4835 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4838 if (numtowrite
!= req
->unread_bytes
) {
4839 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4843 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4844 smb_doff
+ numtowrite
> smblen
) {
4845 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4850 /* If it's an IPC, pass off the pipe handler. */
4852 if (req
->unread_bytes
) {
4853 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4856 reply_pipe_write_and_X(req
);
4860 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4861 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4862 write_through
= BITSETW(req
->vwv
+7,0);
4864 if (!check_fsp(conn
, req
, fsp
)) {
4868 if (!CHECK_WRITE(fsp
)) {
4869 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4873 data
= smb_base(req
->inbuf
) + smb_doff
;
4875 if(req
->wct
== 14) {
4877 * This is a large offset (64 bit) write.
4879 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
4883 /* X/Open SMB protocol says that, unlike SMBwrite
4884 if the length is zero then NO truncation is
4885 done, just a write of zero. To truncate a file,
4888 if(numtowrite
== 0) {
4891 if (req
->unread_bytes
== 0) {
4892 status
= schedule_aio_write_and_X(conn
,
4899 if (NT_STATUS_IS_OK(status
)) {
4900 /* write scheduled - we're done. */
4903 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4904 /* Real error - report to client. */
4905 reply_nterror(req
, status
);
4908 /* NT_STATUS_RETRY - fall through to sync write. */
4911 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4912 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4915 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4916 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4920 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4921 saved_errno
= errno
;
4923 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4927 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4931 if((nwritten
== 0) && (numtowrite
!= 0)) {
4932 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4936 reply_outbuf(req
, 6, 0);
4937 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4938 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4939 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4940 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4942 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4943 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4945 status
= sync_file(conn
, fsp
, write_through
);
4946 if (!NT_STATUS_IS_OK(status
)) {
4947 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4948 fsp_str_dbg(fsp
), nt_errstr(status
)));
4949 reply_nterror(req
, status
);
4953 END_PROFILE(SMBwriteX
);
4957 if (req
->unread_bytes
) {
4958 /* writeX failed. drain socket. */
4959 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
4960 req
->unread_bytes
) {
4961 smb_panic("failed to drain pending bytes");
4963 req
->unread_bytes
= 0;
4966 END_PROFILE(SMBwriteX
);
4970 /****************************************************************************
4972 ****************************************************************************/
4974 void reply_lseek(struct smb_request
*req
)
4976 connection_struct
*conn
= req
->conn
;
4982 START_PROFILE(SMBlseek
);
4985 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4986 END_PROFILE(SMBlseek
);
4990 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4992 if (!check_fsp(conn
, req
, fsp
)) {
4996 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
4998 mode
= SVAL(req
->vwv
+1, 0) & 3;
4999 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5000 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5009 res
= fsp
->fh
->pos
+ startpos
;
5020 if (umode
== SEEK_END
) {
5021 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5022 if(errno
== EINVAL
) {
5023 off_t current_pos
= startpos
;
5025 if(fsp_stat(fsp
) == -1) {
5027 map_nt_error_from_unix(errno
));
5028 END_PROFILE(SMBlseek
);
5032 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5034 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5039 reply_nterror(req
, map_nt_error_from_unix(errno
));
5040 END_PROFILE(SMBlseek
);
5047 reply_outbuf(req
, 2, 0);
5048 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5050 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5051 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5053 END_PROFILE(SMBlseek
);
5057 /****************************************************************************
5059 ****************************************************************************/
5061 void reply_flush(struct smb_request
*req
)
5063 connection_struct
*conn
= req
->conn
;
5067 START_PROFILE(SMBflush
);
5070 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5074 fnum
= SVAL(req
->vwv
+0, 0);
5075 fsp
= file_fsp(req
, fnum
);
5077 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5082 file_sync_all(conn
);
5084 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5085 if (!NT_STATUS_IS_OK(status
)) {
5086 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5087 fsp_str_dbg(fsp
), nt_errstr(status
)));
5088 reply_nterror(req
, status
);
5089 END_PROFILE(SMBflush
);
5094 reply_outbuf(req
, 0, 0);
5096 DEBUG(3,("flush\n"));
5097 END_PROFILE(SMBflush
);
5101 /****************************************************************************
5103 conn POINTER CAN BE NULL HERE !
5104 ****************************************************************************/
5106 void reply_exit(struct smb_request
*req
)
5108 START_PROFILE(SMBexit
);
5110 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5112 reply_outbuf(req
, 0, 0);
5114 DEBUG(3,("exit\n"));
5116 END_PROFILE(SMBexit
);
5120 struct reply_close_state
{
5122 struct smb_request
*smbreq
;
5125 static void do_smb1_close(struct tevent_req
*req
);
5127 void reply_close(struct smb_request
*req
)
5129 connection_struct
*conn
= req
->conn
;
5130 NTSTATUS status
= NT_STATUS_OK
;
5131 files_struct
*fsp
= NULL
;
5132 START_PROFILE(SMBclose
);
5135 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5136 END_PROFILE(SMBclose
);
5140 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5143 * We can only use check_fsp if we know it's not a directory.
5146 if (!check_fsp_open(conn
, req
, fsp
)) {
5147 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5148 END_PROFILE(SMBclose
);
5152 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5153 fsp
->is_directory
? "directory" : "file",
5154 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5155 conn
->num_files_open
));
5157 if (!fsp
->is_directory
) {
5161 * Take care of any time sent in the close.
5164 t
= srv_make_unix_date3(req
->vwv
+1);
5165 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5168 if (fsp
->num_aio_requests
!= 0) {
5170 struct reply_close_state
*state
;
5172 DEBUG(10, ("closing with aio %u requests pending\n",
5173 fsp
->num_aio_requests
));
5176 * We depend on the aio_extra destructor to take care of this
5177 * close request once fsp->num_aio_request drops to 0.
5180 fsp
->deferred_close
= tevent_wait_send(
5181 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5182 if (fsp
->deferred_close
== NULL
) {
5183 status
= NT_STATUS_NO_MEMORY
;
5187 state
= talloc(fsp
, struct reply_close_state
);
5188 if (state
== NULL
) {
5189 TALLOC_FREE(fsp
->deferred_close
);
5190 status
= NT_STATUS_NO_MEMORY
;
5194 state
->smbreq
= talloc_move(fsp
, &req
);
5195 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5197 END_PROFILE(SMBclose
);
5202 * close_file() returns the unix errno if an error was detected on
5203 * close - normally this is due to a disk full error. If not then it
5204 * was probably an I/O error.
5207 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5209 if (!NT_STATUS_IS_OK(status
)) {
5210 reply_nterror(req
, status
);
5211 END_PROFILE(SMBclose
);
5215 reply_outbuf(req
, 0, 0);
5216 END_PROFILE(SMBclose
);
5220 static void do_smb1_close(struct tevent_req
*req
)
5222 struct reply_close_state
*state
= tevent_req_callback_data(
5223 req
, struct reply_close_state
);
5224 struct smb_request
*smbreq
;
5228 ret
= tevent_wait_recv(req
);
5231 DEBUG(10, ("tevent_wait_recv returned %s\n",
5234 * Continue anyway, this should never happen
5239 * fsp->smb2_close_request right now is a talloc grandchild of
5240 * fsp. When we close_file(fsp), it would go with it. No chance to
5243 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5245 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5246 if (NT_STATUS_IS_OK(status
)) {
5247 reply_outbuf(smbreq
, 0, 0);
5249 reply_nterror(smbreq
, status
);
5251 if (!srv_send_smb(smbreq
->xconn
,
5252 (char *)smbreq
->outbuf
,
5255 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5257 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5260 TALLOC_FREE(smbreq
);
5263 /****************************************************************************
5264 Reply to a writeclose (Core+ protocol).
5265 ****************************************************************************/
5267 void reply_writeclose(struct smb_request
*req
)
5269 connection_struct
*conn
= req
->conn
;
5271 ssize_t nwritten
= -1;
5272 NTSTATUS close_status
= NT_STATUS_OK
;
5275 struct timespec mtime
;
5277 struct lock_struct lock
;
5279 START_PROFILE(SMBwriteclose
);
5282 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5283 END_PROFILE(SMBwriteclose
);
5287 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5289 if (!check_fsp(conn
, req
, fsp
)) {
5290 END_PROFILE(SMBwriteclose
);
5293 if (!CHECK_WRITE(fsp
)) {
5294 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5295 END_PROFILE(SMBwriteclose
);
5299 numtowrite
= SVAL(req
->vwv
+1, 0);
5300 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5301 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5302 data
= (const char *)req
->buf
+ 1;
5304 if (fsp
->print_file
== NULL
) {
5305 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5306 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5309 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5310 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5311 END_PROFILE(SMBwriteclose
);
5316 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5318 if (fsp
->print_file
== NULL
) {
5319 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5322 set_close_write_time(fsp
, mtime
);
5325 * More insanity. W2K only closes the file if writelen > 0.
5329 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5330 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5331 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5334 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5335 "file %s\n", fsp_str_dbg(fsp
)));
5336 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5340 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5341 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5345 if(!NT_STATUS_IS_OK(close_status
)) {
5346 reply_nterror(req
, close_status
);
5350 reply_outbuf(req
, 1, 0);
5352 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5356 END_PROFILE(SMBwriteclose
);
5361 #define DBGC_CLASS DBGC_LOCKING
5363 /****************************************************************************
5365 ****************************************************************************/
5367 void reply_lock(struct smb_request
*req
)
5369 connection_struct
*conn
= req
->conn
;
5370 uint64_t count
,offset
;
5373 struct byte_range_lock
*br_lck
= NULL
;
5375 START_PROFILE(SMBlock
);
5378 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5379 END_PROFILE(SMBlock
);
5383 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5385 if (!check_fsp(conn
, req
, fsp
)) {
5386 END_PROFILE(SMBlock
);
5390 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5391 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5393 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5394 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5396 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5398 (uint64_t)req
->smbpid
,
5403 False
, /* Non-blocking lock. */
5407 TALLOC_FREE(br_lck
);
5409 if (NT_STATUS_V(status
)) {
5410 reply_nterror(req
, status
);
5411 END_PROFILE(SMBlock
);
5415 reply_outbuf(req
, 0, 0);
5417 END_PROFILE(SMBlock
);
5421 /****************************************************************************
5423 ****************************************************************************/
5425 void reply_unlock(struct smb_request
*req
)
5427 connection_struct
*conn
= req
->conn
;
5428 uint64_t count
,offset
;
5432 START_PROFILE(SMBunlock
);
5435 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5436 END_PROFILE(SMBunlock
);
5440 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5442 if (!check_fsp(conn
, req
, fsp
)) {
5443 END_PROFILE(SMBunlock
);
5447 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5448 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5450 status
= do_unlock(req
->sconn
->msg_ctx
,
5452 (uint64_t)req
->smbpid
,
5457 if (NT_STATUS_V(status
)) {
5458 reply_nterror(req
, status
);
5459 END_PROFILE(SMBunlock
);
5463 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5464 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5466 reply_outbuf(req
, 0, 0);
5468 END_PROFILE(SMBunlock
);
5473 #define DBGC_CLASS DBGC_ALL
5475 /****************************************************************************
5477 conn POINTER CAN BE NULL HERE !
5478 ****************************************************************************/
5480 void reply_tdis(struct smb_request
*req
)
5483 connection_struct
*conn
= req
->conn
;
5484 struct smbXsrv_tcon
*tcon
;
5486 START_PROFILE(SMBtdis
);
5489 DEBUG(4,("Invalid connection in tdis\n"));
5490 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5491 END_PROFILE(SMBtdis
);
5499 * TODO: cancel all outstanding requests on the tcon
5501 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5502 if (!NT_STATUS_IS_OK(status
)) {
5503 DEBUG(0, ("reply_tdis: "
5504 "smbXsrv_tcon_disconnect() failed: %s\n",
5505 nt_errstr(status
)));
5507 * If we hit this case, there is something completely
5508 * wrong, so we better disconnect the transport connection.
5510 END_PROFILE(SMBtdis
);
5511 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5517 reply_outbuf(req
, 0, 0);
5518 END_PROFILE(SMBtdis
);
5522 /****************************************************************************
5524 conn POINTER CAN BE NULL HERE !
5525 ****************************************************************************/
5527 void reply_echo(struct smb_request
*req
)
5529 connection_struct
*conn
= req
->conn
;
5530 struct smb_perfcount_data local_pcd
;
5531 struct smb_perfcount_data
*cur_pcd
;
5535 START_PROFILE(SMBecho
);
5537 smb_init_perfcount_data(&local_pcd
);
5540 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5541 END_PROFILE(SMBecho
);
5545 smb_reverb
= SVAL(req
->vwv
+0, 0);
5547 reply_outbuf(req
, 1, req
->buflen
);
5549 /* copy any incoming data back out */
5550 if (req
->buflen
> 0) {
5551 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5554 if (smb_reverb
> 100) {
5555 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5559 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5561 /* this makes sure we catch the request pcd */
5562 if (seq_num
== smb_reverb
) {
5563 cur_pcd
= &req
->pcd
;
5565 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5566 cur_pcd
= &local_pcd
;
5569 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5571 show_msg((char *)req
->outbuf
);
5572 if (!srv_send_smb(req
->xconn
,
5573 (char *)req
->outbuf
,
5574 true, req
->seqnum
+1,
5575 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5577 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5580 DEBUG(3,("echo %d times\n", smb_reverb
));
5582 TALLOC_FREE(req
->outbuf
);
5584 END_PROFILE(SMBecho
);
5588 /****************************************************************************
5589 Reply to a printopen.
5590 ****************************************************************************/
5592 void reply_printopen(struct smb_request
*req
)
5594 connection_struct
*conn
= req
->conn
;
5598 START_PROFILE(SMBsplopen
);
5601 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5602 END_PROFILE(SMBsplopen
);
5606 if (!CAN_PRINT(conn
)) {
5607 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5608 END_PROFILE(SMBsplopen
);
5612 status
= file_new(req
, conn
, &fsp
);
5613 if(!NT_STATUS_IS_OK(status
)) {
5614 reply_nterror(req
, status
);
5615 END_PROFILE(SMBsplopen
);
5619 /* Open for exclusive use, write only. */
5620 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5622 if (!NT_STATUS_IS_OK(status
)) {
5623 file_free(req
, fsp
);
5624 reply_nterror(req
, status
);
5625 END_PROFILE(SMBsplopen
);
5629 reply_outbuf(req
, 1, 0);
5630 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5632 DEBUG(3,("openprint fd=%d %s\n",
5633 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5635 END_PROFILE(SMBsplopen
);
5639 /****************************************************************************
5640 Reply to a printclose.
5641 ****************************************************************************/
5643 void reply_printclose(struct smb_request
*req
)
5645 connection_struct
*conn
= req
->conn
;
5649 START_PROFILE(SMBsplclose
);
5652 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5653 END_PROFILE(SMBsplclose
);
5657 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5659 if (!check_fsp(conn
, req
, fsp
)) {
5660 END_PROFILE(SMBsplclose
);
5664 if (!CAN_PRINT(conn
)) {
5665 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5666 END_PROFILE(SMBsplclose
);
5670 DEBUG(3,("printclose fd=%d %s\n",
5671 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5673 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5675 if(!NT_STATUS_IS_OK(status
)) {
5676 reply_nterror(req
, status
);
5677 END_PROFILE(SMBsplclose
);
5681 reply_outbuf(req
, 0, 0);
5683 END_PROFILE(SMBsplclose
);
5687 /****************************************************************************
5688 Reply to a printqueue.
5689 ****************************************************************************/
5691 void reply_printqueue(struct smb_request
*req
)
5693 connection_struct
*conn
= req
->conn
;
5697 START_PROFILE(SMBsplretq
);
5700 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5701 END_PROFILE(SMBsplretq
);
5705 max_count
= SVAL(req
->vwv
+0, 0);
5706 start_index
= SVAL(req
->vwv
+1, 0);
5708 /* we used to allow the client to get the cnum wrong, but that
5709 is really quite gross and only worked when there was only
5710 one printer - I think we should now only accept it if they
5711 get it right (tridge) */
5712 if (!CAN_PRINT(conn
)) {
5713 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5714 END_PROFILE(SMBsplretq
);
5718 reply_outbuf(req
, 2, 3);
5719 SSVAL(req
->outbuf
,smb_vwv0
,0);
5720 SSVAL(req
->outbuf
,smb_vwv1
,0);
5721 SCVAL(smb_buf(req
->outbuf
),0,1);
5722 SSVAL(smb_buf(req
->outbuf
),1,0);
5724 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5725 start_index
, max_count
));
5728 TALLOC_CTX
*mem_ctx
= talloc_tos();
5731 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5732 struct rpc_pipe_client
*cli
= NULL
;
5733 struct dcerpc_binding_handle
*b
= NULL
;
5734 struct policy_handle handle
;
5735 struct spoolss_DevmodeContainer devmode_ctr
;
5736 union spoolss_JobInfo
*info
;
5738 uint32_t num_to_get
;
5742 ZERO_STRUCT(handle
);
5744 status
= rpc_pipe_open_interface(conn
,
5747 conn
->sconn
->remote_address
,
5748 conn
->sconn
->msg_ctx
,
5750 if (!NT_STATUS_IS_OK(status
)) {
5751 DEBUG(0, ("reply_printqueue: "
5752 "could not connect to spoolss: %s\n",
5753 nt_errstr(status
)));
5754 reply_nterror(req
, status
);
5757 b
= cli
->binding_handle
;
5759 ZERO_STRUCT(devmode_ctr
);
5761 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5764 SEC_FLAG_MAXIMUM_ALLOWED
,
5767 if (!NT_STATUS_IS_OK(status
)) {
5768 reply_nterror(req
, status
);
5771 if (!W_ERROR_IS_OK(werr
)) {
5772 reply_nterror(req
, werror_to_ntstatus(werr
));
5776 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5784 if (!W_ERROR_IS_OK(werr
)) {
5785 reply_nterror(req
, werror_to_ntstatus(werr
));
5789 if (max_count
> 0) {
5790 first
= start_index
;
5792 first
= start_index
+ max_count
+ 1;
5795 if (first
>= count
) {
5798 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5801 for (i
= first
; i
< num_to_get
; i
++) {
5804 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5807 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5808 info
[i
].info2
.job_id
);
5810 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5816 srv_put_dos_date2(p
, 0, qtime
);
5817 SCVAL(p
, 4, qstatus
);
5818 SSVAL(p
, 5, qrapjobid
);
5819 SIVAL(p
, 7, info
[i
].info2
.size
);
5821 status
= srvstr_push(blob
, req
->flags2
, p
+12,
5822 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
5823 if (!NT_STATUS_IS_OK(status
)) {
5824 reply_nterror(req
, status
);
5827 if (message_push_blob(
5830 blob
, sizeof(blob
))) == -1) {
5831 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5837 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5838 SSVAL(req
->outbuf
,smb_vwv1
,
5839 (max_count
>0?first
+count
:first
-1));
5840 SCVAL(smb_buf(req
->outbuf
),0,1);
5841 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5845 DEBUG(3, ("%u entries returned in queue\n",
5849 if (b
&& is_valid_policy_hnd(&handle
)) {
5850 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5855 END_PROFILE(SMBsplretq
);
5859 /****************************************************************************
5860 Reply to a printwrite.
5861 ****************************************************************************/
5863 void reply_printwrite(struct smb_request
*req
)
5865 connection_struct
*conn
= req
->conn
;
5870 START_PROFILE(SMBsplwr
);
5873 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5874 END_PROFILE(SMBsplwr
);
5878 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5880 if (!check_fsp(conn
, req
, fsp
)) {
5881 END_PROFILE(SMBsplwr
);
5885 if (!fsp
->print_file
) {
5886 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5887 END_PROFILE(SMBsplwr
);
5891 if (!CHECK_WRITE(fsp
)) {
5892 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5893 END_PROFILE(SMBsplwr
);
5897 numtowrite
= SVAL(req
->buf
, 1);
5899 if (req
->buflen
< numtowrite
+ 3) {
5900 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5901 END_PROFILE(SMBsplwr
);
5905 data
= (const char *)req
->buf
+ 3;
5907 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
5908 reply_nterror(req
, map_nt_error_from_unix(errno
));
5909 END_PROFILE(SMBsplwr
);
5913 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
5915 END_PROFILE(SMBsplwr
);
5919 /****************************************************************************
5921 ****************************************************************************/
5923 void reply_mkdir(struct smb_request
*req
)
5925 connection_struct
*conn
= req
->conn
;
5926 struct smb_filename
*smb_dname
= NULL
;
5927 char *directory
= NULL
;
5929 TALLOC_CTX
*ctx
= talloc_tos();
5931 START_PROFILE(SMBmkdir
);
5933 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5934 STR_TERMINATE
, &status
);
5935 if (!NT_STATUS_IS_OK(status
)) {
5936 reply_nterror(req
, status
);
5940 status
= filename_convert(ctx
, conn
,
5941 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5943 UCF_PREP_CREATEFILE
,
5946 if (!NT_STATUS_IS_OK(status
)) {
5947 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5948 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5949 ERRSRV
, ERRbadpath
);
5952 reply_nterror(req
, status
);
5956 status
= create_directory(conn
, req
, smb_dname
);
5958 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5960 if (!NT_STATUS_IS_OK(status
)) {
5962 if (!use_nt_status()
5963 && NT_STATUS_EQUAL(status
,
5964 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5966 * Yes, in the DOS error code case we get a
5967 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5968 * samba4 torture test.
5970 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5973 reply_nterror(req
, status
);
5977 reply_outbuf(req
, 0, 0);
5979 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5981 TALLOC_FREE(smb_dname
);
5982 END_PROFILE(SMBmkdir
);
5986 /****************************************************************************
5988 ****************************************************************************/
5990 void reply_rmdir(struct smb_request
*req
)
5992 connection_struct
*conn
= req
->conn
;
5993 struct smb_filename
*smb_dname
= NULL
;
5994 char *directory
= NULL
;
5996 TALLOC_CTX
*ctx
= talloc_tos();
5997 files_struct
*fsp
= NULL
;
5999 struct smbd_server_connection
*sconn
= req
->sconn
;
6001 START_PROFILE(SMBrmdir
);
6003 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6004 STR_TERMINATE
, &status
);
6005 if (!NT_STATUS_IS_OK(status
)) {
6006 reply_nterror(req
, status
);
6010 status
= filename_convert(ctx
, conn
,
6011 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6016 if (!NT_STATUS_IS_OK(status
)) {
6017 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6018 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6019 ERRSRV
, ERRbadpath
);
6022 reply_nterror(req
, status
);
6026 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6027 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6031 status
= SMB_VFS_CREATE_FILE(
6034 0, /* root_dir_fid */
6035 smb_dname
, /* fname */
6036 DELETE_ACCESS
, /* access_mask */
6037 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6039 FILE_OPEN
, /* create_disposition*/
6040 FILE_DIRECTORY_FILE
, /* create_options */
6041 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6042 0, /* oplock_request */
6044 0, /* allocation_size */
6045 0, /* private_flags */
6050 NULL
, NULL
); /* create context */
6052 if (!NT_STATUS_IS_OK(status
)) {
6053 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6054 /* We have re-scheduled this call. */
6057 reply_nterror(req
, status
);
6061 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6062 if (!NT_STATUS_IS_OK(status
)) {
6063 close_file(req
, fsp
, ERROR_CLOSE
);
6064 reply_nterror(req
, status
);
6068 if (!set_delete_on_close(fsp
, true,
6069 conn
->session_info
->security_token
,
6070 conn
->session_info
->unix_token
)) {
6071 close_file(req
, fsp
, ERROR_CLOSE
);
6072 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6076 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6077 if (!NT_STATUS_IS_OK(status
)) {
6078 reply_nterror(req
, status
);
6080 reply_outbuf(req
, 0, 0);
6083 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
6085 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6087 TALLOC_FREE(smb_dname
);
6088 END_PROFILE(SMBrmdir
);
6092 /*******************************************************************
6093 Resolve wildcards in a filename rename.
6094 ********************************************************************/
6096 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6101 char *name2_copy
= NULL
;
6106 char *p
,*p2
, *pname1
, *pname2
;
6108 name2_copy
= talloc_strdup(ctx
, name2
);
6113 pname1
= strrchr_m(name1
,'/');
6114 pname2
= strrchr_m(name2_copy
,'/');
6116 if (!pname1
|| !pname2
) {
6120 /* Truncate the copy of name2 at the last '/' */
6123 /* Now go past the '/' */
6127 root1
= talloc_strdup(ctx
, pname1
);
6128 root2
= talloc_strdup(ctx
, pname2
);
6130 if (!root1
|| !root2
) {
6134 p
= strrchr_m(root1
,'.');
6137 ext1
= talloc_strdup(ctx
, p
+1);
6139 ext1
= talloc_strdup(ctx
, "");
6141 p
= strrchr_m(root2
,'.');
6144 ext2
= talloc_strdup(ctx
, p
+1);
6146 ext2
= talloc_strdup(ctx
, "");
6149 if (!ext1
|| !ext2
) {
6157 /* Hmmm. Should this be mb-aware ? */
6160 } else if (*p2
== '*') {
6162 root2
= talloc_asprintf(ctx
, "%s%s",
6181 /* Hmmm. Should this be mb-aware ? */
6184 } else if (*p2
== '*') {
6186 ext2
= talloc_asprintf(ctx
, "%s%s",
6202 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6207 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6219 /****************************************************************************
6220 Ensure open files have their names updated. Updated to notify other smbd's
6222 ****************************************************************************/
6224 static void rename_open_files(connection_struct
*conn
,
6225 struct share_mode_lock
*lck
,
6227 uint32_t orig_name_hash
,
6228 const struct smb_filename
*smb_fname_dst
)
6231 bool did_rename
= False
;
6233 uint32_t new_name_hash
= 0;
6235 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6236 fsp
= file_find_di_next(fsp
)) {
6237 /* fsp_name is a relative path under the fsp. To change this for other
6238 sharepaths we need to manipulate relative paths. */
6239 /* TODO - create the absolute path and manipulate the newname
6240 relative to the sharepath. */
6241 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6244 if (fsp
->name_hash
!= orig_name_hash
) {
6247 DEBUG(10, ("rename_open_files: renaming file %s "
6248 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6249 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6250 smb_fname_str_dbg(smb_fname_dst
)));
6252 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6253 if (NT_STATUS_IS_OK(status
)) {
6255 new_name_hash
= fsp
->name_hash
;
6260 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6261 "for %s\n", file_id_string_tos(&id
),
6262 smb_fname_str_dbg(smb_fname_dst
)));
6265 /* Send messages to all smbd's (not ourself) that the name has changed. */
6266 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6267 orig_name_hash
, new_name_hash
,
6272 /****************************************************************************
6273 We need to check if the source path is a parent directory of the destination
6274 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6275 refuse the rename with a sharing violation. Under UNIX the above call can
6276 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6277 probably need to check that the client is a Windows one before disallowing
6278 this as a UNIX client (one with UNIX extensions) can know the source is a
6279 symlink and make this decision intelligently. Found by an excellent bug
6280 report from <AndyLiebman@aol.com>.
6281 ****************************************************************************/
6283 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6284 const struct smb_filename
*smb_fname_dst
)
6286 const char *psrc
= smb_fname_src
->base_name
;
6287 const char *pdst
= smb_fname_dst
->base_name
;
6290 if (psrc
[0] == '.' && psrc
[1] == '/') {
6293 if (pdst
[0] == '.' && pdst
[1] == '/') {
6296 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6299 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6303 * Do the notify calls from a rename
6306 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6307 const struct smb_filename
*smb_fname_src
,
6308 const struct smb_filename
*smb_fname_dst
)
6310 char *parent_dir_src
= NULL
;
6311 char *parent_dir_dst
= NULL
;
6314 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6315 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6317 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6318 &parent_dir_src
, NULL
) ||
6319 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6320 &parent_dir_dst
, NULL
)) {
6324 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6325 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6326 smb_fname_src
->base_name
);
6327 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6328 smb_fname_dst
->base_name
);
6331 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6332 smb_fname_src
->base_name
);
6333 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6334 smb_fname_dst
->base_name
);
6337 /* this is a strange one. w2k3 gives an additional event for
6338 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6339 files, but not directories */
6341 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6342 FILE_NOTIFY_CHANGE_ATTRIBUTES
6343 |FILE_NOTIFY_CHANGE_CREATION
,
6344 smb_fname_dst
->base_name
);
6347 TALLOC_FREE(parent_dir_src
);
6348 TALLOC_FREE(parent_dir_dst
);
6351 /****************************************************************************
6352 Returns an error if the parent directory for a filename is open in an
6354 ****************************************************************************/
6356 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6357 const struct smb_filename
*smb_fname_dst_in
)
6359 char *parent_dir
= NULL
;
6360 struct smb_filename smb_fname_parent
;
6362 files_struct
*fsp
= NULL
;
6365 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6366 &parent_dir
, NULL
)) {
6367 return NT_STATUS_NO_MEMORY
;
6369 ZERO_STRUCT(smb_fname_parent
);
6370 smb_fname_parent
.base_name
= parent_dir
;
6372 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6374 return map_nt_error_from_unix(errno
);
6378 * We're only checking on this smbd here, mostly good
6379 * enough.. and will pass tests.
6382 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6383 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6384 fsp
= file_find_di_next(fsp
)) {
6385 if (fsp
->access_mask
& DELETE_ACCESS
) {
6386 return NT_STATUS_SHARING_VIOLATION
;
6389 return NT_STATUS_OK
;
6392 /****************************************************************************
6393 Rename an open file - given an fsp.
6394 ****************************************************************************/
6396 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6398 const struct smb_filename
*smb_fname_dst_in
,
6400 bool replace_if_exists
)
6402 TALLOC_CTX
*ctx
= talloc_tos();
6403 struct smb_filename
*smb_fname_dst
= NULL
;
6404 NTSTATUS status
= NT_STATUS_OK
;
6405 struct share_mode_lock
*lck
= NULL
;
6406 bool dst_exists
, old_is_stream
, new_is_stream
;
6408 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6409 if (!NT_STATUS_IS_OK(status
)) {
6413 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6414 if (!NT_STATUS_IS_OK(status
)) {
6418 /* Make a copy of the dst smb_fname structs */
6420 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6421 if (smb_fname_dst
== NULL
) {
6422 status
= NT_STATUS_NO_MEMORY
;
6427 * Check for special case with case preserving and not
6428 * case sensitive. If the old last component differs from the original
6429 * last component only by case, then we should allow
6430 * the rename (user is trying to change the case of the
6433 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6434 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6435 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6437 char *fname_dst_lcomp_base_mod
= NULL
;
6438 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6441 * Get the last component of the destination name.
6443 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6445 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6447 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6449 if (!fname_dst_lcomp_base_mod
) {
6450 status
= NT_STATUS_NO_MEMORY
;
6455 * Create an smb_filename struct using the original last
6456 * component of the destination.
6458 smb_fname_orig_lcomp
= synthetic_smb_fname_split(
6459 ctx
, smb_fname_dst
->original_lcomp
, NULL
);
6460 if (smb_fname_orig_lcomp
== NULL
) {
6461 status
= NT_STATUS_NO_MEMORY
;
6462 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6466 /* If the base names only differ by case, use original. */
6467 if(!strcsequal(fname_dst_lcomp_base_mod
,
6468 smb_fname_orig_lcomp
->base_name
)) {
6471 * Replace the modified last component with the
6475 *last_slash
= '\0'; /* Truncate at the '/' */
6476 tmp
= talloc_asprintf(smb_fname_dst
,
6478 smb_fname_dst
->base_name
,
6479 smb_fname_orig_lcomp
->base_name
);
6481 tmp
= talloc_asprintf(smb_fname_dst
,
6483 smb_fname_orig_lcomp
->base_name
);
6486 status
= NT_STATUS_NO_MEMORY
;
6487 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6488 TALLOC_FREE(smb_fname_orig_lcomp
);
6491 TALLOC_FREE(smb_fname_dst
->base_name
);
6492 smb_fname_dst
->base_name
= tmp
;
6495 /* If the stream_names only differ by case, use original. */
6496 if(!strcsequal(smb_fname_dst
->stream_name
,
6497 smb_fname_orig_lcomp
->stream_name
)) {
6499 /* Use the original stream. */
6500 tmp
= talloc_strdup(smb_fname_dst
,
6501 smb_fname_orig_lcomp
->stream_name
);
6503 status
= NT_STATUS_NO_MEMORY
;
6504 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6505 TALLOC_FREE(smb_fname_orig_lcomp
);
6508 TALLOC_FREE(smb_fname_dst
->stream_name
);
6509 smb_fname_dst
->stream_name
= tmp
;
6511 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6512 TALLOC_FREE(smb_fname_orig_lcomp
);
6516 * If the src and dest names are identical - including case,
6517 * don't do the rename, just return success.
6520 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6521 strcsequal(fsp
->fsp_name
->stream_name
,
6522 smb_fname_dst
->stream_name
)) {
6523 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6524 "- returning success\n",
6525 smb_fname_str_dbg(smb_fname_dst
)));
6526 status
= NT_STATUS_OK
;
6530 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6531 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6533 /* Return the correct error code if both names aren't streams. */
6534 if (!old_is_stream
&& new_is_stream
) {
6535 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6539 if (old_is_stream
&& !new_is_stream
) {
6540 status
= NT_STATUS_INVALID_PARAMETER
;
6544 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6546 if(!replace_if_exists
&& dst_exists
) {
6547 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6548 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6549 smb_fname_str_dbg(smb_fname_dst
)));
6550 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6555 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6556 &smb_fname_dst
->st
);
6557 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6559 /* The file can be open when renaming a stream */
6560 if (dst_fsp
&& !new_is_stream
) {
6561 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6562 status
= NT_STATUS_ACCESS_DENIED
;
6567 /* Ensure we have a valid stat struct for the source. */
6568 status
= vfs_stat_fsp(fsp
);
6569 if (!NT_STATUS_IS_OK(status
)) {
6573 status
= can_rename(conn
, fsp
, attrs
);
6575 if (!NT_STATUS_IS_OK(status
)) {
6576 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6577 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6578 smb_fname_str_dbg(smb_fname_dst
)));
6579 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6580 status
= NT_STATUS_ACCESS_DENIED
;
6584 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6585 status
= NT_STATUS_ACCESS_DENIED
;
6588 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6591 * We have the file open ourselves, so not being able to get the
6592 * corresponding share mode lock is a fatal error.
6595 SMB_ASSERT(lck
!= NULL
);
6597 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6598 uint32 create_options
= fsp
->fh
->private_options
;
6600 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6601 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6602 smb_fname_str_dbg(smb_fname_dst
)));
6604 if (!fsp
->is_directory
&&
6605 !lp_posix_pathnames() &&
6606 (lp_map_archive(SNUM(conn
)) ||
6607 lp_store_dos_attributes(SNUM(conn
)))) {
6608 /* We must set the archive bit on the newly
6610 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6611 uint32_t old_dosmode
= dos_mode(conn
,
6613 file_set_dosmode(conn
,
6615 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6621 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6624 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6628 * A rename acts as a new file create w.r.t. allowing an initial delete
6629 * on close, probably because in Windows there is a new handle to the
6630 * new file. If initial delete on close was requested but not
6631 * originally set, we need to set it here. This is probably not 100% correct,
6632 * but will work for the CIFSFS client which in non-posix mode
6633 * depends on these semantics. JRA.
6636 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6637 status
= can_set_delete_on_close(fsp
, 0);
6639 if (NT_STATUS_IS_OK(status
)) {
6640 /* Note that here we set the *inital* delete on close flag,
6641 * not the regular one. The magic gets handled in close. */
6642 fsp
->initial_delete_on_close
= True
;
6646 status
= NT_STATUS_OK
;
6652 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6653 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6655 status
= map_nt_error_from_unix(errno
);
6658 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6659 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6660 smb_fname_str_dbg(smb_fname_dst
)));
6663 TALLOC_FREE(smb_fname_dst
);
6668 /****************************************************************************
6669 The guts of the rename command, split out so it may be called by the NT SMB
6671 ****************************************************************************/
6673 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6674 connection_struct
*conn
,
6675 struct smb_request
*req
,
6676 struct smb_filename
*smb_fname_src
,
6677 struct smb_filename
*smb_fname_dst
,
6679 bool replace_if_exists
,
6682 uint32_t access_mask
)
6684 char *fname_src_dir
= NULL
;
6685 char *fname_src_mask
= NULL
;
6687 NTSTATUS status
= NT_STATUS_OK
;
6688 struct smb_Dir
*dir_hnd
= NULL
;
6689 const char *dname
= NULL
;
6690 char *talloced
= NULL
;
6692 int create_options
= 0;
6693 bool posix_pathnames
= lp_posix_pathnames();
6697 * Split the old name into directory and last component
6698 * strings. Note that unix_convert may have stripped off a
6699 * leading ./ from both name and newname if the rename is
6700 * at the root of the share. We need to make sure either both
6701 * name and newname contain a / character or neither of them do
6702 * as this is checked in resolve_wildcards().
6705 /* Split up the directory from the filename/mask. */
6706 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6707 &fname_src_dir
, &fname_src_mask
);
6708 if (!NT_STATUS_IS_OK(status
)) {
6709 status
= NT_STATUS_NO_MEMORY
;
6714 * We should only check the mangled cache
6715 * here if unix_convert failed. This means
6716 * that the path in 'mask' doesn't exist
6717 * on the file system and so we need to look
6718 * for a possible mangle. This patch from
6719 * Tine Smukavec <valentin.smukavec@hermes.si>.
6722 if (!VALID_STAT(smb_fname_src
->st
) &&
6723 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6724 char *new_mask
= NULL
;
6725 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6728 TALLOC_FREE(fname_src_mask
);
6729 fname_src_mask
= new_mask
;
6733 if (!src_has_wild
) {
6737 * Only one file needs to be renamed. Append the mask back
6738 * onto the directory.
6740 TALLOC_FREE(smb_fname_src
->base_name
);
6741 if (ISDOT(fname_src_dir
)) {
6742 /* Ensure we use canonical names on open. */
6743 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6747 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6752 if (!smb_fname_src
->base_name
) {
6753 status
= NT_STATUS_NO_MEMORY
;
6757 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6758 "case_preserve = %d, short case preserve = %d, "
6759 "directory = %s, newname = %s, "
6760 "last_component_dest = %s\n",
6761 conn
->case_sensitive
, conn
->case_preserve
,
6762 conn
->short_case_preserve
,
6763 smb_fname_str_dbg(smb_fname_src
),
6764 smb_fname_str_dbg(smb_fname_dst
),
6765 smb_fname_dst
->original_lcomp
));
6767 /* The dest name still may have wildcards. */
6768 if (dest_has_wild
) {
6769 char *fname_dst_mod
= NULL
;
6770 if (!resolve_wildcards(smb_fname_dst
,
6771 smb_fname_src
->base_name
,
6772 smb_fname_dst
->base_name
,
6774 DEBUG(6, ("rename_internals: resolve_wildcards "
6776 smb_fname_src
->base_name
,
6777 smb_fname_dst
->base_name
));
6778 status
= NT_STATUS_NO_MEMORY
;
6781 TALLOC_FREE(smb_fname_dst
->base_name
);
6782 smb_fname_dst
->base_name
= fname_dst_mod
;
6785 ZERO_STRUCT(smb_fname_src
->st
);
6786 if (posix_pathnames
) {
6787 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
6789 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
6792 status
= map_nt_error_from_unix_common(errno
);
6796 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6797 create_options
|= FILE_DIRECTORY_FILE
;
6800 status
= SMB_VFS_CREATE_FILE(
6803 0, /* root_dir_fid */
6804 smb_fname_src
, /* fname */
6805 access_mask
, /* access_mask */
6806 (FILE_SHARE_READ
| /* share_access */
6808 FILE_OPEN
, /* create_disposition*/
6809 create_options
, /* create_options */
6810 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6811 0, /* oplock_request */
6813 0, /* allocation_size */
6814 0, /* private_flags */
6819 NULL
, NULL
); /* create context */
6821 if (!NT_STATUS_IS_OK(status
)) {
6822 DEBUG(3, ("Could not open rename source %s: %s\n",
6823 smb_fname_str_dbg(smb_fname_src
),
6824 nt_errstr(status
)));
6828 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6829 attrs
, replace_if_exists
);
6831 close_file(req
, fsp
, NORMAL_CLOSE
);
6833 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6834 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6835 smb_fname_str_dbg(smb_fname_dst
)));
6841 * Wildcards - process each file that matches.
6843 if (strequal(fname_src_mask
, "????????.???")) {
6844 TALLOC_FREE(fname_src_mask
);
6845 fname_src_mask
= talloc_strdup(ctx
, "*");
6846 if (!fname_src_mask
) {
6847 status
= NT_STATUS_NO_MEMORY
;
6852 status
= check_name(conn
, fname_src_dir
);
6853 if (!NT_STATUS_IS_OK(status
)) {
6857 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6859 if (dir_hnd
== NULL
) {
6860 status
= map_nt_error_from_unix(errno
);
6864 status
= NT_STATUS_NO_SUCH_FILE
;
6866 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6867 * - gentest fix. JRA
6870 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6872 files_struct
*fsp
= NULL
;
6873 char *destname
= NULL
;
6874 bool sysdir_entry
= False
;
6876 /* Quick check for "." and ".." */
6877 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6878 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6879 sysdir_entry
= True
;
6881 TALLOC_FREE(talloced
);
6886 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6887 &smb_fname_src
->st
, false)) {
6888 TALLOC_FREE(talloced
);
6892 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6893 TALLOC_FREE(talloced
);
6898 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6902 TALLOC_FREE(smb_fname_src
->base_name
);
6903 if (ISDOT(fname_src_dir
)) {
6904 /* Ensure we use canonical names on open. */
6905 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6909 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6914 if (!smb_fname_src
->base_name
) {
6915 status
= NT_STATUS_NO_MEMORY
;
6919 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6920 smb_fname_dst
->base_name
,
6922 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6923 smb_fname_src
->base_name
, destname
));
6924 TALLOC_FREE(talloced
);
6928 status
= NT_STATUS_NO_MEMORY
;
6932 TALLOC_FREE(smb_fname_dst
->base_name
);
6933 smb_fname_dst
->base_name
= destname
;
6935 ZERO_STRUCT(smb_fname_src
->st
);
6936 if (posix_pathnames
) {
6937 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6939 SMB_VFS_STAT(conn
, smb_fname_src
);
6944 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6945 create_options
|= FILE_DIRECTORY_FILE
;
6948 status
= SMB_VFS_CREATE_FILE(
6951 0, /* root_dir_fid */
6952 smb_fname_src
, /* fname */
6953 access_mask
, /* access_mask */
6954 (FILE_SHARE_READ
| /* share_access */
6956 FILE_OPEN
, /* create_disposition*/
6957 create_options
, /* create_options */
6958 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6959 0, /* oplock_request */
6961 0, /* allocation_size */
6962 0, /* private_flags */
6967 NULL
, NULL
); /* create context */
6969 if (!NT_STATUS_IS_OK(status
)) {
6970 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6971 "returned %s rename %s -> %s\n",
6973 smb_fname_str_dbg(smb_fname_src
),
6974 smb_fname_str_dbg(smb_fname_dst
)));
6978 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6980 if (!smb_fname_dst
->original_lcomp
) {
6981 status
= NT_STATUS_NO_MEMORY
;
6985 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6986 attrs
, replace_if_exists
);
6988 close_file(req
, fsp
, NORMAL_CLOSE
);
6990 if (!NT_STATUS_IS_OK(status
)) {
6991 DEBUG(3, ("rename_internals_fsp returned %s for "
6992 "rename %s -> %s\n", nt_errstr(status
),
6993 smb_fname_str_dbg(smb_fname_src
),
6994 smb_fname_str_dbg(smb_fname_dst
)));
7000 DEBUG(3,("rename_internals: doing rename on %s -> "
7001 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7002 smb_fname_str_dbg(smb_fname_src
)));
7003 TALLOC_FREE(talloced
);
7005 TALLOC_FREE(dir_hnd
);
7007 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7008 status
= map_nt_error_from_unix(errno
);
7012 TALLOC_FREE(talloced
);
7013 TALLOC_FREE(fname_src_dir
);
7014 TALLOC_FREE(fname_src_mask
);
7018 /****************************************************************************
7020 ****************************************************************************/
7022 void reply_mv(struct smb_request
*req
)
7024 connection_struct
*conn
= req
->conn
;
7026 char *newname
= NULL
;
7030 bool src_has_wcard
= False
;
7031 bool dest_has_wcard
= False
;
7032 TALLOC_CTX
*ctx
= talloc_tos();
7033 struct smb_filename
*smb_fname_src
= NULL
;
7034 struct smb_filename
*smb_fname_dst
= NULL
;
7035 uint32_t src_ucf_flags
= lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP
: UCF_COND_ALLOW_WCARD_LCOMP
;
7036 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
| (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP
);
7037 bool stream_rename
= false;
7039 START_PROFILE(SMBmv
);
7042 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7046 attrs
= SVAL(req
->vwv
+0, 0);
7048 p
= (const char *)req
->buf
+ 1;
7049 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7050 &status
, &src_has_wcard
);
7051 if (!NT_STATUS_IS_OK(status
)) {
7052 reply_nterror(req
, status
);
7056 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7057 &status
, &dest_has_wcard
);
7058 if (!NT_STATUS_IS_OK(status
)) {
7059 reply_nterror(req
, status
);
7063 if (!lp_posix_pathnames()) {
7064 /* The newname must begin with a ':' if the
7065 name contains a ':'. */
7066 if (strchr_m(name
, ':')) {
7067 if (newname
[0] != ':') {
7068 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7071 stream_rename
= true;
7075 status
= filename_convert(ctx
,
7077 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7083 if (!NT_STATUS_IS_OK(status
)) {
7084 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7085 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7086 ERRSRV
, ERRbadpath
);
7089 reply_nterror(req
, status
);
7093 status
= filename_convert(ctx
,
7095 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7101 if (!NT_STATUS_IS_OK(status
)) {
7102 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7103 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7104 ERRSRV
, ERRbadpath
);
7107 reply_nterror(req
, status
);
7111 if (stream_rename
) {
7112 /* smb_fname_dst->base_name must be the same as
7113 smb_fname_src->base_name. */
7114 TALLOC_FREE(smb_fname_dst
->base_name
);
7115 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7116 smb_fname_src
->base_name
);
7117 if (!smb_fname_dst
->base_name
) {
7118 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7123 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7124 smb_fname_str_dbg(smb_fname_dst
)));
7126 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7127 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7129 if (!NT_STATUS_IS_OK(status
)) {
7130 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7131 /* We have re-scheduled this call. */
7134 reply_nterror(req
, status
);
7138 reply_outbuf(req
, 0, 0);
7140 TALLOC_FREE(smb_fname_src
);
7141 TALLOC_FREE(smb_fname_dst
);
7146 /*******************************************************************
7147 Copy a file as part of a reply_copy.
7148 ******************************************************************/
7151 * TODO: check error codes on all callers
7154 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7155 connection_struct
*conn
,
7156 struct smb_filename
*smb_fname_src
,
7157 struct smb_filename
*smb_fname_dst
,
7160 bool target_is_directory
)
7162 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7164 files_struct
*fsp1
,*fsp2
;
7166 uint32 new_create_disposition
;
7170 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7171 if (smb_fname_dst_tmp
== NULL
) {
7172 return NT_STATUS_NO_MEMORY
;
7176 * If the target is a directory, extract the last component from the
7177 * src filename and append it to the dst filename
7179 if (target_is_directory
) {
7182 /* dest/target can't be a stream if it's a directory. */
7183 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7185 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7189 p
= smb_fname_src
->base_name
;
7191 smb_fname_dst_tmp
->base_name
=
7192 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7194 if (!smb_fname_dst_tmp
->base_name
) {
7195 status
= NT_STATUS_NO_MEMORY
;
7200 status
= vfs_file_exist(conn
, smb_fname_src
);
7201 if (!NT_STATUS_IS_OK(status
)) {
7205 if (!target_is_directory
&& count
) {
7206 new_create_disposition
= FILE_OPEN
;
7208 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7211 &new_create_disposition
,
7214 status
= NT_STATUS_INVALID_PARAMETER
;
7219 /* Open the src file for reading. */
7220 status
= SMB_VFS_CREATE_FILE(
7223 0, /* root_dir_fid */
7224 smb_fname_src
, /* fname */
7225 FILE_GENERIC_READ
, /* access_mask */
7226 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7227 FILE_OPEN
, /* create_disposition*/
7228 0, /* create_options */
7229 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7230 INTERNAL_OPEN_ONLY
, /* oplock_request */
7232 0, /* allocation_size */
7233 0, /* private_flags */
7238 NULL
, NULL
); /* create context */
7240 if (!NT_STATUS_IS_OK(status
)) {
7244 dosattrs
= dos_mode(conn
, smb_fname_src
);
7246 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7247 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7250 /* Open the dst file for writing. */
7251 status
= SMB_VFS_CREATE_FILE(
7254 0, /* root_dir_fid */
7255 smb_fname_dst
, /* fname */
7256 FILE_GENERIC_WRITE
, /* access_mask */
7257 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7258 new_create_disposition
, /* create_disposition*/
7259 0, /* create_options */
7260 dosattrs
, /* file_attributes */
7261 INTERNAL_OPEN_ONLY
, /* oplock_request */
7263 0, /* allocation_size */
7264 0, /* private_flags */
7269 NULL
, NULL
); /* create context */
7271 if (!NT_STATUS_IS_OK(status
)) {
7272 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7276 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7277 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7279 DEBUG(0, ("error - vfs lseek returned error %s\n",
7281 status
= map_nt_error_from_unix(errno
);
7282 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7283 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7288 /* Do the actual copy. */
7289 if (smb_fname_src
->st
.st_ex_size
) {
7290 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7295 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7297 /* Ensure the modtime is set correctly on the destination file. */
7298 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7301 * As we are opening fsp1 read-only we only expect
7302 * an error on close on fsp2 if we are out of space.
7303 * Thus we don't look at the error return from the
7306 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7308 if (!NT_STATUS_IS_OK(status
)) {
7312 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7313 status
= NT_STATUS_DISK_FULL
;
7317 status
= NT_STATUS_OK
;
7320 TALLOC_FREE(smb_fname_dst_tmp
);
7324 /****************************************************************************
7325 Reply to a file copy.
7326 ****************************************************************************/
7328 void reply_copy(struct smb_request
*req
)
7330 connection_struct
*conn
= req
->conn
;
7331 struct smb_filename
*smb_fname_src
= NULL
;
7332 struct smb_filename
*smb_fname_dst
= NULL
;
7333 char *fname_src
= NULL
;
7334 char *fname_dst
= NULL
;
7335 char *fname_src_mask
= NULL
;
7336 char *fname_src_dir
= NULL
;
7339 int error
= ERRnoaccess
;
7343 bool target_is_directory
=False
;
7344 bool source_has_wild
= False
;
7345 bool dest_has_wild
= False
;
7347 TALLOC_CTX
*ctx
= talloc_tos();
7349 START_PROFILE(SMBcopy
);
7352 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7356 tid2
= SVAL(req
->vwv
+0, 0);
7357 ofun
= SVAL(req
->vwv
+1, 0);
7358 flags
= SVAL(req
->vwv
+2, 0);
7360 p
= (const char *)req
->buf
;
7361 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7362 &status
, &source_has_wild
);
7363 if (!NT_STATUS_IS_OK(status
)) {
7364 reply_nterror(req
, status
);
7367 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7368 &status
, &dest_has_wild
);
7369 if (!NT_STATUS_IS_OK(status
)) {
7370 reply_nterror(req
, status
);
7374 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7376 if (tid2
!= conn
->cnum
) {
7377 /* can't currently handle inter share copies XXXX */
7378 DEBUG(3,("Rejecting inter-share copy\n"));
7379 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7383 status
= filename_convert(ctx
, conn
,
7384 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7386 UCF_COND_ALLOW_WCARD_LCOMP
,
7389 if (!NT_STATUS_IS_OK(status
)) {
7390 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7391 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7392 ERRSRV
, ERRbadpath
);
7395 reply_nterror(req
, status
);
7399 status
= filename_convert(ctx
, conn
,
7400 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7402 UCF_COND_ALLOW_WCARD_LCOMP
,
7405 if (!NT_STATUS_IS_OK(status
)) {
7406 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7407 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7408 ERRSRV
, ERRbadpath
);
7411 reply_nterror(req
, status
);
7415 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7417 if ((flags
&1) && target_is_directory
) {
7418 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7422 if ((flags
&2) && !target_is_directory
) {
7423 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7427 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7428 /* wants a tree copy! XXXX */
7429 DEBUG(3,("Rejecting tree copy\n"));
7430 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7434 /* Split up the directory from the filename/mask. */
7435 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7436 &fname_src_dir
, &fname_src_mask
);
7437 if (!NT_STATUS_IS_OK(status
)) {
7438 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7443 * We should only check the mangled cache
7444 * here if unix_convert failed. This means
7445 * that the path in 'mask' doesn't exist
7446 * on the file system and so we need to look
7447 * for a possible mangle. This patch from
7448 * Tine Smukavec <valentin.smukavec@hermes.si>.
7450 if (!VALID_STAT(smb_fname_src
->st
) &&
7451 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7452 char *new_mask
= NULL
;
7453 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7454 &new_mask
, conn
->params
);
7456 /* Use demangled name if one was successfully found. */
7458 TALLOC_FREE(fname_src_mask
);
7459 fname_src_mask
= new_mask
;
7463 if (!source_has_wild
) {
7466 * Only one file needs to be copied. Append the mask back onto
7469 TALLOC_FREE(smb_fname_src
->base_name
);
7470 if (ISDOT(fname_src_dir
)) {
7471 /* Ensure we use canonical names on open. */
7472 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7476 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7481 if (!smb_fname_src
->base_name
) {
7482 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7486 if (dest_has_wild
) {
7487 char *fname_dst_mod
= NULL
;
7488 if (!resolve_wildcards(smb_fname_dst
,
7489 smb_fname_src
->base_name
,
7490 smb_fname_dst
->base_name
,
7492 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7495 TALLOC_FREE(smb_fname_dst
->base_name
);
7496 smb_fname_dst
->base_name
= fname_dst_mod
;
7499 status
= check_name(conn
, smb_fname_src
->base_name
);
7500 if (!NT_STATUS_IS_OK(status
)) {
7501 reply_nterror(req
, status
);
7505 status
= check_name(conn
, smb_fname_dst
->base_name
);
7506 if (!NT_STATUS_IS_OK(status
)) {
7507 reply_nterror(req
, status
);
7511 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7512 ofun
, count
, target_is_directory
);
7514 if(!NT_STATUS_IS_OK(status
)) {
7515 reply_nterror(req
, status
);
7521 struct smb_Dir
*dir_hnd
= NULL
;
7522 const char *dname
= NULL
;
7523 char *talloced
= NULL
;
7527 * There is a wildcard that requires us to actually read the
7528 * src dir and copy each file matching the mask to the dst.
7529 * Right now streams won't be copied, but this could
7530 * presumably be added with a nested loop for reach dir entry.
7532 SMB_ASSERT(!smb_fname_src
->stream_name
);
7533 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7535 smb_fname_src
->stream_name
= NULL
;
7536 smb_fname_dst
->stream_name
= NULL
;
7538 if (strequal(fname_src_mask
,"????????.???")) {
7539 TALLOC_FREE(fname_src_mask
);
7540 fname_src_mask
= talloc_strdup(ctx
, "*");
7541 if (!fname_src_mask
) {
7542 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7547 status
= check_name(conn
, fname_src_dir
);
7548 if (!NT_STATUS_IS_OK(status
)) {
7549 reply_nterror(req
, status
);
7553 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7554 if (dir_hnd
== NULL
) {
7555 status
= map_nt_error_from_unix(errno
);
7556 reply_nterror(req
, status
);
7562 /* Iterate over the src dir copying each entry to the dst. */
7563 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7564 &smb_fname_src
->st
, &talloced
))) {
7565 char *destname
= NULL
;
7567 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7568 TALLOC_FREE(talloced
);
7572 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7573 &smb_fname_src
->st
, false)) {
7574 TALLOC_FREE(talloced
);
7578 if(!mask_match(dname
, fname_src_mask
,
7579 conn
->case_sensitive
)) {
7580 TALLOC_FREE(talloced
);
7584 error
= ERRnoaccess
;
7586 /* Get the src smb_fname struct setup. */
7587 TALLOC_FREE(smb_fname_src
->base_name
);
7588 if (ISDOT(fname_src_dir
)) {
7589 /* Ensure we use canonical names on open. */
7590 smb_fname_src
->base_name
=
7591 talloc_asprintf(smb_fname_src
, "%s",
7594 smb_fname_src
->base_name
=
7595 talloc_asprintf(smb_fname_src
, "%s/%s",
7596 fname_src_dir
, dname
);
7599 if (!smb_fname_src
->base_name
) {
7600 TALLOC_FREE(dir_hnd
);
7601 TALLOC_FREE(talloced
);
7602 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7606 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7607 smb_fname_dst
->base_name
,
7609 TALLOC_FREE(talloced
);
7613 TALLOC_FREE(dir_hnd
);
7614 TALLOC_FREE(talloced
);
7615 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7619 TALLOC_FREE(smb_fname_dst
->base_name
);
7620 smb_fname_dst
->base_name
= destname
;
7622 status
= check_name(conn
, smb_fname_src
->base_name
);
7623 if (!NT_STATUS_IS_OK(status
)) {
7624 TALLOC_FREE(dir_hnd
);
7625 TALLOC_FREE(talloced
);
7626 reply_nterror(req
, status
);
7630 status
= check_name(conn
, smb_fname_dst
->base_name
);
7631 if (!NT_STATUS_IS_OK(status
)) {
7632 TALLOC_FREE(dir_hnd
);
7633 TALLOC_FREE(talloced
);
7634 reply_nterror(req
, status
);
7638 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7639 smb_fname_src
->base_name
,
7640 smb_fname_dst
->base_name
));
7642 status
= copy_file(ctx
, conn
, smb_fname_src
,
7643 smb_fname_dst
, ofun
, count
,
7644 target_is_directory
);
7645 if (NT_STATUS_IS_OK(status
)) {
7649 TALLOC_FREE(talloced
);
7651 TALLOC_FREE(dir_hnd
);
7655 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7659 reply_outbuf(req
, 1, 0);
7660 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7662 TALLOC_FREE(smb_fname_src
);
7663 TALLOC_FREE(smb_fname_dst
);
7664 TALLOC_FREE(fname_src
);
7665 TALLOC_FREE(fname_dst
);
7666 TALLOC_FREE(fname_src_mask
);
7667 TALLOC_FREE(fname_src_dir
);
7669 END_PROFILE(SMBcopy
);
7674 #define DBGC_CLASS DBGC_LOCKING
7676 /****************************************************************************
7677 Get a lock pid, dealing with large count requests.
7678 ****************************************************************************/
7680 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7681 bool large_file_format
)
7683 if(!large_file_format
)
7684 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7686 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7689 /****************************************************************************
7690 Get a lock count, dealing with large count requests.
7691 ****************************************************************************/
7693 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7694 bool large_file_format
)
7698 if(!large_file_format
) {
7699 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7702 * No BVAL, this is reversed!
7704 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7705 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7711 /****************************************************************************
7712 Get a lock offset, dealing with large offset requests.
7713 ****************************************************************************/
7715 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7716 bool large_file_format
)
7718 uint64_t offset
= 0;
7720 if(!large_file_format
) {
7721 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7724 * No BVAL, this is reversed!
7726 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7727 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7733 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7738 struct smbd_lock_element
*locks
,
7741 connection_struct
*conn
= req
->conn
;
7743 NTSTATUS status
= NT_STATUS_OK
;
7747 /* Setup the timeout in seconds. */
7749 if (!lp_blocking_locks(SNUM(conn
))) {
7753 for(i
= 0; i
< (int)num_locks
; i
++) {
7754 struct smbd_lock_element
*e
= &locks
[i
];
7756 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7757 "%llu, file %s timeout = %d\n",
7760 (unsigned long long)e
->smblctx
,
7764 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7765 struct blocking_lock_record
*blr
= NULL
;
7767 if (num_locks
> 1) {
7769 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7770 * if the lock vector contains one entry. When given multiple cancel
7771 * requests in a single PDU we expect the server to return an
7772 * error. Windows servers seem to accept the request but only
7773 * cancel the first lock.
7774 * JRA - Do what Windows does (tm) :-).
7778 /* MS-CIFS (2.2.4.32.1) behavior. */
7779 return NT_STATUS_DOS(ERRDOS
,
7780 ERRcancelviolation
);
7782 /* Windows behavior. */
7784 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7785 "cancel request\n"));
7791 if (lp_blocking_locks(SNUM(conn
))) {
7793 /* Schedule a message to ourselves to
7794 remove the blocking lock record and
7795 return the right error. */
7797 blr
= blocking_lock_cancel_smb1(fsp
,
7803 NT_STATUS_FILE_LOCK_CONFLICT
);
7805 return NT_STATUS_DOS(
7807 ERRcancelviolation
);
7810 /* Remove a matching pending lock. */
7811 status
= do_lock_cancel(fsp
,
7817 bool blocking_lock
= timeout
? true : false;
7818 bool defer_lock
= false;
7819 struct byte_range_lock
*br_lck
;
7820 uint64_t block_smblctx
;
7822 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7833 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7834 /* Windows internal resolution for blocking locks seems
7835 to be about 200ms... Don't wait for less than that. JRA. */
7836 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7837 timeout
= lp_lock_spin_time();
7842 /* If a lock sent with timeout of zero would fail, and
7843 * this lock has been requested multiple times,
7844 * according to brl_lock_failed() we convert this
7845 * request to a blocking lock with a timeout of between
7846 * 150 - 300 milliseconds.
7848 * If lp_lock_spin_time() has been set to 0, we skip
7849 * this blocking retry and fail immediately.
7851 * Replacement for do_lock_spin(). JRA. */
7853 if (!req
->sconn
->using_smb2
&&
7854 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7855 lp_lock_spin_time() && !blocking_lock
&&
7856 NT_STATUS_EQUAL((status
),
7857 NT_STATUS_FILE_LOCK_CONFLICT
))
7860 timeout
= lp_lock_spin_time();
7863 if (br_lck
&& defer_lock
) {
7865 * A blocking lock was requested. Package up
7866 * this smb into a queued request and push it
7867 * onto the blocking lock queue.
7869 if(push_blocking_lock_request(br_lck
,
7880 TALLOC_FREE(br_lck
);
7882 return NT_STATUS_OK
;
7886 TALLOC_FREE(br_lck
);
7889 if (!NT_STATUS_IS_OK(status
)) {
7894 /* If any of the above locks failed, then we must unlock
7895 all of the previous locks (X/Open spec). */
7897 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7899 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7900 i
= -1; /* we want to skip the for loop */
7904 * Ensure we don't do a remove on the lock that just failed,
7905 * as under POSIX rules, if we have a lock already there, we
7906 * will delete it (and we shouldn't) .....
7908 for(i
--; i
>= 0; i
--) {
7909 struct smbd_lock_element
*e
= &locks
[i
];
7911 do_unlock(req
->sconn
->msg_ctx
,
7921 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7922 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
));
7924 return NT_STATUS_OK
;
7927 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
7929 uint16_t num_ulocks
,
7930 struct smbd_lock_element
*ulocks
)
7934 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7935 struct smbd_lock_element
*e
= &ulocks
[i
];
7938 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7939 "pid %u, file %s\n", __func__
,
7942 (unsigned int)e
->smblctx
,
7945 if (e
->brltype
!= UNLOCK_LOCK
) {
7946 /* this can only happen with SMB2 */
7947 return NT_STATUS_INVALID_PARAMETER
;
7950 status
= do_unlock(req
->sconn
->msg_ctx
,
7957 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
7958 nt_errstr(status
)));
7960 if (!NT_STATUS_IS_OK(status
)) {
7965 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
7968 return NT_STATUS_OK
;
7971 /****************************************************************************
7972 Reply to a lockingX request.
7973 ****************************************************************************/
7975 void reply_lockingX(struct smb_request
*req
)
7977 connection_struct
*conn
= req
->conn
;
7979 unsigned char locktype
;
7980 unsigned char oplocklevel
;
7985 const uint8_t *data
;
7986 bool large_file_format
;
7987 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7988 struct smbd_lock_element
*ulocks
;
7989 struct smbd_lock_element
*locks
;
7992 START_PROFILE(SMBlockingX
);
7995 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7996 END_PROFILE(SMBlockingX
);
8000 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8001 locktype
= CVAL(req
->vwv
+3, 0);
8002 oplocklevel
= CVAL(req
->vwv
+3, 1);
8003 num_ulocks
= SVAL(req
->vwv
+6, 0);
8004 num_locks
= SVAL(req
->vwv
+7, 0);
8005 lock_timeout
= IVAL(req
->vwv
+4, 0);
8006 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8008 if (!check_fsp(conn
, req
, fsp
)) {
8009 END_PROFILE(SMBlockingX
);
8015 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8016 /* we don't support these - and CANCEL_LOCK makes w2k
8017 and XP reboot so I don't really want to be
8018 compatible! (tridge) */
8019 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8020 END_PROFILE(SMBlockingX
);
8024 /* Check if this is an oplock break on a file
8025 we have granted an oplock on.
8027 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8028 /* Client can insist on breaking to none. */
8029 bool break_to_none
= (oplocklevel
== 0);
8032 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8033 "for %s\n", (unsigned int)oplocklevel
,
8034 fsp_fnum_dbg(fsp
)));
8037 * Make sure we have granted an exclusive or batch oplock on
8041 if (fsp
->oplock_type
== 0) {
8043 /* The Samba4 nbench simulator doesn't understand
8044 the difference between break to level2 and break
8045 to none from level2 - it sends oplock break
8046 replies in both cases. Don't keep logging an error
8047 message here - just ignore it. JRA. */
8049 DEBUG(5,("reply_lockingX: Error : oplock break from "
8050 "client for %s (oplock=%d) and no "
8051 "oplock granted on this file (%s).\n",
8052 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8055 /* if this is a pure oplock break request then don't
8057 if (num_locks
== 0 && num_ulocks
== 0) {
8058 END_PROFILE(SMBlockingX
);
8061 END_PROFILE(SMBlockingX
);
8062 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8067 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8069 result
= remove_oplock(fsp
);
8071 result
= downgrade_oplock(fsp
);
8075 DEBUG(0, ("reply_lockingX: error in removing "
8076 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8077 /* Hmmm. Is this panic justified? */
8078 smb_panic("internal tdb error");
8081 /* if this is a pure oplock break request then don't send a
8083 if (num_locks
== 0 && num_ulocks
== 0) {
8084 /* Sanity check - ensure a pure oplock break is not a
8086 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8087 DEBUG(0,("reply_lockingX: Error : pure oplock "
8088 "break is a chained %d request !\n",
8089 (unsigned int)CVAL(req
->vwv
+0, 0)));
8091 END_PROFILE(SMBlockingX
);
8097 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8098 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8099 END_PROFILE(SMBlockingX
);
8103 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8104 if (ulocks
== NULL
) {
8105 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8106 END_PROFILE(SMBlockingX
);
8110 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8111 if (locks
== NULL
) {
8112 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8113 END_PROFILE(SMBlockingX
);
8117 /* Data now points at the beginning of the list
8118 of smb_unlkrng structs */
8119 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8120 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8121 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8122 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8123 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8126 /* Now do any requested locks */
8127 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8129 /* Data now points at the beginning of the list
8130 of smb_lkrng structs */
8132 for(i
= 0; i
< (int)num_locks
; i
++) {
8133 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8134 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8135 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8137 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8138 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8139 locks
[i
].brltype
= PENDING_READ_LOCK
;
8141 locks
[i
].brltype
= READ_LOCK
;
8144 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8145 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8147 locks
[i
].brltype
= WRITE_LOCK
;
8152 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
);
8153 if (!NT_STATUS_IS_OK(status
)) {
8154 END_PROFILE(SMBlockingX
);
8155 reply_nterror(req
, status
);
8159 status
= smbd_do_locking(req
, fsp
,
8160 locktype
, lock_timeout
,
8163 if (!NT_STATUS_IS_OK(status
)) {
8164 END_PROFILE(SMBlockingX
);
8165 reply_nterror(req
, status
);
8169 END_PROFILE(SMBlockingX
);
8173 reply_outbuf(req
, 2, 0);
8174 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8175 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8177 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8178 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8180 END_PROFILE(SMBlockingX
);
8184 #define DBGC_CLASS DBGC_ALL
8186 /****************************************************************************
8187 Reply to a SMBreadbmpx (read block multiplex) request.
8188 Always reply with an error, if someone has a platform really needs this,
8189 please contact vl@samba.org
8190 ****************************************************************************/
8192 void reply_readbmpx(struct smb_request
*req
)
8194 START_PROFILE(SMBreadBmpx
);
8195 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8196 END_PROFILE(SMBreadBmpx
);
8200 /****************************************************************************
8201 Reply to a SMBreadbs (read block multiplex secondary) request.
8202 Always reply with an error, if someone has a platform really needs this,
8203 please contact vl@samba.org
8204 ****************************************************************************/
8206 void reply_readbs(struct smb_request
*req
)
8208 START_PROFILE(SMBreadBs
);
8209 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8210 END_PROFILE(SMBreadBs
);
8214 /****************************************************************************
8215 Reply to a SMBsetattrE.
8216 ****************************************************************************/
8218 void reply_setattrE(struct smb_request
*req
)
8220 connection_struct
*conn
= req
->conn
;
8221 struct smb_file_time ft
;
8225 START_PROFILE(SMBsetattrE
);
8229 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8233 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8235 if(!fsp
|| (fsp
->conn
!= conn
)) {
8236 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8241 * Convert the DOS times into unix times.
8244 ft
.atime
= convert_time_t_to_timespec(
8245 srv_make_unix_date2(req
->vwv
+3));
8246 ft
.mtime
= convert_time_t_to_timespec(
8247 srv_make_unix_date2(req
->vwv
+5));
8248 ft
.create_time
= convert_time_t_to_timespec(
8249 srv_make_unix_date2(req
->vwv
+1));
8251 reply_outbuf(req
, 0, 0);
8254 * Patch from Ray Frush <frush@engr.colostate.edu>
8255 * Sometimes times are sent as zero - ignore them.
8258 /* Ensure we have a valid stat struct for the source. */
8259 status
= vfs_stat_fsp(fsp
);
8260 if (!NT_STATUS_IS_OK(status
)) {
8261 reply_nterror(req
, status
);
8265 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8266 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8270 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8271 if (!NT_STATUS_IS_OK(status
)) {
8272 reply_nterror(req
, status
);
8276 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8279 (unsigned int)ft
.atime
.tv_sec
,
8280 (unsigned int)ft
.mtime
.tv_sec
,
8281 (unsigned int)ft
.create_time
.tv_sec
8284 END_PROFILE(SMBsetattrE
);
8289 /* Back from the dead for OS/2..... JRA. */
8291 /****************************************************************************
8292 Reply to a SMBwritebmpx (write block multiplex primary) request.
8293 Always reply with an error, if someone has a platform really needs this,
8294 please contact vl@samba.org
8295 ****************************************************************************/
8297 void reply_writebmpx(struct smb_request
*req
)
8299 START_PROFILE(SMBwriteBmpx
);
8300 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8301 END_PROFILE(SMBwriteBmpx
);
8305 /****************************************************************************
8306 Reply to a SMBwritebs (write block multiplex secondary) request.
8307 Always reply with an error, if someone has a platform really needs this,
8308 please contact vl@samba.org
8309 ****************************************************************************/
8311 void reply_writebs(struct smb_request
*req
)
8313 START_PROFILE(SMBwriteBs
);
8314 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8315 END_PROFILE(SMBwriteBs
);
8319 /****************************************************************************
8320 Reply to a SMBgetattrE.
8321 ****************************************************************************/
8323 void reply_getattrE(struct smb_request
*req
)
8325 connection_struct
*conn
= req
->conn
;
8328 struct timespec create_ts
;
8330 START_PROFILE(SMBgetattrE
);
8333 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8334 END_PROFILE(SMBgetattrE
);
8338 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8340 if(!fsp
|| (fsp
->conn
!= conn
)) {
8341 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8342 END_PROFILE(SMBgetattrE
);
8346 /* Do an fstat on this file */
8348 reply_nterror(req
, map_nt_error_from_unix(errno
));
8349 END_PROFILE(SMBgetattrE
);
8353 mode
= dos_mode(conn
, fsp
->fsp_name
);
8356 * Convert the times into dos times. Set create
8357 * date to be last modify date as UNIX doesn't save
8361 reply_outbuf(req
, 11, 0);
8363 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8364 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8365 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8366 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8367 /* Should we check pending modtime here ? JRA */
8368 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8369 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8371 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8372 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8373 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8375 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8376 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
8377 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8379 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8381 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8383 END_PROFILE(SMBgetattrE
);