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 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1752 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1753 &share_mode
, &create_disposition
,
1754 &create_options
, &private_flags
)) {
1755 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1759 status
= filename_convert(ctx
,
1761 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1763 (create_disposition
== FILE_CREATE
)
1764 ? UCF_CREATING_FILE
: 0,
1767 if (!NT_STATUS_IS_OK(status
)) {
1768 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1769 reply_botherror(req
,
1770 NT_STATUS_PATH_NOT_COVERED
,
1771 ERRSRV
, ERRbadpath
);
1774 reply_nterror(req
, status
);
1778 status
= SMB_VFS_CREATE_FILE(
1781 0, /* root_dir_fid */
1782 smb_fname
, /* fname */
1783 access_mask
, /* access_mask */
1784 share_mode
, /* share_access */
1785 create_disposition
, /* create_disposition*/
1786 create_options
, /* create_options */
1787 dos_attr
, /* file_attributes */
1788 oplock_request
, /* oplock_request */
1789 0, /* allocation_size */
1796 if (!NT_STATUS_IS_OK(status
)) {
1797 if (open_was_deferred(req
->mid
)) {
1798 /* We have re-scheduled this call. */
1801 reply_openerror(req
, status
);
1805 size
= smb_fname
->st
.st_ex_size
;
1806 fattr
= dos_mode(conn
, smb_fname
);
1808 /* Deal with other possible opens having a modified
1810 if (ask_sharemode
) {
1811 struct timespec write_time_ts
;
1813 ZERO_STRUCT(write_time_ts
);
1814 get_file_infos(fsp
->file_id
, 0, NULL
, &write_time_ts
);
1815 if (!null_timespec(write_time_ts
)) {
1816 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1820 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1822 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1823 DEBUG(3,("attempt to open a directory %s\n",
1825 close_file(req
, fsp
, ERROR_CLOSE
);
1826 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1827 ERRDOS
, ERRnoaccess
);
1831 reply_outbuf(req
, 7, 0);
1832 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1833 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1834 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1835 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1837 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1839 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1840 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1842 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1843 SCVAL(req
->outbuf
,smb_flg
,
1844 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1847 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1848 SCVAL(req
->outbuf
,smb_flg
,
1849 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1852 TALLOC_FREE(smb_fname
);
1853 END_PROFILE(SMBopen
);
1857 /****************************************************************************
1858 Reply to an open and X.
1859 ****************************************************************************/
1861 void reply_open_and_X(struct smb_request
*req
)
1863 connection_struct
*conn
= req
->conn
;
1864 struct smb_filename
*smb_fname
= NULL
;
1869 /* Breakout the oplock request bits so we can set the
1870 reply bits separately. */
1871 int ex_oplock_request
;
1872 int core_oplock_request
;
1875 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1876 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
1884 uint64_t allocation_size
;
1885 ssize_t retval
= -1;
1888 uint32 create_disposition
;
1889 uint32 create_options
= 0;
1890 uint32_t private_flags
= 0;
1891 TALLOC_CTX
*ctx
= talloc_tos();
1893 START_PROFILE(SMBopenX
);
1895 if (req
->wct
< 15) {
1896 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1900 open_flags
= SVAL(req
->vwv
+2, 0);
1901 deny_mode
= SVAL(req
->vwv
+3, 0);
1902 smb_attr
= SVAL(req
->vwv
+5, 0);
1903 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1904 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1905 oplock_request
= ex_oplock_request
| core_oplock_request
;
1906 smb_ofun
= SVAL(req
->vwv
+8, 0);
1907 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1909 /* If it's an IPC, pass off the pipe handler. */
1911 if (lp_nt_pipe_support()) {
1912 reply_open_pipe_and_X(conn
, req
);
1914 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1919 /* XXXX we need to handle passed times, sattr and flags */
1920 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1921 STR_TERMINATE
, &status
);
1922 if (!NT_STATUS_IS_OK(status
)) {
1923 reply_nterror(req
, status
);
1927 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1929 &access_mask
, &share_mode
,
1930 &create_disposition
,
1933 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1937 status
= filename_convert(ctx
,
1939 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1941 (create_disposition
== FILE_CREATE
)
1942 ? UCF_CREATING_FILE
: 0,
1945 if (!NT_STATUS_IS_OK(status
)) {
1946 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1947 reply_botherror(req
,
1948 NT_STATUS_PATH_NOT_COVERED
,
1949 ERRSRV
, ERRbadpath
);
1952 reply_nterror(req
, status
);
1956 status
= SMB_VFS_CREATE_FILE(
1959 0, /* root_dir_fid */
1960 smb_fname
, /* fname */
1961 access_mask
, /* access_mask */
1962 share_mode
, /* share_access */
1963 create_disposition
, /* create_disposition*/
1964 create_options
, /* create_options */
1965 smb_attr
, /* file_attributes */
1966 oplock_request
, /* oplock_request */
1967 0, /* allocation_size */
1972 &smb_action
); /* pinfo */
1974 if (!NT_STATUS_IS_OK(status
)) {
1975 if (open_was_deferred(req
->mid
)) {
1976 /* We have re-scheduled this call. */
1979 reply_openerror(req
, status
);
1983 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1984 if the file is truncated or created. */
1985 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1986 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1987 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1988 close_file(req
, fsp
, ERROR_CLOSE
);
1989 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1992 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1994 close_file(req
, fsp
, ERROR_CLOSE
);
1995 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1998 status
= vfs_stat_fsp(fsp
);
1999 if (!NT_STATUS_IS_OK(status
)) {
2000 close_file(req
, fsp
, ERROR_CLOSE
);
2001 reply_nterror(req
, status
);
2006 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2007 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2008 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2009 close_file(req
, fsp
, ERROR_CLOSE
);
2010 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2014 /* If the caller set the extended oplock request bit
2015 and we granted one (by whatever means) - set the
2016 correct bit for extended oplock reply.
2019 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2020 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2023 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2024 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2027 /* If the caller set the core oplock request bit
2028 and we granted one (by whatever means) - set the
2029 correct bit for core oplock reply.
2032 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2033 reply_outbuf(req
, 19, 0);
2035 reply_outbuf(req
, 15, 0);
2038 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2039 SCVAL(req
->outbuf
, smb_flg
,
2040 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2043 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2044 SCVAL(req
->outbuf
, smb_flg
,
2045 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2048 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2049 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2050 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2051 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2053 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2055 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2056 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2057 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2059 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2060 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2065 TALLOC_FREE(smb_fname
);
2066 END_PROFILE(SMBopenX
);
2070 /****************************************************************************
2071 Reply to a SMBulogoffX.
2072 ****************************************************************************/
2074 void reply_ulogoffX(struct smb_request
*req
)
2076 struct smbd_server_connection
*sconn
= req
->sconn
;
2079 START_PROFILE(SMBulogoffX
);
2081 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2084 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2088 /* in user level security we are supposed to close any files
2089 open by this user */
2090 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
2091 file_close_user(sconn
, req
->vuid
);
2094 invalidate_vuid(sconn
, req
->vuid
);
2096 reply_outbuf(req
, 2, 0);
2098 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
2100 END_PROFILE(SMBulogoffX
);
2101 req
->vuid
= UID_FIELD_INVALID
;
2105 /****************************************************************************
2106 Reply to a mknew or a create.
2107 ****************************************************************************/
2109 void reply_mknew(struct smb_request
*req
)
2111 connection_struct
*conn
= req
->conn
;
2112 struct smb_filename
*smb_fname
= NULL
;
2115 struct smb_file_time ft
;
2117 int oplock_request
= 0;
2119 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2120 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2121 uint32 create_disposition
;
2122 uint32 create_options
= 0;
2123 TALLOC_CTX
*ctx
= talloc_tos();
2125 START_PROFILE(SMBcreate
);
2129 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2133 fattr
= SVAL(req
->vwv
+0, 0);
2134 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2137 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2139 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2140 STR_TERMINATE
, &status
);
2141 if (!NT_STATUS_IS_OK(status
)) {
2142 reply_nterror(req
, status
);
2146 status
= filename_convert(ctx
,
2148 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2153 if (!NT_STATUS_IS_OK(status
)) {
2154 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2155 reply_botherror(req
,
2156 NT_STATUS_PATH_NOT_COVERED
,
2157 ERRSRV
, ERRbadpath
);
2160 reply_nterror(req
, status
);
2164 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2165 DEBUG(0,("Attempt to create file (%s) with volid set - "
2166 "please report this\n",
2167 smb_fname_str_dbg(smb_fname
)));
2170 if(req
->cmd
== SMBmknew
) {
2171 /* We should fail if file exists. */
2172 create_disposition
= FILE_CREATE
;
2174 /* Create if file doesn't exist, truncate if it does. */
2175 create_disposition
= FILE_OVERWRITE_IF
;
2178 status
= SMB_VFS_CREATE_FILE(
2181 0, /* root_dir_fid */
2182 smb_fname
, /* fname */
2183 access_mask
, /* access_mask */
2184 share_mode
, /* share_access */
2185 create_disposition
, /* create_disposition*/
2186 create_options
, /* create_options */
2187 fattr
, /* file_attributes */
2188 oplock_request
, /* oplock_request */
2189 0, /* allocation_size */
2190 0, /* private_flags */
2196 if (!NT_STATUS_IS_OK(status
)) {
2197 if (open_was_deferred(req
->mid
)) {
2198 /* We have re-scheduled this call. */
2201 reply_openerror(req
, status
);
2205 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2206 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2207 if (!NT_STATUS_IS_OK(status
)) {
2208 END_PROFILE(SMBcreate
);
2212 reply_outbuf(req
, 1, 0);
2213 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2215 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2216 SCVAL(req
->outbuf
,smb_flg
,
2217 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2220 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2221 SCVAL(req
->outbuf
,smb_flg
,
2222 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2225 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2226 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2227 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2228 (unsigned int)fattr
));
2231 TALLOC_FREE(smb_fname
);
2232 END_PROFILE(SMBcreate
);
2236 /****************************************************************************
2237 Reply to a create temporary file.
2238 ****************************************************************************/
2240 void reply_ctemp(struct smb_request
*req
)
2242 connection_struct
*conn
= req
->conn
;
2243 struct smb_filename
*smb_fname
= NULL
;
2244 char *wire_name
= NULL
;
2252 TALLOC_CTX
*ctx
= talloc_tos();
2254 START_PROFILE(SMBctemp
);
2257 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2261 fattr
= SVAL(req
->vwv
+0, 0);
2262 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2264 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2265 STR_TERMINATE
, &status
);
2266 if (!NT_STATUS_IS_OK(status
)) {
2267 reply_nterror(req
, status
);
2271 for (i
= 0; i
< 10; i
++) {
2273 fname
= talloc_asprintf(ctx
,
2276 generate_random_str_list(ctx
, 5, "0123456789"));
2278 fname
= talloc_asprintf(ctx
,
2280 generate_random_str_list(ctx
, 5, "0123456789"));
2284 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2288 status
= filename_convert(ctx
, conn
,
2289 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2294 if (!NT_STATUS_IS_OK(status
)) {
2295 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2296 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2297 ERRSRV
, ERRbadpath
);
2300 reply_nterror(req
, status
);
2304 /* Create the file. */
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_CREATE
, /* create_disposition*/
2313 0, /* create_options */
2314 fattr
, /* file_attributes */
2315 oplock_request
, /* oplock_request */
2316 0, /* allocation_size */
2317 0, /* private_flags */
2323 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2325 TALLOC_FREE(smb_fname
);
2329 if (!NT_STATUS_IS_OK(status
)) {
2330 if (open_was_deferred(req
->mid
)) {
2331 /* We have re-scheduled this call. */
2334 reply_openerror(req
, status
);
2342 /* Collision after 10 times... */
2343 reply_nterror(req
, status
);
2347 reply_outbuf(req
, 1, 0);
2348 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2350 /* the returned filename is relative to the directory */
2351 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2353 s
= fsp
->fsp_name
->base_name
;
2359 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2360 thing in the byte section. JRA */
2361 SSVALS(p
, 0, -1); /* what is this? not in spec */
2363 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2365 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2369 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2370 SCVAL(req
->outbuf
, smb_flg
,
2371 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2374 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2375 SCVAL(req
->outbuf
, smb_flg
,
2376 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2379 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2380 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2381 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2383 TALLOC_FREE(smb_fname
);
2385 TALLOC_FREE(wire_name
);
2386 END_PROFILE(SMBctemp
);
2390 /*******************************************************************
2391 Check if a user is allowed to rename a file.
2392 ********************************************************************/
2394 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2397 if (!CAN_WRITE(conn
)) {
2398 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2401 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2402 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2403 /* Only bother to read the DOS attribute if we might deny the
2404 rename on the grounds of attribute missmatch. */
2405 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2406 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2407 return NT_STATUS_NO_SUCH_FILE
;
2411 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2412 if (fsp
->posix_open
) {
2413 return NT_STATUS_OK
;
2416 /* If no pathnames are open below this
2417 directory, allow the rename. */
2419 if (file_find_subpath(fsp
)) {
2420 return NT_STATUS_ACCESS_DENIED
;
2422 return NT_STATUS_OK
;
2425 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2426 return NT_STATUS_OK
;
2429 return NT_STATUS_ACCESS_DENIED
;
2432 /*******************************************************************
2433 * unlink a file with all relevant access checks
2434 *******************************************************************/
2436 static NTSTATUS
do_unlink(connection_struct
*conn
,
2437 struct smb_request
*req
,
2438 struct smb_filename
*smb_fname
,
2443 uint32 dirtype_orig
= dirtype
;
2446 bool posix_paths
= lp_posix_pathnames();
2448 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2449 smb_fname_str_dbg(smb_fname
),
2452 if (!CAN_WRITE(conn
)) {
2453 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2457 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2459 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2462 return map_nt_error_from_unix(errno
);
2465 fattr
= dos_mode(conn
, smb_fname
);
2467 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2468 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2471 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2473 return NT_STATUS_NO_SUCH_FILE
;
2476 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2477 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2478 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2480 return NT_STATUS_NO_SUCH_FILE
;
2483 if (dirtype_orig
& 0x8000) {
2484 /* These will never be set for POSIX. */
2485 return NT_STATUS_NO_SUCH_FILE
;
2489 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2490 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2493 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2494 return NT_STATUS_NO_SUCH_FILE
;
2497 if (dirtype
& 0xFF00) {
2498 /* These will never be set for POSIX. */
2499 return NT_STATUS_NO_SUCH_FILE
;
2504 return NT_STATUS_NO_SUCH_FILE
;
2507 /* Can't delete a directory. */
2508 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2509 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2514 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2515 return NT_STATUS_OBJECT_NAME_INVALID
;
2516 #endif /* JRATEST */
2518 /* On open checks the open itself will check the share mode, so
2519 don't do it here as we'll get it wrong. */
2521 status
= SMB_VFS_CREATE_FILE
2524 0, /* root_dir_fid */
2525 smb_fname
, /* fname */
2526 DELETE_ACCESS
, /* access_mask */
2527 FILE_SHARE_NONE
, /* share_access */
2528 FILE_OPEN
, /* create_disposition*/
2529 FILE_NON_DIRECTORY_FILE
, /* create_options */
2530 /* file_attributes */
2531 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2532 FILE_ATTRIBUTE_NORMAL
,
2533 0, /* oplock_request */
2534 0, /* allocation_size */
2535 0, /* private_flags */
2541 if (!NT_STATUS_IS_OK(status
)) {
2542 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2543 nt_errstr(status
)));
2547 status
= can_set_delete_on_close(fsp
, fattr
);
2548 if (!NT_STATUS_IS_OK(status
)) {
2549 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2551 smb_fname_str_dbg(smb_fname
),
2552 nt_errstr(status
)));
2553 close_file(req
, fsp
, NORMAL_CLOSE
);
2557 /* The set is across all open files on this dev/inode pair. */
2558 if (!set_delete_on_close(fsp
, true,
2559 conn
->session_info
->security_token
,
2560 &conn
->session_info
->utok
)) {
2561 close_file(req
, fsp
, NORMAL_CLOSE
);
2562 return NT_STATUS_ACCESS_DENIED
;
2565 return close_file(req
, fsp
, NORMAL_CLOSE
);
2568 /****************************************************************************
2569 The guts of the unlink command, split out so it may be called by the NT SMB
2571 ****************************************************************************/
2573 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2574 uint32 dirtype
, struct smb_filename
*smb_fname
,
2577 char *fname_dir
= NULL
;
2578 char *fname_mask
= NULL
;
2580 NTSTATUS status
= NT_STATUS_OK
;
2581 TALLOC_CTX
*ctx
= talloc_tos();
2583 /* Split up the directory from the filename/mask. */
2584 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2585 &fname_dir
, &fname_mask
);
2586 if (!NT_STATUS_IS_OK(status
)) {
2591 * We should only check the mangled cache
2592 * here if unix_convert failed. This means
2593 * that the path in 'mask' doesn't exist
2594 * on the file system and so we need to look
2595 * for a possible mangle. This patch from
2596 * Tine Smukavec <valentin.smukavec@hermes.si>.
2599 if (!VALID_STAT(smb_fname
->st
) &&
2600 mangle_is_mangled(fname_mask
, conn
->params
)) {
2601 char *new_mask
= NULL
;
2602 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2603 &new_mask
, conn
->params
);
2605 TALLOC_FREE(fname_mask
);
2606 fname_mask
= new_mask
;
2613 * Only one file needs to be unlinked. Append the mask back
2614 * onto the directory.
2616 TALLOC_FREE(smb_fname
->base_name
);
2617 if (ISDOT(fname_dir
)) {
2618 /* Ensure we use canonical names on open. */
2619 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2623 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2628 if (!smb_fname
->base_name
) {
2629 status
= NT_STATUS_NO_MEMORY
;
2633 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2636 status
= check_name(conn
, smb_fname
->base_name
);
2637 if (!NT_STATUS_IS_OK(status
)) {
2641 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2642 if (!NT_STATUS_IS_OK(status
)) {
2648 struct smb_Dir
*dir_hnd
= NULL
;
2650 const char *dname
= NULL
;
2651 char *talloced
= NULL
;
2653 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2654 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2658 if (strequal(fname_mask
,"????????.???")) {
2659 TALLOC_FREE(fname_mask
);
2660 fname_mask
= talloc_strdup(ctx
, "*");
2662 status
= NT_STATUS_NO_MEMORY
;
2667 status
= check_name(conn
, fname_dir
);
2668 if (!NT_STATUS_IS_OK(status
)) {
2672 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2674 if (dir_hnd
== NULL
) {
2675 status
= map_nt_error_from_unix(errno
);
2679 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2680 the pattern matches against the long name, otherwise the short name
2681 We don't implement this yet XXXX
2684 status
= NT_STATUS_NO_SUCH_FILE
;
2686 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2687 &smb_fname
->st
, &talloced
))) {
2688 TALLOC_CTX
*frame
= talloc_stackframe();
2690 if (!is_visible_file(conn
, fname_dir
, dname
,
2691 &smb_fname
->st
, true)) {
2693 TALLOC_FREE(talloced
);
2697 /* Quick check for "." and ".." */
2698 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2700 TALLOC_FREE(talloced
);
2704 if(!mask_match(dname
, fname_mask
,
2705 conn
->case_sensitive
)) {
2707 TALLOC_FREE(talloced
);
2711 TALLOC_FREE(smb_fname
->base_name
);
2712 if (ISDOT(fname_dir
)) {
2713 /* Ensure we use canonical names on open. */
2714 smb_fname
->base_name
=
2715 talloc_asprintf(smb_fname
, "%s",
2718 smb_fname
->base_name
=
2719 talloc_asprintf(smb_fname
, "%s/%s",
2723 if (!smb_fname
->base_name
) {
2724 TALLOC_FREE(dir_hnd
);
2725 status
= NT_STATUS_NO_MEMORY
;
2727 TALLOC_FREE(talloced
);
2731 status
= check_name(conn
, smb_fname
->base_name
);
2732 if (!NT_STATUS_IS_OK(status
)) {
2733 TALLOC_FREE(dir_hnd
);
2735 TALLOC_FREE(talloced
);
2739 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2740 if (!NT_STATUS_IS_OK(status
)) {
2742 TALLOC_FREE(talloced
);
2747 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2748 smb_fname
->base_name
));
2751 TALLOC_FREE(talloced
);
2753 TALLOC_FREE(dir_hnd
);
2756 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2757 status
= map_nt_error_from_unix(errno
);
2761 TALLOC_FREE(fname_dir
);
2762 TALLOC_FREE(fname_mask
);
2766 /****************************************************************************
2768 ****************************************************************************/
2770 void reply_unlink(struct smb_request
*req
)
2772 connection_struct
*conn
= req
->conn
;
2774 struct smb_filename
*smb_fname
= NULL
;
2777 bool path_contains_wcard
= False
;
2778 TALLOC_CTX
*ctx
= talloc_tos();
2780 START_PROFILE(SMBunlink
);
2783 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2787 dirtype
= SVAL(req
->vwv
+0, 0);
2789 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2790 STR_TERMINATE
, &status
,
2791 &path_contains_wcard
);
2792 if (!NT_STATUS_IS_OK(status
)) {
2793 reply_nterror(req
, status
);
2797 status
= filename_convert(ctx
, conn
,
2798 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2800 UCF_COND_ALLOW_WCARD_LCOMP
,
2801 &path_contains_wcard
,
2803 if (!NT_STATUS_IS_OK(status
)) {
2804 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2805 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2806 ERRSRV
, ERRbadpath
);
2809 reply_nterror(req
, status
);
2813 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2815 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2816 path_contains_wcard
);
2817 if (!NT_STATUS_IS_OK(status
)) {
2818 if (open_was_deferred(req
->mid
)) {
2819 /* We have re-scheduled this call. */
2822 reply_nterror(req
, status
);
2826 reply_outbuf(req
, 0, 0);
2828 TALLOC_FREE(smb_fname
);
2829 END_PROFILE(SMBunlink
);
2833 /****************************************************************************
2835 ****************************************************************************/
2837 static void fail_readraw(void)
2839 const char *errstr
= talloc_asprintf(talloc_tos(),
2840 "FAIL ! reply_readbraw: socket write fail (%s)",
2845 exit_server_cleanly(errstr
);
2848 /****************************************************************************
2849 Fake (read/write) sendfile. Returns -1 on read or write fail.
2850 ****************************************************************************/
2852 ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
)
2855 size_t tosend
= nread
;
2862 bufsize
= MIN(nread
, 65536);
2864 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2868 while (tosend
> 0) {
2872 if (tosend
> bufsize
) {
2877 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2883 /* If we had a short read, fill with zeros. */
2884 if (ret
< cur_read
) {
2885 memset(buf
+ ret
, '\0', cur_read
- ret
);
2888 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
2890 char addr
[INET6_ADDRSTRLEN
];
2892 * Try and give an error message saying what
2895 DEBUG(0, ("write_data failed for client %s. "
2897 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
2904 startpos
+= cur_read
;
2908 return (ssize_t
)nread
;
2911 /****************************************************************************
2912 Deal with the case of sendfile reading less bytes from the file than
2913 requested. Fill with zeros (all we can do).
2914 ****************************************************************************/
2916 void sendfile_short_send(files_struct
*fsp
,
2921 #define SHORT_SEND_BUFSIZE 1024
2922 if (nread
< headersize
) {
2923 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2924 "header for file %s (%s). Terminating\n",
2925 fsp_str_dbg(fsp
), strerror(errno
)));
2926 exit_server_cleanly("sendfile_short_send failed");
2929 nread
-= headersize
;
2931 if (nread
< smb_maxcnt
) {
2932 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
2934 exit_server_cleanly("sendfile_short_send: "
2938 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2939 "with zeros !\n", fsp_str_dbg(fsp
)));
2941 while (nread
< smb_maxcnt
) {
2943 * We asked for the real file size and told sendfile
2944 * to not go beyond the end of the file. But it can
2945 * happen that in between our fstat call and the
2946 * sendfile call the file was truncated. This is very
2947 * bad because we have already announced the larger
2948 * number of bytes to the client.
2950 * The best we can do now is to send 0-bytes, just as
2951 * a read from a hole in a sparse file would do.
2953 * This should happen rarely enough that I don't care
2954 * about efficiency here :-)
2958 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
2959 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
2961 char addr
[INET6_ADDRSTRLEN
];
2963 * Try and give an error message saying what
2966 DEBUG(0, ("write_data failed for client %s. "
2969 fsp
->conn
->sconn
->sock
, addr
,
2972 exit_server_cleanly("sendfile_short_send: "
2973 "write_data failed");
2981 /****************************************************************************
2982 Return a readbraw error (4 bytes of zero).
2983 ****************************************************************************/
2985 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
2991 smbd_lock_socket(sconn
);
2992 if (write_data(sconn
->sock
,header
,4) != 4) {
2993 char addr
[INET6_ADDRSTRLEN
];
2995 * Try and give an error message saying what
2998 DEBUG(0, ("write_data failed for client %s. "
3000 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
3005 smbd_unlock_socket(sconn
);
3008 /****************************************************************************
3009 Use sendfile in readbraw.
3010 ****************************************************************************/
3012 static void send_file_readbraw(connection_struct
*conn
,
3013 struct smb_request
*req
,
3019 struct smbd_server_connection
*sconn
= req
->sconn
;
3020 char *outbuf
= NULL
;
3024 * We can only use sendfile on a non-chained packet
3025 * but we can use on a non-oplocked file. tridge proved this
3026 * on a train in Germany :-). JRA.
3027 * reply_readbraw has already checked the length.
3030 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3031 (fsp
->wcp
== NULL
) &&
3032 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3033 ssize_t sendfile_read
= -1;
3035 DATA_BLOB header_blob
;
3037 _smb_setlen(header
,nread
);
3038 header_blob
= data_blob_const(header
, 4);
3040 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3041 &header_blob
, startpos
,
3043 if (sendfile_read
== -1) {
3044 /* Returning ENOSYS means no data at all was sent.
3045 * Do this as a normal read. */
3046 if (errno
== ENOSYS
) {
3047 goto normal_readbraw
;
3051 * Special hack for broken Linux with no working sendfile. If we
3052 * return EINTR we sent the header but not the rest of the data.
3053 * Fake this up by doing read/write calls.
3055 if (errno
== EINTR
) {
3056 /* Ensure we don't do this again. */
3057 set_use_sendfile(SNUM(conn
), False
);
3058 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3060 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3061 DEBUG(0,("send_file_readbraw: "
3062 "fake_sendfile failed for "
3066 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3071 DEBUG(0,("send_file_readbraw: sendfile failed for "
3072 "file %s (%s). Terminating\n",
3073 fsp_str_dbg(fsp
), strerror(errno
)));
3074 exit_server_cleanly("send_file_readbraw sendfile failed");
3075 } else if (sendfile_read
== 0) {
3077 * Some sendfile implementations return 0 to indicate
3078 * that there was a short read, but nothing was
3079 * actually written to the socket. In this case,
3080 * fallback to the normal read path so the header gets
3081 * the correct byte count.
3083 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3084 "bytes falling back to the normal read: "
3085 "%s\n", fsp_str_dbg(fsp
)));
3086 goto normal_readbraw
;
3089 /* Deal with possible short send. */
3090 if (sendfile_read
!= 4+nread
) {
3091 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3098 outbuf
= TALLOC_ARRAY(NULL
, char, nread
+4);
3100 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3101 (unsigned)(nread
+4)));
3102 reply_readbraw_error(sconn
);
3107 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3108 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3117 _smb_setlen(outbuf
,ret
);
3118 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3119 char addr
[INET6_ADDRSTRLEN
];
3121 * Try and give an error message saying what
3124 DEBUG(0, ("write_data failed for client %s. "
3126 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3133 TALLOC_FREE(outbuf
);
3136 /****************************************************************************
3137 Reply to a readbraw (core+ protocol).
3138 ****************************************************************************/
3140 void reply_readbraw(struct smb_request
*req
)
3142 connection_struct
*conn
= req
->conn
;
3143 struct smbd_server_connection
*sconn
= req
->sconn
;
3144 ssize_t maxcount
,mincount
;
3148 struct lock_struct lock
;
3151 START_PROFILE(SMBreadbraw
);
3153 if (srv_is_signing_active(sconn
) || req
->encrypted
) {
3154 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3155 "raw reads/writes are disallowed.");
3159 reply_readbraw_error(sconn
);
3160 END_PROFILE(SMBreadbraw
);
3164 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3165 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3166 "'async smb echo handler = yes'\n"));
3167 reply_readbraw_error(sconn
);
3168 END_PROFILE(SMBreadbraw
);
3173 * Special check if an oplock break has been issued
3174 * and the readraw request croses on the wire, we must
3175 * return a zero length response here.
3178 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3181 * We have to do a check_fsp by hand here, as
3182 * we must always return 4 zero bytes on error,
3186 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3187 req
->vuid
!= fsp
->vuid
||
3188 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3190 * fsp could be NULL here so use the value from the packet. JRA.
3192 DEBUG(3,("reply_readbraw: fnum %d not valid "
3194 (int)SVAL(req
->vwv
+0, 0)));
3195 reply_readbraw_error(sconn
);
3196 END_PROFILE(SMBreadbraw
);
3200 /* Do a "by hand" version of CHECK_READ. */
3201 if (!(fsp
->can_read
||
3202 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3203 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3204 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3205 (int)SVAL(req
->vwv
+0, 0)));
3206 reply_readbraw_error(sconn
);
3207 END_PROFILE(SMBreadbraw
);
3211 flush_write_cache(fsp
, READRAW_FLUSH
);
3213 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3214 if(req
->wct
== 10) {
3216 * This is a large offset (64 bit) read.
3218 #ifdef LARGE_SMB_OFF_T
3220 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+8, 0)) << 32);
3222 #else /* !LARGE_SMB_OFF_T */
3225 * Ensure we haven't been sent a >32 bit offset.
3228 if(IVAL(req
->vwv
+8, 0) != 0) {
3229 DEBUG(0,("reply_readbraw: large offset "
3230 "(%x << 32) used and we don't support "
3231 "64 bit offsets.\n",
3232 (unsigned int)IVAL(req
->vwv
+8, 0) ));
3233 reply_readbraw_error(sconn
);
3234 END_PROFILE(SMBreadbraw
);
3238 #endif /* LARGE_SMB_OFF_T */
3241 DEBUG(0,("reply_readbraw: negative 64 bit "
3242 "readraw offset (%.0f) !\n",
3243 (double)startpos
));
3244 reply_readbraw_error(sconn
);
3245 END_PROFILE(SMBreadbraw
);
3250 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3251 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3253 /* ensure we don't overrun the packet size */
3254 maxcount
= MIN(65535,maxcount
);
3256 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3257 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3260 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3261 reply_readbraw_error(sconn
);
3262 END_PROFILE(SMBreadbraw
);
3266 if (fsp_stat(fsp
) == 0) {
3267 size
= fsp
->fsp_name
->st
.st_ex_size
;
3270 if (startpos
>= size
) {
3273 nread
= MIN(maxcount
,(size
- startpos
));
3276 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3277 if (nread
< mincount
)
3281 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3282 "min=%lu nread=%lu\n",
3283 fsp
->fnum
, (double)startpos
,
3284 (unsigned long)maxcount
,
3285 (unsigned long)mincount
,
3286 (unsigned long)nread
) );
3288 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3290 DEBUG(5,("reply_readbraw finished\n"));
3292 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3294 END_PROFILE(SMBreadbraw
);
3299 #define DBGC_CLASS DBGC_LOCKING
3301 /****************************************************************************
3302 Reply to a lockread (core+ protocol).
3303 ****************************************************************************/
3305 void reply_lockread(struct smb_request
*req
)
3307 connection_struct
*conn
= req
->conn
;
3314 struct byte_range_lock
*br_lck
= NULL
;
3316 struct smbd_server_connection
*sconn
= req
->sconn
;
3318 START_PROFILE(SMBlockread
);
3321 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3322 END_PROFILE(SMBlockread
);
3326 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3328 if (!check_fsp(conn
, req
, fsp
)) {
3329 END_PROFILE(SMBlockread
);
3333 if (!CHECK_READ(fsp
,req
)) {
3334 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3335 END_PROFILE(SMBlockread
);
3339 numtoread
= SVAL(req
->vwv
+1, 0);
3340 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3342 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3344 reply_outbuf(req
, 5, numtoread
+ 3);
3346 data
= smb_buf(req
->outbuf
) + 3;
3349 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3350 * protocol request that predates the read/write lock concept.
3351 * Thus instead of asking for a read lock here we need to ask
3352 * for a write lock. JRA.
3353 * Note that the requested lock size is unaffected by max_recv.
3356 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3358 (uint64_t)req
->smbpid
,
3359 (uint64_t)numtoread
,
3363 False
, /* Non-blocking lock. */
3367 TALLOC_FREE(br_lck
);
3369 if (NT_STATUS_V(status
)) {
3370 reply_nterror(req
, status
);
3371 END_PROFILE(SMBlockread
);
3376 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3379 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3380 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3381 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3382 (unsigned int)numtoread
,
3383 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3384 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3386 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3389 reply_nterror(req
, map_nt_error_from_unix(errno
));
3390 END_PROFILE(SMBlockread
);
3394 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3396 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3397 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3398 p
= smb_buf(req
->outbuf
);
3399 SCVAL(p
,0,0); /* pad byte. */
3402 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3403 fsp
->fnum
, (int)numtoread
, (int)nread
));
3405 END_PROFILE(SMBlockread
);
3410 #define DBGC_CLASS DBGC_ALL
3412 /****************************************************************************
3414 ****************************************************************************/
3416 void reply_read(struct smb_request
*req
)
3418 connection_struct
*conn
= req
->conn
;
3425 struct lock_struct lock
;
3426 struct smbd_server_connection
*sconn
= req
->sconn
;
3428 START_PROFILE(SMBread
);
3431 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3432 END_PROFILE(SMBread
);
3436 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3438 if (!check_fsp(conn
, req
, fsp
)) {
3439 END_PROFILE(SMBread
);
3443 if (!CHECK_READ(fsp
,req
)) {
3444 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3445 END_PROFILE(SMBread
);
3449 numtoread
= SVAL(req
->vwv
+1, 0);
3450 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3452 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3455 * The requested read size cannot be greater than max_recv. JRA.
3457 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3458 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3459 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3460 (unsigned int)numtoread
,
3461 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3462 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3465 reply_outbuf(req
, 5, numtoread
+3);
3467 data
= smb_buf(req
->outbuf
) + 3;
3469 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3470 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3473 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3474 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3475 END_PROFILE(SMBread
);
3480 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3483 reply_nterror(req
, map_nt_error_from_unix(errno
));
3487 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3489 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3490 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3491 SCVAL(smb_buf(req
->outbuf
),0,1);
3492 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3494 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3495 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3498 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3500 END_PROFILE(SMBread
);
3504 /****************************************************************************
3506 ****************************************************************************/
3508 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3514 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3515 data
= smb_buf(outbuf
);
3517 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3519 SCVAL(outbuf
,smb_vwv0
,0xFF);
3520 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3521 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3522 SSVAL(outbuf
,smb_vwv6
,
3524 + 1 /* the wct field */
3525 + 12 * sizeof(uint16_t) /* vwv */
3526 + 2); /* the buflen field */
3527 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3528 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3529 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3530 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3534 /****************************************************************************
3535 Reply to a read and X - possibly using sendfile.
3536 ****************************************************************************/
3538 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3539 files_struct
*fsp
, SMB_OFF_T startpos
,
3543 struct lock_struct lock
;
3544 int saved_errno
= 0;
3546 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3547 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3550 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3551 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
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 !req
->encrypted
&& (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];
3568 if(fsp_stat(fsp
) == -1) {
3569 reply_nterror(req
, map_nt_error_from_unix(errno
));
3573 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3574 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3575 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3577 * We already know that we would do a short read, so don't
3578 * try the sendfile() path.
3580 goto nosendfile_read
;
3584 * Set up the packet header before send. We
3585 * assume here the sendfile will work (get the
3586 * correct amount of data).
3589 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3591 construct_reply_common_req(req
, (char *)headerbuf
);
3592 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3594 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3595 startpos
, smb_maxcnt
);
3597 /* Returning ENOSYS means no data at all was sent.
3598 Do this as a normal read. */
3599 if (errno
== ENOSYS
) {
3604 * Special hack for broken Linux with no working sendfile. If we
3605 * return EINTR we sent the header but not the rest of the data.
3606 * Fake this up by doing read/write calls.
3609 if (errno
== EINTR
) {
3610 /* Ensure we don't do this again. */
3611 set_use_sendfile(SNUM(conn
), False
);
3612 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3613 nread
= fake_sendfile(fsp
, startpos
,
3616 DEBUG(0,("send_file_readX: "
3617 "fake_sendfile failed for "
3621 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3623 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3624 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3625 /* No outbuf here means successful sendfile. */
3629 DEBUG(0,("send_file_readX: sendfile failed for file "
3630 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3632 exit_server_cleanly("send_file_readX sendfile failed");
3633 } else if (nread
== 0) {
3635 * Some sendfile implementations return 0 to indicate
3636 * that there was a short read, but nothing was
3637 * actually written to the socket. In this case,
3638 * fallback to the normal read path so the header gets
3639 * the correct byte count.
3641 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3642 "falling back to the normal read: %s\n",
3647 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3648 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3650 /* Deal with possible short send. */
3651 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3652 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3654 /* No outbuf here means successful sendfile. */
3655 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3656 SMB_PERFCOUNT_END(&req
->pcd
);
3662 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3663 uint8 headerbuf
[smb_size
+ 2*12];
3665 construct_reply_common_req(req
, (char *)headerbuf
);
3666 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3668 /* Send out the header. */
3669 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3670 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3672 char addr
[INET6_ADDRSTRLEN
];
3674 * Try and give an error message saying what
3677 DEBUG(0, ("write_data failed for client %s. "
3679 get_peer_addr(req
->sconn
->sock
, addr
,
3683 DEBUG(0,("send_file_readX: write_data failed for file "
3684 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3686 exit_server_cleanly("send_file_readX sendfile failed");
3688 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3690 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3691 "file %s (%s).\n", fsp_str_dbg(fsp
),
3693 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3700 reply_outbuf(req
, 12, smb_maxcnt
);
3702 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3703 saved_errno
= errno
;
3705 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3708 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3712 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3714 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3715 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3721 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3722 TALLOC_FREE(req
->outbuf
);
3726 /****************************************************************************
3727 Reply to a read and X.
3728 ****************************************************************************/
3730 void reply_read_and_X(struct smb_request
*req
)
3732 connection_struct
*conn
= req
->conn
;
3736 bool big_readX
= False
;
3738 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3741 START_PROFILE(SMBreadX
);
3743 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3744 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3748 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3749 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3750 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3752 /* If it's an IPC, pass off the pipe handler. */
3754 reply_pipe_read_and_X(req
);
3755 END_PROFILE(SMBreadX
);
3759 if (!check_fsp(conn
, req
, fsp
)) {
3760 END_PROFILE(SMBreadX
);
3764 if (!CHECK_READ(fsp
,req
)) {
3765 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3766 END_PROFILE(SMBreadX
);
3770 if (global_client_caps
& CAP_LARGE_READX
) {
3771 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3772 smb_maxcnt
|= (upper_size
<<16);
3773 if (upper_size
> 1) {
3774 /* Can't do this on a chained packet. */
3775 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3776 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3777 END_PROFILE(SMBreadX
);
3780 /* We currently don't do this on signed or sealed data. */
3781 if (srv_is_signing_active(req
->sconn
) || req
->encrypted
) {
3782 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3783 END_PROFILE(SMBreadX
);
3786 /* Is there room in the reply for this data ? */
3787 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3789 NT_STATUS_INVALID_PARAMETER
);
3790 END_PROFILE(SMBreadX
);
3797 if (req
->wct
== 12) {
3798 #ifdef LARGE_SMB_OFF_T
3800 * This is a large offset (64 bit) read.
3802 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+10, 0)) << 32);
3804 #else /* !LARGE_SMB_OFF_T */
3807 * Ensure we haven't been sent a >32 bit offset.
3810 if(IVAL(req
->vwv
+10, 0) != 0) {
3811 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3812 "used and we don't support 64 bit offsets.\n",
3813 (unsigned int)IVAL(req
->vwv
+10, 0) ));
3814 END_PROFILE(SMBreadX
);
3815 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3819 #endif /* LARGE_SMB_OFF_T */
3824 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3829 if (NT_STATUS_IS_OK(status
)) {
3830 /* Read scheduled - we're done. */
3833 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3834 /* Real error - report to client. */
3835 END_PROFILE(SMBreadX
);
3836 reply_nterror(req
, status
);
3839 /* NT_STATUS_RETRY - fall back to sync read. */
3842 smbd_lock_socket(req
->sconn
);
3843 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3844 smbd_unlock_socket(req
->sconn
);
3847 END_PROFILE(SMBreadX
);
3851 /****************************************************************************
3852 Error replies to writebraw must have smb_wct == 1. Fix this up.
3853 ****************************************************************************/
3855 void error_to_writebrawerr(struct smb_request
*req
)
3857 uint8
*old_outbuf
= req
->outbuf
;
3859 reply_outbuf(req
, 1, 0);
3861 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3862 TALLOC_FREE(old_outbuf
);
3865 /****************************************************************************
3866 Read 4 bytes of a smb packet and return the smb length of the packet.
3867 Store the result in the buffer. This version of the function will
3868 never return a session keepalive (length of zero).
3869 Timeout is in milliseconds.
3870 ****************************************************************************/
3872 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3875 uint8_t msgtype
= SMBkeepalive
;
3877 while (msgtype
== SMBkeepalive
) {
3880 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3882 if (!NT_STATUS_IS_OK(status
)) {
3883 char addr
[INET6_ADDRSTRLEN
];
3884 /* Try and give an error message
3885 * saying what client failed. */
3886 DEBUG(0, ("read_fd_with_timeout failed for "
3887 "client %s read error = %s.\n",
3888 get_peer_addr(fd
,addr
,sizeof(addr
)),
3889 nt_errstr(status
)));
3893 msgtype
= CVAL(inbuf
, 0);
3896 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3897 (unsigned long)len
));
3899 return NT_STATUS_OK
;
3902 /****************************************************************************
3903 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3904 ****************************************************************************/
3906 void reply_writebraw(struct smb_request
*req
)
3908 connection_struct
*conn
= req
->conn
;
3911 ssize_t total_written
=0;
3912 size_t numtowrite
=0;
3918 struct lock_struct lock
;
3921 START_PROFILE(SMBwritebraw
);
3924 * If we ever reply with an error, it must have the SMB command
3925 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3928 SCVAL(req
->inbuf
,smb_com
,SMBwritec
);
3930 if (srv_is_signing_active(req
->sconn
)) {
3931 END_PROFILE(SMBwritebraw
);
3932 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3933 "raw reads/writes are disallowed.");
3936 if (req
->wct
< 12) {
3937 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3938 error_to_writebrawerr(req
);
3939 END_PROFILE(SMBwritebraw
);
3943 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3944 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3945 "'async smb echo handler = yes'\n"));
3946 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3947 error_to_writebrawerr(req
);
3948 END_PROFILE(SMBwritebraw
);
3952 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3953 if (!check_fsp(conn
, req
, fsp
)) {
3954 error_to_writebrawerr(req
);
3955 END_PROFILE(SMBwritebraw
);
3959 if (!CHECK_WRITE(fsp
)) {
3960 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3961 error_to_writebrawerr(req
);
3962 END_PROFILE(SMBwritebraw
);
3966 tcount
= IVAL(req
->vwv
+1, 0);
3967 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3968 write_through
= BITSETW(req
->vwv
+7,0);
3970 /* We have to deal with slightly different formats depending
3971 on whether we are using the core+ or lanman1.0 protocol */
3973 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
3974 numtowrite
= SVAL(smb_buf(req
->inbuf
),-2);
3975 data
= smb_buf(req
->inbuf
);
3977 numtowrite
= SVAL(req
->vwv
+10, 0);
3978 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3981 /* Ensure we don't write bytes past the end of this packet. */
3982 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3983 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3984 error_to_writebrawerr(req
);
3985 END_PROFILE(SMBwritebraw
);
3989 if (!fsp
->print_file
) {
3990 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3991 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
3994 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3995 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3996 error_to_writebrawerr(req
);
3997 END_PROFILE(SMBwritebraw
);
4003 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4006 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4007 "wrote=%d sync=%d\n",
4008 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4009 (int)nwritten
, (int)write_through
));
4011 if (nwritten
< (ssize_t
)numtowrite
) {
4012 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4013 error_to_writebrawerr(req
);
4017 total_written
= nwritten
;
4019 /* Allocate a buffer of 64k + length. */
4020 buf
= TALLOC_ARRAY(NULL
, char, 65540);
4022 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4023 error_to_writebrawerr(req
);
4027 /* Return a SMBwritebraw message to the redirector to tell
4028 * it to send more bytes */
4030 memcpy(buf
, req
->inbuf
, smb_size
);
4031 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4032 SCVAL(buf
,smb_com
,SMBwritebraw
);
4033 SSVALS(buf
,smb_vwv0
,0xFFFF);
4035 if (!srv_send_smb(req
->sconn
,
4037 false, 0, /* no signing */
4038 IS_CONN_ENCRYPTED(conn
),
4040 exit_server_cleanly("reply_writebraw: srv_send_smb "
4044 /* Now read the raw data into the buffer and write it */
4045 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4047 if (!NT_STATUS_IS_OK(status
)) {
4048 exit_server_cleanly("secondary writebraw failed");
4051 /* Set up outbuf to return the correct size */
4052 reply_outbuf(req
, 1, 0);
4054 if (numtowrite
!= 0) {
4056 if (numtowrite
> 0xFFFF) {
4057 DEBUG(0,("reply_writebraw: Oversize secondary write "
4058 "raw requested (%u). Terminating\n",
4059 (unsigned int)numtowrite
));
4060 exit_server_cleanly("secondary writebraw failed");
4063 if (tcount
> nwritten
+numtowrite
) {
4064 DEBUG(3,("reply_writebraw: Client overestimated the "
4066 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4069 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4071 if (!NT_STATUS_IS_OK(status
)) {
4072 char addr
[INET6_ADDRSTRLEN
];
4073 /* Try and give an error message
4074 * saying what client failed. */
4075 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4076 "raw read failed (%s) for client %s. "
4077 "Terminating\n", nt_errstr(status
),
4078 get_peer_addr(req
->sconn
->sock
, addr
,
4080 exit_server_cleanly("secondary writebraw failed");
4083 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4084 if (nwritten
== -1) {
4086 reply_nterror(req
, map_nt_error_from_unix(errno
));
4087 error_to_writebrawerr(req
);
4091 if (nwritten
< (ssize_t
)numtowrite
) {
4092 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4093 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4097 total_written
+= nwritten
;
4102 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4104 status
= sync_file(conn
, fsp
, write_through
);
4105 if (!NT_STATUS_IS_OK(status
)) {
4106 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4107 fsp_str_dbg(fsp
), nt_errstr(status
)));
4108 reply_nterror(req
, status
);
4109 error_to_writebrawerr(req
);
4113 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4115 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4116 (int)total_written
));
4118 if (!fsp
->print_file
) {
4119 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4122 /* We won't return a status if write through is not selected - this
4123 * follows what WfWg does */
4124 END_PROFILE(SMBwritebraw
);
4126 if (!write_through
&& total_written
==tcount
) {
4128 #if RABBIT_PELLET_FIX
4130 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4131 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4134 if (!send_keepalive(req
->sconn
->sock
)) {
4135 exit_server_cleanly("reply_writebraw: send of "
4136 "keepalive failed");
4139 TALLOC_FREE(req
->outbuf
);
4144 if (!fsp
->print_file
) {
4145 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4148 END_PROFILE(SMBwritebraw
);
4153 #define DBGC_CLASS DBGC_LOCKING
4155 /****************************************************************************
4156 Reply to a writeunlock (core+).
4157 ****************************************************************************/
4159 void reply_writeunlock(struct smb_request
*req
)
4161 connection_struct
*conn
= req
->conn
;
4162 ssize_t nwritten
= -1;
4166 NTSTATUS status
= NT_STATUS_OK
;
4168 struct lock_struct lock
;
4169 int saved_errno
= 0;
4171 START_PROFILE(SMBwriteunlock
);
4174 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4175 END_PROFILE(SMBwriteunlock
);
4179 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4181 if (!check_fsp(conn
, req
, fsp
)) {
4182 END_PROFILE(SMBwriteunlock
);
4186 if (!CHECK_WRITE(fsp
)) {
4187 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4188 END_PROFILE(SMBwriteunlock
);
4192 numtowrite
= SVAL(req
->vwv
+1, 0);
4193 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4194 data
= (const char *)req
->buf
+ 3;
4196 if (!fsp
->print_file
&& numtowrite
> 0) {
4197 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4198 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4201 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4202 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4203 END_PROFILE(SMBwriteunlock
);
4208 /* The special X/Open SMB protocol handling of
4209 zero length writes is *NOT* done for
4211 if(numtowrite
== 0) {
4214 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4215 saved_errno
= errno
;
4218 status
= sync_file(conn
, fsp
, False
/* write through */);
4219 if (!NT_STATUS_IS_OK(status
)) {
4220 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4221 fsp_str_dbg(fsp
), nt_errstr(status
)));
4222 reply_nterror(req
, status
);
4227 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4231 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4232 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4236 if (numtowrite
&& !fsp
->print_file
) {
4237 status
= do_unlock(req
->sconn
->msg_ctx
,
4239 (uint64_t)req
->smbpid
,
4240 (uint64_t)numtowrite
,
4244 if (NT_STATUS_V(status
)) {
4245 reply_nterror(req
, status
);
4250 reply_outbuf(req
, 1, 0);
4252 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4254 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4255 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4258 if (numtowrite
&& !fsp
->print_file
) {
4259 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4262 END_PROFILE(SMBwriteunlock
);
4267 #define DBGC_CLASS DBGC_ALL
4269 /****************************************************************************
4271 ****************************************************************************/
4273 void reply_write(struct smb_request
*req
)
4275 connection_struct
*conn
= req
->conn
;
4277 ssize_t nwritten
= -1;
4281 struct lock_struct lock
;
4283 int saved_errno
= 0;
4285 START_PROFILE(SMBwrite
);
4288 END_PROFILE(SMBwrite
);
4289 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4293 /* If it's an IPC, pass off the pipe handler. */
4295 reply_pipe_write(req
);
4296 END_PROFILE(SMBwrite
);
4300 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4302 if (!check_fsp(conn
, req
, fsp
)) {
4303 END_PROFILE(SMBwrite
);
4307 if (!CHECK_WRITE(fsp
)) {
4308 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4309 END_PROFILE(SMBwrite
);
4313 numtowrite
= SVAL(req
->vwv
+1, 0);
4314 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4315 data
= (const char *)req
->buf
+ 3;
4317 if (!fsp
->print_file
) {
4318 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4319 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4322 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4323 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4324 END_PROFILE(SMBwrite
);
4330 * X/Open SMB protocol says that if smb_vwv1 is
4331 * zero then the file size should be extended or
4332 * truncated to the size given in smb_vwv[2-3].
4335 if(numtowrite
== 0) {
4337 * This is actually an allocate call, and set EOF. JRA.
4339 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
4341 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4344 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
4346 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4349 trigger_write_time_update_immediate(fsp
);
4351 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4354 status
= sync_file(conn
, fsp
, False
);
4355 if (!NT_STATUS_IS_OK(status
)) {
4356 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4357 fsp_str_dbg(fsp
), nt_errstr(status
)));
4358 reply_nterror(req
, status
);
4363 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4367 if((nwritten
== 0) && (numtowrite
!= 0)) {
4368 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4372 reply_outbuf(req
, 1, 0);
4374 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4376 if (nwritten
< (ssize_t
)numtowrite
) {
4377 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4378 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4381 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4384 if (!fsp
->print_file
) {
4385 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4388 END_PROFILE(SMBwrite
);
4392 /****************************************************************************
4393 Ensure a buffer is a valid writeX for recvfile purposes.
4394 ****************************************************************************/
4396 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4397 (2*14) + /* word count (including bcc) */ \
4400 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4401 const uint8_t *inbuf
)
4404 connection_struct
*conn
= NULL
;
4405 unsigned int doff
= 0;
4406 size_t len
= smb_len_large(inbuf
);
4408 if (is_encrypted_packet(inbuf
)) {
4409 /* Can't do this on encrypted
4414 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4418 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4419 CVAL(inbuf
,smb_wct
) != 14) {
4420 DEBUG(10,("is_valid_writeX_buffer: chained or "
4421 "invalid word length.\n"));
4425 conn
= conn_find(sconn
, SVAL(inbuf
, smb_tid
));
4427 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4431 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4434 if (IS_PRINT(conn
)) {
4435 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4438 doff
= SVAL(inbuf
,smb_vwv11
);
4440 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4442 if (len
> doff
&& len
- doff
> 0xFFFF) {
4443 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4446 if (numtowrite
== 0) {
4447 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4451 /* Ensure the sizes match up. */
4452 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4453 /* no pad byte...old smbclient :-( */
4454 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4456 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4460 if (len
- doff
!= numtowrite
) {
4461 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4462 "len = %u, doff = %u, numtowrite = %u\n",
4465 (unsigned int)numtowrite
));
4469 DEBUG(10,("is_valid_writeX_buffer: true "
4470 "len = %u, doff = %u, numtowrite = %u\n",
4473 (unsigned int)numtowrite
));
4478 /****************************************************************************
4479 Reply to a write and X.
4480 ****************************************************************************/
4482 void reply_write_and_X(struct smb_request
*req
)
4484 connection_struct
*conn
= req
->conn
;
4486 struct lock_struct lock
;
4491 unsigned int smb_doff
;
4492 unsigned int smblen
;
4495 int saved_errno
= 0;
4497 START_PROFILE(SMBwriteX
);
4499 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4500 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4501 END_PROFILE(SMBwriteX
);
4505 numtowrite
= SVAL(req
->vwv
+10, 0);
4506 smb_doff
= SVAL(req
->vwv
+11, 0);
4507 smblen
= smb_len(req
->inbuf
);
4509 if (req
->unread_bytes
> 0xFFFF ||
4510 (smblen
> smb_doff
&&
4511 smblen
- smb_doff
> 0xFFFF)) {
4512 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4515 if (req
->unread_bytes
) {
4516 /* Can't do a recvfile write on IPC$ */
4518 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4519 END_PROFILE(SMBwriteX
);
4522 if (numtowrite
!= req
->unread_bytes
) {
4523 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4524 END_PROFILE(SMBwriteX
);
4528 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4529 smb_doff
+ numtowrite
> smblen
) {
4530 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4531 END_PROFILE(SMBwriteX
);
4536 /* If it's an IPC, pass off the pipe handler. */
4538 if (req
->unread_bytes
) {
4539 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4540 END_PROFILE(SMBwriteX
);
4543 reply_pipe_write_and_X(req
);
4544 END_PROFILE(SMBwriteX
);
4548 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4549 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4550 write_through
= BITSETW(req
->vwv
+7,0);
4552 if (!check_fsp(conn
, req
, fsp
)) {
4553 END_PROFILE(SMBwriteX
);
4557 if (!CHECK_WRITE(fsp
)) {
4558 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4559 END_PROFILE(SMBwriteX
);
4563 data
= smb_base(req
->inbuf
) + smb_doff
;
4565 if(req
->wct
== 14) {
4566 #ifdef LARGE_SMB_OFF_T
4568 * This is a large offset (64 bit) write.
4570 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+12, 0)) << 32);
4572 #else /* !LARGE_SMB_OFF_T */
4575 * Ensure we haven't been sent a >32 bit offset.
4578 if(IVAL(req
->vwv
+12, 0) != 0) {
4579 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4580 "used and we don't support 64 bit offsets.\n",
4581 (unsigned int)IVAL(req
->vwv
+12, 0) ));
4582 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4583 END_PROFILE(SMBwriteX
);
4587 #endif /* LARGE_SMB_OFF_T */
4590 /* X/Open SMB protocol says that, unlike SMBwrite
4591 if the length is zero then NO truncation is
4592 done, just a write of zero. To truncate a file,
4595 if(numtowrite
== 0) {
4598 if (req
->unread_bytes
== 0) {
4599 status
= schedule_aio_write_and_X(conn
,
4606 if (NT_STATUS_IS_OK(status
)) {
4607 /* write scheduled - we're done. */
4610 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4611 /* Real error - report to client. */
4612 reply_nterror(req
, status
);
4615 /* NT_STATUS_RETRY - fall through to sync write. */
4618 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4619 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4622 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4623 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4627 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4628 saved_errno
= errno
;
4630 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4634 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4638 if((nwritten
== 0) && (numtowrite
!= 0)) {
4639 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4643 reply_outbuf(req
, 6, 0);
4644 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4645 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4647 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4648 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4650 status
= sync_file(conn
, fsp
, write_through
);
4651 if (!NT_STATUS_IS_OK(status
)) {
4652 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4653 fsp_str_dbg(fsp
), nt_errstr(status
)));
4654 reply_nterror(req
, status
);
4658 END_PROFILE(SMBwriteX
);
4663 END_PROFILE(SMBwriteX
);
4667 /****************************************************************************
4669 ****************************************************************************/
4671 void reply_lseek(struct smb_request
*req
)
4673 connection_struct
*conn
= req
->conn
;
4679 START_PROFILE(SMBlseek
);
4682 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4683 END_PROFILE(SMBlseek
);
4687 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4689 if (!check_fsp(conn
, req
, fsp
)) {
4693 flush_write_cache(fsp
, SEEK_FLUSH
);
4695 mode
= SVAL(req
->vwv
+1, 0) & 3;
4696 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4697 startpos
= (SMB_OFF_T
)IVALS(req
->vwv
+2, 0);
4706 res
= fsp
->fh
->pos
+ startpos
;
4717 if (umode
== SEEK_END
) {
4718 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4719 if(errno
== EINVAL
) {
4720 SMB_OFF_T current_pos
= startpos
;
4722 if(fsp_stat(fsp
) == -1) {
4724 map_nt_error_from_unix(errno
));
4725 END_PROFILE(SMBlseek
);
4729 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4731 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4736 reply_nterror(req
, map_nt_error_from_unix(errno
));
4737 END_PROFILE(SMBlseek
);
4744 reply_outbuf(req
, 2, 0);
4745 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4747 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4748 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4750 END_PROFILE(SMBlseek
);
4754 /****************************************************************************
4756 ****************************************************************************/
4758 void reply_flush(struct smb_request
*req
)
4760 connection_struct
*conn
= req
->conn
;
4764 START_PROFILE(SMBflush
);
4767 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4771 fnum
= SVAL(req
->vwv
+0, 0);
4772 fsp
= file_fsp(req
, fnum
);
4774 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4779 file_sync_all(conn
);
4781 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4782 if (!NT_STATUS_IS_OK(status
)) {
4783 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4784 fsp_str_dbg(fsp
), nt_errstr(status
)));
4785 reply_nterror(req
, status
);
4786 END_PROFILE(SMBflush
);
4791 reply_outbuf(req
, 0, 0);
4793 DEBUG(3,("flush\n"));
4794 END_PROFILE(SMBflush
);
4798 /****************************************************************************
4800 conn POINTER CAN BE NULL HERE !
4801 ****************************************************************************/
4803 void reply_exit(struct smb_request
*req
)
4805 START_PROFILE(SMBexit
);
4807 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
4809 reply_outbuf(req
, 0, 0);
4811 DEBUG(3,("exit\n"));
4813 END_PROFILE(SMBexit
);
4817 /****************************************************************************
4818 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4819 ****************************************************************************/
4821 void reply_close(struct smb_request
*req
)
4823 connection_struct
*conn
= req
->conn
;
4824 NTSTATUS status
= NT_STATUS_OK
;
4825 files_struct
*fsp
= NULL
;
4826 START_PROFILE(SMBclose
);
4829 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4830 END_PROFILE(SMBclose
);
4834 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4837 * We can only use check_fsp if we know it's not a directory.
4840 if (!check_fsp_open(conn
, req
, fsp
)) {
4841 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4842 END_PROFILE(SMBclose
);
4846 if(fsp
->is_directory
) {
4848 * Special case - close NT SMB directory handle.
4850 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4851 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4855 * Close ordinary file.
4858 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4859 fsp
->fh
->fd
, fsp
->fnum
,
4860 conn
->num_files_open
));
4863 * Take care of any time sent in the close.
4866 t
= srv_make_unix_date3(req
->vwv
+1);
4867 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4870 * close_file() returns the unix errno if an error
4871 * was detected on close - normally this is due to
4872 * a disk full error. If not then it was probably an I/O error.
4875 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4878 if (!NT_STATUS_IS_OK(status
)) {
4879 reply_nterror(req
, status
);
4880 END_PROFILE(SMBclose
);
4884 reply_outbuf(req
, 0, 0);
4885 END_PROFILE(SMBclose
);
4889 /****************************************************************************
4890 Reply to a writeclose (Core+ protocol).
4891 ****************************************************************************/
4893 void reply_writeclose(struct smb_request
*req
)
4895 connection_struct
*conn
= req
->conn
;
4897 ssize_t nwritten
= -1;
4898 NTSTATUS close_status
= NT_STATUS_OK
;
4901 struct timespec mtime
;
4903 struct lock_struct lock
;
4905 START_PROFILE(SMBwriteclose
);
4908 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4909 END_PROFILE(SMBwriteclose
);
4913 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4915 if (!check_fsp(conn
, req
, fsp
)) {
4916 END_PROFILE(SMBwriteclose
);
4919 if (!CHECK_WRITE(fsp
)) {
4920 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4921 END_PROFILE(SMBwriteclose
);
4925 numtowrite
= SVAL(req
->vwv
+1, 0);
4926 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4927 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4928 data
= (const char *)req
->buf
+ 1;
4930 if (!fsp
->print_file
) {
4931 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4932 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4935 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4936 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4937 END_PROFILE(SMBwriteclose
);
4942 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4944 set_close_write_time(fsp
, mtime
);
4947 * More insanity. W2K only closes the file if writelen > 0.
4952 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4953 "file %s\n", fsp_str_dbg(fsp
)));
4954 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4957 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4958 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4959 conn
->num_files_open
));
4961 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4962 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4966 if(!NT_STATUS_IS_OK(close_status
)) {
4967 reply_nterror(req
, close_status
);
4971 reply_outbuf(req
, 1, 0);
4973 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4976 if (numtowrite
&& !fsp
->print_file
) {
4977 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4980 END_PROFILE(SMBwriteclose
);
4985 #define DBGC_CLASS DBGC_LOCKING
4987 /****************************************************************************
4989 ****************************************************************************/
4991 void reply_lock(struct smb_request
*req
)
4993 connection_struct
*conn
= req
->conn
;
4994 uint64_t count
,offset
;
4997 struct byte_range_lock
*br_lck
= NULL
;
4999 START_PROFILE(SMBlock
);
5002 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5003 END_PROFILE(SMBlock
);
5007 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5009 if (!check_fsp(conn
, req
, fsp
)) {
5010 END_PROFILE(SMBlock
);
5014 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5015 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5017 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5018 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
5020 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5022 (uint64_t)req
->smbpid
,
5027 False
, /* Non-blocking lock. */
5032 TALLOC_FREE(br_lck
);
5034 if (NT_STATUS_V(status
)) {
5035 reply_nterror(req
, status
);
5036 END_PROFILE(SMBlock
);
5040 reply_outbuf(req
, 0, 0);
5042 END_PROFILE(SMBlock
);
5046 /****************************************************************************
5048 ****************************************************************************/
5050 void reply_unlock(struct smb_request
*req
)
5052 connection_struct
*conn
= req
->conn
;
5053 uint64_t count
,offset
;
5057 START_PROFILE(SMBunlock
);
5060 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5061 END_PROFILE(SMBunlock
);
5065 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5067 if (!check_fsp(conn
, req
, fsp
)) {
5068 END_PROFILE(SMBunlock
);
5072 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5073 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5075 status
= do_unlock(req
->sconn
->msg_ctx
,
5077 (uint64_t)req
->smbpid
,
5082 if (NT_STATUS_V(status
)) {
5083 reply_nterror(req
, status
);
5084 END_PROFILE(SMBunlock
);
5088 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5089 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
5091 reply_outbuf(req
, 0, 0);
5093 END_PROFILE(SMBunlock
);
5098 #define DBGC_CLASS DBGC_ALL
5100 /****************************************************************************
5102 conn POINTER CAN BE NULL HERE !
5103 ****************************************************************************/
5105 void reply_tdis(struct smb_request
*req
)
5107 connection_struct
*conn
= req
->conn
;
5108 START_PROFILE(SMBtdis
);
5111 DEBUG(4,("Invalid connection in tdis\n"));
5112 reply_nterror(req
, NT_STATUS_NETWORK_NAME_DELETED
);
5113 END_PROFILE(SMBtdis
);
5119 close_cnum(conn
,req
->vuid
);
5122 reply_outbuf(req
, 0, 0);
5123 END_PROFILE(SMBtdis
);
5127 /****************************************************************************
5129 conn POINTER CAN BE NULL HERE !
5130 ****************************************************************************/
5132 void reply_echo(struct smb_request
*req
)
5134 connection_struct
*conn
= req
->conn
;
5135 struct smb_perfcount_data local_pcd
;
5136 struct smb_perfcount_data
*cur_pcd
;
5140 START_PROFILE(SMBecho
);
5142 smb_init_perfcount_data(&local_pcd
);
5145 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5146 END_PROFILE(SMBecho
);
5150 smb_reverb
= SVAL(req
->vwv
+0, 0);
5152 reply_outbuf(req
, 1, req
->buflen
);
5154 /* copy any incoming data back out */
5155 if (req
->buflen
> 0) {
5156 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5159 if (smb_reverb
> 100) {
5160 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5164 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5166 /* this makes sure we catch the request pcd */
5167 if (seq_num
== smb_reverb
) {
5168 cur_pcd
= &req
->pcd
;
5170 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5171 cur_pcd
= &local_pcd
;
5174 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5176 show_msg((char *)req
->outbuf
);
5177 if (!srv_send_smb(req
->sconn
,
5178 (char *)req
->outbuf
,
5179 true, req
->seqnum
+1,
5180 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5182 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5185 DEBUG(3,("echo %d times\n", smb_reverb
));
5187 TALLOC_FREE(req
->outbuf
);
5189 END_PROFILE(SMBecho
);
5193 /****************************************************************************
5194 Reply to a printopen.
5195 ****************************************************************************/
5197 void reply_printopen(struct smb_request
*req
)
5199 connection_struct
*conn
= req
->conn
;
5203 START_PROFILE(SMBsplopen
);
5206 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5207 END_PROFILE(SMBsplopen
);
5211 if (!CAN_PRINT(conn
)) {
5212 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5213 END_PROFILE(SMBsplopen
);
5217 status
= file_new(req
, conn
, &fsp
);
5218 if(!NT_STATUS_IS_OK(status
)) {
5219 reply_nterror(req
, status
);
5220 END_PROFILE(SMBsplopen
);
5224 /* Open for exclusive use, write only. */
5225 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5227 if (!NT_STATUS_IS_OK(status
)) {
5228 file_free(req
, fsp
);
5229 reply_nterror(req
, status
);
5230 END_PROFILE(SMBsplopen
);
5234 reply_outbuf(req
, 1, 0);
5235 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5237 DEBUG(3,("openprint fd=%d fnum=%d\n",
5238 fsp
->fh
->fd
, fsp
->fnum
));
5240 END_PROFILE(SMBsplopen
);
5244 /****************************************************************************
5245 Reply to a printclose.
5246 ****************************************************************************/
5248 void reply_printclose(struct smb_request
*req
)
5250 connection_struct
*conn
= req
->conn
;
5254 START_PROFILE(SMBsplclose
);
5257 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5258 END_PROFILE(SMBsplclose
);
5262 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5264 if (!check_fsp(conn
, req
, fsp
)) {
5265 END_PROFILE(SMBsplclose
);
5269 if (!CAN_PRINT(conn
)) {
5270 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5271 END_PROFILE(SMBsplclose
);
5275 DEBUG(3,("printclose fd=%d fnum=%d\n",
5276 fsp
->fh
->fd
,fsp
->fnum
));
5278 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5280 if(!NT_STATUS_IS_OK(status
)) {
5281 reply_nterror(req
, status
);
5282 END_PROFILE(SMBsplclose
);
5286 reply_outbuf(req
, 0, 0);
5288 END_PROFILE(SMBsplclose
);
5292 /****************************************************************************
5293 Reply to a printqueue.
5294 ****************************************************************************/
5296 void reply_printqueue(struct smb_request
*req
)
5298 connection_struct
*conn
= req
->conn
;
5302 START_PROFILE(SMBsplretq
);
5305 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5306 END_PROFILE(SMBsplretq
);
5310 max_count
= SVAL(req
->vwv
+0, 0);
5311 start_index
= SVAL(req
->vwv
+1, 0);
5313 /* we used to allow the client to get the cnum wrong, but that
5314 is really quite gross and only worked when there was only
5315 one printer - I think we should now only accept it if they
5316 get it right (tridge) */
5317 if (!CAN_PRINT(conn
)) {
5318 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5319 END_PROFILE(SMBsplretq
);
5323 reply_outbuf(req
, 2, 3);
5324 SSVAL(req
->outbuf
,smb_vwv0
,0);
5325 SSVAL(req
->outbuf
,smb_vwv1
,0);
5326 SCVAL(smb_buf(req
->outbuf
),0,1);
5327 SSVAL(smb_buf(req
->outbuf
),1,0);
5329 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5330 start_index
, max_count
));
5333 TALLOC_CTX
*mem_ctx
= talloc_tos();
5336 const char *sharename
= lp_servicename(SNUM(conn
));
5337 struct rpc_pipe_client
*cli
= NULL
;
5338 struct dcerpc_binding_handle
*b
= NULL
;
5339 struct policy_handle handle
;
5340 struct spoolss_DevmodeContainer devmode_ctr
;
5341 union spoolss_JobInfo
*info
;
5343 uint32_t num_to_get
;
5347 ZERO_STRUCT(handle
);
5349 status
= rpc_pipe_open_interface(conn
,
5350 &ndr_table_spoolss
.syntax_id
,
5352 &conn
->sconn
->client_id
,
5353 conn
->sconn
->msg_ctx
,
5355 if (!NT_STATUS_IS_OK(status
)) {
5356 DEBUG(0, ("reply_printqueue: "
5357 "could not connect to spoolss: %s\n",
5358 nt_errstr(status
)));
5359 reply_nterror(req
, status
);
5362 b
= cli
->binding_handle
;
5364 ZERO_STRUCT(devmode_ctr
);
5366 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5369 SEC_FLAG_MAXIMUM_ALLOWED
,
5372 if (!NT_STATUS_IS_OK(status
)) {
5373 reply_nterror(req
, status
);
5376 if (!W_ERROR_IS_OK(werr
)) {
5377 reply_nterror(req
, werror_to_ntstatus(werr
));
5381 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5389 if (!W_ERROR_IS_OK(werr
)) {
5390 reply_nterror(req
, werror_to_ntstatus(werr
));
5394 if (max_count
> 0) {
5395 first
= start_index
;
5397 first
= start_index
+ max_count
+ 1;
5400 if (first
>= count
) {
5403 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5406 for (i
= first
; i
< num_to_get
; i
++) {
5409 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5411 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5412 info
[i
].info2
.job_id
);
5414 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5420 srv_put_dos_date2(p
, 0, qtime
);
5421 SCVAL(p
, 4, qstatus
);
5422 SSVAL(p
, 5, qrapjobid
);
5423 SIVAL(p
, 7, info
[i
].info2
.size
);
5425 srvstr_push(blob
, req
->flags2
, p
+12,
5426 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5428 if (message_push_blob(
5431 blob
, sizeof(blob
))) == -1) {
5432 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5438 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5439 SSVAL(req
->outbuf
,smb_vwv1
,
5440 (max_count
>0?first
+count
:first
-1));
5441 SCVAL(smb_buf(req
->outbuf
),0,1);
5442 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5446 DEBUG(3, ("%u entries returned in queue\n",
5450 if (b
&& is_valid_policy_hnd(&handle
)) {
5451 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5456 END_PROFILE(SMBsplretq
);
5460 /****************************************************************************
5461 Reply to a printwrite.
5462 ****************************************************************************/
5464 void reply_printwrite(struct smb_request
*req
)
5466 connection_struct
*conn
= req
->conn
;
5471 START_PROFILE(SMBsplwr
);
5474 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5475 END_PROFILE(SMBsplwr
);
5479 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5481 if (!check_fsp(conn
, req
, fsp
)) {
5482 END_PROFILE(SMBsplwr
);
5486 if (!fsp
->print_file
) {
5487 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5488 END_PROFILE(SMBsplwr
);
5492 if (!CHECK_WRITE(fsp
)) {
5493 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5494 END_PROFILE(SMBsplwr
);
5498 numtowrite
= SVAL(req
->buf
, 1);
5500 if (req
->buflen
< numtowrite
+ 3) {
5501 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5502 END_PROFILE(SMBsplwr
);
5506 data
= (const char *)req
->buf
+ 3;
5508 if (write_file(req
,fsp
,data
,(SMB_OFF_T
)-1,numtowrite
) != numtowrite
) {
5509 reply_nterror(req
, map_nt_error_from_unix(errno
));
5510 END_PROFILE(SMBsplwr
);
5514 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
5516 END_PROFILE(SMBsplwr
);
5520 /****************************************************************************
5522 ****************************************************************************/
5524 void reply_mkdir(struct smb_request
*req
)
5526 connection_struct
*conn
= req
->conn
;
5527 struct smb_filename
*smb_dname
= NULL
;
5528 char *directory
= NULL
;
5530 TALLOC_CTX
*ctx
= talloc_tos();
5532 START_PROFILE(SMBmkdir
);
5534 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5535 STR_TERMINATE
, &status
);
5536 if (!NT_STATUS_IS_OK(status
)) {
5537 reply_nterror(req
, status
);
5541 status
= filename_convert(ctx
, conn
,
5542 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5547 if (!NT_STATUS_IS_OK(status
)) {
5548 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5549 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5550 ERRSRV
, ERRbadpath
);
5553 reply_nterror(req
, status
);
5557 status
= create_directory(conn
, req
, smb_dname
);
5559 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5561 if (!NT_STATUS_IS_OK(status
)) {
5563 if (!use_nt_status()
5564 && NT_STATUS_EQUAL(status
,
5565 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5567 * Yes, in the DOS error code case we get a
5568 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5569 * samba4 torture test.
5571 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5574 reply_nterror(req
, status
);
5578 reply_outbuf(req
, 0, 0);
5580 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5582 TALLOC_FREE(smb_dname
);
5583 END_PROFILE(SMBmkdir
);
5587 /****************************************************************************
5589 ****************************************************************************/
5591 void reply_rmdir(struct smb_request
*req
)
5593 connection_struct
*conn
= req
->conn
;
5594 struct smb_filename
*smb_dname
= NULL
;
5595 char *directory
= NULL
;
5597 TALLOC_CTX
*ctx
= talloc_tos();
5598 files_struct
*fsp
= NULL
;
5600 struct smbd_server_connection
*sconn
= req
->sconn
;
5602 START_PROFILE(SMBrmdir
);
5604 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5605 STR_TERMINATE
, &status
);
5606 if (!NT_STATUS_IS_OK(status
)) {
5607 reply_nterror(req
, status
);
5611 status
= filename_convert(ctx
, conn
,
5612 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5617 if (!NT_STATUS_IS_OK(status
)) {
5618 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5619 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5620 ERRSRV
, ERRbadpath
);
5623 reply_nterror(req
, status
);
5627 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5628 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5632 status
= SMB_VFS_CREATE_FILE(
5635 0, /* root_dir_fid */
5636 smb_dname
, /* fname */
5637 DELETE_ACCESS
, /* access_mask */
5638 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5640 FILE_OPEN
, /* create_disposition*/
5641 FILE_DIRECTORY_FILE
, /* create_options */
5642 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5643 0, /* oplock_request */
5644 0, /* allocation_size */
5645 0, /* private_flags */
5651 if (!NT_STATUS_IS_OK(status
)) {
5652 if (open_was_deferred(req
->mid
)) {
5653 /* We have re-scheduled this call. */
5656 reply_nterror(req
, status
);
5660 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5661 if (!NT_STATUS_IS_OK(status
)) {
5662 close_file(req
, fsp
, ERROR_CLOSE
);
5663 reply_nterror(req
, status
);
5667 if (!set_delete_on_close(fsp
, true,
5668 conn
->session_info
->security_token
,
5669 &conn
->session_info
->utok
)) {
5670 close_file(req
, fsp
, ERROR_CLOSE
);
5671 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5675 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5676 if (!NT_STATUS_IS_OK(status
)) {
5677 reply_nterror(req
, status
);
5679 reply_outbuf(req
, 0, 0);
5682 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5684 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5686 TALLOC_FREE(smb_dname
);
5687 END_PROFILE(SMBrmdir
);
5691 /*******************************************************************
5692 Resolve wildcards in a filename rename.
5693 ********************************************************************/
5695 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5700 char *name2_copy
= NULL
;
5705 char *p
,*p2
, *pname1
, *pname2
;
5707 name2_copy
= talloc_strdup(ctx
, name2
);
5712 pname1
= strrchr_m(name1
,'/');
5713 pname2
= strrchr_m(name2_copy
,'/');
5715 if (!pname1
|| !pname2
) {
5719 /* Truncate the copy of name2 at the last '/' */
5722 /* Now go past the '/' */
5726 root1
= talloc_strdup(ctx
, pname1
);
5727 root2
= talloc_strdup(ctx
, pname2
);
5729 if (!root1
|| !root2
) {
5733 p
= strrchr_m(root1
,'.');
5736 ext1
= talloc_strdup(ctx
, p
+1);
5738 ext1
= talloc_strdup(ctx
, "");
5740 p
= strrchr_m(root2
,'.');
5743 ext2
= talloc_strdup(ctx
, p
+1);
5745 ext2
= talloc_strdup(ctx
, "");
5748 if (!ext1
|| !ext2
) {
5756 /* Hmmm. Should this be mb-aware ? */
5759 } else if (*p2
== '*') {
5761 root2
= talloc_asprintf(ctx
, "%s%s",
5780 /* Hmmm. Should this be mb-aware ? */
5783 } else if (*p2
== '*') {
5785 ext2
= talloc_asprintf(ctx
, "%s%s",
5801 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5806 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5818 /****************************************************************************
5819 Ensure open files have their names updated. Updated to notify other smbd's
5821 ****************************************************************************/
5823 static void rename_open_files(connection_struct
*conn
,
5824 struct share_mode_lock
*lck
,
5825 uint32_t orig_name_hash
,
5826 const struct smb_filename
*smb_fname_dst
)
5829 bool did_rename
= False
;
5831 uint32_t new_name_hash
;
5833 for(fsp
= file_find_di_first(conn
->sconn
, lck
->id
); fsp
;
5834 fsp
= file_find_di_next(fsp
)) {
5835 /* fsp_name is a relative path under the fsp. To change this for other
5836 sharepaths we need to manipulate relative paths. */
5837 /* TODO - create the absolute path and manipulate the newname
5838 relative to the sharepath. */
5839 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5842 if (fsp
->name_hash
!= orig_name_hash
) {
5845 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5846 "(file_id %s) from %s -> %s\n", fsp
->fnum
,
5847 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
5848 smb_fname_str_dbg(smb_fname_dst
)));
5850 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
5851 if (NT_STATUS_IS_OK(status
)) {
5853 new_name_hash
= fsp
->name_hash
;
5858 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5859 "for %s\n", file_id_string_tos(&lck
->id
),
5860 smb_fname_str_dbg(smb_fname_dst
)));
5863 /* Send messages to all smbd's (not ourself) that the name has changed. */
5864 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, conn
->connectpath
,
5865 orig_name_hash
, new_name_hash
,
5870 /****************************************************************************
5871 We need to check if the source path is a parent directory of the destination
5872 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5873 refuse the rename with a sharing violation. Under UNIX the above call can
5874 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5875 probably need to check that the client is a Windows one before disallowing
5876 this as a UNIX client (one with UNIX extensions) can know the source is a
5877 symlink and make this decision intelligently. Found by an excellent bug
5878 report from <AndyLiebman@aol.com>.
5879 ****************************************************************************/
5881 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
5882 const struct smb_filename
*smb_fname_dst
)
5884 const char *psrc
= smb_fname_src
->base_name
;
5885 const char *pdst
= smb_fname_dst
->base_name
;
5888 if (psrc
[0] == '.' && psrc
[1] == '/') {
5891 if (pdst
[0] == '.' && pdst
[1] == '/') {
5894 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5897 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5901 * Do the notify calls from a rename
5904 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5905 const struct smb_filename
*smb_fname_src
,
5906 const struct smb_filename
*smb_fname_dst
)
5908 char *parent_dir_src
= NULL
;
5909 char *parent_dir_dst
= NULL
;
5912 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5913 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5915 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
5916 &parent_dir_src
, NULL
) ||
5917 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
5918 &parent_dir_dst
, NULL
)) {
5922 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
5923 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
5924 smb_fname_src
->base_name
);
5925 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
5926 smb_fname_dst
->base_name
);
5929 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
5930 smb_fname_src
->base_name
);
5931 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
5932 smb_fname_dst
->base_name
);
5935 /* this is a strange one. w2k3 gives an additional event for
5936 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5937 files, but not directories */
5939 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5940 FILE_NOTIFY_CHANGE_ATTRIBUTES
5941 |FILE_NOTIFY_CHANGE_CREATION
,
5942 smb_fname_dst
->base_name
);
5945 TALLOC_FREE(parent_dir_src
);
5946 TALLOC_FREE(parent_dir_dst
);
5949 /****************************************************************************
5950 Returns an error if the parent directory for a filename is open in an
5952 ****************************************************************************/
5954 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
5955 const struct smb_filename
*smb_fname_dst_in
)
5957 char *parent_dir
= NULL
;
5958 struct smb_filename smb_fname_parent
;
5960 files_struct
*fsp
= NULL
;
5963 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
5964 &parent_dir
, NULL
)) {
5965 return NT_STATUS_NO_MEMORY
;
5967 ZERO_STRUCT(smb_fname_parent
);
5968 smb_fname_parent
.base_name
= parent_dir
;
5970 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
5972 return map_nt_error_from_unix(errno
);
5976 * We're only checking on this smbd here, mostly good
5977 * enough.. and will pass tests.
5980 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
5981 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
5982 fsp
= file_find_di_next(fsp
)) {
5983 if (fsp
->access_mask
& DELETE_ACCESS
) {
5984 return NT_STATUS_SHARING_VIOLATION
;
5987 return NT_STATUS_OK
;
5990 /****************************************************************************
5991 Rename an open file - given an fsp.
5992 ****************************************************************************/
5994 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
5996 const struct smb_filename
*smb_fname_dst_in
,
5998 bool replace_if_exists
)
6000 TALLOC_CTX
*ctx
= talloc_tos();
6001 struct smb_filename
*smb_fname_dst
= NULL
;
6002 NTSTATUS status
= NT_STATUS_OK
;
6003 struct share_mode_lock
*lck
= NULL
;
6004 bool dst_exists
, old_is_stream
, new_is_stream
;
6006 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6007 if (!NT_STATUS_IS_OK(status
)) {
6011 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6012 if (!NT_STATUS_IS_OK(status
)) {
6016 /* Make a copy of the dst smb_fname structs */
6018 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
6019 if (!NT_STATUS_IS_OK(status
)) {
6024 * Check for special case with case preserving and not
6025 * case sensitive. If the old last component differs from the original
6026 * last component only by case, then we should allow
6027 * the rename (user is trying to change the case of the
6030 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6031 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6032 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6034 char *fname_dst_lcomp_base_mod
= NULL
;
6035 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6038 * Get the last component of the destination name.
6040 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6042 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6044 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6046 if (!fname_dst_lcomp_base_mod
) {
6047 status
= NT_STATUS_NO_MEMORY
;
6052 * Create an smb_filename struct using the original last
6053 * component of the destination.
6055 status
= create_synthetic_smb_fname_split(ctx
,
6056 smb_fname_dst
->original_lcomp
, NULL
,
6057 &smb_fname_orig_lcomp
);
6058 if (!NT_STATUS_IS_OK(status
)) {
6059 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6063 /* If the base names only differ by case, use original. */
6064 if(!strcsequal(fname_dst_lcomp_base_mod
,
6065 smb_fname_orig_lcomp
->base_name
)) {
6068 * Replace the modified last component with the
6072 *last_slash
= '\0'; /* Truncate at the '/' */
6073 tmp
= talloc_asprintf(smb_fname_dst
,
6075 smb_fname_dst
->base_name
,
6076 smb_fname_orig_lcomp
->base_name
);
6078 tmp
= talloc_asprintf(smb_fname_dst
,
6080 smb_fname_orig_lcomp
->base_name
);
6083 status
= NT_STATUS_NO_MEMORY
;
6084 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6085 TALLOC_FREE(smb_fname_orig_lcomp
);
6088 TALLOC_FREE(smb_fname_dst
->base_name
);
6089 smb_fname_dst
->base_name
= tmp
;
6092 /* If the stream_names only differ by case, use original. */
6093 if(!strcsequal(smb_fname_dst
->stream_name
,
6094 smb_fname_orig_lcomp
->stream_name
)) {
6096 /* Use the original stream. */
6097 tmp
= talloc_strdup(smb_fname_dst
,
6098 smb_fname_orig_lcomp
->stream_name
);
6100 status
= NT_STATUS_NO_MEMORY
;
6101 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6102 TALLOC_FREE(smb_fname_orig_lcomp
);
6105 TALLOC_FREE(smb_fname_dst
->stream_name
);
6106 smb_fname_dst
->stream_name
= tmp
;
6108 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6109 TALLOC_FREE(smb_fname_orig_lcomp
);
6113 * If the src and dest names are identical - including case,
6114 * don't do the rename, just return success.
6117 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6118 strcsequal(fsp
->fsp_name
->stream_name
,
6119 smb_fname_dst
->stream_name
)) {
6120 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6121 "- returning success\n",
6122 smb_fname_str_dbg(smb_fname_dst
)));
6123 status
= NT_STATUS_OK
;
6127 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6128 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6130 /* Return the correct error code if both names aren't streams. */
6131 if (!old_is_stream
&& new_is_stream
) {
6132 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6136 if (old_is_stream
&& !new_is_stream
) {
6137 status
= NT_STATUS_INVALID_PARAMETER
;
6141 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6143 if(!replace_if_exists
&& dst_exists
) {
6144 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6145 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6146 smb_fname_str_dbg(smb_fname_dst
)));
6147 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6152 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6153 &smb_fname_dst
->st
);
6154 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6156 /* The file can be open when renaming a stream */
6157 if (dst_fsp
&& !new_is_stream
) {
6158 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6159 status
= NT_STATUS_ACCESS_DENIED
;
6164 /* Ensure we have a valid stat struct for the source. */
6165 status
= vfs_stat_fsp(fsp
);
6166 if (!NT_STATUS_IS_OK(status
)) {
6170 status
= can_rename(conn
, fsp
, attrs
);
6172 if (!NT_STATUS_IS_OK(status
)) {
6173 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6174 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6175 smb_fname_str_dbg(smb_fname_dst
)));
6176 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6177 status
= NT_STATUS_ACCESS_DENIED
;
6181 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6182 status
= NT_STATUS_ACCESS_DENIED
;
6185 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6189 * We have the file open ourselves, so not being able to get the
6190 * corresponding share mode lock is a fatal error.
6193 SMB_ASSERT(lck
!= NULL
);
6195 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6196 uint32 create_options
= fsp
->fh
->private_options
;
6198 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6199 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6200 smb_fname_str_dbg(smb_fname_dst
)));
6202 if (!fsp
->is_directory
&&
6203 !lp_posix_pathnames() &&
6204 (lp_map_archive(SNUM(conn
)) ||
6205 lp_store_dos_attributes(SNUM(conn
)))) {
6206 /* We must set the archive bit on the newly
6208 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6209 uint32_t old_dosmode
= dos_mode(conn
,
6211 file_set_dosmode(conn
,
6213 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6219 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6222 rename_open_files(conn
, lck
, fsp
->name_hash
, smb_fname_dst
);
6225 * A rename acts as a new file create w.r.t. allowing an initial delete
6226 * on close, probably because in Windows there is a new handle to the
6227 * new file. If initial delete on close was requested but not
6228 * originally set, we need to set it here. This is probably not 100% correct,
6229 * but will work for the CIFSFS client which in non-posix mode
6230 * depends on these semantics. JRA.
6233 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6234 status
= can_set_delete_on_close(fsp
, 0);
6236 if (NT_STATUS_IS_OK(status
)) {
6237 /* Note that here we set the *inital* delete on close flag,
6238 * not the regular one. The magic gets handled in close. */
6239 fsp
->initial_delete_on_close
= True
;
6243 status
= NT_STATUS_OK
;
6249 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6250 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6252 status
= map_nt_error_from_unix(errno
);
6255 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6256 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6257 smb_fname_str_dbg(smb_fname_dst
)));
6260 TALLOC_FREE(smb_fname_dst
);
6265 /****************************************************************************
6266 The guts of the rename command, split out so it may be called by the NT SMB
6268 ****************************************************************************/
6270 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6271 connection_struct
*conn
,
6272 struct smb_request
*req
,
6273 struct smb_filename
*smb_fname_src
,
6274 struct smb_filename
*smb_fname_dst
,
6276 bool replace_if_exists
,
6279 uint32_t access_mask
)
6281 char *fname_src_dir
= NULL
;
6282 char *fname_src_mask
= NULL
;
6284 NTSTATUS status
= NT_STATUS_OK
;
6285 struct smb_Dir
*dir_hnd
= NULL
;
6286 const char *dname
= NULL
;
6287 char *talloced
= NULL
;
6289 int create_options
= 0;
6290 bool posix_pathnames
= lp_posix_pathnames();
6293 * Split the old name into directory and last component
6294 * strings. Note that unix_convert may have stripped off a
6295 * leading ./ from both name and newname if the rename is
6296 * at the root of the share. We need to make sure either both
6297 * name and newname contain a / character or neither of them do
6298 * as this is checked in resolve_wildcards().
6301 /* Split up the directory from the filename/mask. */
6302 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6303 &fname_src_dir
, &fname_src_mask
);
6304 if (!NT_STATUS_IS_OK(status
)) {
6305 status
= NT_STATUS_NO_MEMORY
;
6310 * We should only check the mangled cache
6311 * here if unix_convert failed. This means
6312 * that the path in 'mask' doesn't exist
6313 * on the file system and so we need to look
6314 * for a possible mangle. This patch from
6315 * Tine Smukavec <valentin.smukavec@hermes.si>.
6318 if (!VALID_STAT(smb_fname_src
->st
) &&
6319 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6320 char *new_mask
= NULL
;
6321 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6324 TALLOC_FREE(fname_src_mask
);
6325 fname_src_mask
= new_mask
;
6329 if (!src_has_wild
) {
6333 * Only one file needs to be renamed. Append the mask back
6334 * onto the directory.
6336 TALLOC_FREE(smb_fname_src
->base_name
);
6337 if (ISDOT(fname_src_dir
)) {
6338 /* Ensure we use canonical names on open. */
6339 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6343 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6348 if (!smb_fname_src
->base_name
) {
6349 status
= NT_STATUS_NO_MEMORY
;
6353 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6354 "case_preserve = %d, short case preserve = %d, "
6355 "directory = %s, newname = %s, "
6356 "last_component_dest = %s\n",
6357 conn
->case_sensitive
, conn
->case_preserve
,
6358 conn
->short_case_preserve
,
6359 smb_fname_str_dbg(smb_fname_src
),
6360 smb_fname_str_dbg(smb_fname_dst
),
6361 smb_fname_dst
->original_lcomp
));
6363 /* The dest name still may have wildcards. */
6364 if (dest_has_wild
) {
6365 char *fname_dst_mod
= NULL
;
6366 if (!resolve_wildcards(smb_fname_dst
,
6367 smb_fname_src
->base_name
,
6368 smb_fname_dst
->base_name
,
6370 DEBUG(6, ("rename_internals: resolve_wildcards "
6372 smb_fname_src
->base_name
,
6373 smb_fname_dst
->base_name
));
6374 status
= NT_STATUS_NO_MEMORY
;
6377 TALLOC_FREE(smb_fname_dst
->base_name
);
6378 smb_fname_dst
->base_name
= fname_dst_mod
;
6381 ZERO_STRUCT(smb_fname_src
->st
);
6382 if (posix_pathnames
) {
6383 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6385 SMB_VFS_STAT(conn
, smb_fname_src
);
6388 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6389 create_options
|= FILE_DIRECTORY_FILE
;
6392 status
= SMB_VFS_CREATE_FILE(
6395 0, /* root_dir_fid */
6396 smb_fname_src
, /* fname */
6397 access_mask
, /* access_mask */
6398 (FILE_SHARE_READ
| /* share_access */
6400 FILE_OPEN
, /* create_disposition*/
6401 create_options
, /* create_options */
6402 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6403 0, /* oplock_request */
6404 0, /* allocation_size */
6405 0, /* private_flags */
6411 if (!NT_STATUS_IS_OK(status
)) {
6412 DEBUG(3, ("Could not open rename source %s: %s\n",
6413 smb_fname_str_dbg(smb_fname_src
),
6414 nt_errstr(status
)));
6418 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6419 attrs
, replace_if_exists
);
6421 close_file(req
, fsp
, NORMAL_CLOSE
);
6423 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6424 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6425 smb_fname_str_dbg(smb_fname_dst
)));
6431 * Wildcards - process each file that matches.
6433 if (strequal(fname_src_mask
, "????????.???")) {
6434 TALLOC_FREE(fname_src_mask
);
6435 fname_src_mask
= talloc_strdup(ctx
, "*");
6436 if (!fname_src_mask
) {
6437 status
= NT_STATUS_NO_MEMORY
;
6442 status
= check_name(conn
, fname_src_dir
);
6443 if (!NT_STATUS_IS_OK(status
)) {
6447 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6449 if (dir_hnd
== NULL
) {
6450 status
= map_nt_error_from_unix(errno
);
6454 status
= NT_STATUS_NO_SUCH_FILE
;
6456 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6457 * - gentest fix. JRA
6460 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6462 files_struct
*fsp
= NULL
;
6463 char *destname
= NULL
;
6464 bool sysdir_entry
= False
;
6466 /* Quick check for "." and ".." */
6467 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6468 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6469 sysdir_entry
= True
;
6471 TALLOC_FREE(talloced
);
6476 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6477 &smb_fname_src
->st
, false)) {
6478 TALLOC_FREE(talloced
);
6482 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6483 TALLOC_FREE(talloced
);
6488 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6492 TALLOC_FREE(smb_fname_src
->base_name
);
6493 if (ISDOT(fname_src_dir
)) {
6494 /* Ensure we use canonical names on open. */
6495 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6499 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6504 if (!smb_fname_src
->base_name
) {
6505 status
= NT_STATUS_NO_MEMORY
;
6509 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6510 smb_fname_dst
->base_name
,
6512 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6513 smb_fname_src
->base_name
, destname
));
6514 TALLOC_FREE(talloced
);
6518 status
= NT_STATUS_NO_MEMORY
;
6522 TALLOC_FREE(smb_fname_dst
->base_name
);
6523 smb_fname_dst
->base_name
= destname
;
6525 ZERO_STRUCT(smb_fname_src
->st
);
6526 if (posix_pathnames
) {
6527 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6529 SMB_VFS_STAT(conn
, smb_fname_src
);
6534 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6535 create_options
|= FILE_DIRECTORY_FILE
;
6538 status
= SMB_VFS_CREATE_FILE(
6541 0, /* root_dir_fid */
6542 smb_fname_src
, /* fname */
6543 access_mask
, /* access_mask */
6544 (FILE_SHARE_READ
| /* share_access */
6546 FILE_OPEN
, /* create_disposition*/
6547 create_options
, /* create_options */
6548 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6549 0, /* oplock_request */
6550 0, /* allocation_size */
6551 0, /* private_flags */
6557 if (!NT_STATUS_IS_OK(status
)) {
6558 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6559 "returned %s rename %s -> %s\n",
6561 smb_fname_str_dbg(smb_fname_src
),
6562 smb_fname_str_dbg(smb_fname_dst
)));
6566 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6568 if (!smb_fname_dst
->original_lcomp
) {
6569 status
= NT_STATUS_NO_MEMORY
;
6573 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6574 attrs
, replace_if_exists
);
6576 close_file(req
, fsp
, NORMAL_CLOSE
);
6578 if (!NT_STATUS_IS_OK(status
)) {
6579 DEBUG(3, ("rename_internals_fsp returned %s for "
6580 "rename %s -> %s\n", nt_errstr(status
),
6581 smb_fname_str_dbg(smb_fname_src
),
6582 smb_fname_str_dbg(smb_fname_dst
)));
6588 DEBUG(3,("rename_internals: doing rename on %s -> "
6589 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6590 smb_fname_str_dbg(smb_fname_src
)));
6591 TALLOC_FREE(talloced
);
6593 TALLOC_FREE(dir_hnd
);
6595 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6596 status
= map_nt_error_from_unix(errno
);
6600 TALLOC_FREE(talloced
);
6601 TALLOC_FREE(fname_src_dir
);
6602 TALLOC_FREE(fname_src_mask
);
6606 /****************************************************************************
6608 ****************************************************************************/
6610 void reply_mv(struct smb_request
*req
)
6612 connection_struct
*conn
= req
->conn
;
6614 char *newname
= NULL
;
6618 bool src_has_wcard
= False
;
6619 bool dest_has_wcard
= False
;
6620 TALLOC_CTX
*ctx
= talloc_tos();
6621 struct smb_filename
*smb_fname_src
= NULL
;
6622 struct smb_filename
*smb_fname_dst
= NULL
;
6623 uint32_t src_ucf_flags
= lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP
: UCF_COND_ALLOW_WCARD_LCOMP
;
6624 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
| (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP
);
6625 bool stream_rename
= false;
6627 START_PROFILE(SMBmv
);
6630 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6634 attrs
= SVAL(req
->vwv
+0, 0);
6636 p
= (const char *)req
->buf
+ 1;
6637 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6638 &status
, &src_has_wcard
);
6639 if (!NT_STATUS_IS_OK(status
)) {
6640 reply_nterror(req
, status
);
6644 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6645 &status
, &dest_has_wcard
);
6646 if (!NT_STATUS_IS_OK(status
)) {
6647 reply_nterror(req
, status
);
6651 if (!lp_posix_pathnames()) {
6652 /* The newname must begin with a ':' if the
6653 name contains a ':'. */
6654 if (strchr_m(name
, ':')) {
6655 if (newname
[0] != ':') {
6656 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6659 stream_rename
= true;
6663 status
= filename_convert(ctx
,
6665 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6671 if (!NT_STATUS_IS_OK(status
)) {
6672 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6673 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6674 ERRSRV
, ERRbadpath
);
6677 reply_nterror(req
, status
);
6681 status
= filename_convert(ctx
,
6683 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6689 if (!NT_STATUS_IS_OK(status
)) {
6690 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6691 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6692 ERRSRV
, ERRbadpath
);
6695 reply_nterror(req
, status
);
6699 if (stream_rename
) {
6700 /* smb_fname_dst->base_name must be the same as
6701 smb_fname_src->base_name. */
6702 TALLOC_FREE(smb_fname_dst
->base_name
);
6703 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6704 smb_fname_src
->base_name
);
6705 if (!smb_fname_dst
->base_name
) {
6706 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6711 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6712 smb_fname_str_dbg(smb_fname_dst
)));
6714 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
6715 attrs
, False
, src_has_wcard
, dest_has_wcard
,
6717 if (!NT_STATUS_IS_OK(status
)) {
6718 if (open_was_deferred(req
->mid
)) {
6719 /* We have re-scheduled this call. */
6722 reply_nterror(req
, status
);
6726 reply_outbuf(req
, 0, 0);
6728 TALLOC_FREE(smb_fname_src
);
6729 TALLOC_FREE(smb_fname_dst
);
6734 /*******************************************************************
6735 Copy a file as part of a reply_copy.
6736 ******************************************************************/
6739 * TODO: check error codes on all callers
6742 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6743 connection_struct
*conn
,
6744 struct smb_filename
*smb_fname_src
,
6745 struct smb_filename
*smb_fname_dst
,
6748 bool target_is_directory
)
6750 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
6752 files_struct
*fsp1
,*fsp2
;
6754 uint32 new_create_disposition
;
6758 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
6759 if (!NT_STATUS_IS_OK(status
)) {
6764 * If the target is a directory, extract the last component from the
6765 * src filename and append it to the dst filename
6767 if (target_is_directory
) {
6770 /* dest/target can't be a stream if it's a directory. */
6771 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
6773 p
= strrchr_m(smb_fname_src
->base_name
,'/');
6777 p
= smb_fname_src
->base_name
;
6779 smb_fname_dst_tmp
->base_name
=
6780 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
6782 if (!smb_fname_dst_tmp
->base_name
) {
6783 status
= NT_STATUS_NO_MEMORY
;
6788 status
= vfs_file_exist(conn
, smb_fname_src
);
6789 if (!NT_STATUS_IS_OK(status
)) {
6793 if (!target_is_directory
&& count
) {
6794 new_create_disposition
= FILE_OPEN
;
6796 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
6799 &new_create_disposition
,
6802 status
= NT_STATUS_INVALID_PARAMETER
;
6807 /* Open the src file for reading. */
6808 status
= SMB_VFS_CREATE_FILE(
6811 0, /* root_dir_fid */
6812 smb_fname_src
, /* fname */
6813 FILE_GENERIC_READ
, /* access_mask */
6814 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6815 FILE_OPEN
, /* create_disposition*/
6816 0, /* create_options */
6817 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6818 INTERNAL_OPEN_ONLY
, /* oplock_request */
6819 0, /* allocation_size */
6820 0, /* private_flags */
6826 if (!NT_STATUS_IS_OK(status
)) {
6830 dosattrs
= dos_mode(conn
, smb_fname_src
);
6832 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
6833 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
6836 /* Open the dst file for writing. */
6837 status
= SMB_VFS_CREATE_FILE(
6840 0, /* root_dir_fid */
6841 smb_fname_dst
, /* fname */
6842 FILE_GENERIC_WRITE
, /* access_mask */
6843 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6844 new_create_disposition
, /* create_disposition*/
6845 0, /* create_options */
6846 dosattrs
, /* file_attributes */
6847 INTERNAL_OPEN_ONLY
, /* oplock_request */
6848 0, /* allocation_size */
6849 0, /* private_flags */
6855 if (!NT_STATUS_IS_OK(status
)) {
6856 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6860 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
6861 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
6863 DEBUG(0, ("error - vfs lseek returned error %s\n",
6865 status
= map_nt_error_from_unix(errno
);
6866 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6867 close_file(NULL
, fsp2
, ERROR_CLOSE
);
6872 /* Do the actual copy. */
6873 if (smb_fname_src
->st
.st_ex_size
) {
6874 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
6879 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
6881 /* Ensure the modtime is set correctly on the destination file. */
6882 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
6885 * As we are opening fsp1 read-only we only expect
6886 * an error on close on fsp2 if we are out of space.
6887 * Thus we don't look at the error return from the
6890 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
6892 if (!NT_STATUS_IS_OK(status
)) {
6896 if (ret
!= (SMB_OFF_T
)smb_fname_src
->st
.st_ex_size
) {
6897 status
= NT_STATUS_DISK_FULL
;
6901 status
= NT_STATUS_OK
;
6904 TALLOC_FREE(smb_fname_dst_tmp
);
6908 /****************************************************************************
6909 Reply to a file copy.
6910 ****************************************************************************/
6912 void reply_copy(struct smb_request
*req
)
6914 connection_struct
*conn
= req
->conn
;
6915 struct smb_filename
*smb_fname_src
= NULL
;
6916 struct smb_filename
*smb_fname_dst
= NULL
;
6917 char *fname_src
= NULL
;
6918 char *fname_dst
= NULL
;
6919 char *fname_src_mask
= NULL
;
6920 char *fname_src_dir
= NULL
;
6923 int error
= ERRnoaccess
;
6927 bool target_is_directory
=False
;
6928 bool source_has_wild
= False
;
6929 bool dest_has_wild
= False
;
6931 TALLOC_CTX
*ctx
= talloc_tos();
6933 START_PROFILE(SMBcopy
);
6936 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6940 tid2
= SVAL(req
->vwv
+0, 0);
6941 ofun
= SVAL(req
->vwv
+1, 0);
6942 flags
= SVAL(req
->vwv
+2, 0);
6944 p
= (const char *)req
->buf
;
6945 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
6946 &status
, &source_has_wild
);
6947 if (!NT_STATUS_IS_OK(status
)) {
6948 reply_nterror(req
, status
);
6951 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
6952 &status
, &dest_has_wild
);
6953 if (!NT_STATUS_IS_OK(status
)) {
6954 reply_nterror(req
, status
);
6958 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
6960 if (tid2
!= conn
->cnum
) {
6961 /* can't currently handle inter share copies XXXX */
6962 DEBUG(3,("Rejecting inter-share copy\n"));
6963 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
6967 status
= filename_convert(ctx
, conn
,
6968 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6970 UCF_COND_ALLOW_WCARD_LCOMP
,
6973 if (!NT_STATUS_IS_OK(status
)) {
6974 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6975 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6976 ERRSRV
, ERRbadpath
);
6979 reply_nterror(req
, status
);
6983 status
= filename_convert(ctx
, conn
,
6984 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6986 UCF_COND_ALLOW_WCARD_LCOMP
,
6989 if (!NT_STATUS_IS_OK(status
)) {
6990 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6991 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6992 ERRSRV
, ERRbadpath
);
6995 reply_nterror(req
, status
);
6999 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7001 if ((flags
&1) && target_is_directory
) {
7002 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7006 if ((flags
&2) && !target_is_directory
) {
7007 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7011 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7012 /* wants a tree copy! XXXX */
7013 DEBUG(3,("Rejecting tree copy\n"));
7014 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7018 /* Split up the directory from the filename/mask. */
7019 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7020 &fname_src_dir
, &fname_src_mask
);
7021 if (!NT_STATUS_IS_OK(status
)) {
7022 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7027 * We should only check the mangled cache
7028 * here if unix_convert failed. This means
7029 * that the path in 'mask' doesn't exist
7030 * on the file system and so we need to look
7031 * for a possible mangle. This patch from
7032 * Tine Smukavec <valentin.smukavec@hermes.si>.
7034 if (!VALID_STAT(smb_fname_src
->st
) &&
7035 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7036 char *new_mask
= NULL
;
7037 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7038 &new_mask
, conn
->params
);
7040 /* Use demangled name if one was successfully found. */
7042 TALLOC_FREE(fname_src_mask
);
7043 fname_src_mask
= new_mask
;
7047 if (!source_has_wild
) {
7050 * Only one file needs to be copied. Append the mask back onto
7053 TALLOC_FREE(smb_fname_src
->base_name
);
7054 if (ISDOT(fname_src_dir
)) {
7055 /* Ensure we use canonical names on open. */
7056 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7060 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7065 if (!smb_fname_src
->base_name
) {
7066 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7070 if (dest_has_wild
) {
7071 char *fname_dst_mod
= NULL
;
7072 if (!resolve_wildcards(smb_fname_dst
,
7073 smb_fname_src
->base_name
,
7074 smb_fname_dst
->base_name
,
7076 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7079 TALLOC_FREE(smb_fname_dst
->base_name
);
7080 smb_fname_dst
->base_name
= fname_dst_mod
;
7083 status
= check_name(conn
, smb_fname_src
->base_name
);
7084 if (!NT_STATUS_IS_OK(status
)) {
7085 reply_nterror(req
, status
);
7089 status
= check_name(conn
, smb_fname_dst
->base_name
);
7090 if (!NT_STATUS_IS_OK(status
)) {
7091 reply_nterror(req
, status
);
7095 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7096 ofun
, count
, target_is_directory
);
7098 if(!NT_STATUS_IS_OK(status
)) {
7099 reply_nterror(req
, status
);
7105 struct smb_Dir
*dir_hnd
= NULL
;
7106 const char *dname
= NULL
;
7107 char *talloced
= NULL
;
7111 * There is a wildcard that requires us to actually read the
7112 * src dir and copy each file matching the mask to the dst.
7113 * Right now streams won't be copied, but this could
7114 * presumably be added with a nested loop for reach dir entry.
7116 SMB_ASSERT(!smb_fname_src
->stream_name
);
7117 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7119 smb_fname_src
->stream_name
= NULL
;
7120 smb_fname_dst
->stream_name
= NULL
;
7122 if (strequal(fname_src_mask
,"????????.???")) {
7123 TALLOC_FREE(fname_src_mask
);
7124 fname_src_mask
= talloc_strdup(ctx
, "*");
7125 if (!fname_src_mask
) {
7126 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7131 status
= check_name(conn
, fname_src_dir
);
7132 if (!NT_STATUS_IS_OK(status
)) {
7133 reply_nterror(req
, status
);
7137 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7138 if (dir_hnd
== NULL
) {
7139 status
= map_nt_error_from_unix(errno
);
7140 reply_nterror(req
, status
);
7146 /* Iterate over the src dir copying each entry to the dst. */
7147 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7148 &smb_fname_src
->st
, &talloced
))) {
7149 char *destname
= NULL
;
7151 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7152 TALLOC_FREE(talloced
);
7156 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7157 &smb_fname_src
->st
, false)) {
7158 TALLOC_FREE(talloced
);
7162 if(!mask_match(dname
, fname_src_mask
,
7163 conn
->case_sensitive
)) {
7164 TALLOC_FREE(talloced
);
7168 error
= ERRnoaccess
;
7170 /* Get the src smb_fname struct setup. */
7171 TALLOC_FREE(smb_fname_src
->base_name
);
7172 if (ISDOT(fname_src_dir
)) {
7173 /* Ensure we use canonical names on open. */
7174 smb_fname_src
->base_name
=
7175 talloc_asprintf(smb_fname_src
, "%s",
7178 smb_fname_src
->base_name
=
7179 talloc_asprintf(smb_fname_src
, "%s/%s",
7180 fname_src_dir
, dname
);
7183 if (!smb_fname_src
->base_name
) {
7184 TALLOC_FREE(dir_hnd
);
7185 TALLOC_FREE(talloced
);
7186 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7190 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7191 smb_fname_dst
->base_name
,
7193 TALLOC_FREE(talloced
);
7197 TALLOC_FREE(dir_hnd
);
7198 TALLOC_FREE(talloced
);
7199 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7203 TALLOC_FREE(smb_fname_dst
->base_name
);
7204 smb_fname_dst
->base_name
= destname
;
7206 status
= check_name(conn
, smb_fname_src
->base_name
);
7207 if (!NT_STATUS_IS_OK(status
)) {
7208 TALLOC_FREE(dir_hnd
);
7209 TALLOC_FREE(talloced
);
7210 reply_nterror(req
, status
);
7214 status
= check_name(conn
, smb_fname_dst
->base_name
);
7215 if (!NT_STATUS_IS_OK(status
)) {
7216 TALLOC_FREE(dir_hnd
);
7217 TALLOC_FREE(talloced
);
7218 reply_nterror(req
, status
);
7222 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7223 smb_fname_src
->base_name
,
7224 smb_fname_dst
->base_name
));
7226 status
= copy_file(ctx
, conn
, smb_fname_src
,
7227 smb_fname_dst
, ofun
, count
,
7228 target_is_directory
);
7229 if (NT_STATUS_IS_OK(status
)) {
7233 TALLOC_FREE(talloced
);
7235 TALLOC_FREE(dir_hnd
);
7239 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7243 reply_outbuf(req
, 1, 0);
7244 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7246 TALLOC_FREE(smb_fname_src
);
7247 TALLOC_FREE(smb_fname_dst
);
7248 TALLOC_FREE(fname_src
);
7249 TALLOC_FREE(fname_dst
);
7250 TALLOC_FREE(fname_src_mask
);
7251 TALLOC_FREE(fname_src_dir
);
7253 END_PROFILE(SMBcopy
);
7258 #define DBGC_CLASS DBGC_LOCKING
7260 /****************************************************************************
7261 Get a lock pid, dealing with large count requests.
7262 ****************************************************************************/
7264 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7265 bool large_file_format
)
7267 if(!large_file_format
)
7268 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7270 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7273 /****************************************************************************
7274 Get a lock count, dealing with large count requests.
7275 ****************************************************************************/
7277 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7278 bool large_file_format
)
7282 if(!large_file_format
) {
7283 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7286 #if defined(HAVE_LONGLONG)
7287 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7288 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7289 #else /* HAVE_LONGLONG */
7292 * NT4.x seems to be broken in that it sends large file (64 bit)
7293 * lockingX calls even if the CAP_LARGE_FILES was *not*
7294 * negotiated. For boxes without large unsigned ints truncate the
7295 * lock count by dropping the top 32 bits.
7298 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7299 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7300 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7301 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7302 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7305 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7306 #endif /* HAVE_LONGLONG */
7312 #if !defined(HAVE_LONGLONG)
7313 /****************************************************************************
7314 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7315 ****************************************************************************/
7317 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7321 uint32 highcopy
= high
;
7324 * Try and find out how many significant bits there are in high.
7327 for(i
= 0; highcopy
; i
++)
7331 * We use 31 bits not 32 here as POSIX
7332 * lock offsets may not be negative.
7335 mask
= (~0) << (31 - i
);
7338 return 0; /* Fail. */
7344 #endif /* !defined(HAVE_LONGLONG) */
7346 /****************************************************************************
7347 Get a lock offset, dealing with large offset requests.
7348 ****************************************************************************/
7350 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7351 bool large_file_format
, bool *err
)
7353 uint64_t offset
= 0;
7357 if(!large_file_format
) {
7358 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7361 #if defined(HAVE_LONGLONG)
7362 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7363 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7364 #else /* HAVE_LONGLONG */
7367 * NT4.x seems to be broken in that it sends large file (64 bit)
7368 * lockingX calls even if the CAP_LARGE_FILES was *not*
7369 * negotiated. For boxes without large unsigned ints mangle the
7370 * lock offset by mapping the top 32 bits onto the lower 32.
7373 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7374 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7375 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7378 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7380 return (uint64_t)-1;
7383 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7384 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7385 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7386 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7389 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7390 #endif /* HAVE_LONGLONG */
7396 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7400 uint16_t num_ulocks
,
7401 struct smbd_lock_element
*ulocks
,
7403 struct smbd_lock_element
*locks
,
7406 connection_struct
*conn
= req
->conn
;
7408 NTSTATUS status
= NT_STATUS_OK
;
7412 /* Data now points at the beginning of the list
7413 of smb_unlkrng structs */
7414 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7415 struct smbd_lock_element
*e
= &ulocks
[i
];
7417 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7418 "pid %u, file %s\n",
7421 (unsigned int)e
->smblctx
,
7424 if (e
->brltype
!= UNLOCK_LOCK
) {
7425 /* this can only happen with SMB2 */
7426 return NT_STATUS_INVALID_PARAMETER
;
7429 status
= do_unlock(req
->sconn
->msg_ctx
,
7436 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7437 nt_errstr(status
)));
7439 if (!NT_STATUS_IS_OK(status
)) {
7444 /* Setup the timeout in seconds. */
7446 if (!lp_blocking_locks(SNUM(conn
))) {
7450 /* Data now points at the beginning of the list
7451 of smb_lkrng structs */
7453 for(i
= 0; i
< (int)num_locks
; i
++) {
7454 struct smbd_lock_element
*e
= &locks
[i
];
7456 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7457 "%llu, file %s timeout = %d\n",
7460 (unsigned long long)e
->smblctx
,
7464 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7465 struct blocking_lock_record
*blr
= NULL
;
7467 if (num_locks
> 1) {
7469 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7470 * if the lock vector contains one entry. When given mutliple cancel
7471 * requests in a single PDU we expect the server to return an
7472 * error. Windows servers seem to accept the request but only
7473 * cancel the first lock.
7474 * JRA - Do what Windows does (tm) :-).
7478 /* MS-CIFS (2.2.4.32.1) behavior. */
7479 return NT_STATUS_DOS(ERRDOS
,
7480 ERRcancelviolation
);
7482 /* Windows behavior. */
7484 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7485 "cancel request\n"));
7491 if (lp_blocking_locks(SNUM(conn
))) {
7493 /* Schedule a message to ourselves to
7494 remove the blocking lock record and
7495 return the right error. */
7497 blr
= blocking_lock_cancel_smb1(fsp
,
7503 NT_STATUS_FILE_LOCK_CONFLICT
);
7505 return NT_STATUS_DOS(
7507 ERRcancelviolation
);
7510 /* Remove a matching pending lock. */
7511 status
= do_lock_cancel(fsp
,
7518 bool blocking_lock
= timeout
? true : false;
7519 bool defer_lock
= false;
7520 struct byte_range_lock
*br_lck
;
7521 uint64_t block_smblctx
;
7523 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7535 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7536 /* Windows internal resolution for blocking locks seems
7537 to be about 200ms... Don't wait for less than that. JRA. */
7538 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7539 timeout
= lp_lock_spin_time();
7544 /* If a lock sent with timeout of zero would fail, and
7545 * this lock has been requested multiple times,
7546 * according to brl_lock_failed() we convert this
7547 * request to a blocking lock with a timeout of between
7548 * 150 - 300 milliseconds.
7550 * If lp_lock_spin_time() has been set to 0, we skip
7551 * this blocking retry and fail immediately.
7553 * Replacement for do_lock_spin(). JRA. */
7555 if (!req
->sconn
->using_smb2
&&
7556 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7557 lp_lock_spin_time() && !blocking_lock
&&
7558 NT_STATUS_EQUAL((status
),
7559 NT_STATUS_FILE_LOCK_CONFLICT
))
7562 timeout
= lp_lock_spin_time();
7565 if (br_lck
&& defer_lock
) {
7567 * A blocking lock was requested. Package up
7568 * this smb into a queued request and push it
7569 * onto the blocking lock queue.
7571 if(push_blocking_lock_request(br_lck
,
7582 TALLOC_FREE(br_lck
);
7584 return NT_STATUS_OK
;
7588 TALLOC_FREE(br_lck
);
7591 if (!NT_STATUS_IS_OK(status
)) {
7596 /* If any of the above locks failed, then we must unlock
7597 all of the previous locks (X/Open spec). */
7599 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7601 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7602 i
= -1; /* we want to skip the for loop */
7606 * Ensure we don't do a remove on the lock that just failed,
7607 * as under POSIX rules, if we have a lock already there, we
7608 * will delete it (and we shouldn't) .....
7610 for(i
--; i
>= 0; i
--) {
7611 struct smbd_lock_element
*e
= &locks
[i
];
7613 do_unlock(req
->sconn
->msg_ctx
,
7623 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7624 fsp
->fnum
, (unsigned int)type
, num_locks
, num_ulocks
));
7626 return NT_STATUS_OK
;
7629 /****************************************************************************
7630 Reply to a lockingX request.
7631 ****************************************************************************/
7633 void reply_lockingX(struct smb_request
*req
)
7635 connection_struct
*conn
= req
->conn
;
7637 unsigned char locktype
;
7638 unsigned char oplocklevel
;
7643 const uint8_t *data
;
7644 bool large_file_format
;
7646 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7647 struct smbd_lock_element
*ulocks
;
7648 struct smbd_lock_element
*locks
;
7651 START_PROFILE(SMBlockingX
);
7654 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7655 END_PROFILE(SMBlockingX
);
7659 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7660 locktype
= CVAL(req
->vwv
+3, 0);
7661 oplocklevel
= CVAL(req
->vwv
+3, 1);
7662 num_ulocks
= SVAL(req
->vwv
+6, 0);
7663 num_locks
= SVAL(req
->vwv
+7, 0);
7664 lock_timeout
= IVAL(req
->vwv
+4, 0);
7665 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7667 if (!check_fsp(conn
, req
, fsp
)) {
7668 END_PROFILE(SMBlockingX
);
7674 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7675 /* we don't support these - and CANCEL_LOCK makes w2k
7676 and XP reboot so I don't really want to be
7677 compatible! (tridge) */
7678 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7679 END_PROFILE(SMBlockingX
);
7683 /* Check if this is an oplock break on a file
7684 we have granted an oplock on.
7686 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7687 /* Client can insist on breaking to none. */
7688 bool break_to_none
= (oplocklevel
== 0);
7691 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7692 "for fnum = %d\n", (unsigned int)oplocklevel
,
7696 * Make sure we have granted an exclusive or batch oplock on
7700 if (fsp
->oplock_type
== 0) {
7702 /* The Samba4 nbench simulator doesn't understand
7703 the difference between break to level2 and break
7704 to none from level2 - it sends oplock break
7705 replies in both cases. Don't keep logging an error
7706 message here - just ignore it. JRA. */
7708 DEBUG(5,("reply_lockingX: Error : oplock break from "
7709 "client for fnum = %d (oplock=%d) and no "
7710 "oplock granted on this file (%s).\n",
7711 fsp
->fnum
, fsp
->oplock_type
,
7714 /* if this is a pure oplock break request then don't
7716 if (num_locks
== 0 && num_ulocks
== 0) {
7717 END_PROFILE(SMBlockingX
);
7720 END_PROFILE(SMBlockingX
);
7721 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
7726 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7728 result
= remove_oplock(fsp
);
7730 result
= downgrade_oplock(fsp
);
7734 DEBUG(0, ("reply_lockingX: error in removing "
7735 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7736 /* Hmmm. Is this panic justified? */
7737 smb_panic("internal tdb error");
7740 reply_to_oplock_break_requests(fsp
);
7742 /* if this is a pure oplock break request then don't send a
7744 if (num_locks
== 0 && num_ulocks
== 0) {
7745 /* Sanity check - ensure a pure oplock break is not a
7747 if(CVAL(req
->vwv
+0, 0) != 0xff)
7748 DEBUG(0,("reply_lockingX: Error : pure oplock "
7749 "break is a chained %d request !\n",
7750 (unsigned int)CVAL(req
->vwv
+0, 0)));
7751 END_PROFILE(SMBlockingX
);
7757 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7758 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7759 END_PROFILE(SMBlockingX
);
7763 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
7764 if (ulocks
== NULL
) {
7765 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7766 END_PROFILE(SMBlockingX
);
7770 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
7771 if (locks
== NULL
) {
7772 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7773 END_PROFILE(SMBlockingX
);
7777 /* Data now points at the beginning of the list
7778 of smb_unlkrng structs */
7779 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7780 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7781 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7782 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7783 ulocks
[i
].brltype
= UNLOCK_LOCK
;
7786 * There is no error code marked "stupid client bug".... :-).
7789 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7790 END_PROFILE(SMBlockingX
);
7795 /* Now do any requested locks */
7796 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
7798 /* Data now points at the beginning of the list
7799 of smb_lkrng structs */
7801 for(i
= 0; i
< (int)num_locks
; i
++) {
7802 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7803 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7804 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7806 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
7807 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7808 locks
[i
].brltype
= PENDING_READ_LOCK
;
7810 locks
[i
].brltype
= READ_LOCK
;
7813 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7814 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
7816 locks
[i
].brltype
= WRITE_LOCK
;
7821 * There is no error code marked "stupid client bug".... :-).
7824 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7825 END_PROFILE(SMBlockingX
);
7830 status
= smbd_do_locking(req
, fsp
,
7831 locktype
, lock_timeout
,
7835 if (!NT_STATUS_IS_OK(status
)) {
7836 END_PROFILE(SMBlockingX
);
7837 reply_nterror(req
, status
);
7841 END_PROFILE(SMBlockingX
);
7845 reply_outbuf(req
, 2, 0);
7847 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7848 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7850 END_PROFILE(SMBlockingX
);
7855 #define DBGC_CLASS DBGC_ALL
7857 /****************************************************************************
7858 Reply to a SMBreadbmpx (read block multiplex) request.
7859 Always reply with an error, if someone has a platform really needs this,
7860 please contact vl@samba.org
7861 ****************************************************************************/
7863 void reply_readbmpx(struct smb_request
*req
)
7865 START_PROFILE(SMBreadBmpx
);
7866 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7867 END_PROFILE(SMBreadBmpx
);
7871 /****************************************************************************
7872 Reply to a SMBreadbs (read block multiplex secondary) request.
7873 Always reply with an error, if someone has a platform really needs this,
7874 please contact vl@samba.org
7875 ****************************************************************************/
7877 void reply_readbs(struct smb_request
*req
)
7879 START_PROFILE(SMBreadBs
);
7880 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7881 END_PROFILE(SMBreadBs
);
7885 /****************************************************************************
7886 Reply to a SMBsetattrE.
7887 ****************************************************************************/
7889 void reply_setattrE(struct smb_request
*req
)
7891 connection_struct
*conn
= req
->conn
;
7892 struct smb_file_time ft
;
7896 START_PROFILE(SMBsetattrE
);
7900 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7904 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7906 if(!fsp
|| (fsp
->conn
!= conn
)) {
7907 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7912 * Convert the DOS times into unix times.
7915 ft
.atime
= convert_time_t_to_timespec(
7916 srv_make_unix_date2(req
->vwv
+3));
7917 ft
.mtime
= convert_time_t_to_timespec(
7918 srv_make_unix_date2(req
->vwv
+5));
7919 ft
.create_time
= convert_time_t_to_timespec(
7920 srv_make_unix_date2(req
->vwv
+1));
7922 reply_outbuf(req
, 0, 0);
7925 * Patch from Ray Frush <frush@engr.colostate.edu>
7926 * Sometimes times are sent as zero - ignore them.
7929 /* Ensure we have a valid stat struct for the source. */
7930 status
= vfs_stat_fsp(fsp
);
7931 if (!NT_STATUS_IS_OK(status
)) {
7932 reply_nterror(req
, status
);
7936 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
7937 if (!NT_STATUS_IS_OK(status
)) {
7938 reply_nterror(req
, status
);
7942 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7945 (unsigned int)ft
.atime
.tv_sec
,
7946 (unsigned int)ft
.mtime
.tv_sec
,
7947 (unsigned int)ft
.create_time
.tv_sec
7950 END_PROFILE(SMBsetattrE
);
7955 /* Back from the dead for OS/2..... JRA. */
7957 /****************************************************************************
7958 Reply to a SMBwritebmpx (write block multiplex primary) request.
7959 Always reply with an error, if someone has a platform really needs this,
7960 please contact vl@samba.org
7961 ****************************************************************************/
7963 void reply_writebmpx(struct smb_request
*req
)
7965 START_PROFILE(SMBwriteBmpx
);
7966 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7967 END_PROFILE(SMBwriteBmpx
);
7971 /****************************************************************************
7972 Reply to a SMBwritebs (write block multiplex secondary) request.
7973 Always reply with an error, if someone has a platform really needs this,
7974 please contact vl@samba.org
7975 ****************************************************************************/
7977 void reply_writebs(struct smb_request
*req
)
7979 START_PROFILE(SMBwriteBs
);
7980 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7981 END_PROFILE(SMBwriteBs
);
7985 /****************************************************************************
7986 Reply to a SMBgetattrE.
7987 ****************************************************************************/
7989 void reply_getattrE(struct smb_request
*req
)
7991 connection_struct
*conn
= req
->conn
;
7994 struct timespec create_ts
;
7996 START_PROFILE(SMBgetattrE
);
7999 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8000 END_PROFILE(SMBgetattrE
);
8004 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8006 if(!fsp
|| (fsp
->conn
!= conn
)) {
8007 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8008 END_PROFILE(SMBgetattrE
);
8012 /* Do an fstat on this file */
8014 reply_nterror(req
, map_nt_error_from_unix(errno
));
8015 END_PROFILE(SMBgetattrE
);
8019 mode
= dos_mode(conn
, fsp
->fsp_name
);
8022 * Convert the times into dos times. Set create
8023 * date to be last modify date as UNIX doesn't save
8027 reply_outbuf(req
, 11, 0);
8029 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8030 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8031 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8032 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8033 /* Should we check pending modtime here ? JRA */
8034 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8035 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8037 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8038 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8039 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8041 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8042 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
8043 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8045 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8047 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
8049 END_PROFILE(SMBgetattrE
);