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 "rpc_client/cli_spoolss.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_server/rpc_ncacn_np.h"
38 #include "libcli/security/security.h"
39 #include "libsmb/nmblib.h"
41 #include "smbprofile.h"
43 /****************************************************************************
44 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
45 path or anything including wildcards.
46 We're assuming here that '/' is not the second byte in any multibyte char
47 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
49 ****************************************************************************/
51 /* Custom version for processing POSIX paths. */
52 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
54 static NTSTATUS
check_path_syntax_internal(char *path
,
56 bool *p_last_component_contains_wcard
)
60 NTSTATUS ret
= NT_STATUS_OK
;
61 bool start_of_name_component
= True
;
62 bool stream_started
= false;
64 *p_last_component_contains_wcard
= False
;
71 return NT_STATUS_OBJECT_NAME_INVALID
;
74 return NT_STATUS_OBJECT_NAME_INVALID
;
76 if (strchr_m(&s
[1], ':')) {
77 return NT_STATUS_OBJECT_NAME_INVALID
;
83 if ((*s
== ':') && !posix_path
&& !stream_started
) {
84 if (*p_last_component_contains_wcard
) {
85 return NT_STATUS_OBJECT_NAME_INVALID
;
87 /* Stream names allow more characters than file names.
88 We're overloading posix_path here to allow a wider
89 range of characters. If stream_started is true this
90 is still a Windows path even if posix_path is true.
93 stream_started
= true;
94 start_of_name_component
= false;
98 return NT_STATUS_OBJECT_NAME_INVALID
;
102 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
104 * Safe to assume is not the second part of a mb char
105 * as this is handled below.
107 /* Eat multiple '/' or '\\' */
108 while (IS_PATH_SEP(*s
,posix_path
)) {
111 if ((d
!= path
) && (*s
!= '\0')) {
112 /* We only care about non-leading or trailing '/' or '\\' */
116 start_of_name_component
= True
;
118 *p_last_component_contains_wcard
= False
;
122 if (start_of_name_component
) {
123 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
124 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
127 * No mb char starts with '.' so we're safe checking the directory separator here.
130 /* If we just added a '/' - delete it */
131 if ((d
> path
) && (*(d
-1) == '/')) {
136 /* Are we at the start ? Can't go back further if so. */
138 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
141 /* Go back one level... */
142 /* We know this is safe as '/' cannot be part of a mb sequence. */
143 /* NOTE - if this assumption is invalid we are not in good shape... */
144 /* Decrement d first as d points to the *next* char to write into. */
145 for (d
--; d
> path
; d
--) {
149 s
+= 2; /* Else go past the .. */
150 /* We're still at the start of a name component, just the previous one. */
153 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
165 if (*s
<= 0x1f || *s
== '|') {
166 return NT_STATUS_OBJECT_NAME_INVALID
;
174 *p_last_component_contains_wcard
= True
;
183 /* Get the size of the next MB character. */
184 next_codepoint(s
,&siz
);
202 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
204 return NT_STATUS_INVALID_PARAMETER
;
207 start_of_name_component
= False
;
215 /****************************************************************************
216 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
217 No wildcards allowed.
218 ****************************************************************************/
220 NTSTATUS
check_path_syntax(char *path
)
223 return check_path_syntax_internal(path
, False
, &ignore
);
226 /****************************************************************************
227 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
228 Wildcards allowed - p_contains_wcard returns true if the last component contained
230 ****************************************************************************/
232 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
234 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
237 /****************************************************************************
238 Check the path for a POSIX client.
239 We're assuming here that '/' is not the second byte in any multibyte char
240 set (a safe assumption).
241 ****************************************************************************/
243 NTSTATUS
check_path_syntax_posix(char *path
)
246 return check_path_syntax_internal(path
, True
, &ignore
);
249 /****************************************************************************
250 Pull a string and check the path allowing a wilcard - provide for error return.
251 ****************************************************************************/
253 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
254 const char *base_ptr
,
261 bool *contains_wcard
)
267 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
271 *err
= NT_STATUS_INVALID_PARAMETER
;
275 *contains_wcard
= False
;
277 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
279 * For a DFS path the function parse_dfs_path()
280 * will do the path processing, just make a copy.
286 if (lp_posix_pathnames()) {
287 *err
= check_path_syntax_posix(*pp_dest
);
289 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
295 /****************************************************************************
296 Pull a string and check the path - provide for error return.
297 ****************************************************************************/
299 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
300 const char *base_ptr
,
309 return srvstr_get_path_wcard(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
310 src_len
, flags
, err
, &ignore
);
313 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
314 char **pp_dest
, const char *src
, int flags
,
315 NTSTATUS
*err
, bool *contains_wcard
)
317 return srvstr_get_path_wcard(mem_ctx
, (char *)req
->inbuf
, req
->flags2
,
318 pp_dest
, src
, smbreq_bufrem(req
, src
),
319 flags
, err
, contains_wcard
);
322 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
323 char **pp_dest
, const char *src
, int flags
,
327 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
328 flags
, err
, &ignore
);
331 /****************************************************************************
332 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
333 ****************************************************************************/
335 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
338 if ((fsp
== NULL
) || (conn
== NULL
)) {
339 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
342 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
343 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
349 /****************************************************************************
350 Check if we have a correct fsp pointing to a file.
351 ****************************************************************************/
353 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
356 if (!check_fsp_open(conn
, req
, fsp
)) {
359 if (fsp
->is_directory
) {
360 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
363 if (fsp
->fh
->fd
== -1) {
364 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
367 fsp
->num_smb_operations
++;
371 /****************************************************************************
372 Check if we have a correct fsp pointing to a quota fake file. Replacement for
373 the CHECK_NTQUOTA_HANDLE_OK macro.
374 ****************************************************************************/
376 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
379 if (!check_fsp_open(conn
, req
, fsp
)) {
383 if (fsp
->is_directory
) {
387 if (fsp
->fake_file_handle
== NULL
) {
391 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
395 if (fsp
->fake_file_handle
->private_data
== NULL
) {
402 static bool netbios_session_retarget(struct smbd_server_connection
*sconn
,
403 const char *name
, int name_type
)
406 char *trim_name_type
;
407 const char *retarget_parm
;
410 int retarget_type
= 0x20;
411 int retarget_port
= 139;
412 struct sockaddr_storage retarget_addr
;
413 struct sockaddr_in
*in_addr
;
417 if (get_socket_port(sconn
->sock
) != 139) {
421 trim_name
= talloc_strdup(talloc_tos(), name
);
422 if (trim_name
== NULL
) {
425 trim_char(trim_name
, ' ', ' ');
427 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
429 if (trim_name_type
== NULL
) {
433 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
434 trim_name_type
, NULL
);
435 if (retarget_parm
== NULL
) {
436 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
439 if (retarget_parm
== NULL
) {
443 retarget
= talloc_strdup(trim_name
, retarget_parm
);
444 if (retarget
== NULL
) {
448 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
450 p
= strchr(retarget
, ':');
453 retarget_port
= atoi(p
);
456 p
= strchr_m(retarget
, '#');
459 if (sscanf(p
, "%x", &retarget_type
) != 1) {
464 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
466 DEBUG(10, ("could not resolve %s\n", retarget
));
470 if (retarget_addr
.ss_family
!= AF_INET
) {
471 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
475 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
477 _smb_setlen(outbuf
, 6);
478 SCVAL(outbuf
, 0, 0x84);
479 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
480 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
482 if (!srv_send_smb(sconn
, (char *)outbuf
, false, 0, false,
484 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
490 TALLOC_FREE(trim_name
);
494 /****************************************************************************
495 Reply to a (netbios-level) special message.
496 ****************************************************************************/
498 void reply_special(struct smbd_server_connection
*sconn
, char *inbuf
, size_t inbuf_size
)
500 int msg_type
= CVAL(inbuf
,0);
501 int msg_flags
= CVAL(inbuf
,1);
503 * We only really use 4 bytes of the outbuf, but for the smb_setlen
504 * calculation & friends (srv_send_smb uses that) we need the full smb
507 char outbuf
[smb_size
];
509 memset(outbuf
, '\0', sizeof(outbuf
));
511 smb_setlen(outbuf
,0);
514 case 0x81: /* session request */
516 /* inbuf_size is guarenteed to be at least 4. */
518 int name_type1
, name_type2
;
519 int name_len1
, name_len2
;
523 if (sconn
->nbt
.got_session
) {
524 exit_server_cleanly("multiple session request not permitted");
527 SCVAL(outbuf
,0,0x82);
530 /* inbuf_size is guaranteed to be at least 4. */
531 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
532 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
533 DEBUG(0,("Invalid name length in session request\n"));
536 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
537 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
538 DEBUG(0,("Invalid name length in session request\n"));
542 name_type1
= name_extract((unsigned char *)inbuf
,
543 inbuf_size
,(unsigned int)4,name1
);
544 name_type2
= name_extract((unsigned char *)inbuf
,
545 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
547 if (name_type1
== -1 || name_type2
== -1) {
548 DEBUG(0,("Invalid name type in session request\n"));
552 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
553 name1
, name_type1
, name2
, name_type2
));
555 if (netbios_session_retarget(sconn
, name1
, name_type1
)) {
556 exit_server_cleanly("retargeted client");
560 * Windows NT/2k uses "*SMBSERVER" and XP uses
561 * "*SMBSERV" arrggg!!!
563 if (strequal(name1
, "*SMBSERVER ")
564 || strequal(name1
, "*SMBSERV ")) {
565 fstrcpy(name1
, sconn
->client_id
.addr
);
568 set_local_machine_name(name1
, True
);
569 set_remote_machine_name(name2
, True
);
571 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
572 get_local_machine_name(), get_remote_machine_name(),
575 if (name_type2
== 'R') {
576 /* We are being asked for a pathworks session ---
578 SCVAL(outbuf
, 0,0x83);
582 /* only add the client's machine name to the list
583 of possibly valid usernames if we are operating
584 in share mode security */
585 if (lp_security() == SEC_SHARE
) {
586 add_session_user(sconn
, get_remote_machine_name());
589 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
592 sconn
->nbt
.got_session
= true;
596 case 0x89: /* session keepalive request
597 (some old clients produce this?) */
598 SCVAL(outbuf
,0,SMBkeepalive
);
602 case 0x82: /* positive session response */
603 case 0x83: /* negative session response */
604 case 0x84: /* retarget session response */
605 DEBUG(0,("Unexpected session response\n"));
608 case SMBkeepalive
: /* session keepalive */
613 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
614 msg_type
, msg_flags
));
616 srv_send_smb(sconn
, outbuf
, false, 0, false, NULL
);
620 /****************************************************************************
622 conn POINTER CAN BE NULL HERE !
623 ****************************************************************************/
625 void reply_tcon(struct smb_request
*req
)
627 connection_struct
*conn
= req
->conn
;
629 char *service_buf
= NULL
;
630 char *password
= NULL
;
635 DATA_BLOB password_blob
;
636 TALLOC_CTX
*ctx
= talloc_tos();
637 struct smbd_server_connection
*sconn
= req
->sconn
;
639 START_PROFILE(SMBtcon
);
641 if (req
->buflen
< 4) {
642 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
643 END_PROFILE(SMBtcon
);
647 p
= (const char *)req
->buf
+ 1;
648 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
650 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
652 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
655 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
656 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
657 END_PROFILE(SMBtcon
);
660 p
= strrchr_m(service_buf
,'\\');
664 service
= service_buf
;
667 password_blob
= data_blob(password
, pwlen
+1);
669 conn
= make_connection(sconn
,service
,password_blob
,dev
,
670 req
->vuid
,&nt_status
);
673 data_blob_clear_free(&password_blob
);
676 reply_nterror(req
, nt_status
);
677 END_PROFILE(SMBtcon
);
681 reply_outbuf(req
, 2, 0);
682 SSVAL(req
->outbuf
,smb_vwv0
,sconn
->smb1
.negprot
.max_recv
);
683 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
684 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
686 DEBUG(3,("tcon service=%s cnum=%d\n",
687 service
, conn
->cnum
));
689 END_PROFILE(SMBtcon
);
693 /****************************************************************************
694 Reply to a tcon and X.
695 conn POINTER CAN BE NULL HERE !
696 ****************************************************************************/
698 void reply_tcon_and_X(struct smb_request
*req
)
700 connection_struct
*conn
= req
->conn
;
701 const char *service
= NULL
;
703 TALLOC_CTX
*ctx
= talloc_tos();
704 /* what the cleint thinks the device is */
705 char *client_devicetype
= NULL
;
706 /* what the server tells the client the share represents */
707 const char *server_devicetype
;
713 struct smbd_server_connection
*sconn
= req
->sconn
;
715 START_PROFILE(SMBtconX
);
718 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
719 END_PROFILE(SMBtconX
);
723 passlen
= SVAL(req
->vwv
+3, 0);
724 tcon_flags
= SVAL(req
->vwv
+2, 0);
726 /* we might have to close an old one */
727 if ((tcon_flags
& 0x1) && conn
) {
728 close_cnum(conn
,req
->vuid
);
733 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
734 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
735 END_PROFILE(SMBtconX
);
739 if (sconn
->smb1
.negprot
.encrypted_passwords
) {
740 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
);
741 if (lp_security() == SEC_SHARE
) {
743 * Security = share always has a pad byte
744 * after the password.
746 p
= (const char *)req
->buf
+ passlen
+ 1;
748 p
= (const char *)req
->buf
+ passlen
;
751 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
+1);
752 /* Ensure correct termination */
753 password
.data
[passlen
]=0;
754 p
= (const char *)req
->buf
+ passlen
+ 1;
757 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
760 data_blob_clear_free(&password
);
761 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
762 END_PROFILE(SMBtconX
);
767 * the service name can be either: \\server\share
768 * or share directly like on the DELL PowerVault 705
771 q
= strchr_m(path
+2,'\\');
773 data_blob_clear_free(&password
);
774 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
775 END_PROFILE(SMBtconX
);
783 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
784 &client_devicetype
, p
,
785 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
787 if (client_devicetype
== NULL
) {
788 data_blob_clear_free(&password
);
789 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
790 END_PROFILE(SMBtconX
);
794 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
796 conn
= make_connection(sconn
, service
, password
, client_devicetype
,
797 req
->vuid
, &nt_status
);
800 data_blob_clear_free(&password
);
803 reply_nterror(req
, nt_status
);
804 END_PROFILE(SMBtconX
);
809 server_devicetype
= "IPC";
810 else if ( IS_PRINT(conn
) )
811 server_devicetype
= "LPT1:";
813 server_devicetype
= "A:";
815 if (get_Protocol() < PROTOCOL_NT1
) {
816 reply_outbuf(req
, 2, 0);
817 if (message_push_string(&req
->outbuf
, server_devicetype
,
818 STR_TERMINATE
|STR_ASCII
) == -1) {
819 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
820 END_PROFILE(SMBtconX
);
824 /* NT sets the fstype of IPC$ to the null string */
825 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
827 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
828 /* Return permissions. */
832 reply_outbuf(req
, 7, 0);
835 perm1
= FILE_ALL_ACCESS
;
836 perm2
= FILE_ALL_ACCESS
;
838 perm1
= conn
->share_access
;
841 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
842 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
844 reply_outbuf(req
, 3, 0);
847 if ((message_push_string(&req
->outbuf
, server_devicetype
,
848 STR_TERMINATE
|STR_ASCII
) == -1)
849 || (message_push_string(&req
->outbuf
, fstype
,
850 STR_TERMINATE
) == -1)) {
851 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
852 END_PROFILE(SMBtconX
);
856 /* what does setting this bit do? It is set by NT4 and
857 may affect the ability to autorun mounted cdroms */
858 SSVAL(req
->outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
859 (lp_csc_policy(SNUM(conn
)) << 2));
861 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
862 DEBUG(2,("Serving %s as a Dfs root\n",
863 lp_servicename(SNUM(conn
)) ));
864 SSVAL(req
->outbuf
, smb_vwv2
,
865 SMB_SHARE_IN_DFS
| SVAL(req
->outbuf
, smb_vwv2
));
870 DEBUG(3,("tconX service=%s \n",
873 /* set the incoming and outgoing tid to the just created one */
874 SSVAL(req
->inbuf
,smb_tid
,conn
->cnum
);
875 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
877 END_PROFILE(SMBtconX
);
879 req
->tid
= conn
->cnum
;
884 /****************************************************************************
885 Reply to an unknown type.
886 ****************************************************************************/
888 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
890 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
891 smb_fn_name(type
), type
, type
));
892 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
896 /****************************************************************************
898 conn POINTER CAN BE NULL HERE !
899 ****************************************************************************/
901 void reply_ioctl(struct smb_request
*req
)
903 connection_struct
*conn
= req
->conn
;
910 START_PROFILE(SMBioctl
);
913 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
914 END_PROFILE(SMBioctl
);
918 device
= SVAL(req
->vwv
+1, 0);
919 function
= SVAL(req
->vwv
+2, 0);
920 ioctl_code
= (device
<< 16) + function
;
922 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
924 switch (ioctl_code
) {
925 case IOCTL_QUERY_JOB_INFO
:
929 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
930 END_PROFILE(SMBioctl
);
934 reply_outbuf(req
, 8, replysize
+1);
935 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
936 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
937 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
938 p
= smb_buf(req
->outbuf
);
939 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
940 p
+= 1; /* Allow for alignment */
942 switch (ioctl_code
) {
943 case IOCTL_QUERY_JOB_INFO
:
945 files_struct
*fsp
= file_fsp(
946 req
, SVAL(req
->vwv
+0, 0));
948 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
949 END_PROFILE(SMBioctl
);
953 if (fsp
->print_file
) {
954 SSVAL(p
, 0, fsp
->print_file
->rap_jobid
);
958 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
960 STR_TERMINATE
|STR_ASCII
);
962 srvstr_push((char *)req
->outbuf
, req
->flags2
,
963 p
+18, lp_servicename(SNUM(conn
)),
964 13, STR_TERMINATE
|STR_ASCII
);
972 END_PROFILE(SMBioctl
);
976 /****************************************************************************
977 Strange checkpath NTSTATUS mapping.
978 ****************************************************************************/
980 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
982 /* Strange DOS error code semantics only for checkpath... */
983 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
984 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
985 /* We need to map to ERRbadpath */
986 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
992 /****************************************************************************
993 Reply to a checkpath.
994 ****************************************************************************/
996 void reply_checkpath(struct smb_request
*req
)
998 connection_struct
*conn
= req
->conn
;
999 struct smb_filename
*smb_fname
= NULL
;
1002 TALLOC_CTX
*ctx
= talloc_tos();
1004 START_PROFILE(SMBcheckpath
);
1006 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1007 STR_TERMINATE
, &status
);
1009 if (!NT_STATUS_IS_OK(status
)) {
1010 status
= map_checkpath_error(req
->flags2
, status
);
1011 reply_nterror(req
, status
);
1012 END_PROFILE(SMBcheckpath
);
1016 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1018 status
= filename_convert(ctx
,
1020 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1026 if (!NT_STATUS_IS_OK(status
)) {
1027 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1028 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1029 ERRSRV
, ERRbadpath
);
1030 END_PROFILE(SMBcheckpath
);
1036 if (!VALID_STAT(smb_fname
->st
) &&
1037 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1038 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1039 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1040 status
= map_nt_error_from_unix(errno
);
1044 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1045 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1046 ERRDOS
, ERRbadpath
);
1050 reply_outbuf(req
, 0, 0);
1053 /* We special case this - as when a Windows machine
1054 is parsing a path is steps through the components
1055 one at a time - if a component fails it expects
1056 ERRbadpath, not ERRbadfile.
1058 status
= map_checkpath_error(req
->flags2
, status
);
1059 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1061 * Windows returns different error codes if
1062 * the parent directory is valid but not the
1063 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1064 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1065 * if the path is invalid.
1067 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1068 ERRDOS
, ERRbadpath
);
1072 reply_nterror(req
, status
);
1075 TALLOC_FREE(smb_fname
);
1076 END_PROFILE(SMBcheckpath
);
1080 /****************************************************************************
1082 ****************************************************************************/
1084 void reply_getatr(struct smb_request
*req
)
1086 connection_struct
*conn
= req
->conn
;
1087 struct smb_filename
*smb_fname
= NULL
;
1094 TALLOC_CTX
*ctx
= talloc_tos();
1095 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1097 START_PROFILE(SMBgetatr
);
1099 p
= (const char *)req
->buf
+ 1;
1100 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1101 if (!NT_STATUS_IS_OK(status
)) {
1102 reply_nterror(req
, status
);
1106 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1107 under WfWg - weird! */
1108 if (*fname
== '\0') {
1109 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1110 if (!CAN_WRITE(conn
)) {
1111 mode
|= FILE_ATTRIBUTE_READONLY
;
1116 status
= filename_convert(ctx
,
1118 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1123 if (!NT_STATUS_IS_OK(status
)) {
1124 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1125 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1126 ERRSRV
, ERRbadpath
);
1129 reply_nterror(req
, status
);
1132 if (!VALID_STAT(smb_fname
->st
) &&
1133 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1134 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1135 smb_fname_str_dbg(smb_fname
),
1137 reply_nterror(req
, map_nt_error_from_unix(errno
));
1141 mode
= dos_mode(conn
, smb_fname
);
1142 size
= smb_fname
->st
.st_ex_size
;
1144 if (ask_sharemode
) {
1145 struct timespec write_time_ts
;
1146 struct file_id fileid
;
1148 ZERO_STRUCT(write_time_ts
);
1149 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1150 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1151 if (!null_timespec(write_time_ts
)) {
1152 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1156 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1157 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1162 reply_outbuf(req
, 10, 0);
1164 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1165 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1166 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1168 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1170 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1172 if (get_Protocol() >= PROTOCOL_NT1
) {
1173 SSVAL(req
->outbuf
, smb_flg2
,
1174 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1177 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1178 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1181 TALLOC_FREE(smb_fname
);
1183 END_PROFILE(SMBgetatr
);
1187 /****************************************************************************
1189 ****************************************************************************/
1191 void reply_setatr(struct smb_request
*req
)
1193 struct smb_file_time ft
;
1194 connection_struct
*conn
= req
->conn
;
1195 struct smb_filename
*smb_fname
= NULL
;
1201 TALLOC_CTX
*ctx
= talloc_tos();
1203 START_PROFILE(SMBsetatr
);
1208 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1212 p
= (const char *)req
->buf
+ 1;
1213 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1214 if (!NT_STATUS_IS_OK(status
)) {
1215 reply_nterror(req
, status
);
1219 status
= filename_convert(ctx
,
1221 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1226 if (!NT_STATUS_IS_OK(status
)) {
1227 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1228 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1229 ERRSRV
, ERRbadpath
);
1232 reply_nterror(req
, status
);
1236 if (smb_fname
->base_name
[0] == '.' &&
1237 smb_fname
->base_name
[1] == '\0') {
1239 * Not sure here is the right place to catch this
1240 * condition. Might be moved to somewhere else later -- vl
1242 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1246 mode
= SVAL(req
->vwv
+0, 0);
1247 mtime
= srv_make_unix_date3(req
->vwv
+1);
1249 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1250 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1251 if (!NT_STATUS_IS_OK(status
)) {
1252 reply_nterror(req
, status
);
1256 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1257 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1258 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1260 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1262 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1264 reply_nterror(req
, map_nt_error_from_unix(errno
));
1269 reply_outbuf(req
, 0, 0);
1271 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1274 TALLOC_FREE(smb_fname
);
1275 END_PROFILE(SMBsetatr
);
1279 /****************************************************************************
1281 ****************************************************************************/
1283 void reply_dskattr(struct smb_request
*req
)
1285 connection_struct
*conn
= req
->conn
;
1286 uint64_t dfree
,dsize
,bsize
;
1287 START_PROFILE(SMBdskattr
);
1289 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1290 reply_nterror(req
, map_nt_error_from_unix(errno
));
1291 END_PROFILE(SMBdskattr
);
1295 reply_outbuf(req
, 5, 0);
1297 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1298 double total_space
, free_space
;
1299 /* we need to scale this to a number that DOS6 can handle. We
1300 use floating point so we can handle large drives on systems
1301 that don't have 64 bit integers
1303 we end up displaying a maximum of 2G to DOS systems
1305 total_space
= dsize
* (double)bsize
;
1306 free_space
= dfree
* (double)bsize
;
1308 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1309 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1311 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1312 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1314 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1315 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1316 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1317 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1319 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1320 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1321 SSVAL(req
->outbuf
,smb_vwv2
,512);
1322 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1325 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1327 END_PROFILE(SMBdskattr
);
1332 * Utility function to split the filename from the directory.
1334 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1335 char **fname_dir_out
,
1336 char **fname_mask_out
)
1338 const char *p
= NULL
;
1339 char *fname_dir
= NULL
;
1340 char *fname_mask
= NULL
;
1342 p
= strrchr_m(fname_in
, '/');
1344 fname_dir
= talloc_strdup(ctx
, ".");
1345 fname_mask
= talloc_strdup(ctx
, fname_in
);
1347 fname_dir
= talloc_strndup(ctx
, fname_in
,
1348 PTR_DIFF(p
, fname_in
));
1349 fname_mask
= talloc_strdup(ctx
, p
+1);
1352 if (!fname_dir
|| !fname_mask
) {
1353 TALLOC_FREE(fname_dir
);
1354 TALLOC_FREE(fname_mask
);
1355 return NT_STATUS_NO_MEMORY
;
1358 *fname_dir_out
= fname_dir
;
1359 *fname_mask_out
= fname_mask
;
1360 return NT_STATUS_OK
;
1363 /****************************************************************************
1365 Can be called from SMBsearch, SMBffirst or SMBfunique.
1366 ****************************************************************************/
1368 void reply_search(struct smb_request
*req
)
1370 connection_struct
*conn
= req
->conn
;
1372 const char *mask
= NULL
;
1373 char *directory
= NULL
;
1374 struct smb_filename
*smb_fname
= NULL
;
1378 struct timespec date
;
1380 unsigned int numentries
= 0;
1381 unsigned int maxentries
= 0;
1382 bool finished
= False
;
1387 bool check_descend
= False
;
1388 bool expect_close
= False
;
1390 bool mask_contains_wcard
= False
;
1391 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1392 TALLOC_CTX
*ctx
= talloc_tos();
1393 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1394 struct dptr_struct
*dirptr
= NULL
;
1395 struct smbd_server_connection
*sconn
= req
->sconn
;
1397 START_PROFILE(SMBsearch
);
1400 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1404 if (lp_posix_pathnames()) {
1405 reply_unknown_new(req
, req
->cmd
);
1409 /* If we were called as SMBffirst then we must expect close. */
1410 if(req
->cmd
== SMBffirst
) {
1411 expect_close
= True
;
1414 reply_outbuf(req
, 1, 3);
1415 maxentries
= SVAL(req
->vwv
+0, 0);
1416 dirtype
= SVAL(req
->vwv
+1, 0);
1417 p
= (const char *)req
->buf
+ 1;
1418 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1419 &nt_status
, &mask_contains_wcard
);
1420 if (!NT_STATUS_IS_OK(nt_status
)) {
1421 reply_nterror(req
, nt_status
);
1426 status_len
= SVAL(p
, 0);
1429 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1431 if (status_len
== 0) {
1432 nt_status
= filename_convert(ctx
, conn
,
1433 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1435 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1436 &mask_contains_wcard
,
1438 if (!NT_STATUS_IS_OK(nt_status
)) {
1439 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1440 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1441 ERRSRV
, ERRbadpath
);
1444 reply_nterror(req
, nt_status
);
1448 directory
= smb_fname
->base_name
;
1450 p
= strrchr_m(directory
,'/');
1451 if ((p
!= NULL
) && (*directory
!= '/')) {
1453 directory
= talloc_strndup(ctx
, directory
,
1454 PTR_DIFF(p
, directory
));
1457 directory
= talloc_strdup(ctx
,".");
1461 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1465 memset((char *)status
,'\0',21);
1466 SCVAL(status
,0,(dirtype
& 0x1F));
1468 nt_status
= dptr_create(conn
,
1475 mask_contains_wcard
,
1478 if (!NT_STATUS_IS_OK(nt_status
)) {
1479 reply_nterror(req
, nt_status
);
1482 dptr_num
= dptr_dnum(dirptr
);
1485 const char *dirpath
;
1487 memcpy(status
,p
,21);
1488 status_dirtype
= CVAL(status
,0) & 0x1F;
1489 if (status_dirtype
!= (dirtype
& 0x1F)) {
1490 dirtype
= status_dirtype
;
1493 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1497 dirpath
= dptr_path(sconn
, dptr_num
);
1498 directory
= talloc_strdup(ctx
, dirpath
);
1500 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1504 mask
= dptr_wcard(sconn
, dptr_num
);
1509 * For a 'continue' search we have no string. So
1510 * check from the initial saved string.
1512 mask_contains_wcard
= ms_has_wild(mask
);
1513 dirtype
= dptr_attr(sconn
, dptr_num
);
1516 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1518 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1519 dptr_init_search_op(dirptr
);
1521 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1522 char buf
[DIR_STRUCT_SIZE
];
1523 memcpy(buf
,status
,21);
1524 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1525 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1526 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1529 dptr_fill(sconn
, buf
+12,dptr_num
);
1530 if (dptr_zero(buf
+12) && (status_len
==0)) {
1535 if (message_push_blob(&req
->outbuf
,
1536 data_blob_const(buf
, sizeof(buf
)))
1538 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1546 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1549 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1550 directory
,lp_dontdescend(SNUM(conn
))));
1551 if (in_list(directory
, lp_dontdescend(SNUM(conn
)),True
)) {
1552 check_descend
= True
;
1555 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1556 finished
= !get_dir_entry(ctx
,
1567 char buf
[DIR_STRUCT_SIZE
];
1568 memcpy(buf
,status
,21);
1569 if (!make_dir_struct(ctx
,
1575 convert_timespec_to_time_t(date
),
1576 !allow_long_path_components
)) {
1577 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1580 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1583 if (message_push_blob(&req
->outbuf
,
1584 data_blob_const(buf
, sizeof(buf
)))
1586 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1596 /* If we were called as SMBffirst with smb_search_id == NULL
1597 and no entries were found then return error and close dirptr
1600 if (numentries
== 0) {
1601 dptr_close(sconn
, &dptr_num
);
1602 } else if(expect_close
&& status_len
== 0) {
1603 /* Close the dptr - we know it's gone */
1604 dptr_close(sconn
, &dptr_num
);
1607 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1608 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1609 dptr_close(sconn
, &dptr_num
);
1612 if ((numentries
== 0) && !mask_contains_wcard
) {
1613 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1617 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1618 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1619 SCVAL(smb_buf(req
->outbuf
),0,5);
1620 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1622 /* The replies here are never long name. */
1623 SSVAL(req
->outbuf
, smb_flg2
,
1624 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1625 if (!allow_long_path_components
) {
1626 SSVAL(req
->outbuf
, smb_flg2
,
1627 SVAL(req
->outbuf
, smb_flg2
)
1628 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1631 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1632 SSVAL(req
->outbuf
, smb_flg2
,
1633 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1635 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1636 smb_fn_name(req
->cmd
),
1643 TALLOC_FREE(directory
);
1644 TALLOC_FREE(smb_fname
);
1645 END_PROFILE(SMBsearch
);
1649 /****************************************************************************
1650 Reply to a fclose (stop directory search).
1651 ****************************************************************************/
1653 void reply_fclose(struct smb_request
*req
)
1661 bool path_contains_wcard
= False
;
1662 TALLOC_CTX
*ctx
= talloc_tos();
1663 struct smbd_server_connection
*sconn
= req
->sconn
;
1665 START_PROFILE(SMBfclose
);
1667 if (lp_posix_pathnames()) {
1668 reply_unknown_new(req
, req
->cmd
);
1669 END_PROFILE(SMBfclose
);
1673 p
= (const char *)req
->buf
+ 1;
1674 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1675 &err
, &path_contains_wcard
);
1676 if (!NT_STATUS_IS_OK(err
)) {
1677 reply_nterror(req
, err
);
1678 END_PROFILE(SMBfclose
);
1682 status_len
= SVAL(p
,0);
1685 if (status_len
== 0) {
1686 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1687 END_PROFILE(SMBfclose
);
1691 memcpy(status
,p
,21);
1693 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1694 /* Close the dptr - we know it's gone */
1695 dptr_close(sconn
, &dptr_num
);
1698 reply_outbuf(req
, 1, 0);
1699 SSVAL(req
->outbuf
,smb_vwv0
,0);
1701 DEBUG(3,("search close\n"));
1703 END_PROFILE(SMBfclose
);
1707 /****************************************************************************
1709 ****************************************************************************/
1711 void reply_open(struct smb_request
*req
)
1713 connection_struct
*conn
= req
->conn
;
1714 struct smb_filename
*smb_fname
= NULL
;
1726 uint32 create_disposition
;
1727 uint32 create_options
= 0;
1728 uint32_t private_flags
= 0;
1730 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1731 TALLOC_CTX
*ctx
= talloc_tos();
1733 START_PROFILE(SMBopen
);
1736 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1740 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1741 deny_mode
= SVAL(req
->vwv
+0, 0);
1742 dos_attr
= SVAL(req
->vwv
+1, 0);
1744 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1745 STR_TERMINATE
, &status
);
1746 if (!NT_STATUS_IS_OK(status
)) {
1747 reply_nterror(req
, status
);
1751 status
= filename_convert(ctx
,
1753 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1758 if (!NT_STATUS_IS_OK(status
)) {
1759 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1760 reply_botherror(req
,
1761 NT_STATUS_PATH_NOT_COVERED
,
1762 ERRSRV
, ERRbadpath
);
1765 reply_nterror(req
, status
);
1769 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1770 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1771 &share_mode
, &create_disposition
,
1772 &create_options
, &private_flags
)) {
1773 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1777 status
= SMB_VFS_CREATE_FILE(
1780 0, /* root_dir_fid */
1781 smb_fname
, /* fname */
1782 access_mask
, /* access_mask */
1783 share_mode
, /* share_access */
1784 create_disposition
, /* create_disposition*/
1785 create_options
, /* create_options */
1786 dos_attr
, /* file_attributes */
1787 oplock_request
, /* oplock_request */
1788 0, /* allocation_size */
1795 if (!NT_STATUS_IS_OK(status
)) {
1796 if (open_was_deferred(req
->mid
)) {
1797 /* We have re-scheduled this call. */
1800 reply_openerror(req
, status
);
1804 size
= smb_fname
->st
.st_ex_size
;
1805 fattr
= dos_mode(conn
, smb_fname
);
1807 /* Deal with other possible opens having a modified
1809 if (ask_sharemode
) {
1810 struct timespec write_time_ts
;
1812 ZERO_STRUCT(write_time_ts
);
1813 get_file_infos(fsp
->file_id
, 0, NULL
, &write_time_ts
);
1814 if (!null_timespec(write_time_ts
)) {
1815 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1819 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1821 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1822 DEBUG(3,("attempt to open a directory %s\n",
1824 close_file(req
, fsp
, ERROR_CLOSE
);
1825 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1826 ERRDOS
, ERRnoaccess
);
1830 reply_outbuf(req
, 7, 0);
1831 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1832 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1833 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1834 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1836 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1838 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1839 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1841 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1842 SCVAL(req
->outbuf
,smb_flg
,
1843 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1846 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1847 SCVAL(req
->outbuf
,smb_flg
,
1848 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1851 TALLOC_FREE(smb_fname
);
1852 END_PROFILE(SMBopen
);
1856 /****************************************************************************
1857 Reply to an open and X.
1858 ****************************************************************************/
1860 void reply_open_and_X(struct smb_request
*req
)
1862 connection_struct
*conn
= req
->conn
;
1863 struct smb_filename
*smb_fname
= NULL
;
1868 /* Breakout the oplock request bits so we can set the
1869 reply bits separately. */
1870 int ex_oplock_request
;
1871 int core_oplock_request
;
1874 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1875 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
1883 uint64_t allocation_size
;
1884 ssize_t retval
= -1;
1887 uint32 create_disposition
;
1888 uint32 create_options
= 0;
1889 uint32_t private_flags
= 0;
1890 TALLOC_CTX
*ctx
= talloc_tos();
1892 START_PROFILE(SMBopenX
);
1894 if (req
->wct
< 15) {
1895 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1899 open_flags
= SVAL(req
->vwv
+2, 0);
1900 deny_mode
= SVAL(req
->vwv
+3, 0);
1901 smb_attr
= SVAL(req
->vwv
+5, 0);
1902 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1903 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1904 oplock_request
= ex_oplock_request
| core_oplock_request
;
1905 smb_ofun
= SVAL(req
->vwv
+8, 0);
1906 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1908 /* If it's an IPC, pass off the pipe handler. */
1910 if (lp_nt_pipe_support()) {
1911 reply_open_pipe_and_X(conn
, req
);
1913 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1918 /* XXXX we need to handle passed times, sattr and flags */
1919 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1920 STR_TERMINATE
, &status
);
1921 if (!NT_STATUS_IS_OK(status
)) {
1922 reply_nterror(req
, status
);
1926 status
= filename_convert(ctx
,
1928 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1933 if (!NT_STATUS_IS_OK(status
)) {
1934 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1935 reply_botherror(req
,
1936 NT_STATUS_PATH_NOT_COVERED
,
1937 ERRSRV
, ERRbadpath
);
1940 reply_nterror(req
, status
);
1944 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1946 &access_mask
, &share_mode
,
1947 &create_disposition
,
1950 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1954 status
= SMB_VFS_CREATE_FILE(
1957 0, /* root_dir_fid */
1958 smb_fname
, /* fname */
1959 access_mask
, /* access_mask */
1960 share_mode
, /* share_access */
1961 create_disposition
, /* create_disposition*/
1962 create_options
, /* create_options */
1963 smb_attr
, /* file_attributes */
1964 oplock_request
, /* oplock_request */
1965 0, /* allocation_size */
1970 &smb_action
); /* pinfo */
1972 if (!NT_STATUS_IS_OK(status
)) {
1973 if (open_was_deferred(req
->mid
)) {
1974 /* We have re-scheduled this call. */
1977 reply_openerror(req
, status
);
1981 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1982 if the file is truncated or created. */
1983 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1984 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1985 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1986 close_file(req
, fsp
, ERROR_CLOSE
);
1987 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1990 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1992 close_file(req
, fsp
, ERROR_CLOSE
);
1993 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1996 status
= vfs_stat_fsp(fsp
);
1997 if (!NT_STATUS_IS_OK(status
)) {
1998 close_file(req
, fsp
, ERROR_CLOSE
);
1999 reply_nterror(req
, status
);
2004 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2005 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2006 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2007 close_file(req
, fsp
, ERROR_CLOSE
);
2008 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2012 /* If the caller set the extended oplock request bit
2013 and we granted one (by whatever means) - set the
2014 correct bit for extended oplock reply.
2017 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2018 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2021 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2022 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2025 /* If the caller set the core oplock request bit
2026 and we granted one (by whatever means) - set the
2027 correct bit for core oplock reply.
2030 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2031 reply_outbuf(req
, 19, 0);
2033 reply_outbuf(req
, 15, 0);
2036 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2037 SCVAL(req
->outbuf
, smb_flg
,
2038 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2041 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2042 SCVAL(req
->outbuf
, smb_flg
,
2043 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2046 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2047 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2048 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2049 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2051 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2053 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2054 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2055 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2057 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2058 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2063 TALLOC_FREE(smb_fname
);
2064 END_PROFILE(SMBopenX
);
2068 /****************************************************************************
2069 Reply to a SMBulogoffX.
2070 ****************************************************************************/
2072 void reply_ulogoffX(struct smb_request
*req
)
2074 struct smbd_server_connection
*sconn
= req
->sconn
;
2077 START_PROFILE(SMBulogoffX
);
2079 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2082 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2086 /* in user level security we are supposed to close any files
2087 open by this user */
2088 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
2089 file_close_user(sconn
, req
->vuid
);
2092 invalidate_vuid(sconn
, req
->vuid
);
2094 reply_outbuf(req
, 2, 0);
2096 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
2098 END_PROFILE(SMBulogoffX
);
2099 req
->vuid
= UID_FIELD_INVALID
;
2103 /****************************************************************************
2104 Reply to a mknew or a create.
2105 ****************************************************************************/
2107 void reply_mknew(struct smb_request
*req
)
2109 connection_struct
*conn
= req
->conn
;
2110 struct smb_filename
*smb_fname
= NULL
;
2113 struct smb_file_time ft
;
2115 int oplock_request
= 0;
2117 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2118 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2119 uint32 create_disposition
;
2120 uint32 create_options
= 0;
2121 TALLOC_CTX
*ctx
= talloc_tos();
2123 START_PROFILE(SMBcreate
);
2127 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2131 fattr
= SVAL(req
->vwv
+0, 0);
2132 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2135 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2137 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2138 STR_TERMINATE
, &status
);
2139 if (!NT_STATUS_IS_OK(status
)) {
2140 reply_nterror(req
, status
);
2144 status
= filename_convert(ctx
,
2146 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2151 if (!NT_STATUS_IS_OK(status
)) {
2152 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2153 reply_botherror(req
,
2154 NT_STATUS_PATH_NOT_COVERED
,
2155 ERRSRV
, ERRbadpath
);
2158 reply_nterror(req
, status
);
2162 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2163 DEBUG(0,("Attempt to create file (%s) with volid set - "
2164 "please report this\n",
2165 smb_fname_str_dbg(smb_fname
)));
2168 if(req
->cmd
== SMBmknew
) {
2169 /* We should fail if file exists. */
2170 create_disposition
= FILE_CREATE
;
2172 /* Create if file doesn't exist, truncate if it does. */
2173 create_disposition
= FILE_OVERWRITE_IF
;
2176 status
= SMB_VFS_CREATE_FILE(
2179 0, /* root_dir_fid */
2180 smb_fname
, /* fname */
2181 access_mask
, /* access_mask */
2182 share_mode
, /* share_access */
2183 create_disposition
, /* create_disposition*/
2184 create_options
, /* create_options */
2185 fattr
, /* file_attributes */
2186 oplock_request
, /* oplock_request */
2187 0, /* allocation_size */
2188 0, /* private_flags */
2194 if (!NT_STATUS_IS_OK(status
)) {
2195 if (open_was_deferred(req
->mid
)) {
2196 /* We have re-scheduled this call. */
2199 reply_openerror(req
, status
);
2203 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2204 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2205 if (!NT_STATUS_IS_OK(status
)) {
2206 END_PROFILE(SMBcreate
);
2210 reply_outbuf(req
, 1, 0);
2211 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2213 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2214 SCVAL(req
->outbuf
,smb_flg
,
2215 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2218 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2219 SCVAL(req
->outbuf
,smb_flg
,
2220 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2223 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2224 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2225 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2226 (unsigned int)fattr
));
2229 TALLOC_FREE(smb_fname
);
2230 END_PROFILE(SMBcreate
);
2234 /****************************************************************************
2235 Reply to a create temporary file.
2236 ****************************************************************************/
2238 void reply_ctemp(struct smb_request
*req
)
2240 connection_struct
*conn
= req
->conn
;
2241 struct smb_filename
*smb_fname
= NULL
;
2249 TALLOC_CTX
*ctx
= talloc_tos();
2251 START_PROFILE(SMBctemp
);
2254 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2258 fattr
= SVAL(req
->vwv
+0, 0);
2259 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2261 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2262 STR_TERMINATE
, &status
);
2263 if (!NT_STATUS_IS_OK(status
)) {
2264 reply_nterror(req
, status
);
2268 fname
= talloc_asprintf(ctx
,
2272 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2276 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2280 status
= filename_convert(ctx
, conn
,
2281 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2286 if (!NT_STATUS_IS_OK(status
)) {
2287 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2288 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2289 ERRSRV
, ERRbadpath
);
2292 reply_nterror(req
, status
);
2296 tmpfd
= mkstemp(smb_fname
->base_name
);
2298 reply_nterror(req
, map_nt_error_from_unix(errno
));
2302 SMB_VFS_STAT(conn
, smb_fname
);
2304 /* We should fail if file does not exist. */
2305 status
= SMB_VFS_CREATE_FILE(
2308 0, /* root_dir_fid */
2309 smb_fname
, /* fname */
2310 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2311 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2312 FILE_OPEN
, /* create_disposition*/
2313 0, /* create_options */
2314 fattr
, /* file_attributes */
2315 oplock_request
, /* oplock_request */
2316 0, /* allocation_size */
2317 0, /* private_flags */
2323 /* close fd from mkstemp() */
2326 if (!NT_STATUS_IS_OK(status
)) {
2327 if (open_was_deferred(req
->mid
)) {
2328 /* We have re-scheduled this call. */
2331 reply_openerror(req
, status
);
2335 reply_outbuf(req
, 1, 0);
2336 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2338 /* the returned filename is relative to the directory */
2339 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2341 s
= fsp
->fsp_name
->base_name
;
2347 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2348 thing in the byte section. JRA */
2349 SSVALS(p
, 0, -1); /* what is this? not in spec */
2351 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2353 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2357 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2358 SCVAL(req
->outbuf
, smb_flg
,
2359 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2362 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2363 SCVAL(req
->outbuf
, smb_flg
,
2364 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2367 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2368 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2369 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2371 TALLOC_FREE(smb_fname
);
2372 END_PROFILE(SMBctemp
);
2376 /*******************************************************************
2377 Check if a user is allowed to rename a file.
2378 ********************************************************************/
2380 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2383 if (!CAN_WRITE(conn
)) {
2384 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2387 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2388 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2389 /* Only bother to read the DOS attribute if we might deny the
2390 rename on the grounds of attribute missmatch. */
2391 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2392 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2393 return NT_STATUS_NO_SUCH_FILE
;
2397 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2398 if (fsp
->posix_open
) {
2399 return NT_STATUS_OK
;
2402 /* If no pathnames are open below this
2403 directory, allow the rename. */
2405 if (file_find_subpath(fsp
)) {
2406 return NT_STATUS_ACCESS_DENIED
;
2408 return NT_STATUS_OK
;
2411 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2412 return NT_STATUS_OK
;
2415 return NT_STATUS_ACCESS_DENIED
;
2418 /*******************************************************************
2419 * unlink a file with all relevant access checks
2420 *******************************************************************/
2422 static NTSTATUS
do_unlink(connection_struct
*conn
,
2423 struct smb_request
*req
,
2424 struct smb_filename
*smb_fname
,
2429 uint32 dirtype_orig
= dirtype
;
2432 bool posix_paths
= lp_posix_pathnames();
2434 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2435 smb_fname_str_dbg(smb_fname
),
2438 if (!CAN_WRITE(conn
)) {
2439 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2443 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2445 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2448 return map_nt_error_from_unix(errno
);
2451 fattr
= dos_mode(conn
, smb_fname
);
2453 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2454 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2457 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2459 return NT_STATUS_NO_SUCH_FILE
;
2462 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2463 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2464 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2466 return NT_STATUS_NO_SUCH_FILE
;
2469 if (dirtype_orig
& 0x8000) {
2470 /* These will never be set for POSIX. */
2471 return NT_STATUS_NO_SUCH_FILE
;
2475 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2476 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2479 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2480 return NT_STATUS_NO_SUCH_FILE
;
2483 if (dirtype
& 0xFF00) {
2484 /* These will never be set for POSIX. */
2485 return NT_STATUS_NO_SUCH_FILE
;
2490 return NT_STATUS_NO_SUCH_FILE
;
2493 /* Can't delete a directory. */
2494 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2495 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2500 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2501 return NT_STATUS_OBJECT_NAME_INVALID
;
2502 #endif /* JRATEST */
2504 /* On open checks the open itself will check the share mode, so
2505 don't do it here as we'll get it wrong. */
2507 status
= SMB_VFS_CREATE_FILE
2510 0, /* root_dir_fid */
2511 smb_fname
, /* fname */
2512 DELETE_ACCESS
, /* access_mask */
2513 FILE_SHARE_NONE
, /* share_access */
2514 FILE_OPEN
, /* create_disposition*/
2515 FILE_NON_DIRECTORY_FILE
, /* create_options */
2516 /* file_attributes */
2517 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2518 FILE_ATTRIBUTE_NORMAL
,
2519 0, /* oplock_request */
2520 0, /* allocation_size */
2521 0, /* private_flags */
2527 if (!NT_STATUS_IS_OK(status
)) {
2528 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2529 nt_errstr(status
)));
2533 status
= can_set_delete_on_close(fsp
, fattr
);
2534 if (!NT_STATUS_IS_OK(status
)) {
2535 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2537 smb_fname_str_dbg(smb_fname
),
2538 nt_errstr(status
)));
2539 close_file(req
, fsp
, NORMAL_CLOSE
);
2543 /* The set is across all open files on this dev/inode pair. */
2544 if (!set_delete_on_close(fsp
, True
, &conn
->session_info
->utok
)) {
2545 close_file(req
, fsp
, NORMAL_CLOSE
);
2546 return NT_STATUS_ACCESS_DENIED
;
2549 return close_file(req
, fsp
, NORMAL_CLOSE
);
2552 /****************************************************************************
2553 The guts of the unlink command, split out so it may be called by the NT SMB
2555 ****************************************************************************/
2557 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2558 uint32 dirtype
, struct smb_filename
*smb_fname
,
2561 char *fname_dir
= NULL
;
2562 char *fname_mask
= NULL
;
2564 NTSTATUS status
= NT_STATUS_OK
;
2565 TALLOC_CTX
*ctx
= talloc_tos();
2567 /* Split up the directory from the filename/mask. */
2568 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2569 &fname_dir
, &fname_mask
);
2570 if (!NT_STATUS_IS_OK(status
)) {
2575 * We should only check the mangled cache
2576 * here if unix_convert failed. This means
2577 * that the path in 'mask' doesn't exist
2578 * on the file system and so we need to look
2579 * for a possible mangle. This patch from
2580 * Tine Smukavec <valentin.smukavec@hermes.si>.
2583 if (!VALID_STAT(smb_fname
->st
) &&
2584 mangle_is_mangled(fname_mask
, conn
->params
)) {
2585 char *new_mask
= NULL
;
2586 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2587 &new_mask
, conn
->params
);
2589 TALLOC_FREE(fname_mask
);
2590 fname_mask
= new_mask
;
2597 * Only one file needs to be unlinked. Append the mask back
2598 * onto the directory.
2600 TALLOC_FREE(smb_fname
->base_name
);
2601 if (ISDOT(fname_dir
)) {
2602 /* Ensure we use canonical names on open. */
2603 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2607 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2612 if (!smb_fname
->base_name
) {
2613 status
= NT_STATUS_NO_MEMORY
;
2617 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2620 status
= check_name(conn
, smb_fname
->base_name
);
2621 if (!NT_STATUS_IS_OK(status
)) {
2625 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2626 if (!NT_STATUS_IS_OK(status
)) {
2632 struct smb_Dir
*dir_hnd
= NULL
;
2634 const char *dname
= NULL
;
2635 char *talloced
= NULL
;
2637 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2638 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2642 if (strequal(fname_mask
,"????????.???")) {
2643 TALLOC_FREE(fname_mask
);
2644 fname_mask
= talloc_strdup(ctx
, "*");
2646 status
= NT_STATUS_NO_MEMORY
;
2651 status
= check_name(conn
, fname_dir
);
2652 if (!NT_STATUS_IS_OK(status
)) {
2656 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2658 if (dir_hnd
== NULL
) {
2659 status
= map_nt_error_from_unix(errno
);
2663 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2664 the pattern matches against the long name, otherwise the short name
2665 We don't implement this yet XXXX
2668 status
= NT_STATUS_NO_SUCH_FILE
;
2670 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2671 &smb_fname
->st
, &talloced
))) {
2672 TALLOC_CTX
*frame
= talloc_stackframe();
2674 if (!is_visible_file(conn
, fname_dir
, dname
,
2675 &smb_fname
->st
, true)) {
2677 TALLOC_FREE(talloced
);
2681 /* Quick check for "." and ".." */
2682 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2684 TALLOC_FREE(talloced
);
2688 if(!mask_match(dname
, fname_mask
,
2689 conn
->case_sensitive
)) {
2691 TALLOC_FREE(talloced
);
2695 TALLOC_FREE(smb_fname
->base_name
);
2696 if (ISDOT(fname_dir
)) {
2697 /* Ensure we use canonical names on open. */
2698 smb_fname
->base_name
=
2699 talloc_asprintf(smb_fname
, "%s",
2702 smb_fname
->base_name
=
2703 talloc_asprintf(smb_fname
, "%s/%s",
2707 if (!smb_fname
->base_name
) {
2708 TALLOC_FREE(dir_hnd
);
2709 status
= NT_STATUS_NO_MEMORY
;
2711 TALLOC_FREE(talloced
);
2715 status
= check_name(conn
, smb_fname
->base_name
);
2716 if (!NT_STATUS_IS_OK(status
)) {
2717 TALLOC_FREE(dir_hnd
);
2719 TALLOC_FREE(talloced
);
2723 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2724 if (!NT_STATUS_IS_OK(status
)) {
2726 TALLOC_FREE(talloced
);
2731 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2732 smb_fname
->base_name
));
2735 TALLOC_FREE(talloced
);
2737 TALLOC_FREE(dir_hnd
);
2740 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2741 status
= map_nt_error_from_unix(errno
);
2745 TALLOC_FREE(fname_dir
);
2746 TALLOC_FREE(fname_mask
);
2750 /****************************************************************************
2752 ****************************************************************************/
2754 void reply_unlink(struct smb_request
*req
)
2756 connection_struct
*conn
= req
->conn
;
2758 struct smb_filename
*smb_fname
= NULL
;
2761 bool path_contains_wcard
= False
;
2762 TALLOC_CTX
*ctx
= talloc_tos();
2764 START_PROFILE(SMBunlink
);
2767 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2771 dirtype
= SVAL(req
->vwv
+0, 0);
2773 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2774 STR_TERMINATE
, &status
,
2775 &path_contains_wcard
);
2776 if (!NT_STATUS_IS_OK(status
)) {
2777 reply_nterror(req
, status
);
2781 status
= filename_convert(ctx
, conn
,
2782 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2784 UCF_COND_ALLOW_WCARD_LCOMP
,
2785 &path_contains_wcard
,
2787 if (!NT_STATUS_IS_OK(status
)) {
2788 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2789 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2790 ERRSRV
, ERRbadpath
);
2793 reply_nterror(req
, status
);
2797 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2799 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2800 path_contains_wcard
);
2801 if (!NT_STATUS_IS_OK(status
)) {
2802 if (open_was_deferred(req
->mid
)) {
2803 /* We have re-scheduled this call. */
2806 reply_nterror(req
, status
);
2810 reply_outbuf(req
, 0, 0);
2812 TALLOC_FREE(smb_fname
);
2813 END_PROFILE(SMBunlink
);
2817 /****************************************************************************
2819 ****************************************************************************/
2821 static void fail_readraw(void)
2823 const char *errstr
= talloc_asprintf(talloc_tos(),
2824 "FAIL ! reply_readbraw: socket write fail (%s)",
2829 exit_server_cleanly(errstr
);
2832 /****************************************************************************
2833 Fake (read/write) sendfile. Returns -1 on read or write fail.
2834 ****************************************************************************/
2836 ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
)
2839 size_t tosend
= nread
;
2846 bufsize
= MIN(nread
, 65536);
2848 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2852 while (tosend
> 0) {
2856 if (tosend
> bufsize
) {
2861 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2867 /* If we had a short read, fill with zeros. */
2868 if (ret
< cur_read
) {
2869 memset(buf
+ ret
, '\0', cur_read
- ret
);
2872 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
2874 char addr
[INET6_ADDRSTRLEN
];
2876 * Try and give an error message saying what
2879 DEBUG(0, ("write_data failed for client %s. "
2881 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
2888 startpos
+= cur_read
;
2892 return (ssize_t
)nread
;
2895 /****************************************************************************
2896 Deal with the case of sendfile reading less bytes from the file than
2897 requested. Fill with zeros (all we can do).
2898 ****************************************************************************/
2900 void sendfile_short_send(files_struct
*fsp
,
2905 #define SHORT_SEND_BUFSIZE 1024
2906 if (nread
< headersize
) {
2907 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2908 "header for file %s (%s). Terminating\n",
2909 fsp_str_dbg(fsp
), strerror(errno
)));
2910 exit_server_cleanly("sendfile_short_send failed");
2913 nread
-= headersize
;
2915 if (nread
< smb_maxcnt
) {
2916 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
2918 exit_server_cleanly("sendfile_short_send: "
2922 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2923 "with zeros !\n", fsp_str_dbg(fsp
)));
2925 while (nread
< smb_maxcnt
) {
2927 * We asked for the real file size and told sendfile
2928 * to not go beyond the end of the file. But it can
2929 * happen that in between our fstat call and the
2930 * sendfile call the file was truncated. This is very
2931 * bad because we have already announced the larger
2932 * number of bytes to the client.
2934 * The best we can do now is to send 0-bytes, just as
2935 * a read from a hole in a sparse file would do.
2937 * This should happen rarely enough that I don't care
2938 * about efficiency here :-)
2942 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
2943 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
2945 char addr
[INET6_ADDRSTRLEN
];
2947 * Try and give an error message saying what
2950 DEBUG(0, ("write_data failed for client %s. "
2953 fsp
->conn
->sconn
->sock
, addr
,
2956 exit_server_cleanly("sendfile_short_send: "
2957 "write_data failed");
2965 /****************************************************************************
2966 Return a readbraw error (4 bytes of zero).
2967 ****************************************************************************/
2969 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
2975 smbd_lock_socket(sconn
);
2976 if (write_data(sconn
->sock
,header
,4) != 4) {
2977 char addr
[INET6_ADDRSTRLEN
];
2979 * Try and give an error message saying what
2982 DEBUG(0, ("write_data failed for client %s. "
2984 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
2989 smbd_unlock_socket(sconn
);
2992 /****************************************************************************
2993 Use sendfile in readbraw.
2994 ****************************************************************************/
2996 static void send_file_readbraw(connection_struct
*conn
,
2997 struct smb_request
*req
,
3003 struct smbd_server_connection
*sconn
= req
->sconn
;
3004 char *outbuf
= NULL
;
3008 * We can only use sendfile on a non-chained packet
3009 * but we can use on a non-oplocked file. tridge proved this
3010 * on a train in Germany :-). JRA.
3011 * reply_readbraw has already checked the length.
3014 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3015 (fsp
->wcp
== NULL
) &&
3016 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3017 ssize_t sendfile_read
= -1;
3019 DATA_BLOB header_blob
;
3021 _smb_setlen(header
,nread
);
3022 header_blob
= data_blob_const(header
, 4);
3024 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3025 &header_blob
, startpos
,
3027 if (sendfile_read
== -1) {
3028 /* Returning ENOSYS means no data at all was sent.
3029 * Do this as a normal read. */
3030 if (errno
== ENOSYS
) {
3031 goto normal_readbraw
;
3035 * Special hack for broken Linux with no working sendfile. If we
3036 * return EINTR we sent the header but not the rest of the data.
3037 * Fake this up by doing read/write calls.
3039 if (errno
== EINTR
) {
3040 /* Ensure we don't do this again. */
3041 set_use_sendfile(SNUM(conn
), False
);
3042 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3044 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3045 DEBUG(0,("send_file_readbraw: "
3046 "fake_sendfile failed for "
3050 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3055 DEBUG(0,("send_file_readbraw: sendfile failed for "
3056 "file %s (%s). Terminating\n",
3057 fsp_str_dbg(fsp
), strerror(errno
)));
3058 exit_server_cleanly("send_file_readbraw sendfile failed");
3059 } else if (sendfile_read
== 0) {
3061 * Some sendfile implementations return 0 to indicate
3062 * that there was a short read, but nothing was
3063 * actually written to the socket. In this case,
3064 * fallback to the normal read path so the header gets
3065 * the correct byte count.
3067 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3068 "bytes falling back to the normal read: "
3069 "%s\n", fsp_str_dbg(fsp
)));
3070 goto normal_readbraw
;
3073 /* Deal with possible short send. */
3074 if (sendfile_read
!= 4+nread
) {
3075 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3082 outbuf
= TALLOC_ARRAY(NULL
, char, nread
+4);
3084 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3085 (unsigned)(nread
+4)));
3086 reply_readbraw_error(sconn
);
3091 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3092 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3101 _smb_setlen(outbuf
,ret
);
3102 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3103 char addr
[INET6_ADDRSTRLEN
];
3105 * Try and give an error message saying what
3108 DEBUG(0, ("write_data failed for client %s. "
3110 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3117 TALLOC_FREE(outbuf
);
3120 /****************************************************************************
3121 Reply to a readbraw (core+ protocol).
3122 ****************************************************************************/
3124 void reply_readbraw(struct smb_request
*req
)
3126 connection_struct
*conn
= req
->conn
;
3127 struct smbd_server_connection
*sconn
= req
->sconn
;
3128 ssize_t maxcount
,mincount
;
3132 struct lock_struct lock
;
3135 START_PROFILE(SMBreadbraw
);
3137 if (srv_is_signing_active(sconn
) ||
3138 is_encrypted_packet(req
->inbuf
)) {
3139 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3140 "raw reads/writes are disallowed.");
3144 reply_readbraw_error(sconn
);
3145 END_PROFILE(SMBreadbraw
);
3149 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3150 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3151 "'async smb echo handler = yes'\n"));
3152 reply_readbraw_error(sconn
);
3153 END_PROFILE(SMBreadbraw
);
3158 * Special check if an oplock break has been issued
3159 * and the readraw request croses on the wire, we must
3160 * return a zero length response here.
3163 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3166 * We have to do a check_fsp by hand here, as
3167 * we must always return 4 zero bytes on error,
3171 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3172 req
->vuid
!= fsp
->vuid
||
3173 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3175 * fsp could be NULL here so use the value from the packet. JRA.
3177 DEBUG(3,("reply_readbraw: fnum %d not valid "
3179 (int)SVAL(req
->vwv
+0, 0)));
3180 reply_readbraw_error(sconn
);
3181 END_PROFILE(SMBreadbraw
);
3185 /* Do a "by hand" version of CHECK_READ. */
3186 if (!(fsp
->can_read
||
3187 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3188 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3189 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3190 (int)SVAL(req
->vwv
+0, 0)));
3191 reply_readbraw_error(sconn
);
3192 END_PROFILE(SMBreadbraw
);
3196 flush_write_cache(fsp
, READRAW_FLUSH
);
3198 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3199 if(req
->wct
== 10) {
3201 * This is a large offset (64 bit) read.
3203 #ifdef LARGE_SMB_OFF_T
3205 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+8, 0)) << 32);
3207 #else /* !LARGE_SMB_OFF_T */
3210 * Ensure we haven't been sent a >32 bit offset.
3213 if(IVAL(req
->vwv
+8, 0) != 0) {
3214 DEBUG(0,("reply_readbraw: large offset "
3215 "(%x << 32) used and we don't support "
3216 "64 bit offsets.\n",
3217 (unsigned int)IVAL(req
->vwv
+8, 0) ));
3218 reply_readbraw_error(sconn
);
3219 END_PROFILE(SMBreadbraw
);
3223 #endif /* LARGE_SMB_OFF_T */
3226 DEBUG(0,("reply_readbraw: negative 64 bit "
3227 "readraw offset (%.0f) !\n",
3228 (double)startpos
));
3229 reply_readbraw_error(sconn
);
3230 END_PROFILE(SMBreadbraw
);
3235 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3236 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3238 /* ensure we don't overrun the packet size */
3239 maxcount
= MIN(65535,maxcount
);
3241 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3242 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3245 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3246 reply_readbraw_error(sconn
);
3247 END_PROFILE(SMBreadbraw
);
3251 if (fsp_stat(fsp
) == 0) {
3252 size
= fsp
->fsp_name
->st
.st_ex_size
;
3255 if (startpos
>= size
) {
3258 nread
= MIN(maxcount
,(size
- startpos
));
3261 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3262 if (nread
< mincount
)
3266 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3267 "min=%lu nread=%lu\n",
3268 fsp
->fnum
, (double)startpos
,
3269 (unsigned long)maxcount
,
3270 (unsigned long)mincount
,
3271 (unsigned long)nread
) );
3273 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3275 DEBUG(5,("reply_readbraw finished\n"));
3277 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3279 END_PROFILE(SMBreadbraw
);
3284 #define DBGC_CLASS DBGC_LOCKING
3286 /****************************************************************************
3287 Reply to a lockread (core+ protocol).
3288 ****************************************************************************/
3290 void reply_lockread(struct smb_request
*req
)
3292 connection_struct
*conn
= req
->conn
;
3299 struct byte_range_lock
*br_lck
= NULL
;
3301 struct smbd_server_connection
*sconn
= req
->sconn
;
3303 START_PROFILE(SMBlockread
);
3306 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3307 END_PROFILE(SMBlockread
);
3311 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3313 if (!check_fsp(conn
, req
, fsp
)) {
3314 END_PROFILE(SMBlockread
);
3318 if (!CHECK_READ(fsp
,req
)) {
3319 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3320 END_PROFILE(SMBlockread
);
3324 numtoread
= SVAL(req
->vwv
+1, 0);
3325 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3327 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3329 reply_outbuf(req
, 5, numtoread
+ 3);
3331 data
= smb_buf(req
->outbuf
) + 3;
3334 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3335 * protocol request that predates the read/write lock concept.
3336 * Thus instead of asking for a read lock here we need to ask
3337 * for a write lock. JRA.
3338 * Note that the requested lock size is unaffected by max_recv.
3341 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3343 (uint64_t)req
->smbpid
,
3344 (uint64_t)numtoread
,
3348 False
, /* Non-blocking lock. */
3352 TALLOC_FREE(br_lck
);
3354 if (NT_STATUS_V(status
)) {
3355 reply_nterror(req
, status
);
3356 END_PROFILE(SMBlockread
);
3361 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3364 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3365 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3366 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3367 (unsigned int)numtoread
,
3368 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3369 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3371 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3374 reply_nterror(req
, map_nt_error_from_unix(errno
));
3375 END_PROFILE(SMBlockread
);
3379 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3381 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3382 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3383 p
= smb_buf(req
->outbuf
);
3384 SCVAL(p
,0,0); /* pad byte. */
3387 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3388 fsp
->fnum
, (int)numtoread
, (int)nread
));
3390 END_PROFILE(SMBlockread
);
3395 #define DBGC_CLASS DBGC_ALL
3397 /****************************************************************************
3399 ****************************************************************************/
3401 void reply_read(struct smb_request
*req
)
3403 connection_struct
*conn
= req
->conn
;
3410 struct lock_struct lock
;
3411 struct smbd_server_connection
*sconn
= req
->sconn
;
3413 START_PROFILE(SMBread
);
3416 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3417 END_PROFILE(SMBread
);
3421 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3423 if (!check_fsp(conn
, req
, fsp
)) {
3424 END_PROFILE(SMBread
);
3428 if (!CHECK_READ(fsp
,req
)) {
3429 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3430 END_PROFILE(SMBread
);
3434 numtoread
= SVAL(req
->vwv
+1, 0);
3435 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3437 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3440 * The requested read size cannot be greater than max_recv. JRA.
3442 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3443 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3444 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3445 (unsigned int)numtoread
,
3446 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3447 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3450 reply_outbuf(req
, 5, numtoread
+3);
3452 data
= smb_buf(req
->outbuf
) + 3;
3454 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3455 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3458 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3459 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3460 END_PROFILE(SMBread
);
3465 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3468 reply_nterror(req
, map_nt_error_from_unix(errno
));
3472 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3474 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3475 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3476 SCVAL(smb_buf(req
->outbuf
),0,1);
3477 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3479 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3480 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3483 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3485 END_PROFILE(SMBread
);
3489 /****************************************************************************
3491 ****************************************************************************/
3493 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3499 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3500 data
= smb_buf(outbuf
);
3502 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3504 SCVAL(outbuf
,smb_vwv0
,0xFF);
3505 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3506 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3507 SSVAL(outbuf
,smb_vwv6
,
3509 + 1 /* the wct field */
3510 + 12 * sizeof(uint16_t) /* vwv */
3511 + 2); /* the buflen field */
3512 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3513 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3514 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3515 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3519 /****************************************************************************
3520 Reply to a read and X - possibly using sendfile.
3521 ****************************************************************************/
3523 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3524 files_struct
*fsp
, SMB_OFF_T startpos
,
3528 struct lock_struct lock
;
3529 int saved_errno
= 0;
3531 if(fsp_stat(fsp
) == -1) {
3532 reply_nterror(req
, map_nt_error_from_unix(errno
));
3536 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3537 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3540 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3541 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3545 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3546 (startpos
> fsp
->fsp_name
->st
.st_ex_size
)
3547 || (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3549 * We already know that we would do a short read, so don't
3550 * try the sendfile() path.
3552 goto nosendfile_read
;
3556 * We can only use sendfile on a non-chained packet
3557 * but we can use on a non-oplocked file. tridge proved this
3558 * on a train in Germany :-). JRA.
3561 if (!req_is_in_chain(req
) &&
3562 !is_encrypted_packet(req
->inbuf
) && (fsp
->base_fsp
== NULL
) &&
3563 (fsp
->wcp
== NULL
) &&
3564 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3565 uint8 headerbuf
[smb_size
+ 12 * 2];
3569 * Set up the packet header before send. We
3570 * assume here the sendfile will work (get the
3571 * correct amount of data).
3574 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3576 construct_reply_common_req(req
, (char *)headerbuf
);
3577 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3579 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3580 startpos
, smb_maxcnt
);
3582 /* Returning ENOSYS means no data at all was sent.
3583 Do this as a normal read. */
3584 if (errno
== ENOSYS
) {
3589 * Special hack for broken Linux with no working sendfile. If we
3590 * return EINTR we sent the header but not the rest of the data.
3591 * Fake this up by doing read/write calls.
3594 if (errno
== EINTR
) {
3595 /* Ensure we don't do this again. */
3596 set_use_sendfile(SNUM(conn
), False
);
3597 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3598 nread
= fake_sendfile(fsp
, startpos
,
3601 DEBUG(0,("send_file_readX: "
3602 "fake_sendfile failed for "
3606 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3608 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3609 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3610 /* No outbuf here means successful sendfile. */
3614 DEBUG(0,("send_file_readX: sendfile failed for file "
3615 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3617 exit_server_cleanly("send_file_readX sendfile failed");
3618 } else if (nread
== 0) {
3620 * Some sendfile implementations return 0 to indicate
3621 * that there was a short read, but nothing was
3622 * actually written to the socket. In this case,
3623 * fallback to the normal read path so the header gets
3624 * the correct byte count.
3626 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3627 "falling back to the normal read: %s\n",
3632 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3633 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3635 /* Deal with possible short send. */
3636 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3637 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3639 /* No outbuf here means successful sendfile. */
3640 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3641 SMB_PERFCOUNT_END(&req
->pcd
);
3647 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3648 uint8 headerbuf
[smb_size
+ 2*12];
3650 construct_reply_common_req(req
, (char *)headerbuf
);
3651 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3653 /* Send out the header. */
3654 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3655 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3657 char addr
[INET6_ADDRSTRLEN
];
3659 * Try and give an error message saying what
3662 DEBUG(0, ("write_data failed for client %s. "
3664 get_peer_addr(req
->sconn
->sock
, addr
,
3668 DEBUG(0,("send_file_readX: write_data failed for file "
3669 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3671 exit_server_cleanly("send_file_readX sendfile failed");
3673 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3675 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3676 "file %s (%s).\n", fsp_str_dbg(fsp
),
3678 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3685 reply_outbuf(req
, 12, smb_maxcnt
);
3687 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3688 saved_errno
= errno
;
3690 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3693 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3697 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3699 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3700 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3706 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3707 TALLOC_FREE(req
->outbuf
);
3711 /****************************************************************************
3712 Reply to a read and X.
3713 ****************************************************************************/
3715 void reply_read_and_X(struct smb_request
*req
)
3717 connection_struct
*conn
= req
->conn
;
3721 bool big_readX
= False
;
3723 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3726 START_PROFILE(SMBreadX
);
3728 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3729 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3733 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3734 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3735 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3737 /* If it's an IPC, pass off the pipe handler. */
3739 reply_pipe_read_and_X(req
);
3740 END_PROFILE(SMBreadX
);
3744 if (!check_fsp(conn
, req
, fsp
)) {
3745 END_PROFILE(SMBreadX
);
3749 if (!CHECK_READ(fsp
,req
)) {
3750 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3751 END_PROFILE(SMBreadX
);
3755 if (global_client_caps
& CAP_LARGE_READX
) {
3756 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3757 smb_maxcnt
|= (upper_size
<<16);
3758 if (upper_size
> 1) {
3759 /* Can't do this on a chained packet. */
3760 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3761 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3762 END_PROFILE(SMBreadX
);
3765 /* We currently don't do this on signed or sealed data. */
3766 if (srv_is_signing_active(req
->sconn
) ||
3767 is_encrypted_packet(req
->inbuf
)) {
3768 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3769 END_PROFILE(SMBreadX
);
3772 /* Is there room in the reply for this data ? */
3773 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3775 NT_STATUS_INVALID_PARAMETER
);
3776 END_PROFILE(SMBreadX
);
3783 if (req
->wct
== 12) {
3784 #ifdef LARGE_SMB_OFF_T
3786 * This is a large offset (64 bit) read.
3788 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+10, 0)) << 32);
3790 #else /* !LARGE_SMB_OFF_T */
3793 * Ensure we haven't been sent a >32 bit offset.
3796 if(IVAL(req
->vwv
+10, 0) != 0) {
3797 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3798 "used and we don't support 64 bit offsets.\n",
3799 (unsigned int)IVAL(req
->vwv
+10, 0) ));
3800 END_PROFILE(SMBreadX
);
3801 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3805 #endif /* LARGE_SMB_OFF_T */
3810 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3815 if (NT_STATUS_IS_OK(status
)) {
3816 /* Read scheduled - we're done. */
3819 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3820 /* Real error - report to client. */
3821 END_PROFILE(SMBreadX
);
3822 reply_nterror(req
, status
);
3825 /* NT_STATUS_RETRY - fall back to sync read. */
3828 smbd_lock_socket(req
->sconn
);
3829 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3830 smbd_unlock_socket(req
->sconn
);
3833 END_PROFILE(SMBreadX
);
3837 /****************************************************************************
3838 Error replies to writebraw must have smb_wct == 1. Fix this up.
3839 ****************************************************************************/
3841 void error_to_writebrawerr(struct smb_request
*req
)
3843 uint8
*old_outbuf
= req
->outbuf
;
3845 reply_outbuf(req
, 1, 0);
3847 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3848 TALLOC_FREE(old_outbuf
);
3851 /****************************************************************************
3852 Read 4 bytes of a smb packet and return the smb length of the packet.
3853 Store the result in the buffer. This version of the function will
3854 never return a session keepalive (length of zero).
3855 Timeout is in milliseconds.
3856 ****************************************************************************/
3858 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3861 uint8_t msgtype
= SMBkeepalive
;
3863 while (msgtype
== SMBkeepalive
) {
3866 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3868 if (!NT_STATUS_IS_OK(status
)) {
3869 char addr
[INET6_ADDRSTRLEN
];
3870 /* Try and give an error message
3871 * saying what client failed. */
3872 DEBUG(0, ("read_fd_with_timeout failed for "
3873 "client %s read error = %s.\n",
3874 get_peer_addr(fd
,addr
,sizeof(addr
)),
3875 nt_errstr(status
)));
3879 msgtype
= CVAL(inbuf
, 0);
3882 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3883 (unsigned long)len
));
3885 return NT_STATUS_OK
;
3888 /****************************************************************************
3889 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3890 ****************************************************************************/
3892 void reply_writebraw(struct smb_request
*req
)
3894 connection_struct
*conn
= req
->conn
;
3897 ssize_t total_written
=0;
3898 size_t numtowrite
=0;
3904 struct lock_struct lock
;
3907 START_PROFILE(SMBwritebraw
);
3910 * If we ever reply with an error, it must have the SMB command
3911 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3914 SCVAL(req
->inbuf
,smb_com
,SMBwritec
);
3916 if (srv_is_signing_active(req
->sconn
)) {
3917 END_PROFILE(SMBwritebraw
);
3918 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3919 "raw reads/writes are disallowed.");
3922 if (req
->wct
< 12) {
3923 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3924 error_to_writebrawerr(req
);
3925 END_PROFILE(SMBwritebraw
);
3929 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3930 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3931 "'async smb echo handler = yes'\n"));
3932 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3933 error_to_writebrawerr(req
);
3934 END_PROFILE(SMBwritebraw
);
3938 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3939 if (!check_fsp(conn
, req
, fsp
)) {
3940 error_to_writebrawerr(req
);
3941 END_PROFILE(SMBwritebraw
);
3945 if (!CHECK_WRITE(fsp
)) {
3946 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3947 error_to_writebrawerr(req
);
3948 END_PROFILE(SMBwritebraw
);
3952 tcount
= IVAL(req
->vwv
+1, 0);
3953 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3954 write_through
= BITSETW(req
->vwv
+7,0);
3956 /* We have to deal with slightly different formats depending
3957 on whether we are using the core+ or lanman1.0 protocol */
3959 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
3960 numtowrite
= SVAL(smb_buf(req
->inbuf
),-2);
3961 data
= smb_buf(req
->inbuf
);
3963 numtowrite
= SVAL(req
->vwv
+10, 0);
3964 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3967 /* Ensure we don't write bytes past the end of this packet. */
3968 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3969 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3970 error_to_writebrawerr(req
);
3971 END_PROFILE(SMBwritebraw
);
3975 if (!fsp
->print_file
) {
3976 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3977 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
3980 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3981 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3982 error_to_writebrawerr(req
);
3983 END_PROFILE(SMBwritebraw
);
3989 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3992 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3993 "wrote=%d sync=%d\n",
3994 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3995 (int)nwritten
, (int)write_through
));
3997 if (nwritten
< (ssize_t
)numtowrite
) {
3998 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3999 error_to_writebrawerr(req
);
4003 total_written
= nwritten
;
4005 /* Allocate a buffer of 64k + length. */
4006 buf
= TALLOC_ARRAY(NULL
, char, 65540);
4008 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4009 error_to_writebrawerr(req
);
4013 /* Return a SMBwritebraw message to the redirector to tell
4014 * it to send more bytes */
4016 memcpy(buf
, req
->inbuf
, smb_size
);
4017 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4018 SCVAL(buf
,smb_com
,SMBwritebraw
);
4019 SSVALS(buf
,smb_vwv0
,0xFFFF);
4021 if (!srv_send_smb(req
->sconn
,
4023 false, 0, /* no signing */
4024 IS_CONN_ENCRYPTED(conn
),
4026 exit_server_cleanly("reply_writebraw: srv_send_smb "
4030 /* Now read the raw data into the buffer and write it */
4031 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4033 if (!NT_STATUS_IS_OK(status
)) {
4034 exit_server_cleanly("secondary writebraw failed");
4037 /* Set up outbuf to return the correct size */
4038 reply_outbuf(req
, 1, 0);
4040 if (numtowrite
!= 0) {
4042 if (numtowrite
> 0xFFFF) {
4043 DEBUG(0,("reply_writebraw: Oversize secondary write "
4044 "raw requested (%u). Terminating\n",
4045 (unsigned int)numtowrite
));
4046 exit_server_cleanly("secondary writebraw failed");
4049 if (tcount
> nwritten
+numtowrite
) {
4050 DEBUG(3,("reply_writebraw: Client overestimated the "
4052 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4055 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4057 if (!NT_STATUS_IS_OK(status
)) {
4058 char addr
[INET6_ADDRSTRLEN
];
4059 /* Try and give an error message
4060 * saying what client failed. */
4061 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4062 "raw read failed (%s) for client %s. "
4063 "Terminating\n", nt_errstr(status
),
4064 get_peer_addr(req
->sconn
->sock
, addr
,
4066 exit_server_cleanly("secondary writebraw failed");
4069 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4070 if (nwritten
== -1) {
4072 reply_nterror(req
, map_nt_error_from_unix(errno
));
4073 error_to_writebrawerr(req
);
4077 if (nwritten
< (ssize_t
)numtowrite
) {
4078 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4079 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4083 total_written
+= nwritten
;
4088 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4090 status
= sync_file(conn
, fsp
, write_through
);
4091 if (!NT_STATUS_IS_OK(status
)) {
4092 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4093 fsp_str_dbg(fsp
), nt_errstr(status
)));
4094 reply_nterror(req
, status
);
4095 error_to_writebrawerr(req
);
4099 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4101 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4102 (int)total_written
));
4104 if (!fsp
->print_file
) {
4105 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4108 /* We won't return a status if write through is not selected - this
4109 * follows what WfWg does */
4110 END_PROFILE(SMBwritebraw
);
4112 if (!write_through
&& total_written
==tcount
) {
4114 #if RABBIT_PELLET_FIX
4116 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4117 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4120 if (!send_keepalive(req
->sconn
->sock
)) {
4121 exit_server_cleanly("reply_writebraw: send of "
4122 "keepalive failed");
4125 TALLOC_FREE(req
->outbuf
);
4130 if (!fsp
->print_file
) {
4131 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4134 END_PROFILE(SMBwritebraw
);
4139 #define DBGC_CLASS DBGC_LOCKING
4141 /****************************************************************************
4142 Reply to a writeunlock (core+).
4143 ****************************************************************************/
4145 void reply_writeunlock(struct smb_request
*req
)
4147 connection_struct
*conn
= req
->conn
;
4148 ssize_t nwritten
= -1;
4152 NTSTATUS status
= NT_STATUS_OK
;
4154 struct lock_struct lock
;
4155 int saved_errno
= 0;
4157 START_PROFILE(SMBwriteunlock
);
4160 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4161 END_PROFILE(SMBwriteunlock
);
4165 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4167 if (!check_fsp(conn
, req
, fsp
)) {
4168 END_PROFILE(SMBwriteunlock
);
4172 if (!CHECK_WRITE(fsp
)) {
4173 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4174 END_PROFILE(SMBwriteunlock
);
4178 numtowrite
= SVAL(req
->vwv
+1, 0);
4179 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4180 data
= (const char *)req
->buf
+ 3;
4182 if (!fsp
->print_file
&& numtowrite
> 0) {
4183 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4184 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4187 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4188 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4189 END_PROFILE(SMBwriteunlock
);
4194 /* The special X/Open SMB protocol handling of
4195 zero length writes is *NOT* done for
4197 if(numtowrite
== 0) {
4200 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4201 saved_errno
= errno
;
4204 status
= sync_file(conn
, fsp
, False
/* write through */);
4205 if (!NT_STATUS_IS_OK(status
)) {
4206 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4207 fsp_str_dbg(fsp
), nt_errstr(status
)));
4208 reply_nterror(req
, status
);
4213 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4217 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4218 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4222 if (numtowrite
&& !fsp
->print_file
) {
4223 status
= do_unlock(req
->sconn
->msg_ctx
,
4225 (uint64_t)req
->smbpid
,
4226 (uint64_t)numtowrite
,
4230 if (NT_STATUS_V(status
)) {
4231 reply_nterror(req
, status
);
4236 reply_outbuf(req
, 1, 0);
4238 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4240 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4241 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4244 if (numtowrite
&& !fsp
->print_file
) {
4245 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4248 END_PROFILE(SMBwriteunlock
);
4253 #define DBGC_CLASS DBGC_ALL
4255 /****************************************************************************
4257 ****************************************************************************/
4259 void reply_write(struct smb_request
*req
)
4261 connection_struct
*conn
= req
->conn
;
4263 ssize_t nwritten
= -1;
4267 struct lock_struct lock
;
4269 int saved_errno
= 0;
4271 START_PROFILE(SMBwrite
);
4274 END_PROFILE(SMBwrite
);
4275 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4279 /* If it's an IPC, pass off the pipe handler. */
4281 reply_pipe_write(req
);
4282 END_PROFILE(SMBwrite
);
4286 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4288 if (!check_fsp(conn
, req
, fsp
)) {
4289 END_PROFILE(SMBwrite
);
4293 if (!CHECK_WRITE(fsp
)) {
4294 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4295 END_PROFILE(SMBwrite
);
4299 numtowrite
= SVAL(req
->vwv
+1, 0);
4300 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4301 data
= (const char *)req
->buf
+ 3;
4303 if (!fsp
->print_file
) {
4304 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4305 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4308 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4309 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4310 END_PROFILE(SMBwrite
);
4316 * X/Open SMB protocol says that if smb_vwv1 is
4317 * zero then the file size should be extended or
4318 * truncated to the size given in smb_vwv[2-3].
4321 if(numtowrite
== 0) {
4323 * This is actually an allocate call, and set EOF. JRA.
4325 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
4327 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4330 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
4332 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4335 trigger_write_time_update_immediate(fsp
);
4337 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4340 status
= sync_file(conn
, fsp
, False
);
4341 if (!NT_STATUS_IS_OK(status
)) {
4342 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4343 fsp_str_dbg(fsp
), nt_errstr(status
)));
4344 reply_nterror(req
, status
);
4349 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4353 if((nwritten
== 0) && (numtowrite
!= 0)) {
4354 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4358 reply_outbuf(req
, 1, 0);
4360 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4362 if (nwritten
< (ssize_t
)numtowrite
) {
4363 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4364 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4367 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4370 if (!fsp
->print_file
) {
4371 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4374 END_PROFILE(SMBwrite
);
4378 /****************************************************************************
4379 Ensure a buffer is a valid writeX for recvfile purposes.
4380 ****************************************************************************/
4382 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4383 (2*14) + /* word count (including bcc) */ \
4386 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4387 const uint8_t *inbuf
)
4390 connection_struct
*conn
= NULL
;
4391 unsigned int doff
= 0;
4392 size_t len
= smb_len_large(inbuf
);
4394 if (is_encrypted_packet(inbuf
)) {
4395 /* Can't do this on encrypted
4400 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4404 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4405 CVAL(inbuf
,smb_wct
) != 14) {
4406 DEBUG(10,("is_valid_writeX_buffer: chained or "
4407 "invalid word length.\n"));
4411 conn
= conn_find(sconn
, SVAL(inbuf
, smb_tid
));
4413 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4417 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4420 if (IS_PRINT(conn
)) {
4421 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4424 doff
= SVAL(inbuf
,smb_vwv11
);
4426 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4428 if (len
> doff
&& len
- doff
> 0xFFFF) {
4429 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4432 if (numtowrite
== 0) {
4433 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4437 /* Ensure the sizes match up. */
4438 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4439 /* no pad byte...old smbclient :-( */
4440 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4442 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4446 if (len
- doff
!= numtowrite
) {
4447 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4448 "len = %u, doff = %u, numtowrite = %u\n",
4451 (unsigned int)numtowrite
));
4455 DEBUG(10,("is_valid_writeX_buffer: true "
4456 "len = %u, doff = %u, numtowrite = %u\n",
4459 (unsigned int)numtowrite
));
4464 /****************************************************************************
4465 Reply to a write and X.
4466 ****************************************************************************/
4468 void reply_write_and_X(struct smb_request
*req
)
4470 connection_struct
*conn
= req
->conn
;
4472 struct lock_struct lock
;
4477 unsigned int smb_doff
;
4478 unsigned int smblen
;
4481 int saved_errno
= 0;
4483 START_PROFILE(SMBwriteX
);
4485 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4486 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4487 END_PROFILE(SMBwriteX
);
4491 numtowrite
= SVAL(req
->vwv
+10, 0);
4492 smb_doff
= SVAL(req
->vwv
+11, 0);
4493 smblen
= smb_len(req
->inbuf
);
4495 if (req
->unread_bytes
> 0xFFFF ||
4496 (smblen
> smb_doff
&&
4497 smblen
- smb_doff
> 0xFFFF)) {
4498 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4501 if (req
->unread_bytes
) {
4502 /* Can't do a recvfile write on IPC$ */
4504 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4505 END_PROFILE(SMBwriteX
);
4508 if (numtowrite
!= req
->unread_bytes
) {
4509 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4510 END_PROFILE(SMBwriteX
);
4514 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4515 smb_doff
+ numtowrite
> smblen
) {
4516 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4517 END_PROFILE(SMBwriteX
);
4522 /* If it's an IPC, pass off the pipe handler. */
4524 if (req
->unread_bytes
) {
4525 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4526 END_PROFILE(SMBwriteX
);
4529 reply_pipe_write_and_X(req
);
4530 END_PROFILE(SMBwriteX
);
4534 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4535 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4536 write_through
= BITSETW(req
->vwv
+7,0);
4538 if (!check_fsp(conn
, req
, fsp
)) {
4539 END_PROFILE(SMBwriteX
);
4543 if (!CHECK_WRITE(fsp
)) {
4544 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4545 END_PROFILE(SMBwriteX
);
4549 data
= smb_base(req
->inbuf
) + smb_doff
;
4551 if(req
->wct
== 14) {
4552 #ifdef LARGE_SMB_OFF_T
4554 * This is a large offset (64 bit) write.
4556 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+12, 0)) << 32);
4558 #else /* !LARGE_SMB_OFF_T */
4561 * Ensure we haven't been sent a >32 bit offset.
4564 if(IVAL(req
->vwv
+12, 0) != 0) {
4565 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4566 "used and we don't support 64 bit offsets.\n",
4567 (unsigned int)IVAL(req
->vwv
+12, 0) ));
4568 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4569 END_PROFILE(SMBwriteX
);
4573 #endif /* LARGE_SMB_OFF_T */
4576 /* X/Open SMB protocol says that, unlike SMBwrite
4577 if the length is zero then NO truncation is
4578 done, just a write of zero. To truncate a file,
4581 if(numtowrite
== 0) {
4584 if (req
->unread_bytes
== 0) {
4585 status
= schedule_aio_write_and_X(conn
,
4592 if (NT_STATUS_IS_OK(status
)) {
4593 /* write scheduled - we're done. */
4596 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4597 /* Real error - report to client. */
4598 reply_nterror(req
, status
);
4601 /* NT_STATUS_RETRY - fall through to sync write. */
4604 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4605 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4608 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4609 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4613 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4614 saved_errno
= errno
;
4616 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4620 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4624 if((nwritten
== 0) && (numtowrite
!= 0)) {
4625 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4629 reply_outbuf(req
, 6, 0);
4630 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4631 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4633 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4634 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4636 status
= sync_file(conn
, fsp
, write_through
);
4637 if (!NT_STATUS_IS_OK(status
)) {
4638 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4639 fsp_str_dbg(fsp
), nt_errstr(status
)));
4640 reply_nterror(req
, status
);
4644 END_PROFILE(SMBwriteX
);
4649 END_PROFILE(SMBwriteX
);
4653 /****************************************************************************
4655 ****************************************************************************/
4657 void reply_lseek(struct smb_request
*req
)
4659 connection_struct
*conn
= req
->conn
;
4665 START_PROFILE(SMBlseek
);
4668 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4669 END_PROFILE(SMBlseek
);
4673 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4675 if (!check_fsp(conn
, req
, fsp
)) {
4679 flush_write_cache(fsp
, SEEK_FLUSH
);
4681 mode
= SVAL(req
->vwv
+1, 0) & 3;
4682 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4683 startpos
= (SMB_OFF_T
)IVALS(req
->vwv
+2, 0);
4692 res
= fsp
->fh
->pos
+ startpos
;
4703 if (umode
== SEEK_END
) {
4704 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4705 if(errno
== EINVAL
) {
4706 SMB_OFF_T current_pos
= startpos
;
4708 if(fsp_stat(fsp
) == -1) {
4710 map_nt_error_from_unix(errno
));
4711 END_PROFILE(SMBlseek
);
4715 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4717 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4722 reply_nterror(req
, map_nt_error_from_unix(errno
));
4723 END_PROFILE(SMBlseek
);
4730 reply_outbuf(req
, 2, 0);
4731 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4733 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4734 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4736 END_PROFILE(SMBlseek
);
4740 /****************************************************************************
4742 ****************************************************************************/
4744 void reply_flush(struct smb_request
*req
)
4746 connection_struct
*conn
= req
->conn
;
4750 START_PROFILE(SMBflush
);
4753 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4757 fnum
= SVAL(req
->vwv
+0, 0);
4758 fsp
= file_fsp(req
, fnum
);
4760 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4765 file_sync_all(conn
);
4767 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4768 if (!NT_STATUS_IS_OK(status
)) {
4769 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4770 fsp_str_dbg(fsp
), nt_errstr(status
)));
4771 reply_nterror(req
, status
);
4772 END_PROFILE(SMBflush
);
4777 reply_outbuf(req
, 0, 0);
4779 DEBUG(3,("flush\n"));
4780 END_PROFILE(SMBflush
);
4784 /****************************************************************************
4786 conn POINTER CAN BE NULL HERE !
4787 ****************************************************************************/
4789 void reply_exit(struct smb_request
*req
)
4791 START_PROFILE(SMBexit
);
4793 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
4795 reply_outbuf(req
, 0, 0);
4797 DEBUG(3,("exit\n"));
4799 END_PROFILE(SMBexit
);
4803 /****************************************************************************
4804 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4805 ****************************************************************************/
4807 void reply_close(struct smb_request
*req
)
4809 connection_struct
*conn
= req
->conn
;
4810 NTSTATUS status
= NT_STATUS_OK
;
4811 files_struct
*fsp
= NULL
;
4812 START_PROFILE(SMBclose
);
4815 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4816 END_PROFILE(SMBclose
);
4820 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4823 * We can only use check_fsp if we know it's not a directory.
4826 if (!check_fsp_open(conn
, req
, fsp
)) {
4827 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4828 END_PROFILE(SMBclose
);
4832 if(fsp
->is_directory
) {
4834 * Special case - close NT SMB directory handle.
4836 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4837 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4841 * Close ordinary file.
4844 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4845 fsp
->fh
->fd
, fsp
->fnum
,
4846 conn
->num_files_open
));
4849 * Take care of any time sent in the close.
4852 t
= srv_make_unix_date3(req
->vwv
+1);
4853 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4856 * close_file() returns the unix errno if an error
4857 * was detected on close - normally this is due to
4858 * a disk full error. If not then it was probably an I/O error.
4861 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4864 if (!NT_STATUS_IS_OK(status
)) {
4865 reply_nterror(req
, status
);
4866 END_PROFILE(SMBclose
);
4870 reply_outbuf(req
, 0, 0);
4871 END_PROFILE(SMBclose
);
4875 /****************************************************************************
4876 Reply to a writeclose (Core+ protocol).
4877 ****************************************************************************/
4879 void reply_writeclose(struct smb_request
*req
)
4881 connection_struct
*conn
= req
->conn
;
4883 ssize_t nwritten
= -1;
4884 NTSTATUS close_status
= NT_STATUS_OK
;
4887 struct timespec mtime
;
4889 struct lock_struct lock
;
4891 START_PROFILE(SMBwriteclose
);
4894 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4895 END_PROFILE(SMBwriteclose
);
4899 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4901 if (!check_fsp(conn
, req
, fsp
)) {
4902 END_PROFILE(SMBwriteclose
);
4905 if (!CHECK_WRITE(fsp
)) {
4906 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4907 END_PROFILE(SMBwriteclose
);
4911 numtowrite
= SVAL(req
->vwv
+1, 0);
4912 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4913 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4914 data
= (const char *)req
->buf
+ 1;
4916 if (!fsp
->print_file
) {
4917 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4918 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4921 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4922 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4923 END_PROFILE(SMBwriteclose
);
4928 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4930 set_close_write_time(fsp
, mtime
);
4933 * More insanity. W2K only closes the file if writelen > 0.
4938 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4939 "file %s\n", fsp_str_dbg(fsp
)));
4940 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4943 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4944 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4945 conn
->num_files_open
));
4947 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4948 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4952 if(!NT_STATUS_IS_OK(close_status
)) {
4953 reply_nterror(req
, close_status
);
4957 reply_outbuf(req
, 1, 0);
4959 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4962 if (numtowrite
&& !fsp
->print_file
) {
4963 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4966 END_PROFILE(SMBwriteclose
);
4971 #define DBGC_CLASS DBGC_LOCKING
4973 /****************************************************************************
4975 ****************************************************************************/
4977 void reply_lock(struct smb_request
*req
)
4979 connection_struct
*conn
= req
->conn
;
4980 uint64_t count
,offset
;
4983 struct byte_range_lock
*br_lck
= NULL
;
4985 START_PROFILE(SMBlock
);
4988 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4989 END_PROFILE(SMBlock
);
4993 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4995 if (!check_fsp(conn
, req
, fsp
)) {
4996 END_PROFILE(SMBlock
);
5000 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5001 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5003 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5004 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
5006 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5008 (uint64_t)req
->smbpid
,
5013 False
, /* Non-blocking lock. */
5018 TALLOC_FREE(br_lck
);
5020 if (NT_STATUS_V(status
)) {
5021 reply_nterror(req
, status
);
5022 END_PROFILE(SMBlock
);
5026 reply_outbuf(req
, 0, 0);
5028 END_PROFILE(SMBlock
);
5032 /****************************************************************************
5034 ****************************************************************************/
5036 void reply_unlock(struct smb_request
*req
)
5038 connection_struct
*conn
= req
->conn
;
5039 uint64_t count
,offset
;
5043 START_PROFILE(SMBunlock
);
5046 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5047 END_PROFILE(SMBunlock
);
5051 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5053 if (!check_fsp(conn
, req
, fsp
)) {
5054 END_PROFILE(SMBunlock
);
5058 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5059 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5061 status
= do_unlock(req
->sconn
->msg_ctx
,
5063 (uint64_t)req
->smbpid
,
5068 if (NT_STATUS_V(status
)) {
5069 reply_nterror(req
, status
);
5070 END_PROFILE(SMBunlock
);
5074 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5075 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
5077 reply_outbuf(req
, 0, 0);
5079 END_PROFILE(SMBunlock
);
5084 #define DBGC_CLASS DBGC_ALL
5086 /****************************************************************************
5088 conn POINTER CAN BE NULL HERE !
5089 ****************************************************************************/
5091 void reply_tdis(struct smb_request
*req
)
5093 connection_struct
*conn
= req
->conn
;
5094 START_PROFILE(SMBtdis
);
5097 DEBUG(4,("Invalid connection in tdis\n"));
5098 reply_nterror(req
, NT_STATUS_NETWORK_NAME_DELETED
);
5099 END_PROFILE(SMBtdis
);
5105 close_cnum(conn
,req
->vuid
);
5108 reply_outbuf(req
, 0, 0);
5109 END_PROFILE(SMBtdis
);
5113 /****************************************************************************
5115 conn POINTER CAN BE NULL HERE !
5116 ****************************************************************************/
5118 void reply_echo(struct smb_request
*req
)
5120 connection_struct
*conn
= req
->conn
;
5121 struct smb_perfcount_data local_pcd
;
5122 struct smb_perfcount_data
*cur_pcd
;
5126 START_PROFILE(SMBecho
);
5128 smb_init_perfcount_data(&local_pcd
);
5131 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5132 END_PROFILE(SMBecho
);
5136 smb_reverb
= SVAL(req
->vwv
+0, 0);
5138 reply_outbuf(req
, 1, req
->buflen
);
5140 /* copy any incoming data back out */
5141 if (req
->buflen
> 0) {
5142 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5145 if (smb_reverb
> 100) {
5146 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5150 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5152 /* this makes sure we catch the request pcd */
5153 if (seq_num
== smb_reverb
) {
5154 cur_pcd
= &req
->pcd
;
5156 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5157 cur_pcd
= &local_pcd
;
5160 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5162 show_msg((char *)req
->outbuf
);
5163 if (!srv_send_smb(req
->sconn
,
5164 (char *)req
->outbuf
,
5165 true, req
->seqnum
+1,
5166 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5168 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5171 DEBUG(3,("echo %d times\n", smb_reverb
));
5173 TALLOC_FREE(req
->outbuf
);
5175 END_PROFILE(SMBecho
);
5179 /****************************************************************************
5180 Reply to a printopen.
5181 ****************************************************************************/
5183 void reply_printopen(struct smb_request
*req
)
5185 connection_struct
*conn
= req
->conn
;
5189 START_PROFILE(SMBsplopen
);
5192 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5193 END_PROFILE(SMBsplopen
);
5197 if (!CAN_PRINT(conn
)) {
5198 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5199 END_PROFILE(SMBsplopen
);
5203 status
= file_new(req
, conn
, &fsp
);
5204 if(!NT_STATUS_IS_OK(status
)) {
5205 reply_nterror(req
, status
);
5206 END_PROFILE(SMBsplopen
);
5210 /* Open for exclusive use, write only. */
5211 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5213 if (!NT_STATUS_IS_OK(status
)) {
5214 file_free(req
, fsp
);
5215 reply_nterror(req
, status
);
5216 END_PROFILE(SMBsplopen
);
5220 reply_outbuf(req
, 1, 0);
5221 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5223 DEBUG(3,("openprint fd=%d fnum=%d\n",
5224 fsp
->fh
->fd
, fsp
->fnum
));
5226 END_PROFILE(SMBsplopen
);
5230 /****************************************************************************
5231 Reply to a printclose.
5232 ****************************************************************************/
5234 void reply_printclose(struct smb_request
*req
)
5236 connection_struct
*conn
= req
->conn
;
5240 START_PROFILE(SMBsplclose
);
5243 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5244 END_PROFILE(SMBsplclose
);
5248 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5250 if (!check_fsp(conn
, req
, fsp
)) {
5251 END_PROFILE(SMBsplclose
);
5255 if (!CAN_PRINT(conn
)) {
5256 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5257 END_PROFILE(SMBsplclose
);
5261 DEBUG(3,("printclose fd=%d fnum=%d\n",
5262 fsp
->fh
->fd
,fsp
->fnum
));
5264 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5266 if(!NT_STATUS_IS_OK(status
)) {
5267 reply_nterror(req
, status
);
5268 END_PROFILE(SMBsplclose
);
5272 reply_outbuf(req
, 0, 0);
5274 END_PROFILE(SMBsplclose
);
5278 /****************************************************************************
5279 Reply to a printqueue.
5280 ****************************************************************************/
5282 void reply_printqueue(struct smb_request
*req
)
5284 connection_struct
*conn
= req
->conn
;
5288 START_PROFILE(SMBsplretq
);
5291 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5292 END_PROFILE(SMBsplretq
);
5296 max_count
= SVAL(req
->vwv
+0, 0);
5297 start_index
= SVAL(req
->vwv
+1, 0);
5299 /* we used to allow the client to get the cnum wrong, but that
5300 is really quite gross and only worked when there was only
5301 one printer - I think we should now only accept it if they
5302 get it right (tridge) */
5303 if (!CAN_PRINT(conn
)) {
5304 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5305 END_PROFILE(SMBsplretq
);
5309 reply_outbuf(req
, 2, 3);
5310 SSVAL(req
->outbuf
,smb_vwv0
,0);
5311 SSVAL(req
->outbuf
,smb_vwv1
,0);
5312 SCVAL(smb_buf(req
->outbuf
),0,1);
5313 SSVAL(smb_buf(req
->outbuf
),1,0);
5315 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5316 start_index
, max_count
));
5319 TALLOC_CTX
*mem_ctx
= talloc_tos();
5322 const char *sharename
= lp_servicename(SNUM(conn
));
5323 struct rpc_pipe_client
*cli
= NULL
;
5324 struct dcerpc_binding_handle
*b
= NULL
;
5325 struct policy_handle handle
;
5326 struct spoolss_DevmodeContainer devmode_ctr
;
5327 union spoolss_JobInfo
*info
;
5329 uint32_t num_to_get
;
5333 ZERO_STRUCT(handle
);
5335 status
= rpc_pipe_open_interface(conn
,
5336 &ndr_table_spoolss
.syntax_id
,
5338 &conn
->sconn
->client_id
,
5339 conn
->sconn
->msg_ctx
,
5341 if (!NT_STATUS_IS_OK(status
)) {
5342 DEBUG(0, ("reply_printqueue: "
5343 "could not connect to spoolss: %s\n",
5344 nt_errstr(status
)));
5345 reply_nterror(req
, status
);
5348 b
= cli
->binding_handle
;
5350 ZERO_STRUCT(devmode_ctr
);
5352 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5355 SEC_FLAG_MAXIMUM_ALLOWED
,
5358 if (!NT_STATUS_IS_OK(status
)) {
5359 reply_nterror(req
, status
);
5362 if (!W_ERROR_IS_OK(werr
)) {
5363 reply_nterror(req
, werror_to_ntstatus(werr
));
5367 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5375 if (!W_ERROR_IS_OK(werr
)) {
5376 reply_nterror(req
, werror_to_ntstatus(werr
));
5380 if (max_count
> 0) {
5381 first
= start_index
;
5383 first
= start_index
+ max_count
+ 1;
5386 if (first
>= count
) {
5389 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5392 for (i
= first
; i
< num_to_get
; i
++) {
5395 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5397 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5398 info
[i
].info2
.job_id
);
5400 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5406 srv_put_dos_date2(p
, 0, qtime
);
5407 SCVAL(p
, 4, qstatus
);
5408 SSVAL(p
, 5, qrapjobid
);
5409 SIVAL(p
, 7, info
[i
].info2
.size
);
5411 srvstr_push(blob
, req
->flags2
, p
+12,
5412 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5414 if (message_push_blob(
5417 blob
, sizeof(blob
))) == -1) {
5418 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5424 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5425 SSVAL(req
->outbuf
,smb_vwv1
,
5426 (max_count
>0?first
+count
:first
-1));
5427 SCVAL(smb_buf(req
->outbuf
),0,1);
5428 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5432 DEBUG(3, ("%u entries returned in queue\n",
5436 if (b
&& is_valid_policy_hnd(&handle
)) {
5437 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5442 END_PROFILE(SMBsplretq
);
5446 /****************************************************************************
5447 Reply to a printwrite.
5448 ****************************************************************************/
5450 void reply_printwrite(struct smb_request
*req
)
5452 connection_struct
*conn
= req
->conn
;
5457 START_PROFILE(SMBsplwr
);
5460 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5461 END_PROFILE(SMBsplwr
);
5465 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5467 if (!check_fsp(conn
, req
, fsp
)) {
5468 END_PROFILE(SMBsplwr
);
5472 if (!fsp
->print_file
) {
5473 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5474 END_PROFILE(SMBsplwr
);
5478 if (!CHECK_WRITE(fsp
)) {
5479 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5480 END_PROFILE(SMBsplwr
);
5484 numtowrite
= SVAL(req
->buf
, 1);
5486 if (req
->buflen
< numtowrite
+ 3) {
5487 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5488 END_PROFILE(SMBsplwr
);
5492 data
= (const char *)req
->buf
+ 3;
5494 if (write_file(req
,fsp
,data
,(SMB_OFF_T
)-1,numtowrite
) != numtowrite
) {
5495 reply_nterror(req
, map_nt_error_from_unix(errno
));
5496 END_PROFILE(SMBsplwr
);
5500 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
5502 END_PROFILE(SMBsplwr
);
5506 /****************************************************************************
5508 ****************************************************************************/
5510 void reply_mkdir(struct smb_request
*req
)
5512 connection_struct
*conn
= req
->conn
;
5513 struct smb_filename
*smb_dname
= NULL
;
5514 char *directory
= NULL
;
5516 TALLOC_CTX
*ctx
= talloc_tos();
5518 START_PROFILE(SMBmkdir
);
5520 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5521 STR_TERMINATE
, &status
);
5522 if (!NT_STATUS_IS_OK(status
)) {
5523 reply_nterror(req
, status
);
5527 status
= filename_convert(ctx
, conn
,
5528 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5533 if (!NT_STATUS_IS_OK(status
)) {
5534 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5535 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5536 ERRSRV
, ERRbadpath
);
5539 reply_nterror(req
, status
);
5543 status
= create_directory(conn
, req
, smb_dname
);
5545 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5547 if (!NT_STATUS_IS_OK(status
)) {
5549 if (!use_nt_status()
5550 && NT_STATUS_EQUAL(status
,
5551 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5553 * Yes, in the DOS error code case we get a
5554 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5555 * samba4 torture test.
5557 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5560 reply_nterror(req
, status
);
5564 reply_outbuf(req
, 0, 0);
5566 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5568 TALLOC_FREE(smb_dname
);
5569 END_PROFILE(SMBmkdir
);
5573 /****************************************************************************
5575 ****************************************************************************/
5577 void reply_rmdir(struct smb_request
*req
)
5579 connection_struct
*conn
= req
->conn
;
5580 struct smb_filename
*smb_dname
= NULL
;
5581 char *directory
= NULL
;
5583 TALLOC_CTX
*ctx
= talloc_tos();
5584 files_struct
*fsp
= NULL
;
5586 struct smbd_server_connection
*sconn
= req
->sconn
;
5588 START_PROFILE(SMBrmdir
);
5590 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5591 STR_TERMINATE
, &status
);
5592 if (!NT_STATUS_IS_OK(status
)) {
5593 reply_nterror(req
, status
);
5597 status
= filename_convert(ctx
, conn
,
5598 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5603 if (!NT_STATUS_IS_OK(status
)) {
5604 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5605 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5606 ERRSRV
, ERRbadpath
);
5609 reply_nterror(req
, status
);
5613 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5614 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5618 status
= SMB_VFS_CREATE_FILE(
5621 0, /* root_dir_fid */
5622 smb_dname
, /* fname */
5623 DELETE_ACCESS
, /* access_mask */
5624 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5626 FILE_OPEN
, /* create_disposition*/
5627 FILE_DIRECTORY_FILE
, /* create_options */
5628 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5629 0, /* oplock_request */
5630 0, /* allocation_size */
5631 0, /* private_flags */
5637 if (!NT_STATUS_IS_OK(status
)) {
5638 if (open_was_deferred(req
->mid
)) {
5639 /* We have re-scheduled this call. */
5642 reply_nterror(req
, status
);
5646 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5647 if (!NT_STATUS_IS_OK(status
)) {
5648 close_file(req
, fsp
, ERROR_CLOSE
);
5649 reply_nterror(req
, status
);
5653 if (!set_delete_on_close(fsp
, true, &conn
->session_info
->utok
)) {
5654 close_file(req
, fsp
, ERROR_CLOSE
);
5655 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5659 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5660 if (!NT_STATUS_IS_OK(status
)) {
5661 reply_nterror(req
, status
);
5663 reply_outbuf(req
, 0, 0);
5666 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5668 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5670 TALLOC_FREE(smb_dname
);
5671 END_PROFILE(SMBrmdir
);
5675 /*******************************************************************
5676 Resolve wildcards in a filename rename.
5677 ********************************************************************/
5679 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5684 char *name2_copy
= NULL
;
5689 char *p
,*p2
, *pname1
, *pname2
;
5691 name2_copy
= talloc_strdup(ctx
, name2
);
5696 pname1
= strrchr_m(name1
,'/');
5697 pname2
= strrchr_m(name2_copy
,'/');
5699 if (!pname1
|| !pname2
) {
5703 /* Truncate the copy of name2 at the last '/' */
5706 /* Now go past the '/' */
5710 root1
= talloc_strdup(ctx
, pname1
);
5711 root2
= talloc_strdup(ctx
, pname2
);
5713 if (!root1
|| !root2
) {
5717 p
= strrchr_m(root1
,'.');
5720 ext1
= talloc_strdup(ctx
, p
+1);
5722 ext1
= talloc_strdup(ctx
, "");
5724 p
= strrchr_m(root2
,'.');
5727 ext2
= talloc_strdup(ctx
, p
+1);
5729 ext2
= talloc_strdup(ctx
, "");
5732 if (!ext1
|| !ext2
) {
5740 /* Hmmm. Should this be mb-aware ? */
5743 } else if (*p2
== '*') {
5745 root2
= talloc_asprintf(ctx
, "%s%s",
5764 /* Hmmm. Should this be mb-aware ? */
5767 } else if (*p2
== '*') {
5769 ext2
= talloc_asprintf(ctx
, "%s%s",
5785 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5790 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5802 /****************************************************************************
5803 Ensure open files have their names updated. Updated to notify other smbd's
5805 ****************************************************************************/
5807 static void rename_open_files(connection_struct
*conn
,
5808 struct share_mode_lock
*lck
,
5809 uint32_t orig_name_hash
,
5810 const struct smb_filename
*smb_fname_dst
)
5813 bool did_rename
= False
;
5815 uint32_t new_name_hash
;
5817 for(fsp
= file_find_di_first(conn
->sconn
, lck
->id
); fsp
;
5818 fsp
= file_find_di_next(fsp
)) {
5819 /* fsp_name is a relative path under the fsp. To change this for other
5820 sharepaths we need to manipulate relative paths. */
5821 /* TODO - create the absolute path and manipulate the newname
5822 relative to the sharepath. */
5823 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5826 if (fsp
->name_hash
!= orig_name_hash
) {
5829 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5830 "(file_id %s) from %s -> %s\n", fsp
->fnum
,
5831 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
5832 smb_fname_str_dbg(smb_fname_dst
)));
5834 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
5835 if (NT_STATUS_IS_OK(status
)) {
5837 new_name_hash
= fsp
->name_hash
;
5842 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5843 "for %s\n", file_id_string_tos(&lck
->id
),
5844 smb_fname_str_dbg(smb_fname_dst
)));
5847 /* Send messages to all smbd's (not ourself) that the name has changed. */
5848 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, conn
->connectpath
,
5849 orig_name_hash
, new_name_hash
,
5854 /****************************************************************************
5855 We need to check if the source path is a parent directory of the destination
5856 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5857 refuse the rename with a sharing violation. Under UNIX the above call can
5858 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5859 probably need to check that the client is a Windows one before disallowing
5860 this as a UNIX client (one with UNIX extensions) can know the source is a
5861 symlink and make this decision intelligently. Found by an excellent bug
5862 report from <AndyLiebman@aol.com>.
5863 ****************************************************************************/
5865 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
5866 const struct smb_filename
*smb_fname_dst
)
5868 const char *psrc
= smb_fname_src
->base_name
;
5869 const char *pdst
= smb_fname_dst
->base_name
;
5872 if (psrc
[0] == '.' && psrc
[1] == '/') {
5875 if (pdst
[0] == '.' && pdst
[1] == '/') {
5878 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5881 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5885 * Do the notify calls from a rename
5888 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5889 const struct smb_filename
*smb_fname_src
,
5890 const struct smb_filename
*smb_fname_dst
)
5892 char *parent_dir_src
= NULL
;
5893 char *parent_dir_dst
= NULL
;
5896 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5897 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5899 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
5900 &parent_dir_src
, NULL
) ||
5901 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
5902 &parent_dir_dst
, NULL
)) {
5906 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
5907 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
5908 smb_fname_src
->base_name
);
5909 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
5910 smb_fname_dst
->base_name
);
5913 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
5914 smb_fname_src
->base_name
);
5915 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
5916 smb_fname_dst
->base_name
);
5919 /* this is a strange one. w2k3 gives an additional event for
5920 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5921 files, but not directories */
5923 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5924 FILE_NOTIFY_CHANGE_ATTRIBUTES
5925 |FILE_NOTIFY_CHANGE_CREATION
,
5926 smb_fname_dst
->base_name
);
5929 TALLOC_FREE(parent_dir_src
);
5930 TALLOC_FREE(parent_dir_dst
);
5933 /****************************************************************************
5934 Returns an error if the parent directory for a filename is open in an
5936 ****************************************************************************/
5938 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
5939 const struct smb_filename
*smb_fname_dst_in
)
5941 char *parent_dir
= NULL
;
5942 struct smb_filename smb_fname_parent
;
5944 files_struct
*fsp
= NULL
;
5947 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
5948 &parent_dir
, NULL
)) {
5949 return NT_STATUS_NO_MEMORY
;
5951 ZERO_STRUCT(smb_fname_parent
);
5952 smb_fname_parent
.base_name
= parent_dir
;
5954 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
5956 return map_nt_error_from_unix(errno
);
5960 * We're only checking on this smbd here, mostly good
5961 * enough.. and will pass tests.
5964 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
5965 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
5966 fsp
= file_find_di_next(fsp
)) {
5967 if (fsp
->access_mask
& DELETE_ACCESS
) {
5968 return NT_STATUS_SHARING_VIOLATION
;
5971 return NT_STATUS_OK
;
5974 /****************************************************************************
5975 Rename an open file - given an fsp.
5976 ****************************************************************************/
5978 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
5980 const struct smb_filename
*smb_fname_dst_in
,
5982 bool replace_if_exists
)
5984 TALLOC_CTX
*ctx
= talloc_tos();
5985 struct smb_filename
*smb_fname_dst
= NULL
;
5986 NTSTATUS status
= NT_STATUS_OK
;
5987 struct share_mode_lock
*lck
= NULL
;
5988 bool dst_exists
, old_is_stream
, new_is_stream
;
5990 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
5991 if (!NT_STATUS_IS_OK(status
)) {
5995 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
5996 if (!NT_STATUS_IS_OK(status
)) {
6000 /* Make a copy of the dst smb_fname structs */
6002 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
6003 if (!NT_STATUS_IS_OK(status
)) {
6008 * Check for special case with case preserving and not
6009 * case sensitive. If the old last component differs from the original
6010 * last component only by case, then we should allow
6011 * the rename (user is trying to change the case of the
6014 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6015 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6016 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6018 char *fname_dst_lcomp_base_mod
= NULL
;
6019 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6022 * Get the last component of the destination name.
6024 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6026 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6028 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6030 if (!fname_dst_lcomp_base_mod
) {
6031 status
= NT_STATUS_NO_MEMORY
;
6036 * Create an smb_filename struct using the original last
6037 * component of the destination.
6039 status
= create_synthetic_smb_fname_split(ctx
,
6040 smb_fname_dst
->original_lcomp
, NULL
,
6041 &smb_fname_orig_lcomp
);
6042 if (!NT_STATUS_IS_OK(status
)) {
6043 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6047 /* If the base names only differ by case, use original. */
6048 if(!strcsequal(fname_dst_lcomp_base_mod
,
6049 smb_fname_orig_lcomp
->base_name
)) {
6052 * Replace the modified last component with the
6056 *last_slash
= '\0'; /* Truncate at the '/' */
6057 tmp
= talloc_asprintf(smb_fname_dst
,
6059 smb_fname_dst
->base_name
,
6060 smb_fname_orig_lcomp
->base_name
);
6062 tmp
= talloc_asprintf(smb_fname_dst
,
6064 smb_fname_orig_lcomp
->base_name
);
6067 status
= NT_STATUS_NO_MEMORY
;
6068 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6069 TALLOC_FREE(smb_fname_orig_lcomp
);
6072 TALLOC_FREE(smb_fname_dst
->base_name
);
6073 smb_fname_dst
->base_name
= tmp
;
6076 /* If the stream_names only differ by case, use original. */
6077 if(!strcsequal(smb_fname_dst
->stream_name
,
6078 smb_fname_orig_lcomp
->stream_name
)) {
6080 /* Use the original stream. */
6081 tmp
= talloc_strdup(smb_fname_dst
,
6082 smb_fname_orig_lcomp
->stream_name
);
6084 status
= NT_STATUS_NO_MEMORY
;
6085 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6086 TALLOC_FREE(smb_fname_orig_lcomp
);
6089 TALLOC_FREE(smb_fname_dst
->stream_name
);
6090 smb_fname_dst
->stream_name
= tmp
;
6092 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6093 TALLOC_FREE(smb_fname_orig_lcomp
);
6097 * If the src and dest names are identical - including case,
6098 * don't do the rename, just return success.
6101 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6102 strcsequal(fsp
->fsp_name
->stream_name
,
6103 smb_fname_dst
->stream_name
)) {
6104 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6105 "- returning success\n",
6106 smb_fname_str_dbg(smb_fname_dst
)));
6107 status
= NT_STATUS_OK
;
6111 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6112 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6114 /* Return the correct error code if both names aren't streams. */
6115 if (!old_is_stream
&& new_is_stream
) {
6116 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6120 if (old_is_stream
&& !new_is_stream
) {
6121 status
= NT_STATUS_INVALID_PARAMETER
;
6125 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6127 if(!replace_if_exists
&& dst_exists
) {
6128 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6129 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6130 smb_fname_str_dbg(smb_fname_dst
)));
6131 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6136 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6137 &smb_fname_dst
->st
);
6138 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6140 /* The file can be open when renaming a stream */
6141 if (dst_fsp
&& !new_is_stream
) {
6142 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6143 status
= NT_STATUS_ACCESS_DENIED
;
6148 /* Ensure we have a valid stat struct for the source. */
6149 status
= vfs_stat_fsp(fsp
);
6150 if (!NT_STATUS_IS_OK(status
)) {
6154 status
= can_rename(conn
, fsp
, attrs
);
6156 if (!NT_STATUS_IS_OK(status
)) {
6157 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6158 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6159 smb_fname_str_dbg(smb_fname_dst
)));
6160 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6161 status
= NT_STATUS_ACCESS_DENIED
;
6165 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6166 status
= NT_STATUS_ACCESS_DENIED
;
6169 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6173 * We have the file open ourselves, so not being able to get the
6174 * corresponding share mode lock is a fatal error.
6177 SMB_ASSERT(lck
!= NULL
);
6179 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6180 uint32 create_options
= fsp
->fh
->private_options
;
6182 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6183 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6184 smb_fname_str_dbg(smb_fname_dst
)));
6186 if (!lp_posix_pathnames() &&
6187 (lp_map_archive(SNUM(conn
)) ||
6188 lp_store_dos_attributes(SNUM(conn
)))) {
6189 /* We must set the archive bit on the newly
6191 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6192 uint32_t old_dosmode
= dos_mode(conn
,
6194 file_set_dosmode(conn
,
6196 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6202 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6205 rename_open_files(conn
, lck
, fsp
->name_hash
, smb_fname_dst
);
6208 * A rename acts as a new file create w.r.t. allowing an initial delete
6209 * on close, probably because in Windows there is a new handle to the
6210 * new file. If initial delete on close was requested but not
6211 * originally set, we need to set it here. This is probably not 100% correct,
6212 * but will work for the CIFSFS client which in non-posix mode
6213 * depends on these semantics. JRA.
6216 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6217 status
= can_set_delete_on_close(fsp
, 0);
6219 if (NT_STATUS_IS_OK(status
)) {
6220 /* Note that here we set the *inital* delete on close flag,
6221 * not the regular one. The magic gets handled in close. */
6222 fsp
->initial_delete_on_close
= True
;
6226 status
= NT_STATUS_OK
;
6232 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6233 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6235 status
= map_nt_error_from_unix(errno
);
6238 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6239 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6240 smb_fname_str_dbg(smb_fname_dst
)));
6243 TALLOC_FREE(smb_fname_dst
);
6248 /****************************************************************************
6249 The guts of the rename command, split out so it may be called by the NT SMB
6251 ****************************************************************************/
6253 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6254 connection_struct
*conn
,
6255 struct smb_request
*req
,
6256 struct smb_filename
*smb_fname_src
,
6257 struct smb_filename
*smb_fname_dst
,
6259 bool replace_if_exists
,
6262 uint32_t access_mask
)
6264 char *fname_src_dir
= NULL
;
6265 char *fname_src_mask
= NULL
;
6267 NTSTATUS status
= NT_STATUS_OK
;
6268 struct smb_Dir
*dir_hnd
= NULL
;
6269 const char *dname
= NULL
;
6270 char *talloced
= NULL
;
6272 int create_options
= 0;
6273 bool posix_pathnames
= lp_posix_pathnames();
6276 * Split the old name into directory and last component
6277 * strings. Note that unix_convert may have stripped off a
6278 * leading ./ from both name and newname if the rename is
6279 * at the root of the share. We need to make sure either both
6280 * name and newname contain a / character or neither of them do
6281 * as this is checked in resolve_wildcards().
6284 /* Split up the directory from the filename/mask. */
6285 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6286 &fname_src_dir
, &fname_src_mask
);
6287 if (!NT_STATUS_IS_OK(status
)) {
6288 status
= NT_STATUS_NO_MEMORY
;
6293 * We should only check the mangled cache
6294 * here if unix_convert failed. This means
6295 * that the path in 'mask' doesn't exist
6296 * on the file system and so we need to look
6297 * for a possible mangle. This patch from
6298 * Tine Smukavec <valentin.smukavec@hermes.si>.
6301 if (!VALID_STAT(smb_fname_src
->st
) &&
6302 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6303 char *new_mask
= NULL
;
6304 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6307 TALLOC_FREE(fname_src_mask
);
6308 fname_src_mask
= new_mask
;
6312 if (!src_has_wild
) {
6316 * Only one file needs to be renamed. Append the mask back
6317 * onto the directory.
6319 TALLOC_FREE(smb_fname_src
->base_name
);
6320 if (ISDOT(fname_src_dir
)) {
6321 /* Ensure we use canonical names on open. */
6322 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6326 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6331 if (!smb_fname_src
->base_name
) {
6332 status
= NT_STATUS_NO_MEMORY
;
6336 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6337 "case_preserve = %d, short case preserve = %d, "
6338 "directory = %s, newname = %s, "
6339 "last_component_dest = %s\n",
6340 conn
->case_sensitive
, conn
->case_preserve
,
6341 conn
->short_case_preserve
,
6342 smb_fname_str_dbg(smb_fname_src
),
6343 smb_fname_str_dbg(smb_fname_dst
),
6344 smb_fname_dst
->original_lcomp
));
6346 /* The dest name still may have wildcards. */
6347 if (dest_has_wild
) {
6348 char *fname_dst_mod
= NULL
;
6349 if (!resolve_wildcards(smb_fname_dst
,
6350 smb_fname_src
->base_name
,
6351 smb_fname_dst
->base_name
,
6353 DEBUG(6, ("rename_internals: resolve_wildcards "
6355 smb_fname_src
->base_name
,
6356 smb_fname_dst
->base_name
));
6357 status
= NT_STATUS_NO_MEMORY
;
6360 TALLOC_FREE(smb_fname_dst
->base_name
);
6361 smb_fname_dst
->base_name
= fname_dst_mod
;
6364 ZERO_STRUCT(smb_fname_src
->st
);
6365 if (posix_pathnames
) {
6366 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6368 SMB_VFS_STAT(conn
, smb_fname_src
);
6371 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6372 create_options
|= FILE_DIRECTORY_FILE
;
6375 status
= SMB_VFS_CREATE_FILE(
6378 0, /* root_dir_fid */
6379 smb_fname_src
, /* fname */
6380 access_mask
, /* access_mask */
6381 (FILE_SHARE_READ
| /* share_access */
6383 FILE_OPEN
, /* create_disposition*/
6384 create_options
, /* create_options */
6385 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6386 0, /* oplock_request */
6387 0, /* allocation_size */
6388 0, /* private_flags */
6394 if (!NT_STATUS_IS_OK(status
)) {
6395 DEBUG(3, ("Could not open rename source %s: %s\n",
6396 smb_fname_str_dbg(smb_fname_src
),
6397 nt_errstr(status
)));
6401 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6402 attrs
, replace_if_exists
);
6404 close_file(req
, fsp
, NORMAL_CLOSE
);
6406 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6407 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6408 smb_fname_str_dbg(smb_fname_dst
)));
6414 * Wildcards - process each file that matches.
6416 if (strequal(fname_src_mask
, "????????.???")) {
6417 TALLOC_FREE(fname_src_mask
);
6418 fname_src_mask
= talloc_strdup(ctx
, "*");
6419 if (!fname_src_mask
) {
6420 status
= NT_STATUS_NO_MEMORY
;
6425 status
= check_name(conn
, fname_src_dir
);
6426 if (!NT_STATUS_IS_OK(status
)) {
6430 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6432 if (dir_hnd
== NULL
) {
6433 status
= map_nt_error_from_unix(errno
);
6437 status
= NT_STATUS_NO_SUCH_FILE
;
6439 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6440 * - gentest fix. JRA
6443 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6445 files_struct
*fsp
= NULL
;
6446 char *destname
= NULL
;
6447 bool sysdir_entry
= False
;
6449 /* Quick check for "." and ".." */
6450 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6451 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6452 sysdir_entry
= True
;
6454 TALLOC_FREE(talloced
);
6459 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6460 &smb_fname_src
->st
, false)) {
6461 TALLOC_FREE(talloced
);
6465 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6466 TALLOC_FREE(talloced
);
6471 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6475 TALLOC_FREE(smb_fname_src
->base_name
);
6476 if (ISDOT(fname_src_dir
)) {
6477 /* Ensure we use canonical names on open. */
6478 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6482 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6487 if (!smb_fname_src
->base_name
) {
6488 status
= NT_STATUS_NO_MEMORY
;
6492 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6493 smb_fname_dst
->base_name
,
6495 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6496 smb_fname_src
->base_name
, destname
));
6497 TALLOC_FREE(talloced
);
6501 status
= NT_STATUS_NO_MEMORY
;
6505 TALLOC_FREE(smb_fname_dst
->base_name
);
6506 smb_fname_dst
->base_name
= destname
;
6508 ZERO_STRUCT(smb_fname_src
->st
);
6509 if (posix_pathnames
) {
6510 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6512 SMB_VFS_STAT(conn
, smb_fname_src
);
6517 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6518 create_options
|= FILE_DIRECTORY_FILE
;
6521 status
= SMB_VFS_CREATE_FILE(
6524 0, /* root_dir_fid */
6525 smb_fname_src
, /* fname */
6526 access_mask
, /* access_mask */
6527 (FILE_SHARE_READ
| /* share_access */
6529 FILE_OPEN
, /* create_disposition*/
6530 create_options
, /* create_options */
6531 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6532 0, /* oplock_request */
6533 0, /* allocation_size */
6534 0, /* private_flags */
6540 if (!NT_STATUS_IS_OK(status
)) {
6541 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6542 "returned %s rename %s -> %s\n",
6544 smb_fname_str_dbg(smb_fname_src
),
6545 smb_fname_str_dbg(smb_fname_dst
)));
6549 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6551 if (!smb_fname_dst
->original_lcomp
) {
6552 status
= NT_STATUS_NO_MEMORY
;
6556 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6557 attrs
, replace_if_exists
);
6559 close_file(req
, fsp
, NORMAL_CLOSE
);
6561 if (!NT_STATUS_IS_OK(status
)) {
6562 DEBUG(3, ("rename_internals_fsp returned %s for "
6563 "rename %s -> %s\n", nt_errstr(status
),
6564 smb_fname_str_dbg(smb_fname_src
),
6565 smb_fname_str_dbg(smb_fname_dst
)));
6571 DEBUG(3,("rename_internals: doing rename on %s -> "
6572 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6573 smb_fname_str_dbg(smb_fname_src
)));
6574 TALLOC_FREE(talloced
);
6576 TALLOC_FREE(dir_hnd
);
6578 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6579 status
= map_nt_error_from_unix(errno
);
6583 TALLOC_FREE(talloced
);
6584 TALLOC_FREE(fname_src_dir
);
6585 TALLOC_FREE(fname_src_mask
);
6589 /****************************************************************************
6591 ****************************************************************************/
6593 void reply_mv(struct smb_request
*req
)
6595 connection_struct
*conn
= req
->conn
;
6597 char *newname
= NULL
;
6601 bool src_has_wcard
= False
;
6602 bool dest_has_wcard
= False
;
6603 TALLOC_CTX
*ctx
= talloc_tos();
6604 struct smb_filename
*smb_fname_src
= NULL
;
6605 struct smb_filename
*smb_fname_dst
= NULL
;
6606 uint32_t src_ucf_flags
= lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP
: UCF_COND_ALLOW_WCARD_LCOMP
;
6607 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
| (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP
);
6608 bool stream_rename
= false;
6610 START_PROFILE(SMBmv
);
6613 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6617 attrs
= SVAL(req
->vwv
+0, 0);
6619 p
= (const char *)req
->buf
+ 1;
6620 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6621 &status
, &src_has_wcard
);
6622 if (!NT_STATUS_IS_OK(status
)) {
6623 reply_nterror(req
, status
);
6627 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6628 &status
, &dest_has_wcard
);
6629 if (!NT_STATUS_IS_OK(status
)) {
6630 reply_nterror(req
, status
);
6634 if (!lp_posix_pathnames()) {
6635 /* The newname must begin with a ':' if the
6636 name contains a ':'. */
6637 if (strchr_m(name
, ':')) {
6638 if (newname
[0] != ':') {
6639 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6642 stream_rename
= true;
6646 status
= filename_convert(ctx
,
6648 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6654 if (!NT_STATUS_IS_OK(status
)) {
6655 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6656 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6657 ERRSRV
, ERRbadpath
);
6660 reply_nterror(req
, status
);
6664 status
= filename_convert(ctx
,
6666 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6672 if (!NT_STATUS_IS_OK(status
)) {
6673 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6674 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6675 ERRSRV
, ERRbadpath
);
6678 reply_nterror(req
, status
);
6682 if (stream_rename
) {
6683 /* smb_fname_dst->base_name must be the same as
6684 smb_fname_src->base_name. */
6685 TALLOC_FREE(smb_fname_dst
->base_name
);
6686 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6687 smb_fname_src
->base_name
);
6688 if (!smb_fname_dst
->base_name
) {
6689 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6694 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6695 smb_fname_str_dbg(smb_fname_dst
)));
6697 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
6698 attrs
, False
, src_has_wcard
, dest_has_wcard
,
6700 if (!NT_STATUS_IS_OK(status
)) {
6701 if (open_was_deferred(req
->mid
)) {
6702 /* We have re-scheduled this call. */
6705 reply_nterror(req
, status
);
6709 reply_outbuf(req
, 0, 0);
6711 TALLOC_FREE(smb_fname_src
);
6712 TALLOC_FREE(smb_fname_dst
);
6717 /*******************************************************************
6718 Copy a file as part of a reply_copy.
6719 ******************************************************************/
6722 * TODO: check error codes on all callers
6725 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6726 connection_struct
*conn
,
6727 struct smb_filename
*smb_fname_src
,
6728 struct smb_filename
*smb_fname_dst
,
6731 bool target_is_directory
)
6733 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
6735 files_struct
*fsp1
,*fsp2
;
6737 uint32 new_create_disposition
;
6741 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
6742 if (!NT_STATUS_IS_OK(status
)) {
6747 * If the target is a directory, extract the last component from the
6748 * src filename and append it to the dst filename
6750 if (target_is_directory
) {
6753 /* dest/target can't be a stream if it's a directory. */
6754 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
6756 p
= strrchr_m(smb_fname_src
->base_name
,'/');
6760 p
= smb_fname_src
->base_name
;
6762 smb_fname_dst_tmp
->base_name
=
6763 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
6765 if (!smb_fname_dst_tmp
->base_name
) {
6766 status
= NT_STATUS_NO_MEMORY
;
6771 status
= vfs_file_exist(conn
, smb_fname_src
);
6772 if (!NT_STATUS_IS_OK(status
)) {
6776 if (!target_is_directory
&& count
) {
6777 new_create_disposition
= FILE_OPEN
;
6779 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
6782 &new_create_disposition
,
6785 status
= NT_STATUS_INVALID_PARAMETER
;
6790 /* Open the src file for reading. */
6791 status
= SMB_VFS_CREATE_FILE(
6794 0, /* root_dir_fid */
6795 smb_fname_src
, /* fname */
6796 FILE_GENERIC_READ
, /* access_mask */
6797 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6798 FILE_OPEN
, /* create_disposition*/
6799 0, /* create_options */
6800 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6801 INTERNAL_OPEN_ONLY
, /* oplock_request */
6802 0, /* allocation_size */
6803 0, /* private_flags */
6809 if (!NT_STATUS_IS_OK(status
)) {
6813 dosattrs
= dos_mode(conn
, smb_fname_src
);
6815 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
6816 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
6819 /* Open the dst file for writing. */
6820 status
= SMB_VFS_CREATE_FILE(
6823 0, /* root_dir_fid */
6824 smb_fname_dst
, /* fname */
6825 FILE_GENERIC_WRITE
, /* access_mask */
6826 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6827 new_create_disposition
, /* create_disposition*/
6828 0, /* create_options */
6829 dosattrs
, /* file_attributes */
6830 INTERNAL_OPEN_ONLY
, /* oplock_request */
6831 0, /* allocation_size */
6832 0, /* private_flags */
6838 if (!NT_STATUS_IS_OK(status
)) {
6839 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6843 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
6844 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
6846 DEBUG(0, ("error - vfs lseek returned error %s\n",
6848 status
= map_nt_error_from_unix(errno
);
6849 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6850 close_file(NULL
, fsp2
, ERROR_CLOSE
);
6855 /* Do the actual copy. */
6856 if (smb_fname_src
->st
.st_ex_size
) {
6857 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
6862 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
6864 /* Ensure the modtime is set correctly on the destination file. */
6865 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
6868 * As we are opening fsp1 read-only we only expect
6869 * an error on close on fsp2 if we are out of space.
6870 * Thus we don't look at the error return from the
6873 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
6875 if (!NT_STATUS_IS_OK(status
)) {
6879 if (ret
!= (SMB_OFF_T
)smb_fname_src
->st
.st_ex_size
) {
6880 status
= NT_STATUS_DISK_FULL
;
6884 status
= NT_STATUS_OK
;
6887 TALLOC_FREE(smb_fname_dst_tmp
);
6891 /****************************************************************************
6892 Reply to a file copy.
6893 ****************************************************************************/
6895 void reply_copy(struct smb_request
*req
)
6897 connection_struct
*conn
= req
->conn
;
6898 struct smb_filename
*smb_fname_src
= NULL
;
6899 struct smb_filename
*smb_fname_dst
= NULL
;
6900 char *fname_src
= NULL
;
6901 char *fname_dst
= NULL
;
6902 char *fname_src_mask
= NULL
;
6903 char *fname_src_dir
= NULL
;
6906 int error
= ERRnoaccess
;
6910 bool target_is_directory
=False
;
6911 bool source_has_wild
= False
;
6912 bool dest_has_wild
= False
;
6914 TALLOC_CTX
*ctx
= talloc_tos();
6916 START_PROFILE(SMBcopy
);
6919 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6923 tid2
= SVAL(req
->vwv
+0, 0);
6924 ofun
= SVAL(req
->vwv
+1, 0);
6925 flags
= SVAL(req
->vwv
+2, 0);
6927 p
= (const char *)req
->buf
;
6928 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
6929 &status
, &source_has_wild
);
6930 if (!NT_STATUS_IS_OK(status
)) {
6931 reply_nterror(req
, status
);
6934 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
6935 &status
, &dest_has_wild
);
6936 if (!NT_STATUS_IS_OK(status
)) {
6937 reply_nterror(req
, status
);
6941 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
6943 if (tid2
!= conn
->cnum
) {
6944 /* can't currently handle inter share copies XXXX */
6945 DEBUG(3,("Rejecting inter-share copy\n"));
6946 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
6950 status
= filename_convert(ctx
, conn
,
6951 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6953 UCF_COND_ALLOW_WCARD_LCOMP
,
6956 if (!NT_STATUS_IS_OK(status
)) {
6957 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6958 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6959 ERRSRV
, ERRbadpath
);
6962 reply_nterror(req
, status
);
6966 status
= filename_convert(ctx
, conn
,
6967 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6969 UCF_COND_ALLOW_WCARD_LCOMP
,
6972 if (!NT_STATUS_IS_OK(status
)) {
6973 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6974 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6975 ERRSRV
, ERRbadpath
);
6978 reply_nterror(req
, status
);
6982 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
6984 if ((flags
&1) && target_is_directory
) {
6985 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
6989 if ((flags
&2) && !target_is_directory
) {
6990 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
6994 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
6995 /* wants a tree copy! XXXX */
6996 DEBUG(3,("Rejecting tree copy\n"));
6997 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7001 /* Split up the directory from the filename/mask. */
7002 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7003 &fname_src_dir
, &fname_src_mask
);
7004 if (!NT_STATUS_IS_OK(status
)) {
7005 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7010 * We should only check the mangled cache
7011 * here if unix_convert failed. This means
7012 * that the path in 'mask' doesn't exist
7013 * on the file system and so we need to look
7014 * for a possible mangle. This patch from
7015 * Tine Smukavec <valentin.smukavec@hermes.si>.
7017 if (!VALID_STAT(smb_fname_src
->st
) &&
7018 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7019 char *new_mask
= NULL
;
7020 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7021 &new_mask
, conn
->params
);
7023 /* Use demangled name if one was successfully found. */
7025 TALLOC_FREE(fname_src_mask
);
7026 fname_src_mask
= new_mask
;
7030 if (!source_has_wild
) {
7033 * Only one file needs to be copied. Append the mask back onto
7036 TALLOC_FREE(smb_fname_src
->base_name
);
7037 if (ISDOT(fname_src_dir
)) {
7038 /* Ensure we use canonical names on open. */
7039 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7043 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7048 if (!smb_fname_src
->base_name
) {
7049 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7053 if (dest_has_wild
) {
7054 char *fname_dst_mod
= NULL
;
7055 if (!resolve_wildcards(smb_fname_dst
,
7056 smb_fname_src
->base_name
,
7057 smb_fname_dst
->base_name
,
7059 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7062 TALLOC_FREE(smb_fname_dst
->base_name
);
7063 smb_fname_dst
->base_name
= fname_dst_mod
;
7066 status
= check_name(conn
, smb_fname_src
->base_name
);
7067 if (!NT_STATUS_IS_OK(status
)) {
7068 reply_nterror(req
, status
);
7072 status
= check_name(conn
, smb_fname_dst
->base_name
);
7073 if (!NT_STATUS_IS_OK(status
)) {
7074 reply_nterror(req
, status
);
7078 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7079 ofun
, count
, target_is_directory
);
7081 if(!NT_STATUS_IS_OK(status
)) {
7082 reply_nterror(req
, status
);
7088 struct smb_Dir
*dir_hnd
= NULL
;
7089 const char *dname
= NULL
;
7090 char *talloced
= NULL
;
7094 * There is a wildcard that requires us to actually read the
7095 * src dir and copy each file matching the mask to the dst.
7096 * Right now streams won't be copied, but this could
7097 * presumably be added with a nested loop for reach dir entry.
7099 SMB_ASSERT(!smb_fname_src
->stream_name
);
7100 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7102 smb_fname_src
->stream_name
= NULL
;
7103 smb_fname_dst
->stream_name
= NULL
;
7105 if (strequal(fname_src_mask
,"????????.???")) {
7106 TALLOC_FREE(fname_src_mask
);
7107 fname_src_mask
= talloc_strdup(ctx
, "*");
7108 if (!fname_src_mask
) {
7109 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7114 status
= check_name(conn
, fname_src_dir
);
7115 if (!NT_STATUS_IS_OK(status
)) {
7116 reply_nterror(req
, status
);
7120 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7121 if (dir_hnd
== NULL
) {
7122 status
= map_nt_error_from_unix(errno
);
7123 reply_nterror(req
, status
);
7129 /* Iterate over the src dir copying each entry to the dst. */
7130 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7131 &smb_fname_src
->st
, &talloced
))) {
7132 char *destname
= NULL
;
7134 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7135 TALLOC_FREE(talloced
);
7139 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7140 &smb_fname_src
->st
, false)) {
7141 TALLOC_FREE(talloced
);
7145 if(!mask_match(dname
, fname_src_mask
,
7146 conn
->case_sensitive
)) {
7147 TALLOC_FREE(talloced
);
7151 error
= ERRnoaccess
;
7153 /* Get the src smb_fname struct setup. */
7154 TALLOC_FREE(smb_fname_src
->base_name
);
7155 if (ISDOT(fname_src_dir
)) {
7156 /* Ensure we use canonical names on open. */
7157 smb_fname_src
->base_name
=
7158 talloc_asprintf(smb_fname_src
, "%s",
7161 smb_fname_src
->base_name
=
7162 talloc_asprintf(smb_fname_src
, "%s/%s",
7163 fname_src_dir
, dname
);
7166 if (!smb_fname_src
->base_name
) {
7167 TALLOC_FREE(dir_hnd
);
7168 TALLOC_FREE(talloced
);
7169 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7173 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7174 smb_fname_dst
->base_name
,
7176 TALLOC_FREE(talloced
);
7180 TALLOC_FREE(dir_hnd
);
7181 TALLOC_FREE(talloced
);
7182 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7186 TALLOC_FREE(smb_fname_dst
->base_name
);
7187 smb_fname_dst
->base_name
= destname
;
7189 status
= check_name(conn
, smb_fname_src
->base_name
);
7190 if (!NT_STATUS_IS_OK(status
)) {
7191 TALLOC_FREE(dir_hnd
);
7192 TALLOC_FREE(talloced
);
7193 reply_nterror(req
, status
);
7197 status
= check_name(conn
, smb_fname_dst
->base_name
);
7198 if (!NT_STATUS_IS_OK(status
)) {
7199 TALLOC_FREE(dir_hnd
);
7200 TALLOC_FREE(talloced
);
7201 reply_nterror(req
, status
);
7205 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7206 smb_fname_src
->base_name
,
7207 smb_fname_dst
->base_name
));
7209 status
= copy_file(ctx
, conn
, smb_fname_src
,
7210 smb_fname_dst
, ofun
, count
,
7211 target_is_directory
);
7212 if (NT_STATUS_IS_OK(status
)) {
7216 TALLOC_FREE(talloced
);
7218 TALLOC_FREE(dir_hnd
);
7222 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7226 reply_outbuf(req
, 1, 0);
7227 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7229 TALLOC_FREE(smb_fname_src
);
7230 TALLOC_FREE(smb_fname_dst
);
7231 TALLOC_FREE(fname_src
);
7232 TALLOC_FREE(fname_dst
);
7233 TALLOC_FREE(fname_src_mask
);
7234 TALLOC_FREE(fname_src_dir
);
7236 END_PROFILE(SMBcopy
);
7241 #define DBGC_CLASS DBGC_LOCKING
7243 /****************************************************************************
7244 Get a lock pid, dealing with large count requests.
7245 ****************************************************************************/
7247 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7248 bool large_file_format
)
7250 if(!large_file_format
)
7251 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7253 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7256 /****************************************************************************
7257 Get a lock count, dealing with large count requests.
7258 ****************************************************************************/
7260 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7261 bool large_file_format
)
7265 if(!large_file_format
) {
7266 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7269 #if defined(HAVE_LONGLONG)
7270 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7271 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7272 #else /* HAVE_LONGLONG */
7275 * NT4.x seems to be broken in that it sends large file (64 bit)
7276 * lockingX calls even if the CAP_LARGE_FILES was *not*
7277 * negotiated. For boxes without large unsigned ints truncate the
7278 * lock count by dropping the top 32 bits.
7281 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7282 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7283 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7284 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7285 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7288 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7289 #endif /* HAVE_LONGLONG */
7295 #if !defined(HAVE_LONGLONG)
7296 /****************************************************************************
7297 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7298 ****************************************************************************/
7300 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7304 uint32 highcopy
= high
;
7307 * Try and find out how many significant bits there are in high.
7310 for(i
= 0; highcopy
; i
++)
7314 * We use 31 bits not 32 here as POSIX
7315 * lock offsets may not be negative.
7318 mask
= (~0) << (31 - i
);
7321 return 0; /* Fail. */
7327 #endif /* !defined(HAVE_LONGLONG) */
7329 /****************************************************************************
7330 Get a lock offset, dealing with large offset requests.
7331 ****************************************************************************/
7333 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7334 bool large_file_format
, bool *err
)
7336 uint64_t offset
= 0;
7340 if(!large_file_format
) {
7341 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7344 #if defined(HAVE_LONGLONG)
7345 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7346 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7347 #else /* HAVE_LONGLONG */
7350 * NT4.x seems to be broken in that it sends large file (64 bit)
7351 * lockingX calls even if the CAP_LARGE_FILES was *not*
7352 * negotiated. For boxes without large unsigned ints mangle the
7353 * lock offset by mapping the top 32 bits onto the lower 32.
7356 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7357 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7358 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7361 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7363 return (uint64_t)-1;
7366 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7367 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7368 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7369 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7372 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7373 #endif /* HAVE_LONGLONG */
7379 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7383 uint16_t num_ulocks
,
7384 struct smbd_lock_element
*ulocks
,
7386 struct smbd_lock_element
*locks
,
7389 connection_struct
*conn
= req
->conn
;
7391 NTSTATUS status
= NT_STATUS_OK
;
7395 /* Data now points at the beginning of the list
7396 of smb_unlkrng structs */
7397 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7398 struct smbd_lock_element
*e
= &ulocks
[i
];
7400 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7401 "pid %u, file %s\n",
7404 (unsigned int)e
->smblctx
,
7407 if (e
->brltype
!= UNLOCK_LOCK
) {
7408 /* this can only happen with SMB2 */
7409 return NT_STATUS_INVALID_PARAMETER
;
7412 status
= do_unlock(req
->sconn
->msg_ctx
,
7419 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7420 nt_errstr(status
)));
7422 if (!NT_STATUS_IS_OK(status
)) {
7427 /* Setup the timeout in seconds. */
7429 if (!lp_blocking_locks(SNUM(conn
))) {
7433 /* Data now points at the beginning of the list
7434 of smb_lkrng structs */
7436 for(i
= 0; i
< (int)num_locks
; i
++) {
7437 struct smbd_lock_element
*e
= &locks
[i
];
7439 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7440 "%llu, file %s timeout = %d\n",
7443 (unsigned long long)e
->smblctx
,
7447 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7448 struct blocking_lock_record
*blr
= NULL
;
7450 if (num_locks
> 1) {
7452 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7453 * if the lock vector contains one entry. When given mutliple cancel
7454 * requests in a single PDU we expect the server to return an
7455 * error. Windows servers seem to accept the request but only
7456 * cancel the first lock.
7457 * JRA - Do what Windows does (tm) :-).
7461 /* MS-CIFS (2.2.4.32.1) behavior. */
7462 return NT_STATUS_DOS(ERRDOS
,
7463 ERRcancelviolation
);
7465 /* Windows behavior. */
7467 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7468 "cancel request\n"));
7474 if (lp_blocking_locks(SNUM(conn
))) {
7476 /* Schedule a message to ourselves to
7477 remove the blocking lock record and
7478 return the right error. */
7480 blr
= blocking_lock_cancel_smb1(fsp
,
7486 NT_STATUS_FILE_LOCK_CONFLICT
);
7488 return NT_STATUS_DOS(
7490 ERRcancelviolation
);
7493 /* Remove a matching pending lock. */
7494 status
= do_lock_cancel(fsp
,
7501 bool blocking_lock
= timeout
? true : false;
7502 bool defer_lock
= false;
7503 struct byte_range_lock
*br_lck
;
7504 uint64_t block_smblctx
;
7506 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7518 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7519 /* Windows internal resolution for blocking locks seems
7520 to be about 200ms... Don't wait for less than that. JRA. */
7521 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7522 timeout
= lp_lock_spin_time();
7527 /* If a lock sent with timeout of zero would fail, and
7528 * this lock has been requested multiple times,
7529 * according to brl_lock_failed() we convert this
7530 * request to a blocking lock with a timeout of between
7531 * 150 - 300 milliseconds.
7533 * If lp_lock_spin_time() has been set to 0, we skip
7534 * this blocking retry and fail immediately.
7536 * Replacement for do_lock_spin(). JRA. */
7538 if (!req
->sconn
->using_smb2
&&
7539 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7540 lp_lock_spin_time() && !blocking_lock
&&
7541 NT_STATUS_EQUAL((status
),
7542 NT_STATUS_FILE_LOCK_CONFLICT
))
7545 timeout
= lp_lock_spin_time();
7548 if (br_lck
&& defer_lock
) {
7550 * A blocking lock was requested. Package up
7551 * this smb into a queued request and push it
7552 * onto the blocking lock queue.
7554 if(push_blocking_lock_request(br_lck
,
7565 TALLOC_FREE(br_lck
);
7567 return NT_STATUS_OK
;
7571 TALLOC_FREE(br_lck
);
7574 if (!NT_STATUS_IS_OK(status
)) {
7579 /* If any of the above locks failed, then we must unlock
7580 all of the previous locks (X/Open spec). */
7582 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7584 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7585 i
= -1; /* we want to skip the for loop */
7589 * Ensure we don't do a remove on the lock that just failed,
7590 * as under POSIX rules, if we have a lock already there, we
7591 * will delete it (and we shouldn't) .....
7593 for(i
--; i
>= 0; i
--) {
7594 struct smbd_lock_element
*e
= &locks
[i
];
7596 do_unlock(req
->sconn
->msg_ctx
,
7606 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7607 fsp
->fnum
, (unsigned int)type
, num_locks
, num_ulocks
));
7609 return NT_STATUS_OK
;
7612 /****************************************************************************
7613 Reply to a lockingX request.
7614 ****************************************************************************/
7616 void reply_lockingX(struct smb_request
*req
)
7618 connection_struct
*conn
= req
->conn
;
7620 unsigned char locktype
;
7621 unsigned char oplocklevel
;
7626 const uint8_t *data
;
7627 bool large_file_format
;
7629 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7630 struct smbd_lock_element
*ulocks
;
7631 struct smbd_lock_element
*locks
;
7634 START_PROFILE(SMBlockingX
);
7637 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7638 END_PROFILE(SMBlockingX
);
7642 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7643 locktype
= CVAL(req
->vwv
+3, 0);
7644 oplocklevel
= CVAL(req
->vwv
+3, 1);
7645 num_ulocks
= SVAL(req
->vwv
+6, 0);
7646 num_locks
= SVAL(req
->vwv
+7, 0);
7647 lock_timeout
= IVAL(req
->vwv
+4, 0);
7648 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7650 if (!check_fsp(conn
, req
, fsp
)) {
7651 END_PROFILE(SMBlockingX
);
7657 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7658 /* we don't support these - and CANCEL_LOCK makes w2k
7659 and XP reboot so I don't really want to be
7660 compatible! (tridge) */
7661 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7662 END_PROFILE(SMBlockingX
);
7666 /* Check if this is an oplock break on a file
7667 we have granted an oplock on.
7669 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7670 /* Client can insist on breaking to none. */
7671 bool break_to_none
= (oplocklevel
== 0);
7674 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7675 "for fnum = %d\n", (unsigned int)oplocklevel
,
7679 * Make sure we have granted an exclusive or batch oplock on
7683 if (fsp
->oplock_type
== 0) {
7685 /* The Samba4 nbench simulator doesn't understand
7686 the difference between break to level2 and break
7687 to none from level2 - it sends oplock break
7688 replies in both cases. Don't keep logging an error
7689 message here - just ignore it. JRA. */
7691 DEBUG(5,("reply_lockingX: Error : oplock break from "
7692 "client for fnum = %d (oplock=%d) and no "
7693 "oplock granted on this file (%s).\n",
7694 fsp
->fnum
, fsp
->oplock_type
,
7697 /* if this is a pure oplock break request then don't
7699 if (num_locks
== 0 && num_ulocks
== 0) {
7700 END_PROFILE(SMBlockingX
);
7703 END_PROFILE(SMBlockingX
);
7704 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
7709 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7711 result
= remove_oplock(fsp
);
7713 result
= downgrade_oplock(fsp
);
7717 DEBUG(0, ("reply_lockingX: error in removing "
7718 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7719 /* Hmmm. Is this panic justified? */
7720 smb_panic("internal tdb error");
7723 reply_to_oplock_break_requests(fsp
);
7725 /* if this is a pure oplock break request then don't send a
7727 if (num_locks
== 0 && num_ulocks
== 0) {
7728 /* Sanity check - ensure a pure oplock break is not a
7730 if(CVAL(req
->vwv
+0, 0) != 0xff)
7731 DEBUG(0,("reply_lockingX: Error : pure oplock "
7732 "break is a chained %d request !\n",
7733 (unsigned int)CVAL(req
->vwv
+0, 0)));
7734 END_PROFILE(SMBlockingX
);
7740 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7741 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7742 END_PROFILE(SMBlockingX
);
7746 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
7747 if (ulocks
== NULL
) {
7748 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7749 END_PROFILE(SMBlockingX
);
7753 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
7754 if (locks
== NULL
) {
7755 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7756 END_PROFILE(SMBlockingX
);
7760 /* Data now points at the beginning of the list
7761 of smb_unlkrng structs */
7762 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7763 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7764 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7765 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7766 ulocks
[i
].brltype
= UNLOCK_LOCK
;
7769 * There is no error code marked "stupid client bug".... :-).
7772 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7773 END_PROFILE(SMBlockingX
);
7778 /* Now do any requested locks */
7779 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
7781 /* Data now points at the beginning of the list
7782 of smb_lkrng structs */
7784 for(i
= 0; i
< (int)num_locks
; i
++) {
7785 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7786 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7787 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7789 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
7790 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7791 locks
[i
].brltype
= PENDING_READ_LOCK
;
7793 locks
[i
].brltype
= READ_LOCK
;
7796 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7797 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
7799 locks
[i
].brltype
= WRITE_LOCK
;
7804 * There is no error code marked "stupid client bug".... :-).
7807 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7808 END_PROFILE(SMBlockingX
);
7813 status
= smbd_do_locking(req
, fsp
,
7814 locktype
, lock_timeout
,
7818 if (!NT_STATUS_IS_OK(status
)) {
7819 END_PROFILE(SMBlockingX
);
7820 reply_nterror(req
, status
);
7824 END_PROFILE(SMBlockingX
);
7828 reply_outbuf(req
, 2, 0);
7830 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7831 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7833 END_PROFILE(SMBlockingX
);
7838 #define DBGC_CLASS DBGC_ALL
7840 /****************************************************************************
7841 Reply to a SMBreadbmpx (read block multiplex) request.
7842 Always reply with an error, if someone has a platform really needs this,
7843 please contact vl@samba.org
7844 ****************************************************************************/
7846 void reply_readbmpx(struct smb_request
*req
)
7848 START_PROFILE(SMBreadBmpx
);
7849 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7850 END_PROFILE(SMBreadBmpx
);
7854 /****************************************************************************
7855 Reply to a SMBreadbs (read block multiplex secondary) request.
7856 Always reply with an error, if someone has a platform really needs this,
7857 please contact vl@samba.org
7858 ****************************************************************************/
7860 void reply_readbs(struct smb_request
*req
)
7862 START_PROFILE(SMBreadBs
);
7863 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7864 END_PROFILE(SMBreadBs
);
7868 /****************************************************************************
7869 Reply to a SMBsetattrE.
7870 ****************************************************************************/
7872 void reply_setattrE(struct smb_request
*req
)
7874 connection_struct
*conn
= req
->conn
;
7875 struct smb_file_time ft
;
7879 START_PROFILE(SMBsetattrE
);
7883 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7887 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7889 if(!fsp
|| (fsp
->conn
!= conn
)) {
7890 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7895 * Convert the DOS times into unix times.
7898 ft
.atime
= convert_time_t_to_timespec(
7899 srv_make_unix_date2(req
->vwv
+3));
7900 ft
.mtime
= convert_time_t_to_timespec(
7901 srv_make_unix_date2(req
->vwv
+5));
7902 ft
.create_time
= convert_time_t_to_timespec(
7903 srv_make_unix_date2(req
->vwv
+1));
7905 reply_outbuf(req
, 0, 0);
7908 * Patch from Ray Frush <frush@engr.colostate.edu>
7909 * Sometimes times are sent as zero - ignore them.
7912 /* Ensure we have a valid stat struct for the source. */
7913 status
= vfs_stat_fsp(fsp
);
7914 if (!NT_STATUS_IS_OK(status
)) {
7915 reply_nterror(req
, status
);
7919 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
7920 if (!NT_STATUS_IS_OK(status
)) {
7921 reply_nterror(req
, status
);
7925 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7928 (unsigned int)ft
.atime
.tv_sec
,
7929 (unsigned int)ft
.mtime
.tv_sec
,
7930 (unsigned int)ft
.create_time
.tv_sec
7933 END_PROFILE(SMBsetattrE
);
7938 /* Back from the dead for OS/2..... JRA. */
7940 /****************************************************************************
7941 Reply to a SMBwritebmpx (write block multiplex primary) request.
7942 Always reply with an error, if someone has a platform really needs this,
7943 please contact vl@samba.org
7944 ****************************************************************************/
7946 void reply_writebmpx(struct smb_request
*req
)
7948 START_PROFILE(SMBwriteBmpx
);
7949 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7950 END_PROFILE(SMBwriteBmpx
);
7954 /****************************************************************************
7955 Reply to a SMBwritebs (write block multiplex secondary) request.
7956 Always reply with an error, if someone has a platform really needs this,
7957 please contact vl@samba.org
7958 ****************************************************************************/
7960 void reply_writebs(struct smb_request
*req
)
7962 START_PROFILE(SMBwriteBs
);
7963 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7964 END_PROFILE(SMBwriteBs
);
7968 /****************************************************************************
7969 Reply to a SMBgetattrE.
7970 ****************************************************************************/
7972 void reply_getattrE(struct smb_request
*req
)
7974 connection_struct
*conn
= req
->conn
;
7977 struct timespec create_ts
;
7979 START_PROFILE(SMBgetattrE
);
7982 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7983 END_PROFILE(SMBgetattrE
);
7987 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7989 if(!fsp
|| (fsp
->conn
!= conn
)) {
7990 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7991 END_PROFILE(SMBgetattrE
);
7995 /* Do an fstat on this file */
7997 reply_nterror(req
, map_nt_error_from_unix(errno
));
7998 END_PROFILE(SMBgetattrE
);
8002 mode
= dos_mode(conn
, fsp
->fsp_name
);
8005 * Convert the times into dos times. Set create
8006 * date to be last modify date as UNIX doesn't save
8010 reply_outbuf(req
, 11, 0);
8012 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8013 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8014 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8015 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8016 /* Should we check pending modtime here ? JRA */
8017 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8018 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8020 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8021 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8022 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8024 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8025 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
8026 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8028 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8030 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
8032 END_PROFILE(SMBgetattrE
);