2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/cli_spoolss.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_server/rpc_ncacn_np.h"
38 #include "libcli/security/security.h"
39 #include "libsmb/nmblib.h"
41 #include "smbprofile.h"
42 #include "../lib/tsocket/tsocket.h"
44 /****************************************************************************
45 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
46 path or anything including wildcards.
47 We're assuming here that '/' is not the second byte in any multibyte char
48 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
50 ****************************************************************************/
52 /* Custom version for processing POSIX paths. */
53 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
55 static NTSTATUS
check_path_syntax_internal(char *path
,
57 bool *p_last_component_contains_wcard
)
61 NTSTATUS ret
= NT_STATUS_OK
;
62 bool start_of_name_component
= True
;
63 bool stream_started
= false;
65 *p_last_component_contains_wcard
= False
;
72 return NT_STATUS_OBJECT_NAME_INVALID
;
75 return NT_STATUS_OBJECT_NAME_INVALID
;
77 if (strchr_m(&s
[1], ':')) {
78 return NT_STATUS_OBJECT_NAME_INVALID
;
84 if ((*s
== ':') && !posix_path
&& !stream_started
) {
85 if (*p_last_component_contains_wcard
) {
86 return NT_STATUS_OBJECT_NAME_INVALID
;
88 /* Stream names allow more characters than file names.
89 We're overloading posix_path here to allow a wider
90 range of characters. If stream_started is true this
91 is still a Windows path even if posix_path is true.
94 stream_started
= true;
95 start_of_name_component
= false;
99 return NT_STATUS_OBJECT_NAME_INVALID
;
103 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
105 * Safe to assume is not the second part of a mb char
106 * as this is handled below.
108 /* Eat multiple '/' or '\\' */
109 while (IS_PATH_SEP(*s
,posix_path
)) {
112 if ((d
!= path
) && (*s
!= '\0')) {
113 /* We only care about non-leading or trailing '/' or '\\' */
117 start_of_name_component
= True
;
119 *p_last_component_contains_wcard
= False
;
123 if (start_of_name_component
) {
124 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
125 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
128 * No mb char starts with '.' so we're safe checking the directory separator here.
131 /* If we just added a '/' - delete it */
132 if ((d
> path
) && (*(d
-1) == '/')) {
137 /* Are we at the start ? Can't go back further if so. */
139 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
142 /* Go back one level... */
143 /* We know this is safe as '/' cannot be part of a mb sequence. */
144 /* NOTE - if this assumption is invalid we are not in good shape... */
145 /* Decrement d first as d points to the *next* char to write into. */
146 for (d
--; d
> path
; d
--) {
150 s
+= 2; /* Else go past the .. */
151 /* We're still at the start of a name component, just the previous one. */
154 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
166 if (*s
<= 0x1f || *s
== '|') {
167 return NT_STATUS_OBJECT_NAME_INVALID
;
175 *p_last_component_contains_wcard
= True
;
184 /* Get the size of the next MB character. */
185 next_codepoint(s
,&siz
);
203 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
205 return NT_STATUS_INVALID_PARAMETER
;
208 start_of_name_component
= False
;
216 /****************************************************************************
217 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
218 No wildcards allowed.
219 ****************************************************************************/
221 NTSTATUS
check_path_syntax(char *path
)
224 return check_path_syntax_internal(path
, False
, &ignore
);
227 /****************************************************************************
228 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
229 Wildcards allowed - p_contains_wcard returns true if the last component contained
231 ****************************************************************************/
233 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
235 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
238 /****************************************************************************
239 Check the path for a POSIX client.
240 We're assuming here that '/' is not the second byte in any multibyte char
241 set (a safe assumption).
242 ****************************************************************************/
244 NTSTATUS
check_path_syntax_posix(char *path
)
247 return check_path_syntax_internal(path
, True
, &ignore
);
250 /****************************************************************************
251 Pull a string and check the path allowing a wilcard - provide for error return.
252 ****************************************************************************/
254 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
255 const char *base_ptr
,
262 bool *contains_wcard
)
268 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
272 *err
= NT_STATUS_INVALID_PARAMETER
;
276 *contains_wcard
= False
;
278 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
280 * For a DFS path the function parse_dfs_path()
281 * will do the path processing, just make a copy.
287 if (lp_posix_pathnames()) {
288 *err
= check_path_syntax_posix(*pp_dest
);
290 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
296 /****************************************************************************
297 Pull a string and check the path - provide for error return.
298 ****************************************************************************/
300 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
301 const char *base_ptr
,
310 return srvstr_get_path_wcard(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
311 src_len
, flags
, err
, &ignore
);
314 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
315 char **pp_dest
, const char *src
, int flags
,
316 NTSTATUS
*err
, bool *contains_wcard
)
318 return srvstr_get_path_wcard(mem_ctx
, (const char *)req
->inbuf
, req
->flags2
,
319 pp_dest
, src
, smbreq_bufrem(req
, src
),
320 flags
, err
, contains_wcard
);
323 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
324 char **pp_dest
, const char *src
, int flags
,
328 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
329 flags
, err
, &ignore
);
332 /****************************************************************************
333 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
334 ****************************************************************************/
336 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
339 if ((fsp
== NULL
) || (conn
== NULL
)) {
340 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
343 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
344 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
350 /****************************************************************************
351 Check if we have a correct fsp pointing to a file.
352 ****************************************************************************/
354 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
357 if (!check_fsp_open(conn
, req
, fsp
)) {
360 if (fsp
->is_directory
) {
361 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
364 if (fsp
->fh
->fd
== -1) {
365 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
368 fsp
->num_smb_operations
++;
372 /****************************************************************************
373 Check if we have a correct fsp pointing to a quota fake file. Replacement for
374 the CHECK_NTQUOTA_HANDLE_OK macro.
375 ****************************************************************************/
377 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
380 if (!check_fsp_open(conn
, req
, fsp
)) {
384 if (fsp
->is_directory
) {
388 if (fsp
->fake_file_handle
== NULL
) {
392 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
396 if (fsp
->fake_file_handle
->private_data
== NULL
) {
403 static bool netbios_session_retarget(struct smbd_server_connection
*sconn
,
404 const char *name
, int name_type
)
407 char *trim_name_type
;
408 const char *retarget_parm
;
411 int retarget_type
= 0x20;
412 int retarget_port
= 139;
413 struct sockaddr_storage retarget_addr
;
414 struct sockaddr_in
*in_addr
;
418 if (get_socket_port(sconn
->sock
) != 139) {
422 trim_name
= talloc_strdup(talloc_tos(), name
);
423 if (trim_name
== NULL
) {
426 trim_char(trim_name
, ' ', ' ');
428 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
430 if (trim_name_type
== NULL
) {
434 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
435 trim_name_type
, NULL
);
436 if (retarget_parm
== NULL
) {
437 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
440 if (retarget_parm
== NULL
) {
444 retarget
= talloc_strdup(trim_name
, retarget_parm
);
445 if (retarget
== NULL
) {
449 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
451 p
= strchr(retarget
, ':');
454 retarget_port
= atoi(p
);
457 p
= strchr_m(retarget
, '#');
460 if (sscanf(p
, "%x", &retarget_type
) != 1) {
465 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
467 DEBUG(10, ("could not resolve %s\n", retarget
));
471 if (retarget_addr
.ss_family
!= AF_INET
) {
472 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
476 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
478 _smb_setlen(outbuf
, 6);
479 SCVAL(outbuf
, 0, 0x84);
480 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
481 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
483 if (!srv_send_smb(sconn
, (char *)outbuf
, false, 0, false,
485 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
491 TALLOC_FREE(trim_name
);
495 static void reply_called_name_not_present(char *outbuf
)
497 smb_setlen(outbuf
, 1);
498 SCVAL(outbuf
, 0, 0x83);
499 SCVAL(outbuf
, 4, 0x82);
502 /****************************************************************************
503 Reply to a (netbios-level) special message.
504 ****************************************************************************/
506 void reply_special(struct smbd_server_connection
*sconn
, char *inbuf
, size_t inbuf_size
)
508 int msg_type
= CVAL(inbuf
,0);
509 int msg_flags
= CVAL(inbuf
,1);
511 * We only really use 4 bytes of the outbuf, but for the smb_setlen
512 * calculation & friends (srv_send_smb uses that) we need the full smb
515 char outbuf
[smb_size
];
517 memset(outbuf
, '\0', sizeof(outbuf
));
519 smb_setlen(outbuf
,0);
522 case NBSSrequest
: /* session request */
524 /* inbuf_size is guarenteed to be at least 4. */
526 int name_type1
, name_type2
;
527 int name_len1
, name_len2
;
531 if (sconn
->nbt
.got_session
) {
532 exit_server_cleanly("multiple session request not permitted");
535 SCVAL(outbuf
,0,NBSSpositive
);
538 /* inbuf_size is guaranteed to be at least 4. */
539 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
540 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
541 DEBUG(0,("Invalid name length in session request\n"));
542 reply_called_name_not_present(outbuf
);
545 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
546 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
547 DEBUG(0,("Invalid name length in session request\n"));
548 reply_called_name_not_present(outbuf
);
552 name_type1
= name_extract((unsigned char *)inbuf
,
553 inbuf_size
,(unsigned int)4,name1
);
554 name_type2
= name_extract((unsigned char *)inbuf
,
555 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
557 if (name_type1
== -1 || name_type2
== -1) {
558 DEBUG(0,("Invalid name type in session request\n"));
559 reply_called_name_not_present(outbuf
);
563 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
564 name1
, name_type1
, name2
, name_type2
));
566 if (netbios_session_retarget(sconn
, name1
, name_type1
)) {
567 exit_server_cleanly("retargeted client");
571 * Windows NT/2k uses "*SMBSERVER" and XP uses
572 * "*SMBSERV" arrggg!!!
574 if (strequal(name1
, "*SMBSERVER ")
575 || strequal(name1
, "*SMBSERV ")) {
578 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
581 exit_server_cleanly("could not allocate raddr");
584 fstrcpy(name1
, raddr
);
587 set_local_machine_name(name1
, True
);
588 set_remote_machine_name(name2
, True
);
590 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
591 get_local_machine_name(), get_remote_machine_name(),
594 if (name_type2
== 'R') {
595 /* We are being asked for a pathworks session ---
597 reply_called_name_not_present(outbuf
);
601 /* only add the client's machine name to the list
602 of possibly valid usernames if we are operating
603 in share mode security */
604 if (lp_security() == SEC_SHARE
) {
605 add_session_user(sconn
, get_remote_machine_name());
608 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
611 sconn
->nbt
.got_session
= true;
615 case 0x89: /* session keepalive request
616 (some old clients produce this?) */
617 SCVAL(outbuf
,0,NBSSkeepalive
);
621 case NBSSpositive
: /* positive session response */
622 case NBSSnegative
: /* negative session response */
623 case NBSSretarget
: /* retarget session response */
624 DEBUG(0,("Unexpected session response\n"));
627 case NBSSkeepalive
: /* session keepalive */
632 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
633 msg_type
, msg_flags
));
635 srv_send_smb(sconn
, outbuf
, false, 0, false, NULL
);
637 if (CVAL(outbuf
, 0) != 0x82) {
638 exit_server_cleanly("invalid netbios session");
643 /****************************************************************************
645 conn POINTER CAN BE NULL HERE !
646 ****************************************************************************/
648 void reply_tcon(struct smb_request
*req
)
650 connection_struct
*conn
= req
->conn
;
652 char *service_buf
= NULL
;
653 char *password
= NULL
;
658 DATA_BLOB password_blob
;
659 TALLOC_CTX
*ctx
= talloc_tos();
660 struct smbd_server_connection
*sconn
= req
->sconn
;
662 START_PROFILE(SMBtcon
);
664 if (req
->buflen
< 4) {
665 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
666 END_PROFILE(SMBtcon
);
670 p
= (const char *)req
->buf
+ 1;
671 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
673 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
675 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
678 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
679 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
680 END_PROFILE(SMBtcon
);
683 p
= strrchr_m(service_buf
,'\\');
687 service
= service_buf
;
690 password_blob
= data_blob(password
, pwlen
+1);
692 conn
= make_connection(sconn
,service
,password_blob
,dev
,
693 req
->vuid
,&nt_status
);
696 data_blob_clear_free(&password_blob
);
699 reply_nterror(req
, nt_status
);
700 END_PROFILE(SMBtcon
);
704 reply_outbuf(req
, 2, 0);
705 SSVAL(req
->outbuf
,smb_vwv0
,sconn
->smb1
.negprot
.max_recv
);
706 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
707 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
709 DEBUG(3,("tcon service=%s cnum=%d\n",
710 service
, conn
->cnum
));
712 END_PROFILE(SMBtcon
);
716 /****************************************************************************
717 Reply to a tcon and X.
718 conn POINTER CAN BE NULL HERE !
719 ****************************************************************************/
721 void reply_tcon_and_X(struct smb_request
*req
)
723 connection_struct
*conn
= req
->conn
;
724 const char *service
= NULL
;
726 TALLOC_CTX
*ctx
= talloc_tos();
727 /* what the cleint thinks the device is */
728 char *client_devicetype
= NULL
;
729 /* what the server tells the client the share represents */
730 const char *server_devicetype
;
736 struct smbd_server_connection
*sconn
= req
->sconn
;
738 START_PROFILE(SMBtconX
);
741 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
742 END_PROFILE(SMBtconX
);
746 passlen
= SVAL(req
->vwv
+3, 0);
747 tcon_flags
= SVAL(req
->vwv
+2, 0);
749 /* we might have to close an old one */
750 if ((tcon_flags
& 0x1) && conn
) {
751 close_cnum(conn
,req
->vuid
);
756 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
757 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
758 END_PROFILE(SMBtconX
);
762 if (sconn
->smb1
.negprot
.encrypted_passwords
) {
763 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
);
764 if (lp_security() == SEC_SHARE
) {
766 * Security = share always has a pad byte
767 * after the password.
769 p
= (const char *)req
->buf
+ passlen
+ 1;
771 p
= (const char *)req
->buf
+ passlen
;
774 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
+1);
775 /* Ensure correct termination */
776 password
.data
[passlen
]=0;
777 p
= (const char *)req
->buf
+ passlen
+ 1;
780 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
783 data_blob_clear_free(&password
);
784 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
785 END_PROFILE(SMBtconX
);
790 * the service name can be either: \\server\share
791 * or share directly like on the DELL PowerVault 705
794 q
= strchr_m(path
+2,'\\');
796 data_blob_clear_free(&password
);
797 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
798 END_PROFILE(SMBtconX
);
806 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
807 &client_devicetype
, p
,
808 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
810 if (client_devicetype
== NULL
) {
811 data_blob_clear_free(&password
);
812 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
813 END_PROFILE(SMBtconX
);
817 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
819 conn
= make_connection(sconn
, service
, password
, client_devicetype
,
820 req
->vuid
, &nt_status
);
823 data_blob_clear_free(&password
);
826 reply_nterror(req
, nt_status
);
827 END_PROFILE(SMBtconX
);
832 server_devicetype
= "IPC";
833 else if ( IS_PRINT(conn
) )
834 server_devicetype
= "LPT1:";
836 server_devicetype
= "A:";
838 if (get_Protocol() < PROTOCOL_NT1
) {
839 reply_outbuf(req
, 2, 0);
840 if (message_push_string(&req
->outbuf
, server_devicetype
,
841 STR_TERMINATE
|STR_ASCII
) == -1) {
842 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
843 END_PROFILE(SMBtconX
);
847 /* NT sets the fstype of IPC$ to the null string */
848 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
850 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
851 /* Return permissions. */
855 reply_outbuf(req
, 7, 0);
858 perm1
= FILE_ALL_ACCESS
;
859 perm2
= FILE_ALL_ACCESS
;
861 perm1
= conn
->share_access
;
864 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
865 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
867 reply_outbuf(req
, 3, 0);
870 if ((message_push_string(&req
->outbuf
, server_devicetype
,
871 STR_TERMINATE
|STR_ASCII
) == -1)
872 || (message_push_string(&req
->outbuf
, fstype
,
873 STR_TERMINATE
) == -1)) {
874 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
875 END_PROFILE(SMBtconX
);
879 /* what does setting this bit do? It is set by NT4 and
880 may affect the ability to autorun mounted cdroms */
881 SSVAL(req
->outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
882 (lp_csc_policy(SNUM(conn
)) << 2));
884 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
885 DEBUG(2,("Serving %s as a Dfs root\n",
886 lp_servicename(SNUM(conn
)) ));
887 SSVAL(req
->outbuf
, smb_vwv2
,
888 SMB_SHARE_IN_DFS
| SVAL(req
->outbuf
, smb_vwv2
));
893 DEBUG(3,("tconX service=%s \n",
896 /* set the incoming and outgoing tid to the just created one */
897 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
898 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
900 END_PROFILE(SMBtconX
);
902 req
->tid
= conn
->cnum
;
907 /****************************************************************************
908 Reply to an unknown type.
909 ****************************************************************************/
911 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
913 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
914 smb_fn_name(type
), type
, type
));
915 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
919 /****************************************************************************
921 conn POINTER CAN BE NULL HERE !
922 ****************************************************************************/
924 void reply_ioctl(struct smb_request
*req
)
926 connection_struct
*conn
= req
->conn
;
933 START_PROFILE(SMBioctl
);
936 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
937 END_PROFILE(SMBioctl
);
941 device
= SVAL(req
->vwv
+1, 0);
942 function
= SVAL(req
->vwv
+2, 0);
943 ioctl_code
= (device
<< 16) + function
;
945 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
947 switch (ioctl_code
) {
948 case IOCTL_QUERY_JOB_INFO
:
952 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
953 END_PROFILE(SMBioctl
);
957 reply_outbuf(req
, 8, replysize
+1);
958 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
959 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
960 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
961 p
= smb_buf(req
->outbuf
);
962 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
963 p
+= 1; /* Allow for alignment */
965 switch (ioctl_code
) {
966 case IOCTL_QUERY_JOB_INFO
:
968 files_struct
*fsp
= file_fsp(
969 req
, SVAL(req
->vwv
+0, 0));
971 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
972 END_PROFILE(SMBioctl
);
976 if (fsp
->print_file
) {
977 SSVAL(p
, 0, fsp
->print_file
->rap_jobid
);
981 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
982 lp_netbios_name(), 15,
983 STR_TERMINATE
|STR_ASCII
);
985 srvstr_push((char *)req
->outbuf
, req
->flags2
,
986 p
+18, lp_servicename(SNUM(conn
)),
987 13, STR_TERMINATE
|STR_ASCII
);
995 END_PROFILE(SMBioctl
);
999 /****************************************************************************
1000 Strange checkpath NTSTATUS mapping.
1001 ****************************************************************************/
1003 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1005 /* Strange DOS error code semantics only for checkpath... */
1006 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1007 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1008 /* We need to map to ERRbadpath */
1009 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1015 /****************************************************************************
1016 Reply to a checkpath.
1017 ****************************************************************************/
1019 void reply_checkpath(struct smb_request
*req
)
1021 connection_struct
*conn
= req
->conn
;
1022 struct smb_filename
*smb_fname
= NULL
;
1025 TALLOC_CTX
*ctx
= talloc_tos();
1027 START_PROFILE(SMBcheckpath
);
1029 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1030 STR_TERMINATE
, &status
);
1032 if (!NT_STATUS_IS_OK(status
)) {
1033 status
= map_checkpath_error(req
->flags2
, status
);
1034 reply_nterror(req
, status
);
1035 END_PROFILE(SMBcheckpath
);
1039 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1041 status
= filename_convert(ctx
,
1043 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1049 if (!NT_STATUS_IS_OK(status
)) {
1050 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1051 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1052 ERRSRV
, ERRbadpath
);
1053 END_PROFILE(SMBcheckpath
);
1059 if (!VALID_STAT(smb_fname
->st
) &&
1060 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1061 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1062 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1063 status
= map_nt_error_from_unix(errno
);
1067 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1068 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1069 ERRDOS
, ERRbadpath
);
1073 reply_outbuf(req
, 0, 0);
1076 /* We special case this - as when a Windows machine
1077 is parsing a path is steps through the components
1078 one at a time - if a component fails it expects
1079 ERRbadpath, not ERRbadfile.
1081 status
= map_checkpath_error(req
->flags2
, status
);
1082 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1084 * Windows returns different error codes if
1085 * the parent directory is valid but not the
1086 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1087 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1088 * if the path is invalid.
1090 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1091 ERRDOS
, ERRbadpath
);
1095 reply_nterror(req
, status
);
1098 TALLOC_FREE(smb_fname
);
1099 END_PROFILE(SMBcheckpath
);
1103 /****************************************************************************
1105 ****************************************************************************/
1107 void reply_getatr(struct smb_request
*req
)
1109 connection_struct
*conn
= req
->conn
;
1110 struct smb_filename
*smb_fname
= NULL
;
1117 TALLOC_CTX
*ctx
= talloc_tos();
1118 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1120 START_PROFILE(SMBgetatr
);
1122 p
= (const char *)req
->buf
+ 1;
1123 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1124 if (!NT_STATUS_IS_OK(status
)) {
1125 reply_nterror(req
, status
);
1129 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1130 under WfWg - weird! */
1131 if (*fname
== '\0') {
1132 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1133 if (!CAN_WRITE(conn
)) {
1134 mode
|= FILE_ATTRIBUTE_READONLY
;
1139 status
= filename_convert(ctx
,
1141 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1146 if (!NT_STATUS_IS_OK(status
)) {
1147 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1148 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1149 ERRSRV
, ERRbadpath
);
1152 reply_nterror(req
, status
);
1155 if (!VALID_STAT(smb_fname
->st
) &&
1156 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1157 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1158 smb_fname_str_dbg(smb_fname
),
1160 reply_nterror(req
, map_nt_error_from_unix(errno
));
1164 mode
= dos_mode(conn
, smb_fname
);
1165 size
= smb_fname
->st
.st_ex_size
;
1167 if (ask_sharemode
) {
1168 struct timespec write_time_ts
;
1169 struct file_id fileid
;
1171 ZERO_STRUCT(write_time_ts
);
1172 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1173 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1174 if (!null_timespec(write_time_ts
)) {
1175 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1179 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1180 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1185 reply_outbuf(req
, 10, 0);
1187 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1188 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1189 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1191 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1193 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1195 if (get_Protocol() >= PROTOCOL_NT1
) {
1196 SSVAL(req
->outbuf
, smb_flg2
,
1197 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1200 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1201 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1204 TALLOC_FREE(smb_fname
);
1206 END_PROFILE(SMBgetatr
);
1210 /****************************************************************************
1212 ****************************************************************************/
1214 void reply_setatr(struct smb_request
*req
)
1216 struct smb_file_time ft
;
1217 connection_struct
*conn
= req
->conn
;
1218 struct smb_filename
*smb_fname
= NULL
;
1224 TALLOC_CTX
*ctx
= talloc_tos();
1226 START_PROFILE(SMBsetatr
);
1231 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1235 p
= (const char *)req
->buf
+ 1;
1236 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1237 if (!NT_STATUS_IS_OK(status
)) {
1238 reply_nterror(req
, status
);
1242 status
= filename_convert(ctx
,
1244 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1249 if (!NT_STATUS_IS_OK(status
)) {
1250 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1251 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1252 ERRSRV
, ERRbadpath
);
1255 reply_nterror(req
, status
);
1259 if (smb_fname
->base_name
[0] == '.' &&
1260 smb_fname
->base_name
[1] == '\0') {
1262 * Not sure here is the right place to catch this
1263 * condition. Might be moved to somewhere else later -- vl
1265 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1269 mode
= SVAL(req
->vwv
+0, 0);
1270 mtime
= srv_make_unix_date3(req
->vwv
+1);
1272 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1273 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1274 if (!NT_STATUS_IS_OK(status
)) {
1275 reply_nterror(req
, status
);
1279 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1280 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1281 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1283 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1285 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1287 reply_nterror(req
, map_nt_error_from_unix(errno
));
1292 reply_outbuf(req
, 0, 0);
1294 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1297 TALLOC_FREE(smb_fname
);
1298 END_PROFILE(SMBsetatr
);
1302 /****************************************************************************
1304 ****************************************************************************/
1306 void reply_dskattr(struct smb_request
*req
)
1308 connection_struct
*conn
= req
->conn
;
1309 uint64_t dfree
,dsize
,bsize
;
1310 START_PROFILE(SMBdskattr
);
1312 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1313 reply_nterror(req
, map_nt_error_from_unix(errno
));
1314 END_PROFILE(SMBdskattr
);
1318 reply_outbuf(req
, 5, 0);
1320 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1321 double total_space
, free_space
;
1322 /* we need to scale this to a number that DOS6 can handle. We
1323 use floating point so we can handle large drives on systems
1324 that don't have 64 bit integers
1326 we end up displaying a maximum of 2G to DOS systems
1328 total_space
= dsize
* (double)bsize
;
1329 free_space
= dfree
* (double)bsize
;
1331 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1332 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1334 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1335 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1337 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1338 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1339 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1340 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1342 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1343 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1344 SSVAL(req
->outbuf
,smb_vwv2
,512);
1345 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1348 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1350 END_PROFILE(SMBdskattr
);
1355 * Utility function to split the filename from the directory.
1357 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1358 char **fname_dir_out
,
1359 char **fname_mask_out
)
1361 const char *p
= NULL
;
1362 char *fname_dir
= NULL
;
1363 char *fname_mask
= NULL
;
1365 p
= strrchr_m(fname_in
, '/');
1367 fname_dir
= talloc_strdup(ctx
, ".");
1368 fname_mask
= talloc_strdup(ctx
, fname_in
);
1370 fname_dir
= talloc_strndup(ctx
, fname_in
,
1371 PTR_DIFF(p
, fname_in
));
1372 fname_mask
= talloc_strdup(ctx
, p
+1);
1375 if (!fname_dir
|| !fname_mask
) {
1376 TALLOC_FREE(fname_dir
);
1377 TALLOC_FREE(fname_mask
);
1378 return NT_STATUS_NO_MEMORY
;
1381 *fname_dir_out
= fname_dir
;
1382 *fname_mask_out
= fname_mask
;
1383 return NT_STATUS_OK
;
1386 /****************************************************************************
1388 Can be called from SMBsearch, SMBffirst or SMBfunique.
1389 ****************************************************************************/
1391 void reply_search(struct smb_request
*req
)
1393 connection_struct
*conn
= req
->conn
;
1395 const char *mask
= NULL
;
1396 char *directory
= NULL
;
1397 struct smb_filename
*smb_fname
= NULL
;
1401 struct timespec date
;
1403 unsigned int numentries
= 0;
1404 unsigned int maxentries
= 0;
1405 bool finished
= False
;
1410 bool check_descend
= False
;
1411 bool expect_close
= False
;
1413 bool mask_contains_wcard
= False
;
1414 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1415 TALLOC_CTX
*ctx
= talloc_tos();
1416 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1417 struct dptr_struct
*dirptr
= NULL
;
1418 struct smbd_server_connection
*sconn
= req
->sconn
;
1420 START_PROFILE(SMBsearch
);
1423 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1427 if (lp_posix_pathnames()) {
1428 reply_unknown_new(req
, req
->cmd
);
1432 /* If we were called as SMBffirst then we must expect close. */
1433 if(req
->cmd
== SMBffirst
) {
1434 expect_close
= True
;
1437 reply_outbuf(req
, 1, 3);
1438 maxentries
= SVAL(req
->vwv
+0, 0);
1439 dirtype
= SVAL(req
->vwv
+1, 0);
1440 p
= (const char *)req
->buf
+ 1;
1441 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1442 &nt_status
, &mask_contains_wcard
);
1443 if (!NT_STATUS_IS_OK(nt_status
)) {
1444 reply_nterror(req
, nt_status
);
1449 status_len
= SVAL(p
, 0);
1452 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1454 if (status_len
== 0) {
1455 nt_status
= filename_convert(ctx
, conn
,
1456 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1458 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1459 &mask_contains_wcard
,
1461 if (!NT_STATUS_IS_OK(nt_status
)) {
1462 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1463 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1464 ERRSRV
, ERRbadpath
);
1467 reply_nterror(req
, nt_status
);
1471 directory
= smb_fname
->base_name
;
1473 p
= strrchr_m(directory
,'/');
1474 if ((p
!= NULL
) && (*directory
!= '/')) {
1476 directory
= talloc_strndup(ctx
, directory
,
1477 PTR_DIFF(p
, directory
));
1480 directory
= talloc_strdup(ctx
,".");
1484 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1488 memset((char *)status
,'\0',21);
1489 SCVAL(status
,0,(dirtype
& 0x1F));
1491 nt_status
= dptr_create(conn
,
1498 mask_contains_wcard
,
1501 if (!NT_STATUS_IS_OK(nt_status
)) {
1502 reply_nterror(req
, nt_status
);
1505 dptr_num
= dptr_dnum(dirptr
);
1508 const char *dirpath
;
1510 memcpy(status
,p
,21);
1511 status_dirtype
= CVAL(status
,0) & 0x1F;
1512 if (status_dirtype
!= (dirtype
& 0x1F)) {
1513 dirtype
= status_dirtype
;
1516 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1520 dirpath
= dptr_path(sconn
, dptr_num
);
1521 directory
= talloc_strdup(ctx
, dirpath
);
1523 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1527 mask
= dptr_wcard(sconn
, dptr_num
);
1532 * For a 'continue' search we have no string. So
1533 * check from the initial saved string.
1535 mask_contains_wcard
= ms_has_wild(mask
);
1536 dirtype
= dptr_attr(sconn
, dptr_num
);
1539 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1541 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1542 dptr_init_search_op(dirptr
);
1544 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1545 char buf
[DIR_STRUCT_SIZE
];
1546 memcpy(buf
,status
,21);
1547 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1548 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1549 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1552 dptr_fill(sconn
, buf
+12,dptr_num
);
1553 if (dptr_zero(buf
+12) && (status_len
==0)) {
1558 if (message_push_blob(&req
->outbuf
,
1559 data_blob_const(buf
, sizeof(buf
)))
1561 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1569 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1572 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1573 directory
,lp_dontdescend(SNUM(conn
))));
1574 if (in_list(directory
, lp_dontdescend(SNUM(conn
)),True
)) {
1575 check_descend
= True
;
1578 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1579 finished
= !get_dir_entry(ctx
,
1590 char buf
[DIR_STRUCT_SIZE
];
1591 memcpy(buf
,status
,21);
1592 if (!make_dir_struct(ctx
,
1598 convert_timespec_to_time_t(date
),
1599 !allow_long_path_components
)) {
1600 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1603 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1606 if (message_push_blob(&req
->outbuf
,
1607 data_blob_const(buf
, sizeof(buf
)))
1609 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1619 /* If we were called as SMBffirst with smb_search_id == NULL
1620 and no entries were found then return error and close dirptr
1623 if (numentries
== 0) {
1624 dptr_close(sconn
, &dptr_num
);
1625 } else if(expect_close
&& status_len
== 0) {
1626 /* Close the dptr - we know it's gone */
1627 dptr_close(sconn
, &dptr_num
);
1630 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1631 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1632 dptr_close(sconn
, &dptr_num
);
1635 if ((numentries
== 0) && !mask_contains_wcard
) {
1636 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1640 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1641 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1642 SCVAL(smb_buf(req
->outbuf
),0,5);
1643 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1645 /* The replies here are never long name. */
1646 SSVAL(req
->outbuf
, smb_flg2
,
1647 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1648 if (!allow_long_path_components
) {
1649 SSVAL(req
->outbuf
, smb_flg2
,
1650 SVAL(req
->outbuf
, smb_flg2
)
1651 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1654 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1655 SSVAL(req
->outbuf
, smb_flg2
,
1656 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1658 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1659 smb_fn_name(req
->cmd
),
1666 TALLOC_FREE(directory
);
1667 TALLOC_FREE(smb_fname
);
1668 END_PROFILE(SMBsearch
);
1672 /****************************************************************************
1673 Reply to a fclose (stop directory search).
1674 ****************************************************************************/
1676 void reply_fclose(struct smb_request
*req
)
1684 bool path_contains_wcard
= False
;
1685 TALLOC_CTX
*ctx
= talloc_tos();
1686 struct smbd_server_connection
*sconn
= req
->sconn
;
1688 START_PROFILE(SMBfclose
);
1690 if (lp_posix_pathnames()) {
1691 reply_unknown_new(req
, req
->cmd
);
1692 END_PROFILE(SMBfclose
);
1696 p
= (const char *)req
->buf
+ 1;
1697 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1698 &err
, &path_contains_wcard
);
1699 if (!NT_STATUS_IS_OK(err
)) {
1700 reply_nterror(req
, err
);
1701 END_PROFILE(SMBfclose
);
1705 status_len
= SVAL(p
,0);
1708 if (status_len
== 0) {
1709 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1710 END_PROFILE(SMBfclose
);
1714 memcpy(status
,p
,21);
1716 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1717 /* Close the dptr - we know it's gone */
1718 dptr_close(sconn
, &dptr_num
);
1721 reply_outbuf(req
, 1, 0);
1722 SSVAL(req
->outbuf
,smb_vwv0
,0);
1724 DEBUG(3,("search close\n"));
1726 END_PROFILE(SMBfclose
);
1730 /****************************************************************************
1732 ****************************************************************************/
1734 void reply_open(struct smb_request
*req
)
1736 connection_struct
*conn
= req
->conn
;
1737 struct smb_filename
*smb_fname
= NULL
;
1749 uint32 create_disposition
;
1750 uint32 create_options
= 0;
1751 uint32_t private_flags
= 0;
1753 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1754 TALLOC_CTX
*ctx
= talloc_tos();
1756 START_PROFILE(SMBopen
);
1759 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1763 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1764 deny_mode
= SVAL(req
->vwv
+0, 0);
1765 dos_attr
= SVAL(req
->vwv
+1, 0);
1767 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1768 STR_TERMINATE
, &status
);
1769 if (!NT_STATUS_IS_OK(status
)) {
1770 reply_nterror(req
, status
);
1774 status
= filename_convert(ctx
,
1776 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1781 if (!NT_STATUS_IS_OK(status
)) {
1782 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1783 reply_botherror(req
,
1784 NT_STATUS_PATH_NOT_COVERED
,
1785 ERRSRV
, ERRbadpath
);
1788 reply_nterror(req
, status
);
1792 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1793 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1794 &share_mode
, &create_disposition
,
1795 &create_options
, &private_flags
)) {
1796 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1800 status
= SMB_VFS_CREATE_FILE(
1803 0, /* root_dir_fid */
1804 smb_fname
, /* fname */
1805 access_mask
, /* access_mask */
1806 share_mode
, /* share_access */
1807 create_disposition
, /* create_disposition*/
1808 create_options
, /* create_options */
1809 dos_attr
, /* file_attributes */
1810 oplock_request
, /* oplock_request */
1811 0, /* allocation_size */
1818 if (!NT_STATUS_IS_OK(status
)) {
1819 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1820 /* We have re-scheduled this call. */
1823 reply_openerror(req
, status
);
1827 size
= smb_fname
->st
.st_ex_size
;
1828 fattr
= dos_mode(conn
, smb_fname
);
1830 /* Deal with other possible opens having a modified
1832 if (ask_sharemode
) {
1833 struct timespec write_time_ts
;
1835 ZERO_STRUCT(write_time_ts
);
1836 get_file_infos(fsp
->file_id
, 0, NULL
, &write_time_ts
);
1837 if (!null_timespec(write_time_ts
)) {
1838 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1842 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1844 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1845 DEBUG(3,("attempt to open a directory %s\n",
1847 close_file(req
, fsp
, ERROR_CLOSE
);
1848 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1849 ERRDOS
, ERRnoaccess
);
1853 reply_outbuf(req
, 7, 0);
1854 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1855 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1856 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1857 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1859 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1861 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1862 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1864 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1865 SCVAL(req
->outbuf
,smb_flg
,
1866 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1869 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1870 SCVAL(req
->outbuf
,smb_flg
,
1871 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1874 TALLOC_FREE(smb_fname
);
1875 END_PROFILE(SMBopen
);
1879 /****************************************************************************
1880 Reply to an open and X.
1881 ****************************************************************************/
1883 void reply_open_and_X(struct smb_request
*req
)
1885 connection_struct
*conn
= req
->conn
;
1886 struct smb_filename
*smb_fname
= NULL
;
1891 /* Breakout the oplock request bits so we can set the
1892 reply bits separately. */
1893 int ex_oplock_request
;
1894 int core_oplock_request
;
1897 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1898 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
1906 uint64_t allocation_size
;
1907 ssize_t retval
= -1;
1910 uint32 create_disposition
;
1911 uint32 create_options
= 0;
1912 uint32_t private_flags
= 0;
1913 TALLOC_CTX
*ctx
= talloc_tos();
1915 START_PROFILE(SMBopenX
);
1917 if (req
->wct
< 15) {
1918 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1922 open_flags
= SVAL(req
->vwv
+2, 0);
1923 deny_mode
= SVAL(req
->vwv
+3, 0);
1924 smb_attr
= SVAL(req
->vwv
+5, 0);
1925 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1926 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1927 oplock_request
= ex_oplock_request
| core_oplock_request
;
1928 smb_ofun
= SVAL(req
->vwv
+8, 0);
1929 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1931 /* If it's an IPC, pass off the pipe handler. */
1933 if (lp_nt_pipe_support()) {
1934 reply_open_pipe_and_X(conn
, req
);
1936 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1941 /* XXXX we need to handle passed times, sattr and flags */
1942 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1943 STR_TERMINATE
, &status
);
1944 if (!NT_STATUS_IS_OK(status
)) {
1945 reply_nterror(req
, status
);
1949 status
= filename_convert(ctx
,
1951 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1956 if (!NT_STATUS_IS_OK(status
)) {
1957 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1958 reply_botherror(req
,
1959 NT_STATUS_PATH_NOT_COVERED
,
1960 ERRSRV
, ERRbadpath
);
1963 reply_nterror(req
, status
);
1967 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1969 &access_mask
, &share_mode
,
1970 &create_disposition
,
1973 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1977 status
= SMB_VFS_CREATE_FILE(
1980 0, /* root_dir_fid */
1981 smb_fname
, /* fname */
1982 access_mask
, /* access_mask */
1983 share_mode
, /* share_access */
1984 create_disposition
, /* create_disposition*/
1985 create_options
, /* create_options */
1986 smb_attr
, /* file_attributes */
1987 oplock_request
, /* oplock_request */
1988 0, /* allocation_size */
1993 &smb_action
); /* pinfo */
1995 if (!NT_STATUS_IS_OK(status
)) {
1996 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1997 /* We have re-scheduled this call. */
2000 reply_openerror(req
, status
);
2004 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2005 if the file is truncated or created. */
2006 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2007 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2008 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2009 close_file(req
, fsp
, ERROR_CLOSE
);
2010 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2013 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
2015 close_file(req
, fsp
, ERROR_CLOSE
);
2016 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2019 status
= vfs_stat_fsp(fsp
);
2020 if (!NT_STATUS_IS_OK(status
)) {
2021 close_file(req
, fsp
, ERROR_CLOSE
);
2022 reply_nterror(req
, status
);
2027 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2028 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2029 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2030 close_file(req
, fsp
, ERROR_CLOSE
);
2031 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2035 /* If the caller set the extended oplock request bit
2036 and we granted one (by whatever means) - set the
2037 correct bit for extended oplock reply.
2040 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2041 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2044 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2045 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2048 /* If the caller set the core oplock request bit
2049 and we granted one (by whatever means) - set the
2050 correct bit for core oplock reply.
2053 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2054 reply_outbuf(req
, 19, 0);
2056 reply_outbuf(req
, 15, 0);
2059 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2060 SCVAL(req
->outbuf
, smb_flg
,
2061 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2064 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2065 SCVAL(req
->outbuf
, smb_flg
,
2066 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2069 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2070 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2071 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2072 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2074 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2076 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2077 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2078 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2080 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2081 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2086 TALLOC_FREE(smb_fname
);
2087 END_PROFILE(SMBopenX
);
2091 /****************************************************************************
2092 Reply to a SMBulogoffX.
2093 ****************************************************************************/
2095 void reply_ulogoffX(struct smb_request
*req
)
2097 struct smbd_server_connection
*sconn
= req
->sconn
;
2100 START_PROFILE(SMBulogoffX
);
2102 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2105 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2109 /* in user level security we are supposed to close any files
2110 open by this user */
2111 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
2112 file_close_user(sconn
, req
->vuid
);
2115 invalidate_vuid(sconn
, req
->vuid
);
2117 reply_outbuf(req
, 2, 0);
2119 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
2121 END_PROFILE(SMBulogoffX
);
2122 req
->vuid
= UID_FIELD_INVALID
;
2126 /****************************************************************************
2127 Reply to a mknew or a create.
2128 ****************************************************************************/
2130 void reply_mknew(struct smb_request
*req
)
2132 connection_struct
*conn
= req
->conn
;
2133 struct smb_filename
*smb_fname
= NULL
;
2136 struct smb_file_time ft
;
2138 int oplock_request
= 0;
2140 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2141 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2142 uint32 create_disposition
;
2143 uint32 create_options
= 0;
2144 TALLOC_CTX
*ctx
= talloc_tos();
2146 START_PROFILE(SMBcreate
);
2150 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2154 fattr
= SVAL(req
->vwv
+0, 0);
2155 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2158 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2160 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2161 STR_TERMINATE
, &status
);
2162 if (!NT_STATUS_IS_OK(status
)) {
2163 reply_nterror(req
, status
);
2167 status
= filename_convert(ctx
,
2169 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2174 if (!NT_STATUS_IS_OK(status
)) {
2175 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2176 reply_botherror(req
,
2177 NT_STATUS_PATH_NOT_COVERED
,
2178 ERRSRV
, ERRbadpath
);
2181 reply_nterror(req
, status
);
2185 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2186 DEBUG(0,("Attempt to create file (%s) with volid set - "
2187 "please report this\n",
2188 smb_fname_str_dbg(smb_fname
)));
2191 if(req
->cmd
== SMBmknew
) {
2192 /* We should fail if file exists. */
2193 create_disposition
= FILE_CREATE
;
2195 /* Create if file doesn't exist, truncate if it does. */
2196 create_disposition
= FILE_OVERWRITE_IF
;
2199 status
= SMB_VFS_CREATE_FILE(
2202 0, /* root_dir_fid */
2203 smb_fname
, /* fname */
2204 access_mask
, /* access_mask */
2205 share_mode
, /* share_access */
2206 create_disposition
, /* create_disposition*/
2207 create_options
, /* create_options */
2208 fattr
, /* file_attributes */
2209 oplock_request
, /* oplock_request */
2210 0, /* allocation_size */
2211 0, /* private_flags */
2217 if (!NT_STATUS_IS_OK(status
)) {
2218 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2219 /* We have re-scheduled this call. */
2222 reply_openerror(req
, status
);
2226 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2227 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2228 if (!NT_STATUS_IS_OK(status
)) {
2229 END_PROFILE(SMBcreate
);
2233 reply_outbuf(req
, 1, 0);
2234 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2236 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2237 SCVAL(req
->outbuf
,smb_flg
,
2238 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2241 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2242 SCVAL(req
->outbuf
,smb_flg
,
2243 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2246 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2247 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2248 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2249 (unsigned int)fattr
));
2252 TALLOC_FREE(smb_fname
);
2253 END_PROFILE(SMBcreate
);
2257 /****************************************************************************
2258 Reply to a create temporary file.
2259 ****************************************************************************/
2261 void reply_ctemp(struct smb_request
*req
)
2263 connection_struct
*conn
= req
->conn
;
2264 struct smb_filename
*smb_fname
= NULL
;
2272 TALLOC_CTX
*ctx
= talloc_tos();
2274 START_PROFILE(SMBctemp
);
2277 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2281 fattr
= SVAL(req
->vwv
+0, 0);
2282 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2284 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2285 STR_TERMINATE
, &status
);
2286 if (!NT_STATUS_IS_OK(status
)) {
2287 reply_nterror(req
, status
);
2291 fname
= talloc_asprintf(ctx
,
2295 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2299 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2303 status
= filename_convert(ctx
, conn
,
2304 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2309 if (!NT_STATUS_IS_OK(status
)) {
2310 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2311 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2312 ERRSRV
, ERRbadpath
);
2315 reply_nterror(req
, status
);
2319 tmpfd
= mkstemp(smb_fname
->base_name
);
2321 reply_nterror(req
, map_nt_error_from_unix(errno
));
2325 SMB_VFS_STAT(conn
, smb_fname
);
2327 /* We should fail if file does not exist. */
2328 status
= SMB_VFS_CREATE_FILE(
2331 0, /* root_dir_fid */
2332 smb_fname
, /* fname */
2333 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2334 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2335 FILE_OPEN
, /* create_disposition*/
2336 0, /* create_options */
2337 fattr
, /* file_attributes */
2338 oplock_request
, /* oplock_request */
2339 0, /* allocation_size */
2340 0, /* private_flags */
2346 /* close fd from mkstemp() */
2349 if (!NT_STATUS_IS_OK(status
)) {
2350 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2351 /* We have re-scheduled this call. */
2354 reply_openerror(req
, status
);
2358 reply_outbuf(req
, 1, 0);
2359 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2361 /* the returned filename is relative to the directory */
2362 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2364 s
= fsp
->fsp_name
->base_name
;
2370 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2371 thing in the byte section. JRA */
2372 SSVALS(p
, 0, -1); /* what is this? not in spec */
2374 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2376 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2380 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2381 SCVAL(req
->outbuf
, smb_flg
,
2382 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2385 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2386 SCVAL(req
->outbuf
, smb_flg
,
2387 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2390 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2391 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2392 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2394 TALLOC_FREE(smb_fname
);
2395 END_PROFILE(SMBctemp
);
2399 /*******************************************************************
2400 Check if a user is allowed to rename a file.
2401 ********************************************************************/
2403 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2406 if (!CAN_WRITE(conn
)) {
2407 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2410 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2411 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2412 /* Only bother to read the DOS attribute if we might deny the
2413 rename on the grounds of attribute missmatch. */
2414 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2415 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2416 return NT_STATUS_NO_SUCH_FILE
;
2420 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2421 if (fsp
->posix_open
) {
2422 return NT_STATUS_OK
;
2425 /* If no pathnames are open below this
2426 directory, allow the rename. */
2428 if (file_find_subpath(fsp
)) {
2429 return NT_STATUS_ACCESS_DENIED
;
2431 return NT_STATUS_OK
;
2434 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2435 return NT_STATUS_OK
;
2438 return NT_STATUS_ACCESS_DENIED
;
2441 /*******************************************************************
2442 * unlink a file with all relevant access checks
2443 *******************************************************************/
2445 static NTSTATUS
do_unlink(connection_struct
*conn
,
2446 struct smb_request
*req
,
2447 struct smb_filename
*smb_fname
,
2452 uint32 dirtype_orig
= dirtype
;
2455 bool posix_paths
= lp_posix_pathnames();
2457 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2458 smb_fname_str_dbg(smb_fname
),
2461 if (!CAN_WRITE(conn
)) {
2462 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2466 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2468 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2471 return map_nt_error_from_unix(errno
);
2474 fattr
= dos_mode(conn
, smb_fname
);
2476 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2477 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2480 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2482 return NT_STATUS_NO_SUCH_FILE
;
2485 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2486 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2487 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2489 return NT_STATUS_NO_SUCH_FILE
;
2492 if (dirtype_orig
& 0x8000) {
2493 /* These will never be set for POSIX. */
2494 return NT_STATUS_NO_SUCH_FILE
;
2498 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2499 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2502 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2503 return NT_STATUS_NO_SUCH_FILE
;
2506 if (dirtype
& 0xFF00) {
2507 /* These will never be set for POSIX. */
2508 return NT_STATUS_NO_SUCH_FILE
;
2513 return NT_STATUS_NO_SUCH_FILE
;
2516 /* Can't delete a directory. */
2517 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2518 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2523 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2524 return NT_STATUS_OBJECT_NAME_INVALID
;
2525 #endif /* JRATEST */
2527 /* On open checks the open itself will check the share mode, so
2528 don't do it here as we'll get it wrong. */
2530 status
= SMB_VFS_CREATE_FILE
2533 0, /* root_dir_fid */
2534 smb_fname
, /* fname */
2535 DELETE_ACCESS
, /* access_mask */
2536 FILE_SHARE_NONE
, /* share_access */
2537 FILE_OPEN
, /* create_disposition*/
2538 FILE_NON_DIRECTORY_FILE
, /* create_options */
2539 /* file_attributes */
2540 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2541 FILE_ATTRIBUTE_NORMAL
,
2542 0, /* oplock_request */
2543 0, /* allocation_size */
2544 0, /* private_flags */
2550 if (!NT_STATUS_IS_OK(status
)) {
2551 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2552 nt_errstr(status
)));
2556 status
= can_set_delete_on_close(fsp
, fattr
);
2557 if (!NT_STATUS_IS_OK(status
)) {
2558 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2560 smb_fname_str_dbg(smb_fname
),
2561 nt_errstr(status
)));
2562 close_file(req
, fsp
, NORMAL_CLOSE
);
2566 /* The set is across all open files on this dev/inode pair. */
2567 if (!set_delete_on_close(fsp
, True
, conn
->session_info
->unix_token
)) {
2568 close_file(req
, fsp
, NORMAL_CLOSE
);
2569 return NT_STATUS_ACCESS_DENIED
;
2572 return close_file(req
, fsp
, NORMAL_CLOSE
);
2575 /****************************************************************************
2576 The guts of the unlink command, split out so it may be called by the NT SMB
2578 ****************************************************************************/
2580 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2581 uint32 dirtype
, struct smb_filename
*smb_fname
,
2584 char *fname_dir
= NULL
;
2585 char *fname_mask
= NULL
;
2587 NTSTATUS status
= NT_STATUS_OK
;
2588 TALLOC_CTX
*ctx
= talloc_tos();
2590 /* Split up the directory from the filename/mask. */
2591 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2592 &fname_dir
, &fname_mask
);
2593 if (!NT_STATUS_IS_OK(status
)) {
2598 * We should only check the mangled cache
2599 * here if unix_convert failed. This means
2600 * that the path in 'mask' doesn't exist
2601 * on the file system and so we need to look
2602 * for a possible mangle. This patch from
2603 * Tine Smukavec <valentin.smukavec@hermes.si>.
2606 if (!VALID_STAT(smb_fname
->st
) &&
2607 mangle_is_mangled(fname_mask
, conn
->params
)) {
2608 char *new_mask
= NULL
;
2609 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2610 &new_mask
, conn
->params
);
2612 TALLOC_FREE(fname_mask
);
2613 fname_mask
= new_mask
;
2620 * Only one file needs to be unlinked. Append the mask back
2621 * onto the directory.
2623 TALLOC_FREE(smb_fname
->base_name
);
2624 if (ISDOT(fname_dir
)) {
2625 /* Ensure we use canonical names on open. */
2626 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2630 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2635 if (!smb_fname
->base_name
) {
2636 status
= NT_STATUS_NO_MEMORY
;
2640 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2643 status
= check_name(conn
, smb_fname
->base_name
);
2644 if (!NT_STATUS_IS_OK(status
)) {
2648 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2649 if (!NT_STATUS_IS_OK(status
)) {
2655 struct smb_Dir
*dir_hnd
= NULL
;
2657 const char *dname
= NULL
;
2658 char *talloced
= NULL
;
2660 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2661 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2665 if (strequal(fname_mask
,"????????.???")) {
2666 TALLOC_FREE(fname_mask
);
2667 fname_mask
= talloc_strdup(ctx
, "*");
2669 status
= NT_STATUS_NO_MEMORY
;
2674 status
= check_name(conn
, fname_dir
);
2675 if (!NT_STATUS_IS_OK(status
)) {
2679 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2681 if (dir_hnd
== NULL
) {
2682 status
= map_nt_error_from_unix(errno
);
2686 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2687 the pattern matches against the long name, otherwise the short name
2688 We don't implement this yet XXXX
2691 status
= NT_STATUS_NO_SUCH_FILE
;
2693 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2694 &smb_fname
->st
, &talloced
))) {
2695 TALLOC_CTX
*frame
= talloc_stackframe();
2697 if (!is_visible_file(conn
, fname_dir
, dname
,
2698 &smb_fname
->st
, true)) {
2700 TALLOC_FREE(talloced
);
2704 /* Quick check for "." and ".." */
2705 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2707 TALLOC_FREE(talloced
);
2711 if(!mask_match(dname
, fname_mask
,
2712 conn
->case_sensitive
)) {
2714 TALLOC_FREE(talloced
);
2718 TALLOC_FREE(smb_fname
->base_name
);
2719 if (ISDOT(fname_dir
)) {
2720 /* Ensure we use canonical names on open. */
2721 smb_fname
->base_name
=
2722 talloc_asprintf(smb_fname
, "%s",
2725 smb_fname
->base_name
=
2726 talloc_asprintf(smb_fname
, "%s/%s",
2730 if (!smb_fname
->base_name
) {
2731 TALLOC_FREE(dir_hnd
);
2732 status
= NT_STATUS_NO_MEMORY
;
2734 TALLOC_FREE(talloced
);
2738 status
= check_name(conn
, smb_fname
->base_name
);
2739 if (!NT_STATUS_IS_OK(status
)) {
2740 TALLOC_FREE(dir_hnd
);
2742 TALLOC_FREE(talloced
);
2746 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2747 if (!NT_STATUS_IS_OK(status
)) {
2749 TALLOC_FREE(talloced
);
2754 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2755 smb_fname
->base_name
));
2758 TALLOC_FREE(talloced
);
2760 TALLOC_FREE(dir_hnd
);
2763 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2764 status
= map_nt_error_from_unix(errno
);
2768 TALLOC_FREE(fname_dir
);
2769 TALLOC_FREE(fname_mask
);
2773 /****************************************************************************
2775 ****************************************************************************/
2777 void reply_unlink(struct smb_request
*req
)
2779 connection_struct
*conn
= req
->conn
;
2781 struct smb_filename
*smb_fname
= NULL
;
2784 bool path_contains_wcard
= False
;
2785 TALLOC_CTX
*ctx
= talloc_tos();
2787 START_PROFILE(SMBunlink
);
2790 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2794 dirtype
= SVAL(req
->vwv
+0, 0);
2796 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2797 STR_TERMINATE
, &status
,
2798 &path_contains_wcard
);
2799 if (!NT_STATUS_IS_OK(status
)) {
2800 reply_nterror(req
, status
);
2804 status
= filename_convert(ctx
, conn
,
2805 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2807 UCF_COND_ALLOW_WCARD_LCOMP
,
2808 &path_contains_wcard
,
2810 if (!NT_STATUS_IS_OK(status
)) {
2811 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2812 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2813 ERRSRV
, ERRbadpath
);
2816 reply_nterror(req
, status
);
2820 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2822 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2823 path_contains_wcard
);
2824 if (!NT_STATUS_IS_OK(status
)) {
2825 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2826 /* We have re-scheduled this call. */
2829 reply_nterror(req
, status
);
2833 reply_outbuf(req
, 0, 0);
2835 TALLOC_FREE(smb_fname
);
2836 END_PROFILE(SMBunlink
);
2840 /****************************************************************************
2842 ****************************************************************************/
2844 static void fail_readraw(void)
2846 const char *errstr
= talloc_asprintf(talloc_tos(),
2847 "FAIL ! reply_readbraw: socket write fail (%s)",
2852 exit_server_cleanly(errstr
);
2855 /****************************************************************************
2856 Fake (read/write) sendfile. Returns -1 on read or write fail.
2857 ****************************************************************************/
2859 ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
)
2862 size_t tosend
= nread
;
2869 bufsize
= MIN(nread
, 65536);
2871 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2875 while (tosend
> 0) {
2879 if (tosend
> bufsize
) {
2884 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2890 /* If we had a short read, fill with zeros. */
2891 if (ret
< cur_read
) {
2892 memset(buf
+ ret
, '\0', cur_read
- ret
);
2895 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
2897 char addr
[INET6_ADDRSTRLEN
];
2899 * Try and give an error message saying what
2902 DEBUG(0, ("write_data failed for client %s. "
2904 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
2911 startpos
+= cur_read
;
2915 return (ssize_t
)nread
;
2918 /****************************************************************************
2919 Deal with the case of sendfile reading less bytes from the file than
2920 requested. Fill with zeros (all we can do).
2921 ****************************************************************************/
2923 void sendfile_short_send(files_struct
*fsp
,
2928 #define SHORT_SEND_BUFSIZE 1024
2929 if (nread
< headersize
) {
2930 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2931 "header for file %s (%s). Terminating\n",
2932 fsp_str_dbg(fsp
), strerror(errno
)));
2933 exit_server_cleanly("sendfile_short_send failed");
2936 nread
-= headersize
;
2938 if (nread
< smb_maxcnt
) {
2939 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
2941 exit_server_cleanly("sendfile_short_send: "
2945 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2946 "with zeros !\n", fsp_str_dbg(fsp
)));
2948 while (nread
< smb_maxcnt
) {
2950 * We asked for the real file size and told sendfile
2951 * to not go beyond the end of the file. But it can
2952 * happen that in between our fstat call and the
2953 * sendfile call the file was truncated. This is very
2954 * bad because we have already announced the larger
2955 * number of bytes to the client.
2957 * The best we can do now is to send 0-bytes, just as
2958 * a read from a hole in a sparse file would do.
2960 * This should happen rarely enough that I don't care
2961 * about efficiency here :-)
2965 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
2966 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
2968 char addr
[INET6_ADDRSTRLEN
];
2970 * Try and give an error message saying what
2973 DEBUG(0, ("write_data failed for client %s. "
2976 fsp
->conn
->sconn
->sock
, addr
,
2979 exit_server_cleanly("sendfile_short_send: "
2980 "write_data failed");
2988 /****************************************************************************
2989 Return a readbraw error (4 bytes of zero).
2990 ****************************************************************************/
2992 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
2998 smbd_lock_socket(sconn
);
2999 if (write_data(sconn
->sock
,header
,4) != 4) {
3000 char addr
[INET6_ADDRSTRLEN
];
3002 * Try and give an error message saying what
3005 DEBUG(0, ("write_data failed for client %s. "
3007 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
3012 smbd_unlock_socket(sconn
);
3015 /****************************************************************************
3016 Use sendfile in readbraw.
3017 ****************************************************************************/
3019 static void send_file_readbraw(connection_struct
*conn
,
3020 struct smb_request
*req
,
3026 struct smbd_server_connection
*sconn
= req
->sconn
;
3027 char *outbuf
= NULL
;
3031 * We can only use sendfile on a non-chained packet
3032 * but we can use on a non-oplocked file. tridge proved this
3033 * on a train in Germany :-). JRA.
3034 * reply_readbraw has already checked the length.
3037 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3038 (fsp
->wcp
== NULL
) &&
3039 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3040 ssize_t sendfile_read
= -1;
3042 DATA_BLOB header_blob
;
3044 _smb_setlen(header
,nread
);
3045 header_blob
= data_blob_const(header
, 4);
3047 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3048 &header_blob
, startpos
,
3050 if (sendfile_read
== -1) {
3051 /* Returning ENOSYS means no data at all was sent.
3052 * Do this as a normal read. */
3053 if (errno
== ENOSYS
) {
3054 goto normal_readbraw
;
3058 * Special hack for broken Linux with no working sendfile. If we
3059 * return EINTR we sent the header but not the rest of the data.
3060 * Fake this up by doing read/write calls.
3062 if (errno
== EINTR
) {
3063 /* Ensure we don't do this again. */
3064 set_use_sendfile(SNUM(conn
), False
);
3065 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3067 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3068 DEBUG(0,("send_file_readbraw: "
3069 "fake_sendfile failed for "
3073 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3078 DEBUG(0,("send_file_readbraw: sendfile failed for "
3079 "file %s (%s). Terminating\n",
3080 fsp_str_dbg(fsp
), strerror(errno
)));
3081 exit_server_cleanly("send_file_readbraw sendfile failed");
3082 } else if (sendfile_read
== 0) {
3084 * Some sendfile implementations return 0 to indicate
3085 * that there was a short read, but nothing was
3086 * actually written to the socket. In this case,
3087 * fallback to the normal read path so the header gets
3088 * the correct byte count.
3090 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3091 "bytes falling back to the normal read: "
3092 "%s\n", fsp_str_dbg(fsp
)));
3093 goto normal_readbraw
;
3096 /* Deal with possible short send. */
3097 if (sendfile_read
!= 4+nread
) {
3098 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3105 outbuf
= talloc_array(NULL
, char, nread
+4);
3107 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3108 (unsigned)(nread
+4)));
3109 reply_readbraw_error(sconn
);
3114 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3115 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3124 _smb_setlen(outbuf
,ret
);
3125 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3126 char addr
[INET6_ADDRSTRLEN
];
3128 * Try and give an error message saying what
3131 DEBUG(0, ("write_data failed for client %s. "
3133 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3140 TALLOC_FREE(outbuf
);
3143 /****************************************************************************
3144 Reply to a readbraw (core+ protocol).
3145 ****************************************************************************/
3147 void reply_readbraw(struct smb_request
*req
)
3149 connection_struct
*conn
= req
->conn
;
3150 struct smbd_server_connection
*sconn
= req
->sconn
;
3151 ssize_t maxcount
,mincount
;
3155 struct lock_struct lock
;
3158 START_PROFILE(SMBreadbraw
);
3160 if (srv_is_signing_active(sconn
) ||
3161 is_encrypted_packet(sconn
, req
->inbuf
)) {
3162 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3163 "raw reads/writes are disallowed.");
3167 reply_readbraw_error(sconn
);
3168 END_PROFILE(SMBreadbraw
);
3172 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3173 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3174 "'async smb echo handler = yes'\n"));
3175 reply_readbraw_error(sconn
);
3176 END_PROFILE(SMBreadbraw
);
3181 * Special check if an oplock break has been issued
3182 * and the readraw request croses on the wire, we must
3183 * return a zero length response here.
3186 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3189 * We have to do a check_fsp by hand here, as
3190 * we must always return 4 zero bytes on error,
3194 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3195 req
->vuid
!= fsp
->vuid
||
3196 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3198 * fsp could be NULL here so use the value from the packet. JRA.
3200 DEBUG(3,("reply_readbraw: fnum %d not valid "
3202 (int)SVAL(req
->vwv
+0, 0)));
3203 reply_readbraw_error(sconn
);
3204 END_PROFILE(SMBreadbraw
);
3208 /* Do a "by hand" version of CHECK_READ. */
3209 if (!(fsp
->can_read
||
3210 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3211 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3212 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3213 (int)SVAL(req
->vwv
+0, 0)));
3214 reply_readbraw_error(sconn
);
3215 END_PROFILE(SMBreadbraw
);
3219 flush_write_cache(fsp
, READRAW_FLUSH
);
3221 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3222 if(req
->wct
== 10) {
3224 * This is a large offset (64 bit) read.
3226 #ifdef LARGE_SMB_OFF_T
3228 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+8, 0)) << 32);
3230 #else /* !LARGE_SMB_OFF_T */
3233 * Ensure we haven't been sent a >32 bit offset.
3236 if(IVAL(req
->vwv
+8, 0) != 0) {
3237 DEBUG(0,("reply_readbraw: large offset "
3238 "(%x << 32) used and we don't support "
3239 "64 bit offsets.\n",
3240 (unsigned int)IVAL(req
->vwv
+8, 0) ));
3241 reply_readbraw_error(sconn
);
3242 END_PROFILE(SMBreadbraw
);
3246 #endif /* LARGE_SMB_OFF_T */
3249 DEBUG(0,("reply_readbraw: negative 64 bit "
3250 "readraw offset (%.0f) !\n",
3251 (double)startpos
));
3252 reply_readbraw_error(sconn
);
3253 END_PROFILE(SMBreadbraw
);
3258 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3259 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3261 /* ensure we don't overrun the packet size */
3262 maxcount
= MIN(65535,maxcount
);
3264 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3265 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3268 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3269 reply_readbraw_error(sconn
);
3270 END_PROFILE(SMBreadbraw
);
3274 if (fsp_stat(fsp
) == 0) {
3275 size
= fsp
->fsp_name
->st
.st_ex_size
;
3278 if (startpos
>= size
) {
3281 nread
= MIN(maxcount
,(size
- startpos
));
3284 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3285 if (nread
< mincount
)
3289 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3290 "min=%lu nread=%lu\n",
3291 fsp
->fnum
, (double)startpos
,
3292 (unsigned long)maxcount
,
3293 (unsigned long)mincount
,
3294 (unsigned long)nread
) );
3296 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3298 DEBUG(5,("reply_readbraw finished\n"));
3300 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3302 END_PROFILE(SMBreadbraw
);
3307 #define DBGC_CLASS DBGC_LOCKING
3309 /****************************************************************************
3310 Reply to a lockread (core+ protocol).
3311 ****************************************************************************/
3313 void reply_lockread(struct smb_request
*req
)
3315 connection_struct
*conn
= req
->conn
;
3322 struct byte_range_lock
*br_lck
= NULL
;
3324 struct smbd_server_connection
*sconn
= req
->sconn
;
3326 START_PROFILE(SMBlockread
);
3329 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3330 END_PROFILE(SMBlockread
);
3334 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3336 if (!check_fsp(conn
, req
, fsp
)) {
3337 END_PROFILE(SMBlockread
);
3341 if (!CHECK_READ(fsp
,req
)) {
3342 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3343 END_PROFILE(SMBlockread
);
3347 numtoread
= SVAL(req
->vwv
+1, 0);
3348 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3350 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3352 reply_outbuf(req
, 5, numtoread
+ 3);
3354 data
= smb_buf(req
->outbuf
) + 3;
3357 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3358 * protocol request that predates the read/write lock concept.
3359 * Thus instead of asking for a read lock here we need to ask
3360 * for a write lock. JRA.
3361 * Note that the requested lock size is unaffected by max_recv.
3364 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3366 (uint64_t)req
->smbpid
,
3367 (uint64_t)numtoread
,
3371 False
, /* Non-blocking lock. */
3375 TALLOC_FREE(br_lck
);
3377 if (NT_STATUS_V(status
)) {
3378 reply_nterror(req
, status
);
3379 END_PROFILE(SMBlockread
);
3384 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3387 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3388 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3389 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3390 (unsigned int)numtoread
,
3391 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3392 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3394 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3397 reply_nterror(req
, map_nt_error_from_unix(errno
));
3398 END_PROFILE(SMBlockread
);
3402 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3404 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3405 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3406 p
= smb_buf(req
->outbuf
);
3407 SCVAL(p
,0,0); /* pad byte. */
3410 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3411 fsp
->fnum
, (int)numtoread
, (int)nread
));
3413 END_PROFILE(SMBlockread
);
3418 #define DBGC_CLASS DBGC_ALL
3420 /****************************************************************************
3422 ****************************************************************************/
3424 void reply_read(struct smb_request
*req
)
3426 connection_struct
*conn
= req
->conn
;
3433 struct lock_struct lock
;
3434 struct smbd_server_connection
*sconn
= req
->sconn
;
3436 START_PROFILE(SMBread
);
3439 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3440 END_PROFILE(SMBread
);
3444 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3446 if (!check_fsp(conn
, req
, fsp
)) {
3447 END_PROFILE(SMBread
);
3451 if (!CHECK_READ(fsp
,req
)) {
3452 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3453 END_PROFILE(SMBread
);
3457 numtoread
= SVAL(req
->vwv
+1, 0);
3458 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3460 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3463 * The requested read size cannot be greater than max_recv. JRA.
3465 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3466 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3467 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3468 (unsigned int)numtoread
,
3469 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3470 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3473 reply_outbuf(req
, 5, numtoread
+3);
3475 data
= smb_buf(req
->outbuf
) + 3;
3477 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3478 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3481 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3482 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3483 END_PROFILE(SMBread
);
3488 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3491 reply_nterror(req
, map_nt_error_from_unix(errno
));
3495 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3497 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3498 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3499 SCVAL(smb_buf(req
->outbuf
),0,1);
3500 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3502 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3503 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3506 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3508 END_PROFILE(SMBread
);
3512 /****************************************************************************
3514 ****************************************************************************/
3516 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3522 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3523 data
= smb_buf(outbuf
);
3525 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3527 SCVAL(outbuf
,smb_vwv0
,0xFF);
3528 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3529 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3530 SSVAL(outbuf
,smb_vwv6
,
3532 + 1 /* the wct field */
3533 + 12 * sizeof(uint16_t) /* vwv */
3534 + 2); /* the buflen field */
3535 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3536 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3537 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3538 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3542 /****************************************************************************
3543 Reply to a read and X - possibly using sendfile.
3544 ****************************************************************************/
3546 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3547 files_struct
*fsp
, SMB_OFF_T startpos
,
3551 struct lock_struct lock
;
3552 int saved_errno
= 0;
3554 if(fsp_stat(fsp
) == -1) {
3555 reply_nterror(req
, map_nt_error_from_unix(errno
));
3559 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3560 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3563 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3564 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3568 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3569 (startpos
> fsp
->fsp_name
->st
.st_ex_size
)
3570 || (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3572 * We already know that we would do a short read, so don't
3573 * try the sendfile() path.
3575 goto nosendfile_read
;
3579 * We can only use sendfile on a non-chained packet
3580 * but we can use on a non-oplocked file. tridge proved this
3581 * on a train in Germany :-). JRA.
3584 if (!req_is_in_chain(req
) &&
3585 !is_encrypted_packet(req
->sconn
, req
->inbuf
) &&
3586 (fsp
->base_fsp
== NULL
) &&
3587 (fsp
->wcp
== NULL
) &&
3588 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3589 uint8 headerbuf
[smb_size
+ 12 * 2];
3593 * Set up the packet header before send. We
3594 * assume here the sendfile will work (get the
3595 * correct amount of data).
3598 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3600 construct_reply_common_req(req
, (char *)headerbuf
);
3601 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3603 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3604 startpos
, smb_maxcnt
);
3606 /* Returning ENOSYS means no data at all was sent.
3607 Do this as a normal read. */
3608 if (errno
== ENOSYS
) {
3613 * Special hack for broken Linux with no working sendfile. If we
3614 * return EINTR we sent the header but not the rest of the data.
3615 * Fake this up by doing read/write calls.
3618 if (errno
== EINTR
) {
3619 /* Ensure we don't do this again. */
3620 set_use_sendfile(SNUM(conn
), False
);
3621 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3622 nread
= fake_sendfile(fsp
, startpos
,
3625 DEBUG(0,("send_file_readX: "
3626 "fake_sendfile failed for "
3630 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3632 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3633 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3634 /* No outbuf here means successful sendfile. */
3638 DEBUG(0,("send_file_readX: sendfile failed for file "
3639 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3641 exit_server_cleanly("send_file_readX sendfile failed");
3642 } else if (nread
== 0) {
3644 * Some sendfile implementations return 0 to indicate
3645 * that there was a short read, but nothing was
3646 * actually written to the socket. In this case,
3647 * fallback to the normal read path so the header gets
3648 * the correct byte count.
3650 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3651 "falling back to the normal read: %s\n",
3656 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3657 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3659 /* Deal with possible short send. */
3660 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3661 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3663 /* No outbuf here means successful sendfile. */
3664 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3665 SMB_PERFCOUNT_END(&req
->pcd
);
3671 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3672 uint8 headerbuf
[smb_size
+ 2*12];
3674 construct_reply_common_req(req
, (char *)headerbuf
);
3675 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3677 /* Send out the header. */
3678 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3679 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3681 char addr
[INET6_ADDRSTRLEN
];
3683 * Try and give an error message saying what
3686 DEBUG(0, ("write_data failed for client %s. "
3688 get_peer_addr(req
->sconn
->sock
, addr
,
3692 DEBUG(0,("send_file_readX: write_data failed for file "
3693 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3695 exit_server_cleanly("send_file_readX sendfile failed");
3697 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3699 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3700 "file %s (%s).\n", fsp_str_dbg(fsp
),
3702 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3709 reply_outbuf(req
, 12, smb_maxcnt
);
3711 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3712 saved_errno
= errno
;
3714 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3717 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3721 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3723 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3724 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3730 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3731 TALLOC_FREE(req
->outbuf
);
3735 /****************************************************************************
3736 Reply to a read and X.
3737 ****************************************************************************/
3739 void reply_read_and_X(struct smb_request
*req
)
3741 struct smbd_server_connection
*sconn
= req
->sconn
;
3742 connection_struct
*conn
= req
->conn
;
3746 bool big_readX
= False
;
3748 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3751 START_PROFILE(SMBreadX
);
3753 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3754 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3758 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3759 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3760 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3762 /* If it's an IPC, pass off the pipe handler. */
3764 reply_pipe_read_and_X(req
);
3765 END_PROFILE(SMBreadX
);
3769 if (!check_fsp(conn
, req
, fsp
)) {
3770 END_PROFILE(SMBreadX
);
3774 if (!CHECK_READ(fsp
,req
)) {
3775 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3776 END_PROFILE(SMBreadX
);
3780 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_LARGE_READ_CAP
) ||
3781 (get_remote_arch() == RA_SAMBA
)) {
3783 * This is Samba only behavior (up to Samba 3.6)!
3785 * Windows 2008 R2 ignores the upper_size,
3786 * so we do unless unix extentions are active
3787 * or "smbclient" is talking to us.
3789 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3790 smb_maxcnt
|= (upper_size
<<16);
3791 if (upper_size
> 1) {
3792 /* Can't do this on a chained packet. */
3793 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3794 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3795 END_PROFILE(SMBreadX
);
3798 /* We currently don't do this on signed or sealed data. */
3799 if (srv_is_signing_active(req
->sconn
) ||
3800 is_encrypted_packet(req
->sconn
, req
->inbuf
)) {
3801 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3802 END_PROFILE(SMBreadX
);
3805 /* Is there room in the reply for this data ? */
3806 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3808 NT_STATUS_INVALID_PARAMETER
);
3809 END_PROFILE(SMBreadX
);
3816 if (req
->wct
== 12) {
3817 #ifdef LARGE_SMB_OFF_T
3819 * This is a large offset (64 bit) read.
3821 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+10, 0)) << 32);
3823 #else /* !LARGE_SMB_OFF_T */
3826 * Ensure we haven't been sent a >32 bit offset.
3829 if(IVAL(req
->vwv
+10, 0) != 0) {
3830 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3831 "used and we don't support 64 bit offsets.\n",
3832 (unsigned int)IVAL(req
->vwv
+10, 0) ));
3833 END_PROFILE(SMBreadX
);
3834 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3838 #endif /* LARGE_SMB_OFF_T */
3843 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3848 if (NT_STATUS_IS_OK(status
)) {
3849 /* Read scheduled - we're done. */
3852 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3853 /* Real error - report to client. */
3854 END_PROFILE(SMBreadX
);
3855 reply_nterror(req
, status
);
3858 /* NT_STATUS_RETRY - fall back to sync read. */
3861 smbd_lock_socket(req
->sconn
);
3862 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3863 smbd_unlock_socket(req
->sconn
);
3866 END_PROFILE(SMBreadX
);
3870 /****************************************************************************
3871 Error replies to writebraw must have smb_wct == 1. Fix this up.
3872 ****************************************************************************/
3874 void error_to_writebrawerr(struct smb_request
*req
)
3876 uint8
*old_outbuf
= req
->outbuf
;
3878 reply_outbuf(req
, 1, 0);
3880 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3881 TALLOC_FREE(old_outbuf
);
3884 /****************************************************************************
3885 Read 4 bytes of a smb packet and return the smb length of the packet.
3886 Store the result in the buffer. This version of the function will
3887 never return a session keepalive (length of zero).
3888 Timeout is in milliseconds.
3889 ****************************************************************************/
3891 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3894 uint8_t msgtype
= NBSSkeepalive
;
3896 while (msgtype
== NBSSkeepalive
) {
3899 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3901 if (!NT_STATUS_IS_OK(status
)) {
3902 char addr
[INET6_ADDRSTRLEN
];
3903 /* Try and give an error message
3904 * saying what client failed. */
3905 DEBUG(0, ("read_fd_with_timeout failed for "
3906 "client %s read error = %s.\n",
3907 get_peer_addr(fd
,addr
,sizeof(addr
)),
3908 nt_errstr(status
)));
3912 msgtype
= CVAL(inbuf
, 0);
3915 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3916 (unsigned long)len
));
3918 return NT_STATUS_OK
;
3921 /****************************************************************************
3922 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3923 ****************************************************************************/
3925 void reply_writebraw(struct smb_request
*req
)
3927 connection_struct
*conn
= req
->conn
;
3930 ssize_t total_written
=0;
3931 size_t numtowrite
=0;
3934 const char *data
=NULL
;
3937 struct lock_struct lock
;
3940 START_PROFILE(SMBwritebraw
);
3943 * If we ever reply with an error, it must have the SMB command
3944 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3947 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
3949 if (srv_is_signing_active(req
->sconn
)) {
3950 END_PROFILE(SMBwritebraw
);
3951 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3952 "raw reads/writes are disallowed.");
3955 if (req
->wct
< 12) {
3956 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3957 error_to_writebrawerr(req
);
3958 END_PROFILE(SMBwritebraw
);
3962 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3963 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3964 "'async smb echo handler = yes'\n"));
3965 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3966 error_to_writebrawerr(req
);
3967 END_PROFILE(SMBwritebraw
);
3971 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3972 if (!check_fsp(conn
, req
, fsp
)) {
3973 error_to_writebrawerr(req
);
3974 END_PROFILE(SMBwritebraw
);
3978 if (!CHECK_WRITE(fsp
)) {
3979 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3980 error_to_writebrawerr(req
);
3981 END_PROFILE(SMBwritebraw
);
3985 tcount
= IVAL(req
->vwv
+1, 0);
3986 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3987 write_through
= BITSETW(req
->vwv
+7,0);
3989 /* We have to deal with slightly different formats depending
3990 on whether we are using the core+ or lanman1.0 protocol */
3992 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
3993 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
3994 data
= smb_buf_const(req
->inbuf
);
3996 numtowrite
= SVAL(req
->vwv
+10, 0);
3997 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4000 /* Ensure we don't write bytes past the end of this packet. */
4001 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4002 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4003 error_to_writebrawerr(req
);
4004 END_PROFILE(SMBwritebraw
);
4008 if (!fsp
->print_file
) {
4009 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4010 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4013 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4014 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4015 error_to_writebrawerr(req
);
4016 END_PROFILE(SMBwritebraw
);
4022 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4025 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4026 "wrote=%d sync=%d\n",
4027 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4028 (int)nwritten
, (int)write_through
));
4030 if (nwritten
< (ssize_t
)numtowrite
) {
4031 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4032 error_to_writebrawerr(req
);
4036 total_written
= nwritten
;
4038 /* Allocate a buffer of 64k + length. */
4039 buf
= talloc_array(NULL
, char, 65540);
4041 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4042 error_to_writebrawerr(req
);
4046 /* Return a SMBwritebraw message to the redirector to tell
4047 * it to send more bytes */
4049 memcpy(buf
, req
->inbuf
, smb_size
);
4050 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4051 SCVAL(buf
,smb_com
,SMBwritebraw
);
4052 SSVALS(buf
,smb_vwv0
,0xFFFF);
4054 if (!srv_send_smb(req
->sconn
,
4056 false, 0, /* no signing */
4057 IS_CONN_ENCRYPTED(conn
),
4059 exit_server_cleanly("reply_writebraw: srv_send_smb "
4063 /* Now read the raw data into the buffer and write it */
4064 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4066 if (!NT_STATUS_IS_OK(status
)) {
4067 exit_server_cleanly("secondary writebraw failed");
4070 /* Set up outbuf to return the correct size */
4071 reply_outbuf(req
, 1, 0);
4073 if (numtowrite
!= 0) {
4075 if (numtowrite
> 0xFFFF) {
4076 DEBUG(0,("reply_writebraw: Oversize secondary write "
4077 "raw requested (%u). Terminating\n",
4078 (unsigned int)numtowrite
));
4079 exit_server_cleanly("secondary writebraw failed");
4082 if (tcount
> nwritten
+numtowrite
) {
4083 DEBUG(3,("reply_writebraw: Client overestimated the "
4085 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4088 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4090 if (!NT_STATUS_IS_OK(status
)) {
4091 char addr
[INET6_ADDRSTRLEN
];
4092 /* Try and give an error message
4093 * saying what client failed. */
4094 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4095 "raw read failed (%s) for client %s. "
4096 "Terminating\n", nt_errstr(status
),
4097 get_peer_addr(req
->sconn
->sock
, addr
,
4099 exit_server_cleanly("secondary writebraw failed");
4102 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4103 if (nwritten
== -1) {
4105 reply_nterror(req
, map_nt_error_from_unix(errno
));
4106 error_to_writebrawerr(req
);
4110 if (nwritten
< (ssize_t
)numtowrite
) {
4111 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4112 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4116 total_written
+= nwritten
;
4121 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4123 status
= sync_file(conn
, fsp
, write_through
);
4124 if (!NT_STATUS_IS_OK(status
)) {
4125 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4126 fsp_str_dbg(fsp
), nt_errstr(status
)));
4127 reply_nterror(req
, status
);
4128 error_to_writebrawerr(req
);
4132 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4134 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4135 (int)total_written
));
4137 if (!fsp
->print_file
) {
4138 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4141 /* We won't return a status if write through is not selected - this
4142 * follows what WfWg does */
4143 END_PROFILE(SMBwritebraw
);
4145 if (!write_through
&& total_written
==tcount
) {
4147 #if RABBIT_PELLET_FIX
4149 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4150 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4153 if (!send_keepalive(req
->sconn
->sock
)) {
4154 exit_server_cleanly("reply_writebraw: send of "
4155 "keepalive failed");
4158 TALLOC_FREE(req
->outbuf
);
4163 if (!fsp
->print_file
) {
4164 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4167 END_PROFILE(SMBwritebraw
);
4172 #define DBGC_CLASS DBGC_LOCKING
4174 /****************************************************************************
4175 Reply to a writeunlock (core+).
4176 ****************************************************************************/
4178 void reply_writeunlock(struct smb_request
*req
)
4180 connection_struct
*conn
= req
->conn
;
4181 ssize_t nwritten
= -1;
4185 NTSTATUS status
= NT_STATUS_OK
;
4187 struct lock_struct lock
;
4188 int saved_errno
= 0;
4190 START_PROFILE(SMBwriteunlock
);
4193 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4194 END_PROFILE(SMBwriteunlock
);
4198 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4200 if (!check_fsp(conn
, req
, fsp
)) {
4201 END_PROFILE(SMBwriteunlock
);
4205 if (!CHECK_WRITE(fsp
)) {
4206 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4207 END_PROFILE(SMBwriteunlock
);
4211 numtowrite
= SVAL(req
->vwv
+1, 0);
4212 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4213 data
= (const char *)req
->buf
+ 3;
4215 if (!fsp
->print_file
&& numtowrite
> 0) {
4216 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4217 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4220 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4221 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4222 END_PROFILE(SMBwriteunlock
);
4227 /* The special X/Open SMB protocol handling of
4228 zero length writes is *NOT* done for
4230 if(numtowrite
== 0) {
4233 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4234 saved_errno
= errno
;
4237 status
= sync_file(conn
, fsp
, False
/* write through */);
4238 if (!NT_STATUS_IS_OK(status
)) {
4239 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4240 fsp_str_dbg(fsp
), nt_errstr(status
)));
4241 reply_nterror(req
, status
);
4246 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4250 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4251 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4255 if (numtowrite
&& !fsp
->print_file
) {
4256 status
= do_unlock(req
->sconn
->msg_ctx
,
4258 (uint64_t)req
->smbpid
,
4259 (uint64_t)numtowrite
,
4263 if (NT_STATUS_V(status
)) {
4264 reply_nterror(req
, status
);
4269 reply_outbuf(req
, 1, 0);
4271 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4273 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4274 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4277 if (numtowrite
&& !fsp
->print_file
) {
4278 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4281 END_PROFILE(SMBwriteunlock
);
4286 #define DBGC_CLASS DBGC_ALL
4288 /****************************************************************************
4290 ****************************************************************************/
4292 void reply_write(struct smb_request
*req
)
4294 connection_struct
*conn
= req
->conn
;
4296 ssize_t nwritten
= -1;
4300 struct lock_struct lock
;
4302 int saved_errno
= 0;
4304 START_PROFILE(SMBwrite
);
4307 END_PROFILE(SMBwrite
);
4308 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4312 /* If it's an IPC, pass off the pipe handler. */
4314 reply_pipe_write(req
);
4315 END_PROFILE(SMBwrite
);
4319 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4321 if (!check_fsp(conn
, req
, fsp
)) {
4322 END_PROFILE(SMBwrite
);
4326 if (!CHECK_WRITE(fsp
)) {
4327 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4328 END_PROFILE(SMBwrite
);
4332 numtowrite
= SVAL(req
->vwv
+1, 0);
4333 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4334 data
= (const char *)req
->buf
+ 3;
4336 if (!fsp
->print_file
) {
4337 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4338 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4341 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4342 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4343 END_PROFILE(SMBwrite
);
4349 * X/Open SMB protocol says that if smb_vwv1 is
4350 * zero then the file size should be extended or
4351 * truncated to the size given in smb_vwv[2-3].
4354 if(numtowrite
== 0) {
4356 * This is actually an allocate call, and set EOF. JRA.
4358 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
4360 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4363 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
4365 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4368 trigger_write_time_update_immediate(fsp
);
4370 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4373 status
= sync_file(conn
, fsp
, False
);
4374 if (!NT_STATUS_IS_OK(status
)) {
4375 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4376 fsp_str_dbg(fsp
), nt_errstr(status
)));
4377 reply_nterror(req
, status
);
4382 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4386 if((nwritten
== 0) && (numtowrite
!= 0)) {
4387 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4391 reply_outbuf(req
, 1, 0);
4393 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4395 if (nwritten
< (ssize_t
)numtowrite
) {
4396 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4397 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4400 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4403 if (!fsp
->print_file
) {
4404 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4407 END_PROFILE(SMBwrite
);
4411 /****************************************************************************
4412 Ensure a buffer is a valid writeX for recvfile purposes.
4413 ****************************************************************************/
4415 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4416 (2*14) + /* word count (including bcc) */ \
4419 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4420 const uint8_t *inbuf
)
4423 connection_struct
*conn
= NULL
;
4424 unsigned int doff
= 0;
4425 size_t len
= smb_len_large(inbuf
);
4427 if (is_encrypted_packet(sconn
, inbuf
)) {
4428 /* Can't do this on encrypted
4433 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4437 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4438 CVAL(inbuf
,smb_wct
) != 14) {
4439 DEBUG(10,("is_valid_writeX_buffer: chained or "
4440 "invalid word length.\n"));
4444 conn
= conn_find(sconn
, SVAL(inbuf
, smb_tid
));
4446 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4450 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4453 if (IS_PRINT(conn
)) {
4454 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4457 doff
= SVAL(inbuf
,smb_vwv11
);
4459 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4461 if (len
> doff
&& len
- doff
> 0xFFFF) {
4462 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4465 if (numtowrite
== 0) {
4466 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4470 /* Ensure the sizes match up. */
4471 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4472 /* no pad byte...old smbclient :-( */
4473 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4475 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4479 if (len
- doff
!= numtowrite
) {
4480 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4481 "len = %u, doff = %u, numtowrite = %u\n",
4484 (unsigned int)numtowrite
));
4488 DEBUG(10,("is_valid_writeX_buffer: true "
4489 "len = %u, doff = %u, numtowrite = %u\n",
4492 (unsigned int)numtowrite
));
4497 /****************************************************************************
4498 Reply to a write and X.
4499 ****************************************************************************/
4501 void reply_write_and_X(struct smb_request
*req
)
4503 connection_struct
*conn
= req
->conn
;
4505 struct lock_struct lock
;
4510 unsigned int smb_doff
;
4511 unsigned int smblen
;
4514 int saved_errno
= 0;
4516 START_PROFILE(SMBwriteX
);
4518 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4519 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4520 END_PROFILE(SMBwriteX
);
4524 numtowrite
= SVAL(req
->vwv
+10, 0);
4525 smb_doff
= SVAL(req
->vwv
+11, 0);
4526 smblen
= smb_len(req
->inbuf
);
4528 if (req
->unread_bytes
> 0xFFFF ||
4529 (smblen
> smb_doff
&&
4530 smblen
- smb_doff
> 0xFFFF)) {
4531 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4534 if (req
->unread_bytes
) {
4535 /* Can't do a recvfile write on IPC$ */
4537 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4538 END_PROFILE(SMBwriteX
);
4541 if (numtowrite
!= req
->unread_bytes
) {
4542 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4543 END_PROFILE(SMBwriteX
);
4547 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4548 smb_doff
+ numtowrite
> smblen
) {
4549 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4550 END_PROFILE(SMBwriteX
);
4555 /* If it's an IPC, pass off the pipe handler. */
4557 if (req
->unread_bytes
) {
4558 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4559 END_PROFILE(SMBwriteX
);
4562 reply_pipe_write_and_X(req
);
4563 END_PROFILE(SMBwriteX
);
4567 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4568 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4569 write_through
= BITSETW(req
->vwv
+7,0);
4571 if (!check_fsp(conn
, req
, fsp
)) {
4572 END_PROFILE(SMBwriteX
);
4576 if (!CHECK_WRITE(fsp
)) {
4577 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4578 END_PROFILE(SMBwriteX
);
4582 data
= smb_base(req
->inbuf
) + smb_doff
;
4584 if(req
->wct
== 14) {
4585 #ifdef LARGE_SMB_OFF_T
4587 * This is a large offset (64 bit) write.
4589 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+12, 0)) << 32);
4591 #else /* !LARGE_SMB_OFF_T */
4594 * Ensure we haven't been sent a >32 bit offset.
4597 if(IVAL(req
->vwv
+12, 0) != 0) {
4598 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4599 "used and we don't support 64 bit offsets.\n",
4600 (unsigned int)IVAL(req
->vwv
+12, 0) ));
4601 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4602 END_PROFILE(SMBwriteX
);
4606 #endif /* LARGE_SMB_OFF_T */
4609 /* X/Open SMB protocol says that, unlike SMBwrite
4610 if the length is zero then NO truncation is
4611 done, just a write of zero. To truncate a file,
4614 if(numtowrite
== 0) {
4617 if (req
->unread_bytes
== 0) {
4618 status
= schedule_aio_write_and_X(conn
,
4625 if (NT_STATUS_IS_OK(status
)) {
4626 /* write scheduled - we're done. */
4629 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4630 /* Real error - report to client. */
4631 reply_nterror(req
, status
);
4634 /* NT_STATUS_RETRY - fall through to sync write. */
4637 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4638 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4641 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4642 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4646 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4647 saved_errno
= errno
;
4649 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4653 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4657 if((nwritten
== 0) && (numtowrite
!= 0)) {
4658 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4662 reply_outbuf(req
, 6, 0);
4663 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4664 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4666 if (nwritten
< (ssize_t
)numtowrite
) {
4667 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4668 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4671 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4672 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4674 status
= sync_file(conn
, fsp
, write_through
);
4675 if (!NT_STATUS_IS_OK(status
)) {
4676 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4677 fsp_str_dbg(fsp
), nt_errstr(status
)));
4678 reply_nterror(req
, status
);
4682 END_PROFILE(SMBwriteX
);
4687 END_PROFILE(SMBwriteX
);
4691 /****************************************************************************
4693 ****************************************************************************/
4695 void reply_lseek(struct smb_request
*req
)
4697 connection_struct
*conn
= req
->conn
;
4703 START_PROFILE(SMBlseek
);
4706 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4707 END_PROFILE(SMBlseek
);
4711 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4713 if (!check_fsp(conn
, req
, fsp
)) {
4717 flush_write_cache(fsp
, SEEK_FLUSH
);
4719 mode
= SVAL(req
->vwv
+1, 0) & 3;
4720 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4721 startpos
= (SMB_OFF_T
)IVALS(req
->vwv
+2, 0);
4730 res
= fsp
->fh
->pos
+ startpos
;
4741 if (umode
== SEEK_END
) {
4742 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4743 if(errno
== EINVAL
) {
4744 SMB_OFF_T current_pos
= startpos
;
4746 if(fsp_stat(fsp
) == -1) {
4748 map_nt_error_from_unix(errno
));
4749 END_PROFILE(SMBlseek
);
4753 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4755 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4760 reply_nterror(req
, map_nt_error_from_unix(errno
));
4761 END_PROFILE(SMBlseek
);
4768 reply_outbuf(req
, 2, 0);
4769 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4771 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4772 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4774 END_PROFILE(SMBlseek
);
4778 /****************************************************************************
4780 ****************************************************************************/
4782 void reply_flush(struct smb_request
*req
)
4784 connection_struct
*conn
= req
->conn
;
4788 START_PROFILE(SMBflush
);
4791 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4795 fnum
= SVAL(req
->vwv
+0, 0);
4796 fsp
= file_fsp(req
, fnum
);
4798 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4803 file_sync_all(conn
);
4805 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4806 if (!NT_STATUS_IS_OK(status
)) {
4807 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4808 fsp_str_dbg(fsp
), nt_errstr(status
)));
4809 reply_nterror(req
, status
);
4810 END_PROFILE(SMBflush
);
4815 reply_outbuf(req
, 0, 0);
4817 DEBUG(3,("flush\n"));
4818 END_PROFILE(SMBflush
);
4822 /****************************************************************************
4824 conn POINTER CAN BE NULL HERE !
4825 ****************************************************************************/
4827 void reply_exit(struct smb_request
*req
)
4829 START_PROFILE(SMBexit
);
4831 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
4833 reply_outbuf(req
, 0, 0);
4835 DEBUG(3,("exit\n"));
4837 END_PROFILE(SMBexit
);
4841 /****************************************************************************
4842 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4843 ****************************************************************************/
4845 void reply_close(struct smb_request
*req
)
4847 connection_struct
*conn
= req
->conn
;
4848 NTSTATUS status
= NT_STATUS_OK
;
4849 files_struct
*fsp
= NULL
;
4850 START_PROFILE(SMBclose
);
4853 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4854 END_PROFILE(SMBclose
);
4858 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4861 * We can only use check_fsp if we know it's not a directory.
4864 if (!check_fsp_open(conn
, req
, fsp
)) {
4865 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4866 END_PROFILE(SMBclose
);
4870 if(fsp
->is_directory
) {
4872 * Special case - close NT SMB directory handle.
4874 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4875 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4879 * Close ordinary file.
4882 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4883 fsp
->fh
->fd
, fsp
->fnum
,
4884 conn
->num_files_open
));
4887 * Take care of any time sent in the close.
4890 t
= srv_make_unix_date3(req
->vwv
+1);
4891 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4894 * close_file() returns the unix errno if an error
4895 * was detected on close - normally this is due to
4896 * a disk full error. If not then it was probably an I/O error.
4899 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4902 if (!NT_STATUS_IS_OK(status
)) {
4903 reply_nterror(req
, status
);
4904 END_PROFILE(SMBclose
);
4908 reply_outbuf(req
, 0, 0);
4909 END_PROFILE(SMBclose
);
4913 /****************************************************************************
4914 Reply to a writeclose (Core+ protocol).
4915 ****************************************************************************/
4917 void reply_writeclose(struct smb_request
*req
)
4919 connection_struct
*conn
= req
->conn
;
4921 ssize_t nwritten
= -1;
4922 NTSTATUS close_status
= NT_STATUS_OK
;
4925 struct timespec mtime
;
4927 struct lock_struct lock
;
4929 START_PROFILE(SMBwriteclose
);
4932 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4933 END_PROFILE(SMBwriteclose
);
4937 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4939 if (!check_fsp(conn
, req
, fsp
)) {
4940 END_PROFILE(SMBwriteclose
);
4943 if (!CHECK_WRITE(fsp
)) {
4944 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4945 END_PROFILE(SMBwriteclose
);
4949 numtowrite
= SVAL(req
->vwv
+1, 0);
4950 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4951 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4952 data
= (const char *)req
->buf
+ 1;
4954 if (!fsp
->print_file
) {
4955 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4956 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4959 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4960 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4961 END_PROFILE(SMBwriteclose
);
4966 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4968 set_close_write_time(fsp
, mtime
);
4971 * More insanity. W2K only closes the file if writelen > 0.
4976 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4977 "file %s\n", fsp_str_dbg(fsp
)));
4978 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4981 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4982 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4983 conn
->num_files_open
));
4985 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4986 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4990 if(!NT_STATUS_IS_OK(close_status
)) {
4991 reply_nterror(req
, close_status
);
4995 reply_outbuf(req
, 1, 0);
4997 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5000 if (numtowrite
&& !fsp
->print_file
) {
5001 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5004 END_PROFILE(SMBwriteclose
);
5009 #define DBGC_CLASS DBGC_LOCKING
5011 /****************************************************************************
5013 ****************************************************************************/
5015 void reply_lock(struct smb_request
*req
)
5017 connection_struct
*conn
= req
->conn
;
5018 uint64_t count
,offset
;
5021 struct byte_range_lock
*br_lck
= NULL
;
5023 START_PROFILE(SMBlock
);
5026 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5027 END_PROFILE(SMBlock
);
5031 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5033 if (!check_fsp(conn
, req
, fsp
)) {
5034 END_PROFILE(SMBlock
);
5038 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5039 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5041 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5042 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
5044 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5046 (uint64_t)req
->smbpid
,
5051 False
, /* Non-blocking lock. */
5056 TALLOC_FREE(br_lck
);
5058 if (NT_STATUS_V(status
)) {
5059 reply_nterror(req
, status
);
5060 END_PROFILE(SMBlock
);
5064 reply_outbuf(req
, 0, 0);
5066 END_PROFILE(SMBlock
);
5070 /****************************************************************************
5072 ****************************************************************************/
5074 void reply_unlock(struct smb_request
*req
)
5076 connection_struct
*conn
= req
->conn
;
5077 uint64_t count
,offset
;
5081 START_PROFILE(SMBunlock
);
5084 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5085 END_PROFILE(SMBunlock
);
5089 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5091 if (!check_fsp(conn
, req
, fsp
)) {
5092 END_PROFILE(SMBunlock
);
5096 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5097 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5099 status
= do_unlock(req
->sconn
->msg_ctx
,
5101 (uint64_t)req
->smbpid
,
5106 if (NT_STATUS_V(status
)) {
5107 reply_nterror(req
, status
);
5108 END_PROFILE(SMBunlock
);
5112 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5113 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
5115 reply_outbuf(req
, 0, 0);
5117 END_PROFILE(SMBunlock
);
5122 #define DBGC_CLASS DBGC_ALL
5124 /****************************************************************************
5126 conn POINTER CAN BE NULL HERE !
5127 ****************************************************************************/
5129 void reply_tdis(struct smb_request
*req
)
5131 connection_struct
*conn
= req
->conn
;
5132 START_PROFILE(SMBtdis
);
5135 DEBUG(4,("Invalid connection in tdis\n"));
5136 reply_nterror(req
, NT_STATUS_NETWORK_NAME_DELETED
);
5137 END_PROFILE(SMBtdis
);
5143 close_cnum(conn
,req
->vuid
);
5146 reply_outbuf(req
, 0, 0);
5147 END_PROFILE(SMBtdis
);
5151 /****************************************************************************
5153 conn POINTER CAN BE NULL HERE !
5154 ****************************************************************************/
5156 void reply_echo(struct smb_request
*req
)
5158 connection_struct
*conn
= req
->conn
;
5159 struct smb_perfcount_data local_pcd
;
5160 struct smb_perfcount_data
*cur_pcd
;
5164 START_PROFILE(SMBecho
);
5166 smb_init_perfcount_data(&local_pcd
);
5169 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5170 END_PROFILE(SMBecho
);
5174 smb_reverb
= SVAL(req
->vwv
+0, 0);
5176 reply_outbuf(req
, 1, req
->buflen
);
5178 /* copy any incoming data back out */
5179 if (req
->buflen
> 0) {
5180 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5183 if (smb_reverb
> 100) {
5184 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5188 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5190 /* this makes sure we catch the request pcd */
5191 if (seq_num
== smb_reverb
) {
5192 cur_pcd
= &req
->pcd
;
5194 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5195 cur_pcd
= &local_pcd
;
5198 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5200 show_msg((char *)req
->outbuf
);
5201 if (!srv_send_smb(req
->sconn
,
5202 (char *)req
->outbuf
,
5203 true, req
->seqnum
+1,
5204 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5206 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5209 DEBUG(3,("echo %d times\n", smb_reverb
));
5211 TALLOC_FREE(req
->outbuf
);
5213 END_PROFILE(SMBecho
);
5217 /****************************************************************************
5218 Reply to a printopen.
5219 ****************************************************************************/
5221 void reply_printopen(struct smb_request
*req
)
5223 connection_struct
*conn
= req
->conn
;
5227 START_PROFILE(SMBsplopen
);
5230 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5231 END_PROFILE(SMBsplopen
);
5235 if (!CAN_PRINT(conn
)) {
5236 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5237 END_PROFILE(SMBsplopen
);
5241 status
= file_new(req
, conn
, &fsp
);
5242 if(!NT_STATUS_IS_OK(status
)) {
5243 reply_nterror(req
, status
);
5244 END_PROFILE(SMBsplopen
);
5248 /* Open for exclusive use, write only. */
5249 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5251 if (!NT_STATUS_IS_OK(status
)) {
5252 file_free(req
, fsp
);
5253 reply_nterror(req
, status
);
5254 END_PROFILE(SMBsplopen
);
5258 reply_outbuf(req
, 1, 0);
5259 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5261 DEBUG(3,("openprint fd=%d fnum=%d\n",
5262 fsp
->fh
->fd
, fsp
->fnum
));
5264 END_PROFILE(SMBsplopen
);
5268 /****************************************************************************
5269 Reply to a printclose.
5270 ****************************************************************************/
5272 void reply_printclose(struct smb_request
*req
)
5274 connection_struct
*conn
= req
->conn
;
5278 START_PROFILE(SMBsplclose
);
5281 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5282 END_PROFILE(SMBsplclose
);
5286 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5288 if (!check_fsp(conn
, req
, fsp
)) {
5289 END_PROFILE(SMBsplclose
);
5293 if (!CAN_PRINT(conn
)) {
5294 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5295 END_PROFILE(SMBsplclose
);
5299 DEBUG(3,("printclose fd=%d fnum=%d\n",
5300 fsp
->fh
->fd
,fsp
->fnum
));
5302 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5304 if(!NT_STATUS_IS_OK(status
)) {
5305 reply_nterror(req
, status
);
5306 END_PROFILE(SMBsplclose
);
5310 reply_outbuf(req
, 0, 0);
5312 END_PROFILE(SMBsplclose
);
5316 /****************************************************************************
5317 Reply to a printqueue.
5318 ****************************************************************************/
5320 void reply_printqueue(struct smb_request
*req
)
5322 connection_struct
*conn
= req
->conn
;
5326 START_PROFILE(SMBsplretq
);
5329 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5330 END_PROFILE(SMBsplretq
);
5334 max_count
= SVAL(req
->vwv
+0, 0);
5335 start_index
= SVAL(req
->vwv
+1, 0);
5337 /* we used to allow the client to get the cnum wrong, but that
5338 is really quite gross and only worked when there was only
5339 one printer - I think we should now only accept it if they
5340 get it right (tridge) */
5341 if (!CAN_PRINT(conn
)) {
5342 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5343 END_PROFILE(SMBsplretq
);
5347 reply_outbuf(req
, 2, 3);
5348 SSVAL(req
->outbuf
,smb_vwv0
,0);
5349 SSVAL(req
->outbuf
,smb_vwv1
,0);
5350 SCVAL(smb_buf(req
->outbuf
),0,1);
5351 SSVAL(smb_buf(req
->outbuf
),1,0);
5353 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5354 start_index
, max_count
));
5357 TALLOC_CTX
*mem_ctx
= talloc_tos();
5360 const char *sharename
= lp_servicename(SNUM(conn
));
5361 struct rpc_pipe_client
*cli
= NULL
;
5362 struct dcerpc_binding_handle
*b
= NULL
;
5363 struct policy_handle handle
;
5364 struct spoolss_DevmodeContainer devmode_ctr
;
5365 union spoolss_JobInfo
*info
;
5367 uint32_t num_to_get
;
5371 ZERO_STRUCT(handle
);
5373 status
= rpc_pipe_open_interface(conn
,
5374 &ndr_table_spoolss
.syntax_id
,
5376 conn
->sconn
->remote_address
,
5377 conn
->sconn
->msg_ctx
,
5379 if (!NT_STATUS_IS_OK(status
)) {
5380 DEBUG(0, ("reply_printqueue: "
5381 "could not connect to spoolss: %s\n",
5382 nt_errstr(status
)));
5383 reply_nterror(req
, status
);
5386 b
= cli
->binding_handle
;
5388 ZERO_STRUCT(devmode_ctr
);
5390 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5393 SEC_FLAG_MAXIMUM_ALLOWED
,
5396 if (!NT_STATUS_IS_OK(status
)) {
5397 reply_nterror(req
, status
);
5400 if (!W_ERROR_IS_OK(werr
)) {
5401 reply_nterror(req
, werror_to_ntstatus(werr
));
5405 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5413 if (!W_ERROR_IS_OK(werr
)) {
5414 reply_nterror(req
, werror_to_ntstatus(werr
));
5418 if (max_count
> 0) {
5419 first
= start_index
;
5421 first
= start_index
+ max_count
+ 1;
5424 if (first
>= count
) {
5427 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5430 for (i
= first
; i
< num_to_get
; i
++) {
5433 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5435 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5436 info
[i
].info2
.job_id
);
5438 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5444 srv_put_dos_date2(p
, 0, qtime
);
5445 SCVAL(p
, 4, qstatus
);
5446 SSVAL(p
, 5, qrapjobid
);
5447 SIVAL(p
, 7, info
[i
].info2
.size
);
5449 srvstr_push(blob
, req
->flags2
, p
+12,
5450 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5452 if (message_push_blob(
5455 blob
, sizeof(blob
))) == -1) {
5456 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5462 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5463 SSVAL(req
->outbuf
,smb_vwv1
,
5464 (max_count
>0?first
+count
:first
-1));
5465 SCVAL(smb_buf(req
->outbuf
),0,1);
5466 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5470 DEBUG(3, ("%u entries returned in queue\n",
5474 if (b
&& is_valid_policy_hnd(&handle
)) {
5475 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5480 END_PROFILE(SMBsplretq
);
5484 /****************************************************************************
5485 Reply to a printwrite.
5486 ****************************************************************************/
5488 void reply_printwrite(struct smb_request
*req
)
5490 connection_struct
*conn
= req
->conn
;
5495 START_PROFILE(SMBsplwr
);
5498 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5499 END_PROFILE(SMBsplwr
);
5503 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5505 if (!check_fsp(conn
, req
, fsp
)) {
5506 END_PROFILE(SMBsplwr
);
5510 if (!fsp
->print_file
) {
5511 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5512 END_PROFILE(SMBsplwr
);
5516 if (!CHECK_WRITE(fsp
)) {
5517 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5518 END_PROFILE(SMBsplwr
);
5522 numtowrite
= SVAL(req
->buf
, 1);
5524 if (req
->buflen
< numtowrite
+ 3) {
5525 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5526 END_PROFILE(SMBsplwr
);
5530 data
= (const char *)req
->buf
+ 3;
5532 if (write_file(req
,fsp
,data
,(SMB_OFF_T
)-1,numtowrite
) != numtowrite
) {
5533 reply_nterror(req
, map_nt_error_from_unix(errno
));
5534 END_PROFILE(SMBsplwr
);
5538 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
5540 END_PROFILE(SMBsplwr
);
5544 /****************************************************************************
5546 ****************************************************************************/
5548 void reply_mkdir(struct smb_request
*req
)
5550 connection_struct
*conn
= req
->conn
;
5551 struct smb_filename
*smb_dname
= NULL
;
5552 char *directory
= NULL
;
5554 TALLOC_CTX
*ctx
= talloc_tos();
5556 START_PROFILE(SMBmkdir
);
5558 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5559 STR_TERMINATE
, &status
);
5560 if (!NT_STATUS_IS_OK(status
)) {
5561 reply_nterror(req
, status
);
5565 status
= filename_convert(ctx
, conn
,
5566 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5571 if (!NT_STATUS_IS_OK(status
)) {
5572 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5573 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5574 ERRSRV
, ERRbadpath
);
5577 reply_nterror(req
, status
);
5581 status
= create_directory(conn
, req
, smb_dname
);
5583 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5585 if (!NT_STATUS_IS_OK(status
)) {
5587 if (!use_nt_status()
5588 && NT_STATUS_EQUAL(status
,
5589 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5591 * Yes, in the DOS error code case we get a
5592 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5593 * samba4 torture test.
5595 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5598 reply_nterror(req
, status
);
5602 reply_outbuf(req
, 0, 0);
5604 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5606 TALLOC_FREE(smb_dname
);
5607 END_PROFILE(SMBmkdir
);
5611 /****************************************************************************
5613 ****************************************************************************/
5615 void reply_rmdir(struct smb_request
*req
)
5617 connection_struct
*conn
= req
->conn
;
5618 struct smb_filename
*smb_dname
= NULL
;
5619 char *directory
= NULL
;
5621 TALLOC_CTX
*ctx
= talloc_tos();
5622 files_struct
*fsp
= NULL
;
5624 struct smbd_server_connection
*sconn
= req
->sconn
;
5626 START_PROFILE(SMBrmdir
);
5628 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5629 STR_TERMINATE
, &status
);
5630 if (!NT_STATUS_IS_OK(status
)) {
5631 reply_nterror(req
, status
);
5635 status
= filename_convert(ctx
, conn
,
5636 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5641 if (!NT_STATUS_IS_OK(status
)) {
5642 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5643 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5644 ERRSRV
, ERRbadpath
);
5647 reply_nterror(req
, status
);
5651 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5652 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5656 status
= SMB_VFS_CREATE_FILE(
5659 0, /* root_dir_fid */
5660 smb_dname
, /* fname */
5661 DELETE_ACCESS
, /* access_mask */
5662 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5664 FILE_OPEN
, /* create_disposition*/
5665 FILE_DIRECTORY_FILE
, /* create_options */
5666 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5667 0, /* oplock_request */
5668 0, /* allocation_size */
5669 0, /* private_flags */
5675 if (!NT_STATUS_IS_OK(status
)) {
5676 if (open_was_deferred(req
->sconn
, req
->mid
)) {
5677 /* We have re-scheduled this call. */
5680 reply_nterror(req
, status
);
5684 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5685 if (!NT_STATUS_IS_OK(status
)) {
5686 close_file(req
, fsp
, ERROR_CLOSE
);
5687 reply_nterror(req
, status
);
5691 if (!set_delete_on_close(fsp
, true, conn
->session_info
->unix_token
)) {
5692 close_file(req
, fsp
, ERROR_CLOSE
);
5693 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5697 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5698 if (!NT_STATUS_IS_OK(status
)) {
5699 reply_nterror(req
, status
);
5701 reply_outbuf(req
, 0, 0);
5704 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5706 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5708 TALLOC_FREE(smb_dname
);
5709 END_PROFILE(SMBrmdir
);
5713 /*******************************************************************
5714 Resolve wildcards in a filename rename.
5715 ********************************************************************/
5717 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5722 char *name2_copy
= NULL
;
5727 char *p
,*p2
, *pname1
, *pname2
;
5729 name2_copy
= talloc_strdup(ctx
, name2
);
5734 pname1
= strrchr_m(name1
,'/');
5735 pname2
= strrchr_m(name2_copy
,'/');
5737 if (!pname1
|| !pname2
) {
5741 /* Truncate the copy of name2 at the last '/' */
5744 /* Now go past the '/' */
5748 root1
= talloc_strdup(ctx
, pname1
);
5749 root2
= talloc_strdup(ctx
, pname2
);
5751 if (!root1
|| !root2
) {
5755 p
= strrchr_m(root1
,'.');
5758 ext1
= talloc_strdup(ctx
, p
+1);
5760 ext1
= talloc_strdup(ctx
, "");
5762 p
= strrchr_m(root2
,'.');
5765 ext2
= talloc_strdup(ctx
, p
+1);
5767 ext2
= talloc_strdup(ctx
, "");
5770 if (!ext1
|| !ext2
) {
5778 /* Hmmm. Should this be mb-aware ? */
5781 } else if (*p2
== '*') {
5783 root2
= talloc_asprintf(ctx
, "%s%s",
5802 /* Hmmm. Should this be mb-aware ? */
5805 } else if (*p2
== '*') {
5807 ext2
= talloc_asprintf(ctx
, "%s%s",
5823 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5828 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5840 /****************************************************************************
5841 Ensure open files have their names updated. Updated to notify other smbd's
5843 ****************************************************************************/
5845 static void rename_open_files(connection_struct
*conn
,
5846 struct share_mode_lock
*lck
,
5847 uint32_t orig_name_hash
,
5848 const struct smb_filename
*smb_fname_dst
)
5851 bool did_rename
= False
;
5853 uint32_t new_name_hash
= 0;
5855 for(fsp
= file_find_di_first(conn
->sconn
, lck
->id
); fsp
;
5856 fsp
= file_find_di_next(fsp
)) {
5857 /* fsp_name is a relative path under the fsp. To change this for other
5858 sharepaths we need to manipulate relative paths. */
5859 /* TODO - create the absolute path and manipulate the newname
5860 relative to the sharepath. */
5861 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5864 if (fsp
->name_hash
!= orig_name_hash
) {
5867 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5868 "(file_id %s) from %s -> %s\n", fsp
->fnum
,
5869 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
5870 smb_fname_str_dbg(smb_fname_dst
)));
5872 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
5873 if (NT_STATUS_IS_OK(status
)) {
5875 new_name_hash
= fsp
->name_hash
;
5880 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5881 "for %s\n", file_id_string_tos(&lck
->id
),
5882 smb_fname_str_dbg(smb_fname_dst
)));
5885 /* Send messages to all smbd's (not ourself) that the name has changed. */
5886 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, conn
->connectpath
,
5887 orig_name_hash
, new_name_hash
,
5892 /****************************************************************************
5893 We need to check if the source path is a parent directory of the destination
5894 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5895 refuse the rename with a sharing violation. Under UNIX the above call can
5896 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5897 probably need to check that the client is a Windows one before disallowing
5898 this as a UNIX client (one with UNIX extensions) can know the source is a
5899 symlink and make this decision intelligently. Found by an excellent bug
5900 report from <AndyLiebman@aol.com>.
5901 ****************************************************************************/
5903 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
5904 const struct smb_filename
*smb_fname_dst
)
5906 const char *psrc
= smb_fname_src
->base_name
;
5907 const char *pdst
= smb_fname_dst
->base_name
;
5910 if (psrc
[0] == '.' && psrc
[1] == '/') {
5913 if (pdst
[0] == '.' && pdst
[1] == '/') {
5916 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5919 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5923 * Do the notify calls from a rename
5926 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5927 const struct smb_filename
*smb_fname_src
,
5928 const struct smb_filename
*smb_fname_dst
)
5930 char *parent_dir_src
= NULL
;
5931 char *parent_dir_dst
= NULL
;
5934 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5935 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5937 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
5938 &parent_dir_src
, NULL
) ||
5939 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
5940 &parent_dir_dst
, NULL
)) {
5944 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
5945 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
5946 smb_fname_src
->base_name
);
5947 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
5948 smb_fname_dst
->base_name
);
5951 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
5952 smb_fname_src
->base_name
);
5953 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
5954 smb_fname_dst
->base_name
);
5957 /* this is a strange one. w2k3 gives an additional event for
5958 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5959 files, but not directories */
5961 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5962 FILE_NOTIFY_CHANGE_ATTRIBUTES
5963 |FILE_NOTIFY_CHANGE_CREATION
,
5964 smb_fname_dst
->base_name
);
5967 TALLOC_FREE(parent_dir_src
);
5968 TALLOC_FREE(parent_dir_dst
);
5971 /****************************************************************************
5972 Returns an error if the parent directory for a filename is open in an
5974 ****************************************************************************/
5976 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
5977 const struct smb_filename
*smb_fname_dst_in
)
5979 char *parent_dir
= NULL
;
5980 struct smb_filename smb_fname_parent
;
5982 files_struct
*fsp
= NULL
;
5985 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
5986 &parent_dir
, NULL
)) {
5987 return NT_STATUS_NO_MEMORY
;
5989 ZERO_STRUCT(smb_fname_parent
);
5990 smb_fname_parent
.base_name
= parent_dir
;
5992 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
5994 return map_nt_error_from_unix(errno
);
5998 * We're only checking on this smbd here, mostly good
5999 * enough.. and will pass tests.
6002 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6003 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6004 fsp
= file_find_di_next(fsp
)) {
6005 if (fsp
->access_mask
& DELETE_ACCESS
) {
6006 return NT_STATUS_SHARING_VIOLATION
;
6009 return NT_STATUS_OK
;
6012 /****************************************************************************
6013 Rename an open file - given an fsp.
6014 ****************************************************************************/
6016 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6018 const struct smb_filename
*smb_fname_dst_in
,
6020 bool replace_if_exists
)
6022 TALLOC_CTX
*ctx
= talloc_tos();
6023 struct smb_filename
*smb_fname_dst
= NULL
;
6024 NTSTATUS status
= NT_STATUS_OK
;
6025 struct share_mode_lock
*lck
= NULL
;
6026 bool dst_exists
, old_is_stream
, new_is_stream
;
6028 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6029 if (!NT_STATUS_IS_OK(status
)) {
6033 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6034 if (!NT_STATUS_IS_OK(status
)) {
6038 /* Make a copy of the dst smb_fname structs */
6040 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
6041 if (!NT_STATUS_IS_OK(status
)) {
6046 * Check for special case with case preserving and not
6047 * case sensitive. If the old last component differs from the original
6048 * last component only by case, then we should allow
6049 * the rename (user is trying to change the case of the
6052 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6053 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6054 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6056 char *fname_dst_lcomp_base_mod
= NULL
;
6057 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6060 * Get the last component of the destination name.
6062 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6064 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6066 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6068 if (!fname_dst_lcomp_base_mod
) {
6069 status
= NT_STATUS_NO_MEMORY
;
6074 * Create an smb_filename struct using the original last
6075 * component of the destination.
6077 status
= create_synthetic_smb_fname_split(ctx
,
6078 smb_fname_dst
->original_lcomp
, NULL
,
6079 &smb_fname_orig_lcomp
);
6080 if (!NT_STATUS_IS_OK(status
)) {
6081 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6085 /* If the base names only differ by case, use original. */
6086 if(!strcsequal(fname_dst_lcomp_base_mod
,
6087 smb_fname_orig_lcomp
->base_name
)) {
6090 * Replace the modified last component with the
6094 *last_slash
= '\0'; /* Truncate at the '/' */
6095 tmp
= talloc_asprintf(smb_fname_dst
,
6097 smb_fname_dst
->base_name
,
6098 smb_fname_orig_lcomp
->base_name
);
6100 tmp
= talloc_asprintf(smb_fname_dst
,
6102 smb_fname_orig_lcomp
->base_name
);
6105 status
= NT_STATUS_NO_MEMORY
;
6106 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6107 TALLOC_FREE(smb_fname_orig_lcomp
);
6110 TALLOC_FREE(smb_fname_dst
->base_name
);
6111 smb_fname_dst
->base_name
= tmp
;
6114 /* If the stream_names only differ by case, use original. */
6115 if(!strcsequal(smb_fname_dst
->stream_name
,
6116 smb_fname_orig_lcomp
->stream_name
)) {
6118 /* Use the original stream. */
6119 tmp
= talloc_strdup(smb_fname_dst
,
6120 smb_fname_orig_lcomp
->stream_name
);
6122 status
= NT_STATUS_NO_MEMORY
;
6123 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6124 TALLOC_FREE(smb_fname_orig_lcomp
);
6127 TALLOC_FREE(smb_fname_dst
->stream_name
);
6128 smb_fname_dst
->stream_name
= tmp
;
6130 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6131 TALLOC_FREE(smb_fname_orig_lcomp
);
6135 * If the src and dest names are identical - including case,
6136 * don't do the rename, just return success.
6139 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6140 strcsequal(fsp
->fsp_name
->stream_name
,
6141 smb_fname_dst
->stream_name
)) {
6142 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6143 "- returning success\n",
6144 smb_fname_str_dbg(smb_fname_dst
)));
6145 status
= NT_STATUS_OK
;
6149 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6150 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6152 /* Return the correct error code if both names aren't streams. */
6153 if (!old_is_stream
&& new_is_stream
) {
6154 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6158 if (old_is_stream
&& !new_is_stream
) {
6159 status
= NT_STATUS_INVALID_PARAMETER
;
6163 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6165 if(!replace_if_exists
&& dst_exists
) {
6166 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6167 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6168 smb_fname_str_dbg(smb_fname_dst
)));
6169 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6174 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6175 &smb_fname_dst
->st
);
6176 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6178 /* The file can be open when renaming a stream */
6179 if (dst_fsp
&& !new_is_stream
) {
6180 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6181 status
= NT_STATUS_ACCESS_DENIED
;
6186 /* Ensure we have a valid stat struct for the source. */
6187 status
= vfs_stat_fsp(fsp
);
6188 if (!NT_STATUS_IS_OK(status
)) {
6192 status
= can_rename(conn
, fsp
, attrs
);
6194 if (!NT_STATUS_IS_OK(status
)) {
6195 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6196 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6197 smb_fname_str_dbg(smb_fname_dst
)));
6198 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6199 status
= NT_STATUS_ACCESS_DENIED
;
6203 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6204 status
= NT_STATUS_ACCESS_DENIED
;
6207 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6211 * We have the file open ourselves, so not being able to get the
6212 * corresponding share mode lock is a fatal error.
6215 SMB_ASSERT(lck
!= NULL
);
6217 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6218 uint32 create_options
= fsp
->fh
->private_options
;
6220 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6221 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6222 smb_fname_str_dbg(smb_fname_dst
)));
6224 if (!lp_posix_pathnames() &&
6225 (lp_map_archive(SNUM(conn
)) ||
6226 lp_store_dos_attributes(SNUM(conn
)))) {
6227 /* We must set the archive bit on the newly
6229 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6230 uint32_t old_dosmode
= dos_mode(conn
,
6232 file_set_dosmode(conn
,
6234 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6240 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6243 rename_open_files(conn
, lck
, fsp
->name_hash
, smb_fname_dst
);
6246 * A rename acts as a new file create w.r.t. allowing an initial delete
6247 * on close, probably because in Windows there is a new handle to the
6248 * new file. If initial delete on close was requested but not
6249 * originally set, we need to set it here. This is probably not 100% correct,
6250 * but will work for the CIFSFS client which in non-posix mode
6251 * depends on these semantics. JRA.
6254 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6255 status
= can_set_delete_on_close(fsp
, 0);
6257 if (NT_STATUS_IS_OK(status
)) {
6258 /* Note that here we set the *inital* delete on close flag,
6259 * not the regular one. The magic gets handled in close. */
6260 fsp
->initial_delete_on_close
= True
;
6264 status
= NT_STATUS_OK
;
6270 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6271 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6273 status
= map_nt_error_from_unix(errno
);
6276 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6277 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6278 smb_fname_str_dbg(smb_fname_dst
)));
6281 TALLOC_FREE(smb_fname_dst
);
6286 /****************************************************************************
6287 The guts of the rename command, split out so it may be called by the NT SMB
6289 ****************************************************************************/
6291 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6292 connection_struct
*conn
,
6293 struct smb_request
*req
,
6294 struct smb_filename
*smb_fname_src
,
6295 struct smb_filename
*smb_fname_dst
,
6297 bool replace_if_exists
,
6300 uint32_t access_mask
)
6302 char *fname_src_dir
= NULL
;
6303 char *fname_src_mask
= NULL
;
6305 NTSTATUS status
= NT_STATUS_OK
;
6306 struct smb_Dir
*dir_hnd
= NULL
;
6307 const char *dname
= NULL
;
6308 char *talloced
= NULL
;
6310 int create_options
= 0;
6311 bool posix_pathnames
= lp_posix_pathnames();
6314 * Split the old name into directory and last component
6315 * strings. Note that unix_convert may have stripped off a
6316 * leading ./ from both name and newname if the rename is
6317 * at the root of the share. We need to make sure either both
6318 * name and newname contain a / character or neither of them do
6319 * as this is checked in resolve_wildcards().
6322 /* Split up the directory from the filename/mask. */
6323 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6324 &fname_src_dir
, &fname_src_mask
);
6325 if (!NT_STATUS_IS_OK(status
)) {
6326 status
= NT_STATUS_NO_MEMORY
;
6331 * We should only check the mangled cache
6332 * here if unix_convert failed. This means
6333 * that the path in 'mask' doesn't exist
6334 * on the file system and so we need to look
6335 * for a possible mangle. This patch from
6336 * Tine Smukavec <valentin.smukavec@hermes.si>.
6339 if (!VALID_STAT(smb_fname_src
->st
) &&
6340 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6341 char *new_mask
= NULL
;
6342 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6345 TALLOC_FREE(fname_src_mask
);
6346 fname_src_mask
= new_mask
;
6350 if (!src_has_wild
) {
6354 * Only one file needs to be renamed. Append the mask back
6355 * onto the directory.
6357 TALLOC_FREE(smb_fname_src
->base_name
);
6358 if (ISDOT(fname_src_dir
)) {
6359 /* Ensure we use canonical names on open. */
6360 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6364 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6369 if (!smb_fname_src
->base_name
) {
6370 status
= NT_STATUS_NO_MEMORY
;
6374 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6375 "case_preserve = %d, short case preserve = %d, "
6376 "directory = %s, newname = %s, "
6377 "last_component_dest = %s\n",
6378 conn
->case_sensitive
, conn
->case_preserve
,
6379 conn
->short_case_preserve
,
6380 smb_fname_str_dbg(smb_fname_src
),
6381 smb_fname_str_dbg(smb_fname_dst
),
6382 smb_fname_dst
->original_lcomp
));
6384 /* The dest name still may have wildcards. */
6385 if (dest_has_wild
) {
6386 char *fname_dst_mod
= NULL
;
6387 if (!resolve_wildcards(smb_fname_dst
,
6388 smb_fname_src
->base_name
,
6389 smb_fname_dst
->base_name
,
6391 DEBUG(6, ("rename_internals: resolve_wildcards "
6393 smb_fname_src
->base_name
,
6394 smb_fname_dst
->base_name
));
6395 status
= NT_STATUS_NO_MEMORY
;
6398 TALLOC_FREE(smb_fname_dst
->base_name
);
6399 smb_fname_dst
->base_name
= fname_dst_mod
;
6402 ZERO_STRUCT(smb_fname_src
->st
);
6403 if (posix_pathnames
) {
6404 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6406 SMB_VFS_STAT(conn
, smb_fname_src
);
6409 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6410 create_options
|= FILE_DIRECTORY_FILE
;
6413 status
= SMB_VFS_CREATE_FILE(
6416 0, /* root_dir_fid */
6417 smb_fname_src
, /* fname */
6418 access_mask
, /* access_mask */
6419 (FILE_SHARE_READ
| /* share_access */
6421 FILE_OPEN
, /* create_disposition*/
6422 create_options
, /* create_options */
6423 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6424 0, /* oplock_request */
6425 0, /* allocation_size */
6426 0, /* private_flags */
6432 if (!NT_STATUS_IS_OK(status
)) {
6433 DEBUG(3, ("Could not open rename source %s: %s\n",
6434 smb_fname_str_dbg(smb_fname_src
),
6435 nt_errstr(status
)));
6439 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6440 attrs
, replace_if_exists
);
6442 close_file(req
, fsp
, NORMAL_CLOSE
);
6444 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6445 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6446 smb_fname_str_dbg(smb_fname_dst
)));
6452 * Wildcards - process each file that matches.
6454 if (strequal(fname_src_mask
, "????????.???")) {
6455 TALLOC_FREE(fname_src_mask
);
6456 fname_src_mask
= talloc_strdup(ctx
, "*");
6457 if (!fname_src_mask
) {
6458 status
= NT_STATUS_NO_MEMORY
;
6463 status
= check_name(conn
, fname_src_dir
);
6464 if (!NT_STATUS_IS_OK(status
)) {
6468 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6470 if (dir_hnd
== NULL
) {
6471 status
= map_nt_error_from_unix(errno
);
6475 status
= NT_STATUS_NO_SUCH_FILE
;
6477 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6478 * - gentest fix. JRA
6481 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6483 files_struct
*fsp
= NULL
;
6484 char *destname
= NULL
;
6485 bool sysdir_entry
= False
;
6487 /* Quick check for "." and ".." */
6488 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6489 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6490 sysdir_entry
= True
;
6492 TALLOC_FREE(talloced
);
6497 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6498 &smb_fname_src
->st
, false)) {
6499 TALLOC_FREE(talloced
);
6503 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6504 TALLOC_FREE(talloced
);
6509 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6513 TALLOC_FREE(smb_fname_src
->base_name
);
6514 if (ISDOT(fname_src_dir
)) {
6515 /* Ensure we use canonical names on open. */
6516 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6520 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6525 if (!smb_fname_src
->base_name
) {
6526 status
= NT_STATUS_NO_MEMORY
;
6530 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6531 smb_fname_dst
->base_name
,
6533 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6534 smb_fname_src
->base_name
, destname
));
6535 TALLOC_FREE(talloced
);
6539 status
= NT_STATUS_NO_MEMORY
;
6543 TALLOC_FREE(smb_fname_dst
->base_name
);
6544 smb_fname_dst
->base_name
= destname
;
6546 ZERO_STRUCT(smb_fname_src
->st
);
6547 if (posix_pathnames
) {
6548 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6550 SMB_VFS_STAT(conn
, smb_fname_src
);
6555 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6556 create_options
|= FILE_DIRECTORY_FILE
;
6559 status
= SMB_VFS_CREATE_FILE(
6562 0, /* root_dir_fid */
6563 smb_fname_src
, /* fname */
6564 access_mask
, /* access_mask */
6565 (FILE_SHARE_READ
| /* share_access */
6567 FILE_OPEN
, /* create_disposition*/
6568 create_options
, /* create_options */
6569 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6570 0, /* oplock_request */
6571 0, /* allocation_size */
6572 0, /* private_flags */
6578 if (!NT_STATUS_IS_OK(status
)) {
6579 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6580 "returned %s rename %s -> %s\n",
6582 smb_fname_str_dbg(smb_fname_src
),
6583 smb_fname_str_dbg(smb_fname_dst
)));
6587 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6589 if (!smb_fname_dst
->original_lcomp
) {
6590 status
= NT_STATUS_NO_MEMORY
;
6594 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6595 attrs
, replace_if_exists
);
6597 close_file(req
, fsp
, NORMAL_CLOSE
);
6599 if (!NT_STATUS_IS_OK(status
)) {
6600 DEBUG(3, ("rename_internals_fsp returned %s for "
6601 "rename %s -> %s\n", nt_errstr(status
),
6602 smb_fname_str_dbg(smb_fname_src
),
6603 smb_fname_str_dbg(smb_fname_dst
)));
6609 DEBUG(3,("rename_internals: doing rename on %s -> "
6610 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6611 smb_fname_str_dbg(smb_fname_src
)));
6612 TALLOC_FREE(talloced
);
6614 TALLOC_FREE(dir_hnd
);
6616 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6617 status
= map_nt_error_from_unix(errno
);
6621 TALLOC_FREE(talloced
);
6622 TALLOC_FREE(fname_src_dir
);
6623 TALLOC_FREE(fname_src_mask
);
6627 /****************************************************************************
6629 ****************************************************************************/
6631 void reply_mv(struct smb_request
*req
)
6633 connection_struct
*conn
= req
->conn
;
6635 char *newname
= NULL
;
6639 bool src_has_wcard
= False
;
6640 bool dest_has_wcard
= False
;
6641 TALLOC_CTX
*ctx
= talloc_tos();
6642 struct smb_filename
*smb_fname_src
= NULL
;
6643 struct smb_filename
*smb_fname_dst
= NULL
;
6644 bool stream_rename
= false;
6646 START_PROFILE(SMBmv
);
6649 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6653 attrs
= SVAL(req
->vwv
+0, 0);
6655 p
= (const char *)req
->buf
+ 1;
6656 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6657 &status
, &src_has_wcard
);
6658 if (!NT_STATUS_IS_OK(status
)) {
6659 reply_nterror(req
, status
);
6663 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6664 &status
, &dest_has_wcard
);
6665 if (!NT_STATUS_IS_OK(status
)) {
6666 reply_nterror(req
, status
);
6670 if (!lp_posix_pathnames()) {
6671 /* The newname must begin with a ':' if the
6672 name contains a ':'. */
6673 if (strchr_m(name
, ':')) {
6674 if (newname
[0] != ':') {
6675 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6678 stream_rename
= true;
6682 status
= filename_convert(ctx
,
6684 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6686 UCF_COND_ALLOW_WCARD_LCOMP
,
6690 if (!NT_STATUS_IS_OK(status
)) {
6691 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6692 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6693 ERRSRV
, ERRbadpath
);
6696 reply_nterror(req
, status
);
6700 status
= filename_convert(ctx
,
6702 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6704 UCF_COND_ALLOW_WCARD_LCOMP
| UCF_SAVE_LCOMP
,
6708 if (!NT_STATUS_IS_OK(status
)) {
6709 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6710 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6711 ERRSRV
, ERRbadpath
);
6714 reply_nterror(req
, status
);
6718 if (stream_rename
) {
6719 /* smb_fname_dst->base_name must be the same as
6720 smb_fname_src->base_name. */
6721 TALLOC_FREE(smb_fname_dst
->base_name
);
6722 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6723 smb_fname_src
->base_name
);
6724 if (!smb_fname_dst
->base_name
) {
6725 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6730 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6731 smb_fname_str_dbg(smb_fname_dst
)));
6733 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
6734 attrs
, False
, src_has_wcard
, dest_has_wcard
,
6736 if (!NT_STATUS_IS_OK(status
)) {
6737 if (open_was_deferred(req
->sconn
, req
->mid
)) {
6738 /* We have re-scheduled this call. */
6741 reply_nterror(req
, status
);
6745 reply_outbuf(req
, 0, 0);
6747 TALLOC_FREE(smb_fname_src
);
6748 TALLOC_FREE(smb_fname_dst
);
6753 /*******************************************************************
6754 Copy a file as part of a reply_copy.
6755 ******************************************************************/
6758 * TODO: check error codes on all callers
6761 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6762 connection_struct
*conn
,
6763 struct smb_filename
*smb_fname_src
,
6764 struct smb_filename
*smb_fname_dst
,
6767 bool target_is_directory
)
6769 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
6771 files_struct
*fsp1
,*fsp2
;
6773 uint32 new_create_disposition
;
6777 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
6778 if (!NT_STATUS_IS_OK(status
)) {
6783 * If the target is a directory, extract the last component from the
6784 * src filename and append it to the dst filename
6786 if (target_is_directory
) {
6789 /* dest/target can't be a stream if it's a directory. */
6790 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
6792 p
= strrchr_m(smb_fname_src
->base_name
,'/');
6796 p
= smb_fname_src
->base_name
;
6798 smb_fname_dst_tmp
->base_name
=
6799 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
6801 if (!smb_fname_dst_tmp
->base_name
) {
6802 status
= NT_STATUS_NO_MEMORY
;
6807 status
= vfs_file_exist(conn
, smb_fname_src
);
6808 if (!NT_STATUS_IS_OK(status
)) {
6812 if (!target_is_directory
&& count
) {
6813 new_create_disposition
= FILE_OPEN
;
6815 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
6818 &new_create_disposition
,
6821 status
= NT_STATUS_INVALID_PARAMETER
;
6826 /* Open the src file for reading. */
6827 status
= SMB_VFS_CREATE_FILE(
6830 0, /* root_dir_fid */
6831 smb_fname_src
, /* fname */
6832 FILE_GENERIC_READ
, /* access_mask */
6833 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6834 FILE_OPEN
, /* create_disposition*/
6835 0, /* create_options */
6836 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6837 INTERNAL_OPEN_ONLY
, /* oplock_request */
6838 0, /* allocation_size */
6839 0, /* private_flags */
6845 if (!NT_STATUS_IS_OK(status
)) {
6849 dosattrs
= dos_mode(conn
, smb_fname_src
);
6851 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
6852 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
6855 /* Open the dst file for writing. */
6856 status
= SMB_VFS_CREATE_FILE(
6859 0, /* root_dir_fid */
6860 smb_fname_dst
, /* fname */
6861 FILE_GENERIC_WRITE
, /* access_mask */
6862 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6863 new_create_disposition
, /* create_disposition*/
6864 0, /* create_options */
6865 dosattrs
, /* file_attributes */
6866 INTERNAL_OPEN_ONLY
, /* oplock_request */
6867 0, /* allocation_size */
6868 0, /* private_flags */
6874 if (!NT_STATUS_IS_OK(status
)) {
6875 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6879 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
6880 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
6882 DEBUG(0, ("error - vfs lseek returned error %s\n",
6884 status
= map_nt_error_from_unix(errno
);
6885 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6886 close_file(NULL
, fsp2
, ERROR_CLOSE
);
6891 /* Do the actual copy. */
6892 if (smb_fname_src
->st
.st_ex_size
) {
6893 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
6898 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
6900 /* Ensure the modtime is set correctly on the destination file. */
6901 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
6904 * As we are opening fsp1 read-only we only expect
6905 * an error on close on fsp2 if we are out of space.
6906 * Thus we don't look at the error return from the
6909 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
6911 if (!NT_STATUS_IS_OK(status
)) {
6915 if (ret
!= (SMB_OFF_T
)smb_fname_src
->st
.st_ex_size
) {
6916 status
= NT_STATUS_DISK_FULL
;
6920 status
= NT_STATUS_OK
;
6923 TALLOC_FREE(smb_fname_dst_tmp
);
6927 /****************************************************************************
6928 Reply to a file copy.
6929 ****************************************************************************/
6931 void reply_copy(struct smb_request
*req
)
6933 connection_struct
*conn
= req
->conn
;
6934 struct smb_filename
*smb_fname_src
= NULL
;
6935 struct smb_filename
*smb_fname_dst
= NULL
;
6936 char *fname_src
= NULL
;
6937 char *fname_dst
= NULL
;
6938 char *fname_src_mask
= NULL
;
6939 char *fname_src_dir
= NULL
;
6942 int error
= ERRnoaccess
;
6946 bool target_is_directory
=False
;
6947 bool source_has_wild
= False
;
6948 bool dest_has_wild
= False
;
6950 TALLOC_CTX
*ctx
= talloc_tos();
6952 START_PROFILE(SMBcopy
);
6955 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6959 tid2
= SVAL(req
->vwv
+0, 0);
6960 ofun
= SVAL(req
->vwv
+1, 0);
6961 flags
= SVAL(req
->vwv
+2, 0);
6963 p
= (const char *)req
->buf
;
6964 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
6965 &status
, &source_has_wild
);
6966 if (!NT_STATUS_IS_OK(status
)) {
6967 reply_nterror(req
, status
);
6970 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
6971 &status
, &dest_has_wild
);
6972 if (!NT_STATUS_IS_OK(status
)) {
6973 reply_nterror(req
, status
);
6977 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
6979 if (tid2
!= conn
->cnum
) {
6980 /* can't currently handle inter share copies XXXX */
6981 DEBUG(3,("Rejecting inter-share copy\n"));
6982 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
6986 status
= filename_convert(ctx
, conn
,
6987 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6989 UCF_COND_ALLOW_WCARD_LCOMP
,
6992 if (!NT_STATUS_IS_OK(status
)) {
6993 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6994 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6995 ERRSRV
, ERRbadpath
);
6998 reply_nterror(req
, status
);
7002 status
= filename_convert(ctx
, conn
,
7003 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7005 UCF_COND_ALLOW_WCARD_LCOMP
,
7008 if (!NT_STATUS_IS_OK(status
)) {
7009 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7010 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7011 ERRSRV
, ERRbadpath
);
7014 reply_nterror(req
, status
);
7018 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7020 if ((flags
&1) && target_is_directory
) {
7021 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7025 if ((flags
&2) && !target_is_directory
) {
7026 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7030 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7031 /* wants a tree copy! XXXX */
7032 DEBUG(3,("Rejecting tree copy\n"));
7033 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7037 /* Split up the directory from the filename/mask. */
7038 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7039 &fname_src_dir
, &fname_src_mask
);
7040 if (!NT_STATUS_IS_OK(status
)) {
7041 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7046 * We should only check the mangled cache
7047 * here if unix_convert failed. This means
7048 * that the path in 'mask' doesn't exist
7049 * on the file system and so we need to look
7050 * for a possible mangle. This patch from
7051 * Tine Smukavec <valentin.smukavec@hermes.si>.
7053 if (!VALID_STAT(smb_fname_src
->st
) &&
7054 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7055 char *new_mask
= NULL
;
7056 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7057 &new_mask
, conn
->params
);
7059 /* Use demangled name if one was successfully found. */
7061 TALLOC_FREE(fname_src_mask
);
7062 fname_src_mask
= new_mask
;
7066 if (!source_has_wild
) {
7069 * Only one file needs to be copied. Append the mask back onto
7072 TALLOC_FREE(smb_fname_src
->base_name
);
7073 if (ISDOT(fname_src_dir
)) {
7074 /* Ensure we use canonical names on open. */
7075 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7079 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7084 if (!smb_fname_src
->base_name
) {
7085 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7089 if (dest_has_wild
) {
7090 char *fname_dst_mod
= NULL
;
7091 if (!resolve_wildcards(smb_fname_dst
,
7092 smb_fname_src
->base_name
,
7093 smb_fname_dst
->base_name
,
7095 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7098 TALLOC_FREE(smb_fname_dst
->base_name
);
7099 smb_fname_dst
->base_name
= fname_dst_mod
;
7102 status
= check_name(conn
, smb_fname_src
->base_name
);
7103 if (!NT_STATUS_IS_OK(status
)) {
7104 reply_nterror(req
, status
);
7108 status
= check_name(conn
, smb_fname_dst
->base_name
);
7109 if (!NT_STATUS_IS_OK(status
)) {
7110 reply_nterror(req
, status
);
7114 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7115 ofun
, count
, target_is_directory
);
7117 if(!NT_STATUS_IS_OK(status
)) {
7118 reply_nterror(req
, status
);
7124 struct smb_Dir
*dir_hnd
= NULL
;
7125 const char *dname
= NULL
;
7126 char *talloced
= NULL
;
7130 * There is a wildcard that requires us to actually read the
7131 * src dir and copy each file matching the mask to the dst.
7132 * Right now streams won't be copied, but this could
7133 * presumably be added with a nested loop for reach dir entry.
7135 SMB_ASSERT(!smb_fname_src
->stream_name
);
7136 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7138 smb_fname_src
->stream_name
= NULL
;
7139 smb_fname_dst
->stream_name
= NULL
;
7141 if (strequal(fname_src_mask
,"????????.???")) {
7142 TALLOC_FREE(fname_src_mask
);
7143 fname_src_mask
= talloc_strdup(ctx
, "*");
7144 if (!fname_src_mask
) {
7145 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7150 status
= check_name(conn
, fname_src_dir
);
7151 if (!NT_STATUS_IS_OK(status
)) {
7152 reply_nterror(req
, status
);
7156 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7157 if (dir_hnd
== NULL
) {
7158 status
= map_nt_error_from_unix(errno
);
7159 reply_nterror(req
, status
);
7165 /* Iterate over the src dir copying each entry to the dst. */
7166 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7167 &smb_fname_src
->st
, &talloced
))) {
7168 char *destname
= NULL
;
7170 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7171 TALLOC_FREE(talloced
);
7175 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7176 &smb_fname_src
->st
, false)) {
7177 TALLOC_FREE(talloced
);
7181 if(!mask_match(dname
, fname_src_mask
,
7182 conn
->case_sensitive
)) {
7183 TALLOC_FREE(talloced
);
7187 error
= ERRnoaccess
;
7189 /* Get the src smb_fname struct setup. */
7190 TALLOC_FREE(smb_fname_src
->base_name
);
7191 if (ISDOT(fname_src_dir
)) {
7192 /* Ensure we use canonical names on open. */
7193 smb_fname_src
->base_name
=
7194 talloc_asprintf(smb_fname_src
, "%s",
7197 smb_fname_src
->base_name
=
7198 talloc_asprintf(smb_fname_src
, "%s/%s",
7199 fname_src_dir
, dname
);
7202 if (!smb_fname_src
->base_name
) {
7203 TALLOC_FREE(dir_hnd
);
7204 TALLOC_FREE(talloced
);
7205 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7209 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7210 smb_fname_dst
->base_name
,
7212 TALLOC_FREE(talloced
);
7216 TALLOC_FREE(dir_hnd
);
7217 TALLOC_FREE(talloced
);
7218 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7222 TALLOC_FREE(smb_fname_dst
->base_name
);
7223 smb_fname_dst
->base_name
= destname
;
7225 status
= check_name(conn
, smb_fname_src
->base_name
);
7226 if (!NT_STATUS_IS_OK(status
)) {
7227 TALLOC_FREE(dir_hnd
);
7228 TALLOC_FREE(talloced
);
7229 reply_nterror(req
, status
);
7233 status
= check_name(conn
, smb_fname_dst
->base_name
);
7234 if (!NT_STATUS_IS_OK(status
)) {
7235 TALLOC_FREE(dir_hnd
);
7236 TALLOC_FREE(talloced
);
7237 reply_nterror(req
, status
);
7241 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7242 smb_fname_src
->base_name
,
7243 smb_fname_dst
->base_name
));
7245 status
= copy_file(ctx
, conn
, smb_fname_src
,
7246 smb_fname_dst
, ofun
, count
,
7247 target_is_directory
);
7248 if (NT_STATUS_IS_OK(status
)) {
7252 TALLOC_FREE(talloced
);
7254 TALLOC_FREE(dir_hnd
);
7258 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7262 reply_outbuf(req
, 1, 0);
7263 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7265 TALLOC_FREE(smb_fname_src
);
7266 TALLOC_FREE(smb_fname_dst
);
7267 TALLOC_FREE(fname_src
);
7268 TALLOC_FREE(fname_dst
);
7269 TALLOC_FREE(fname_src_mask
);
7270 TALLOC_FREE(fname_src_dir
);
7272 END_PROFILE(SMBcopy
);
7277 #define DBGC_CLASS DBGC_LOCKING
7279 /****************************************************************************
7280 Get a lock pid, dealing with large count requests.
7281 ****************************************************************************/
7283 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7284 bool large_file_format
)
7286 if(!large_file_format
)
7287 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7289 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7292 /****************************************************************************
7293 Get a lock count, dealing with large count requests.
7294 ****************************************************************************/
7296 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7297 bool large_file_format
)
7301 if(!large_file_format
) {
7302 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7305 #if defined(HAVE_LONGLONG)
7306 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7307 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7308 #else /* HAVE_LONGLONG */
7311 * NT4.x seems to be broken in that it sends large file (64 bit)
7312 * lockingX calls even if the CAP_LARGE_FILES was *not*
7313 * negotiated. For boxes without large unsigned ints truncate the
7314 * lock count by dropping the top 32 bits.
7317 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7318 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7319 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7320 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7321 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7324 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7325 #endif /* HAVE_LONGLONG */
7331 #if !defined(HAVE_LONGLONG)
7332 /****************************************************************************
7333 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7334 ****************************************************************************/
7336 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7340 uint32 highcopy
= high
;
7343 * Try and find out how many significant bits there are in high.
7346 for(i
= 0; highcopy
; i
++)
7350 * We use 31 bits not 32 here as POSIX
7351 * lock offsets may not be negative.
7354 mask
= (~0) << (31 - i
);
7357 return 0; /* Fail. */
7363 #endif /* !defined(HAVE_LONGLONG) */
7365 /****************************************************************************
7366 Get a lock offset, dealing with large offset requests.
7367 ****************************************************************************/
7369 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7370 bool large_file_format
, bool *err
)
7372 uint64_t offset
= 0;
7376 if(!large_file_format
) {
7377 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7380 #if defined(HAVE_LONGLONG)
7381 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7382 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7383 #else /* HAVE_LONGLONG */
7386 * NT4.x seems to be broken in that it sends large file (64 bit)
7387 * lockingX calls even if the CAP_LARGE_FILES was *not*
7388 * negotiated. For boxes without large unsigned ints mangle the
7389 * lock offset by mapping the top 32 bits onto the lower 32.
7392 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7393 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7394 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7397 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7399 return (uint64_t)-1;
7402 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7403 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7404 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7405 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7408 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7409 #endif /* HAVE_LONGLONG */
7415 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7419 uint16_t num_ulocks
,
7420 struct smbd_lock_element
*ulocks
,
7422 struct smbd_lock_element
*locks
,
7425 connection_struct
*conn
= req
->conn
;
7427 NTSTATUS status
= NT_STATUS_OK
;
7431 /* Data now points at the beginning of the list
7432 of smb_unlkrng structs */
7433 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7434 struct smbd_lock_element
*e
= &ulocks
[i
];
7436 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7437 "pid %u, file %s\n",
7440 (unsigned int)e
->smblctx
,
7443 if (e
->brltype
!= UNLOCK_LOCK
) {
7444 /* this can only happen with SMB2 */
7445 return NT_STATUS_INVALID_PARAMETER
;
7448 status
= do_unlock(req
->sconn
->msg_ctx
,
7455 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7456 nt_errstr(status
)));
7458 if (!NT_STATUS_IS_OK(status
)) {
7463 /* Setup the timeout in seconds. */
7465 if (!lp_blocking_locks(SNUM(conn
))) {
7469 /* Data now points at the beginning of the list
7470 of smb_lkrng structs */
7472 for(i
= 0; i
< (int)num_locks
; i
++) {
7473 struct smbd_lock_element
*e
= &locks
[i
];
7475 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7476 "%llu, file %s timeout = %d\n",
7479 (unsigned long long)e
->smblctx
,
7483 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7484 struct blocking_lock_record
*blr
= NULL
;
7486 if (num_locks
> 1) {
7488 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7489 * if the lock vector contains one entry. When given mutliple cancel
7490 * requests in a single PDU we expect the server to return an
7491 * error. Windows servers seem to accept the request but only
7492 * cancel the first lock.
7493 * JRA - Do what Windows does (tm) :-).
7497 /* MS-CIFS (2.2.4.32.1) behavior. */
7498 return NT_STATUS_DOS(ERRDOS
,
7499 ERRcancelviolation
);
7501 /* Windows behavior. */
7503 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7504 "cancel request\n"));
7510 if (lp_blocking_locks(SNUM(conn
))) {
7512 /* Schedule a message to ourselves to
7513 remove the blocking lock record and
7514 return the right error. */
7516 blr
= blocking_lock_cancel_smb1(fsp
,
7522 NT_STATUS_FILE_LOCK_CONFLICT
);
7524 return NT_STATUS_DOS(
7526 ERRcancelviolation
);
7529 /* Remove a matching pending lock. */
7530 status
= do_lock_cancel(fsp
,
7537 bool blocking_lock
= timeout
? true : false;
7538 bool defer_lock
= false;
7539 struct byte_range_lock
*br_lck
;
7540 uint64_t block_smblctx
;
7542 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7554 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7555 /* Windows internal resolution for blocking locks seems
7556 to be about 200ms... Don't wait for less than that. JRA. */
7557 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7558 timeout
= lp_lock_spin_time();
7563 /* If a lock sent with timeout of zero would fail, and
7564 * this lock has been requested multiple times,
7565 * according to brl_lock_failed() we convert this
7566 * request to a blocking lock with a timeout of between
7567 * 150 - 300 milliseconds.
7569 * If lp_lock_spin_time() has been set to 0, we skip
7570 * this blocking retry and fail immediately.
7572 * Replacement for do_lock_spin(). JRA. */
7574 if (!req
->sconn
->using_smb2
&&
7575 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7576 lp_lock_spin_time() && !blocking_lock
&&
7577 NT_STATUS_EQUAL((status
),
7578 NT_STATUS_FILE_LOCK_CONFLICT
))
7581 timeout
= lp_lock_spin_time();
7584 if (br_lck
&& defer_lock
) {
7586 * A blocking lock was requested. Package up
7587 * this smb into a queued request and push it
7588 * onto the blocking lock queue.
7590 if(push_blocking_lock_request(br_lck
,
7601 TALLOC_FREE(br_lck
);
7603 return NT_STATUS_OK
;
7607 TALLOC_FREE(br_lck
);
7610 if (!NT_STATUS_IS_OK(status
)) {
7615 /* If any of the above locks failed, then we must unlock
7616 all of the previous locks (X/Open spec). */
7618 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7620 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7621 i
= -1; /* we want to skip the for loop */
7625 * Ensure we don't do a remove on the lock that just failed,
7626 * as under POSIX rules, if we have a lock already there, we
7627 * will delete it (and we shouldn't) .....
7629 for(i
--; i
>= 0; i
--) {
7630 struct smbd_lock_element
*e
= &locks
[i
];
7632 do_unlock(req
->sconn
->msg_ctx
,
7642 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7643 fsp
->fnum
, (unsigned int)type
, num_locks
, num_ulocks
));
7645 return NT_STATUS_OK
;
7648 /****************************************************************************
7649 Reply to a lockingX request.
7650 ****************************************************************************/
7652 void reply_lockingX(struct smb_request
*req
)
7654 connection_struct
*conn
= req
->conn
;
7656 unsigned char locktype
;
7657 unsigned char oplocklevel
;
7662 const uint8_t *data
;
7663 bool large_file_format
;
7665 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7666 struct smbd_lock_element
*ulocks
;
7667 struct smbd_lock_element
*locks
;
7670 START_PROFILE(SMBlockingX
);
7673 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7674 END_PROFILE(SMBlockingX
);
7678 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7679 locktype
= CVAL(req
->vwv
+3, 0);
7680 oplocklevel
= CVAL(req
->vwv
+3, 1);
7681 num_ulocks
= SVAL(req
->vwv
+6, 0);
7682 num_locks
= SVAL(req
->vwv
+7, 0);
7683 lock_timeout
= IVAL(req
->vwv
+4, 0);
7684 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7686 if (!check_fsp(conn
, req
, fsp
)) {
7687 END_PROFILE(SMBlockingX
);
7693 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7694 /* we don't support these - and CANCEL_LOCK makes w2k
7695 and XP reboot so I don't really want to be
7696 compatible! (tridge) */
7697 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7698 END_PROFILE(SMBlockingX
);
7702 /* Check if this is an oplock break on a file
7703 we have granted an oplock on.
7705 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7706 /* Client can insist on breaking to none. */
7707 bool break_to_none
= (oplocklevel
== 0);
7710 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7711 "for fnum = %d\n", (unsigned int)oplocklevel
,
7715 * Make sure we have granted an exclusive or batch oplock on
7719 if (fsp
->oplock_type
== 0) {
7721 /* The Samba4 nbench simulator doesn't understand
7722 the difference between break to level2 and break
7723 to none from level2 - it sends oplock break
7724 replies in both cases. Don't keep logging an error
7725 message here - just ignore it. JRA. */
7727 DEBUG(5,("reply_lockingX: Error : oplock break from "
7728 "client for fnum = %d (oplock=%d) and no "
7729 "oplock granted on this file (%s).\n",
7730 fsp
->fnum
, fsp
->oplock_type
,
7733 /* if this is a pure oplock break request then don't
7735 if (num_locks
== 0 && num_ulocks
== 0) {
7736 END_PROFILE(SMBlockingX
);
7739 END_PROFILE(SMBlockingX
);
7740 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
7745 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7747 result
= remove_oplock(fsp
);
7749 result
= downgrade_oplock(fsp
);
7753 DEBUG(0, ("reply_lockingX: error in removing "
7754 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7755 /* Hmmm. Is this panic justified? */
7756 smb_panic("internal tdb error");
7759 reply_to_oplock_break_requests(fsp
);
7761 /* if this is a pure oplock break request then don't send a
7763 if (num_locks
== 0 && num_ulocks
== 0) {
7764 /* Sanity check - ensure a pure oplock break is not a
7766 if(CVAL(req
->vwv
+0, 0) != 0xff)
7767 DEBUG(0,("reply_lockingX: Error : pure oplock "
7768 "break is a chained %d request !\n",
7769 (unsigned int)CVAL(req
->vwv
+0, 0)));
7770 END_PROFILE(SMBlockingX
);
7776 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7777 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7778 END_PROFILE(SMBlockingX
);
7782 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
7783 if (ulocks
== NULL
) {
7784 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7785 END_PROFILE(SMBlockingX
);
7789 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
7790 if (locks
== NULL
) {
7791 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7792 END_PROFILE(SMBlockingX
);
7796 /* Data now points at the beginning of the list
7797 of smb_unlkrng structs */
7798 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7799 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7800 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7801 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7802 ulocks
[i
].brltype
= UNLOCK_LOCK
;
7805 * There is no error code marked "stupid client bug".... :-).
7808 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7809 END_PROFILE(SMBlockingX
);
7814 /* Now do any requested locks */
7815 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
7817 /* Data now points at the beginning of the list
7818 of smb_lkrng structs */
7820 for(i
= 0; i
< (int)num_locks
; i
++) {
7821 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7822 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7823 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7825 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
7826 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7827 locks
[i
].brltype
= PENDING_READ_LOCK
;
7829 locks
[i
].brltype
= READ_LOCK
;
7832 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7833 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
7835 locks
[i
].brltype
= WRITE_LOCK
;
7840 * There is no error code marked "stupid client bug".... :-).
7843 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7844 END_PROFILE(SMBlockingX
);
7849 status
= smbd_do_locking(req
, fsp
,
7850 locktype
, lock_timeout
,
7854 if (!NT_STATUS_IS_OK(status
)) {
7855 END_PROFILE(SMBlockingX
);
7856 reply_nterror(req
, status
);
7860 END_PROFILE(SMBlockingX
);
7864 reply_outbuf(req
, 2, 0);
7866 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7867 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7869 END_PROFILE(SMBlockingX
);
7874 #define DBGC_CLASS DBGC_ALL
7876 /****************************************************************************
7877 Reply to a SMBreadbmpx (read block multiplex) request.
7878 Always reply with an error, if someone has a platform really needs this,
7879 please contact vl@samba.org
7880 ****************************************************************************/
7882 void reply_readbmpx(struct smb_request
*req
)
7884 START_PROFILE(SMBreadBmpx
);
7885 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7886 END_PROFILE(SMBreadBmpx
);
7890 /****************************************************************************
7891 Reply to a SMBreadbs (read block multiplex secondary) request.
7892 Always reply with an error, if someone has a platform really needs this,
7893 please contact vl@samba.org
7894 ****************************************************************************/
7896 void reply_readbs(struct smb_request
*req
)
7898 START_PROFILE(SMBreadBs
);
7899 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7900 END_PROFILE(SMBreadBs
);
7904 /****************************************************************************
7905 Reply to a SMBsetattrE.
7906 ****************************************************************************/
7908 void reply_setattrE(struct smb_request
*req
)
7910 connection_struct
*conn
= req
->conn
;
7911 struct smb_file_time ft
;
7915 START_PROFILE(SMBsetattrE
);
7919 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7923 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7925 if(!fsp
|| (fsp
->conn
!= conn
)) {
7926 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7931 * Convert the DOS times into unix times.
7934 ft
.atime
= convert_time_t_to_timespec(
7935 srv_make_unix_date2(req
->vwv
+3));
7936 ft
.mtime
= convert_time_t_to_timespec(
7937 srv_make_unix_date2(req
->vwv
+5));
7938 ft
.create_time
= convert_time_t_to_timespec(
7939 srv_make_unix_date2(req
->vwv
+1));
7941 reply_outbuf(req
, 0, 0);
7944 * Patch from Ray Frush <frush@engr.colostate.edu>
7945 * Sometimes times are sent as zero - ignore them.
7948 /* Ensure we have a valid stat struct for the source. */
7949 status
= vfs_stat_fsp(fsp
);
7950 if (!NT_STATUS_IS_OK(status
)) {
7951 reply_nterror(req
, status
);
7955 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
7956 if (!NT_STATUS_IS_OK(status
)) {
7957 reply_nterror(req
, status
);
7961 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7964 (unsigned int)ft
.atime
.tv_sec
,
7965 (unsigned int)ft
.mtime
.tv_sec
,
7966 (unsigned int)ft
.create_time
.tv_sec
7969 END_PROFILE(SMBsetattrE
);
7974 /* Back from the dead for OS/2..... JRA. */
7976 /****************************************************************************
7977 Reply to a SMBwritebmpx (write block multiplex primary) request.
7978 Always reply with an error, if someone has a platform really needs this,
7979 please contact vl@samba.org
7980 ****************************************************************************/
7982 void reply_writebmpx(struct smb_request
*req
)
7984 START_PROFILE(SMBwriteBmpx
);
7985 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7986 END_PROFILE(SMBwriteBmpx
);
7990 /****************************************************************************
7991 Reply to a SMBwritebs (write block multiplex secondary) request.
7992 Always reply with an error, if someone has a platform really needs this,
7993 please contact vl@samba.org
7994 ****************************************************************************/
7996 void reply_writebs(struct smb_request
*req
)
7998 START_PROFILE(SMBwriteBs
);
7999 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8000 END_PROFILE(SMBwriteBs
);
8004 /****************************************************************************
8005 Reply to a SMBgetattrE.
8006 ****************************************************************************/
8008 void reply_getattrE(struct smb_request
*req
)
8010 connection_struct
*conn
= req
->conn
;
8013 struct timespec create_ts
;
8015 START_PROFILE(SMBgetattrE
);
8018 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8019 END_PROFILE(SMBgetattrE
);
8023 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8025 if(!fsp
|| (fsp
->conn
!= conn
)) {
8026 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8027 END_PROFILE(SMBgetattrE
);
8031 /* Do an fstat on this file */
8033 reply_nterror(req
, map_nt_error_from_unix(errno
));
8034 END_PROFILE(SMBgetattrE
);
8038 mode
= dos_mode(conn
, fsp
->fsp_name
);
8041 * Convert the times into dos times. Set create
8042 * date to be last modify date as UNIX doesn't save
8046 reply_outbuf(req
, 11, 0);
8048 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8049 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8050 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8051 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8052 /* Should we check pending modtime here ? JRA */
8053 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8054 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8056 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8057 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8058 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8060 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8061 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
8062 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8064 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8066 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
8068 END_PROFILE(SMBgetattrE
);