2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
47 /****************************************************************************
48 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
49 path or anything including wildcards.
50 We're assuming here that '/' is not the second byte in any multibyte char
51 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
53 ****************************************************************************/
55 /* Custom version for processing POSIX paths. */
56 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
58 static NTSTATUS
check_path_syntax_internal(char *path
,
60 bool *p_last_component_contains_wcard
)
64 NTSTATUS ret
= NT_STATUS_OK
;
65 bool start_of_name_component
= True
;
66 bool stream_started
= false;
68 *p_last_component_contains_wcard
= False
;
75 return NT_STATUS_OBJECT_NAME_INVALID
;
78 return NT_STATUS_OBJECT_NAME_INVALID
;
80 if (strchr_m(&s
[1], ':')) {
81 return NT_STATUS_OBJECT_NAME_INVALID
;
87 if ((*s
== ':') && !posix_path
&& !stream_started
) {
88 if (*p_last_component_contains_wcard
) {
89 return NT_STATUS_OBJECT_NAME_INVALID
;
91 /* Stream names allow more characters than file names.
92 We're overloading posix_path here to allow a wider
93 range of characters. If stream_started is true this
94 is still a Windows path even if posix_path is true.
97 stream_started
= true;
98 start_of_name_component
= false;
102 return NT_STATUS_OBJECT_NAME_INVALID
;
106 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
108 * Safe to assume is not the second part of a mb char
109 * as this is handled below.
111 /* Eat multiple '/' or '\\' */
112 while (IS_PATH_SEP(*s
,posix_path
)) {
115 if ((d
!= path
) && (*s
!= '\0')) {
116 /* We only care about non-leading or trailing '/' or '\\' */
120 start_of_name_component
= True
;
122 *p_last_component_contains_wcard
= False
;
126 if (start_of_name_component
) {
127 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
128 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
131 * No mb char starts with '.' so we're safe checking the directory separator here.
134 /* If we just added a '/' - delete it */
135 if ((d
> path
) && (*(d
-1) == '/')) {
140 /* Are we at the start ? Can't go back further if so. */
142 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
145 /* Go back one level... */
146 /* We know this is safe as '/' cannot be part of a mb sequence. */
147 /* NOTE - if this assumption is invalid we are not in good shape... */
148 /* Decrement d first as d points to the *next* char to write into. */
149 for (d
--; d
> path
; d
--) {
153 s
+= 2; /* Else go past the .. */
154 /* We're still at the start of a name component, just the previous one. */
157 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
169 if (*s
<= 0x1f || *s
== '|') {
170 return NT_STATUS_OBJECT_NAME_INVALID
;
178 *p_last_component_contains_wcard
= True
;
187 /* Get the size of the next MB character. */
188 next_codepoint(s
,&siz
);
206 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
208 return NT_STATUS_INVALID_PARAMETER
;
211 start_of_name_component
= False
;
219 /****************************************************************************
220 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
221 No wildcards allowed.
222 ****************************************************************************/
224 NTSTATUS
check_path_syntax(char *path
)
227 return check_path_syntax_internal(path
, False
, &ignore
);
230 /****************************************************************************
231 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
232 Wildcards allowed - p_contains_wcard returns true if the last component contained
234 ****************************************************************************/
236 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
238 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
241 /****************************************************************************
242 Check the path for a POSIX client.
243 We're assuming here that '/' is not the second byte in any multibyte char
244 set (a safe assumption).
245 ****************************************************************************/
247 NTSTATUS
check_path_syntax_posix(char *path
)
250 return check_path_syntax_internal(path
, True
, &ignore
);
253 /****************************************************************************
254 Pull a string and check the path allowing a wilcard - provide for error return.
255 ****************************************************************************/
257 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
258 const char *base_ptr
,
265 bool *contains_wcard
)
271 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
275 *err
= NT_STATUS_INVALID_PARAMETER
;
279 *contains_wcard
= False
;
281 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
283 * For a DFS path the function parse_dfs_path()
284 * will do the path processing, just make a copy.
290 if (lp_posix_pathnames()) {
291 *err
= check_path_syntax_posix(*pp_dest
);
293 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
299 /****************************************************************************
300 Pull a string and check the path - provide for error return.
301 ****************************************************************************/
303 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
304 const char *base_ptr
,
313 return srvstr_get_path_wcard(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
314 src_len
, flags
, err
, &ignore
);
317 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
318 char **pp_dest
, const char *src
, int flags
,
319 NTSTATUS
*err
, bool *contains_wcard
)
321 ssize_t bufrem
= smbreq_bufrem(req
, src
);
324 *err
= NT_STATUS_INVALID_PARAMETER
;
328 return srvstr_get_path_wcard(mem_ctx
, (const char *)req
->inbuf
,
329 req
->flags2
, pp_dest
, src
, bufrem
, flags
,
330 err
, contains_wcard
);
333 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
334 char **pp_dest
, const char *src
, int flags
,
338 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
339 flags
, err
, &ignore
);
343 * pull a string from the smb_buf part of a packet. In this case the
344 * string can either be null terminated or it can be terminated by the
345 * end of the smbbuf area
347 size_t srvstr_pull_req_talloc(TALLOC_CTX
*ctx
, struct smb_request
*req
,
348 char **dest
, const char *src
, int flags
)
350 ssize_t bufrem
= smbreq_bufrem(req
, src
);
356 return pull_string_talloc(ctx
, req
->inbuf
, req
->flags2
, dest
, src
,
360 /****************************************************************************
361 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
362 ****************************************************************************/
364 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
367 if ((fsp
== NULL
) || (conn
== NULL
)) {
368 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
371 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
372 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
378 /****************************************************************************
379 Check if we have a correct fsp pointing to a file.
380 ****************************************************************************/
382 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
385 if (!check_fsp_open(conn
, req
, fsp
)) {
388 if (fsp
->is_directory
) {
389 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
392 if (fsp
->fh
->fd
== -1) {
393 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
396 fsp
->num_smb_operations
++;
400 /****************************************************************************
401 Check if we have a correct fsp pointing to a quota fake file. Replacement for
402 the CHECK_NTQUOTA_HANDLE_OK macro.
403 ****************************************************************************/
405 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
408 if (!check_fsp_open(conn
, req
, fsp
)) {
412 if (fsp
->is_directory
) {
416 if (fsp
->fake_file_handle
== NULL
) {
420 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
424 if (fsp
->fake_file_handle
->private_data
== NULL
) {
431 static bool netbios_session_retarget(struct smbd_server_connection
*sconn
,
432 const char *name
, int name_type
)
435 char *trim_name_type
;
436 const char *retarget_parm
;
439 int retarget_type
= 0x20;
440 int retarget_port
= NBT_SMB_PORT
;
441 struct sockaddr_storage retarget_addr
;
442 struct sockaddr_in
*in_addr
;
446 if (get_socket_port(sconn
->sock
) != NBT_SMB_PORT
) {
450 trim_name
= talloc_strdup(talloc_tos(), name
);
451 if (trim_name
== NULL
) {
454 trim_char(trim_name
, ' ', ' ');
456 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
458 if (trim_name_type
== NULL
) {
462 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
463 trim_name_type
, NULL
);
464 if (retarget_parm
== NULL
) {
465 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
468 if (retarget_parm
== NULL
) {
472 retarget
= talloc_strdup(trim_name
, retarget_parm
);
473 if (retarget
== NULL
) {
477 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
479 p
= strchr(retarget
, ':');
482 retarget_port
= atoi(p
);
485 p
= strchr_m(retarget
, '#');
488 if (sscanf(p
, "%x", &retarget_type
) != 1) {
493 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
495 DEBUG(10, ("could not resolve %s\n", retarget
));
499 if (retarget_addr
.ss_family
!= AF_INET
) {
500 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
504 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
506 _smb_setlen(outbuf
, 6);
507 SCVAL(outbuf
, 0, 0x84);
508 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
509 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
511 if (!srv_send_smb(sconn
, (char *)outbuf
, false, 0, false,
513 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
519 TALLOC_FREE(trim_name
);
523 static void reply_called_name_not_present(char *outbuf
)
525 smb_setlen(outbuf
, 1);
526 SCVAL(outbuf
, 0, 0x83);
527 SCVAL(outbuf
, 4, 0x82);
530 /****************************************************************************
531 Reply to a (netbios-level) special message.
532 ****************************************************************************/
534 void reply_special(struct smbd_server_connection
*sconn
, char *inbuf
, size_t inbuf_size
)
536 int msg_type
= CVAL(inbuf
,0);
537 int msg_flags
= CVAL(inbuf
,1);
539 * We only really use 4 bytes of the outbuf, but for the smb_setlen
540 * calculation & friends (srv_send_smb uses that) we need the full smb
543 char outbuf
[smb_size
];
545 memset(outbuf
, '\0', sizeof(outbuf
));
547 smb_setlen(outbuf
,0);
550 case NBSSrequest
: /* session request */
552 /* inbuf_size is guarenteed to be at least 4. */
554 int name_type1
, name_type2
;
555 int name_len1
, name_len2
;
559 if (sconn
->nbt
.got_session
) {
560 exit_server_cleanly("multiple session request not permitted");
563 SCVAL(outbuf
,0,NBSSpositive
);
566 /* inbuf_size is guaranteed to be at least 4. */
567 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
568 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
569 DEBUG(0,("Invalid name length in session request\n"));
570 reply_called_name_not_present(outbuf
);
573 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
574 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
575 DEBUG(0,("Invalid name length in session request\n"));
576 reply_called_name_not_present(outbuf
);
580 name_type1
= name_extract((unsigned char *)inbuf
,
581 inbuf_size
,(unsigned int)4,name1
);
582 name_type2
= name_extract((unsigned char *)inbuf
,
583 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
585 if (name_type1
== -1 || name_type2
== -1) {
586 DEBUG(0,("Invalid name type in session request\n"));
587 reply_called_name_not_present(outbuf
);
591 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
592 name1
, name_type1
, name2
, name_type2
));
594 if (netbios_session_retarget(sconn
, name1
, name_type1
)) {
595 exit_server_cleanly("retargeted client");
599 * Windows NT/2k uses "*SMBSERVER" and XP uses
600 * "*SMBSERV" arrggg!!!
602 if (strequal(name1
, "*SMBSERVER ")
603 || strequal(name1
, "*SMBSERV ")) {
606 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
609 exit_server_cleanly("could not allocate raddr");
612 fstrcpy(name1
, raddr
);
615 set_local_machine_name(name1
, True
);
616 set_remote_machine_name(name2
, True
);
618 if (is_ipaddress(sconn
->remote_hostname
)) {
619 char *p
= discard_const_p(char, sconn
->remote_hostname
);
623 sconn
->remote_hostname
= talloc_strdup(sconn
,
624 get_remote_machine_name());
625 if (sconn
->remote_hostname
== NULL
) {
626 exit_server_cleanly("could not copy remote name");
628 sconn
->conn
->remote_hostname
= sconn
->remote_hostname
;
631 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
632 get_local_machine_name(), get_remote_machine_name(),
635 if (name_type2
== 'R') {
636 /* We are being asked for a pathworks session ---
638 reply_called_name_not_present(outbuf
);
642 reload_services(sconn
, conn_snum_used
, true);
645 sconn
->nbt
.got_session
= true;
649 case 0x89: /* session keepalive request
650 (some old clients produce this?) */
651 SCVAL(outbuf
,0,NBSSkeepalive
);
655 case NBSSpositive
: /* positive session response */
656 case NBSSnegative
: /* negative session response */
657 case NBSSretarget
: /* retarget session response */
658 DEBUG(0,("Unexpected session response\n"));
661 case NBSSkeepalive
: /* session keepalive */
666 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
667 msg_type
, msg_flags
));
669 srv_send_smb(sconn
, outbuf
, false, 0, false, NULL
);
671 if (CVAL(outbuf
, 0) != 0x82) {
672 exit_server_cleanly("invalid netbios session");
677 /****************************************************************************
679 conn POINTER CAN BE NULL HERE !
680 ****************************************************************************/
682 void reply_tcon(struct smb_request
*req
)
684 connection_struct
*conn
= req
->conn
;
686 char *service_buf
= NULL
;
687 char *password
= NULL
;
692 TALLOC_CTX
*ctx
= talloc_tos();
693 struct smbd_server_connection
*sconn
= req
->sconn
;
694 NTTIME now
= timeval_to_nttime(&req
->request_time
);
696 START_PROFILE(SMBtcon
);
698 if (req
->buflen
< 4) {
699 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
700 END_PROFILE(SMBtcon
);
704 p
= (const char *)req
->buf
+ 1;
705 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
707 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
709 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
712 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
713 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
714 END_PROFILE(SMBtcon
);
717 p
= strrchr_m(service_buf
,'\\');
721 service
= service_buf
;
724 conn
= make_connection(sconn
, now
, service
, dev
,
725 req
->vuid
,&nt_status
);
729 reply_nterror(req
, nt_status
);
730 END_PROFILE(SMBtcon
);
734 reply_outbuf(req
, 2, 0);
735 SSVAL(req
->outbuf
,smb_vwv0
,sconn
->smb1
.negprot
.max_recv
);
736 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
737 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
739 DEBUG(3,("tcon service=%s cnum=%d\n",
740 service
, conn
->cnum
));
742 END_PROFILE(SMBtcon
);
746 /****************************************************************************
747 Reply to a tcon and X.
748 conn POINTER CAN BE NULL HERE !
749 ****************************************************************************/
751 void reply_tcon_and_X(struct smb_request
*req
)
753 connection_struct
*conn
= req
->conn
;
754 const char *service
= NULL
;
755 TALLOC_CTX
*ctx
= talloc_tos();
756 /* what the cleint thinks the device is */
757 char *client_devicetype
= NULL
;
758 /* what the server tells the client the share represents */
759 const char *server_devicetype
;
765 struct smbXsrv_session
*session
= NULL
;
766 NTTIME now
= timeval_to_nttime(&req
->request_time
);
767 bool session_key_updated
= false;
768 uint16_t optional_support
= 0;
769 struct smbd_server_connection
*sconn
= req
->sconn
;
771 START_PROFILE(SMBtconX
);
774 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
775 END_PROFILE(SMBtconX
);
779 passlen
= SVAL(req
->vwv
+3, 0);
780 tcon_flags
= SVAL(req
->vwv
+2, 0);
782 /* we might have to close an old one */
783 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
784 struct smbXsrv_tcon
*tcon
;
792 * TODO: cancel all outstanding requests on the tcon
794 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
795 if (!NT_STATUS_IS_OK(status
)) {
796 DEBUG(0, ("reply_tcon_and_X: "
797 "smbXsrv_tcon_disconnect() failed: %s\n",
800 * If we hit this case, there is something completely
801 * wrong, so we better disconnect the transport connection.
803 END_PROFILE(SMBtconX
);
804 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
811 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
812 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
813 END_PROFILE(SMBtconX
);
817 if (sconn
->smb1
.negprot
.encrypted_passwords
) {
818 p
= (const char *)req
->buf
+ passlen
;
820 p
= (const char *)req
->buf
+ passlen
+ 1;
823 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
826 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
827 END_PROFILE(SMBtconX
);
832 * the service name can be either: \\server\share
833 * or share directly like on the DELL PowerVault 705
836 q
= strchr_m(path
+2,'\\');
838 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
839 END_PROFILE(SMBtconX
);
847 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
848 &client_devicetype
, p
,
849 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
851 if (client_devicetype
== NULL
) {
852 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
853 END_PROFILE(SMBtconX
);
857 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
859 nt_status
= smb1srv_session_lookup(req
->sconn
->conn
,
860 req
->vuid
, now
, &session
);
861 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
862 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
863 END_PROFILE(SMBtconX
);
866 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
867 reply_nterror(req
, nt_status
);
868 END_PROFILE(SMBtconX
);
871 if (!NT_STATUS_IS_OK(nt_status
)) {
872 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
873 END_PROFILE(SMBtconX
);
877 if (session
->global
->auth_session_info
== NULL
) {
878 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
879 END_PROFILE(SMBtconX
);
884 * If there is no application key defined yet
887 * This means we setup the application key on the
888 * first tcon that happens via the given session.
890 * Once the application key is defined, it does not
893 if (session
->global
->application_key
.length
== 0 &&
894 session
->global
->signing_key
.length
> 0)
896 struct smbXsrv_session
*x
= session
;
897 struct auth_session_info
*session_info
=
898 session
->global
->auth_session_info
;
899 uint8_t session_key
[16];
901 ZERO_STRUCT(session_key
);
902 memcpy(session_key
, x
->global
->signing_key
.data
,
903 MIN(x
->global
->signing_key
.length
, sizeof(session_key
)));
906 * The application key is truncated/padded to 16 bytes
908 x
->global
->application_key
= data_blob_talloc(x
->global
,
910 sizeof(session_key
));
911 ZERO_STRUCT(session_key
);
912 if (x
->global
->application_key
.data
== NULL
) {
913 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
914 END_PROFILE(SMBtconX
);
918 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
919 smb_key_derivation(x
->global
->application_key
.data
,
920 x
->global
->application_key
.length
,
921 x
->global
->application_key
.data
);
922 optional_support
|= SMB_EXTENDED_SIGNATURES
;
926 * Place the application key into the session_info
928 data_blob_clear_free(&session_info
->session_key
);
929 session_info
->session_key
= data_blob_dup_talloc(session_info
,
930 x
->global
->application_key
);
931 if (session_info
->session_key
.data
== NULL
) {
932 data_blob_clear_free(&x
->global
->application_key
);
933 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
934 END_PROFILE(SMBtconX
);
937 session_key_updated
= true;
940 conn
= make_connection(sconn
, now
, service
, client_devicetype
,
941 req
->vuid
, &nt_status
);
945 if (session_key_updated
) {
946 struct smbXsrv_session
*x
= session
;
947 struct auth_session_info
*session_info
=
948 session
->global
->auth_session_info
;
949 data_blob_clear_free(&x
->global
->application_key
);
950 data_blob_clear_free(&session_info
->session_key
);
952 reply_nterror(req
, nt_status
);
953 END_PROFILE(SMBtconX
);
958 server_devicetype
= "IPC";
959 else if ( IS_PRINT(conn
) )
960 server_devicetype
= "LPT1:";
962 server_devicetype
= "A:";
964 if (get_Protocol() < PROTOCOL_NT1
) {
965 reply_outbuf(req
, 2, 0);
966 if (message_push_string(&req
->outbuf
, server_devicetype
,
967 STR_TERMINATE
|STR_ASCII
) == -1) {
968 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
969 END_PROFILE(SMBtconX
);
973 /* NT sets the fstype of IPC$ to the null string */
974 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(ctx
, SNUM(conn
));
976 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
977 /* Return permissions. */
981 reply_outbuf(req
, 7, 0);
984 perm1
= FILE_ALL_ACCESS
;
985 perm2
= FILE_ALL_ACCESS
;
987 perm1
= conn
->share_access
;
990 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
991 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
993 reply_outbuf(req
, 3, 0);
996 if ((message_push_string(&req
->outbuf
, server_devicetype
,
997 STR_TERMINATE
|STR_ASCII
) == -1)
998 || (message_push_string(&req
->outbuf
, fstype
,
999 STR_TERMINATE
) == -1)) {
1000 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1001 END_PROFILE(SMBtconX
);
1005 /* what does setting this bit do? It is set by NT4 and
1006 may affect the ability to autorun mounted cdroms */
1007 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
1009 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
1011 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
1012 DEBUG(2,("Serving %s as a Dfs root\n",
1013 lp_servicename(ctx
, SNUM(conn
)) ));
1014 optional_support
|= SMB_SHARE_IN_DFS
;
1017 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
1020 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1021 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1023 DEBUG(3,("tconX service=%s \n",
1026 /* set the incoming and outgoing tid to the just created one */
1027 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1028 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1030 END_PROFILE(SMBtconX
);
1032 req
->tid
= conn
->cnum
;
1035 /****************************************************************************
1036 Reply to an unknown type.
1037 ****************************************************************************/
1039 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
1041 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1042 smb_fn_name(type
), type
, type
));
1043 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1047 /****************************************************************************
1049 conn POINTER CAN BE NULL HERE !
1050 ****************************************************************************/
1052 void reply_ioctl(struct smb_request
*req
)
1054 connection_struct
*conn
= req
->conn
;
1061 START_PROFILE(SMBioctl
);
1064 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1065 END_PROFILE(SMBioctl
);
1069 device
= SVAL(req
->vwv
+1, 0);
1070 function
= SVAL(req
->vwv
+2, 0);
1071 ioctl_code
= (device
<< 16) + function
;
1073 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1075 switch (ioctl_code
) {
1076 case IOCTL_QUERY_JOB_INFO
:
1080 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1081 END_PROFILE(SMBioctl
);
1085 reply_outbuf(req
, 8, replysize
+1);
1086 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1087 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1088 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1089 p
= smb_buf(req
->outbuf
);
1090 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1091 p
+= 1; /* Allow for alignment */
1093 switch (ioctl_code
) {
1094 case IOCTL_QUERY_JOB_INFO
:
1096 files_struct
*fsp
= file_fsp(
1097 req
, SVAL(req
->vwv
+0, 0));
1099 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1100 END_PROFILE(SMBioctl
);
1104 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1106 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1107 lp_netbios_name(), 15,
1108 STR_TERMINATE
|STR_ASCII
);
1110 srvstr_push((char *)req
->outbuf
, req
->flags2
,
1112 lp_servicename(talloc_tos(),
1114 13, STR_TERMINATE
|STR_ASCII
);
1116 memset(p
+18, 0, 13);
1122 END_PROFILE(SMBioctl
);
1126 /****************************************************************************
1127 Strange checkpath NTSTATUS mapping.
1128 ****************************************************************************/
1130 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1132 /* Strange DOS error code semantics only for checkpath... */
1133 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1134 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1135 /* We need to map to ERRbadpath */
1136 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1142 /****************************************************************************
1143 Reply to a checkpath.
1144 ****************************************************************************/
1146 void reply_checkpath(struct smb_request
*req
)
1148 connection_struct
*conn
= req
->conn
;
1149 struct smb_filename
*smb_fname
= NULL
;
1152 TALLOC_CTX
*ctx
= talloc_tos();
1154 START_PROFILE(SMBcheckpath
);
1156 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1157 STR_TERMINATE
, &status
);
1159 if (!NT_STATUS_IS_OK(status
)) {
1160 status
= map_checkpath_error(req
->flags2
, status
);
1161 reply_nterror(req
, status
);
1162 END_PROFILE(SMBcheckpath
);
1166 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1168 status
= filename_convert(ctx
,
1170 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1176 if (!NT_STATUS_IS_OK(status
)) {
1177 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1178 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1179 ERRSRV
, ERRbadpath
);
1180 END_PROFILE(SMBcheckpath
);
1186 if (!VALID_STAT(smb_fname
->st
) &&
1187 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1188 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1189 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1190 status
= map_nt_error_from_unix(errno
);
1194 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1195 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1196 ERRDOS
, ERRbadpath
);
1200 reply_outbuf(req
, 0, 0);
1203 /* We special case this - as when a Windows machine
1204 is parsing a path is steps through the components
1205 one at a time - if a component fails it expects
1206 ERRbadpath, not ERRbadfile.
1208 status
= map_checkpath_error(req
->flags2
, status
);
1209 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1211 * Windows returns different error codes if
1212 * the parent directory is valid but not the
1213 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1214 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1215 * if the path is invalid.
1217 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1218 ERRDOS
, ERRbadpath
);
1222 reply_nterror(req
, status
);
1225 TALLOC_FREE(smb_fname
);
1226 END_PROFILE(SMBcheckpath
);
1230 /****************************************************************************
1232 ****************************************************************************/
1234 void reply_getatr(struct smb_request
*req
)
1236 connection_struct
*conn
= req
->conn
;
1237 struct smb_filename
*smb_fname
= NULL
;
1244 TALLOC_CTX
*ctx
= talloc_tos();
1245 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1247 START_PROFILE(SMBgetatr
);
1249 p
= (const char *)req
->buf
+ 1;
1250 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1251 if (!NT_STATUS_IS_OK(status
)) {
1252 reply_nterror(req
, status
);
1256 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1257 under WfWg - weird! */
1258 if (*fname
== '\0') {
1259 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1260 if (!CAN_WRITE(conn
)) {
1261 mode
|= FILE_ATTRIBUTE_READONLY
;
1266 status
= filename_convert(ctx
,
1268 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1273 if (!NT_STATUS_IS_OK(status
)) {
1274 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1275 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1276 ERRSRV
, ERRbadpath
);
1279 reply_nterror(req
, status
);
1282 if (!VALID_STAT(smb_fname
->st
) &&
1283 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1284 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1285 smb_fname_str_dbg(smb_fname
),
1287 reply_nterror(req
, map_nt_error_from_unix(errno
));
1291 mode
= dos_mode(conn
, smb_fname
);
1292 size
= smb_fname
->st
.st_ex_size
;
1294 if (ask_sharemode
) {
1295 struct timespec write_time_ts
;
1296 struct file_id fileid
;
1298 ZERO_STRUCT(write_time_ts
);
1299 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1300 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1301 if (!null_timespec(write_time_ts
)) {
1302 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1306 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1307 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1312 reply_outbuf(req
, 10, 0);
1314 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1315 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1316 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1318 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1320 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1322 if (get_Protocol() >= PROTOCOL_NT1
) {
1323 SSVAL(req
->outbuf
, smb_flg2
,
1324 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1327 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1328 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1331 TALLOC_FREE(smb_fname
);
1333 END_PROFILE(SMBgetatr
);
1337 /****************************************************************************
1339 ****************************************************************************/
1341 void reply_setatr(struct smb_request
*req
)
1343 struct smb_file_time ft
;
1344 connection_struct
*conn
= req
->conn
;
1345 struct smb_filename
*smb_fname
= NULL
;
1351 TALLOC_CTX
*ctx
= talloc_tos();
1353 START_PROFILE(SMBsetatr
);
1358 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1362 p
= (const char *)req
->buf
+ 1;
1363 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1364 if (!NT_STATUS_IS_OK(status
)) {
1365 reply_nterror(req
, status
);
1369 status
= filename_convert(ctx
,
1371 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1376 if (!NT_STATUS_IS_OK(status
)) {
1377 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1378 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1379 ERRSRV
, ERRbadpath
);
1382 reply_nterror(req
, status
);
1386 if (smb_fname
->base_name
[0] == '.' &&
1387 smb_fname
->base_name
[1] == '\0') {
1389 * Not sure here is the right place to catch this
1390 * condition. Might be moved to somewhere else later -- vl
1392 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1396 mode
= SVAL(req
->vwv
+0, 0);
1397 mtime
= srv_make_unix_date3(req
->vwv
+1);
1399 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1400 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1401 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1403 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1405 status
= check_access(conn
, NULL
, smb_fname
,
1406 FILE_WRITE_ATTRIBUTES
);
1407 if (!NT_STATUS_IS_OK(status
)) {
1408 reply_nterror(req
, status
);
1412 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1414 reply_nterror(req
, map_nt_error_from_unix(errno
));
1419 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1420 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1421 if (!NT_STATUS_IS_OK(status
)) {
1422 reply_nterror(req
, status
);
1426 reply_outbuf(req
, 0, 0);
1428 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1431 TALLOC_FREE(smb_fname
);
1432 END_PROFILE(SMBsetatr
);
1436 /****************************************************************************
1438 ****************************************************************************/
1440 void reply_dskattr(struct smb_request
*req
)
1442 connection_struct
*conn
= req
->conn
;
1443 uint64_t dfree
,dsize
,bsize
;
1444 START_PROFILE(SMBdskattr
);
1446 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1447 reply_nterror(req
, map_nt_error_from_unix(errno
));
1448 END_PROFILE(SMBdskattr
);
1452 reply_outbuf(req
, 5, 0);
1454 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1455 double total_space
, free_space
;
1456 /* we need to scale this to a number that DOS6 can handle. We
1457 use floating point so we can handle large drives on systems
1458 that don't have 64 bit integers
1460 we end up displaying a maximum of 2G to DOS systems
1462 total_space
= dsize
* (double)bsize
;
1463 free_space
= dfree
* (double)bsize
;
1465 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1466 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1468 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1469 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1471 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1472 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1473 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1474 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1476 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1477 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1478 SSVAL(req
->outbuf
,smb_vwv2
,512);
1479 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1482 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1484 END_PROFILE(SMBdskattr
);
1489 * Utility function to split the filename from the directory.
1491 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1492 char **fname_dir_out
,
1493 char **fname_mask_out
)
1495 const char *p
= NULL
;
1496 char *fname_dir
= NULL
;
1497 char *fname_mask
= NULL
;
1499 p
= strrchr_m(fname_in
, '/');
1501 fname_dir
= talloc_strdup(ctx
, ".");
1502 fname_mask
= talloc_strdup(ctx
, fname_in
);
1504 fname_dir
= talloc_strndup(ctx
, fname_in
,
1505 PTR_DIFF(p
, fname_in
));
1506 fname_mask
= talloc_strdup(ctx
, p
+1);
1509 if (!fname_dir
|| !fname_mask
) {
1510 TALLOC_FREE(fname_dir
);
1511 TALLOC_FREE(fname_mask
);
1512 return NT_STATUS_NO_MEMORY
;
1515 *fname_dir_out
= fname_dir
;
1516 *fname_mask_out
= fname_mask
;
1517 return NT_STATUS_OK
;
1520 /****************************************************************************
1522 Can be called from SMBsearch, SMBffirst or SMBfunique.
1523 ****************************************************************************/
1525 void reply_search(struct smb_request
*req
)
1527 connection_struct
*conn
= req
->conn
;
1529 const char *mask
= NULL
;
1530 char *directory
= NULL
;
1531 struct smb_filename
*smb_fname
= NULL
;
1535 struct timespec date
;
1537 unsigned int numentries
= 0;
1538 unsigned int maxentries
= 0;
1539 bool finished
= False
;
1544 bool check_descend
= False
;
1545 bool expect_close
= False
;
1547 bool mask_contains_wcard
= False
;
1548 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1549 TALLOC_CTX
*ctx
= talloc_tos();
1550 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1551 struct dptr_struct
*dirptr
= NULL
;
1552 struct smbd_server_connection
*sconn
= req
->sconn
;
1554 START_PROFILE(SMBsearch
);
1557 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1561 if (lp_posix_pathnames()) {
1562 reply_unknown_new(req
, req
->cmd
);
1566 /* If we were called as SMBffirst then we must expect close. */
1567 if(req
->cmd
== SMBffirst
) {
1568 expect_close
= True
;
1571 reply_outbuf(req
, 1, 3);
1572 maxentries
= SVAL(req
->vwv
+0, 0);
1573 dirtype
= SVAL(req
->vwv
+1, 0);
1574 p
= (const char *)req
->buf
+ 1;
1575 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1576 &nt_status
, &mask_contains_wcard
);
1577 if (!NT_STATUS_IS_OK(nt_status
)) {
1578 reply_nterror(req
, nt_status
);
1583 status_len
= SVAL(p
, 0);
1586 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1588 if (status_len
== 0) {
1589 nt_status
= filename_convert(ctx
, conn
,
1590 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1592 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1593 &mask_contains_wcard
,
1595 if (!NT_STATUS_IS_OK(nt_status
)) {
1596 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1597 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1598 ERRSRV
, ERRbadpath
);
1601 reply_nterror(req
, nt_status
);
1605 directory
= smb_fname
->base_name
;
1607 p
= strrchr_m(directory
,'/');
1608 if ((p
!= NULL
) && (*directory
!= '/')) {
1610 directory
= talloc_strndup(ctx
, directory
,
1611 PTR_DIFF(p
, directory
));
1614 directory
= talloc_strdup(ctx
,".");
1618 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1622 memset((char *)status
,'\0',21);
1623 SCVAL(status
,0,(dirtype
& 0x1F));
1625 nt_status
= dptr_create(conn
,
1633 mask_contains_wcard
,
1636 if (!NT_STATUS_IS_OK(nt_status
)) {
1637 reply_nterror(req
, nt_status
);
1640 dptr_num
= dptr_dnum(dirptr
);
1643 const char *dirpath
;
1645 memcpy(status
,p
,21);
1646 status_dirtype
= CVAL(status
,0) & 0x1F;
1647 if (status_dirtype
!= (dirtype
& 0x1F)) {
1648 dirtype
= status_dirtype
;
1651 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1655 dirpath
= dptr_path(sconn
, dptr_num
);
1656 directory
= talloc_strdup(ctx
, dirpath
);
1658 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1662 mask
= dptr_wcard(sconn
, dptr_num
);
1667 * For a 'continue' search we have no string. So
1668 * check from the initial saved string.
1670 mask_contains_wcard
= ms_has_wild(mask
);
1671 dirtype
= dptr_attr(sconn
, dptr_num
);
1674 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1676 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1677 dptr_init_search_op(dirptr
);
1679 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1680 char buf
[DIR_STRUCT_SIZE
];
1681 memcpy(buf
,status
,21);
1682 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1683 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1684 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1687 dptr_fill(sconn
, buf
+12,dptr_num
);
1688 if (dptr_zero(buf
+12) && (status_len
==0)) {
1693 if (message_push_blob(&req
->outbuf
,
1694 data_blob_const(buf
, sizeof(buf
)))
1696 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1704 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1707 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1708 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
1709 if (in_list(directory
, lp_dontdescend(ctx
, SNUM(conn
)),True
)) {
1710 check_descend
= True
;
1713 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1714 finished
= !get_dir_entry(ctx
,
1725 char buf
[DIR_STRUCT_SIZE
];
1726 memcpy(buf
,status
,21);
1727 if (!make_dir_struct(ctx
,
1733 convert_timespec_to_time_t(date
),
1734 !allow_long_path_components
)) {
1735 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1738 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1741 if (message_push_blob(&req
->outbuf
,
1742 data_blob_const(buf
, sizeof(buf
)))
1744 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1754 /* If we were called as SMBffirst with smb_search_id == NULL
1755 and no entries were found then return error and close dirptr
1758 if (numentries
== 0) {
1759 dptr_close(sconn
, &dptr_num
);
1760 } else if(expect_close
&& status_len
== 0) {
1761 /* Close the dptr - we know it's gone */
1762 dptr_close(sconn
, &dptr_num
);
1765 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1766 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1767 dptr_close(sconn
, &dptr_num
);
1770 if ((numentries
== 0) && !mask_contains_wcard
) {
1771 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1775 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1776 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1777 SCVAL(smb_buf(req
->outbuf
),0,5);
1778 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1780 /* The replies here are never long name. */
1781 SSVAL(req
->outbuf
, smb_flg2
,
1782 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1783 if (!allow_long_path_components
) {
1784 SSVAL(req
->outbuf
, smb_flg2
,
1785 SVAL(req
->outbuf
, smb_flg2
)
1786 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1789 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1790 SSVAL(req
->outbuf
, smb_flg2
,
1791 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1793 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1794 smb_fn_name(req
->cmd
),
1801 TALLOC_FREE(directory
);
1802 TALLOC_FREE(smb_fname
);
1803 END_PROFILE(SMBsearch
);
1807 /****************************************************************************
1808 Reply to a fclose (stop directory search).
1809 ****************************************************************************/
1811 void reply_fclose(struct smb_request
*req
)
1819 bool path_contains_wcard
= False
;
1820 TALLOC_CTX
*ctx
= talloc_tos();
1821 struct smbd_server_connection
*sconn
= req
->sconn
;
1823 START_PROFILE(SMBfclose
);
1825 if (lp_posix_pathnames()) {
1826 reply_unknown_new(req
, req
->cmd
);
1827 END_PROFILE(SMBfclose
);
1831 p
= (const char *)req
->buf
+ 1;
1832 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1833 &err
, &path_contains_wcard
);
1834 if (!NT_STATUS_IS_OK(err
)) {
1835 reply_nterror(req
, err
);
1836 END_PROFILE(SMBfclose
);
1840 status_len
= SVAL(p
,0);
1843 if (status_len
== 0) {
1844 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1845 END_PROFILE(SMBfclose
);
1849 memcpy(status
,p
,21);
1851 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1852 /* Close the dptr - we know it's gone */
1853 dptr_close(sconn
, &dptr_num
);
1856 reply_outbuf(req
, 1, 0);
1857 SSVAL(req
->outbuf
,smb_vwv0
,0);
1859 DEBUG(3,("search close\n"));
1861 END_PROFILE(SMBfclose
);
1865 /****************************************************************************
1867 ****************************************************************************/
1869 void reply_open(struct smb_request
*req
)
1871 connection_struct
*conn
= req
->conn
;
1872 struct smb_filename
*smb_fname
= NULL
;
1884 uint32 create_disposition
;
1885 uint32 create_options
= 0;
1886 uint32_t private_flags
= 0;
1888 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1889 TALLOC_CTX
*ctx
= talloc_tos();
1891 START_PROFILE(SMBopen
);
1894 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1898 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1899 deny_mode
= SVAL(req
->vwv
+0, 0);
1900 dos_attr
= SVAL(req
->vwv
+1, 0);
1902 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1903 STR_TERMINATE
, &status
);
1904 if (!NT_STATUS_IS_OK(status
)) {
1905 reply_nterror(req
, status
);
1909 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1910 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1911 &share_mode
, &create_disposition
,
1912 &create_options
, &private_flags
)) {
1913 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1917 status
= filename_convert(ctx
,
1919 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1921 (create_disposition
== FILE_CREATE
)
1922 ? UCF_CREATING_FILE
: 0,
1925 if (!NT_STATUS_IS_OK(status
)) {
1926 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1927 reply_botherror(req
,
1928 NT_STATUS_PATH_NOT_COVERED
,
1929 ERRSRV
, ERRbadpath
);
1932 reply_nterror(req
, status
);
1936 status
= SMB_VFS_CREATE_FILE(
1939 0, /* root_dir_fid */
1940 smb_fname
, /* fname */
1941 access_mask
, /* access_mask */
1942 share_mode
, /* share_access */
1943 create_disposition
, /* create_disposition*/
1944 create_options
, /* create_options */
1945 dos_attr
, /* file_attributes */
1946 oplock_request
, /* oplock_request */
1947 0, /* allocation_size */
1954 if (!NT_STATUS_IS_OK(status
)) {
1955 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1956 /* We have re-scheduled this call. */
1959 reply_openerror(req
, status
);
1963 size
= smb_fname
->st
.st_ex_size
;
1964 fattr
= dos_mode(conn
, smb_fname
);
1966 /* Deal with other possible opens having a modified
1968 if (ask_sharemode
) {
1969 struct timespec write_time_ts
;
1971 ZERO_STRUCT(write_time_ts
);
1972 get_file_infos(fsp
->file_id
, 0, NULL
, &write_time_ts
);
1973 if (!null_timespec(write_time_ts
)) {
1974 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1978 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1980 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1981 DEBUG(3,("attempt to open a directory %s\n",
1983 close_file(req
, fsp
, ERROR_CLOSE
);
1984 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1985 ERRDOS
, ERRnoaccess
);
1989 reply_outbuf(req
, 7, 0);
1990 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1991 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1992 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1993 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1995 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1997 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1998 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2000 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2001 SCVAL(req
->outbuf
,smb_flg
,
2002 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2005 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2006 SCVAL(req
->outbuf
,smb_flg
,
2007 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2010 TALLOC_FREE(smb_fname
);
2011 END_PROFILE(SMBopen
);
2015 /****************************************************************************
2016 Reply to an open and X.
2017 ****************************************************************************/
2019 void reply_open_and_X(struct smb_request
*req
)
2021 connection_struct
*conn
= req
->conn
;
2022 struct smb_filename
*smb_fname
= NULL
;
2027 /* Breakout the oplock request bits so we can set the
2028 reply bits separately. */
2029 int ex_oplock_request
;
2030 int core_oplock_request
;
2033 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2034 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
2042 uint64_t allocation_size
;
2043 ssize_t retval
= -1;
2046 uint32 create_disposition
;
2047 uint32 create_options
= 0;
2048 uint32_t private_flags
= 0;
2049 TALLOC_CTX
*ctx
= talloc_tos();
2051 START_PROFILE(SMBopenX
);
2053 if (req
->wct
< 15) {
2054 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2058 open_flags
= SVAL(req
->vwv
+2, 0);
2059 deny_mode
= SVAL(req
->vwv
+3, 0);
2060 smb_attr
= SVAL(req
->vwv
+5, 0);
2061 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2062 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2063 oplock_request
= ex_oplock_request
| core_oplock_request
;
2064 smb_ofun
= SVAL(req
->vwv
+8, 0);
2065 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2067 /* If it's an IPC, pass off the pipe handler. */
2069 if (lp_nt_pipe_support()) {
2070 reply_open_pipe_and_X(conn
, req
);
2072 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2077 /* XXXX we need to handle passed times, sattr and flags */
2078 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2079 STR_TERMINATE
, &status
);
2080 if (!NT_STATUS_IS_OK(status
)) {
2081 reply_nterror(req
, status
);
2085 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2087 &access_mask
, &share_mode
,
2088 &create_disposition
,
2091 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2095 status
= filename_convert(ctx
,
2097 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2099 (create_disposition
== FILE_CREATE
)
2100 ? UCF_CREATING_FILE
: 0,
2103 if (!NT_STATUS_IS_OK(status
)) {
2104 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2105 reply_botherror(req
,
2106 NT_STATUS_PATH_NOT_COVERED
,
2107 ERRSRV
, ERRbadpath
);
2110 reply_nterror(req
, status
);
2114 status
= SMB_VFS_CREATE_FILE(
2117 0, /* root_dir_fid */
2118 smb_fname
, /* fname */
2119 access_mask
, /* access_mask */
2120 share_mode
, /* share_access */
2121 create_disposition
, /* create_disposition*/
2122 create_options
, /* create_options */
2123 smb_attr
, /* file_attributes */
2124 oplock_request
, /* oplock_request */
2125 0, /* allocation_size */
2130 &smb_action
); /* pinfo */
2132 if (!NT_STATUS_IS_OK(status
)) {
2133 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2134 /* We have re-scheduled this call. */
2137 reply_openerror(req
, status
);
2141 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2142 if the file is truncated or created. */
2143 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2144 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2145 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2146 close_file(req
, fsp
, ERROR_CLOSE
);
2147 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2150 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2152 close_file(req
, fsp
, ERROR_CLOSE
);
2153 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2156 status
= vfs_stat_fsp(fsp
);
2157 if (!NT_STATUS_IS_OK(status
)) {
2158 close_file(req
, fsp
, ERROR_CLOSE
);
2159 reply_nterror(req
, status
);
2164 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2165 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2166 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2167 close_file(req
, fsp
, ERROR_CLOSE
);
2168 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2172 /* If the caller set the extended oplock request bit
2173 and we granted one (by whatever means) - set the
2174 correct bit for extended oplock reply.
2177 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2178 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2181 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2182 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2185 /* If the caller set the core oplock request bit
2186 and we granted one (by whatever means) - set the
2187 correct bit for core oplock reply.
2190 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2191 reply_outbuf(req
, 19, 0);
2193 reply_outbuf(req
, 15, 0);
2196 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2197 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2199 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2200 SCVAL(req
->outbuf
, smb_flg
,
2201 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2204 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2205 SCVAL(req
->outbuf
, smb_flg
,
2206 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2209 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2210 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2211 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2212 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2214 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2216 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2217 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2218 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2220 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2221 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2225 TALLOC_FREE(smb_fname
);
2226 END_PROFILE(SMBopenX
);
2230 /****************************************************************************
2231 Reply to a SMBulogoffX.
2232 ****************************************************************************/
2234 void reply_ulogoffX(struct smb_request
*req
)
2236 struct smbd_server_connection
*sconn
= req
->sconn
;
2237 struct user_struct
*vuser
;
2238 struct smbXsrv_session
*session
= NULL
;
2241 START_PROFILE(SMBulogoffX
);
2243 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2246 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2247 (unsigned long long)req
->vuid
));
2249 req
->vuid
= UID_FIELD_INVALID
;
2250 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2251 END_PROFILE(SMBulogoffX
);
2255 session
= vuser
->session
;
2259 * TODO: cancel all outstanding requests on the session
2261 status
= smbXsrv_session_logoff(session
);
2262 if (!NT_STATUS_IS_OK(status
)) {
2263 DEBUG(0, ("reply_ulogoff: "
2264 "smbXsrv_session_logoff() failed: %s\n",
2265 nt_errstr(status
)));
2267 * If we hit this case, there is something completely
2268 * wrong, so we better disconnect the transport connection.
2270 END_PROFILE(SMBulogoffX
);
2271 exit_server(__location__
": smbXsrv_session_logoff failed");
2275 TALLOC_FREE(session
);
2277 reply_outbuf(req
, 2, 0);
2278 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2279 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2281 DEBUG(3, ("ulogoffX vuid=%llu\n",
2282 (unsigned long long)req
->vuid
));
2284 END_PROFILE(SMBulogoffX
);
2285 req
->vuid
= UID_FIELD_INVALID
;
2288 /****************************************************************************
2289 Reply to a mknew or a create.
2290 ****************************************************************************/
2292 void reply_mknew(struct smb_request
*req
)
2294 connection_struct
*conn
= req
->conn
;
2295 struct smb_filename
*smb_fname
= NULL
;
2298 struct smb_file_time ft
;
2300 int oplock_request
= 0;
2302 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2303 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2304 uint32 create_disposition
;
2305 uint32 create_options
= 0;
2306 TALLOC_CTX
*ctx
= talloc_tos();
2308 START_PROFILE(SMBcreate
);
2312 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2316 fattr
= SVAL(req
->vwv
+0, 0);
2317 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2320 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2322 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2323 STR_TERMINATE
, &status
);
2324 if (!NT_STATUS_IS_OK(status
)) {
2325 reply_nterror(req
, status
);
2329 status
= filename_convert(ctx
,
2331 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2336 if (!NT_STATUS_IS_OK(status
)) {
2337 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2338 reply_botherror(req
,
2339 NT_STATUS_PATH_NOT_COVERED
,
2340 ERRSRV
, ERRbadpath
);
2343 reply_nterror(req
, status
);
2347 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2348 DEBUG(0,("Attempt to create file (%s) with volid set - "
2349 "please report this\n",
2350 smb_fname_str_dbg(smb_fname
)));
2353 if(req
->cmd
== SMBmknew
) {
2354 /* We should fail if file exists. */
2355 create_disposition
= FILE_CREATE
;
2357 /* Create if file doesn't exist, truncate if it does. */
2358 create_disposition
= FILE_OVERWRITE_IF
;
2361 status
= SMB_VFS_CREATE_FILE(
2364 0, /* root_dir_fid */
2365 smb_fname
, /* fname */
2366 access_mask
, /* access_mask */
2367 share_mode
, /* share_access */
2368 create_disposition
, /* create_disposition*/
2369 create_options
, /* create_options */
2370 fattr
, /* file_attributes */
2371 oplock_request
, /* oplock_request */
2372 0, /* allocation_size */
2373 0, /* private_flags */
2379 if (!NT_STATUS_IS_OK(status
)) {
2380 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2381 /* We have re-scheduled this call. */
2384 reply_openerror(req
, status
);
2388 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2389 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2390 if (!NT_STATUS_IS_OK(status
)) {
2391 END_PROFILE(SMBcreate
);
2395 reply_outbuf(req
, 1, 0);
2396 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2398 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2399 SCVAL(req
->outbuf
,smb_flg
,
2400 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2403 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2404 SCVAL(req
->outbuf
,smb_flg
,
2405 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2408 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2409 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2410 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2411 (unsigned int)fattr
));
2414 TALLOC_FREE(smb_fname
);
2415 END_PROFILE(SMBcreate
);
2419 /****************************************************************************
2420 Reply to a create temporary file.
2421 ****************************************************************************/
2423 void reply_ctemp(struct smb_request
*req
)
2425 connection_struct
*conn
= req
->conn
;
2426 struct smb_filename
*smb_fname
= NULL
;
2427 char *wire_name
= NULL
;
2435 TALLOC_CTX
*ctx
= talloc_tos();
2437 START_PROFILE(SMBctemp
);
2440 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2444 fattr
= SVAL(req
->vwv
+0, 0);
2445 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2447 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2448 STR_TERMINATE
, &status
);
2449 if (!NT_STATUS_IS_OK(status
)) {
2450 reply_nterror(req
, status
);
2454 for (i
= 0; i
< 10; i
++) {
2456 fname
= talloc_asprintf(ctx
,
2459 generate_random_str_list(ctx
, 5, "0123456789"));
2461 fname
= talloc_asprintf(ctx
,
2463 generate_random_str_list(ctx
, 5, "0123456789"));
2467 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2471 status
= filename_convert(ctx
, conn
,
2472 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2477 if (!NT_STATUS_IS_OK(status
)) {
2478 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2479 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2480 ERRSRV
, ERRbadpath
);
2483 reply_nterror(req
, status
);
2487 /* Create the file. */
2488 status
= SMB_VFS_CREATE_FILE(
2491 0, /* root_dir_fid */
2492 smb_fname
, /* fname */
2493 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2494 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2495 FILE_CREATE
, /* create_disposition*/
2496 0, /* create_options */
2497 fattr
, /* file_attributes */
2498 oplock_request
, /* oplock_request */
2499 0, /* allocation_size */
2500 0, /* private_flags */
2506 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2508 TALLOC_FREE(smb_fname
);
2512 if (!NT_STATUS_IS_OK(status
)) {
2513 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2514 /* We have re-scheduled this call. */
2517 reply_openerror(req
, status
);
2525 /* Collision after 10 times... */
2526 reply_nterror(req
, status
);
2530 reply_outbuf(req
, 1, 0);
2531 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2533 /* the returned filename is relative to the directory */
2534 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2536 s
= fsp
->fsp_name
->base_name
;
2542 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2543 thing in the byte section. JRA */
2544 SSVALS(p
, 0, -1); /* what is this? not in spec */
2546 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2548 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2552 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2553 SCVAL(req
->outbuf
, smb_flg
,
2554 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2557 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2558 SCVAL(req
->outbuf
, smb_flg
,
2559 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2562 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2563 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2564 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2566 TALLOC_FREE(smb_fname
);
2567 TALLOC_FREE(wire_name
);
2568 END_PROFILE(SMBctemp
);
2572 /*******************************************************************
2573 Check if a user is allowed to rename a file.
2574 ********************************************************************/
2576 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2579 if (!CAN_WRITE(conn
)) {
2580 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2583 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2584 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2585 /* Only bother to read the DOS attribute if we might deny the
2586 rename on the grounds of attribute missmatch. */
2587 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2588 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2589 return NT_STATUS_NO_SUCH_FILE
;
2593 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2594 if (fsp
->posix_open
) {
2595 return NT_STATUS_OK
;
2598 /* If no pathnames are open below this
2599 directory, allow the rename. */
2601 if (file_find_subpath(fsp
)) {
2602 return NT_STATUS_ACCESS_DENIED
;
2604 return NT_STATUS_OK
;
2607 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2608 return NT_STATUS_OK
;
2611 return NT_STATUS_ACCESS_DENIED
;
2614 /*******************************************************************
2615 * unlink a file with all relevant access checks
2616 *******************************************************************/
2618 static NTSTATUS
do_unlink(connection_struct
*conn
,
2619 struct smb_request
*req
,
2620 struct smb_filename
*smb_fname
,
2625 uint32 dirtype_orig
= dirtype
;
2628 bool posix_paths
= lp_posix_pathnames();
2630 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2631 smb_fname_str_dbg(smb_fname
),
2634 if (!CAN_WRITE(conn
)) {
2635 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2639 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2641 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2644 return map_nt_error_from_unix(errno
);
2647 fattr
= dos_mode(conn
, smb_fname
);
2649 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2650 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2653 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2655 return NT_STATUS_NO_SUCH_FILE
;
2658 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2659 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2660 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2662 return NT_STATUS_NO_SUCH_FILE
;
2665 if (dirtype_orig
& 0x8000) {
2666 /* These will never be set for POSIX. */
2667 return NT_STATUS_NO_SUCH_FILE
;
2671 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2672 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2675 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2676 return NT_STATUS_NO_SUCH_FILE
;
2679 if (dirtype
& 0xFF00) {
2680 /* These will never be set for POSIX. */
2681 return NT_STATUS_NO_SUCH_FILE
;
2686 return NT_STATUS_NO_SUCH_FILE
;
2689 /* Can't delete a directory. */
2690 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2691 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2696 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2697 return NT_STATUS_OBJECT_NAME_INVALID
;
2698 #endif /* JRATEST */
2700 /* On open checks the open itself will check the share mode, so
2701 don't do it here as we'll get it wrong. */
2703 status
= SMB_VFS_CREATE_FILE
2706 0, /* root_dir_fid */
2707 smb_fname
, /* fname */
2708 DELETE_ACCESS
, /* access_mask */
2709 FILE_SHARE_NONE
, /* share_access */
2710 FILE_OPEN
, /* create_disposition*/
2711 FILE_NON_DIRECTORY_FILE
, /* create_options */
2712 /* file_attributes */
2713 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2714 FILE_ATTRIBUTE_NORMAL
,
2715 0, /* oplock_request */
2716 0, /* allocation_size */
2717 0, /* private_flags */
2723 if (!NT_STATUS_IS_OK(status
)) {
2724 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2725 nt_errstr(status
)));
2729 status
= can_set_delete_on_close(fsp
, fattr
);
2730 if (!NT_STATUS_IS_OK(status
)) {
2731 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2733 smb_fname_str_dbg(smb_fname
),
2734 nt_errstr(status
)));
2735 close_file(req
, fsp
, NORMAL_CLOSE
);
2739 /* The set is across all open files on this dev/inode pair. */
2740 if (!set_delete_on_close(fsp
, True
,
2741 conn
->session_info
->security_token
,
2742 conn
->session_info
->unix_token
)) {
2743 close_file(req
, fsp
, NORMAL_CLOSE
);
2744 return NT_STATUS_ACCESS_DENIED
;
2747 return close_file(req
, fsp
, NORMAL_CLOSE
);
2750 /****************************************************************************
2751 The guts of the unlink command, split out so it may be called by the NT SMB
2753 ****************************************************************************/
2755 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2756 uint32 dirtype
, struct smb_filename
*smb_fname
,
2759 char *fname_dir
= NULL
;
2760 char *fname_mask
= NULL
;
2762 NTSTATUS status
= NT_STATUS_OK
;
2763 TALLOC_CTX
*ctx
= talloc_tos();
2765 /* Split up the directory from the filename/mask. */
2766 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2767 &fname_dir
, &fname_mask
);
2768 if (!NT_STATUS_IS_OK(status
)) {
2773 * We should only check the mangled cache
2774 * here if unix_convert failed. This means
2775 * that the path in 'mask' doesn't exist
2776 * on the file system and so we need to look
2777 * for a possible mangle. This patch from
2778 * Tine Smukavec <valentin.smukavec@hermes.si>.
2781 if (!VALID_STAT(smb_fname
->st
) &&
2782 mangle_is_mangled(fname_mask
, conn
->params
)) {
2783 char *new_mask
= NULL
;
2784 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2785 &new_mask
, conn
->params
);
2787 TALLOC_FREE(fname_mask
);
2788 fname_mask
= new_mask
;
2795 * Only one file needs to be unlinked. Append the mask back
2796 * onto the directory.
2798 TALLOC_FREE(smb_fname
->base_name
);
2799 if (ISDOT(fname_dir
)) {
2800 /* Ensure we use canonical names on open. */
2801 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2805 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2810 if (!smb_fname
->base_name
) {
2811 status
= NT_STATUS_NO_MEMORY
;
2815 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2818 status
= check_name(conn
, smb_fname
->base_name
);
2819 if (!NT_STATUS_IS_OK(status
)) {
2823 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2824 if (!NT_STATUS_IS_OK(status
)) {
2830 struct smb_Dir
*dir_hnd
= NULL
;
2832 const char *dname
= NULL
;
2833 char *talloced
= NULL
;
2835 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2836 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2840 if (strequal(fname_mask
,"????????.???")) {
2841 TALLOC_FREE(fname_mask
);
2842 fname_mask
= talloc_strdup(ctx
, "*");
2844 status
= NT_STATUS_NO_MEMORY
;
2849 status
= check_name(conn
, fname_dir
);
2850 if (!NT_STATUS_IS_OK(status
)) {
2854 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2856 if (dir_hnd
== NULL
) {
2857 status
= map_nt_error_from_unix(errno
);
2861 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2862 the pattern matches against the long name, otherwise the short name
2863 We don't implement this yet XXXX
2866 status
= NT_STATUS_NO_SUCH_FILE
;
2868 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2869 &smb_fname
->st
, &talloced
))) {
2870 TALLOC_CTX
*frame
= talloc_stackframe();
2872 if (!is_visible_file(conn
, fname_dir
, dname
,
2873 &smb_fname
->st
, true)) {
2875 TALLOC_FREE(talloced
);
2879 /* Quick check for "." and ".." */
2880 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2882 TALLOC_FREE(talloced
);
2886 if(!mask_match(dname
, fname_mask
,
2887 conn
->case_sensitive
)) {
2889 TALLOC_FREE(talloced
);
2893 TALLOC_FREE(smb_fname
->base_name
);
2894 if (ISDOT(fname_dir
)) {
2895 /* Ensure we use canonical names on open. */
2896 smb_fname
->base_name
=
2897 talloc_asprintf(smb_fname
, "%s",
2900 smb_fname
->base_name
=
2901 talloc_asprintf(smb_fname
, "%s/%s",
2905 if (!smb_fname
->base_name
) {
2906 TALLOC_FREE(dir_hnd
);
2907 status
= NT_STATUS_NO_MEMORY
;
2909 TALLOC_FREE(talloced
);
2913 status
= check_name(conn
, smb_fname
->base_name
);
2914 if (!NT_STATUS_IS_OK(status
)) {
2915 TALLOC_FREE(dir_hnd
);
2917 TALLOC_FREE(talloced
);
2921 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2922 if (!NT_STATUS_IS_OK(status
)) {
2924 TALLOC_FREE(talloced
);
2929 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2930 smb_fname
->base_name
));
2933 TALLOC_FREE(talloced
);
2935 TALLOC_FREE(dir_hnd
);
2938 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2939 status
= map_nt_error_from_unix(errno
);
2943 TALLOC_FREE(fname_dir
);
2944 TALLOC_FREE(fname_mask
);
2948 /****************************************************************************
2950 ****************************************************************************/
2952 void reply_unlink(struct smb_request
*req
)
2954 connection_struct
*conn
= req
->conn
;
2956 struct smb_filename
*smb_fname
= NULL
;
2959 bool path_contains_wcard
= False
;
2960 TALLOC_CTX
*ctx
= talloc_tos();
2962 START_PROFILE(SMBunlink
);
2965 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2969 dirtype
= SVAL(req
->vwv
+0, 0);
2971 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2972 STR_TERMINATE
, &status
,
2973 &path_contains_wcard
);
2974 if (!NT_STATUS_IS_OK(status
)) {
2975 reply_nterror(req
, status
);
2979 status
= filename_convert(ctx
, conn
,
2980 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2982 UCF_COND_ALLOW_WCARD_LCOMP
,
2983 &path_contains_wcard
,
2985 if (!NT_STATUS_IS_OK(status
)) {
2986 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2987 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2988 ERRSRV
, ERRbadpath
);
2991 reply_nterror(req
, status
);
2995 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2997 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2998 path_contains_wcard
);
2999 if (!NT_STATUS_IS_OK(status
)) {
3000 if (open_was_deferred(req
->sconn
, req
->mid
)) {
3001 /* We have re-scheduled this call. */
3004 reply_nterror(req
, status
);
3008 reply_outbuf(req
, 0, 0);
3010 TALLOC_FREE(smb_fname
);
3011 END_PROFILE(SMBunlink
);
3015 /****************************************************************************
3017 ****************************************************************************/
3019 static void fail_readraw(void)
3021 const char *errstr
= talloc_asprintf(talloc_tos(),
3022 "FAIL ! reply_readbraw: socket write fail (%s)",
3027 exit_server_cleanly(errstr
);
3030 /****************************************************************************
3031 Fake (read/write) sendfile. Returns -1 on read or write fail.
3032 ****************************************************************************/
3034 ssize_t
fake_sendfile(files_struct
*fsp
, off_t startpos
, size_t nread
)
3037 size_t tosend
= nread
;
3044 bufsize
= MIN(nread
, 65536);
3046 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3050 while (tosend
> 0) {
3054 if (tosend
> bufsize
) {
3059 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3065 /* If we had a short read, fill with zeros. */
3066 if (ret
< cur_read
) {
3067 memset(buf
+ ret
, '\0', cur_read
- ret
);
3070 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
3072 char addr
[INET6_ADDRSTRLEN
];
3074 * Try and give an error message saying what
3077 DEBUG(0, ("write_data failed for client %s. "
3079 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3086 startpos
+= cur_read
;
3090 return (ssize_t
)nread
;
3093 /****************************************************************************
3094 Deal with the case of sendfile reading less bytes from the file than
3095 requested. Fill with zeros (all we can do).
3096 ****************************************************************************/
3098 void sendfile_short_send(files_struct
*fsp
,
3103 #define SHORT_SEND_BUFSIZE 1024
3104 if (nread
< headersize
) {
3105 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3106 "header for file %s (%s). Terminating\n",
3107 fsp_str_dbg(fsp
), strerror(errno
)));
3108 exit_server_cleanly("sendfile_short_send failed");
3111 nread
-= headersize
;
3113 if (nread
< smb_maxcnt
) {
3114 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3116 exit_server_cleanly("sendfile_short_send: "
3120 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3121 "with zeros !\n", fsp_str_dbg(fsp
)));
3123 while (nread
< smb_maxcnt
) {
3125 * We asked for the real file size and told sendfile
3126 * to not go beyond the end of the file. But it can
3127 * happen that in between our fstat call and the
3128 * sendfile call the file was truncated. This is very
3129 * bad because we have already announced the larger
3130 * number of bytes to the client.
3132 * The best we can do now is to send 0-bytes, just as
3133 * a read from a hole in a sparse file would do.
3135 * This should happen rarely enough that I don't care
3136 * about efficiency here :-)
3140 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3141 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
3143 char addr
[INET6_ADDRSTRLEN
];
3145 * Try and give an error message saying what
3148 DEBUG(0, ("write_data failed for client %s. "
3151 fsp
->conn
->sconn
->sock
, addr
,
3154 exit_server_cleanly("sendfile_short_send: "
3155 "write_data failed");
3163 /****************************************************************************
3164 Return a readbraw error (4 bytes of zero).
3165 ****************************************************************************/
3167 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
3173 smbd_lock_socket(sconn
);
3174 if (write_data(sconn
->sock
,header
,4) != 4) {
3175 char addr
[INET6_ADDRSTRLEN
];
3177 * Try and give an error message saying what
3180 DEBUG(0, ("write_data failed for client %s. "
3182 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
3187 smbd_unlock_socket(sconn
);
3190 /****************************************************************************
3191 Use sendfile in readbraw.
3192 ****************************************************************************/
3194 static void send_file_readbraw(connection_struct
*conn
,
3195 struct smb_request
*req
,
3201 struct smbd_server_connection
*sconn
= req
->sconn
;
3202 char *outbuf
= NULL
;
3206 * We can only use sendfile on a non-chained packet
3207 * but we can use on a non-oplocked file. tridge proved this
3208 * on a train in Germany :-). JRA.
3209 * reply_readbraw has already checked the length.
3212 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3213 (fsp
->wcp
== NULL
) &&
3214 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3215 ssize_t sendfile_read
= -1;
3217 DATA_BLOB header_blob
;
3219 _smb_setlen(header
,nread
);
3220 header_blob
= data_blob_const(header
, 4);
3222 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3223 &header_blob
, startpos
,
3225 if (sendfile_read
== -1) {
3226 /* Returning ENOSYS means no data at all was sent.
3227 * Do this as a normal read. */
3228 if (errno
== ENOSYS
) {
3229 goto normal_readbraw
;
3233 * Special hack for broken Linux with no working sendfile. If we
3234 * return EINTR we sent the header but not the rest of the data.
3235 * Fake this up by doing read/write calls.
3237 if (errno
== EINTR
) {
3238 /* Ensure we don't do this again. */
3239 set_use_sendfile(SNUM(conn
), False
);
3240 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3242 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3243 DEBUG(0,("send_file_readbraw: "
3244 "fake_sendfile failed for "
3248 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3253 DEBUG(0,("send_file_readbraw: sendfile failed for "
3254 "file %s (%s). Terminating\n",
3255 fsp_str_dbg(fsp
), strerror(errno
)));
3256 exit_server_cleanly("send_file_readbraw sendfile failed");
3257 } else if (sendfile_read
== 0) {
3259 * Some sendfile implementations return 0 to indicate
3260 * that there was a short read, but nothing was
3261 * actually written to the socket. In this case,
3262 * fallback to the normal read path so the header gets
3263 * the correct byte count.
3265 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3266 "bytes falling back to the normal read: "
3267 "%s\n", fsp_str_dbg(fsp
)));
3268 goto normal_readbraw
;
3271 /* Deal with possible short send. */
3272 if (sendfile_read
!= 4+nread
) {
3273 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3280 outbuf
= talloc_array(NULL
, char, nread
+4);
3282 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3283 (unsigned)(nread
+4)));
3284 reply_readbraw_error(sconn
);
3289 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3290 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3299 _smb_setlen(outbuf
,ret
);
3300 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3301 char addr
[INET6_ADDRSTRLEN
];
3303 * Try and give an error message saying what
3306 DEBUG(0, ("write_data failed for client %s. "
3308 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3315 TALLOC_FREE(outbuf
);
3318 /****************************************************************************
3319 Reply to a readbraw (core+ protocol).
3320 ****************************************************************************/
3322 void reply_readbraw(struct smb_request
*req
)
3324 connection_struct
*conn
= req
->conn
;
3325 struct smbd_server_connection
*sconn
= req
->sconn
;
3326 ssize_t maxcount
,mincount
;
3330 struct lock_struct lock
;
3333 START_PROFILE(SMBreadbraw
);
3335 if (srv_is_signing_active(sconn
) || req
->encrypted
) {
3336 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3337 "raw reads/writes are disallowed.");
3341 reply_readbraw_error(sconn
);
3342 END_PROFILE(SMBreadbraw
);
3346 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3347 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3348 "'async smb echo handler = yes'\n"));
3349 reply_readbraw_error(sconn
);
3350 END_PROFILE(SMBreadbraw
);
3355 * Special check if an oplock break has been issued
3356 * and the readraw request croses on the wire, we must
3357 * return a zero length response here.
3360 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3363 * We have to do a check_fsp by hand here, as
3364 * we must always return 4 zero bytes on error,
3368 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3369 req
->vuid
!= fsp
->vuid
||
3370 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3372 * fsp could be NULL here so use the value from the packet. JRA.
3374 DEBUG(3,("reply_readbraw: fnum %d not valid "
3376 (int)SVAL(req
->vwv
+0, 0)));
3377 reply_readbraw_error(sconn
);
3378 END_PROFILE(SMBreadbraw
);
3382 /* Do a "by hand" version of CHECK_READ. */
3383 if (!(fsp
->can_read
||
3384 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3385 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3386 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3387 (int)SVAL(req
->vwv
+0, 0)));
3388 reply_readbraw_error(sconn
);
3389 END_PROFILE(SMBreadbraw
);
3393 flush_write_cache(fsp
, READRAW_FLUSH
);
3395 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3396 if(req
->wct
== 10) {
3398 * This is a large offset (64 bit) read.
3401 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3404 DEBUG(0,("reply_readbraw: negative 64 bit "
3405 "readraw offset (%.0f) !\n",
3406 (double)startpos
));
3407 reply_readbraw_error(sconn
);
3408 END_PROFILE(SMBreadbraw
);
3413 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3414 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3416 /* ensure we don't overrun the packet size */
3417 maxcount
= MIN(65535,maxcount
);
3419 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3420 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3423 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3424 reply_readbraw_error(sconn
);
3425 END_PROFILE(SMBreadbraw
);
3429 if (fsp_stat(fsp
) == 0) {
3430 size
= fsp
->fsp_name
->st
.st_ex_size
;
3433 if (startpos
>= size
) {
3436 nread
= MIN(maxcount
,(size
- startpos
));
3439 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3440 if (nread
< mincount
)
3444 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3445 "min=%lu nread=%lu\n",
3446 fsp_fnum_dbg(fsp
), (double)startpos
,
3447 (unsigned long)maxcount
,
3448 (unsigned long)mincount
,
3449 (unsigned long)nread
) );
3451 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3453 DEBUG(5,("reply_readbraw finished\n"));
3455 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3457 END_PROFILE(SMBreadbraw
);
3462 #define DBGC_CLASS DBGC_LOCKING
3464 /****************************************************************************
3465 Reply to a lockread (core+ protocol).
3466 ****************************************************************************/
3468 void reply_lockread(struct smb_request
*req
)
3470 connection_struct
*conn
= req
->conn
;
3477 struct byte_range_lock
*br_lck
= NULL
;
3479 struct smbd_server_connection
*sconn
= req
->sconn
;
3481 START_PROFILE(SMBlockread
);
3484 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3485 END_PROFILE(SMBlockread
);
3489 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3491 if (!check_fsp(conn
, req
, fsp
)) {
3492 END_PROFILE(SMBlockread
);
3496 if (!CHECK_READ(fsp
,req
)) {
3497 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3498 END_PROFILE(SMBlockread
);
3502 numtoread
= SVAL(req
->vwv
+1, 0);
3503 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3505 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3507 reply_outbuf(req
, 5, numtoread
+ 3);
3509 data
= smb_buf(req
->outbuf
) + 3;
3512 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3513 * protocol request that predates the read/write lock concept.
3514 * Thus instead of asking for a read lock here we need to ask
3515 * for a write lock. JRA.
3516 * Note that the requested lock size is unaffected by max_recv.
3519 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3521 (uint64_t)req
->smbpid
,
3522 (uint64_t)numtoread
,
3526 False
, /* Non-blocking lock. */
3530 TALLOC_FREE(br_lck
);
3532 if (NT_STATUS_V(status
)) {
3533 reply_nterror(req
, status
);
3534 END_PROFILE(SMBlockread
);
3539 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3542 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3543 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3544 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3545 (unsigned int)numtoread
,
3546 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3547 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3549 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3552 reply_nterror(req
, map_nt_error_from_unix(errno
));
3553 END_PROFILE(SMBlockread
);
3557 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3559 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3560 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3561 p
= smb_buf(req
->outbuf
);
3562 SCVAL(p
,0,0); /* pad byte. */
3565 DEBUG(3,("lockread %s num=%d nread=%d\n",
3566 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3568 END_PROFILE(SMBlockread
);
3573 #define DBGC_CLASS DBGC_ALL
3575 /****************************************************************************
3577 ****************************************************************************/
3579 void reply_read(struct smb_request
*req
)
3581 connection_struct
*conn
= req
->conn
;
3588 struct lock_struct lock
;
3589 struct smbd_server_connection
*sconn
= req
->sconn
;
3591 START_PROFILE(SMBread
);
3594 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3595 END_PROFILE(SMBread
);
3599 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3601 if (!check_fsp(conn
, req
, fsp
)) {
3602 END_PROFILE(SMBread
);
3606 if (!CHECK_READ(fsp
,req
)) {
3607 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3608 END_PROFILE(SMBread
);
3612 numtoread
= SVAL(req
->vwv
+1, 0);
3613 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3615 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3618 * The requested read size cannot be greater than max_recv. JRA.
3620 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3621 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3622 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3623 (unsigned int)numtoread
,
3624 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3625 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3628 reply_outbuf(req
, 5, numtoread
+3);
3630 data
= smb_buf(req
->outbuf
) + 3;
3632 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3633 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3636 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3637 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3638 END_PROFILE(SMBread
);
3643 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3646 reply_nterror(req
, map_nt_error_from_unix(errno
));
3650 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3652 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3653 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3654 SCVAL(smb_buf(req
->outbuf
),0,1);
3655 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3657 DEBUG(3, ("read %s num=%d nread=%d\n",
3658 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3661 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3663 END_PROFILE(SMBread
);
3667 /****************************************************************************
3669 ****************************************************************************/
3671 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3676 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3678 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3680 SCVAL(outbuf
,smb_vwv0
,0xFF);
3681 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3682 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3683 SSVAL(outbuf
,smb_vwv6
,
3684 (smb_wct
- 4) /* offset from smb header to wct */
3685 + 1 /* the wct field */
3686 + 12 * sizeof(uint16_t) /* vwv */
3687 + 2); /* the buflen field */
3688 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3689 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3690 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3691 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3695 /****************************************************************************
3696 Reply to a read and X - possibly using sendfile.
3697 ****************************************************************************/
3699 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3700 files_struct
*fsp
, off_t startpos
,
3704 struct lock_struct lock
;
3705 int saved_errno
= 0;
3707 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3708 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3711 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3712 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3717 * We can only use sendfile on a non-chained packet
3718 * but we can use on a non-oplocked file. tridge proved this
3719 * on a train in Germany :-). JRA.
3722 if (!req_is_in_chain(req
) &&
3724 (fsp
->base_fsp
== NULL
) &&
3725 (fsp
->wcp
== NULL
) &&
3726 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3727 uint8 headerbuf
[smb_size
+ 12 * 2];
3730 if(fsp_stat(fsp
) == -1) {
3731 reply_nterror(req
, map_nt_error_from_unix(errno
));
3735 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3736 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3737 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3739 * We already know that we would do a short read, so don't
3740 * try the sendfile() path.
3742 goto nosendfile_read
;
3746 * Set up the packet header before send. We
3747 * assume here the sendfile will work (get the
3748 * correct amount of data).
3751 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3753 construct_reply_common_req(req
, (char *)headerbuf
);
3754 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3756 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3757 startpos
, smb_maxcnt
);
3759 /* Returning ENOSYS means no data at all was sent.
3760 Do this as a normal read. */
3761 if (errno
== ENOSYS
) {
3766 * Special hack for broken Linux with no working sendfile. If we
3767 * return EINTR we sent the header but not the rest of the data.
3768 * Fake this up by doing read/write calls.
3771 if (errno
== EINTR
) {
3772 /* Ensure we don't do this again. */
3773 set_use_sendfile(SNUM(conn
), False
);
3774 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3775 nread
= fake_sendfile(fsp
, startpos
,
3778 DEBUG(0,("send_file_readX: "
3779 "fake_sendfile failed for "
3783 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3785 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3786 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3787 /* No outbuf here means successful sendfile. */
3791 DEBUG(0,("send_file_readX: sendfile failed for file "
3792 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3794 exit_server_cleanly("send_file_readX sendfile failed");
3795 } else if (nread
== 0) {
3797 * Some sendfile implementations return 0 to indicate
3798 * that there was a short read, but nothing was
3799 * actually written to the socket. In this case,
3800 * fallback to the normal read path so the header gets
3801 * the correct byte count.
3803 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3804 "falling back to the normal read: %s\n",
3809 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3810 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3812 /* Deal with possible short send. */
3813 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3814 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3816 /* No outbuf here means successful sendfile. */
3817 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3818 SMB_PERFCOUNT_END(&req
->pcd
);
3824 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3825 uint8 headerbuf
[smb_size
+ 2*12];
3827 construct_reply_common_req(req
, (char *)headerbuf
);
3828 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3830 /* Send out the header. */
3831 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3832 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3834 char addr
[INET6_ADDRSTRLEN
];
3836 * Try and give an error message saying what
3839 DEBUG(0, ("write_data failed for client %s. "
3841 get_peer_addr(req
->sconn
->sock
, addr
,
3845 DEBUG(0,("send_file_readX: write_data failed for file "
3846 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3848 exit_server_cleanly("send_file_readX sendfile failed");
3850 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3852 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3853 "file %s (%s).\n", fsp_str_dbg(fsp
),
3855 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3862 reply_outbuf(req
, 12, smb_maxcnt
);
3863 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
3864 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
3866 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3867 saved_errno
= errno
;
3869 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3872 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3876 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3878 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3879 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3883 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3884 TALLOC_FREE(req
->outbuf
);
3888 /****************************************************************************
3889 Work out how much space we have for a read return.
3890 ****************************************************************************/
3892 static size_t calc_max_read_pdu(const struct smb_request
*req
)
3894 if (req
->sconn
->conn
->protocol
< PROTOCOL_NT1
) {
3895 return req
->sconn
->smb1
.sessions
.max_send
;
3898 if (!lp_large_readwrite()) {
3899 return req
->sconn
->smb1
.sessions
.max_send
;
3902 if (req_is_in_chain(req
)) {
3903 return req
->sconn
->smb1
.sessions
.max_send
;
3906 if (req
->encrypted
) {
3908 * Don't take encrypted traffic up to the
3909 * limit. There are padding considerations
3910 * that make that tricky.
3912 return req
->sconn
->smb1
.sessions
.max_send
;
3915 if (srv_is_signing_active(req
->sconn
)) {
3919 if (!lp_unix_extensions()) {
3924 * We can do ultra-large POSIX reads.
3929 /****************************************************************************
3930 Calculate how big a read can be. Copes with all clients. It's always
3931 safe to return a short read - Windows does this.
3932 ****************************************************************************/
3934 static size_t calc_read_size(const struct smb_request
*req
,
3938 size_t max_pdu
= calc_max_read_pdu(req
);
3939 size_t total_size
= 0;
3940 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
3941 size_t max_len
= max_pdu
- hdr_len
;
3944 * Windows explicitly ignores upper size of 0xFFFF.
3945 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3946 * We must do the same as these will never fit even in
3947 * an extended size NetBIOS packet.
3949 if (upper_size
== 0xFFFF) {
3953 if (req
->sconn
->conn
->protocol
< PROTOCOL_NT1
) {
3957 total_size
= ((upper_size
<<16) | lower_size
);
3960 * LARGE_READX test shows it's always safe to return
3961 * a short read. Windows does so.
3963 return MIN(total_size
, max_len
);
3966 /****************************************************************************
3967 Reply to a read and X.
3968 ****************************************************************************/
3970 void reply_read_and_X(struct smb_request
*req
)
3972 connection_struct
*conn
= req
->conn
;
3977 bool big_readX
= False
;
3979 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3982 START_PROFILE(SMBreadX
);
3984 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3985 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3989 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3990 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3991 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3993 /* If it's an IPC, pass off the pipe handler. */
3995 reply_pipe_read_and_X(req
);
3996 END_PROFILE(SMBreadX
);
4000 if (!check_fsp(conn
, req
, fsp
)) {
4001 END_PROFILE(SMBreadX
);
4005 if (!CHECK_READ(fsp
,req
)) {
4006 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4007 END_PROFILE(SMBreadX
);
4011 upper_size
= SVAL(req
->vwv
+7, 0);
4012 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4013 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4015 * This is a heuristic to avoid keeping large
4016 * outgoing buffers around over long-lived aio
4022 if (req
->wct
== 12) {
4024 * This is a large offset (64 bit) read.
4026 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4031 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4036 if (NT_STATUS_IS_OK(status
)) {
4037 /* Read scheduled - we're done. */
4040 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4041 /* Real error - report to client. */
4042 END_PROFILE(SMBreadX
);
4043 reply_nterror(req
, status
);
4046 /* NT_STATUS_RETRY - fall back to sync read. */
4049 smbd_lock_socket(req
->sconn
);
4050 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4051 smbd_unlock_socket(req
->sconn
);
4054 END_PROFILE(SMBreadX
);
4058 /****************************************************************************
4059 Error replies to writebraw must have smb_wct == 1. Fix this up.
4060 ****************************************************************************/
4062 void error_to_writebrawerr(struct smb_request
*req
)
4064 uint8
*old_outbuf
= req
->outbuf
;
4066 reply_outbuf(req
, 1, 0);
4068 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4069 TALLOC_FREE(old_outbuf
);
4072 /****************************************************************************
4073 Read 4 bytes of a smb packet and return the smb length of the packet.
4074 Store the result in the buffer. This version of the function will
4075 never return a session keepalive (length of zero).
4076 Timeout is in milliseconds.
4077 ****************************************************************************/
4079 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4082 uint8_t msgtype
= NBSSkeepalive
;
4084 while (msgtype
== NBSSkeepalive
) {
4087 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4089 if (!NT_STATUS_IS_OK(status
)) {
4090 char addr
[INET6_ADDRSTRLEN
];
4091 /* Try and give an error message
4092 * saying what client failed. */
4093 DEBUG(0, ("read_fd_with_timeout failed for "
4094 "client %s read error = %s.\n",
4095 get_peer_addr(fd
,addr
,sizeof(addr
)),
4096 nt_errstr(status
)));
4100 msgtype
= CVAL(inbuf
, 0);
4103 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4104 (unsigned long)len
));
4106 return NT_STATUS_OK
;
4109 /****************************************************************************
4110 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4111 ****************************************************************************/
4113 void reply_writebraw(struct smb_request
*req
)
4115 connection_struct
*conn
= req
->conn
;
4118 ssize_t total_written
=0;
4119 size_t numtowrite
=0;
4122 const char *data
=NULL
;
4125 struct lock_struct lock
;
4128 START_PROFILE(SMBwritebraw
);
4131 * If we ever reply with an error, it must have the SMB command
4132 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4135 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4137 if (srv_is_signing_active(req
->sconn
)) {
4138 END_PROFILE(SMBwritebraw
);
4139 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4140 "raw reads/writes are disallowed.");
4143 if (req
->wct
< 12) {
4144 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4145 error_to_writebrawerr(req
);
4146 END_PROFILE(SMBwritebraw
);
4150 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
4151 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4152 "'async smb echo handler = yes'\n"));
4153 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4154 error_to_writebrawerr(req
);
4155 END_PROFILE(SMBwritebraw
);
4159 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4160 if (!check_fsp(conn
, req
, fsp
)) {
4161 error_to_writebrawerr(req
);
4162 END_PROFILE(SMBwritebraw
);
4166 if (!CHECK_WRITE(fsp
)) {
4167 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4168 error_to_writebrawerr(req
);
4169 END_PROFILE(SMBwritebraw
);
4173 tcount
= IVAL(req
->vwv
+1, 0);
4174 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4175 write_through
= BITSETW(req
->vwv
+7,0);
4177 /* We have to deal with slightly different formats depending
4178 on whether we are using the core+ or lanman1.0 protocol */
4180 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4181 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4182 data
= smb_buf_const(req
->inbuf
);
4184 numtowrite
= SVAL(req
->vwv
+10, 0);
4185 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4188 /* Ensure we don't write bytes past the end of this packet. */
4189 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4190 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4191 error_to_writebrawerr(req
);
4192 END_PROFILE(SMBwritebraw
);
4196 if (!fsp
->print_file
) {
4197 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4198 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4201 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4202 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4203 error_to_writebrawerr(req
);
4204 END_PROFILE(SMBwritebraw
);
4210 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4213 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4214 "wrote=%d sync=%d\n",
4215 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4216 (int)nwritten
, (int)write_through
));
4218 if (nwritten
< (ssize_t
)numtowrite
) {
4219 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4220 error_to_writebrawerr(req
);
4224 total_written
= nwritten
;
4226 /* Allocate a buffer of 64k + length. */
4227 buf
= talloc_array(NULL
, char, 65540);
4229 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4230 error_to_writebrawerr(req
);
4234 /* Return a SMBwritebraw message to the redirector to tell
4235 * it to send more bytes */
4237 memcpy(buf
, req
->inbuf
, smb_size
);
4238 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4239 SCVAL(buf
,smb_com
,SMBwritebraw
);
4240 SSVALS(buf
,smb_vwv0
,0xFFFF);
4242 if (!srv_send_smb(req
->sconn
,
4244 false, 0, /* no signing */
4245 IS_CONN_ENCRYPTED(conn
),
4247 exit_server_cleanly("reply_writebraw: srv_send_smb "
4251 /* Now read the raw data into the buffer and write it */
4252 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4254 if (!NT_STATUS_IS_OK(status
)) {
4255 exit_server_cleanly("secondary writebraw failed");
4258 /* Set up outbuf to return the correct size */
4259 reply_outbuf(req
, 1, 0);
4261 if (numtowrite
!= 0) {
4263 if (numtowrite
> 0xFFFF) {
4264 DEBUG(0,("reply_writebraw: Oversize secondary write "
4265 "raw requested (%u). Terminating\n",
4266 (unsigned int)numtowrite
));
4267 exit_server_cleanly("secondary writebraw failed");
4270 if (tcount
> nwritten
+numtowrite
) {
4271 DEBUG(3,("reply_writebraw: Client overestimated the "
4273 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4276 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4278 if (!NT_STATUS_IS_OK(status
)) {
4279 char addr
[INET6_ADDRSTRLEN
];
4280 /* Try and give an error message
4281 * saying what client failed. */
4282 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4283 "raw read failed (%s) for client %s. "
4284 "Terminating\n", nt_errstr(status
),
4285 get_peer_addr(req
->sconn
->sock
, addr
,
4287 exit_server_cleanly("secondary writebraw failed");
4290 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4291 if (nwritten
== -1) {
4293 reply_nterror(req
, map_nt_error_from_unix(errno
));
4294 error_to_writebrawerr(req
);
4298 if (nwritten
< (ssize_t
)numtowrite
) {
4299 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4300 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4304 total_written
+= nwritten
;
4309 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4311 status
= sync_file(conn
, fsp
, write_through
);
4312 if (!NT_STATUS_IS_OK(status
)) {
4313 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4314 fsp_str_dbg(fsp
), nt_errstr(status
)));
4315 reply_nterror(req
, status
);
4316 error_to_writebrawerr(req
);
4320 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4322 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4323 (int)total_written
));
4325 if (!fsp
->print_file
) {
4326 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4329 /* We won't return a status if write through is not selected - this
4330 * follows what WfWg does */
4331 END_PROFILE(SMBwritebraw
);
4333 if (!write_through
&& total_written
==tcount
) {
4335 #if RABBIT_PELLET_FIX
4337 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4338 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4341 if (!send_keepalive(req
->sconn
->sock
)) {
4342 exit_server_cleanly("reply_writebraw: send of "
4343 "keepalive failed");
4346 TALLOC_FREE(req
->outbuf
);
4351 if (!fsp
->print_file
) {
4352 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4355 END_PROFILE(SMBwritebraw
);
4360 #define DBGC_CLASS DBGC_LOCKING
4362 /****************************************************************************
4363 Reply to a writeunlock (core+).
4364 ****************************************************************************/
4366 void reply_writeunlock(struct smb_request
*req
)
4368 connection_struct
*conn
= req
->conn
;
4369 ssize_t nwritten
= -1;
4373 NTSTATUS status
= NT_STATUS_OK
;
4375 struct lock_struct lock
;
4376 int saved_errno
= 0;
4378 START_PROFILE(SMBwriteunlock
);
4381 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4382 END_PROFILE(SMBwriteunlock
);
4386 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4388 if (!check_fsp(conn
, req
, fsp
)) {
4389 END_PROFILE(SMBwriteunlock
);
4393 if (!CHECK_WRITE(fsp
)) {
4394 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4395 END_PROFILE(SMBwriteunlock
);
4399 numtowrite
= SVAL(req
->vwv
+1, 0);
4400 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4401 data
= (const char *)req
->buf
+ 3;
4403 if (!fsp
->print_file
&& numtowrite
> 0) {
4404 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4405 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4408 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4409 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4410 END_PROFILE(SMBwriteunlock
);
4415 /* The special X/Open SMB protocol handling of
4416 zero length writes is *NOT* done for
4418 if(numtowrite
== 0) {
4421 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4422 saved_errno
= errno
;
4425 status
= sync_file(conn
, fsp
, False
/* write through */);
4426 if (!NT_STATUS_IS_OK(status
)) {
4427 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4428 fsp_str_dbg(fsp
), nt_errstr(status
)));
4429 reply_nterror(req
, status
);
4434 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4438 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4439 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4443 if (numtowrite
&& !fsp
->print_file
) {
4444 status
= do_unlock(req
->sconn
->msg_ctx
,
4446 (uint64_t)req
->smbpid
,
4447 (uint64_t)numtowrite
,
4451 if (NT_STATUS_V(status
)) {
4452 reply_nterror(req
, status
);
4457 reply_outbuf(req
, 1, 0);
4459 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4461 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4462 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4465 if (numtowrite
&& !fsp
->print_file
) {
4466 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4469 END_PROFILE(SMBwriteunlock
);
4474 #define DBGC_CLASS DBGC_ALL
4476 /****************************************************************************
4478 ****************************************************************************/
4480 void reply_write(struct smb_request
*req
)
4482 connection_struct
*conn
= req
->conn
;
4484 ssize_t nwritten
= -1;
4488 struct lock_struct lock
;
4490 int saved_errno
= 0;
4492 START_PROFILE(SMBwrite
);
4495 END_PROFILE(SMBwrite
);
4496 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4500 /* If it's an IPC, pass off the pipe handler. */
4502 reply_pipe_write(req
);
4503 END_PROFILE(SMBwrite
);
4507 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4509 if (!check_fsp(conn
, req
, fsp
)) {
4510 END_PROFILE(SMBwrite
);
4514 if (!CHECK_WRITE(fsp
)) {
4515 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4516 END_PROFILE(SMBwrite
);
4520 numtowrite
= SVAL(req
->vwv
+1, 0);
4521 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4522 data
= (const char *)req
->buf
+ 3;
4524 if (!fsp
->print_file
) {
4525 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4526 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4529 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4530 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4531 END_PROFILE(SMBwrite
);
4537 * X/Open SMB protocol says that if smb_vwv1 is
4538 * zero then the file size should be extended or
4539 * truncated to the size given in smb_vwv[2-3].
4542 if(numtowrite
== 0) {
4544 * This is actually an allocate call, and set EOF. JRA.
4546 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4548 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4551 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4553 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4556 trigger_write_time_update_immediate(fsp
);
4558 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4561 status
= sync_file(conn
, fsp
, False
);
4562 if (!NT_STATUS_IS_OK(status
)) {
4563 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4564 fsp_str_dbg(fsp
), nt_errstr(status
)));
4565 reply_nterror(req
, status
);
4570 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4574 if((nwritten
== 0) && (numtowrite
!= 0)) {
4575 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4579 reply_outbuf(req
, 1, 0);
4581 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4583 if (nwritten
< (ssize_t
)numtowrite
) {
4584 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4585 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4588 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4591 if (!fsp
->print_file
) {
4592 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4595 END_PROFILE(SMBwrite
);
4599 /****************************************************************************
4600 Ensure a buffer is a valid writeX for recvfile purposes.
4601 ****************************************************************************/
4603 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4604 (2*14) + /* word count (including bcc) */ \
4607 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4608 const uint8_t *inbuf
)
4611 connection_struct
*conn
= NULL
;
4612 unsigned int doff
= 0;
4613 size_t len
= smb_len_large(inbuf
);
4614 struct smbXsrv_tcon
*tcon
;
4618 if (is_encrypted_packet(sconn
, inbuf
)) {
4619 /* Can't do this on encrypted
4624 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4628 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4629 CVAL(inbuf
,smb_wct
) != 14) {
4630 DEBUG(10,("is_valid_writeX_buffer: chained or "
4631 "invalid word length.\n"));
4635 status
= smb1srv_tcon_lookup(sconn
->conn
, SVAL(inbuf
, smb_tid
),
4637 if (!NT_STATUS_IS_OK(status
)) {
4638 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4641 conn
= tcon
->compat
;
4644 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4647 if (IS_PRINT(conn
)) {
4648 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4651 doff
= SVAL(inbuf
,smb_vwv11
);
4653 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4655 if (len
> doff
&& len
- doff
> 0xFFFF) {
4656 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4659 if (numtowrite
== 0) {
4660 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4664 /* Ensure the sizes match up. */
4665 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4666 /* no pad byte...old smbclient :-( */
4667 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4669 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4673 if (len
- doff
!= numtowrite
) {
4674 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4675 "len = %u, doff = %u, numtowrite = %u\n",
4678 (unsigned int)numtowrite
));
4682 DEBUG(10,("is_valid_writeX_buffer: true "
4683 "len = %u, doff = %u, numtowrite = %u\n",
4686 (unsigned int)numtowrite
));
4691 /****************************************************************************
4692 Reply to a write and X.
4693 ****************************************************************************/
4695 void reply_write_and_X(struct smb_request
*req
)
4697 connection_struct
*conn
= req
->conn
;
4699 struct lock_struct lock
;
4704 unsigned int smb_doff
;
4705 unsigned int smblen
;
4708 int saved_errno
= 0;
4710 START_PROFILE(SMBwriteX
);
4712 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4713 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4717 numtowrite
= SVAL(req
->vwv
+10, 0);
4718 smb_doff
= SVAL(req
->vwv
+11, 0);
4719 smblen
= smb_len(req
->inbuf
);
4721 if (req
->unread_bytes
> 0xFFFF ||
4722 (smblen
> smb_doff
&&
4723 smblen
- smb_doff
> 0xFFFF)) {
4724 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4727 if (req
->unread_bytes
) {
4728 /* Can't do a recvfile write on IPC$ */
4730 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4733 if (numtowrite
!= req
->unread_bytes
) {
4734 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4738 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4739 smb_doff
+ numtowrite
> smblen
) {
4740 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4745 /* If it's an IPC, pass off the pipe handler. */
4747 if (req
->unread_bytes
) {
4748 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4751 reply_pipe_write_and_X(req
);
4755 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4756 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4757 write_through
= BITSETW(req
->vwv
+7,0);
4759 if (!check_fsp(conn
, req
, fsp
)) {
4763 if (!CHECK_WRITE(fsp
)) {
4764 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4768 data
= smb_base(req
->inbuf
) + smb_doff
;
4770 if(req
->wct
== 14) {
4772 * This is a large offset (64 bit) write.
4774 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
4778 /* X/Open SMB protocol says that, unlike SMBwrite
4779 if the length is zero then NO truncation is
4780 done, just a write of zero. To truncate a file,
4783 if(numtowrite
== 0) {
4786 if (req
->unread_bytes
== 0) {
4787 status
= schedule_aio_write_and_X(conn
,
4794 if (NT_STATUS_IS_OK(status
)) {
4795 /* write scheduled - we're done. */
4798 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4799 /* Real error - report to client. */
4800 reply_nterror(req
, status
);
4803 /* NT_STATUS_RETRY - fall through to sync write. */
4806 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4807 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4810 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4811 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4815 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4816 saved_errno
= errno
;
4818 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4822 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4826 if((nwritten
== 0) && (numtowrite
!= 0)) {
4827 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4831 reply_outbuf(req
, 6, 0);
4832 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4833 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4834 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4835 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4837 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4838 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4840 status
= sync_file(conn
, fsp
, write_through
);
4841 if (!NT_STATUS_IS_OK(status
)) {
4842 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4843 fsp_str_dbg(fsp
), nt_errstr(status
)));
4844 reply_nterror(req
, status
);
4848 END_PROFILE(SMBwriteX
);
4852 if (req
->unread_bytes
) {
4853 /* writeX failed. drain socket. */
4854 if (drain_socket(req
->sconn
->sock
, req
->unread_bytes
) !=
4855 req
->unread_bytes
) {
4856 smb_panic("failed to drain pending bytes");
4858 req
->unread_bytes
= 0;
4861 END_PROFILE(SMBwriteX
);
4865 /****************************************************************************
4867 ****************************************************************************/
4869 void reply_lseek(struct smb_request
*req
)
4871 connection_struct
*conn
= req
->conn
;
4877 START_PROFILE(SMBlseek
);
4880 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4881 END_PROFILE(SMBlseek
);
4885 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4887 if (!check_fsp(conn
, req
, fsp
)) {
4891 flush_write_cache(fsp
, SEEK_FLUSH
);
4893 mode
= SVAL(req
->vwv
+1, 0) & 3;
4894 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4895 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
4904 res
= fsp
->fh
->pos
+ startpos
;
4915 if (umode
== SEEK_END
) {
4916 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4917 if(errno
== EINVAL
) {
4918 off_t current_pos
= startpos
;
4920 if(fsp_stat(fsp
) == -1) {
4922 map_nt_error_from_unix(errno
));
4923 END_PROFILE(SMBlseek
);
4927 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4929 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4934 reply_nterror(req
, map_nt_error_from_unix(errno
));
4935 END_PROFILE(SMBlseek
);
4942 reply_outbuf(req
, 2, 0);
4943 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4945 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4946 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
4948 END_PROFILE(SMBlseek
);
4952 /****************************************************************************
4954 ****************************************************************************/
4956 void reply_flush(struct smb_request
*req
)
4958 connection_struct
*conn
= req
->conn
;
4962 START_PROFILE(SMBflush
);
4965 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4969 fnum
= SVAL(req
->vwv
+0, 0);
4970 fsp
= file_fsp(req
, fnum
);
4972 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4977 file_sync_all(conn
);
4979 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4980 if (!NT_STATUS_IS_OK(status
)) {
4981 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4982 fsp_str_dbg(fsp
), nt_errstr(status
)));
4983 reply_nterror(req
, status
);
4984 END_PROFILE(SMBflush
);
4989 reply_outbuf(req
, 0, 0);
4991 DEBUG(3,("flush\n"));
4992 END_PROFILE(SMBflush
);
4996 /****************************************************************************
4998 conn POINTER CAN BE NULL HERE !
4999 ****************************************************************************/
5001 void reply_exit(struct smb_request
*req
)
5003 START_PROFILE(SMBexit
);
5005 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5007 reply_outbuf(req
, 0, 0);
5009 DEBUG(3,("exit\n"));
5011 END_PROFILE(SMBexit
);
5015 struct reply_close_state
{
5017 struct smb_request
*smbreq
;
5020 static void do_smb1_close(struct tevent_req
*req
);
5022 void reply_close(struct smb_request
*req
)
5024 connection_struct
*conn
= req
->conn
;
5025 NTSTATUS status
= NT_STATUS_OK
;
5026 files_struct
*fsp
= NULL
;
5027 START_PROFILE(SMBclose
);
5030 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5031 END_PROFILE(SMBclose
);
5035 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5038 * We can only use check_fsp if we know it's not a directory.
5041 if (!check_fsp_open(conn
, req
, fsp
)) {
5042 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5043 END_PROFILE(SMBclose
);
5047 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5048 fsp
->is_directory
? "directory" : "file",
5049 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5050 conn
->num_files_open
));
5052 if (!fsp
->is_directory
) {
5056 * Take care of any time sent in the close.
5059 t
= srv_make_unix_date3(req
->vwv
+1);
5060 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5063 if (fsp
->num_aio_requests
!= 0) {
5065 struct reply_close_state
*state
;
5067 DEBUG(10, ("closing with aio %u requests pending\n",
5068 fsp
->num_aio_requests
));
5071 * We depend on the aio_extra destructor to take care of this
5072 * close request once fsp->num_aio_request drops to 0.
5075 fsp
->deferred_close
= tevent_wait_send(
5076 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5077 if (fsp
->deferred_close
== NULL
) {
5078 status
= NT_STATUS_NO_MEMORY
;
5082 state
= talloc(fsp
, struct reply_close_state
);
5083 if (state
== NULL
) {
5084 TALLOC_FREE(fsp
->deferred_close
);
5085 status
= NT_STATUS_NO_MEMORY
;
5089 state
->smbreq
= talloc_move(fsp
, &req
);
5090 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5092 END_PROFILE(SMBclose
);
5097 * close_file() returns the unix errno if an error was detected on
5098 * close - normally this is due to a disk full error. If not then it
5099 * was probably an I/O error.
5102 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5104 if (!NT_STATUS_IS_OK(status
)) {
5105 reply_nterror(req
, status
);
5106 END_PROFILE(SMBclose
);
5110 reply_outbuf(req
, 0, 0);
5111 END_PROFILE(SMBclose
);
5115 static void do_smb1_close(struct tevent_req
*req
)
5117 struct reply_close_state
*state
= tevent_req_callback_data(
5118 req
, struct reply_close_state
);
5119 struct smb_request
*smbreq
;
5123 ret
= tevent_wait_recv(req
);
5126 DEBUG(10, ("tevent_wait_recv returned %s\n",
5129 * Continue anyway, this should never happen
5134 * fsp->smb2_close_request right now is a talloc grandchild of
5135 * fsp. When we close_file(fsp), it would go with it. No chance to
5138 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5140 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5141 if (NT_STATUS_IS_OK(status
)) {
5142 reply_outbuf(smbreq
, 0, 0);
5144 reply_nterror(smbreq
, status
);
5146 if (!srv_send_smb(smbreq
->sconn
,
5147 (char *)smbreq
->outbuf
,
5150 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5152 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5155 TALLOC_FREE(smbreq
);
5158 /****************************************************************************
5159 Reply to a writeclose (Core+ protocol).
5160 ****************************************************************************/
5162 void reply_writeclose(struct smb_request
*req
)
5164 connection_struct
*conn
= req
->conn
;
5166 ssize_t nwritten
= -1;
5167 NTSTATUS close_status
= NT_STATUS_OK
;
5170 struct timespec mtime
;
5172 struct lock_struct lock
;
5174 START_PROFILE(SMBwriteclose
);
5177 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5178 END_PROFILE(SMBwriteclose
);
5182 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5184 if (!check_fsp(conn
, req
, fsp
)) {
5185 END_PROFILE(SMBwriteclose
);
5188 if (!CHECK_WRITE(fsp
)) {
5189 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5190 END_PROFILE(SMBwriteclose
);
5194 numtowrite
= SVAL(req
->vwv
+1, 0);
5195 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5196 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5197 data
= (const char *)req
->buf
+ 1;
5199 if (!fsp
->print_file
) {
5200 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5201 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5204 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5205 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5206 END_PROFILE(SMBwriteclose
);
5211 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5213 set_close_write_time(fsp
, mtime
);
5216 * More insanity. W2K only closes the file if writelen > 0.
5221 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5222 "file %s\n", fsp_str_dbg(fsp
)));
5223 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5226 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5227 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5228 conn
->num_files_open
));
5230 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5231 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5235 if(!NT_STATUS_IS_OK(close_status
)) {
5236 reply_nterror(req
, close_status
);
5240 reply_outbuf(req
, 1, 0);
5242 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5245 if (numtowrite
&& !fsp
->print_file
) {
5246 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5249 END_PROFILE(SMBwriteclose
);
5254 #define DBGC_CLASS DBGC_LOCKING
5256 /****************************************************************************
5258 ****************************************************************************/
5260 void reply_lock(struct smb_request
*req
)
5262 connection_struct
*conn
= req
->conn
;
5263 uint64_t count
,offset
;
5266 struct byte_range_lock
*br_lck
= NULL
;
5268 START_PROFILE(SMBlock
);
5271 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5272 END_PROFILE(SMBlock
);
5276 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5278 if (!check_fsp(conn
, req
, fsp
)) {
5279 END_PROFILE(SMBlock
);
5283 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5284 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5286 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5287 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5289 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5291 (uint64_t)req
->smbpid
,
5296 False
, /* Non-blocking lock. */
5301 TALLOC_FREE(br_lck
);
5303 if (NT_STATUS_V(status
)) {
5304 reply_nterror(req
, status
);
5305 END_PROFILE(SMBlock
);
5309 reply_outbuf(req
, 0, 0);
5311 END_PROFILE(SMBlock
);
5315 /****************************************************************************
5317 ****************************************************************************/
5319 void reply_unlock(struct smb_request
*req
)
5321 connection_struct
*conn
= req
->conn
;
5322 uint64_t count
,offset
;
5326 START_PROFILE(SMBunlock
);
5329 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5330 END_PROFILE(SMBunlock
);
5334 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5336 if (!check_fsp(conn
, req
, fsp
)) {
5337 END_PROFILE(SMBunlock
);
5341 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5342 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5344 status
= do_unlock(req
->sconn
->msg_ctx
,
5346 (uint64_t)req
->smbpid
,
5351 if (NT_STATUS_V(status
)) {
5352 reply_nterror(req
, status
);
5353 END_PROFILE(SMBunlock
);
5357 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5358 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5360 reply_outbuf(req
, 0, 0);
5362 END_PROFILE(SMBunlock
);
5367 #define DBGC_CLASS DBGC_ALL
5369 /****************************************************************************
5371 conn POINTER CAN BE NULL HERE !
5372 ****************************************************************************/
5374 void reply_tdis(struct smb_request
*req
)
5377 connection_struct
*conn
= req
->conn
;
5378 struct smbXsrv_tcon
*tcon
;
5380 START_PROFILE(SMBtdis
);
5383 DEBUG(4,("Invalid connection in tdis\n"));
5384 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5385 END_PROFILE(SMBtdis
);
5393 * TODO: cancel all outstanding requests on the tcon
5395 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5396 if (!NT_STATUS_IS_OK(status
)) {
5397 DEBUG(0, ("reply_tdis: "
5398 "smbXsrv_tcon_disconnect() failed: %s\n",
5399 nt_errstr(status
)));
5401 * If we hit this case, there is something completely
5402 * wrong, so we better disconnect the transport connection.
5404 END_PROFILE(SMBtdis
);
5405 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5411 reply_outbuf(req
, 0, 0);
5412 END_PROFILE(SMBtdis
);
5416 /****************************************************************************
5418 conn POINTER CAN BE NULL HERE !
5419 ****************************************************************************/
5421 void reply_echo(struct smb_request
*req
)
5423 connection_struct
*conn
= req
->conn
;
5424 struct smb_perfcount_data local_pcd
;
5425 struct smb_perfcount_data
*cur_pcd
;
5429 START_PROFILE(SMBecho
);
5431 smb_init_perfcount_data(&local_pcd
);
5434 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5435 END_PROFILE(SMBecho
);
5439 smb_reverb
= SVAL(req
->vwv
+0, 0);
5441 reply_outbuf(req
, 1, req
->buflen
);
5443 /* copy any incoming data back out */
5444 if (req
->buflen
> 0) {
5445 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5448 if (smb_reverb
> 100) {
5449 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5453 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5455 /* this makes sure we catch the request pcd */
5456 if (seq_num
== smb_reverb
) {
5457 cur_pcd
= &req
->pcd
;
5459 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5460 cur_pcd
= &local_pcd
;
5463 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5465 show_msg((char *)req
->outbuf
);
5466 if (!srv_send_smb(req
->sconn
,
5467 (char *)req
->outbuf
,
5468 true, req
->seqnum
+1,
5469 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5471 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5474 DEBUG(3,("echo %d times\n", smb_reverb
));
5476 TALLOC_FREE(req
->outbuf
);
5478 END_PROFILE(SMBecho
);
5482 /****************************************************************************
5483 Reply to a printopen.
5484 ****************************************************************************/
5486 void reply_printopen(struct smb_request
*req
)
5488 connection_struct
*conn
= req
->conn
;
5492 START_PROFILE(SMBsplopen
);
5495 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5496 END_PROFILE(SMBsplopen
);
5500 if (!CAN_PRINT(conn
)) {
5501 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5502 END_PROFILE(SMBsplopen
);
5506 status
= file_new(req
, conn
, &fsp
);
5507 if(!NT_STATUS_IS_OK(status
)) {
5508 reply_nterror(req
, status
);
5509 END_PROFILE(SMBsplopen
);
5513 /* Open for exclusive use, write only. */
5514 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5516 if (!NT_STATUS_IS_OK(status
)) {
5517 file_free(req
, fsp
);
5518 reply_nterror(req
, status
);
5519 END_PROFILE(SMBsplopen
);
5523 reply_outbuf(req
, 1, 0);
5524 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5526 DEBUG(3,("openprint fd=%d %s\n",
5527 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5529 END_PROFILE(SMBsplopen
);
5533 /****************************************************************************
5534 Reply to a printclose.
5535 ****************************************************************************/
5537 void reply_printclose(struct smb_request
*req
)
5539 connection_struct
*conn
= req
->conn
;
5543 START_PROFILE(SMBsplclose
);
5546 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5547 END_PROFILE(SMBsplclose
);
5551 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5553 if (!check_fsp(conn
, req
, fsp
)) {
5554 END_PROFILE(SMBsplclose
);
5558 if (!CAN_PRINT(conn
)) {
5559 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5560 END_PROFILE(SMBsplclose
);
5564 DEBUG(3,("printclose fd=%d %s\n",
5565 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5567 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5569 if(!NT_STATUS_IS_OK(status
)) {
5570 reply_nterror(req
, status
);
5571 END_PROFILE(SMBsplclose
);
5575 reply_outbuf(req
, 0, 0);
5577 END_PROFILE(SMBsplclose
);
5581 /****************************************************************************
5582 Reply to a printqueue.
5583 ****************************************************************************/
5585 void reply_printqueue(struct smb_request
*req
)
5587 connection_struct
*conn
= req
->conn
;
5591 START_PROFILE(SMBsplretq
);
5594 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5595 END_PROFILE(SMBsplretq
);
5599 max_count
= SVAL(req
->vwv
+0, 0);
5600 start_index
= SVAL(req
->vwv
+1, 0);
5602 /* we used to allow the client to get the cnum wrong, but that
5603 is really quite gross and only worked when there was only
5604 one printer - I think we should now only accept it if they
5605 get it right (tridge) */
5606 if (!CAN_PRINT(conn
)) {
5607 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5608 END_PROFILE(SMBsplretq
);
5612 reply_outbuf(req
, 2, 3);
5613 SSVAL(req
->outbuf
,smb_vwv0
,0);
5614 SSVAL(req
->outbuf
,smb_vwv1
,0);
5615 SCVAL(smb_buf(req
->outbuf
),0,1);
5616 SSVAL(smb_buf(req
->outbuf
),1,0);
5618 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5619 start_index
, max_count
));
5622 TALLOC_CTX
*mem_ctx
= talloc_tos();
5625 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5626 struct rpc_pipe_client
*cli
= NULL
;
5627 struct dcerpc_binding_handle
*b
= NULL
;
5628 struct policy_handle handle
;
5629 struct spoolss_DevmodeContainer devmode_ctr
;
5630 union spoolss_JobInfo
*info
;
5632 uint32_t num_to_get
;
5636 ZERO_STRUCT(handle
);
5638 status
= rpc_pipe_open_interface(conn
,
5641 conn
->sconn
->remote_address
,
5642 conn
->sconn
->msg_ctx
,
5644 if (!NT_STATUS_IS_OK(status
)) {
5645 DEBUG(0, ("reply_printqueue: "
5646 "could not connect to spoolss: %s\n",
5647 nt_errstr(status
)));
5648 reply_nterror(req
, status
);
5651 b
= cli
->binding_handle
;
5653 ZERO_STRUCT(devmode_ctr
);
5655 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5658 SEC_FLAG_MAXIMUM_ALLOWED
,
5661 if (!NT_STATUS_IS_OK(status
)) {
5662 reply_nterror(req
, status
);
5665 if (!W_ERROR_IS_OK(werr
)) {
5666 reply_nterror(req
, werror_to_ntstatus(werr
));
5670 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5678 if (!W_ERROR_IS_OK(werr
)) {
5679 reply_nterror(req
, werror_to_ntstatus(werr
));
5683 if (max_count
> 0) {
5684 first
= start_index
;
5686 first
= start_index
+ max_count
+ 1;
5689 if (first
>= count
) {
5692 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5695 for (i
= first
; i
< num_to_get
; i
++) {
5698 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5700 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5701 info
[i
].info2
.job_id
);
5703 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5709 srv_put_dos_date2(p
, 0, qtime
);
5710 SCVAL(p
, 4, qstatus
);
5711 SSVAL(p
, 5, qrapjobid
);
5712 SIVAL(p
, 7, info
[i
].info2
.size
);
5714 srvstr_push(blob
, req
->flags2
, p
+12,
5715 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5717 if (message_push_blob(
5720 blob
, sizeof(blob
))) == -1) {
5721 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5727 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5728 SSVAL(req
->outbuf
,smb_vwv1
,
5729 (max_count
>0?first
+count
:first
-1));
5730 SCVAL(smb_buf(req
->outbuf
),0,1);
5731 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5735 DEBUG(3, ("%u entries returned in queue\n",
5739 if (b
&& is_valid_policy_hnd(&handle
)) {
5740 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5745 END_PROFILE(SMBsplretq
);
5749 /****************************************************************************
5750 Reply to a printwrite.
5751 ****************************************************************************/
5753 void reply_printwrite(struct smb_request
*req
)
5755 connection_struct
*conn
= req
->conn
;
5760 START_PROFILE(SMBsplwr
);
5763 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5764 END_PROFILE(SMBsplwr
);
5768 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5770 if (!check_fsp(conn
, req
, fsp
)) {
5771 END_PROFILE(SMBsplwr
);
5775 if (!fsp
->print_file
) {
5776 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5777 END_PROFILE(SMBsplwr
);
5781 if (!CHECK_WRITE(fsp
)) {
5782 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5783 END_PROFILE(SMBsplwr
);
5787 numtowrite
= SVAL(req
->buf
, 1);
5789 if (req
->buflen
< numtowrite
+ 3) {
5790 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5791 END_PROFILE(SMBsplwr
);
5795 data
= (const char *)req
->buf
+ 3;
5797 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
5798 reply_nterror(req
, map_nt_error_from_unix(errno
));
5799 END_PROFILE(SMBsplwr
);
5803 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
5805 END_PROFILE(SMBsplwr
);
5809 /****************************************************************************
5811 ****************************************************************************/
5813 void reply_mkdir(struct smb_request
*req
)
5815 connection_struct
*conn
= req
->conn
;
5816 struct smb_filename
*smb_dname
= NULL
;
5817 char *directory
= NULL
;
5819 TALLOC_CTX
*ctx
= talloc_tos();
5821 START_PROFILE(SMBmkdir
);
5823 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5824 STR_TERMINATE
, &status
);
5825 if (!NT_STATUS_IS_OK(status
)) {
5826 reply_nterror(req
, status
);
5830 status
= filename_convert(ctx
, conn
,
5831 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5836 if (!NT_STATUS_IS_OK(status
)) {
5837 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5838 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5839 ERRSRV
, ERRbadpath
);
5842 reply_nterror(req
, status
);
5846 status
= create_directory(conn
, req
, smb_dname
);
5848 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5850 if (!NT_STATUS_IS_OK(status
)) {
5852 if (!use_nt_status()
5853 && NT_STATUS_EQUAL(status
,
5854 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5856 * Yes, in the DOS error code case we get a
5857 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5858 * samba4 torture test.
5860 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5863 reply_nterror(req
, status
);
5867 reply_outbuf(req
, 0, 0);
5869 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5871 TALLOC_FREE(smb_dname
);
5872 END_PROFILE(SMBmkdir
);
5876 /****************************************************************************
5878 ****************************************************************************/
5880 void reply_rmdir(struct smb_request
*req
)
5882 connection_struct
*conn
= req
->conn
;
5883 struct smb_filename
*smb_dname
= NULL
;
5884 char *directory
= NULL
;
5886 TALLOC_CTX
*ctx
= talloc_tos();
5887 files_struct
*fsp
= NULL
;
5889 struct smbd_server_connection
*sconn
= req
->sconn
;
5891 START_PROFILE(SMBrmdir
);
5893 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5894 STR_TERMINATE
, &status
);
5895 if (!NT_STATUS_IS_OK(status
)) {
5896 reply_nterror(req
, status
);
5900 status
= filename_convert(ctx
, conn
,
5901 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5906 if (!NT_STATUS_IS_OK(status
)) {
5907 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5908 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5909 ERRSRV
, ERRbadpath
);
5912 reply_nterror(req
, status
);
5916 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5917 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5921 status
= SMB_VFS_CREATE_FILE(
5924 0, /* root_dir_fid */
5925 smb_dname
, /* fname */
5926 DELETE_ACCESS
, /* access_mask */
5927 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5929 FILE_OPEN
, /* create_disposition*/
5930 FILE_DIRECTORY_FILE
, /* create_options */
5931 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5932 0, /* oplock_request */
5933 0, /* allocation_size */
5934 0, /* private_flags */
5940 if (!NT_STATUS_IS_OK(status
)) {
5941 if (open_was_deferred(req
->sconn
, req
->mid
)) {
5942 /* We have re-scheduled this call. */
5945 reply_nterror(req
, status
);
5949 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5950 if (!NT_STATUS_IS_OK(status
)) {
5951 close_file(req
, fsp
, ERROR_CLOSE
);
5952 reply_nterror(req
, status
);
5956 if (!set_delete_on_close(fsp
, true,
5957 conn
->session_info
->security_token
,
5958 conn
->session_info
->unix_token
)) {
5959 close_file(req
, fsp
, ERROR_CLOSE
);
5960 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5964 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5965 if (!NT_STATUS_IS_OK(status
)) {
5966 reply_nterror(req
, status
);
5968 reply_outbuf(req
, 0, 0);
5971 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5973 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5975 TALLOC_FREE(smb_dname
);
5976 END_PROFILE(SMBrmdir
);
5980 /*******************************************************************
5981 Resolve wildcards in a filename rename.
5982 ********************************************************************/
5984 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5989 char *name2_copy
= NULL
;
5994 char *p
,*p2
, *pname1
, *pname2
;
5996 name2_copy
= talloc_strdup(ctx
, name2
);
6001 pname1
= strrchr_m(name1
,'/');
6002 pname2
= strrchr_m(name2_copy
,'/');
6004 if (!pname1
|| !pname2
) {
6008 /* Truncate the copy of name2 at the last '/' */
6011 /* Now go past the '/' */
6015 root1
= talloc_strdup(ctx
, pname1
);
6016 root2
= talloc_strdup(ctx
, pname2
);
6018 if (!root1
|| !root2
) {
6022 p
= strrchr_m(root1
,'.');
6025 ext1
= talloc_strdup(ctx
, p
+1);
6027 ext1
= talloc_strdup(ctx
, "");
6029 p
= strrchr_m(root2
,'.');
6032 ext2
= talloc_strdup(ctx
, p
+1);
6034 ext2
= talloc_strdup(ctx
, "");
6037 if (!ext1
|| !ext2
) {
6045 /* Hmmm. Should this be mb-aware ? */
6048 } else if (*p2
== '*') {
6050 root2
= talloc_asprintf(ctx
, "%s%s",
6069 /* Hmmm. Should this be mb-aware ? */
6072 } else if (*p2
== '*') {
6074 ext2
= talloc_asprintf(ctx
, "%s%s",
6090 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6095 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6107 /****************************************************************************
6108 Ensure open files have their names updated. Updated to notify other smbd's
6110 ****************************************************************************/
6112 static void rename_open_files(connection_struct
*conn
,
6113 struct share_mode_lock
*lck
,
6114 uint32_t orig_name_hash
,
6115 const struct smb_filename
*smb_fname_dst
)
6118 bool did_rename
= False
;
6120 uint32_t new_name_hash
= 0;
6122 for(fsp
= file_find_di_first(conn
->sconn
, lck
->data
->id
); fsp
;
6123 fsp
= file_find_di_next(fsp
)) {
6124 /* fsp_name is a relative path under the fsp. To change this for other
6125 sharepaths we need to manipulate relative paths. */
6126 /* TODO - create the absolute path and manipulate the newname
6127 relative to the sharepath. */
6128 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6131 if (fsp
->name_hash
!= orig_name_hash
) {
6134 DEBUG(10, ("rename_open_files: renaming file %s "
6135 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6136 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6137 smb_fname_str_dbg(smb_fname_dst
)));
6139 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6140 if (NT_STATUS_IS_OK(status
)) {
6142 new_name_hash
= fsp
->name_hash
;
6147 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6148 "for %s\n", file_id_string_tos(&lck
->data
->id
),
6149 smb_fname_str_dbg(smb_fname_dst
)));
6152 /* Send messages to all smbd's (not ourself) that the name has changed. */
6153 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, conn
->connectpath
,
6154 orig_name_hash
, new_name_hash
,
6159 /****************************************************************************
6160 We need to check if the source path is a parent directory of the destination
6161 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6162 refuse the rename with a sharing violation. Under UNIX the above call can
6163 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6164 probably need to check that the client is a Windows one before disallowing
6165 this as a UNIX client (one with UNIX extensions) can know the source is a
6166 symlink and make this decision intelligently. Found by an excellent bug
6167 report from <AndyLiebman@aol.com>.
6168 ****************************************************************************/
6170 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6171 const struct smb_filename
*smb_fname_dst
)
6173 const char *psrc
= smb_fname_src
->base_name
;
6174 const char *pdst
= smb_fname_dst
->base_name
;
6177 if (psrc
[0] == '.' && psrc
[1] == '/') {
6180 if (pdst
[0] == '.' && pdst
[1] == '/') {
6183 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6186 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6190 * Do the notify calls from a rename
6193 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6194 const struct smb_filename
*smb_fname_src
,
6195 const struct smb_filename
*smb_fname_dst
)
6197 char *parent_dir_src
= NULL
;
6198 char *parent_dir_dst
= NULL
;
6201 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6202 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6204 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6205 &parent_dir_src
, NULL
) ||
6206 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6207 &parent_dir_dst
, NULL
)) {
6211 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6212 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6213 smb_fname_src
->base_name
);
6214 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6215 smb_fname_dst
->base_name
);
6218 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6219 smb_fname_src
->base_name
);
6220 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6221 smb_fname_dst
->base_name
);
6224 /* this is a strange one. w2k3 gives an additional event for
6225 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6226 files, but not directories */
6228 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6229 FILE_NOTIFY_CHANGE_ATTRIBUTES
6230 |FILE_NOTIFY_CHANGE_CREATION
,
6231 smb_fname_dst
->base_name
);
6234 TALLOC_FREE(parent_dir_src
);
6235 TALLOC_FREE(parent_dir_dst
);
6238 /****************************************************************************
6239 Returns an error if the parent directory for a filename is open in an
6241 ****************************************************************************/
6243 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6244 const struct smb_filename
*smb_fname_dst_in
)
6246 char *parent_dir
= NULL
;
6247 struct smb_filename smb_fname_parent
;
6249 files_struct
*fsp
= NULL
;
6252 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6253 &parent_dir
, NULL
)) {
6254 return NT_STATUS_NO_MEMORY
;
6256 ZERO_STRUCT(smb_fname_parent
);
6257 smb_fname_parent
.base_name
= parent_dir
;
6259 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6261 return map_nt_error_from_unix(errno
);
6265 * We're only checking on this smbd here, mostly good
6266 * enough.. and will pass tests.
6269 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6270 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6271 fsp
= file_find_di_next(fsp
)) {
6272 if (fsp
->access_mask
& DELETE_ACCESS
) {
6273 return NT_STATUS_SHARING_VIOLATION
;
6276 return NT_STATUS_OK
;
6279 /****************************************************************************
6280 Rename an open file - given an fsp.
6281 ****************************************************************************/
6283 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6285 const struct smb_filename
*smb_fname_dst_in
,
6287 bool replace_if_exists
)
6289 TALLOC_CTX
*ctx
= talloc_tos();
6290 struct smb_filename
*smb_fname_dst
= NULL
;
6291 NTSTATUS status
= NT_STATUS_OK
;
6292 struct share_mode_lock
*lck
= NULL
;
6293 bool dst_exists
, old_is_stream
, new_is_stream
;
6295 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6296 if (!NT_STATUS_IS_OK(status
)) {
6300 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6301 if (!NT_STATUS_IS_OK(status
)) {
6305 /* Make a copy of the dst smb_fname structs */
6307 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6308 if (smb_fname_dst
== NULL
) {
6309 status
= NT_STATUS_NO_MEMORY
;
6314 * Check for special case with case preserving and not
6315 * case sensitive. If the old last component differs from the original
6316 * last component only by case, then we should allow
6317 * the rename (user is trying to change the case of the
6320 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6321 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6322 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6324 char *fname_dst_lcomp_base_mod
= NULL
;
6325 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6328 * Get the last component of the destination name.
6330 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6332 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6334 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6336 if (!fname_dst_lcomp_base_mod
) {
6337 status
= NT_STATUS_NO_MEMORY
;
6342 * Create an smb_filename struct using the original last
6343 * component of the destination.
6345 smb_fname_orig_lcomp
= synthetic_smb_fname_split(
6346 ctx
, smb_fname_dst
->original_lcomp
, NULL
);
6347 if (smb_fname_orig_lcomp
== NULL
) {
6348 status
= NT_STATUS_NO_MEMORY
;
6349 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6353 /* If the base names only differ by case, use original. */
6354 if(!strcsequal(fname_dst_lcomp_base_mod
,
6355 smb_fname_orig_lcomp
->base_name
)) {
6358 * Replace the modified last component with the
6362 *last_slash
= '\0'; /* Truncate at the '/' */
6363 tmp
= talloc_asprintf(smb_fname_dst
,
6365 smb_fname_dst
->base_name
,
6366 smb_fname_orig_lcomp
->base_name
);
6368 tmp
= talloc_asprintf(smb_fname_dst
,
6370 smb_fname_orig_lcomp
->base_name
);
6373 status
= NT_STATUS_NO_MEMORY
;
6374 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6375 TALLOC_FREE(smb_fname_orig_lcomp
);
6378 TALLOC_FREE(smb_fname_dst
->base_name
);
6379 smb_fname_dst
->base_name
= tmp
;
6382 /* If the stream_names only differ by case, use original. */
6383 if(!strcsequal(smb_fname_dst
->stream_name
,
6384 smb_fname_orig_lcomp
->stream_name
)) {
6386 /* Use the original stream. */
6387 tmp
= talloc_strdup(smb_fname_dst
,
6388 smb_fname_orig_lcomp
->stream_name
);
6390 status
= NT_STATUS_NO_MEMORY
;
6391 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6392 TALLOC_FREE(smb_fname_orig_lcomp
);
6395 TALLOC_FREE(smb_fname_dst
->stream_name
);
6396 smb_fname_dst
->stream_name
= tmp
;
6398 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6399 TALLOC_FREE(smb_fname_orig_lcomp
);
6403 * If the src and dest names are identical - including case,
6404 * don't do the rename, just return success.
6407 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6408 strcsequal(fsp
->fsp_name
->stream_name
,
6409 smb_fname_dst
->stream_name
)) {
6410 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6411 "- returning success\n",
6412 smb_fname_str_dbg(smb_fname_dst
)));
6413 status
= NT_STATUS_OK
;
6417 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6418 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6420 /* Return the correct error code if both names aren't streams. */
6421 if (!old_is_stream
&& new_is_stream
) {
6422 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6426 if (old_is_stream
&& !new_is_stream
) {
6427 status
= NT_STATUS_INVALID_PARAMETER
;
6431 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6433 if(!replace_if_exists
&& dst_exists
) {
6434 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6435 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6436 smb_fname_str_dbg(smb_fname_dst
)));
6437 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6442 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6443 &smb_fname_dst
->st
);
6444 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6446 /* The file can be open when renaming a stream */
6447 if (dst_fsp
&& !new_is_stream
) {
6448 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6449 status
= NT_STATUS_ACCESS_DENIED
;
6454 /* Ensure we have a valid stat struct for the source. */
6455 status
= vfs_stat_fsp(fsp
);
6456 if (!NT_STATUS_IS_OK(status
)) {
6460 status
= can_rename(conn
, fsp
, attrs
);
6462 if (!NT_STATUS_IS_OK(status
)) {
6463 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6464 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6465 smb_fname_str_dbg(smb_fname_dst
)));
6466 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6467 status
= NT_STATUS_ACCESS_DENIED
;
6471 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6472 status
= NT_STATUS_ACCESS_DENIED
;
6475 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6478 * We have the file open ourselves, so not being able to get the
6479 * corresponding share mode lock is a fatal error.
6482 SMB_ASSERT(lck
!= NULL
);
6484 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6485 uint32 create_options
= fsp
->fh
->private_options
;
6487 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6488 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6489 smb_fname_str_dbg(smb_fname_dst
)));
6491 if (!fsp
->is_directory
&&
6492 !lp_posix_pathnames() &&
6493 (lp_map_archive(SNUM(conn
)) ||
6494 lp_store_dos_attributes(SNUM(conn
)))) {
6495 /* We must set the archive bit on the newly
6497 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6498 uint32_t old_dosmode
= dos_mode(conn
,
6500 file_set_dosmode(conn
,
6502 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6508 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6511 rename_open_files(conn
, lck
, fsp
->name_hash
, smb_fname_dst
);
6514 * A rename acts as a new file create w.r.t. allowing an initial delete
6515 * on close, probably because in Windows there is a new handle to the
6516 * new file. If initial delete on close was requested but not
6517 * originally set, we need to set it here. This is probably not 100% correct,
6518 * but will work for the CIFSFS client which in non-posix mode
6519 * depends on these semantics. JRA.
6522 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6523 status
= can_set_delete_on_close(fsp
, 0);
6525 if (NT_STATUS_IS_OK(status
)) {
6526 /* Note that here we set the *inital* delete on close flag,
6527 * not the regular one. The magic gets handled in close. */
6528 fsp
->initial_delete_on_close
= True
;
6532 status
= NT_STATUS_OK
;
6538 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6539 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6541 status
= map_nt_error_from_unix(errno
);
6544 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6545 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6546 smb_fname_str_dbg(smb_fname_dst
)));
6549 TALLOC_FREE(smb_fname_dst
);
6554 /****************************************************************************
6555 The guts of the rename command, split out so it may be called by the NT SMB
6557 ****************************************************************************/
6559 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6560 connection_struct
*conn
,
6561 struct smb_request
*req
,
6562 struct smb_filename
*smb_fname_src
,
6563 struct smb_filename
*smb_fname_dst
,
6565 bool replace_if_exists
,
6568 uint32_t access_mask
)
6570 char *fname_src_dir
= NULL
;
6571 char *fname_src_mask
= NULL
;
6573 NTSTATUS status
= NT_STATUS_OK
;
6574 struct smb_Dir
*dir_hnd
= NULL
;
6575 const char *dname
= NULL
;
6576 char *talloced
= NULL
;
6578 int create_options
= 0;
6579 bool posix_pathnames
= lp_posix_pathnames();
6583 * Split the old name into directory and last component
6584 * strings. Note that unix_convert may have stripped off a
6585 * leading ./ from both name and newname if the rename is
6586 * at the root of the share. We need to make sure either both
6587 * name and newname contain a / character or neither of them do
6588 * as this is checked in resolve_wildcards().
6591 /* Split up the directory from the filename/mask. */
6592 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6593 &fname_src_dir
, &fname_src_mask
);
6594 if (!NT_STATUS_IS_OK(status
)) {
6595 status
= NT_STATUS_NO_MEMORY
;
6600 * We should only check the mangled cache
6601 * here if unix_convert failed. This means
6602 * that the path in 'mask' doesn't exist
6603 * on the file system and so we need to look
6604 * for a possible mangle. This patch from
6605 * Tine Smukavec <valentin.smukavec@hermes.si>.
6608 if (!VALID_STAT(smb_fname_src
->st
) &&
6609 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6610 char *new_mask
= NULL
;
6611 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6614 TALLOC_FREE(fname_src_mask
);
6615 fname_src_mask
= new_mask
;
6619 if (!src_has_wild
) {
6623 * Only one file needs to be renamed. Append the mask back
6624 * onto the directory.
6626 TALLOC_FREE(smb_fname_src
->base_name
);
6627 if (ISDOT(fname_src_dir
)) {
6628 /* Ensure we use canonical names on open. */
6629 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6633 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6638 if (!smb_fname_src
->base_name
) {
6639 status
= NT_STATUS_NO_MEMORY
;
6643 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6644 "case_preserve = %d, short case preserve = %d, "
6645 "directory = %s, newname = %s, "
6646 "last_component_dest = %s\n",
6647 conn
->case_sensitive
, conn
->case_preserve
,
6648 conn
->short_case_preserve
,
6649 smb_fname_str_dbg(smb_fname_src
),
6650 smb_fname_str_dbg(smb_fname_dst
),
6651 smb_fname_dst
->original_lcomp
));
6653 /* The dest name still may have wildcards. */
6654 if (dest_has_wild
) {
6655 char *fname_dst_mod
= NULL
;
6656 if (!resolve_wildcards(smb_fname_dst
,
6657 smb_fname_src
->base_name
,
6658 smb_fname_dst
->base_name
,
6660 DEBUG(6, ("rename_internals: resolve_wildcards "
6662 smb_fname_src
->base_name
,
6663 smb_fname_dst
->base_name
));
6664 status
= NT_STATUS_NO_MEMORY
;
6667 TALLOC_FREE(smb_fname_dst
->base_name
);
6668 smb_fname_dst
->base_name
= fname_dst_mod
;
6671 ZERO_STRUCT(smb_fname_src
->st
);
6672 if (posix_pathnames
) {
6673 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
6675 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
6678 status
= map_nt_error_from_unix_common(errno
);
6682 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6683 create_options
|= FILE_DIRECTORY_FILE
;
6686 status
= SMB_VFS_CREATE_FILE(
6689 0, /* root_dir_fid */
6690 smb_fname_src
, /* fname */
6691 access_mask
, /* access_mask */
6692 (FILE_SHARE_READ
| /* share_access */
6694 FILE_OPEN
, /* create_disposition*/
6695 create_options
, /* create_options */
6696 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6697 0, /* oplock_request */
6698 0, /* allocation_size */
6699 0, /* private_flags */
6705 if (!NT_STATUS_IS_OK(status
)) {
6706 DEBUG(3, ("Could not open rename source %s: %s\n",
6707 smb_fname_str_dbg(smb_fname_src
),
6708 nt_errstr(status
)));
6712 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6713 attrs
, replace_if_exists
);
6715 close_file(req
, fsp
, NORMAL_CLOSE
);
6717 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6718 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6719 smb_fname_str_dbg(smb_fname_dst
)));
6725 * Wildcards - process each file that matches.
6727 if (strequal(fname_src_mask
, "????????.???")) {
6728 TALLOC_FREE(fname_src_mask
);
6729 fname_src_mask
= talloc_strdup(ctx
, "*");
6730 if (!fname_src_mask
) {
6731 status
= NT_STATUS_NO_MEMORY
;
6736 status
= check_name(conn
, fname_src_dir
);
6737 if (!NT_STATUS_IS_OK(status
)) {
6741 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6743 if (dir_hnd
== NULL
) {
6744 status
= map_nt_error_from_unix(errno
);
6748 status
= NT_STATUS_NO_SUCH_FILE
;
6750 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6751 * - gentest fix. JRA
6754 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6756 files_struct
*fsp
= NULL
;
6757 char *destname
= NULL
;
6758 bool sysdir_entry
= False
;
6760 /* Quick check for "." and ".." */
6761 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6762 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6763 sysdir_entry
= True
;
6765 TALLOC_FREE(talloced
);
6770 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6771 &smb_fname_src
->st
, false)) {
6772 TALLOC_FREE(talloced
);
6776 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6777 TALLOC_FREE(talloced
);
6782 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6786 TALLOC_FREE(smb_fname_src
->base_name
);
6787 if (ISDOT(fname_src_dir
)) {
6788 /* Ensure we use canonical names on open. */
6789 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6793 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6798 if (!smb_fname_src
->base_name
) {
6799 status
= NT_STATUS_NO_MEMORY
;
6803 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6804 smb_fname_dst
->base_name
,
6806 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6807 smb_fname_src
->base_name
, destname
));
6808 TALLOC_FREE(talloced
);
6812 status
= NT_STATUS_NO_MEMORY
;
6816 TALLOC_FREE(smb_fname_dst
->base_name
);
6817 smb_fname_dst
->base_name
= destname
;
6819 ZERO_STRUCT(smb_fname_src
->st
);
6820 if (posix_pathnames
) {
6821 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6823 SMB_VFS_STAT(conn
, smb_fname_src
);
6828 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6829 create_options
|= FILE_DIRECTORY_FILE
;
6832 status
= SMB_VFS_CREATE_FILE(
6835 0, /* root_dir_fid */
6836 smb_fname_src
, /* fname */
6837 access_mask
, /* access_mask */
6838 (FILE_SHARE_READ
| /* share_access */
6840 FILE_OPEN
, /* create_disposition*/
6841 create_options
, /* create_options */
6842 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6843 0, /* oplock_request */
6844 0, /* allocation_size */
6845 0, /* private_flags */
6851 if (!NT_STATUS_IS_OK(status
)) {
6852 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6853 "returned %s rename %s -> %s\n",
6855 smb_fname_str_dbg(smb_fname_src
),
6856 smb_fname_str_dbg(smb_fname_dst
)));
6860 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6862 if (!smb_fname_dst
->original_lcomp
) {
6863 status
= NT_STATUS_NO_MEMORY
;
6867 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6868 attrs
, replace_if_exists
);
6870 close_file(req
, fsp
, NORMAL_CLOSE
);
6872 if (!NT_STATUS_IS_OK(status
)) {
6873 DEBUG(3, ("rename_internals_fsp returned %s for "
6874 "rename %s -> %s\n", nt_errstr(status
),
6875 smb_fname_str_dbg(smb_fname_src
),
6876 smb_fname_str_dbg(smb_fname_dst
)));
6882 DEBUG(3,("rename_internals: doing rename on %s -> "
6883 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6884 smb_fname_str_dbg(smb_fname_src
)));
6885 TALLOC_FREE(talloced
);
6887 TALLOC_FREE(dir_hnd
);
6889 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6890 status
= map_nt_error_from_unix(errno
);
6894 TALLOC_FREE(talloced
);
6895 TALLOC_FREE(fname_src_dir
);
6896 TALLOC_FREE(fname_src_mask
);
6900 /****************************************************************************
6902 ****************************************************************************/
6904 void reply_mv(struct smb_request
*req
)
6906 connection_struct
*conn
= req
->conn
;
6908 char *newname
= NULL
;
6912 bool src_has_wcard
= False
;
6913 bool dest_has_wcard
= False
;
6914 TALLOC_CTX
*ctx
= talloc_tos();
6915 struct smb_filename
*smb_fname_src
= NULL
;
6916 struct smb_filename
*smb_fname_dst
= NULL
;
6917 uint32_t src_ucf_flags
= lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP
: UCF_COND_ALLOW_WCARD_LCOMP
;
6918 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
| (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP
);
6919 bool stream_rename
= false;
6921 START_PROFILE(SMBmv
);
6924 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6928 attrs
= SVAL(req
->vwv
+0, 0);
6930 p
= (const char *)req
->buf
+ 1;
6931 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6932 &status
, &src_has_wcard
);
6933 if (!NT_STATUS_IS_OK(status
)) {
6934 reply_nterror(req
, status
);
6938 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6939 &status
, &dest_has_wcard
);
6940 if (!NT_STATUS_IS_OK(status
)) {
6941 reply_nterror(req
, status
);
6945 if (!lp_posix_pathnames()) {
6946 /* The newname must begin with a ':' if the
6947 name contains a ':'. */
6948 if (strchr_m(name
, ':')) {
6949 if (newname
[0] != ':') {
6950 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6953 stream_rename
= true;
6957 status
= filename_convert(ctx
,
6959 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6965 if (!NT_STATUS_IS_OK(status
)) {
6966 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6967 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6968 ERRSRV
, ERRbadpath
);
6971 reply_nterror(req
, status
);
6975 status
= filename_convert(ctx
,
6977 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6983 if (!NT_STATUS_IS_OK(status
)) {
6984 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6985 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6986 ERRSRV
, ERRbadpath
);
6989 reply_nterror(req
, status
);
6993 if (stream_rename
) {
6994 /* smb_fname_dst->base_name must be the same as
6995 smb_fname_src->base_name. */
6996 TALLOC_FREE(smb_fname_dst
->base_name
);
6997 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6998 smb_fname_src
->base_name
);
6999 if (!smb_fname_dst
->base_name
) {
7000 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7005 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7006 smb_fname_str_dbg(smb_fname_dst
)));
7008 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7009 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7011 if (!NT_STATUS_IS_OK(status
)) {
7012 if (open_was_deferred(req
->sconn
, req
->mid
)) {
7013 /* We have re-scheduled this call. */
7016 reply_nterror(req
, status
);
7020 reply_outbuf(req
, 0, 0);
7022 TALLOC_FREE(smb_fname_src
);
7023 TALLOC_FREE(smb_fname_dst
);
7028 /*******************************************************************
7029 Copy a file as part of a reply_copy.
7030 ******************************************************************/
7033 * TODO: check error codes on all callers
7036 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7037 connection_struct
*conn
,
7038 struct smb_filename
*smb_fname_src
,
7039 struct smb_filename
*smb_fname_dst
,
7042 bool target_is_directory
)
7044 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7046 files_struct
*fsp1
,*fsp2
;
7048 uint32 new_create_disposition
;
7052 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7053 if (smb_fname_dst_tmp
== NULL
) {
7054 return NT_STATUS_NO_MEMORY
;
7058 * If the target is a directory, extract the last component from the
7059 * src filename and append it to the dst filename
7061 if (target_is_directory
) {
7064 /* dest/target can't be a stream if it's a directory. */
7065 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7067 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7071 p
= smb_fname_src
->base_name
;
7073 smb_fname_dst_tmp
->base_name
=
7074 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7076 if (!smb_fname_dst_tmp
->base_name
) {
7077 status
= NT_STATUS_NO_MEMORY
;
7082 status
= vfs_file_exist(conn
, smb_fname_src
);
7083 if (!NT_STATUS_IS_OK(status
)) {
7087 if (!target_is_directory
&& count
) {
7088 new_create_disposition
= FILE_OPEN
;
7090 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7093 &new_create_disposition
,
7096 status
= NT_STATUS_INVALID_PARAMETER
;
7101 /* Open the src file for reading. */
7102 status
= SMB_VFS_CREATE_FILE(
7105 0, /* root_dir_fid */
7106 smb_fname_src
, /* fname */
7107 FILE_GENERIC_READ
, /* access_mask */
7108 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7109 FILE_OPEN
, /* create_disposition*/
7110 0, /* create_options */
7111 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7112 INTERNAL_OPEN_ONLY
, /* oplock_request */
7113 0, /* allocation_size */
7114 0, /* private_flags */
7120 if (!NT_STATUS_IS_OK(status
)) {
7124 dosattrs
= dos_mode(conn
, smb_fname_src
);
7126 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7127 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7130 /* Open the dst file for writing. */
7131 status
= SMB_VFS_CREATE_FILE(
7134 0, /* root_dir_fid */
7135 smb_fname_dst
, /* fname */
7136 FILE_GENERIC_WRITE
, /* access_mask */
7137 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7138 new_create_disposition
, /* create_disposition*/
7139 0, /* create_options */
7140 dosattrs
, /* file_attributes */
7141 INTERNAL_OPEN_ONLY
, /* oplock_request */
7142 0, /* allocation_size */
7143 0, /* private_flags */
7149 if (!NT_STATUS_IS_OK(status
)) {
7150 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7154 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7155 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7157 DEBUG(0, ("error - vfs lseek returned error %s\n",
7159 status
= map_nt_error_from_unix(errno
);
7160 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7161 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7166 /* Do the actual copy. */
7167 if (smb_fname_src
->st
.st_ex_size
) {
7168 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7173 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7175 /* Ensure the modtime is set correctly on the destination file. */
7176 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7179 * As we are opening fsp1 read-only we only expect
7180 * an error on close on fsp2 if we are out of space.
7181 * Thus we don't look at the error return from the
7184 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7186 if (!NT_STATUS_IS_OK(status
)) {
7190 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7191 status
= NT_STATUS_DISK_FULL
;
7195 status
= NT_STATUS_OK
;
7198 TALLOC_FREE(smb_fname_dst_tmp
);
7202 /****************************************************************************
7203 Reply to a file copy.
7204 ****************************************************************************/
7206 void reply_copy(struct smb_request
*req
)
7208 connection_struct
*conn
= req
->conn
;
7209 struct smb_filename
*smb_fname_src
= NULL
;
7210 struct smb_filename
*smb_fname_dst
= NULL
;
7211 char *fname_src
= NULL
;
7212 char *fname_dst
= NULL
;
7213 char *fname_src_mask
= NULL
;
7214 char *fname_src_dir
= NULL
;
7217 int error
= ERRnoaccess
;
7221 bool target_is_directory
=False
;
7222 bool source_has_wild
= False
;
7223 bool dest_has_wild
= False
;
7225 TALLOC_CTX
*ctx
= talloc_tos();
7227 START_PROFILE(SMBcopy
);
7230 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7234 tid2
= SVAL(req
->vwv
+0, 0);
7235 ofun
= SVAL(req
->vwv
+1, 0);
7236 flags
= SVAL(req
->vwv
+2, 0);
7238 p
= (const char *)req
->buf
;
7239 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7240 &status
, &source_has_wild
);
7241 if (!NT_STATUS_IS_OK(status
)) {
7242 reply_nterror(req
, status
);
7245 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7246 &status
, &dest_has_wild
);
7247 if (!NT_STATUS_IS_OK(status
)) {
7248 reply_nterror(req
, status
);
7252 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7254 if (tid2
!= conn
->cnum
) {
7255 /* can't currently handle inter share copies XXXX */
7256 DEBUG(3,("Rejecting inter-share copy\n"));
7257 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7261 status
= filename_convert(ctx
, conn
,
7262 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7264 UCF_COND_ALLOW_WCARD_LCOMP
,
7267 if (!NT_STATUS_IS_OK(status
)) {
7268 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7269 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7270 ERRSRV
, ERRbadpath
);
7273 reply_nterror(req
, status
);
7277 status
= filename_convert(ctx
, conn
,
7278 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7280 UCF_COND_ALLOW_WCARD_LCOMP
,
7283 if (!NT_STATUS_IS_OK(status
)) {
7284 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7285 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7286 ERRSRV
, ERRbadpath
);
7289 reply_nterror(req
, status
);
7293 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7295 if ((flags
&1) && target_is_directory
) {
7296 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7300 if ((flags
&2) && !target_is_directory
) {
7301 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7305 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7306 /* wants a tree copy! XXXX */
7307 DEBUG(3,("Rejecting tree copy\n"));
7308 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7312 /* Split up the directory from the filename/mask. */
7313 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7314 &fname_src_dir
, &fname_src_mask
);
7315 if (!NT_STATUS_IS_OK(status
)) {
7316 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7321 * We should only check the mangled cache
7322 * here if unix_convert failed. This means
7323 * that the path in 'mask' doesn't exist
7324 * on the file system and so we need to look
7325 * for a possible mangle. This patch from
7326 * Tine Smukavec <valentin.smukavec@hermes.si>.
7328 if (!VALID_STAT(smb_fname_src
->st
) &&
7329 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7330 char *new_mask
= NULL
;
7331 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7332 &new_mask
, conn
->params
);
7334 /* Use demangled name if one was successfully found. */
7336 TALLOC_FREE(fname_src_mask
);
7337 fname_src_mask
= new_mask
;
7341 if (!source_has_wild
) {
7344 * Only one file needs to be copied. Append the mask back onto
7347 TALLOC_FREE(smb_fname_src
->base_name
);
7348 if (ISDOT(fname_src_dir
)) {
7349 /* Ensure we use canonical names on open. */
7350 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7354 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7359 if (!smb_fname_src
->base_name
) {
7360 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7364 if (dest_has_wild
) {
7365 char *fname_dst_mod
= NULL
;
7366 if (!resolve_wildcards(smb_fname_dst
,
7367 smb_fname_src
->base_name
,
7368 smb_fname_dst
->base_name
,
7370 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7373 TALLOC_FREE(smb_fname_dst
->base_name
);
7374 smb_fname_dst
->base_name
= fname_dst_mod
;
7377 status
= check_name(conn
, smb_fname_src
->base_name
);
7378 if (!NT_STATUS_IS_OK(status
)) {
7379 reply_nterror(req
, status
);
7383 status
= check_name(conn
, smb_fname_dst
->base_name
);
7384 if (!NT_STATUS_IS_OK(status
)) {
7385 reply_nterror(req
, status
);
7389 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7390 ofun
, count
, target_is_directory
);
7392 if(!NT_STATUS_IS_OK(status
)) {
7393 reply_nterror(req
, status
);
7399 struct smb_Dir
*dir_hnd
= NULL
;
7400 const char *dname
= NULL
;
7401 char *talloced
= NULL
;
7405 * There is a wildcard that requires us to actually read the
7406 * src dir and copy each file matching the mask to the dst.
7407 * Right now streams won't be copied, but this could
7408 * presumably be added with a nested loop for reach dir entry.
7410 SMB_ASSERT(!smb_fname_src
->stream_name
);
7411 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7413 smb_fname_src
->stream_name
= NULL
;
7414 smb_fname_dst
->stream_name
= NULL
;
7416 if (strequal(fname_src_mask
,"????????.???")) {
7417 TALLOC_FREE(fname_src_mask
);
7418 fname_src_mask
= talloc_strdup(ctx
, "*");
7419 if (!fname_src_mask
) {
7420 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7425 status
= check_name(conn
, fname_src_dir
);
7426 if (!NT_STATUS_IS_OK(status
)) {
7427 reply_nterror(req
, status
);
7431 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7432 if (dir_hnd
== NULL
) {
7433 status
= map_nt_error_from_unix(errno
);
7434 reply_nterror(req
, status
);
7440 /* Iterate over the src dir copying each entry to the dst. */
7441 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7442 &smb_fname_src
->st
, &talloced
))) {
7443 char *destname
= NULL
;
7445 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7446 TALLOC_FREE(talloced
);
7450 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7451 &smb_fname_src
->st
, false)) {
7452 TALLOC_FREE(talloced
);
7456 if(!mask_match(dname
, fname_src_mask
,
7457 conn
->case_sensitive
)) {
7458 TALLOC_FREE(talloced
);
7462 error
= ERRnoaccess
;
7464 /* Get the src smb_fname struct setup. */
7465 TALLOC_FREE(smb_fname_src
->base_name
);
7466 if (ISDOT(fname_src_dir
)) {
7467 /* Ensure we use canonical names on open. */
7468 smb_fname_src
->base_name
=
7469 talloc_asprintf(smb_fname_src
, "%s",
7472 smb_fname_src
->base_name
=
7473 talloc_asprintf(smb_fname_src
, "%s/%s",
7474 fname_src_dir
, dname
);
7477 if (!smb_fname_src
->base_name
) {
7478 TALLOC_FREE(dir_hnd
);
7479 TALLOC_FREE(talloced
);
7480 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7484 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7485 smb_fname_dst
->base_name
,
7487 TALLOC_FREE(talloced
);
7491 TALLOC_FREE(dir_hnd
);
7492 TALLOC_FREE(talloced
);
7493 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7497 TALLOC_FREE(smb_fname_dst
->base_name
);
7498 smb_fname_dst
->base_name
= destname
;
7500 status
= check_name(conn
, smb_fname_src
->base_name
);
7501 if (!NT_STATUS_IS_OK(status
)) {
7502 TALLOC_FREE(dir_hnd
);
7503 TALLOC_FREE(talloced
);
7504 reply_nterror(req
, status
);
7508 status
= check_name(conn
, smb_fname_dst
->base_name
);
7509 if (!NT_STATUS_IS_OK(status
)) {
7510 TALLOC_FREE(dir_hnd
);
7511 TALLOC_FREE(talloced
);
7512 reply_nterror(req
, status
);
7516 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7517 smb_fname_src
->base_name
,
7518 smb_fname_dst
->base_name
));
7520 status
= copy_file(ctx
, conn
, smb_fname_src
,
7521 smb_fname_dst
, ofun
, count
,
7522 target_is_directory
);
7523 if (NT_STATUS_IS_OK(status
)) {
7527 TALLOC_FREE(talloced
);
7529 TALLOC_FREE(dir_hnd
);
7533 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7537 reply_outbuf(req
, 1, 0);
7538 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7540 TALLOC_FREE(smb_fname_src
);
7541 TALLOC_FREE(smb_fname_dst
);
7542 TALLOC_FREE(fname_src
);
7543 TALLOC_FREE(fname_dst
);
7544 TALLOC_FREE(fname_src_mask
);
7545 TALLOC_FREE(fname_src_dir
);
7547 END_PROFILE(SMBcopy
);
7552 #define DBGC_CLASS DBGC_LOCKING
7554 /****************************************************************************
7555 Get a lock pid, dealing with large count requests.
7556 ****************************************************************************/
7558 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7559 bool large_file_format
)
7561 if(!large_file_format
)
7562 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7564 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7567 /****************************************************************************
7568 Get a lock count, dealing with large count requests.
7569 ****************************************************************************/
7571 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7572 bool large_file_format
)
7576 if(!large_file_format
) {
7577 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7580 #if defined(HAVE_LONGLONG)
7581 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7582 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7583 #else /* HAVE_LONGLONG */
7586 * NT4.x seems to be broken in that it sends large file (64 bit)
7587 * lockingX calls even if the CAP_LARGE_FILES was *not*
7588 * negotiated. For boxes without large unsigned ints truncate the
7589 * lock count by dropping the top 32 bits.
7592 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7593 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7594 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7595 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7596 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7599 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7600 #endif /* HAVE_LONGLONG */
7606 #if !defined(HAVE_LONGLONG)
7607 /****************************************************************************
7608 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7609 ****************************************************************************/
7611 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7615 uint32 highcopy
= high
;
7618 * Try and find out how many significant bits there are in high.
7621 for(i
= 0; highcopy
; i
++)
7625 * We use 31 bits not 32 here as POSIX
7626 * lock offsets may not be negative.
7629 mask
= (~0) << (31 - i
);
7632 return 0; /* Fail. */
7638 #endif /* !defined(HAVE_LONGLONG) */
7640 /****************************************************************************
7641 Get a lock offset, dealing with large offset requests.
7642 ****************************************************************************/
7644 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7645 bool large_file_format
, bool *err
)
7647 uint64_t offset
= 0;
7651 if(!large_file_format
) {
7652 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7655 #if defined(HAVE_LONGLONG)
7656 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7657 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7658 #else /* HAVE_LONGLONG */
7661 * NT4.x seems to be broken in that it sends large file (64 bit)
7662 * lockingX calls even if the CAP_LARGE_FILES was *not*
7663 * negotiated. For boxes without large unsigned ints mangle the
7664 * lock offset by mapping the top 32 bits onto the lower 32.
7667 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7668 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7669 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7672 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7674 return (uint64_t)-1;
7677 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7678 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7679 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7680 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7683 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7684 #endif /* HAVE_LONGLONG */
7690 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7694 uint16_t num_ulocks
,
7695 struct smbd_lock_element
*ulocks
,
7697 struct smbd_lock_element
*locks
,
7700 connection_struct
*conn
= req
->conn
;
7702 NTSTATUS status
= NT_STATUS_OK
;
7706 /* Data now points at the beginning of the list
7707 of smb_unlkrng structs */
7708 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7709 struct smbd_lock_element
*e
= &ulocks
[i
];
7711 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7712 "pid %u, file %s\n",
7715 (unsigned int)e
->smblctx
,
7718 if (e
->brltype
!= UNLOCK_LOCK
) {
7719 /* this can only happen with SMB2 */
7720 return NT_STATUS_INVALID_PARAMETER
;
7723 status
= do_unlock(req
->sconn
->msg_ctx
,
7730 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7731 nt_errstr(status
)));
7733 if (!NT_STATUS_IS_OK(status
)) {
7738 /* Setup the timeout in seconds. */
7740 if (!lp_blocking_locks(SNUM(conn
))) {
7744 /* Data now points at the beginning of the list
7745 of smb_lkrng structs */
7747 for(i
= 0; i
< (int)num_locks
; i
++) {
7748 struct smbd_lock_element
*e
= &locks
[i
];
7750 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7751 "%llu, file %s timeout = %d\n",
7754 (unsigned long long)e
->smblctx
,
7758 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7759 struct blocking_lock_record
*blr
= NULL
;
7761 if (num_locks
> 1) {
7763 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7764 * if the lock vector contains one entry. When given mutliple cancel
7765 * requests in a single PDU we expect the server to return an
7766 * error. Windows servers seem to accept the request but only
7767 * cancel the first lock.
7768 * JRA - Do what Windows does (tm) :-).
7772 /* MS-CIFS (2.2.4.32.1) behavior. */
7773 return NT_STATUS_DOS(ERRDOS
,
7774 ERRcancelviolation
);
7776 /* Windows behavior. */
7778 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7779 "cancel request\n"));
7785 if (lp_blocking_locks(SNUM(conn
))) {
7787 /* Schedule a message to ourselves to
7788 remove the blocking lock record and
7789 return the right error. */
7791 blr
= blocking_lock_cancel_smb1(fsp
,
7797 NT_STATUS_FILE_LOCK_CONFLICT
);
7799 return NT_STATUS_DOS(
7801 ERRcancelviolation
);
7804 /* Remove a matching pending lock. */
7805 status
= do_lock_cancel(fsp
,
7812 bool blocking_lock
= timeout
? true : false;
7813 bool defer_lock
= false;
7814 struct byte_range_lock
*br_lck
;
7815 uint64_t block_smblctx
;
7817 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7829 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7830 /* Windows internal resolution for blocking locks seems
7831 to be about 200ms... Don't wait for less than that. JRA. */
7832 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7833 timeout
= lp_lock_spin_time();
7838 /* If a lock sent with timeout of zero would fail, and
7839 * this lock has been requested multiple times,
7840 * according to brl_lock_failed() we convert this
7841 * request to a blocking lock with a timeout of between
7842 * 150 - 300 milliseconds.
7844 * If lp_lock_spin_time() has been set to 0, we skip
7845 * this blocking retry and fail immediately.
7847 * Replacement for do_lock_spin(). JRA. */
7849 if (!req
->sconn
->using_smb2
&&
7850 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7851 lp_lock_spin_time() && !blocking_lock
&&
7852 NT_STATUS_EQUAL((status
),
7853 NT_STATUS_FILE_LOCK_CONFLICT
))
7856 timeout
= lp_lock_spin_time();
7859 if (br_lck
&& defer_lock
) {
7861 * A blocking lock was requested. Package up
7862 * this smb into a queued request and push it
7863 * onto the blocking lock queue.
7865 if(push_blocking_lock_request(br_lck
,
7876 TALLOC_FREE(br_lck
);
7878 return NT_STATUS_OK
;
7882 TALLOC_FREE(br_lck
);
7885 if (!NT_STATUS_IS_OK(status
)) {
7890 /* If any of the above locks failed, then we must unlock
7891 all of the previous locks (X/Open spec). */
7893 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7895 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7896 i
= -1; /* we want to skip the for loop */
7900 * Ensure we don't do a remove on the lock that just failed,
7901 * as under POSIX rules, if we have a lock already there, we
7902 * will delete it (and we shouldn't) .....
7904 for(i
--; i
>= 0; i
--) {
7905 struct smbd_lock_element
*e
= &locks
[i
];
7907 do_unlock(req
->sconn
->msg_ctx
,
7917 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d num_ulocks=%d\n",
7918 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
, num_ulocks
));
7920 return NT_STATUS_OK
;
7923 /****************************************************************************
7924 Reply to a lockingX request.
7925 ****************************************************************************/
7927 void reply_lockingX(struct smb_request
*req
)
7929 connection_struct
*conn
= req
->conn
;
7931 unsigned char locktype
;
7932 unsigned char oplocklevel
;
7937 const uint8_t *data
;
7938 bool large_file_format
;
7940 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7941 struct smbd_lock_element
*ulocks
;
7942 struct smbd_lock_element
*locks
;
7945 START_PROFILE(SMBlockingX
);
7948 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7949 END_PROFILE(SMBlockingX
);
7953 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7954 locktype
= CVAL(req
->vwv
+3, 0);
7955 oplocklevel
= CVAL(req
->vwv
+3, 1);
7956 num_ulocks
= SVAL(req
->vwv
+6, 0);
7957 num_locks
= SVAL(req
->vwv
+7, 0);
7958 lock_timeout
= IVAL(req
->vwv
+4, 0);
7959 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7961 if (!check_fsp(conn
, req
, fsp
)) {
7962 END_PROFILE(SMBlockingX
);
7968 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7969 /* we don't support these - and CANCEL_LOCK makes w2k
7970 and XP reboot so I don't really want to be
7971 compatible! (tridge) */
7972 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7973 END_PROFILE(SMBlockingX
);
7977 /* Check if this is an oplock break on a file
7978 we have granted an oplock on.
7980 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7981 /* Client can insist on breaking to none. */
7982 bool break_to_none
= (oplocklevel
== 0);
7985 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7986 "for %s\n", (unsigned int)oplocklevel
,
7987 fsp_fnum_dbg(fsp
)));
7990 * Make sure we have granted an exclusive or batch oplock on
7994 if (fsp
->oplock_type
== 0) {
7996 /* The Samba4 nbench simulator doesn't understand
7997 the difference between break to level2 and break
7998 to none from level2 - it sends oplock break
7999 replies in both cases. Don't keep logging an error
8000 message here - just ignore it. JRA. */
8002 DEBUG(5,("reply_lockingX: Error : oplock break from "
8003 "client for %s (oplock=%d) and no "
8004 "oplock granted on this file (%s).\n",
8005 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8008 /* if this is a pure oplock break request then don't
8010 if (num_locks
== 0 && num_ulocks
== 0) {
8011 END_PROFILE(SMBlockingX
);
8014 END_PROFILE(SMBlockingX
);
8015 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8020 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8022 result
= remove_oplock(fsp
);
8024 result
= downgrade_oplock(fsp
);
8028 DEBUG(0, ("reply_lockingX: error in removing "
8029 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8030 /* Hmmm. Is this panic justified? */
8031 smb_panic("internal tdb error");
8034 /* if this is a pure oplock break request then don't send a
8036 if (num_locks
== 0 && num_ulocks
== 0) {
8037 /* Sanity check - ensure a pure oplock break is not a
8039 if(CVAL(req
->vwv
+0, 0) != 0xff)
8040 DEBUG(0,("reply_lockingX: Error : pure oplock "
8041 "break is a chained %d request !\n",
8042 (unsigned int)CVAL(req
->vwv
+0, 0)));
8043 END_PROFILE(SMBlockingX
);
8049 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8050 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8051 END_PROFILE(SMBlockingX
);
8055 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8056 if (ulocks
== NULL
) {
8057 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8058 END_PROFILE(SMBlockingX
);
8062 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8063 if (locks
== NULL
) {
8064 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8065 END_PROFILE(SMBlockingX
);
8069 /* Data now points at the beginning of the list
8070 of smb_unlkrng structs */
8071 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8072 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8073 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8074 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
8075 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8078 * There is no error code marked "stupid client bug".... :-).
8081 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8082 END_PROFILE(SMBlockingX
);
8087 /* Now do any requested locks */
8088 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8090 /* Data now points at the beginning of the list
8091 of smb_lkrng structs */
8093 for(i
= 0; i
< (int)num_locks
; i
++) {
8094 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8095 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8096 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
8098 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8099 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8100 locks
[i
].brltype
= PENDING_READ_LOCK
;
8102 locks
[i
].brltype
= READ_LOCK
;
8105 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8106 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8108 locks
[i
].brltype
= WRITE_LOCK
;
8113 * There is no error code marked "stupid client bug".... :-).
8116 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8117 END_PROFILE(SMBlockingX
);
8122 status
= smbd_do_locking(req
, fsp
,
8123 locktype
, lock_timeout
,
8127 if (!NT_STATUS_IS_OK(status
)) {
8128 END_PROFILE(SMBlockingX
);
8129 reply_nterror(req
, status
);
8133 END_PROFILE(SMBlockingX
);
8137 reply_outbuf(req
, 2, 0);
8138 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8139 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8141 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8142 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8144 END_PROFILE(SMBlockingX
);
8148 #define DBGC_CLASS DBGC_ALL
8150 /****************************************************************************
8151 Reply to a SMBreadbmpx (read block multiplex) request.
8152 Always reply with an error, if someone has a platform really needs this,
8153 please contact vl@samba.org
8154 ****************************************************************************/
8156 void reply_readbmpx(struct smb_request
*req
)
8158 START_PROFILE(SMBreadBmpx
);
8159 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8160 END_PROFILE(SMBreadBmpx
);
8164 /****************************************************************************
8165 Reply to a SMBreadbs (read block multiplex secondary) request.
8166 Always reply with an error, if someone has a platform really needs this,
8167 please contact vl@samba.org
8168 ****************************************************************************/
8170 void reply_readbs(struct smb_request
*req
)
8172 START_PROFILE(SMBreadBs
);
8173 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8174 END_PROFILE(SMBreadBs
);
8178 /****************************************************************************
8179 Reply to a SMBsetattrE.
8180 ****************************************************************************/
8182 void reply_setattrE(struct smb_request
*req
)
8184 connection_struct
*conn
= req
->conn
;
8185 struct smb_file_time ft
;
8189 START_PROFILE(SMBsetattrE
);
8193 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8197 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8199 if(!fsp
|| (fsp
->conn
!= conn
)) {
8200 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8205 * Convert the DOS times into unix times.
8208 ft
.atime
= convert_time_t_to_timespec(
8209 srv_make_unix_date2(req
->vwv
+3));
8210 ft
.mtime
= convert_time_t_to_timespec(
8211 srv_make_unix_date2(req
->vwv
+5));
8212 ft
.create_time
= convert_time_t_to_timespec(
8213 srv_make_unix_date2(req
->vwv
+1));
8215 reply_outbuf(req
, 0, 0);
8218 * Patch from Ray Frush <frush@engr.colostate.edu>
8219 * Sometimes times are sent as zero - ignore them.
8222 /* Ensure we have a valid stat struct for the source. */
8223 status
= vfs_stat_fsp(fsp
);
8224 if (!NT_STATUS_IS_OK(status
)) {
8225 reply_nterror(req
, status
);
8229 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8230 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8234 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8235 if (!NT_STATUS_IS_OK(status
)) {
8236 reply_nterror(req
, status
);
8240 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8243 (unsigned int)ft
.atime
.tv_sec
,
8244 (unsigned int)ft
.mtime
.tv_sec
,
8245 (unsigned int)ft
.create_time
.tv_sec
8248 END_PROFILE(SMBsetattrE
);
8253 /* Back from the dead for OS/2..... JRA. */
8255 /****************************************************************************
8256 Reply to a SMBwritebmpx (write block multiplex primary) request.
8257 Always reply with an error, if someone has a platform really needs this,
8258 please contact vl@samba.org
8259 ****************************************************************************/
8261 void reply_writebmpx(struct smb_request
*req
)
8263 START_PROFILE(SMBwriteBmpx
);
8264 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8265 END_PROFILE(SMBwriteBmpx
);
8269 /****************************************************************************
8270 Reply to a SMBwritebs (write block multiplex secondary) request.
8271 Always reply with an error, if someone has a platform really needs this,
8272 please contact vl@samba.org
8273 ****************************************************************************/
8275 void reply_writebs(struct smb_request
*req
)
8277 START_PROFILE(SMBwriteBs
);
8278 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8279 END_PROFILE(SMBwriteBs
);
8283 /****************************************************************************
8284 Reply to a SMBgetattrE.
8285 ****************************************************************************/
8287 void reply_getattrE(struct smb_request
*req
)
8289 connection_struct
*conn
= req
->conn
;
8292 struct timespec create_ts
;
8294 START_PROFILE(SMBgetattrE
);
8297 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8298 END_PROFILE(SMBgetattrE
);
8302 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8304 if(!fsp
|| (fsp
->conn
!= conn
)) {
8305 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8306 END_PROFILE(SMBgetattrE
);
8310 /* Do an fstat on this file */
8312 reply_nterror(req
, map_nt_error_from_unix(errno
));
8313 END_PROFILE(SMBgetattrE
);
8317 mode
= dos_mode(conn
, fsp
->fsp_name
);
8320 * Convert the times into dos times. Set create
8321 * date to be last modify date as UNIX doesn't save
8325 reply_outbuf(req
, 11, 0);
8327 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8328 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8329 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8330 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8331 /* Should we check pending modtime here ? JRA */
8332 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8333 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8335 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8336 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8337 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8339 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8340 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
8341 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8343 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8345 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8347 END_PROFILE(SMBgetattrE
);