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 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1273 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1274 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1276 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1278 status
= check_access(conn
, NULL
, smb_fname
,
1279 FILE_WRITE_ATTRIBUTES
);
1280 if (!NT_STATUS_IS_OK(status
)) {
1281 reply_nterror(req
, status
);
1285 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1287 reply_nterror(req
, map_nt_error_from_unix(errno
));
1292 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1293 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1294 if (!NT_STATUS_IS_OK(status
)) {
1295 reply_nterror(req
, status
);
1299 reply_outbuf(req
, 0, 0);
1301 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1304 TALLOC_FREE(smb_fname
);
1305 END_PROFILE(SMBsetatr
);
1309 /****************************************************************************
1311 ****************************************************************************/
1313 void reply_dskattr(struct smb_request
*req
)
1315 connection_struct
*conn
= req
->conn
;
1316 uint64_t dfree
,dsize
,bsize
;
1317 START_PROFILE(SMBdskattr
);
1319 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1320 reply_nterror(req
, map_nt_error_from_unix(errno
));
1321 END_PROFILE(SMBdskattr
);
1325 reply_outbuf(req
, 5, 0);
1327 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1328 double total_space
, free_space
;
1329 /* we need to scale this to a number that DOS6 can handle. We
1330 use floating point so we can handle large drives on systems
1331 that don't have 64 bit integers
1333 we end up displaying a maximum of 2G to DOS systems
1335 total_space
= dsize
* (double)bsize
;
1336 free_space
= dfree
* (double)bsize
;
1338 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1339 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1341 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1342 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1344 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1345 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1346 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1347 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1349 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1350 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1351 SSVAL(req
->outbuf
,smb_vwv2
,512);
1352 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1355 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1357 END_PROFILE(SMBdskattr
);
1362 * Utility function to split the filename from the directory.
1364 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1365 char **fname_dir_out
,
1366 char **fname_mask_out
)
1368 const char *p
= NULL
;
1369 char *fname_dir
= NULL
;
1370 char *fname_mask
= NULL
;
1372 p
= strrchr_m(fname_in
, '/');
1374 fname_dir
= talloc_strdup(ctx
, ".");
1375 fname_mask
= talloc_strdup(ctx
, fname_in
);
1377 fname_dir
= talloc_strndup(ctx
, fname_in
,
1378 PTR_DIFF(p
, fname_in
));
1379 fname_mask
= talloc_strdup(ctx
, p
+1);
1382 if (!fname_dir
|| !fname_mask
) {
1383 TALLOC_FREE(fname_dir
);
1384 TALLOC_FREE(fname_mask
);
1385 return NT_STATUS_NO_MEMORY
;
1388 *fname_dir_out
= fname_dir
;
1389 *fname_mask_out
= fname_mask
;
1390 return NT_STATUS_OK
;
1393 /****************************************************************************
1395 Can be called from SMBsearch, SMBffirst or SMBfunique.
1396 ****************************************************************************/
1398 void reply_search(struct smb_request
*req
)
1400 connection_struct
*conn
= req
->conn
;
1402 const char *mask
= NULL
;
1403 char *directory
= NULL
;
1404 struct smb_filename
*smb_fname
= NULL
;
1408 struct timespec date
;
1410 unsigned int numentries
= 0;
1411 unsigned int maxentries
= 0;
1412 bool finished
= False
;
1417 bool check_descend
= False
;
1418 bool expect_close
= False
;
1420 bool mask_contains_wcard
= False
;
1421 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1422 TALLOC_CTX
*ctx
= talloc_tos();
1423 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1424 struct dptr_struct
*dirptr
= NULL
;
1425 struct smbd_server_connection
*sconn
= req
->sconn
;
1427 START_PROFILE(SMBsearch
);
1430 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1434 if (lp_posix_pathnames()) {
1435 reply_unknown_new(req
, req
->cmd
);
1439 /* If we were called as SMBffirst then we must expect close. */
1440 if(req
->cmd
== SMBffirst
) {
1441 expect_close
= True
;
1444 reply_outbuf(req
, 1, 3);
1445 maxentries
= SVAL(req
->vwv
+0, 0);
1446 dirtype
= SVAL(req
->vwv
+1, 0);
1447 p
= (const char *)req
->buf
+ 1;
1448 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1449 &nt_status
, &mask_contains_wcard
);
1450 if (!NT_STATUS_IS_OK(nt_status
)) {
1451 reply_nterror(req
, nt_status
);
1456 status_len
= SVAL(p
, 0);
1459 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1461 if (status_len
== 0) {
1462 nt_status
= filename_convert(ctx
, conn
,
1463 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1465 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1466 &mask_contains_wcard
,
1468 if (!NT_STATUS_IS_OK(nt_status
)) {
1469 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1470 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1471 ERRSRV
, ERRbadpath
);
1474 reply_nterror(req
, nt_status
);
1478 directory
= smb_fname
->base_name
;
1480 p
= strrchr_m(directory
,'/');
1481 if ((p
!= NULL
) && (*directory
!= '/')) {
1483 directory
= talloc_strndup(ctx
, directory
,
1484 PTR_DIFF(p
, directory
));
1487 directory
= talloc_strdup(ctx
,".");
1491 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1495 memset((char *)status
,'\0',21);
1496 SCVAL(status
,0,(dirtype
& 0x1F));
1498 nt_status
= dptr_create(conn
,
1505 mask_contains_wcard
,
1508 if (!NT_STATUS_IS_OK(nt_status
)) {
1509 reply_nterror(req
, nt_status
);
1512 dptr_num
= dptr_dnum(dirptr
);
1515 const char *dirpath
;
1517 memcpy(status
,p
,21);
1518 status_dirtype
= CVAL(status
,0) & 0x1F;
1519 if (status_dirtype
!= (dirtype
& 0x1F)) {
1520 dirtype
= status_dirtype
;
1523 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1527 dirpath
= dptr_path(sconn
, dptr_num
);
1528 directory
= talloc_strdup(ctx
, dirpath
);
1530 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1534 mask
= dptr_wcard(sconn
, dptr_num
);
1539 * For a 'continue' search we have no string. So
1540 * check from the initial saved string.
1542 mask_contains_wcard
= ms_has_wild(mask
);
1543 dirtype
= dptr_attr(sconn
, dptr_num
);
1546 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1548 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1549 dptr_init_search_op(dirptr
);
1551 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1552 char buf
[DIR_STRUCT_SIZE
];
1553 memcpy(buf
,status
,21);
1554 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1555 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1556 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1559 dptr_fill(sconn
, buf
+12,dptr_num
);
1560 if (dptr_zero(buf
+12) && (status_len
==0)) {
1565 if (message_push_blob(&req
->outbuf
,
1566 data_blob_const(buf
, sizeof(buf
)))
1568 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1576 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1579 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1580 directory
,lp_dontdescend(SNUM(conn
))));
1581 if (in_list(directory
, lp_dontdescend(SNUM(conn
)),True
)) {
1582 check_descend
= True
;
1585 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1586 finished
= !get_dir_entry(ctx
,
1597 char buf
[DIR_STRUCT_SIZE
];
1598 memcpy(buf
,status
,21);
1599 if (!make_dir_struct(ctx
,
1605 convert_timespec_to_time_t(date
),
1606 !allow_long_path_components
)) {
1607 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1610 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1613 if (message_push_blob(&req
->outbuf
,
1614 data_blob_const(buf
, sizeof(buf
)))
1616 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1626 /* If we were called as SMBffirst with smb_search_id == NULL
1627 and no entries were found then return error and close dirptr
1630 if (numentries
== 0) {
1631 dptr_close(sconn
, &dptr_num
);
1632 } else if(expect_close
&& status_len
== 0) {
1633 /* Close the dptr - we know it's gone */
1634 dptr_close(sconn
, &dptr_num
);
1637 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1638 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1639 dptr_close(sconn
, &dptr_num
);
1642 if ((numentries
== 0) && !mask_contains_wcard
) {
1643 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1647 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1648 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1649 SCVAL(smb_buf(req
->outbuf
),0,5);
1650 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1652 /* The replies here are never long name. */
1653 SSVAL(req
->outbuf
, smb_flg2
,
1654 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1655 if (!allow_long_path_components
) {
1656 SSVAL(req
->outbuf
, smb_flg2
,
1657 SVAL(req
->outbuf
, smb_flg2
)
1658 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1661 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1662 SSVAL(req
->outbuf
, smb_flg2
,
1663 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1665 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1666 smb_fn_name(req
->cmd
),
1673 TALLOC_FREE(directory
);
1674 TALLOC_FREE(smb_fname
);
1675 END_PROFILE(SMBsearch
);
1679 /****************************************************************************
1680 Reply to a fclose (stop directory search).
1681 ****************************************************************************/
1683 void reply_fclose(struct smb_request
*req
)
1691 bool path_contains_wcard
= False
;
1692 TALLOC_CTX
*ctx
= talloc_tos();
1693 struct smbd_server_connection
*sconn
= req
->sconn
;
1695 START_PROFILE(SMBfclose
);
1697 if (lp_posix_pathnames()) {
1698 reply_unknown_new(req
, req
->cmd
);
1699 END_PROFILE(SMBfclose
);
1703 p
= (const char *)req
->buf
+ 1;
1704 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1705 &err
, &path_contains_wcard
);
1706 if (!NT_STATUS_IS_OK(err
)) {
1707 reply_nterror(req
, err
);
1708 END_PROFILE(SMBfclose
);
1712 status_len
= SVAL(p
,0);
1715 if (status_len
== 0) {
1716 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1717 END_PROFILE(SMBfclose
);
1721 memcpy(status
,p
,21);
1723 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1724 /* Close the dptr - we know it's gone */
1725 dptr_close(sconn
, &dptr_num
);
1728 reply_outbuf(req
, 1, 0);
1729 SSVAL(req
->outbuf
,smb_vwv0
,0);
1731 DEBUG(3,("search close\n"));
1733 END_PROFILE(SMBfclose
);
1737 /****************************************************************************
1739 ****************************************************************************/
1741 void reply_open(struct smb_request
*req
)
1743 connection_struct
*conn
= req
->conn
;
1744 struct smb_filename
*smb_fname
= NULL
;
1756 uint32 create_disposition
;
1757 uint32 create_options
= 0;
1758 uint32_t private_flags
= 0;
1760 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1761 TALLOC_CTX
*ctx
= talloc_tos();
1763 START_PROFILE(SMBopen
);
1766 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1770 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1771 deny_mode
= SVAL(req
->vwv
+0, 0);
1772 dos_attr
= SVAL(req
->vwv
+1, 0);
1774 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1775 STR_TERMINATE
, &status
);
1776 if (!NT_STATUS_IS_OK(status
)) {
1777 reply_nterror(req
, status
);
1781 status
= filename_convert(ctx
,
1783 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1788 if (!NT_STATUS_IS_OK(status
)) {
1789 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1790 reply_botherror(req
,
1791 NT_STATUS_PATH_NOT_COVERED
,
1792 ERRSRV
, ERRbadpath
);
1795 reply_nterror(req
, status
);
1799 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1800 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1801 &share_mode
, &create_disposition
,
1802 &create_options
, &private_flags
)) {
1803 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1807 status
= SMB_VFS_CREATE_FILE(
1810 0, /* root_dir_fid */
1811 smb_fname
, /* fname */
1812 access_mask
, /* access_mask */
1813 share_mode
, /* share_access */
1814 create_disposition
, /* create_disposition*/
1815 create_options
, /* create_options */
1816 dos_attr
, /* file_attributes */
1817 oplock_request
, /* oplock_request */
1818 0, /* allocation_size */
1825 if (!NT_STATUS_IS_OK(status
)) {
1826 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1827 /* We have re-scheduled this call. */
1830 reply_openerror(req
, status
);
1834 size
= smb_fname
->st
.st_ex_size
;
1835 fattr
= dos_mode(conn
, smb_fname
);
1837 /* Deal with other possible opens having a modified
1839 if (ask_sharemode
) {
1840 struct timespec write_time_ts
;
1842 ZERO_STRUCT(write_time_ts
);
1843 get_file_infos(fsp
->file_id
, 0, NULL
, &write_time_ts
);
1844 if (!null_timespec(write_time_ts
)) {
1845 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1849 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1851 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1852 DEBUG(3,("attempt to open a directory %s\n",
1854 close_file(req
, fsp
, ERROR_CLOSE
);
1855 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1856 ERRDOS
, ERRnoaccess
);
1860 reply_outbuf(req
, 7, 0);
1861 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1862 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1863 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1864 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1866 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1868 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1869 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1871 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1872 SCVAL(req
->outbuf
,smb_flg
,
1873 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1876 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1877 SCVAL(req
->outbuf
,smb_flg
,
1878 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1881 TALLOC_FREE(smb_fname
);
1882 END_PROFILE(SMBopen
);
1886 /****************************************************************************
1887 Reply to an open and X.
1888 ****************************************************************************/
1890 void reply_open_and_X(struct smb_request
*req
)
1892 connection_struct
*conn
= req
->conn
;
1893 struct smb_filename
*smb_fname
= NULL
;
1898 /* Breakout the oplock request bits so we can set the
1899 reply bits separately. */
1900 int ex_oplock_request
;
1901 int core_oplock_request
;
1904 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1905 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
1913 uint64_t allocation_size
;
1914 ssize_t retval
= -1;
1917 uint32 create_disposition
;
1918 uint32 create_options
= 0;
1919 uint32_t private_flags
= 0;
1920 TALLOC_CTX
*ctx
= talloc_tos();
1922 START_PROFILE(SMBopenX
);
1924 if (req
->wct
< 15) {
1925 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1929 open_flags
= SVAL(req
->vwv
+2, 0);
1930 deny_mode
= SVAL(req
->vwv
+3, 0);
1931 smb_attr
= SVAL(req
->vwv
+5, 0);
1932 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1933 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1934 oplock_request
= ex_oplock_request
| core_oplock_request
;
1935 smb_ofun
= SVAL(req
->vwv
+8, 0);
1936 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1938 /* If it's an IPC, pass off the pipe handler. */
1940 if (lp_nt_pipe_support()) {
1941 reply_open_pipe_and_X(conn
, req
);
1943 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1948 /* XXXX we need to handle passed times, sattr and flags */
1949 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1950 STR_TERMINATE
, &status
);
1951 if (!NT_STATUS_IS_OK(status
)) {
1952 reply_nterror(req
, status
);
1956 status
= filename_convert(ctx
,
1958 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1963 if (!NT_STATUS_IS_OK(status
)) {
1964 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1965 reply_botherror(req
,
1966 NT_STATUS_PATH_NOT_COVERED
,
1967 ERRSRV
, ERRbadpath
);
1970 reply_nterror(req
, status
);
1974 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1976 &access_mask
, &share_mode
,
1977 &create_disposition
,
1980 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1984 status
= SMB_VFS_CREATE_FILE(
1987 0, /* root_dir_fid */
1988 smb_fname
, /* fname */
1989 access_mask
, /* access_mask */
1990 share_mode
, /* share_access */
1991 create_disposition
, /* create_disposition*/
1992 create_options
, /* create_options */
1993 smb_attr
, /* file_attributes */
1994 oplock_request
, /* oplock_request */
1995 0, /* allocation_size */
2000 &smb_action
); /* pinfo */
2002 if (!NT_STATUS_IS_OK(status
)) {
2003 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2004 /* We have re-scheduled this call. */
2007 reply_openerror(req
, status
);
2011 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2012 if the file is truncated or created. */
2013 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2014 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2015 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2016 close_file(req
, fsp
, ERROR_CLOSE
);
2017 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2020 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
2022 close_file(req
, fsp
, ERROR_CLOSE
);
2023 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2026 status
= vfs_stat_fsp(fsp
);
2027 if (!NT_STATUS_IS_OK(status
)) {
2028 close_file(req
, fsp
, ERROR_CLOSE
);
2029 reply_nterror(req
, status
);
2034 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2035 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2036 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2037 close_file(req
, fsp
, ERROR_CLOSE
);
2038 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2042 /* If the caller set the extended oplock request bit
2043 and we granted one (by whatever means) - set the
2044 correct bit for extended oplock reply.
2047 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2048 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2051 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2052 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2055 /* If the caller set the core oplock request bit
2056 and we granted one (by whatever means) - set the
2057 correct bit for core oplock reply.
2060 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2061 reply_outbuf(req
, 19, 0);
2063 reply_outbuf(req
, 15, 0);
2066 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2067 SCVAL(req
->outbuf
, smb_flg
,
2068 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2071 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2072 SCVAL(req
->outbuf
, smb_flg
,
2073 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2076 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2077 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2078 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2079 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2081 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2083 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)fsp
->fsp_name
->st
.st_ex_size
);
2084 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2085 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2087 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2088 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2093 TALLOC_FREE(smb_fname
);
2094 END_PROFILE(SMBopenX
);
2098 /****************************************************************************
2099 Reply to a SMBulogoffX.
2100 ****************************************************************************/
2102 void reply_ulogoffX(struct smb_request
*req
)
2104 struct smbd_server_connection
*sconn
= req
->sconn
;
2107 START_PROFILE(SMBulogoffX
);
2109 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2112 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2116 /* in user level security we are supposed to close any files
2117 open by this user */
2118 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
2119 file_close_user(sconn
, req
->vuid
);
2122 invalidate_vuid(sconn
, req
->vuid
);
2124 reply_outbuf(req
, 2, 0);
2126 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
2128 END_PROFILE(SMBulogoffX
);
2129 req
->vuid
= UID_FIELD_INVALID
;
2133 /****************************************************************************
2134 Reply to a mknew or a create.
2135 ****************************************************************************/
2137 void reply_mknew(struct smb_request
*req
)
2139 connection_struct
*conn
= req
->conn
;
2140 struct smb_filename
*smb_fname
= NULL
;
2143 struct smb_file_time ft
;
2145 int oplock_request
= 0;
2147 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2148 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2149 uint32 create_disposition
;
2150 uint32 create_options
= 0;
2151 TALLOC_CTX
*ctx
= talloc_tos();
2153 START_PROFILE(SMBcreate
);
2157 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2161 fattr
= SVAL(req
->vwv
+0, 0);
2162 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2165 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2167 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2168 STR_TERMINATE
, &status
);
2169 if (!NT_STATUS_IS_OK(status
)) {
2170 reply_nterror(req
, status
);
2174 status
= filename_convert(ctx
,
2176 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2181 if (!NT_STATUS_IS_OK(status
)) {
2182 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2183 reply_botherror(req
,
2184 NT_STATUS_PATH_NOT_COVERED
,
2185 ERRSRV
, ERRbadpath
);
2188 reply_nterror(req
, status
);
2192 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2193 DEBUG(0,("Attempt to create file (%s) with volid set - "
2194 "please report this\n",
2195 smb_fname_str_dbg(smb_fname
)));
2198 if(req
->cmd
== SMBmknew
) {
2199 /* We should fail if file exists. */
2200 create_disposition
= FILE_CREATE
;
2202 /* Create if file doesn't exist, truncate if it does. */
2203 create_disposition
= FILE_OVERWRITE_IF
;
2206 status
= SMB_VFS_CREATE_FILE(
2209 0, /* root_dir_fid */
2210 smb_fname
, /* fname */
2211 access_mask
, /* access_mask */
2212 share_mode
, /* share_access */
2213 create_disposition
, /* create_disposition*/
2214 create_options
, /* create_options */
2215 fattr
, /* file_attributes */
2216 oplock_request
, /* oplock_request */
2217 0, /* allocation_size */
2218 0, /* private_flags */
2224 if (!NT_STATUS_IS_OK(status
)) {
2225 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2226 /* We have re-scheduled this call. */
2229 reply_openerror(req
, status
);
2233 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2234 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2235 if (!NT_STATUS_IS_OK(status
)) {
2236 END_PROFILE(SMBcreate
);
2240 reply_outbuf(req
, 1, 0);
2241 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2243 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2244 SCVAL(req
->outbuf
,smb_flg
,
2245 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2248 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2249 SCVAL(req
->outbuf
,smb_flg
,
2250 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2253 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2254 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2255 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2256 (unsigned int)fattr
));
2259 TALLOC_FREE(smb_fname
);
2260 END_PROFILE(SMBcreate
);
2264 /****************************************************************************
2265 Reply to a create temporary file.
2266 ****************************************************************************/
2268 void reply_ctemp(struct smb_request
*req
)
2270 connection_struct
*conn
= req
->conn
;
2271 struct smb_filename
*smb_fname
= NULL
;
2279 TALLOC_CTX
*ctx
= talloc_tos();
2281 START_PROFILE(SMBctemp
);
2284 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2288 fattr
= SVAL(req
->vwv
+0, 0);
2289 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2291 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2292 STR_TERMINATE
, &status
);
2293 if (!NT_STATUS_IS_OK(status
)) {
2294 reply_nterror(req
, status
);
2298 fname
= talloc_asprintf(ctx
,
2302 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2306 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2310 status
= filename_convert(ctx
, conn
,
2311 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2316 if (!NT_STATUS_IS_OK(status
)) {
2317 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2318 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2319 ERRSRV
, ERRbadpath
);
2322 reply_nterror(req
, status
);
2326 tmpfd
= mkstemp(smb_fname
->base_name
);
2328 reply_nterror(req
, map_nt_error_from_unix(errno
));
2332 SMB_VFS_STAT(conn
, smb_fname
);
2334 /* We should fail if file does not exist. */
2335 status
= SMB_VFS_CREATE_FILE(
2338 0, /* root_dir_fid */
2339 smb_fname
, /* fname */
2340 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2341 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2342 FILE_OPEN
, /* create_disposition*/
2343 0, /* create_options */
2344 fattr
, /* file_attributes */
2345 oplock_request
, /* oplock_request */
2346 0, /* allocation_size */
2347 0, /* private_flags */
2353 /* close fd from mkstemp() */
2356 if (!NT_STATUS_IS_OK(status
)) {
2357 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2358 /* We have re-scheduled this call. */
2361 reply_openerror(req
, status
);
2365 reply_outbuf(req
, 1, 0);
2366 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2368 /* the returned filename is relative to the directory */
2369 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2371 s
= fsp
->fsp_name
->base_name
;
2377 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2378 thing in the byte section. JRA */
2379 SSVALS(p
, 0, -1); /* what is this? not in spec */
2381 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2383 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2387 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2388 SCVAL(req
->outbuf
, smb_flg
,
2389 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2392 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2393 SCVAL(req
->outbuf
, smb_flg
,
2394 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2397 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2398 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2399 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2401 TALLOC_FREE(smb_fname
);
2402 END_PROFILE(SMBctemp
);
2406 /*******************************************************************
2407 Check if a user is allowed to rename a file.
2408 ********************************************************************/
2410 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2413 if (!CAN_WRITE(conn
)) {
2414 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2417 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2418 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2419 /* Only bother to read the DOS attribute if we might deny the
2420 rename on the grounds of attribute missmatch. */
2421 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2422 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2423 return NT_STATUS_NO_SUCH_FILE
;
2427 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2428 if (fsp
->posix_open
) {
2429 return NT_STATUS_OK
;
2432 /* If no pathnames are open below this
2433 directory, allow the rename. */
2435 if (file_find_subpath(fsp
)) {
2436 return NT_STATUS_ACCESS_DENIED
;
2438 return NT_STATUS_OK
;
2441 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2442 return NT_STATUS_OK
;
2445 return NT_STATUS_ACCESS_DENIED
;
2448 /*******************************************************************
2449 * unlink a file with all relevant access checks
2450 *******************************************************************/
2452 static NTSTATUS
do_unlink(connection_struct
*conn
,
2453 struct smb_request
*req
,
2454 struct smb_filename
*smb_fname
,
2459 uint32 dirtype_orig
= dirtype
;
2462 bool posix_paths
= lp_posix_pathnames();
2464 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2465 smb_fname_str_dbg(smb_fname
),
2468 if (!CAN_WRITE(conn
)) {
2469 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2473 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2475 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2478 return map_nt_error_from_unix(errno
);
2481 fattr
= dos_mode(conn
, smb_fname
);
2483 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2484 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2487 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2489 return NT_STATUS_NO_SUCH_FILE
;
2492 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2493 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2494 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2496 return NT_STATUS_NO_SUCH_FILE
;
2499 if (dirtype_orig
& 0x8000) {
2500 /* These will never be set for POSIX. */
2501 return NT_STATUS_NO_SUCH_FILE
;
2505 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2506 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2509 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2510 return NT_STATUS_NO_SUCH_FILE
;
2513 if (dirtype
& 0xFF00) {
2514 /* These will never be set for POSIX. */
2515 return NT_STATUS_NO_SUCH_FILE
;
2520 return NT_STATUS_NO_SUCH_FILE
;
2523 /* Can't delete a directory. */
2524 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2525 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2530 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2531 return NT_STATUS_OBJECT_NAME_INVALID
;
2532 #endif /* JRATEST */
2534 /* On open checks the open itself will check the share mode, so
2535 don't do it here as we'll get it wrong. */
2537 status
= SMB_VFS_CREATE_FILE
2540 0, /* root_dir_fid */
2541 smb_fname
, /* fname */
2542 DELETE_ACCESS
, /* access_mask */
2543 FILE_SHARE_NONE
, /* share_access */
2544 FILE_OPEN
, /* create_disposition*/
2545 FILE_NON_DIRECTORY_FILE
, /* create_options */
2546 /* file_attributes */
2547 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2548 FILE_ATTRIBUTE_NORMAL
,
2549 0, /* oplock_request */
2550 0, /* allocation_size */
2551 0, /* private_flags */
2557 if (!NT_STATUS_IS_OK(status
)) {
2558 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2559 nt_errstr(status
)));
2563 status
= can_set_delete_on_close(fsp
, fattr
);
2564 if (!NT_STATUS_IS_OK(status
)) {
2565 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2567 smb_fname_str_dbg(smb_fname
),
2568 nt_errstr(status
)));
2569 close_file(req
, fsp
, NORMAL_CLOSE
);
2573 /* The set is across all open files on this dev/inode pair. */
2574 if (!set_delete_on_close(fsp
, True
, conn
->session_info
->unix_token
)) {
2575 close_file(req
, fsp
, NORMAL_CLOSE
);
2576 return NT_STATUS_ACCESS_DENIED
;
2579 return close_file(req
, fsp
, NORMAL_CLOSE
);
2582 /****************************************************************************
2583 The guts of the unlink command, split out so it may be called by the NT SMB
2585 ****************************************************************************/
2587 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2588 uint32 dirtype
, struct smb_filename
*smb_fname
,
2591 char *fname_dir
= NULL
;
2592 char *fname_mask
= NULL
;
2594 NTSTATUS status
= NT_STATUS_OK
;
2595 TALLOC_CTX
*ctx
= talloc_tos();
2597 /* Split up the directory from the filename/mask. */
2598 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2599 &fname_dir
, &fname_mask
);
2600 if (!NT_STATUS_IS_OK(status
)) {
2605 * We should only check the mangled cache
2606 * here if unix_convert failed. This means
2607 * that the path in 'mask' doesn't exist
2608 * on the file system and so we need to look
2609 * for a possible mangle. This patch from
2610 * Tine Smukavec <valentin.smukavec@hermes.si>.
2613 if (!VALID_STAT(smb_fname
->st
) &&
2614 mangle_is_mangled(fname_mask
, conn
->params
)) {
2615 char *new_mask
= NULL
;
2616 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2617 &new_mask
, conn
->params
);
2619 TALLOC_FREE(fname_mask
);
2620 fname_mask
= new_mask
;
2627 * Only one file needs to be unlinked. Append the mask back
2628 * onto the directory.
2630 TALLOC_FREE(smb_fname
->base_name
);
2631 if (ISDOT(fname_dir
)) {
2632 /* Ensure we use canonical names on open. */
2633 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2637 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2642 if (!smb_fname
->base_name
) {
2643 status
= NT_STATUS_NO_MEMORY
;
2647 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2650 status
= check_name(conn
, smb_fname
->base_name
);
2651 if (!NT_STATUS_IS_OK(status
)) {
2655 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2656 if (!NT_STATUS_IS_OK(status
)) {
2662 struct smb_Dir
*dir_hnd
= NULL
;
2664 const char *dname
= NULL
;
2665 char *talloced
= NULL
;
2667 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
2668 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2672 if (strequal(fname_mask
,"????????.???")) {
2673 TALLOC_FREE(fname_mask
);
2674 fname_mask
= talloc_strdup(ctx
, "*");
2676 status
= NT_STATUS_NO_MEMORY
;
2681 status
= check_name(conn
, fname_dir
);
2682 if (!NT_STATUS_IS_OK(status
)) {
2686 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2688 if (dir_hnd
== NULL
) {
2689 status
= map_nt_error_from_unix(errno
);
2693 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2694 the pattern matches against the long name, otherwise the short name
2695 We don't implement this yet XXXX
2698 status
= NT_STATUS_NO_SUCH_FILE
;
2700 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2701 &smb_fname
->st
, &talloced
))) {
2702 TALLOC_CTX
*frame
= talloc_stackframe();
2704 if (!is_visible_file(conn
, fname_dir
, dname
,
2705 &smb_fname
->st
, true)) {
2707 TALLOC_FREE(talloced
);
2711 /* Quick check for "." and ".." */
2712 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2714 TALLOC_FREE(talloced
);
2718 if(!mask_match(dname
, fname_mask
,
2719 conn
->case_sensitive
)) {
2721 TALLOC_FREE(talloced
);
2725 TALLOC_FREE(smb_fname
->base_name
);
2726 if (ISDOT(fname_dir
)) {
2727 /* Ensure we use canonical names on open. */
2728 smb_fname
->base_name
=
2729 talloc_asprintf(smb_fname
, "%s",
2732 smb_fname
->base_name
=
2733 talloc_asprintf(smb_fname
, "%s/%s",
2737 if (!smb_fname
->base_name
) {
2738 TALLOC_FREE(dir_hnd
);
2739 status
= NT_STATUS_NO_MEMORY
;
2741 TALLOC_FREE(talloced
);
2745 status
= check_name(conn
, smb_fname
->base_name
);
2746 if (!NT_STATUS_IS_OK(status
)) {
2747 TALLOC_FREE(dir_hnd
);
2749 TALLOC_FREE(talloced
);
2753 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2754 if (!NT_STATUS_IS_OK(status
)) {
2756 TALLOC_FREE(talloced
);
2761 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2762 smb_fname
->base_name
));
2765 TALLOC_FREE(talloced
);
2767 TALLOC_FREE(dir_hnd
);
2770 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2771 status
= map_nt_error_from_unix(errno
);
2775 TALLOC_FREE(fname_dir
);
2776 TALLOC_FREE(fname_mask
);
2780 /****************************************************************************
2782 ****************************************************************************/
2784 void reply_unlink(struct smb_request
*req
)
2786 connection_struct
*conn
= req
->conn
;
2788 struct smb_filename
*smb_fname
= NULL
;
2791 bool path_contains_wcard
= False
;
2792 TALLOC_CTX
*ctx
= talloc_tos();
2794 START_PROFILE(SMBunlink
);
2797 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2801 dirtype
= SVAL(req
->vwv
+0, 0);
2803 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2804 STR_TERMINATE
, &status
,
2805 &path_contains_wcard
);
2806 if (!NT_STATUS_IS_OK(status
)) {
2807 reply_nterror(req
, status
);
2811 status
= filename_convert(ctx
, conn
,
2812 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2814 UCF_COND_ALLOW_WCARD_LCOMP
,
2815 &path_contains_wcard
,
2817 if (!NT_STATUS_IS_OK(status
)) {
2818 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2819 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2820 ERRSRV
, ERRbadpath
);
2823 reply_nterror(req
, status
);
2827 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2829 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2830 path_contains_wcard
);
2831 if (!NT_STATUS_IS_OK(status
)) {
2832 if (open_was_deferred(req
->sconn
, req
->mid
)) {
2833 /* We have re-scheduled this call. */
2836 reply_nterror(req
, status
);
2840 reply_outbuf(req
, 0, 0);
2842 TALLOC_FREE(smb_fname
);
2843 END_PROFILE(SMBunlink
);
2847 /****************************************************************************
2849 ****************************************************************************/
2851 static void fail_readraw(void)
2853 const char *errstr
= talloc_asprintf(talloc_tos(),
2854 "FAIL ! reply_readbraw: socket write fail (%s)",
2859 exit_server_cleanly(errstr
);
2862 /****************************************************************************
2863 Fake (read/write) sendfile. Returns -1 on read or write fail.
2864 ****************************************************************************/
2866 ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
)
2869 size_t tosend
= nread
;
2876 bufsize
= MIN(nread
, 65536);
2878 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2882 while (tosend
> 0) {
2886 if (tosend
> bufsize
) {
2891 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2897 /* If we had a short read, fill with zeros. */
2898 if (ret
< cur_read
) {
2899 memset(buf
+ ret
, '\0', cur_read
- ret
);
2902 if (write_data(fsp
->conn
->sconn
->sock
, buf
, cur_read
)
2904 char addr
[INET6_ADDRSTRLEN
];
2906 * Try and give an error message saying what
2909 DEBUG(0, ("write_data failed for client %s. "
2911 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
2918 startpos
+= cur_read
;
2922 return (ssize_t
)nread
;
2925 /****************************************************************************
2926 Deal with the case of sendfile reading less bytes from the file than
2927 requested. Fill with zeros (all we can do).
2928 ****************************************************************************/
2930 void sendfile_short_send(files_struct
*fsp
,
2935 #define SHORT_SEND_BUFSIZE 1024
2936 if (nread
< headersize
) {
2937 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2938 "header for file %s (%s). Terminating\n",
2939 fsp_str_dbg(fsp
), strerror(errno
)));
2940 exit_server_cleanly("sendfile_short_send failed");
2943 nread
-= headersize
;
2945 if (nread
< smb_maxcnt
) {
2946 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
2948 exit_server_cleanly("sendfile_short_send: "
2952 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2953 "with zeros !\n", fsp_str_dbg(fsp
)));
2955 while (nread
< smb_maxcnt
) {
2957 * We asked for the real file size and told sendfile
2958 * to not go beyond the end of the file. But it can
2959 * happen that in between our fstat call and the
2960 * sendfile call the file was truncated. This is very
2961 * bad because we have already announced the larger
2962 * number of bytes to the client.
2964 * The best we can do now is to send 0-bytes, just as
2965 * a read from a hole in a sparse file would do.
2967 * This should happen rarely enough that I don't care
2968 * about efficiency here :-)
2972 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
2973 if (write_data(fsp
->conn
->sconn
->sock
, buf
, to_write
)
2975 char addr
[INET6_ADDRSTRLEN
];
2977 * Try and give an error message saying what
2980 DEBUG(0, ("write_data failed for client %s. "
2983 fsp
->conn
->sconn
->sock
, addr
,
2986 exit_server_cleanly("sendfile_short_send: "
2987 "write_data failed");
2995 /****************************************************************************
2996 Return a readbraw error (4 bytes of zero).
2997 ****************************************************************************/
2999 static void reply_readbraw_error(struct smbd_server_connection
*sconn
)
3005 smbd_lock_socket(sconn
);
3006 if (write_data(sconn
->sock
,header
,4) != 4) {
3007 char addr
[INET6_ADDRSTRLEN
];
3009 * Try and give an error message saying what
3012 DEBUG(0, ("write_data failed for client %s. "
3014 get_peer_addr(sconn
->sock
, addr
, sizeof(addr
)),
3019 smbd_unlock_socket(sconn
);
3022 /****************************************************************************
3023 Use sendfile in readbraw.
3024 ****************************************************************************/
3026 static void send_file_readbraw(connection_struct
*conn
,
3027 struct smb_request
*req
,
3033 struct smbd_server_connection
*sconn
= req
->sconn
;
3034 char *outbuf
= NULL
;
3038 * We can only use sendfile on a non-chained packet
3039 * but we can use on a non-oplocked file. tridge proved this
3040 * on a train in Germany :-). JRA.
3041 * reply_readbraw has already checked the length.
3044 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3045 (fsp
->wcp
== NULL
) &&
3046 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3047 ssize_t sendfile_read
= -1;
3049 DATA_BLOB header_blob
;
3051 _smb_setlen(header
,nread
);
3052 header_blob
= data_blob_const(header
, 4);
3054 sendfile_read
= SMB_VFS_SENDFILE(sconn
->sock
, fsp
,
3055 &header_blob
, startpos
,
3057 if (sendfile_read
== -1) {
3058 /* Returning ENOSYS means no data at all was sent.
3059 * Do this as a normal read. */
3060 if (errno
== ENOSYS
) {
3061 goto normal_readbraw
;
3065 * Special hack for broken Linux with no working sendfile. If we
3066 * return EINTR we sent the header but not the rest of the data.
3067 * Fake this up by doing read/write calls.
3069 if (errno
== EINTR
) {
3070 /* Ensure we don't do this again. */
3071 set_use_sendfile(SNUM(conn
), False
);
3072 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3074 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
3075 DEBUG(0,("send_file_readbraw: "
3076 "fake_sendfile failed for "
3080 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3085 DEBUG(0,("send_file_readbraw: sendfile failed for "
3086 "file %s (%s). Terminating\n",
3087 fsp_str_dbg(fsp
), strerror(errno
)));
3088 exit_server_cleanly("send_file_readbraw sendfile failed");
3089 } else if (sendfile_read
== 0) {
3091 * Some sendfile implementations return 0 to indicate
3092 * that there was a short read, but nothing was
3093 * actually written to the socket. In this case,
3094 * fallback to the normal read path so the header gets
3095 * the correct byte count.
3097 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3098 "bytes falling back to the normal read: "
3099 "%s\n", fsp_str_dbg(fsp
)));
3100 goto normal_readbraw
;
3103 /* Deal with possible short send. */
3104 if (sendfile_read
!= 4+nread
) {
3105 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
3112 outbuf
= talloc_array(NULL
, char, nread
+4);
3114 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3115 (unsigned)(nread
+4)));
3116 reply_readbraw_error(sconn
);
3121 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3122 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3131 _smb_setlen(outbuf
,ret
);
3132 if (write_data(sconn
->sock
, outbuf
, 4+ret
) != 4+ret
) {
3133 char addr
[INET6_ADDRSTRLEN
];
3135 * Try and give an error message saying what
3138 DEBUG(0, ("write_data failed for client %s. "
3140 get_peer_addr(fsp
->conn
->sconn
->sock
, addr
,
3147 TALLOC_FREE(outbuf
);
3150 /****************************************************************************
3151 Reply to a readbraw (core+ protocol).
3152 ****************************************************************************/
3154 void reply_readbraw(struct smb_request
*req
)
3156 connection_struct
*conn
= req
->conn
;
3157 struct smbd_server_connection
*sconn
= req
->sconn
;
3158 ssize_t maxcount
,mincount
;
3162 struct lock_struct lock
;
3165 START_PROFILE(SMBreadbraw
);
3167 if (srv_is_signing_active(sconn
) ||
3168 is_encrypted_packet(sconn
, req
->inbuf
)) {
3169 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3170 "raw reads/writes are disallowed.");
3174 reply_readbraw_error(sconn
);
3175 END_PROFILE(SMBreadbraw
);
3179 if (sconn
->smb1
.echo_handler
.trusted_fde
) {
3180 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3181 "'async smb echo handler = yes'\n"));
3182 reply_readbraw_error(sconn
);
3183 END_PROFILE(SMBreadbraw
);
3188 * Special check if an oplock break has been issued
3189 * and the readraw request croses on the wire, we must
3190 * return a zero length response here.
3193 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3196 * We have to do a check_fsp by hand here, as
3197 * we must always return 4 zero bytes on error,
3201 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3202 req
->vuid
!= fsp
->vuid
||
3203 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3205 * fsp could be NULL here so use the value from the packet. JRA.
3207 DEBUG(3,("reply_readbraw: fnum %d not valid "
3209 (int)SVAL(req
->vwv
+0, 0)));
3210 reply_readbraw_error(sconn
);
3211 END_PROFILE(SMBreadbraw
);
3215 /* Do a "by hand" version of CHECK_READ. */
3216 if (!(fsp
->can_read
||
3217 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3218 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3219 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3220 (int)SVAL(req
->vwv
+0, 0)));
3221 reply_readbraw_error(sconn
);
3222 END_PROFILE(SMBreadbraw
);
3226 flush_write_cache(fsp
, READRAW_FLUSH
);
3228 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3229 if(req
->wct
== 10) {
3231 * This is a large offset (64 bit) read.
3233 #ifdef LARGE_SMB_OFF_T
3235 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+8, 0)) << 32);
3237 #else /* !LARGE_SMB_OFF_T */
3240 * Ensure we haven't been sent a >32 bit offset.
3243 if(IVAL(req
->vwv
+8, 0) != 0) {
3244 DEBUG(0,("reply_readbraw: large offset "
3245 "(%x << 32) used and we don't support "
3246 "64 bit offsets.\n",
3247 (unsigned int)IVAL(req
->vwv
+8, 0) ));
3248 reply_readbraw_error(sconn
);
3249 END_PROFILE(SMBreadbraw
);
3253 #endif /* LARGE_SMB_OFF_T */
3256 DEBUG(0,("reply_readbraw: negative 64 bit "
3257 "readraw offset (%.0f) !\n",
3258 (double)startpos
));
3259 reply_readbraw_error(sconn
);
3260 END_PROFILE(SMBreadbraw
);
3265 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3266 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3268 /* ensure we don't overrun the packet size */
3269 maxcount
= MIN(65535,maxcount
);
3271 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3272 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3275 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3276 reply_readbraw_error(sconn
);
3277 END_PROFILE(SMBreadbraw
);
3281 if (fsp_stat(fsp
) == 0) {
3282 size
= fsp
->fsp_name
->st
.st_ex_size
;
3285 if (startpos
>= size
) {
3288 nread
= MIN(maxcount
,(size
- startpos
));
3291 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3292 if (nread
< mincount
)
3296 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3297 "min=%lu nread=%lu\n",
3298 fsp
->fnum
, (double)startpos
,
3299 (unsigned long)maxcount
,
3300 (unsigned long)mincount
,
3301 (unsigned long)nread
) );
3303 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3305 DEBUG(5,("reply_readbraw finished\n"));
3307 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3309 END_PROFILE(SMBreadbraw
);
3314 #define DBGC_CLASS DBGC_LOCKING
3316 /****************************************************************************
3317 Reply to a lockread (core+ protocol).
3318 ****************************************************************************/
3320 void reply_lockread(struct smb_request
*req
)
3322 connection_struct
*conn
= req
->conn
;
3329 struct byte_range_lock
*br_lck
= NULL
;
3331 struct smbd_server_connection
*sconn
= req
->sconn
;
3333 START_PROFILE(SMBlockread
);
3336 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3337 END_PROFILE(SMBlockread
);
3341 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3343 if (!check_fsp(conn
, req
, fsp
)) {
3344 END_PROFILE(SMBlockread
);
3348 if (!CHECK_READ(fsp
,req
)) {
3349 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3350 END_PROFILE(SMBlockread
);
3354 numtoread
= SVAL(req
->vwv
+1, 0);
3355 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3357 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3359 reply_outbuf(req
, 5, numtoread
+ 3);
3361 data
= smb_buf(req
->outbuf
) + 3;
3364 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3365 * protocol request that predates the read/write lock concept.
3366 * Thus instead of asking for a read lock here we need to ask
3367 * for a write lock. JRA.
3368 * Note that the requested lock size is unaffected by max_recv.
3371 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3373 (uint64_t)req
->smbpid
,
3374 (uint64_t)numtoread
,
3378 False
, /* Non-blocking lock. */
3382 TALLOC_FREE(br_lck
);
3384 if (NT_STATUS_V(status
)) {
3385 reply_nterror(req
, status
);
3386 END_PROFILE(SMBlockread
);
3391 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3394 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3395 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3396 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3397 (unsigned int)numtoread
,
3398 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3399 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3401 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3404 reply_nterror(req
, map_nt_error_from_unix(errno
));
3405 END_PROFILE(SMBlockread
);
3409 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3411 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3412 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3413 p
= smb_buf(req
->outbuf
);
3414 SCVAL(p
,0,0); /* pad byte. */
3417 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3418 fsp
->fnum
, (int)numtoread
, (int)nread
));
3420 END_PROFILE(SMBlockread
);
3425 #define DBGC_CLASS DBGC_ALL
3427 /****************************************************************************
3429 ****************************************************************************/
3431 void reply_read(struct smb_request
*req
)
3433 connection_struct
*conn
= req
->conn
;
3440 struct lock_struct lock
;
3441 struct smbd_server_connection
*sconn
= req
->sconn
;
3443 START_PROFILE(SMBread
);
3446 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3447 END_PROFILE(SMBread
);
3451 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3453 if (!check_fsp(conn
, req
, fsp
)) {
3454 END_PROFILE(SMBread
);
3458 if (!CHECK_READ(fsp
,req
)) {
3459 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3460 END_PROFILE(SMBread
);
3464 numtoread
= SVAL(req
->vwv
+1, 0);
3465 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3467 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3470 * The requested read size cannot be greater than max_recv. JRA.
3472 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3473 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3474 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3475 (unsigned int)numtoread
,
3476 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3477 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3480 reply_outbuf(req
, 5, numtoread
+3);
3482 data
= smb_buf(req
->outbuf
) + 3;
3484 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3485 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3488 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3489 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3490 END_PROFILE(SMBread
);
3495 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3498 reply_nterror(req
, map_nt_error_from_unix(errno
));
3502 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3504 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3505 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3506 SCVAL(smb_buf(req
->outbuf
),0,1);
3507 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3509 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3510 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3513 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3515 END_PROFILE(SMBread
);
3519 /****************************************************************************
3521 ****************************************************************************/
3523 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3529 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3530 data
= smb_buf(outbuf
);
3532 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3534 SCVAL(outbuf
,smb_vwv0
,0xFF);
3535 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3536 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3537 SSVAL(outbuf
,smb_vwv6
,
3539 + 1 /* the wct field */
3540 + 12 * sizeof(uint16_t) /* vwv */
3541 + 2); /* the buflen field */
3542 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3543 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3544 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3545 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3549 /****************************************************************************
3550 Reply to a read and X - possibly using sendfile.
3551 ****************************************************************************/
3553 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3554 files_struct
*fsp
, SMB_OFF_T startpos
,
3558 struct lock_struct lock
;
3559 int saved_errno
= 0;
3561 if(fsp_stat(fsp
) == -1) {
3562 reply_nterror(req
, map_nt_error_from_unix(errno
));
3566 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3567 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3570 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3571 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3575 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3576 (startpos
> fsp
->fsp_name
->st
.st_ex_size
)
3577 || (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3579 * We already know that we would do a short read, so don't
3580 * try the sendfile() path.
3582 goto nosendfile_read
;
3586 * We can only use sendfile on a non-chained packet
3587 * but we can use on a non-oplocked file. tridge proved this
3588 * on a train in Germany :-). JRA.
3591 if (!req_is_in_chain(req
) &&
3592 !is_encrypted_packet(req
->sconn
, req
->inbuf
) &&
3593 (fsp
->base_fsp
== NULL
) &&
3594 (fsp
->wcp
== NULL
) &&
3595 lp_use_sendfile(SNUM(conn
), req
->sconn
->smb1
.signing_state
) ) {
3596 uint8 headerbuf
[smb_size
+ 12 * 2];
3600 * Set up the packet header before send. We
3601 * assume here the sendfile will work (get the
3602 * correct amount of data).
3605 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3607 construct_reply_common_req(req
, (char *)headerbuf
);
3608 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3610 nread
= SMB_VFS_SENDFILE(req
->sconn
->sock
, fsp
, &header
,
3611 startpos
, smb_maxcnt
);
3613 /* Returning ENOSYS means no data at all was sent.
3614 Do this as a normal read. */
3615 if (errno
== ENOSYS
) {
3620 * Special hack for broken Linux with no working sendfile. If we
3621 * return EINTR we sent the header but not the rest of the data.
3622 * Fake this up by doing read/write calls.
3625 if (errno
== EINTR
) {
3626 /* Ensure we don't do this again. */
3627 set_use_sendfile(SNUM(conn
), False
);
3628 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3629 nread
= fake_sendfile(fsp
, startpos
,
3632 DEBUG(0,("send_file_readX: "
3633 "fake_sendfile failed for "
3637 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3639 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3640 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3641 /* No outbuf here means successful sendfile. */
3645 DEBUG(0,("send_file_readX: sendfile failed for file "
3646 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3648 exit_server_cleanly("send_file_readX sendfile failed");
3649 } else if (nread
== 0) {
3651 * Some sendfile implementations return 0 to indicate
3652 * that there was a short read, but nothing was
3653 * actually written to the socket. In this case,
3654 * fallback to the normal read path so the header gets
3655 * the correct byte count.
3657 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3658 "falling back to the normal read: %s\n",
3663 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3664 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3666 /* Deal with possible short send. */
3667 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3668 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3670 /* No outbuf here means successful sendfile. */
3671 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3672 SMB_PERFCOUNT_END(&req
->pcd
);
3678 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3679 uint8 headerbuf
[smb_size
+ 2*12];
3681 construct_reply_common_req(req
, (char *)headerbuf
);
3682 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3684 /* Send out the header. */
3685 if (write_data(req
->sconn
->sock
, (char *)headerbuf
,
3686 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3688 char addr
[INET6_ADDRSTRLEN
];
3690 * Try and give an error message saying what
3693 DEBUG(0, ("write_data failed for client %s. "
3695 get_peer_addr(req
->sconn
->sock
, addr
,
3699 DEBUG(0,("send_file_readX: write_data failed for file "
3700 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3702 exit_server_cleanly("send_file_readX sendfile failed");
3704 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3706 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3707 "file %s (%s).\n", fsp_str_dbg(fsp
),
3709 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3716 reply_outbuf(req
, 12, smb_maxcnt
);
3718 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3719 saved_errno
= errno
;
3721 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3724 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3728 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3730 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3731 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3737 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3738 TALLOC_FREE(req
->outbuf
);
3742 /****************************************************************************
3743 Reply to a read and X.
3744 ****************************************************************************/
3746 void reply_read_and_X(struct smb_request
*req
)
3748 struct smbd_server_connection
*sconn
= req
->sconn
;
3749 connection_struct
*conn
= req
->conn
;
3753 bool big_readX
= False
;
3755 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3758 START_PROFILE(SMBreadX
);
3760 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3761 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3765 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3766 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3767 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3769 /* If it's an IPC, pass off the pipe handler. */
3771 reply_pipe_read_and_X(req
);
3772 END_PROFILE(SMBreadX
);
3776 if (!check_fsp(conn
, req
, fsp
)) {
3777 END_PROFILE(SMBreadX
);
3781 if (!CHECK_READ(fsp
,req
)) {
3782 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3783 END_PROFILE(SMBreadX
);
3787 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_LARGE_READ_CAP
) ||
3788 (get_remote_arch() == RA_SAMBA
)) {
3790 * This is Samba only behavior (up to Samba 3.6)!
3792 * Windows 2008 R2 ignores the upper_size,
3793 * so we do unless unix extentions are active
3794 * or "smbclient" is talking to us.
3796 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3797 smb_maxcnt
|= (upper_size
<<16);
3798 if (upper_size
> 1) {
3799 /* Can't do this on a chained packet. */
3800 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3801 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3802 END_PROFILE(SMBreadX
);
3805 /* We currently don't do this on signed or sealed data. */
3806 if (srv_is_signing_active(req
->sconn
) ||
3807 is_encrypted_packet(req
->sconn
, req
->inbuf
)) {
3808 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3809 END_PROFILE(SMBreadX
);
3812 /* Is there room in the reply for this data ? */
3813 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3815 NT_STATUS_INVALID_PARAMETER
);
3816 END_PROFILE(SMBreadX
);
3823 if (req
->wct
== 12) {
3824 #ifdef LARGE_SMB_OFF_T
3826 * This is a large offset (64 bit) read.
3828 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+10, 0)) << 32);
3830 #else /* !LARGE_SMB_OFF_T */
3833 * Ensure we haven't been sent a >32 bit offset.
3836 if(IVAL(req
->vwv
+10, 0) != 0) {
3837 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3838 "used and we don't support 64 bit offsets.\n",
3839 (unsigned int)IVAL(req
->vwv
+10, 0) ));
3840 END_PROFILE(SMBreadX
);
3841 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3845 #endif /* LARGE_SMB_OFF_T */
3850 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3855 if (NT_STATUS_IS_OK(status
)) {
3856 /* Read scheduled - we're done. */
3859 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3860 /* Real error - report to client. */
3861 END_PROFILE(SMBreadX
);
3862 reply_nterror(req
, status
);
3865 /* NT_STATUS_RETRY - fall back to sync read. */
3868 smbd_lock_socket(req
->sconn
);
3869 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3870 smbd_unlock_socket(req
->sconn
);
3873 END_PROFILE(SMBreadX
);
3877 /****************************************************************************
3878 Error replies to writebraw must have smb_wct == 1. Fix this up.
3879 ****************************************************************************/
3881 void error_to_writebrawerr(struct smb_request
*req
)
3883 uint8
*old_outbuf
= req
->outbuf
;
3885 reply_outbuf(req
, 1, 0);
3887 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3888 TALLOC_FREE(old_outbuf
);
3891 /****************************************************************************
3892 Read 4 bytes of a smb packet and return the smb length of the packet.
3893 Store the result in the buffer. This version of the function will
3894 never return a session keepalive (length of zero).
3895 Timeout is in milliseconds.
3896 ****************************************************************************/
3898 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3901 uint8_t msgtype
= NBSSkeepalive
;
3903 while (msgtype
== NBSSkeepalive
) {
3906 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3908 if (!NT_STATUS_IS_OK(status
)) {
3909 char addr
[INET6_ADDRSTRLEN
];
3910 /* Try and give an error message
3911 * saying what client failed. */
3912 DEBUG(0, ("read_fd_with_timeout failed for "
3913 "client %s read error = %s.\n",
3914 get_peer_addr(fd
,addr
,sizeof(addr
)),
3915 nt_errstr(status
)));
3919 msgtype
= CVAL(inbuf
, 0);
3922 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3923 (unsigned long)len
));
3925 return NT_STATUS_OK
;
3928 /****************************************************************************
3929 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3930 ****************************************************************************/
3932 void reply_writebraw(struct smb_request
*req
)
3934 connection_struct
*conn
= req
->conn
;
3937 ssize_t total_written
=0;
3938 size_t numtowrite
=0;
3941 const char *data
=NULL
;
3944 struct lock_struct lock
;
3947 START_PROFILE(SMBwritebraw
);
3950 * If we ever reply with an error, it must have the SMB command
3951 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3954 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
3956 if (srv_is_signing_active(req
->sconn
)) {
3957 END_PROFILE(SMBwritebraw
);
3958 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3959 "raw reads/writes are disallowed.");
3962 if (req
->wct
< 12) {
3963 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3964 error_to_writebrawerr(req
);
3965 END_PROFILE(SMBwritebraw
);
3969 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3970 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3971 "'async smb echo handler = yes'\n"));
3972 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3973 error_to_writebrawerr(req
);
3974 END_PROFILE(SMBwritebraw
);
3978 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3979 if (!check_fsp(conn
, req
, fsp
)) {
3980 error_to_writebrawerr(req
);
3981 END_PROFILE(SMBwritebraw
);
3985 if (!CHECK_WRITE(fsp
)) {
3986 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3987 error_to_writebrawerr(req
);
3988 END_PROFILE(SMBwritebraw
);
3992 tcount
= IVAL(req
->vwv
+1, 0);
3993 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3994 write_through
= BITSETW(req
->vwv
+7,0);
3996 /* We have to deal with slightly different formats depending
3997 on whether we are using the core+ or lanman1.0 protocol */
3999 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4000 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4001 data
= smb_buf_const(req
->inbuf
);
4003 numtowrite
= SVAL(req
->vwv
+10, 0);
4004 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4007 /* Ensure we don't write bytes past the end of this packet. */
4008 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4009 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4010 error_to_writebrawerr(req
);
4011 END_PROFILE(SMBwritebraw
);
4015 if (!fsp
->print_file
) {
4016 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4017 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4020 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4021 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4022 error_to_writebrawerr(req
);
4023 END_PROFILE(SMBwritebraw
);
4029 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4032 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4033 "wrote=%d sync=%d\n",
4034 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4035 (int)nwritten
, (int)write_through
));
4037 if (nwritten
< (ssize_t
)numtowrite
) {
4038 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4039 error_to_writebrawerr(req
);
4043 total_written
= nwritten
;
4045 /* Allocate a buffer of 64k + length. */
4046 buf
= talloc_array(NULL
, char, 65540);
4048 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4049 error_to_writebrawerr(req
);
4053 /* Return a SMBwritebraw message to the redirector to tell
4054 * it to send more bytes */
4056 memcpy(buf
, req
->inbuf
, smb_size
);
4057 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4058 SCVAL(buf
,smb_com
,SMBwritebraw
);
4059 SSVALS(buf
,smb_vwv0
,0xFFFF);
4061 if (!srv_send_smb(req
->sconn
,
4063 false, 0, /* no signing */
4064 IS_CONN_ENCRYPTED(conn
),
4066 exit_server_cleanly("reply_writebraw: srv_send_smb "
4070 /* Now read the raw data into the buffer and write it */
4071 status
= read_smb_length(req
->sconn
->sock
, buf
, SMB_SECONDARY_WAIT
,
4073 if (!NT_STATUS_IS_OK(status
)) {
4074 exit_server_cleanly("secondary writebraw failed");
4077 /* Set up outbuf to return the correct size */
4078 reply_outbuf(req
, 1, 0);
4080 if (numtowrite
!= 0) {
4082 if (numtowrite
> 0xFFFF) {
4083 DEBUG(0,("reply_writebraw: Oversize secondary write "
4084 "raw requested (%u). Terminating\n",
4085 (unsigned int)numtowrite
));
4086 exit_server_cleanly("secondary writebraw failed");
4089 if (tcount
> nwritten
+numtowrite
) {
4090 DEBUG(3,("reply_writebraw: Client overestimated the "
4092 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4095 status
= read_data(req
->sconn
->sock
, buf
+4, numtowrite
);
4097 if (!NT_STATUS_IS_OK(status
)) {
4098 char addr
[INET6_ADDRSTRLEN
];
4099 /* Try and give an error message
4100 * saying what client failed. */
4101 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4102 "raw read failed (%s) for client %s. "
4103 "Terminating\n", nt_errstr(status
),
4104 get_peer_addr(req
->sconn
->sock
, addr
,
4106 exit_server_cleanly("secondary writebraw failed");
4109 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4110 if (nwritten
== -1) {
4112 reply_nterror(req
, map_nt_error_from_unix(errno
));
4113 error_to_writebrawerr(req
);
4117 if (nwritten
< (ssize_t
)numtowrite
) {
4118 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4119 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4123 total_written
+= nwritten
;
4128 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4130 status
= sync_file(conn
, fsp
, write_through
);
4131 if (!NT_STATUS_IS_OK(status
)) {
4132 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4133 fsp_str_dbg(fsp
), nt_errstr(status
)));
4134 reply_nterror(req
, status
);
4135 error_to_writebrawerr(req
);
4139 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4141 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
4142 (int)total_written
));
4144 if (!fsp
->print_file
) {
4145 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4148 /* We won't return a status if write through is not selected - this
4149 * follows what WfWg does */
4150 END_PROFILE(SMBwritebraw
);
4152 if (!write_through
&& total_written
==tcount
) {
4154 #if RABBIT_PELLET_FIX
4156 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4157 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4160 if (!send_keepalive(req
->sconn
->sock
)) {
4161 exit_server_cleanly("reply_writebraw: send of "
4162 "keepalive failed");
4165 TALLOC_FREE(req
->outbuf
);
4170 if (!fsp
->print_file
) {
4171 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4174 END_PROFILE(SMBwritebraw
);
4179 #define DBGC_CLASS DBGC_LOCKING
4181 /****************************************************************************
4182 Reply to a writeunlock (core+).
4183 ****************************************************************************/
4185 void reply_writeunlock(struct smb_request
*req
)
4187 connection_struct
*conn
= req
->conn
;
4188 ssize_t nwritten
= -1;
4192 NTSTATUS status
= NT_STATUS_OK
;
4194 struct lock_struct lock
;
4195 int saved_errno
= 0;
4197 START_PROFILE(SMBwriteunlock
);
4200 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4201 END_PROFILE(SMBwriteunlock
);
4205 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4207 if (!check_fsp(conn
, req
, fsp
)) {
4208 END_PROFILE(SMBwriteunlock
);
4212 if (!CHECK_WRITE(fsp
)) {
4213 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4214 END_PROFILE(SMBwriteunlock
);
4218 numtowrite
= SVAL(req
->vwv
+1, 0);
4219 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4220 data
= (const char *)req
->buf
+ 3;
4222 if (!fsp
->print_file
&& numtowrite
> 0) {
4223 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4224 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4227 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4228 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4229 END_PROFILE(SMBwriteunlock
);
4234 /* The special X/Open SMB protocol handling of
4235 zero length writes is *NOT* done for
4237 if(numtowrite
== 0) {
4240 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4241 saved_errno
= errno
;
4244 status
= sync_file(conn
, fsp
, False
/* write through */);
4245 if (!NT_STATUS_IS_OK(status
)) {
4246 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4247 fsp_str_dbg(fsp
), nt_errstr(status
)));
4248 reply_nterror(req
, status
);
4253 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4257 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4258 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4262 if (numtowrite
&& !fsp
->print_file
) {
4263 status
= do_unlock(req
->sconn
->msg_ctx
,
4265 (uint64_t)req
->smbpid
,
4266 (uint64_t)numtowrite
,
4270 if (NT_STATUS_V(status
)) {
4271 reply_nterror(req
, status
);
4276 reply_outbuf(req
, 1, 0);
4278 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4280 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4281 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4284 if (numtowrite
&& !fsp
->print_file
) {
4285 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4288 END_PROFILE(SMBwriteunlock
);
4293 #define DBGC_CLASS DBGC_ALL
4295 /****************************************************************************
4297 ****************************************************************************/
4299 void reply_write(struct smb_request
*req
)
4301 connection_struct
*conn
= req
->conn
;
4303 ssize_t nwritten
= -1;
4307 struct lock_struct lock
;
4309 int saved_errno
= 0;
4311 START_PROFILE(SMBwrite
);
4314 END_PROFILE(SMBwrite
);
4315 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4319 /* If it's an IPC, pass off the pipe handler. */
4321 reply_pipe_write(req
);
4322 END_PROFILE(SMBwrite
);
4326 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4328 if (!check_fsp(conn
, req
, fsp
)) {
4329 END_PROFILE(SMBwrite
);
4333 if (!CHECK_WRITE(fsp
)) {
4334 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4335 END_PROFILE(SMBwrite
);
4339 numtowrite
= SVAL(req
->vwv
+1, 0);
4340 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4341 data
= (const char *)req
->buf
+ 3;
4343 if (!fsp
->print_file
) {
4344 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4345 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4348 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4349 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4350 END_PROFILE(SMBwrite
);
4356 * X/Open SMB protocol says that if smb_vwv1 is
4357 * zero then the file size should be extended or
4358 * truncated to the size given in smb_vwv[2-3].
4361 if(numtowrite
== 0) {
4363 * This is actually an allocate call, and set EOF. JRA.
4365 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
4367 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4370 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
4372 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4375 trigger_write_time_update_immediate(fsp
);
4377 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4380 status
= sync_file(conn
, fsp
, False
);
4381 if (!NT_STATUS_IS_OK(status
)) {
4382 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4383 fsp_str_dbg(fsp
), nt_errstr(status
)));
4384 reply_nterror(req
, status
);
4389 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4393 if((nwritten
== 0) && (numtowrite
!= 0)) {
4394 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4398 reply_outbuf(req
, 1, 0);
4400 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4402 if (nwritten
< (ssize_t
)numtowrite
) {
4403 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4404 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4407 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4410 if (!fsp
->print_file
) {
4411 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4414 END_PROFILE(SMBwrite
);
4418 /****************************************************************************
4419 Ensure a buffer is a valid writeX for recvfile purposes.
4420 ****************************************************************************/
4422 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4423 (2*14) + /* word count (including bcc) */ \
4426 bool is_valid_writeX_buffer(struct smbd_server_connection
*sconn
,
4427 const uint8_t *inbuf
)
4430 connection_struct
*conn
= NULL
;
4431 unsigned int doff
= 0;
4432 size_t len
= smb_len_large(inbuf
);
4434 if (is_encrypted_packet(sconn
, inbuf
)) {
4435 /* Can't do this on encrypted
4440 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4444 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4445 CVAL(inbuf
,smb_wct
) != 14) {
4446 DEBUG(10,("is_valid_writeX_buffer: chained or "
4447 "invalid word length.\n"));
4451 conn
= conn_find(sconn
, SVAL(inbuf
, smb_tid
));
4453 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4457 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4460 if (IS_PRINT(conn
)) {
4461 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4464 doff
= SVAL(inbuf
,smb_vwv11
);
4466 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4468 if (len
> doff
&& len
- doff
> 0xFFFF) {
4469 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4472 if (numtowrite
== 0) {
4473 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4477 /* Ensure the sizes match up. */
4478 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4479 /* no pad byte...old smbclient :-( */
4480 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4482 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4486 if (len
- doff
!= numtowrite
) {
4487 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4488 "len = %u, doff = %u, numtowrite = %u\n",
4491 (unsigned int)numtowrite
));
4495 DEBUG(10,("is_valid_writeX_buffer: true "
4496 "len = %u, doff = %u, numtowrite = %u\n",
4499 (unsigned int)numtowrite
));
4504 /****************************************************************************
4505 Reply to a write and X.
4506 ****************************************************************************/
4508 void reply_write_and_X(struct smb_request
*req
)
4510 connection_struct
*conn
= req
->conn
;
4512 struct lock_struct lock
;
4517 unsigned int smb_doff
;
4518 unsigned int smblen
;
4521 int saved_errno
= 0;
4523 START_PROFILE(SMBwriteX
);
4525 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4526 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4527 END_PROFILE(SMBwriteX
);
4531 numtowrite
= SVAL(req
->vwv
+10, 0);
4532 smb_doff
= SVAL(req
->vwv
+11, 0);
4533 smblen
= smb_len(req
->inbuf
);
4535 if (req
->unread_bytes
> 0xFFFF ||
4536 (smblen
> smb_doff
&&
4537 smblen
- smb_doff
> 0xFFFF)) {
4538 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4541 if (req
->unread_bytes
) {
4542 /* Can't do a recvfile write on IPC$ */
4544 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4545 END_PROFILE(SMBwriteX
);
4548 if (numtowrite
!= req
->unread_bytes
) {
4549 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4550 END_PROFILE(SMBwriteX
);
4554 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4555 smb_doff
+ numtowrite
> smblen
) {
4556 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4557 END_PROFILE(SMBwriteX
);
4562 /* If it's an IPC, pass off the pipe handler. */
4564 if (req
->unread_bytes
) {
4565 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4566 END_PROFILE(SMBwriteX
);
4569 reply_pipe_write_and_X(req
);
4570 END_PROFILE(SMBwriteX
);
4574 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4575 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4576 write_through
= BITSETW(req
->vwv
+7,0);
4578 if (!check_fsp(conn
, req
, fsp
)) {
4579 END_PROFILE(SMBwriteX
);
4583 if (!CHECK_WRITE(fsp
)) {
4584 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4585 END_PROFILE(SMBwriteX
);
4589 data
= smb_base(req
->inbuf
) + smb_doff
;
4591 if(req
->wct
== 14) {
4592 #ifdef LARGE_SMB_OFF_T
4594 * This is a large offset (64 bit) write.
4596 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+12, 0)) << 32);
4598 #else /* !LARGE_SMB_OFF_T */
4601 * Ensure we haven't been sent a >32 bit offset.
4604 if(IVAL(req
->vwv
+12, 0) != 0) {
4605 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4606 "used and we don't support 64 bit offsets.\n",
4607 (unsigned int)IVAL(req
->vwv
+12, 0) ));
4608 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4609 END_PROFILE(SMBwriteX
);
4613 #endif /* LARGE_SMB_OFF_T */
4616 /* X/Open SMB protocol says that, unlike SMBwrite
4617 if the length is zero then NO truncation is
4618 done, just a write of zero. To truncate a file,
4621 if(numtowrite
== 0) {
4624 if (req
->unread_bytes
== 0) {
4625 status
= schedule_aio_write_and_X(conn
,
4632 if (NT_STATUS_IS_OK(status
)) {
4633 /* write scheduled - we're done. */
4636 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4637 /* Real error - report to client. */
4638 reply_nterror(req
, status
);
4641 /* NT_STATUS_RETRY - fall through to sync write. */
4644 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4645 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4648 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4649 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4653 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4654 saved_errno
= errno
;
4656 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4660 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4664 if((nwritten
== 0) && (numtowrite
!= 0)) {
4665 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4669 reply_outbuf(req
, 6, 0);
4670 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4671 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4673 if (nwritten
< (ssize_t
)numtowrite
) {
4674 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4675 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4678 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4679 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4681 status
= sync_file(conn
, fsp
, write_through
);
4682 if (!NT_STATUS_IS_OK(status
)) {
4683 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4684 fsp_str_dbg(fsp
), nt_errstr(status
)));
4685 reply_nterror(req
, status
);
4689 END_PROFILE(SMBwriteX
);
4694 END_PROFILE(SMBwriteX
);
4698 /****************************************************************************
4700 ****************************************************************************/
4702 void reply_lseek(struct smb_request
*req
)
4704 connection_struct
*conn
= req
->conn
;
4710 START_PROFILE(SMBlseek
);
4713 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4714 END_PROFILE(SMBlseek
);
4718 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4720 if (!check_fsp(conn
, req
, fsp
)) {
4724 flush_write_cache(fsp
, SEEK_FLUSH
);
4726 mode
= SVAL(req
->vwv
+1, 0) & 3;
4727 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4728 startpos
= (SMB_OFF_T
)IVALS(req
->vwv
+2, 0);
4737 res
= fsp
->fh
->pos
+ startpos
;
4748 if (umode
== SEEK_END
) {
4749 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4750 if(errno
== EINVAL
) {
4751 SMB_OFF_T current_pos
= startpos
;
4753 if(fsp_stat(fsp
) == -1) {
4755 map_nt_error_from_unix(errno
));
4756 END_PROFILE(SMBlseek
);
4760 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4762 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4767 reply_nterror(req
, map_nt_error_from_unix(errno
));
4768 END_PROFILE(SMBlseek
);
4775 reply_outbuf(req
, 2, 0);
4776 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4778 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4779 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4781 END_PROFILE(SMBlseek
);
4785 /****************************************************************************
4787 ****************************************************************************/
4789 void reply_flush(struct smb_request
*req
)
4791 connection_struct
*conn
= req
->conn
;
4795 START_PROFILE(SMBflush
);
4798 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4802 fnum
= SVAL(req
->vwv
+0, 0);
4803 fsp
= file_fsp(req
, fnum
);
4805 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4810 file_sync_all(conn
);
4812 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4813 if (!NT_STATUS_IS_OK(status
)) {
4814 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4815 fsp_str_dbg(fsp
), nt_errstr(status
)));
4816 reply_nterror(req
, status
);
4817 END_PROFILE(SMBflush
);
4822 reply_outbuf(req
, 0, 0);
4824 DEBUG(3,("flush\n"));
4825 END_PROFILE(SMBflush
);
4829 /****************************************************************************
4831 conn POINTER CAN BE NULL HERE !
4832 ****************************************************************************/
4834 void reply_exit(struct smb_request
*req
)
4836 START_PROFILE(SMBexit
);
4838 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
4840 reply_outbuf(req
, 0, 0);
4842 DEBUG(3,("exit\n"));
4844 END_PROFILE(SMBexit
);
4848 /****************************************************************************
4849 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4850 ****************************************************************************/
4852 void reply_close(struct smb_request
*req
)
4854 connection_struct
*conn
= req
->conn
;
4855 NTSTATUS status
= NT_STATUS_OK
;
4856 files_struct
*fsp
= NULL
;
4857 START_PROFILE(SMBclose
);
4860 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4861 END_PROFILE(SMBclose
);
4865 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4868 * We can only use check_fsp if we know it's not a directory.
4871 if (!check_fsp_open(conn
, req
, fsp
)) {
4872 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4873 END_PROFILE(SMBclose
);
4877 if(fsp
->is_directory
) {
4879 * Special case - close NT SMB directory handle.
4881 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4882 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4886 * Close ordinary file.
4889 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4890 fsp
->fh
->fd
, fsp
->fnum
,
4891 conn
->num_files_open
));
4894 * Take care of any time sent in the close.
4897 t
= srv_make_unix_date3(req
->vwv
+1);
4898 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4901 * close_file() returns the unix errno if an error
4902 * was detected on close - normally this is due to
4903 * a disk full error. If not then it was probably an I/O error.
4906 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4909 if (!NT_STATUS_IS_OK(status
)) {
4910 reply_nterror(req
, status
);
4911 END_PROFILE(SMBclose
);
4915 reply_outbuf(req
, 0, 0);
4916 END_PROFILE(SMBclose
);
4920 /****************************************************************************
4921 Reply to a writeclose (Core+ protocol).
4922 ****************************************************************************/
4924 void reply_writeclose(struct smb_request
*req
)
4926 connection_struct
*conn
= req
->conn
;
4928 ssize_t nwritten
= -1;
4929 NTSTATUS close_status
= NT_STATUS_OK
;
4932 struct timespec mtime
;
4934 struct lock_struct lock
;
4936 START_PROFILE(SMBwriteclose
);
4939 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4940 END_PROFILE(SMBwriteclose
);
4944 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4946 if (!check_fsp(conn
, req
, fsp
)) {
4947 END_PROFILE(SMBwriteclose
);
4950 if (!CHECK_WRITE(fsp
)) {
4951 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4952 END_PROFILE(SMBwriteclose
);
4956 numtowrite
= SVAL(req
->vwv
+1, 0);
4957 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4958 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4959 data
= (const char *)req
->buf
+ 1;
4961 if (!fsp
->print_file
) {
4962 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4963 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4966 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4967 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4968 END_PROFILE(SMBwriteclose
);
4973 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4975 set_close_write_time(fsp
, mtime
);
4978 * More insanity. W2K only closes the file if writelen > 0.
4983 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4984 "file %s\n", fsp_str_dbg(fsp
)));
4985 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4988 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4989 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4990 conn
->num_files_open
));
4992 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4993 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4997 if(!NT_STATUS_IS_OK(close_status
)) {
4998 reply_nterror(req
, close_status
);
5002 reply_outbuf(req
, 1, 0);
5004 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5007 if (numtowrite
&& !fsp
->print_file
) {
5008 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5011 END_PROFILE(SMBwriteclose
);
5016 #define DBGC_CLASS DBGC_LOCKING
5018 /****************************************************************************
5020 ****************************************************************************/
5022 void reply_lock(struct smb_request
*req
)
5024 connection_struct
*conn
= req
->conn
;
5025 uint64_t count
,offset
;
5028 struct byte_range_lock
*br_lck
= NULL
;
5030 START_PROFILE(SMBlock
);
5033 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5034 END_PROFILE(SMBlock
);
5038 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5040 if (!check_fsp(conn
, req
, fsp
)) {
5041 END_PROFILE(SMBlock
);
5045 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5046 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5048 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5049 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
5051 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5053 (uint64_t)req
->smbpid
,
5058 False
, /* Non-blocking lock. */
5063 TALLOC_FREE(br_lck
);
5065 if (NT_STATUS_V(status
)) {
5066 reply_nterror(req
, status
);
5067 END_PROFILE(SMBlock
);
5071 reply_outbuf(req
, 0, 0);
5073 END_PROFILE(SMBlock
);
5077 /****************************************************************************
5079 ****************************************************************************/
5081 void reply_unlock(struct smb_request
*req
)
5083 connection_struct
*conn
= req
->conn
;
5084 uint64_t count
,offset
;
5088 START_PROFILE(SMBunlock
);
5091 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5092 END_PROFILE(SMBunlock
);
5096 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5098 if (!check_fsp(conn
, req
, fsp
)) {
5099 END_PROFILE(SMBunlock
);
5103 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5104 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5106 status
= do_unlock(req
->sconn
->msg_ctx
,
5108 (uint64_t)req
->smbpid
,
5113 if (NT_STATUS_V(status
)) {
5114 reply_nterror(req
, status
);
5115 END_PROFILE(SMBunlock
);
5119 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5120 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
5122 reply_outbuf(req
, 0, 0);
5124 END_PROFILE(SMBunlock
);
5129 #define DBGC_CLASS DBGC_ALL
5131 /****************************************************************************
5133 conn POINTER CAN BE NULL HERE !
5134 ****************************************************************************/
5136 void reply_tdis(struct smb_request
*req
)
5138 connection_struct
*conn
= req
->conn
;
5139 START_PROFILE(SMBtdis
);
5142 DEBUG(4,("Invalid connection in tdis\n"));
5143 reply_nterror(req
, NT_STATUS_NETWORK_NAME_DELETED
);
5144 END_PROFILE(SMBtdis
);
5150 close_cnum(conn
,req
->vuid
);
5153 reply_outbuf(req
, 0, 0);
5154 END_PROFILE(SMBtdis
);
5158 /****************************************************************************
5160 conn POINTER CAN BE NULL HERE !
5161 ****************************************************************************/
5163 void reply_echo(struct smb_request
*req
)
5165 connection_struct
*conn
= req
->conn
;
5166 struct smb_perfcount_data local_pcd
;
5167 struct smb_perfcount_data
*cur_pcd
;
5171 START_PROFILE(SMBecho
);
5173 smb_init_perfcount_data(&local_pcd
);
5176 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5177 END_PROFILE(SMBecho
);
5181 smb_reverb
= SVAL(req
->vwv
+0, 0);
5183 reply_outbuf(req
, 1, req
->buflen
);
5185 /* copy any incoming data back out */
5186 if (req
->buflen
> 0) {
5187 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5190 if (smb_reverb
> 100) {
5191 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5195 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5197 /* this makes sure we catch the request pcd */
5198 if (seq_num
== smb_reverb
) {
5199 cur_pcd
= &req
->pcd
;
5201 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5202 cur_pcd
= &local_pcd
;
5205 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5207 show_msg((char *)req
->outbuf
);
5208 if (!srv_send_smb(req
->sconn
,
5209 (char *)req
->outbuf
,
5210 true, req
->seqnum
+1,
5211 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5213 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5216 DEBUG(3,("echo %d times\n", smb_reverb
));
5218 TALLOC_FREE(req
->outbuf
);
5220 END_PROFILE(SMBecho
);
5224 /****************************************************************************
5225 Reply to a printopen.
5226 ****************************************************************************/
5228 void reply_printopen(struct smb_request
*req
)
5230 connection_struct
*conn
= req
->conn
;
5234 START_PROFILE(SMBsplopen
);
5237 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5238 END_PROFILE(SMBsplopen
);
5242 if (!CAN_PRINT(conn
)) {
5243 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5244 END_PROFILE(SMBsplopen
);
5248 status
= file_new(req
, conn
, &fsp
);
5249 if(!NT_STATUS_IS_OK(status
)) {
5250 reply_nterror(req
, status
);
5251 END_PROFILE(SMBsplopen
);
5255 /* Open for exclusive use, write only. */
5256 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5258 if (!NT_STATUS_IS_OK(status
)) {
5259 file_free(req
, fsp
);
5260 reply_nterror(req
, status
);
5261 END_PROFILE(SMBsplopen
);
5265 reply_outbuf(req
, 1, 0);
5266 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5268 DEBUG(3,("openprint fd=%d fnum=%d\n",
5269 fsp
->fh
->fd
, fsp
->fnum
));
5271 END_PROFILE(SMBsplopen
);
5275 /****************************************************************************
5276 Reply to a printclose.
5277 ****************************************************************************/
5279 void reply_printclose(struct smb_request
*req
)
5281 connection_struct
*conn
= req
->conn
;
5285 START_PROFILE(SMBsplclose
);
5288 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5289 END_PROFILE(SMBsplclose
);
5293 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5295 if (!check_fsp(conn
, req
, fsp
)) {
5296 END_PROFILE(SMBsplclose
);
5300 if (!CAN_PRINT(conn
)) {
5301 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5302 END_PROFILE(SMBsplclose
);
5306 DEBUG(3,("printclose fd=%d fnum=%d\n",
5307 fsp
->fh
->fd
,fsp
->fnum
));
5309 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5311 if(!NT_STATUS_IS_OK(status
)) {
5312 reply_nterror(req
, status
);
5313 END_PROFILE(SMBsplclose
);
5317 reply_outbuf(req
, 0, 0);
5319 END_PROFILE(SMBsplclose
);
5323 /****************************************************************************
5324 Reply to a printqueue.
5325 ****************************************************************************/
5327 void reply_printqueue(struct smb_request
*req
)
5329 connection_struct
*conn
= req
->conn
;
5333 START_PROFILE(SMBsplretq
);
5336 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5337 END_PROFILE(SMBsplretq
);
5341 max_count
= SVAL(req
->vwv
+0, 0);
5342 start_index
= SVAL(req
->vwv
+1, 0);
5344 /* we used to allow the client to get the cnum wrong, but that
5345 is really quite gross and only worked when there was only
5346 one printer - I think we should now only accept it if they
5347 get it right (tridge) */
5348 if (!CAN_PRINT(conn
)) {
5349 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5350 END_PROFILE(SMBsplretq
);
5354 reply_outbuf(req
, 2, 3);
5355 SSVAL(req
->outbuf
,smb_vwv0
,0);
5356 SSVAL(req
->outbuf
,smb_vwv1
,0);
5357 SCVAL(smb_buf(req
->outbuf
),0,1);
5358 SSVAL(smb_buf(req
->outbuf
),1,0);
5360 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5361 start_index
, max_count
));
5364 TALLOC_CTX
*mem_ctx
= talloc_tos();
5367 const char *sharename
= lp_servicename(SNUM(conn
));
5368 struct rpc_pipe_client
*cli
= NULL
;
5369 struct dcerpc_binding_handle
*b
= NULL
;
5370 struct policy_handle handle
;
5371 struct spoolss_DevmodeContainer devmode_ctr
;
5372 union spoolss_JobInfo
*info
;
5374 uint32_t num_to_get
;
5378 ZERO_STRUCT(handle
);
5380 status
= rpc_pipe_open_interface(conn
,
5381 &ndr_table_spoolss
.syntax_id
,
5383 conn
->sconn
->remote_address
,
5384 conn
->sconn
->msg_ctx
,
5386 if (!NT_STATUS_IS_OK(status
)) {
5387 DEBUG(0, ("reply_printqueue: "
5388 "could not connect to spoolss: %s\n",
5389 nt_errstr(status
)));
5390 reply_nterror(req
, status
);
5393 b
= cli
->binding_handle
;
5395 ZERO_STRUCT(devmode_ctr
);
5397 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5400 SEC_FLAG_MAXIMUM_ALLOWED
,
5403 if (!NT_STATUS_IS_OK(status
)) {
5404 reply_nterror(req
, status
);
5407 if (!W_ERROR_IS_OK(werr
)) {
5408 reply_nterror(req
, werror_to_ntstatus(werr
));
5412 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5420 if (!W_ERROR_IS_OK(werr
)) {
5421 reply_nterror(req
, werror_to_ntstatus(werr
));
5425 if (max_count
> 0) {
5426 first
= start_index
;
5428 first
= start_index
+ max_count
+ 1;
5431 if (first
>= count
) {
5434 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5437 for (i
= first
; i
< num_to_get
; i
++) {
5440 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5442 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5443 info
[i
].info2
.job_id
);
5445 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5451 srv_put_dos_date2(p
, 0, qtime
);
5452 SCVAL(p
, 4, qstatus
);
5453 SSVAL(p
, 5, qrapjobid
);
5454 SIVAL(p
, 7, info
[i
].info2
.size
);
5456 srvstr_push(blob
, req
->flags2
, p
+12,
5457 info
[i
].info2
.notify_name
, 16, STR_ASCII
);
5459 if (message_push_blob(
5462 blob
, sizeof(blob
))) == -1) {
5463 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5469 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5470 SSVAL(req
->outbuf
,smb_vwv1
,
5471 (max_count
>0?first
+count
:first
-1));
5472 SCVAL(smb_buf(req
->outbuf
),0,1);
5473 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5477 DEBUG(3, ("%u entries returned in queue\n",
5481 if (b
&& is_valid_policy_hnd(&handle
)) {
5482 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5487 END_PROFILE(SMBsplretq
);
5491 /****************************************************************************
5492 Reply to a printwrite.
5493 ****************************************************************************/
5495 void reply_printwrite(struct smb_request
*req
)
5497 connection_struct
*conn
= req
->conn
;
5502 START_PROFILE(SMBsplwr
);
5505 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5506 END_PROFILE(SMBsplwr
);
5510 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5512 if (!check_fsp(conn
, req
, fsp
)) {
5513 END_PROFILE(SMBsplwr
);
5517 if (!fsp
->print_file
) {
5518 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5519 END_PROFILE(SMBsplwr
);
5523 if (!CHECK_WRITE(fsp
)) {
5524 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5525 END_PROFILE(SMBsplwr
);
5529 numtowrite
= SVAL(req
->buf
, 1);
5531 if (req
->buflen
< numtowrite
+ 3) {
5532 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5533 END_PROFILE(SMBsplwr
);
5537 data
= (const char *)req
->buf
+ 3;
5539 if (write_file(req
,fsp
,data
,(SMB_OFF_T
)-1,numtowrite
) != numtowrite
) {
5540 reply_nterror(req
, map_nt_error_from_unix(errno
));
5541 END_PROFILE(SMBsplwr
);
5545 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
5547 END_PROFILE(SMBsplwr
);
5551 /****************************************************************************
5553 ****************************************************************************/
5555 void reply_mkdir(struct smb_request
*req
)
5557 connection_struct
*conn
= req
->conn
;
5558 struct smb_filename
*smb_dname
= NULL
;
5559 char *directory
= NULL
;
5561 TALLOC_CTX
*ctx
= talloc_tos();
5563 START_PROFILE(SMBmkdir
);
5565 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5566 STR_TERMINATE
, &status
);
5567 if (!NT_STATUS_IS_OK(status
)) {
5568 reply_nterror(req
, status
);
5572 status
= filename_convert(ctx
, conn
,
5573 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5578 if (!NT_STATUS_IS_OK(status
)) {
5579 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5580 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5581 ERRSRV
, ERRbadpath
);
5584 reply_nterror(req
, status
);
5588 status
= create_directory(conn
, req
, smb_dname
);
5590 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5592 if (!NT_STATUS_IS_OK(status
)) {
5594 if (!use_nt_status()
5595 && NT_STATUS_EQUAL(status
,
5596 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5598 * Yes, in the DOS error code case we get a
5599 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5600 * samba4 torture test.
5602 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5605 reply_nterror(req
, status
);
5609 reply_outbuf(req
, 0, 0);
5611 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5613 TALLOC_FREE(smb_dname
);
5614 END_PROFILE(SMBmkdir
);
5618 /****************************************************************************
5620 ****************************************************************************/
5622 void reply_rmdir(struct smb_request
*req
)
5624 connection_struct
*conn
= req
->conn
;
5625 struct smb_filename
*smb_dname
= NULL
;
5626 char *directory
= NULL
;
5628 TALLOC_CTX
*ctx
= talloc_tos();
5629 files_struct
*fsp
= NULL
;
5631 struct smbd_server_connection
*sconn
= req
->sconn
;
5633 START_PROFILE(SMBrmdir
);
5635 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5636 STR_TERMINATE
, &status
);
5637 if (!NT_STATUS_IS_OK(status
)) {
5638 reply_nterror(req
, status
);
5642 status
= filename_convert(ctx
, conn
,
5643 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5648 if (!NT_STATUS_IS_OK(status
)) {
5649 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5650 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5651 ERRSRV
, ERRbadpath
);
5654 reply_nterror(req
, status
);
5658 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5659 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5663 status
= SMB_VFS_CREATE_FILE(
5666 0, /* root_dir_fid */
5667 smb_dname
, /* fname */
5668 DELETE_ACCESS
, /* access_mask */
5669 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5671 FILE_OPEN
, /* create_disposition*/
5672 FILE_DIRECTORY_FILE
, /* create_options */
5673 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5674 0, /* oplock_request */
5675 0, /* allocation_size */
5676 0, /* private_flags */
5682 if (!NT_STATUS_IS_OK(status
)) {
5683 if (open_was_deferred(req
->sconn
, req
->mid
)) {
5684 /* We have re-scheduled this call. */
5687 reply_nterror(req
, status
);
5691 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5692 if (!NT_STATUS_IS_OK(status
)) {
5693 close_file(req
, fsp
, ERROR_CLOSE
);
5694 reply_nterror(req
, status
);
5698 if (!set_delete_on_close(fsp
, true, conn
->session_info
->unix_token
)) {
5699 close_file(req
, fsp
, ERROR_CLOSE
);
5700 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5704 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5705 if (!NT_STATUS_IS_OK(status
)) {
5706 reply_nterror(req
, status
);
5708 reply_outbuf(req
, 0, 0);
5711 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5713 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5715 TALLOC_FREE(smb_dname
);
5716 END_PROFILE(SMBrmdir
);
5720 /*******************************************************************
5721 Resolve wildcards in a filename rename.
5722 ********************************************************************/
5724 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5729 char *name2_copy
= NULL
;
5734 char *p
,*p2
, *pname1
, *pname2
;
5736 name2_copy
= talloc_strdup(ctx
, name2
);
5741 pname1
= strrchr_m(name1
,'/');
5742 pname2
= strrchr_m(name2_copy
,'/');
5744 if (!pname1
|| !pname2
) {
5748 /* Truncate the copy of name2 at the last '/' */
5751 /* Now go past the '/' */
5755 root1
= talloc_strdup(ctx
, pname1
);
5756 root2
= talloc_strdup(ctx
, pname2
);
5758 if (!root1
|| !root2
) {
5762 p
= strrchr_m(root1
,'.');
5765 ext1
= talloc_strdup(ctx
, p
+1);
5767 ext1
= talloc_strdup(ctx
, "");
5769 p
= strrchr_m(root2
,'.');
5772 ext2
= talloc_strdup(ctx
, p
+1);
5774 ext2
= talloc_strdup(ctx
, "");
5777 if (!ext1
|| !ext2
) {
5785 /* Hmmm. Should this be mb-aware ? */
5788 } else if (*p2
== '*') {
5790 root2
= talloc_asprintf(ctx
, "%s%s",
5809 /* Hmmm. Should this be mb-aware ? */
5812 } else if (*p2
== '*') {
5814 ext2
= talloc_asprintf(ctx
, "%s%s",
5830 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5835 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5847 /****************************************************************************
5848 Ensure open files have their names updated. Updated to notify other smbd's
5850 ****************************************************************************/
5852 static void rename_open_files(connection_struct
*conn
,
5853 struct share_mode_lock
*lck
,
5854 uint32_t orig_name_hash
,
5855 const struct smb_filename
*smb_fname_dst
)
5858 bool did_rename
= False
;
5860 uint32_t new_name_hash
= 0;
5862 for(fsp
= file_find_di_first(conn
->sconn
, lck
->id
); fsp
;
5863 fsp
= file_find_di_next(fsp
)) {
5864 /* fsp_name is a relative path under the fsp. To change this for other
5865 sharepaths we need to manipulate relative paths. */
5866 /* TODO - create the absolute path and manipulate the newname
5867 relative to the sharepath. */
5868 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5871 if (fsp
->name_hash
!= orig_name_hash
) {
5874 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5875 "(file_id %s) from %s -> %s\n", fsp
->fnum
,
5876 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
5877 smb_fname_str_dbg(smb_fname_dst
)));
5879 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
5880 if (NT_STATUS_IS_OK(status
)) {
5882 new_name_hash
= fsp
->name_hash
;
5887 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5888 "for %s\n", file_id_string_tos(&lck
->id
),
5889 smb_fname_str_dbg(smb_fname_dst
)));
5892 /* Send messages to all smbd's (not ourself) that the name has changed. */
5893 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, conn
->connectpath
,
5894 orig_name_hash
, new_name_hash
,
5899 /****************************************************************************
5900 We need to check if the source path is a parent directory of the destination
5901 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5902 refuse the rename with a sharing violation. Under UNIX the above call can
5903 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5904 probably need to check that the client is a Windows one before disallowing
5905 this as a UNIX client (one with UNIX extensions) can know the source is a
5906 symlink and make this decision intelligently. Found by an excellent bug
5907 report from <AndyLiebman@aol.com>.
5908 ****************************************************************************/
5910 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
5911 const struct smb_filename
*smb_fname_dst
)
5913 const char *psrc
= smb_fname_src
->base_name
;
5914 const char *pdst
= smb_fname_dst
->base_name
;
5917 if (psrc
[0] == '.' && psrc
[1] == '/') {
5920 if (pdst
[0] == '.' && pdst
[1] == '/') {
5923 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5926 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5930 * Do the notify calls from a rename
5933 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5934 const struct smb_filename
*smb_fname_src
,
5935 const struct smb_filename
*smb_fname_dst
)
5937 char *parent_dir_src
= NULL
;
5938 char *parent_dir_dst
= NULL
;
5941 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5942 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5944 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
5945 &parent_dir_src
, NULL
) ||
5946 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
5947 &parent_dir_dst
, NULL
)) {
5951 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
5952 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
5953 smb_fname_src
->base_name
);
5954 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
5955 smb_fname_dst
->base_name
);
5958 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
5959 smb_fname_src
->base_name
);
5960 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
5961 smb_fname_dst
->base_name
);
5964 /* this is a strange one. w2k3 gives an additional event for
5965 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5966 files, but not directories */
5968 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5969 FILE_NOTIFY_CHANGE_ATTRIBUTES
5970 |FILE_NOTIFY_CHANGE_CREATION
,
5971 smb_fname_dst
->base_name
);
5974 TALLOC_FREE(parent_dir_src
);
5975 TALLOC_FREE(parent_dir_dst
);
5978 /****************************************************************************
5979 Returns an error if the parent directory for a filename is open in an
5981 ****************************************************************************/
5983 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
5984 const struct smb_filename
*smb_fname_dst_in
)
5986 char *parent_dir
= NULL
;
5987 struct smb_filename smb_fname_parent
;
5989 files_struct
*fsp
= NULL
;
5992 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
5993 &parent_dir
, NULL
)) {
5994 return NT_STATUS_NO_MEMORY
;
5996 ZERO_STRUCT(smb_fname_parent
);
5997 smb_fname_parent
.base_name
= parent_dir
;
5999 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6001 return map_nt_error_from_unix(errno
);
6005 * We're only checking on this smbd here, mostly good
6006 * enough.. and will pass tests.
6009 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6010 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6011 fsp
= file_find_di_next(fsp
)) {
6012 if (fsp
->access_mask
& DELETE_ACCESS
) {
6013 return NT_STATUS_SHARING_VIOLATION
;
6016 return NT_STATUS_OK
;
6019 /****************************************************************************
6020 Rename an open file - given an fsp.
6021 ****************************************************************************/
6023 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6025 const struct smb_filename
*smb_fname_dst_in
,
6027 bool replace_if_exists
)
6029 TALLOC_CTX
*ctx
= talloc_tos();
6030 struct smb_filename
*smb_fname_dst
= NULL
;
6031 NTSTATUS status
= NT_STATUS_OK
;
6032 struct share_mode_lock
*lck
= NULL
;
6033 bool dst_exists
, old_is_stream
, new_is_stream
;
6035 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6036 if (!NT_STATUS_IS_OK(status
)) {
6040 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6041 if (!NT_STATUS_IS_OK(status
)) {
6045 /* Make a copy of the dst smb_fname structs */
6047 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
6048 if (!NT_STATUS_IS_OK(status
)) {
6053 * Check for special case with case preserving and not
6054 * case sensitive. If the old last component differs from the original
6055 * last component only by case, then we should allow
6056 * the rename (user is trying to change the case of the
6059 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
6060 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6061 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6063 char *fname_dst_lcomp_base_mod
= NULL
;
6064 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
6067 * Get the last component of the destination name.
6069 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
6071 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
6073 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, smb_fname_dst
->base_name
);
6075 if (!fname_dst_lcomp_base_mod
) {
6076 status
= NT_STATUS_NO_MEMORY
;
6081 * Create an smb_filename struct using the original last
6082 * component of the destination.
6084 status
= create_synthetic_smb_fname_split(ctx
,
6085 smb_fname_dst
->original_lcomp
, NULL
,
6086 &smb_fname_orig_lcomp
);
6087 if (!NT_STATUS_IS_OK(status
)) {
6088 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6092 /* If the base names only differ by case, use original. */
6093 if(!strcsequal(fname_dst_lcomp_base_mod
,
6094 smb_fname_orig_lcomp
->base_name
)) {
6097 * Replace the modified last component with the
6101 *last_slash
= '\0'; /* Truncate at the '/' */
6102 tmp
= talloc_asprintf(smb_fname_dst
,
6104 smb_fname_dst
->base_name
,
6105 smb_fname_orig_lcomp
->base_name
);
6107 tmp
= talloc_asprintf(smb_fname_dst
,
6109 smb_fname_orig_lcomp
->base_name
);
6112 status
= NT_STATUS_NO_MEMORY
;
6113 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6114 TALLOC_FREE(smb_fname_orig_lcomp
);
6117 TALLOC_FREE(smb_fname_dst
->base_name
);
6118 smb_fname_dst
->base_name
= tmp
;
6121 /* If the stream_names only differ by case, use original. */
6122 if(!strcsequal(smb_fname_dst
->stream_name
,
6123 smb_fname_orig_lcomp
->stream_name
)) {
6125 /* Use the original stream. */
6126 tmp
= talloc_strdup(smb_fname_dst
,
6127 smb_fname_orig_lcomp
->stream_name
);
6129 status
= NT_STATUS_NO_MEMORY
;
6130 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6131 TALLOC_FREE(smb_fname_orig_lcomp
);
6134 TALLOC_FREE(smb_fname_dst
->stream_name
);
6135 smb_fname_dst
->stream_name
= tmp
;
6137 TALLOC_FREE(fname_dst_lcomp_base_mod
);
6138 TALLOC_FREE(smb_fname_orig_lcomp
);
6142 * If the src and dest names are identical - including case,
6143 * don't do the rename, just return success.
6146 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6147 strcsequal(fsp
->fsp_name
->stream_name
,
6148 smb_fname_dst
->stream_name
)) {
6149 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6150 "- returning success\n",
6151 smb_fname_str_dbg(smb_fname_dst
)));
6152 status
= NT_STATUS_OK
;
6156 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6157 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6159 /* Return the correct error code if both names aren't streams. */
6160 if (!old_is_stream
&& new_is_stream
) {
6161 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6165 if (old_is_stream
&& !new_is_stream
) {
6166 status
= NT_STATUS_INVALID_PARAMETER
;
6170 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6172 if(!replace_if_exists
&& dst_exists
) {
6173 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6174 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6175 smb_fname_str_dbg(smb_fname_dst
)));
6176 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6181 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6182 &smb_fname_dst
->st
);
6183 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6185 /* The file can be open when renaming a stream */
6186 if (dst_fsp
&& !new_is_stream
) {
6187 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6188 status
= NT_STATUS_ACCESS_DENIED
;
6193 /* Ensure we have a valid stat struct for the source. */
6194 status
= vfs_stat_fsp(fsp
);
6195 if (!NT_STATUS_IS_OK(status
)) {
6199 status
= can_rename(conn
, fsp
, attrs
);
6201 if (!NT_STATUS_IS_OK(status
)) {
6202 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6203 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6204 smb_fname_str_dbg(smb_fname_dst
)));
6205 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6206 status
= NT_STATUS_ACCESS_DENIED
;
6210 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6211 status
= NT_STATUS_ACCESS_DENIED
;
6214 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6218 * We have the file open ourselves, so not being able to get the
6219 * corresponding share mode lock is a fatal error.
6222 SMB_ASSERT(lck
!= NULL
);
6224 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6225 uint32 create_options
= fsp
->fh
->private_options
;
6227 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6228 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6229 smb_fname_str_dbg(smb_fname_dst
)));
6231 if (!lp_posix_pathnames() &&
6232 (lp_map_archive(SNUM(conn
)) ||
6233 lp_store_dos_attributes(SNUM(conn
)))) {
6234 /* We must set the archive bit on the newly
6236 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6237 uint32_t old_dosmode
= dos_mode(conn
,
6239 file_set_dosmode(conn
,
6241 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6247 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6250 rename_open_files(conn
, lck
, fsp
->name_hash
, smb_fname_dst
);
6253 * A rename acts as a new file create w.r.t. allowing an initial delete
6254 * on close, probably because in Windows there is a new handle to the
6255 * new file. If initial delete on close was requested but not
6256 * originally set, we need to set it here. This is probably not 100% correct,
6257 * but will work for the CIFSFS client which in non-posix mode
6258 * depends on these semantics. JRA.
6261 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6262 status
= can_set_delete_on_close(fsp
, 0);
6264 if (NT_STATUS_IS_OK(status
)) {
6265 /* Note that here we set the *inital* delete on close flag,
6266 * not the regular one. The magic gets handled in close. */
6267 fsp
->initial_delete_on_close
= True
;
6271 status
= NT_STATUS_OK
;
6277 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6278 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6280 status
= map_nt_error_from_unix(errno
);
6283 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6284 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6285 smb_fname_str_dbg(smb_fname_dst
)));
6288 TALLOC_FREE(smb_fname_dst
);
6293 /****************************************************************************
6294 The guts of the rename command, split out so it may be called by the NT SMB
6296 ****************************************************************************/
6298 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6299 connection_struct
*conn
,
6300 struct smb_request
*req
,
6301 struct smb_filename
*smb_fname_src
,
6302 struct smb_filename
*smb_fname_dst
,
6304 bool replace_if_exists
,
6307 uint32_t access_mask
)
6309 char *fname_src_dir
= NULL
;
6310 char *fname_src_mask
= NULL
;
6312 NTSTATUS status
= NT_STATUS_OK
;
6313 struct smb_Dir
*dir_hnd
= NULL
;
6314 const char *dname
= NULL
;
6315 char *talloced
= NULL
;
6317 int create_options
= 0;
6318 bool posix_pathnames
= lp_posix_pathnames();
6321 * Split the old name into directory and last component
6322 * strings. Note that unix_convert may have stripped off a
6323 * leading ./ from both name and newname if the rename is
6324 * at the root of the share. We need to make sure either both
6325 * name and newname contain a / character or neither of them do
6326 * as this is checked in resolve_wildcards().
6329 /* Split up the directory from the filename/mask. */
6330 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6331 &fname_src_dir
, &fname_src_mask
);
6332 if (!NT_STATUS_IS_OK(status
)) {
6333 status
= NT_STATUS_NO_MEMORY
;
6338 * We should only check the mangled cache
6339 * here if unix_convert failed. This means
6340 * that the path in 'mask' doesn't exist
6341 * on the file system and so we need to look
6342 * for a possible mangle. This patch from
6343 * Tine Smukavec <valentin.smukavec@hermes.si>.
6346 if (!VALID_STAT(smb_fname_src
->st
) &&
6347 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6348 char *new_mask
= NULL
;
6349 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6352 TALLOC_FREE(fname_src_mask
);
6353 fname_src_mask
= new_mask
;
6357 if (!src_has_wild
) {
6361 * Only one file needs to be renamed. Append the mask back
6362 * onto the directory.
6364 TALLOC_FREE(smb_fname_src
->base_name
);
6365 if (ISDOT(fname_src_dir
)) {
6366 /* Ensure we use canonical names on open. */
6367 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6371 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6376 if (!smb_fname_src
->base_name
) {
6377 status
= NT_STATUS_NO_MEMORY
;
6381 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6382 "case_preserve = %d, short case preserve = %d, "
6383 "directory = %s, newname = %s, "
6384 "last_component_dest = %s\n",
6385 conn
->case_sensitive
, conn
->case_preserve
,
6386 conn
->short_case_preserve
,
6387 smb_fname_str_dbg(smb_fname_src
),
6388 smb_fname_str_dbg(smb_fname_dst
),
6389 smb_fname_dst
->original_lcomp
));
6391 /* The dest name still may have wildcards. */
6392 if (dest_has_wild
) {
6393 char *fname_dst_mod
= NULL
;
6394 if (!resolve_wildcards(smb_fname_dst
,
6395 smb_fname_src
->base_name
,
6396 smb_fname_dst
->base_name
,
6398 DEBUG(6, ("rename_internals: resolve_wildcards "
6400 smb_fname_src
->base_name
,
6401 smb_fname_dst
->base_name
));
6402 status
= NT_STATUS_NO_MEMORY
;
6405 TALLOC_FREE(smb_fname_dst
->base_name
);
6406 smb_fname_dst
->base_name
= fname_dst_mod
;
6409 ZERO_STRUCT(smb_fname_src
->st
);
6410 if (posix_pathnames
) {
6411 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6413 SMB_VFS_STAT(conn
, smb_fname_src
);
6416 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6417 create_options
|= FILE_DIRECTORY_FILE
;
6420 status
= SMB_VFS_CREATE_FILE(
6423 0, /* root_dir_fid */
6424 smb_fname_src
, /* fname */
6425 access_mask
, /* access_mask */
6426 (FILE_SHARE_READ
| /* share_access */
6428 FILE_OPEN
, /* create_disposition*/
6429 create_options
, /* create_options */
6430 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6431 0, /* oplock_request */
6432 0, /* allocation_size */
6433 0, /* private_flags */
6439 if (!NT_STATUS_IS_OK(status
)) {
6440 DEBUG(3, ("Could not open rename source %s: %s\n",
6441 smb_fname_str_dbg(smb_fname_src
),
6442 nt_errstr(status
)));
6446 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6447 attrs
, replace_if_exists
);
6449 close_file(req
, fsp
, NORMAL_CLOSE
);
6451 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6452 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6453 smb_fname_str_dbg(smb_fname_dst
)));
6459 * Wildcards - process each file that matches.
6461 if (strequal(fname_src_mask
, "????????.???")) {
6462 TALLOC_FREE(fname_src_mask
);
6463 fname_src_mask
= talloc_strdup(ctx
, "*");
6464 if (!fname_src_mask
) {
6465 status
= NT_STATUS_NO_MEMORY
;
6470 status
= check_name(conn
, fname_src_dir
);
6471 if (!NT_STATUS_IS_OK(status
)) {
6475 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6477 if (dir_hnd
== NULL
) {
6478 status
= map_nt_error_from_unix(errno
);
6482 status
= NT_STATUS_NO_SUCH_FILE
;
6484 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6485 * - gentest fix. JRA
6488 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
6490 files_struct
*fsp
= NULL
;
6491 char *destname
= NULL
;
6492 bool sysdir_entry
= False
;
6494 /* Quick check for "." and ".." */
6495 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6496 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
6497 sysdir_entry
= True
;
6499 TALLOC_FREE(talloced
);
6504 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6505 &smb_fname_src
->st
, false)) {
6506 TALLOC_FREE(talloced
);
6510 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6511 TALLOC_FREE(talloced
);
6516 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6520 TALLOC_FREE(smb_fname_src
->base_name
);
6521 if (ISDOT(fname_src_dir
)) {
6522 /* Ensure we use canonical names on open. */
6523 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6527 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6532 if (!smb_fname_src
->base_name
) {
6533 status
= NT_STATUS_NO_MEMORY
;
6537 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6538 smb_fname_dst
->base_name
,
6540 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6541 smb_fname_src
->base_name
, destname
));
6542 TALLOC_FREE(talloced
);
6546 status
= NT_STATUS_NO_MEMORY
;
6550 TALLOC_FREE(smb_fname_dst
->base_name
);
6551 smb_fname_dst
->base_name
= destname
;
6553 ZERO_STRUCT(smb_fname_src
->st
);
6554 if (posix_pathnames
) {
6555 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6557 SMB_VFS_STAT(conn
, smb_fname_src
);
6562 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6563 create_options
|= FILE_DIRECTORY_FILE
;
6566 status
= SMB_VFS_CREATE_FILE(
6569 0, /* root_dir_fid */
6570 smb_fname_src
, /* fname */
6571 access_mask
, /* access_mask */
6572 (FILE_SHARE_READ
| /* share_access */
6574 FILE_OPEN
, /* create_disposition*/
6575 create_options
, /* create_options */
6576 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6577 0, /* oplock_request */
6578 0, /* allocation_size */
6579 0, /* private_flags */
6585 if (!NT_STATUS_IS_OK(status
)) {
6586 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6587 "returned %s rename %s -> %s\n",
6589 smb_fname_str_dbg(smb_fname_src
),
6590 smb_fname_str_dbg(smb_fname_dst
)));
6594 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6596 if (!smb_fname_dst
->original_lcomp
) {
6597 status
= NT_STATUS_NO_MEMORY
;
6601 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6602 attrs
, replace_if_exists
);
6604 close_file(req
, fsp
, NORMAL_CLOSE
);
6606 if (!NT_STATUS_IS_OK(status
)) {
6607 DEBUG(3, ("rename_internals_fsp returned %s for "
6608 "rename %s -> %s\n", nt_errstr(status
),
6609 smb_fname_str_dbg(smb_fname_src
),
6610 smb_fname_str_dbg(smb_fname_dst
)));
6616 DEBUG(3,("rename_internals: doing rename on %s -> "
6617 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6618 smb_fname_str_dbg(smb_fname_src
)));
6619 TALLOC_FREE(talloced
);
6621 TALLOC_FREE(dir_hnd
);
6623 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6624 status
= map_nt_error_from_unix(errno
);
6628 TALLOC_FREE(talloced
);
6629 TALLOC_FREE(fname_src_dir
);
6630 TALLOC_FREE(fname_src_mask
);
6634 /****************************************************************************
6636 ****************************************************************************/
6638 void reply_mv(struct smb_request
*req
)
6640 connection_struct
*conn
= req
->conn
;
6642 char *newname
= NULL
;
6646 bool src_has_wcard
= False
;
6647 bool dest_has_wcard
= False
;
6648 TALLOC_CTX
*ctx
= talloc_tos();
6649 struct smb_filename
*smb_fname_src
= NULL
;
6650 struct smb_filename
*smb_fname_dst
= NULL
;
6651 bool stream_rename
= false;
6653 START_PROFILE(SMBmv
);
6656 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6660 attrs
= SVAL(req
->vwv
+0, 0);
6662 p
= (const char *)req
->buf
+ 1;
6663 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6664 &status
, &src_has_wcard
);
6665 if (!NT_STATUS_IS_OK(status
)) {
6666 reply_nterror(req
, status
);
6670 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6671 &status
, &dest_has_wcard
);
6672 if (!NT_STATUS_IS_OK(status
)) {
6673 reply_nterror(req
, status
);
6677 if (!lp_posix_pathnames()) {
6678 /* The newname must begin with a ':' if the
6679 name contains a ':'. */
6680 if (strchr_m(name
, ':')) {
6681 if (newname
[0] != ':') {
6682 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6685 stream_rename
= true;
6689 status
= filename_convert(ctx
,
6691 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6693 UCF_COND_ALLOW_WCARD_LCOMP
,
6697 if (!NT_STATUS_IS_OK(status
)) {
6698 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6699 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6700 ERRSRV
, ERRbadpath
);
6703 reply_nterror(req
, status
);
6707 status
= filename_convert(ctx
,
6709 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6711 UCF_COND_ALLOW_WCARD_LCOMP
| UCF_SAVE_LCOMP
,
6715 if (!NT_STATUS_IS_OK(status
)) {
6716 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6717 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6718 ERRSRV
, ERRbadpath
);
6721 reply_nterror(req
, status
);
6725 if (stream_rename
) {
6726 /* smb_fname_dst->base_name must be the same as
6727 smb_fname_src->base_name. */
6728 TALLOC_FREE(smb_fname_dst
->base_name
);
6729 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6730 smb_fname_src
->base_name
);
6731 if (!smb_fname_dst
->base_name
) {
6732 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6737 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6738 smb_fname_str_dbg(smb_fname_dst
)));
6740 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
6741 attrs
, False
, src_has_wcard
, dest_has_wcard
,
6743 if (!NT_STATUS_IS_OK(status
)) {
6744 if (open_was_deferred(req
->sconn
, req
->mid
)) {
6745 /* We have re-scheduled this call. */
6748 reply_nterror(req
, status
);
6752 reply_outbuf(req
, 0, 0);
6754 TALLOC_FREE(smb_fname_src
);
6755 TALLOC_FREE(smb_fname_dst
);
6760 /*******************************************************************
6761 Copy a file as part of a reply_copy.
6762 ******************************************************************/
6765 * TODO: check error codes on all callers
6768 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6769 connection_struct
*conn
,
6770 struct smb_filename
*smb_fname_src
,
6771 struct smb_filename
*smb_fname_dst
,
6774 bool target_is_directory
)
6776 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
6778 files_struct
*fsp1
,*fsp2
;
6780 uint32 new_create_disposition
;
6784 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
6785 if (!NT_STATUS_IS_OK(status
)) {
6790 * If the target is a directory, extract the last component from the
6791 * src filename and append it to the dst filename
6793 if (target_is_directory
) {
6796 /* dest/target can't be a stream if it's a directory. */
6797 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
6799 p
= strrchr_m(smb_fname_src
->base_name
,'/');
6803 p
= smb_fname_src
->base_name
;
6805 smb_fname_dst_tmp
->base_name
=
6806 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
6808 if (!smb_fname_dst_tmp
->base_name
) {
6809 status
= NT_STATUS_NO_MEMORY
;
6814 status
= vfs_file_exist(conn
, smb_fname_src
);
6815 if (!NT_STATUS_IS_OK(status
)) {
6819 if (!target_is_directory
&& count
) {
6820 new_create_disposition
= FILE_OPEN
;
6822 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
6825 &new_create_disposition
,
6828 status
= NT_STATUS_INVALID_PARAMETER
;
6833 /* Open the src file for reading. */
6834 status
= SMB_VFS_CREATE_FILE(
6837 0, /* root_dir_fid */
6838 smb_fname_src
, /* fname */
6839 FILE_GENERIC_READ
, /* access_mask */
6840 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6841 FILE_OPEN
, /* create_disposition*/
6842 0, /* create_options */
6843 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6844 INTERNAL_OPEN_ONLY
, /* oplock_request */
6845 0, /* allocation_size */
6846 0, /* private_flags */
6852 if (!NT_STATUS_IS_OK(status
)) {
6856 dosattrs
= dos_mode(conn
, smb_fname_src
);
6858 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
6859 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
6862 /* Open the dst file for writing. */
6863 status
= SMB_VFS_CREATE_FILE(
6866 0, /* root_dir_fid */
6867 smb_fname_dst
, /* fname */
6868 FILE_GENERIC_WRITE
, /* access_mask */
6869 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6870 new_create_disposition
, /* create_disposition*/
6871 0, /* create_options */
6872 dosattrs
, /* file_attributes */
6873 INTERNAL_OPEN_ONLY
, /* oplock_request */
6874 0, /* allocation_size */
6875 0, /* private_flags */
6881 if (!NT_STATUS_IS_OK(status
)) {
6882 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6886 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
6887 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
6889 DEBUG(0, ("error - vfs lseek returned error %s\n",
6891 status
= map_nt_error_from_unix(errno
);
6892 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6893 close_file(NULL
, fsp2
, ERROR_CLOSE
);
6898 /* Do the actual copy. */
6899 if (smb_fname_src
->st
.st_ex_size
) {
6900 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
6905 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
6907 /* Ensure the modtime is set correctly on the destination file. */
6908 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
6911 * As we are opening fsp1 read-only we only expect
6912 * an error on close on fsp2 if we are out of space.
6913 * Thus we don't look at the error return from the
6916 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
6918 if (!NT_STATUS_IS_OK(status
)) {
6922 if (ret
!= (SMB_OFF_T
)smb_fname_src
->st
.st_ex_size
) {
6923 status
= NT_STATUS_DISK_FULL
;
6927 status
= NT_STATUS_OK
;
6930 TALLOC_FREE(smb_fname_dst_tmp
);
6934 /****************************************************************************
6935 Reply to a file copy.
6936 ****************************************************************************/
6938 void reply_copy(struct smb_request
*req
)
6940 connection_struct
*conn
= req
->conn
;
6941 struct smb_filename
*smb_fname_src
= NULL
;
6942 struct smb_filename
*smb_fname_dst
= NULL
;
6943 char *fname_src
= NULL
;
6944 char *fname_dst
= NULL
;
6945 char *fname_src_mask
= NULL
;
6946 char *fname_src_dir
= NULL
;
6949 int error
= ERRnoaccess
;
6953 bool target_is_directory
=False
;
6954 bool source_has_wild
= False
;
6955 bool dest_has_wild
= False
;
6957 TALLOC_CTX
*ctx
= talloc_tos();
6959 START_PROFILE(SMBcopy
);
6962 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6966 tid2
= SVAL(req
->vwv
+0, 0);
6967 ofun
= SVAL(req
->vwv
+1, 0);
6968 flags
= SVAL(req
->vwv
+2, 0);
6970 p
= (const char *)req
->buf
;
6971 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
6972 &status
, &source_has_wild
);
6973 if (!NT_STATUS_IS_OK(status
)) {
6974 reply_nterror(req
, status
);
6977 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
6978 &status
, &dest_has_wild
);
6979 if (!NT_STATUS_IS_OK(status
)) {
6980 reply_nterror(req
, status
);
6984 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
6986 if (tid2
!= conn
->cnum
) {
6987 /* can't currently handle inter share copies XXXX */
6988 DEBUG(3,("Rejecting inter-share copy\n"));
6989 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
6993 status
= filename_convert(ctx
, conn
,
6994 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6996 UCF_COND_ALLOW_WCARD_LCOMP
,
6999 if (!NT_STATUS_IS_OK(status
)) {
7000 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7001 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7002 ERRSRV
, ERRbadpath
);
7005 reply_nterror(req
, status
);
7009 status
= filename_convert(ctx
, conn
,
7010 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7012 UCF_COND_ALLOW_WCARD_LCOMP
,
7015 if (!NT_STATUS_IS_OK(status
)) {
7016 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7017 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7018 ERRSRV
, ERRbadpath
);
7021 reply_nterror(req
, status
);
7025 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7027 if ((flags
&1) && target_is_directory
) {
7028 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7032 if ((flags
&2) && !target_is_directory
) {
7033 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7037 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7038 /* wants a tree copy! XXXX */
7039 DEBUG(3,("Rejecting tree copy\n"));
7040 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7044 /* Split up the directory from the filename/mask. */
7045 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7046 &fname_src_dir
, &fname_src_mask
);
7047 if (!NT_STATUS_IS_OK(status
)) {
7048 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7053 * We should only check the mangled cache
7054 * here if unix_convert failed. This means
7055 * that the path in 'mask' doesn't exist
7056 * on the file system and so we need to look
7057 * for a possible mangle. This patch from
7058 * Tine Smukavec <valentin.smukavec@hermes.si>.
7060 if (!VALID_STAT(smb_fname_src
->st
) &&
7061 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7062 char *new_mask
= NULL
;
7063 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7064 &new_mask
, conn
->params
);
7066 /* Use demangled name if one was successfully found. */
7068 TALLOC_FREE(fname_src_mask
);
7069 fname_src_mask
= new_mask
;
7073 if (!source_has_wild
) {
7076 * Only one file needs to be copied. Append the mask back onto
7079 TALLOC_FREE(smb_fname_src
->base_name
);
7080 if (ISDOT(fname_src_dir
)) {
7081 /* Ensure we use canonical names on open. */
7082 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7086 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7091 if (!smb_fname_src
->base_name
) {
7092 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7096 if (dest_has_wild
) {
7097 char *fname_dst_mod
= NULL
;
7098 if (!resolve_wildcards(smb_fname_dst
,
7099 smb_fname_src
->base_name
,
7100 smb_fname_dst
->base_name
,
7102 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7105 TALLOC_FREE(smb_fname_dst
->base_name
);
7106 smb_fname_dst
->base_name
= fname_dst_mod
;
7109 status
= check_name(conn
, smb_fname_src
->base_name
);
7110 if (!NT_STATUS_IS_OK(status
)) {
7111 reply_nterror(req
, status
);
7115 status
= check_name(conn
, smb_fname_dst
->base_name
);
7116 if (!NT_STATUS_IS_OK(status
)) {
7117 reply_nterror(req
, status
);
7121 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7122 ofun
, count
, target_is_directory
);
7124 if(!NT_STATUS_IS_OK(status
)) {
7125 reply_nterror(req
, status
);
7131 struct smb_Dir
*dir_hnd
= NULL
;
7132 const char *dname
= NULL
;
7133 char *talloced
= NULL
;
7137 * There is a wildcard that requires us to actually read the
7138 * src dir and copy each file matching the mask to the dst.
7139 * Right now streams won't be copied, but this could
7140 * presumably be added with a nested loop for reach dir entry.
7142 SMB_ASSERT(!smb_fname_src
->stream_name
);
7143 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7145 smb_fname_src
->stream_name
= NULL
;
7146 smb_fname_dst
->stream_name
= NULL
;
7148 if (strequal(fname_src_mask
,"????????.???")) {
7149 TALLOC_FREE(fname_src_mask
);
7150 fname_src_mask
= talloc_strdup(ctx
, "*");
7151 if (!fname_src_mask
) {
7152 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7157 status
= check_name(conn
, fname_src_dir
);
7158 if (!NT_STATUS_IS_OK(status
)) {
7159 reply_nterror(req
, status
);
7163 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
7164 if (dir_hnd
== NULL
) {
7165 status
= map_nt_error_from_unix(errno
);
7166 reply_nterror(req
, status
);
7172 /* Iterate over the src dir copying each entry to the dst. */
7173 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7174 &smb_fname_src
->st
, &talloced
))) {
7175 char *destname
= NULL
;
7177 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7178 TALLOC_FREE(talloced
);
7182 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7183 &smb_fname_src
->st
, false)) {
7184 TALLOC_FREE(talloced
);
7188 if(!mask_match(dname
, fname_src_mask
,
7189 conn
->case_sensitive
)) {
7190 TALLOC_FREE(talloced
);
7194 error
= ERRnoaccess
;
7196 /* Get the src smb_fname struct setup. */
7197 TALLOC_FREE(smb_fname_src
->base_name
);
7198 if (ISDOT(fname_src_dir
)) {
7199 /* Ensure we use canonical names on open. */
7200 smb_fname_src
->base_name
=
7201 talloc_asprintf(smb_fname_src
, "%s",
7204 smb_fname_src
->base_name
=
7205 talloc_asprintf(smb_fname_src
, "%s/%s",
7206 fname_src_dir
, dname
);
7209 if (!smb_fname_src
->base_name
) {
7210 TALLOC_FREE(dir_hnd
);
7211 TALLOC_FREE(talloced
);
7212 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7216 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7217 smb_fname_dst
->base_name
,
7219 TALLOC_FREE(talloced
);
7223 TALLOC_FREE(dir_hnd
);
7224 TALLOC_FREE(talloced
);
7225 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7229 TALLOC_FREE(smb_fname_dst
->base_name
);
7230 smb_fname_dst
->base_name
= destname
;
7232 status
= check_name(conn
, smb_fname_src
->base_name
);
7233 if (!NT_STATUS_IS_OK(status
)) {
7234 TALLOC_FREE(dir_hnd
);
7235 TALLOC_FREE(talloced
);
7236 reply_nterror(req
, status
);
7240 status
= check_name(conn
, smb_fname_dst
->base_name
);
7241 if (!NT_STATUS_IS_OK(status
)) {
7242 TALLOC_FREE(dir_hnd
);
7243 TALLOC_FREE(talloced
);
7244 reply_nterror(req
, status
);
7248 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7249 smb_fname_src
->base_name
,
7250 smb_fname_dst
->base_name
));
7252 status
= copy_file(ctx
, conn
, smb_fname_src
,
7253 smb_fname_dst
, ofun
, count
,
7254 target_is_directory
);
7255 if (NT_STATUS_IS_OK(status
)) {
7259 TALLOC_FREE(talloced
);
7261 TALLOC_FREE(dir_hnd
);
7265 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7269 reply_outbuf(req
, 1, 0);
7270 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7272 TALLOC_FREE(smb_fname_src
);
7273 TALLOC_FREE(smb_fname_dst
);
7274 TALLOC_FREE(fname_src
);
7275 TALLOC_FREE(fname_dst
);
7276 TALLOC_FREE(fname_src_mask
);
7277 TALLOC_FREE(fname_src_dir
);
7279 END_PROFILE(SMBcopy
);
7284 #define DBGC_CLASS DBGC_LOCKING
7286 /****************************************************************************
7287 Get a lock pid, dealing with large count requests.
7288 ****************************************************************************/
7290 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7291 bool large_file_format
)
7293 if(!large_file_format
)
7294 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7296 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7299 /****************************************************************************
7300 Get a lock count, dealing with large count requests.
7301 ****************************************************************************/
7303 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7304 bool large_file_format
)
7308 if(!large_file_format
) {
7309 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7312 #if defined(HAVE_LONGLONG)
7313 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7314 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7315 #else /* HAVE_LONGLONG */
7318 * NT4.x seems to be broken in that it sends large file (64 bit)
7319 * lockingX calls even if the CAP_LARGE_FILES was *not*
7320 * negotiated. For boxes without large unsigned ints truncate the
7321 * lock count by dropping the top 32 bits.
7324 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7325 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7326 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7327 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7328 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7331 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7332 #endif /* HAVE_LONGLONG */
7338 #if !defined(HAVE_LONGLONG)
7339 /****************************************************************************
7340 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7341 ****************************************************************************/
7343 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7347 uint32 highcopy
= high
;
7350 * Try and find out how many significant bits there are in high.
7353 for(i
= 0; highcopy
; i
++)
7357 * We use 31 bits not 32 here as POSIX
7358 * lock offsets may not be negative.
7361 mask
= (~0) << (31 - i
);
7364 return 0; /* Fail. */
7370 #endif /* !defined(HAVE_LONGLONG) */
7372 /****************************************************************************
7373 Get a lock offset, dealing with large offset requests.
7374 ****************************************************************************/
7376 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7377 bool large_file_format
, bool *err
)
7379 uint64_t offset
= 0;
7383 if(!large_file_format
) {
7384 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7387 #if defined(HAVE_LONGLONG)
7388 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7389 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7390 #else /* HAVE_LONGLONG */
7393 * NT4.x seems to be broken in that it sends large file (64 bit)
7394 * lockingX calls even if the CAP_LARGE_FILES was *not*
7395 * negotiated. For boxes without large unsigned ints mangle the
7396 * lock offset by mapping the top 32 bits onto the lower 32.
7399 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7400 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7401 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7404 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7406 return (uint64_t)-1;
7409 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7410 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7411 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7412 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7415 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7416 #endif /* HAVE_LONGLONG */
7422 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7426 uint16_t num_ulocks
,
7427 struct smbd_lock_element
*ulocks
,
7429 struct smbd_lock_element
*locks
,
7432 connection_struct
*conn
= req
->conn
;
7434 NTSTATUS status
= NT_STATUS_OK
;
7438 /* Data now points at the beginning of the list
7439 of smb_unlkrng structs */
7440 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7441 struct smbd_lock_element
*e
= &ulocks
[i
];
7443 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7444 "pid %u, file %s\n",
7447 (unsigned int)e
->smblctx
,
7450 if (e
->brltype
!= UNLOCK_LOCK
) {
7451 /* this can only happen with SMB2 */
7452 return NT_STATUS_INVALID_PARAMETER
;
7455 status
= do_unlock(req
->sconn
->msg_ctx
,
7462 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7463 nt_errstr(status
)));
7465 if (!NT_STATUS_IS_OK(status
)) {
7470 /* Setup the timeout in seconds. */
7472 if (!lp_blocking_locks(SNUM(conn
))) {
7476 /* Data now points at the beginning of the list
7477 of smb_lkrng structs */
7479 for(i
= 0; i
< (int)num_locks
; i
++) {
7480 struct smbd_lock_element
*e
= &locks
[i
];
7482 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7483 "%llu, file %s timeout = %d\n",
7486 (unsigned long long)e
->smblctx
,
7490 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7491 struct blocking_lock_record
*blr
= NULL
;
7493 if (num_locks
> 1) {
7495 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7496 * if the lock vector contains one entry. When given mutliple cancel
7497 * requests in a single PDU we expect the server to return an
7498 * error. Windows servers seem to accept the request but only
7499 * cancel the first lock.
7500 * JRA - Do what Windows does (tm) :-).
7504 /* MS-CIFS (2.2.4.32.1) behavior. */
7505 return NT_STATUS_DOS(ERRDOS
,
7506 ERRcancelviolation
);
7508 /* Windows behavior. */
7510 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7511 "cancel request\n"));
7517 if (lp_blocking_locks(SNUM(conn
))) {
7519 /* Schedule a message to ourselves to
7520 remove the blocking lock record and
7521 return the right error. */
7523 blr
= blocking_lock_cancel_smb1(fsp
,
7529 NT_STATUS_FILE_LOCK_CONFLICT
);
7531 return NT_STATUS_DOS(
7533 ERRcancelviolation
);
7536 /* Remove a matching pending lock. */
7537 status
= do_lock_cancel(fsp
,
7544 bool blocking_lock
= timeout
? true : false;
7545 bool defer_lock
= false;
7546 struct byte_range_lock
*br_lck
;
7547 uint64_t block_smblctx
;
7549 br_lck
= do_lock(req
->sconn
->msg_ctx
,
7561 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7562 /* Windows internal resolution for blocking locks seems
7563 to be about 200ms... Don't wait for less than that. JRA. */
7564 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7565 timeout
= lp_lock_spin_time();
7570 /* If a lock sent with timeout of zero would fail, and
7571 * this lock has been requested multiple times,
7572 * according to brl_lock_failed() we convert this
7573 * request to a blocking lock with a timeout of between
7574 * 150 - 300 milliseconds.
7576 * If lp_lock_spin_time() has been set to 0, we skip
7577 * this blocking retry and fail immediately.
7579 * Replacement for do_lock_spin(). JRA. */
7581 if (!req
->sconn
->using_smb2
&&
7582 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
7583 lp_lock_spin_time() && !blocking_lock
&&
7584 NT_STATUS_EQUAL((status
),
7585 NT_STATUS_FILE_LOCK_CONFLICT
))
7588 timeout
= lp_lock_spin_time();
7591 if (br_lck
&& defer_lock
) {
7593 * A blocking lock was requested. Package up
7594 * this smb into a queued request and push it
7595 * onto the blocking lock queue.
7597 if(push_blocking_lock_request(br_lck
,
7608 TALLOC_FREE(br_lck
);
7610 return NT_STATUS_OK
;
7614 TALLOC_FREE(br_lck
);
7617 if (!NT_STATUS_IS_OK(status
)) {
7622 /* If any of the above locks failed, then we must unlock
7623 all of the previous locks (X/Open spec). */
7625 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7627 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7628 i
= -1; /* we want to skip the for loop */
7632 * Ensure we don't do a remove on the lock that just failed,
7633 * as under POSIX rules, if we have a lock already there, we
7634 * will delete it (and we shouldn't) .....
7636 for(i
--; i
>= 0; i
--) {
7637 struct smbd_lock_element
*e
= &locks
[i
];
7639 do_unlock(req
->sconn
->msg_ctx
,
7649 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7650 fsp
->fnum
, (unsigned int)type
, num_locks
, num_ulocks
));
7652 return NT_STATUS_OK
;
7655 /****************************************************************************
7656 Reply to a lockingX request.
7657 ****************************************************************************/
7659 void reply_lockingX(struct smb_request
*req
)
7661 connection_struct
*conn
= req
->conn
;
7663 unsigned char locktype
;
7664 unsigned char oplocklevel
;
7669 const uint8_t *data
;
7670 bool large_file_format
;
7672 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7673 struct smbd_lock_element
*ulocks
;
7674 struct smbd_lock_element
*locks
;
7677 START_PROFILE(SMBlockingX
);
7680 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7681 END_PROFILE(SMBlockingX
);
7685 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7686 locktype
= CVAL(req
->vwv
+3, 0);
7687 oplocklevel
= CVAL(req
->vwv
+3, 1);
7688 num_ulocks
= SVAL(req
->vwv
+6, 0);
7689 num_locks
= SVAL(req
->vwv
+7, 0);
7690 lock_timeout
= IVAL(req
->vwv
+4, 0);
7691 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7693 if (!check_fsp(conn
, req
, fsp
)) {
7694 END_PROFILE(SMBlockingX
);
7700 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7701 /* we don't support these - and CANCEL_LOCK makes w2k
7702 and XP reboot so I don't really want to be
7703 compatible! (tridge) */
7704 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
7705 END_PROFILE(SMBlockingX
);
7709 /* Check if this is an oplock break on a file
7710 we have granted an oplock on.
7712 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7713 /* Client can insist on breaking to none. */
7714 bool break_to_none
= (oplocklevel
== 0);
7717 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7718 "for fnum = %d\n", (unsigned int)oplocklevel
,
7722 * Make sure we have granted an exclusive or batch oplock on
7726 if (fsp
->oplock_type
== 0) {
7728 /* The Samba4 nbench simulator doesn't understand
7729 the difference between break to level2 and break
7730 to none from level2 - it sends oplock break
7731 replies in both cases. Don't keep logging an error
7732 message here - just ignore it. JRA. */
7734 DEBUG(5,("reply_lockingX: Error : oplock break from "
7735 "client for fnum = %d (oplock=%d) and no "
7736 "oplock granted on this file (%s).\n",
7737 fsp
->fnum
, fsp
->oplock_type
,
7740 /* if this is a pure oplock break request then don't
7742 if (num_locks
== 0 && num_ulocks
== 0) {
7743 END_PROFILE(SMBlockingX
);
7746 END_PROFILE(SMBlockingX
);
7747 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
7752 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7754 result
= remove_oplock(fsp
);
7756 result
= downgrade_oplock(fsp
);
7760 DEBUG(0, ("reply_lockingX: error in removing "
7761 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7762 /* Hmmm. Is this panic justified? */
7763 smb_panic("internal tdb error");
7766 reply_to_oplock_break_requests(fsp
);
7768 /* if this is a pure oplock break request then don't send a
7770 if (num_locks
== 0 && num_ulocks
== 0) {
7771 /* Sanity check - ensure a pure oplock break is not a
7773 if(CVAL(req
->vwv
+0, 0) != 0xff)
7774 DEBUG(0,("reply_lockingX: Error : pure oplock "
7775 "break is a chained %d request !\n",
7776 (unsigned int)CVAL(req
->vwv
+0, 0)));
7777 END_PROFILE(SMBlockingX
);
7783 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7784 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7785 END_PROFILE(SMBlockingX
);
7789 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
7790 if (ulocks
== NULL
) {
7791 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7792 END_PROFILE(SMBlockingX
);
7796 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
7797 if (locks
== NULL
) {
7798 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7799 END_PROFILE(SMBlockingX
);
7803 /* Data now points at the beginning of the list
7804 of smb_unlkrng structs */
7805 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7806 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7807 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7808 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7809 ulocks
[i
].brltype
= UNLOCK_LOCK
;
7812 * There is no error code marked "stupid client bug".... :-).
7815 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7816 END_PROFILE(SMBlockingX
);
7821 /* Now do any requested locks */
7822 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
7824 /* Data now points at the beginning of the list
7825 of smb_lkrng structs */
7827 for(i
= 0; i
< (int)num_locks
; i
++) {
7828 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
7829 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7830 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7832 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
7833 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7834 locks
[i
].brltype
= PENDING_READ_LOCK
;
7836 locks
[i
].brltype
= READ_LOCK
;
7839 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7840 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
7842 locks
[i
].brltype
= WRITE_LOCK
;
7847 * There is no error code marked "stupid client bug".... :-).
7850 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7851 END_PROFILE(SMBlockingX
);
7856 status
= smbd_do_locking(req
, fsp
,
7857 locktype
, lock_timeout
,
7861 if (!NT_STATUS_IS_OK(status
)) {
7862 END_PROFILE(SMBlockingX
);
7863 reply_nterror(req
, status
);
7867 END_PROFILE(SMBlockingX
);
7871 reply_outbuf(req
, 2, 0);
7873 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7874 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7876 END_PROFILE(SMBlockingX
);
7881 #define DBGC_CLASS DBGC_ALL
7883 /****************************************************************************
7884 Reply to a SMBreadbmpx (read block multiplex) request.
7885 Always reply with an error, if someone has a platform really needs this,
7886 please contact vl@samba.org
7887 ****************************************************************************/
7889 void reply_readbmpx(struct smb_request
*req
)
7891 START_PROFILE(SMBreadBmpx
);
7892 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7893 END_PROFILE(SMBreadBmpx
);
7897 /****************************************************************************
7898 Reply to a SMBreadbs (read block multiplex secondary) request.
7899 Always reply with an error, if someone has a platform really needs this,
7900 please contact vl@samba.org
7901 ****************************************************************************/
7903 void reply_readbs(struct smb_request
*req
)
7905 START_PROFILE(SMBreadBs
);
7906 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7907 END_PROFILE(SMBreadBs
);
7911 /****************************************************************************
7912 Reply to a SMBsetattrE.
7913 ****************************************************************************/
7915 void reply_setattrE(struct smb_request
*req
)
7917 connection_struct
*conn
= req
->conn
;
7918 struct smb_file_time ft
;
7922 START_PROFILE(SMBsetattrE
);
7926 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7930 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7932 if(!fsp
|| (fsp
->conn
!= conn
)) {
7933 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7938 * Convert the DOS times into unix times.
7941 ft
.atime
= convert_time_t_to_timespec(
7942 srv_make_unix_date2(req
->vwv
+3));
7943 ft
.mtime
= convert_time_t_to_timespec(
7944 srv_make_unix_date2(req
->vwv
+5));
7945 ft
.create_time
= convert_time_t_to_timespec(
7946 srv_make_unix_date2(req
->vwv
+1));
7948 reply_outbuf(req
, 0, 0);
7951 * Patch from Ray Frush <frush@engr.colostate.edu>
7952 * Sometimes times are sent as zero - ignore them.
7955 /* Ensure we have a valid stat struct for the source. */
7956 status
= vfs_stat_fsp(fsp
);
7957 if (!NT_STATUS_IS_OK(status
)) {
7958 reply_nterror(req
, status
);
7962 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
7963 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7967 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
7968 if (!NT_STATUS_IS_OK(status
)) {
7969 reply_nterror(req
, status
);
7973 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7976 (unsigned int)ft
.atime
.tv_sec
,
7977 (unsigned int)ft
.mtime
.tv_sec
,
7978 (unsigned int)ft
.create_time
.tv_sec
7981 END_PROFILE(SMBsetattrE
);
7986 /* Back from the dead for OS/2..... JRA. */
7988 /****************************************************************************
7989 Reply to a SMBwritebmpx (write block multiplex primary) request.
7990 Always reply with an error, if someone has a platform really needs this,
7991 please contact vl@samba.org
7992 ****************************************************************************/
7994 void reply_writebmpx(struct smb_request
*req
)
7996 START_PROFILE(SMBwriteBmpx
);
7997 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7998 END_PROFILE(SMBwriteBmpx
);
8002 /****************************************************************************
8003 Reply to a SMBwritebs (write block multiplex secondary) request.
8004 Always reply with an error, if someone has a platform really needs this,
8005 please contact vl@samba.org
8006 ****************************************************************************/
8008 void reply_writebs(struct smb_request
*req
)
8010 START_PROFILE(SMBwriteBs
);
8011 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8012 END_PROFILE(SMBwriteBs
);
8016 /****************************************************************************
8017 Reply to a SMBgetattrE.
8018 ****************************************************************************/
8020 void reply_getattrE(struct smb_request
*req
)
8022 connection_struct
*conn
= req
->conn
;
8025 struct timespec create_ts
;
8027 START_PROFILE(SMBgetattrE
);
8030 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8031 END_PROFILE(SMBgetattrE
);
8035 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8037 if(!fsp
|| (fsp
->conn
!= conn
)) {
8038 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8039 END_PROFILE(SMBgetattrE
);
8043 /* Do an fstat on this file */
8045 reply_nterror(req
, map_nt_error_from_unix(errno
));
8046 END_PROFILE(SMBgetattrE
);
8050 mode
= dos_mode(conn
, fsp
->fsp_name
);
8053 * Convert the times into dos times. Set create
8054 * date to be last modify date as UNIX doesn't save
8058 reply_outbuf(req
, 11, 0);
8060 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8061 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8062 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8063 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8064 /* Should we check pending modtime here ? JRA */
8065 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8066 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8068 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8069 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8070 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8072 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8073 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)fsp
->fsp_name
->st
.st_ex_size
);
8074 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8076 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8078 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
8080 END_PROFILE(SMBgetattrE
);