2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
45 /****************************************************************************
46 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
47 path or anything including wildcards.
48 We're assuming here that '/' is not the second byte in any multibyte char
49 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
51 ****************************************************************************/
53 /* Custom version for processing POSIX paths. */
54 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
56 static NTSTATUS
check_path_syntax_internal(char *path
,
58 bool *p_last_component_contains_wcard
)
62 NTSTATUS ret
= NT_STATUS_OK
;
63 bool start_of_name_component
= True
;
64 bool stream_started
= false;
66 *p_last_component_contains_wcard
= False
;
73 return NT_STATUS_OBJECT_NAME_INVALID
;
76 return NT_STATUS_OBJECT_NAME_INVALID
;
78 if (strchr_m(&s
[1], ':')) {
79 return NT_STATUS_OBJECT_NAME_INVALID
;
85 if ((*s
== ':') && !posix_path
&& !stream_started
) {
86 if (*p_last_component_contains_wcard
) {
87 return NT_STATUS_OBJECT_NAME_INVALID
;
89 /* Stream names allow more characters than file names.
90 We're overloading posix_path here to allow a wider
91 range of characters. If stream_started is true this
92 is still a Windows path even if posix_path is true.
95 stream_started
= true;
96 start_of_name_component
= false;
100 return NT_STATUS_OBJECT_NAME_INVALID
;
104 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
106 * Safe to assume is not the second part of a mb char
107 * as this is handled below.
109 /* Eat multiple '/' or '\\' */
110 while (IS_PATH_SEP(*s
,posix_path
)) {
113 if ((d
!= path
) && (*s
!= '\0')) {
114 /* We only care about non-leading or trailing '/' or '\\' */
118 start_of_name_component
= True
;
120 *p_last_component_contains_wcard
= False
;
124 if (start_of_name_component
) {
125 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
126 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
129 * No mb char starts with '.' so we're safe checking the directory separator here.
132 /* If we just added a '/' - delete it */
133 if ((d
> path
) && (*(d
-1) == '/')) {
138 /* Are we at the start ? Can't go back further if so. */
140 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
143 /* Go back one level... */
144 /* We know this is safe as '/' cannot be part of a mb sequence. */
145 /* NOTE - if this assumption is invalid we are not in good shape... */
146 /* Decrement d first as d points to the *next* char to write into. */
147 for (d
--; d
> path
; d
--) {
151 s
+= 2; /* Else go past the .. */
152 /* We're still at the start of a name component, just the previous one. */
155 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
167 if (*s
<= 0x1f || *s
== '|') {
168 return NT_STATUS_OBJECT_NAME_INVALID
;
176 *p_last_component_contains_wcard
= True
;
185 /* Get the size of the next MB character. */
186 next_codepoint(s
,&siz
);
204 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
206 return NT_STATUS_INVALID_PARAMETER
;
209 start_of_name_component
= False
;
217 /****************************************************************************
218 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219 No wildcards allowed.
220 ****************************************************************************/
222 NTSTATUS
check_path_syntax(char *path
)
225 return check_path_syntax_internal(path
, False
, &ignore
);
228 /****************************************************************************
229 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
230 Wildcards allowed - p_contains_wcard returns true if the last component contained
232 ****************************************************************************/
234 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
236 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
239 /****************************************************************************
240 Check the path for a POSIX client.
241 We're assuming here that '/' is not the second byte in any multibyte char
242 set (a safe assumption).
243 ****************************************************************************/
245 NTSTATUS
check_path_syntax_posix(char *path
)
248 return check_path_syntax_internal(path
, True
, &ignore
);
251 /****************************************************************************
252 Pull a string and check the path allowing a wilcard - provide for error return.
253 ****************************************************************************/
255 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
256 const char *base_ptr
,
263 bool *contains_wcard
)
269 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
273 *err
= NT_STATUS_INVALID_PARAMETER
;
277 *contains_wcard
= False
;
279 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
281 * For a DFS path the function parse_dfs_path()
282 * will do the path processing, just make a copy.
288 if (lp_posix_pathnames()) {
289 *err
= check_path_syntax_posix(*pp_dest
);
291 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
297 /****************************************************************************
298 Pull a string and check the path - provide for error return.
299 ****************************************************************************/
301 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
302 const char *base_ptr
,
311 return srvstr_get_path_wcard(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
312 src_len
, flags
, err
, &ignore
);
315 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
316 char **pp_dest
, const char *src
, int flags
,
317 NTSTATUS
*err
, bool *contains_wcard
)
319 return srvstr_get_path_wcard(mem_ctx
, (const char *)req
->inbuf
, req
->flags2
,
320 pp_dest
, src
, smbreq_bufrem(req
, src
),
321 flags
, err
, contains_wcard
);
324 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
325 char **pp_dest
, const char *src
, int flags
,
329 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
330 flags
, err
, &ignore
);
333 /****************************************************************************
334 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
335 ****************************************************************************/
337 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
340 if ((fsp
== NULL
) || (conn
== NULL
)) {
341 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
344 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
345 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
351 /****************************************************************************
352 Check if we have a correct fsp pointing to a file.
353 ****************************************************************************/
355 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
358 if (!check_fsp_open(conn
, req
, fsp
)) {
361 if (fsp
->is_directory
) {
362 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
365 if (fsp
->fh
->fd
== -1) {
366 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
369 fsp
->num_smb_operations
++;
373 /****************************************************************************
374 Check if we have a correct fsp pointing to a quota fake file. Replacement for
375 the CHECK_NTQUOTA_HANDLE_OK macro.
376 ****************************************************************************/
378 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
381 if (!check_fsp_open(conn
, req
, fsp
)) {
385 if (fsp
->is_directory
) {
389 if (fsp
->fake_file_handle
== NULL
) {
393 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
397 if (fsp
->fake_file_handle
->private_data
== NULL
) {
404 static bool netbios_session_retarget(struct smbd_server_connection
*sconn
,
405 const char *name
, int name_type
)
408 char *trim_name_type
;
409 const char *retarget_parm
;
412 int retarget_type
= 0x20;
413 int retarget_port
= 139;
414 struct sockaddr_storage retarget_addr
;
415 struct sockaddr_in
*in_addr
;
419 if (get_socket_port(sconn
->sock
) != 139) {
423 trim_name
= talloc_strdup(talloc_tos(), name
);
424 if (trim_name
== NULL
) {
427 trim_char(trim_name
, ' ', ' ');
429 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
431 if (trim_name_type
== NULL
) {
435 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
436 trim_name_type
, NULL
);
437 if (retarget_parm
== NULL
) {
438 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
441 if (retarget_parm
== NULL
) {
445 retarget
= talloc_strdup(trim_name
, retarget_parm
);
446 if (retarget
== NULL
) {
450 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
452 p
= strchr(retarget
, ':');
455 retarget_port
= atoi(p
);
458 p
= strchr_m(retarget
, '#');
461 if (sscanf(p
, "%x", &retarget_type
) != 1) {
466 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
468 DEBUG(10, ("could not resolve %s\n", retarget
));
472 if (retarget_addr
.ss_family
!= AF_INET
) {
473 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
477 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
479 _smb_setlen(outbuf
, 6);
480 SCVAL(outbuf
, 0, 0x84);
481 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
482 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
484 if (!srv_send_smb(sconn
, (char *)outbuf
, false, 0, false,
486 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
492 TALLOC_FREE(trim_name
);
496 static void reply_called_name_not_present(char *outbuf
)
498 smb_setlen(outbuf
, 1);
499 SCVAL(outbuf
, 0, 0x83);
500 SCVAL(outbuf
, 4, 0x82);
503 /****************************************************************************
504 Reply to a (netbios-level) special message.
505 ****************************************************************************/
507 void reply_special(struct smbd_server_connection
*sconn
, char *inbuf
, size_t inbuf_size
)
509 int msg_type
= CVAL(inbuf
,0);
510 int msg_flags
= CVAL(inbuf
,1);
512 * We only really use 4 bytes of the outbuf, but for the smb_setlen
513 * calculation & friends (srv_send_smb uses that) we need the full smb
516 char outbuf
[smb_size
];
518 memset(outbuf
, '\0', sizeof(outbuf
));
520 smb_setlen(outbuf
,0);
523 case NBSSrequest
: /* session request */
525 /* inbuf_size is guarenteed to be at least 4. */
527 int name_type1
, name_type2
;
528 int name_len1
, name_len2
;
532 if (sconn
->nbt
.got_session
) {
533 exit_server_cleanly("multiple session request not permitted");
536 SCVAL(outbuf
,0,NBSSpositive
);
539 /* inbuf_size is guaranteed to be at least 4. */
540 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
541 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
542 DEBUG(0,("Invalid name length in session request\n"));
543 reply_called_name_not_present(outbuf
);
546 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
547 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
548 DEBUG(0,("Invalid name length in session request\n"));
549 reply_called_name_not_present(outbuf
);
553 name_type1
= name_extract((unsigned char *)inbuf
,
554 inbuf_size
,(unsigned int)4,name1
);
555 name_type2
= name_extract((unsigned char *)inbuf
,
556 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
558 if (name_type1
== -1 || name_type2
== -1) {
559 DEBUG(0,("Invalid name type in session request\n"));
560 reply_called_name_not_present(outbuf
);
564 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
565 name1
, name_type1
, name2
, name_type2
));
567 if (netbios_session_retarget(sconn
, name1
, name_type1
)) {
568 exit_server_cleanly("retargeted client");
572 * Windows NT/2k uses "*SMBSERVER" and XP uses
573 * "*SMBSERV" arrggg!!!
575 if (strequal(name1
, "*SMBSERVER ")
576 || strequal(name1
, "*SMBSERV ")) {
579 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
582 exit_server_cleanly("could not allocate raddr");
585 fstrcpy(name1
, raddr
);
588 set_local_machine_name(name1
, True
);
589 set_remote_machine_name(name2
, True
);
591 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
592 get_local_machine_name(), get_remote_machine_name(),
595 if (name_type2
== 'R') {
596 /* We are being asked for a pathworks session ---
598 reply_called_name_not_present(outbuf
);
602 /* only add the client's machine name to the list
603 of possibly valid usernames if we are operating
604 in share mode security */
605 if (lp_security() == SEC_SHARE
) {
606 add_session_user(sconn
, get_remote_machine_name());
609 reload_services(sconn
, conn_snum_used
, true);
612 sconn
->nbt
.got_session
= true;
616 case 0x89: /* session keepalive request
617 (some old clients produce this?) */
618 SCVAL(outbuf
,0,NBSSkeepalive
);
622 case NBSSpositive
: /* positive session response */
623 case NBSSnegative
: /* negative session response */
624 case NBSSretarget
: /* retarget session response */
625 DEBUG(0,("Unexpected session response\n"));
628 case NBSSkeepalive
: /* session keepalive */
633 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
634 msg_type
, msg_flags
));
636 srv_send_smb(sconn
, outbuf
, false, 0, false, NULL
);
638 if (CVAL(outbuf
, 0) != 0x82) {
639 exit_server_cleanly("invalid netbios session");
644 /****************************************************************************
646 conn POINTER CAN BE NULL HERE !
647 ****************************************************************************/
649 void reply_tcon(struct smb_request
*req
)
651 connection_struct
*conn
= req
->conn
;
653 char *service_buf
= NULL
;
654 char *password
= NULL
;
659 DATA_BLOB password_blob
;
660 TALLOC_CTX
*ctx
= talloc_tos();
661 struct smbd_server_connection
*sconn
= req
->sconn
;
663 START_PROFILE(SMBtcon
);
665 if (req
->buflen
< 4) {
666 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
667 END_PROFILE(SMBtcon
);
671 p
= (const char *)req
->buf
+ 1;
672 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
674 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
676 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
679 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
680 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
681 END_PROFILE(SMBtcon
);
684 p
= strrchr_m(service_buf
,'\\');
688 service
= service_buf
;
691 password_blob
= data_blob(password
, pwlen
+1);
693 conn
= make_connection(sconn
,service
,password_blob
,dev
,
694 req
->vuid
,&nt_status
);
697 data_blob_clear_free(&password_blob
);
700 reply_nterror(req
, nt_status
);
701 END_PROFILE(SMBtcon
);
705 reply_outbuf(req
, 2, 0);
706 SSVAL(req
->outbuf
,smb_vwv0
,sconn
->smb1
.negprot
.max_recv
);
707 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
708 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
710 DEBUG(3,("tcon service=%s cnum=%d\n",
711 service
, conn
->cnum
));
713 END_PROFILE(SMBtcon
);
717 /****************************************************************************
718 Reply to a tcon and X.
719 conn POINTER CAN BE NULL HERE !
720 ****************************************************************************/
722 void reply_tcon_and_X(struct smb_request
*req
)
724 connection_struct
*conn
= req
->conn
;
725 const char *service
= NULL
;
727 TALLOC_CTX
*ctx
= talloc_tos();
728 /* what the cleint thinks the device is */
729 char *client_devicetype
= NULL
;
730 /* what the server tells the client the share represents */
731 const char *server_devicetype
;
737 struct smbd_server_connection
*sconn
= req
->sconn
;
739 START_PROFILE(SMBtconX
);
742 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
743 END_PROFILE(SMBtconX
);
747 passlen
= SVAL(req
->vwv
+3, 0);
748 tcon_flags
= SVAL(req
->vwv
+2, 0);
750 /* we might have to close an old one */
751 if ((tcon_flags
& 0x1) && conn
) {
752 close_cnum(conn
,req
->vuid
);
757 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
758 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
759 END_PROFILE(SMBtconX
);
763 if (sconn
->smb1
.negprot
.encrypted_passwords
) {
764 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
);
765 if (lp_security() == SEC_SHARE
) {
767 * Security = share always has a pad byte
768 * after the password.
770 p
= (const char *)req
->buf
+ passlen
+ 1;
772 p
= (const char *)req
->buf
+ passlen
;
775 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
+1);
776 /* Ensure correct termination */
777 password
.data
[passlen
]=0;
778 p
= (const char *)req
->buf
+ passlen
+ 1;
781 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
784 data_blob_clear_free(&password
);
785 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
786 END_PROFILE(SMBtconX
);
791 * the service name can be either: \\server\share
792 * or share directly like on the DELL PowerVault 705
795 q
= strchr_m(path
+2,'\\');
797 data_blob_clear_free(&password
);
798 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
799 END_PROFILE(SMBtconX
);
807 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
808 &client_devicetype
, p
,
809 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
811 if (client_devicetype
== NULL
) {
812 data_blob_clear_free(&password
);
813 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
814 END_PROFILE(SMBtconX
);
818 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
820 conn
= make_connection(sconn
, service
, password
, client_devicetype
,
821 req
->vuid
, &nt_status
);
824 data_blob_clear_free(&password
);
827 reply_nterror(req
, nt_status
);
828 END_PROFILE(SMBtconX
);
833 server_devicetype
= "IPC";
834 else if ( IS_PRINT(conn
) )
835 server_devicetype
= "LPT1:";
837 server_devicetype
= "A:";
839 if (get_Protocol() < PROTOCOL_NT1
) {
840 reply_outbuf(req
, 2, 0);
841 if (message_push_string(&req
->outbuf
, server_devicetype
,
842 STR_TERMINATE
|STR_ASCII
) == -1) {
843 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
844 END_PROFILE(SMBtconX
);
848 /* NT sets the fstype of IPC$ to the null string */
849 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
851 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
852 /* Return permissions. */
856 reply_outbuf(req
, 7, 0);
859 perm1
= FILE_ALL_ACCESS
;
860 perm2
= FILE_ALL_ACCESS
;
862 perm1
= conn
->share_access
;
865 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
866 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
868 reply_outbuf(req
, 3, 0);
871 if ((message_push_string(&req
->outbuf
, server_devicetype
,
872 STR_TERMINATE
|STR_ASCII
) == -1)
873 || (message_push_string(&req
->outbuf
, fstype
,
874 STR_TERMINATE
) == -1)) {
875 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
876 END_PROFILE(SMBtconX
);
880 /* what does setting this bit do? It is set by NT4 and
881 may affect the ability to autorun mounted cdroms */
882 SSVAL(req
->outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
883 (lp_csc_policy(SNUM(conn
)) << 2));
885 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
886 DEBUG(2,("Serving %s as a Dfs root\n",
887 lp_servicename(SNUM(conn
)) ));
888 SSVAL(req
->outbuf
, smb_vwv2
,
889 SMB_SHARE_IN_DFS
| SVAL(req
->outbuf
, smb_vwv2
));
894 DEBUG(3,("tconX service=%s \n",
897 /* set the incoming and outgoing tid to the just created one */
898 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
899 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
901 END_PROFILE(SMBtconX
);
903 req
->tid
= conn
->cnum
;
908 /****************************************************************************
909 Reply to an unknown type.
910 ****************************************************************************/
912 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
914 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
915 smb_fn_name(type
), type
, type
));
916 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
920 /****************************************************************************
922 conn POINTER CAN BE NULL HERE !
923 ****************************************************************************/
925 void reply_ioctl(struct smb_request
*req
)
927 connection_struct
*conn
= req
->conn
;
934 START_PROFILE(SMBioctl
);
937 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
938 END_PROFILE(SMBioctl
);
942 device
= SVAL(req
->vwv
+1, 0);
943 function
= SVAL(req
->vwv
+2, 0);
944 ioctl_code
= (device
<< 16) + function
;
946 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
948 switch (ioctl_code
) {
949 case IOCTL_QUERY_JOB_INFO
:
953 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
954 END_PROFILE(SMBioctl
);
958 reply_outbuf(req
, 8, replysize
+1);
959 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
960 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
961 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
962 p
= smb_buf(req
->outbuf
);
963 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
964 p
+= 1; /* Allow for alignment */
966 switch (ioctl_code
) {
967 case IOCTL_QUERY_JOB_INFO
:
969 files_struct
*fsp
= file_fsp(
970 req
, SVAL(req
->vwv
+0, 0));
972 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
973 END_PROFILE(SMBioctl
);
977 if (fsp
->print_file
) {
978 SSVAL(p
, 0, fsp
->print_file
->rap_jobid
);
982 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
983 lp_netbios_name(), 15,
984 STR_TERMINATE
|STR_ASCII
);
986 srvstr_push((char *)req
->outbuf
, req
->flags2
,
987 p
+18, lp_servicename(SNUM(conn
)),
988 13, STR_TERMINATE
|STR_ASCII
);
996 END_PROFILE(SMBioctl
);
1000 /****************************************************************************
1001 Strange checkpath NTSTATUS mapping.
1002 ****************************************************************************/
1004 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1006 /* Strange DOS error code semantics only for checkpath... */
1007 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1008 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1009 /* We need to map to ERRbadpath */
1010 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1016 /****************************************************************************
1017 Reply to a checkpath.
1018 ****************************************************************************/
1020 void reply_checkpath(struct smb_request
*req
)
1022 connection_struct
*conn
= req
->conn
;
1023 struct smb_filename
*smb_fname
= NULL
;
1026 TALLOC_CTX
*ctx
= talloc_tos();
1028 START_PROFILE(SMBcheckpath
);
1030 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1031 STR_TERMINATE
, &status
);
1033 if (!NT_STATUS_IS_OK(status
)) {
1034 status
= map_checkpath_error(req
->flags2
, status
);
1035 reply_nterror(req
, status
);
1036 END_PROFILE(SMBcheckpath
);
1040 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1042 status
= filename_convert(ctx
,
1044 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1050 if (!NT_STATUS_IS_OK(status
)) {
1051 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1052 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1053 ERRSRV
, ERRbadpath
);
1054 END_PROFILE(SMBcheckpath
);
1060 if (!VALID_STAT(smb_fname
->st
) &&
1061 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1062 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1063 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1064 status
= map_nt_error_from_unix(errno
);
1068 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1069 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1070 ERRDOS
, ERRbadpath
);
1074 reply_outbuf(req
, 0, 0);
1077 /* We special case this - as when a Windows machine
1078 is parsing a path is steps through the components
1079 one at a time - if a component fails it expects
1080 ERRbadpath, not ERRbadfile.
1082 status
= map_checkpath_error(req
->flags2
, status
);
1083 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1085 * Windows returns different error codes if
1086 * the parent directory is valid but not the
1087 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1088 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1089 * if the path is invalid.
1091 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1092 ERRDOS
, ERRbadpath
);
1096 reply_nterror(req
, status
);
1099 TALLOC_FREE(smb_fname
);
1100 END_PROFILE(SMBcheckpath
);
1104 /****************************************************************************
1106 ****************************************************************************/
1108 void reply_getatr(struct smb_request
*req
)
1110 connection_struct
*conn
= req
->conn
;
1111 struct smb_filename
*smb_fname
= NULL
;
1118 TALLOC_CTX
*ctx
= talloc_tos();
1119 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1121 START_PROFILE(SMBgetatr
);
1123 p
= (const char *)req
->buf
+ 1;
1124 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1125 if (!NT_STATUS_IS_OK(status
)) {
1126 reply_nterror(req
, status
);
1130 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1131 under WfWg - weird! */
1132 if (*fname
== '\0') {
1133 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1134 if (!CAN_WRITE(conn
)) {
1135 mode
|= FILE_ATTRIBUTE_READONLY
;
1140 status
= filename_convert(ctx
,
1142 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1147 if (!NT_STATUS_IS_OK(status
)) {
1148 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1149 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1150 ERRSRV
, ERRbadpath
);
1153 reply_nterror(req
, status
);
1156 if (!VALID_STAT(smb_fname
->st
) &&
1157 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1158 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1159 smb_fname_str_dbg(smb_fname
),
1161 reply_nterror(req
, map_nt_error_from_unix(errno
));
1165 mode
= dos_mode(conn
, smb_fname
);
1166 size
= smb_fname
->st
.st_ex_size
;
1168 if (ask_sharemode
) {
1169 struct timespec write_time_ts
;
1170 struct file_id fileid
;
1172 ZERO_STRUCT(write_time_ts
);
1173 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1174 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1175 if (!null_timespec(write_time_ts
)) {
1176 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1180 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1181 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1186 reply_outbuf(req
, 10, 0);
1188 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1189 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1190 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1192 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1194 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1196 if (get_Protocol() >= PROTOCOL_NT1
) {
1197 SSVAL(req
->outbuf
, smb_flg2
,
1198 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1201 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1202 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1205 TALLOC_FREE(smb_fname
);
1207 END_PROFILE(SMBgetatr
);
1211 /****************************************************************************
1213 ****************************************************************************/
1215 void reply_setatr(struct smb_request
*req
)
1217 struct smb_file_time ft
;
1218 connection_struct
*conn
= req
->conn
;
1219 struct smb_filename
*smb_fname
= NULL
;
1225 TALLOC_CTX
*ctx
= talloc_tos();
1227 START_PROFILE(SMBsetatr
);
1232 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1236 p
= (const char *)req
->buf
+ 1;
1237 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1238 if (!NT_STATUS_IS_OK(status
)) {
1239 reply_nterror(req
, status
);
1243 status
= filename_convert(ctx
,
1245 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1250 if (!NT_STATUS_IS_OK(status
)) {
1251 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1252 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1253 ERRSRV
, ERRbadpath
);
1256 reply_nterror(req
, status
);
1260 if (smb_fname
->base_name
[0] == '.' &&
1261 smb_fname
->base_name
[1] == '\0') {
1263 * Not sure here is the right place to catch this
1264 * condition. Might be moved to somewhere else later -- vl
1266 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1270 mode
= SVAL(req
->vwv
+0, 0);
1271 mtime
= srv_make_unix_date3(req
->vwv
+1);
1273 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1274 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1275 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1277 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1279 status
= check_access(conn
, NULL
, smb_fname
,
1280 FILE_WRITE_ATTRIBUTES
);
1281 if (!NT_STATUS_IS_OK(status
)) {
1282 reply_nterror(req
, status
);
1286 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1288 reply_nterror(req
, map_nt_error_from_unix(errno
));
1293 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1294 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1295 if (!NT_STATUS_IS_OK(status
)) {
1296 reply_nterror(req
, status
);
1300 reply_outbuf(req
, 0, 0);
1302 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1305 TALLOC_FREE(smb_fname
);
1306 END_PROFILE(SMBsetatr
);
1310 /****************************************************************************
1312 ****************************************************************************/
1314 void reply_dskattr(struct smb_request
*req
)
1316 connection_struct
*conn
= req
->conn
;
1317 uint64_t dfree
,dsize
,bsize
;
1318 START_PROFILE(SMBdskattr
);
1320 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1321 reply_nterror(req
, map_nt_error_from_unix(errno
));
1322 END_PROFILE(SMBdskattr
);
1326 reply_outbuf(req
, 5, 0);
1328 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1329 double total_space
, free_space
;
1330 /* we need to scale this to a number that DOS6 can handle. We
1331 use floating point so we can handle large drives on systems
1332 that don't have 64 bit integers
1334 we end up displaying a maximum of 2G to DOS systems
1336 total_space
= dsize
* (double)bsize
;
1337 free_space
= dfree
* (double)bsize
;
1339 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1340 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1342 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1343 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1345 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1346 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1347 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1348 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1350 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1351 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1352 SSVAL(req
->outbuf
,smb_vwv2
,512);
1353 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1356 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1358 END_PROFILE(SMBdskattr
);
1363 * Utility function to split the filename from the directory.
1365 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1366 char **fname_dir_out
,
1367 char **fname_mask_out
)
1369 const char *p
= NULL
;
1370 char *fname_dir
= NULL
;
1371 char *fname_mask
= NULL
;
1373 p
= strrchr_m(fname_in
, '/');
1375 fname_dir
= talloc_strdup(ctx
, ".");
1376 fname_mask
= talloc_strdup(ctx
, fname_in
);
1378 fname_dir
= talloc_strndup(ctx
, fname_in
,
1379 PTR_DIFF(p
, fname_in
));
1380 fname_mask
= talloc_strdup(ctx
, p
+1);
1383 if (!fname_dir
|| !fname_mask
) {
1384 TALLOC_FREE(fname_dir
);
1385 TALLOC_FREE(fname_mask
);
1386 return NT_STATUS_NO_MEMORY
;
1389 *fname_dir_out
= fname_dir
;
1390 *fname_mask_out
= fname_mask
;
1391 return NT_STATUS_OK
;
1394 /****************************************************************************
1396 Can be called from SMBsearch, SMBffirst or SMBfunique.
1397 ****************************************************************************/
1399 void reply_search(struct smb_request
*req
)
1401 connection_struct
*conn
= req
->conn
;
1403 const char *mask
= NULL
;
1404 char *directory
= NULL
;
1405 struct smb_filename
*smb_fname
= NULL
;
1409 struct timespec date
;
1411 unsigned int numentries
= 0;
1412 unsigned int maxentries
= 0;
1413 bool finished
= False
;
1418 bool check_descend
= False
;
1419 bool expect_close
= False
;
1421 bool mask_contains_wcard
= False
;
1422 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1423 TALLOC_CTX
*ctx
= talloc_tos();
1424 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1425 struct dptr_struct
*dirptr
= NULL
;
1426 struct smbd_server_connection
*sconn
= req
->sconn
;
1428 START_PROFILE(SMBsearch
);
1431 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1435 if (lp_posix_pathnames()) {
1436 reply_unknown_new(req
, req
->cmd
);
1440 /* If we were called as SMBffirst then we must expect close. */
1441 if(req
->cmd
== SMBffirst
) {
1442 expect_close
= True
;
1445 reply_outbuf(req
, 1, 3);
1446 maxentries
= SVAL(req
->vwv
+0, 0);
1447 dirtype
= SVAL(req
->vwv
+1, 0);
1448 p
= (const char *)req
->buf
+ 1;
1449 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1450 &nt_status
, &mask_contains_wcard
);
1451 if (!NT_STATUS_IS_OK(nt_status
)) {
1452 reply_nterror(req
, nt_status
);
1457 status_len
= SVAL(p
, 0);
1460 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1462 if (status_len
== 0) {
1463 nt_status
= filename_convert(ctx
, conn
,
1464 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1466 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1467 &mask_contains_wcard
,
1469 if (!NT_STATUS_IS_OK(nt_status
)) {
1470 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1471 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1472 ERRSRV
, ERRbadpath
);
1475 reply_nterror(req
, nt_status
);
1479 directory
= smb_fname
->base_name
;
1481 p
= strrchr_m(directory
,'/');
1482 if ((p
!= NULL
) && (*directory
!= '/')) {
1484 directory
= talloc_strndup(ctx
, directory
,
1485 PTR_DIFF(p
, directory
));
1488 directory
= talloc_strdup(ctx
,".");
1492 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1496 memset((char *)status
,'\0',21);
1497 SCVAL(status
,0,(dirtype
& 0x1F));
1499 nt_status
= dptr_create(conn
,
1506 mask_contains_wcard
,
1509 if (!NT_STATUS_IS_OK(nt_status
)) {
1510 reply_nterror(req
, nt_status
);
1513 dptr_num
= dptr_dnum(dirptr
);
1516 const char *dirpath
;
1518 memcpy(status
,p
,21);
1519 status_dirtype
= CVAL(status
,0) & 0x1F;
1520 if (status_dirtype
!= (dirtype
& 0x1F)) {
1521 dirtype
= status_dirtype
;
1524 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1528 dirpath
= dptr_path(sconn
, dptr_num
);
1529 directory
= talloc_strdup(ctx
, dirpath
);
1531 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1535 mask
= dptr_wcard(sconn
, dptr_num
);
1540 * For a 'continue' search we have no string. So
1541 * check from the initial saved string.
1543 mask_contains_wcard
= ms_has_wild(mask
);
1544 dirtype
= dptr_attr(sconn
, dptr_num
);
1547 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1549 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1550 dptr_init_search_op(dirptr
);
1552 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1553 char buf
[DIR_STRUCT_SIZE
];
1554 memcpy(buf
,status
,21);
1555 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1556 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1557 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1560 dptr_fill(sconn
, buf
+12,dptr_num
);
1561 if (dptr_zero(buf
+12) && (status_len
==0)) {
1566 if (message_push_blob(&req
->outbuf
,
1567 data_blob_const(buf
, sizeof(buf
)))
1569 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1577 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1580 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1581 directory
,lp_dontdescend(SNUM(conn
))));
1582 if (in_list(directory
, lp_dontdescend(SNUM(conn
)),True
)) {
1583 check_descend
= True
;
1586 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1587 finished
= !get_dir_entry(ctx
,
1598 char buf
[DIR_STRUCT_SIZE
];
1599 memcpy(buf
,status
,21);
1600 if (!make_dir_struct(ctx
,
1606 convert_timespec_to_time_t(date
),
1607 !allow_long_path_components
)) {
1608 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1611 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1614 if (message_push_blob(&req
->outbuf
,
1615 data_blob_const(buf
, sizeof(buf
)))
1617 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1627 /* If we were called as SMBffirst with smb_search_id == NULL
1628 and no entries were found then return error and close dirptr
1631 if (numentries
== 0) {
1632 dptr_close(sconn
, &dptr_num
);
1633 } else if(expect_close
&& status_len
== 0) {
1634 /* Close the dptr - we know it's gone */
1635 dptr_close(sconn
, &dptr_num
);
1638 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1639 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1640 dptr_close(sconn
, &dptr_num
);
1643 if ((numentries
== 0) && !mask_contains_wcard
) {
1644 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1648 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1649 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1650 SCVAL(smb_buf(req
->outbuf
),0,5);
1651 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1653 /* The replies here are never long name. */
1654 SSVAL(req
->outbuf
, smb_flg2
,
1655 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1656 if (!allow_long_path_components
) {
1657 SSVAL(req
->outbuf
, smb_flg2
,
1658 SVAL(req
->outbuf
, smb_flg2
)
1659 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1662 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1663 SSVAL(req
->outbuf
, smb_flg2
,
1664 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1666 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1667 smb_fn_name(req
->cmd
),
1674 TALLOC_FREE(directory
);
1675 TALLOC_FREE(smb_fname
);
1676 END_PROFILE(SMBsearch
);
1680 /****************************************************************************
1681 Reply to a fclose (stop directory search).
1682 ****************************************************************************/
1684 void reply_fclose(struct smb_request
*req
)
1692 bool path_contains_wcard
= False
;
1693 TALLOC_CTX
*ctx
= talloc_tos();
1694 struct smbd_server_connection
*sconn
= req
->sconn
;
1696 START_PROFILE(SMBfclose
);
1698 if (lp_posix_pathnames()) {
1699 reply_unknown_new(req
, req
->cmd
);
1700 END_PROFILE(SMBfclose
);
1704 p
= (const char *)req
->buf
+ 1;
1705 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1706 &err
, &path_contains_wcard
);
1707 if (!NT_STATUS_IS_OK(err
)) {
1708 reply_nterror(req
, err
);
1709 END_PROFILE(SMBfclose
);
1713 status_len
= SVAL(p
,0);
1716 if (status_len
== 0) {
1717 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1718 END_PROFILE(SMBfclose
);
1722 memcpy(status
,p
,21);
1724 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1725 /* Close the dptr - we know it's gone */
1726 dptr_close(sconn
, &dptr_num
);
1729 reply_outbuf(req
, 1, 0);
1730 SSVAL(req
->outbuf
,smb_vwv0
,0);
1732 DEBUG(3,("search close\n"));
1734 END_PROFILE(SMBfclose
);
1738 /****************************************************************************
1740 ****************************************************************************/
1742 void reply_open(struct smb_request
*req
)
1744 connection_struct
*conn
= req
->conn
;
1745 struct smb_filename
*smb_fname
= NULL
;
1757 uint32 create_disposition
;
1758 uint32 create_options
= 0;
1759 uint32_t private_flags
= 0;
1761 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1762 TALLOC_CTX
*ctx
= talloc_tos();
1764 START_PROFILE(SMBopen
);
1767 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1771 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1772 deny_mode
= SVAL(req
->vwv
+0, 0);
1773 dos_attr
= SVAL(req
->vwv
+1, 0);
1775 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1776 STR_TERMINATE
, &status
);
1777 if (!NT_STATUS_IS_OK(status
)) {
1778 reply_nterror(req
, status
);
1782 status
= filename_convert(ctx
,
1784 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1789 if (!NT_STATUS_IS_OK(status
)) {
1790 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1791 reply_botherror(req
,
1792 NT_STATUS_PATH_NOT_COVERED
,
1793 ERRSRV
, ERRbadpath
);
1796 reply_nterror(req
, status
);
1800 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1801 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1802 &share_mode
, &create_disposition
,
1803 &create_options
, &private_flags
)) {
1804 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1808 status
= SMB_VFS_CREATE_FILE(
1811 0, /* root_dir_fid */
1812 smb_fname
, /* fname */
1813 access_mask
, /* access_mask */
1814 share_mode
, /* share_access */
1815 create_disposition
, /* create_disposition*/
1816 create_options
, /* create_options */
1817 dos_attr
, /* file_attributes */
1818 oplock_request
, /* oplock_request */
1819 0, /* allocation_size */
1826 if (!NT_STATUS_IS_OK(status
)) {
1827 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1828 /* We have re-scheduled this call. */
1831 reply_openerror(req
, status
);
1835 size
= smb_fname
->st
.st_ex_size
;
1836 fattr
= dos_mode(conn
, smb_fname
);
1838 /* Deal with other possible opens having a modified
1840 if (ask_sharemode
) {
1841 struct timespec write_time_ts
;
1843 ZERO_STRUCT(write_time_ts
);
1844 get_file_infos(fsp
->file_id
, 0, NULL
, &write_time_ts
);
1845 if (!null_timespec(write_time_ts
)) {
1846 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1850 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1852 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1853 DEBUG(3,("attempt to open a directory %s\n",
1855 close_file(req
, fsp
, ERROR_CLOSE
);
1856 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1857 ERRDOS
, ERRnoaccess
);
1861 reply_outbuf(req
, 7, 0);
1862 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1863 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1864 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1865 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1867 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1869 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1870 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1872 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1873 SCVAL(req
->outbuf
,smb_flg
,
1874 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1877 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1878 SCVAL(req
->outbuf
,smb_flg
,
1879 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1882 TALLOC_FREE(smb_fname
);
1883 END_PROFILE(SMBopen
);
1887 /****************************************************************************
1888 Reply to an open and X.
1889 ****************************************************************************/
1891 void reply_open_and_X(struct smb_request
*req
)
1893 connection_struct
*conn
= req
->conn
;
1894 struct smb_filename
*smb_fname
= NULL
;
1899 /* Breakout the oplock request bits so we can set the
1900 reply bits separately. */
1901 int ex_oplock_request
;
1902 int core_oplock_request
;
1905 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1906 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
1914 uint64_t allocation_size
;
1915 ssize_t retval
= -1;
1918 uint32 create_disposition
;
1919 uint32 create_options
= 0;
1920 uint32_t private_flags
= 0;
1921 TALLOC_CTX
*ctx
= talloc_tos();
1923 START_PROFILE(SMBopenX
);
1925 if (req
->wct
< 15) {
1926 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1930 open_flags
= SVAL(req
->vwv
+2, 0);
1931 deny_mode
= SVAL(req
->vwv
+3, 0);
1932 smb_attr
= SVAL(req
->vwv
+5, 0);
1933 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1934 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1935 oplock_request
= ex_oplock_request
| core_oplock_request
;
1936 smb_ofun
= SVAL(req
->vwv
+8, 0);
1937 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1939 /* If it's an IPC, pass off the pipe handler. */
1941 if (lp_nt_pipe_support()) {
1942 reply_open_pipe_and_X(conn
, req
);
1944 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1949 /* XXXX we need to handle passed times, sattr and flags */
1950 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1951 STR_TERMINATE
, &status
);
1952 if (!NT_STATUS_IS_OK(status
)) {
1953 reply_nterror(req
, status
);
1957 status
= filename_convert(ctx
,
1959 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1964 if (!NT_STATUS_IS_OK(status
)) {
1965 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1966 reply_botherror(req
,
1967 NT_STATUS_PATH_NOT_COVERED
,
1968 ERRSRV
, ERRbadpath
);
1971 reply_nterror(req
, status
);
1975 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1977 &access_mask
, &share_mode
,
1978 &create_disposition
,
1981 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1985 status
= SMB_VFS_CREATE_FILE(
1988 0, /* root_dir_fid */
1989 smb_fname
, /* fname */
1990 access_mask
, /* access_mask */
1991 share_mode
, /* share_access */
1992 create_disposition
, /* create_disposition*/
1993 create_options
, /* create_options */
1994 smb_attr
, /* file_attributes */
1995 oplock_request
, /* oplock_request */
1996 0, /* allocation_size */
2001 &smb_action
); /* pinfo */
2003 if (!NT_STATUS_IS_OK(status
)) {
2004 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2005 /* We have re-scheduled this call. */
2008 reply_openerror(req
, status
);
2012 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2013 if the file is truncated or created. */
2014 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2015 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2016 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2017 close_file(req
, fsp
, ERROR_CLOSE
);
2018 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2021 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
2023 close_file(req
, fsp
, ERROR_CLOSE
);
2024 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2027 status
= vfs_stat_fsp(fsp
);
2028 if (!NT_STATUS_IS_OK(status
)) {
2029 close_file(req
, fsp
, ERROR_CLOSE
);
2030 reply_nterror(req
, status
);
2035 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2036 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2037 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2038 close_file(req
, fsp
, ERROR_CLOSE
);
2039 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2043 /* If the caller set the extended oplock request bit
2044 and we granted one (by whatever means) - set the
2045 correct bit for extended oplock reply.
2048 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2049 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2052 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2053 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2056 /* If the caller set the core oplock request bit
2057 and we granted one (by whatever means) - set the
2058 correct bit for core oplock reply.
2061 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2062 reply_outbuf(req
, 19, 0);
2064 reply_outbuf(req
, 15, 0);
2067 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2068 SCVAL(req
->outbuf
, smb_flg
,
2069 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2072 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2073 SCVAL(req
->outbuf
, smb_flg
,
2074 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2077 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2078 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2079 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2080 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2082 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2084 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2085 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2086 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2088 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2089 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2094 TALLOC_FREE(smb_fname
);
2095 END_PROFILE(SMBopenX
);
2099 /****************************************************************************
2100 Reply to a SMBulogoffX.
2101 ****************************************************************************/
2103 void reply_ulogoffX(struct smb_request
*req
)
2105 struct smbd_server_connection
*sconn
= req
->sconn
;
2108 START_PROFILE(SMBulogoffX
);
2110 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2113 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2117 /* in user level security we are supposed to close any files
2118 open by this user */
2119 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
2120 file_close_user(sconn
, req
->vuid
);
2123 invalidate_vuid(sconn
, req
->vuid
);
2125 reply_outbuf(req
, 2, 0);
2127 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
2129 END_PROFILE(SMBulogoffX
);
2130 req
->vuid
= UID_FIELD_INVALID
;
2134 /****************************************************************************
2135 Reply to a mknew or a create.
2136 ****************************************************************************/
2138 void reply_mknew(struct smb_request
*req
)
2140 connection_struct
*conn
= req
->conn
;
2141 struct smb_filename
*smb_fname
= NULL
;
2144 struct smb_file_time ft
;
2146 int oplock_request
= 0;
2148 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2149 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2150 uint32 create_disposition
;
2151 uint32 create_options
= 0;
2152 TALLOC_CTX
*ctx
= talloc_tos();
2154 START_PROFILE(SMBcreate
);
2158 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2162 fattr
= SVAL(req
->vwv
+0, 0);
2163 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2166 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2168 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2169 STR_TERMINATE
, &status
);
2170 if (!NT_STATUS_IS_OK(status
)) {
2171 reply_nterror(req
, status
);
2175 status
= filename_convert(ctx
,
2177 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2182 if (!NT_STATUS_IS_OK(status
)) {
2183 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2184 reply_botherror(req
,
2185 NT_STATUS_PATH_NOT_COVERED
,
2186 ERRSRV
, ERRbadpath
);
2189 reply_nterror(req
, status
);
2193 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2194 DEBUG(0,("Attempt to create file (%s) with volid set - "
2195 "please report this\n",
2196 smb_fname_str_dbg(smb_fname
)));
2199 if(req
->cmd
== SMBmknew
) {
2200 /* We should fail if file exists. */
2201 create_disposition
= FILE_CREATE
;
2203 /* Create if file doesn't exist, truncate if it does. */
2204 create_disposition
= FILE_OVERWRITE_IF
;
2207 status
= SMB_VFS_CREATE_FILE(
2210 0, /* root_dir_fid */
2211 smb_fname
, /* fname */
2212 access_mask
, /* access_mask */
2213 share_mode
, /* share_access */
2214 create_disposition
, /* create_disposition*/
2215 create_options
, /* create_options */
2216 fattr
, /* file_attributes */
2217 oplock_request
, /* oplock_request */
2218 0, /* allocation_size */
2219 0, /* private_flags */
2225 if (!NT_STATUS_IS_OK(status
)) {
2226 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2227 /* We have re-scheduled this call. */
2230 reply_openerror(req
, status
);
2234 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2235 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2236 if (!NT_STATUS_IS_OK(status
)) {
2237 END_PROFILE(SMBcreate
);
2241 reply_outbuf(req
, 1, 0);
2242 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2244 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2245 SCVAL(req
->outbuf
,smb_flg
,
2246 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2249 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2250 SCVAL(req
->outbuf
,smb_flg
,
2251 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2254 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2255 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2256 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2257 (unsigned int)fattr
));
2260 TALLOC_FREE(smb_fname
);
2261 END_PROFILE(SMBcreate
);
2265 /****************************************************************************
2266 Reply to a create temporary file.
2267 ****************************************************************************/
2269 void reply_ctemp(struct smb_request
*req
)
2271 connection_struct
*conn
= req
->conn
;
2272 struct smb_filename
*smb_fname
= NULL
;
2280 TALLOC_CTX
*ctx
= talloc_tos();
2282 START_PROFILE(SMBctemp
);
2285 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2289 fattr
= SVAL(req
->vwv
+0, 0);
2290 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2292 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2293 STR_TERMINATE
, &status
);
2294 if (!NT_STATUS_IS_OK(status
)) {
2295 reply_nterror(req
, status
);
2299 fname
= talloc_asprintf(ctx
,
2303 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2307 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2311 status
= filename_convert(ctx
, conn
,
2312 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2317 if (!NT_STATUS_IS_OK(status
)) {
2318 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2319 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2320 ERRSRV
, ERRbadpath
);
2323 reply_nterror(req
, status
);
2327 tmpfd
= mkstemp(smb_fname
->base_name
);
2329 reply_nterror(req
, map_nt_error_from_unix(errno
));
2333 SMB_VFS_STAT(conn
, smb_fname
);
2335 /* We should fail if file does not exist. */
2336 status
= SMB_VFS_CREATE_FILE(
2339 0, /* root_dir_fid */
2340 smb_fname
, /* fname */
2341 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2342 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2343 FILE_OPEN
, /* create_disposition*/
2344 0, /* create_options */
2345 fattr
, /* file_attributes */
2346 oplock_request
, /* oplock_request */
2347 0, /* allocation_size */
2348 0, /* private_flags */
2354 /* close fd from mkstemp() */
2357 if (!NT_STATUS_IS_OK(status
)) {
2358 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2359 /* We have re-scheduled this call. */
2362 reply_openerror(req
, status
);
2366 reply_outbuf(req
, 1, 0);
2367 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2369 /* the returned filename is relative to the directory */
2370 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2372 s
= fsp
->fsp_name
->base_name
;
2378 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2379 thing in the byte section. JRA */
2380 SSVALS(p
, 0, -1); /* what is this? not in spec */
2382 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2384 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2388 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2389 SCVAL(req
->outbuf
, smb_flg
,
2390 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2393 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2394 SCVAL(req
->outbuf
, smb_flg
,
2395 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2398 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2399 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2400 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2402 TALLOC_FREE(smb_fname
);
2403 END_PROFILE(SMBctemp
);
2407 /*******************************************************************
2408 Check if a user is allowed to rename a file.
2409 ********************************************************************/
2411 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2414 if (!CAN_WRITE(conn
)) {
2415 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2418 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2419 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2420 /* Only bother to read the DOS attribute if we might deny the
2421 rename on the grounds of attribute missmatch. */
2422 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2423 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2424 return NT_STATUS_NO_SUCH_FILE
;
2428 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2429 if (fsp
->posix_open
) {
2430 return NT_STATUS_OK
;
2433 /* If no pathnames are open below this
2434 directory, allow the rename. */
2436 if (file_find_subpath(fsp
)) {
2437 return NT_STATUS_ACCESS_DENIED
;
2439 return NT_STATUS_OK
;
2442 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2443 return NT_STATUS_OK
;
2446 return NT_STATUS_ACCESS_DENIED
;
2449 /*******************************************************************
2450 * unlink a file with all relevant access checks
2451 *******************************************************************/
2453 static NTSTATUS
do_unlink(connection_struct
*conn
,
2454 struct smb_request
*req
,
2455 struct smb_filename
*smb_fname
,
2460 uint32 dirtype_orig
= dirtype
;
2463 bool posix_paths
= lp_posix_pathnames();
2465 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2466 smb_fname_str_dbg(smb_fname
),
2469 if (!CAN_WRITE(conn
)) {
2470 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2474 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2476 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2479 return map_nt_error_from_unix(errno
);
2482 fattr
= dos_mode(conn
, smb_fname
);
2484 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2485 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2488 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2490 return NT_STATUS_NO_SUCH_FILE
;
2493 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2494 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2495 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2497 return NT_STATUS_NO_SUCH_FILE
;
2500 if (dirtype_orig
& 0x8000) {
2501 /* These will never be set for POSIX. */
2502 return NT_STATUS_NO_SUCH_FILE
;
2506 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2507 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2510 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2511 return NT_STATUS_NO_SUCH_FILE
;
2514 if (dirtype
& 0xFF00) {
2515 /* These will never be set for POSIX. */
2516 return NT_STATUS_NO_SUCH_FILE
;
2521 return NT_STATUS_NO_SUCH_FILE
;
2524 /* Can't delete a directory. */
2525 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2526 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2531 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2532 return NT_STATUS_OBJECT_NAME_INVALID
;
2533 #endif /* JRATEST */
2535 /* On open checks the open itself will check the share mode, so
2536 don't do it here as we'll get it wrong. */
2538 status
= SMB_VFS_CREATE_FILE
2541 0, /* root_dir_fid */
2542 smb_fname
, /* fname */
2543 DELETE_ACCESS
, /* access_mask */
2544 FILE_SHARE_NONE
, /* share_access */
2545 FILE_OPEN
, /* create_disposition*/
2546 FILE_NON_DIRECTORY_FILE
, /* create_options */
2547 /* file_attributes */
2548 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2549 FILE_ATTRIBUTE_NORMAL
,
2550 0, /* oplock_request */
2551 0, /* allocation_size */
2552 0, /* private_flags */
2558 if (!NT_STATUS_IS_OK(status
)) {
2559 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2560 nt_errstr(status
)));
2564 status
= can_set_delete_on_close(fsp
, fattr
);
2565 if (!NT_STATUS_IS_OK(status
)) {
2566 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2568 smb_fname_str_dbg(smb_fname
),
2569 nt_errstr(status
)));
2570 close_file(req
, fsp
, NORMAL_CLOSE
);
2574 /* The set is across all open files on this dev/inode pair. */
2575 if (!set_delete_on_close(fsp
, True
, conn
->session_info
->unix_token
)) {
2576 close_file(req
, fsp
, NORMAL_CLOSE
);
2577 return NT_STATUS_ACCESS_DENIED
;
2580 return close_file(req
, fsp
, NORMAL_CLOSE
);
2583 /****************************************************************************
2584 The guts of the unlink command, split out so it may be called by the NT SMB
2586 ****************************************************************************/
2588 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2589 uint32 dirtype
, struct smb_filename
*smb_fname
,
2592 char *fname_dir
= NULL
;
2593 char *fname_mask
= NULL
;
2595 NTSTATUS status
= NT_STATUS_OK
;
2596 TALLOC_CTX
*ctx
= talloc_tos();
2598 /* Split up the directory from the filename/mask. */
2599 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2600 &fname_dir
, &fname_mask
);
2601 if (!NT_STATUS_IS_OK(status
)) {
2606 * We should only check the mangled cache
2607 * here if unix_convert failed. This means
2608 * that the path in 'mask' doesn't exist
2609 * on the file system and so we need to look
2610 * for a possible mangle. This patch from
2611 * Tine Smukavec <valentin.smukavec@hermes.si>.
2614 if (!VALID_STAT(smb_fname
->st
) &&
2615 mangle_is_mangled(fname_mask
, conn
->params
)) {
2616 char *new_mask
= NULL
;
2617 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2618 &new_mask
, conn
->params
);
2620 TALLOC_FREE(fname_mask
);
2621 fname_mask
= new_mask
;
2628 * Only one file needs to be unlinked. Append the mask back
2629 * onto the directory.
2631 TALLOC_FREE(smb_fname
->base_name
);
2632 if (ISDOT(fname_dir
)) {
2633 /* Ensure we use canonical names on open. */
2634 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2638 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2643 if (!smb_fname
->base_name
) {
2644 status
= NT_STATUS_NO_MEMORY
;
2648 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2651 status
= check_name(conn
, smb_fname
->base_name
);
2652 if (!NT_STATUS_IS_OK(status
)) {
2656 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2657 if (!NT_STATUS_IS_OK(status
)) {
2663 struct smb_Dir
*dir_hnd
= NULL
;
2665 const char *dname
= NULL
;
2666 char *talloced
= NULL
;
2668 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2669 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2673 if (strequal(fname_mask
,"????????.???")) {
2674 TALLOC_FREE(fname_mask
);
2675 fname_mask
= talloc_strdup(ctx
, "*");
2677 status
= NT_STATUS_NO_MEMORY
;
2682 status
= check_name(conn
, fname_dir
);
2683 if (!NT_STATUS_IS_OK(status
)) {
2687 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2689 if (dir_hnd
== NULL
) {
2690 status
= map_nt_error_from_unix(errno
);
2694 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2695 the pattern matches against the long name, otherwise the short name
2696 We don't implement this yet XXXX
2699 status
= NT_STATUS_NO_SUCH_FILE
;
2701 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2702 &smb_fname
->st
, &talloced
))) {
2703 TALLOC_CTX
*frame
= talloc_stackframe();
2705 if (!is_visible_file(conn
, fname_dir
, dname
,
2706 &smb_fname
->st
, true)) {
2708 TALLOC_FREE(talloced
);
2712 /* Quick check for "." and ".." */
2713 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2715 TALLOC_FREE(talloced
);
2719 if(!mask_match(dname
, fname_mask
,
2720 conn
->case_sensitive
)) {
2722 TALLOC_FREE(talloced
);
2726 TALLOC_FREE(smb_fname
->base_name
);
2727 if (ISDOT(fname_dir
)) {
2728 /* Ensure we use canonical names on open. */
2729 smb_fname
->base_name
=
2730 talloc_asprintf(smb_fname
, "%s",
2733 smb_fname
->base_name
=
2734 talloc_asprintf(smb_fname
, "%s/%s",
2738 if (!smb_fname
->base_name
) {
2739 TALLOC_FREE(dir_hnd
);
2740 status
= NT_STATUS_NO_MEMORY
;
2742 TALLOC_FREE(talloced
);
2746 status
= check_name(conn
, smb_fname
->base_name
);
2747 if (!NT_STATUS_IS_OK(status
)) {
2748 TALLOC_FREE(dir_hnd
);
2750 TALLOC_FREE(talloced
);
2754 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2755 if (!NT_STATUS_IS_OK(status
)) {
2757 TALLOC_FREE(talloced
);
2762 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2763 smb_fname
->base_name
));
2766 TALLOC_FREE(talloced
);
2768 TALLOC_FREE(dir_hnd
);
2771 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2772 status
= map_nt_error_from_unix(errno
);
2776 TALLOC_FREE(fname_dir
);
2777 TALLOC_FREE(fname_mask
);
2781 /****************************************************************************
2783 ****************************************************************************/
2785 void reply_unlink(struct smb_request
*req
)
2787 connection_struct
*conn
= req
->conn
;
2789 struct smb_filename
*smb_fname
= NULL
;
2792 bool path_contains_wcard
= False
;
2793 TALLOC_CTX
*ctx
= talloc_tos();
2795 START_PROFILE(SMBunlink
);
2798 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2802 dirtype
= SVAL(req
->vwv
+0, 0);
2804 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2805 STR_TERMINATE
, &status
,
2806 &path_contains_wcard
);
2807 if (!NT_STATUS_IS_OK(status
)) {
2808 reply_nterror(req
, status
);
2812 status
= filename_convert(ctx
, conn
,
2813 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2815 UCF_COND_ALLOW_WCARD_LCOMP
,
2816 &path_contains_wcard
,
2818 if (!NT_STATUS_IS_OK(status
)) {
2819 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2820 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2821 ERRSRV
, ERRbadpath
);
2824 reply_nterror(req
, status
);
2828 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2830 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2831 path_contains_wcard
);
2832 if (!NT_STATUS_IS_OK(status
)) {
2833 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2834 /* We have re-scheduled this call. */
2837 reply_nterror(req
, status
);
2841 reply_outbuf(req
, 0, 0);
2843 TALLOC_FREE(smb_fname
);
2844 END_PROFILE(SMBunlink
);
2848 /****************************************************************************
2850 ****************************************************************************/
2852 static void fail_readraw(void)
2854 const char *errstr
= talloc_asprintf(talloc_tos(),
2855 "FAIL ! reply_readbraw: socket write fail (%s)",
2860 exit_server_cleanly(errstr
);
2863 /****************************************************************************
2864 Fake (read/write) sendfile. Returns -1 on read or write fail.
2865 ****************************************************************************/
2867 ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
)
2870 size_t tosend
= nread
;
2877 bufsize
= MIN(nread
, 65536);
2879 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2883 while (tosend
> 0) {
2887 if (tosend
> bufsize
) {
2892 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2898 /* If we had a short read, fill with zeros. */
2899 if (ret
< cur_read
) {
2900 memset(buf
+ ret
, '\0', cur_read
- ret
);
2903 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
2905 char addr
[INET6_ADDRSTRLEN
];
2907 * Try and give an error message saying what
2910 DEBUG(0, ("write_data failed for client %s. "
2912 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
2919 startpos
+= cur_read
;
2923 return (ssize_t
)nread
;
2926 /****************************************************************************
2927 Deal with the case of sendfile reading less bytes from the file than
2928 requested. Fill with zeros (all we can do).
2929 ****************************************************************************/
2931 void sendfile_short_send(files_struct
*fsp
,
2936 #define SHORT_SEND_BUFSIZE 1024
2937 if (nread
< headersize
) {
2938 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2939 "header for file %s (%s). Terminating\n",
2940 fsp_str_dbg(fsp
), strerror(errno
)));
2941 exit_server_cleanly("sendfile_short_send failed");
2944 nread
-= headersize
;
2946 if (nread
< smb_maxcnt
) {
2947 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
2949 exit_server_cleanly("sendfile_short_send: "
2953 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2954 "with zeros !\n", fsp_str_dbg(fsp
)));
2956 while (nread
< smb_maxcnt
) {
2958 * We asked for the real file size and told sendfile
2959 * to not go beyond the end of the file. But it can
2960 * happen that in between our fstat call and the
2961 * sendfile call the file was truncated. This is very
2962 * bad because we have already announced the larger
2963 * number of bytes to the client.
2965 * The best we can do now is to send 0-bytes, just as
2966 * a read from a hole in a sparse file would do.
2968 * This should happen rarely enough that I don't care
2969 * about efficiency here :-)
2973 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
2974 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
2976 char addr
[INET6_ADDRSTRLEN
];
2978 * Try and give an error message saying what
2981 DEBUG(0, ("write_data failed for client %s. "
2984 fsp
->conn
->sconn
->sock
, addr
,
2987 exit_server_cleanly("sendfile_short_send: "
2988 "write_data failed");
2996 /****************************************************************************
2997 Return a readbraw error (4 bytes of zero).
2998 ****************************************************************************/
3000 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
3006 smbd_lock_socket(sconn
);
3007 if (write_data(sconn
->sock
,header
,4) != 4) {
3008 char addr
[INET6_ADDRSTRLEN
];
3010 * Try and give an error message saying what
3013 DEBUG(0, ("write_data failed for client %s. "
3015 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
3020 smbd_unlock_socket(sconn
);
3023 /****************************************************************************
3024 Use sendfile in readbraw.
3025 ****************************************************************************/
3027 static void send_file_readbraw(connection_struct
*conn
,
3028 struct smb_request
*req
,
3034 struct smbd_server_connection
*sconn
= req
->sconn
;
3035 char *outbuf
= NULL
;
3039 * We can only use sendfile on a non-chained packet
3040 * but we can use on a non-oplocked file. tridge proved this
3041 * on a train in Germany :-). JRA.
3042 * reply_readbraw has already checked the length.
3045 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3046 (fsp
->wcp
== NULL
) &&
3047 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3048 ssize_t sendfile_read
= -1;
3050 DATA_BLOB header_blob
;
3052 _smb_setlen(header
,nread
);
3053 header_blob
= data_blob_const(header
, 4);
3055 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3056 &header_blob
, startpos
,
3058 if (sendfile_read
== -1) {
3059 /* Returning ENOSYS means no data at all was sent.
3060 * Do this as a normal read. */
3061 if (errno
== ENOSYS
) {
3062 goto normal_readbraw
;
3066 * Special hack for broken Linux with no working sendfile. If we
3067 * return EINTR we sent the header but not the rest of the data.
3068 * Fake this up by doing read/write calls.
3070 if (errno
== EINTR
) {
3071 /* Ensure we don't do this again. */
3072 set_use_sendfile(SNUM(conn
), False
);
3073 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3075 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3076 DEBUG(0,("send_file_readbraw: "
3077 "fake_sendfile failed for "
3081 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3086 DEBUG(0,("send_file_readbraw: sendfile failed for "
3087 "file %s (%s). Terminating\n",
3088 fsp_str_dbg(fsp
), strerror(errno
)));
3089 exit_server_cleanly("send_file_readbraw sendfile failed");
3090 } else if (sendfile_read
== 0) {
3092 * Some sendfile implementations return 0 to indicate
3093 * that there was a short read, but nothing was
3094 * actually written to the socket. In this case,
3095 * fallback to the normal read path so the header gets
3096 * the correct byte count.
3098 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3099 "bytes falling back to the normal read: "
3100 "%s\n", fsp_str_dbg(fsp
)));
3101 goto normal_readbraw
;
3104 /* Deal with possible short send. */
3105 if (sendfile_read
!= 4+nread
) {
3106 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3113 outbuf
= talloc_array(NULL
, char, nread
+4);
3115 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3116 (unsigned)(nread
+4)));
3117 reply_readbraw_error(sconn
);
3122 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3123 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3132 _smb_setlen(outbuf
,ret
);
3133 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3134 char addr
[INET6_ADDRSTRLEN
];
3136 * Try and give an error message saying what
3139 DEBUG(0, ("write_data failed for client %s. "
3141 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3148 TALLOC_FREE(outbuf
);
3151 /****************************************************************************
3152 Reply to a readbraw (core+ protocol).
3153 ****************************************************************************/
3155 void reply_readbraw(struct smb_request
*req
)
3157 connection_struct
*conn
= req
->conn
;
3158 struct smbd_server_connection
*sconn
= req
->sconn
;
3159 ssize_t maxcount
,mincount
;
3163 struct lock_struct lock
;
3166 START_PROFILE(SMBreadbraw
);
3168 if (srv_is_signing_active(sconn
) ||
3169 is_encrypted_packet(sconn
, req
->inbuf
)) {
3170 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3171 "raw reads/writes are disallowed.");
3175 reply_readbraw_error(sconn
);
3176 END_PROFILE(SMBreadbraw
);
3180 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3181 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3182 "'async smb echo handler = yes'\n"));
3183 reply_readbraw_error(sconn
);
3184 END_PROFILE(SMBreadbraw
);
3189 * Special check if an oplock break has been issued
3190 * and the readraw request croses on the wire, we must
3191 * return a zero length response here.
3194 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3197 * We have to do a check_fsp by hand here, as
3198 * we must always return 4 zero bytes on error,
3202 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3203 req
->vuid
!= fsp
->vuid
||
3204 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3206 * fsp could be NULL here so use the value from the packet. JRA.
3208 DEBUG(3,("reply_readbraw: fnum %d not valid "
3210 (int)SVAL(req
->vwv
+0, 0)));
3211 reply_readbraw_error(sconn
);
3212 END_PROFILE(SMBreadbraw
);
3216 /* Do a "by hand" version of CHECK_READ. */
3217 if (!(fsp
->can_read
||
3218 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3219 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3220 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3221 (int)SVAL(req
->vwv
+0, 0)));
3222 reply_readbraw_error(sconn
);
3223 END_PROFILE(SMBreadbraw
);
3227 flush_write_cache(fsp
, READRAW_FLUSH
);
3229 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3230 if(req
->wct
== 10) {
3232 * This is a large offset (64 bit) read.
3234 #ifdef LARGE_SMB_OFF_T
3236 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+8, 0)) << 32);
3238 #else /* !LARGE_SMB_OFF_T */
3241 * Ensure we haven't been sent a >32 bit offset.
3244 if(IVAL(req
->vwv
+8, 0) != 0) {
3245 DEBUG(0,("reply_readbraw: large offset "
3246 "(%x << 32) used and we don't support "
3247 "64 bit offsets.\n",
3248 (unsigned int)IVAL(req
->vwv
+8, 0) ));
3249 reply_readbraw_error(sconn
);
3250 END_PROFILE(SMBreadbraw
);
3254 #endif /* LARGE_SMB_OFF_T */
3257 DEBUG(0,("reply_readbraw: negative 64 bit "
3258 "readraw offset (%.0f) !\n",
3259 (double)startpos
));
3260 reply_readbraw_error(sconn
);
3261 END_PROFILE(SMBreadbraw
);
3266 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3267 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3269 /* ensure we don't overrun the packet size */
3270 maxcount
= MIN(65535,maxcount
);
3272 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3273 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3276 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3277 reply_readbraw_error(sconn
);
3278 END_PROFILE(SMBreadbraw
);
3282 if (fsp_stat(fsp
) == 0) {
3283 size
= fsp
->fsp_name
->st
.st_ex_size
;
3286 if (startpos
>= size
) {
3289 nread
= MIN(maxcount
,(size
- startpos
));
3292 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3293 if (nread
< mincount
)
3297 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3298 "min=%lu nread=%lu\n",
3299 fsp
->fnum
, (double)startpos
,
3300 (unsigned long)maxcount
,
3301 (unsigned long)mincount
,
3302 (unsigned long)nread
) );
3304 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3306 DEBUG(5,("reply_readbraw finished\n"));
3308 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3310 END_PROFILE(SMBreadbraw
);
3315 #define DBGC_CLASS DBGC_LOCKING
3317 /****************************************************************************
3318 Reply to a lockread (core+ protocol).
3319 ****************************************************************************/
3321 void reply_lockread(struct smb_request
*req
)
3323 connection_struct
*conn
= req
->conn
;
3330 struct byte_range_lock
*br_lck
= NULL
;
3332 struct smbd_server_connection
*sconn
= req
->sconn
;
3334 START_PROFILE(SMBlockread
);
3337 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3338 END_PROFILE(SMBlockread
);
3342 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3344 if (!check_fsp(conn
, req
, fsp
)) {
3345 END_PROFILE(SMBlockread
);
3349 if (!CHECK_READ(fsp
,req
)) {
3350 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3351 END_PROFILE(SMBlockread
);
3355 numtoread
= SVAL(req
->vwv
+1, 0);
3356 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3358 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3360 reply_outbuf(req
, 5, numtoread
+ 3);
3362 data
= smb_buf(req
->outbuf
) + 3;
3365 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3366 * protocol request that predates the read/write lock concept.
3367 * Thus instead of asking for a read lock here we need to ask
3368 * for a write lock. JRA.
3369 * Note that the requested lock size is unaffected by max_recv.
3372 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3374 (uint64_t)req
->smbpid
,
3375 (uint64_t)numtoread
,
3379 False
, /* Non-blocking lock. */
3383 TALLOC_FREE(br_lck
);
3385 if (NT_STATUS_V(status
)) {
3386 reply_nterror(req
, status
);
3387 END_PROFILE(SMBlockread
);
3392 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3395 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3396 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3397 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3398 (unsigned int)numtoread
,
3399 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3400 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3402 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3405 reply_nterror(req
, map_nt_error_from_unix(errno
));
3406 END_PROFILE(SMBlockread
);
3410 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3412 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3413 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3414 p
= smb_buf(req
->outbuf
);
3415 SCVAL(p
,0,0); /* pad byte. */
3418 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3419 fsp
->fnum
, (int)numtoread
, (int)nread
));
3421 END_PROFILE(SMBlockread
);
3426 #define DBGC_CLASS DBGC_ALL
3428 /****************************************************************************
3430 ****************************************************************************/
3432 void reply_read(struct smb_request
*req
)
3434 connection_struct
*conn
= req
->conn
;
3441 struct lock_struct lock
;
3442 struct smbd_server_connection
*sconn
= req
->sconn
;
3444 START_PROFILE(SMBread
);
3447 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3448 END_PROFILE(SMBread
);
3452 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3454 if (!check_fsp(conn
, req
, fsp
)) {
3455 END_PROFILE(SMBread
);
3459 if (!CHECK_READ(fsp
,req
)) {
3460 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3461 END_PROFILE(SMBread
);
3465 numtoread
= SVAL(req
->vwv
+1, 0);
3466 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3468 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3471 * The requested read size cannot be greater than max_recv. JRA.
3473 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3474 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3475 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3476 (unsigned int)numtoread
,
3477 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3478 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3481 reply_outbuf(req
, 5, numtoread
+3);
3483 data
= smb_buf(req
->outbuf
) + 3;
3485 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3486 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3489 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3490 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3491 END_PROFILE(SMBread
);
3496 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3499 reply_nterror(req
, map_nt_error_from_unix(errno
));
3503 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3505 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3506 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3507 SCVAL(smb_buf(req
->outbuf
),0,1);
3508 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3510 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3511 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3514 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3516 END_PROFILE(SMBread
);
3520 /****************************************************************************
3522 ****************************************************************************/
3524 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3530 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3531 data
= smb_buf(outbuf
);
3533 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3535 SCVAL(outbuf
,smb_vwv0
,0xFF);
3536 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3537 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3538 SSVAL(outbuf
,smb_vwv6
,
3540 + 1 /* the wct field */
3541 + 12 * sizeof(uint16_t) /* vwv */
3542 + 2); /* the buflen field */
3543 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3544 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3545 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3546 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3550 /****************************************************************************
3551 Reply to a read and X - possibly using sendfile.
3552 ****************************************************************************/
3554 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3555 files_struct
*fsp
, SMB_OFF_T startpos
,
3559 struct lock_struct lock
;
3560 int saved_errno
= 0;
3562 if(fsp_stat(fsp
) == -1) {
3563 reply_nterror(req
, map_nt_error_from_unix(errno
));
3567 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3568 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3571 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3572 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3576 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3577 (startpos
> fsp
->fsp_name
->st
.st_ex_size
)
3578 || (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3580 * We already know that we would do a short read, so don't
3581 * try the sendfile() path.
3583 goto nosendfile_read
;
3587 * We can only use sendfile on a non-chained packet
3588 * but we can use on a non-oplocked file. tridge proved this
3589 * on a train in Germany :-). JRA.
3592 if (!req_is_in_chain(req
) &&
3593 !is_encrypted_packet(req
->sconn
, req
->inbuf
) &&
3594 (fsp
->base_fsp
== NULL
) &&
3595 (fsp
->wcp
== NULL
) &&
3596 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3597 uint8 headerbuf
[smb_size
+ 12 * 2];
3601 * Set up the packet header before send. We
3602 * assume here the sendfile will work (get the
3603 * correct amount of data).
3606 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3608 construct_reply_common_req(req
, (char *)headerbuf
);
3609 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3611 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3612 startpos
, smb_maxcnt
);
3614 /* Returning ENOSYS means no data at all was sent.
3615 Do this as a normal read. */
3616 if (errno
== ENOSYS
) {
3621 * Special hack for broken Linux with no working sendfile. If we
3622 * return EINTR we sent the header but not the rest of the data.
3623 * Fake this up by doing read/write calls.
3626 if (errno
== EINTR
) {
3627 /* Ensure we don't do this again. */
3628 set_use_sendfile(SNUM(conn
), False
);
3629 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3630 nread
= fake_sendfile(fsp
, startpos
,
3633 DEBUG(0,("send_file_readX: "
3634 "fake_sendfile failed for "
3638 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3640 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3641 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3642 /* No outbuf here means successful sendfile. */
3646 DEBUG(0,("send_file_readX: sendfile failed for file "
3647 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3649 exit_server_cleanly("send_file_readX sendfile failed");
3650 } else if (nread
== 0) {
3652 * Some sendfile implementations return 0 to indicate
3653 * that there was a short read, but nothing was
3654 * actually written to the socket. In this case,
3655 * fallback to the normal read path so the header gets
3656 * the correct byte count.
3658 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3659 "falling back to the normal read: %s\n",
3664 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3665 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3667 /* Deal with possible short send. */
3668 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3669 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3671 /* No outbuf here means successful sendfile. */
3672 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3673 SMB_PERFCOUNT_END(&req
->pcd
);
3679 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3680 uint8 headerbuf
[smb_size
+ 2*12];
3682 construct_reply_common_req(req
, (char *)headerbuf
);
3683 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3685 /* Send out the header. */
3686 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3687 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3689 char addr
[INET6_ADDRSTRLEN
];
3691 * Try and give an error message saying what
3694 DEBUG(0, ("write_data failed for client %s. "
3696 get_peer_addr(req
->sconn
->sock
, addr
,
3700 DEBUG(0,("send_file_readX: write_data failed for file "
3701 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3703 exit_server_cleanly("send_file_readX sendfile failed");
3705 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3707 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3708 "file %s (%s).\n", fsp_str_dbg(fsp
),
3710 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3717 reply_outbuf(req
, 12, smb_maxcnt
);
3719 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3720 saved_errno
= errno
;
3722 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3725 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3729 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3731 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3732 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3738 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3739 TALLOC_FREE(req
->outbuf
);
3743 /****************************************************************************
3744 Reply to a read and X.
3745 ****************************************************************************/
3747 void reply_read_and_X(struct smb_request
*req
)
3749 struct smbd_server_connection
*sconn
= req
->sconn
;
3750 connection_struct
*conn
= req
->conn
;
3754 bool big_readX
= False
;
3756 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3759 START_PROFILE(SMBreadX
);
3761 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3762 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3766 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3767 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3768 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3770 /* If it's an IPC, pass off the pipe handler. */
3772 reply_pipe_read_and_X(req
);
3773 END_PROFILE(SMBreadX
);
3777 if (!check_fsp(conn
, req
, fsp
)) {
3778 END_PROFILE(SMBreadX
);
3782 if (!CHECK_READ(fsp
,req
)) {
3783 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3784 END_PROFILE(SMBreadX
);
3788 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_LARGE_READ_CAP
) ||
3789 (get_remote_arch() == RA_SAMBA
)) {
3791 * This is Samba only behavior (up to Samba 3.6)!
3793 * Windows 2008 R2 ignores the upper_size,
3794 * so we do unless unix extentions are active
3795 * or "smbclient" is talking to us.
3797 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3798 smb_maxcnt
|= (upper_size
<<16);
3799 if (upper_size
> 1) {
3800 /* Can't do this on a chained packet. */
3801 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3802 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3803 END_PROFILE(SMBreadX
);
3806 /* We currently don't do this on signed or sealed data. */
3807 if (srv_is_signing_active(req
->sconn
) ||
3808 is_encrypted_packet(req
->sconn
, req
->inbuf
)) {
3809 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3810 END_PROFILE(SMBreadX
);
3813 /* Is there room in the reply for this data ? */
3814 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3816 NT_STATUS_INVALID_PARAMETER
);
3817 END_PROFILE(SMBreadX
);
3824 if (req
->wct
== 12) {
3825 #ifdef LARGE_SMB_OFF_T
3827 * This is a large offset (64 bit) read.
3829 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+10, 0)) << 32);
3831 #else /* !LARGE_SMB_OFF_T */
3834 * Ensure we haven't been sent a >32 bit offset.
3837 if(IVAL(req
->vwv
+10, 0) != 0) {
3838 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3839 "used and we don't support 64 bit offsets.\n",
3840 (unsigned int)IVAL(req
->vwv
+10, 0) ));
3841 END_PROFILE(SMBreadX
);
3842 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3846 #endif /* LARGE_SMB_OFF_T */
3851 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3856 if (NT_STATUS_IS_OK(status
)) {
3857 /* Read scheduled - we're done. */
3860 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3861 /* Real error - report to client. */
3862 END_PROFILE(SMBreadX
);
3863 reply_nterror(req
, status
);
3866 /* NT_STATUS_RETRY - fall back to sync read. */
3869 smbd_lock_socket(req
->sconn
);
3870 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3871 smbd_unlock_socket(req
->sconn
);
3874 END_PROFILE(SMBreadX
);
3878 /****************************************************************************
3879 Error replies to writebraw must have smb_wct == 1. Fix this up.
3880 ****************************************************************************/
3882 void error_to_writebrawerr(struct smb_request
*req
)
3884 uint8
*old_outbuf
= req
->outbuf
;
3886 reply_outbuf(req
, 1, 0);
3888 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3889 TALLOC_FREE(old_outbuf
);
3892 /****************************************************************************
3893 Read 4 bytes of a smb packet and return the smb length of the packet.
3894 Store the result in the buffer. This version of the function will
3895 never return a session keepalive (length of zero).
3896 Timeout is in milliseconds.
3897 ****************************************************************************/
3899 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3902 uint8_t msgtype
= NBSSkeepalive
;
3904 while (msgtype
== NBSSkeepalive
) {
3907 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3909 if (!NT_STATUS_IS_OK(status
)) {
3910 char addr
[INET6_ADDRSTRLEN
];
3911 /* Try and give an error message
3912 * saying what client failed. */
3913 DEBUG(0, ("read_fd_with_timeout failed for "
3914 "client %s read error = %s.\n",
3915 get_peer_addr(fd
,addr
,sizeof(addr
)),
3916 nt_errstr(status
)));
3920 msgtype
= CVAL(inbuf
, 0);
3923 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3924 (unsigned long)len
));
3926 return NT_STATUS_OK
;
3929 /****************************************************************************
3930 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3931 ****************************************************************************/
3933 void reply_writebraw(struct smb_request
*req
)
3935 connection_struct
*conn
= req
->conn
;
3938 ssize_t total_written
=0;
3939 size_t numtowrite
=0;
3942 const char *data
=NULL
;
3945 struct lock_struct lock
;
3948 START_PROFILE(SMBwritebraw
);
3951 * If we ever reply with an error, it must have the SMB command
3952 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3955 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
3957 if (srv_is_signing_active(req
->sconn
)) {
3958 END_PROFILE(SMBwritebraw
);
3959 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3960 "raw reads/writes are disallowed.");
3963 if (req
->wct
< 12) {
3964 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3965 error_to_writebrawerr(req
);
3966 END_PROFILE(SMBwritebraw
);
3970 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3971 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3972 "'async smb echo handler = yes'\n"));
3973 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3974 error_to_writebrawerr(req
);
3975 END_PROFILE(SMBwritebraw
);
3979 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3980 if (!check_fsp(conn
, req
, fsp
)) {
3981 error_to_writebrawerr(req
);
3982 END_PROFILE(SMBwritebraw
);
3986 if (!CHECK_WRITE(fsp
)) {
3987 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3988 error_to_writebrawerr(req
);
3989 END_PROFILE(SMBwritebraw
);
3993 tcount
= IVAL(req
->vwv
+1, 0);
3994 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3995 write_through
= BITSETW(req
->vwv
+7,0);
3997 /* We have to deal with slightly different formats depending
3998 on whether we are using the core+ or lanman1.0 protocol */
4000 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4001 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4002 data
= smb_buf_const(req
->inbuf
);
4004 numtowrite
= SVAL(req
->vwv
+10, 0);
4005 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4008 /* Ensure we don't write bytes past the end of this packet. */
4009 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4010 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4011 error_to_writebrawerr(req
);
4012 END_PROFILE(SMBwritebraw
);
4016 if (!fsp
->print_file
) {
4017 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4018 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4021 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4022 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4023 error_to_writebrawerr(req
);
4024 END_PROFILE(SMBwritebraw
);
4030 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4033 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4034 "wrote=%d sync=%d\n",
4035 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4036 (int)nwritten
, (int)write_through
));
4038 if (nwritten
< (ssize_t
)numtowrite
) {
4039 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4040 error_to_writebrawerr(req
);
4044 total_written
= nwritten
;
4046 /* Allocate a buffer of 64k + length. */
4047 buf
= talloc_array(NULL
, char, 65540);
4049 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4050 error_to_writebrawerr(req
);
4054 /* Return a SMBwritebraw message to the redirector to tell
4055 * it to send more bytes */
4057 memcpy(buf
, req
->inbuf
, smb_size
);
4058 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4059 SCVAL(buf
,smb_com
,SMBwritebraw
);
4060 SSVALS(buf
,smb_vwv0
,0xFFFF);
4062 if (!srv_send_smb(req
->sconn
,
4064 false, 0, /* no signing */
4065 IS_CONN_ENCRYPTED(conn
),
4067 exit_server_cleanly("reply_writebraw: srv_send_smb "
4071 /* Now read the raw data into the buffer and write it */
4072 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4074 if (!NT_STATUS_IS_OK(status
)) {
4075 exit_server_cleanly("secondary writebraw failed");
4078 /* Set up outbuf to return the correct size */
4079 reply_outbuf(req
, 1, 0);
4081 if (numtowrite
!= 0) {
4083 if (numtowrite
> 0xFFFF) {
4084 DEBUG(0,("reply_writebraw: Oversize secondary write "
4085 "raw requested (%u). Terminating\n",
4086 (unsigned int)numtowrite
));
4087 exit_server_cleanly("secondary writebraw failed");
4090 if (tcount
> nwritten
+numtowrite
) {
4091 DEBUG(3,("reply_writebraw: Client overestimated the "
4093 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4096 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4098 if (!NT_STATUS_IS_OK(status
)) {
4099 char addr
[INET6_ADDRSTRLEN
];
4100 /* Try and give an error message
4101 * saying what client failed. */
4102 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4103 "raw read failed (%s) for client %s. "
4104 "Terminating\n", nt_errstr(status
),
4105 get_peer_addr(req
->sconn
->sock
, addr
,
4107 exit_server_cleanly("secondary writebraw failed");
4110 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4111 if (nwritten
== -1) {
4113 reply_nterror(req
, map_nt_error_from_unix(errno
));
4114 error_to_writebrawerr(req
);
4118 if (nwritten
< (ssize_t
)numtowrite
) {
4119 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4120 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4124 total_written
+= nwritten
;
4129 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4131 status
= sync_file(conn
, fsp
, write_through
);
4132 if (!NT_STATUS_IS_OK(status
)) {
4133 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4134 fsp_str_dbg(fsp
), nt_errstr(status
)));
4135 reply_nterror(req
, status
);
4136 error_to_writebrawerr(req
);
4140 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4142 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4143 (int)total_written
));
4145 if (!fsp
->print_file
) {
4146 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4149 /* We won't return a status if write through is not selected - this
4150 * follows what WfWg does */
4151 END_PROFILE(SMBwritebraw
);
4153 if (!write_through
&& total_written
==tcount
) {
4155 #if RABBIT_PELLET_FIX
4157 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4158 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4161 if (!send_keepalive(req
->sconn
->sock
)) {
4162 exit_server_cleanly("reply_writebraw: send of "
4163 "keepalive failed");
4166 TALLOC_FREE(req
->outbuf
);
4171 if (!fsp
->print_file
) {
4172 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4175 END_PROFILE(SMBwritebraw
);
4180 #define DBGC_CLASS DBGC_LOCKING
4182 /****************************************************************************
4183 Reply to a writeunlock (core+).
4184 ****************************************************************************/
4186 void reply_writeunlock(struct smb_request
*req
)
4188 connection_struct
*conn
= req
->conn
;
4189 ssize_t nwritten
= -1;
4193 NTSTATUS status
= NT_STATUS_OK
;
4195 struct lock_struct lock
;
4196 int saved_errno
= 0;
4198 START_PROFILE(SMBwriteunlock
);
4201 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4202 END_PROFILE(SMBwriteunlock
);
4206 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4208 if (!check_fsp(conn
, req
, fsp
)) {
4209 END_PROFILE(SMBwriteunlock
);
4213 if (!CHECK_WRITE(fsp
)) {
4214 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4215 END_PROFILE(SMBwriteunlock
);
4219 numtowrite
= SVAL(req
->vwv
+1, 0);
4220 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4221 data
= (const char *)req
->buf
+ 3;
4223 if (!fsp
->print_file
&& numtowrite
> 0) {
4224 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4225 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4228 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4229 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4230 END_PROFILE(SMBwriteunlock
);
4235 /* The special X/Open SMB protocol handling of
4236 zero length writes is *NOT* done for
4238 if(numtowrite
== 0) {
4241 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4242 saved_errno
= errno
;
4245 status
= sync_file(conn
, fsp
, False
/* write through */);
4246 if (!NT_STATUS_IS_OK(status
)) {
4247 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4248 fsp_str_dbg(fsp
), nt_errstr(status
)));
4249 reply_nterror(req
, status
);
4254 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4258 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4259 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4263 if (numtowrite
&& !fsp
->print_file
) {
4264 status
= do_unlock(req
->sconn
->msg_ctx
,
4266 (uint64_t)req
->smbpid
,
4267 (uint64_t)numtowrite
,
4271 if (NT_STATUS_V(status
)) {
4272 reply_nterror(req
, status
);
4277 reply_outbuf(req
, 1, 0);
4279 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4281 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4282 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4285 if (numtowrite
&& !fsp
->print_file
) {
4286 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4289 END_PROFILE(SMBwriteunlock
);
4294 #define DBGC_CLASS DBGC_ALL
4296 /****************************************************************************
4298 ****************************************************************************/
4300 void reply_write(struct smb_request
*req
)
4302 connection_struct
*conn
= req
->conn
;
4304 ssize_t nwritten
= -1;
4308 struct lock_struct lock
;
4310 int saved_errno
= 0;
4312 START_PROFILE(SMBwrite
);
4315 END_PROFILE(SMBwrite
);
4316 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4320 /* If it's an IPC, pass off the pipe handler. */
4322 reply_pipe_write(req
);
4323 END_PROFILE(SMBwrite
);
4327 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4329 if (!check_fsp(conn
, req
, fsp
)) {
4330 END_PROFILE(SMBwrite
);
4334 if (!CHECK_WRITE(fsp
)) {
4335 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4336 END_PROFILE(SMBwrite
);
4340 numtowrite
= SVAL(req
->vwv
+1, 0);
4341 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4342 data
= (const char *)req
->buf
+ 3;
4344 if (!fsp
->print_file
) {
4345 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4346 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4349 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4350 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4351 END_PROFILE(SMBwrite
);
4357 * X/Open SMB protocol says that if smb_vwv1 is
4358 * zero then the file size should be extended or
4359 * truncated to the size given in smb_vwv[2-3].
4362 if(numtowrite
== 0) {
4364 * This is actually an allocate call, and set EOF. JRA.
4366 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
4368 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4371 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
4373 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4376 trigger_write_time_update_immediate(fsp
);
4378 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4381 status
= sync_file(conn
, fsp
, False
);
4382 if (!NT_STATUS_IS_OK(status
)) {
4383 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4384 fsp_str_dbg(fsp
), nt_errstr(status
)));
4385 reply_nterror(req
, status
);
4390 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4394 if((nwritten
== 0) && (numtowrite
!= 0)) {
4395 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4399 reply_outbuf(req
, 1, 0);
4401 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4403 if (nwritten
< (ssize_t
)numtowrite
) {
4404 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4405 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4408 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4411 if (!fsp
->print_file
) {
4412 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4415 END_PROFILE(SMBwrite
);
4419 /****************************************************************************
4420 Ensure a buffer is a valid writeX for recvfile purposes.
4421 ****************************************************************************/
4423 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4424 (2*14) + /* word count (including bcc) */ \
4427 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4428 const uint8_t *inbuf
)
4431 connection_struct
*conn
= NULL
;
4432 unsigned int doff
= 0;
4433 size_t len
= smb_len_large(inbuf
);
4435 if (is_encrypted_packet(sconn
, inbuf
)) {
4436 /* Can't do this on encrypted
4441 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4445 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4446 CVAL(inbuf
,smb_wct
) != 14) {
4447 DEBUG(10,("is_valid_writeX_buffer: chained or "
4448 "invalid word length.\n"));
4452 conn
= conn_find(sconn
, SVAL(inbuf
, smb_tid
));
4454 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4458 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4461 if (IS_PRINT(conn
)) {
4462 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4465 doff
= SVAL(inbuf
,smb_vwv11
);
4467 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4469 if (len
> doff
&& len
- doff
> 0xFFFF) {
4470 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4473 if (numtowrite
== 0) {
4474 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4478 /* Ensure the sizes match up. */
4479 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4480 /* no pad byte...old smbclient :-( */
4481 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4483 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4487 if (len
- doff
!= numtowrite
) {
4488 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4489 "len = %u, doff = %u, numtowrite = %u\n",
4492 (unsigned int)numtowrite
));
4496 DEBUG(10,("is_valid_writeX_buffer: true "
4497 "len = %u, doff = %u, numtowrite = %u\n",
4500 (unsigned int)numtowrite
));
4505 /****************************************************************************
4506 Reply to a write and X.
4507 ****************************************************************************/
4509 void reply_write_and_X(struct smb_request
*req
)
4511 connection_struct
*conn
= req
->conn
;
4513 struct lock_struct lock
;
4518 unsigned int smb_doff
;
4519 unsigned int smblen
;
4522 int saved_errno
= 0;
4524 START_PROFILE(SMBwriteX
);
4526 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4527 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4528 END_PROFILE(SMBwriteX
);
4532 numtowrite
= SVAL(req
->vwv
+10, 0);
4533 smb_doff
= SVAL(req
->vwv
+11, 0);
4534 smblen
= smb_len(req
->inbuf
);
4536 if (req
->unread_bytes
> 0xFFFF ||
4537 (smblen
> smb_doff
&&
4538 smblen
- smb_doff
> 0xFFFF)) {
4539 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4542 if (req
->unread_bytes
) {
4543 /* Can't do a recvfile write on IPC$ */
4545 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4546 END_PROFILE(SMBwriteX
);
4549 if (numtowrite
!= req
->unread_bytes
) {
4550 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4551 END_PROFILE(SMBwriteX
);
4555 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4556 smb_doff
+ numtowrite
> smblen
) {
4557 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4558 END_PROFILE(SMBwriteX
);
4563 /* If it's an IPC, pass off the pipe handler. */
4565 if (req
->unread_bytes
) {
4566 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4567 END_PROFILE(SMBwriteX
);
4570 reply_pipe_write_and_X(req
);
4571 END_PROFILE(SMBwriteX
);
4575 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4576 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4577 write_through
= BITSETW(req
->vwv
+7,0);
4579 if (!check_fsp(conn
, req
, fsp
)) {
4580 END_PROFILE(SMBwriteX
);
4584 if (!CHECK_WRITE(fsp
)) {
4585 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4586 END_PROFILE(SMBwriteX
);
4590 data
= smb_base(req
->inbuf
) + smb_doff
;
4592 if(req
->wct
== 14) {
4593 #ifdef LARGE_SMB_OFF_T
4595 * This is a large offset (64 bit) write.
4597 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+12, 0)) << 32);
4599 #else /* !LARGE_SMB_OFF_T */
4602 * Ensure we haven't been sent a >32 bit offset.
4605 if(IVAL(req
->vwv
+12, 0) != 0) {
4606 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4607 "used and we don't support 64 bit offsets.\n",
4608 (unsigned int)IVAL(req
->vwv
+12, 0) ));
4609 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4610 END_PROFILE(SMBwriteX
);
4614 #endif /* LARGE_SMB_OFF_T */
4617 /* X/Open SMB protocol says that, unlike SMBwrite
4618 if the length is zero then NO truncation is
4619 done, just a write of zero. To truncate a file,
4622 if(numtowrite
== 0) {
4625 if (req
->unread_bytes
== 0) {
4626 status
= schedule_aio_write_and_X(conn
,
4633 if (NT_STATUS_IS_OK(status
)) {
4634 /* write scheduled - we're done. */
4637 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4638 /* Real error - report to client. */
4639 reply_nterror(req
, status
);
4642 /* NT_STATUS_RETRY - fall through to sync write. */
4645 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4646 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4649 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4650 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4654 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4655 saved_errno
= errno
;
4657 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4661 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4665 if((nwritten
== 0) && (numtowrite
!= 0)) {
4666 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4670 reply_outbuf(req
, 6, 0);
4671 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4672 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4674 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4675 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4677 status
= sync_file(conn
, fsp
, write_through
);
4678 if (!NT_STATUS_IS_OK(status
)) {
4679 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4680 fsp_str_dbg(fsp
), nt_errstr(status
)));
4681 reply_nterror(req
, status
);
4685 END_PROFILE(SMBwriteX
);
4690 END_PROFILE(SMBwriteX
);
4694 /****************************************************************************
4696 ****************************************************************************/
4698 void reply_lseek(struct smb_request
*req
)
4700 connection_struct
*conn
= req
->conn
;
4706 START_PROFILE(SMBlseek
);
4709 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4710 END_PROFILE(SMBlseek
);
4714 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4716 if (!check_fsp(conn
, req
, fsp
)) {
4720 flush_write_cache(fsp
, SEEK_FLUSH
);
4722 mode
= SVAL(req
->vwv
+1, 0) & 3;
4723 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4724 startpos
= (SMB_OFF_T
)IVALS(req
->vwv
+2, 0);
4733 res
= fsp
->fh
->pos
+ startpos
;
4744 if (umode
== SEEK_END
) {
4745 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4746 if(errno
== EINVAL
) {
4747 SMB_OFF_T current_pos
= startpos
;
4749 if(fsp_stat(fsp
) == -1) {
4751 map_nt_error_from_unix(errno
));
4752 END_PROFILE(SMBlseek
);
4756 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4758 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4763 reply_nterror(req
, map_nt_error_from_unix(errno
));
4764 END_PROFILE(SMBlseek
);
4771 reply_outbuf(req
, 2, 0);
4772 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4774 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4775 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4777 END_PROFILE(SMBlseek
);
4781 /****************************************************************************
4783 ****************************************************************************/
4785 void reply_flush(struct smb_request
*req
)
4787 connection_struct
*conn
= req
->conn
;
4791 START_PROFILE(SMBflush
);
4794 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4798 fnum
= SVAL(req
->vwv
+0, 0);
4799 fsp
= file_fsp(req
, fnum
);
4801 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4806 file_sync_all(conn
);
4808 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4809 if (!NT_STATUS_IS_OK(status
)) {
4810 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4811 fsp_str_dbg(fsp
), nt_errstr(status
)));
4812 reply_nterror(req
, status
);
4813 END_PROFILE(SMBflush
);
4818 reply_outbuf(req
, 0, 0);
4820 DEBUG(3,("flush\n"));
4821 END_PROFILE(SMBflush
);
4825 /****************************************************************************
4827 conn POINTER CAN BE NULL HERE !
4828 ****************************************************************************/
4830 void reply_exit(struct smb_request
*req
)
4832 START_PROFILE(SMBexit
);
4834 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
4836 reply_outbuf(req
, 0, 0);
4838 DEBUG(3,("exit\n"));
4840 END_PROFILE(SMBexit
);
4844 /****************************************************************************
4845 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4846 ****************************************************************************/
4848 void reply_close(struct smb_request
*req
)
4850 connection_struct
*conn
= req
->conn
;
4851 NTSTATUS status
= NT_STATUS_OK
;
4852 files_struct
*fsp
= NULL
;
4853 START_PROFILE(SMBclose
);
4856 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4857 END_PROFILE(SMBclose
);
4861 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4864 * We can only use check_fsp if we know it's not a directory.
4867 if (!check_fsp_open(conn
, req
, fsp
)) {
4868 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4869 END_PROFILE(SMBclose
);
4873 if(fsp
->is_directory
) {
4875 * Special case - close NT SMB directory handle.
4877 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4878 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4882 * Close ordinary file.
4885 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4886 fsp
->fh
->fd
, fsp
->fnum
,
4887 conn
->num_files_open
));
4890 * Take care of any time sent in the close.
4893 t
= srv_make_unix_date3(req
->vwv
+1);
4894 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4897 * close_file() returns the unix errno if an error
4898 * was detected on close - normally this is due to
4899 * a disk full error. If not then it was probably an I/O error.
4902 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4905 if (!NT_STATUS_IS_OK(status
)) {
4906 reply_nterror(req
, status
);
4907 END_PROFILE(SMBclose
);
4911 reply_outbuf(req
, 0, 0);
4912 END_PROFILE(SMBclose
);
4916 /****************************************************************************
4917 Reply to a writeclose (Core+ protocol).
4918 ****************************************************************************/
4920 void reply_writeclose(struct smb_request
*req
)
4922 connection_struct
*conn
= req
->conn
;
4924 ssize_t nwritten
= -1;
4925 NTSTATUS close_status
= NT_STATUS_OK
;
4928 struct timespec mtime
;
4930 struct lock_struct lock
;
4932 START_PROFILE(SMBwriteclose
);
4935 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4936 END_PROFILE(SMBwriteclose
);
4940 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4942 if (!check_fsp(conn
, req
, fsp
)) {
4943 END_PROFILE(SMBwriteclose
);
4946 if (!CHECK_WRITE(fsp
)) {
4947 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4948 END_PROFILE(SMBwriteclose
);
4952 numtowrite
= SVAL(req
->vwv
+1, 0);
4953 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4954 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4955 data
= (const char *)req
->buf
+ 1;
4957 if (!fsp
->print_file
) {
4958 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4959 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4962 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4963 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4964 END_PROFILE(SMBwriteclose
);
4969 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4971 set_close_write_time(fsp
, mtime
);
4974 * More insanity. W2K only closes the file if writelen > 0.
4979 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4980 "file %s\n", fsp_str_dbg(fsp
)));
4981 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4984 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4985 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4986 conn
->num_files_open
));
4988 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4989 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4993 if(!NT_STATUS_IS_OK(close_status
)) {
4994 reply_nterror(req
, close_status
);
4998 reply_outbuf(req
, 1, 0);
5000 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5003 if (numtowrite
&& !fsp
->print_file
) {
5004 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5007 END_PROFILE(SMBwriteclose
);
5012 #define DBGC_CLASS DBGC_LOCKING
5014 /****************************************************************************
5016 ****************************************************************************/
5018 void reply_lock(struct smb_request
*req
)
5020 connection_struct
*conn
= req
->conn
;
5021 uint64_t count
,offset
;
5024 struct byte_range_lock
*br_lck
= NULL
;
5026 START_PROFILE(SMBlock
);
5029 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5030 END_PROFILE(SMBlock
);
5034 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5036 if (!check_fsp(conn
, req
, fsp
)) {
5037 END_PROFILE(SMBlock
);
5041 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5042 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5044 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5045 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
5047 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5049 (uint64_t)req
->smbpid
,
5054 False
, /* Non-blocking lock. */
5059 TALLOC_FREE(br_lck
);
5061 if (NT_STATUS_V(status
)) {
5062 reply_nterror(req
, status
);
5063 END_PROFILE(SMBlock
);
5067 reply_outbuf(req
, 0, 0);
5069 END_PROFILE(SMBlock
);
5073 /****************************************************************************
5075 ****************************************************************************/
5077 void reply_unlock(struct smb_request
*req
)
5079 connection_struct
*conn
= req
->conn
;
5080 uint64_t count
,offset
;
5084 START_PROFILE(SMBunlock
);
5087 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5088 END_PROFILE(SMBunlock
);
5092 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5094 if (!check_fsp(conn
, req
, fsp
)) {
5095 END_PROFILE(SMBunlock
);
5099 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5100 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5102 status
= do_unlock(req
->sconn
->msg_ctx
,
5104 (uint64_t)req
->smbpid
,
5109 if (NT_STATUS_V(status
)) {
5110 reply_nterror(req
, status
);
5111 END_PROFILE(SMBunlock
);
5115 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5116 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
5118 reply_outbuf(req
, 0, 0);
5120 END_PROFILE(SMBunlock
);
5125 #define DBGC_CLASS DBGC_ALL
5127 /****************************************************************************
5129 conn POINTER CAN BE NULL HERE !
5130 ****************************************************************************/
5132 void reply_tdis(struct smb_request
*req
)
5134 connection_struct
*conn
= req
->conn
;
5135 START_PROFILE(SMBtdis
);
5138 DEBUG(4,("Invalid connection in tdis\n"));
5139 reply_nterror(req
, NT_STATUS_NETWORK_NAME_DELETED
);
5140 END_PROFILE(SMBtdis
);
5146 close_cnum(conn
,req
->vuid
);
5149 reply_outbuf(req
, 0, 0);
5150 END_PROFILE(SMBtdis
);
5154 /****************************************************************************
5156 conn POINTER CAN BE NULL HERE !
5157 ****************************************************************************/
5159 void reply_echo(struct smb_request
*req
)
5161 connection_struct
*conn
= req
->conn
;
5162 struct smb_perfcount_data local_pcd
;
5163 struct smb_perfcount_data
*cur_pcd
;
5167 START_PROFILE(SMBecho
);
5169 smb_init_perfcount_data(&local_pcd
);
5172 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5173 END_PROFILE(SMBecho
);
5177 smb_reverb
= SVAL(req
->vwv
+0, 0);
5179 reply_outbuf(req
, 1, req
->buflen
);
5181 /* copy any incoming data back out */
5182 if (req
->buflen
> 0) {
5183 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5186 if (smb_reverb
> 100) {
5187 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5191 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5193 /* this makes sure we catch the request pcd */
5194 if (seq_num
== smb_reverb
) {
5195 cur_pcd
= &req
->pcd
;
5197 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5198 cur_pcd
= &local_pcd
;
5201 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5203 show_msg((char *)req
->outbuf
);
5204 if (!srv_send_smb(req
->sconn
,
5205 (char *)req
->outbuf
,
5206 true, req
->seqnum
+1,
5207 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5209 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5212 DEBUG(3,("echo %d times\n", smb_reverb
));
5214 TALLOC_FREE(req
->outbuf
);
5216 END_PROFILE(SMBecho
);
5220 /****************************************************************************
5221 Reply to a printopen.
5222 ****************************************************************************/
5224 void reply_printopen(struct smb_request
*req
)
5226 connection_struct
*conn
= req
->conn
;
5230 START_PROFILE(SMBsplopen
);
5233 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5234 END_PROFILE(SMBsplopen
);
5238 if (!CAN_PRINT(conn
)) {
5239 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5240 END_PROFILE(SMBsplopen
);
5244 status
= file_new(req
, conn
, &fsp
);
5245 if(!NT_STATUS_IS_OK(status
)) {
5246 reply_nterror(req
, status
);
5247 END_PROFILE(SMBsplopen
);
5251 /* Open for exclusive use, write only. */
5252 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5254 if (!NT_STATUS_IS_OK(status
)) {
5255 file_free(req
, fsp
);
5256 reply_nterror(req
, status
);
5257 END_PROFILE(SMBsplopen
);
5261 reply_outbuf(req
, 1, 0);
5262 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5264 DEBUG(3,("openprint fd=%d fnum=%d\n",
5265 fsp
->fh
->fd
, fsp
->fnum
));
5267 END_PROFILE(SMBsplopen
);
5271 /****************************************************************************
5272 Reply to a printclose.
5273 ****************************************************************************/
5275 void reply_printclose(struct smb_request
*req
)
5277 connection_struct
*conn
= req
->conn
;
5281 START_PROFILE(SMBsplclose
);
5284 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5285 END_PROFILE(SMBsplclose
);
5289 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5291 if (!check_fsp(conn
, req
, fsp
)) {
5292 END_PROFILE(SMBsplclose
);
5296 if (!CAN_PRINT(conn
)) {
5297 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5298 END_PROFILE(SMBsplclose
);
5302 DEBUG(3,("printclose fd=%d fnum=%d\n",
5303 fsp
->fh
->fd
,fsp
->fnum
));
5305 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5307 if(!NT_STATUS_IS_OK(status
)) {
5308 reply_nterror(req
, status
);
5309 END_PROFILE(SMBsplclose
);
5313 reply_outbuf(req
, 0, 0);
5315 END_PROFILE(SMBsplclose
);
5319 /****************************************************************************
5320 Reply to a printqueue.
5321 ****************************************************************************/
5323 void reply_printqueue(struct smb_request
*req
)
5325 connection_struct
*conn
= req
->conn
;
5329 START_PROFILE(SMBsplretq
);
5332 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5333 END_PROFILE(SMBsplretq
);
5337 max_count
= SVAL(req
->vwv
+0, 0);
5338 start_index
= SVAL(req
->vwv
+1, 0);
5340 /* we used to allow the client to get the cnum wrong, but that
5341 is really quite gross and only worked when there was only
5342 one printer - I think we should now only accept it if they
5343 get it right (tridge) */
5344 if (!CAN_PRINT(conn
)) {
5345 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5346 END_PROFILE(SMBsplretq
);
5350 reply_outbuf(req
, 2, 3);
5351 SSVAL(req
->outbuf
,smb_vwv0
,0);
5352 SSVAL(req
->outbuf
,smb_vwv1
,0);
5353 SCVAL(smb_buf(req
->outbuf
),0,1);
5354 SSVAL(smb_buf(req
->outbuf
),1,0);
5356 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5357 start_index
, max_count
));
5360 TALLOC_CTX
*mem_ctx
= talloc_tos();
5363 const char *sharename
= lp_servicename(SNUM(conn
));
5364 struct rpc_pipe_client
*cli
= NULL
;
5365 struct dcerpc_binding_handle
*b
= NULL
;
5366 struct policy_handle handle
;
5367 struct spoolss_DevmodeContainer devmode_ctr
;
5368 union spoolss_JobInfo
*info
;
5370 uint32_t num_to_get
;
5374 ZERO_STRUCT(handle
);
5376 status
= rpc_pipe_open_interface(conn
,
5377 &ndr_table_spoolss
.syntax_id
,
5379 conn
->sconn
->remote_address
,
5380 conn
->sconn
->msg_ctx
,
5382 if (!NT_STATUS_IS_OK(status
)) {
5383 DEBUG(0, ("reply_printqueue: "
5384 "could not connect to spoolss: %s\n",
5385 nt_errstr(status
)));
5386 reply_nterror(req
, status
);
5389 b
= cli
->binding_handle
;
5391 ZERO_STRUCT(devmode_ctr
);
5393 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5396 SEC_FLAG_MAXIMUM_ALLOWED
,
5399 if (!NT_STATUS_IS_OK(status
)) {
5400 reply_nterror(req
, status
);
5403 if (!W_ERROR_IS_OK(werr
)) {
5404 reply_nterror(req
, werror_to_ntstatus(werr
));
5408 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5416 if (!W_ERROR_IS_OK(werr
)) {
5417 reply_nterror(req
, werror_to_ntstatus(werr
));
5421 if (max_count
> 0) {
5422 first
= start_index
;
5424 first
= start_index
+ max_count
+ 1;
5427 if (first
>= count
) {
5430 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5433 for (i
= first
; i
< num_to_get
; i
++) {
5436 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5438 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5439 info
[i
].info2
.job_id
);
5441 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5447 srv_put_dos_date2(p
, 0, qtime
);
5448 SCVAL(p
, 4, qstatus
);
5449 SSVAL(p
, 5, qrapjobid
);
5450 SIVAL(p
, 7, info
[i
].info2
.size
);
5452 srvstr_push(blob
, req
->flags2
, p
+12,
5453 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5455 if (message_push_blob(
5458 blob
, sizeof(blob
))) == -1) {
5459 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5465 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5466 SSVAL(req
->outbuf
,smb_vwv1
,
5467 (max_count
>0?first
+count
:first
-1));
5468 SCVAL(smb_buf(req
->outbuf
),0,1);
5469 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5473 DEBUG(3, ("%u entries returned in queue\n",
5477 if (b
&& is_valid_policy_hnd(&handle
)) {
5478 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5483 END_PROFILE(SMBsplretq
);
5487 /****************************************************************************
5488 Reply to a printwrite.
5489 ****************************************************************************/
5491 void reply_printwrite(struct smb_request
*req
)
5493 connection_struct
*conn
= req
->conn
;
5498 START_PROFILE(SMBsplwr
);
5501 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5502 END_PROFILE(SMBsplwr
);
5506 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5508 if (!check_fsp(conn
, req
, fsp
)) {
5509 END_PROFILE(SMBsplwr
);
5513 if (!fsp
->print_file
) {
5514 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5515 END_PROFILE(SMBsplwr
);
5519 if (!CHECK_WRITE(fsp
)) {
5520 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5521 END_PROFILE(SMBsplwr
);
5525 numtowrite
= SVAL(req
->buf
, 1);
5527 if (req
->buflen
< numtowrite
+ 3) {
5528 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5529 END_PROFILE(SMBsplwr
);
5533 data
= (const char *)req
->buf
+ 3;
5535 if (write_file(req
,fsp
,data
,(SMB_OFF_T
)-1,numtowrite
) != numtowrite
) {
5536 reply_nterror(req
, map_nt_error_from_unix(errno
));
5537 END_PROFILE(SMBsplwr
);
5541 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
5543 END_PROFILE(SMBsplwr
);
5547 /****************************************************************************
5549 ****************************************************************************/
5551 void reply_mkdir(struct smb_request
*req
)
5553 connection_struct
*conn
= req
->conn
;
5554 struct smb_filename
*smb_dname
= NULL
;
5555 char *directory
= NULL
;
5557 TALLOC_CTX
*ctx
= talloc_tos();
5559 START_PROFILE(SMBmkdir
);
5561 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5562 STR_TERMINATE
, &status
);
5563 if (!NT_STATUS_IS_OK(status
)) {
5564 reply_nterror(req
, status
);
5568 status
= filename_convert(ctx
, conn
,
5569 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5574 if (!NT_STATUS_IS_OK(status
)) {
5575 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5576 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5577 ERRSRV
, ERRbadpath
);
5580 reply_nterror(req
, status
);
5584 status
= create_directory(conn
, req
, smb_dname
);
5586 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5588 if (!NT_STATUS_IS_OK(status
)) {
5590 if (!use_nt_status()
5591 && NT_STATUS_EQUAL(status
,
5592 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5594 * Yes, in the DOS error code case we get a
5595 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5596 * samba4 torture test.
5598 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5601 reply_nterror(req
, status
);
5605 reply_outbuf(req
, 0, 0);
5607 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5609 TALLOC_FREE(smb_dname
);
5610 END_PROFILE(SMBmkdir
);
5614 /****************************************************************************
5616 ****************************************************************************/
5618 void reply_rmdir(struct smb_request
*req
)
5620 connection_struct
*conn
= req
->conn
;
5621 struct smb_filename
*smb_dname
= NULL
;
5622 char *directory
= NULL
;
5624 TALLOC_CTX
*ctx
= talloc_tos();
5625 files_struct
*fsp
= NULL
;
5627 struct smbd_server_connection
*sconn
= req
->sconn
;
5629 START_PROFILE(SMBrmdir
);
5631 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5632 STR_TERMINATE
, &status
);
5633 if (!NT_STATUS_IS_OK(status
)) {
5634 reply_nterror(req
, status
);
5638 status
= filename_convert(ctx
, conn
,
5639 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5644 if (!NT_STATUS_IS_OK(status
)) {
5645 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5646 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5647 ERRSRV
, ERRbadpath
);
5650 reply_nterror(req
, status
);
5654 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5655 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5659 status
= SMB_VFS_CREATE_FILE(
5662 0, /* root_dir_fid */
5663 smb_dname
, /* fname */
5664 DELETE_ACCESS
, /* access_mask */
5665 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5667 FILE_OPEN
, /* create_disposition*/
5668 FILE_DIRECTORY_FILE
, /* create_options */
5669 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5670 0, /* oplock_request */
5671 0, /* allocation_size */
5672 0, /* private_flags */
5678 if (!NT_STATUS_IS_OK(status
)) {
5679 if (open_was_deferred(req
->sconn
, req
->mid
)) {
5680 /* We have re-scheduled this call. */
5683 reply_nterror(req
, status
);
5687 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5688 if (!NT_STATUS_IS_OK(status
)) {
5689 close_file(req
, fsp
, ERROR_CLOSE
);
5690 reply_nterror(req
, status
);
5694 if (!set_delete_on_close(fsp
, true, conn
->session_info
->unix_token
)) {
5695 close_file(req
, fsp
, ERROR_CLOSE
);
5696 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5700 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5701 if (!NT_STATUS_IS_OK(status
)) {
5702 reply_nterror(req
, status
);
5704 reply_outbuf(req
, 0, 0);
5707 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5709 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5711 TALLOC_FREE(smb_dname
);
5712 END_PROFILE(SMBrmdir
);
5716 /*******************************************************************
5717 Resolve wildcards in a filename rename.
5718 ********************************************************************/
5720 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5725 char *name2_copy
= NULL
;
5730 char *p
,*p2
, *pname1
, *pname2
;
5732 name2_copy
= talloc_strdup(ctx
, name2
);
5737 pname1
= strrchr_m(name1
,'/');
5738 pname2
= strrchr_m(name2_copy
,'/');
5740 if (!pname1
|| !pname2
) {
5744 /* Truncate the copy of name2 at the last '/' */
5747 /* Now go past the '/' */
5751 root1
= talloc_strdup(ctx
, pname1
);
5752 root2
= talloc_strdup(ctx
, pname2
);
5754 if (!root1
|| !root2
) {
5758 p
= strrchr_m(root1
,'.');
5761 ext1
= talloc_strdup(ctx
, p
+1);
5763 ext1
= talloc_strdup(ctx
, "");
5765 p
= strrchr_m(root2
,'.');
5768 ext2
= talloc_strdup(ctx
, p
+1);
5770 ext2
= talloc_strdup(ctx
, "");
5773 if (!ext1
|| !ext2
) {
5781 /* Hmmm. Should this be mb-aware ? */
5784 } else if (*p2
== '*') {
5786 root2
= talloc_asprintf(ctx
, "%s%s",
5805 /* Hmmm. Should this be mb-aware ? */
5808 } else if (*p2
== '*') {
5810 ext2
= talloc_asprintf(ctx
, "%s%s",
5826 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5831 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5843 /****************************************************************************
5844 Ensure open files have their names updated. Updated to notify other smbd's
5846 ****************************************************************************/
5848 static void rename_open_files(connection_struct
*conn
,
5849 struct share_mode_lock
*lck
,
5850 uint32_t orig_name_hash
,
5851 const struct smb_filename
*smb_fname_dst
)
5854 bool did_rename
= False
;
5856 uint32_t new_name_hash
= 0;
5858 for(fsp
= file_find_di_first(conn
->sconn
, lck
->id
); fsp
;
5859 fsp
= file_find_di_next(fsp
)) {
5860 /* fsp_name is a relative path under the fsp. To change this for other
5861 sharepaths we need to manipulate relative paths. */
5862 /* TODO - create the absolute path and manipulate the newname
5863 relative to the sharepath. */
5864 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5867 if (fsp
->name_hash
!= orig_name_hash
) {
5870 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5871 "(file_id %s) from %s -> %s\n", fsp
->fnum
,
5872 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
5873 smb_fname_str_dbg(smb_fname_dst
)));
5875 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
5876 if (NT_STATUS_IS_OK(status
)) {
5878 new_name_hash
= fsp
->name_hash
;
5883 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5884 "for %s\n", file_id_string_tos(&lck
->id
),
5885 smb_fname_str_dbg(smb_fname_dst
)));
5888 /* Send messages to all smbd's (not ourself) that the name has changed. */
5889 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, conn
->connectpath
,
5890 orig_name_hash
, new_name_hash
,
5895 /****************************************************************************
5896 We need to check if the source path is a parent directory of the destination
5897 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5898 refuse the rename with a sharing violation. Under UNIX the above call can
5899 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5900 probably need to check that the client is a Windows one before disallowing
5901 this as a UNIX client (one with UNIX extensions) can know the source is a
5902 symlink and make this decision intelligently. Found by an excellent bug
5903 report from <AndyLiebman@aol.com>.
5904 ****************************************************************************/
5906 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
5907 const struct smb_filename
*smb_fname_dst
)
5909 const char *psrc
= smb_fname_src
->base_name
;
5910 const char *pdst
= smb_fname_dst
->base_name
;
5913 if (psrc
[0] == '.' && psrc
[1] == '/') {
5916 if (pdst
[0] == '.' && pdst
[1] == '/') {
5919 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5922 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5926 * Do the notify calls from a rename
5929 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5930 const struct smb_filename
*smb_fname_src
,
5931 const struct smb_filename
*smb_fname_dst
)
5933 char *parent_dir_src
= NULL
;
5934 char *parent_dir_dst
= NULL
;
5937 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5938 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5940 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
5941 &parent_dir_src
, NULL
) ||
5942 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
5943 &parent_dir_dst
, NULL
)) {
5947 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
5948 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
5949 smb_fname_src
->base_name
);
5950 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
5951 smb_fname_dst
->base_name
);
5954 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
5955 smb_fname_src
->base_name
);
5956 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
5957 smb_fname_dst
->base_name
);
5960 /* this is a strange one. w2k3 gives an additional event for
5961 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5962 files, but not directories */
5964 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5965 FILE_NOTIFY_CHANGE_ATTRIBUTES
5966 |FILE_NOTIFY_CHANGE_CREATION
,
5967 smb_fname_dst
->base_name
);
5970 TALLOC_FREE(parent_dir_src
);
5971 TALLOC_FREE(parent_dir_dst
);
5974 /****************************************************************************
5975 Returns an error if the parent directory for a filename is open in an
5977 ****************************************************************************/
5979 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
5980 const struct smb_filename
*smb_fname_dst_in
)
5982 char *parent_dir
= NULL
;
5983 struct smb_filename smb_fname_parent
;
5985 files_struct
*fsp
= NULL
;
5988 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
5989 &parent_dir
, NULL
)) {
5990 return NT_STATUS_NO_MEMORY
;
5992 ZERO_STRUCT(smb_fname_parent
);
5993 smb_fname_parent
.base_name
= parent_dir
;
5995 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
5997 return map_nt_error_from_unix(errno
);
6001 * We're only checking on this smbd here, mostly good
6002 * enough.. and will pass tests.
6005 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6006 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6007 fsp
= file_find_di_next(fsp
)) {
6008 if (fsp
->access_mask
& DELETE_ACCESS
) {
6009 return NT_STATUS_SHARING_VIOLATION
;
6012 return NT_STATUS_OK
;
6015 /****************************************************************************
6016 Rename an open file - given an fsp.
6017 ****************************************************************************/
6019 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6021 const struct smb_filename
*smb_fname_dst_in
,
6023 bool replace_if_exists
)
6025 TALLOC_CTX
*ctx
= talloc_tos();
6026 struct smb_filename
*smb_fname_dst
= NULL
;
6027 NTSTATUS status
= NT_STATUS_OK
;
6028 struct share_mode_lock
*lck
= NULL
;
6029 bool dst_exists
, old_is_stream
, new_is_stream
;
6031 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6032 if (!NT_STATUS_IS_OK(status
)) {
6036 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6037 if (!NT_STATUS_IS_OK(status
)) {
6041 /* Make a copy of the dst smb_fname structs */
6043 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
6044 if (!NT_STATUS_IS_OK(status
)) {
6049 * Check for special case with case preserving and not
6050 * case sensitive. If the old last component differs from the original
6051 * last component only by case, then we should allow
6052 * the rename (user is trying to change the case of the
6055 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6056 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6057 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6059 char *fname_dst_lcomp_base_mod
= NULL
;
6060 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6063 * Get the last component of the destination name.
6065 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6067 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6069 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6071 if (!fname_dst_lcomp_base_mod
) {
6072 status
= NT_STATUS_NO_MEMORY
;
6077 * Create an smb_filename struct using the original last
6078 * component of the destination.
6080 status
= create_synthetic_smb_fname_split(ctx
,
6081 smb_fname_dst
->original_lcomp
, NULL
,
6082 &smb_fname_orig_lcomp
);
6083 if (!NT_STATUS_IS_OK(status
)) {
6084 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6088 /* If the base names only differ by case, use original. */
6089 if(!strcsequal(fname_dst_lcomp_base_mod
,
6090 smb_fname_orig_lcomp
->base_name
)) {
6093 * Replace the modified last component with the
6097 *last_slash
= '\0'; /* Truncate at the '/' */
6098 tmp
= talloc_asprintf(smb_fname_dst
,
6100 smb_fname_dst
->base_name
,
6101 smb_fname_orig_lcomp
->base_name
);
6103 tmp
= talloc_asprintf(smb_fname_dst
,
6105 smb_fname_orig_lcomp
->base_name
);
6108 status
= NT_STATUS_NO_MEMORY
;
6109 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6110 TALLOC_FREE(smb_fname_orig_lcomp
);
6113 TALLOC_FREE(smb_fname_dst
->base_name
);
6114 smb_fname_dst
->base_name
= tmp
;
6117 /* If the stream_names only differ by case, use original. */
6118 if(!strcsequal(smb_fname_dst
->stream_name
,
6119 smb_fname_orig_lcomp
->stream_name
)) {
6121 /* Use the original stream. */
6122 tmp
= talloc_strdup(smb_fname_dst
,
6123 smb_fname_orig_lcomp
->stream_name
);
6125 status
= NT_STATUS_NO_MEMORY
;
6126 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6127 TALLOC_FREE(smb_fname_orig_lcomp
);
6130 TALLOC_FREE(smb_fname_dst
->stream_name
);
6131 smb_fname_dst
->stream_name
= tmp
;
6133 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6134 TALLOC_FREE(smb_fname_orig_lcomp
);
6138 * If the src and dest names are identical - including case,
6139 * don't do the rename, just return success.
6142 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6143 strcsequal(fsp
->fsp_name
->stream_name
,
6144 smb_fname_dst
->stream_name
)) {
6145 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6146 "- returning success\n",
6147 smb_fname_str_dbg(smb_fname_dst
)));
6148 status
= NT_STATUS_OK
;
6152 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6153 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6155 /* Return the correct error code if both names aren't streams. */
6156 if (!old_is_stream
&& new_is_stream
) {
6157 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6161 if (old_is_stream
&& !new_is_stream
) {
6162 status
= NT_STATUS_INVALID_PARAMETER
;
6166 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6168 if(!replace_if_exists
&& dst_exists
) {
6169 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6170 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6171 smb_fname_str_dbg(smb_fname_dst
)));
6172 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6177 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6178 &smb_fname_dst
->st
);
6179 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6181 /* The file can be open when renaming a stream */
6182 if (dst_fsp
&& !new_is_stream
) {
6183 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6184 status
= NT_STATUS_ACCESS_DENIED
;
6189 /* Ensure we have a valid stat struct for the source. */
6190 status
= vfs_stat_fsp(fsp
);
6191 if (!NT_STATUS_IS_OK(status
)) {
6195 status
= can_rename(conn
, fsp
, attrs
);
6197 if (!NT_STATUS_IS_OK(status
)) {
6198 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6199 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6200 smb_fname_str_dbg(smb_fname_dst
)));
6201 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6202 status
= NT_STATUS_ACCESS_DENIED
;
6206 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6207 status
= NT_STATUS_ACCESS_DENIED
;
6210 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6214 * We have the file open ourselves, so not being able to get the
6215 * corresponding share mode lock is a fatal error.
6218 SMB_ASSERT(lck
!= NULL
);
6220 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6221 uint32 create_options
= fsp
->fh
->private_options
;
6223 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6224 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6225 smb_fname_str_dbg(smb_fname_dst
)));
6227 if (!lp_posix_pathnames() &&
6228 (lp_map_archive(SNUM(conn
)) ||
6229 lp_store_dos_attributes(SNUM(conn
)))) {
6230 /* We must set the archive bit on the newly
6232 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6233 uint32_t old_dosmode
= dos_mode(conn
,
6235 file_set_dosmode(conn
,
6237 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6243 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6246 rename_open_files(conn
, lck
, fsp
->name_hash
, smb_fname_dst
);
6249 * A rename acts as a new file create w.r.t. allowing an initial delete
6250 * on close, probably because in Windows there is a new handle to the
6251 * new file. If initial delete on close was requested but not
6252 * originally set, we need to set it here. This is probably not 100% correct,
6253 * but will work for the CIFSFS client which in non-posix mode
6254 * depends on these semantics. JRA.
6257 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6258 status
= can_set_delete_on_close(fsp
, 0);
6260 if (NT_STATUS_IS_OK(status
)) {
6261 /* Note that here we set the *inital* delete on close flag,
6262 * not the regular one. The magic gets handled in close. */
6263 fsp
->initial_delete_on_close
= True
;
6267 status
= NT_STATUS_OK
;
6273 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6274 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6276 status
= map_nt_error_from_unix(errno
);
6279 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6280 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6281 smb_fname_str_dbg(smb_fname_dst
)));
6284 TALLOC_FREE(smb_fname_dst
);
6289 /****************************************************************************
6290 The guts of the rename command, split out so it may be called by the NT SMB
6292 ****************************************************************************/
6294 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6295 connection_struct
*conn
,
6296 struct smb_request
*req
,
6297 struct smb_filename
*smb_fname_src
,
6298 struct smb_filename
*smb_fname_dst
,
6300 bool replace_if_exists
,
6303 uint32_t access_mask
)
6305 char *fname_src_dir
= NULL
;
6306 char *fname_src_mask
= NULL
;
6308 NTSTATUS status
= NT_STATUS_OK
;
6309 struct smb_Dir
*dir_hnd
= NULL
;
6310 const char *dname
= NULL
;
6311 char *talloced
= NULL
;
6313 int create_options
= 0;
6314 bool posix_pathnames
= lp_posix_pathnames();
6317 * Split the old name into directory and last component
6318 * strings. Note that unix_convert may have stripped off a
6319 * leading ./ from both name and newname if the rename is
6320 * at the root of the share. We need to make sure either both
6321 * name and newname contain a / character or neither of them do
6322 * as this is checked in resolve_wildcards().
6325 /* Split up the directory from the filename/mask. */
6326 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6327 &fname_src_dir
, &fname_src_mask
);
6328 if (!NT_STATUS_IS_OK(status
)) {
6329 status
= NT_STATUS_NO_MEMORY
;
6334 * We should only check the mangled cache
6335 * here if unix_convert failed. This means
6336 * that the path in 'mask' doesn't exist
6337 * on the file system and so we need to look
6338 * for a possible mangle. This patch from
6339 * Tine Smukavec <valentin.smukavec@hermes.si>.
6342 if (!VALID_STAT(smb_fname_src
->st
) &&
6343 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6344 char *new_mask
= NULL
;
6345 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6348 TALLOC_FREE(fname_src_mask
);
6349 fname_src_mask
= new_mask
;
6353 if (!src_has_wild
) {
6357 * Only one file needs to be renamed. Append the mask back
6358 * onto the directory.
6360 TALLOC_FREE(smb_fname_src
->base_name
);
6361 if (ISDOT(fname_src_dir
)) {
6362 /* Ensure we use canonical names on open. */
6363 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6367 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6372 if (!smb_fname_src
->base_name
) {
6373 status
= NT_STATUS_NO_MEMORY
;
6377 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6378 "case_preserve = %d, short case preserve = %d, "
6379 "directory = %s, newname = %s, "
6380 "last_component_dest = %s\n",
6381 conn
->case_sensitive
, conn
->case_preserve
,
6382 conn
->short_case_preserve
,
6383 smb_fname_str_dbg(smb_fname_src
),
6384 smb_fname_str_dbg(smb_fname_dst
),
6385 smb_fname_dst
->original_lcomp
));
6387 /* The dest name still may have wildcards. */
6388 if (dest_has_wild
) {
6389 char *fname_dst_mod
= NULL
;
6390 if (!resolve_wildcards(smb_fname_dst
,
6391 smb_fname_src
->base_name
,
6392 smb_fname_dst
->base_name
,
6394 DEBUG(6, ("rename_internals: resolve_wildcards "
6396 smb_fname_src
->base_name
,
6397 smb_fname_dst
->base_name
));
6398 status
= NT_STATUS_NO_MEMORY
;
6401 TALLOC_FREE(smb_fname_dst
->base_name
);
6402 smb_fname_dst
->base_name
= fname_dst_mod
;
6405 ZERO_STRUCT(smb_fname_src
->st
);
6406 if (posix_pathnames
) {
6407 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6409 SMB_VFS_STAT(conn
, smb_fname_src
);
6412 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6413 create_options
|= FILE_DIRECTORY_FILE
;
6416 status
= SMB_VFS_CREATE_FILE(
6419 0, /* root_dir_fid */
6420 smb_fname_src
, /* fname */
6421 access_mask
, /* access_mask */
6422 (FILE_SHARE_READ
| /* share_access */
6424 FILE_OPEN
, /* create_disposition*/
6425 create_options
, /* create_options */
6426 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6427 0, /* oplock_request */
6428 0, /* allocation_size */
6429 0, /* private_flags */
6435 if (!NT_STATUS_IS_OK(status
)) {
6436 DEBUG(3, ("Could not open rename source %s: %s\n",
6437 smb_fname_str_dbg(smb_fname_src
),
6438 nt_errstr(status
)));
6442 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6443 attrs
, replace_if_exists
);
6445 close_file(req
, fsp
, NORMAL_CLOSE
);
6447 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6448 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6449 smb_fname_str_dbg(smb_fname_dst
)));
6455 * Wildcards - process each file that matches.
6457 if (strequal(fname_src_mask
, "????????.???")) {
6458 TALLOC_FREE(fname_src_mask
);
6459 fname_src_mask
= talloc_strdup(ctx
, "*");
6460 if (!fname_src_mask
) {
6461 status
= NT_STATUS_NO_MEMORY
;
6466 status
= check_name(conn
, fname_src_dir
);
6467 if (!NT_STATUS_IS_OK(status
)) {
6471 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6473 if (dir_hnd
== NULL
) {
6474 status
= map_nt_error_from_unix(errno
);
6478 status
= NT_STATUS_NO_SUCH_FILE
;
6480 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6481 * - gentest fix. JRA
6484 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6486 files_struct
*fsp
= NULL
;
6487 char *destname
= NULL
;
6488 bool sysdir_entry
= False
;
6490 /* Quick check for "." and ".." */
6491 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6492 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6493 sysdir_entry
= True
;
6495 TALLOC_FREE(talloced
);
6500 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6501 &smb_fname_src
->st
, false)) {
6502 TALLOC_FREE(talloced
);
6506 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6507 TALLOC_FREE(talloced
);
6512 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6516 TALLOC_FREE(smb_fname_src
->base_name
);
6517 if (ISDOT(fname_src_dir
)) {
6518 /* Ensure we use canonical names on open. */
6519 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6523 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6528 if (!smb_fname_src
->base_name
) {
6529 status
= NT_STATUS_NO_MEMORY
;
6533 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6534 smb_fname_dst
->base_name
,
6536 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6537 smb_fname_src
->base_name
, destname
));
6538 TALLOC_FREE(talloced
);
6542 status
= NT_STATUS_NO_MEMORY
;
6546 TALLOC_FREE(smb_fname_dst
->base_name
);
6547 smb_fname_dst
->base_name
= destname
;
6549 ZERO_STRUCT(smb_fname_src
->st
);
6550 if (posix_pathnames
) {
6551 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6553 SMB_VFS_STAT(conn
, smb_fname_src
);
6558 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6559 create_options
|= FILE_DIRECTORY_FILE
;
6562 status
= SMB_VFS_CREATE_FILE(
6565 0, /* root_dir_fid */
6566 smb_fname_src
, /* fname */
6567 access_mask
, /* access_mask */
6568 (FILE_SHARE_READ
| /* share_access */
6570 FILE_OPEN
, /* create_disposition*/
6571 create_options
, /* create_options */
6572 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6573 0, /* oplock_request */
6574 0, /* allocation_size */
6575 0, /* private_flags */
6581 if (!NT_STATUS_IS_OK(status
)) {
6582 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6583 "returned %s rename %s -> %s\n",
6585 smb_fname_str_dbg(smb_fname_src
),
6586 smb_fname_str_dbg(smb_fname_dst
)));
6590 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6592 if (!smb_fname_dst
->original_lcomp
) {
6593 status
= NT_STATUS_NO_MEMORY
;
6597 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6598 attrs
, replace_if_exists
);
6600 close_file(req
, fsp
, NORMAL_CLOSE
);
6602 if (!NT_STATUS_IS_OK(status
)) {
6603 DEBUG(3, ("rename_internals_fsp returned %s for "
6604 "rename %s -> %s\n", nt_errstr(status
),
6605 smb_fname_str_dbg(smb_fname_src
),
6606 smb_fname_str_dbg(smb_fname_dst
)));
6612 DEBUG(3,("rename_internals: doing rename on %s -> "
6613 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6614 smb_fname_str_dbg(smb_fname_src
)));
6615 TALLOC_FREE(talloced
);
6617 TALLOC_FREE(dir_hnd
);
6619 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6620 status
= map_nt_error_from_unix(errno
);
6624 TALLOC_FREE(talloced
);
6625 TALLOC_FREE(fname_src_dir
);
6626 TALLOC_FREE(fname_src_mask
);
6630 /****************************************************************************
6632 ****************************************************************************/
6634 void reply_mv(struct smb_request
*req
)
6636 connection_struct
*conn
= req
->conn
;
6638 char *newname
= NULL
;
6642 bool src_has_wcard
= False
;
6643 bool dest_has_wcard
= False
;
6644 TALLOC_CTX
*ctx
= talloc_tos();
6645 struct smb_filename
*smb_fname_src
= NULL
;
6646 struct smb_filename
*smb_fname_dst
= NULL
;
6647 uint32_t src_ucf_flags
= lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP
: UCF_COND_ALLOW_WCARD_LCOMP
;
6648 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
| (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP
);
6649 bool stream_rename
= false;
6651 START_PROFILE(SMBmv
);
6654 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6658 attrs
= SVAL(req
->vwv
+0, 0);
6660 p
= (const char *)req
->buf
+ 1;
6661 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6662 &status
, &src_has_wcard
);
6663 if (!NT_STATUS_IS_OK(status
)) {
6664 reply_nterror(req
, status
);
6668 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6669 &status
, &dest_has_wcard
);
6670 if (!NT_STATUS_IS_OK(status
)) {
6671 reply_nterror(req
, status
);
6675 if (!lp_posix_pathnames()) {
6676 /* The newname must begin with a ':' if the
6677 name contains a ':'. */
6678 if (strchr_m(name
, ':')) {
6679 if (newname
[0] != ':') {
6680 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6683 stream_rename
= true;
6687 status
= filename_convert(ctx
,
6689 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6695 if (!NT_STATUS_IS_OK(status
)) {
6696 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6697 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6698 ERRSRV
, ERRbadpath
);
6701 reply_nterror(req
, status
);
6705 status
= filename_convert(ctx
,
6707 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6713 if (!NT_STATUS_IS_OK(status
)) {
6714 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6715 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6716 ERRSRV
, ERRbadpath
);
6719 reply_nterror(req
, status
);
6723 if (stream_rename
) {
6724 /* smb_fname_dst->base_name must be the same as
6725 smb_fname_src->base_name. */
6726 TALLOC_FREE(smb_fname_dst
->base_name
);
6727 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6728 smb_fname_src
->base_name
);
6729 if (!smb_fname_dst
->base_name
) {
6730 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6735 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6736 smb_fname_str_dbg(smb_fname_dst
)));
6738 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
6739 attrs
, False
, src_has_wcard
, dest_has_wcard
,
6741 if (!NT_STATUS_IS_OK(status
)) {
6742 if (open_was_deferred(req
->sconn
, req
->mid
)) {
6743 /* We have re-scheduled this call. */
6746 reply_nterror(req
, status
);
6750 reply_outbuf(req
, 0, 0);
6752 TALLOC_FREE(smb_fname_src
);
6753 TALLOC_FREE(smb_fname_dst
);
6758 /*******************************************************************
6759 Copy a file as part of a reply_copy.
6760 ******************************************************************/
6763 * TODO: check error codes on all callers
6766 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6767 connection_struct
*conn
,
6768 struct smb_filename
*smb_fname_src
,
6769 struct smb_filename
*smb_fname_dst
,
6772 bool target_is_directory
)
6774 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
6776 files_struct
*fsp1
,*fsp2
;
6778 uint32 new_create_disposition
;
6782 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
6783 if (!NT_STATUS_IS_OK(status
)) {
6788 * If the target is a directory, extract the last component from the
6789 * src filename and append it to the dst filename
6791 if (target_is_directory
) {
6794 /* dest/target can't be a stream if it's a directory. */
6795 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
6797 p
= strrchr_m(smb_fname_src
->base_name
,'/');
6801 p
= smb_fname_src
->base_name
;
6803 smb_fname_dst_tmp
->base_name
=
6804 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
6806 if (!smb_fname_dst_tmp
->base_name
) {
6807 status
= NT_STATUS_NO_MEMORY
;
6812 status
= vfs_file_exist(conn
, smb_fname_src
);
6813 if (!NT_STATUS_IS_OK(status
)) {
6817 if (!target_is_directory
&& count
) {
6818 new_create_disposition
= FILE_OPEN
;
6820 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
6823 &new_create_disposition
,
6826 status
= NT_STATUS_INVALID_PARAMETER
;
6831 /* Open the src file for reading. */
6832 status
= SMB_VFS_CREATE_FILE(
6835 0, /* root_dir_fid */
6836 smb_fname_src
, /* fname */
6837 FILE_GENERIC_READ
, /* access_mask */
6838 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6839 FILE_OPEN
, /* create_disposition*/
6840 0, /* create_options */
6841 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6842 INTERNAL_OPEN_ONLY
, /* oplock_request */
6843 0, /* allocation_size */
6844 0, /* private_flags */
6850 if (!NT_STATUS_IS_OK(status
)) {
6854 dosattrs
= dos_mode(conn
, smb_fname_src
);
6856 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
6857 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
6860 /* Open the dst file for writing. */
6861 status
= SMB_VFS_CREATE_FILE(
6864 0, /* root_dir_fid */
6865 smb_fname_dst
, /* fname */
6866 FILE_GENERIC_WRITE
, /* access_mask */
6867 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6868 new_create_disposition
, /* create_disposition*/
6869 0, /* create_options */
6870 dosattrs
, /* file_attributes */
6871 INTERNAL_OPEN_ONLY
, /* oplock_request */
6872 0, /* allocation_size */
6873 0, /* private_flags */
6879 if (!NT_STATUS_IS_OK(status
)) {
6880 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6884 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
6885 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
6887 DEBUG(0, ("error - vfs lseek returned error %s\n",
6889 status
= map_nt_error_from_unix(errno
);
6890 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6891 close_file(NULL
, fsp2
, ERROR_CLOSE
);
6896 /* Do the actual copy. */
6897 if (smb_fname_src
->st
.st_ex_size
) {
6898 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
6903 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
6905 /* Ensure the modtime is set correctly on the destination file. */
6906 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
6909 * As we are opening fsp1 read-only we only expect
6910 * an error on close on fsp2 if we are out of space.
6911 * Thus we don't look at the error return from the
6914 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
6916 if (!NT_STATUS_IS_OK(status
)) {
6920 if (ret
!= (SMB_OFF_T
)smb_fname_src
->st
.st_ex_size
) {
6921 status
= NT_STATUS_DISK_FULL
;
6925 status
= NT_STATUS_OK
;
6928 TALLOC_FREE(smb_fname_dst_tmp
);
6932 /****************************************************************************
6933 Reply to a file copy.
6934 ****************************************************************************/
6936 void reply_copy(struct smb_request
*req
)
6938 connection_struct
*conn
= req
->conn
;
6939 struct smb_filename
*smb_fname_src
= NULL
;
6940 struct smb_filename
*smb_fname_dst
= NULL
;
6941 char *fname_src
= NULL
;
6942 char *fname_dst
= NULL
;
6943 char *fname_src_mask
= NULL
;
6944 char *fname_src_dir
= NULL
;
6947 int error
= ERRnoaccess
;
6951 bool target_is_directory
=False
;
6952 bool source_has_wild
= False
;
6953 bool dest_has_wild
= False
;
6955 TALLOC_CTX
*ctx
= talloc_tos();
6957 START_PROFILE(SMBcopy
);
6960 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6964 tid2
= SVAL(req
->vwv
+0, 0);
6965 ofun
= SVAL(req
->vwv
+1, 0);
6966 flags
= SVAL(req
->vwv
+2, 0);
6968 p
= (const char *)req
->buf
;
6969 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
6970 &status
, &source_has_wild
);
6971 if (!NT_STATUS_IS_OK(status
)) {
6972 reply_nterror(req
, status
);
6975 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
6976 &status
, &dest_has_wild
);
6977 if (!NT_STATUS_IS_OK(status
)) {
6978 reply_nterror(req
, status
);
6982 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
6984 if (tid2
!= conn
->cnum
) {
6985 /* can't currently handle inter share copies XXXX */
6986 DEBUG(3,("Rejecting inter-share copy\n"));
6987 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
6991 status
= filename_convert(ctx
, conn
,
6992 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6994 UCF_COND_ALLOW_WCARD_LCOMP
,
6997 if (!NT_STATUS_IS_OK(status
)) {
6998 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6999 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7000 ERRSRV
, ERRbadpath
);
7003 reply_nterror(req
, status
);
7007 status
= filename_convert(ctx
, conn
,
7008 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7010 UCF_COND_ALLOW_WCARD_LCOMP
,
7013 if (!NT_STATUS_IS_OK(status
)) {
7014 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7015 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7016 ERRSRV
, ERRbadpath
);
7019 reply_nterror(req
, status
);
7023 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7025 if ((flags
&1) && target_is_directory
) {
7026 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7030 if ((flags
&2) && !target_is_directory
) {
7031 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7035 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7036 /* wants a tree copy! XXXX */
7037 DEBUG(3,("Rejecting tree copy\n"));
7038 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7042 /* Split up the directory from the filename/mask. */
7043 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7044 &fname_src_dir
, &fname_src_mask
);
7045 if (!NT_STATUS_IS_OK(status
)) {
7046 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7051 * We should only check the mangled cache
7052 * here if unix_convert failed. This means
7053 * that the path in 'mask' doesn't exist
7054 * on the file system and so we need to look
7055 * for a possible mangle. This patch from
7056 * Tine Smukavec <valentin.smukavec@hermes.si>.
7058 if (!VALID_STAT(smb_fname_src
->st
) &&
7059 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7060 char *new_mask
= NULL
;
7061 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7062 &new_mask
, conn
->params
);
7064 /* Use demangled name if one was successfully found. */
7066 TALLOC_FREE(fname_src_mask
);
7067 fname_src_mask
= new_mask
;
7071 if (!source_has_wild
) {
7074 * Only one file needs to be copied. Append the mask back onto
7077 TALLOC_FREE(smb_fname_src
->base_name
);
7078 if (ISDOT(fname_src_dir
)) {
7079 /* Ensure we use canonical names on open. */
7080 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7084 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7089 if (!smb_fname_src
->base_name
) {
7090 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7094 if (dest_has_wild
) {
7095 char *fname_dst_mod
= NULL
;
7096 if (!resolve_wildcards(smb_fname_dst
,
7097 smb_fname_src
->base_name
,
7098 smb_fname_dst
->base_name
,
7100 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7103 TALLOC_FREE(smb_fname_dst
->base_name
);
7104 smb_fname_dst
->base_name
= fname_dst_mod
;
7107 status
= check_name(conn
, smb_fname_src
->base_name
);
7108 if (!NT_STATUS_IS_OK(status
)) {
7109 reply_nterror(req
, status
);
7113 status
= check_name(conn
, smb_fname_dst
->base_name
);
7114 if (!NT_STATUS_IS_OK(status
)) {
7115 reply_nterror(req
, status
);
7119 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7120 ofun
, count
, target_is_directory
);
7122 if(!NT_STATUS_IS_OK(status
)) {
7123 reply_nterror(req
, status
);
7129 struct smb_Dir
*dir_hnd
= NULL
;
7130 const char *dname
= NULL
;
7131 char *talloced
= NULL
;
7135 * There is a wildcard that requires us to actually read the
7136 * src dir and copy each file matching the mask to the dst.
7137 * Right now streams won't be copied, but this could
7138 * presumably be added with a nested loop for reach dir entry.
7140 SMB_ASSERT(!smb_fname_src
->stream_name
);
7141 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7143 smb_fname_src
->stream_name
= NULL
;
7144 smb_fname_dst
->stream_name
= NULL
;
7146 if (strequal(fname_src_mask
,"????????.???")) {
7147 TALLOC_FREE(fname_src_mask
);
7148 fname_src_mask
= talloc_strdup(ctx
, "*");
7149 if (!fname_src_mask
) {
7150 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7155 status
= check_name(conn
, fname_src_dir
);
7156 if (!NT_STATUS_IS_OK(status
)) {
7157 reply_nterror(req
, status
);
7161 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7162 if (dir_hnd
== NULL
) {
7163 status
= map_nt_error_from_unix(errno
);
7164 reply_nterror(req
, status
);
7170 /* Iterate over the src dir copying each entry to the dst. */
7171 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7172 &smb_fname_src
->st
, &talloced
))) {
7173 char *destname
= NULL
;
7175 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7176 TALLOC_FREE(talloced
);
7180 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7181 &smb_fname_src
->st
, false)) {
7182 TALLOC_FREE(talloced
);
7186 if(!mask_match(dname
, fname_src_mask
,
7187 conn
->case_sensitive
)) {
7188 TALLOC_FREE(talloced
);
7192 error
= ERRnoaccess
;
7194 /* Get the src smb_fname struct setup. */
7195 TALLOC_FREE(smb_fname_src
->base_name
);
7196 if (ISDOT(fname_src_dir
)) {
7197 /* Ensure we use canonical names on open. */
7198 smb_fname_src
->base_name
=
7199 talloc_asprintf(smb_fname_src
, "%s",
7202 smb_fname_src
->base_name
=
7203 talloc_asprintf(smb_fname_src
, "%s/%s",
7204 fname_src_dir
, dname
);
7207 if (!smb_fname_src
->base_name
) {
7208 TALLOC_FREE(dir_hnd
);
7209 TALLOC_FREE(talloced
);
7210 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7214 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7215 smb_fname_dst
->base_name
,
7217 TALLOC_FREE(talloced
);
7221 TALLOC_FREE(dir_hnd
);
7222 TALLOC_FREE(talloced
);
7223 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7227 TALLOC_FREE(smb_fname_dst
->base_name
);
7228 smb_fname_dst
->base_name
= destname
;
7230 status
= check_name(conn
, smb_fname_src
->base_name
);
7231 if (!NT_STATUS_IS_OK(status
)) {
7232 TALLOC_FREE(dir_hnd
);
7233 TALLOC_FREE(talloced
);
7234 reply_nterror(req
, status
);
7238 status
= check_name(conn
, smb_fname_dst
->base_name
);
7239 if (!NT_STATUS_IS_OK(status
)) {
7240 TALLOC_FREE(dir_hnd
);
7241 TALLOC_FREE(talloced
);
7242 reply_nterror(req
, status
);
7246 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7247 smb_fname_src
->base_name
,
7248 smb_fname_dst
->base_name
));
7250 status
= copy_file(ctx
, conn
, smb_fname_src
,
7251 smb_fname_dst
, ofun
, count
,
7252 target_is_directory
);
7253 if (NT_STATUS_IS_OK(status
)) {
7257 TALLOC_FREE(talloced
);
7259 TALLOC_FREE(dir_hnd
);
7263 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7267 reply_outbuf(req
, 1, 0);
7268 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7270 TALLOC_FREE(smb_fname_src
);
7271 TALLOC_FREE(smb_fname_dst
);
7272 TALLOC_FREE(fname_src
);
7273 TALLOC_FREE(fname_dst
);
7274 TALLOC_FREE(fname_src_mask
);
7275 TALLOC_FREE(fname_src_dir
);
7277 END_PROFILE(SMBcopy
);
7282 #define DBGC_CLASS DBGC_LOCKING
7284 /****************************************************************************
7285 Get a lock pid, dealing with large count requests.
7286 ****************************************************************************/
7288 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7289 bool large_file_format
)
7291 if(!large_file_format
)
7292 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7294 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7297 /****************************************************************************
7298 Get a lock count, dealing with large count requests.
7299 ****************************************************************************/
7301 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7302 bool large_file_format
)
7306 if(!large_file_format
) {
7307 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7310 #if defined(HAVE_LONGLONG)
7311 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7312 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7313 #else /* HAVE_LONGLONG */
7316 * NT4.x seems to be broken in that it sends large file (64 bit)
7317 * lockingX calls even if the CAP_LARGE_FILES was *not*
7318 * negotiated. For boxes without large unsigned ints truncate the
7319 * lock count by dropping the top 32 bits.
7322 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7323 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7324 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7325 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7326 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7329 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7330 #endif /* HAVE_LONGLONG */
7336 #if !defined(HAVE_LONGLONG)
7337 /****************************************************************************
7338 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7339 ****************************************************************************/
7341 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7345 uint32 highcopy
= high
;
7348 * Try and find out how many significant bits there are in high.
7351 for(i
= 0; highcopy
; i
++)
7355 * We use 31 bits not 32 here as POSIX
7356 * lock offsets may not be negative.
7359 mask
= (~0) << (31 - i
);
7362 return 0; /* Fail. */
7368 #endif /* !defined(HAVE_LONGLONG) */
7370 /****************************************************************************
7371 Get a lock offset, dealing with large offset requests.
7372 ****************************************************************************/
7374 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7375 bool large_file_format
, bool *err
)
7377 uint64_t offset
= 0;
7381 if(!large_file_format
) {
7382 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7385 #if defined(HAVE_LONGLONG)
7386 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7387 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7388 #else /* HAVE_LONGLONG */
7391 * NT4.x seems to be broken in that it sends large file (64 bit)
7392 * lockingX calls even if the CAP_LARGE_FILES was *not*
7393 * negotiated. For boxes without large unsigned ints mangle the
7394 * lock offset by mapping the top 32 bits onto the lower 32.
7397 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7398 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7399 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7402 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7404 return (uint64_t)-1;
7407 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7408 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7409 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7410 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7413 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7414 #endif /* HAVE_LONGLONG */
7420 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7424 uint16_t num_ulocks
,
7425 struct smbd_lock_element
*ulocks
,
7427 struct smbd_lock_element
*locks
,
7430 connection_struct
*conn
= req
->conn
;
7432 NTSTATUS status
= NT_STATUS_OK
;
7436 /* Data now points at the beginning of the list
7437 of smb_unlkrng structs */
7438 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7439 struct smbd_lock_element
*e
= &ulocks
[i
];
7441 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7442 "pid %u, file %s\n",
7445 (unsigned int)e
->smblctx
,
7448 if (e
->brltype
!= UNLOCK_LOCK
) {
7449 /* this can only happen with SMB2 */
7450 return NT_STATUS_INVALID_PARAMETER
;
7453 status
= do_unlock(req
->sconn
->msg_ctx
,
7460 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7461 nt_errstr(status
)));
7463 if (!NT_STATUS_IS_OK(status
)) {
7468 /* Setup the timeout in seconds. */
7470 if (!lp_blocking_locks(SNUM(conn
))) {
7474 /* Data now points at the beginning of the list
7475 of smb_lkrng structs */
7477 for(i
= 0; i
< (int)num_locks
; i
++) {
7478 struct smbd_lock_element
*e
= &locks
[i
];
7480 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7481 "%llu, file %s timeout = %d\n",
7484 (unsigned long long)e
->smblctx
,
7488 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7489 struct blocking_lock_record
*blr
= NULL
;
7491 if (num_locks
> 1) {
7493 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7494 * if the lock vector contains one entry. When given mutliple cancel
7495 * requests in a single PDU we expect the server to return an
7496 * error. Windows servers seem to accept the request but only
7497 * cancel the first lock.
7498 * JRA - Do what Windows does (tm) :-).
7502 /* MS-CIFS (2.2.4.32.1) behavior. */
7503 return NT_STATUS_DOS(ERRDOS
,
7504 ERRcancelviolation
);
7506 /* Windows behavior. */
7508 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7509 "cancel request\n"));
7515 if (lp_blocking_locks(SNUM(conn
))) {
7517 /* Schedule a message to ourselves to
7518 remove the blocking lock record and
7519 return the right error. */
7521 blr
= blocking_lock_cancel_smb1(fsp
,
7527 NT_STATUS_FILE_LOCK_CONFLICT
);
7529 return NT_STATUS_DOS(
7531 ERRcancelviolation
);
7534 /* Remove a matching pending lock. */
7535 status
= do_lock_cancel(fsp
,
7542 bool blocking_lock
= timeout
? true : false;
7543 bool defer_lock
= false;
7544 struct byte_range_lock
*br_lck
;
7545 uint64_t block_smblctx
;
7547 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7559 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7560 /* Windows internal resolution for blocking locks seems
7561 to be about 200ms... Don't wait for less than that. JRA. */
7562 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7563 timeout
= lp_lock_spin_time();
7568 /* If a lock sent with timeout of zero would fail, and
7569 * this lock has been requested multiple times,
7570 * according to brl_lock_failed() we convert this
7571 * request to a blocking lock with a timeout of between
7572 * 150 - 300 milliseconds.
7574 * If lp_lock_spin_time() has been set to 0, we skip
7575 * this blocking retry and fail immediately.
7577 * Replacement for do_lock_spin(). JRA. */
7579 if (!req
->sconn
->using_smb2
&&
7580 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7581 lp_lock_spin_time() && !blocking_lock
&&
7582 NT_STATUS_EQUAL((status
),
7583 NT_STATUS_FILE_LOCK_CONFLICT
))
7586 timeout
= lp_lock_spin_time();
7589 if (br_lck
&& defer_lock
) {
7591 * A blocking lock was requested. Package up
7592 * this smb into a queued request and push it
7593 * onto the blocking lock queue.
7595 if(push_blocking_lock_request(br_lck
,
7606 TALLOC_FREE(br_lck
);
7608 return NT_STATUS_OK
;
7612 TALLOC_FREE(br_lck
);
7615 if (!NT_STATUS_IS_OK(status
)) {
7620 /* If any of the above locks failed, then we must unlock
7621 all of the previous locks (X/Open spec). */
7623 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7625 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7626 i
= -1; /* we want to skip the for loop */
7630 * Ensure we don't do a remove on the lock that just failed,
7631 * as under POSIX rules, if we have a lock already there, we
7632 * will delete it (and we shouldn't) .....
7634 for(i
--; i
>= 0; i
--) {
7635 struct smbd_lock_element
*e
= &locks
[i
];
7637 do_unlock(req
->sconn
->msg_ctx
,
7647 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7648 fsp
->fnum
, (unsigned int)type
, num_locks
, num_ulocks
));
7650 return NT_STATUS_OK
;
7653 /****************************************************************************
7654 Reply to a lockingX request.
7655 ****************************************************************************/
7657 void reply_lockingX(struct smb_request
*req
)
7659 connection_struct
*conn
= req
->conn
;
7661 unsigned char locktype
;
7662 unsigned char oplocklevel
;
7667 const uint8_t *data
;
7668 bool large_file_format
;
7670 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7671 struct smbd_lock_element
*ulocks
;
7672 struct smbd_lock_element
*locks
;
7675 START_PROFILE(SMBlockingX
);
7678 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7679 END_PROFILE(SMBlockingX
);
7683 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7684 locktype
= CVAL(req
->vwv
+3, 0);
7685 oplocklevel
= CVAL(req
->vwv
+3, 1);
7686 num_ulocks
= SVAL(req
->vwv
+6, 0);
7687 num_locks
= SVAL(req
->vwv
+7, 0);
7688 lock_timeout
= IVAL(req
->vwv
+4, 0);
7689 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7691 if (!check_fsp(conn
, req
, fsp
)) {
7692 END_PROFILE(SMBlockingX
);
7698 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7699 /* we don't support these - and CANCEL_LOCK makes w2k
7700 and XP reboot so I don't really want to be
7701 compatible! (tridge) */
7702 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7703 END_PROFILE(SMBlockingX
);
7707 /* Check if this is an oplock break on a file
7708 we have granted an oplock on.
7710 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7711 /* Client can insist on breaking to none. */
7712 bool break_to_none
= (oplocklevel
== 0);
7715 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7716 "for fnum = %d\n", (unsigned int)oplocklevel
,
7720 * Make sure we have granted an exclusive or batch oplock on
7724 if (fsp
->oplock_type
== 0) {
7726 /* The Samba4 nbench simulator doesn't understand
7727 the difference between break to level2 and break
7728 to none from level2 - it sends oplock break
7729 replies in both cases. Don't keep logging an error
7730 message here - just ignore it. JRA. */
7732 DEBUG(5,("reply_lockingX: Error : oplock break from "
7733 "client for fnum = %d (oplock=%d) and no "
7734 "oplock granted on this file (%s).\n",
7735 fsp
->fnum
, fsp
->oplock_type
,
7738 /* if this is a pure oplock break request then don't
7740 if (num_locks
== 0 && num_ulocks
== 0) {
7741 END_PROFILE(SMBlockingX
);
7744 END_PROFILE(SMBlockingX
);
7745 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
7750 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7752 result
= remove_oplock(fsp
);
7754 result
= downgrade_oplock(fsp
);
7758 DEBUG(0, ("reply_lockingX: error in removing "
7759 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7760 /* Hmmm. Is this panic justified? */
7761 smb_panic("internal tdb error");
7764 reply_to_oplock_break_requests(fsp
);
7766 /* if this is a pure oplock break request then don't send a
7768 if (num_locks
== 0 && num_ulocks
== 0) {
7769 /* Sanity check - ensure a pure oplock break is not a
7771 if(CVAL(req
->vwv
+0, 0) != 0xff)
7772 DEBUG(0,("reply_lockingX: Error : pure oplock "
7773 "break is a chained %d request !\n",
7774 (unsigned int)CVAL(req
->vwv
+0, 0)));
7775 END_PROFILE(SMBlockingX
);
7781 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7782 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7783 END_PROFILE(SMBlockingX
);
7787 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
7788 if (ulocks
== NULL
) {
7789 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7790 END_PROFILE(SMBlockingX
);
7794 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
7795 if (locks
== NULL
) {
7796 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7797 END_PROFILE(SMBlockingX
);
7801 /* Data now points at the beginning of the list
7802 of smb_unlkrng structs */
7803 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7804 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7805 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7806 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7807 ulocks
[i
].brltype
= UNLOCK_LOCK
;
7810 * There is no error code marked "stupid client bug".... :-).
7813 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7814 END_PROFILE(SMBlockingX
);
7819 /* Now do any requested locks */
7820 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
7822 /* Data now points at the beginning of the list
7823 of smb_lkrng structs */
7825 for(i
= 0; i
< (int)num_locks
; i
++) {
7826 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7827 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7828 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7830 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
7831 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7832 locks
[i
].brltype
= PENDING_READ_LOCK
;
7834 locks
[i
].brltype
= READ_LOCK
;
7837 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7838 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
7840 locks
[i
].brltype
= WRITE_LOCK
;
7845 * There is no error code marked "stupid client bug".... :-).
7848 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7849 END_PROFILE(SMBlockingX
);
7854 status
= smbd_do_locking(req
, fsp
,
7855 locktype
, lock_timeout
,
7859 if (!NT_STATUS_IS_OK(status
)) {
7860 END_PROFILE(SMBlockingX
);
7861 reply_nterror(req
, status
);
7865 END_PROFILE(SMBlockingX
);
7869 reply_outbuf(req
, 2, 0);
7871 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7872 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7874 END_PROFILE(SMBlockingX
);
7879 #define DBGC_CLASS DBGC_ALL
7881 /****************************************************************************
7882 Reply to a SMBreadbmpx (read block multiplex) request.
7883 Always reply with an error, if someone has a platform really needs this,
7884 please contact vl@samba.org
7885 ****************************************************************************/
7887 void reply_readbmpx(struct smb_request
*req
)
7889 START_PROFILE(SMBreadBmpx
);
7890 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7891 END_PROFILE(SMBreadBmpx
);
7895 /****************************************************************************
7896 Reply to a SMBreadbs (read block multiplex secondary) 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_readbs(struct smb_request
*req
)
7903 START_PROFILE(SMBreadBs
);
7904 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7905 END_PROFILE(SMBreadBs
);
7909 /****************************************************************************
7910 Reply to a SMBsetattrE.
7911 ****************************************************************************/
7913 void reply_setattrE(struct smb_request
*req
)
7915 connection_struct
*conn
= req
->conn
;
7916 struct smb_file_time ft
;
7920 START_PROFILE(SMBsetattrE
);
7924 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7928 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7930 if(!fsp
|| (fsp
->conn
!= conn
)) {
7931 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7936 * Convert the DOS times into unix times.
7939 ft
.atime
= convert_time_t_to_timespec(
7940 srv_make_unix_date2(req
->vwv
+3));
7941 ft
.mtime
= convert_time_t_to_timespec(
7942 srv_make_unix_date2(req
->vwv
+5));
7943 ft
.create_time
= convert_time_t_to_timespec(
7944 srv_make_unix_date2(req
->vwv
+1));
7946 reply_outbuf(req
, 0, 0);
7949 * Patch from Ray Frush <frush@engr.colostate.edu>
7950 * Sometimes times are sent as zero - ignore them.
7953 /* Ensure we have a valid stat struct for the source. */
7954 status
= vfs_stat_fsp(fsp
);
7955 if (!NT_STATUS_IS_OK(status
)) {
7956 reply_nterror(req
, status
);
7960 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
7961 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7965 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
7966 if (!NT_STATUS_IS_OK(status
)) {
7967 reply_nterror(req
, status
);
7971 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7974 (unsigned int)ft
.atime
.tv_sec
,
7975 (unsigned int)ft
.mtime
.tv_sec
,
7976 (unsigned int)ft
.create_time
.tv_sec
7979 END_PROFILE(SMBsetattrE
);
7984 /* Back from the dead for OS/2..... JRA. */
7986 /****************************************************************************
7987 Reply to a SMBwritebmpx (write block multiplex primary) request.
7988 Always reply with an error, if someone has a platform really needs this,
7989 please contact vl@samba.org
7990 ****************************************************************************/
7992 void reply_writebmpx(struct smb_request
*req
)
7994 START_PROFILE(SMBwriteBmpx
);
7995 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7996 END_PROFILE(SMBwriteBmpx
);
8000 /****************************************************************************
8001 Reply to a SMBwritebs (write block multiplex secondary) request.
8002 Always reply with an error, if someone has a platform really needs this,
8003 please contact vl@samba.org
8004 ****************************************************************************/
8006 void reply_writebs(struct smb_request
*req
)
8008 START_PROFILE(SMBwriteBs
);
8009 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8010 END_PROFILE(SMBwriteBs
);
8014 /****************************************************************************
8015 Reply to a SMBgetattrE.
8016 ****************************************************************************/
8018 void reply_getattrE(struct smb_request
*req
)
8020 connection_struct
*conn
= req
->conn
;
8023 struct timespec create_ts
;
8025 START_PROFILE(SMBgetattrE
);
8028 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8029 END_PROFILE(SMBgetattrE
);
8033 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8035 if(!fsp
|| (fsp
->conn
!= conn
)) {
8036 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8037 END_PROFILE(SMBgetattrE
);
8041 /* Do an fstat on this file */
8043 reply_nterror(req
, map_nt_error_from_unix(errno
));
8044 END_PROFILE(SMBgetattrE
);
8048 mode
= dos_mode(conn
, fsp
->fsp_name
);
8051 * Convert the times into dos times. Set create
8052 * date to be last modify date as UNIX doesn't save
8056 reply_outbuf(req
, 11, 0);
8058 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8059 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8060 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8061 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8062 /* Should we check pending modtime here ? JRA */
8063 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8064 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8066 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8067 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8068 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8070 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8071 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
8072 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8074 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8076 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
8078 END_PROFILE(SMBgetattrE
);