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
, 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
, deny_mode
, smb_ofun
,
1945 &access_mask
, &share_mode
,
1946 &create_disposition
,
1949 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1953 status
= SMB_VFS_CREATE_FILE(
1956 0, /* root_dir_fid */
1957 smb_fname
, /* fname */
1958 access_mask
, /* access_mask */
1959 share_mode
, /* share_access */
1960 create_disposition
, /* create_disposition*/
1961 create_options
, /* create_options */
1962 smb_attr
, /* file_attributes */
1963 oplock_request
, /* oplock_request */
1964 0, /* allocation_size */
1969 &smb_action
); /* pinfo */
1971 if (!NT_STATUS_IS_OK(status
)) {
1972 if (open_was_deferred(req
->mid
)) {
1973 /* We have re-scheduled this call. */
1976 reply_openerror(req
, status
);
1980 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1981 if the file is truncated or created. */
1982 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1983 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1984 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1985 close_file(req
, fsp
, ERROR_CLOSE
);
1986 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1989 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1991 close_file(req
, fsp
, ERROR_CLOSE
);
1992 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1995 status
= vfs_stat_fsp(fsp
);
1996 if (!NT_STATUS_IS_OK(status
)) {
1997 close_file(req
, fsp
, ERROR_CLOSE
);
1998 reply_nterror(req
, status
);
2003 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2004 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2005 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2006 close_file(req
, fsp
, ERROR_CLOSE
);
2007 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2011 /* If the caller set the extended oplock request bit
2012 and we granted one (by whatever means) - set the
2013 correct bit for extended oplock reply.
2016 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2017 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2020 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2021 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2024 /* If the caller set the core oplock request bit
2025 and we granted one (by whatever means) - set the
2026 correct bit for core oplock reply.
2029 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2030 reply_outbuf(req
, 19, 0);
2032 reply_outbuf(req
, 15, 0);
2035 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2036 SCVAL(req
->outbuf
, smb_flg
,
2037 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2040 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2041 SCVAL(req
->outbuf
, smb_flg
,
2042 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2045 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2046 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2047 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2048 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2050 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2052 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2053 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2054 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2056 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2057 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2062 TALLOC_FREE(smb_fname
);
2063 END_PROFILE(SMBopenX
);
2067 /****************************************************************************
2068 Reply to a SMBulogoffX.
2069 ****************************************************************************/
2071 void reply_ulogoffX(struct smb_request
*req
)
2073 struct smbd_server_connection
*sconn
= req
->sconn
;
2076 START_PROFILE(SMBulogoffX
);
2078 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2081 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2085 /* in user level security we are supposed to close any files
2086 open by this user */
2087 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
2088 file_close_user(sconn
, req
->vuid
);
2091 invalidate_vuid(sconn
, req
->vuid
);
2093 reply_outbuf(req
, 2, 0);
2095 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
2097 END_PROFILE(SMBulogoffX
);
2098 req
->vuid
= UID_FIELD_INVALID
;
2102 /****************************************************************************
2103 Reply to a mknew or a create.
2104 ****************************************************************************/
2106 void reply_mknew(struct smb_request
*req
)
2108 connection_struct
*conn
= req
->conn
;
2109 struct smb_filename
*smb_fname
= NULL
;
2112 struct smb_file_time ft
;
2114 int oplock_request
= 0;
2116 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2117 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2118 uint32 create_disposition
;
2119 uint32 create_options
= 0;
2120 TALLOC_CTX
*ctx
= talloc_tos();
2122 START_PROFILE(SMBcreate
);
2126 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2130 fattr
= SVAL(req
->vwv
+0, 0);
2131 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2134 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2136 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2137 STR_TERMINATE
, &status
);
2138 if (!NT_STATUS_IS_OK(status
)) {
2139 reply_nterror(req
, status
);
2143 status
= filename_convert(ctx
,
2145 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2150 if (!NT_STATUS_IS_OK(status
)) {
2151 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2152 reply_botherror(req
,
2153 NT_STATUS_PATH_NOT_COVERED
,
2154 ERRSRV
, ERRbadpath
);
2157 reply_nterror(req
, status
);
2161 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2162 DEBUG(0,("Attempt to create file (%s) with volid set - "
2163 "please report this\n",
2164 smb_fname_str_dbg(smb_fname
)));
2167 if(req
->cmd
== SMBmknew
) {
2168 /* We should fail if file exists. */
2169 create_disposition
= FILE_CREATE
;
2171 /* Create if file doesn't exist, truncate if it does. */
2172 create_disposition
= FILE_OVERWRITE_IF
;
2175 status
= SMB_VFS_CREATE_FILE(
2178 0, /* root_dir_fid */
2179 smb_fname
, /* fname */
2180 access_mask
, /* access_mask */
2181 share_mode
, /* share_access */
2182 create_disposition
, /* create_disposition*/
2183 create_options
, /* create_options */
2184 fattr
, /* file_attributes */
2185 oplock_request
, /* oplock_request */
2186 0, /* allocation_size */
2187 0, /* private_flags */
2193 if (!NT_STATUS_IS_OK(status
)) {
2194 if (open_was_deferred(req
->mid
)) {
2195 /* We have re-scheduled this call. */
2198 reply_openerror(req
, status
);
2202 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2203 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2204 if (!NT_STATUS_IS_OK(status
)) {
2205 END_PROFILE(SMBcreate
);
2209 reply_outbuf(req
, 1, 0);
2210 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2212 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2213 SCVAL(req
->outbuf
,smb_flg
,
2214 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2217 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2218 SCVAL(req
->outbuf
,smb_flg
,
2219 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2222 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2223 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2224 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2225 (unsigned int)fattr
));
2228 TALLOC_FREE(smb_fname
);
2229 END_PROFILE(SMBcreate
);
2233 /****************************************************************************
2234 Reply to a create temporary file.
2235 ****************************************************************************/
2237 void reply_ctemp(struct smb_request
*req
)
2239 connection_struct
*conn
= req
->conn
;
2240 struct smb_filename
*smb_fname
= NULL
;
2248 TALLOC_CTX
*ctx
= talloc_tos();
2250 START_PROFILE(SMBctemp
);
2253 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2257 fattr
= SVAL(req
->vwv
+0, 0);
2258 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2260 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2261 STR_TERMINATE
, &status
);
2262 if (!NT_STATUS_IS_OK(status
)) {
2263 reply_nterror(req
, status
);
2267 fname
= talloc_asprintf(ctx
,
2271 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2275 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2279 status
= filename_convert(ctx
, conn
,
2280 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2285 if (!NT_STATUS_IS_OK(status
)) {
2286 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2287 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2288 ERRSRV
, ERRbadpath
);
2291 reply_nterror(req
, status
);
2295 tmpfd
= mkstemp(smb_fname
->base_name
);
2297 reply_nterror(req
, map_nt_error_from_unix(errno
));
2301 SMB_VFS_STAT(conn
, smb_fname
);
2303 /* We should fail if file does not exist. */
2304 status
= SMB_VFS_CREATE_FILE(
2307 0, /* root_dir_fid */
2308 smb_fname
, /* fname */
2309 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2310 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2311 FILE_OPEN
, /* create_disposition*/
2312 0, /* create_options */
2313 fattr
, /* file_attributes */
2314 oplock_request
, /* oplock_request */
2315 0, /* allocation_size */
2316 0, /* private_flags */
2322 /* close fd from mkstemp() */
2325 if (!NT_STATUS_IS_OK(status
)) {
2326 if (open_was_deferred(req
->mid
)) {
2327 /* We have re-scheduled this call. */
2330 reply_openerror(req
, status
);
2334 reply_outbuf(req
, 1, 0);
2335 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2337 /* the returned filename is relative to the directory */
2338 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2340 s
= fsp
->fsp_name
->base_name
;
2346 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2347 thing in the byte section. JRA */
2348 SSVALS(p
, 0, -1); /* what is this? not in spec */
2350 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2352 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2356 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2357 SCVAL(req
->outbuf
, smb_flg
,
2358 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2361 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2362 SCVAL(req
->outbuf
, smb_flg
,
2363 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2366 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2367 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2368 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2370 TALLOC_FREE(smb_fname
);
2371 END_PROFILE(SMBctemp
);
2375 /*******************************************************************
2376 Check if a user is allowed to rename a file.
2377 ********************************************************************/
2379 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2382 if (!CAN_WRITE(conn
)) {
2383 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2386 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2387 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2388 /* Only bother to read the DOS attribute if we might deny the
2389 rename on the grounds of attribute missmatch. */
2390 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2391 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2392 return NT_STATUS_NO_SUCH_FILE
;
2396 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2397 if (fsp
->posix_open
) {
2398 return NT_STATUS_OK
;
2401 /* If no pathnames are open below this
2402 directory, allow the rename. */
2404 if (file_find_subpath(fsp
)) {
2405 return NT_STATUS_ACCESS_DENIED
;
2407 return NT_STATUS_OK
;
2410 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2411 return NT_STATUS_OK
;
2414 return NT_STATUS_ACCESS_DENIED
;
2417 /*******************************************************************
2418 * unlink a file with all relevant access checks
2419 *******************************************************************/
2421 static NTSTATUS
do_unlink(connection_struct
*conn
,
2422 struct smb_request
*req
,
2423 struct smb_filename
*smb_fname
,
2428 uint32 dirtype_orig
= dirtype
;
2431 bool posix_paths
= lp_posix_pathnames();
2433 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2434 smb_fname_str_dbg(smb_fname
),
2437 if (!CAN_WRITE(conn
)) {
2438 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2442 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2444 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2447 return map_nt_error_from_unix(errno
);
2450 fattr
= dos_mode(conn
, smb_fname
);
2452 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2453 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2456 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2458 return NT_STATUS_NO_SUCH_FILE
;
2461 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2462 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2463 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2465 return NT_STATUS_NO_SUCH_FILE
;
2468 if (dirtype_orig
& 0x8000) {
2469 /* These will never be set for POSIX. */
2470 return NT_STATUS_NO_SUCH_FILE
;
2474 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2475 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2478 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2479 return NT_STATUS_NO_SUCH_FILE
;
2482 if (dirtype
& 0xFF00) {
2483 /* These will never be set for POSIX. */
2484 return NT_STATUS_NO_SUCH_FILE
;
2489 return NT_STATUS_NO_SUCH_FILE
;
2492 /* Can't delete a directory. */
2493 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2494 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2499 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2500 return NT_STATUS_OBJECT_NAME_INVALID
;
2501 #endif /* JRATEST */
2503 /* On open checks the open itself will check the share mode, so
2504 don't do it here as we'll get it wrong. */
2506 status
= SMB_VFS_CREATE_FILE
2509 0, /* root_dir_fid */
2510 smb_fname
, /* fname */
2511 DELETE_ACCESS
, /* access_mask */
2512 FILE_SHARE_NONE
, /* share_access */
2513 FILE_OPEN
, /* create_disposition*/
2514 FILE_NON_DIRECTORY_FILE
, /* create_options */
2515 /* file_attributes */
2516 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2517 FILE_ATTRIBUTE_NORMAL
,
2518 0, /* oplock_request */
2519 0, /* allocation_size */
2520 0, /* private_flags */
2526 if (!NT_STATUS_IS_OK(status
)) {
2527 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2528 nt_errstr(status
)));
2532 status
= can_set_delete_on_close(fsp
, fattr
);
2533 if (!NT_STATUS_IS_OK(status
)) {
2534 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2536 smb_fname_str_dbg(smb_fname
),
2537 nt_errstr(status
)));
2538 close_file(req
, fsp
, NORMAL_CLOSE
);
2542 /* The set is across all open files on this dev/inode pair. */
2543 if (!set_delete_on_close(fsp
, True
, &conn
->session_info
->utok
)) {
2544 close_file(req
, fsp
, NORMAL_CLOSE
);
2545 return NT_STATUS_ACCESS_DENIED
;
2548 return close_file(req
, fsp
, NORMAL_CLOSE
);
2551 /****************************************************************************
2552 The guts of the unlink command, split out so it may be called by the NT SMB
2554 ****************************************************************************/
2556 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2557 uint32 dirtype
, struct smb_filename
*smb_fname
,
2560 char *fname_dir
= NULL
;
2561 char *fname_mask
= NULL
;
2563 NTSTATUS status
= NT_STATUS_OK
;
2564 TALLOC_CTX
*ctx
= talloc_tos();
2566 /* Split up the directory from the filename/mask. */
2567 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2568 &fname_dir
, &fname_mask
);
2569 if (!NT_STATUS_IS_OK(status
)) {
2574 * We should only check the mangled cache
2575 * here if unix_convert failed. This means
2576 * that the path in 'mask' doesn't exist
2577 * on the file system and so we need to look
2578 * for a possible mangle. This patch from
2579 * Tine Smukavec <valentin.smukavec@hermes.si>.
2582 if (!VALID_STAT(smb_fname
->st
) &&
2583 mangle_is_mangled(fname_mask
, conn
->params
)) {
2584 char *new_mask
= NULL
;
2585 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2586 &new_mask
, conn
->params
);
2588 TALLOC_FREE(fname_mask
);
2589 fname_mask
= new_mask
;
2596 * Only one file needs to be unlinked. Append the mask back
2597 * onto the directory.
2599 TALLOC_FREE(smb_fname
->base_name
);
2600 if (ISDOT(fname_dir
)) {
2601 /* Ensure we use canonical names on open. */
2602 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2606 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2611 if (!smb_fname
->base_name
) {
2612 status
= NT_STATUS_NO_MEMORY
;
2616 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2619 status
= check_name(conn
, smb_fname
->base_name
);
2620 if (!NT_STATUS_IS_OK(status
)) {
2624 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2625 if (!NT_STATUS_IS_OK(status
)) {
2631 struct smb_Dir
*dir_hnd
= NULL
;
2633 const char *dname
= NULL
;
2634 char *talloced
= NULL
;
2636 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2637 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2641 if (strequal(fname_mask
,"????????.???")) {
2642 TALLOC_FREE(fname_mask
);
2643 fname_mask
= talloc_strdup(ctx
, "*");
2645 status
= NT_STATUS_NO_MEMORY
;
2650 status
= check_name(conn
, fname_dir
);
2651 if (!NT_STATUS_IS_OK(status
)) {
2655 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2657 if (dir_hnd
== NULL
) {
2658 status
= map_nt_error_from_unix(errno
);
2662 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2663 the pattern matches against the long name, otherwise the short name
2664 We don't implement this yet XXXX
2667 status
= NT_STATUS_NO_SUCH_FILE
;
2669 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2670 &smb_fname
->st
, &talloced
))) {
2671 TALLOC_CTX
*frame
= talloc_stackframe();
2673 if (!is_visible_file(conn
, fname_dir
, dname
,
2674 &smb_fname
->st
, true)) {
2676 TALLOC_FREE(talloced
);
2680 /* Quick check for "." and ".." */
2681 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2683 TALLOC_FREE(talloced
);
2687 if(!mask_match(dname
, fname_mask
,
2688 conn
->case_sensitive
)) {
2690 TALLOC_FREE(talloced
);
2694 TALLOC_FREE(smb_fname
->base_name
);
2695 if (ISDOT(fname_dir
)) {
2696 /* Ensure we use canonical names on open. */
2697 smb_fname
->base_name
=
2698 talloc_asprintf(smb_fname
, "%s",
2701 smb_fname
->base_name
=
2702 talloc_asprintf(smb_fname
, "%s/%s",
2706 if (!smb_fname
->base_name
) {
2707 TALLOC_FREE(dir_hnd
);
2708 status
= NT_STATUS_NO_MEMORY
;
2710 TALLOC_FREE(talloced
);
2714 status
= check_name(conn
, smb_fname
->base_name
);
2715 if (!NT_STATUS_IS_OK(status
)) {
2716 TALLOC_FREE(dir_hnd
);
2718 TALLOC_FREE(talloced
);
2722 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2723 if (!NT_STATUS_IS_OK(status
)) {
2725 TALLOC_FREE(talloced
);
2730 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2731 smb_fname
->base_name
));
2734 TALLOC_FREE(talloced
);
2736 TALLOC_FREE(dir_hnd
);
2739 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2740 status
= map_nt_error_from_unix(errno
);
2744 TALLOC_FREE(fname_dir
);
2745 TALLOC_FREE(fname_mask
);
2749 /****************************************************************************
2751 ****************************************************************************/
2753 void reply_unlink(struct smb_request
*req
)
2755 connection_struct
*conn
= req
->conn
;
2757 struct smb_filename
*smb_fname
= NULL
;
2760 bool path_contains_wcard
= False
;
2761 TALLOC_CTX
*ctx
= talloc_tos();
2763 START_PROFILE(SMBunlink
);
2766 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2770 dirtype
= SVAL(req
->vwv
+0, 0);
2772 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2773 STR_TERMINATE
, &status
,
2774 &path_contains_wcard
);
2775 if (!NT_STATUS_IS_OK(status
)) {
2776 reply_nterror(req
, status
);
2780 status
= filename_convert(ctx
, conn
,
2781 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2783 UCF_COND_ALLOW_WCARD_LCOMP
,
2784 &path_contains_wcard
,
2786 if (!NT_STATUS_IS_OK(status
)) {
2787 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2788 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2789 ERRSRV
, ERRbadpath
);
2792 reply_nterror(req
, status
);
2796 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2798 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2799 path_contains_wcard
);
2800 if (!NT_STATUS_IS_OK(status
)) {
2801 if (open_was_deferred(req
->mid
)) {
2802 /* We have re-scheduled this call. */
2805 reply_nterror(req
, status
);
2809 reply_outbuf(req
, 0, 0);
2811 TALLOC_FREE(smb_fname
);
2812 END_PROFILE(SMBunlink
);
2816 /****************************************************************************
2818 ****************************************************************************/
2820 static void fail_readraw(void)
2822 const char *errstr
= talloc_asprintf(talloc_tos(),
2823 "FAIL ! reply_readbraw: socket write fail (%s)",
2828 exit_server_cleanly(errstr
);
2831 /****************************************************************************
2832 Fake (read/write) sendfile. Returns -1 on read or write fail.
2833 ****************************************************************************/
2835 ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
)
2838 size_t tosend
= nread
;
2845 bufsize
= MIN(nread
, 65536);
2847 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2851 while (tosend
> 0) {
2855 if (tosend
> bufsize
) {
2860 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2866 /* If we had a short read, fill with zeros. */
2867 if (ret
< cur_read
) {
2868 memset(buf
+ ret
, '\0', cur_read
- ret
);
2871 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
2873 char addr
[INET6_ADDRSTRLEN
];
2875 * Try and give an error message saying what
2878 DEBUG(0, ("write_data failed for client %s. "
2880 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
2887 startpos
+= cur_read
;
2891 return (ssize_t
)nread
;
2894 /****************************************************************************
2895 Deal with the case of sendfile reading less bytes from the file than
2896 requested. Fill with zeros (all we can do).
2897 ****************************************************************************/
2899 void sendfile_short_send(files_struct
*fsp
,
2904 #define SHORT_SEND_BUFSIZE 1024
2905 if (nread
< headersize
) {
2906 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2907 "header for file %s (%s). Terminating\n",
2908 fsp_str_dbg(fsp
), strerror(errno
)));
2909 exit_server_cleanly("sendfile_short_send failed");
2912 nread
-= headersize
;
2914 if (nread
< smb_maxcnt
) {
2915 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
2917 exit_server_cleanly("sendfile_short_send: "
2921 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2922 "with zeros !\n", fsp_str_dbg(fsp
)));
2924 while (nread
< smb_maxcnt
) {
2926 * We asked for the real file size and told sendfile
2927 * to not go beyond the end of the file. But it can
2928 * happen that in between our fstat call and the
2929 * sendfile call the file was truncated. This is very
2930 * bad because we have already announced the larger
2931 * number of bytes to the client.
2933 * The best we can do now is to send 0-bytes, just as
2934 * a read from a hole in a sparse file would do.
2936 * This should happen rarely enough that I don't care
2937 * about efficiency here :-)
2941 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
2942 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
2944 char addr
[INET6_ADDRSTRLEN
];
2946 * Try and give an error message saying what
2949 DEBUG(0, ("write_data failed for client %s. "
2952 fsp
->conn
->sconn
->sock
, addr
,
2955 exit_server_cleanly("sendfile_short_send: "
2956 "write_data failed");
2964 /****************************************************************************
2965 Return a readbraw error (4 bytes of zero).
2966 ****************************************************************************/
2968 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
2974 smbd_lock_socket(sconn
);
2975 if (write_data(sconn
->sock
,header
,4) != 4) {
2976 char addr
[INET6_ADDRSTRLEN
];
2978 * Try and give an error message saying what
2981 DEBUG(0, ("write_data failed for client %s. "
2983 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
2988 smbd_unlock_socket(sconn
);
2991 /****************************************************************************
2992 Use sendfile in readbraw.
2993 ****************************************************************************/
2995 static void send_file_readbraw(connection_struct
*conn
,
2996 struct smb_request
*req
,
3002 struct smbd_server_connection
*sconn
= req
->sconn
;
3003 char *outbuf
= NULL
;
3007 * We can only use sendfile on a non-chained packet
3008 * but we can use on a non-oplocked file. tridge proved this
3009 * on a train in Germany :-). JRA.
3010 * reply_readbraw has already checked the length.
3013 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3014 (fsp
->wcp
== NULL
) &&
3015 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3016 ssize_t sendfile_read
= -1;
3018 DATA_BLOB header_blob
;
3020 _smb_setlen(header
,nread
);
3021 header_blob
= data_blob_const(header
, 4);
3023 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3024 &header_blob
, startpos
,
3026 if (sendfile_read
== -1) {
3027 /* Returning ENOSYS means no data at all was sent.
3028 * Do this as a normal read. */
3029 if (errno
== ENOSYS
) {
3030 goto normal_readbraw
;
3034 * Special hack for broken Linux with no working sendfile. If we
3035 * return EINTR we sent the header but not the rest of the data.
3036 * Fake this up by doing read/write calls.
3038 if (errno
== EINTR
) {
3039 /* Ensure we don't do this again. */
3040 set_use_sendfile(SNUM(conn
), False
);
3041 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3043 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3044 DEBUG(0,("send_file_readbraw: "
3045 "fake_sendfile failed for "
3049 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3054 DEBUG(0,("send_file_readbraw: sendfile failed for "
3055 "file %s (%s). Terminating\n",
3056 fsp_str_dbg(fsp
), strerror(errno
)));
3057 exit_server_cleanly("send_file_readbraw sendfile failed");
3058 } else if (sendfile_read
== 0) {
3060 * Some sendfile implementations return 0 to indicate
3061 * that there was a short read, but nothing was
3062 * actually written to the socket. In this case,
3063 * fallback to the normal read path so the header gets
3064 * the correct byte count.
3066 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3067 "bytes falling back to the normal read: "
3068 "%s\n", fsp_str_dbg(fsp
)));
3069 goto normal_readbraw
;
3072 /* Deal with possible short send. */
3073 if (sendfile_read
!= 4+nread
) {
3074 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3081 outbuf
= TALLOC_ARRAY(NULL
, char, nread
+4);
3083 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3084 (unsigned)(nread
+4)));
3085 reply_readbraw_error(sconn
);
3090 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3091 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3100 _smb_setlen(outbuf
,ret
);
3101 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3102 char addr
[INET6_ADDRSTRLEN
];
3104 * Try and give an error message saying what
3107 DEBUG(0, ("write_data failed for client %s. "
3109 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3116 TALLOC_FREE(outbuf
);
3119 /****************************************************************************
3120 Reply to a readbraw (core+ protocol).
3121 ****************************************************************************/
3123 void reply_readbraw(struct smb_request
*req
)
3125 connection_struct
*conn
= req
->conn
;
3126 struct smbd_server_connection
*sconn
= req
->sconn
;
3127 ssize_t maxcount
,mincount
;
3131 struct lock_struct lock
;
3134 START_PROFILE(SMBreadbraw
);
3136 if (srv_is_signing_active(sconn
) ||
3137 is_encrypted_packet(req
->inbuf
)) {
3138 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3139 "raw reads/writes are disallowed.");
3143 reply_readbraw_error(sconn
);
3144 END_PROFILE(SMBreadbraw
);
3148 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3149 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3150 "'async smb echo handler = yes'\n"));
3151 reply_readbraw_error(sconn
);
3152 END_PROFILE(SMBreadbraw
);
3157 * Special check if an oplock break has been issued
3158 * and the readraw request croses on the wire, we must
3159 * return a zero length response here.
3162 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3165 * We have to do a check_fsp by hand here, as
3166 * we must always return 4 zero bytes on error,
3170 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3171 req
->vuid
!= fsp
->vuid
||
3172 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3174 * fsp could be NULL here so use the value from the packet. JRA.
3176 DEBUG(3,("reply_readbraw: fnum %d not valid "
3178 (int)SVAL(req
->vwv
+0, 0)));
3179 reply_readbraw_error(sconn
);
3180 END_PROFILE(SMBreadbraw
);
3184 /* Do a "by hand" version of CHECK_READ. */
3185 if (!(fsp
->can_read
||
3186 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3187 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3188 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3189 (int)SVAL(req
->vwv
+0, 0)));
3190 reply_readbraw_error(sconn
);
3191 END_PROFILE(SMBreadbraw
);
3195 flush_write_cache(fsp
, READRAW_FLUSH
);
3197 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3198 if(req
->wct
== 10) {
3200 * This is a large offset (64 bit) read.
3202 #ifdef LARGE_SMB_OFF_T
3204 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+8, 0)) << 32);
3206 #else /* !LARGE_SMB_OFF_T */
3209 * Ensure we haven't been sent a >32 bit offset.
3212 if(IVAL(req
->vwv
+8, 0) != 0) {
3213 DEBUG(0,("reply_readbraw: large offset "
3214 "(%x << 32) used and we don't support "
3215 "64 bit offsets.\n",
3216 (unsigned int)IVAL(req
->vwv
+8, 0) ));
3217 reply_readbraw_error(sconn
);
3218 END_PROFILE(SMBreadbraw
);
3222 #endif /* LARGE_SMB_OFF_T */
3225 DEBUG(0,("reply_readbraw: negative 64 bit "
3226 "readraw offset (%.0f) !\n",
3227 (double)startpos
));
3228 reply_readbraw_error(sconn
);
3229 END_PROFILE(SMBreadbraw
);
3234 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3235 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3237 /* ensure we don't overrun the packet size */
3238 maxcount
= MIN(65535,maxcount
);
3240 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3241 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3244 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3245 reply_readbraw_error(sconn
);
3246 END_PROFILE(SMBreadbraw
);
3250 if (fsp_stat(fsp
) == 0) {
3251 size
= fsp
->fsp_name
->st
.st_ex_size
;
3254 if (startpos
>= size
) {
3257 nread
= MIN(maxcount
,(size
- startpos
));
3260 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3261 if (nread
< mincount
)
3265 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3266 "min=%lu nread=%lu\n",
3267 fsp
->fnum
, (double)startpos
,
3268 (unsigned long)maxcount
,
3269 (unsigned long)mincount
,
3270 (unsigned long)nread
) );
3272 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3274 DEBUG(5,("reply_readbraw finished\n"));
3276 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3278 END_PROFILE(SMBreadbraw
);
3283 #define DBGC_CLASS DBGC_LOCKING
3285 /****************************************************************************
3286 Reply to a lockread (core+ protocol).
3287 ****************************************************************************/
3289 void reply_lockread(struct smb_request
*req
)
3291 connection_struct
*conn
= req
->conn
;
3298 struct byte_range_lock
*br_lck
= NULL
;
3300 struct smbd_server_connection
*sconn
= req
->sconn
;
3302 START_PROFILE(SMBlockread
);
3305 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3306 END_PROFILE(SMBlockread
);
3310 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3312 if (!check_fsp(conn
, req
, fsp
)) {
3313 END_PROFILE(SMBlockread
);
3317 if (!CHECK_READ(fsp
,req
)) {
3318 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3319 END_PROFILE(SMBlockread
);
3323 numtoread
= SVAL(req
->vwv
+1, 0);
3324 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3326 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3328 reply_outbuf(req
, 5, numtoread
+ 3);
3330 data
= smb_buf(req
->outbuf
) + 3;
3333 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3334 * protocol request that predates the read/write lock concept.
3335 * Thus instead of asking for a read lock here we need to ask
3336 * for a write lock. JRA.
3337 * Note that the requested lock size is unaffected by max_recv.
3340 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3342 (uint64_t)req
->smbpid
,
3343 (uint64_t)numtoread
,
3347 False
, /* Non-blocking lock. */
3351 TALLOC_FREE(br_lck
);
3353 if (NT_STATUS_V(status
)) {
3354 reply_nterror(req
, status
);
3355 END_PROFILE(SMBlockread
);
3360 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3363 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3364 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3365 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3366 (unsigned int)numtoread
,
3367 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3368 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3370 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3373 reply_nterror(req
, map_nt_error_from_unix(errno
));
3374 END_PROFILE(SMBlockread
);
3378 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3380 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3381 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3382 p
= smb_buf(req
->outbuf
);
3383 SCVAL(p
,0,0); /* pad byte. */
3386 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3387 fsp
->fnum
, (int)numtoread
, (int)nread
));
3389 END_PROFILE(SMBlockread
);
3394 #define DBGC_CLASS DBGC_ALL
3396 /****************************************************************************
3398 ****************************************************************************/
3400 void reply_read(struct smb_request
*req
)
3402 connection_struct
*conn
= req
->conn
;
3409 struct lock_struct lock
;
3410 struct smbd_server_connection
*sconn
= req
->sconn
;
3412 START_PROFILE(SMBread
);
3415 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3416 END_PROFILE(SMBread
);
3420 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3422 if (!check_fsp(conn
, req
, fsp
)) {
3423 END_PROFILE(SMBread
);
3427 if (!CHECK_READ(fsp
,req
)) {
3428 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3429 END_PROFILE(SMBread
);
3433 numtoread
= SVAL(req
->vwv
+1, 0);
3434 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3436 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3439 * The requested read size cannot be greater than max_recv. JRA.
3441 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3442 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3443 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3444 (unsigned int)numtoread
,
3445 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3446 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3449 reply_outbuf(req
, 5, numtoread
+3);
3451 data
= smb_buf(req
->outbuf
) + 3;
3453 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3454 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3457 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3458 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3459 END_PROFILE(SMBread
);
3464 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3467 reply_nterror(req
, map_nt_error_from_unix(errno
));
3471 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3473 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3474 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3475 SCVAL(smb_buf(req
->outbuf
),0,1);
3476 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3478 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3479 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3482 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3484 END_PROFILE(SMBread
);
3488 /****************************************************************************
3490 ****************************************************************************/
3492 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3498 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3499 data
= smb_buf(outbuf
);
3501 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3503 SCVAL(outbuf
,smb_vwv0
,0xFF);
3504 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3505 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3506 SSVAL(outbuf
,smb_vwv6
,
3508 + 1 /* the wct field */
3509 + 12 * sizeof(uint16_t) /* vwv */
3510 + 2); /* the buflen field */
3511 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3512 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3513 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3514 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3518 /****************************************************************************
3519 Reply to a read and X - possibly using sendfile.
3520 ****************************************************************************/
3522 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3523 files_struct
*fsp
, SMB_OFF_T startpos
,
3527 struct lock_struct lock
;
3528 int saved_errno
= 0;
3530 if(fsp_stat(fsp
) == -1) {
3531 reply_nterror(req
, map_nt_error_from_unix(errno
));
3535 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3536 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3539 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3540 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3544 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3545 (startpos
> fsp
->fsp_name
->st
.st_ex_size
)
3546 || (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3548 * We already know that we would do a short read, so don't
3549 * try the sendfile() path.
3551 goto nosendfile_read
;
3555 * We can only use sendfile on a non-chained packet
3556 * but we can use on a non-oplocked file. tridge proved this
3557 * on a train in Germany :-). JRA.
3560 if (!req_is_in_chain(req
) &&
3561 !is_encrypted_packet(req
->inbuf
) && (fsp
->base_fsp
== NULL
) &&
3562 (fsp
->wcp
== NULL
) &&
3563 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3564 uint8 headerbuf
[smb_size
+ 12 * 2];
3568 * Set up the packet header before send. We
3569 * assume here the sendfile will work (get the
3570 * correct amount of data).
3573 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3575 construct_reply_common_req(req
, (char *)headerbuf
);
3576 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3578 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3579 startpos
, smb_maxcnt
);
3581 /* Returning ENOSYS means no data at all was sent.
3582 Do this as a normal read. */
3583 if (errno
== ENOSYS
) {
3588 * Special hack for broken Linux with no working sendfile. If we
3589 * return EINTR we sent the header but not the rest of the data.
3590 * Fake this up by doing read/write calls.
3593 if (errno
== EINTR
) {
3594 /* Ensure we don't do this again. */
3595 set_use_sendfile(SNUM(conn
), False
);
3596 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3597 nread
= fake_sendfile(fsp
, startpos
,
3600 DEBUG(0,("send_file_readX: "
3601 "fake_sendfile failed for "
3605 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3607 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3608 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3609 /* No outbuf here means successful sendfile. */
3613 DEBUG(0,("send_file_readX: sendfile failed for file "
3614 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3616 exit_server_cleanly("send_file_readX sendfile failed");
3617 } else if (nread
== 0) {
3619 * Some sendfile implementations return 0 to indicate
3620 * that there was a short read, but nothing was
3621 * actually written to the socket. In this case,
3622 * fallback to the normal read path so the header gets
3623 * the correct byte count.
3625 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3626 "falling back to the normal read: %s\n",
3631 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3632 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3634 /* Deal with possible short send. */
3635 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3636 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3638 /* No outbuf here means successful sendfile. */
3639 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3640 SMB_PERFCOUNT_END(&req
->pcd
);
3646 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3647 uint8 headerbuf
[smb_size
+ 2*12];
3649 construct_reply_common_req(req
, (char *)headerbuf
);
3650 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3652 /* Send out the header. */
3653 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3654 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3656 char addr
[INET6_ADDRSTRLEN
];
3658 * Try and give an error message saying what
3661 DEBUG(0, ("write_data failed for client %s. "
3663 get_peer_addr(req
->sconn
->sock
, addr
,
3667 DEBUG(0,("send_file_readX: write_data failed for file "
3668 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3670 exit_server_cleanly("send_file_readX sendfile failed");
3672 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3674 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3675 "file %s (%s).\n", fsp_str_dbg(fsp
),
3677 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3684 reply_outbuf(req
, 12, smb_maxcnt
);
3686 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3687 saved_errno
= errno
;
3689 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3692 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3696 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3698 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3699 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3705 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3706 TALLOC_FREE(req
->outbuf
);
3710 /****************************************************************************
3711 Reply to a read and X.
3712 ****************************************************************************/
3714 void reply_read_and_X(struct smb_request
*req
)
3716 connection_struct
*conn
= req
->conn
;
3720 bool big_readX
= False
;
3722 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3725 START_PROFILE(SMBreadX
);
3727 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3728 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3732 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3733 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3734 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3736 /* If it's an IPC, pass off the pipe handler. */
3738 reply_pipe_read_and_X(req
);
3739 END_PROFILE(SMBreadX
);
3743 if (!check_fsp(conn
, req
, fsp
)) {
3744 END_PROFILE(SMBreadX
);
3748 if (!CHECK_READ(fsp
,req
)) {
3749 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3750 END_PROFILE(SMBreadX
);
3754 if (global_client_caps
& CAP_LARGE_READX
) {
3755 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3756 smb_maxcnt
|= (upper_size
<<16);
3757 if (upper_size
> 1) {
3758 /* Can't do this on a chained packet. */
3759 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3760 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3761 END_PROFILE(SMBreadX
);
3764 /* We currently don't do this on signed or sealed data. */
3765 if (srv_is_signing_active(req
->sconn
) ||
3766 is_encrypted_packet(req
->inbuf
)) {
3767 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3768 END_PROFILE(SMBreadX
);
3771 /* Is there room in the reply for this data ? */
3772 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3774 NT_STATUS_INVALID_PARAMETER
);
3775 END_PROFILE(SMBreadX
);
3782 if (req
->wct
== 12) {
3783 #ifdef LARGE_SMB_OFF_T
3785 * This is a large offset (64 bit) read.
3787 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+10, 0)) << 32);
3789 #else /* !LARGE_SMB_OFF_T */
3792 * Ensure we haven't been sent a >32 bit offset.
3795 if(IVAL(req
->vwv
+10, 0) != 0) {
3796 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3797 "used and we don't support 64 bit offsets.\n",
3798 (unsigned int)IVAL(req
->vwv
+10, 0) ));
3799 END_PROFILE(SMBreadX
);
3800 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3804 #endif /* LARGE_SMB_OFF_T */
3809 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3814 if (NT_STATUS_IS_OK(status
)) {
3815 /* Read scheduled - we're done. */
3818 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3819 /* Real error - report to client. */
3820 END_PROFILE(SMBreadX
);
3821 reply_nterror(req
, status
);
3824 /* NT_STATUS_RETRY - fall back to sync read. */
3827 smbd_lock_socket(req
->sconn
);
3828 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3829 smbd_unlock_socket(req
->sconn
);
3832 END_PROFILE(SMBreadX
);
3836 /****************************************************************************
3837 Error replies to writebraw must have smb_wct == 1. Fix this up.
3838 ****************************************************************************/
3840 void error_to_writebrawerr(struct smb_request
*req
)
3842 uint8
*old_outbuf
= req
->outbuf
;
3844 reply_outbuf(req
, 1, 0);
3846 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3847 TALLOC_FREE(old_outbuf
);
3850 /****************************************************************************
3851 Read 4 bytes of a smb packet and return the smb length of the packet.
3852 Store the result in the buffer. This version of the function will
3853 never return a session keepalive (length of zero).
3854 Timeout is in milliseconds.
3855 ****************************************************************************/
3857 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3860 uint8_t msgtype
= SMBkeepalive
;
3862 while (msgtype
== SMBkeepalive
) {
3865 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3867 if (!NT_STATUS_IS_OK(status
)) {
3868 char addr
[INET6_ADDRSTRLEN
];
3869 /* Try and give an error message
3870 * saying what client failed. */
3871 DEBUG(0, ("read_fd_with_timeout failed for "
3872 "client %s read error = %s.\n",
3873 get_peer_addr(fd
,addr
,sizeof(addr
)),
3874 nt_errstr(status
)));
3878 msgtype
= CVAL(inbuf
, 0);
3881 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3882 (unsigned long)len
));
3884 return NT_STATUS_OK
;
3887 /****************************************************************************
3888 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3889 ****************************************************************************/
3891 void reply_writebraw(struct smb_request
*req
)
3893 connection_struct
*conn
= req
->conn
;
3896 ssize_t total_written
=0;
3897 size_t numtowrite
=0;
3903 struct lock_struct lock
;
3906 START_PROFILE(SMBwritebraw
);
3909 * If we ever reply with an error, it must have the SMB command
3910 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3913 SCVAL(req
->inbuf
,smb_com
,SMBwritec
);
3915 if (srv_is_signing_active(req
->sconn
)) {
3916 END_PROFILE(SMBwritebraw
);
3917 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3918 "raw reads/writes are disallowed.");
3921 if (req
->wct
< 12) {
3922 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3923 error_to_writebrawerr(req
);
3924 END_PROFILE(SMBwritebraw
);
3928 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3929 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3930 "'async smb echo handler = yes'\n"));
3931 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3932 error_to_writebrawerr(req
);
3933 END_PROFILE(SMBwritebraw
);
3937 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3938 if (!check_fsp(conn
, req
, fsp
)) {
3939 error_to_writebrawerr(req
);
3940 END_PROFILE(SMBwritebraw
);
3944 if (!CHECK_WRITE(fsp
)) {
3945 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3946 error_to_writebrawerr(req
);
3947 END_PROFILE(SMBwritebraw
);
3951 tcount
= IVAL(req
->vwv
+1, 0);
3952 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3953 write_through
= BITSETW(req
->vwv
+7,0);
3955 /* We have to deal with slightly different formats depending
3956 on whether we are using the core+ or lanman1.0 protocol */
3958 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
3959 numtowrite
= SVAL(smb_buf(req
->inbuf
),-2);
3960 data
= smb_buf(req
->inbuf
);
3962 numtowrite
= SVAL(req
->vwv
+10, 0);
3963 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3966 /* Ensure we don't write bytes past the end of this packet. */
3967 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3968 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3969 error_to_writebrawerr(req
);
3970 END_PROFILE(SMBwritebraw
);
3974 if (!fsp
->print_file
) {
3975 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3976 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
3979 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3980 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3981 error_to_writebrawerr(req
);
3982 END_PROFILE(SMBwritebraw
);
3988 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3991 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3992 "wrote=%d sync=%d\n",
3993 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3994 (int)nwritten
, (int)write_through
));
3996 if (nwritten
< (ssize_t
)numtowrite
) {
3997 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3998 error_to_writebrawerr(req
);
4002 total_written
= nwritten
;
4004 /* Allocate a buffer of 64k + length. */
4005 buf
= TALLOC_ARRAY(NULL
, char, 65540);
4007 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4008 error_to_writebrawerr(req
);
4012 /* Return a SMBwritebraw message to the redirector to tell
4013 * it to send more bytes */
4015 memcpy(buf
, req
->inbuf
, smb_size
);
4016 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4017 SCVAL(buf
,smb_com
,SMBwritebraw
);
4018 SSVALS(buf
,smb_vwv0
,0xFFFF);
4020 if (!srv_send_smb(req
->sconn
,
4022 false, 0, /* no signing */
4023 IS_CONN_ENCRYPTED(conn
),
4025 exit_server_cleanly("reply_writebraw: srv_send_smb "
4029 /* Now read the raw data into the buffer and write it */
4030 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4032 if (!NT_STATUS_IS_OK(status
)) {
4033 exit_server_cleanly("secondary writebraw failed");
4036 /* Set up outbuf to return the correct size */
4037 reply_outbuf(req
, 1, 0);
4039 if (numtowrite
!= 0) {
4041 if (numtowrite
> 0xFFFF) {
4042 DEBUG(0,("reply_writebraw: Oversize secondary write "
4043 "raw requested (%u). Terminating\n",
4044 (unsigned int)numtowrite
));
4045 exit_server_cleanly("secondary writebraw failed");
4048 if (tcount
> nwritten
+numtowrite
) {
4049 DEBUG(3,("reply_writebraw: Client overestimated the "
4051 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4054 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4056 if (!NT_STATUS_IS_OK(status
)) {
4057 char addr
[INET6_ADDRSTRLEN
];
4058 /* Try and give an error message
4059 * saying what client failed. */
4060 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4061 "raw read failed (%s) for client %s. "
4062 "Terminating\n", nt_errstr(status
),
4063 get_peer_addr(req
->sconn
->sock
, addr
,
4065 exit_server_cleanly("secondary writebraw failed");
4068 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4069 if (nwritten
== -1) {
4071 reply_nterror(req
, map_nt_error_from_unix(errno
));
4072 error_to_writebrawerr(req
);
4076 if (nwritten
< (ssize_t
)numtowrite
) {
4077 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4078 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4082 total_written
+= nwritten
;
4087 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4089 status
= sync_file(conn
, fsp
, write_through
);
4090 if (!NT_STATUS_IS_OK(status
)) {
4091 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4092 fsp_str_dbg(fsp
), nt_errstr(status
)));
4093 reply_nterror(req
, status
);
4094 error_to_writebrawerr(req
);
4098 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4100 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4101 (int)total_written
));
4103 if (!fsp
->print_file
) {
4104 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4107 /* We won't return a status if write through is not selected - this
4108 * follows what WfWg does */
4109 END_PROFILE(SMBwritebraw
);
4111 if (!write_through
&& total_written
==tcount
) {
4113 #if RABBIT_PELLET_FIX
4115 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4116 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4119 if (!send_keepalive(req
->sconn
->sock
)) {
4120 exit_server_cleanly("reply_writebraw: send of "
4121 "keepalive failed");
4124 TALLOC_FREE(req
->outbuf
);
4129 if (!fsp
->print_file
) {
4130 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4133 END_PROFILE(SMBwritebraw
);
4138 #define DBGC_CLASS DBGC_LOCKING
4140 /****************************************************************************
4141 Reply to a writeunlock (core+).
4142 ****************************************************************************/
4144 void reply_writeunlock(struct smb_request
*req
)
4146 connection_struct
*conn
= req
->conn
;
4147 ssize_t nwritten
= -1;
4151 NTSTATUS status
= NT_STATUS_OK
;
4153 struct lock_struct lock
;
4154 int saved_errno
= 0;
4156 START_PROFILE(SMBwriteunlock
);
4159 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4160 END_PROFILE(SMBwriteunlock
);
4164 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4166 if (!check_fsp(conn
, req
, fsp
)) {
4167 END_PROFILE(SMBwriteunlock
);
4171 if (!CHECK_WRITE(fsp
)) {
4172 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4173 END_PROFILE(SMBwriteunlock
);
4177 numtowrite
= SVAL(req
->vwv
+1, 0);
4178 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4179 data
= (const char *)req
->buf
+ 3;
4181 if (!fsp
->print_file
&& numtowrite
> 0) {
4182 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4183 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4186 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4187 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4188 END_PROFILE(SMBwriteunlock
);
4193 /* The special X/Open SMB protocol handling of
4194 zero length writes is *NOT* done for
4196 if(numtowrite
== 0) {
4199 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4200 saved_errno
= errno
;
4203 status
= sync_file(conn
, fsp
, False
/* write through */);
4204 if (!NT_STATUS_IS_OK(status
)) {
4205 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4206 fsp_str_dbg(fsp
), nt_errstr(status
)));
4207 reply_nterror(req
, status
);
4212 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4216 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4217 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4221 if (numtowrite
&& !fsp
->print_file
) {
4222 status
= do_unlock(req
->sconn
->msg_ctx
,
4224 (uint64_t)req
->smbpid
,
4225 (uint64_t)numtowrite
,
4229 if (NT_STATUS_V(status
)) {
4230 reply_nterror(req
, status
);
4235 reply_outbuf(req
, 1, 0);
4237 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4239 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4240 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4243 if (numtowrite
&& !fsp
->print_file
) {
4244 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4247 END_PROFILE(SMBwriteunlock
);
4252 #define DBGC_CLASS DBGC_ALL
4254 /****************************************************************************
4256 ****************************************************************************/
4258 void reply_write(struct smb_request
*req
)
4260 connection_struct
*conn
= req
->conn
;
4262 ssize_t nwritten
= -1;
4266 struct lock_struct lock
;
4268 int saved_errno
= 0;
4270 START_PROFILE(SMBwrite
);
4273 END_PROFILE(SMBwrite
);
4274 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4278 /* If it's an IPC, pass off the pipe handler. */
4280 reply_pipe_write(req
);
4281 END_PROFILE(SMBwrite
);
4285 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4287 if (!check_fsp(conn
, req
, fsp
)) {
4288 END_PROFILE(SMBwrite
);
4292 if (!CHECK_WRITE(fsp
)) {
4293 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4294 END_PROFILE(SMBwrite
);
4298 numtowrite
= SVAL(req
->vwv
+1, 0);
4299 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4300 data
= (const char *)req
->buf
+ 3;
4302 if (!fsp
->print_file
) {
4303 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4304 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4307 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4308 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4309 END_PROFILE(SMBwrite
);
4315 * X/Open SMB protocol says that if smb_vwv1 is
4316 * zero then the file size should be extended or
4317 * truncated to the size given in smb_vwv[2-3].
4320 if(numtowrite
== 0) {
4322 * This is actually an allocate call, and set EOF. JRA.
4324 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
4326 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4329 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
4331 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4334 trigger_write_time_update_immediate(fsp
);
4336 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4339 status
= sync_file(conn
, fsp
, False
);
4340 if (!NT_STATUS_IS_OK(status
)) {
4341 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4342 fsp_str_dbg(fsp
), nt_errstr(status
)));
4343 reply_nterror(req
, status
);
4348 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4352 if((nwritten
== 0) && (numtowrite
!= 0)) {
4353 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4357 reply_outbuf(req
, 1, 0);
4359 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4361 if (nwritten
< (ssize_t
)numtowrite
) {
4362 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4363 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4366 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4369 if (!fsp
->print_file
) {
4370 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4373 END_PROFILE(SMBwrite
);
4377 /****************************************************************************
4378 Ensure a buffer is a valid writeX for recvfile purposes.
4379 ****************************************************************************/
4381 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4382 (2*14) + /* word count (including bcc) */ \
4385 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4386 const uint8_t *inbuf
)
4389 connection_struct
*conn
= NULL
;
4390 unsigned int doff
= 0;
4391 size_t len
= smb_len_large(inbuf
);
4393 if (is_encrypted_packet(inbuf
)) {
4394 /* Can't do this on encrypted
4399 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4403 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4404 CVAL(inbuf
,smb_wct
) != 14) {
4405 DEBUG(10,("is_valid_writeX_buffer: chained or "
4406 "invalid word length.\n"));
4410 conn
= conn_find(sconn
, SVAL(inbuf
, smb_tid
));
4412 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4416 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4419 if (IS_PRINT(conn
)) {
4420 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4423 doff
= SVAL(inbuf
,smb_vwv11
);
4425 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4427 if (len
> doff
&& len
- doff
> 0xFFFF) {
4428 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4431 if (numtowrite
== 0) {
4432 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4436 /* Ensure the sizes match up. */
4437 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4438 /* no pad byte...old smbclient :-( */
4439 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4441 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4445 if (len
- doff
!= numtowrite
) {
4446 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4447 "len = %u, doff = %u, numtowrite = %u\n",
4450 (unsigned int)numtowrite
));
4454 DEBUG(10,("is_valid_writeX_buffer: true "
4455 "len = %u, doff = %u, numtowrite = %u\n",
4458 (unsigned int)numtowrite
));
4463 /****************************************************************************
4464 Reply to a write and X.
4465 ****************************************************************************/
4467 void reply_write_and_X(struct smb_request
*req
)
4469 connection_struct
*conn
= req
->conn
;
4471 struct lock_struct lock
;
4476 unsigned int smb_doff
;
4477 unsigned int smblen
;
4480 int saved_errno
= 0;
4482 START_PROFILE(SMBwriteX
);
4484 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4485 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4486 END_PROFILE(SMBwriteX
);
4490 numtowrite
= SVAL(req
->vwv
+10, 0);
4491 smb_doff
= SVAL(req
->vwv
+11, 0);
4492 smblen
= smb_len(req
->inbuf
);
4494 if (req
->unread_bytes
> 0xFFFF ||
4495 (smblen
> smb_doff
&&
4496 smblen
- smb_doff
> 0xFFFF)) {
4497 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4500 if (req
->unread_bytes
) {
4501 /* Can't do a recvfile write on IPC$ */
4503 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4504 END_PROFILE(SMBwriteX
);
4507 if (numtowrite
!= req
->unread_bytes
) {
4508 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4509 END_PROFILE(SMBwriteX
);
4513 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4514 smb_doff
+ numtowrite
> smblen
) {
4515 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4516 END_PROFILE(SMBwriteX
);
4521 /* If it's an IPC, pass off the pipe handler. */
4523 if (req
->unread_bytes
) {
4524 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4525 END_PROFILE(SMBwriteX
);
4528 reply_pipe_write_and_X(req
);
4529 END_PROFILE(SMBwriteX
);
4533 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4534 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4535 write_through
= BITSETW(req
->vwv
+7,0);
4537 if (!check_fsp(conn
, req
, fsp
)) {
4538 END_PROFILE(SMBwriteX
);
4542 if (!CHECK_WRITE(fsp
)) {
4543 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4544 END_PROFILE(SMBwriteX
);
4548 data
= smb_base(req
->inbuf
) + smb_doff
;
4550 if(req
->wct
== 14) {
4551 #ifdef LARGE_SMB_OFF_T
4553 * This is a large offset (64 bit) write.
4555 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+12, 0)) << 32);
4557 #else /* !LARGE_SMB_OFF_T */
4560 * Ensure we haven't been sent a >32 bit offset.
4563 if(IVAL(req
->vwv
+12, 0) != 0) {
4564 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4565 "used and we don't support 64 bit offsets.\n",
4566 (unsigned int)IVAL(req
->vwv
+12, 0) ));
4567 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4568 END_PROFILE(SMBwriteX
);
4572 #endif /* LARGE_SMB_OFF_T */
4575 /* X/Open SMB protocol says that, unlike SMBwrite
4576 if the length is zero then NO truncation is
4577 done, just a write of zero. To truncate a file,
4580 if(numtowrite
== 0) {
4583 if (req
->unread_bytes
== 0) {
4584 status
= schedule_aio_write_and_X(conn
,
4591 if (NT_STATUS_IS_OK(status
)) {
4592 /* write scheduled - we're done. */
4595 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4596 /* Real error - report to client. */
4597 reply_nterror(req
, status
);
4600 /* NT_STATUS_RETRY - fall through to sync write. */
4603 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4604 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4607 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4608 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4612 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4613 saved_errno
= errno
;
4615 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4619 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4623 if((nwritten
== 0) && (numtowrite
!= 0)) {
4624 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4628 reply_outbuf(req
, 6, 0);
4629 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4630 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4632 if (nwritten
< (ssize_t
)numtowrite
) {
4633 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4634 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4637 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4638 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4640 status
= sync_file(conn
, fsp
, write_through
);
4641 if (!NT_STATUS_IS_OK(status
)) {
4642 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4643 fsp_str_dbg(fsp
), nt_errstr(status
)));
4644 reply_nterror(req
, status
);
4648 END_PROFILE(SMBwriteX
);
4653 END_PROFILE(SMBwriteX
);
4657 /****************************************************************************
4659 ****************************************************************************/
4661 void reply_lseek(struct smb_request
*req
)
4663 connection_struct
*conn
= req
->conn
;
4669 START_PROFILE(SMBlseek
);
4672 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4673 END_PROFILE(SMBlseek
);
4677 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4679 if (!check_fsp(conn
, req
, fsp
)) {
4683 flush_write_cache(fsp
, SEEK_FLUSH
);
4685 mode
= SVAL(req
->vwv
+1, 0) & 3;
4686 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4687 startpos
= (SMB_OFF_T
)IVALS(req
->vwv
+2, 0);
4696 res
= fsp
->fh
->pos
+ startpos
;
4707 if (umode
== SEEK_END
) {
4708 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4709 if(errno
== EINVAL
) {
4710 SMB_OFF_T current_pos
= startpos
;
4712 if(fsp_stat(fsp
) == -1) {
4714 map_nt_error_from_unix(errno
));
4715 END_PROFILE(SMBlseek
);
4719 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4721 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4726 reply_nterror(req
, map_nt_error_from_unix(errno
));
4727 END_PROFILE(SMBlseek
);
4734 reply_outbuf(req
, 2, 0);
4735 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4737 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4738 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4740 END_PROFILE(SMBlseek
);
4744 /****************************************************************************
4746 ****************************************************************************/
4748 void reply_flush(struct smb_request
*req
)
4750 connection_struct
*conn
= req
->conn
;
4754 START_PROFILE(SMBflush
);
4757 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4761 fnum
= SVAL(req
->vwv
+0, 0);
4762 fsp
= file_fsp(req
, fnum
);
4764 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4769 file_sync_all(conn
);
4771 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4772 if (!NT_STATUS_IS_OK(status
)) {
4773 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4774 fsp_str_dbg(fsp
), nt_errstr(status
)));
4775 reply_nterror(req
, status
);
4776 END_PROFILE(SMBflush
);
4781 reply_outbuf(req
, 0, 0);
4783 DEBUG(3,("flush\n"));
4784 END_PROFILE(SMBflush
);
4788 /****************************************************************************
4790 conn POINTER CAN BE NULL HERE !
4791 ****************************************************************************/
4793 void reply_exit(struct smb_request
*req
)
4795 START_PROFILE(SMBexit
);
4797 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
4799 reply_outbuf(req
, 0, 0);
4801 DEBUG(3,("exit\n"));
4803 END_PROFILE(SMBexit
);
4807 /****************************************************************************
4808 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4809 ****************************************************************************/
4811 void reply_close(struct smb_request
*req
)
4813 connection_struct
*conn
= req
->conn
;
4814 NTSTATUS status
= NT_STATUS_OK
;
4815 files_struct
*fsp
= NULL
;
4816 START_PROFILE(SMBclose
);
4819 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4820 END_PROFILE(SMBclose
);
4824 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4827 * We can only use check_fsp if we know it's not a directory.
4830 if (!check_fsp_open(conn
, req
, fsp
)) {
4831 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4832 END_PROFILE(SMBclose
);
4836 if(fsp
->is_directory
) {
4838 * Special case - close NT SMB directory handle.
4840 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4841 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4845 * Close ordinary file.
4848 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4849 fsp
->fh
->fd
, fsp
->fnum
,
4850 conn
->num_files_open
));
4853 * Take care of any time sent in the close.
4856 t
= srv_make_unix_date3(req
->vwv
+1);
4857 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4860 * close_file() returns the unix errno if an error
4861 * was detected on close - normally this is due to
4862 * a disk full error. If not then it was probably an I/O error.
4865 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4868 if (!NT_STATUS_IS_OK(status
)) {
4869 reply_nterror(req
, status
);
4870 END_PROFILE(SMBclose
);
4874 reply_outbuf(req
, 0, 0);
4875 END_PROFILE(SMBclose
);
4879 /****************************************************************************
4880 Reply to a writeclose (Core+ protocol).
4881 ****************************************************************************/
4883 void reply_writeclose(struct smb_request
*req
)
4885 connection_struct
*conn
= req
->conn
;
4887 ssize_t nwritten
= -1;
4888 NTSTATUS close_status
= NT_STATUS_OK
;
4891 struct timespec mtime
;
4893 struct lock_struct lock
;
4895 START_PROFILE(SMBwriteclose
);
4898 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4899 END_PROFILE(SMBwriteclose
);
4903 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4905 if (!check_fsp(conn
, req
, fsp
)) {
4906 END_PROFILE(SMBwriteclose
);
4909 if (!CHECK_WRITE(fsp
)) {
4910 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4911 END_PROFILE(SMBwriteclose
);
4915 numtowrite
= SVAL(req
->vwv
+1, 0);
4916 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4917 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4918 data
= (const char *)req
->buf
+ 1;
4920 if (!fsp
->print_file
) {
4921 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4922 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4925 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4926 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4927 END_PROFILE(SMBwriteclose
);
4932 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4934 set_close_write_time(fsp
, mtime
);
4937 * More insanity. W2K only closes the file if writelen > 0.
4942 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4943 "file %s\n", fsp_str_dbg(fsp
)));
4944 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4947 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4948 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4949 conn
->num_files_open
));
4951 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4952 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4956 if(!NT_STATUS_IS_OK(close_status
)) {
4957 reply_nterror(req
, close_status
);
4961 reply_outbuf(req
, 1, 0);
4963 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4966 if (numtowrite
&& !fsp
->print_file
) {
4967 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4970 END_PROFILE(SMBwriteclose
);
4975 #define DBGC_CLASS DBGC_LOCKING
4977 /****************************************************************************
4979 ****************************************************************************/
4981 void reply_lock(struct smb_request
*req
)
4983 connection_struct
*conn
= req
->conn
;
4984 uint64_t count
,offset
;
4987 struct byte_range_lock
*br_lck
= NULL
;
4989 START_PROFILE(SMBlock
);
4992 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4993 END_PROFILE(SMBlock
);
4997 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4999 if (!check_fsp(conn
, req
, fsp
)) {
5000 END_PROFILE(SMBlock
);
5004 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5005 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5007 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5008 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
5010 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5012 (uint64_t)req
->smbpid
,
5017 False
, /* Non-blocking lock. */
5022 TALLOC_FREE(br_lck
);
5024 if (NT_STATUS_V(status
)) {
5025 reply_nterror(req
, status
);
5026 END_PROFILE(SMBlock
);
5030 reply_outbuf(req
, 0, 0);
5032 END_PROFILE(SMBlock
);
5036 /****************************************************************************
5038 ****************************************************************************/
5040 void reply_unlock(struct smb_request
*req
)
5042 connection_struct
*conn
= req
->conn
;
5043 uint64_t count
,offset
;
5047 START_PROFILE(SMBunlock
);
5050 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5051 END_PROFILE(SMBunlock
);
5055 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5057 if (!check_fsp(conn
, req
, fsp
)) {
5058 END_PROFILE(SMBunlock
);
5062 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5063 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5065 status
= do_unlock(req
->sconn
->msg_ctx
,
5067 (uint64_t)req
->smbpid
,
5072 if (NT_STATUS_V(status
)) {
5073 reply_nterror(req
, status
);
5074 END_PROFILE(SMBunlock
);
5078 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5079 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
5081 reply_outbuf(req
, 0, 0);
5083 END_PROFILE(SMBunlock
);
5088 #define DBGC_CLASS DBGC_ALL
5090 /****************************************************************************
5092 conn POINTER CAN BE NULL HERE !
5093 ****************************************************************************/
5095 void reply_tdis(struct smb_request
*req
)
5097 connection_struct
*conn
= req
->conn
;
5098 START_PROFILE(SMBtdis
);
5101 DEBUG(4,("Invalid connection in tdis\n"));
5102 reply_nterror(req
, NT_STATUS_NETWORK_NAME_DELETED
);
5103 END_PROFILE(SMBtdis
);
5109 close_cnum(conn
,req
->vuid
);
5112 reply_outbuf(req
, 0, 0);
5113 END_PROFILE(SMBtdis
);
5117 /****************************************************************************
5119 conn POINTER CAN BE NULL HERE !
5120 ****************************************************************************/
5122 void reply_echo(struct smb_request
*req
)
5124 connection_struct
*conn
= req
->conn
;
5125 struct smb_perfcount_data local_pcd
;
5126 struct smb_perfcount_data
*cur_pcd
;
5130 START_PROFILE(SMBecho
);
5132 smb_init_perfcount_data(&local_pcd
);
5135 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5136 END_PROFILE(SMBecho
);
5140 smb_reverb
= SVAL(req
->vwv
+0, 0);
5142 reply_outbuf(req
, 1, req
->buflen
);
5144 /* copy any incoming data back out */
5145 if (req
->buflen
> 0) {
5146 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5149 if (smb_reverb
> 100) {
5150 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5154 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5156 /* this makes sure we catch the request pcd */
5157 if (seq_num
== smb_reverb
) {
5158 cur_pcd
= &req
->pcd
;
5160 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5161 cur_pcd
= &local_pcd
;
5164 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5166 show_msg((char *)req
->outbuf
);
5167 if (!srv_send_smb(req
->sconn
,
5168 (char *)req
->outbuf
,
5169 true, req
->seqnum
+1,
5170 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5172 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5175 DEBUG(3,("echo %d times\n", smb_reverb
));
5177 TALLOC_FREE(req
->outbuf
);
5179 END_PROFILE(SMBecho
);
5183 /****************************************************************************
5184 Reply to a printopen.
5185 ****************************************************************************/
5187 void reply_printopen(struct smb_request
*req
)
5189 connection_struct
*conn
= req
->conn
;
5193 START_PROFILE(SMBsplopen
);
5196 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5197 END_PROFILE(SMBsplopen
);
5201 if (!CAN_PRINT(conn
)) {
5202 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5203 END_PROFILE(SMBsplopen
);
5207 status
= file_new(req
, conn
, &fsp
);
5208 if(!NT_STATUS_IS_OK(status
)) {
5209 reply_nterror(req
, status
);
5210 END_PROFILE(SMBsplopen
);
5214 /* Open for exclusive use, write only. */
5215 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5217 if (!NT_STATUS_IS_OK(status
)) {
5218 file_free(req
, fsp
);
5219 reply_nterror(req
, status
);
5220 END_PROFILE(SMBsplopen
);
5224 reply_outbuf(req
, 1, 0);
5225 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5227 DEBUG(3,("openprint fd=%d fnum=%d\n",
5228 fsp
->fh
->fd
, fsp
->fnum
));
5230 END_PROFILE(SMBsplopen
);
5234 /****************************************************************************
5235 Reply to a printclose.
5236 ****************************************************************************/
5238 void reply_printclose(struct smb_request
*req
)
5240 connection_struct
*conn
= req
->conn
;
5244 START_PROFILE(SMBsplclose
);
5247 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5248 END_PROFILE(SMBsplclose
);
5252 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5254 if (!check_fsp(conn
, req
, fsp
)) {
5255 END_PROFILE(SMBsplclose
);
5259 if (!CAN_PRINT(conn
)) {
5260 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5261 END_PROFILE(SMBsplclose
);
5265 DEBUG(3,("printclose fd=%d fnum=%d\n",
5266 fsp
->fh
->fd
,fsp
->fnum
));
5268 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5270 if(!NT_STATUS_IS_OK(status
)) {
5271 reply_nterror(req
, status
);
5272 END_PROFILE(SMBsplclose
);
5276 reply_outbuf(req
, 0, 0);
5278 END_PROFILE(SMBsplclose
);
5282 /****************************************************************************
5283 Reply to a printqueue.
5284 ****************************************************************************/
5286 void reply_printqueue(struct smb_request
*req
)
5288 connection_struct
*conn
= req
->conn
;
5292 START_PROFILE(SMBsplretq
);
5295 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5296 END_PROFILE(SMBsplretq
);
5300 max_count
= SVAL(req
->vwv
+0, 0);
5301 start_index
= SVAL(req
->vwv
+1, 0);
5303 /* we used to allow the client to get the cnum wrong, but that
5304 is really quite gross and only worked when there was only
5305 one printer - I think we should now only accept it if they
5306 get it right (tridge) */
5307 if (!CAN_PRINT(conn
)) {
5308 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5309 END_PROFILE(SMBsplretq
);
5313 reply_outbuf(req
, 2, 3);
5314 SSVAL(req
->outbuf
,smb_vwv0
,0);
5315 SSVAL(req
->outbuf
,smb_vwv1
,0);
5316 SCVAL(smb_buf(req
->outbuf
),0,1);
5317 SSVAL(smb_buf(req
->outbuf
),1,0);
5319 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5320 start_index
, max_count
));
5323 TALLOC_CTX
*mem_ctx
= talloc_tos();
5326 const char *sharename
= lp_servicename(SNUM(conn
));
5327 struct rpc_pipe_client
*cli
= NULL
;
5328 struct dcerpc_binding_handle
*b
= NULL
;
5329 struct policy_handle handle
;
5330 struct spoolss_DevmodeContainer devmode_ctr
;
5331 union spoolss_JobInfo
*info
;
5333 uint32_t num_to_get
;
5337 ZERO_STRUCT(handle
);
5339 status
= rpc_pipe_open_interface(conn
,
5340 &ndr_table_spoolss
.syntax_id
,
5342 &conn
->sconn
->client_id
,
5343 conn
->sconn
->msg_ctx
,
5345 if (!NT_STATUS_IS_OK(status
)) {
5346 DEBUG(0, ("reply_printqueue: "
5347 "could not connect to spoolss: %s\n",
5348 nt_errstr(status
)));
5349 reply_nterror(req
, status
);
5352 b
= cli
->binding_handle
;
5354 ZERO_STRUCT(devmode_ctr
);
5356 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5359 SEC_FLAG_MAXIMUM_ALLOWED
,
5362 if (!NT_STATUS_IS_OK(status
)) {
5363 reply_nterror(req
, status
);
5366 if (!W_ERROR_IS_OK(werr
)) {
5367 reply_nterror(req
, werror_to_ntstatus(werr
));
5371 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5379 if (!W_ERROR_IS_OK(werr
)) {
5380 reply_nterror(req
, werror_to_ntstatus(werr
));
5384 if (max_count
> 0) {
5385 first
= start_index
;
5387 first
= start_index
+ max_count
+ 1;
5390 if (first
>= count
) {
5393 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5396 for (i
= first
; i
< num_to_get
; i
++) {
5399 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5401 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5402 info
[i
].info2
.job_id
);
5404 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5410 srv_put_dos_date2(p
, 0, qtime
);
5411 SCVAL(p
, 4, qstatus
);
5412 SSVAL(p
, 5, qrapjobid
);
5413 SIVAL(p
, 7, info
[i
].info2
.size
);
5415 srvstr_push(blob
, req
->flags2
, p
+12,
5416 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5418 if (message_push_blob(
5421 blob
, sizeof(blob
))) == -1) {
5422 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5428 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5429 SSVAL(req
->outbuf
,smb_vwv1
,
5430 (max_count
>0?first
+count
:first
-1));
5431 SCVAL(smb_buf(req
->outbuf
),0,1);
5432 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5436 DEBUG(3, ("%u entries returned in queue\n",
5440 if (b
&& is_valid_policy_hnd(&handle
)) {
5441 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5446 END_PROFILE(SMBsplretq
);
5450 /****************************************************************************
5451 Reply to a printwrite.
5452 ****************************************************************************/
5454 void reply_printwrite(struct smb_request
*req
)
5456 connection_struct
*conn
= req
->conn
;
5461 START_PROFILE(SMBsplwr
);
5464 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5465 END_PROFILE(SMBsplwr
);
5469 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5471 if (!check_fsp(conn
, req
, fsp
)) {
5472 END_PROFILE(SMBsplwr
);
5476 if (!fsp
->print_file
) {
5477 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5478 END_PROFILE(SMBsplwr
);
5482 if (!CHECK_WRITE(fsp
)) {
5483 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5484 END_PROFILE(SMBsplwr
);
5488 numtowrite
= SVAL(req
->buf
, 1);
5490 if (req
->buflen
< numtowrite
+ 3) {
5491 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5492 END_PROFILE(SMBsplwr
);
5496 data
= (const char *)req
->buf
+ 3;
5498 if (write_file(req
,fsp
,data
,(SMB_OFF_T
)-1,numtowrite
) != numtowrite
) {
5499 reply_nterror(req
, map_nt_error_from_unix(errno
));
5500 END_PROFILE(SMBsplwr
);
5504 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
5506 END_PROFILE(SMBsplwr
);
5510 /****************************************************************************
5512 ****************************************************************************/
5514 void reply_mkdir(struct smb_request
*req
)
5516 connection_struct
*conn
= req
->conn
;
5517 struct smb_filename
*smb_dname
= NULL
;
5518 char *directory
= NULL
;
5520 TALLOC_CTX
*ctx
= talloc_tos();
5522 START_PROFILE(SMBmkdir
);
5524 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5525 STR_TERMINATE
, &status
);
5526 if (!NT_STATUS_IS_OK(status
)) {
5527 reply_nterror(req
, status
);
5531 status
= filename_convert(ctx
, conn
,
5532 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5537 if (!NT_STATUS_IS_OK(status
)) {
5538 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5539 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5540 ERRSRV
, ERRbadpath
);
5543 reply_nterror(req
, status
);
5547 status
= create_directory(conn
, req
, smb_dname
);
5549 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5551 if (!NT_STATUS_IS_OK(status
)) {
5553 if (!use_nt_status()
5554 && NT_STATUS_EQUAL(status
,
5555 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5557 * Yes, in the DOS error code case we get a
5558 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5559 * samba4 torture test.
5561 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5564 reply_nterror(req
, status
);
5568 reply_outbuf(req
, 0, 0);
5570 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5572 TALLOC_FREE(smb_dname
);
5573 END_PROFILE(SMBmkdir
);
5577 /****************************************************************************
5579 ****************************************************************************/
5581 void reply_rmdir(struct smb_request
*req
)
5583 connection_struct
*conn
= req
->conn
;
5584 struct smb_filename
*smb_dname
= NULL
;
5585 char *directory
= NULL
;
5587 TALLOC_CTX
*ctx
= talloc_tos();
5588 files_struct
*fsp
= NULL
;
5590 struct smbd_server_connection
*sconn
= req
->sconn
;
5592 START_PROFILE(SMBrmdir
);
5594 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5595 STR_TERMINATE
, &status
);
5596 if (!NT_STATUS_IS_OK(status
)) {
5597 reply_nterror(req
, status
);
5601 status
= filename_convert(ctx
, conn
,
5602 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5607 if (!NT_STATUS_IS_OK(status
)) {
5608 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5609 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5610 ERRSRV
, ERRbadpath
);
5613 reply_nterror(req
, status
);
5617 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5618 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5622 status
= SMB_VFS_CREATE_FILE(
5625 0, /* root_dir_fid */
5626 smb_dname
, /* fname */
5627 DELETE_ACCESS
, /* access_mask */
5628 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5630 FILE_OPEN
, /* create_disposition*/
5631 FILE_DIRECTORY_FILE
, /* create_options */
5632 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5633 0, /* oplock_request */
5634 0, /* allocation_size */
5635 0, /* private_flags */
5641 if (!NT_STATUS_IS_OK(status
)) {
5642 if (open_was_deferred(req
->mid
)) {
5643 /* We have re-scheduled this call. */
5646 reply_nterror(req
, status
);
5650 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5651 if (!NT_STATUS_IS_OK(status
)) {
5652 close_file(req
, fsp
, ERROR_CLOSE
);
5653 reply_nterror(req
, status
);
5657 if (!set_delete_on_close(fsp
, true, &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 Rename an open file - given an fsp.
5939 ****************************************************************************/
5941 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
5943 const struct smb_filename
*smb_fname_dst_in
,
5945 bool replace_if_exists
)
5947 TALLOC_CTX
*ctx
= talloc_tos();
5948 struct smb_filename
*smb_fname_dst
= NULL
;
5949 NTSTATUS status
= NT_STATUS_OK
;
5950 struct share_mode_lock
*lck
= NULL
;
5951 bool dst_exists
, old_is_stream
, new_is_stream
;
5953 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
5954 if (!NT_STATUS_IS_OK(status
)) {
5958 /* Make a copy of the dst smb_fname structs */
5960 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
5961 if (!NT_STATUS_IS_OK(status
)) {
5966 * Check for special case with case preserving and not
5967 * case sensitive. If the old last component differs from the original
5968 * last component only by case, then we should allow
5969 * the rename (user is trying to change the case of the
5972 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
5973 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
5974 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
5976 char *fname_dst_lcomp_base_mod
= NULL
;
5977 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
5980 * Get the last component of the destination name.
5982 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
5984 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
5986 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
5988 if (!fname_dst_lcomp_base_mod
) {
5989 status
= NT_STATUS_NO_MEMORY
;
5994 * Create an smb_filename struct using the original last
5995 * component of the destination.
5997 status
= create_synthetic_smb_fname_split(ctx
,
5998 smb_fname_dst
->original_lcomp
, NULL
,
5999 &smb_fname_orig_lcomp
);
6000 if (!NT_STATUS_IS_OK(status
)) {
6001 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6005 /* If the base names only differ by case, use original. */
6006 if(!strcsequal(fname_dst_lcomp_base_mod
,
6007 smb_fname_orig_lcomp
->base_name
)) {
6010 * Replace the modified last component with the
6014 *last_slash
= '\0'; /* Truncate at the '/' */
6015 tmp
= talloc_asprintf(smb_fname_dst
,
6017 smb_fname_dst
->base_name
,
6018 smb_fname_orig_lcomp
->base_name
);
6020 tmp
= talloc_asprintf(smb_fname_dst
,
6022 smb_fname_orig_lcomp
->base_name
);
6025 status
= NT_STATUS_NO_MEMORY
;
6026 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6027 TALLOC_FREE(smb_fname_orig_lcomp
);
6030 TALLOC_FREE(smb_fname_dst
->base_name
);
6031 smb_fname_dst
->base_name
= tmp
;
6034 /* If the stream_names only differ by case, use original. */
6035 if(!strcsequal(smb_fname_dst
->stream_name
,
6036 smb_fname_orig_lcomp
->stream_name
)) {
6038 /* Use the original stream. */
6039 tmp
= talloc_strdup(smb_fname_dst
,
6040 smb_fname_orig_lcomp
->stream_name
);
6042 status
= NT_STATUS_NO_MEMORY
;
6043 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6044 TALLOC_FREE(smb_fname_orig_lcomp
);
6047 TALLOC_FREE(smb_fname_dst
->stream_name
);
6048 smb_fname_dst
->stream_name
= tmp
;
6050 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6051 TALLOC_FREE(smb_fname_orig_lcomp
);
6055 * If the src and dest names are identical - including case,
6056 * don't do the rename, just return success.
6059 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6060 strcsequal(fsp
->fsp_name
->stream_name
,
6061 smb_fname_dst
->stream_name
)) {
6062 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6063 "- returning success\n",
6064 smb_fname_str_dbg(smb_fname_dst
)));
6065 status
= NT_STATUS_OK
;
6069 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6070 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6072 /* Return the correct error code if both names aren't streams. */
6073 if (!old_is_stream
&& new_is_stream
) {
6074 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6078 if (old_is_stream
&& !new_is_stream
) {
6079 status
= NT_STATUS_INVALID_PARAMETER
;
6083 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6085 if(!replace_if_exists
&& dst_exists
) {
6086 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6087 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6088 smb_fname_str_dbg(smb_fname_dst
)));
6089 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6094 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6095 &smb_fname_dst
->st
);
6096 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6098 /* The file can be open when renaming a stream */
6099 if (dst_fsp
&& !new_is_stream
) {
6100 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6101 status
= NT_STATUS_ACCESS_DENIED
;
6106 /* Ensure we have a valid stat struct for the source. */
6107 status
= vfs_stat_fsp(fsp
);
6108 if (!NT_STATUS_IS_OK(status
)) {
6112 status
= can_rename(conn
, fsp
, attrs
);
6114 if (!NT_STATUS_IS_OK(status
)) {
6115 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6116 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6117 smb_fname_str_dbg(smb_fname_dst
)));
6118 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6119 status
= NT_STATUS_ACCESS_DENIED
;
6123 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6124 status
= NT_STATUS_ACCESS_DENIED
;
6127 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6131 * We have the file open ourselves, so not being able to get the
6132 * corresponding share mode lock is a fatal error.
6135 SMB_ASSERT(lck
!= NULL
);
6137 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6138 uint32 create_options
= fsp
->fh
->private_options
;
6140 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6141 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6142 smb_fname_str_dbg(smb_fname_dst
)));
6144 if (!lp_posix_pathnames() &&
6145 (lp_map_archive(SNUM(conn
)) ||
6146 lp_store_dos_attributes(SNUM(conn
)))) {
6147 /* We must set the archive bit on the newly
6149 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6150 uint32_t old_dosmode
= dos_mode(conn
,
6152 file_set_dosmode(conn
,
6154 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6160 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6163 rename_open_files(conn
, lck
, fsp
->name_hash
, smb_fname_dst
);
6166 * A rename acts as a new file create w.r.t. allowing an initial delete
6167 * on close, probably because in Windows there is a new handle to the
6168 * new file. If initial delete on close was requested but not
6169 * originally set, we need to set it here. This is probably not 100% correct,
6170 * but will work for the CIFSFS client which in non-posix mode
6171 * depends on these semantics. JRA.
6174 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6175 status
= can_set_delete_on_close(fsp
, 0);
6177 if (NT_STATUS_IS_OK(status
)) {
6178 /* Note that here we set the *inital* delete on close flag,
6179 * not the regular one. The magic gets handled in close. */
6180 fsp
->initial_delete_on_close
= True
;
6184 status
= NT_STATUS_OK
;
6190 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6191 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6193 status
= map_nt_error_from_unix(errno
);
6196 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6197 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6198 smb_fname_str_dbg(smb_fname_dst
)));
6201 TALLOC_FREE(smb_fname_dst
);
6206 /****************************************************************************
6207 The guts of the rename command, split out so it may be called by the NT SMB
6209 ****************************************************************************/
6211 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6212 connection_struct
*conn
,
6213 struct smb_request
*req
,
6214 struct smb_filename
*smb_fname_src
,
6215 struct smb_filename
*smb_fname_dst
,
6217 bool replace_if_exists
,
6220 uint32_t access_mask
)
6222 char *fname_src_dir
= NULL
;
6223 char *fname_src_mask
= NULL
;
6225 NTSTATUS status
= NT_STATUS_OK
;
6226 struct smb_Dir
*dir_hnd
= NULL
;
6227 const char *dname
= NULL
;
6228 char *talloced
= NULL
;
6230 int create_options
= 0;
6231 bool posix_pathnames
= lp_posix_pathnames();
6234 * Split the old name into directory and last component
6235 * strings. Note that unix_convert may have stripped off a
6236 * leading ./ from both name and newname if the rename is
6237 * at the root of the share. We need to make sure either both
6238 * name and newname contain a / character or neither of them do
6239 * as this is checked in resolve_wildcards().
6242 /* Split up the directory from the filename/mask. */
6243 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6244 &fname_src_dir
, &fname_src_mask
);
6245 if (!NT_STATUS_IS_OK(status
)) {
6246 status
= NT_STATUS_NO_MEMORY
;
6251 * We should only check the mangled cache
6252 * here if unix_convert failed. This means
6253 * that the path in 'mask' doesn't exist
6254 * on the file system and so we need to look
6255 * for a possible mangle. This patch from
6256 * Tine Smukavec <valentin.smukavec@hermes.si>.
6259 if (!VALID_STAT(smb_fname_src
->st
) &&
6260 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6261 char *new_mask
= NULL
;
6262 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6265 TALLOC_FREE(fname_src_mask
);
6266 fname_src_mask
= new_mask
;
6270 if (!src_has_wild
) {
6274 * Only one file needs to be renamed. Append the mask back
6275 * onto the directory.
6277 TALLOC_FREE(smb_fname_src
->base_name
);
6278 if (ISDOT(fname_src_dir
)) {
6279 /* Ensure we use canonical names on open. */
6280 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6284 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6289 if (!smb_fname_src
->base_name
) {
6290 status
= NT_STATUS_NO_MEMORY
;
6294 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6295 "case_preserve = %d, short case preserve = %d, "
6296 "directory = %s, newname = %s, "
6297 "last_component_dest = %s\n",
6298 conn
->case_sensitive
, conn
->case_preserve
,
6299 conn
->short_case_preserve
,
6300 smb_fname_str_dbg(smb_fname_src
),
6301 smb_fname_str_dbg(smb_fname_dst
),
6302 smb_fname_dst
->original_lcomp
));
6304 /* The dest name still may have wildcards. */
6305 if (dest_has_wild
) {
6306 char *fname_dst_mod
= NULL
;
6307 if (!resolve_wildcards(smb_fname_dst
,
6308 smb_fname_src
->base_name
,
6309 smb_fname_dst
->base_name
,
6311 DEBUG(6, ("rename_internals: resolve_wildcards "
6313 smb_fname_src
->base_name
,
6314 smb_fname_dst
->base_name
));
6315 status
= NT_STATUS_NO_MEMORY
;
6318 TALLOC_FREE(smb_fname_dst
->base_name
);
6319 smb_fname_dst
->base_name
= fname_dst_mod
;
6322 ZERO_STRUCT(smb_fname_src
->st
);
6323 if (posix_pathnames
) {
6324 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6326 SMB_VFS_STAT(conn
, smb_fname_src
);
6329 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6330 create_options
|= FILE_DIRECTORY_FILE
;
6333 status
= SMB_VFS_CREATE_FILE(
6336 0, /* root_dir_fid */
6337 smb_fname_src
, /* fname */
6338 access_mask
, /* access_mask */
6339 (FILE_SHARE_READ
| /* share_access */
6341 FILE_OPEN
, /* create_disposition*/
6342 create_options
, /* create_options */
6343 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6344 0, /* oplock_request */
6345 0, /* allocation_size */
6346 0, /* private_flags */
6352 if (!NT_STATUS_IS_OK(status
)) {
6353 DEBUG(3, ("Could not open rename source %s: %s\n",
6354 smb_fname_str_dbg(smb_fname_src
),
6355 nt_errstr(status
)));
6359 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6360 attrs
, replace_if_exists
);
6362 close_file(req
, fsp
, NORMAL_CLOSE
);
6364 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6365 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6366 smb_fname_str_dbg(smb_fname_dst
)));
6372 * Wildcards - process each file that matches.
6374 if (strequal(fname_src_mask
, "????????.???")) {
6375 TALLOC_FREE(fname_src_mask
);
6376 fname_src_mask
= talloc_strdup(ctx
, "*");
6377 if (!fname_src_mask
) {
6378 status
= NT_STATUS_NO_MEMORY
;
6383 status
= check_name(conn
, fname_src_dir
);
6384 if (!NT_STATUS_IS_OK(status
)) {
6388 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6390 if (dir_hnd
== NULL
) {
6391 status
= map_nt_error_from_unix(errno
);
6395 status
= NT_STATUS_NO_SUCH_FILE
;
6397 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6398 * - gentest fix. JRA
6401 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6403 files_struct
*fsp
= NULL
;
6404 char *destname
= NULL
;
6405 bool sysdir_entry
= False
;
6407 /* Quick check for "." and ".." */
6408 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6409 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6410 sysdir_entry
= True
;
6412 TALLOC_FREE(talloced
);
6417 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6418 &smb_fname_src
->st
, false)) {
6419 TALLOC_FREE(talloced
);
6423 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6424 TALLOC_FREE(talloced
);
6429 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6433 TALLOC_FREE(smb_fname_src
->base_name
);
6434 if (ISDOT(fname_src_dir
)) {
6435 /* Ensure we use canonical names on open. */
6436 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6440 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6445 if (!smb_fname_src
->base_name
) {
6446 status
= NT_STATUS_NO_MEMORY
;
6450 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6451 smb_fname_dst
->base_name
,
6453 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6454 smb_fname_src
->base_name
, destname
));
6455 TALLOC_FREE(talloced
);
6459 status
= NT_STATUS_NO_MEMORY
;
6463 TALLOC_FREE(smb_fname_dst
->base_name
);
6464 smb_fname_dst
->base_name
= destname
;
6466 ZERO_STRUCT(smb_fname_src
->st
);
6467 if (posix_pathnames
) {
6468 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6470 SMB_VFS_STAT(conn
, smb_fname_src
);
6475 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6476 create_options
|= FILE_DIRECTORY_FILE
;
6479 status
= SMB_VFS_CREATE_FILE(
6482 0, /* root_dir_fid */
6483 smb_fname_src
, /* fname */
6484 access_mask
, /* access_mask */
6485 (FILE_SHARE_READ
| /* share_access */
6487 FILE_OPEN
, /* create_disposition*/
6488 create_options
, /* create_options */
6489 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6490 0, /* oplock_request */
6491 0, /* allocation_size */
6492 0, /* private_flags */
6498 if (!NT_STATUS_IS_OK(status
)) {
6499 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6500 "returned %s rename %s -> %s\n",
6502 smb_fname_str_dbg(smb_fname_src
),
6503 smb_fname_str_dbg(smb_fname_dst
)));
6507 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6509 if (!smb_fname_dst
->original_lcomp
) {
6510 status
= NT_STATUS_NO_MEMORY
;
6514 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6515 attrs
, replace_if_exists
);
6517 close_file(req
, fsp
, NORMAL_CLOSE
);
6519 if (!NT_STATUS_IS_OK(status
)) {
6520 DEBUG(3, ("rename_internals_fsp returned %s for "
6521 "rename %s -> %s\n", nt_errstr(status
),
6522 smb_fname_str_dbg(smb_fname_src
),
6523 smb_fname_str_dbg(smb_fname_dst
)));
6529 DEBUG(3,("rename_internals: doing rename on %s -> "
6530 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6531 smb_fname_str_dbg(smb_fname_src
)));
6532 TALLOC_FREE(talloced
);
6534 TALLOC_FREE(dir_hnd
);
6536 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6537 status
= map_nt_error_from_unix(errno
);
6541 TALLOC_FREE(talloced
);
6542 TALLOC_FREE(fname_src_dir
);
6543 TALLOC_FREE(fname_src_mask
);
6547 /****************************************************************************
6549 ****************************************************************************/
6551 void reply_mv(struct smb_request
*req
)
6553 connection_struct
*conn
= req
->conn
;
6555 char *newname
= NULL
;
6559 bool src_has_wcard
= False
;
6560 bool dest_has_wcard
= False
;
6561 TALLOC_CTX
*ctx
= talloc_tos();
6562 struct smb_filename
*smb_fname_src
= NULL
;
6563 struct smb_filename
*smb_fname_dst
= NULL
;
6564 bool stream_rename
= false;
6566 START_PROFILE(SMBmv
);
6569 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6573 attrs
= SVAL(req
->vwv
+0, 0);
6575 p
= (const char *)req
->buf
+ 1;
6576 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6577 &status
, &src_has_wcard
);
6578 if (!NT_STATUS_IS_OK(status
)) {
6579 reply_nterror(req
, status
);
6583 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6584 &status
, &dest_has_wcard
);
6585 if (!NT_STATUS_IS_OK(status
)) {
6586 reply_nterror(req
, status
);
6590 if (!lp_posix_pathnames()) {
6591 /* The newname must begin with a ':' if the
6592 name contains a ':'. */
6593 if (strchr_m(name
, ':')) {
6594 if (newname
[0] != ':') {
6595 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6598 stream_rename
= true;
6602 status
= filename_convert(ctx
,
6604 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6606 UCF_COND_ALLOW_WCARD_LCOMP
,
6610 if (!NT_STATUS_IS_OK(status
)) {
6611 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6612 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6613 ERRSRV
, ERRbadpath
);
6616 reply_nterror(req
, status
);
6620 status
= filename_convert(ctx
,
6622 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6624 UCF_COND_ALLOW_WCARD_LCOMP
| UCF_SAVE_LCOMP
,
6628 if (!NT_STATUS_IS_OK(status
)) {
6629 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6630 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6631 ERRSRV
, ERRbadpath
);
6634 reply_nterror(req
, status
);
6638 if (stream_rename
) {
6639 /* smb_fname_dst->base_name must be the same as
6640 smb_fname_src->base_name. */
6641 TALLOC_FREE(smb_fname_dst
->base_name
);
6642 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6643 smb_fname_src
->base_name
);
6644 if (!smb_fname_dst
->base_name
) {
6645 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6650 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6651 smb_fname_str_dbg(smb_fname_dst
)));
6653 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
6654 attrs
, False
, src_has_wcard
, dest_has_wcard
,
6656 if (!NT_STATUS_IS_OK(status
)) {
6657 if (open_was_deferred(req
->mid
)) {
6658 /* We have re-scheduled this call. */
6661 reply_nterror(req
, status
);
6665 reply_outbuf(req
, 0, 0);
6667 TALLOC_FREE(smb_fname_src
);
6668 TALLOC_FREE(smb_fname_dst
);
6673 /*******************************************************************
6674 Copy a file as part of a reply_copy.
6675 ******************************************************************/
6678 * TODO: check error codes on all callers
6681 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6682 connection_struct
*conn
,
6683 struct smb_filename
*smb_fname_src
,
6684 struct smb_filename
*smb_fname_dst
,
6687 bool target_is_directory
)
6689 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
6691 files_struct
*fsp1
,*fsp2
;
6693 uint32 new_create_disposition
;
6697 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
6698 if (!NT_STATUS_IS_OK(status
)) {
6703 * If the target is a directory, extract the last component from the
6704 * src filename and append it to the dst filename
6706 if (target_is_directory
) {
6709 /* dest/target can't be a stream if it's a directory. */
6710 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
6712 p
= strrchr_m(smb_fname_src
->base_name
,'/');
6716 p
= smb_fname_src
->base_name
;
6718 smb_fname_dst_tmp
->base_name
=
6719 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
6721 if (!smb_fname_dst_tmp
->base_name
) {
6722 status
= NT_STATUS_NO_MEMORY
;
6727 status
= vfs_file_exist(conn
, smb_fname_src
);
6728 if (!NT_STATUS_IS_OK(status
)) {
6732 if (!target_is_directory
&& count
) {
6733 new_create_disposition
= FILE_OPEN
;
6735 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
, 0, ofun
,
6737 &new_create_disposition
,
6740 status
= NT_STATUS_INVALID_PARAMETER
;
6745 /* Open the src file for reading. */
6746 status
= SMB_VFS_CREATE_FILE(
6749 0, /* root_dir_fid */
6750 smb_fname_src
, /* fname */
6751 FILE_GENERIC_READ
, /* access_mask */
6752 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6753 FILE_OPEN
, /* create_disposition*/
6754 0, /* create_options */
6755 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6756 INTERNAL_OPEN_ONLY
, /* oplock_request */
6757 0, /* allocation_size */
6758 0, /* private_flags */
6764 if (!NT_STATUS_IS_OK(status
)) {
6768 dosattrs
= dos_mode(conn
, smb_fname_src
);
6770 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
6771 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
6774 /* Open the dst file for writing. */
6775 status
= SMB_VFS_CREATE_FILE(
6778 0, /* root_dir_fid */
6779 smb_fname_dst
, /* fname */
6780 FILE_GENERIC_WRITE
, /* access_mask */
6781 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6782 new_create_disposition
, /* create_disposition*/
6783 0, /* create_options */
6784 dosattrs
, /* file_attributes */
6785 INTERNAL_OPEN_ONLY
, /* oplock_request */
6786 0, /* allocation_size */
6787 0, /* private_flags */
6793 if (!NT_STATUS_IS_OK(status
)) {
6794 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6798 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
6799 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
6801 DEBUG(0, ("error - vfs lseek returned error %s\n",
6803 status
= map_nt_error_from_unix(errno
);
6804 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6805 close_file(NULL
, fsp2
, ERROR_CLOSE
);
6810 /* Do the actual copy. */
6811 if (smb_fname_src
->st
.st_ex_size
) {
6812 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
6817 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
6819 /* Ensure the modtime is set correctly on the destination file. */
6820 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
6823 * As we are opening fsp1 read-only we only expect
6824 * an error on close on fsp2 if we are out of space.
6825 * Thus we don't look at the error return from the
6828 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
6830 if (!NT_STATUS_IS_OK(status
)) {
6834 if (ret
!= (SMB_OFF_T
)smb_fname_src
->st
.st_ex_size
) {
6835 status
= NT_STATUS_DISK_FULL
;
6839 status
= NT_STATUS_OK
;
6842 TALLOC_FREE(smb_fname_dst_tmp
);
6846 /****************************************************************************
6847 Reply to a file copy.
6848 ****************************************************************************/
6850 void reply_copy(struct smb_request
*req
)
6852 connection_struct
*conn
= req
->conn
;
6853 struct smb_filename
*smb_fname_src
= NULL
;
6854 struct smb_filename
*smb_fname_dst
= NULL
;
6855 char *fname_src
= NULL
;
6856 char *fname_dst
= NULL
;
6857 char *fname_src_mask
= NULL
;
6858 char *fname_src_dir
= NULL
;
6861 int error
= ERRnoaccess
;
6865 bool target_is_directory
=False
;
6866 bool source_has_wild
= False
;
6867 bool dest_has_wild
= False
;
6869 TALLOC_CTX
*ctx
= talloc_tos();
6871 START_PROFILE(SMBcopy
);
6874 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6878 tid2
= SVAL(req
->vwv
+0, 0);
6879 ofun
= SVAL(req
->vwv
+1, 0);
6880 flags
= SVAL(req
->vwv
+2, 0);
6882 p
= (const char *)req
->buf
;
6883 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
6884 &status
, &source_has_wild
);
6885 if (!NT_STATUS_IS_OK(status
)) {
6886 reply_nterror(req
, status
);
6889 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
6890 &status
, &dest_has_wild
);
6891 if (!NT_STATUS_IS_OK(status
)) {
6892 reply_nterror(req
, status
);
6896 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
6898 if (tid2
!= conn
->cnum
) {
6899 /* can't currently handle inter share copies XXXX */
6900 DEBUG(3,("Rejecting inter-share copy\n"));
6901 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
6905 status
= filename_convert(ctx
, conn
,
6906 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6908 UCF_COND_ALLOW_WCARD_LCOMP
,
6911 if (!NT_STATUS_IS_OK(status
)) {
6912 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6913 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6914 ERRSRV
, ERRbadpath
);
6917 reply_nterror(req
, status
);
6921 status
= filename_convert(ctx
, conn
,
6922 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6924 UCF_COND_ALLOW_WCARD_LCOMP
,
6927 if (!NT_STATUS_IS_OK(status
)) {
6928 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6929 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6930 ERRSRV
, ERRbadpath
);
6933 reply_nterror(req
, status
);
6937 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
6939 if ((flags
&1) && target_is_directory
) {
6940 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
6944 if ((flags
&2) && !target_is_directory
) {
6945 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
6949 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
6950 /* wants a tree copy! XXXX */
6951 DEBUG(3,("Rejecting tree copy\n"));
6952 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6956 /* Split up the directory from the filename/mask. */
6957 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6958 &fname_src_dir
, &fname_src_mask
);
6959 if (!NT_STATUS_IS_OK(status
)) {
6960 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6965 * We should only check the mangled cache
6966 * here if unix_convert failed. This means
6967 * that the path in 'mask' doesn't exist
6968 * on the file system and so we need to look
6969 * for a possible mangle. This patch from
6970 * Tine Smukavec <valentin.smukavec@hermes.si>.
6972 if (!VALID_STAT(smb_fname_src
->st
) &&
6973 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6974 char *new_mask
= NULL
;
6975 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
6976 &new_mask
, conn
->params
);
6978 /* Use demangled name if one was successfully found. */
6980 TALLOC_FREE(fname_src_mask
);
6981 fname_src_mask
= new_mask
;
6985 if (!source_has_wild
) {
6988 * Only one file needs to be copied. Append the mask back onto
6991 TALLOC_FREE(smb_fname_src
->base_name
);
6992 if (ISDOT(fname_src_dir
)) {
6993 /* Ensure we use canonical names on open. */
6994 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6998 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7003 if (!smb_fname_src
->base_name
) {
7004 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7008 if (dest_has_wild
) {
7009 char *fname_dst_mod
= NULL
;
7010 if (!resolve_wildcards(smb_fname_dst
,
7011 smb_fname_src
->base_name
,
7012 smb_fname_dst
->base_name
,
7014 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7017 TALLOC_FREE(smb_fname_dst
->base_name
);
7018 smb_fname_dst
->base_name
= fname_dst_mod
;
7021 status
= check_name(conn
, smb_fname_src
->base_name
);
7022 if (!NT_STATUS_IS_OK(status
)) {
7023 reply_nterror(req
, status
);
7027 status
= check_name(conn
, smb_fname_dst
->base_name
);
7028 if (!NT_STATUS_IS_OK(status
)) {
7029 reply_nterror(req
, status
);
7033 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7034 ofun
, count
, target_is_directory
);
7036 if(!NT_STATUS_IS_OK(status
)) {
7037 reply_nterror(req
, status
);
7043 struct smb_Dir
*dir_hnd
= NULL
;
7044 const char *dname
= NULL
;
7045 char *talloced
= NULL
;
7049 * There is a wildcard that requires us to actually read the
7050 * src dir and copy each file matching the mask to the dst.
7051 * Right now streams won't be copied, but this could
7052 * presumably be added with a nested loop for reach dir entry.
7054 SMB_ASSERT(!smb_fname_src
->stream_name
);
7055 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7057 smb_fname_src
->stream_name
= NULL
;
7058 smb_fname_dst
->stream_name
= NULL
;
7060 if (strequal(fname_src_mask
,"????????.???")) {
7061 TALLOC_FREE(fname_src_mask
);
7062 fname_src_mask
= talloc_strdup(ctx
, "*");
7063 if (!fname_src_mask
) {
7064 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7069 status
= check_name(conn
, fname_src_dir
);
7070 if (!NT_STATUS_IS_OK(status
)) {
7071 reply_nterror(req
, status
);
7075 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7076 if (dir_hnd
== NULL
) {
7077 status
= map_nt_error_from_unix(errno
);
7078 reply_nterror(req
, status
);
7084 /* Iterate over the src dir copying each entry to the dst. */
7085 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7086 &smb_fname_src
->st
, &talloced
))) {
7087 char *destname
= NULL
;
7089 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7090 TALLOC_FREE(talloced
);
7094 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7095 &smb_fname_src
->st
, false)) {
7096 TALLOC_FREE(talloced
);
7100 if(!mask_match(dname
, fname_src_mask
,
7101 conn
->case_sensitive
)) {
7102 TALLOC_FREE(talloced
);
7106 error
= ERRnoaccess
;
7108 /* Get the src smb_fname struct setup. */
7109 TALLOC_FREE(smb_fname_src
->base_name
);
7110 if (ISDOT(fname_src_dir
)) {
7111 /* Ensure we use canonical names on open. */
7112 smb_fname_src
->base_name
=
7113 talloc_asprintf(smb_fname_src
, "%s",
7116 smb_fname_src
->base_name
=
7117 talloc_asprintf(smb_fname_src
, "%s/%s",
7118 fname_src_dir
, dname
);
7121 if (!smb_fname_src
->base_name
) {
7122 TALLOC_FREE(dir_hnd
);
7123 TALLOC_FREE(talloced
);
7124 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7128 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7129 smb_fname_dst
->base_name
,
7131 TALLOC_FREE(talloced
);
7135 TALLOC_FREE(dir_hnd
);
7136 TALLOC_FREE(talloced
);
7137 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7141 TALLOC_FREE(smb_fname_dst
->base_name
);
7142 smb_fname_dst
->base_name
= destname
;
7144 status
= check_name(conn
, smb_fname_src
->base_name
);
7145 if (!NT_STATUS_IS_OK(status
)) {
7146 TALLOC_FREE(dir_hnd
);
7147 TALLOC_FREE(talloced
);
7148 reply_nterror(req
, status
);
7152 status
= check_name(conn
, smb_fname_dst
->base_name
);
7153 if (!NT_STATUS_IS_OK(status
)) {
7154 TALLOC_FREE(dir_hnd
);
7155 TALLOC_FREE(talloced
);
7156 reply_nterror(req
, status
);
7160 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7161 smb_fname_src
->base_name
,
7162 smb_fname_dst
->base_name
));
7164 status
= copy_file(ctx
, conn
, smb_fname_src
,
7165 smb_fname_dst
, ofun
, count
,
7166 target_is_directory
);
7167 if (NT_STATUS_IS_OK(status
)) {
7171 TALLOC_FREE(talloced
);
7173 TALLOC_FREE(dir_hnd
);
7177 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7181 reply_outbuf(req
, 1, 0);
7182 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7184 TALLOC_FREE(smb_fname_src
);
7185 TALLOC_FREE(smb_fname_dst
);
7186 TALLOC_FREE(fname_src
);
7187 TALLOC_FREE(fname_dst
);
7188 TALLOC_FREE(fname_src_mask
);
7189 TALLOC_FREE(fname_src_dir
);
7191 END_PROFILE(SMBcopy
);
7196 #define DBGC_CLASS DBGC_LOCKING
7198 /****************************************************************************
7199 Get a lock pid, dealing with large count requests.
7200 ****************************************************************************/
7202 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7203 bool large_file_format
)
7205 if(!large_file_format
)
7206 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7208 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7211 /****************************************************************************
7212 Get a lock count, dealing with large count requests.
7213 ****************************************************************************/
7215 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7216 bool large_file_format
)
7220 if(!large_file_format
) {
7221 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7224 #if defined(HAVE_LONGLONG)
7225 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7226 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7227 #else /* HAVE_LONGLONG */
7230 * NT4.x seems to be broken in that it sends large file (64 bit)
7231 * lockingX calls even if the CAP_LARGE_FILES was *not*
7232 * negotiated. For boxes without large unsigned ints truncate the
7233 * lock count by dropping the top 32 bits.
7236 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7237 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7238 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7239 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7240 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7243 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7244 #endif /* HAVE_LONGLONG */
7250 #if !defined(HAVE_LONGLONG)
7251 /****************************************************************************
7252 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7253 ****************************************************************************/
7255 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7259 uint32 highcopy
= high
;
7262 * Try and find out how many significant bits there are in high.
7265 for(i
= 0; highcopy
; i
++)
7269 * We use 31 bits not 32 here as POSIX
7270 * lock offsets may not be negative.
7273 mask
= (~0) << (31 - i
);
7276 return 0; /* Fail. */
7282 #endif /* !defined(HAVE_LONGLONG) */
7284 /****************************************************************************
7285 Get a lock offset, dealing with large offset requests.
7286 ****************************************************************************/
7288 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7289 bool large_file_format
, bool *err
)
7291 uint64_t offset
= 0;
7295 if(!large_file_format
) {
7296 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7299 #if defined(HAVE_LONGLONG)
7300 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7301 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7302 #else /* HAVE_LONGLONG */
7305 * NT4.x seems to be broken in that it sends large file (64 bit)
7306 * lockingX calls even if the CAP_LARGE_FILES was *not*
7307 * negotiated. For boxes without large unsigned ints mangle the
7308 * lock offset by mapping the top 32 bits onto the lower 32.
7311 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7312 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7313 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7316 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7318 return (uint64_t)-1;
7321 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7322 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7323 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7324 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7327 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7328 #endif /* HAVE_LONGLONG */
7334 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7338 uint16_t num_ulocks
,
7339 struct smbd_lock_element
*ulocks
,
7341 struct smbd_lock_element
*locks
,
7344 connection_struct
*conn
= req
->conn
;
7346 NTSTATUS status
= NT_STATUS_OK
;
7350 /* Data now points at the beginning of the list
7351 of smb_unlkrng structs */
7352 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7353 struct smbd_lock_element
*e
= &ulocks
[i
];
7355 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7356 "pid %u, file %s\n",
7359 (unsigned int)e
->smblctx
,
7362 if (e
->brltype
!= UNLOCK_LOCK
) {
7363 /* this can only happen with SMB2 */
7364 return NT_STATUS_INVALID_PARAMETER
;
7367 status
= do_unlock(req
->sconn
->msg_ctx
,
7374 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7375 nt_errstr(status
)));
7377 if (!NT_STATUS_IS_OK(status
)) {
7382 /* Setup the timeout in seconds. */
7384 if (!lp_blocking_locks(SNUM(conn
))) {
7388 /* Data now points at the beginning of the list
7389 of smb_lkrng structs */
7391 for(i
= 0; i
< (int)num_locks
; i
++) {
7392 struct smbd_lock_element
*e
= &locks
[i
];
7394 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7395 "%llu, file %s timeout = %d\n",
7398 (unsigned long long)e
->smblctx
,
7402 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7403 struct blocking_lock_record
*blr
= NULL
;
7405 if (num_locks
> 1) {
7407 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7408 * if the lock vector contains one entry. When given mutliple cancel
7409 * requests in a single PDU we expect the server to return an
7410 * error. Windows servers seem to accept the request but only
7411 * cancel the first lock.
7412 * JRA - Do what Windows does (tm) :-).
7416 /* MS-CIFS (2.2.4.32.1) behavior. */
7417 return NT_STATUS_DOS(ERRDOS
,
7418 ERRcancelviolation
);
7420 /* Windows behavior. */
7422 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7423 "cancel request\n"));
7429 if (lp_blocking_locks(SNUM(conn
))) {
7431 /* Schedule a message to ourselves to
7432 remove the blocking lock record and
7433 return the right error. */
7435 blr
= blocking_lock_cancel_smb1(fsp
,
7441 NT_STATUS_FILE_LOCK_CONFLICT
);
7443 return NT_STATUS_DOS(
7445 ERRcancelviolation
);
7448 /* Remove a matching pending lock. */
7449 status
= do_lock_cancel(fsp
,
7456 bool blocking_lock
= timeout
? true : false;
7457 bool defer_lock
= false;
7458 struct byte_range_lock
*br_lck
;
7459 uint64_t block_smblctx
;
7461 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7473 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7474 /* Windows internal resolution for blocking locks seems
7475 to be about 200ms... Don't wait for less than that. JRA. */
7476 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7477 timeout
= lp_lock_spin_time();
7482 /* If a lock sent with timeout of zero would fail, and
7483 * this lock has been requested multiple times,
7484 * according to brl_lock_failed() we convert this
7485 * request to a blocking lock with a timeout of between
7486 * 150 - 300 milliseconds.
7488 * If lp_lock_spin_time() has been set to 0, we skip
7489 * this blocking retry and fail immediately.
7491 * Replacement for do_lock_spin(). JRA. */
7493 if (!req
->sconn
->using_smb2
&&
7494 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7495 lp_lock_spin_time() && !blocking_lock
&&
7496 NT_STATUS_EQUAL((status
),
7497 NT_STATUS_FILE_LOCK_CONFLICT
))
7500 timeout
= lp_lock_spin_time();
7503 if (br_lck
&& defer_lock
) {
7505 * A blocking lock was requested. Package up
7506 * this smb into a queued request and push it
7507 * onto the blocking lock queue.
7509 if(push_blocking_lock_request(br_lck
,
7520 TALLOC_FREE(br_lck
);
7522 return NT_STATUS_OK
;
7526 TALLOC_FREE(br_lck
);
7529 if (!NT_STATUS_IS_OK(status
)) {
7534 /* If any of the above locks failed, then we must unlock
7535 all of the previous locks (X/Open spec). */
7537 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7539 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7540 i
= -1; /* we want to skip the for loop */
7544 * Ensure we don't do a remove on the lock that just failed,
7545 * as under POSIX rules, if we have a lock already there, we
7546 * will delete it (and we shouldn't) .....
7548 for(i
--; i
>= 0; i
--) {
7549 struct smbd_lock_element
*e
= &locks
[i
];
7551 do_unlock(req
->sconn
->msg_ctx
,
7561 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7562 fsp
->fnum
, (unsigned int)type
, num_locks
, num_ulocks
));
7564 return NT_STATUS_OK
;
7567 /****************************************************************************
7568 Reply to a lockingX request.
7569 ****************************************************************************/
7571 void reply_lockingX(struct smb_request
*req
)
7573 connection_struct
*conn
= req
->conn
;
7575 unsigned char locktype
;
7576 unsigned char oplocklevel
;
7581 const uint8_t *data
;
7582 bool large_file_format
;
7584 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7585 struct smbd_lock_element
*ulocks
;
7586 struct smbd_lock_element
*locks
;
7589 START_PROFILE(SMBlockingX
);
7592 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7593 END_PROFILE(SMBlockingX
);
7597 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7598 locktype
= CVAL(req
->vwv
+3, 0);
7599 oplocklevel
= CVAL(req
->vwv
+3, 1);
7600 num_ulocks
= SVAL(req
->vwv
+6, 0);
7601 num_locks
= SVAL(req
->vwv
+7, 0);
7602 lock_timeout
= IVAL(req
->vwv
+4, 0);
7603 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7605 if (!check_fsp(conn
, req
, fsp
)) {
7606 END_PROFILE(SMBlockingX
);
7612 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7613 /* we don't support these - and CANCEL_LOCK makes w2k
7614 and XP reboot so I don't really want to be
7615 compatible! (tridge) */
7616 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7617 END_PROFILE(SMBlockingX
);
7621 /* Check if this is an oplock break on a file
7622 we have granted an oplock on.
7624 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7625 /* Client can insist on breaking to none. */
7626 bool break_to_none
= (oplocklevel
== 0);
7629 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7630 "for fnum = %d\n", (unsigned int)oplocklevel
,
7634 * Make sure we have granted an exclusive or batch oplock on
7638 if (fsp
->oplock_type
== 0) {
7640 /* The Samba4 nbench simulator doesn't understand
7641 the difference between break to level2 and break
7642 to none from level2 - it sends oplock break
7643 replies in both cases. Don't keep logging an error
7644 message here - just ignore it. JRA. */
7646 DEBUG(5,("reply_lockingX: Error : oplock break from "
7647 "client for fnum = %d (oplock=%d) and no "
7648 "oplock granted on this file (%s).\n",
7649 fsp
->fnum
, fsp
->oplock_type
,
7652 /* if this is a pure oplock break request then don't
7654 if (num_locks
== 0 && num_ulocks
== 0) {
7655 END_PROFILE(SMBlockingX
);
7658 END_PROFILE(SMBlockingX
);
7659 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
7664 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7666 result
= remove_oplock(fsp
);
7668 result
= downgrade_oplock(fsp
);
7672 DEBUG(0, ("reply_lockingX: error in removing "
7673 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7674 /* Hmmm. Is this panic justified? */
7675 smb_panic("internal tdb error");
7678 reply_to_oplock_break_requests(fsp
);
7680 /* if this is a pure oplock break request then don't send a
7682 if (num_locks
== 0 && num_ulocks
== 0) {
7683 /* Sanity check - ensure a pure oplock break is not a
7685 if(CVAL(req
->vwv
+0, 0) != 0xff)
7686 DEBUG(0,("reply_lockingX: Error : pure oplock "
7687 "break is a chained %d request !\n",
7688 (unsigned int)CVAL(req
->vwv
+0, 0)));
7689 END_PROFILE(SMBlockingX
);
7695 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7696 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7697 END_PROFILE(SMBlockingX
);
7701 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
7702 if (ulocks
== NULL
) {
7703 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7704 END_PROFILE(SMBlockingX
);
7708 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
7709 if (locks
== NULL
) {
7710 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7711 END_PROFILE(SMBlockingX
);
7715 /* Data now points at the beginning of the list
7716 of smb_unlkrng structs */
7717 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7718 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7719 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7720 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7721 ulocks
[i
].brltype
= UNLOCK_LOCK
;
7724 * There is no error code marked "stupid client bug".... :-).
7727 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7728 END_PROFILE(SMBlockingX
);
7733 /* Now do any requested locks */
7734 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
7736 /* Data now points at the beginning of the list
7737 of smb_lkrng structs */
7739 for(i
= 0; i
< (int)num_locks
; i
++) {
7740 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7741 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7742 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7744 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
7745 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7746 locks
[i
].brltype
= PENDING_READ_LOCK
;
7748 locks
[i
].brltype
= READ_LOCK
;
7751 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7752 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
7754 locks
[i
].brltype
= WRITE_LOCK
;
7759 * There is no error code marked "stupid client bug".... :-).
7762 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7763 END_PROFILE(SMBlockingX
);
7768 status
= smbd_do_locking(req
, fsp
,
7769 locktype
, lock_timeout
,
7773 if (!NT_STATUS_IS_OK(status
)) {
7774 END_PROFILE(SMBlockingX
);
7775 reply_nterror(req
, status
);
7779 END_PROFILE(SMBlockingX
);
7783 reply_outbuf(req
, 2, 0);
7785 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7786 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7788 END_PROFILE(SMBlockingX
);
7793 #define DBGC_CLASS DBGC_ALL
7795 /****************************************************************************
7796 Reply to a SMBreadbmpx (read block multiplex) request.
7797 Always reply with an error, if someone has a platform really needs this,
7798 please contact vl@samba.org
7799 ****************************************************************************/
7801 void reply_readbmpx(struct smb_request
*req
)
7803 START_PROFILE(SMBreadBmpx
);
7804 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7805 END_PROFILE(SMBreadBmpx
);
7809 /****************************************************************************
7810 Reply to a SMBreadbs (read block multiplex secondary) request.
7811 Always reply with an error, if someone has a platform really needs this,
7812 please contact vl@samba.org
7813 ****************************************************************************/
7815 void reply_readbs(struct smb_request
*req
)
7817 START_PROFILE(SMBreadBs
);
7818 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7819 END_PROFILE(SMBreadBs
);
7823 /****************************************************************************
7824 Reply to a SMBsetattrE.
7825 ****************************************************************************/
7827 void reply_setattrE(struct smb_request
*req
)
7829 connection_struct
*conn
= req
->conn
;
7830 struct smb_file_time ft
;
7834 START_PROFILE(SMBsetattrE
);
7838 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7842 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7844 if(!fsp
|| (fsp
->conn
!= conn
)) {
7845 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7850 * Convert the DOS times into unix times.
7853 ft
.atime
= convert_time_t_to_timespec(
7854 srv_make_unix_date2(req
->vwv
+3));
7855 ft
.mtime
= convert_time_t_to_timespec(
7856 srv_make_unix_date2(req
->vwv
+5));
7857 ft
.create_time
= convert_time_t_to_timespec(
7858 srv_make_unix_date2(req
->vwv
+1));
7860 reply_outbuf(req
, 0, 0);
7863 * Patch from Ray Frush <frush@engr.colostate.edu>
7864 * Sometimes times are sent as zero - ignore them.
7867 /* Ensure we have a valid stat struct for the source. */
7868 status
= vfs_stat_fsp(fsp
);
7869 if (!NT_STATUS_IS_OK(status
)) {
7870 reply_nterror(req
, status
);
7874 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
7875 if (!NT_STATUS_IS_OK(status
)) {
7876 reply_nterror(req
, status
);
7880 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7883 (unsigned int)ft
.atime
.tv_sec
,
7884 (unsigned int)ft
.mtime
.tv_sec
,
7885 (unsigned int)ft
.create_time
.tv_sec
7888 END_PROFILE(SMBsetattrE
);
7893 /* Back from the dead for OS/2..... JRA. */
7895 /****************************************************************************
7896 Reply to a SMBwritebmpx (write block multiplex primary) request.
7897 Always reply with an error, if someone has a platform really needs this,
7898 please contact vl@samba.org
7899 ****************************************************************************/
7901 void reply_writebmpx(struct smb_request
*req
)
7903 START_PROFILE(SMBwriteBmpx
);
7904 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7905 END_PROFILE(SMBwriteBmpx
);
7909 /****************************************************************************
7910 Reply to a SMBwritebs (write block multiplex secondary) request.
7911 Always reply with an error, if someone has a platform really needs this,
7912 please contact vl@samba.org
7913 ****************************************************************************/
7915 void reply_writebs(struct smb_request
*req
)
7917 START_PROFILE(SMBwriteBs
);
7918 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7919 END_PROFILE(SMBwriteBs
);
7923 /****************************************************************************
7924 Reply to a SMBgetattrE.
7925 ****************************************************************************/
7927 void reply_getattrE(struct smb_request
*req
)
7929 connection_struct
*conn
= req
->conn
;
7932 struct timespec create_ts
;
7934 START_PROFILE(SMBgetattrE
);
7937 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7938 END_PROFILE(SMBgetattrE
);
7942 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7944 if(!fsp
|| (fsp
->conn
!= conn
)) {
7945 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7946 END_PROFILE(SMBgetattrE
);
7950 /* Do an fstat on this file */
7952 reply_nterror(req
, map_nt_error_from_unix(errno
));
7953 END_PROFILE(SMBgetattrE
);
7957 mode
= dos_mode(conn
, fsp
->fsp_name
);
7960 * Convert the times into dos times. Set create
7961 * date to be last modify date as UNIX doesn't save
7965 reply_outbuf(req
, 11, 0);
7967 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
7968 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
7969 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
7970 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
7971 /* Should we check pending modtime here ? JRA */
7972 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
7973 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
7975 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
7976 SIVAL(req
->outbuf
, smb_vwv6
, 0);
7977 SIVAL(req
->outbuf
, smb_vwv8
, 0);
7979 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
7980 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
7981 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
7983 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
7985 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
7987 END_PROFILE(SMBgetattrE
);