2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/cli_spoolss.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_server/rpc_ncacn_np.h"
38 #include "libcli/security/security.h"
39 #include "libsmb/nmblib.h"
41 #include "smbprofile.h"
43 /****************************************************************************
44 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
45 path or anything including wildcards.
46 We're assuming here that '/' is not the second byte in any multibyte char
47 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
49 ****************************************************************************/
51 /* Custom version for processing POSIX paths. */
52 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
54 static NTSTATUS
check_path_syntax_internal(char *path
,
56 bool *p_last_component_contains_wcard
)
60 NTSTATUS ret
= NT_STATUS_OK
;
61 bool start_of_name_component
= True
;
62 bool stream_started
= false;
64 *p_last_component_contains_wcard
= False
;
71 return NT_STATUS_OBJECT_NAME_INVALID
;
74 return NT_STATUS_OBJECT_NAME_INVALID
;
76 if (strchr_m(&s
[1], ':')) {
77 return NT_STATUS_OBJECT_NAME_INVALID
;
83 if ((*s
== ':') && !posix_path
&& !stream_started
) {
84 if (*p_last_component_contains_wcard
) {
85 return NT_STATUS_OBJECT_NAME_INVALID
;
87 /* Stream names allow more characters than file names.
88 We're overloading posix_path here to allow a wider
89 range of characters. If stream_started is true this
90 is still a Windows path even if posix_path is true.
93 stream_started
= true;
94 start_of_name_component
= false;
98 return NT_STATUS_OBJECT_NAME_INVALID
;
102 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
104 * Safe to assume is not the second part of a mb char
105 * as this is handled below.
107 /* Eat multiple '/' or '\\' */
108 while (IS_PATH_SEP(*s
,posix_path
)) {
111 if ((d
!= path
) && (*s
!= '\0')) {
112 /* We only care about non-leading or trailing '/' or '\\' */
116 start_of_name_component
= True
;
118 *p_last_component_contains_wcard
= False
;
122 if (start_of_name_component
) {
123 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
124 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
127 * No mb char starts with '.' so we're safe checking the directory separator here.
130 /* If we just added a '/' - delete it */
131 if ((d
> path
) && (*(d
-1) == '/')) {
136 /* Are we at the start ? Can't go back further if so. */
138 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
141 /* Go back one level... */
142 /* We know this is safe as '/' cannot be part of a mb sequence. */
143 /* NOTE - if this assumption is invalid we are not in good shape... */
144 /* Decrement d first as d points to the *next* char to write into. */
145 for (d
--; d
> path
; d
--) {
149 s
+= 2; /* Else go past the .. */
150 /* We're still at the start of a name component, just the previous one. */
153 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
165 if (*s
<= 0x1f || *s
== '|') {
166 return NT_STATUS_OBJECT_NAME_INVALID
;
174 *p_last_component_contains_wcard
= True
;
183 /* Get the size of the next MB character. */
184 next_codepoint(s
,&siz
);
202 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
204 return NT_STATUS_INVALID_PARAMETER
;
207 start_of_name_component
= False
;
215 /****************************************************************************
216 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
217 No wildcards allowed.
218 ****************************************************************************/
220 NTSTATUS
check_path_syntax(char *path
)
223 return check_path_syntax_internal(path
, False
, &ignore
);
226 /****************************************************************************
227 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
228 Wildcards allowed - p_contains_wcard returns true if the last component contained
230 ****************************************************************************/
232 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
234 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
237 /****************************************************************************
238 Check the path for a POSIX client.
239 We're assuming here that '/' is not the second byte in any multibyte char
240 set (a safe assumption).
241 ****************************************************************************/
243 NTSTATUS
check_path_syntax_posix(char *path
)
246 return check_path_syntax_internal(path
, True
, &ignore
);
249 /****************************************************************************
250 Pull a string and check the path allowing a wilcard - provide for error return.
251 ****************************************************************************/
253 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
254 const char *base_ptr
,
261 bool *contains_wcard
)
267 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
271 *err
= NT_STATUS_INVALID_PARAMETER
;
275 *contains_wcard
= False
;
277 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
279 * For a DFS path the function parse_dfs_path()
280 * will do the path processing, just make a copy.
286 if (lp_posix_pathnames()) {
287 *err
= check_path_syntax_posix(*pp_dest
);
289 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
295 /****************************************************************************
296 Pull a string and check the path - provide for error return.
297 ****************************************************************************/
299 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
300 const char *base_ptr
,
309 return srvstr_get_path_wcard(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
310 src_len
, flags
, err
, &ignore
);
313 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
314 char **pp_dest
, const char *src
, int flags
,
315 NTSTATUS
*err
, bool *contains_wcard
)
317 return srvstr_get_path_wcard(mem_ctx
, (char *)req
->inbuf
, req
->flags2
,
318 pp_dest
, src
, smbreq_bufrem(req
, src
),
319 flags
, err
, contains_wcard
);
322 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
323 char **pp_dest
, const char *src
, int flags
,
327 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
328 flags
, err
, &ignore
);
331 /****************************************************************************
332 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
333 ****************************************************************************/
335 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
338 if ((fsp
== NULL
) || (conn
== NULL
)) {
339 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
342 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
343 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
349 /****************************************************************************
350 Check if we have a correct fsp pointing to a file.
351 ****************************************************************************/
353 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
356 if (!check_fsp_open(conn
, req
, fsp
)) {
359 if (fsp
->is_directory
) {
360 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
363 if (fsp
->fh
->fd
== -1) {
364 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
367 fsp
->num_smb_operations
++;
371 /****************************************************************************
372 Check if we have a correct fsp pointing to a quota fake file. Replacement for
373 the CHECK_NTQUOTA_HANDLE_OK macro.
374 ****************************************************************************/
376 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
379 if (!check_fsp_open(conn
, req
, fsp
)) {
383 if (fsp
->is_directory
) {
387 if (fsp
->fake_file_handle
== NULL
) {
391 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
395 if (fsp
->fake_file_handle
->private_data
== NULL
) {
402 static bool netbios_session_retarget(struct smbd_server_connection
*sconn
,
403 const char *name
, int name_type
)
406 char *trim_name_type
;
407 const char *retarget_parm
;
410 int retarget_type
= 0x20;
411 int retarget_port
= 139;
412 struct sockaddr_storage retarget_addr
;
413 struct sockaddr_in
*in_addr
;
417 if (get_socket_port(sconn
->sock
) != 139) {
421 trim_name
= talloc_strdup(talloc_tos(), name
);
422 if (trim_name
== NULL
) {
425 trim_char(trim_name
, ' ', ' ');
427 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
429 if (trim_name_type
== NULL
) {
433 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
434 trim_name_type
, NULL
);
435 if (retarget_parm
== NULL
) {
436 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
439 if (retarget_parm
== NULL
) {
443 retarget
= talloc_strdup(trim_name
, retarget_parm
);
444 if (retarget
== NULL
) {
448 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
450 p
= strchr(retarget
, ':');
453 retarget_port
= atoi(p
);
456 p
= strchr_m(retarget
, '#');
459 if (sscanf(p
, "%x", &retarget_type
) != 1) {
464 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
466 DEBUG(10, ("could not resolve %s\n", retarget
));
470 if (retarget_addr
.ss_family
!= AF_INET
) {
471 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
475 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
477 _smb_setlen(outbuf
, 6);
478 SCVAL(outbuf
, 0, 0x84);
479 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
480 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
482 if (!srv_send_smb(sconn
, (char *)outbuf
, false, 0, false,
484 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
490 TALLOC_FREE(trim_name
);
494 /****************************************************************************
495 Reply to a (netbios-level) special message.
496 ****************************************************************************/
498 void reply_special(struct smbd_server_connection
*sconn
, char *inbuf
, size_t inbuf_size
)
500 int msg_type
= CVAL(inbuf
,0);
501 int msg_flags
= CVAL(inbuf
,1);
503 * We only really use 4 bytes of the outbuf, but for the smb_setlen
504 * calculation & friends (srv_send_smb uses that) we need the full smb
507 char outbuf
[smb_size
];
509 memset(outbuf
, '\0', sizeof(outbuf
));
511 smb_setlen(outbuf
,0);
514 case 0x81: /* session request */
516 /* inbuf_size is guarenteed to be at least 4. */
518 int name_type1
, name_type2
;
519 int name_len1
, name_len2
;
523 if (sconn
->nbt
.got_session
) {
524 exit_server_cleanly("multiple session request not permitted");
527 SCVAL(outbuf
,0,0x82);
530 /* inbuf_size is guaranteed to be at least 4. */
531 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
532 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
533 DEBUG(0,("Invalid name length in session request\n"));
536 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
537 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
538 DEBUG(0,("Invalid name length in session request\n"));
542 name_type1
= name_extract((unsigned char *)inbuf
,
543 inbuf_size
,(unsigned int)4,name1
);
544 name_type2
= name_extract((unsigned char *)inbuf
,
545 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
547 if (name_type1
== -1 || name_type2
== -1) {
548 DEBUG(0,("Invalid name type in session request\n"));
552 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
553 name1
, name_type1
, name2
, name_type2
));
555 if (netbios_session_retarget(sconn
, name1
, name_type1
)) {
556 exit_server_cleanly("retargeted client");
560 * Windows NT/2k uses "*SMBSERVER" and XP uses
561 * "*SMBSERV" arrggg!!!
563 if (strequal(name1
, "*SMBSERVER ")
564 || strequal(name1
, "*SMBSERV ")) {
565 fstrcpy(name1
, sconn
->client_id
.addr
);
568 set_local_machine_name(name1
, True
);
569 set_remote_machine_name(name2
, True
);
571 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
572 get_local_machine_name(), get_remote_machine_name(),
575 if (name_type2
== 'R') {
576 /* We are being asked for a pathworks session ---
578 SCVAL(outbuf
, 0,0x83);
582 /* only add the client's machine name to the list
583 of possibly valid usernames if we are operating
584 in share mode security */
585 if (lp_security() == SEC_SHARE
) {
586 add_session_user(sconn
, get_remote_machine_name());
589 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
592 sconn
->nbt
.got_session
= true;
596 case 0x89: /* session keepalive request
597 (some old clients produce this?) */
598 SCVAL(outbuf
,0,SMBkeepalive
);
602 case 0x82: /* positive session response */
603 case 0x83: /* negative session response */
604 case 0x84: /* retarget session response */
605 DEBUG(0,("Unexpected session response\n"));
608 case SMBkeepalive
: /* session keepalive */
613 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
614 msg_type
, msg_flags
));
616 srv_send_smb(sconn
, outbuf
, false, 0, false, NULL
);
620 /****************************************************************************
622 conn POINTER CAN BE NULL HERE !
623 ****************************************************************************/
625 void reply_tcon(struct smb_request
*req
)
627 connection_struct
*conn
= req
->conn
;
629 char *service_buf
= NULL
;
630 char *password
= NULL
;
635 DATA_BLOB password_blob
;
636 TALLOC_CTX
*ctx
= talloc_tos();
637 struct smbd_server_connection
*sconn
= req
->sconn
;
639 START_PROFILE(SMBtcon
);
641 if (req
->buflen
< 4) {
642 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
643 END_PROFILE(SMBtcon
);
647 p
= (const char *)req
->buf
+ 1;
648 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
650 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
652 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
655 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
656 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
657 END_PROFILE(SMBtcon
);
660 p
= strrchr_m(service_buf
,'\\');
664 service
= service_buf
;
667 password_blob
= data_blob(password
, pwlen
+1);
669 conn
= make_connection(sconn
,service
,password_blob
,dev
,
670 req
->vuid
,&nt_status
);
673 data_blob_clear_free(&password_blob
);
676 reply_nterror(req
, nt_status
);
677 END_PROFILE(SMBtcon
);
681 reply_outbuf(req
, 2, 0);
682 SSVAL(req
->outbuf
,smb_vwv0
,sconn
->smb1
.negprot
.max_recv
);
683 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
684 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
686 DEBUG(3,("tcon service=%s cnum=%d\n",
687 service
, conn
->cnum
));
689 END_PROFILE(SMBtcon
);
693 /****************************************************************************
694 Reply to a tcon and X.
695 conn POINTER CAN BE NULL HERE !
696 ****************************************************************************/
698 void reply_tcon_and_X(struct smb_request
*req
)
700 connection_struct
*conn
= req
->conn
;
701 const char *service
= NULL
;
703 TALLOC_CTX
*ctx
= talloc_tos();
704 /* what the cleint thinks the device is */
705 char *client_devicetype
= NULL
;
706 /* what the server tells the client the share represents */
707 const char *server_devicetype
;
713 struct smbd_server_connection
*sconn
= req
->sconn
;
715 START_PROFILE(SMBtconX
);
718 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
719 END_PROFILE(SMBtconX
);
723 passlen
= SVAL(req
->vwv
+3, 0);
724 tcon_flags
= SVAL(req
->vwv
+2, 0);
726 /* we might have to close an old one */
727 if ((tcon_flags
& 0x1) && conn
) {
728 close_cnum(conn
,req
->vuid
);
733 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
734 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
735 END_PROFILE(SMBtconX
);
739 if (sconn
->smb1
.negprot
.encrypted_passwords
) {
740 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
);
741 if (lp_security() == SEC_SHARE
) {
743 * Security = share always has a pad byte
744 * after the password.
746 p
= (const char *)req
->buf
+ passlen
+ 1;
748 p
= (const char *)req
->buf
+ passlen
;
751 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
+1);
752 /* Ensure correct termination */
753 password
.data
[passlen
]=0;
754 p
= (const char *)req
->buf
+ passlen
+ 1;
757 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
760 data_blob_clear_free(&password
);
761 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
762 END_PROFILE(SMBtconX
);
767 * the service name can be either: \\server\share
768 * or share directly like on the DELL PowerVault 705
771 q
= strchr_m(path
+2,'\\');
773 data_blob_clear_free(&password
);
774 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
775 END_PROFILE(SMBtconX
);
783 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
784 &client_devicetype
, p
,
785 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
787 if (client_devicetype
== NULL
) {
788 data_blob_clear_free(&password
);
789 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
790 END_PROFILE(SMBtconX
);
794 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
796 conn
= make_connection(sconn
, service
, password
, client_devicetype
,
797 req
->vuid
, &nt_status
);
800 data_blob_clear_free(&password
);
803 reply_nterror(req
, nt_status
);
804 END_PROFILE(SMBtconX
);
809 server_devicetype
= "IPC";
810 else if ( IS_PRINT(conn
) )
811 server_devicetype
= "LPT1:";
813 server_devicetype
= "A:";
815 if (get_Protocol() < PROTOCOL_NT1
) {
816 reply_outbuf(req
, 2, 0);
817 if (message_push_string(&req
->outbuf
, server_devicetype
,
818 STR_TERMINATE
|STR_ASCII
) == -1) {
819 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
820 END_PROFILE(SMBtconX
);
824 /* NT sets the fstype of IPC$ to the null string */
825 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
827 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
828 /* Return permissions. */
832 reply_outbuf(req
, 7, 0);
835 perm1
= FILE_ALL_ACCESS
;
836 perm2
= FILE_ALL_ACCESS
;
838 perm1
= conn
->share_access
;
841 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
842 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
844 reply_outbuf(req
, 3, 0);
847 if ((message_push_string(&req
->outbuf
, server_devicetype
,
848 STR_TERMINATE
|STR_ASCII
) == -1)
849 || (message_push_string(&req
->outbuf
, fstype
,
850 STR_TERMINATE
) == -1)) {
851 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
852 END_PROFILE(SMBtconX
);
856 /* what does setting this bit do? It is set by NT4 and
857 may affect the ability to autorun mounted cdroms */
858 SSVAL(req
->outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
859 (lp_csc_policy(SNUM(conn
)) << 2));
861 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
862 DEBUG(2,("Serving %s as a Dfs root\n",
863 lp_servicename(SNUM(conn
)) ));
864 SSVAL(req
->outbuf
, smb_vwv2
,
865 SMB_SHARE_IN_DFS
| SVAL(req
->outbuf
, smb_vwv2
));
870 DEBUG(3,("tconX service=%s \n",
873 /* set the incoming and outgoing tid to the just created one */
874 SSVAL(req
->inbuf
,smb_tid
,conn
->cnum
);
875 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
877 END_PROFILE(SMBtconX
);
879 req
->tid
= conn
->cnum
;
884 /****************************************************************************
885 Reply to an unknown type.
886 ****************************************************************************/
888 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
890 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
891 smb_fn_name(type
), type
, type
));
892 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
896 /****************************************************************************
898 conn POINTER CAN BE NULL HERE !
899 ****************************************************************************/
901 void reply_ioctl(struct smb_request
*req
)
903 connection_struct
*conn
= req
->conn
;
910 START_PROFILE(SMBioctl
);
913 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
914 END_PROFILE(SMBioctl
);
918 device
= SVAL(req
->vwv
+1, 0);
919 function
= SVAL(req
->vwv
+2, 0);
920 ioctl_code
= (device
<< 16) + function
;
922 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
924 switch (ioctl_code
) {
925 case IOCTL_QUERY_JOB_INFO
:
929 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
930 END_PROFILE(SMBioctl
);
934 reply_outbuf(req
, 8, replysize
+1);
935 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
936 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
937 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
938 p
= smb_buf(req
->outbuf
);
939 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
940 p
+= 1; /* Allow for alignment */
942 switch (ioctl_code
) {
943 case IOCTL_QUERY_JOB_INFO
:
945 files_struct
*fsp
= file_fsp(
946 req
, SVAL(req
->vwv
+0, 0));
948 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
949 END_PROFILE(SMBioctl
);
953 if (fsp
->print_file
) {
954 SSVAL(p
, 0, fsp
->print_file
->rap_jobid
);
958 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
960 STR_TERMINATE
|STR_ASCII
);
962 srvstr_push((char *)req
->outbuf
, req
->flags2
,
963 p
+18, lp_servicename(SNUM(conn
)),
964 13, STR_TERMINATE
|STR_ASCII
);
972 END_PROFILE(SMBioctl
);
976 /****************************************************************************
977 Strange checkpath NTSTATUS mapping.
978 ****************************************************************************/
980 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
982 /* Strange DOS error code semantics only for checkpath... */
983 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
984 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
985 /* We need to map to ERRbadpath */
986 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
992 /****************************************************************************
993 Reply to a checkpath.
994 ****************************************************************************/
996 void reply_checkpath(struct smb_request
*req
)
998 connection_struct
*conn
= req
->conn
;
999 struct smb_filename
*smb_fname
= NULL
;
1002 TALLOC_CTX
*ctx
= talloc_tos();
1004 START_PROFILE(SMBcheckpath
);
1006 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1007 STR_TERMINATE
, &status
);
1009 if (!NT_STATUS_IS_OK(status
)) {
1010 status
= map_checkpath_error(req
->flags2
, status
);
1011 reply_nterror(req
, status
);
1012 END_PROFILE(SMBcheckpath
);
1016 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1018 status
= filename_convert(ctx
,
1020 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1026 if (!NT_STATUS_IS_OK(status
)) {
1027 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1028 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1029 ERRSRV
, ERRbadpath
);
1030 END_PROFILE(SMBcheckpath
);
1036 if (!VALID_STAT(smb_fname
->st
) &&
1037 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1038 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1039 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1040 status
= map_nt_error_from_unix(errno
);
1044 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1045 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1046 ERRDOS
, ERRbadpath
);
1050 reply_outbuf(req
, 0, 0);
1053 /* We special case this - as when a Windows machine
1054 is parsing a path is steps through the components
1055 one at a time - if a component fails it expects
1056 ERRbadpath, not ERRbadfile.
1058 status
= map_checkpath_error(req
->flags2
, status
);
1059 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1061 * Windows returns different error codes if
1062 * the parent directory is valid but not the
1063 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1064 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1065 * if the path is invalid.
1067 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1068 ERRDOS
, ERRbadpath
);
1072 reply_nterror(req
, status
);
1075 TALLOC_FREE(smb_fname
);
1076 END_PROFILE(SMBcheckpath
);
1080 /****************************************************************************
1082 ****************************************************************************/
1084 void reply_getatr(struct smb_request
*req
)
1086 connection_struct
*conn
= req
->conn
;
1087 struct smb_filename
*smb_fname
= NULL
;
1094 TALLOC_CTX
*ctx
= talloc_tos();
1095 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1097 START_PROFILE(SMBgetatr
);
1099 p
= (const char *)req
->buf
+ 1;
1100 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1101 if (!NT_STATUS_IS_OK(status
)) {
1102 reply_nterror(req
, status
);
1106 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1107 under WfWg - weird! */
1108 if (*fname
== '\0') {
1109 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1110 if (!CAN_WRITE(conn
)) {
1111 mode
|= FILE_ATTRIBUTE_READONLY
;
1116 status
= filename_convert(ctx
,
1118 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1123 if (!NT_STATUS_IS_OK(status
)) {
1124 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1125 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1126 ERRSRV
, ERRbadpath
);
1129 reply_nterror(req
, status
);
1132 if (!VALID_STAT(smb_fname
->st
) &&
1133 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1134 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1135 smb_fname_str_dbg(smb_fname
),
1137 reply_nterror(req
, map_nt_error_from_unix(errno
));
1141 mode
= dos_mode(conn
, smb_fname
);
1142 size
= smb_fname
->st
.st_ex_size
;
1144 if (ask_sharemode
) {
1145 struct timespec write_time_ts
;
1146 struct file_id fileid
;
1148 ZERO_STRUCT(write_time_ts
);
1149 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1150 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1151 if (!null_timespec(write_time_ts
)) {
1152 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1156 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1157 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1162 reply_outbuf(req
, 10, 0);
1164 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1165 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1166 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1168 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1170 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1172 if (get_Protocol() >= PROTOCOL_NT1
) {
1173 SSVAL(req
->outbuf
, smb_flg2
,
1174 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1177 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1178 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1181 TALLOC_FREE(smb_fname
);
1183 END_PROFILE(SMBgetatr
);
1187 /****************************************************************************
1189 ****************************************************************************/
1191 void reply_setatr(struct smb_request
*req
)
1193 struct smb_file_time ft
;
1194 connection_struct
*conn
= req
->conn
;
1195 struct smb_filename
*smb_fname
= NULL
;
1201 TALLOC_CTX
*ctx
= talloc_tos();
1203 START_PROFILE(SMBsetatr
);
1208 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1212 p
= (const char *)req
->buf
+ 1;
1213 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1214 if (!NT_STATUS_IS_OK(status
)) {
1215 reply_nterror(req
, status
);
1219 status
= filename_convert(ctx
,
1221 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1226 if (!NT_STATUS_IS_OK(status
)) {
1227 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1228 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1229 ERRSRV
, ERRbadpath
);
1232 reply_nterror(req
, status
);
1236 if (smb_fname
->base_name
[0] == '.' &&
1237 smb_fname
->base_name
[1] == '\0') {
1239 * Not sure here is the right place to catch this
1240 * condition. Might be moved to somewhere else later -- vl
1242 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1246 mode
= SVAL(req
->vwv
+0, 0);
1247 mtime
= srv_make_unix_date3(req
->vwv
+1);
1249 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1250 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1251 if (!NT_STATUS_IS_OK(status
)) {
1252 reply_nterror(req
, status
);
1256 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1257 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1258 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1260 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1262 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1264 reply_nterror(req
, map_nt_error_from_unix(errno
));
1269 reply_outbuf(req
, 0, 0);
1271 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1274 TALLOC_FREE(smb_fname
);
1275 END_PROFILE(SMBsetatr
);
1279 /****************************************************************************
1281 ****************************************************************************/
1283 void reply_dskattr(struct smb_request
*req
)
1285 connection_struct
*conn
= req
->conn
;
1286 uint64_t dfree
,dsize
,bsize
;
1287 START_PROFILE(SMBdskattr
);
1289 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1290 reply_nterror(req
, map_nt_error_from_unix(errno
));
1291 END_PROFILE(SMBdskattr
);
1295 reply_outbuf(req
, 5, 0);
1297 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1298 double total_space
, free_space
;
1299 /* we need to scale this to a number that DOS6 can handle. We
1300 use floating point so we can handle large drives on systems
1301 that don't have 64 bit integers
1303 we end up displaying a maximum of 2G to DOS systems
1305 total_space
= dsize
* (double)bsize
;
1306 free_space
= dfree
* (double)bsize
;
1308 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1309 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1311 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1312 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1314 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1315 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1316 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1317 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1319 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1320 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1321 SSVAL(req
->outbuf
,smb_vwv2
,512);
1322 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1325 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1327 END_PROFILE(SMBdskattr
);
1332 * Utility function to split the filename from the directory.
1334 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1335 char **fname_dir_out
,
1336 char **fname_mask_out
)
1338 const char *p
= NULL
;
1339 char *fname_dir
= NULL
;
1340 char *fname_mask
= NULL
;
1342 p
= strrchr_m(fname_in
, '/');
1344 fname_dir
= talloc_strdup(ctx
, ".");
1345 fname_mask
= talloc_strdup(ctx
, fname_in
);
1347 fname_dir
= talloc_strndup(ctx
, fname_in
,
1348 PTR_DIFF(p
, fname_in
));
1349 fname_mask
= talloc_strdup(ctx
, p
+1);
1352 if (!fname_dir
|| !fname_mask
) {
1353 TALLOC_FREE(fname_dir
);
1354 TALLOC_FREE(fname_mask
);
1355 return NT_STATUS_NO_MEMORY
;
1358 *fname_dir_out
= fname_dir
;
1359 *fname_mask_out
= fname_mask
;
1360 return NT_STATUS_OK
;
1363 /****************************************************************************
1365 Can be called from SMBsearch, SMBffirst or SMBfunique.
1366 ****************************************************************************/
1368 void reply_search(struct smb_request
*req
)
1370 connection_struct
*conn
= req
->conn
;
1372 const char *mask
= NULL
;
1373 char *directory
= NULL
;
1374 struct smb_filename
*smb_fname
= NULL
;
1378 struct timespec date
;
1380 unsigned int numentries
= 0;
1381 unsigned int maxentries
= 0;
1382 bool finished
= False
;
1387 bool check_descend
= False
;
1388 bool expect_close
= False
;
1390 bool mask_contains_wcard
= False
;
1391 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1392 TALLOC_CTX
*ctx
= talloc_tos();
1393 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1394 struct dptr_struct
*dirptr
= NULL
;
1395 struct smbd_server_connection
*sconn
= req
->sconn
;
1397 START_PROFILE(SMBsearch
);
1400 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1404 if (lp_posix_pathnames()) {
1405 reply_unknown_new(req
, req
->cmd
);
1409 /* If we were called as SMBffirst then we must expect close. */
1410 if(req
->cmd
== SMBffirst
) {
1411 expect_close
= True
;
1414 reply_outbuf(req
, 1, 3);
1415 maxentries
= SVAL(req
->vwv
+0, 0);
1416 dirtype
= SVAL(req
->vwv
+1, 0);
1417 p
= (const char *)req
->buf
+ 1;
1418 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1419 &nt_status
, &mask_contains_wcard
);
1420 if (!NT_STATUS_IS_OK(nt_status
)) {
1421 reply_nterror(req
, nt_status
);
1426 status_len
= SVAL(p
, 0);
1429 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1431 if (status_len
== 0) {
1432 nt_status
= filename_convert(ctx
, conn
,
1433 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1435 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1436 &mask_contains_wcard
,
1438 if (!NT_STATUS_IS_OK(nt_status
)) {
1439 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1440 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1441 ERRSRV
, ERRbadpath
);
1444 reply_nterror(req
, nt_status
);
1448 directory
= smb_fname
->base_name
;
1450 p
= strrchr_m(directory
,'/');
1451 if ((p
!= NULL
) && (*directory
!= '/')) {
1453 directory
= talloc_strndup(ctx
, directory
,
1454 PTR_DIFF(p
, directory
));
1457 directory
= talloc_strdup(ctx
,".");
1461 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1465 memset((char *)status
,'\0',21);
1466 SCVAL(status
,0,(dirtype
& 0x1F));
1468 nt_status
= dptr_create(conn
,
1475 mask_contains_wcard
,
1478 if (!NT_STATUS_IS_OK(nt_status
)) {
1479 reply_nterror(req
, nt_status
);
1482 dptr_num
= dptr_dnum(dirptr
);
1485 const char *dirpath
;
1487 memcpy(status
,p
,21);
1488 status_dirtype
= CVAL(status
,0) & 0x1F;
1489 if (status_dirtype
!= (dirtype
& 0x1F)) {
1490 dirtype
= status_dirtype
;
1493 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1497 dirpath
= dptr_path(sconn
, dptr_num
);
1498 directory
= talloc_strdup(ctx
, dirpath
);
1500 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1504 mask
= dptr_wcard(sconn
, dptr_num
);
1509 * For a 'continue' search we have no string. So
1510 * check from the initial saved string.
1512 mask_contains_wcard
= ms_has_wild(mask
);
1513 dirtype
= dptr_attr(sconn
, dptr_num
);
1516 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1518 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1519 dptr_init_search_op(dirptr
);
1521 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1522 char buf
[DIR_STRUCT_SIZE
];
1523 memcpy(buf
,status
,21);
1524 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1525 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1526 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1529 dptr_fill(sconn
, buf
+12,dptr_num
);
1530 if (dptr_zero(buf
+12) && (status_len
==0)) {
1535 if (message_push_blob(&req
->outbuf
,
1536 data_blob_const(buf
, sizeof(buf
)))
1538 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1546 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1549 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1550 directory
,lp_dontdescend(SNUM(conn
))));
1551 if (in_list(directory
, lp_dontdescend(SNUM(conn
)),True
)) {
1552 check_descend
= True
;
1555 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1556 finished
= !get_dir_entry(ctx
,
1567 char buf
[DIR_STRUCT_SIZE
];
1568 memcpy(buf
,status
,21);
1569 if (!make_dir_struct(ctx
,
1575 convert_timespec_to_time_t(date
),
1576 !allow_long_path_components
)) {
1577 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1580 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1583 if (message_push_blob(&req
->outbuf
,
1584 data_blob_const(buf
, sizeof(buf
)))
1586 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1596 /* If we were called as SMBffirst with smb_search_id == NULL
1597 and no entries were found then return error and close dirptr
1600 if (numentries
== 0) {
1601 dptr_close(sconn
, &dptr_num
);
1602 } else if(expect_close
&& status_len
== 0) {
1603 /* Close the dptr - we know it's gone */
1604 dptr_close(sconn
, &dptr_num
);
1607 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1608 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1609 dptr_close(sconn
, &dptr_num
);
1612 if ((numentries
== 0) && !mask_contains_wcard
) {
1613 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1617 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1618 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1619 SCVAL(smb_buf(req
->outbuf
),0,5);
1620 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1622 /* The replies here are never long name. */
1623 SSVAL(req
->outbuf
, smb_flg2
,
1624 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1625 if (!allow_long_path_components
) {
1626 SSVAL(req
->outbuf
, smb_flg2
,
1627 SVAL(req
->outbuf
, smb_flg2
)
1628 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1631 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1632 SSVAL(req
->outbuf
, smb_flg2
,
1633 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1635 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1636 smb_fn_name(req
->cmd
),
1643 TALLOC_FREE(directory
);
1644 TALLOC_FREE(smb_fname
);
1645 END_PROFILE(SMBsearch
);
1649 /****************************************************************************
1650 Reply to a fclose (stop directory search).
1651 ****************************************************************************/
1653 void reply_fclose(struct smb_request
*req
)
1661 bool path_contains_wcard
= False
;
1662 TALLOC_CTX
*ctx
= talloc_tos();
1663 struct smbd_server_connection
*sconn
= req
->sconn
;
1665 START_PROFILE(SMBfclose
);
1667 if (lp_posix_pathnames()) {
1668 reply_unknown_new(req
, req
->cmd
);
1669 END_PROFILE(SMBfclose
);
1673 p
= (const char *)req
->buf
+ 1;
1674 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1675 &err
, &path_contains_wcard
);
1676 if (!NT_STATUS_IS_OK(err
)) {
1677 reply_nterror(req
, err
);
1678 END_PROFILE(SMBfclose
);
1682 status_len
= SVAL(p
,0);
1685 if (status_len
== 0) {
1686 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1687 END_PROFILE(SMBfclose
);
1691 memcpy(status
,p
,21);
1693 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1694 /* Close the dptr - we know it's gone */
1695 dptr_close(sconn
, &dptr_num
);
1698 reply_outbuf(req
, 1, 0);
1699 SSVAL(req
->outbuf
,smb_vwv0
,0);
1701 DEBUG(3,("search close\n"));
1703 END_PROFILE(SMBfclose
);
1707 /****************************************************************************
1709 ****************************************************************************/
1711 void reply_open(struct smb_request
*req
)
1713 connection_struct
*conn
= req
->conn
;
1714 struct smb_filename
*smb_fname
= NULL
;
1726 uint32 create_disposition
;
1727 uint32 create_options
= 0;
1728 uint32_t private_flags
= 0;
1730 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1731 TALLOC_CTX
*ctx
= talloc_tos();
1733 START_PROFILE(SMBopen
);
1736 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1740 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1741 deny_mode
= SVAL(req
->vwv
+0, 0);
1742 dos_attr
= SVAL(req
->vwv
+1, 0);
1744 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1745 STR_TERMINATE
, &status
);
1746 if (!NT_STATUS_IS_OK(status
)) {
1747 reply_nterror(req
, status
);
1751 status
= filename_convert(ctx
,
1753 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1758 if (!NT_STATUS_IS_OK(status
)) {
1759 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1760 reply_botherror(req
,
1761 NT_STATUS_PATH_NOT_COVERED
,
1762 ERRSRV
, ERRbadpath
);
1765 reply_nterror(req
, status
);
1769 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1770 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1771 &share_mode
, &create_disposition
,
1772 &create_options
, &private_flags
)) {
1773 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1777 status
= SMB_VFS_CREATE_FILE(
1780 0, /* root_dir_fid */
1781 smb_fname
, /* fname */
1782 access_mask
, /* access_mask */
1783 share_mode
, /* share_access */
1784 create_disposition
, /* create_disposition*/
1785 create_options
, /* create_options */
1786 dos_attr
, /* file_attributes */
1787 oplock_request
, /* oplock_request */
1788 0, /* allocation_size */
1795 if (!NT_STATUS_IS_OK(status
)) {
1796 if (open_was_deferred(req
->mid
)) {
1797 /* We have re-scheduled this call. */
1800 reply_openerror(req
, status
);
1804 size
= smb_fname
->st
.st_ex_size
;
1805 fattr
= dos_mode(conn
, smb_fname
);
1807 /* Deal with other possible opens having a modified
1809 if (ask_sharemode
) {
1810 struct timespec write_time_ts
;
1812 ZERO_STRUCT(write_time_ts
);
1813 get_file_infos(fsp
->file_id
, 0, NULL
, &write_time_ts
);
1814 if (!null_timespec(write_time_ts
)) {
1815 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1819 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1821 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1822 DEBUG(3,("attempt to open a directory %s\n",
1824 close_file(req
, fsp
, ERROR_CLOSE
);
1825 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1826 ERRDOS
, ERRnoaccess
);
1830 reply_outbuf(req
, 7, 0);
1831 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1832 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1833 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1834 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1836 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1838 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1839 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1841 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1842 SCVAL(req
->outbuf
,smb_flg
,
1843 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1846 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1847 SCVAL(req
->outbuf
,smb_flg
,
1848 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1851 TALLOC_FREE(smb_fname
);
1852 END_PROFILE(SMBopen
);
1856 /****************************************************************************
1857 Reply to an open and X.
1858 ****************************************************************************/
1860 void reply_open_and_X(struct smb_request
*req
)
1862 connection_struct
*conn
= req
->conn
;
1863 struct smb_filename
*smb_fname
= NULL
;
1868 /* Breakout the oplock request bits so we can set the
1869 reply bits separately. */
1870 int ex_oplock_request
;
1871 int core_oplock_request
;
1874 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1875 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
1883 uint64_t allocation_size
;
1884 ssize_t retval
= -1;
1887 uint32 create_disposition
;
1888 uint32 create_options
= 0;
1889 uint32_t private_flags
= 0;
1890 TALLOC_CTX
*ctx
= talloc_tos();
1892 START_PROFILE(SMBopenX
);
1894 if (req
->wct
< 15) {
1895 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1899 open_flags
= SVAL(req
->vwv
+2, 0);
1900 deny_mode
= SVAL(req
->vwv
+3, 0);
1901 smb_attr
= SVAL(req
->vwv
+5, 0);
1902 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1903 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1904 oplock_request
= ex_oplock_request
| core_oplock_request
;
1905 smb_ofun
= SVAL(req
->vwv
+8, 0);
1906 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1908 /* If it's an IPC, pass off the pipe handler. */
1910 if (lp_nt_pipe_support()) {
1911 reply_open_pipe_and_X(conn
, req
);
1913 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1918 /* XXXX we need to handle passed times, sattr and flags */
1919 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1920 STR_TERMINATE
, &status
);
1921 if (!NT_STATUS_IS_OK(status
)) {
1922 reply_nterror(req
, status
);
1926 status
= filename_convert(ctx
,
1928 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1933 if (!NT_STATUS_IS_OK(status
)) {
1934 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1935 reply_botherror(req
,
1936 NT_STATUS_PATH_NOT_COVERED
,
1937 ERRSRV
, ERRbadpath
);
1940 reply_nterror(req
, status
);
1944 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1946 &access_mask
, &share_mode
,
1947 &create_disposition
,
1950 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1954 status
= SMB_VFS_CREATE_FILE(
1957 0, /* root_dir_fid */
1958 smb_fname
, /* fname */
1959 access_mask
, /* access_mask */
1960 share_mode
, /* share_access */
1961 create_disposition
, /* create_disposition*/
1962 create_options
, /* create_options */
1963 smb_attr
, /* file_attributes */
1964 oplock_request
, /* oplock_request */
1965 0, /* allocation_size */
1970 &smb_action
); /* pinfo */
1972 if (!NT_STATUS_IS_OK(status
)) {
1973 if (open_was_deferred(req
->mid
)) {
1974 /* We have re-scheduled this call. */
1977 reply_openerror(req
, status
);
1981 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1982 if the file is truncated or created. */
1983 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1984 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1985 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1986 close_file(req
, fsp
, ERROR_CLOSE
);
1987 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1990 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1992 close_file(req
, fsp
, ERROR_CLOSE
);
1993 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1996 status
= vfs_stat_fsp(fsp
);
1997 if (!NT_STATUS_IS_OK(status
)) {
1998 close_file(req
, fsp
, ERROR_CLOSE
);
1999 reply_nterror(req
, status
);
2004 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2005 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2006 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2007 close_file(req
, fsp
, ERROR_CLOSE
);
2008 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2012 /* If the caller set the extended oplock request bit
2013 and we granted one (by whatever means) - set the
2014 correct bit for extended oplock reply.
2017 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2018 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2021 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2022 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2025 /* If the caller set the core oplock request bit
2026 and we granted one (by whatever means) - set the
2027 correct bit for core oplock reply.
2030 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2031 reply_outbuf(req
, 19, 0);
2033 reply_outbuf(req
, 15, 0);
2036 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2037 SCVAL(req
->outbuf
, smb_flg
,
2038 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2041 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2042 SCVAL(req
->outbuf
, smb_flg
,
2043 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2046 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2047 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2048 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2049 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2051 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2053 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2054 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2055 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2057 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2058 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2063 TALLOC_FREE(smb_fname
);
2064 END_PROFILE(SMBopenX
);
2068 /****************************************************************************
2069 Reply to a SMBulogoffX.
2070 ****************************************************************************/
2072 void reply_ulogoffX(struct smb_request
*req
)
2074 struct smbd_server_connection
*sconn
= req
->sconn
;
2077 START_PROFILE(SMBulogoffX
);
2079 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2082 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2086 /* in user level security we are supposed to close any files
2087 open by this user */
2088 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
2089 file_close_user(sconn
, req
->vuid
);
2092 invalidate_vuid(sconn
, req
->vuid
);
2094 reply_outbuf(req
, 2, 0);
2096 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
2098 END_PROFILE(SMBulogoffX
);
2099 req
->vuid
= UID_FIELD_INVALID
;
2103 /****************************************************************************
2104 Reply to a mknew or a create.
2105 ****************************************************************************/
2107 void reply_mknew(struct smb_request
*req
)
2109 connection_struct
*conn
= req
->conn
;
2110 struct smb_filename
*smb_fname
= NULL
;
2113 struct smb_file_time ft
;
2115 int oplock_request
= 0;
2117 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2118 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2119 uint32 create_disposition
;
2120 uint32 create_options
= 0;
2121 TALLOC_CTX
*ctx
= talloc_tos();
2123 START_PROFILE(SMBcreate
);
2127 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2131 fattr
= SVAL(req
->vwv
+0, 0);
2132 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2135 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2137 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2138 STR_TERMINATE
, &status
);
2139 if (!NT_STATUS_IS_OK(status
)) {
2140 reply_nterror(req
, status
);
2144 status
= filename_convert(ctx
,
2146 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2151 if (!NT_STATUS_IS_OK(status
)) {
2152 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2153 reply_botherror(req
,
2154 NT_STATUS_PATH_NOT_COVERED
,
2155 ERRSRV
, ERRbadpath
);
2158 reply_nterror(req
, status
);
2162 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2163 DEBUG(0,("Attempt to create file (%s) with volid set - "
2164 "please report this\n",
2165 smb_fname_str_dbg(smb_fname
)));
2168 if(req
->cmd
== SMBmknew
) {
2169 /* We should fail if file exists. */
2170 create_disposition
= FILE_CREATE
;
2172 /* Create if file doesn't exist, truncate if it does. */
2173 create_disposition
= FILE_OVERWRITE_IF
;
2176 status
= SMB_VFS_CREATE_FILE(
2179 0, /* root_dir_fid */
2180 smb_fname
, /* fname */
2181 access_mask
, /* access_mask */
2182 share_mode
, /* share_access */
2183 create_disposition
, /* create_disposition*/
2184 create_options
, /* create_options */
2185 fattr
, /* file_attributes */
2186 oplock_request
, /* oplock_request */
2187 0, /* allocation_size */
2188 0, /* private_flags */
2194 if (!NT_STATUS_IS_OK(status
)) {
2195 if (open_was_deferred(req
->mid
)) {
2196 /* We have re-scheduled this call. */
2199 reply_openerror(req
, status
);
2203 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2204 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2205 if (!NT_STATUS_IS_OK(status
)) {
2206 END_PROFILE(SMBcreate
);
2210 reply_outbuf(req
, 1, 0);
2211 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2213 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2214 SCVAL(req
->outbuf
,smb_flg
,
2215 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2218 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2219 SCVAL(req
->outbuf
,smb_flg
,
2220 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2223 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2224 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2225 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2226 (unsigned int)fattr
));
2229 TALLOC_FREE(smb_fname
);
2230 END_PROFILE(SMBcreate
);
2234 /****************************************************************************
2235 Reply to a create temporary file.
2236 ****************************************************************************/
2238 void reply_ctemp(struct smb_request
*req
)
2240 connection_struct
*conn
= req
->conn
;
2241 struct smb_filename
*smb_fname
= NULL
;
2249 TALLOC_CTX
*ctx
= talloc_tos();
2251 START_PROFILE(SMBctemp
);
2254 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2258 fattr
= SVAL(req
->vwv
+0, 0);
2259 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2261 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2262 STR_TERMINATE
, &status
);
2263 if (!NT_STATUS_IS_OK(status
)) {
2264 reply_nterror(req
, status
);
2268 fname
= talloc_asprintf(ctx
,
2272 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2276 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2280 status
= filename_convert(ctx
, conn
,
2281 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2286 if (!NT_STATUS_IS_OK(status
)) {
2287 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2288 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2289 ERRSRV
, ERRbadpath
);
2292 reply_nterror(req
, status
);
2296 tmpfd
= mkstemp(smb_fname
->base_name
);
2298 reply_nterror(req
, map_nt_error_from_unix(errno
));
2302 SMB_VFS_STAT(conn
, smb_fname
);
2304 /* We should fail if file does not exist. */
2305 status
= SMB_VFS_CREATE_FILE(
2308 0, /* root_dir_fid */
2309 smb_fname
, /* fname */
2310 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2311 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2312 FILE_OPEN
, /* create_disposition*/
2313 0, /* create_options */
2314 fattr
, /* file_attributes */
2315 oplock_request
, /* oplock_request */
2316 0, /* allocation_size */
2317 0, /* private_flags */
2323 /* close fd from mkstemp() */
2326 if (!NT_STATUS_IS_OK(status
)) {
2327 if (open_was_deferred(req
->mid
)) {
2328 /* We have re-scheduled this call. */
2331 reply_openerror(req
, status
);
2335 reply_outbuf(req
, 1, 0);
2336 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2338 /* the returned filename is relative to the directory */
2339 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2341 s
= fsp
->fsp_name
->base_name
;
2347 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2348 thing in the byte section. JRA */
2349 SSVALS(p
, 0, -1); /* what is this? not in spec */
2351 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2353 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2357 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2358 SCVAL(req
->outbuf
, smb_flg
,
2359 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2362 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2363 SCVAL(req
->outbuf
, smb_flg
,
2364 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2367 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2368 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2369 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2371 TALLOC_FREE(smb_fname
);
2372 END_PROFILE(SMBctemp
);
2376 /*******************************************************************
2377 Check if a user is allowed to rename a file.
2378 ********************************************************************/
2380 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2383 if (!CAN_WRITE(conn
)) {
2384 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2387 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2388 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2389 /* Only bother to read the DOS attribute if we might deny the
2390 rename on the grounds of attribute missmatch. */
2391 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2392 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2393 return NT_STATUS_NO_SUCH_FILE
;
2397 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2398 if (fsp
->posix_open
) {
2399 return NT_STATUS_OK
;
2402 /* If no pathnames are open below this
2403 directory, allow the rename. */
2405 if (file_find_subpath(fsp
)) {
2406 return NT_STATUS_ACCESS_DENIED
;
2408 return NT_STATUS_OK
;
2411 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2412 return NT_STATUS_OK
;
2415 return NT_STATUS_ACCESS_DENIED
;
2418 /*******************************************************************
2419 * unlink a file with all relevant access checks
2420 *******************************************************************/
2422 static NTSTATUS
do_unlink(connection_struct
*conn
,
2423 struct smb_request
*req
,
2424 struct smb_filename
*smb_fname
,
2429 uint32 dirtype_orig
= dirtype
;
2432 bool posix_paths
= lp_posix_pathnames();
2434 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2435 smb_fname_str_dbg(smb_fname
),
2438 if (!CAN_WRITE(conn
)) {
2439 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2443 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2445 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2448 return map_nt_error_from_unix(errno
);
2451 fattr
= dos_mode(conn
, smb_fname
);
2453 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2454 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2457 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2459 return NT_STATUS_NO_SUCH_FILE
;
2462 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2463 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2464 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2466 return NT_STATUS_NO_SUCH_FILE
;
2469 if (dirtype_orig
& 0x8000) {
2470 /* These will never be set for POSIX. */
2471 return NT_STATUS_NO_SUCH_FILE
;
2475 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2476 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2479 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2480 return NT_STATUS_NO_SUCH_FILE
;
2483 if (dirtype
& 0xFF00) {
2484 /* These will never be set for POSIX. */
2485 return NT_STATUS_NO_SUCH_FILE
;
2490 return NT_STATUS_NO_SUCH_FILE
;
2493 /* Can't delete a directory. */
2494 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2495 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2500 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2501 return NT_STATUS_OBJECT_NAME_INVALID
;
2502 #endif /* JRATEST */
2504 /* On open checks the open itself will check the share mode, so
2505 don't do it here as we'll get it wrong. */
2507 status
= SMB_VFS_CREATE_FILE
2510 0, /* root_dir_fid */
2511 smb_fname
, /* fname */
2512 DELETE_ACCESS
, /* access_mask */
2513 FILE_SHARE_NONE
, /* share_access */
2514 FILE_OPEN
, /* create_disposition*/
2515 FILE_NON_DIRECTORY_FILE
, /* create_options */
2516 /* file_attributes */
2517 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2518 FILE_ATTRIBUTE_NORMAL
,
2519 0, /* oplock_request */
2520 0, /* allocation_size */
2521 0, /* private_flags */
2527 if (!NT_STATUS_IS_OK(status
)) {
2528 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2529 nt_errstr(status
)));
2533 status
= can_set_delete_on_close(fsp
, fattr
);
2534 if (!NT_STATUS_IS_OK(status
)) {
2535 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2537 smb_fname_str_dbg(smb_fname
),
2538 nt_errstr(status
)));
2539 close_file(req
, fsp
, NORMAL_CLOSE
);
2543 /* The set is across all open files on this dev/inode pair. */
2544 if (!set_delete_on_close(fsp
, true,
2545 conn
->session_info
->security_token
,
2546 &conn
->session_info
->utok
)) {
2547 close_file(req
, fsp
, NORMAL_CLOSE
);
2548 return NT_STATUS_ACCESS_DENIED
;
2551 return close_file(req
, fsp
, NORMAL_CLOSE
);
2554 /****************************************************************************
2555 The guts of the unlink command, split out so it may be called by the NT SMB
2557 ****************************************************************************/
2559 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2560 uint32 dirtype
, struct smb_filename
*smb_fname
,
2563 char *fname_dir
= NULL
;
2564 char *fname_mask
= NULL
;
2566 NTSTATUS status
= NT_STATUS_OK
;
2567 TALLOC_CTX
*ctx
= talloc_tos();
2569 /* Split up the directory from the filename/mask. */
2570 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2571 &fname_dir
, &fname_mask
);
2572 if (!NT_STATUS_IS_OK(status
)) {
2577 * We should only check the mangled cache
2578 * here if unix_convert failed. This means
2579 * that the path in 'mask' doesn't exist
2580 * on the file system and so we need to look
2581 * for a possible mangle. This patch from
2582 * Tine Smukavec <valentin.smukavec@hermes.si>.
2585 if (!VALID_STAT(smb_fname
->st
) &&
2586 mangle_is_mangled(fname_mask
, conn
->params
)) {
2587 char *new_mask
= NULL
;
2588 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2589 &new_mask
, conn
->params
);
2591 TALLOC_FREE(fname_mask
);
2592 fname_mask
= new_mask
;
2599 * Only one file needs to be unlinked. Append the mask back
2600 * onto the directory.
2602 TALLOC_FREE(smb_fname
->base_name
);
2603 if (ISDOT(fname_dir
)) {
2604 /* Ensure we use canonical names on open. */
2605 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2609 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2614 if (!smb_fname
->base_name
) {
2615 status
= NT_STATUS_NO_MEMORY
;
2619 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2622 status
= check_name(conn
, smb_fname
->base_name
);
2623 if (!NT_STATUS_IS_OK(status
)) {
2627 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2628 if (!NT_STATUS_IS_OK(status
)) {
2634 struct smb_Dir
*dir_hnd
= NULL
;
2636 const char *dname
= NULL
;
2637 char *talloced
= NULL
;
2639 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2640 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2644 if (strequal(fname_mask
,"????????.???")) {
2645 TALLOC_FREE(fname_mask
);
2646 fname_mask
= talloc_strdup(ctx
, "*");
2648 status
= NT_STATUS_NO_MEMORY
;
2653 status
= check_name(conn
, fname_dir
);
2654 if (!NT_STATUS_IS_OK(status
)) {
2658 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2660 if (dir_hnd
== NULL
) {
2661 status
= map_nt_error_from_unix(errno
);
2665 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2666 the pattern matches against the long name, otherwise the short name
2667 We don't implement this yet XXXX
2670 status
= NT_STATUS_NO_SUCH_FILE
;
2672 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2673 &smb_fname
->st
, &talloced
))) {
2674 TALLOC_CTX
*frame
= talloc_stackframe();
2676 if (!is_visible_file(conn
, fname_dir
, dname
,
2677 &smb_fname
->st
, true)) {
2679 TALLOC_FREE(talloced
);
2683 /* Quick check for "." and ".." */
2684 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2686 TALLOC_FREE(talloced
);
2690 if(!mask_match(dname
, fname_mask
,
2691 conn
->case_sensitive
)) {
2693 TALLOC_FREE(talloced
);
2697 TALLOC_FREE(smb_fname
->base_name
);
2698 if (ISDOT(fname_dir
)) {
2699 /* Ensure we use canonical names on open. */
2700 smb_fname
->base_name
=
2701 talloc_asprintf(smb_fname
, "%s",
2704 smb_fname
->base_name
=
2705 talloc_asprintf(smb_fname
, "%s/%s",
2709 if (!smb_fname
->base_name
) {
2710 TALLOC_FREE(dir_hnd
);
2711 status
= NT_STATUS_NO_MEMORY
;
2713 TALLOC_FREE(talloced
);
2717 status
= check_name(conn
, smb_fname
->base_name
);
2718 if (!NT_STATUS_IS_OK(status
)) {
2719 TALLOC_FREE(dir_hnd
);
2721 TALLOC_FREE(talloced
);
2725 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2726 if (!NT_STATUS_IS_OK(status
)) {
2728 TALLOC_FREE(talloced
);
2733 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2734 smb_fname
->base_name
));
2737 TALLOC_FREE(talloced
);
2739 TALLOC_FREE(dir_hnd
);
2742 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2743 status
= map_nt_error_from_unix(errno
);
2747 TALLOC_FREE(fname_dir
);
2748 TALLOC_FREE(fname_mask
);
2752 /****************************************************************************
2754 ****************************************************************************/
2756 void reply_unlink(struct smb_request
*req
)
2758 connection_struct
*conn
= req
->conn
;
2760 struct smb_filename
*smb_fname
= NULL
;
2763 bool path_contains_wcard
= False
;
2764 TALLOC_CTX
*ctx
= talloc_tos();
2766 START_PROFILE(SMBunlink
);
2769 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2773 dirtype
= SVAL(req
->vwv
+0, 0);
2775 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2776 STR_TERMINATE
, &status
,
2777 &path_contains_wcard
);
2778 if (!NT_STATUS_IS_OK(status
)) {
2779 reply_nterror(req
, status
);
2783 status
= filename_convert(ctx
, conn
,
2784 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2786 UCF_COND_ALLOW_WCARD_LCOMP
,
2787 &path_contains_wcard
,
2789 if (!NT_STATUS_IS_OK(status
)) {
2790 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2791 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2792 ERRSRV
, ERRbadpath
);
2795 reply_nterror(req
, status
);
2799 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2801 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2802 path_contains_wcard
);
2803 if (!NT_STATUS_IS_OK(status
)) {
2804 if (open_was_deferred(req
->mid
)) {
2805 /* We have re-scheduled this call. */
2808 reply_nterror(req
, status
);
2812 reply_outbuf(req
, 0, 0);
2814 TALLOC_FREE(smb_fname
);
2815 END_PROFILE(SMBunlink
);
2819 /****************************************************************************
2821 ****************************************************************************/
2823 static void fail_readraw(void)
2825 const char *errstr
= talloc_asprintf(talloc_tos(),
2826 "FAIL ! reply_readbraw: socket write fail (%s)",
2831 exit_server_cleanly(errstr
);
2834 /****************************************************************************
2835 Fake (read/write) sendfile. Returns -1 on read or write fail.
2836 ****************************************************************************/
2838 ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
)
2841 size_t tosend
= nread
;
2848 bufsize
= MIN(nread
, 65536);
2850 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2854 while (tosend
> 0) {
2858 if (tosend
> bufsize
) {
2863 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2869 /* If we had a short read, fill with zeros. */
2870 if (ret
< cur_read
) {
2871 memset(buf
+ ret
, '\0', cur_read
- ret
);
2874 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
2876 char addr
[INET6_ADDRSTRLEN
];
2878 * Try and give an error message saying what
2881 DEBUG(0, ("write_data failed for client %s. "
2883 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
2890 startpos
+= cur_read
;
2894 return (ssize_t
)nread
;
2897 /****************************************************************************
2898 Deal with the case of sendfile reading less bytes from the file than
2899 requested. Fill with zeros (all we can do).
2900 ****************************************************************************/
2902 void sendfile_short_send(files_struct
*fsp
,
2907 #define SHORT_SEND_BUFSIZE 1024
2908 if (nread
< headersize
) {
2909 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2910 "header for file %s (%s). Terminating\n",
2911 fsp_str_dbg(fsp
), strerror(errno
)));
2912 exit_server_cleanly("sendfile_short_send failed");
2915 nread
-= headersize
;
2917 if (nread
< smb_maxcnt
) {
2918 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
2920 exit_server_cleanly("sendfile_short_send: "
2924 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2925 "with zeros !\n", fsp_str_dbg(fsp
)));
2927 while (nread
< smb_maxcnt
) {
2929 * We asked for the real file size and told sendfile
2930 * to not go beyond the end of the file. But it can
2931 * happen that in between our fstat call and the
2932 * sendfile call the file was truncated. This is very
2933 * bad because we have already announced the larger
2934 * number of bytes to the client.
2936 * The best we can do now is to send 0-bytes, just as
2937 * a read from a hole in a sparse file would do.
2939 * This should happen rarely enough that I don't care
2940 * about efficiency here :-)
2944 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
2945 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
2947 char addr
[INET6_ADDRSTRLEN
];
2949 * Try and give an error message saying what
2952 DEBUG(0, ("write_data failed for client %s. "
2955 fsp
->conn
->sconn
->sock
, addr
,
2958 exit_server_cleanly("sendfile_short_send: "
2959 "write_data failed");
2967 /****************************************************************************
2968 Return a readbraw error (4 bytes of zero).
2969 ****************************************************************************/
2971 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
2977 smbd_lock_socket(sconn
);
2978 if (write_data(sconn
->sock
,header
,4) != 4) {
2979 char addr
[INET6_ADDRSTRLEN
];
2981 * Try and give an error message saying what
2984 DEBUG(0, ("write_data failed for client %s. "
2986 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
2991 smbd_unlock_socket(sconn
);
2994 /****************************************************************************
2995 Use sendfile in readbraw.
2996 ****************************************************************************/
2998 static void send_file_readbraw(connection_struct
*conn
,
2999 struct smb_request
*req
,
3005 struct smbd_server_connection
*sconn
= req
->sconn
;
3006 char *outbuf
= NULL
;
3010 * We can only use sendfile on a non-chained packet
3011 * but we can use on a non-oplocked file. tridge proved this
3012 * on a train in Germany :-). JRA.
3013 * reply_readbraw has already checked the length.
3016 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3017 (fsp
->wcp
== NULL
) &&
3018 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3019 ssize_t sendfile_read
= -1;
3021 DATA_BLOB header_blob
;
3023 _smb_setlen(header
,nread
);
3024 header_blob
= data_blob_const(header
, 4);
3026 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3027 &header_blob
, startpos
,
3029 if (sendfile_read
== -1) {
3030 /* Returning ENOSYS means no data at all was sent.
3031 * Do this as a normal read. */
3032 if (errno
== ENOSYS
) {
3033 goto normal_readbraw
;
3037 * Special hack for broken Linux with no working sendfile. If we
3038 * return EINTR we sent the header but not the rest of the data.
3039 * Fake this up by doing read/write calls.
3041 if (errno
== EINTR
) {
3042 /* Ensure we don't do this again. */
3043 set_use_sendfile(SNUM(conn
), False
);
3044 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3046 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3047 DEBUG(0,("send_file_readbraw: "
3048 "fake_sendfile failed for "
3052 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3057 DEBUG(0,("send_file_readbraw: sendfile failed for "
3058 "file %s (%s). Terminating\n",
3059 fsp_str_dbg(fsp
), strerror(errno
)));
3060 exit_server_cleanly("send_file_readbraw sendfile failed");
3061 } else if (sendfile_read
== 0) {
3063 * Some sendfile implementations return 0 to indicate
3064 * that there was a short read, but nothing was
3065 * actually written to the socket. In this case,
3066 * fallback to the normal read path so the header gets
3067 * the correct byte count.
3069 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3070 "bytes falling back to the normal read: "
3071 "%s\n", fsp_str_dbg(fsp
)));
3072 goto normal_readbraw
;
3075 /* Deal with possible short send. */
3076 if (sendfile_read
!= 4+nread
) {
3077 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3084 outbuf
= TALLOC_ARRAY(NULL
, char, nread
+4);
3086 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3087 (unsigned)(nread
+4)));
3088 reply_readbraw_error(sconn
);
3093 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3094 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3103 _smb_setlen(outbuf
,ret
);
3104 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3105 char addr
[INET6_ADDRSTRLEN
];
3107 * Try and give an error message saying what
3110 DEBUG(0, ("write_data failed for client %s. "
3112 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3119 TALLOC_FREE(outbuf
);
3122 /****************************************************************************
3123 Reply to a readbraw (core+ protocol).
3124 ****************************************************************************/
3126 void reply_readbraw(struct smb_request
*req
)
3128 connection_struct
*conn
= req
->conn
;
3129 struct smbd_server_connection
*sconn
= req
->sconn
;
3130 ssize_t maxcount
,mincount
;
3134 struct lock_struct lock
;
3137 START_PROFILE(SMBreadbraw
);
3139 if (srv_is_signing_active(sconn
) ||
3140 is_encrypted_packet(req
->inbuf
)) {
3141 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3142 "raw reads/writes are disallowed.");
3146 reply_readbraw_error(sconn
);
3147 END_PROFILE(SMBreadbraw
);
3151 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3152 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3153 "'async smb echo handler = yes'\n"));
3154 reply_readbraw_error(sconn
);
3155 END_PROFILE(SMBreadbraw
);
3160 * Special check if an oplock break has been issued
3161 * and the readraw request croses on the wire, we must
3162 * return a zero length response here.
3165 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3168 * We have to do a check_fsp by hand here, as
3169 * we must always return 4 zero bytes on error,
3173 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3174 req
->vuid
!= fsp
->vuid
||
3175 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3177 * fsp could be NULL here so use the value from the packet. JRA.
3179 DEBUG(3,("reply_readbraw: fnum %d not valid "
3181 (int)SVAL(req
->vwv
+0, 0)));
3182 reply_readbraw_error(sconn
);
3183 END_PROFILE(SMBreadbraw
);
3187 /* Do a "by hand" version of CHECK_READ. */
3188 if (!(fsp
->can_read
||
3189 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3190 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3191 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3192 (int)SVAL(req
->vwv
+0, 0)));
3193 reply_readbraw_error(sconn
);
3194 END_PROFILE(SMBreadbraw
);
3198 flush_write_cache(fsp
, READRAW_FLUSH
);
3200 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3201 if(req
->wct
== 10) {
3203 * This is a large offset (64 bit) read.
3205 #ifdef LARGE_SMB_OFF_T
3207 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+8, 0)) << 32);
3209 #else /* !LARGE_SMB_OFF_T */
3212 * Ensure we haven't been sent a >32 bit offset.
3215 if(IVAL(req
->vwv
+8, 0) != 0) {
3216 DEBUG(0,("reply_readbraw: large offset "
3217 "(%x << 32) used and we don't support "
3218 "64 bit offsets.\n",
3219 (unsigned int)IVAL(req
->vwv
+8, 0) ));
3220 reply_readbraw_error(sconn
);
3221 END_PROFILE(SMBreadbraw
);
3225 #endif /* LARGE_SMB_OFF_T */
3228 DEBUG(0,("reply_readbraw: negative 64 bit "
3229 "readraw offset (%.0f) !\n",
3230 (double)startpos
));
3231 reply_readbraw_error(sconn
);
3232 END_PROFILE(SMBreadbraw
);
3237 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3238 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3240 /* ensure we don't overrun the packet size */
3241 maxcount
= MIN(65535,maxcount
);
3243 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3244 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3247 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3248 reply_readbraw_error(sconn
);
3249 END_PROFILE(SMBreadbraw
);
3253 if (fsp_stat(fsp
) == 0) {
3254 size
= fsp
->fsp_name
->st
.st_ex_size
;
3257 if (startpos
>= size
) {
3260 nread
= MIN(maxcount
,(size
- startpos
));
3263 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3264 if (nread
< mincount
)
3268 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3269 "min=%lu nread=%lu\n",
3270 fsp
->fnum
, (double)startpos
,
3271 (unsigned long)maxcount
,
3272 (unsigned long)mincount
,
3273 (unsigned long)nread
) );
3275 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3277 DEBUG(5,("reply_readbraw finished\n"));
3279 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3281 END_PROFILE(SMBreadbraw
);
3286 #define DBGC_CLASS DBGC_LOCKING
3288 /****************************************************************************
3289 Reply to a lockread (core+ protocol).
3290 ****************************************************************************/
3292 void reply_lockread(struct smb_request
*req
)
3294 connection_struct
*conn
= req
->conn
;
3301 struct byte_range_lock
*br_lck
= NULL
;
3303 struct smbd_server_connection
*sconn
= req
->sconn
;
3305 START_PROFILE(SMBlockread
);
3308 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3309 END_PROFILE(SMBlockread
);
3313 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3315 if (!check_fsp(conn
, req
, fsp
)) {
3316 END_PROFILE(SMBlockread
);
3320 if (!CHECK_READ(fsp
,req
)) {
3321 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3322 END_PROFILE(SMBlockread
);
3326 numtoread
= SVAL(req
->vwv
+1, 0);
3327 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3329 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3331 reply_outbuf(req
, 5, numtoread
+ 3);
3333 data
= smb_buf(req
->outbuf
) + 3;
3336 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3337 * protocol request that predates the read/write lock concept.
3338 * Thus instead of asking for a read lock here we need to ask
3339 * for a write lock. JRA.
3340 * Note that the requested lock size is unaffected by max_recv.
3343 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3345 (uint64_t)req
->smbpid
,
3346 (uint64_t)numtoread
,
3350 False
, /* Non-blocking lock. */
3354 TALLOC_FREE(br_lck
);
3356 if (NT_STATUS_V(status
)) {
3357 reply_nterror(req
, status
);
3358 END_PROFILE(SMBlockread
);
3363 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3366 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3367 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3368 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3369 (unsigned int)numtoread
,
3370 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3371 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3373 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3376 reply_nterror(req
, map_nt_error_from_unix(errno
));
3377 END_PROFILE(SMBlockread
);
3381 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3383 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3384 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3385 p
= smb_buf(req
->outbuf
);
3386 SCVAL(p
,0,0); /* pad byte. */
3389 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3390 fsp
->fnum
, (int)numtoread
, (int)nread
));
3392 END_PROFILE(SMBlockread
);
3397 #define DBGC_CLASS DBGC_ALL
3399 /****************************************************************************
3401 ****************************************************************************/
3403 void reply_read(struct smb_request
*req
)
3405 connection_struct
*conn
= req
->conn
;
3412 struct lock_struct lock
;
3413 struct smbd_server_connection
*sconn
= req
->sconn
;
3415 START_PROFILE(SMBread
);
3418 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3419 END_PROFILE(SMBread
);
3423 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3425 if (!check_fsp(conn
, req
, fsp
)) {
3426 END_PROFILE(SMBread
);
3430 if (!CHECK_READ(fsp
,req
)) {
3431 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3432 END_PROFILE(SMBread
);
3436 numtoread
= SVAL(req
->vwv
+1, 0);
3437 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3439 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3442 * The requested read size cannot be greater than max_recv. JRA.
3444 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3445 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3446 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3447 (unsigned int)numtoread
,
3448 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3449 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3452 reply_outbuf(req
, 5, numtoread
+3);
3454 data
= smb_buf(req
->outbuf
) + 3;
3456 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3457 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3460 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3461 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3462 END_PROFILE(SMBread
);
3467 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3470 reply_nterror(req
, map_nt_error_from_unix(errno
));
3474 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3476 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3477 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3478 SCVAL(smb_buf(req
->outbuf
),0,1);
3479 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3481 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3482 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3485 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3487 END_PROFILE(SMBread
);
3491 /****************************************************************************
3493 ****************************************************************************/
3495 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3501 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3502 data
= smb_buf(outbuf
);
3504 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3506 SCVAL(outbuf
,smb_vwv0
,0xFF);
3507 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3508 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3509 SSVAL(outbuf
,smb_vwv6
,
3511 + 1 /* the wct field */
3512 + 12 * sizeof(uint16_t) /* vwv */
3513 + 2); /* the buflen field */
3514 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3515 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3516 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3517 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3521 /****************************************************************************
3522 Reply to a read and X - possibly using sendfile.
3523 ****************************************************************************/
3525 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3526 files_struct
*fsp
, SMB_OFF_T startpos
,
3530 struct lock_struct lock
;
3531 int saved_errno
= 0;
3533 if(fsp_stat(fsp
) == -1) {
3534 reply_nterror(req
, map_nt_error_from_unix(errno
));
3538 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3539 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3542 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3543 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3547 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3548 (startpos
> fsp
->fsp_name
->st
.st_ex_size
)
3549 || (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3551 * We already know that we would do a short read, so don't
3552 * try the sendfile() path.
3554 goto nosendfile_read
;
3558 * We can only use sendfile on a non-chained packet
3559 * but we can use on a non-oplocked file. tridge proved this
3560 * on a train in Germany :-). JRA.
3563 if (!req_is_in_chain(req
) &&
3564 !is_encrypted_packet(req
->inbuf
) && (fsp
->base_fsp
== NULL
) &&
3565 (fsp
->wcp
== NULL
) &&
3566 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3567 uint8 headerbuf
[smb_size
+ 12 * 2];
3571 * Set up the packet header before send. We
3572 * assume here the sendfile will work (get the
3573 * correct amount of data).
3576 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3578 construct_reply_common_req(req
, (char *)headerbuf
);
3579 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3581 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3582 startpos
, smb_maxcnt
);
3584 /* Returning ENOSYS means no data at all was sent.
3585 Do this as a normal read. */
3586 if (errno
== ENOSYS
) {
3591 * Special hack for broken Linux with no working sendfile. If we
3592 * return EINTR we sent the header but not the rest of the data.
3593 * Fake this up by doing read/write calls.
3596 if (errno
== EINTR
) {
3597 /* Ensure we don't do this again. */
3598 set_use_sendfile(SNUM(conn
), False
);
3599 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3600 nread
= fake_sendfile(fsp
, startpos
,
3603 DEBUG(0,("send_file_readX: "
3604 "fake_sendfile failed for "
3608 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3610 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3611 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3612 /* No outbuf here means successful sendfile. */
3616 DEBUG(0,("send_file_readX: sendfile failed for file "
3617 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3619 exit_server_cleanly("send_file_readX sendfile failed");
3620 } else if (nread
== 0) {
3622 * Some sendfile implementations return 0 to indicate
3623 * that there was a short read, but nothing was
3624 * actually written to the socket. In this case,
3625 * fallback to the normal read path so the header gets
3626 * the correct byte count.
3628 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3629 "falling back to the normal read: %s\n",
3634 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3635 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3637 /* Deal with possible short send. */
3638 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3639 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3641 /* No outbuf here means successful sendfile. */
3642 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3643 SMB_PERFCOUNT_END(&req
->pcd
);
3649 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3650 uint8 headerbuf
[smb_size
+ 2*12];
3652 construct_reply_common_req(req
, (char *)headerbuf
);
3653 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3655 /* Send out the header. */
3656 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3657 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3659 char addr
[INET6_ADDRSTRLEN
];
3661 * Try and give an error message saying what
3664 DEBUG(0, ("write_data failed for client %s. "
3666 get_peer_addr(req
->sconn
->sock
, addr
,
3670 DEBUG(0,("send_file_readX: write_data failed for file "
3671 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3673 exit_server_cleanly("send_file_readX sendfile failed");
3675 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3677 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3678 "file %s (%s).\n", fsp_str_dbg(fsp
),
3680 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3687 reply_outbuf(req
, 12, smb_maxcnt
);
3689 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3690 saved_errno
= errno
;
3692 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3695 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3699 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3701 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3702 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3708 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3709 TALLOC_FREE(req
->outbuf
);
3713 /****************************************************************************
3714 Reply to a read and X.
3715 ****************************************************************************/
3717 void reply_read_and_X(struct smb_request
*req
)
3719 connection_struct
*conn
= req
->conn
;
3723 bool big_readX
= False
;
3725 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3728 START_PROFILE(SMBreadX
);
3730 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3731 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3735 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3736 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3737 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3739 /* If it's an IPC, pass off the pipe handler. */
3741 reply_pipe_read_and_X(req
);
3742 END_PROFILE(SMBreadX
);
3746 if (!check_fsp(conn
, req
, fsp
)) {
3747 END_PROFILE(SMBreadX
);
3751 if (!CHECK_READ(fsp
,req
)) {
3752 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3753 END_PROFILE(SMBreadX
);
3757 if (global_client_caps
& CAP_LARGE_READX
) {
3758 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3759 smb_maxcnt
|= (upper_size
<<16);
3760 if (upper_size
> 1) {
3761 /* Can't do this on a chained packet. */
3762 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3763 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3764 END_PROFILE(SMBreadX
);
3767 /* We currently don't do this on signed or sealed data. */
3768 if (srv_is_signing_active(req
->sconn
) ||
3769 is_encrypted_packet(req
->inbuf
)) {
3770 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3771 END_PROFILE(SMBreadX
);
3774 /* Is there room in the reply for this data ? */
3775 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3777 NT_STATUS_INVALID_PARAMETER
);
3778 END_PROFILE(SMBreadX
);
3785 if (req
->wct
== 12) {
3786 #ifdef LARGE_SMB_OFF_T
3788 * This is a large offset (64 bit) read.
3790 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+10, 0)) << 32);
3792 #else /* !LARGE_SMB_OFF_T */
3795 * Ensure we haven't been sent a >32 bit offset.
3798 if(IVAL(req
->vwv
+10, 0) != 0) {
3799 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3800 "used and we don't support 64 bit offsets.\n",
3801 (unsigned int)IVAL(req
->vwv
+10, 0) ));
3802 END_PROFILE(SMBreadX
);
3803 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3807 #endif /* LARGE_SMB_OFF_T */
3812 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3817 if (NT_STATUS_IS_OK(status
)) {
3818 /* Read scheduled - we're done. */
3821 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3822 /* Real error - report to client. */
3823 END_PROFILE(SMBreadX
);
3824 reply_nterror(req
, status
);
3827 /* NT_STATUS_RETRY - fall back to sync read. */
3830 smbd_lock_socket(req
->sconn
);
3831 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3832 smbd_unlock_socket(req
->sconn
);
3835 END_PROFILE(SMBreadX
);
3839 /****************************************************************************
3840 Error replies to writebraw must have smb_wct == 1. Fix this up.
3841 ****************************************************************************/
3843 void error_to_writebrawerr(struct smb_request
*req
)
3845 uint8
*old_outbuf
= req
->outbuf
;
3847 reply_outbuf(req
, 1, 0);
3849 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3850 TALLOC_FREE(old_outbuf
);
3853 /****************************************************************************
3854 Read 4 bytes of a smb packet and return the smb length of the packet.
3855 Store the result in the buffer. This version of the function will
3856 never return a session keepalive (length of zero).
3857 Timeout is in milliseconds.
3858 ****************************************************************************/
3860 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3863 uint8_t msgtype
= SMBkeepalive
;
3865 while (msgtype
== SMBkeepalive
) {
3868 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3870 if (!NT_STATUS_IS_OK(status
)) {
3871 char addr
[INET6_ADDRSTRLEN
];
3872 /* Try and give an error message
3873 * saying what client failed. */
3874 DEBUG(0, ("read_fd_with_timeout failed for "
3875 "client %s read error = %s.\n",
3876 get_peer_addr(fd
,addr
,sizeof(addr
)),
3877 nt_errstr(status
)));
3881 msgtype
= CVAL(inbuf
, 0);
3884 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3885 (unsigned long)len
));
3887 return NT_STATUS_OK
;
3890 /****************************************************************************
3891 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3892 ****************************************************************************/
3894 void reply_writebraw(struct smb_request
*req
)
3896 connection_struct
*conn
= req
->conn
;
3899 ssize_t total_written
=0;
3900 size_t numtowrite
=0;
3906 struct lock_struct lock
;
3909 START_PROFILE(SMBwritebraw
);
3912 * If we ever reply with an error, it must have the SMB command
3913 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3916 SCVAL(req
->inbuf
,smb_com
,SMBwritec
);
3918 if (srv_is_signing_active(req
->sconn
)) {
3919 END_PROFILE(SMBwritebraw
);
3920 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3921 "raw reads/writes are disallowed.");
3924 if (req
->wct
< 12) {
3925 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3926 error_to_writebrawerr(req
);
3927 END_PROFILE(SMBwritebraw
);
3931 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3932 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3933 "'async smb echo handler = yes'\n"));
3934 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3935 error_to_writebrawerr(req
);
3936 END_PROFILE(SMBwritebraw
);
3940 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3941 if (!check_fsp(conn
, req
, fsp
)) {
3942 error_to_writebrawerr(req
);
3943 END_PROFILE(SMBwritebraw
);
3947 if (!CHECK_WRITE(fsp
)) {
3948 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3949 error_to_writebrawerr(req
);
3950 END_PROFILE(SMBwritebraw
);
3954 tcount
= IVAL(req
->vwv
+1, 0);
3955 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3956 write_through
= BITSETW(req
->vwv
+7,0);
3958 /* We have to deal with slightly different formats depending
3959 on whether we are using the core+ or lanman1.0 protocol */
3961 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
3962 numtowrite
= SVAL(smb_buf(req
->inbuf
),-2);
3963 data
= smb_buf(req
->inbuf
);
3965 numtowrite
= SVAL(req
->vwv
+10, 0);
3966 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3969 /* Ensure we don't write bytes past the end of this packet. */
3970 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3971 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3972 error_to_writebrawerr(req
);
3973 END_PROFILE(SMBwritebraw
);
3977 if (!fsp
->print_file
) {
3978 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3979 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
3982 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3983 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3984 error_to_writebrawerr(req
);
3985 END_PROFILE(SMBwritebraw
);
3991 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3994 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3995 "wrote=%d sync=%d\n",
3996 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3997 (int)nwritten
, (int)write_through
));
3999 if (nwritten
< (ssize_t
)numtowrite
) {
4000 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4001 error_to_writebrawerr(req
);
4005 total_written
= nwritten
;
4007 /* Allocate a buffer of 64k + length. */
4008 buf
= TALLOC_ARRAY(NULL
, char, 65540);
4010 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4011 error_to_writebrawerr(req
);
4015 /* Return a SMBwritebraw message to the redirector to tell
4016 * it to send more bytes */
4018 memcpy(buf
, req
->inbuf
, smb_size
);
4019 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4020 SCVAL(buf
,smb_com
,SMBwritebraw
);
4021 SSVALS(buf
,smb_vwv0
,0xFFFF);
4023 if (!srv_send_smb(req
->sconn
,
4025 false, 0, /* no signing */
4026 IS_CONN_ENCRYPTED(conn
),
4028 exit_server_cleanly("reply_writebraw: srv_send_smb "
4032 /* Now read the raw data into the buffer and write it */
4033 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4035 if (!NT_STATUS_IS_OK(status
)) {
4036 exit_server_cleanly("secondary writebraw failed");
4039 /* Set up outbuf to return the correct size */
4040 reply_outbuf(req
, 1, 0);
4042 if (numtowrite
!= 0) {
4044 if (numtowrite
> 0xFFFF) {
4045 DEBUG(0,("reply_writebraw: Oversize secondary write "
4046 "raw requested (%u). Terminating\n",
4047 (unsigned int)numtowrite
));
4048 exit_server_cleanly("secondary writebraw failed");
4051 if (tcount
> nwritten
+numtowrite
) {
4052 DEBUG(3,("reply_writebraw: Client overestimated the "
4054 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4057 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4059 if (!NT_STATUS_IS_OK(status
)) {
4060 char addr
[INET6_ADDRSTRLEN
];
4061 /* Try and give an error message
4062 * saying what client failed. */
4063 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4064 "raw read failed (%s) for client %s. "
4065 "Terminating\n", nt_errstr(status
),
4066 get_peer_addr(req
->sconn
->sock
, addr
,
4068 exit_server_cleanly("secondary writebraw failed");
4071 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4072 if (nwritten
== -1) {
4074 reply_nterror(req
, map_nt_error_from_unix(errno
));
4075 error_to_writebrawerr(req
);
4079 if (nwritten
< (ssize_t
)numtowrite
) {
4080 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4081 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4085 total_written
+= nwritten
;
4090 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4092 status
= sync_file(conn
, fsp
, write_through
);
4093 if (!NT_STATUS_IS_OK(status
)) {
4094 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4095 fsp_str_dbg(fsp
), nt_errstr(status
)));
4096 reply_nterror(req
, status
);
4097 error_to_writebrawerr(req
);
4101 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4103 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4104 (int)total_written
));
4106 if (!fsp
->print_file
) {
4107 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4110 /* We won't return a status if write through is not selected - this
4111 * follows what WfWg does */
4112 END_PROFILE(SMBwritebraw
);
4114 if (!write_through
&& total_written
==tcount
) {
4116 #if RABBIT_PELLET_FIX
4118 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4119 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4122 if (!send_keepalive(req
->sconn
->sock
)) {
4123 exit_server_cleanly("reply_writebraw: send of "
4124 "keepalive failed");
4127 TALLOC_FREE(req
->outbuf
);
4132 if (!fsp
->print_file
) {
4133 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4136 END_PROFILE(SMBwritebraw
);
4141 #define DBGC_CLASS DBGC_LOCKING
4143 /****************************************************************************
4144 Reply to a writeunlock (core+).
4145 ****************************************************************************/
4147 void reply_writeunlock(struct smb_request
*req
)
4149 connection_struct
*conn
= req
->conn
;
4150 ssize_t nwritten
= -1;
4154 NTSTATUS status
= NT_STATUS_OK
;
4156 struct lock_struct lock
;
4157 int saved_errno
= 0;
4159 START_PROFILE(SMBwriteunlock
);
4162 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4163 END_PROFILE(SMBwriteunlock
);
4167 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4169 if (!check_fsp(conn
, req
, fsp
)) {
4170 END_PROFILE(SMBwriteunlock
);
4174 if (!CHECK_WRITE(fsp
)) {
4175 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4176 END_PROFILE(SMBwriteunlock
);
4180 numtowrite
= SVAL(req
->vwv
+1, 0);
4181 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4182 data
= (const char *)req
->buf
+ 3;
4184 if (!fsp
->print_file
&& numtowrite
> 0) {
4185 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4186 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4189 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4190 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4191 END_PROFILE(SMBwriteunlock
);
4196 /* The special X/Open SMB protocol handling of
4197 zero length writes is *NOT* done for
4199 if(numtowrite
== 0) {
4202 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4203 saved_errno
= errno
;
4206 status
= sync_file(conn
, fsp
, False
/* write through */);
4207 if (!NT_STATUS_IS_OK(status
)) {
4208 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4209 fsp_str_dbg(fsp
), nt_errstr(status
)));
4210 reply_nterror(req
, status
);
4215 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4219 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4220 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4224 if (numtowrite
&& !fsp
->print_file
) {
4225 status
= do_unlock(req
->sconn
->msg_ctx
,
4227 (uint64_t)req
->smbpid
,
4228 (uint64_t)numtowrite
,
4232 if (NT_STATUS_V(status
)) {
4233 reply_nterror(req
, status
);
4238 reply_outbuf(req
, 1, 0);
4240 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4242 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4243 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4246 if (numtowrite
&& !fsp
->print_file
) {
4247 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4250 END_PROFILE(SMBwriteunlock
);
4255 #define DBGC_CLASS DBGC_ALL
4257 /****************************************************************************
4259 ****************************************************************************/
4261 void reply_write(struct smb_request
*req
)
4263 connection_struct
*conn
= req
->conn
;
4265 ssize_t nwritten
= -1;
4269 struct lock_struct lock
;
4271 int saved_errno
= 0;
4273 START_PROFILE(SMBwrite
);
4276 END_PROFILE(SMBwrite
);
4277 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4281 /* If it's an IPC, pass off the pipe handler. */
4283 reply_pipe_write(req
);
4284 END_PROFILE(SMBwrite
);
4288 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4290 if (!check_fsp(conn
, req
, fsp
)) {
4291 END_PROFILE(SMBwrite
);
4295 if (!CHECK_WRITE(fsp
)) {
4296 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4297 END_PROFILE(SMBwrite
);
4301 numtowrite
= SVAL(req
->vwv
+1, 0);
4302 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4303 data
= (const char *)req
->buf
+ 3;
4305 if (!fsp
->print_file
) {
4306 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4307 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4310 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4311 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4312 END_PROFILE(SMBwrite
);
4318 * X/Open SMB protocol says that if smb_vwv1 is
4319 * zero then the file size should be extended or
4320 * truncated to the size given in smb_vwv[2-3].
4323 if(numtowrite
== 0) {
4325 * This is actually an allocate call, and set EOF. JRA.
4327 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
4329 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4332 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
4334 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4337 trigger_write_time_update_immediate(fsp
);
4339 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4342 status
= sync_file(conn
, fsp
, False
);
4343 if (!NT_STATUS_IS_OK(status
)) {
4344 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4345 fsp_str_dbg(fsp
), nt_errstr(status
)));
4346 reply_nterror(req
, status
);
4351 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4355 if((nwritten
== 0) && (numtowrite
!= 0)) {
4356 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4360 reply_outbuf(req
, 1, 0);
4362 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4364 if (nwritten
< (ssize_t
)numtowrite
) {
4365 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4366 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4369 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4372 if (!fsp
->print_file
) {
4373 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4376 END_PROFILE(SMBwrite
);
4380 /****************************************************************************
4381 Ensure a buffer is a valid writeX for recvfile purposes.
4382 ****************************************************************************/
4384 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4385 (2*14) + /* word count (including bcc) */ \
4388 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4389 const uint8_t *inbuf
)
4392 connection_struct
*conn
= NULL
;
4393 unsigned int doff
= 0;
4394 size_t len
= smb_len_large(inbuf
);
4396 if (is_encrypted_packet(inbuf
)) {
4397 /* Can't do this on encrypted
4402 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4406 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4407 CVAL(inbuf
,smb_wct
) != 14) {
4408 DEBUG(10,("is_valid_writeX_buffer: chained or "
4409 "invalid word length.\n"));
4413 conn
= conn_find(sconn
, SVAL(inbuf
, smb_tid
));
4415 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4419 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4422 if (IS_PRINT(conn
)) {
4423 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4426 doff
= SVAL(inbuf
,smb_vwv11
);
4428 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4430 if (len
> doff
&& len
- doff
> 0xFFFF) {
4431 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4434 if (numtowrite
== 0) {
4435 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4439 /* Ensure the sizes match up. */
4440 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4441 /* no pad byte...old smbclient :-( */
4442 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4444 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4448 if (len
- doff
!= numtowrite
) {
4449 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4450 "len = %u, doff = %u, numtowrite = %u\n",
4453 (unsigned int)numtowrite
));
4457 DEBUG(10,("is_valid_writeX_buffer: true "
4458 "len = %u, doff = %u, numtowrite = %u\n",
4461 (unsigned int)numtowrite
));
4466 /****************************************************************************
4467 Reply to a write and X.
4468 ****************************************************************************/
4470 void reply_write_and_X(struct smb_request
*req
)
4472 connection_struct
*conn
= req
->conn
;
4474 struct lock_struct lock
;
4479 unsigned int smb_doff
;
4480 unsigned int smblen
;
4483 int saved_errno
= 0;
4485 START_PROFILE(SMBwriteX
);
4487 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4488 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4489 END_PROFILE(SMBwriteX
);
4493 numtowrite
= SVAL(req
->vwv
+10, 0);
4494 smb_doff
= SVAL(req
->vwv
+11, 0);
4495 smblen
= smb_len(req
->inbuf
);
4497 if (req
->unread_bytes
> 0xFFFF ||
4498 (smblen
> smb_doff
&&
4499 smblen
- smb_doff
> 0xFFFF)) {
4500 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4503 if (req
->unread_bytes
) {
4504 /* Can't do a recvfile write on IPC$ */
4506 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4507 END_PROFILE(SMBwriteX
);
4510 if (numtowrite
!= req
->unread_bytes
) {
4511 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4512 END_PROFILE(SMBwriteX
);
4516 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4517 smb_doff
+ numtowrite
> smblen
) {
4518 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4519 END_PROFILE(SMBwriteX
);
4524 /* If it's an IPC, pass off the pipe handler. */
4526 if (req
->unread_bytes
) {
4527 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4528 END_PROFILE(SMBwriteX
);
4531 reply_pipe_write_and_X(req
);
4532 END_PROFILE(SMBwriteX
);
4536 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4537 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4538 write_through
= BITSETW(req
->vwv
+7,0);
4540 if (!check_fsp(conn
, req
, fsp
)) {
4541 END_PROFILE(SMBwriteX
);
4545 if (!CHECK_WRITE(fsp
)) {
4546 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4547 END_PROFILE(SMBwriteX
);
4551 data
= smb_base(req
->inbuf
) + smb_doff
;
4553 if(req
->wct
== 14) {
4554 #ifdef LARGE_SMB_OFF_T
4556 * This is a large offset (64 bit) write.
4558 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+12, 0)) << 32);
4560 #else /* !LARGE_SMB_OFF_T */
4563 * Ensure we haven't been sent a >32 bit offset.
4566 if(IVAL(req
->vwv
+12, 0) != 0) {
4567 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4568 "used and we don't support 64 bit offsets.\n",
4569 (unsigned int)IVAL(req
->vwv
+12, 0) ));
4570 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4571 END_PROFILE(SMBwriteX
);
4575 #endif /* LARGE_SMB_OFF_T */
4578 /* X/Open SMB protocol says that, unlike SMBwrite
4579 if the length is zero then NO truncation is
4580 done, just a write of zero. To truncate a file,
4583 if(numtowrite
== 0) {
4586 if (req
->unread_bytes
== 0) {
4587 status
= schedule_aio_write_and_X(conn
,
4594 if (NT_STATUS_IS_OK(status
)) {
4595 /* write scheduled - we're done. */
4598 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4599 /* Real error - report to client. */
4600 reply_nterror(req
, status
);
4603 /* NT_STATUS_RETRY - fall through to sync write. */
4606 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4607 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4610 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4611 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4615 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4616 saved_errno
= errno
;
4618 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4622 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4626 if((nwritten
== 0) && (numtowrite
!= 0)) {
4627 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4631 reply_outbuf(req
, 6, 0);
4632 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4633 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4635 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4636 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4638 status
= sync_file(conn
, fsp
, write_through
);
4639 if (!NT_STATUS_IS_OK(status
)) {
4640 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4641 fsp_str_dbg(fsp
), nt_errstr(status
)));
4642 reply_nterror(req
, status
);
4646 END_PROFILE(SMBwriteX
);
4651 END_PROFILE(SMBwriteX
);
4655 /****************************************************************************
4657 ****************************************************************************/
4659 void reply_lseek(struct smb_request
*req
)
4661 connection_struct
*conn
= req
->conn
;
4667 START_PROFILE(SMBlseek
);
4670 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4671 END_PROFILE(SMBlseek
);
4675 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4677 if (!check_fsp(conn
, req
, fsp
)) {
4681 flush_write_cache(fsp
, SEEK_FLUSH
);
4683 mode
= SVAL(req
->vwv
+1, 0) & 3;
4684 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4685 startpos
= (SMB_OFF_T
)IVALS(req
->vwv
+2, 0);
4694 res
= fsp
->fh
->pos
+ startpos
;
4705 if (umode
== SEEK_END
) {
4706 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4707 if(errno
== EINVAL
) {
4708 SMB_OFF_T current_pos
= startpos
;
4710 if(fsp_stat(fsp
) == -1) {
4712 map_nt_error_from_unix(errno
));
4713 END_PROFILE(SMBlseek
);
4717 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4719 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4724 reply_nterror(req
, map_nt_error_from_unix(errno
));
4725 END_PROFILE(SMBlseek
);
4732 reply_outbuf(req
, 2, 0);
4733 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4735 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4736 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4738 END_PROFILE(SMBlseek
);
4742 /****************************************************************************
4744 ****************************************************************************/
4746 void reply_flush(struct smb_request
*req
)
4748 connection_struct
*conn
= req
->conn
;
4752 START_PROFILE(SMBflush
);
4755 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4759 fnum
= SVAL(req
->vwv
+0, 0);
4760 fsp
= file_fsp(req
, fnum
);
4762 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4767 file_sync_all(conn
);
4769 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4770 if (!NT_STATUS_IS_OK(status
)) {
4771 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4772 fsp_str_dbg(fsp
), nt_errstr(status
)));
4773 reply_nterror(req
, status
);
4774 END_PROFILE(SMBflush
);
4779 reply_outbuf(req
, 0, 0);
4781 DEBUG(3,("flush\n"));
4782 END_PROFILE(SMBflush
);
4786 /****************************************************************************
4788 conn POINTER CAN BE NULL HERE !
4789 ****************************************************************************/
4791 void reply_exit(struct smb_request
*req
)
4793 START_PROFILE(SMBexit
);
4795 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
4797 reply_outbuf(req
, 0, 0);
4799 DEBUG(3,("exit\n"));
4801 END_PROFILE(SMBexit
);
4805 /****************************************************************************
4806 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4807 ****************************************************************************/
4809 void reply_close(struct smb_request
*req
)
4811 connection_struct
*conn
= req
->conn
;
4812 NTSTATUS status
= NT_STATUS_OK
;
4813 files_struct
*fsp
= NULL
;
4814 START_PROFILE(SMBclose
);
4817 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4818 END_PROFILE(SMBclose
);
4822 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4825 * We can only use check_fsp if we know it's not a directory.
4828 if (!check_fsp_open(conn
, req
, fsp
)) {
4829 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4830 END_PROFILE(SMBclose
);
4834 if(fsp
->is_directory
) {
4836 * Special case - close NT SMB directory handle.
4838 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4839 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4843 * Close ordinary file.
4846 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4847 fsp
->fh
->fd
, fsp
->fnum
,
4848 conn
->num_files_open
));
4851 * Take care of any time sent in the close.
4854 t
= srv_make_unix_date3(req
->vwv
+1);
4855 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4858 * close_file() returns the unix errno if an error
4859 * was detected on close - normally this is due to
4860 * a disk full error. If not then it was probably an I/O error.
4863 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4866 if (!NT_STATUS_IS_OK(status
)) {
4867 reply_nterror(req
, status
);
4868 END_PROFILE(SMBclose
);
4872 reply_outbuf(req
, 0, 0);
4873 END_PROFILE(SMBclose
);
4877 /****************************************************************************
4878 Reply to a writeclose (Core+ protocol).
4879 ****************************************************************************/
4881 void reply_writeclose(struct smb_request
*req
)
4883 connection_struct
*conn
= req
->conn
;
4885 ssize_t nwritten
= -1;
4886 NTSTATUS close_status
= NT_STATUS_OK
;
4889 struct timespec mtime
;
4891 struct lock_struct lock
;
4893 START_PROFILE(SMBwriteclose
);
4896 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4897 END_PROFILE(SMBwriteclose
);
4901 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4903 if (!check_fsp(conn
, req
, fsp
)) {
4904 END_PROFILE(SMBwriteclose
);
4907 if (!CHECK_WRITE(fsp
)) {
4908 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4909 END_PROFILE(SMBwriteclose
);
4913 numtowrite
= SVAL(req
->vwv
+1, 0);
4914 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4915 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4916 data
= (const char *)req
->buf
+ 1;
4918 if (!fsp
->print_file
) {
4919 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4920 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4923 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4924 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4925 END_PROFILE(SMBwriteclose
);
4930 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4932 set_close_write_time(fsp
, mtime
);
4935 * More insanity. W2K only closes the file if writelen > 0.
4940 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4941 "file %s\n", fsp_str_dbg(fsp
)));
4942 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4945 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4946 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4947 conn
->num_files_open
));
4949 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4950 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4954 if(!NT_STATUS_IS_OK(close_status
)) {
4955 reply_nterror(req
, close_status
);
4959 reply_outbuf(req
, 1, 0);
4961 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4964 if (numtowrite
&& !fsp
->print_file
) {
4965 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4968 END_PROFILE(SMBwriteclose
);
4973 #define DBGC_CLASS DBGC_LOCKING
4975 /****************************************************************************
4977 ****************************************************************************/
4979 void reply_lock(struct smb_request
*req
)
4981 connection_struct
*conn
= req
->conn
;
4982 uint64_t count
,offset
;
4985 struct byte_range_lock
*br_lck
= NULL
;
4987 START_PROFILE(SMBlock
);
4990 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4991 END_PROFILE(SMBlock
);
4995 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4997 if (!check_fsp(conn
, req
, fsp
)) {
4998 END_PROFILE(SMBlock
);
5002 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5003 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5005 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5006 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
5008 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5010 (uint64_t)req
->smbpid
,
5015 False
, /* Non-blocking lock. */
5020 TALLOC_FREE(br_lck
);
5022 if (NT_STATUS_V(status
)) {
5023 reply_nterror(req
, status
);
5024 END_PROFILE(SMBlock
);
5028 reply_outbuf(req
, 0, 0);
5030 END_PROFILE(SMBlock
);
5034 /****************************************************************************
5036 ****************************************************************************/
5038 void reply_unlock(struct smb_request
*req
)
5040 connection_struct
*conn
= req
->conn
;
5041 uint64_t count
,offset
;
5045 START_PROFILE(SMBunlock
);
5048 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5049 END_PROFILE(SMBunlock
);
5053 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5055 if (!check_fsp(conn
, req
, fsp
)) {
5056 END_PROFILE(SMBunlock
);
5060 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5061 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5063 status
= do_unlock(req
->sconn
->msg_ctx
,
5065 (uint64_t)req
->smbpid
,
5070 if (NT_STATUS_V(status
)) {
5071 reply_nterror(req
, status
);
5072 END_PROFILE(SMBunlock
);
5076 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5077 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
5079 reply_outbuf(req
, 0, 0);
5081 END_PROFILE(SMBunlock
);
5086 #define DBGC_CLASS DBGC_ALL
5088 /****************************************************************************
5090 conn POINTER CAN BE NULL HERE !
5091 ****************************************************************************/
5093 void reply_tdis(struct smb_request
*req
)
5095 connection_struct
*conn
= req
->conn
;
5096 START_PROFILE(SMBtdis
);
5099 DEBUG(4,("Invalid connection in tdis\n"));
5100 reply_nterror(req
, NT_STATUS_NETWORK_NAME_DELETED
);
5101 END_PROFILE(SMBtdis
);
5107 close_cnum(conn
,req
->vuid
);
5110 reply_outbuf(req
, 0, 0);
5111 END_PROFILE(SMBtdis
);
5115 /****************************************************************************
5117 conn POINTER CAN BE NULL HERE !
5118 ****************************************************************************/
5120 void reply_echo(struct smb_request
*req
)
5122 connection_struct
*conn
= req
->conn
;
5123 struct smb_perfcount_data local_pcd
;
5124 struct smb_perfcount_data
*cur_pcd
;
5128 START_PROFILE(SMBecho
);
5130 smb_init_perfcount_data(&local_pcd
);
5133 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5134 END_PROFILE(SMBecho
);
5138 smb_reverb
= SVAL(req
->vwv
+0, 0);
5140 reply_outbuf(req
, 1, req
->buflen
);
5142 /* copy any incoming data back out */
5143 if (req
->buflen
> 0) {
5144 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5147 if (smb_reverb
> 100) {
5148 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5152 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5154 /* this makes sure we catch the request pcd */
5155 if (seq_num
== smb_reverb
) {
5156 cur_pcd
= &req
->pcd
;
5158 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5159 cur_pcd
= &local_pcd
;
5162 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5164 show_msg((char *)req
->outbuf
);
5165 if (!srv_send_smb(req
->sconn
,
5166 (char *)req
->outbuf
,
5167 true, req
->seqnum
+1,
5168 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5170 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5173 DEBUG(3,("echo %d times\n", smb_reverb
));
5175 TALLOC_FREE(req
->outbuf
);
5177 END_PROFILE(SMBecho
);
5181 /****************************************************************************
5182 Reply to a printopen.
5183 ****************************************************************************/
5185 void reply_printopen(struct smb_request
*req
)
5187 connection_struct
*conn
= req
->conn
;
5191 START_PROFILE(SMBsplopen
);
5194 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5195 END_PROFILE(SMBsplopen
);
5199 if (!CAN_PRINT(conn
)) {
5200 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5201 END_PROFILE(SMBsplopen
);
5205 status
= file_new(req
, conn
, &fsp
);
5206 if(!NT_STATUS_IS_OK(status
)) {
5207 reply_nterror(req
, status
);
5208 END_PROFILE(SMBsplopen
);
5212 /* Open for exclusive use, write only. */
5213 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5215 if (!NT_STATUS_IS_OK(status
)) {
5216 file_free(req
, fsp
);
5217 reply_nterror(req
, status
);
5218 END_PROFILE(SMBsplopen
);
5222 reply_outbuf(req
, 1, 0);
5223 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5225 DEBUG(3,("openprint fd=%d fnum=%d\n",
5226 fsp
->fh
->fd
, fsp
->fnum
));
5228 END_PROFILE(SMBsplopen
);
5232 /****************************************************************************
5233 Reply to a printclose.
5234 ****************************************************************************/
5236 void reply_printclose(struct smb_request
*req
)
5238 connection_struct
*conn
= req
->conn
;
5242 START_PROFILE(SMBsplclose
);
5245 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5246 END_PROFILE(SMBsplclose
);
5250 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5252 if (!check_fsp(conn
, req
, fsp
)) {
5253 END_PROFILE(SMBsplclose
);
5257 if (!CAN_PRINT(conn
)) {
5258 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5259 END_PROFILE(SMBsplclose
);
5263 DEBUG(3,("printclose fd=%d fnum=%d\n",
5264 fsp
->fh
->fd
,fsp
->fnum
));
5266 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5268 if(!NT_STATUS_IS_OK(status
)) {
5269 reply_nterror(req
, status
);
5270 END_PROFILE(SMBsplclose
);
5274 reply_outbuf(req
, 0, 0);
5276 END_PROFILE(SMBsplclose
);
5280 /****************************************************************************
5281 Reply to a printqueue.
5282 ****************************************************************************/
5284 void reply_printqueue(struct smb_request
*req
)
5286 connection_struct
*conn
= req
->conn
;
5290 START_PROFILE(SMBsplretq
);
5293 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5294 END_PROFILE(SMBsplretq
);
5298 max_count
= SVAL(req
->vwv
+0, 0);
5299 start_index
= SVAL(req
->vwv
+1, 0);
5301 /* we used to allow the client to get the cnum wrong, but that
5302 is really quite gross and only worked when there was only
5303 one printer - I think we should now only accept it if they
5304 get it right (tridge) */
5305 if (!CAN_PRINT(conn
)) {
5306 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5307 END_PROFILE(SMBsplretq
);
5311 reply_outbuf(req
, 2, 3);
5312 SSVAL(req
->outbuf
,smb_vwv0
,0);
5313 SSVAL(req
->outbuf
,smb_vwv1
,0);
5314 SCVAL(smb_buf(req
->outbuf
),0,1);
5315 SSVAL(smb_buf(req
->outbuf
),1,0);
5317 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5318 start_index
, max_count
));
5321 TALLOC_CTX
*mem_ctx
= talloc_tos();
5324 const char *sharename
= lp_servicename(SNUM(conn
));
5325 struct rpc_pipe_client
*cli
= NULL
;
5326 struct dcerpc_binding_handle
*b
= NULL
;
5327 struct policy_handle handle
;
5328 struct spoolss_DevmodeContainer devmode_ctr
;
5329 union spoolss_JobInfo
*info
;
5331 uint32_t num_to_get
;
5335 ZERO_STRUCT(handle
);
5337 status
= rpc_pipe_open_interface(conn
,
5338 &ndr_table_spoolss
.syntax_id
,
5340 &conn
->sconn
->client_id
,
5341 conn
->sconn
->msg_ctx
,
5343 if (!NT_STATUS_IS_OK(status
)) {
5344 DEBUG(0, ("reply_printqueue: "
5345 "could not connect to spoolss: %s\n",
5346 nt_errstr(status
)));
5347 reply_nterror(req
, status
);
5350 b
= cli
->binding_handle
;
5352 ZERO_STRUCT(devmode_ctr
);
5354 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5357 SEC_FLAG_MAXIMUM_ALLOWED
,
5360 if (!NT_STATUS_IS_OK(status
)) {
5361 reply_nterror(req
, status
);
5364 if (!W_ERROR_IS_OK(werr
)) {
5365 reply_nterror(req
, werror_to_ntstatus(werr
));
5369 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5377 if (!W_ERROR_IS_OK(werr
)) {
5378 reply_nterror(req
, werror_to_ntstatus(werr
));
5382 if (max_count
> 0) {
5383 first
= start_index
;
5385 first
= start_index
+ max_count
+ 1;
5388 if (first
>= count
) {
5391 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5394 for (i
= first
; i
< num_to_get
; i
++) {
5397 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5399 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5400 info
[i
].info2
.job_id
);
5402 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5408 srv_put_dos_date2(p
, 0, qtime
);
5409 SCVAL(p
, 4, qstatus
);
5410 SSVAL(p
, 5, qrapjobid
);
5411 SIVAL(p
, 7, info
[i
].info2
.size
);
5413 srvstr_push(blob
, req
->flags2
, p
+12,
5414 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5416 if (message_push_blob(
5419 blob
, sizeof(blob
))) == -1) {
5420 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5426 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5427 SSVAL(req
->outbuf
,smb_vwv1
,
5428 (max_count
>0?first
+count
:first
-1));
5429 SCVAL(smb_buf(req
->outbuf
),0,1);
5430 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5434 DEBUG(3, ("%u entries returned in queue\n",
5438 if (b
&& is_valid_policy_hnd(&handle
)) {
5439 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5444 END_PROFILE(SMBsplretq
);
5448 /****************************************************************************
5449 Reply to a printwrite.
5450 ****************************************************************************/
5452 void reply_printwrite(struct smb_request
*req
)
5454 connection_struct
*conn
= req
->conn
;
5459 START_PROFILE(SMBsplwr
);
5462 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5463 END_PROFILE(SMBsplwr
);
5467 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5469 if (!check_fsp(conn
, req
, fsp
)) {
5470 END_PROFILE(SMBsplwr
);
5474 if (!fsp
->print_file
) {
5475 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5476 END_PROFILE(SMBsplwr
);
5480 if (!CHECK_WRITE(fsp
)) {
5481 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5482 END_PROFILE(SMBsplwr
);
5486 numtowrite
= SVAL(req
->buf
, 1);
5488 if (req
->buflen
< numtowrite
+ 3) {
5489 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5490 END_PROFILE(SMBsplwr
);
5494 data
= (const char *)req
->buf
+ 3;
5496 if (write_file(req
,fsp
,data
,(SMB_OFF_T
)-1,numtowrite
) != numtowrite
) {
5497 reply_nterror(req
, map_nt_error_from_unix(errno
));
5498 END_PROFILE(SMBsplwr
);
5502 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
5504 END_PROFILE(SMBsplwr
);
5508 /****************************************************************************
5510 ****************************************************************************/
5512 void reply_mkdir(struct smb_request
*req
)
5514 connection_struct
*conn
= req
->conn
;
5515 struct smb_filename
*smb_dname
= NULL
;
5516 char *directory
= NULL
;
5518 TALLOC_CTX
*ctx
= talloc_tos();
5520 START_PROFILE(SMBmkdir
);
5522 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5523 STR_TERMINATE
, &status
);
5524 if (!NT_STATUS_IS_OK(status
)) {
5525 reply_nterror(req
, status
);
5529 status
= filename_convert(ctx
, conn
,
5530 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5535 if (!NT_STATUS_IS_OK(status
)) {
5536 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5537 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5538 ERRSRV
, ERRbadpath
);
5541 reply_nterror(req
, status
);
5545 status
= create_directory(conn
, req
, smb_dname
);
5547 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5549 if (!NT_STATUS_IS_OK(status
)) {
5551 if (!use_nt_status()
5552 && NT_STATUS_EQUAL(status
,
5553 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5555 * Yes, in the DOS error code case we get a
5556 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5557 * samba4 torture test.
5559 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5562 reply_nterror(req
, status
);
5566 reply_outbuf(req
, 0, 0);
5568 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5570 TALLOC_FREE(smb_dname
);
5571 END_PROFILE(SMBmkdir
);
5575 /****************************************************************************
5577 ****************************************************************************/
5579 void reply_rmdir(struct smb_request
*req
)
5581 connection_struct
*conn
= req
->conn
;
5582 struct smb_filename
*smb_dname
= NULL
;
5583 char *directory
= NULL
;
5585 TALLOC_CTX
*ctx
= talloc_tos();
5586 files_struct
*fsp
= NULL
;
5588 struct smbd_server_connection
*sconn
= req
->sconn
;
5590 START_PROFILE(SMBrmdir
);
5592 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5593 STR_TERMINATE
, &status
);
5594 if (!NT_STATUS_IS_OK(status
)) {
5595 reply_nterror(req
, status
);
5599 status
= filename_convert(ctx
, conn
,
5600 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5605 if (!NT_STATUS_IS_OK(status
)) {
5606 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5607 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5608 ERRSRV
, ERRbadpath
);
5611 reply_nterror(req
, status
);
5615 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5616 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5620 status
= SMB_VFS_CREATE_FILE(
5623 0, /* root_dir_fid */
5624 smb_dname
, /* fname */
5625 DELETE_ACCESS
, /* access_mask */
5626 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5628 FILE_OPEN
, /* create_disposition*/
5629 FILE_DIRECTORY_FILE
, /* create_options */
5630 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5631 0, /* oplock_request */
5632 0, /* allocation_size */
5633 0, /* private_flags */
5639 if (!NT_STATUS_IS_OK(status
)) {
5640 if (open_was_deferred(req
->mid
)) {
5641 /* We have re-scheduled this call. */
5644 reply_nterror(req
, status
);
5648 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5649 if (!NT_STATUS_IS_OK(status
)) {
5650 close_file(req
, fsp
, ERROR_CLOSE
);
5651 reply_nterror(req
, status
);
5655 if (!set_delete_on_close(fsp
, true,
5656 conn
->session_info
->security_token
,
5657 &conn
->session_info
->utok
)) {
5658 close_file(req
, fsp
, ERROR_CLOSE
);
5659 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5663 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5664 if (!NT_STATUS_IS_OK(status
)) {
5665 reply_nterror(req
, status
);
5667 reply_outbuf(req
, 0, 0);
5670 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5672 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5674 TALLOC_FREE(smb_dname
);
5675 END_PROFILE(SMBrmdir
);
5679 /*******************************************************************
5680 Resolve wildcards in a filename rename.
5681 ********************************************************************/
5683 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5688 char *name2_copy
= NULL
;
5693 char *p
,*p2
, *pname1
, *pname2
;
5695 name2_copy
= talloc_strdup(ctx
, name2
);
5700 pname1
= strrchr_m(name1
,'/');
5701 pname2
= strrchr_m(name2_copy
,'/');
5703 if (!pname1
|| !pname2
) {
5707 /* Truncate the copy of name2 at the last '/' */
5710 /* Now go past the '/' */
5714 root1
= talloc_strdup(ctx
, pname1
);
5715 root2
= talloc_strdup(ctx
, pname2
);
5717 if (!root1
|| !root2
) {
5721 p
= strrchr_m(root1
,'.');
5724 ext1
= talloc_strdup(ctx
, p
+1);
5726 ext1
= talloc_strdup(ctx
, "");
5728 p
= strrchr_m(root2
,'.');
5731 ext2
= talloc_strdup(ctx
, p
+1);
5733 ext2
= talloc_strdup(ctx
, "");
5736 if (!ext1
|| !ext2
) {
5744 /* Hmmm. Should this be mb-aware ? */
5747 } else if (*p2
== '*') {
5749 root2
= talloc_asprintf(ctx
, "%s%s",
5768 /* Hmmm. Should this be mb-aware ? */
5771 } else if (*p2
== '*') {
5773 ext2
= talloc_asprintf(ctx
, "%s%s",
5789 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5794 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5806 /****************************************************************************
5807 Ensure open files have their names updated. Updated to notify other smbd's
5809 ****************************************************************************/
5811 static void rename_open_files(connection_struct
*conn
,
5812 struct share_mode_lock
*lck
,
5813 uint32_t orig_name_hash
,
5814 const struct smb_filename
*smb_fname_dst
)
5817 bool did_rename
= False
;
5819 uint32_t new_name_hash
;
5821 for(fsp
= file_find_di_first(conn
->sconn
, lck
->id
); fsp
;
5822 fsp
= file_find_di_next(fsp
)) {
5823 /* fsp_name is a relative path under the fsp. To change this for other
5824 sharepaths we need to manipulate relative paths. */
5825 /* TODO - create the absolute path and manipulate the newname
5826 relative to the sharepath. */
5827 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5830 if (fsp
->name_hash
!= orig_name_hash
) {
5833 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5834 "(file_id %s) from %s -> %s\n", fsp
->fnum
,
5835 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
5836 smb_fname_str_dbg(smb_fname_dst
)));
5838 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
5839 if (NT_STATUS_IS_OK(status
)) {
5841 new_name_hash
= fsp
->name_hash
;
5846 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5847 "for %s\n", file_id_string_tos(&lck
->id
),
5848 smb_fname_str_dbg(smb_fname_dst
)));
5851 /* Send messages to all smbd's (not ourself) that the name has changed. */
5852 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, conn
->connectpath
,
5853 orig_name_hash
, new_name_hash
,
5858 /****************************************************************************
5859 We need to check if the source path is a parent directory of the destination
5860 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5861 refuse the rename with a sharing violation. Under UNIX the above call can
5862 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5863 probably need to check that the client is a Windows one before disallowing
5864 this as a UNIX client (one with UNIX extensions) can know the source is a
5865 symlink and make this decision intelligently. Found by an excellent bug
5866 report from <AndyLiebman@aol.com>.
5867 ****************************************************************************/
5869 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
5870 const struct smb_filename
*smb_fname_dst
)
5872 const char *psrc
= smb_fname_src
->base_name
;
5873 const char *pdst
= smb_fname_dst
->base_name
;
5876 if (psrc
[0] == '.' && psrc
[1] == '/') {
5879 if (pdst
[0] == '.' && pdst
[1] == '/') {
5882 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5885 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5889 * Do the notify calls from a rename
5892 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5893 const struct smb_filename
*smb_fname_src
,
5894 const struct smb_filename
*smb_fname_dst
)
5896 char *parent_dir_src
= NULL
;
5897 char *parent_dir_dst
= NULL
;
5900 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5901 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5903 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
5904 &parent_dir_src
, NULL
) ||
5905 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
5906 &parent_dir_dst
, NULL
)) {
5910 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
5911 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
5912 smb_fname_src
->base_name
);
5913 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
5914 smb_fname_dst
->base_name
);
5917 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
5918 smb_fname_src
->base_name
);
5919 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
5920 smb_fname_dst
->base_name
);
5923 /* this is a strange one. w2k3 gives an additional event for
5924 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5925 files, but not directories */
5927 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5928 FILE_NOTIFY_CHANGE_ATTRIBUTES
5929 |FILE_NOTIFY_CHANGE_CREATION
,
5930 smb_fname_dst
->base_name
);
5933 TALLOC_FREE(parent_dir_src
);
5934 TALLOC_FREE(parent_dir_dst
);
5937 /****************************************************************************
5938 Returns an error if the parent directory for a filename is open in an
5940 ****************************************************************************/
5942 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
5943 const struct smb_filename
*smb_fname_dst_in
)
5945 char *parent_dir
= NULL
;
5946 struct smb_filename smb_fname_parent
;
5948 files_struct
*fsp
= NULL
;
5951 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
5952 &parent_dir
, NULL
)) {
5953 return NT_STATUS_NO_MEMORY
;
5955 ZERO_STRUCT(smb_fname_parent
);
5956 smb_fname_parent
.base_name
= parent_dir
;
5958 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
5960 return map_nt_error_from_unix(errno
);
5964 * We're only checking on this smbd here, mostly good
5965 * enough.. and will pass tests.
5968 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
5969 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
5970 fsp
= file_find_di_next(fsp
)) {
5971 if (fsp
->access_mask
& DELETE_ACCESS
) {
5972 return NT_STATUS_SHARING_VIOLATION
;
5975 return NT_STATUS_OK
;
5978 /****************************************************************************
5979 Rename an open file - given an fsp.
5980 ****************************************************************************/
5982 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
5984 const struct smb_filename
*smb_fname_dst_in
,
5986 bool replace_if_exists
)
5988 TALLOC_CTX
*ctx
= talloc_tos();
5989 struct smb_filename
*smb_fname_dst
= NULL
;
5990 NTSTATUS status
= NT_STATUS_OK
;
5991 struct share_mode_lock
*lck
= NULL
;
5992 bool dst_exists
, old_is_stream
, new_is_stream
;
5994 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
5995 if (!NT_STATUS_IS_OK(status
)) {
5999 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6000 if (!NT_STATUS_IS_OK(status
)) {
6004 /* Make a copy of the dst smb_fname structs */
6006 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
6007 if (!NT_STATUS_IS_OK(status
)) {
6012 * Check for special case with case preserving and not
6013 * case sensitive. If the old last component differs from the original
6014 * last component only by case, then we should allow
6015 * the rename (user is trying to change the case of the
6018 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6019 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6020 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6022 char *fname_dst_lcomp_base_mod
= NULL
;
6023 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6026 * Get the last component of the destination name.
6028 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6030 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6032 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6034 if (!fname_dst_lcomp_base_mod
) {
6035 status
= NT_STATUS_NO_MEMORY
;
6040 * Create an smb_filename struct using the original last
6041 * component of the destination.
6043 status
= create_synthetic_smb_fname_split(ctx
,
6044 smb_fname_dst
->original_lcomp
, NULL
,
6045 &smb_fname_orig_lcomp
);
6046 if (!NT_STATUS_IS_OK(status
)) {
6047 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6051 /* If the base names only differ by case, use original. */
6052 if(!strcsequal(fname_dst_lcomp_base_mod
,
6053 smb_fname_orig_lcomp
->base_name
)) {
6056 * Replace the modified last component with the
6060 *last_slash
= '\0'; /* Truncate at the '/' */
6061 tmp
= talloc_asprintf(smb_fname_dst
,
6063 smb_fname_dst
->base_name
,
6064 smb_fname_orig_lcomp
->base_name
);
6066 tmp
= talloc_asprintf(smb_fname_dst
,
6068 smb_fname_orig_lcomp
->base_name
);
6071 status
= NT_STATUS_NO_MEMORY
;
6072 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6073 TALLOC_FREE(smb_fname_orig_lcomp
);
6076 TALLOC_FREE(smb_fname_dst
->base_name
);
6077 smb_fname_dst
->base_name
= tmp
;
6080 /* If the stream_names only differ by case, use original. */
6081 if(!strcsequal(smb_fname_dst
->stream_name
,
6082 smb_fname_orig_lcomp
->stream_name
)) {
6084 /* Use the original stream. */
6085 tmp
= talloc_strdup(smb_fname_dst
,
6086 smb_fname_orig_lcomp
->stream_name
);
6088 status
= NT_STATUS_NO_MEMORY
;
6089 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6090 TALLOC_FREE(smb_fname_orig_lcomp
);
6093 TALLOC_FREE(smb_fname_dst
->stream_name
);
6094 smb_fname_dst
->stream_name
= tmp
;
6096 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6097 TALLOC_FREE(smb_fname_orig_lcomp
);
6101 * If the src and dest names are identical - including case,
6102 * don't do the rename, just return success.
6105 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6106 strcsequal(fsp
->fsp_name
->stream_name
,
6107 smb_fname_dst
->stream_name
)) {
6108 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6109 "- returning success\n",
6110 smb_fname_str_dbg(smb_fname_dst
)));
6111 status
= NT_STATUS_OK
;
6115 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6116 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6118 /* Return the correct error code if both names aren't streams. */
6119 if (!old_is_stream
&& new_is_stream
) {
6120 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6124 if (old_is_stream
&& !new_is_stream
) {
6125 status
= NT_STATUS_INVALID_PARAMETER
;
6129 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6131 if(!replace_if_exists
&& dst_exists
) {
6132 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6133 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6134 smb_fname_str_dbg(smb_fname_dst
)));
6135 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6140 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6141 &smb_fname_dst
->st
);
6142 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6144 /* The file can be open when renaming a stream */
6145 if (dst_fsp
&& !new_is_stream
) {
6146 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6147 status
= NT_STATUS_ACCESS_DENIED
;
6152 /* Ensure we have a valid stat struct for the source. */
6153 status
= vfs_stat_fsp(fsp
);
6154 if (!NT_STATUS_IS_OK(status
)) {
6158 status
= can_rename(conn
, fsp
, attrs
);
6160 if (!NT_STATUS_IS_OK(status
)) {
6161 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6162 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6163 smb_fname_str_dbg(smb_fname_dst
)));
6164 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6165 status
= NT_STATUS_ACCESS_DENIED
;
6169 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6170 status
= NT_STATUS_ACCESS_DENIED
;
6173 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6177 * We have the file open ourselves, so not being able to get the
6178 * corresponding share mode lock is a fatal error.
6181 SMB_ASSERT(lck
!= NULL
);
6183 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6184 uint32 create_options
= fsp
->fh
->private_options
;
6186 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6187 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6188 smb_fname_str_dbg(smb_fname_dst
)));
6190 if (!fsp
->is_directory
&&
6191 !lp_posix_pathnames() &&
6192 (lp_map_archive(SNUM(conn
)) ||
6193 lp_store_dos_attributes(SNUM(conn
)))) {
6194 /* We must set the archive bit on the newly
6196 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6197 uint32_t old_dosmode
= dos_mode(conn
,
6199 file_set_dosmode(conn
,
6201 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6207 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6210 rename_open_files(conn
, lck
, fsp
->name_hash
, smb_fname_dst
);
6213 * A rename acts as a new file create w.r.t. allowing an initial delete
6214 * on close, probably because in Windows there is a new handle to the
6215 * new file. If initial delete on close was requested but not
6216 * originally set, we need to set it here. This is probably not 100% correct,
6217 * but will work for the CIFSFS client which in non-posix mode
6218 * depends on these semantics. JRA.
6221 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6222 status
= can_set_delete_on_close(fsp
, 0);
6224 if (NT_STATUS_IS_OK(status
)) {
6225 /* Note that here we set the *inital* delete on close flag,
6226 * not the regular one. The magic gets handled in close. */
6227 fsp
->initial_delete_on_close
= True
;
6231 status
= NT_STATUS_OK
;
6237 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6238 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6240 status
= map_nt_error_from_unix(errno
);
6243 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6244 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6245 smb_fname_str_dbg(smb_fname_dst
)));
6248 TALLOC_FREE(smb_fname_dst
);
6253 /****************************************************************************
6254 The guts of the rename command, split out so it may be called by the NT SMB
6256 ****************************************************************************/
6258 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6259 connection_struct
*conn
,
6260 struct smb_request
*req
,
6261 struct smb_filename
*smb_fname_src
,
6262 struct smb_filename
*smb_fname_dst
,
6264 bool replace_if_exists
,
6267 uint32_t access_mask
)
6269 char *fname_src_dir
= NULL
;
6270 char *fname_src_mask
= NULL
;
6272 NTSTATUS status
= NT_STATUS_OK
;
6273 struct smb_Dir
*dir_hnd
= NULL
;
6274 const char *dname
= NULL
;
6275 char *talloced
= NULL
;
6277 int create_options
= 0;
6278 bool posix_pathnames
= lp_posix_pathnames();
6281 * Split the old name into directory and last component
6282 * strings. Note that unix_convert may have stripped off a
6283 * leading ./ from both name and newname if the rename is
6284 * at the root of the share. We need to make sure either both
6285 * name and newname contain a / character or neither of them do
6286 * as this is checked in resolve_wildcards().
6289 /* Split up the directory from the filename/mask. */
6290 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6291 &fname_src_dir
, &fname_src_mask
);
6292 if (!NT_STATUS_IS_OK(status
)) {
6293 status
= NT_STATUS_NO_MEMORY
;
6298 * We should only check the mangled cache
6299 * here if unix_convert failed. This means
6300 * that the path in 'mask' doesn't exist
6301 * on the file system and so we need to look
6302 * for a possible mangle. This patch from
6303 * Tine Smukavec <valentin.smukavec@hermes.si>.
6306 if (!VALID_STAT(smb_fname_src
->st
) &&
6307 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6308 char *new_mask
= NULL
;
6309 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6312 TALLOC_FREE(fname_src_mask
);
6313 fname_src_mask
= new_mask
;
6317 if (!src_has_wild
) {
6321 * Only one file needs to be renamed. Append the mask back
6322 * onto the directory.
6324 TALLOC_FREE(smb_fname_src
->base_name
);
6325 if (ISDOT(fname_src_dir
)) {
6326 /* Ensure we use canonical names on open. */
6327 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6331 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6336 if (!smb_fname_src
->base_name
) {
6337 status
= NT_STATUS_NO_MEMORY
;
6341 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6342 "case_preserve = %d, short case preserve = %d, "
6343 "directory = %s, newname = %s, "
6344 "last_component_dest = %s\n",
6345 conn
->case_sensitive
, conn
->case_preserve
,
6346 conn
->short_case_preserve
,
6347 smb_fname_str_dbg(smb_fname_src
),
6348 smb_fname_str_dbg(smb_fname_dst
),
6349 smb_fname_dst
->original_lcomp
));
6351 /* The dest name still may have wildcards. */
6352 if (dest_has_wild
) {
6353 char *fname_dst_mod
= NULL
;
6354 if (!resolve_wildcards(smb_fname_dst
,
6355 smb_fname_src
->base_name
,
6356 smb_fname_dst
->base_name
,
6358 DEBUG(6, ("rename_internals: resolve_wildcards "
6360 smb_fname_src
->base_name
,
6361 smb_fname_dst
->base_name
));
6362 status
= NT_STATUS_NO_MEMORY
;
6365 TALLOC_FREE(smb_fname_dst
->base_name
);
6366 smb_fname_dst
->base_name
= fname_dst_mod
;
6369 ZERO_STRUCT(smb_fname_src
->st
);
6370 if (posix_pathnames
) {
6371 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6373 SMB_VFS_STAT(conn
, smb_fname_src
);
6376 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6377 create_options
|= FILE_DIRECTORY_FILE
;
6380 status
= SMB_VFS_CREATE_FILE(
6383 0, /* root_dir_fid */
6384 smb_fname_src
, /* fname */
6385 access_mask
, /* access_mask */
6386 (FILE_SHARE_READ
| /* share_access */
6388 FILE_OPEN
, /* create_disposition*/
6389 create_options
, /* create_options */
6390 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6391 0, /* oplock_request */
6392 0, /* allocation_size */
6393 0, /* private_flags */
6399 if (!NT_STATUS_IS_OK(status
)) {
6400 DEBUG(3, ("Could not open rename source %s: %s\n",
6401 smb_fname_str_dbg(smb_fname_src
),
6402 nt_errstr(status
)));
6406 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6407 attrs
, replace_if_exists
);
6409 close_file(req
, fsp
, NORMAL_CLOSE
);
6411 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6412 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6413 smb_fname_str_dbg(smb_fname_dst
)));
6419 * Wildcards - process each file that matches.
6421 if (strequal(fname_src_mask
, "????????.???")) {
6422 TALLOC_FREE(fname_src_mask
);
6423 fname_src_mask
= talloc_strdup(ctx
, "*");
6424 if (!fname_src_mask
) {
6425 status
= NT_STATUS_NO_MEMORY
;
6430 status
= check_name(conn
, fname_src_dir
);
6431 if (!NT_STATUS_IS_OK(status
)) {
6435 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6437 if (dir_hnd
== NULL
) {
6438 status
= map_nt_error_from_unix(errno
);
6442 status
= NT_STATUS_NO_SUCH_FILE
;
6444 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6445 * - gentest fix. JRA
6448 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6450 files_struct
*fsp
= NULL
;
6451 char *destname
= NULL
;
6452 bool sysdir_entry
= False
;
6454 /* Quick check for "." and ".." */
6455 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6456 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6457 sysdir_entry
= True
;
6459 TALLOC_FREE(talloced
);
6464 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6465 &smb_fname_src
->st
, false)) {
6466 TALLOC_FREE(talloced
);
6470 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6471 TALLOC_FREE(talloced
);
6476 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6480 TALLOC_FREE(smb_fname_src
->base_name
);
6481 if (ISDOT(fname_src_dir
)) {
6482 /* Ensure we use canonical names on open. */
6483 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6487 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6492 if (!smb_fname_src
->base_name
) {
6493 status
= NT_STATUS_NO_MEMORY
;
6497 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6498 smb_fname_dst
->base_name
,
6500 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6501 smb_fname_src
->base_name
, destname
));
6502 TALLOC_FREE(talloced
);
6506 status
= NT_STATUS_NO_MEMORY
;
6510 TALLOC_FREE(smb_fname_dst
->base_name
);
6511 smb_fname_dst
->base_name
= destname
;
6513 ZERO_STRUCT(smb_fname_src
->st
);
6514 if (posix_pathnames
) {
6515 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6517 SMB_VFS_STAT(conn
, smb_fname_src
);
6522 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6523 create_options
|= FILE_DIRECTORY_FILE
;
6526 status
= SMB_VFS_CREATE_FILE(
6529 0, /* root_dir_fid */
6530 smb_fname_src
, /* fname */
6531 access_mask
, /* access_mask */
6532 (FILE_SHARE_READ
| /* share_access */
6534 FILE_OPEN
, /* create_disposition*/
6535 create_options
, /* create_options */
6536 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6537 0, /* oplock_request */
6538 0, /* allocation_size */
6539 0, /* private_flags */
6545 if (!NT_STATUS_IS_OK(status
)) {
6546 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6547 "returned %s rename %s -> %s\n",
6549 smb_fname_str_dbg(smb_fname_src
),
6550 smb_fname_str_dbg(smb_fname_dst
)));
6554 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6556 if (!smb_fname_dst
->original_lcomp
) {
6557 status
= NT_STATUS_NO_MEMORY
;
6561 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6562 attrs
, replace_if_exists
);
6564 close_file(req
, fsp
, NORMAL_CLOSE
);
6566 if (!NT_STATUS_IS_OK(status
)) {
6567 DEBUG(3, ("rename_internals_fsp returned %s for "
6568 "rename %s -> %s\n", nt_errstr(status
),
6569 smb_fname_str_dbg(smb_fname_src
),
6570 smb_fname_str_dbg(smb_fname_dst
)));
6576 DEBUG(3,("rename_internals: doing rename on %s -> "
6577 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6578 smb_fname_str_dbg(smb_fname_src
)));
6579 TALLOC_FREE(talloced
);
6581 TALLOC_FREE(dir_hnd
);
6583 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6584 status
= map_nt_error_from_unix(errno
);
6588 TALLOC_FREE(talloced
);
6589 TALLOC_FREE(fname_src_dir
);
6590 TALLOC_FREE(fname_src_mask
);
6594 /****************************************************************************
6596 ****************************************************************************/
6598 void reply_mv(struct smb_request
*req
)
6600 connection_struct
*conn
= req
->conn
;
6602 char *newname
= NULL
;
6606 bool src_has_wcard
= False
;
6607 bool dest_has_wcard
= False
;
6608 TALLOC_CTX
*ctx
= talloc_tos();
6609 struct smb_filename
*smb_fname_src
= NULL
;
6610 struct smb_filename
*smb_fname_dst
= NULL
;
6611 uint32_t src_ucf_flags
= lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP
: UCF_COND_ALLOW_WCARD_LCOMP
;
6612 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
| (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP
);
6613 bool stream_rename
= false;
6615 START_PROFILE(SMBmv
);
6618 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6622 attrs
= SVAL(req
->vwv
+0, 0);
6624 p
= (const char *)req
->buf
+ 1;
6625 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6626 &status
, &src_has_wcard
);
6627 if (!NT_STATUS_IS_OK(status
)) {
6628 reply_nterror(req
, status
);
6632 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6633 &status
, &dest_has_wcard
);
6634 if (!NT_STATUS_IS_OK(status
)) {
6635 reply_nterror(req
, status
);
6639 if (!lp_posix_pathnames()) {
6640 /* The newname must begin with a ':' if the
6641 name contains a ':'. */
6642 if (strchr_m(name
, ':')) {
6643 if (newname
[0] != ':') {
6644 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6647 stream_rename
= true;
6651 status
= filename_convert(ctx
,
6653 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6659 if (!NT_STATUS_IS_OK(status
)) {
6660 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6661 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6662 ERRSRV
, ERRbadpath
);
6665 reply_nterror(req
, status
);
6669 status
= filename_convert(ctx
,
6671 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6677 if (!NT_STATUS_IS_OK(status
)) {
6678 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6679 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6680 ERRSRV
, ERRbadpath
);
6683 reply_nterror(req
, status
);
6687 if (stream_rename
) {
6688 /* smb_fname_dst->base_name must be the same as
6689 smb_fname_src->base_name. */
6690 TALLOC_FREE(smb_fname_dst
->base_name
);
6691 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6692 smb_fname_src
->base_name
);
6693 if (!smb_fname_dst
->base_name
) {
6694 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6699 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6700 smb_fname_str_dbg(smb_fname_dst
)));
6702 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
6703 attrs
, False
, src_has_wcard
, dest_has_wcard
,
6705 if (!NT_STATUS_IS_OK(status
)) {
6706 if (open_was_deferred(req
->mid
)) {
6707 /* We have re-scheduled this call. */
6710 reply_nterror(req
, status
);
6714 reply_outbuf(req
, 0, 0);
6716 TALLOC_FREE(smb_fname_src
);
6717 TALLOC_FREE(smb_fname_dst
);
6722 /*******************************************************************
6723 Copy a file as part of a reply_copy.
6724 ******************************************************************/
6727 * TODO: check error codes on all callers
6730 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6731 connection_struct
*conn
,
6732 struct smb_filename
*smb_fname_src
,
6733 struct smb_filename
*smb_fname_dst
,
6736 bool target_is_directory
)
6738 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
6740 files_struct
*fsp1
,*fsp2
;
6742 uint32 new_create_disposition
;
6746 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
6747 if (!NT_STATUS_IS_OK(status
)) {
6752 * If the target is a directory, extract the last component from the
6753 * src filename and append it to the dst filename
6755 if (target_is_directory
) {
6758 /* dest/target can't be a stream if it's a directory. */
6759 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
6761 p
= strrchr_m(smb_fname_src
->base_name
,'/');
6765 p
= smb_fname_src
->base_name
;
6767 smb_fname_dst_tmp
->base_name
=
6768 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
6770 if (!smb_fname_dst_tmp
->base_name
) {
6771 status
= NT_STATUS_NO_MEMORY
;
6776 status
= vfs_file_exist(conn
, smb_fname_src
);
6777 if (!NT_STATUS_IS_OK(status
)) {
6781 if (!target_is_directory
&& count
) {
6782 new_create_disposition
= FILE_OPEN
;
6784 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
6787 &new_create_disposition
,
6790 status
= NT_STATUS_INVALID_PARAMETER
;
6795 /* Open the src file for reading. */
6796 status
= SMB_VFS_CREATE_FILE(
6799 0, /* root_dir_fid */
6800 smb_fname_src
, /* fname */
6801 FILE_GENERIC_READ
, /* access_mask */
6802 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6803 FILE_OPEN
, /* create_disposition*/
6804 0, /* create_options */
6805 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6806 INTERNAL_OPEN_ONLY
, /* oplock_request */
6807 0, /* allocation_size */
6808 0, /* private_flags */
6814 if (!NT_STATUS_IS_OK(status
)) {
6818 dosattrs
= dos_mode(conn
, smb_fname_src
);
6820 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
6821 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
6824 /* Open the dst file for writing. */
6825 status
= SMB_VFS_CREATE_FILE(
6828 0, /* root_dir_fid */
6829 smb_fname_dst
, /* fname */
6830 FILE_GENERIC_WRITE
, /* access_mask */
6831 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6832 new_create_disposition
, /* create_disposition*/
6833 0, /* create_options */
6834 dosattrs
, /* file_attributes */
6835 INTERNAL_OPEN_ONLY
, /* oplock_request */
6836 0, /* allocation_size */
6837 0, /* private_flags */
6843 if (!NT_STATUS_IS_OK(status
)) {
6844 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6848 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
6849 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
6851 DEBUG(0, ("error - vfs lseek returned error %s\n",
6853 status
= map_nt_error_from_unix(errno
);
6854 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6855 close_file(NULL
, fsp2
, ERROR_CLOSE
);
6860 /* Do the actual copy. */
6861 if (smb_fname_src
->st
.st_ex_size
) {
6862 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
6867 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
6869 /* Ensure the modtime is set correctly on the destination file. */
6870 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
6873 * As we are opening fsp1 read-only we only expect
6874 * an error on close on fsp2 if we are out of space.
6875 * Thus we don't look at the error return from the
6878 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
6880 if (!NT_STATUS_IS_OK(status
)) {
6884 if (ret
!= (SMB_OFF_T
)smb_fname_src
->st
.st_ex_size
) {
6885 status
= NT_STATUS_DISK_FULL
;
6889 status
= NT_STATUS_OK
;
6892 TALLOC_FREE(smb_fname_dst_tmp
);
6896 /****************************************************************************
6897 Reply to a file copy.
6898 ****************************************************************************/
6900 void reply_copy(struct smb_request
*req
)
6902 connection_struct
*conn
= req
->conn
;
6903 struct smb_filename
*smb_fname_src
= NULL
;
6904 struct smb_filename
*smb_fname_dst
= NULL
;
6905 char *fname_src
= NULL
;
6906 char *fname_dst
= NULL
;
6907 char *fname_src_mask
= NULL
;
6908 char *fname_src_dir
= NULL
;
6911 int error
= ERRnoaccess
;
6915 bool target_is_directory
=False
;
6916 bool source_has_wild
= False
;
6917 bool dest_has_wild
= False
;
6919 TALLOC_CTX
*ctx
= talloc_tos();
6921 START_PROFILE(SMBcopy
);
6924 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6928 tid2
= SVAL(req
->vwv
+0, 0);
6929 ofun
= SVAL(req
->vwv
+1, 0);
6930 flags
= SVAL(req
->vwv
+2, 0);
6932 p
= (const char *)req
->buf
;
6933 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
6934 &status
, &source_has_wild
);
6935 if (!NT_STATUS_IS_OK(status
)) {
6936 reply_nterror(req
, status
);
6939 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
6940 &status
, &dest_has_wild
);
6941 if (!NT_STATUS_IS_OK(status
)) {
6942 reply_nterror(req
, status
);
6946 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
6948 if (tid2
!= conn
->cnum
) {
6949 /* can't currently handle inter share copies XXXX */
6950 DEBUG(3,("Rejecting inter-share copy\n"));
6951 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
6955 status
= filename_convert(ctx
, conn
,
6956 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6958 UCF_COND_ALLOW_WCARD_LCOMP
,
6961 if (!NT_STATUS_IS_OK(status
)) {
6962 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6963 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6964 ERRSRV
, ERRbadpath
);
6967 reply_nterror(req
, status
);
6971 status
= filename_convert(ctx
, conn
,
6972 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6974 UCF_COND_ALLOW_WCARD_LCOMP
,
6977 if (!NT_STATUS_IS_OK(status
)) {
6978 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6979 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6980 ERRSRV
, ERRbadpath
);
6983 reply_nterror(req
, status
);
6987 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
6989 if ((flags
&1) && target_is_directory
) {
6990 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
6994 if ((flags
&2) && !target_is_directory
) {
6995 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
6999 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7000 /* wants a tree copy! XXXX */
7001 DEBUG(3,("Rejecting tree copy\n"));
7002 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7006 /* Split up the directory from the filename/mask. */
7007 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7008 &fname_src_dir
, &fname_src_mask
);
7009 if (!NT_STATUS_IS_OK(status
)) {
7010 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7015 * We should only check the mangled cache
7016 * here if unix_convert failed. This means
7017 * that the path in 'mask' doesn't exist
7018 * on the file system and so we need to look
7019 * for a possible mangle. This patch from
7020 * Tine Smukavec <valentin.smukavec@hermes.si>.
7022 if (!VALID_STAT(smb_fname_src
->st
) &&
7023 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7024 char *new_mask
= NULL
;
7025 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7026 &new_mask
, conn
->params
);
7028 /* Use demangled name if one was successfully found. */
7030 TALLOC_FREE(fname_src_mask
);
7031 fname_src_mask
= new_mask
;
7035 if (!source_has_wild
) {
7038 * Only one file needs to be copied. Append the mask back onto
7041 TALLOC_FREE(smb_fname_src
->base_name
);
7042 if (ISDOT(fname_src_dir
)) {
7043 /* Ensure we use canonical names on open. */
7044 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7048 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7053 if (!smb_fname_src
->base_name
) {
7054 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7058 if (dest_has_wild
) {
7059 char *fname_dst_mod
= NULL
;
7060 if (!resolve_wildcards(smb_fname_dst
,
7061 smb_fname_src
->base_name
,
7062 smb_fname_dst
->base_name
,
7064 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7067 TALLOC_FREE(smb_fname_dst
->base_name
);
7068 smb_fname_dst
->base_name
= fname_dst_mod
;
7071 status
= check_name(conn
, smb_fname_src
->base_name
);
7072 if (!NT_STATUS_IS_OK(status
)) {
7073 reply_nterror(req
, status
);
7077 status
= check_name(conn
, smb_fname_dst
->base_name
);
7078 if (!NT_STATUS_IS_OK(status
)) {
7079 reply_nterror(req
, status
);
7083 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7084 ofun
, count
, target_is_directory
);
7086 if(!NT_STATUS_IS_OK(status
)) {
7087 reply_nterror(req
, status
);
7093 struct smb_Dir
*dir_hnd
= NULL
;
7094 const char *dname
= NULL
;
7095 char *talloced
= NULL
;
7099 * There is a wildcard that requires us to actually read the
7100 * src dir and copy each file matching the mask to the dst.
7101 * Right now streams won't be copied, but this could
7102 * presumably be added with a nested loop for reach dir entry.
7104 SMB_ASSERT(!smb_fname_src
->stream_name
);
7105 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7107 smb_fname_src
->stream_name
= NULL
;
7108 smb_fname_dst
->stream_name
= NULL
;
7110 if (strequal(fname_src_mask
,"????????.???")) {
7111 TALLOC_FREE(fname_src_mask
);
7112 fname_src_mask
= talloc_strdup(ctx
, "*");
7113 if (!fname_src_mask
) {
7114 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7119 status
= check_name(conn
, fname_src_dir
);
7120 if (!NT_STATUS_IS_OK(status
)) {
7121 reply_nterror(req
, status
);
7125 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7126 if (dir_hnd
== NULL
) {
7127 status
= map_nt_error_from_unix(errno
);
7128 reply_nterror(req
, status
);
7134 /* Iterate over the src dir copying each entry to the dst. */
7135 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7136 &smb_fname_src
->st
, &talloced
))) {
7137 char *destname
= NULL
;
7139 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7140 TALLOC_FREE(talloced
);
7144 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7145 &smb_fname_src
->st
, false)) {
7146 TALLOC_FREE(talloced
);
7150 if(!mask_match(dname
, fname_src_mask
,
7151 conn
->case_sensitive
)) {
7152 TALLOC_FREE(talloced
);
7156 error
= ERRnoaccess
;
7158 /* Get the src smb_fname struct setup. */
7159 TALLOC_FREE(smb_fname_src
->base_name
);
7160 if (ISDOT(fname_src_dir
)) {
7161 /* Ensure we use canonical names on open. */
7162 smb_fname_src
->base_name
=
7163 talloc_asprintf(smb_fname_src
, "%s",
7166 smb_fname_src
->base_name
=
7167 talloc_asprintf(smb_fname_src
, "%s/%s",
7168 fname_src_dir
, dname
);
7171 if (!smb_fname_src
->base_name
) {
7172 TALLOC_FREE(dir_hnd
);
7173 TALLOC_FREE(talloced
);
7174 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7178 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7179 smb_fname_dst
->base_name
,
7181 TALLOC_FREE(talloced
);
7185 TALLOC_FREE(dir_hnd
);
7186 TALLOC_FREE(talloced
);
7187 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7191 TALLOC_FREE(smb_fname_dst
->base_name
);
7192 smb_fname_dst
->base_name
= destname
;
7194 status
= check_name(conn
, smb_fname_src
->base_name
);
7195 if (!NT_STATUS_IS_OK(status
)) {
7196 TALLOC_FREE(dir_hnd
);
7197 TALLOC_FREE(talloced
);
7198 reply_nterror(req
, status
);
7202 status
= check_name(conn
, smb_fname_dst
->base_name
);
7203 if (!NT_STATUS_IS_OK(status
)) {
7204 TALLOC_FREE(dir_hnd
);
7205 TALLOC_FREE(talloced
);
7206 reply_nterror(req
, status
);
7210 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7211 smb_fname_src
->base_name
,
7212 smb_fname_dst
->base_name
));
7214 status
= copy_file(ctx
, conn
, smb_fname_src
,
7215 smb_fname_dst
, ofun
, count
,
7216 target_is_directory
);
7217 if (NT_STATUS_IS_OK(status
)) {
7221 TALLOC_FREE(talloced
);
7223 TALLOC_FREE(dir_hnd
);
7227 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7231 reply_outbuf(req
, 1, 0);
7232 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7234 TALLOC_FREE(smb_fname_src
);
7235 TALLOC_FREE(smb_fname_dst
);
7236 TALLOC_FREE(fname_src
);
7237 TALLOC_FREE(fname_dst
);
7238 TALLOC_FREE(fname_src_mask
);
7239 TALLOC_FREE(fname_src_dir
);
7241 END_PROFILE(SMBcopy
);
7246 #define DBGC_CLASS DBGC_LOCKING
7248 /****************************************************************************
7249 Get a lock pid, dealing with large count requests.
7250 ****************************************************************************/
7252 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7253 bool large_file_format
)
7255 if(!large_file_format
)
7256 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7258 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7261 /****************************************************************************
7262 Get a lock count, dealing with large count requests.
7263 ****************************************************************************/
7265 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7266 bool large_file_format
)
7270 if(!large_file_format
) {
7271 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7274 #if defined(HAVE_LONGLONG)
7275 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7276 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7277 #else /* HAVE_LONGLONG */
7280 * NT4.x seems to be broken in that it sends large file (64 bit)
7281 * lockingX calls even if the CAP_LARGE_FILES was *not*
7282 * negotiated. For boxes without large unsigned ints truncate the
7283 * lock count by dropping the top 32 bits.
7286 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7287 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7288 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7289 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7290 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7293 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7294 #endif /* HAVE_LONGLONG */
7300 #if !defined(HAVE_LONGLONG)
7301 /****************************************************************************
7302 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7303 ****************************************************************************/
7305 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7309 uint32 highcopy
= high
;
7312 * Try and find out how many significant bits there are in high.
7315 for(i
= 0; highcopy
; i
++)
7319 * We use 31 bits not 32 here as POSIX
7320 * lock offsets may not be negative.
7323 mask
= (~0) << (31 - i
);
7326 return 0; /* Fail. */
7332 #endif /* !defined(HAVE_LONGLONG) */
7334 /****************************************************************************
7335 Get a lock offset, dealing with large offset requests.
7336 ****************************************************************************/
7338 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7339 bool large_file_format
, bool *err
)
7341 uint64_t offset
= 0;
7345 if(!large_file_format
) {
7346 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7349 #if defined(HAVE_LONGLONG)
7350 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7351 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7352 #else /* HAVE_LONGLONG */
7355 * NT4.x seems to be broken in that it sends large file (64 bit)
7356 * lockingX calls even if the CAP_LARGE_FILES was *not*
7357 * negotiated. For boxes without large unsigned ints mangle the
7358 * lock offset by mapping the top 32 bits onto the lower 32.
7361 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7362 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7363 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7366 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7368 return (uint64_t)-1;
7371 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7372 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7373 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7374 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7377 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7378 #endif /* HAVE_LONGLONG */
7384 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7388 uint16_t num_ulocks
,
7389 struct smbd_lock_element
*ulocks
,
7391 struct smbd_lock_element
*locks
,
7394 connection_struct
*conn
= req
->conn
;
7396 NTSTATUS status
= NT_STATUS_OK
;
7400 /* Data now points at the beginning of the list
7401 of smb_unlkrng structs */
7402 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7403 struct smbd_lock_element
*e
= &ulocks
[i
];
7405 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7406 "pid %u, file %s\n",
7409 (unsigned int)e
->smblctx
,
7412 if (e
->brltype
!= UNLOCK_LOCK
) {
7413 /* this can only happen with SMB2 */
7414 return NT_STATUS_INVALID_PARAMETER
;
7417 status
= do_unlock(req
->sconn
->msg_ctx
,
7424 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7425 nt_errstr(status
)));
7427 if (!NT_STATUS_IS_OK(status
)) {
7432 /* Setup the timeout in seconds. */
7434 if (!lp_blocking_locks(SNUM(conn
))) {
7438 /* Data now points at the beginning of the list
7439 of smb_lkrng structs */
7441 for(i
= 0; i
< (int)num_locks
; i
++) {
7442 struct smbd_lock_element
*e
= &locks
[i
];
7444 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7445 "%llu, file %s timeout = %d\n",
7448 (unsigned long long)e
->smblctx
,
7452 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7453 struct blocking_lock_record
*blr
= NULL
;
7455 if (num_locks
> 1) {
7457 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7458 * if the lock vector contains one entry. When given mutliple cancel
7459 * requests in a single PDU we expect the server to return an
7460 * error. Windows servers seem to accept the request but only
7461 * cancel the first lock.
7462 * JRA - Do what Windows does (tm) :-).
7466 /* MS-CIFS (2.2.4.32.1) behavior. */
7467 return NT_STATUS_DOS(ERRDOS
,
7468 ERRcancelviolation
);
7470 /* Windows behavior. */
7472 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7473 "cancel request\n"));
7479 if (lp_blocking_locks(SNUM(conn
))) {
7481 /* Schedule a message to ourselves to
7482 remove the blocking lock record and
7483 return the right error. */
7485 blr
= blocking_lock_cancel_smb1(fsp
,
7491 NT_STATUS_FILE_LOCK_CONFLICT
);
7493 return NT_STATUS_DOS(
7495 ERRcancelviolation
);
7498 /* Remove a matching pending lock. */
7499 status
= do_lock_cancel(fsp
,
7506 bool blocking_lock
= timeout
? true : false;
7507 bool defer_lock
= false;
7508 struct byte_range_lock
*br_lck
;
7509 uint64_t block_smblctx
;
7511 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7523 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7524 /* Windows internal resolution for blocking locks seems
7525 to be about 200ms... Don't wait for less than that. JRA. */
7526 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7527 timeout
= lp_lock_spin_time();
7532 /* If a lock sent with timeout of zero would fail, and
7533 * this lock has been requested multiple times,
7534 * according to brl_lock_failed() we convert this
7535 * request to a blocking lock with a timeout of between
7536 * 150 - 300 milliseconds.
7538 * If lp_lock_spin_time() has been set to 0, we skip
7539 * this blocking retry and fail immediately.
7541 * Replacement for do_lock_spin(). JRA. */
7543 if (!req
->sconn
->using_smb2
&&
7544 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7545 lp_lock_spin_time() && !blocking_lock
&&
7546 NT_STATUS_EQUAL((status
),
7547 NT_STATUS_FILE_LOCK_CONFLICT
))
7550 timeout
= lp_lock_spin_time();
7553 if (br_lck
&& defer_lock
) {
7555 * A blocking lock was requested. Package up
7556 * this smb into a queued request and push it
7557 * onto the blocking lock queue.
7559 if(push_blocking_lock_request(br_lck
,
7570 TALLOC_FREE(br_lck
);
7572 return NT_STATUS_OK
;
7576 TALLOC_FREE(br_lck
);
7579 if (!NT_STATUS_IS_OK(status
)) {
7584 /* If any of the above locks failed, then we must unlock
7585 all of the previous locks (X/Open spec). */
7587 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7589 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7590 i
= -1; /* we want to skip the for loop */
7594 * Ensure we don't do a remove on the lock that just failed,
7595 * as under POSIX rules, if we have a lock already there, we
7596 * will delete it (and we shouldn't) .....
7598 for(i
--; i
>= 0; i
--) {
7599 struct smbd_lock_element
*e
= &locks
[i
];
7601 do_unlock(req
->sconn
->msg_ctx
,
7611 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7612 fsp
->fnum
, (unsigned int)type
, num_locks
, num_ulocks
));
7614 return NT_STATUS_OK
;
7617 /****************************************************************************
7618 Reply to a lockingX request.
7619 ****************************************************************************/
7621 void reply_lockingX(struct smb_request
*req
)
7623 connection_struct
*conn
= req
->conn
;
7625 unsigned char locktype
;
7626 unsigned char oplocklevel
;
7631 const uint8_t *data
;
7632 bool large_file_format
;
7634 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7635 struct smbd_lock_element
*ulocks
;
7636 struct smbd_lock_element
*locks
;
7639 START_PROFILE(SMBlockingX
);
7642 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7643 END_PROFILE(SMBlockingX
);
7647 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7648 locktype
= CVAL(req
->vwv
+3, 0);
7649 oplocklevel
= CVAL(req
->vwv
+3, 1);
7650 num_ulocks
= SVAL(req
->vwv
+6, 0);
7651 num_locks
= SVAL(req
->vwv
+7, 0);
7652 lock_timeout
= IVAL(req
->vwv
+4, 0);
7653 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7655 if (!check_fsp(conn
, req
, fsp
)) {
7656 END_PROFILE(SMBlockingX
);
7662 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7663 /* we don't support these - and CANCEL_LOCK makes w2k
7664 and XP reboot so I don't really want to be
7665 compatible! (tridge) */
7666 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7667 END_PROFILE(SMBlockingX
);
7671 /* Check if this is an oplock break on a file
7672 we have granted an oplock on.
7674 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7675 /* Client can insist on breaking to none. */
7676 bool break_to_none
= (oplocklevel
== 0);
7679 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7680 "for fnum = %d\n", (unsigned int)oplocklevel
,
7684 * Make sure we have granted an exclusive or batch oplock on
7688 if (fsp
->oplock_type
== 0) {
7690 /* The Samba4 nbench simulator doesn't understand
7691 the difference between break to level2 and break
7692 to none from level2 - it sends oplock break
7693 replies in both cases. Don't keep logging an error
7694 message here - just ignore it. JRA. */
7696 DEBUG(5,("reply_lockingX: Error : oplock break from "
7697 "client for fnum = %d (oplock=%d) and no "
7698 "oplock granted on this file (%s).\n",
7699 fsp
->fnum
, fsp
->oplock_type
,
7702 /* if this is a pure oplock break request then don't
7704 if (num_locks
== 0 && num_ulocks
== 0) {
7705 END_PROFILE(SMBlockingX
);
7708 END_PROFILE(SMBlockingX
);
7709 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
7714 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7716 result
= remove_oplock(fsp
);
7718 result
= downgrade_oplock(fsp
);
7722 DEBUG(0, ("reply_lockingX: error in removing "
7723 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7724 /* Hmmm. Is this panic justified? */
7725 smb_panic("internal tdb error");
7728 reply_to_oplock_break_requests(fsp
);
7730 /* if this is a pure oplock break request then don't send a
7732 if (num_locks
== 0 && num_ulocks
== 0) {
7733 /* Sanity check - ensure a pure oplock break is not a
7735 if(CVAL(req
->vwv
+0, 0) != 0xff)
7736 DEBUG(0,("reply_lockingX: Error : pure oplock "
7737 "break is a chained %d request !\n",
7738 (unsigned int)CVAL(req
->vwv
+0, 0)));
7739 END_PROFILE(SMBlockingX
);
7745 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7746 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7747 END_PROFILE(SMBlockingX
);
7751 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
7752 if (ulocks
== NULL
) {
7753 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7754 END_PROFILE(SMBlockingX
);
7758 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
7759 if (locks
== NULL
) {
7760 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7761 END_PROFILE(SMBlockingX
);
7765 /* Data now points at the beginning of the list
7766 of smb_unlkrng structs */
7767 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7768 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7769 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7770 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7771 ulocks
[i
].brltype
= UNLOCK_LOCK
;
7774 * There is no error code marked "stupid client bug".... :-).
7777 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7778 END_PROFILE(SMBlockingX
);
7783 /* Now do any requested locks */
7784 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
7786 /* Data now points at the beginning of the list
7787 of smb_lkrng structs */
7789 for(i
= 0; i
< (int)num_locks
; i
++) {
7790 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7791 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7792 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7794 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
7795 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7796 locks
[i
].brltype
= PENDING_READ_LOCK
;
7798 locks
[i
].brltype
= READ_LOCK
;
7801 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7802 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
7804 locks
[i
].brltype
= WRITE_LOCK
;
7809 * There is no error code marked "stupid client bug".... :-).
7812 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7813 END_PROFILE(SMBlockingX
);
7818 status
= smbd_do_locking(req
, fsp
,
7819 locktype
, lock_timeout
,
7823 if (!NT_STATUS_IS_OK(status
)) {
7824 END_PROFILE(SMBlockingX
);
7825 reply_nterror(req
, status
);
7829 END_PROFILE(SMBlockingX
);
7833 reply_outbuf(req
, 2, 0);
7835 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7836 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7838 END_PROFILE(SMBlockingX
);
7843 #define DBGC_CLASS DBGC_ALL
7845 /****************************************************************************
7846 Reply to a SMBreadbmpx (read block multiplex) request.
7847 Always reply with an error, if someone has a platform really needs this,
7848 please contact vl@samba.org
7849 ****************************************************************************/
7851 void reply_readbmpx(struct smb_request
*req
)
7853 START_PROFILE(SMBreadBmpx
);
7854 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7855 END_PROFILE(SMBreadBmpx
);
7859 /****************************************************************************
7860 Reply to a SMBreadbs (read block multiplex secondary) request.
7861 Always reply with an error, if someone has a platform really needs this,
7862 please contact vl@samba.org
7863 ****************************************************************************/
7865 void reply_readbs(struct smb_request
*req
)
7867 START_PROFILE(SMBreadBs
);
7868 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7869 END_PROFILE(SMBreadBs
);
7873 /****************************************************************************
7874 Reply to a SMBsetattrE.
7875 ****************************************************************************/
7877 void reply_setattrE(struct smb_request
*req
)
7879 connection_struct
*conn
= req
->conn
;
7880 struct smb_file_time ft
;
7884 START_PROFILE(SMBsetattrE
);
7888 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7892 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7894 if(!fsp
|| (fsp
->conn
!= conn
)) {
7895 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7900 * Convert the DOS times into unix times.
7903 ft
.atime
= convert_time_t_to_timespec(
7904 srv_make_unix_date2(req
->vwv
+3));
7905 ft
.mtime
= convert_time_t_to_timespec(
7906 srv_make_unix_date2(req
->vwv
+5));
7907 ft
.create_time
= convert_time_t_to_timespec(
7908 srv_make_unix_date2(req
->vwv
+1));
7910 reply_outbuf(req
, 0, 0);
7913 * Patch from Ray Frush <frush@engr.colostate.edu>
7914 * Sometimes times are sent as zero - ignore them.
7917 /* Ensure we have a valid stat struct for the source. */
7918 status
= vfs_stat_fsp(fsp
);
7919 if (!NT_STATUS_IS_OK(status
)) {
7920 reply_nterror(req
, status
);
7924 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
7925 if (!NT_STATUS_IS_OK(status
)) {
7926 reply_nterror(req
, status
);
7930 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7933 (unsigned int)ft
.atime
.tv_sec
,
7934 (unsigned int)ft
.mtime
.tv_sec
,
7935 (unsigned int)ft
.create_time
.tv_sec
7938 END_PROFILE(SMBsetattrE
);
7943 /* Back from the dead for OS/2..... JRA. */
7945 /****************************************************************************
7946 Reply to a SMBwritebmpx (write block multiplex primary) request.
7947 Always reply with an error, if someone has a platform really needs this,
7948 please contact vl@samba.org
7949 ****************************************************************************/
7951 void reply_writebmpx(struct smb_request
*req
)
7953 START_PROFILE(SMBwriteBmpx
);
7954 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7955 END_PROFILE(SMBwriteBmpx
);
7959 /****************************************************************************
7960 Reply to a SMBwritebs (write block multiplex secondary) request.
7961 Always reply with an error, if someone has a platform really needs this,
7962 please contact vl@samba.org
7963 ****************************************************************************/
7965 void reply_writebs(struct smb_request
*req
)
7967 START_PROFILE(SMBwriteBs
);
7968 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7969 END_PROFILE(SMBwriteBs
);
7973 /****************************************************************************
7974 Reply to a SMBgetattrE.
7975 ****************************************************************************/
7977 void reply_getattrE(struct smb_request
*req
)
7979 connection_struct
*conn
= req
->conn
;
7982 struct timespec create_ts
;
7984 START_PROFILE(SMBgetattrE
);
7987 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7988 END_PROFILE(SMBgetattrE
);
7992 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7994 if(!fsp
|| (fsp
->conn
!= conn
)) {
7995 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7996 END_PROFILE(SMBgetattrE
);
8000 /* Do an fstat on this file */
8002 reply_nterror(req
, map_nt_error_from_unix(errno
));
8003 END_PROFILE(SMBgetattrE
);
8007 mode
= dos_mode(conn
, fsp
->fsp_name
);
8010 * Convert the times into dos times. Set create
8011 * date to be last modify date as UNIX doesn't save
8015 reply_outbuf(req
, 11, 0);
8017 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8018 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8019 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8020 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8021 /* Should we check pending modtime here ? JRA */
8022 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8023 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8025 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8026 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8027 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8029 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8030 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
8031 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8033 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8035 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
8037 END_PROFILE(SMBgetattrE
);