2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
47 /****************************************************************************
48 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
49 path or anything including wildcards.
50 We're assuming here that '/' is not the second byte in any multibyte char
51 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
53 ****************************************************************************/
55 /* Custom version for processing POSIX paths. */
56 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
58 static NTSTATUS
check_path_syntax_internal(char *path
,
60 bool *p_last_component_contains_wcard
)
64 NTSTATUS ret
= NT_STATUS_OK
;
65 bool start_of_name_component
= True
;
66 bool stream_started
= false;
68 *p_last_component_contains_wcard
= False
;
75 return NT_STATUS_OBJECT_NAME_INVALID
;
78 return NT_STATUS_OBJECT_NAME_INVALID
;
80 if (strchr_m(&s
[1], ':')) {
81 return NT_STATUS_OBJECT_NAME_INVALID
;
87 if ((*s
== ':') && !posix_path
&& !stream_started
) {
88 if (*p_last_component_contains_wcard
) {
89 return NT_STATUS_OBJECT_NAME_INVALID
;
91 /* Stream names allow more characters than file names.
92 We're overloading posix_path here to allow a wider
93 range of characters. If stream_started is true this
94 is still a Windows path even if posix_path is true.
97 stream_started
= true;
98 start_of_name_component
= false;
102 return NT_STATUS_OBJECT_NAME_INVALID
;
106 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
108 * Safe to assume is not the second part of a mb char
109 * as this is handled below.
111 /* Eat multiple '/' or '\\' */
112 while (IS_PATH_SEP(*s
,posix_path
)) {
115 if ((d
!= path
) && (*s
!= '\0')) {
116 /* We only care about non-leading or trailing '/' or '\\' */
120 start_of_name_component
= True
;
122 *p_last_component_contains_wcard
= False
;
126 if (start_of_name_component
) {
127 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
128 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
131 * No mb char starts with '.' so we're safe checking the directory separator here.
134 /* If we just added a '/' - delete it */
135 if ((d
> path
) && (*(d
-1) == '/')) {
140 /* Are we at the start ? Can't go back further if so. */
142 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
145 /* Go back one level... */
146 /* We know this is safe as '/' cannot be part of a mb sequence. */
147 /* NOTE - if this assumption is invalid we are not in good shape... */
148 /* Decrement d first as d points to the *next* char to write into. */
149 for (d
--; d
> path
; d
--) {
153 s
+= 2; /* Else go past the .. */
154 /* We're still at the start of a name component, just the previous one. */
157 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
169 if (*s
<= 0x1f || *s
== '|') {
170 return NT_STATUS_OBJECT_NAME_INVALID
;
178 *p_last_component_contains_wcard
= True
;
187 /* Get the size of the next MB character. */
188 next_codepoint(s
,&siz
);
206 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
208 return NT_STATUS_INVALID_PARAMETER
;
211 start_of_name_component
= False
;
219 /****************************************************************************
220 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
221 No wildcards allowed.
222 ****************************************************************************/
224 NTSTATUS
check_path_syntax(char *path
)
227 return check_path_syntax_internal(path
, False
, &ignore
);
230 /****************************************************************************
231 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
232 Wildcards allowed - p_contains_wcard returns true if the last component contained
234 ****************************************************************************/
236 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
238 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
241 /****************************************************************************
242 Check the path for a POSIX client.
243 We're assuming here that '/' is not the second byte in any multibyte char
244 set (a safe assumption).
245 ****************************************************************************/
247 NTSTATUS
check_path_syntax_posix(char *path
)
250 return check_path_syntax_internal(path
, True
, &ignore
);
253 /****************************************************************************
254 Pull a string and check the path allowing a wilcard - provide for error return.
255 ****************************************************************************/
257 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
258 const char *base_ptr
,
265 bool *contains_wcard
)
271 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
275 *err
= NT_STATUS_INVALID_PARAMETER
;
279 *contains_wcard
= False
;
281 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
283 * For a DFS path the function parse_dfs_path()
284 * will do the path processing, just make a copy.
290 if (lp_posix_pathnames()) {
291 *err
= check_path_syntax_posix(*pp_dest
);
293 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
299 /****************************************************************************
300 Pull a string and check the path - provide for error return.
301 ****************************************************************************/
303 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
304 const char *base_ptr
,
313 return srvstr_get_path_wcard(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
314 src_len
, flags
, err
, &ignore
);
317 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
318 char **pp_dest
, const char *src
, int flags
,
319 NTSTATUS
*err
, bool *contains_wcard
)
321 ssize_t bufrem
= smbreq_bufrem(req
, src
);
324 *err
= NT_STATUS_INVALID_PARAMETER
;
328 return srvstr_get_path_wcard(mem_ctx
, (const char *)req
->inbuf
,
329 req
->flags2
, pp_dest
, src
, bufrem
, flags
,
330 err
, contains_wcard
);
333 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
334 char **pp_dest
, const char *src
, int flags
,
338 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
339 flags
, err
, &ignore
);
342 /* pull a string from the smb_buf part of a packet. In this case the
343 string can either be null terminated or it can be terminated by the
344 end of the smbbuf area
346 size_t srvstr_pull_req_talloc(TALLOC_CTX
*ctx
, struct smb_request
*req
,
347 char **dest
, const char *src
, int flags
)
349 ssize_t bufrem
= smbreq_bufrem(req
, src
);
355 return pull_string_talloc(ctx
, req
->inbuf
, req
->flags2
, dest
, src
,
359 /****************************************************************************
360 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
361 ****************************************************************************/
363 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
366 if ((fsp
== NULL
) || (conn
== NULL
)) {
367 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
370 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
371 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
377 /****************************************************************************
378 Check if we have a correct fsp pointing to a file.
379 ****************************************************************************/
381 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
384 if (!check_fsp_open(conn
, req
, fsp
)) {
387 if (fsp
->is_directory
) {
388 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
391 if (fsp
->fh
->fd
== -1) {
392 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
395 fsp
->num_smb_operations
++;
399 /****************************************************************************
400 Check if we have a correct fsp pointing to a quota fake file. Replacement for
401 the CHECK_NTQUOTA_HANDLE_OK macro.
402 ****************************************************************************/
404 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
407 if (!check_fsp_open(conn
, req
, fsp
)) {
411 if (fsp
->is_directory
) {
415 if (fsp
->fake_file_handle
== NULL
) {
419 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
423 if (fsp
->fake_file_handle
->private_data
== NULL
) {
430 static bool netbios_session_retarget(struct smbd_server_connection
*sconn
,
431 const char *name
, int name_type
)
434 char *trim_name_type
;
435 const char *retarget_parm
;
438 int retarget_type
= 0x20;
439 int retarget_port
= NBT_SMB_PORT
;
440 struct sockaddr_storage retarget_addr
;
441 struct sockaddr_in
*in_addr
;
445 if (get_socket_port(sconn
->sock
) != NBT_SMB_PORT
) {
449 trim_name
= talloc_strdup(talloc_tos(), name
);
450 if (trim_name
== NULL
) {
453 trim_char(trim_name
, ' ', ' ');
455 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
457 if (trim_name_type
== NULL
) {
461 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
462 trim_name_type
, NULL
);
463 if (retarget_parm
== NULL
) {
464 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
467 if (retarget_parm
== NULL
) {
471 retarget
= talloc_strdup(trim_name
, retarget_parm
);
472 if (retarget
== NULL
) {
476 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
478 p
= strchr(retarget
, ':');
481 retarget_port
= atoi(p
);
484 p
= strchr_m(retarget
, '#');
487 if (sscanf(p
, "%x", &retarget_type
) != 1) {
492 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
494 DEBUG(10, ("could not resolve %s\n", retarget
));
498 if (retarget_addr
.ss_family
!= AF_INET
) {
499 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
503 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
505 _smb_setlen(outbuf
, 6);
506 SCVAL(outbuf
, 0, 0x84);
507 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
508 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
510 if (!srv_send_smb(sconn
, (char *)outbuf
, false, 0, false,
512 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
518 TALLOC_FREE(trim_name
);
522 static void reply_called_name_not_present(char *outbuf
)
524 smb_setlen(outbuf
, 1);
525 SCVAL(outbuf
, 0, 0x83);
526 SCVAL(outbuf
, 4, 0x82);
529 /****************************************************************************
530 Reply to a (netbios-level) special message.
531 ****************************************************************************/
533 void reply_special(struct smbd_server_connection
*sconn
, char *inbuf
, size_t inbuf_size
)
535 int msg_type
= CVAL(inbuf
,0);
536 int msg_flags
= CVAL(inbuf
,1);
538 * We only really use 4 bytes of the outbuf, but for the smb_setlen
539 * calculation & friends (srv_send_smb uses that) we need the full smb
542 char outbuf
[smb_size
];
544 memset(outbuf
, '\0', sizeof(outbuf
));
546 smb_setlen(outbuf
,0);
549 case NBSSrequest
: /* session request */
551 /* inbuf_size is guarenteed to be at least 4. */
553 int name_type1
, name_type2
;
554 int name_len1
, name_len2
;
558 if (sconn
->nbt
.got_session
) {
559 exit_server_cleanly("multiple session request not permitted");
562 SCVAL(outbuf
,0,NBSSpositive
);
565 /* inbuf_size is guaranteed to be at least 4. */
566 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
567 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
568 DEBUG(0,("Invalid name length in session request\n"));
569 reply_called_name_not_present(outbuf
);
572 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
573 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
574 DEBUG(0,("Invalid name length in session request\n"));
575 reply_called_name_not_present(outbuf
);
579 name_type1
= name_extract((unsigned char *)inbuf
,
580 inbuf_size
,(unsigned int)4,name1
);
581 name_type2
= name_extract((unsigned char *)inbuf
,
582 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
584 if (name_type1
== -1 || name_type2
== -1) {
585 DEBUG(0,("Invalid name type in session request\n"));
586 reply_called_name_not_present(outbuf
);
590 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
591 name1
, name_type1
, name2
, name_type2
));
593 if (netbios_session_retarget(sconn
, name1
, name_type1
)) {
594 exit_server_cleanly("retargeted client");
598 * Windows NT/2k uses "*SMBSERVER" and XP uses
599 * "*SMBSERV" arrggg!!!
601 if (strequal(name1
, "*SMBSERVER ")
602 || strequal(name1
, "*SMBSERV ")) {
605 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
608 exit_server_cleanly("could not allocate raddr");
611 fstrcpy(name1
, raddr
);
614 set_local_machine_name(name1
, True
);
615 set_remote_machine_name(name2
, True
);
617 if (is_ipaddress(sconn
->remote_hostname
)) {
618 char *p
= discard_const_p(char, sconn
->remote_hostname
);
622 sconn
->remote_hostname
= talloc_strdup(sconn
,
623 get_remote_machine_name());
624 if (sconn
->remote_hostname
== NULL
) {
625 exit_server_cleanly("could not copy remote name");
627 sconn
->conn
->remote_hostname
= sconn
->remote_hostname
;
630 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
631 get_local_machine_name(), get_remote_machine_name(),
634 if (name_type2
== 'R') {
635 /* We are being asked for a pathworks session ---
637 reply_called_name_not_present(outbuf
);
641 reload_services(sconn
, conn_snum_used
, true);
644 sconn
->nbt
.got_session
= true;
648 case 0x89: /* session keepalive request
649 (some old clients produce this?) */
650 SCVAL(outbuf
,0,NBSSkeepalive
);
654 case NBSSpositive
: /* positive session response */
655 case NBSSnegative
: /* negative session response */
656 case NBSSretarget
: /* retarget session response */
657 DEBUG(0,("Unexpected session response\n"));
660 case NBSSkeepalive
: /* session keepalive */
665 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
666 msg_type
, msg_flags
));
668 srv_send_smb(sconn
, outbuf
, false, 0, false, NULL
);
670 if (CVAL(outbuf
, 0) != 0x82) {
671 exit_server_cleanly("invalid netbios session");
676 /****************************************************************************
678 conn POINTER CAN BE NULL HERE !
679 ****************************************************************************/
681 void reply_tcon(struct smb_request
*req
)
683 connection_struct
*conn
= req
->conn
;
685 char *service_buf
= NULL
;
686 char *password
= NULL
;
691 TALLOC_CTX
*ctx
= talloc_tos();
692 struct smbd_server_connection
*sconn
= req
->sconn
;
693 NTTIME now
= timeval_to_nttime(&req
->request_time
);
695 START_PROFILE(SMBtcon
);
697 if (req
->buflen
< 4) {
698 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
699 END_PROFILE(SMBtcon
);
703 p
= (const char *)req
->buf
+ 1;
704 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
706 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
708 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
711 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
712 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
713 END_PROFILE(SMBtcon
);
716 p
= strrchr_m(service_buf
,'\\');
720 service
= service_buf
;
723 conn
= make_connection(sconn
, now
, service
, dev
,
724 req
->vuid
,&nt_status
);
728 reply_nterror(req
, nt_status
);
729 END_PROFILE(SMBtcon
);
733 reply_outbuf(req
, 2, 0);
734 SSVAL(req
->outbuf
,smb_vwv0
,sconn
->smb1
.negprot
.max_recv
);
735 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
736 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
738 DEBUG(3,("tcon service=%s cnum=%d\n",
739 service
, conn
->cnum
));
741 END_PROFILE(SMBtcon
);
745 /****************************************************************************
746 Reply to a tcon and X.
747 conn POINTER CAN BE NULL HERE !
748 ****************************************************************************/
750 void reply_tcon_and_X(struct smb_request
*req
)
752 connection_struct
*conn
= req
->conn
;
753 const char *service
= NULL
;
754 TALLOC_CTX
*ctx
= talloc_tos();
755 /* what the cleint thinks the device is */
756 char *client_devicetype
= NULL
;
757 /* what the server tells the client the share represents */
758 const char *server_devicetype
;
764 struct smbXsrv_session
*session
= NULL
;
765 NTTIME now
= timeval_to_nttime(&req
->request_time
);
766 bool session_key_updated
= false;
767 uint16_t optional_support
= 0;
768 struct smbd_server_connection
*sconn
= req
->sconn
;
770 START_PROFILE(SMBtconX
);
773 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
774 END_PROFILE(SMBtconX
);
778 passlen
= SVAL(req
->vwv
+3, 0);
779 tcon_flags
= SVAL(req
->vwv
+2, 0);
781 /* we might have to close an old one */
782 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
783 struct smbXsrv_tcon
*tcon
;
791 * TODO: cancel all outstanding requests on the tcon
793 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
794 if (!NT_STATUS_IS_OK(status
)) {
795 DEBUG(0, ("reply_tcon_and_X: "
796 "smbXsrv_tcon_disconnect() failed: %s\n",
799 * If we hit this case, there is something completely
800 * wrong, so we better disconnect the transport connection.
802 END_PROFILE(SMBtconX
);
803 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
810 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
811 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
812 END_PROFILE(SMBtconX
);
816 if (sconn
->smb1
.negprot
.encrypted_passwords
) {
817 p
= (const char *)req
->buf
+ passlen
;
819 p
= (const char *)req
->buf
+ passlen
+ 1;
822 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
825 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
826 END_PROFILE(SMBtconX
);
831 * the service name can be either: \\server\share
832 * or share directly like on the DELL PowerVault 705
835 q
= strchr_m(path
+2,'\\');
837 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
838 END_PROFILE(SMBtconX
);
846 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
847 &client_devicetype
, p
,
848 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
850 if (client_devicetype
== NULL
) {
851 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
852 END_PROFILE(SMBtconX
);
856 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
858 nt_status
= smb1srv_session_lookup(req
->sconn
->conn
,
859 req
->vuid
, now
, &session
);
860 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
861 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
862 END_PROFILE(SMBtconX
);
865 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
866 reply_nterror(req
, nt_status
);
867 END_PROFILE(SMBtconX
);
870 if (!NT_STATUS_IS_OK(nt_status
)) {
871 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
872 END_PROFILE(SMBtconX
);
876 if (session
->global
->auth_session_info
== NULL
) {
877 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
878 END_PROFILE(SMBtconX
);
883 * If there is no application key defined yet
886 * This means we setup the application key on the
887 * first tcon that happens via the given session.
889 * Once the application key is defined, it does not
892 if (session
->global
->application_key
.length
== 0 &&
893 session
->global
->signing_key
.length
> 0)
895 struct smbXsrv_session
*x
= session
;
896 struct auth_session_info
*session_info
=
897 session
->global
->auth_session_info
;
898 uint8_t session_key
[16];
900 ZERO_STRUCT(session_key
);
901 memcpy(session_key
, x
->global
->signing_key
.data
,
902 MIN(x
->global
->signing_key
.length
, sizeof(session_key
)));
905 * The application key is truncated/padded to 16 bytes
907 x
->global
->application_key
= data_blob_talloc(x
->global
,
909 sizeof(session_key
));
910 ZERO_STRUCT(session_key
);
911 if (x
->global
->application_key
.data
== NULL
) {
912 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
913 END_PROFILE(SMBtconX
);
917 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
918 smb_key_derivation(x
->global
->application_key
.data
,
919 x
->global
->application_key
.length
,
920 x
->global
->application_key
.data
);
921 optional_support
|= SMB_EXTENDED_SIGNATURES
;
925 * Place the application key into the session_info
927 data_blob_clear_free(&session_info
->session_key
);
928 session_info
->session_key
= data_blob_dup_talloc(session_info
,
929 x
->global
->application_key
);
930 if (session_info
->session_key
.data
== NULL
) {
931 data_blob_clear_free(&x
->global
->application_key
);
932 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
933 END_PROFILE(SMBtconX
);
936 session_key_updated
= true;
939 conn
= make_connection(sconn
, now
, service
, client_devicetype
,
940 req
->vuid
, &nt_status
);
944 if (session_key_updated
) {
945 struct smbXsrv_session
*x
= session
;
946 struct auth_session_info
*session_info
=
947 session
->global
->auth_session_info
;
948 data_blob_clear_free(&x
->global
->application_key
);
949 data_blob_clear_free(&session_info
->session_key
);
951 reply_nterror(req
, nt_status
);
952 END_PROFILE(SMBtconX
);
957 server_devicetype
= "IPC";
958 else if ( IS_PRINT(conn
) )
959 server_devicetype
= "LPT1:";
961 server_devicetype
= "A:";
963 if (get_Protocol() < PROTOCOL_NT1
) {
964 reply_outbuf(req
, 2, 0);
965 if (message_push_string(&req
->outbuf
, server_devicetype
,
966 STR_TERMINATE
|STR_ASCII
) == -1) {
967 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
968 END_PROFILE(SMBtconX
);
972 /* NT sets the fstype of IPC$ to the null string */
973 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(ctx
, SNUM(conn
));
975 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
976 /* Return permissions. */
980 reply_outbuf(req
, 7, 0);
983 perm1
= FILE_ALL_ACCESS
;
984 perm2
= FILE_ALL_ACCESS
;
986 perm1
= conn
->share_access
;
989 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
990 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
992 reply_outbuf(req
, 3, 0);
995 if ((message_push_string(&req
->outbuf
, server_devicetype
,
996 STR_TERMINATE
|STR_ASCII
) == -1)
997 || (message_push_string(&req
->outbuf
, fstype
,
998 STR_TERMINATE
) == -1)) {
999 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1000 END_PROFILE(SMBtconX
);
1004 /* what does setting this bit do? It is set by NT4 and
1005 may affect the ability to autorun mounted cdroms */
1006 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
1008 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
1010 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
1011 DEBUG(2,("Serving %s as a Dfs root\n",
1012 lp_servicename(ctx
, SNUM(conn
)) ));
1013 optional_support
|= SMB_SHARE_IN_DFS
;
1016 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
1019 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1020 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1022 DEBUG(3,("tconX service=%s \n",
1025 /* set the incoming and outgoing tid to the just created one */
1026 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1027 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1029 END_PROFILE(SMBtconX
);
1031 req
->tid
= conn
->cnum
;
1034 /****************************************************************************
1035 Reply to an unknown type.
1036 ****************************************************************************/
1038 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
1040 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1041 smb_fn_name(type
), type
, type
));
1042 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1046 /****************************************************************************
1048 conn POINTER CAN BE NULL HERE !
1049 ****************************************************************************/
1051 void reply_ioctl(struct smb_request
*req
)
1053 connection_struct
*conn
= req
->conn
;
1060 START_PROFILE(SMBioctl
);
1063 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1064 END_PROFILE(SMBioctl
);
1068 device
= SVAL(req
->vwv
+1, 0);
1069 function
= SVAL(req
->vwv
+2, 0);
1070 ioctl_code
= (device
<< 16) + function
;
1072 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1074 switch (ioctl_code
) {
1075 case IOCTL_QUERY_JOB_INFO
:
1079 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1080 END_PROFILE(SMBioctl
);
1084 reply_outbuf(req
, 8, replysize
+1);
1085 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1086 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1087 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1088 p
= smb_buf(req
->outbuf
);
1089 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1090 p
+= 1; /* Allow for alignment */
1092 switch (ioctl_code
) {
1093 case IOCTL_QUERY_JOB_INFO
:
1095 files_struct
*fsp
= file_fsp(
1096 req
, SVAL(req
->vwv
+0, 0));
1098 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1099 END_PROFILE(SMBioctl
);
1103 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1105 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1106 lp_netbios_name(), 15,
1107 STR_TERMINATE
|STR_ASCII
);
1109 srvstr_push((char *)req
->outbuf
, req
->flags2
,
1111 lp_servicename(talloc_tos(),
1113 13, STR_TERMINATE
|STR_ASCII
);
1115 memset(p
+18, 0, 13);
1121 END_PROFILE(SMBioctl
);
1125 /****************************************************************************
1126 Strange checkpath NTSTATUS mapping.
1127 ****************************************************************************/
1129 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1131 /* Strange DOS error code semantics only for checkpath... */
1132 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1133 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1134 /* We need to map to ERRbadpath */
1135 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1141 /****************************************************************************
1142 Reply to a checkpath.
1143 ****************************************************************************/
1145 void reply_checkpath(struct smb_request
*req
)
1147 connection_struct
*conn
= req
->conn
;
1148 struct smb_filename
*smb_fname
= NULL
;
1151 TALLOC_CTX
*ctx
= talloc_tos();
1153 START_PROFILE(SMBcheckpath
);
1155 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1156 STR_TERMINATE
, &status
);
1158 if (!NT_STATUS_IS_OK(status
)) {
1159 status
= map_checkpath_error(req
->flags2
, status
);
1160 reply_nterror(req
, status
);
1161 END_PROFILE(SMBcheckpath
);
1165 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1167 status
= filename_convert(ctx
,
1169 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1175 if (!NT_STATUS_IS_OK(status
)) {
1176 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1177 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1178 ERRSRV
, ERRbadpath
);
1179 END_PROFILE(SMBcheckpath
);
1185 if (!VALID_STAT(smb_fname
->st
) &&
1186 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1187 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1188 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1189 status
= map_nt_error_from_unix(errno
);
1193 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1194 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1195 ERRDOS
, ERRbadpath
);
1199 reply_outbuf(req
, 0, 0);
1202 /* We special case this - as when a Windows machine
1203 is parsing a path is steps through the components
1204 one at a time - if a component fails it expects
1205 ERRbadpath, not ERRbadfile.
1207 status
= map_checkpath_error(req
->flags2
, status
);
1208 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1210 * Windows returns different error codes if
1211 * the parent directory is valid but not the
1212 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1213 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1214 * if the path is invalid.
1216 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1217 ERRDOS
, ERRbadpath
);
1221 reply_nterror(req
, status
);
1224 TALLOC_FREE(smb_fname
);
1225 END_PROFILE(SMBcheckpath
);
1229 /****************************************************************************
1231 ****************************************************************************/
1233 void reply_getatr(struct smb_request
*req
)
1235 connection_struct
*conn
= req
->conn
;
1236 struct smb_filename
*smb_fname
= NULL
;
1243 TALLOC_CTX
*ctx
= talloc_tos();
1244 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1246 START_PROFILE(SMBgetatr
);
1248 p
= (const char *)req
->buf
+ 1;
1249 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1250 if (!NT_STATUS_IS_OK(status
)) {
1251 reply_nterror(req
, status
);
1255 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1256 under WfWg - weird! */
1257 if (*fname
== '\0') {
1258 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1259 if (!CAN_WRITE(conn
)) {
1260 mode
|= FILE_ATTRIBUTE_READONLY
;
1265 status
= filename_convert(ctx
,
1267 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1272 if (!NT_STATUS_IS_OK(status
)) {
1273 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1274 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1275 ERRSRV
, ERRbadpath
);
1278 reply_nterror(req
, status
);
1281 if (!VALID_STAT(smb_fname
->st
) &&
1282 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1283 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1284 smb_fname_str_dbg(smb_fname
),
1286 reply_nterror(req
, map_nt_error_from_unix(errno
));
1290 mode
= dos_mode(conn
, smb_fname
);
1291 size
= smb_fname
->st
.st_ex_size
;
1293 if (ask_sharemode
) {
1294 struct timespec write_time_ts
;
1295 struct file_id fileid
;
1297 ZERO_STRUCT(write_time_ts
);
1298 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1299 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1300 if (!null_timespec(write_time_ts
)) {
1301 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1305 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1306 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1311 reply_outbuf(req
, 10, 0);
1313 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1314 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1315 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1317 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1319 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1321 if (get_Protocol() >= PROTOCOL_NT1
) {
1322 SSVAL(req
->outbuf
, smb_flg2
,
1323 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1326 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1327 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1330 TALLOC_FREE(smb_fname
);
1332 END_PROFILE(SMBgetatr
);
1336 /****************************************************************************
1338 ****************************************************************************/
1340 void reply_setatr(struct smb_request
*req
)
1342 struct smb_file_time ft
;
1343 connection_struct
*conn
= req
->conn
;
1344 struct smb_filename
*smb_fname
= NULL
;
1350 TALLOC_CTX
*ctx
= talloc_tos();
1352 START_PROFILE(SMBsetatr
);
1357 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1361 p
= (const char *)req
->buf
+ 1;
1362 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1363 if (!NT_STATUS_IS_OK(status
)) {
1364 reply_nterror(req
, status
);
1368 status
= filename_convert(ctx
,
1370 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1375 if (!NT_STATUS_IS_OK(status
)) {
1376 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1377 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1378 ERRSRV
, ERRbadpath
);
1381 reply_nterror(req
, status
);
1385 if (smb_fname
->base_name
[0] == '.' &&
1386 smb_fname
->base_name
[1] == '\0') {
1388 * Not sure here is the right place to catch this
1389 * condition. Might be moved to somewhere else later -- vl
1391 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1395 mode
= SVAL(req
->vwv
+0, 0);
1396 mtime
= srv_make_unix_date3(req
->vwv
+1);
1398 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1399 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1400 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1402 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1404 status
= check_access(conn
, NULL
, smb_fname
,
1405 FILE_WRITE_ATTRIBUTES
);
1406 if (!NT_STATUS_IS_OK(status
)) {
1407 reply_nterror(req
, status
);
1411 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1413 reply_nterror(req
, map_nt_error_from_unix(errno
));
1418 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1419 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1420 if (!NT_STATUS_IS_OK(status
)) {
1421 reply_nterror(req
, status
);
1425 reply_outbuf(req
, 0, 0);
1427 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1430 TALLOC_FREE(smb_fname
);
1431 END_PROFILE(SMBsetatr
);
1435 /****************************************************************************
1437 ****************************************************************************/
1439 void reply_dskattr(struct smb_request
*req
)
1441 connection_struct
*conn
= req
->conn
;
1442 uint64_t dfree
,dsize
,bsize
;
1443 START_PROFILE(SMBdskattr
);
1445 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1446 reply_nterror(req
, map_nt_error_from_unix(errno
));
1447 END_PROFILE(SMBdskattr
);
1451 reply_outbuf(req
, 5, 0);
1453 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1454 double total_space
, free_space
;
1455 /* we need to scale this to a number that DOS6 can handle. We
1456 use floating point so we can handle large drives on systems
1457 that don't have 64 bit integers
1459 we end up displaying a maximum of 2G to DOS systems
1461 total_space
= dsize
* (double)bsize
;
1462 free_space
= dfree
* (double)bsize
;
1464 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1465 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1467 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1468 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1470 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1471 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1472 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1473 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1475 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1476 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1477 SSVAL(req
->outbuf
,smb_vwv2
,512);
1478 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1481 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1483 END_PROFILE(SMBdskattr
);
1488 * Utility function to split the filename from the directory.
1490 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1491 char **fname_dir_out
,
1492 char **fname_mask_out
)
1494 const char *p
= NULL
;
1495 char *fname_dir
= NULL
;
1496 char *fname_mask
= NULL
;
1498 p
= strrchr_m(fname_in
, '/');
1500 fname_dir
= talloc_strdup(ctx
, ".");
1501 fname_mask
= talloc_strdup(ctx
, fname_in
);
1503 fname_dir
= talloc_strndup(ctx
, fname_in
,
1504 PTR_DIFF(p
, fname_in
));
1505 fname_mask
= talloc_strdup(ctx
, p
+1);
1508 if (!fname_dir
|| !fname_mask
) {
1509 TALLOC_FREE(fname_dir
);
1510 TALLOC_FREE(fname_mask
);
1511 return NT_STATUS_NO_MEMORY
;
1514 *fname_dir_out
= fname_dir
;
1515 *fname_mask_out
= fname_mask
;
1516 return NT_STATUS_OK
;
1519 /****************************************************************************
1521 Can be called from SMBsearch, SMBffirst or SMBfunique.
1522 ****************************************************************************/
1524 void reply_search(struct smb_request
*req
)
1526 connection_struct
*conn
= req
->conn
;
1528 const char *mask
= NULL
;
1529 char *directory
= NULL
;
1530 struct smb_filename
*smb_fname
= NULL
;
1534 struct timespec date
;
1536 unsigned int numentries
= 0;
1537 unsigned int maxentries
= 0;
1538 bool finished
= False
;
1543 bool check_descend
= False
;
1544 bool expect_close
= False
;
1546 bool mask_contains_wcard
= False
;
1547 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1548 TALLOC_CTX
*ctx
= talloc_tos();
1549 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1550 struct dptr_struct
*dirptr
= NULL
;
1551 struct smbd_server_connection
*sconn
= req
->sconn
;
1553 START_PROFILE(SMBsearch
);
1556 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1560 if (lp_posix_pathnames()) {
1561 reply_unknown_new(req
, req
->cmd
);
1565 /* If we were called as SMBffirst then we must expect close. */
1566 if(req
->cmd
== SMBffirst
) {
1567 expect_close
= True
;
1570 reply_outbuf(req
, 1, 3);
1571 maxentries
= SVAL(req
->vwv
+0, 0);
1572 dirtype
= SVAL(req
->vwv
+1, 0);
1573 p
= (const char *)req
->buf
+ 1;
1574 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1575 &nt_status
, &mask_contains_wcard
);
1576 if (!NT_STATUS_IS_OK(nt_status
)) {
1577 reply_nterror(req
, nt_status
);
1582 status_len
= SVAL(p
, 0);
1585 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1587 if (status_len
== 0) {
1588 nt_status
= filename_convert(ctx
, conn
,
1589 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1591 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1592 &mask_contains_wcard
,
1594 if (!NT_STATUS_IS_OK(nt_status
)) {
1595 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1596 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1597 ERRSRV
, ERRbadpath
);
1600 reply_nterror(req
, nt_status
);
1604 directory
= smb_fname
->base_name
;
1606 p
= strrchr_m(directory
,'/');
1607 if ((p
!= NULL
) && (*directory
!= '/')) {
1609 directory
= talloc_strndup(ctx
, directory
,
1610 PTR_DIFF(p
, directory
));
1613 directory
= talloc_strdup(ctx
,".");
1617 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1621 memset((char *)status
,'\0',21);
1622 SCVAL(status
,0,(dirtype
& 0x1F));
1624 nt_status
= dptr_create(conn
,
1632 mask_contains_wcard
,
1635 if (!NT_STATUS_IS_OK(nt_status
)) {
1636 reply_nterror(req
, nt_status
);
1639 dptr_num
= dptr_dnum(dirptr
);
1642 const char *dirpath
;
1644 memcpy(status
,p
,21);
1645 status_dirtype
= CVAL(status
,0) & 0x1F;
1646 if (status_dirtype
!= (dirtype
& 0x1F)) {
1647 dirtype
= status_dirtype
;
1650 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1654 dirpath
= dptr_path(sconn
, dptr_num
);
1655 directory
= talloc_strdup(ctx
, dirpath
);
1657 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1661 mask
= dptr_wcard(sconn
, dptr_num
);
1666 * For a 'continue' search we have no string. So
1667 * check from the initial saved string.
1669 mask_contains_wcard
= ms_has_wild(mask
);
1670 dirtype
= dptr_attr(sconn
, dptr_num
);
1673 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1675 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1676 dptr_init_search_op(dirptr
);
1678 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1679 char buf
[DIR_STRUCT_SIZE
];
1680 memcpy(buf
,status
,21);
1681 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1682 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1683 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1686 dptr_fill(sconn
, buf
+12,dptr_num
);
1687 if (dptr_zero(buf
+12) && (status_len
==0)) {
1692 if (message_push_blob(&req
->outbuf
,
1693 data_blob_const(buf
, sizeof(buf
)))
1695 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1703 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1706 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1707 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
1708 if (in_list(directory
, lp_dontdescend(ctx
, SNUM(conn
)),True
)) {
1709 check_descend
= True
;
1712 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1713 finished
= !get_dir_entry(ctx
,
1724 char buf
[DIR_STRUCT_SIZE
];
1725 memcpy(buf
,status
,21);
1726 if (!make_dir_struct(ctx
,
1732 convert_timespec_to_time_t(date
),
1733 !allow_long_path_components
)) {
1734 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1737 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1740 if (message_push_blob(&req
->outbuf
,
1741 data_blob_const(buf
, sizeof(buf
)))
1743 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1753 /* If we were called as SMBffirst with smb_search_id == NULL
1754 and no entries were found then return error and close dirptr
1757 if (numentries
== 0) {
1758 dptr_close(sconn
, &dptr_num
);
1759 } else if(expect_close
&& status_len
== 0) {
1760 /* Close the dptr - we know it's gone */
1761 dptr_close(sconn
, &dptr_num
);
1764 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1765 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1766 dptr_close(sconn
, &dptr_num
);
1769 if ((numentries
== 0) && !mask_contains_wcard
) {
1770 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1774 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1775 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1776 SCVAL(smb_buf(req
->outbuf
),0,5);
1777 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1779 /* The replies here are never long name. */
1780 SSVAL(req
->outbuf
, smb_flg2
,
1781 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1782 if (!allow_long_path_components
) {
1783 SSVAL(req
->outbuf
, smb_flg2
,
1784 SVAL(req
->outbuf
, smb_flg2
)
1785 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1788 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1789 SSVAL(req
->outbuf
, smb_flg2
,
1790 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1792 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1793 smb_fn_name(req
->cmd
),
1800 TALLOC_FREE(directory
);
1801 TALLOC_FREE(smb_fname
);
1802 END_PROFILE(SMBsearch
);
1806 /****************************************************************************
1807 Reply to a fclose (stop directory search).
1808 ****************************************************************************/
1810 void reply_fclose(struct smb_request
*req
)
1818 bool path_contains_wcard
= False
;
1819 TALLOC_CTX
*ctx
= talloc_tos();
1820 struct smbd_server_connection
*sconn
= req
->sconn
;
1822 START_PROFILE(SMBfclose
);
1824 if (lp_posix_pathnames()) {
1825 reply_unknown_new(req
, req
->cmd
);
1826 END_PROFILE(SMBfclose
);
1830 p
= (const char *)req
->buf
+ 1;
1831 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1832 &err
, &path_contains_wcard
);
1833 if (!NT_STATUS_IS_OK(err
)) {
1834 reply_nterror(req
, err
);
1835 END_PROFILE(SMBfclose
);
1839 status_len
= SVAL(p
,0);
1842 if (status_len
== 0) {
1843 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1844 END_PROFILE(SMBfclose
);
1848 memcpy(status
,p
,21);
1850 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1851 /* Close the dptr - we know it's gone */
1852 dptr_close(sconn
, &dptr_num
);
1855 reply_outbuf(req
, 1, 0);
1856 SSVAL(req
->outbuf
,smb_vwv0
,0);
1858 DEBUG(3,("search close\n"));
1860 END_PROFILE(SMBfclose
);
1864 /****************************************************************************
1866 ****************************************************************************/
1868 void reply_open(struct smb_request
*req
)
1870 connection_struct
*conn
= req
->conn
;
1871 struct smb_filename
*smb_fname
= NULL
;
1883 uint32 create_disposition
;
1884 uint32 create_options
= 0;
1885 uint32_t private_flags
= 0;
1887 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1888 TALLOC_CTX
*ctx
= talloc_tos();
1890 START_PROFILE(SMBopen
);
1893 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1897 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1898 deny_mode
= SVAL(req
->vwv
+0, 0);
1899 dos_attr
= SVAL(req
->vwv
+1, 0);
1901 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1902 STR_TERMINATE
, &status
);
1903 if (!NT_STATUS_IS_OK(status
)) {
1904 reply_nterror(req
, status
);
1908 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1909 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1910 &share_mode
, &create_disposition
,
1911 &create_options
, &private_flags
)) {
1912 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1916 status
= filename_convert(ctx
,
1918 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1920 UCF_PREP_CREATEFILE
,
1923 if (!NT_STATUS_IS_OK(status
)) {
1924 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1925 reply_botherror(req
,
1926 NT_STATUS_PATH_NOT_COVERED
,
1927 ERRSRV
, ERRbadpath
);
1930 reply_nterror(req
, status
);
1934 status
= SMB_VFS_CREATE_FILE(
1937 0, /* root_dir_fid */
1938 smb_fname
, /* fname */
1939 access_mask
, /* access_mask */
1940 share_mode
, /* share_access */
1941 create_disposition
, /* create_disposition*/
1942 create_options
, /* create_options */
1943 dos_attr
, /* file_attributes */
1944 oplock_request
, /* oplock_request */
1945 0, /* allocation_size */
1952 if (!NT_STATUS_IS_OK(status
)) {
1953 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1954 /* We have re-scheduled this call. */
1957 reply_openerror(req
, status
);
1961 size
= smb_fname
->st
.st_ex_size
;
1962 fattr
= dos_mode(conn
, smb_fname
);
1964 /* Deal with other possible opens having a modified
1966 if (ask_sharemode
) {
1967 struct timespec write_time_ts
;
1969 ZERO_STRUCT(write_time_ts
);
1970 get_file_infos(fsp
->file_id
, 0, NULL
, &write_time_ts
);
1971 if (!null_timespec(write_time_ts
)) {
1972 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1976 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1978 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1979 DEBUG(3,("attempt to open a directory %s\n",
1981 close_file(req
, fsp
, ERROR_CLOSE
);
1982 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1983 ERRDOS
, ERRnoaccess
);
1987 reply_outbuf(req
, 7, 0);
1988 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1989 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1990 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1991 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1993 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1995 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1996 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1998 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1999 SCVAL(req
->outbuf
,smb_flg
,
2000 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2003 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2004 SCVAL(req
->outbuf
,smb_flg
,
2005 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2008 TALLOC_FREE(smb_fname
);
2009 END_PROFILE(SMBopen
);
2013 /****************************************************************************
2014 Reply to an open and X.
2015 ****************************************************************************/
2017 void reply_open_and_X(struct smb_request
*req
)
2019 connection_struct
*conn
= req
->conn
;
2020 struct smb_filename
*smb_fname
= NULL
;
2025 /* Breakout the oplock request bits so we can set the
2026 reply bits separately. */
2027 int ex_oplock_request
;
2028 int core_oplock_request
;
2031 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2032 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
2040 uint64_t allocation_size
;
2041 ssize_t retval
= -1;
2044 uint32 create_disposition
;
2045 uint32 create_options
= 0;
2046 uint32_t private_flags
= 0;
2047 TALLOC_CTX
*ctx
= talloc_tos();
2049 START_PROFILE(SMBopenX
);
2051 if (req
->wct
< 15) {
2052 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2056 open_flags
= SVAL(req
->vwv
+2, 0);
2057 deny_mode
= SVAL(req
->vwv
+3, 0);
2058 smb_attr
= SVAL(req
->vwv
+5, 0);
2059 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2060 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2061 oplock_request
= ex_oplock_request
| core_oplock_request
;
2062 smb_ofun
= SVAL(req
->vwv
+8, 0);
2063 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2065 /* If it's an IPC, pass off the pipe handler. */
2067 if (lp_nt_pipe_support()) {
2068 reply_open_pipe_and_X(conn
, req
);
2070 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2075 /* XXXX we need to handle passed times, sattr and flags */
2076 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2077 STR_TERMINATE
, &status
);
2078 if (!NT_STATUS_IS_OK(status
)) {
2079 reply_nterror(req
, status
);
2083 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2085 &access_mask
, &share_mode
,
2086 &create_disposition
,
2089 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2093 status
= filename_convert(ctx
,
2095 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2097 UCF_PREP_CREATEFILE
,
2100 if (!NT_STATUS_IS_OK(status
)) {
2101 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2102 reply_botherror(req
,
2103 NT_STATUS_PATH_NOT_COVERED
,
2104 ERRSRV
, ERRbadpath
);
2107 reply_nterror(req
, status
);
2111 status
= SMB_VFS_CREATE_FILE(
2114 0, /* root_dir_fid */
2115 smb_fname
, /* fname */
2116 access_mask
, /* access_mask */
2117 share_mode
, /* share_access */
2118 create_disposition
, /* create_disposition*/
2119 create_options
, /* create_options */
2120 smb_attr
, /* file_attributes */
2121 oplock_request
, /* oplock_request */
2122 0, /* allocation_size */
2127 &smb_action
); /* pinfo */
2129 if (!NT_STATUS_IS_OK(status
)) {
2130 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2131 /* We have re-scheduled this call. */
2134 reply_openerror(req
, status
);
2138 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2139 if the file is truncated or created. */
2140 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2141 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2142 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2143 close_file(req
, fsp
, ERROR_CLOSE
);
2144 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2147 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2149 close_file(req
, fsp
, ERROR_CLOSE
);
2150 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2153 status
= vfs_stat_fsp(fsp
);
2154 if (!NT_STATUS_IS_OK(status
)) {
2155 close_file(req
, fsp
, ERROR_CLOSE
);
2156 reply_nterror(req
, status
);
2161 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2162 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2163 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2164 close_file(req
, fsp
, ERROR_CLOSE
);
2165 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2169 /* If the caller set the extended oplock request bit
2170 and we granted one (by whatever means) - set the
2171 correct bit for extended oplock reply.
2174 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2175 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2178 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2179 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2182 /* If the caller set the core oplock request bit
2183 and we granted one (by whatever means) - set the
2184 correct bit for core oplock reply.
2187 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2188 reply_outbuf(req
, 19, 0);
2190 reply_outbuf(req
, 15, 0);
2193 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2194 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2196 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2197 SCVAL(req
->outbuf
, smb_flg
,
2198 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2201 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2202 SCVAL(req
->outbuf
, smb_flg
,
2203 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2206 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2207 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2208 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2209 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2211 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2213 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2214 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2215 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2217 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2218 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2222 TALLOC_FREE(smb_fname
);
2223 END_PROFILE(SMBopenX
);
2227 /****************************************************************************
2228 Reply to a SMBulogoffX.
2229 ****************************************************************************/
2231 void reply_ulogoffX(struct smb_request
*req
)
2233 struct smbd_server_connection
*sconn
= req
->sconn
;
2234 struct user_struct
*vuser
;
2235 struct smbXsrv_session
*session
= NULL
;
2238 START_PROFILE(SMBulogoffX
);
2240 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2243 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2244 (unsigned long long)req
->vuid
));
2246 req
->vuid
= UID_FIELD_INVALID
;
2247 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2248 END_PROFILE(SMBulogoffX
);
2252 session
= vuser
->session
;
2256 * TODO: cancel all outstanding requests on the session
2258 status
= smbXsrv_session_logoff(session
);
2259 if (!NT_STATUS_IS_OK(status
)) {
2260 DEBUG(0, ("reply_ulogoff: "
2261 "smbXsrv_session_logoff() failed: %s\n",
2262 nt_errstr(status
)));
2264 * If we hit this case, there is something completely
2265 * wrong, so we better disconnect the transport connection.
2267 END_PROFILE(SMBulogoffX
);
2268 exit_server(__location__
": smbXsrv_session_logoff failed");
2272 TALLOC_FREE(session
);
2274 reply_outbuf(req
, 2, 0);
2275 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2276 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2278 DEBUG(3, ("ulogoffX vuid=%llu\n",
2279 (unsigned long long)req
->vuid
));
2281 END_PROFILE(SMBulogoffX
);
2282 req
->vuid
= UID_FIELD_INVALID
;
2285 /****************************************************************************
2286 Reply to a mknew or a create.
2287 ****************************************************************************/
2289 void reply_mknew(struct smb_request
*req
)
2291 connection_struct
*conn
= req
->conn
;
2292 struct smb_filename
*smb_fname
= NULL
;
2295 struct smb_file_time ft
;
2297 int oplock_request
= 0;
2299 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2300 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2301 uint32 create_disposition
;
2302 uint32 create_options
= 0;
2303 TALLOC_CTX
*ctx
= talloc_tos();
2305 START_PROFILE(SMBcreate
);
2309 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2313 fattr
= SVAL(req
->vwv
+0, 0);
2314 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2317 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2319 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2320 STR_TERMINATE
, &status
);
2321 if (!NT_STATUS_IS_OK(status
)) {
2322 reply_nterror(req
, status
);
2326 status
= filename_convert(ctx
,
2328 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2330 UCF_PREP_CREATEFILE
,
2333 if (!NT_STATUS_IS_OK(status
)) {
2334 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2335 reply_botherror(req
,
2336 NT_STATUS_PATH_NOT_COVERED
,
2337 ERRSRV
, ERRbadpath
);
2340 reply_nterror(req
, status
);
2344 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2345 DEBUG(0,("Attempt to create file (%s) with volid set - "
2346 "please report this\n",
2347 smb_fname_str_dbg(smb_fname
)));
2350 if(req
->cmd
== SMBmknew
) {
2351 /* We should fail if file exists. */
2352 create_disposition
= FILE_CREATE
;
2354 /* Create if file doesn't exist, truncate if it does. */
2355 create_disposition
= FILE_OVERWRITE_IF
;
2358 status
= SMB_VFS_CREATE_FILE(
2361 0, /* root_dir_fid */
2362 smb_fname
, /* fname */
2363 access_mask
, /* access_mask */
2364 share_mode
, /* share_access */
2365 create_disposition
, /* create_disposition*/
2366 create_options
, /* create_options */
2367 fattr
, /* file_attributes */
2368 oplock_request
, /* oplock_request */
2369 0, /* allocation_size */
2370 0, /* private_flags */
2376 if (!NT_STATUS_IS_OK(status
)) {
2377 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2378 /* We have re-scheduled this call. */
2381 reply_openerror(req
, status
);
2385 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2386 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2387 if (!NT_STATUS_IS_OK(status
)) {
2388 END_PROFILE(SMBcreate
);
2392 reply_outbuf(req
, 1, 0);
2393 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2395 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2396 SCVAL(req
->outbuf
,smb_flg
,
2397 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2400 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2401 SCVAL(req
->outbuf
,smb_flg
,
2402 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2405 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2406 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2407 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2408 (unsigned int)fattr
));
2411 TALLOC_FREE(smb_fname
);
2412 END_PROFILE(SMBcreate
);
2416 /****************************************************************************
2417 Reply to a create temporary file.
2418 ****************************************************************************/
2420 void reply_ctemp(struct smb_request
*req
)
2422 connection_struct
*conn
= req
->conn
;
2423 struct smb_filename
*smb_fname
= NULL
;
2424 char *wire_name
= NULL
;
2432 TALLOC_CTX
*ctx
= talloc_tos();
2434 START_PROFILE(SMBctemp
);
2437 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2441 fattr
= SVAL(req
->vwv
+0, 0);
2442 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2444 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2445 STR_TERMINATE
, &status
);
2446 if (!NT_STATUS_IS_OK(status
)) {
2447 reply_nterror(req
, status
);
2451 for (i
= 0; i
< 10; i
++) {
2453 fname
= talloc_asprintf(ctx
,
2456 generate_random_str_list(ctx
, 5, "0123456789"));
2458 fname
= talloc_asprintf(ctx
,
2460 generate_random_str_list(ctx
, 5, "0123456789"));
2464 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2468 status
= filename_convert(ctx
, conn
,
2469 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2471 UCF_PREP_CREATEFILE
,
2474 if (!NT_STATUS_IS_OK(status
)) {
2475 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2476 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2477 ERRSRV
, ERRbadpath
);
2480 reply_nterror(req
, status
);
2484 /* Create the file. */
2485 status
= SMB_VFS_CREATE_FILE(
2488 0, /* root_dir_fid */
2489 smb_fname
, /* fname */
2490 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2491 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2492 FILE_CREATE
, /* create_disposition*/
2493 0, /* create_options */
2494 fattr
, /* file_attributes */
2495 oplock_request
, /* oplock_request */
2496 0, /* allocation_size */
2497 0, /* private_flags */
2503 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2505 TALLOC_FREE(smb_fname
);
2509 if (!NT_STATUS_IS_OK(status
)) {
2510 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2511 /* We have re-scheduled this call. */
2514 reply_openerror(req
, status
);
2522 /* Collision after 10 times... */
2523 reply_nterror(req
, status
);
2527 reply_outbuf(req
, 1, 0);
2528 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2530 /* the returned filename is relative to the directory */
2531 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2533 s
= fsp
->fsp_name
->base_name
;
2539 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2540 thing in the byte section. JRA */
2541 SSVALS(p
, 0, -1); /* what is this? not in spec */
2543 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2545 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2549 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2550 SCVAL(req
->outbuf
, smb_flg
,
2551 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2554 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2555 SCVAL(req
->outbuf
, smb_flg
,
2556 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2559 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2560 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2561 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2563 TALLOC_FREE(smb_fname
);
2564 TALLOC_FREE(wire_name
);
2565 END_PROFILE(SMBctemp
);
2569 /*******************************************************************
2570 Check if a user is allowed to rename a file.
2571 ********************************************************************/
2573 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2576 if (!CAN_WRITE(conn
)) {
2577 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2580 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2581 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2582 /* Only bother to read the DOS attribute if we might deny the
2583 rename on the grounds of attribute missmatch. */
2584 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2585 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2586 return NT_STATUS_NO_SUCH_FILE
;
2590 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2591 if (fsp
->posix_open
) {
2592 return NT_STATUS_OK
;
2595 /* If no pathnames are open below this
2596 directory, allow the rename. */
2598 if (file_find_subpath(fsp
)) {
2599 return NT_STATUS_ACCESS_DENIED
;
2601 return NT_STATUS_OK
;
2604 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2605 return NT_STATUS_OK
;
2608 return NT_STATUS_ACCESS_DENIED
;
2611 /*******************************************************************
2612 * unlink a file with all relevant access checks
2613 *******************************************************************/
2615 static NTSTATUS
do_unlink(connection_struct
*conn
,
2616 struct smb_request
*req
,
2617 struct smb_filename
*smb_fname
,
2622 uint32 dirtype_orig
= dirtype
;
2625 bool posix_paths
= lp_posix_pathnames();
2627 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2628 smb_fname_str_dbg(smb_fname
),
2631 if (!CAN_WRITE(conn
)) {
2632 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2636 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2638 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2641 return map_nt_error_from_unix(errno
);
2644 fattr
= dos_mode(conn
, smb_fname
);
2646 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2647 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2650 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2652 return NT_STATUS_NO_SUCH_FILE
;
2655 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2656 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2657 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2659 return NT_STATUS_NO_SUCH_FILE
;
2662 if (dirtype_orig
& 0x8000) {
2663 /* These will never be set for POSIX. */
2664 return NT_STATUS_NO_SUCH_FILE
;
2668 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2669 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2672 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2673 return NT_STATUS_NO_SUCH_FILE
;
2676 if (dirtype
& 0xFF00) {
2677 /* These will never be set for POSIX. */
2678 return NT_STATUS_NO_SUCH_FILE
;
2683 return NT_STATUS_NO_SUCH_FILE
;
2686 /* Can't delete a directory. */
2687 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2688 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2693 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2694 return NT_STATUS_OBJECT_NAME_INVALID
;
2695 #endif /* JRATEST */
2697 /* On open checks the open itself will check the share mode, so
2698 don't do it here as we'll get it wrong. */
2700 status
= SMB_VFS_CREATE_FILE
2703 0, /* root_dir_fid */
2704 smb_fname
, /* fname */
2705 DELETE_ACCESS
, /* access_mask */
2706 FILE_SHARE_NONE
, /* share_access */
2707 FILE_OPEN
, /* create_disposition*/
2708 FILE_NON_DIRECTORY_FILE
, /* create_options */
2709 /* file_attributes */
2710 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2711 FILE_ATTRIBUTE_NORMAL
,
2712 0, /* oplock_request */
2713 0, /* allocation_size */
2714 0, /* private_flags */
2720 if (!NT_STATUS_IS_OK(status
)) {
2721 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2722 nt_errstr(status
)));
2726 status
= can_set_delete_on_close(fsp
, fattr
);
2727 if (!NT_STATUS_IS_OK(status
)) {
2728 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2730 smb_fname_str_dbg(smb_fname
),
2731 nt_errstr(status
)));
2732 close_file(req
, fsp
, NORMAL_CLOSE
);
2736 /* The set is across all open files on this dev/inode pair. */
2737 if (!set_delete_on_close(fsp
, True
,
2738 conn
->session_info
->security_token
,
2739 conn
->session_info
->unix_token
)) {
2740 close_file(req
, fsp
, NORMAL_CLOSE
);
2741 return NT_STATUS_ACCESS_DENIED
;
2744 return close_file(req
, fsp
, NORMAL_CLOSE
);
2747 /****************************************************************************
2748 The guts of the unlink command, split out so it may be called by the NT SMB
2750 ****************************************************************************/
2752 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2753 uint32 dirtype
, struct smb_filename
*smb_fname
,
2756 char *fname_dir
= NULL
;
2757 char *fname_mask
= NULL
;
2759 NTSTATUS status
= NT_STATUS_OK
;
2760 TALLOC_CTX
*ctx
= talloc_tos();
2762 /* Split up the directory from the filename/mask. */
2763 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2764 &fname_dir
, &fname_mask
);
2765 if (!NT_STATUS_IS_OK(status
)) {
2770 * We should only check the mangled cache
2771 * here if unix_convert failed. This means
2772 * that the path in 'mask' doesn't exist
2773 * on the file system and so we need to look
2774 * for a possible mangle. This patch from
2775 * Tine Smukavec <valentin.smukavec@hermes.si>.
2778 if (!VALID_STAT(smb_fname
->st
) &&
2779 mangle_is_mangled(fname_mask
, conn
->params
)) {
2780 char *new_mask
= NULL
;
2781 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2782 &new_mask
, conn
->params
);
2784 TALLOC_FREE(fname_mask
);
2785 fname_mask
= new_mask
;
2792 * Only one file needs to be unlinked. Append the mask back
2793 * onto the directory.
2795 TALLOC_FREE(smb_fname
->base_name
);
2796 if (ISDOT(fname_dir
)) {
2797 /* Ensure we use canonical names on open. */
2798 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2802 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2807 if (!smb_fname
->base_name
) {
2808 status
= NT_STATUS_NO_MEMORY
;
2812 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2815 status
= check_name(conn
, smb_fname
->base_name
);
2816 if (!NT_STATUS_IS_OK(status
)) {
2820 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2821 if (!NT_STATUS_IS_OK(status
)) {
2827 struct smb_Dir
*dir_hnd
= NULL
;
2829 const char *dname
= NULL
;
2830 char *talloced
= NULL
;
2832 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2833 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2837 if (strequal(fname_mask
,"????????.???")) {
2838 TALLOC_FREE(fname_mask
);
2839 fname_mask
= talloc_strdup(ctx
, "*");
2841 status
= NT_STATUS_NO_MEMORY
;
2846 status
= check_name(conn
, fname_dir
);
2847 if (!NT_STATUS_IS_OK(status
)) {
2851 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2853 if (dir_hnd
== NULL
) {
2854 status
= map_nt_error_from_unix(errno
);
2858 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2859 the pattern matches against the long name, otherwise the short name
2860 We don't implement this yet XXXX
2863 status
= NT_STATUS_NO_SUCH_FILE
;
2865 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2866 &smb_fname
->st
, &talloced
))) {
2867 TALLOC_CTX
*frame
= talloc_stackframe();
2869 if (!is_visible_file(conn
, fname_dir
, dname
,
2870 &smb_fname
->st
, true)) {
2872 TALLOC_FREE(talloced
);
2876 /* Quick check for "." and ".." */
2877 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2879 TALLOC_FREE(talloced
);
2883 if(!mask_match(dname
, fname_mask
,
2884 conn
->case_sensitive
)) {
2886 TALLOC_FREE(talloced
);
2890 TALLOC_FREE(smb_fname
->base_name
);
2891 if (ISDOT(fname_dir
)) {
2892 /* Ensure we use canonical names on open. */
2893 smb_fname
->base_name
=
2894 talloc_asprintf(smb_fname
, "%s",
2897 smb_fname
->base_name
=
2898 talloc_asprintf(smb_fname
, "%s/%s",
2902 if (!smb_fname
->base_name
) {
2903 TALLOC_FREE(dir_hnd
);
2904 status
= NT_STATUS_NO_MEMORY
;
2906 TALLOC_FREE(talloced
);
2910 status
= check_name(conn
, smb_fname
->base_name
);
2911 if (!NT_STATUS_IS_OK(status
)) {
2912 TALLOC_FREE(dir_hnd
);
2914 TALLOC_FREE(talloced
);
2918 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2919 if (!NT_STATUS_IS_OK(status
)) {
2921 TALLOC_FREE(talloced
);
2926 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2927 smb_fname
->base_name
));
2930 TALLOC_FREE(talloced
);
2932 TALLOC_FREE(dir_hnd
);
2935 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2936 status
= map_nt_error_from_unix(errno
);
2940 TALLOC_FREE(fname_dir
);
2941 TALLOC_FREE(fname_mask
);
2945 /****************************************************************************
2947 ****************************************************************************/
2949 void reply_unlink(struct smb_request
*req
)
2951 connection_struct
*conn
= req
->conn
;
2953 struct smb_filename
*smb_fname
= NULL
;
2956 bool path_contains_wcard
= False
;
2957 TALLOC_CTX
*ctx
= talloc_tos();
2959 START_PROFILE(SMBunlink
);
2962 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2966 dirtype
= SVAL(req
->vwv
+0, 0);
2968 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2969 STR_TERMINATE
, &status
,
2970 &path_contains_wcard
);
2971 if (!NT_STATUS_IS_OK(status
)) {
2972 reply_nterror(req
, status
);
2976 status
= filename_convert(ctx
, conn
,
2977 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2979 UCF_COND_ALLOW_WCARD_LCOMP
,
2980 &path_contains_wcard
,
2982 if (!NT_STATUS_IS_OK(status
)) {
2983 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2984 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2985 ERRSRV
, ERRbadpath
);
2988 reply_nterror(req
, status
);
2992 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2994 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2995 path_contains_wcard
);
2996 if (!NT_STATUS_IS_OK(status
)) {
2997 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2998 /* We have re-scheduled this call. */
3001 reply_nterror(req
, status
);
3005 reply_outbuf(req
, 0, 0);
3007 TALLOC_FREE(smb_fname
);
3008 END_PROFILE(SMBunlink
);
3012 /****************************************************************************
3014 ****************************************************************************/
3016 static void fail_readraw(void)
3018 const char *errstr
= talloc_asprintf(talloc_tos(),
3019 "FAIL ! reply_readbraw: socket write fail (%s)",
3024 exit_server_cleanly(errstr
);
3027 /****************************************************************************
3028 Fake (read/write) sendfile. Returns -1 on read or write fail.
3029 ****************************************************************************/
3031 ssize_t
fake_sendfile(files_struct
*fsp
, off_t startpos
, size_t nread
)
3034 size_t tosend
= nread
;
3041 bufsize
= MIN(nread
, 65536);
3043 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3047 while (tosend
> 0) {
3051 if (tosend
> bufsize
) {
3056 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3062 /* If we had a short read, fill with zeros. */
3063 if (ret
< cur_read
) {
3064 memset(buf
+ ret
, '\0', cur_read
- ret
);
3067 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
3069 char addr
[INET6_ADDRSTRLEN
];
3071 * Try and give an error message saying what
3074 DEBUG(0, ("write_data failed for client %s. "
3076 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3083 startpos
+= cur_read
;
3087 return (ssize_t
)nread
;
3090 /****************************************************************************
3091 Deal with the case of sendfile reading less bytes from the file than
3092 requested. Fill with zeros (all we can do).
3093 ****************************************************************************/
3095 void sendfile_short_send(files_struct
*fsp
,
3100 #define SHORT_SEND_BUFSIZE 1024
3101 if (nread
< headersize
) {
3102 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3103 "header for file %s (%s). Terminating\n",
3104 fsp_str_dbg(fsp
), strerror(errno
)));
3105 exit_server_cleanly("sendfile_short_send failed");
3108 nread
-= headersize
;
3110 if (nread
< smb_maxcnt
) {
3111 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3113 exit_server_cleanly("sendfile_short_send: "
3117 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3118 "with zeros !\n", fsp_str_dbg(fsp
)));
3120 while (nread
< smb_maxcnt
) {
3122 * We asked for the real file size and told sendfile
3123 * to not go beyond the end of the file. But it can
3124 * happen that in between our fstat call and the
3125 * sendfile call the file was truncated. This is very
3126 * bad because we have already announced the larger
3127 * number of bytes to the client.
3129 * The best we can do now is to send 0-bytes, just as
3130 * a read from a hole in a sparse file would do.
3132 * This should happen rarely enough that I don't care
3133 * about efficiency here :-)
3137 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3138 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
3140 char addr
[INET6_ADDRSTRLEN
];
3142 * Try and give an error message saying what
3145 DEBUG(0, ("write_data failed for client %s. "
3148 fsp
->conn
->sconn
->sock
, addr
,
3151 exit_server_cleanly("sendfile_short_send: "
3152 "write_data failed");
3160 /****************************************************************************
3161 Return a readbraw error (4 bytes of zero).
3162 ****************************************************************************/
3164 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
3170 smbd_lock_socket(sconn
);
3171 if (write_data(sconn
->sock
,header
,4) != 4) {
3172 char addr
[INET6_ADDRSTRLEN
];
3174 * Try and give an error message saying what
3177 DEBUG(0, ("write_data failed for client %s. "
3179 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
3184 smbd_unlock_socket(sconn
);
3187 /****************************************************************************
3188 Use sendfile in readbraw.
3189 ****************************************************************************/
3191 static void send_file_readbraw(connection_struct
*conn
,
3192 struct smb_request
*req
,
3198 struct smbd_server_connection
*sconn
= req
->sconn
;
3199 char *outbuf
= NULL
;
3203 * We can only use sendfile on a non-chained packet
3204 * but we can use on a non-oplocked file. tridge proved this
3205 * on a train in Germany :-). JRA.
3206 * reply_readbraw has already checked the length.
3209 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3210 (fsp
->wcp
== NULL
) &&
3211 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3212 ssize_t sendfile_read
= -1;
3214 DATA_BLOB header_blob
;
3216 _smb_setlen(header
,nread
);
3217 header_blob
= data_blob_const(header
, 4);
3219 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3220 &header_blob
, startpos
,
3222 if (sendfile_read
== -1) {
3223 /* Returning ENOSYS means no data at all was sent.
3224 * Do this as a normal read. */
3225 if (errno
== ENOSYS
) {
3226 goto normal_readbraw
;
3230 * Special hack for broken Linux with no working sendfile. If we
3231 * return EINTR we sent the header but not the rest of the data.
3232 * Fake this up by doing read/write calls.
3234 if (errno
== EINTR
) {
3235 /* Ensure we don't do this again. */
3236 set_use_sendfile(SNUM(conn
), False
);
3237 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3239 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3240 DEBUG(0,("send_file_readbraw: "
3241 "fake_sendfile failed for "
3245 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3250 DEBUG(0,("send_file_readbraw: sendfile failed for "
3251 "file %s (%s). Terminating\n",
3252 fsp_str_dbg(fsp
), strerror(errno
)));
3253 exit_server_cleanly("send_file_readbraw sendfile failed");
3254 } else if (sendfile_read
== 0) {
3256 * Some sendfile implementations return 0 to indicate
3257 * that there was a short read, but nothing was
3258 * actually written to the socket. In this case,
3259 * fallback to the normal read path so the header gets
3260 * the correct byte count.
3262 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3263 "bytes falling back to the normal read: "
3264 "%s\n", fsp_str_dbg(fsp
)));
3265 goto normal_readbraw
;
3268 /* Deal with possible short send. */
3269 if (sendfile_read
!= 4+nread
) {
3270 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3277 outbuf
= talloc_array(NULL
, char, nread
+4);
3279 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3280 (unsigned)(nread
+4)));
3281 reply_readbraw_error(sconn
);
3286 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3287 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3296 _smb_setlen(outbuf
,ret
);
3297 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3298 char addr
[INET6_ADDRSTRLEN
];
3300 * Try and give an error message saying what
3303 DEBUG(0, ("write_data failed for client %s. "
3305 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3312 TALLOC_FREE(outbuf
);
3315 /****************************************************************************
3316 Reply to a readbraw (core+ protocol).
3317 ****************************************************************************/
3319 void reply_readbraw(struct smb_request
*req
)
3321 connection_struct
*conn
= req
->conn
;
3322 struct smbd_server_connection
*sconn
= req
->sconn
;
3323 ssize_t maxcount
,mincount
;
3327 struct lock_struct lock
;
3330 START_PROFILE(SMBreadbraw
);
3332 if (srv_is_signing_active(sconn
) || req
->encrypted
) {
3333 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3334 "raw reads/writes are disallowed.");
3338 reply_readbraw_error(sconn
);
3339 END_PROFILE(SMBreadbraw
);
3343 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3344 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3345 "'async smb echo handler = yes'\n"));
3346 reply_readbraw_error(sconn
);
3347 END_PROFILE(SMBreadbraw
);
3352 * Special check if an oplock break has been issued
3353 * and the readraw request croses on the wire, we must
3354 * return a zero length response here.
3357 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3360 * We have to do a check_fsp by hand here, as
3361 * we must always return 4 zero bytes on error,
3365 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3366 req
->vuid
!= fsp
->vuid
||
3367 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3369 * fsp could be NULL here so use the value from the packet. JRA.
3371 DEBUG(3,("reply_readbraw: fnum %d not valid "
3373 (int)SVAL(req
->vwv
+0, 0)));
3374 reply_readbraw_error(sconn
);
3375 END_PROFILE(SMBreadbraw
);
3379 /* Do a "by hand" version of CHECK_READ. */
3380 if (!(fsp
->can_read
||
3381 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3382 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3383 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3384 (int)SVAL(req
->vwv
+0, 0)));
3385 reply_readbraw_error(sconn
);
3386 END_PROFILE(SMBreadbraw
);
3390 flush_write_cache(fsp
, READRAW_FLUSH
);
3392 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3393 if(req
->wct
== 10) {
3395 * This is a large offset (64 bit) read.
3398 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3401 DEBUG(0,("reply_readbraw: negative 64 bit "
3402 "readraw offset (%.0f) !\n",
3403 (double)startpos
));
3404 reply_readbraw_error(sconn
);
3405 END_PROFILE(SMBreadbraw
);
3410 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3411 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3413 /* ensure we don't overrun the packet size */
3414 maxcount
= MIN(65535,maxcount
);
3416 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3417 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3420 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3421 reply_readbraw_error(sconn
);
3422 END_PROFILE(SMBreadbraw
);
3426 if (fsp_stat(fsp
) == 0) {
3427 size
= fsp
->fsp_name
->st
.st_ex_size
;
3430 if (startpos
>= size
) {
3433 nread
= MIN(maxcount
,(size
- startpos
));
3436 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3437 if (nread
< mincount
)
3441 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3442 "min=%lu nread=%lu\n",
3443 fsp_fnum_dbg(fsp
), (double)startpos
,
3444 (unsigned long)maxcount
,
3445 (unsigned long)mincount
,
3446 (unsigned long)nread
) );
3448 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3450 DEBUG(5,("reply_readbraw finished\n"));
3452 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3454 END_PROFILE(SMBreadbraw
);
3459 #define DBGC_CLASS DBGC_LOCKING
3461 /****************************************************************************
3462 Reply to a lockread (core+ protocol).
3463 ****************************************************************************/
3465 void reply_lockread(struct smb_request
*req
)
3467 connection_struct
*conn
= req
->conn
;
3474 struct byte_range_lock
*br_lck
= NULL
;
3476 struct smbd_server_connection
*sconn
= req
->sconn
;
3478 START_PROFILE(SMBlockread
);
3481 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3482 END_PROFILE(SMBlockread
);
3486 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3488 if (!check_fsp(conn
, req
, fsp
)) {
3489 END_PROFILE(SMBlockread
);
3493 if (!CHECK_READ(fsp
,req
)) {
3494 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3495 END_PROFILE(SMBlockread
);
3499 numtoread
= SVAL(req
->vwv
+1, 0);
3500 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3502 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3504 reply_outbuf(req
, 5, numtoread
+ 3);
3506 data
= smb_buf(req
->outbuf
) + 3;
3509 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3510 * protocol request that predates the read/write lock concept.
3511 * Thus instead of asking for a read lock here we need to ask
3512 * for a write lock. JRA.
3513 * Note that the requested lock size is unaffected by max_recv.
3516 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3518 (uint64_t)req
->smbpid
,
3519 (uint64_t)numtoread
,
3523 False
, /* Non-blocking lock. */
3527 TALLOC_FREE(br_lck
);
3529 if (NT_STATUS_V(status
)) {
3530 reply_nterror(req
, status
);
3531 END_PROFILE(SMBlockread
);
3536 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3539 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3540 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3541 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3542 (unsigned int)numtoread
,
3543 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3544 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3546 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3549 reply_nterror(req
, map_nt_error_from_unix(errno
));
3550 END_PROFILE(SMBlockread
);
3554 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3556 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3557 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3558 p
= smb_buf(req
->outbuf
);
3559 SCVAL(p
,0,0); /* pad byte. */
3562 DEBUG(3,("lockread %s num=%d nread=%d\n",
3563 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3565 END_PROFILE(SMBlockread
);
3570 #define DBGC_CLASS DBGC_ALL
3572 /****************************************************************************
3574 ****************************************************************************/
3576 void reply_read(struct smb_request
*req
)
3578 connection_struct
*conn
= req
->conn
;
3585 struct lock_struct lock
;
3586 struct smbd_server_connection
*sconn
= req
->sconn
;
3588 START_PROFILE(SMBread
);
3591 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3592 END_PROFILE(SMBread
);
3596 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3598 if (!check_fsp(conn
, req
, fsp
)) {
3599 END_PROFILE(SMBread
);
3603 if (!CHECK_READ(fsp
,req
)) {
3604 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3605 END_PROFILE(SMBread
);
3609 numtoread
= SVAL(req
->vwv
+1, 0);
3610 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3612 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3615 * The requested read size cannot be greater than max_recv. JRA.
3617 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3618 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3619 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3620 (unsigned int)numtoread
,
3621 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3622 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3625 reply_outbuf(req
, 5, numtoread
+3);
3627 data
= smb_buf(req
->outbuf
) + 3;
3629 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3630 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3633 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3634 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3635 END_PROFILE(SMBread
);
3640 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3643 reply_nterror(req
, map_nt_error_from_unix(errno
));
3647 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3649 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3650 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3651 SCVAL(smb_buf(req
->outbuf
),0,1);
3652 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3654 DEBUG(3, ("read %s num=%d nread=%d\n",
3655 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3658 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3660 END_PROFILE(SMBread
);
3664 /****************************************************************************
3666 ****************************************************************************/
3668 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3673 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3675 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3677 SCVAL(outbuf
,smb_vwv0
,0xFF);
3678 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3679 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3680 SSVAL(outbuf
,smb_vwv6
,
3681 (smb_wct
- 4) /* offset from smb header to wct */
3682 + 1 /* the wct field */
3683 + 12 * sizeof(uint16_t) /* vwv */
3684 + 2); /* the buflen field */
3685 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3686 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3687 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3688 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3692 /****************************************************************************
3693 Reply to a read and X - possibly using sendfile.
3694 ****************************************************************************/
3696 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3697 files_struct
*fsp
, off_t startpos
,
3701 struct lock_struct lock
;
3702 int saved_errno
= 0;
3704 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3705 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3708 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3709 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3714 * We can only use sendfile on a non-chained packet
3715 * but we can use on a non-oplocked file. tridge proved this
3716 * on a train in Germany :-). JRA.
3719 if (!req_is_in_chain(req
) &&
3721 (fsp
->base_fsp
== NULL
) &&
3722 (fsp
->wcp
== NULL
) &&
3723 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3724 uint8 headerbuf
[smb_size
+ 12 * 2];
3727 if(fsp_stat(fsp
) == -1) {
3728 reply_nterror(req
, map_nt_error_from_unix(errno
));
3732 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3733 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3734 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3736 * We already know that we would do a short read, so don't
3737 * try the sendfile() path.
3739 goto nosendfile_read
;
3743 * Set up the packet header before send. We
3744 * assume here the sendfile will work (get the
3745 * correct amount of data).
3748 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3750 construct_reply_common_req(req
, (char *)headerbuf
);
3751 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3753 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3754 startpos
, smb_maxcnt
);
3756 /* Returning ENOSYS means no data at all was sent.
3757 Do this as a normal read. */
3758 if (errno
== ENOSYS
) {
3763 * Special hack for broken Linux with no working sendfile. If we
3764 * return EINTR we sent the header but not the rest of the data.
3765 * Fake this up by doing read/write calls.
3768 if (errno
== EINTR
) {
3769 /* Ensure we don't do this again. */
3770 set_use_sendfile(SNUM(conn
), False
);
3771 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3772 nread
= fake_sendfile(fsp
, startpos
,
3775 DEBUG(0,("send_file_readX: "
3776 "fake_sendfile failed for "
3780 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3782 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3783 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3784 /* No outbuf here means successful sendfile. */
3788 DEBUG(0,("send_file_readX: sendfile failed for file "
3789 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3791 exit_server_cleanly("send_file_readX sendfile failed");
3792 } else if (nread
== 0) {
3794 * Some sendfile implementations return 0 to indicate
3795 * that there was a short read, but nothing was
3796 * actually written to the socket. In this case,
3797 * fallback to the normal read path so the header gets
3798 * the correct byte count.
3800 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3801 "falling back to the normal read: %s\n",
3806 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3807 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3809 /* Deal with possible short send. */
3810 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3811 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3813 /* No outbuf here means successful sendfile. */
3814 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3815 SMB_PERFCOUNT_END(&req
->pcd
);
3821 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3822 uint8 headerbuf
[smb_size
+ 2*12];
3824 construct_reply_common_req(req
, (char *)headerbuf
);
3825 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3827 /* Send out the header. */
3828 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3829 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3831 char addr
[INET6_ADDRSTRLEN
];
3833 * Try and give an error message saying what
3836 DEBUG(0, ("write_data failed for client %s. "
3838 get_peer_addr(req
->sconn
->sock
, addr
,
3842 DEBUG(0,("send_file_readX: write_data failed for file "
3843 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3845 exit_server_cleanly("send_file_readX sendfile failed");
3847 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3849 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3850 "file %s (%s).\n", fsp_str_dbg(fsp
),
3852 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3859 reply_outbuf(req
, 12, smb_maxcnt
);
3860 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
3861 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
3863 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3864 saved_errno
= errno
;
3866 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3869 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3873 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3875 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3876 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3880 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3881 TALLOC_FREE(req
->outbuf
);
3885 /****************************************************************************
3886 Work out how much space we have for a read return.
3887 ****************************************************************************/
3889 static size_t calc_max_read_pdu(const struct smb_request
*req
)
3891 if (req
->sconn
->conn
->protocol
< PROTOCOL_NT1
) {
3892 return req
->sconn
->smb1
.sessions
.max_send
;
3895 if (!lp_large_readwrite()) {
3896 return req
->sconn
->smb1
.sessions
.max_send
;
3899 if (req_is_in_chain(req
)) {
3900 return req
->sconn
->smb1
.sessions
.max_send
;
3903 if (req
->encrypted
) {
3905 * Don't take encrypted traffic up to the
3906 * limit. There are padding considerations
3907 * that make that tricky.
3909 return req
->sconn
->smb1
.sessions
.max_send
;
3912 if (srv_is_signing_active(req
->sconn
)) {
3916 if (!lp_unix_extensions()) {
3921 * We can do ultra-large POSIX reads.
3926 /****************************************************************************
3927 Calculate how big a read can be. Copes with all clients. It's always
3928 safe to return a short read - Windows does this.
3929 ****************************************************************************/
3931 static size_t calc_read_size(const struct smb_request
*req
,
3935 size_t max_pdu
= calc_max_read_pdu(req
);
3936 size_t total_size
= 0;
3937 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
3938 size_t max_len
= max_pdu
- hdr_len
;
3941 * Windows explicitly ignores upper size of 0xFFFF.
3942 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3943 * We must do the same as these will never fit even in
3944 * an extended size NetBIOS packet.
3946 if (upper_size
== 0xFFFF) {
3950 if (req
->sconn
->conn
->protocol
< PROTOCOL_NT1
) {
3954 total_size
= ((upper_size
<<16) | lower_size
);
3957 * LARGE_READX test shows it's always safe to return
3958 * a short read. Windows does so.
3960 return MIN(total_size
, max_len
);
3963 /****************************************************************************
3964 Reply to a read and X.
3965 ****************************************************************************/
3967 void reply_read_and_X(struct smb_request
*req
)
3969 connection_struct
*conn
= req
->conn
;
3974 bool big_readX
= False
;
3976 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3979 START_PROFILE(SMBreadX
);
3981 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3982 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3986 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3987 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3988 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3990 /* If it's an IPC, pass off the pipe handler. */
3992 reply_pipe_read_and_X(req
);
3993 END_PROFILE(SMBreadX
);
3997 if (!check_fsp(conn
, req
, fsp
)) {
3998 END_PROFILE(SMBreadX
);
4002 if (!CHECK_READ(fsp
,req
)) {
4003 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4004 END_PROFILE(SMBreadX
);
4008 upper_size
= SVAL(req
->vwv
+7, 0);
4009 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4010 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4012 * This is a heuristic to avoid keeping large
4013 * outgoing buffers around over long-lived aio
4019 if (req
->wct
== 12) {
4021 * This is a large offset (64 bit) read.
4023 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4028 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4033 if (NT_STATUS_IS_OK(status
)) {
4034 /* Read scheduled - we're done. */
4037 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4038 /* Real error - report to client. */
4039 END_PROFILE(SMBreadX
);
4040 reply_nterror(req
, status
);
4043 /* NT_STATUS_RETRY - fall back to sync read. */
4046 smbd_lock_socket(req
->sconn
);
4047 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4048 smbd_unlock_socket(req
->sconn
);
4051 END_PROFILE(SMBreadX
);
4055 /****************************************************************************
4056 Error replies to writebraw must have smb_wct == 1. Fix this up.
4057 ****************************************************************************/
4059 void error_to_writebrawerr(struct smb_request
*req
)
4061 uint8
*old_outbuf
= req
->outbuf
;
4063 reply_outbuf(req
, 1, 0);
4065 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4066 TALLOC_FREE(old_outbuf
);
4069 /****************************************************************************
4070 Read 4 bytes of a smb packet and return the smb length of the packet.
4071 Store the result in the buffer. This version of the function will
4072 never return a session keepalive (length of zero).
4073 Timeout is in milliseconds.
4074 ****************************************************************************/
4076 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4079 uint8_t msgtype
= NBSSkeepalive
;
4081 while (msgtype
== NBSSkeepalive
) {
4084 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4086 if (!NT_STATUS_IS_OK(status
)) {
4087 char addr
[INET6_ADDRSTRLEN
];
4088 /* Try and give an error message
4089 * saying what client failed. */
4090 DEBUG(0, ("read_fd_with_timeout failed for "
4091 "client %s read error = %s.\n",
4092 get_peer_addr(fd
,addr
,sizeof(addr
)),
4093 nt_errstr(status
)));
4097 msgtype
= CVAL(inbuf
, 0);
4100 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4101 (unsigned long)len
));
4103 return NT_STATUS_OK
;
4106 /****************************************************************************
4107 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4108 ****************************************************************************/
4110 void reply_writebraw(struct smb_request
*req
)
4112 connection_struct
*conn
= req
->conn
;
4115 ssize_t total_written
=0;
4116 size_t numtowrite
=0;
4119 const char *data
=NULL
;
4122 struct lock_struct lock
;
4125 START_PROFILE(SMBwritebraw
);
4128 * If we ever reply with an error, it must have the SMB command
4129 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4132 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4134 if (srv_is_signing_active(req
->sconn
)) {
4135 END_PROFILE(SMBwritebraw
);
4136 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4137 "raw reads/writes are disallowed.");
4140 if (req
->wct
< 12) {
4141 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4142 error_to_writebrawerr(req
);
4143 END_PROFILE(SMBwritebraw
);
4147 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
4148 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4149 "'async smb echo handler = yes'\n"));
4150 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4151 error_to_writebrawerr(req
);
4152 END_PROFILE(SMBwritebraw
);
4156 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4157 if (!check_fsp(conn
, req
, fsp
)) {
4158 error_to_writebrawerr(req
);
4159 END_PROFILE(SMBwritebraw
);
4163 if (!CHECK_WRITE(fsp
)) {
4164 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4165 error_to_writebrawerr(req
);
4166 END_PROFILE(SMBwritebraw
);
4170 tcount
= IVAL(req
->vwv
+1, 0);
4171 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4172 write_through
= BITSETW(req
->vwv
+7,0);
4174 /* We have to deal with slightly different formats depending
4175 on whether we are using the core+ or lanman1.0 protocol */
4177 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4178 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4179 data
= smb_buf_const(req
->inbuf
);
4181 numtowrite
= SVAL(req
->vwv
+10, 0);
4182 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4185 /* Ensure we don't write bytes past the end of this packet. */
4186 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4187 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4188 error_to_writebrawerr(req
);
4189 END_PROFILE(SMBwritebraw
);
4193 if (!fsp
->print_file
) {
4194 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4195 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4198 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4199 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4200 error_to_writebrawerr(req
);
4201 END_PROFILE(SMBwritebraw
);
4207 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4210 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4211 "wrote=%d sync=%d\n",
4212 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4213 (int)nwritten
, (int)write_through
));
4215 if (nwritten
< (ssize_t
)numtowrite
) {
4216 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4217 error_to_writebrawerr(req
);
4221 total_written
= nwritten
;
4223 /* Allocate a buffer of 64k + length. */
4224 buf
= talloc_array(NULL
, char, 65540);
4226 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4227 error_to_writebrawerr(req
);
4231 /* Return a SMBwritebraw message to the redirector to tell
4232 * it to send more bytes */
4234 memcpy(buf
, req
->inbuf
, smb_size
);
4235 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4236 SCVAL(buf
,smb_com
,SMBwritebraw
);
4237 SSVALS(buf
,smb_vwv0
,0xFFFF);
4239 if (!srv_send_smb(req
->sconn
,
4241 false, 0, /* no signing */
4242 IS_CONN_ENCRYPTED(conn
),
4244 exit_server_cleanly("reply_writebraw: srv_send_smb "
4248 /* Now read the raw data into the buffer and write it */
4249 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4251 if (!NT_STATUS_IS_OK(status
)) {
4252 exit_server_cleanly("secondary writebraw failed");
4255 /* Set up outbuf to return the correct size */
4256 reply_outbuf(req
, 1, 0);
4258 if (numtowrite
!= 0) {
4260 if (numtowrite
> 0xFFFF) {
4261 DEBUG(0,("reply_writebraw: Oversize secondary write "
4262 "raw requested (%u). Terminating\n",
4263 (unsigned int)numtowrite
));
4264 exit_server_cleanly("secondary writebraw failed");
4267 if (tcount
> nwritten
+numtowrite
) {
4268 DEBUG(3,("reply_writebraw: Client overestimated the "
4270 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4273 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4275 if (!NT_STATUS_IS_OK(status
)) {
4276 char addr
[INET6_ADDRSTRLEN
];
4277 /* Try and give an error message
4278 * saying what client failed. */
4279 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4280 "raw read failed (%s) for client %s. "
4281 "Terminating\n", nt_errstr(status
),
4282 get_peer_addr(req
->sconn
->sock
, addr
,
4284 exit_server_cleanly("secondary writebraw failed");
4287 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4288 if (nwritten
== -1) {
4290 reply_nterror(req
, map_nt_error_from_unix(errno
));
4291 error_to_writebrawerr(req
);
4295 if (nwritten
< (ssize_t
)numtowrite
) {
4296 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4297 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4301 total_written
+= nwritten
;
4306 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4308 status
= sync_file(conn
, fsp
, write_through
);
4309 if (!NT_STATUS_IS_OK(status
)) {
4310 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4311 fsp_str_dbg(fsp
), nt_errstr(status
)));
4312 reply_nterror(req
, status
);
4313 error_to_writebrawerr(req
);
4317 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4319 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4320 (int)total_written
));
4322 if (!fsp
->print_file
) {
4323 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4326 /* We won't return a status if write through is not selected - this
4327 * follows what WfWg does */
4328 END_PROFILE(SMBwritebraw
);
4330 if (!write_through
&& total_written
==tcount
) {
4332 #if RABBIT_PELLET_FIX
4334 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4335 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4338 if (!send_keepalive(req
->sconn
->sock
)) {
4339 exit_server_cleanly("reply_writebraw: send of "
4340 "keepalive failed");
4343 TALLOC_FREE(req
->outbuf
);
4348 if (!fsp
->print_file
) {
4349 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4352 END_PROFILE(SMBwritebraw
);
4357 #define DBGC_CLASS DBGC_LOCKING
4359 /****************************************************************************
4360 Reply to a writeunlock (core+).
4361 ****************************************************************************/
4363 void reply_writeunlock(struct smb_request
*req
)
4365 connection_struct
*conn
= req
->conn
;
4366 ssize_t nwritten
= -1;
4370 NTSTATUS status
= NT_STATUS_OK
;
4372 struct lock_struct lock
;
4373 int saved_errno
= 0;
4375 START_PROFILE(SMBwriteunlock
);
4378 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4379 END_PROFILE(SMBwriteunlock
);
4383 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4385 if (!check_fsp(conn
, req
, fsp
)) {
4386 END_PROFILE(SMBwriteunlock
);
4390 if (!CHECK_WRITE(fsp
)) {
4391 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4392 END_PROFILE(SMBwriteunlock
);
4396 numtowrite
= SVAL(req
->vwv
+1, 0);
4397 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4398 data
= (const char *)req
->buf
+ 3;
4400 if (!fsp
->print_file
&& numtowrite
> 0) {
4401 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4402 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4405 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4406 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4407 END_PROFILE(SMBwriteunlock
);
4412 /* The special X/Open SMB protocol handling of
4413 zero length writes is *NOT* done for
4415 if(numtowrite
== 0) {
4418 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4419 saved_errno
= errno
;
4422 status
= sync_file(conn
, fsp
, False
/* write through */);
4423 if (!NT_STATUS_IS_OK(status
)) {
4424 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4425 fsp_str_dbg(fsp
), nt_errstr(status
)));
4426 reply_nterror(req
, status
);
4431 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4435 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4436 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4440 if (numtowrite
&& !fsp
->print_file
) {
4441 status
= do_unlock(req
->sconn
->msg_ctx
,
4443 (uint64_t)req
->smbpid
,
4444 (uint64_t)numtowrite
,
4448 if (NT_STATUS_V(status
)) {
4449 reply_nterror(req
, status
);
4454 reply_outbuf(req
, 1, 0);
4456 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4458 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4459 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4462 if (numtowrite
&& !fsp
->print_file
) {
4463 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4466 END_PROFILE(SMBwriteunlock
);
4471 #define DBGC_CLASS DBGC_ALL
4473 /****************************************************************************
4475 ****************************************************************************/
4477 void reply_write(struct smb_request
*req
)
4479 connection_struct
*conn
= req
->conn
;
4481 ssize_t nwritten
= -1;
4485 struct lock_struct lock
;
4487 int saved_errno
= 0;
4489 START_PROFILE(SMBwrite
);
4492 END_PROFILE(SMBwrite
);
4493 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4497 /* If it's an IPC, pass off the pipe handler. */
4499 reply_pipe_write(req
);
4500 END_PROFILE(SMBwrite
);
4504 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4506 if (!check_fsp(conn
, req
, fsp
)) {
4507 END_PROFILE(SMBwrite
);
4511 if (!CHECK_WRITE(fsp
)) {
4512 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4513 END_PROFILE(SMBwrite
);
4517 numtowrite
= SVAL(req
->vwv
+1, 0);
4518 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4519 data
= (const char *)req
->buf
+ 3;
4521 if (!fsp
->print_file
) {
4522 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4523 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4526 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4527 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4528 END_PROFILE(SMBwrite
);
4534 * X/Open SMB protocol says that if smb_vwv1 is
4535 * zero then the file size should be extended or
4536 * truncated to the size given in smb_vwv[2-3].
4539 if(numtowrite
== 0) {
4541 * This is actually an allocate call, and set EOF. JRA.
4543 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4545 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4548 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4550 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4553 trigger_write_time_update_immediate(fsp
);
4555 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4558 status
= sync_file(conn
, fsp
, False
);
4559 if (!NT_STATUS_IS_OK(status
)) {
4560 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4561 fsp_str_dbg(fsp
), nt_errstr(status
)));
4562 reply_nterror(req
, status
);
4567 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4571 if((nwritten
== 0) && (numtowrite
!= 0)) {
4572 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4576 reply_outbuf(req
, 1, 0);
4578 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4580 if (nwritten
< (ssize_t
)numtowrite
) {
4581 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4582 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4585 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4588 if (!fsp
->print_file
) {
4589 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4592 END_PROFILE(SMBwrite
);
4596 /****************************************************************************
4597 Ensure a buffer is a valid writeX for recvfile purposes.
4598 ****************************************************************************/
4600 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4601 (2*14) + /* word count (including bcc) */ \
4604 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4605 const uint8_t *inbuf
)
4608 connection_struct
*conn
= NULL
;
4609 unsigned int doff
= 0;
4610 size_t len
= smb_len_large(inbuf
);
4611 struct smbXsrv_tcon
*tcon
;
4615 if (is_encrypted_packet(sconn
, inbuf
)) {
4616 /* Can't do this on encrypted
4621 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4625 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4626 CVAL(inbuf
,smb_wct
) != 14) {
4627 DEBUG(10,("is_valid_writeX_buffer: chained or "
4628 "invalid word length.\n"));
4632 status
= smb1srv_tcon_lookup(sconn
->conn
, SVAL(inbuf
, smb_tid
),
4634 if (!NT_STATUS_IS_OK(status
)) {
4635 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4638 conn
= tcon
->compat
;
4641 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4644 if (IS_PRINT(conn
)) {
4645 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4648 doff
= SVAL(inbuf
,smb_vwv11
);
4650 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4652 if (len
> doff
&& len
- doff
> 0xFFFF) {
4653 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4656 if (numtowrite
== 0) {
4657 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4661 /* Ensure the sizes match up. */
4662 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4663 /* no pad byte...old smbclient :-( */
4664 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4666 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4670 if (len
- doff
!= numtowrite
) {
4671 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4672 "len = %u, doff = %u, numtowrite = %u\n",
4675 (unsigned int)numtowrite
));
4679 DEBUG(10,("is_valid_writeX_buffer: true "
4680 "len = %u, doff = %u, numtowrite = %u\n",
4683 (unsigned int)numtowrite
));
4688 /****************************************************************************
4689 Reply to a write and X.
4690 ****************************************************************************/
4692 void reply_write_and_X(struct smb_request
*req
)
4694 connection_struct
*conn
= req
->conn
;
4696 struct lock_struct lock
;
4701 unsigned int smb_doff
;
4702 unsigned int smblen
;
4705 int saved_errno
= 0;
4707 START_PROFILE(SMBwriteX
);
4709 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4710 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4714 numtowrite
= SVAL(req
->vwv
+10, 0);
4715 smb_doff
= SVAL(req
->vwv
+11, 0);
4716 smblen
= smb_len(req
->inbuf
);
4718 if (req
->unread_bytes
> 0xFFFF ||
4719 (smblen
> smb_doff
&&
4720 smblen
- smb_doff
> 0xFFFF)) {
4721 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4724 if (req
->unread_bytes
) {
4725 /* Can't do a recvfile write on IPC$ */
4727 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4730 if (numtowrite
!= req
->unread_bytes
) {
4731 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4735 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4736 smb_doff
+ numtowrite
> smblen
) {
4737 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4742 /* If it's an IPC, pass off the pipe handler. */
4744 if (req
->unread_bytes
) {
4745 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4748 reply_pipe_write_and_X(req
);
4752 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4753 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4754 write_through
= BITSETW(req
->vwv
+7,0);
4756 if (!check_fsp(conn
, req
, fsp
)) {
4760 if (!CHECK_WRITE(fsp
)) {
4761 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4765 data
= smb_base(req
->inbuf
) + smb_doff
;
4767 if(req
->wct
== 14) {
4769 * This is a large offset (64 bit) write.
4771 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
4775 /* X/Open SMB protocol says that, unlike SMBwrite
4776 if the length is zero then NO truncation is
4777 done, just a write of zero. To truncate a file,
4780 if(numtowrite
== 0) {
4783 if (req
->unread_bytes
== 0) {
4784 status
= schedule_aio_write_and_X(conn
,
4791 if (NT_STATUS_IS_OK(status
)) {
4792 /* write scheduled - we're done. */
4795 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4796 /* Real error - report to client. */
4797 reply_nterror(req
, status
);
4800 /* NT_STATUS_RETRY - fall through to sync write. */
4803 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4804 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4807 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4808 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4812 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4813 saved_errno
= errno
;
4815 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4819 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4823 if((nwritten
== 0) && (numtowrite
!= 0)) {
4824 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4828 reply_outbuf(req
, 6, 0);
4829 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4830 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4831 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4832 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4834 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4835 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4837 status
= sync_file(conn
, fsp
, write_through
);
4838 if (!NT_STATUS_IS_OK(status
)) {
4839 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4840 fsp_str_dbg(fsp
), nt_errstr(status
)));
4841 reply_nterror(req
, status
);
4845 END_PROFILE(SMBwriteX
);
4849 if (req
->unread_bytes
) {
4850 /* writeX failed. drain socket. */
4851 if (drain_socket(req
->sconn
->sock
, req
->unread_bytes
) !=
4852 req
->unread_bytes
) {
4853 smb_panic("failed to drain pending bytes");
4855 req
->unread_bytes
= 0;
4858 END_PROFILE(SMBwriteX
);
4862 /****************************************************************************
4864 ****************************************************************************/
4866 void reply_lseek(struct smb_request
*req
)
4868 connection_struct
*conn
= req
->conn
;
4874 START_PROFILE(SMBlseek
);
4877 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4878 END_PROFILE(SMBlseek
);
4882 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4884 if (!check_fsp(conn
, req
, fsp
)) {
4888 flush_write_cache(fsp
, SEEK_FLUSH
);
4890 mode
= SVAL(req
->vwv
+1, 0) & 3;
4891 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4892 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
4901 res
= fsp
->fh
->pos
+ startpos
;
4912 if (umode
== SEEK_END
) {
4913 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4914 if(errno
== EINVAL
) {
4915 off_t current_pos
= startpos
;
4917 if(fsp_stat(fsp
) == -1) {
4919 map_nt_error_from_unix(errno
));
4920 END_PROFILE(SMBlseek
);
4924 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4926 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4931 reply_nterror(req
, map_nt_error_from_unix(errno
));
4932 END_PROFILE(SMBlseek
);
4939 reply_outbuf(req
, 2, 0);
4940 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4942 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4943 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
4945 END_PROFILE(SMBlseek
);
4949 /****************************************************************************
4951 ****************************************************************************/
4953 void reply_flush(struct smb_request
*req
)
4955 connection_struct
*conn
= req
->conn
;
4959 START_PROFILE(SMBflush
);
4962 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4966 fnum
= SVAL(req
->vwv
+0, 0);
4967 fsp
= file_fsp(req
, fnum
);
4969 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4974 file_sync_all(conn
);
4976 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4977 if (!NT_STATUS_IS_OK(status
)) {
4978 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4979 fsp_str_dbg(fsp
), nt_errstr(status
)));
4980 reply_nterror(req
, status
);
4981 END_PROFILE(SMBflush
);
4986 reply_outbuf(req
, 0, 0);
4988 DEBUG(3,("flush\n"));
4989 END_PROFILE(SMBflush
);
4993 /****************************************************************************
4995 conn POINTER CAN BE NULL HERE !
4996 ****************************************************************************/
4998 void reply_exit(struct smb_request
*req
)
5000 START_PROFILE(SMBexit
);
5002 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5004 reply_outbuf(req
, 0, 0);
5006 DEBUG(3,("exit\n"));
5008 END_PROFILE(SMBexit
);
5012 struct reply_close_state
{
5014 struct smb_request
*smbreq
;
5017 static void do_smb1_close(struct tevent_req
*req
);
5019 void reply_close(struct smb_request
*req
)
5021 connection_struct
*conn
= req
->conn
;
5022 NTSTATUS status
= NT_STATUS_OK
;
5023 files_struct
*fsp
= NULL
;
5024 START_PROFILE(SMBclose
);
5027 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5028 END_PROFILE(SMBclose
);
5032 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5035 * We can only use check_fsp if we know it's not a directory.
5038 if (!check_fsp_open(conn
, req
, fsp
)) {
5039 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5040 END_PROFILE(SMBclose
);
5044 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5045 fsp
->is_directory
? "directory" : "file",
5046 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5047 conn
->num_files_open
));
5049 if (!fsp
->is_directory
) {
5053 * Take care of any time sent in the close.
5056 t
= srv_make_unix_date3(req
->vwv
+1);
5057 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5060 if (fsp
->num_aio_requests
!= 0) {
5062 struct reply_close_state
*state
;
5064 DEBUG(10, ("closing with aio %u requests pending\n",
5065 fsp
->num_aio_requests
));
5068 * We depend on the aio_extra destructor to take care of this
5069 * close request once fsp->num_aio_request drops to 0.
5072 fsp
->deferred_close
= tevent_wait_send(
5073 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5074 if (fsp
->deferred_close
== NULL
) {
5075 status
= NT_STATUS_NO_MEMORY
;
5079 state
= talloc(fsp
, struct reply_close_state
);
5080 if (state
== NULL
) {
5081 TALLOC_FREE(fsp
->deferred_close
);
5082 status
= NT_STATUS_NO_MEMORY
;
5086 state
->smbreq
= talloc_move(fsp
, &req
);
5087 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5089 END_PROFILE(SMBclose
);
5094 * close_file() returns the unix errno if an error was detected on
5095 * close - normally this is due to a disk full error. If not then it
5096 * was probably an I/O error.
5099 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5101 if (!NT_STATUS_IS_OK(status
)) {
5102 reply_nterror(req
, status
);
5103 END_PROFILE(SMBclose
);
5107 reply_outbuf(req
, 0, 0);
5108 END_PROFILE(SMBclose
);
5112 static void do_smb1_close(struct tevent_req
*req
)
5114 struct reply_close_state
*state
= tevent_req_callback_data(
5115 req
, struct reply_close_state
);
5116 struct smb_request
*smbreq
;
5120 ret
= tevent_wait_recv(req
);
5123 DEBUG(10, ("tevent_wait_recv returned %s\n",
5126 * Continue anyway, this should never happen
5131 * fsp->smb2_close_request right now is a talloc grandchild of
5132 * fsp. When we close_file(fsp), it would go with it. No chance to
5135 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5137 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5138 if (NT_STATUS_IS_OK(status
)) {
5139 reply_outbuf(smbreq
, 0, 0);
5141 reply_nterror(smbreq
, status
);
5143 if (!srv_send_smb(smbreq
->sconn
,
5144 (char *)smbreq
->outbuf
,
5147 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5149 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5152 TALLOC_FREE(smbreq
);
5155 /****************************************************************************
5156 Reply to a writeclose (Core+ protocol).
5157 ****************************************************************************/
5159 void reply_writeclose(struct smb_request
*req
)
5161 connection_struct
*conn
= req
->conn
;
5163 ssize_t nwritten
= -1;
5164 NTSTATUS close_status
= NT_STATUS_OK
;
5167 struct timespec mtime
;
5169 struct lock_struct lock
;
5171 START_PROFILE(SMBwriteclose
);
5174 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5175 END_PROFILE(SMBwriteclose
);
5179 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5181 if (!check_fsp(conn
, req
, fsp
)) {
5182 END_PROFILE(SMBwriteclose
);
5185 if (!CHECK_WRITE(fsp
)) {
5186 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5187 END_PROFILE(SMBwriteclose
);
5191 numtowrite
= SVAL(req
->vwv
+1, 0);
5192 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5193 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5194 data
= (const char *)req
->buf
+ 1;
5196 if (!fsp
->print_file
) {
5197 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5198 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5201 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5202 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5203 END_PROFILE(SMBwriteclose
);
5208 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5210 set_close_write_time(fsp
, mtime
);
5213 * More insanity. W2K only closes the file if writelen > 0.
5218 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5219 "file %s\n", fsp_str_dbg(fsp
)));
5220 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5223 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5224 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5225 conn
->num_files_open
));
5227 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5228 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5232 if(!NT_STATUS_IS_OK(close_status
)) {
5233 reply_nterror(req
, close_status
);
5237 reply_outbuf(req
, 1, 0);
5239 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5242 if (numtowrite
&& !fsp
->print_file
) {
5243 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5246 END_PROFILE(SMBwriteclose
);
5251 #define DBGC_CLASS DBGC_LOCKING
5253 /****************************************************************************
5255 ****************************************************************************/
5257 void reply_lock(struct smb_request
*req
)
5259 connection_struct
*conn
= req
->conn
;
5260 uint64_t count
,offset
;
5263 struct byte_range_lock
*br_lck
= NULL
;
5265 START_PROFILE(SMBlock
);
5268 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5269 END_PROFILE(SMBlock
);
5273 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5275 if (!check_fsp(conn
, req
, fsp
)) {
5276 END_PROFILE(SMBlock
);
5280 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5281 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5283 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5284 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5286 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5288 (uint64_t)req
->smbpid
,
5293 False
, /* Non-blocking lock. */
5298 TALLOC_FREE(br_lck
);
5300 if (NT_STATUS_V(status
)) {
5301 reply_nterror(req
, status
);
5302 END_PROFILE(SMBlock
);
5306 reply_outbuf(req
, 0, 0);
5308 END_PROFILE(SMBlock
);
5312 /****************************************************************************
5314 ****************************************************************************/
5316 void reply_unlock(struct smb_request
*req
)
5318 connection_struct
*conn
= req
->conn
;
5319 uint64_t count
,offset
;
5323 START_PROFILE(SMBunlock
);
5326 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5327 END_PROFILE(SMBunlock
);
5331 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5333 if (!check_fsp(conn
, req
, fsp
)) {
5334 END_PROFILE(SMBunlock
);
5338 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5339 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5341 status
= do_unlock(req
->sconn
->msg_ctx
,
5343 (uint64_t)req
->smbpid
,
5348 if (NT_STATUS_V(status
)) {
5349 reply_nterror(req
, status
);
5350 END_PROFILE(SMBunlock
);
5354 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5355 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5357 reply_outbuf(req
, 0, 0);
5359 END_PROFILE(SMBunlock
);
5364 #define DBGC_CLASS DBGC_ALL
5366 /****************************************************************************
5368 conn POINTER CAN BE NULL HERE !
5369 ****************************************************************************/
5371 void reply_tdis(struct smb_request
*req
)
5374 connection_struct
*conn
= req
->conn
;
5375 struct smbXsrv_tcon
*tcon
;
5377 START_PROFILE(SMBtdis
);
5380 DEBUG(4,("Invalid connection in tdis\n"));
5381 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5382 END_PROFILE(SMBtdis
);
5390 * TODO: cancel all outstanding requests on the tcon
5392 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5393 if (!NT_STATUS_IS_OK(status
)) {
5394 DEBUG(0, ("reply_tdis: "
5395 "smbXsrv_tcon_disconnect() failed: %s\n",
5396 nt_errstr(status
)));
5398 * If we hit this case, there is something completely
5399 * wrong, so we better disconnect the transport connection.
5401 END_PROFILE(SMBtdis
);
5402 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5408 reply_outbuf(req
, 0, 0);
5409 END_PROFILE(SMBtdis
);
5413 /****************************************************************************
5415 conn POINTER CAN BE NULL HERE !
5416 ****************************************************************************/
5418 void reply_echo(struct smb_request
*req
)
5420 connection_struct
*conn
= req
->conn
;
5421 struct smb_perfcount_data local_pcd
;
5422 struct smb_perfcount_data
*cur_pcd
;
5426 START_PROFILE(SMBecho
);
5428 smb_init_perfcount_data(&local_pcd
);
5431 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5432 END_PROFILE(SMBecho
);
5436 smb_reverb
= SVAL(req
->vwv
+0, 0);
5438 reply_outbuf(req
, 1, req
->buflen
);
5440 /* copy any incoming data back out */
5441 if (req
->buflen
> 0) {
5442 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5445 if (smb_reverb
> 100) {
5446 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5450 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5452 /* this makes sure we catch the request pcd */
5453 if (seq_num
== smb_reverb
) {
5454 cur_pcd
= &req
->pcd
;
5456 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5457 cur_pcd
= &local_pcd
;
5460 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5462 show_msg((char *)req
->outbuf
);
5463 if (!srv_send_smb(req
->sconn
,
5464 (char *)req
->outbuf
,
5465 true, req
->seqnum
+1,
5466 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5468 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5471 DEBUG(3,("echo %d times\n", smb_reverb
));
5473 TALLOC_FREE(req
->outbuf
);
5475 END_PROFILE(SMBecho
);
5479 /****************************************************************************
5480 Reply to a printopen.
5481 ****************************************************************************/
5483 void reply_printopen(struct smb_request
*req
)
5485 connection_struct
*conn
= req
->conn
;
5489 START_PROFILE(SMBsplopen
);
5492 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5493 END_PROFILE(SMBsplopen
);
5497 if (!CAN_PRINT(conn
)) {
5498 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5499 END_PROFILE(SMBsplopen
);
5503 status
= file_new(req
, conn
, &fsp
);
5504 if(!NT_STATUS_IS_OK(status
)) {
5505 reply_nterror(req
, status
);
5506 END_PROFILE(SMBsplopen
);
5510 /* Open for exclusive use, write only. */
5511 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5513 if (!NT_STATUS_IS_OK(status
)) {
5514 file_free(req
, fsp
);
5515 reply_nterror(req
, status
);
5516 END_PROFILE(SMBsplopen
);
5520 reply_outbuf(req
, 1, 0);
5521 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5523 DEBUG(3,("openprint fd=%d %s\n",
5524 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5526 END_PROFILE(SMBsplopen
);
5530 /****************************************************************************
5531 Reply to a printclose.
5532 ****************************************************************************/
5534 void reply_printclose(struct smb_request
*req
)
5536 connection_struct
*conn
= req
->conn
;
5540 START_PROFILE(SMBsplclose
);
5543 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5544 END_PROFILE(SMBsplclose
);
5548 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5550 if (!check_fsp(conn
, req
, fsp
)) {
5551 END_PROFILE(SMBsplclose
);
5555 if (!CAN_PRINT(conn
)) {
5556 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5557 END_PROFILE(SMBsplclose
);
5561 DEBUG(3,("printclose fd=%d %s\n",
5562 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5564 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5566 if(!NT_STATUS_IS_OK(status
)) {
5567 reply_nterror(req
, status
);
5568 END_PROFILE(SMBsplclose
);
5572 reply_outbuf(req
, 0, 0);
5574 END_PROFILE(SMBsplclose
);
5578 /****************************************************************************
5579 Reply to a printqueue.
5580 ****************************************************************************/
5582 void reply_printqueue(struct smb_request
*req
)
5584 connection_struct
*conn
= req
->conn
;
5588 START_PROFILE(SMBsplretq
);
5591 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5592 END_PROFILE(SMBsplretq
);
5596 max_count
= SVAL(req
->vwv
+0, 0);
5597 start_index
= SVAL(req
->vwv
+1, 0);
5599 /* we used to allow the client to get the cnum wrong, but that
5600 is really quite gross and only worked when there was only
5601 one printer - I think we should now only accept it if they
5602 get it right (tridge) */
5603 if (!CAN_PRINT(conn
)) {
5604 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5605 END_PROFILE(SMBsplretq
);
5609 reply_outbuf(req
, 2, 3);
5610 SSVAL(req
->outbuf
,smb_vwv0
,0);
5611 SSVAL(req
->outbuf
,smb_vwv1
,0);
5612 SCVAL(smb_buf(req
->outbuf
),0,1);
5613 SSVAL(smb_buf(req
->outbuf
),1,0);
5615 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5616 start_index
, max_count
));
5619 TALLOC_CTX
*mem_ctx
= talloc_tos();
5622 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5623 struct rpc_pipe_client
*cli
= NULL
;
5624 struct dcerpc_binding_handle
*b
= NULL
;
5625 struct policy_handle handle
;
5626 struct spoolss_DevmodeContainer devmode_ctr
;
5627 union spoolss_JobInfo
*info
;
5629 uint32_t num_to_get
;
5633 ZERO_STRUCT(handle
);
5635 status
= rpc_pipe_open_interface(conn
,
5636 &ndr_table_spoolss
.syntax_id
,
5638 conn
->sconn
->remote_address
,
5639 conn
->sconn
->msg_ctx
,
5641 if (!NT_STATUS_IS_OK(status
)) {
5642 DEBUG(0, ("reply_printqueue: "
5643 "could not connect to spoolss: %s\n",
5644 nt_errstr(status
)));
5645 reply_nterror(req
, status
);
5648 b
= cli
->binding_handle
;
5650 ZERO_STRUCT(devmode_ctr
);
5652 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5655 SEC_FLAG_MAXIMUM_ALLOWED
,
5658 if (!NT_STATUS_IS_OK(status
)) {
5659 reply_nterror(req
, status
);
5662 if (!W_ERROR_IS_OK(werr
)) {
5663 reply_nterror(req
, werror_to_ntstatus(werr
));
5667 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5675 if (!W_ERROR_IS_OK(werr
)) {
5676 reply_nterror(req
, werror_to_ntstatus(werr
));
5680 if (max_count
> 0) {
5681 first
= start_index
;
5683 first
= start_index
+ max_count
+ 1;
5686 if (first
>= count
) {
5689 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5692 for (i
= first
; i
< num_to_get
; i
++) {
5695 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5697 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5698 info
[i
].info2
.job_id
);
5700 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5706 srv_put_dos_date2(p
, 0, qtime
);
5707 SCVAL(p
, 4, qstatus
);
5708 SSVAL(p
, 5, qrapjobid
);
5709 SIVAL(p
, 7, info
[i
].info2
.size
);
5711 srvstr_push(blob
, req
->flags2
, p
+12,
5712 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5714 if (message_push_blob(
5717 blob
, sizeof(blob
))) == -1) {
5718 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5724 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5725 SSVAL(req
->outbuf
,smb_vwv1
,
5726 (max_count
>0?first
+count
:first
-1));
5727 SCVAL(smb_buf(req
->outbuf
),0,1);
5728 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5732 DEBUG(3, ("%u entries returned in queue\n",
5736 if (b
&& is_valid_policy_hnd(&handle
)) {
5737 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5742 END_PROFILE(SMBsplretq
);
5746 /****************************************************************************
5747 Reply to a printwrite.
5748 ****************************************************************************/
5750 void reply_printwrite(struct smb_request
*req
)
5752 connection_struct
*conn
= req
->conn
;
5757 START_PROFILE(SMBsplwr
);
5760 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5761 END_PROFILE(SMBsplwr
);
5765 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5767 if (!check_fsp(conn
, req
, fsp
)) {
5768 END_PROFILE(SMBsplwr
);
5772 if (!fsp
->print_file
) {
5773 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5774 END_PROFILE(SMBsplwr
);
5778 if (!CHECK_WRITE(fsp
)) {
5779 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5780 END_PROFILE(SMBsplwr
);
5784 numtowrite
= SVAL(req
->buf
, 1);
5786 if (req
->buflen
< numtowrite
+ 3) {
5787 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5788 END_PROFILE(SMBsplwr
);
5792 data
= (const char *)req
->buf
+ 3;
5794 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
5795 reply_nterror(req
, map_nt_error_from_unix(errno
));
5796 END_PROFILE(SMBsplwr
);
5800 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
5802 END_PROFILE(SMBsplwr
);
5806 /****************************************************************************
5808 ****************************************************************************/
5810 void reply_mkdir(struct smb_request
*req
)
5812 connection_struct
*conn
= req
->conn
;
5813 struct smb_filename
*smb_dname
= NULL
;
5814 char *directory
= NULL
;
5816 TALLOC_CTX
*ctx
= talloc_tos();
5818 START_PROFILE(SMBmkdir
);
5820 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5821 STR_TERMINATE
, &status
);
5822 if (!NT_STATUS_IS_OK(status
)) {
5823 reply_nterror(req
, status
);
5827 status
= filename_convert(ctx
, conn
,
5828 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5830 UCF_PREP_CREATEFILE
,
5833 if (!NT_STATUS_IS_OK(status
)) {
5834 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5835 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5836 ERRSRV
, ERRbadpath
);
5839 reply_nterror(req
, status
);
5843 status
= create_directory(conn
, req
, smb_dname
);
5845 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5847 if (!NT_STATUS_IS_OK(status
)) {
5849 if (!use_nt_status()
5850 && NT_STATUS_EQUAL(status
,
5851 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5853 * Yes, in the DOS error code case we get a
5854 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5855 * samba4 torture test.
5857 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5860 reply_nterror(req
, status
);
5864 reply_outbuf(req
, 0, 0);
5866 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5868 TALLOC_FREE(smb_dname
);
5869 END_PROFILE(SMBmkdir
);
5873 /****************************************************************************
5875 ****************************************************************************/
5877 void reply_rmdir(struct smb_request
*req
)
5879 connection_struct
*conn
= req
->conn
;
5880 struct smb_filename
*smb_dname
= NULL
;
5881 char *directory
= NULL
;
5883 TALLOC_CTX
*ctx
= talloc_tos();
5884 files_struct
*fsp
= NULL
;
5886 struct smbd_server_connection
*sconn
= req
->sconn
;
5888 START_PROFILE(SMBrmdir
);
5890 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5891 STR_TERMINATE
, &status
);
5892 if (!NT_STATUS_IS_OK(status
)) {
5893 reply_nterror(req
, status
);
5897 status
= filename_convert(ctx
, conn
,
5898 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5903 if (!NT_STATUS_IS_OK(status
)) {
5904 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5905 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5906 ERRSRV
, ERRbadpath
);
5909 reply_nterror(req
, status
);
5913 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5914 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5918 status
= SMB_VFS_CREATE_FILE(
5921 0, /* root_dir_fid */
5922 smb_dname
, /* fname */
5923 DELETE_ACCESS
, /* access_mask */
5924 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5926 FILE_OPEN
, /* create_disposition*/
5927 FILE_DIRECTORY_FILE
, /* create_options */
5928 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5929 0, /* oplock_request */
5930 0, /* allocation_size */
5931 0, /* private_flags */
5937 if (!NT_STATUS_IS_OK(status
)) {
5938 if (open_was_deferred(req
->sconn
, req
->mid
)) {
5939 /* We have re-scheduled this call. */
5942 reply_nterror(req
, status
);
5946 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5947 if (!NT_STATUS_IS_OK(status
)) {
5948 close_file(req
, fsp
, ERROR_CLOSE
);
5949 reply_nterror(req
, status
);
5953 if (!set_delete_on_close(fsp
, true,
5954 conn
->session_info
->security_token
,
5955 conn
->session_info
->unix_token
)) {
5956 close_file(req
, fsp
, ERROR_CLOSE
);
5957 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5961 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5962 if (!NT_STATUS_IS_OK(status
)) {
5963 reply_nterror(req
, status
);
5965 reply_outbuf(req
, 0, 0);
5968 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5970 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5972 TALLOC_FREE(smb_dname
);
5973 END_PROFILE(SMBrmdir
);
5977 /*******************************************************************
5978 Resolve wildcards in a filename rename.
5979 ********************************************************************/
5981 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5986 char *name2_copy
= NULL
;
5991 char *p
,*p2
, *pname1
, *pname2
;
5993 name2_copy
= talloc_strdup(ctx
, name2
);
5998 pname1
= strrchr_m(name1
,'/');
5999 pname2
= strrchr_m(name2_copy
,'/');
6001 if (!pname1
|| !pname2
) {
6005 /* Truncate the copy of name2 at the last '/' */
6008 /* Now go past the '/' */
6012 root1
= talloc_strdup(ctx
, pname1
);
6013 root2
= talloc_strdup(ctx
, pname2
);
6015 if (!root1
|| !root2
) {
6019 p
= strrchr_m(root1
,'.');
6022 ext1
= talloc_strdup(ctx
, p
+1);
6024 ext1
= talloc_strdup(ctx
, "");
6026 p
= strrchr_m(root2
,'.');
6029 ext2
= talloc_strdup(ctx
, p
+1);
6031 ext2
= talloc_strdup(ctx
, "");
6034 if (!ext1
|| !ext2
) {
6042 /* Hmmm. Should this be mb-aware ? */
6045 } else if (*p2
== '*') {
6047 root2
= talloc_asprintf(ctx
, "%s%s",
6066 /* Hmmm. Should this be mb-aware ? */
6069 } else if (*p2
== '*') {
6071 ext2
= talloc_asprintf(ctx
, "%s%s",
6087 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6092 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6104 /****************************************************************************
6105 Ensure open files have their names updated. Updated to notify other smbd's
6107 ****************************************************************************/
6109 static void rename_open_files(connection_struct
*conn
,
6110 struct share_mode_lock
*lck
,
6111 uint32_t orig_name_hash
,
6112 const struct smb_filename
*smb_fname_dst
)
6115 bool did_rename
= False
;
6117 uint32_t new_name_hash
= 0;
6119 for(fsp
= file_find_di_first(conn
->sconn
, lck
->data
->id
); fsp
;
6120 fsp
= file_find_di_next(fsp
)) {
6121 /* fsp_name is a relative path under the fsp. To change this for other
6122 sharepaths we need to manipulate relative paths. */
6123 /* TODO - create the absolute path and manipulate the newname
6124 relative to the sharepath. */
6125 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6128 if (fsp
->name_hash
!= orig_name_hash
) {
6131 DEBUG(10, ("rename_open_files: renaming file %s "
6132 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6133 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6134 smb_fname_str_dbg(smb_fname_dst
)));
6136 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6137 if (NT_STATUS_IS_OK(status
)) {
6139 new_name_hash
= fsp
->name_hash
;
6144 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6145 "for %s\n", file_id_string_tos(&lck
->data
->id
),
6146 smb_fname_str_dbg(smb_fname_dst
)));
6149 /* Send messages to all smbd's (not ourself) that the name has changed. */
6150 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, conn
->connectpath
,
6151 orig_name_hash
, new_name_hash
,
6156 /****************************************************************************
6157 We need to check if the source path is a parent directory of the destination
6158 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6159 refuse the rename with a sharing violation. Under UNIX the above call can
6160 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6161 probably need to check that the client is a Windows one before disallowing
6162 this as a UNIX client (one with UNIX extensions) can know the source is a
6163 symlink and make this decision intelligently. Found by an excellent bug
6164 report from <AndyLiebman@aol.com>.
6165 ****************************************************************************/
6167 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6168 const struct smb_filename
*smb_fname_dst
)
6170 const char *psrc
= smb_fname_src
->base_name
;
6171 const char *pdst
= smb_fname_dst
->base_name
;
6174 if (psrc
[0] == '.' && psrc
[1] == '/') {
6177 if (pdst
[0] == '.' && pdst
[1] == '/') {
6180 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6183 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6187 * Do the notify calls from a rename
6190 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6191 const struct smb_filename
*smb_fname_src
,
6192 const struct smb_filename
*smb_fname_dst
)
6194 char *parent_dir_src
= NULL
;
6195 char *parent_dir_dst
= NULL
;
6198 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6199 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6201 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6202 &parent_dir_src
, NULL
) ||
6203 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6204 &parent_dir_dst
, NULL
)) {
6208 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6209 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6210 smb_fname_src
->base_name
);
6211 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6212 smb_fname_dst
->base_name
);
6215 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6216 smb_fname_src
->base_name
);
6217 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6218 smb_fname_dst
->base_name
);
6221 /* this is a strange one. w2k3 gives an additional event for
6222 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6223 files, but not directories */
6225 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6226 FILE_NOTIFY_CHANGE_ATTRIBUTES
6227 |FILE_NOTIFY_CHANGE_CREATION
,
6228 smb_fname_dst
->base_name
);
6231 TALLOC_FREE(parent_dir_src
);
6232 TALLOC_FREE(parent_dir_dst
);
6235 /****************************************************************************
6236 Returns an error if the parent directory for a filename is open in an
6238 ****************************************************************************/
6240 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6241 const struct smb_filename
*smb_fname_dst_in
)
6243 char *parent_dir
= NULL
;
6244 struct smb_filename smb_fname_parent
;
6246 files_struct
*fsp
= NULL
;
6249 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6250 &parent_dir
, NULL
)) {
6251 return NT_STATUS_NO_MEMORY
;
6253 ZERO_STRUCT(smb_fname_parent
);
6254 smb_fname_parent
.base_name
= parent_dir
;
6256 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6258 return map_nt_error_from_unix(errno
);
6262 * We're only checking on this smbd here, mostly good
6263 * enough.. and will pass tests.
6266 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6267 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6268 fsp
= file_find_di_next(fsp
)) {
6269 if (fsp
->access_mask
& DELETE_ACCESS
) {
6270 return NT_STATUS_SHARING_VIOLATION
;
6273 return NT_STATUS_OK
;
6276 /****************************************************************************
6277 Rename an open file - given an fsp.
6278 ****************************************************************************/
6280 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6282 const struct smb_filename
*smb_fname_dst_in
,
6284 bool replace_if_exists
)
6286 TALLOC_CTX
*ctx
= talloc_tos();
6287 struct smb_filename
*smb_fname_dst
= NULL
;
6288 NTSTATUS status
= NT_STATUS_OK
;
6289 struct share_mode_lock
*lck
= NULL
;
6290 bool dst_exists
, old_is_stream
, new_is_stream
;
6292 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6293 if (!NT_STATUS_IS_OK(status
)) {
6297 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6298 if (!NT_STATUS_IS_OK(status
)) {
6302 /* Make a copy of the dst smb_fname structs */
6304 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
6305 if (!NT_STATUS_IS_OK(status
)) {
6310 * Check for special case with case preserving and not
6311 * case sensitive. If the old last component differs from the original
6312 * last component only by case, then we should allow
6313 * the rename (user is trying to change the case of the
6316 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6317 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6318 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6320 char *fname_dst_lcomp_base_mod
= NULL
;
6321 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6324 * Get the last component of the destination name.
6326 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6328 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6330 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6332 if (!fname_dst_lcomp_base_mod
) {
6333 status
= NT_STATUS_NO_MEMORY
;
6338 * Create an smb_filename struct using the original last
6339 * component of the destination.
6341 status
= create_synthetic_smb_fname_split(ctx
,
6342 smb_fname_dst
->original_lcomp
, NULL
,
6343 &smb_fname_orig_lcomp
);
6344 if (!NT_STATUS_IS_OK(status
)) {
6345 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6349 /* If the base names only differ by case, use original. */
6350 if(!strcsequal(fname_dst_lcomp_base_mod
,
6351 smb_fname_orig_lcomp
->base_name
)) {
6354 * Replace the modified last component with the
6358 *last_slash
= '\0'; /* Truncate at the '/' */
6359 tmp
= talloc_asprintf(smb_fname_dst
,
6361 smb_fname_dst
->base_name
,
6362 smb_fname_orig_lcomp
->base_name
);
6364 tmp
= talloc_asprintf(smb_fname_dst
,
6366 smb_fname_orig_lcomp
->base_name
);
6369 status
= NT_STATUS_NO_MEMORY
;
6370 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6371 TALLOC_FREE(smb_fname_orig_lcomp
);
6374 TALLOC_FREE(smb_fname_dst
->base_name
);
6375 smb_fname_dst
->base_name
= tmp
;
6378 /* If the stream_names only differ by case, use original. */
6379 if(!strcsequal(smb_fname_dst
->stream_name
,
6380 smb_fname_orig_lcomp
->stream_name
)) {
6382 /* Use the original stream. */
6383 tmp
= talloc_strdup(smb_fname_dst
,
6384 smb_fname_orig_lcomp
->stream_name
);
6386 status
= NT_STATUS_NO_MEMORY
;
6387 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6388 TALLOC_FREE(smb_fname_orig_lcomp
);
6391 TALLOC_FREE(smb_fname_dst
->stream_name
);
6392 smb_fname_dst
->stream_name
= tmp
;
6394 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6395 TALLOC_FREE(smb_fname_orig_lcomp
);
6399 * If the src and dest names are identical - including case,
6400 * don't do the rename, just return success.
6403 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6404 strcsequal(fsp
->fsp_name
->stream_name
,
6405 smb_fname_dst
->stream_name
)) {
6406 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6407 "- returning success\n",
6408 smb_fname_str_dbg(smb_fname_dst
)));
6409 status
= NT_STATUS_OK
;
6413 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6414 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6416 /* Return the correct error code if both names aren't streams. */
6417 if (!old_is_stream
&& new_is_stream
) {
6418 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6422 if (old_is_stream
&& !new_is_stream
) {
6423 status
= NT_STATUS_INVALID_PARAMETER
;
6427 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6429 if(!replace_if_exists
&& dst_exists
) {
6430 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6431 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6432 smb_fname_str_dbg(smb_fname_dst
)));
6433 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6438 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6439 &smb_fname_dst
->st
);
6440 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6442 /* The file can be open when renaming a stream */
6443 if (dst_fsp
&& !new_is_stream
) {
6444 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6445 status
= NT_STATUS_ACCESS_DENIED
;
6450 /* Ensure we have a valid stat struct for the source. */
6451 status
= vfs_stat_fsp(fsp
);
6452 if (!NT_STATUS_IS_OK(status
)) {
6456 status
= can_rename(conn
, fsp
, attrs
);
6458 if (!NT_STATUS_IS_OK(status
)) {
6459 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6460 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6461 smb_fname_str_dbg(smb_fname_dst
)));
6462 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6463 status
= NT_STATUS_ACCESS_DENIED
;
6467 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6468 status
= NT_STATUS_ACCESS_DENIED
;
6471 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6474 * We have the file open ourselves, so not being able to get the
6475 * corresponding share mode lock is a fatal error.
6478 SMB_ASSERT(lck
!= NULL
);
6480 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6481 uint32 create_options
= fsp
->fh
->private_options
;
6483 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6484 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6485 smb_fname_str_dbg(smb_fname_dst
)));
6487 if (!fsp
->is_directory
&&
6488 !lp_posix_pathnames() &&
6489 (lp_map_archive(SNUM(conn
)) ||
6490 lp_store_dos_attributes(SNUM(conn
)))) {
6491 /* We must set the archive bit on the newly
6493 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6494 uint32_t old_dosmode
= dos_mode(conn
,
6496 file_set_dosmode(conn
,
6498 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6504 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6507 rename_open_files(conn
, lck
, fsp
->name_hash
, smb_fname_dst
);
6510 * A rename acts as a new file create w.r.t. allowing an initial delete
6511 * on close, probably because in Windows there is a new handle to the
6512 * new file. If initial delete on close was requested but not
6513 * originally set, we need to set it here. This is probably not 100% correct,
6514 * but will work for the CIFSFS client which in non-posix mode
6515 * depends on these semantics. JRA.
6518 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6519 status
= can_set_delete_on_close(fsp
, 0);
6521 if (NT_STATUS_IS_OK(status
)) {
6522 /* Note that here we set the *inital* delete on close flag,
6523 * not the regular one. The magic gets handled in close. */
6524 fsp
->initial_delete_on_close
= True
;
6528 status
= NT_STATUS_OK
;
6534 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6535 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6537 status
= map_nt_error_from_unix(errno
);
6540 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6541 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6542 smb_fname_str_dbg(smb_fname_dst
)));
6545 TALLOC_FREE(smb_fname_dst
);
6550 /****************************************************************************
6551 The guts of the rename command, split out so it may be called by the NT SMB
6553 ****************************************************************************/
6555 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6556 connection_struct
*conn
,
6557 struct smb_request
*req
,
6558 struct smb_filename
*smb_fname_src
,
6559 struct smb_filename
*smb_fname_dst
,
6561 bool replace_if_exists
,
6564 uint32_t access_mask
)
6566 char *fname_src_dir
= NULL
;
6567 char *fname_src_mask
= NULL
;
6569 NTSTATUS status
= NT_STATUS_OK
;
6570 struct smb_Dir
*dir_hnd
= NULL
;
6571 const char *dname
= NULL
;
6572 char *talloced
= NULL
;
6574 int create_options
= 0;
6575 bool posix_pathnames
= lp_posix_pathnames();
6578 * Split the old name into directory and last component
6579 * strings. Note that unix_convert may have stripped off a
6580 * leading ./ from both name and newname if the rename is
6581 * at the root of the share. We need to make sure either both
6582 * name and newname contain a / character or neither of them do
6583 * as this is checked in resolve_wildcards().
6586 /* Split up the directory from the filename/mask. */
6587 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6588 &fname_src_dir
, &fname_src_mask
);
6589 if (!NT_STATUS_IS_OK(status
)) {
6590 status
= NT_STATUS_NO_MEMORY
;
6595 * We should only check the mangled cache
6596 * here if unix_convert failed. This means
6597 * that the path in 'mask' doesn't exist
6598 * on the file system and so we need to look
6599 * for a possible mangle. This patch from
6600 * Tine Smukavec <valentin.smukavec@hermes.si>.
6603 if (!VALID_STAT(smb_fname_src
->st
) &&
6604 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6605 char *new_mask
= NULL
;
6606 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6609 TALLOC_FREE(fname_src_mask
);
6610 fname_src_mask
= new_mask
;
6614 if (!src_has_wild
) {
6618 * Only one file needs to be renamed. Append the mask back
6619 * onto the directory.
6621 TALLOC_FREE(smb_fname_src
->base_name
);
6622 if (ISDOT(fname_src_dir
)) {
6623 /* Ensure we use canonical names on open. */
6624 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6628 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6633 if (!smb_fname_src
->base_name
) {
6634 status
= NT_STATUS_NO_MEMORY
;
6638 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6639 "case_preserve = %d, short case preserve = %d, "
6640 "directory = %s, newname = %s, "
6641 "last_component_dest = %s\n",
6642 conn
->case_sensitive
, conn
->case_preserve
,
6643 conn
->short_case_preserve
,
6644 smb_fname_str_dbg(smb_fname_src
),
6645 smb_fname_str_dbg(smb_fname_dst
),
6646 smb_fname_dst
->original_lcomp
));
6648 /* The dest name still may have wildcards. */
6649 if (dest_has_wild
) {
6650 char *fname_dst_mod
= NULL
;
6651 if (!resolve_wildcards(smb_fname_dst
,
6652 smb_fname_src
->base_name
,
6653 smb_fname_dst
->base_name
,
6655 DEBUG(6, ("rename_internals: resolve_wildcards "
6657 smb_fname_src
->base_name
,
6658 smb_fname_dst
->base_name
));
6659 status
= NT_STATUS_NO_MEMORY
;
6662 TALLOC_FREE(smb_fname_dst
->base_name
);
6663 smb_fname_dst
->base_name
= fname_dst_mod
;
6666 ZERO_STRUCT(smb_fname_src
->st
);
6667 if (posix_pathnames
) {
6668 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6670 SMB_VFS_STAT(conn
, smb_fname_src
);
6673 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6674 create_options
|= FILE_DIRECTORY_FILE
;
6677 status
= SMB_VFS_CREATE_FILE(
6680 0, /* root_dir_fid */
6681 smb_fname_src
, /* fname */
6682 access_mask
, /* access_mask */
6683 (FILE_SHARE_READ
| /* share_access */
6685 FILE_OPEN
, /* create_disposition*/
6686 create_options
, /* create_options */
6687 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6688 0, /* oplock_request */
6689 0, /* allocation_size */
6690 0, /* private_flags */
6696 if (!NT_STATUS_IS_OK(status
)) {
6697 DEBUG(3, ("Could not open rename source %s: %s\n",
6698 smb_fname_str_dbg(smb_fname_src
),
6699 nt_errstr(status
)));
6703 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6704 attrs
, replace_if_exists
);
6706 close_file(req
, fsp
, NORMAL_CLOSE
);
6708 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6709 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6710 smb_fname_str_dbg(smb_fname_dst
)));
6716 * Wildcards - process each file that matches.
6718 if (strequal(fname_src_mask
, "????????.???")) {
6719 TALLOC_FREE(fname_src_mask
);
6720 fname_src_mask
= talloc_strdup(ctx
, "*");
6721 if (!fname_src_mask
) {
6722 status
= NT_STATUS_NO_MEMORY
;
6727 status
= check_name(conn
, fname_src_dir
);
6728 if (!NT_STATUS_IS_OK(status
)) {
6732 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6734 if (dir_hnd
== NULL
) {
6735 status
= map_nt_error_from_unix(errno
);
6739 status
= NT_STATUS_NO_SUCH_FILE
;
6741 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6742 * - gentest fix. JRA
6745 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6747 files_struct
*fsp
= NULL
;
6748 char *destname
= NULL
;
6749 bool sysdir_entry
= False
;
6751 /* Quick check for "." and ".." */
6752 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6753 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6754 sysdir_entry
= True
;
6756 TALLOC_FREE(talloced
);
6761 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6762 &smb_fname_src
->st
, false)) {
6763 TALLOC_FREE(talloced
);
6767 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6768 TALLOC_FREE(talloced
);
6773 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6777 TALLOC_FREE(smb_fname_src
->base_name
);
6778 if (ISDOT(fname_src_dir
)) {
6779 /* Ensure we use canonical names on open. */
6780 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6784 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6789 if (!smb_fname_src
->base_name
) {
6790 status
= NT_STATUS_NO_MEMORY
;
6794 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6795 smb_fname_dst
->base_name
,
6797 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6798 smb_fname_src
->base_name
, destname
));
6799 TALLOC_FREE(talloced
);
6803 status
= NT_STATUS_NO_MEMORY
;
6807 TALLOC_FREE(smb_fname_dst
->base_name
);
6808 smb_fname_dst
->base_name
= destname
;
6810 ZERO_STRUCT(smb_fname_src
->st
);
6811 if (posix_pathnames
) {
6812 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6814 SMB_VFS_STAT(conn
, smb_fname_src
);
6819 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6820 create_options
|= FILE_DIRECTORY_FILE
;
6823 status
= SMB_VFS_CREATE_FILE(
6826 0, /* root_dir_fid */
6827 smb_fname_src
, /* fname */
6828 access_mask
, /* access_mask */
6829 (FILE_SHARE_READ
| /* share_access */
6831 FILE_OPEN
, /* create_disposition*/
6832 create_options
, /* create_options */
6833 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6834 0, /* oplock_request */
6835 0, /* allocation_size */
6836 0, /* private_flags */
6842 if (!NT_STATUS_IS_OK(status
)) {
6843 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6844 "returned %s rename %s -> %s\n",
6846 smb_fname_str_dbg(smb_fname_src
),
6847 smb_fname_str_dbg(smb_fname_dst
)));
6851 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6853 if (!smb_fname_dst
->original_lcomp
) {
6854 status
= NT_STATUS_NO_MEMORY
;
6858 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6859 attrs
, replace_if_exists
);
6861 close_file(req
, fsp
, NORMAL_CLOSE
);
6863 if (!NT_STATUS_IS_OK(status
)) {
6864 DEBUG(3, ("rename_internals_fsp returned %s for "
6865 "rename %s -> %s\n", nt_errstr(status
),
6866 smb_fname_str_dbg(smb_fname_src
),
6867 smb_fname_str_dbg(smb_fname_dst
)));
6873 DEBUG(3,("rename_internals: doing rename on %s -> "
6874 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6875 smb_fname_str_dbg(smb_fname_src
)));
6876 TALLOC_FREE(talloced
);
6878 TALLOC_FREE(dir_hnd
);
6880 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6881 status
= map_nt_error_from_unix(errno
);
6885 TALLOC_FREE(talloced
);
6886 TALLOC_FREE(fname_src_dir
);
6887 TALLOC_FREE(fname_src_mask
);
6891 /****************************************************************************
6893 ****************************************************************************/
6895 void reply_mv(struct smb_request
*req
)
6897 connection_struct
*conn
= req
->conn
;
6899 char *newname
= NULL
;
6903 bool src_has_wcard
= False
;
6904 bool dest_has_wcard
= False
;
6905 TALLOC_CTX
*ctx
= talloc_tos();
6906 struct smb_filename
*smb_fname_src
= NULL
;
6907 struct smb_filename
*smb_fname_dst
= NULL
;
6908 uint32_t src_ucf_flags
= lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP
: UCF_COND_ALLOW_WCARD_LCOMP
;
6909 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
| (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP
);
6910 bool stream_rename
= false;
6912 START_PROFILE(SMBmv
);
6915 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6919 attrs
= SVAL(req
->vwv
+0, 0);
6921 p
= (const char *)req
->buf
+ 1;
6922 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6923 &status
, &src_has_wcard
);
6924 if (!NT_STATUS_IS_OK(status
)) {
6925 reply_nterror(req
, status
);
6929 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6930 &status
, &dest_has_wcard
);
6931 if (!NT_STATUS_IS_OK(status
)) {
6932 reply_nterror(req
, status
);
6936 if (!lp_posix_pathnames()) {
6937 /* The newname must begin with a ':' if the
6938 name contains a ':'. */
6939 if (strchr_m(name
, ':')) {
6940 if (newname
[0] != ':') {
6941 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6944 stream_rename
= true;
6948 status
= filename_convert(ctx
,
6950 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6956 if (!NT_STATUS_IS_OK(status
)) {
6957 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6958 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6959 ERRSRV
, ERRbadpath
);
6962 reply_nterror(req
, status
);
6966 status
= filename_convert(ctx
,
6968 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6974 if (!NT_STATUS_IS_OK(status
)) {
6975 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6976 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6977 ERRSRV
, ERRbadpath
);
6980 reply_nterror(req
, status
);
6984 if (stream_rename
) {
6985 /* smb_fname_dst->base_name must be the same as
6986 smb_fname_src->base_name. */
6987 TALLOC_FREE(smb_fname_dst
->base_name
);
6988 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6989 smb_fname_src
->base_name
);
6990 if (!smb_fname_dst
->base_name
) {
6991 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6996 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6997 smb_fname_str_dbg(smb_fname_dst
)));
6999 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7000 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7002 if (!NT_STATUS_IS_OK(status
)) {
7003 if (open_was_deferred(req
->sconn
, req
->mid
)) {
7004 /* We have re-scheduled this call. */
7007 reply_nterror(req
, status
);
7011 reply_outbuf(req
, 0, 0);
7013 TALLOC_FREE(smb_fname_src
);
7014 TALLOC_FREE(smb_fname_dst
);
7019 /*******************************************************************
7020 Copy a file as part of a reply_copy.
7021 ******************************************************************/
7024 * TODO: check error codes on all callers
7027 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7028 connection_struct
*conn
,
7029 struct smb_filename
*smb_fname_src
,
7030 struct smb_filename
*smb_fname_dst
,
7033 bool target_is_directory
)
7035 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7037 files_struct
*fsp1
,*fsp2
;
7039 uint32 new_create_disposition
;
7043 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
7044 if (!NT_STATUS_IS_OK(status
)) {
7049 * If the target is a directory, extract the last component from the
7050 * src filename and append it to the dst filename
7052 if (target_is_directory
) {
7055 /* dest/target can't be a stream if it's a directory. */
7056 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7058 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7062 p
= smb_fname_src
->base_name
;
7064 smb_fname_dst_tmp
->base_name
=
7065 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7067 if (!smb_fname_dst_tmp
->base_name
) {
7068 status
= NT_STATUS_NO_MEMORY
;
7073 status
= vfs_file_exist(conn
, smb_fname_src
);
7074 if (!NT_STATUS_IS_OK(status
)) {
7078 if (!target_is_directory
&& count
) {
7079 new_create_disposition
= FILE_OPEN
;
7081 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7084 &new_create_disposition
,
7087 status
= NT_STATUS_INVALID_PARAMETER
;
7092 /* Open the src file for reading. */
7093 status
= SMB_VFS_CREATE_FILE(
7096 0, /* root_dir_fid */
7097 smb_fname_src
, /* fname */
7098 FILE_GENERIC_READ
, /* access_mask */
7099 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7100 FILE_OPEN
, /* create_disposition*/
7101 0, /* create_options */
7102 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7103 INTERNAL_OPEN_ONLY
, /* oplock_request */
7104 0, /* allocation_size */
7105 0, /* private_flags */
7111 if (!NT_STATUS_IS_OK(status
)) {
7115 dosattrs
= dos_mode(conn
, smb_fname_src
);
7117 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7118 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7121 /* Open the dst file for writing. */
7122 status
= SMB_VFS_CREATE_FILE(
7125 0, /* root_dir_fid */
7126 smb_fname_dst
, /* fname */
7127 FILE_GENERIC_WRITE
, /* access_mask */
7128 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7129 new_create_disposition
, /* create_disposition*/
7130 0, /* create_options */
7131 dosattrs
, /* file_attributes */
7132 INTERNAL_OPEN_ONLY
, /* oplock_request */
7133 0, /* allocation_size */
7134 0, /* private_flags */
7140 if (!NT_STATUS_IS_OK(status
)) {
7141 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7145 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7146 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7148 DEBUG(0, ("error - vfs lseek returned error %s\n",
7150 status
= map_nt_error_from_unix(errno
);
7151 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7152 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7157 /* Do the actual copy. */
7158 if (smb_fname_src
->st
.st_ex_size
) {
7159 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7164 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7166 /* Ensure the modtime is set correctly on the destination file. */
7167 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7170 * As we are opening fsp1 read-only we only expect
7171 * an error on close on fsp2 if we are out of space.
7172 * Thus we don't look at the error return from the
7175 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7177 if (!NT_STATUS_IS_OK(status
)) {
7181 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7182 status
= NT_STATUS_DISK_FULL
;
7186 status
= NT_STATUS_OK
;
7189 TALLOC_FREE(smb_fname_dst_tmp
);
7193 /****************************************************************************
7194 Reply to a file copy.
7195 ****************************************************************************/
7197 void reply_copy(struct smb_request
*req
)
7199 connection_struct
*conn
= req
->conn
;
7200 struct smb_filename
*smb_fname_src
= NULL
;
7201 struct smb_filename
*smb_fname_dst
= NULL
;
7202 char *fname_src
= NULL
;
7203 char *fname_dst
= NULL
;
7204 char *fname_src_mask
= NULL
;
7205 char *fname_src_dir
= NULL
;
7208 int error
= ERRnoaccess
;
7212 bool target_is_directory
=False
;
7213 bool source_has_wild
= False
;
7214 bool dest_has_wild
= False
;
7216 TALLOC_CTX
*ctx
= talloc_tos();
7218 START_PROFILE(SMBcopy
);
7221 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7225 tid2
= SVAL(req
->vwv
+0, 0);
7226 ofun
= SVAL(req
->vwv
+1, 0);
7227 flags
= SVAL(req
->vwv
+2, 0);
7229 p
= (const char *)req
->buf
;
7230 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7231 &status
, &source_has_wild
);
7232 if (!NT_STATUS_IS_OK(status
)) {
7233 reply_nterror(req
, status
);
7236 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7237 &status
, &dest_has_wild
);
7238 if (!NT_STATUS_IS_OK(status
)) {
7239 reply_nterror(req
, status
);
7243 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7245 if (tid2
!= conn
->cnum
) {
7246 /* can't currently handle inter share copies XXXX */
7247 DEBUG(3,("Rejecting inter-share copy\n"));
7248 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7252 status
= filename_convert(ctx
, conn
,
7253 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7255 UCF_COND_ALLOW_WCARD_LCOMP
,
7258 if (!NT_STATUS_IS_OK(status
)) {
7259 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7260 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7261 ERRSRV
, ERRbadpath
);
7264 reply_nterror(req
, status
);
7268 status
= filename_convert(ctx
, conn
,
7269 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7271 UCF_COND_ALLOW_WCARD_LCOMP
,
7274 if (!NT_STATUS_IS_OK(status
)) {
7275 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7276 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7277 ERRSRV
, ERRbadpath
);
7280 reply_nterror(req
, status
);
7284 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7286 if ((flags
&1) && target_is_directory
) {
7287 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7291 if ((flags
&2) && !target_is_directory
) {
7292 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7296 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7297 /* wants a tree copy! XXXX */
7298 DEBUG(3,("Rejecting tree copy\n"));
7299 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7303 /* Split up the directory from the filename/mask. */
7304 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7305 &fname_src_dir
, &fname_src_mask
);
7306 if (!NT_STATUS_IS_OK(status
)) {
7307 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7312 * We should only check the mangled cache
7313 * here if unix_convert failed. This means
7314 * that the path in 'mask' doesn't exist
7315 * on the file system and so we need to look
7316 * for a possible mangle. This patch from
7317 * Tine Smukavec <valentin.smukavec@hermes.si>.
7319 if (!VALID_STAT(smb_fname_src
->st
) &&
7320 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7321 char *new_mask
= NULL
;
7322 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7323 &new_mask
, conn
->params
);
7325 /* Use demangled name if one was successfully found. */
7327 TALLOC_FREE(fname_src_mask
);
7328 fname_src_mask
= new_mask
;
7332 if (!source_has_wild
) {
7335 * Only one file needs to be copied. Append the mask back onto
7338 TALLOC_FREE(smb_fname_src
->base_name
);
7339 if (ISDOT(fname_src_dir
)) {
7340 /* Ensure we use canonical names on open. */
7341 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7345 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7350 if (!smb_fname_src
->base_name
) {
7351 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7355 if (dest_has_wild
) {
7356 char *fname_dst_mod
= NULL
;
7357 if (!resolve_wildcards(smb_fname_dst
,
7358 smb_fname_src
->base_name
,
7359 smb_fname_dst
->base_name
,
7361 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7364 TALLOC_FREE(smb_fname_dst
->base_name
);
7365 smb_fname_dst
->base_name
= fname_dst_mod
;
7368 status
= check_name(conn
, smb_fname_src
->base_name
);
7369 if (!NT_STATUS_IS_OK(status
)) {
7370 reply_nterror(req
, status
);
7374 status
= check_name(conn
, smb_fname_dst
->base_name
);
7375 if (!NT_STATUS_IS_OK(status
)) {
7376 reply_nterror(req
, status
);
7380 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7381 ofun
, count
, target_is_directory
);
7383 if(!NT_STATUS_IS_OK(status
)) {
7384 reply_nterror(req
, status
);
7390 struct smb_Dir
*dir_hnd
= NULL
;
7391 const char *dname
= NULL
;
7392 char *talloced
= NULL
;
7396 * There is a wildcard that requires us to actually read the
7397 * src dir and copy each file matching the mask to the dst.
7398 * Right now streams won't be copied, but this could
7399 * presumably be added with a nested loop for reach dir entry.
7401 SMB_ASSERT(!smb_fname_src
->stream_name
);
7402 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7404 smb_fname_src
->stream_name
= NULL
;
7405 smb_fname_dst
->stream_name
= NULL
;
7407 if (strequal(fname_src_mask
,"????????.???")) {
7408 TALLOC_FREE(fname_src_mask
);
7409 fname_src_mask
= talloc_strdup(ctx
, "*");
7410 if (!fname_src_mask
) {
7411 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7416 status
= check_name(conn
, fname_src_dir
);
7417 if (!NT_STATUS_IS_OK(status
)) {
7418 reply_nterror(req
, status
);
7422 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7423 if (dir_hnd
== NULL
) {
7424 status
= map_nt_error_from_unix(errno
);
7425 reply_nterror(req
, status
);
7431 /* Iterate over the src dir copying each entry to the dst. */
7432 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7433 &smb_fname_src
->st
, &talloced
))) {
7434 char *destname
= NULL
;
7436 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7437 TALLOC_FREE(talloced
);
7441 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7442 &smb_fname_src
->st
, false)) {
7443 TALLOC_FREE(talloced
);
7447 if(!mask_match(dname
, fname_src_mask
,
7448 conn
->case_sensitive
)) {
7449 TALLOC_FREE(talloced
);
7453 error
= ERRnoaccess
;
7455 /* Get the src smb_fname struct setup. */
7456 TALLOC_FREE(smb_fname_src
->base_name
);
7457 if (ISDOT(fname_src_dir
)) {
7458 /* Ensure we use canonical names on open. */
7459 smb_fname_src
->base_name
=
7460 talloc_asprintf(smb_fname_src
, "%s",
7463 smb_fname_src
->base_name
=
7464 talloc_asprintf(smb_fname_src
, "%s/%s",
7465 fname_src_dir
, dname
);
7468 if (!smb_fname_src
->base_name
) {
7469 TALLOC_FREE(dir_hnd
);
7470 TALLOC_FREE(talloced
);
7471 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7475 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7476 smb_fname_dst
->base_name
,
7478 TALLOC_FREE(talloced
);
7482 TALLOC_FREE(dir_hnd
);
7483 TALLOC_FREE(talloced
);
7484 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7488 TALLOC_FREE(smb_fname_dst
->base_name
);
7489 smb_fname_dst
->base_name
= destname
;
7491 status
= check_name(conn
, smb_fname_src
->base_name
);
7492 if (!NT_STATUS_IS_OK(status
)) {
7493 TALLOC_FREE(dir_hnd
);
7494 TALLOC_FREE(talloced
);
7495 reply_nterror(req
, status
);
7499 status
= check_name(conn
, smb_fname_dst
->base_name
);
7500 if (!NT_STATUS_IS_OK(status
)) {
7501 TALLOC_FREE(dir_hnd
);
7502 TALLOC_FREE(talloced
);
7503 reply_nterror(req
, status
);
7507 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7508 smb_fname_src
->base_name
,
7509 smb_fname_dst
->base_name
));
7511 status
= copy_file(ctx
, conn
, smb_fname_src
,
7512 smb_fname_dst
, ofun
, count
,
7513 target_is_directory
);
7514 if (NT_STATUS_IS_OK(status
)) {
7518 TALLOC_FREE(talloced
);
7520 TALLOC_FREE(dir_hnd
);
7524 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7528 reply_outbuf(req
, 1, 0);
7529 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7531 TALLOC_FREE(smb_fname_src
);
7532 TALLOC_FREE(smb_fname_dst
);
7533 TALLOC_FREE(fname_src
);
7534 TALLOC_FREE(fname_dst
);
7535 TALLOC_FREE(fname_src_mask
);
7536 TALLOC_FREE(fname_src_dir
);
7538 END_PROFILE(SMBcopy
);
7543 #define DBGC_CLASS DBGC_LOCKING
7545 /****************************************************************************
7546 Get a lock pid, dealing with large count requests.
7547 ****************************************************************************/
7549 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7550 bool large_file_format
)
7552 if(!large_file_format
)
7553 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7555 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7558 /****************************************************************************
7559 Get a lock count, dealing with large count requests.
7560 ****************************************************************************/
7562 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7563 bool large_file_format
)
7567 if(!large_file_format
) {
7568 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7571 #if defined(HAVE_LONGLONG)
7572 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7573 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7574 #else /* HAVE_LONGLONG */
7577 * NT4.x seems to be broken in that it sends large file (64 bit)
7578 * lockingX calls even if the CAP_LARGE_FILES was *not*
7579 * negotiated. For boxes without large unsigned ints truncate the
7580 * lock count by dropping the top 32 bits.
7583 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7584 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7585 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7586 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7587 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7590 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7591 #endif /* HAVE_LONGLONG */
7597 #if !defined(HAVE_LONGLONG)
7598 /****************************************************************************
7599 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7600 ****************************************************************************/
7602 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7606 uint32 highcopy
= high
;
7609 * Try and find out how many significant bits there are in high.
7612 for(i
= 0; highcopy
; i
++)
7616 * We use 31 bits not 32 here as POSIX
7617 * lock offsets may not be negative.
7620 mask
= (~0) << (31 - i
);
7623 return 0; /* Fail. */
7629 #endif /* !defined(HAVE_LONGLONG) */
7631 /****************************************************************************
7632 Get a lock offset, dealing with large offset requests.
7633 ****************************************************************************/
7635 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7636 bool large_file_format
, bool *err
)
7638 uint64_t offset
= 0;
7642 if(!large_file_format
) {
7643 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7646 #if defined(HAVE_LONGLONG)
7647 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7648 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7649 #else /* HAVE_LONGLONG */
7652 * NT4.x seems to be broken in that it sends large file (64 bit)
7653 * lockingX calls even if the CAP_LARGE_FILES was *not*
7654 * negotiated. For boxes without large unsigned ints mangle the
7655 * lock offset by mapping the top 32 bits onto the lower 32.
7658 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7659 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7660 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7663 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7665 return (uint64_t)-1;
7668 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7669 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7670 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7671 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7674 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7675 #endif /* HAVE_LONGLONG */
7681 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7685 uint16_t num_ulocks
,
7686 struct smbd_lock_element
*ulocks
,
7688 struct smbd_lock_element
*locks
,
7691 connection_struct
*conn
= req
->conn
;
7693 NTSTATUS status
= NT_STATUS_OK
;
7697 /* Data now points at the beginning of the list
7698 of smb_unlkrng structs */
7699 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7700 struct smbd_lock_element
*e
= &ulocks
[i
];
7702 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7703 "pid %u, file %s\n",
7706 (unsigned int)e
->smblctx
,
7709 if (e
->brltype
!= UNLOCK_LOCK
) {
7710 /* this can only happen with SMB2 */
7711 return NT_STATUS_INVALID_PARAMETER
;
7714 status
= do_unlock(req
->sconn
->msg_ctx
,
7721 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7722 nt_errstr(status
)));
7724 if (!NT_STATUS_IS_OK(status
)) {
7729 /* Setup the timeout in seconds. */
7731 if (!lp_blocking_locks(SNUM(conn
))) {
7735 /* Data now points at the beginning of the list
7736 of smb_lkrng structs */
7738 for(i
= 0; i
< (int)num_locks
; i
++) {
7739 struct smbd_lock_element
*e
= &locks
[i
];
7741 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7742 "%llu, file %s timeout = %d\n",
7745 (unsigned long long)e
->smblctx
,
7749 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7750 struct blocking_lock_record
*blr
= NULL
;
7752 if (num_locks
> 1) {
7754 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7755 * if the lock vector contains one entry. When given mutliple cancel
7756 * requests in a single PDU we expect the server to return an
7757 * error. Windows servers seem to accept the request but only
7758 * cancel the first lock.
7759 * JRA - Do what Windows does (tm) :-).
7763 /* MS-CIFS (2.2.4.32.1) behavior. */
7764 return NT_STATUS_DOS(ERRDOS
,
7765 ERRcancelviolation
);
7767 /* Windows behavior. */
7769 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7770 "cancel request\n"));
7776 if (lp_blocking_locks(SNUM(conn
))) {
7778 /* Schedule a message to ourselves to
7779 remove the blocking lock record and
7780 return the right error. */
7782 blr
= blocking_lock_cancel_smb1(fsp
,
7788 NT_STATUS_FILE_LOCK_CONFLICT
);
7790 return NT_STATUS_DOS(
7792 ERRcancelviolation
);
7795 /* Remove a matching pending lock. */
7796 status
= do_lock_cancel(fsp
,
7803 bool blocking_lock
= timeout
? true : false;
7804 bool defer_lock
= false;
7805 struct byte_range_lock
*br_lck
;
7806 uint64_t block_smblctx
;
7808 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7820 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7821 /* Windows internal resolution for blocking locks seems
7822 to be about 200ms... Don't wait for less than that. JRA. */
7823 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7824 timeout
= lp_lock_spin_time();
7829 /* If a lock sent with timeout of zero would fail, and
7830 * this lock has been requested multiple times,
7831 * according to brl_lock_failed() we convert this
7832 * request to a blocking lock with a timeout of between
7833 * 150 - 300 milliseconds.
7835 * If lp_lock_spin_time() has been set to 0, we skip
7836 * this blocking retry and fail immediately.
7838 * Replacement for do_lock_spin(). JRA. */
7840 if (!req
->sconn
->using_smb2
&&
7841 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7842 lp_lock_spin_time() && !blocking_lock
&&
7843 NT_STATUS_EQUAL((status
),
7844 NT_STATUS_FILE_LOCK_CONFLICT
))
7847 timeout
= lp_lock_spin_time();
7850 if (br_lck
&& defer_lock
) {
7852 * A blocking lock was requested. Package up
7853 * this smb into a queued request and push it
7854 * onto the blocking lock queue.
7856 if(push_blocking_lock_request(br_lck
,
7867 TALLOC_FREE(br_lck
);
7869 return NT_STATUS_OK
;
7873 TALLOC_FREE(br_lck
);
7876 if (!NT_STATUS_IS_OK(status
)) {
7881 /* If any of the above locks failed, then we must unlock
7882 all of the previous locks (X/Open spec). */
7884 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7886 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7887 i
= -1; /* we want to skip the for loop */
7891 * Ensure we don't do a remove on the lock that just failed,
7892 * as under POSIX rules, if we have a lock already there, we
7893 * will delete it (and we shouldn't) .....
7895 for(i
--; i
>= 0; i
--) {
7896 struct smbd_lock_element
*e
= &locks
[i
];
7898 do_unlock(req
->sconn
->msg_ctx
,
7908 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d num_ulocks=%d\n",
7909 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
, num_ulocks
));
7911 return NT_STATUS_OK
;
7914 /****************************************************************************
7915 Reply to a lockingX request.
7916 ****************************************************************************/
7918 void reply_lockingX(struct smb_request
*req
)
7920 connection_struct
*conn
= req
->conn
;
7922 unsigned char locktype
;
7923 unsigned char oplocklevel
;
7928 const uint8_t *data
;
7929 bool large_file_format
;
7931 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7932 struct smbd_lock_element
*ulocks
;
7933 struct smbd_lock_element
*locks
;
7936 START_PROFILE(SMBlockingX
);
7939 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7940 END_PROFILE(SMBlockingX
);
7944 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7945 locktype
= CVAL(req
->vwv
+3, 0);
7946 oplocklevel
= CVAL(req
->vwv
+3, 1);
7947 num_ulocks
= SVAL(req
->vwv
+6, 0);
7948 num_locks
= SVAL(req
->vwv
+7, 0);
7949 lock_timeout
= IVAL(req
->vwv
+4, 0);
7950 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7952 if (!check_fsp(conn
, req
, fsp
)) {
7953 END_PROFILE(SMBlockingX
);
7959 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7960 /* we don't support these - and CANCEL_LOCK makes w2k
7961 and XP reboot so I don't really want to be
7962 compatible! (tridge) */
7963 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7964 END_PROFILE(SMBlockingX
);
7968 /* Check if this is an oplock break on a file
7969 we have granted an oplock on.
7971 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7972 /* Client can insist on breaking to none. */
7973 bool break_to_none
= (oplocklevel
== 0);
7976 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7977 "for %s\n", (unsigned int)oplocklevel
,
7978 fsp_fnum_dbg(fsp
)));
7981 * Make sure we have granted an exclusive or batch oplock on
7985 if (fsp
->oplock_type
== 0) {
7987 /* The Samba4 nbench simulator doesn't understand
7988 the difference between break to level2 and break
7989 to none from level2 - it sends oplock break
7990 replies in both cases. Don't keep logging an error
7991 message here - just ignore it. JRA. */
7993 DEBUG(5,("reply_lockingX: Error : oplock break from "
7994 "client for %s (oplock=%d) and no "
7995 "oplock granted on this file (%s).\n",
7996 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
7999 /* if this is a pure oplock break request then don't
8001 if (num_locks
== 0 && num_ulocks
== 0) {
8002 END_PROFILE(SMBlockingX
);
8005 END_PROFILE(SMBlockingX
);
8006 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8011 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8013 result
= remove_oplock(fsp
);
8015 result
= downgrade_oplock(fsp
);
8019 DEBUG(0, ("reply_lockingX: error in removing "
8020 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8021 /* Hmmm. Is this panic justified? */
8022 smb_panic("internal tdb error");
8025 reply_to_oplock_break_requests(fsp
);
8027 /* if this is a pure oplock break request then don't send a
8029 if (num_locks
== 0 && num_ulocks
== 0) {
8030 /* Sanity check - ensure a pure oplock break is not a
8032 if(CVAL(req
->vwv
+0, 0) != 0xff)
8033 DEBUG(0,("reply_lockingX: Error : pure oplock "
8034 "break is a chained %d request !\n",
8035 (unsigned int)CVAL(req
->vwv
+0, 0)));
8036 END_PROFILE(SMBlockingX
);
8042 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8043 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8044 END_PROFILE(SMBlockingX
);
8048 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8049 if (ulocks
== NULL
) {
8050 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8051 END_PROFILE(SMBlockingX
);
8055 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8056 if (locks
== NULL
) {
8057 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8058 END_PROFILE(SMBlockingX
);
8062 /* Data now points at the beginning of the list
8063 of smb_unlkrng structs */
8064 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8065 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8066 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8067 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
8068 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8071 * There is no error code marked "stupid client bug".... :-).
8074 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8075 END_PROFILE(SMBlockingX
);
8080 /* Now do any requested locks */
8081 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8083 /* Data now points at the beginning of the list
8084 of smb_lkrng structs */
8086 for(i
= 0; i
< (int)num_locks
; i
++) {
8087 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8088 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8089 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
8091 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8092 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8093 locks
[i
].brltype
= PENDING_READ_LOCK
;
8095 locks
[i
].brltype
= READ_LOCK
;
8098 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8099 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8101 locks
[i
].brltype
= WRITE_LOCK
;
8106 * There is no error code marked "stupid client bug".... :-).
8109 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8110 END_PROFILE(SMBlockingX
);
8115 status
= smbd_do_locking(req
, fsp
,
8116 locktype
, lock_timeout
,
8120 if (!NT_STATUS_IS_OK(status
)) {
8121 END_PROFILE(SMBlockingX
);
8122 reply_nterror(req
, status
);
8126 END_PROFILE(SMBlockingX
);
8130 reply_outbuf(req
, 2, 0);
8131 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8132 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8134 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8135 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8137 END_PROFILE(SMBlockingX
);
8141 #define DBGC_CLASS DBGC_ALL
8143 /****************************************************************************
8144 Reply to a SMBreadbmpx (read block multiplex) request.
8145 Always reply with an error, if someone has a platform really needs this,
8146 please contact vl@samba.org
8147 ****************************************************************************/
8149 void reply_readbmpx(struct smb_request
*req
)
8151 START_PROFILE(SMBreadBmpx
);
8152 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8153 END_PROFILE(SMBreadBmpx
);
8157 /****************************************************************************
8158 Reply to a SMBreadbs (read block multiplex secondary) request.
8159 Always reply with an error, if someone has a platform really needs this,
8160 please contact vl@samba.org
8161 ****************************************************************************/
8163 void reply_readbs(struct smb_request
*req
)
8165 START_PROFILE(SMBreadBs
);
8166 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8167 END_PROFILE(SMBreadBs
);
8171 /****************************************************************************
8172 Reply to a SMBsetattrE.
8173 ****************************************************************************/
8175 void reply_setattrE(struct smb_request
*req
)
8177 connection_struct
*conn
= req
->conn
;
8178 struct smb_file_time ft
;
8182 START_PROFILE(SMBsetattrE
);
8186 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8190 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8192 if(!fsp
|| (fsp
->conn
!= conn
)) {
8193 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8198 * Convert the DOS times into unix times.
8201 ft
.atime
= convert_time_t_to_timespec(
8202 srv_make_unix_date2(req
->vwv
+3));
8203 ft
.mtime
= convert_time_t_to_timespec(
8204 srv_make_unix_date2(req
->vwv
+5));
8205 ft
.create_time
= convert_time_t_to_timespec(
8206 srv_make_unix_date2(req
->vwv
+1));
8208 reply_outbuf(req
, 0, 0);
8211 * Patch from Ray Frush <frush@engr.colostate.edu>
8212 * Sometimes times are sent as zero - ignore them.
8215 /* Ensure we have a valid stat struct for the source. */
8216 status
= vfs_stat_fsp(fsp
);
8217 if (!NT_STATUS_IS_OK(status
)) {
8218 reply_nterror(req
, status
);
8222 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8223 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8227 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8228 if (!NT_STATUS_IS_OK(status
)) {
8229 reply_nterror(req
, status
);
8233 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8236 (unsigned int)ft
.atime
.tv_sec
,
8237 (unsigned int)ft
.mtime
.tv_sec
,
8238 (unsigned int)ft
.create_time
.tv_sec
8241 END_PROFILE(SMBsetattrE
);
8246 /* Back from the dead for OS/2..... JRA. */
8248 /****************************************************************************
8249 Reply to a SMBwritebmpx (write block multiplex primary) request.
8250 Always reply with an error, if someone has a platform really needs this,
8251 please contact vl@samba.org
8252 ****************************************************************************/
8254 void reply_writebmpx(struct smb_request
*req
)
8256 START_PROFILE(SMBwriteBmpx
);
8257 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8258 END_PROFILE(SMBwriteBmpx
);
8262 /****************************************************************************
8263 Reply to a SMBwritebs (write block multiplex secondary) request.
8264 Always reply with an error, if someone has a platform really needs this,
8265 please contact vl@samba.org
8266 ****************************************************************************/
8268 void reply_writebs(struct smb_request
*req
)
8270 START_PROFILE(SMBwriteBs
);
8271 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8272 END_PROFILE(SMBwriteBs
);
8276 /****************************************************************************
8277 Reply to a SMBgetattrE.
8278 ****************************************************************************/
8280 void reply_getattrE(struct smb_request
*req
)
8282 connection_struct
*conn
= req
->conn
;
8285 struct timespec create_ts
;
8287 START_PROFILE(SMBgetattrE
);
8290 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8291 END_PROFILE(SMBgetattrE
);
8295 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8297 if(!fsp
|| (fsp
->conn
!= conn
)) {
8298 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8299 END_PROFILE(SMBgetattrE
);
8303 /* Do an fstat on this file */
8305 reply_nterror(req
, map_nt_error_from_unix(errno
));
8306 END_PROFILE(SMBgetattrE
);
8310 mode
= dos_mode(conn
, fsp
->fsp_name
);
8313 * Convert the times into dos times. Set create
8314 * date to be last modify date as UNIX doesn't save
8318 reply_outbuf(req
, 11, 0);
8320 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8321 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8322 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8323 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8324 /* Should we check pending modtime here ? JRA */
8325 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8326 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8328 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8329 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8330 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8332 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8333 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
8334 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8336 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8338 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8340 END_PROFILE(SMBgetattrE
);