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 "smbd/globals.h"
30 extern enum protocol_types Protocol
;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS
check_path_syntax_internal(char *path
,
45 bool *p_last_component_contains_wcard
)
49 NTSTATUS ret
= NT_STATUS_OK
;
50 bool start_of_name_component
= True
;
51 bool stream_started
= false;
53 *p_last_component_contains_wcard
= False
;
60 return NT_STATUS_OBJECT_NAME_INVALID
;
63 return NT_STATUS_OBJECT_NAME_INVALID
;
65 if (strchr_m(&s
[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID
;
68 if (StrCaseCmp(s
, ":$DATA") != 0) {
69 return NT_STATUS_INVALID_PARAMETER
;
75 if (!stream_started
&& *s
== ':') {
76 if (*p_last_component_contains_wcard
) {
77 return NT_STATUS_OBJECT_NAME_INVALID
;
79 /* stream names allow more characters than file names */
80 stream_started
= true;
81 start_of_name_component
= false;
85 return NT_STATUS_OBJECT_NAME_INVALID
;
89 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
91 * Safe to assume is not the second part of a mb char
92 * as this is handled below.
94 /* Eat multiple '/' or '\\' */
95 while (IS_PATH_SEP(*s
,posix_path
)) {
98 if ((d
!= path
) && (*s
!= '\0')) {
99 /* We only care about non-leading or trailing '/' or '\\' */
103 start_of_name_component
= True
;
105 *p_last_component_contains_wcard
= False
;
109 if (start_of_name_component
) {
110 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
111 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
114 * No mb char starts with '.' so we're safe checking the directory separator here.
117 /* If we just added a '/' - delete it */
118 if ((d
> path
) && (*(d
-1) == '/')) {
123 /* Are we at the start ? Can't go back further if so. */
125 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
128 /* Go back one level... */
129 /* We know this is safe as '/' cannot be part of a mb sequence. */
130 /* NOTE - if this assumption is invalid we are not in good shape... */
131 /* Decrement d first as d points to the *next* char to write into. */
132 for (d
--; d
> path
; d
--) {
136 s
+= 2; /* Else go past the .. */
137 /* We're still at the start of a name component, just the previous one. */
140 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
152 if (*s
<= 0x1f || *s
== '|') {
153 return NT_STATUS_OBJECT_NAME_INVALID
;
161 *p_last_component_contains_wcard
= True
;
170 /* Get the size of the next MB character. */
171 next_codepoint(s
,&siz
);
189 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
191 return NT_STATUS_INVALID_PARAMETER
;
194 start_of_name_component
= False
;
202 /****************************************************************************
203 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
204 No wildcards allowed.
205 ****************************************************************************/
207 NTSTATUS
check_path_syntax(char *path
)
210 return check_path_syntax_internal(path
, False
, &ignore
);
213 /****************************************************************************
214 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
215 Wildcards allowed - p_contains_wcard returns true if the last component contained
217 ****************************************************************************/
219 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
221 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
224 /****************************************************************************
225 Check the path for a POSIX client.
226 We're assuming here that '/' is not the second byte in any multibyte char
227 set (a safe assumption).
228 ****************************************************************************/
230 NTSTATUS
check_path_syntax_posix(char *path
)
233 return check_path_syntax_internal(path
, True
, &ignore
);
236 /****************************************************************************
237 Pull a string and check the path allowing a wilcard - provide for error return.
238 ****************************************************************************/
240 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
241 const char *base_ptr
,
248 bool *contains_wcard
)
254 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
258 *err
= NT_STATUS_INVALID_PARAMETER
;
262 *contains_wcard
= False
;
264 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
266 * For a DFS path the function parse_dfs_path()
267 * will do the path processing, just make a copy.
273 if (lp_posix_pathnames()) {
274 *err
= check_path_syntax_posix(*pp_dest
);
276 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
282 /****************************************************************************
283 Pull a string and check the path - provide for error return.
284 ****************************************************************************/
286 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
287 const char *base_ptr
,
296 return srvstr_get_path_wcard(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
297 src_len
, flags
, err
, &ignore
);
300 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
301 char **pp_dest
, const char *src
, int flags
,
302 NTSTATUS
*err
, bool *contains_wcard
)
304 return srvstr_get_path_wcard(mem_ctx
, (char *)req
->inbuf
, req
->flags2
,
305 pp_dest
, src
, smbreq_bufrem(req
, src
),
306 flags
, err
, contains_wcard
);
309 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
310 char **pp_dest
, const char *src
, int flags
,
314 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
315 flags
, err
, &ignore
);
318 /****************************************************************************
319 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
320 ****************************************************************************/
322 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
325 if (!(fsp
) || !(conn
)) {
326 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
329 if (((conn
) != (fsp
)->conn
) || req
->vuid
!= (fsp
)->vuid
) {
330 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
336 /****************************************************************************
337 Check if we have a correct fsp pointing to a file.
338 ****************************************************************************/
340 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
343 if (!check_fsp_open(conn
, req
, fsp
)) {
346 if ((fsp
)->is_directory
) {
347 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
350 if ((fsp
)->fh
->fd
== -1) {
351 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
354 (fsp
)->num_smb_operations
++;
358 /****************************************************************************
359 Check if we have a correct fsp pointing to a quota fake file. Replacement for
360 the CHECK_NTQUOTA_HANDLE_OK macro.
361 ****************************************************************************/
363 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
366 if (!check_fsp_open(conn
, req
, fsp
)) {
370 if (fsp
->is_directory
) {
374 if (fsp
->fake_file_handle
== NULL
) {
378 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
382 if (fsp
->fake_file_handle
->private_data
== NULL
) {
389 /****************************************************************************
390 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
391 ****************************************************************************/
393 bool fsp_belongs_conn(connection_struct
*conn
, struct smb_request
*req
,
396 if ((fsp
) && (conn
) && ((conn
)==(fsp
)->conn
)
397 && (req
->vuid
== (fsp
)->vuid
)) {
401 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
405 /****************************************************************************
406 Reply to a (netbios-level) special message.
407 ****************************************************************************/
409 void reply_special(char *inbuf
)
411 int msg_type
= CVAL(inbuf
,0);
412 int msg_flags
= CVAL(inbuf
,1);
417 * We only really use 4 bytes of the outbuf, but for the smb_setlen
418 * calculation & friends (srv_send_smb uses that) we need the full smb
421 char outbuf
[smb_size
];
425 memset(outbuf
, '\0', sizeof(outbuf
));
427 smb_setlen(outbuf
,0);
430 case 0x81: /* session request */
432 if (already_got_session
) {
433 exit_server_cleanly("multiple session request not permitted");
436 SCVAL(outbuf
,0,0x82);
438 if (name_len(inbuf
+4) > 50 ||
439 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
440 DEBUG(0,("Invalid name length in session request\n"));
443 name_extract(inbuf
,4,name1
);
444 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
445 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
448 set_local_machine_name(name1
, True
);
449 set_remote_machine_name(name2
, True
);
451 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
452 get_local_machine_name(), get_remote_machine_name(),
455 if (name_type
== 'R') {
456 /* We are being asked for a pathworks session ---
458 SCVAL(outbuf
, 0,0x83);
462 /* only add the client's machine name to the list
463 of possibly valid usernames if we are operating
464 in share mode security */
465 if (lp_security() == SEC_SHARE
) {
466 add_session_user(get_remote_machine_name());
469 reload_services(True
);
472 already_got_session
= True
;
475 case 0x89: /* session keepalive request
476 (some old clients produce this?) */
477 SCVAL(outbuf
,0,SMBkeepalive
);
481 case 0x82: /* positive session response */
482 case 0x83: /* negative session response */
483 case 0x84: /* retarget session response */
484 DEBUG(0,("Unexpected session response\n"));
487 case SMBkeepalive
: /* session keepalive */
492 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
493 msg_type
, msg_flags
));
495 srv_send_smb(smbd_server_fd(), outbuf
, false, NULL
);
499 /****************************************************************************
501 conn POINTER CAN BE NULL HERE !
502 ****************************************************************************/
504 void reply_tcon(struct smb_request
*req
)
506 connection_struct
*conn
= req
->conn
;
508 char *service_buf
= NULL
;
509 char *password
= NULL
;
514 DATA_BLOB password_blob
;
515 TALLOC_CTX
*ctx
= talloc_tos();
517 START_PROFILE(SMBtcon
);
519 if (req
->buflen
< 4) {
520 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
521 END_PROFILE(SMBtcon
);
525 p
= (const char *)req
->buf
+ 1;
526 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
528 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
530 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
533 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
534 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
535 END_PROFILE(SMBtcon
);
538 p
= strrchr_m(service_buf
,'\\');
542 service
= service_buf
;
545 password_blob
= data_blob(password
, pwlen
+1);
547 conn
= make_connection(service
,password_blob
,dev
,req
->vuid
,&nt_status
);
550 data_blob_clear_free(&password_blob
);
553 reply_nterror(req
, nt_status
);
554 END_PROFILE(SMBtcon
);
558 reply_outbuf(req
, 2, 0);
559 SSVAL(req
->outbuf
,smb_vwv0
,max_recv
);
560 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
561 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
563 DEBUG(3,("tcon service=%s cnum=%d\n",
564 service
, conn
->cnum
));
566 END_PROFILE(SMBtcon
);
570 /****************************************************************************
571 Reply to a tcon and X.
572 conn POINTER CAN BE NULL HERE !
573 ****************************************************************************/
575 void reply_tcon_and_X(struct smb_request
*req
)
577 connection_struct
*conn
= req
->conn
;
578 const char *service
= NULL
;
580 TALLOC_CTX
*ctx
= talloc_tos();
581 /* what the cleint thinks the device is */
582 char *client_devicetype
= NULL
;
583 /* what the server tells the client the share represents */
584 const char *server_devicetype
;
591 START_PROFILE(SMBtconX
);
594 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
595 END_PROFILE(SMBtconX
);
599 passlen
= SVAL(req
->vwv
+3, 0);
600 tcon_flags
= SVAL(req
->vwv
+2, 0);
602 /* we might have to close an old one */
603 if ((tcon_flags
& 0x1) && conn
) {
604 close_cnum(conn
,req
->vuid
);
609 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
610 reply_doserror(req
, ERRDOS
, ERRbuftoosmall
);
611 END_PROFILE(SMBtconX
);
615 if (global_encrypted_passwords_negotiated
) {
616 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
);
617 if (lp_security() == SEC_SHARE
) {
619 * Security = share always has a pad byte
620 * after the password.
622 p
= (const char *)req
->buf
+ passlen
+ 1;
624 p
= (const char *)req
->buf
+ passlen
;
627 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
+1);
628 /* Ensure correct termination */
629 password
.data
[passlen
]=0;
630 p
= (const char *)req
->buf
+ passlen
+ 1;
633 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
636 data_blob_clear_free(&password
);
637 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
638 END_PROFILE(SMBtconX
);
643 * the service name can be either: \\server\share
644 * or share directly like on the DELL PowerVault 705
647 q
= strchr_m(path
+2,'\\');
649 data_blob_clear_free(&password
);
650 reply_doserror(req
, ERRDOS
, ERRnosuchshare
);
651 END_PROFILE(SMBtconX
);
659 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
660 &client_devicetype
, p
,
661 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
663 if (client_devicetype
== NULL
) {
664 data_blob_clear_free(&password
);
665 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
666 END_PROFILE(SMBtconX
);
670 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
672 conn
= make_connection(service
, password
, client_devicetype
,
673 req
->vuid
, &nt_status
);
676 data_blob_clear_free(&password
);
679 reply_nterror(req
, nt_status
);
680 END_PROFILE(SMBtconX
);
685 server_devicetype
= "IPC";
686 else if ( IS_PRINT(conn
) )
687 server_devicetype
= "LPT1:";
689 server_devicetype
= "A:";
691 if (Protocol
< PROTOCOL_NT1
) {
692 reply_outbuf(req
, 2, 0);
693 if (message_push_string(&req
->outbuf
, server_devicetype
,
694 STR_TERMINATE
|STR_ASCII
) == -1) {
695 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
696 END_PROFILE(SMBtconX
);
700 /* NT sets the fstype of IPC$ to the null string */
701 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
703 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
704 /* Return permissions. */
708 reply_outbuf(req
, 7, 0);
711 perm1
= FILE_ALL_ACCESS
;
712 perm2
= FILE_ALL_ACCESS
;
714 perm1
= CAN_WRITE(conn
) ?
719 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
720 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
722 reply_outbuf(req
, 3, 0);
725 if ((message_push_string(&req
->outbuf
, server_devicetype
,
726 STR_TERMINATE
|STR_ASCII
) == -1)
727 || (message_push_string(&req
->outbuf
, fstype
,
728 STR_TERMINATE
) == -1)) {
729 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
730 END_PROFILE(SMBtconX
);
734 /* what does setting this bit do? It is set by NT4 and
735 may affect the ability to autorun mounted cdroms */
736 SSVAL(req
->outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
737 (lp_csc_policy(SNUM(conn
)) << 2));
739 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
740 DEBUG(2,("Serving %s as a Dfs root\n",
741 lp_servicename(SNUM(conn
)) ));
742 SSVAL(req
->outbuf
, smb_vwv2
,
743 SMB_SHARE_IN_DFS
| SVAL(req
->outbuf
, smb_vwv2
));
748 DEBUG(3,("tconX service=%s \n",
751 /* set the incoming and outgoing tid to the just created one */
752 SSVAL(req
->inbuf
,smb_tid
,conn
->cnum
);
753 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
755 END_PROFILE(SMBtconX
);
761 /****************************************************************************
762 Reply to an unknown type.
763 ****************************************************************************/
765 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
767 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
768 smb_fn_name(type
), type
, type
));
769 reply_doserror(req
, ERRSRV
, ERRunknownsmb
);
773 /****************************************************************************
775 conn POINTER CAN BE NULL HERE !
776 ****************************************************************************/
778 void reply_ioctl(struct smb_request
*req
)
780 connection_struct
*conn
= req
->conn
;
787 START_PROFILE(SMBioctl
);
790 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
791 END_PROFILE(SMBioctl
);
795 device
= SVAL(req
->vwv
+1, 0);
796 function
= SVAL(req
->vwv
+2, 0);
797 ioctl_code
= (device
<< 16) + function
;
799 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
801 switch (ioctl_code
) {
802 case IOCTL_QUERY_JOB_INFO
:
806 reply_doserror(req
, ERRSRV
, ERRnosupport
);
807 END_PROFILE(SMBioctl
);
811 reply_outbuf(req
, 8, replysize
+1);
812 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
813 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
814 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
815 p
= smb_buf(req
->outbuf
);
816 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
817 p
+= 1; /* Allow for alignment */
819 switch (ioctl_code
) {
820 case IOCTL_QUERY_JOB_INFO
:
822 files_struct
*fsp
= file_fsp(
823 req
, SVAL(req
->vwv
+0, 0));
825 reply_doserror(req
, ERRDOS
, ERRbadfid
);
826 END_PROFILE(SMBioctl
);
829 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
830 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
832 STR_TERMINATE
|STR_ASCII
);
834 srvstr_push((char *)req
->outbuf
, req
->flags2
,
835 p
+18, lp_servicename(SNUM(conn
)),
836 13, STR_TERMINATE
|STR_ASCII
);
844 END_PROFILE(SMBioctl
);
848 /****************************************************************************
849 Strange checkpath NTSTATUS mapping.
850 ****************************************************************************/
852 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
854 /* Strange DOS error code semantics only for checkpath... */
855 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
856 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
857 /* We need to map to ERRbadpath */
858 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
864 /****************************************************************************
865 Reply to a checkpath.
866 ****************************************************************************/
868 void reply_checkpath(struct smb_request
*req
)
870 connection_struct
*conn
= req
->conn
;
872 SMB_STRUCT_STAT sbuf
;
874 TALLOC_CTX
*ctx
= talloc_tos();
876 START_PROFILE(SMBcheckpath
);
878 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
879 STR_TERMINATE
, &status
);
881 if (!NT_STATUS_IS_OK(status
)) {
882 status
= map_checkpath_error(req
->flags2
, status
);
883 reply_nterror(req
, status
);
884 END_PROFILE(SMBcheckpath
);
888 status
= resolve_dfspath(ctx
, conn
,
889 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
892 if (!NT_STATUS_IS_OK(status
)) {
893 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
894 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
896 END_PROFILE(SMBcheckpath
);
902 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
904 status
= unix_convert(ctx
, conn
, name
, False
, &name
, NULL
, &sbuf
);
905 if (!NT_STATUS_IS_OK(status
)) {
909 status
= check_name(conn
, name
);
910 if (!NT_STATUS_IS_OK(status
)) {
911 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name
,nt_errstr(status
)));
915 if (!VALID_STAT(sbuf
) && (SMB_VFS_STAT(conn
,name
,&sbuf
) != 0)) {
916 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name
,strerror(errno
)));
917 status
= map_nt_error_from_unix(errno
);
921 if (!S_ISDIR(sbuf
.st_mode
)) {
922 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
924 END_PROFILE(SMBcheckpath
);
928 reply_outbuf(req
, 0, 0);
930 END_PROFILE(SMBcheckpath
);
935 END_PROFILE(SMBcheckpath
);
937 /* We special case this - as when a Windows machine
938 is parsing a path is steps through the components
939 one at a time - if a component fails it expects
940 ERRbadpath, not ERRbadfile.
942 status
= map_checkpath_error(req
->flags2
, status
);
943 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
945 * Windows returns different error codes if
946 * the parent directory is valid but not the
947 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
948 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
949 * if the path is invalid.
951 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
956 reply_nterror(req
, status
);
959 /****************************************************************************
961 ****************************************************************************/
963 void reply_getatr(struct smb_request
*req
)
965 connection_struct
*conn
= req
->conn
;
967 SMB_STRUCT_STAT sbuf
;
973 TALLOC_CTX
*ctx
= talloc_tos();
975 START_PROFILE(SMBgetatr
);
977 p
= (const char *)req
->buf
+ 1;
978 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
979 if (!NT_STATUS_IS_OK(status
)) {
980 reply_nterror(req
, status
);
981 END_PROFILE(SMBgetatr
);
985 status
= resolve_dfspath(ctx
, conn
,
986 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
989 if (!NT_STATUS_IS_OK(status
)) {
990 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
991 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
993 END_PROFILE(SMBgetatr
);
996 reply_nterror(req
, status
);
997 END_PROFILE(SMBgetatr
);
1001 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1002 under WfWg - weird! */
1003 if (*fname
== '\0') {
1004 mode
= aHIDDEN
| aDIR
;
1005 if (!CAN_WRITE(conn
)) {
1011 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
,&sbuf
);
1012 if (!NT_STATUS_IS_OK(status
)) {
1013 reply_nterror(req
, status
);
1014 END_PROFILE(SMBgetatr
);
1017 status
= check_name(conn
, fname
);
1018 if (!NT_STATUS_IS_OK(status
)) {
1019 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname
,nt_errstr(status
)));
1020 reply_nterror(req
, status
);
1021 END_PROFILE(SMBgetatr
);
1024 if (!VALID_STAT(sbuf
) && (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0)) {
1025 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname
,strerror(errno
)));
1026 reply_unixerror(req
, ERRDOS
,ERRbadfile
);
1027 END_PROFILE(SMBgetatr
);
1031 mode
= dos_mode(conn
,fname
,&sbuf
);
1032 size
= sbuf
.st_size
;
1033 mtime
= sbuf
.st_mtime
;
1039 reply_outbuf(req
, 10, 0);
1041 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1042 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1043 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1045 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1047 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1049 if (Protocol
>= PROTOCOL_NT1
) {
1050 SSVAL(req
->outbuf
, smb_flg2
,
1051 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1054 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname
, mode
, (unsigned int)size
) );
1056 END_PROFILE(SMBgetatr
);
1060 /****************************************************************************
1062 ****************************************************************************/
1064 void reply_setatr(struct smb_request
*req
)
1066 struct smb_file_time ft
;
1067 connection_struct
*conn
= req
->conn
;
1071 SMB_STRUCT_STAT sbuf
;
1074 TALLOC_CTX
*ctx
= talloc_tos();
1076 START_PROFILE(SMBsetatr
);
1081 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1085 p
= (const char *)req
->buf
+ 1;
1086 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1087 if (!NT_STATUS_IS_OK(status
)) {
1088 reply_nterror(req
, status
);
1089 END_PROFILE(SMBsetatr
);
1093 status
= resolve_dfspath(ctx
, conn
,
1094 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1097 if (!NT_STATUS_IS_OK(status
)) {
1098 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1099 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1100 ERRSRV
, ERRbadpath
);
1101 END_PROFILE(SMBsetatr
);
1104 reply_nterror(req
, status
);
1105 END_PROFILE(SMBsetatr
);
1109 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
1110 if (!NT_STATUS_IS_OK(status
)) {
1111 reply_nterror(req
, status
);
1112 END_PROFILE(SMBsetatr
);
1116 status
= check_name(conn
, fname
);
1117 if (!NT_STATUS_IS_OK(status
)) {
1118 reply_nterror(req
, status
);
1119 END_PROFILE(SMBsetatr
);
1123 if (fname
[0] == '.' && fname
[1] == '\0') {
1125 * Not sure here is the right place to catch this
1126 * condition. Might be moved to somewhere else later -- vl
1128 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1129 END_PROFILE(SMBsetatr
);
1133 mode
= SVAL(req
->vwv
+0, 0);
1134 mtime
= srv_make_unix_date3(req
->vwv
+1);
1136 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1137 status
= smb_set_file_time(conn
, NULL
, fname
,
1139 if (!NT_STATUS_IS_OK(status
)) {
1140 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
1141 END_PROFILE(SMBsetatr
);
1145 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1146 if (VALID_STAT_OF_DIR(sbuf
))
1151 if (file_set_dosmode(conn
,fname
,mode
,&sbuf
,NULL
,false) != 0) {
1152 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
1153 END_PROFILE(SMBsetatr
);
1158 reply_outbuf(req
, 0, 0);
1160 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
1162 END_PROFILE(SMBsetatr
);
1166 /****************************************************************************
1168 ****************************************************************************/
1170 void reply_dskattr(struct smb_request
*req
)
1172 connection_struct
*conn
= req
->conn
;
1173 uint64_t dfree
,dsize
,bsize
;
1174 START_PROFILE(SMBdskattr
);
1176 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1177 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
1178 END_PROFILE(SMBdskattr
);
1182 reply_outbuf(req
, 5, 0);
1184 if (Protocol
<= PROTOCOL_LANMAN2
) {
1185 double total_space
, free_space
;
1186 /* we need to scale this to a number that DOS6 can handle. We
1187 use floating point so we can handle large drives on systems
1188 that don't have 64 bit integers
1190 we end up displaying a maximum of 2G to DOS systems
1192 total_space
= dsize
* (double)bsize
;
1193 free_space
= dfree
* (double)bsize
;
1195 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1196 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1198 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1199 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1201 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1202 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1203 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1204 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1206 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1207 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1208 SSVAL(req
->outbuf
,smb_vwv2
,512);
1209 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1212 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1214 END_PROFILE(SMBdskattr
);
1218 /****************************************************************************
1220 Can be called from SMBsearch, SMBffirst or SMBfunique.
1221 ****************************************************************************/
1223 void reply_search(struct smb_request
*req
)
1225 connection_struct
*conn
= req
->conn
;
1226 const char *mask
= NULL
;
1227 char *directory
= NULL
;
1233 unsigned int numentries
= 0;
1234 unsigned int maxentries
= 0;
1235 bool finished
= False
;
1241 bool check_descend
= False
;
1242 bool expect_close
= False
;
1244 bool mask_contains_wcard
= False
;
1245 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1246 TALLOC_CTX
*ctx
= talloc_tos();
1247 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1249 START_PROFILE(SMBsearch
);
1252 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1253 END_PROFILE(SMBsearch
);
1257 if (lp_posix_pathnames()) {
1258 reply_unknown_new(req
, req
->cmd
);
1259 END_PROFILE(SMBsearch
);
1263 /* If we were called as SMBffirst then we must expect close. */
1264 if(req
->cmd
== SMBffirst
) {
1265 expect_close
= True
;
1268 reply_outbuf(req
, 1, 3);
1269 maxentries
= SVAL(req
->vwv
+0, 0);
1270 dirtype
= SVAL(req
->vwv
+1, 0);
1271 p
= (const char *)req
->buf
+ 1;
1272 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1273 &nt_status
, &mask_contains_wcard
);
1274 if (!NT_STATUS_IS_OK(nt_status
)) {
1275 reply_nterror(req
, nt_status
);
1276 END_PROFILE(SMBsearch
);
1280 nt_status
= resolve_dfspath_wcard(ctx
, conn
,
1281 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1284 &mask_contains_wcard
);
1285 if (!NT_STATUS_IS_OK(nt_status
)) {
1286 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1287 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1288 ERRSRV
, ERRbadpath
);
1289 END_PROFILE(SMBsearch
);
1292 reply_nterror(req
, nt_status
);
1293 END_PROFILE(SMBsearch
);
1298 status_len
= SVAL(p
, 0);
1301 /* dirtype &= ~aDIR; */
1303 if (status_len
== 0) {
1304 SMB_STRUCT_STAT sbuf
;
1306 nt_status
= unix_convert(ctx
, conn
, path
, True
,
1307 &directory
, NULL
, &sbuf
);
1308 if (!NT_STATUS_IS_OK(nt_status
)) {
1309 reply_nterror(req
, nt_status
);
1310 END_PROFILE(SMBsearch
);
1314 nt_status
= check_name(conn
, directory
);
1315 if (!NT_STATUS_IS_OK(nt_status
)) {
1316 reply_nterror(req
, nt_status
);
1317 END_PROFILE(SMBsearch
);
1321 p
= strrchr_m(directory
,'/');
1322 if ((p
!= NULL
) && (*directory
!= '/')) {
1324 directory
= talloc_strndup(ctx
, directory
,
1325 PTR_DIFF(p
, directory
));
1328 directory
= talloc_strdup(ctx
,".");
1332 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1333 END_PROFILE(SMBsearch
);
1337 memset((char *)status
,'\0',21);
1338 SCVAL(status
,0,(dirtype
& 0x1F));
1340 nt_status
= dptr_create(conn
,
1346 mask_contains_wcard
,
1349 if (!NT_STATUS_IS_OK(nt_status
)) {
1350 reply_nterror(req
, nt_status
);
1351 END_PROFILE(SMBsearch
);
1354 dptr_num
= dptr_dnum(conn
->dirptr
);
1358 memcpy(status
,p
,21);
1359 status_dirtype
= CVAL(status
,0) & 0x1F;
1360 if (status_dirtype
!= (dirtype
& 0x1F)) {
1361 dirtype
= status_dirtype
;
1364 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1365 if (!conn
->dirptr
) {
1368 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1369 mask
= dptr_wcard(dptr_num
);
1374 * For a 'continue' search we have no string. So
1375 * check from the initial saved string.
1377 mask_contains_wcard
= ms_has_wild(mask
);
1378 dirtype
= dptr_attr(dptr_num
);
1381 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1383 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1384 dptr_init_search_op(conn
->dirptr
);
1386 if ((dirtype
&0x1F) == aVOLID
) {
1387 char buf
[DIR_STRUCT_SIZE
];
1388 memcpy(buf
,status
,21);
1389 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1390 0,aVOLID
,0,!allow_long_path_components
)) {
1391 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1392 END_PROFILE(SMBsearch
);
1395 dptr_fill(buf
+12,dptr_num
);
1396 if (dptr_zero(buf
+12) && (status_len
==0)) {
1401 if (message_push_blob(&req
->outbuf
,
1402 data_blob_const(buf
, sizeof(buf
)))
1404 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1405 END_PROFILE(SMBsearch
);
1413 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1416 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1417 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1418 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
)) {
1419 check_descend
= True
;
1422 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1423 finished
= !get_dir_entry(ctx
,
1434 char buf
[DIR_STRUCT_SIZE
];
1435 memcpy(buf
,status
,21);
1436 if (!make_dir_struct(ctx
,
1443 !allow_long_path_components
)) {
1444 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1445 END_PROFILE(SMBsearch
);
1448 if (!dptr_fill(buf
+12,dptr_num
)) {
1451 if (message_push_blob(&req
->outbuf
,
1452 data_blob_const(buf
, sizeof(buf
)))
1454 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1455 END_PROFILE(SMBsearch
);
1465 /* If we were called as SMBffirst with smb_search_id == NULL
1466 and no entries were found then return error and close dirptr
1469 if (numentries
== 0) {
1470 dptr_close(&dptr_num
);
1471 } else if(expect_close
&& status_len
== 0) {
1472 /* Close the dptr - we know it's gone */
1473 dptr_close(&dptr_num
);
1476 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1477 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1478 dptr_close(&dptr_num
);
1481 if ((numentries
== 0) && !mask_contains_wcard
) {
1482 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1483 END_PROFILE(SMBsearch
);
1487 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1488 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1489 SCVAL(smb_buf(req
->outbuf
),0,5);
1490 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1492 /* The replies here are never long name. */
1493 SSVAL(req
->outbuf
, smb_flg2
,
1494 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1495 if (!allow_long_path_components
) {
1496 SSVAL(req
->outbuf
, smb_flg2
,
1497 SVAL(req
->outbuf
, smb_flg2
)
1498 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1501 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1502 SSVAL(req
->outbuf
, smb_flg2
,
1503 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1506 directory
= dptr_path(dptr_num
);
1509 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1510 smb_fn_name(req
->cmd
),
1512 directory
? directory
: "./",
1517 END_PROFILE(SMBsearch
);
1521 /****************************************************************************
1522 Reply to a fclose (stop directory search).
1523 ****************************************************************************/
1525 void reply_fclose(struct smb_request
*req
)
1533 bool path_contains_wcard
= False
;
1534 TALLOC_CTX
*ctx
= talloc_tos();
1536 START_PROFILE(SMBfclose
);
1538 if (lp_posix_pathnames()) {
1539 reply_unknown_new(req
, req
->cmd
);
1540 END_PROFILE(SMBfclose
);
1544 p
= (const char *)req
->buf
+ 1;
1545 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1546 &err
, &path_contains_wcard
);
1547 if (!NT_STATUS_IS_OK(err
)) {
1548 reply_nterror(req
, err
);
1549 END_PROFILE(SMBfclose
);
1553 status_len
= SVAL(p
,0);
1556 if (status_len
== 0) {
1557 reply_doserror(req
, ERRSRV
, ERRsrverror
);
1558 END_PROFILE(SMBfclose
);
1562 memcpy(status
,p
,21);
1564 if(dptr_fetch(status
+12,&dptr_num
)) {
1565 /* Close the dptr - we know it's gone */
1566 dptr_close(&dptr_num
);
1569 reply_outbuf(req
, 1, 0);
1570 SSVAL(req
->outbuf
,smb_vwv0
,0);
1572 DEBUG(3,("search close\n"));
1574 END_PROFILE(SMBfclose
);
1578 /****************************************************************************
1580 ****************************************************************************/
1582 void reply_open(struct smb_request
*req
)
1584 connection_struct
*conn
= req
->conn
;
1590 SMB_STRUCT_STAT sbuf
;
1597 uint32 create_disposition
;
1598 uint32 create_options
= 0;
1600 TALLOC_CTX
*ctx
= talloc_tos();
1602 START_PROFILE(SMBopen
);
1605 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1606 END_PROFILE(SMBopen
);
1610 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1611 deny_mode
= SVAL(req
->vwv
+0, 0);
1612 dos_attr
= SVAL(req
->vwv
+1, 0);
1614 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1615 STR_TERMINATE
, &status
);
1616 if (!NT_STATUS_IS_OK(status
)) {
1617 reply_nterror(req
, status
);
1618 END_PROFILE(SMBopen
);
1622 if (!map_open_params_to_ntcreate(
1623 fname
, deny_mode
, OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1624 &share_mode
, &create_disposition
, &create_options
)) {
1625 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1626 END_PROFILE(SMBopen
);
1630 status
= SMB_VFS_CREATE_FILE(
1633 0, /* root_dir_fid */
1635 CFF_DOS_PATH
, /* create_file_flags */
1636 access_mask
, /* access_mask */
1637 share_mode
, /* share_access */
1638 create_disposition
, /* create_disposition*/
1639 create_options
, /* create_options */
1640 dos_attr
, /* file_attributes */
1641 oplock_request
, /* oplock_request */
1642 0, /* allocation_size */
1649 if (!NT_STATUS_IS_OK(status
)) {
1650 if (open_was_deferred(req
->mid
)) {
1651 /* We have re-scheduled this call. */
1652 END_PROFILE(SMBopen
);
1655 reply_openerror(req
, status
);
1656 END_PROFILE(SMBopen
);
1660 size
= sbuf
.st_size
;
1661 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1662 mtime
= sbuf
.st_mtime
;
1665 DEBUG(3,("attempt to open a directory %s\n",fsp
->fsp_name
));
1666 close_file(req
, fsp
, ERROR_CLOSE
);
1667 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1668 END_PROFILE(SMBopen
);
1672 reply_outbuf(req
, 7, 0);
1673 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1674 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1675 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1676 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1678 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1680 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1681 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1683 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1684 SCVAL(req
->outbuf
,smb_flg
,
1685 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1688 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1689 SCVAL(req
->outbuf
,smb_flg
,
1690 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1692 END_PROFILE(SMBopen
);
1696 /****************************************************************************
1697 Reply to an open and X.
1698 ****************************************************************************/
1700 void reply_open_and_X(struct smb_request
*req
)
1702 connection_struct
*conn
= req
->conn
;
1707 /* Breakout the oplock request bits so we can set the
1708 reply bits separately. */
1709 int ex_oplock_request
;
1710 int core_oplock_request
;
1713 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1714 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
1719 SMB_STRUCT_STAT sbuf
;
1723 uint64_t allocation_size
;
1724 ssize_t retval
= -1;
1727 uint32 create_disposition
;
1728 uint32 create_options
= 0;
1729 TALLOC_CTX
*ctx
= talloc_tos();
1731 START_PROFILE(SMBopenX
);
1733 if (req
->wct
< 15) {
1734 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1735 END_PROFILE(SMBopenX
);
1739 open_flags
= SVAL(req
->vwv
+2, 0);
1740 deny_mode
= SVAL(req
->vwv
+3, 0);
1741 smb_attr
= SVAL(req
->vwv
+5, 0);
1742 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1743 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1744 oplock_request
= ex_oplock_request
| core_oplock_request
;
1745 smb_ofun
= SVAL(req
->vwv
+8, 0);
1746 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1748 /* If it's an IPC, pass off the pipe handler. */
1750 if (lp_nt_pipe_support()) {
1751 reply_open_pipe_and_X(conn
, req
);
1753 reply_doserror(req
, ERRSRV
, ERRaccess
);
1755 END_PROFILE(SMBopenX
);
1759 /* XXXX we need to handle passed times, sattr and flags */
1760 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1761 STR_TERMINATE
, &status
);
1762 if (!NT_STATUS_IS_OK(status
)) {
1763 reply_nterror(req
, status
);
1764 END_PROFILE(SMBopenX
);
1768 if (!map_open_params_to_ntcreate(
1769 fname
, deny_mode
, smb_ofun
, &access_mask
,
1770 &share_mode
, &create_disposition
, &create_options
)) {
1771 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1772 END_PROFILE(SMBopenX
);
1776 status
= SMB_VFS_CREATE_FILE(
1779 0, /* root_dir_fid */
1781 CFF_DOS_PATH
, /* create_file_flags */
1782 access_mask
, /* access_mask */
1783 share_mode
, /* share_access */
1784 create_disposition
, /* create_disposition*/
1785 create_options
, /* create_options */
1786 smb_attr
, /* file_attributes */
1787 oplock_request
, /* oplock_request */
1788 0, /* allocation_size */
1792 &smb_action
, /* pinfo */
1795 if (!NT_STATUS_IS_OK(status
)) {
1796 END_PROFILE(SMBopenX
);
1797 if (open_was_deferred(req
->mid
)) {
1798 /* We have re-scheduled this call. */
1801 reply_openerror(req
, status
);
1805 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1806 if the file is truncated or created. */
1807 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1808 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1809 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1810 close_file(req
, fsp
, ERROR_CLOSE
);
1811 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1812 END_PROFILE(SMBopenX
);
1815 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1817 close_file(req
, fsp
, ERROR_CLOSE
);
1818 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1819 END_PROFILE(SMBopenX
);
1822 sbuf
.st_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,&sbuf
);
1825 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1826 mtime
= sbuf
.st_mtime
;
1828 close_file(req
, fsp
, ERROR_CLOSE
);
1829 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
1830 END_PROFILE(SMBopenX
);
1834 /* If the caller set the extended oplock request bit
1835 and we granted one (by whatever means) - set the
1836 correct bit for extended oplock reply.
1839 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1840 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1843 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1844 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1847 /* If the caller set the core oplock request bit
1848 and we granted one (by whatever means) - set the
1849 correct bit for core oplock reply.
1852 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1853 reply_outbuf(req
, 19, 0);
1855 reply_outbuf(req
, 15, 0);
1858 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1859 SCVAL(req
->outbuf
, smb_flg
,
1860 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1863 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1864 SCVAL(req
->outbuf
, smb_flg
,
1865 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1868 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
1869 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
1870 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1871 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
1873 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
1875 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
1876 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
1877 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
1879 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1880 SIVAL(req
->outbuf
, smb_vwv15
, STD_RIGHT_ALL_ACCESS
);
1883 END_PROFILE(SMBopenX
);
1888 /****************************************************************************
1889 Reply to a SMBulogoffX.
1890 ****************************************************************************/
1892 void reply_ulogoffX(struct smb_request
*req
)
1896 START_PROFILE(SMBulogoffX
);
1898 vuser
= get_valid_user_struct(req
->vuid
);
1901 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1905 /* in user level security we are supposed to close any files
1906 open by this user */
1907 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
1908 file_close_user(req
->vuid
);
1911 invalidate_vuid(req
->vuid
);
1913 reply_outbuf(req
, 2, 0);
1915 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
1917 END_PROFILE(SMBulogoffX
);
1921 /****************************************************************************
1922 Reply to a mknew or a create.
1923 ****************************************************************************/
1925 void reply_mknew(struct smb_request
*req
)
1927 connection_struct
*conn
= req
->conn
;
1930 struct smb_file_time ft
;
1932 int oplock_request
= 0;
1933 SMB_STRUCT_STAT sbuf
;
1935 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
1936 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
1937 uint32 create_disposition
;
1938 uint32 create_options
= 0;
1939 TALLOC_CTX
*ctx
= talloc_tos();
1941 START_PROFILE(SMBcreate
);
1945 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1946 END_PROFILE(SMBcreate
);
1950 fattr
= SVAL(req
->vwv
+0, 0);
1951 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1954 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
1956 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
1957 STR_TERMINATE
, &status
);
1958 if (!NT_STATUS_IS_OK(status
)) {
1959 reply_nterror(req
, status
);
1960 END_PROFILE(SMBcreate
);
1964 if (fattr
& aVOLID
) {
1965 DEBUG(0,("Attempt to create file (%s) with volid set - "
1966 "please report this\n", fname
));
1969 if(req
->cmd
== SMBmknew
) {
1970 /* We should fail if file exists. */
1971 create_disposition
= FILE_CREATE
;
1973 /* Create if file doesn't exist, truncate if it does. */
1974 create_disposition
= FILE_OVERWRITE_IF
;
1977 status
= SMB_VFS_CREATE_FILE(
1980 0, /* root_dir_fid */
1982 CFF_DOS_PATH
, /* create_file_flags */
1983 access_mask
, /* access_mask */
1984 share_mode
, /* share_access */
1985 create_disposition
, /* create_disposition*/
1986 create_options
, /* create_options */
1987 fattr
, /* file_attributes */
1988 oplock_request
, /* oplock_request */
1989 0, /* allocation_size */
1996 if (!NT_STATUS_IS_OK(status
)) {
1997 END_PROFILE(SMBcreate
);
1998 if (open_was_deferred(req
->mid
)) {
1999 /* We have re-scheduled this call. */
2002 reply_openerror(req
, status
);
2006 ft
.atime
= get_atimespec(&sbuf
); /* atime. */
2007 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &sbuf
, &ft
, true);
2008 if (!NT_STATUS_IS_OK(status
)) {
2009 END_PROFILE(SMBcreate
);
2010 reply_openerror(req
, status
);
2014 reply_outbuf(req
, 1, 0);
2015 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2017 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2018 SCVAL(req
->outbuf
,smb_flg
,
2019 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2022 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2023 SCVAL(req
->outbuf
,smb_flg
,
2024 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2027 DEBUG( 2, ( "reply_mknew: file %s\n", fsp
->fsp_name
) );
2028 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2029 fsp
->fsp_name
, fsp
->fh
->fd
, (unsigned int)fattr
) );
2031 END_PROFILE(SMBcreate
);
2035 /****************************************************************************
2036 Reply to a create temporary file.
2037 ****************************************************************************/
2039 void reply_ctemp(struct smb_request
*req
)
2041 connection_struct
*conn
= req
->conn
;
2047 SMB_STRUCT_STAT sbuf
;
2050 TALLOC_CTX
*ctx
= talloc_tos();
2052 START_PROFILE(SMBctemp
);
2055 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2056 END_PROFILE(SMBctemp
);
2060 fattr
= SVAL(req
->vwv
+0, 0);
2061 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2063 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2064 STR_TERMINATE
, &status
);
2065 if (!NT_STATUS_IS_OK(status
)) {
2066 reply_nterror(req
, status
);
2067 END_PROFILE(SMBctemp
);
2071 fname
= talloc_asprintf(ctx
,
2075 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2079 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2080 END_PROFILE(SMBctemp
);
2084 status
= resolve_dfspath(ctx
, conn
,
2085 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2088 if (!NT_STATUS_IS_OK(status
)) {
2089 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2090 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2091 ERRSRV
, ERRbadpath
);
2092 END_PROFILE(SMBctemp
);
2095 reply_nterror(req
, status
);
2096 END_PROFILE(SMBctemp
);
2100 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
2101 if (!NT_STATUS_IS_OK(status
)) {
2102 reply_nterror(req
, status
);
2103 END_PROFILE(SMBctemp
);
2107 status
= check_name(conn
, fname
);
2108 if (!NT_STATUS_IS_OK(status
)) {
2109 reply_nterror(req
, status
);
2110 END_PROFILE(SMBctemp
);
2114 tmpfd
= smb_mkstemp(fname
);
2116 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
2117 END_PROFILE(SMBctemp
);
2121 SMB_VFS_STAT(conn
,fname
,&sbuf
);
2123 /* We should fail if file does not exist. */
2124 status
= SMB_VFS_CREATE_FILE(
2127 0, /* root_dir_fid */
2129 0, /* create_file_flags */
2130 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2131 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2132 FILE_OPEN
, /* create_disposition*/
2133 0, /* create_options */
2134 fattr
, /* file_attributes */
2135 oplock_request
, /* oplock_request */
2136 0, /* allocation_size */
2143 /* close fd from smb_mkstemp() */
2146 if (!NT_STATUS_IS_OK(status
)) {
2147 if (open_was_deferred(req
->mid
)) {
2148 /* We have re-scheduled this call. */
2149 END_PROFILE(SMBctemp
);
2152 reply_openerror(req
, status
);
2153 END_PROFILE(SMBctemp
);
2157 reply_outbuf(req
, 1, 0);
2158 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2160 /* the returned filename is relative to the directory */
2161 s
= strrchr_m(fsp
->fsp_name
, '/');
2169 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2170 thing in the byte section. JRA */
2171 SSVALS(p
, 0, -1); /* what is this? not in spec */
2173 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2175 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2176 END_PROFILE(SMBctemp
);
2180 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2181 SCVAL(req
->outbuf
, smb_flg
,
2182 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2185 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2186 SCVAL(req
->outbuf
, smb_flg
,
2187 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2190 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp
->fsp_name
) );
2191 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp
->fsp_name
,
2192 fsp
->fh
->fd
, (unsigned int)sbuf
.st_mode
) );
2194 END_PROFILE(SMBctemp
);
2198 /*******************************************************************
2199 Check if a user is allowed to rename a file.
2200 ********************************************************************/
2202 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2203 uint16 dirtype
, SMB_STRUCT_STAT
*pst
)
2207 if (!CAN_WRITE(conn
)) {
2208 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2211 fmode
= dos_mode(conn
, fsp
->fsp_name
, pst
);
2212 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
)) {
2213 return NT_STATUS_NO_SUCH_FILE
;
2216 if (S_ISDIR(pst
->st_mode
)) {
2217 return NT_STATUS_OK
;
2220 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2221 return NT_STATUS_OK
;
2224 return NT_STATUS_ACCESS_DENIED
;
2227 /*******************************************************************
2228 * unlink a file with all relevant access checks
2229 *******************************************************************/
2231 static NTSTATUS
do_unlink(connection_struct
*conn
,
2232 struct smb_request
*req
,
2236 SMB_STRUCT_STAT sbuf
;
2239 uint32 dirtype_orig
= dirtype
;
2242 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname
, dirtype
));
2244 if (!CAN_WRITE(conn
)) {
2245 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2248 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
) != 0) {
2249 return map_nt_error_from_unix(errno
);
2252 fattr
= dos_mode(conn
,fname
,&sbuf
);
2254 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2255 dirtype
= aDIR
|aARCH
|aRONLY
;
2258 dirtype
&= (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
);
2260 return NT_STATUS_NO_SUCH_FILE
;
2263 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2265 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2267 return NT_STATUS_NO_SUCH_FILE
;
2270 if (dirtype_orig
& 0x8000) {
2271 /* These will never be set for POSIX. */
2272 return NT_STATUS_NO_SUCH_FILE
;
2276 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2277 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2280 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2281 return NT_STATUS_NO_SUCH_FILE
;
2284 if (dirtype
& 0xFF00) {
2285 /* These will never be set for POSIX. */
2286 return NT_STATUS_NO_SUCH_FILE
;
2291 return NT_STATUS_NO_SUCH_FILE
;
2294 /* Can't delete a directory. */
2296 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2301 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
2302 return NT_STATUS_OBJECT_NAME_INVALID
;
2303 #endif /* JRATEST */
2305 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2307 On a Windows share, a file with read-only dosmode can be opened with
2308 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2309 fails with NT_STATUS_CANNOT_DELETE error.
2311 This semantic causes a problem that a user can not
2312 rename a file with read-only dosmode on a Samba share
2313 from a Windows command prompt (i.e. cmd.exe, but can rename
2314 from Windows Explorer).
2317 if (!lp_delete_readonly(SNUM(conn
))) {
2318 if (fattr
& aRONLY
) {
2319 return NT_STATUS_CANNOT_DELETE
;
2323 /* On open checks the open itself will check the share mode, so
2324 don't do it here as we'll get it wrong. */
2326 status
= SMB_VFS_CREATE_FILE
2329 0, /* root_dir_fid */
2331 0, /* create_file_flags */
2332 DELETE_ACCESS
, /* access_mask */
2333 FILE_SHARE_NONE
, /* share_access */
2334 FILE_OPEN
, /* create_disposition*/
2335 FILE_NON_DIRECTORY_FILE
, /* create_options */
2336 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
2337 0, /* oplock_request */
2338 0, /* allocation_size */
2345 if (!NT_STATUS_IS_OK(status
)) {
2346 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2347 nt_errstr(status
)));
2351 /* The set is across all open files on this dev/inode pair. */
2352 if (!set_delete_on_close(fsp
, True
, &conn
->server_info
->utok
)) {
2353 close_file(req
, fsp
, NORMAL_CLOSE
);
2354 return NT_STATUS_ACCESS_DENIED
;
2357 return close_file(req
, fsp
, NORMAL_CLOSE
);
2360 /****************************************************************************
2361 The guts of the unlink command, split out so it may be called by the NT SMB
2363 ****************************************************************************/
2365 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2366 uint32 dirtype
, const char *name_in
, bool has_wild
)
2368 const char *directory
= NULL
;
2373 NTSTATUS status
= NT_STATUS_OK
;
2374 SMB_STRUCT_STAT sbuf
, st
;
2375 TALLOC_CTX
*ctx
= talloc_tos();
2377 status
= unix_convert(ctx
, conn
, name_in
, has_wild
, &name
, NULL
, &sbuf
);
2378 if (!NT_STATUS_IS_OK(status
)) {
2382 p
= strrchr_m(name
,'/');
2384 directory
= talloc_strdup(ctx
, ".");
2386 return NT_STATUS_NO_MEMORY
;
2396 * We should only check the mangled cache
2397 * here if unix_convert failed. This means
2398 * that the path in 'mask' doesn't exist
2399 * on the file system and so we need to look
2400 * for a possible mangle. This patch from
2401 * Tine Smukavec <valentin.smukavec@hermes.si>.
2404 if (!VALID_STAT(sbuf
) && mangle_is_mangled(mask
,conn
->params
)) {
2405 char *new_mask
= NULL
;
2406 mangle_lookup_name_from_8_3(ctx
,
2416 directory
= talloc_asprintf(ctx
,
2421 return NT_STATUS_NO_MEMORY
;
2424 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2427 status
= check_name(conn
, directory
);
2428 if (!NT_STATUS_IS_OK(status
)) {
2432 status
= do_unlink(conn
, req
, directory
, dirtype
);
2433 if (!NT_STATUS_IS_OK(status
)) {
2439 struct smb_Dir
*dir_hnd
= NULL
;
2443 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == aDIR
) {
2444 return NT_STATUS_OBJECT_NAME_INVALID
;
2447 if (strequal(mask
,"????????.???")) {
2452 status
= check_name(conn
, directory
);
2453 if (!NT_STATUS_IS_OK(status
)) {
2457 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
,
2459 if (dir_hnd
== NULL
) {
2460 return map_nt_error_from_unix(errno
);
2463 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2464 the pattern matches against the long name, otherwise the short name
2465 We don't implement this yet XXXX
2468 status
= NT_STATUS_NO_SUCH_FILE
;
2470 while ((dname
= ReadDirName(dir_hnd
, &offset
, &st
))) {
2473 if (!is_visible_file(conn
, directory
, dname
, &st
,
2479 /* Quick check for "." and ".." */
2480 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2484 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
2488 fname
= talloc_asprintf(ctx
, "%s/%s",
2492 return NT_STATUS_NO_MEMORY
;
2495 status
= check_name(conn
, fname
);
2496 if (!NT_STATUS_IS_OK(status
)) {
2497 TALLOC_FREE(dir_hnd
);
2501 status
= do_unlink(conn
, req
, fname
, dirtype
);
2502 if (!NT_STATUS_IS_OK(status
)) {
2508 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2513 TALLOC_FREE(dir_hnd
);
2516 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2517 status
= map_nt_error_from_unix(errno
);
2523 /****************************************************************************
2525 ****************************************************************************/
2527 void reply_unlink(struct smb_request
*req
)
2529 connection_struct
*conn
= req
->conn
;
2533 bool path_contains_wcard
= False
;
2534 TALLOC_CTX
*ctx
= talloc_tos();
2536 START_PROFILE(SMBunlink
);
2539 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2540 END_PROFILE(SMBunlink
);
2544 dirtype
= SVAL(req
->vwv
+0, 0);
2546 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2547 STR_TERMINATE
, &status
,
2548 &path_contains_wcard
);
2549 if (!NT_STATUS_IS_OK(status
)) {
2550 reply_nterror(req
, status
);
2551 END_PROFILE(SMBunlink
);
2555 status
= resolve_dfspath_wcard(ctx
, conn
,
2556 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2559 &path_contains_wcard
);
2560 if (!NT_STATUS_IS_OK(status
)) {
2561 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2562 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2563 ERRSRV
, ERRbadpath
);
2564 END_PROFILE(SMBunlink
);
2567 reply_nterror(req
, status
);
2568 END_PROFILE(SMBunlink
);
2572 DEBUG(3,("reply_unlink : %s\n",name
));
2574 status
= unlink_internals(conn
, req
, dirtype
, name
,
2575 path_contains_wcard
);
2576 if (!NT_STATUS_IS_OK(status
)) {
2577 if (open_was_deferred(req
->mid
)) {
2578 /* We have re-scheduled this call. */
2579 END_PROFILE(SMBunlink
);
2582 reply_nterror(req
, status
);
2583 END_PROFILE(SMBunlink
);
2587 reply_outbuf(req
, 0, 0);
2588 END_PROFILE(SMBunlink
);
2593 /****************************************************************************
2595 ****************************************************************************/
2597 static void fail_readraw(void)
2599 const char *errstr
= talloc_asprintf(talloc_tos(),
2600 "FAIL ! reply_readbraw: socket write fail (%s)",
2605 exit_server_cleanly(errstr
);
2608 /****************************************************************************
2609 Fake (read/write) sendfile. Returns -1 on read or write fail.
2610 ****************************************************************************/
2612 static ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
,
2616 size_t tosend
= nread
;
2623 bufsize
= MIN(nread
, 65536);
2625 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2629 while (tosend
> 0) {
2633 if (tosend
> bufsize
) {
2638 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2644 /* If we had a short read, fill with zeros. */
2645 if (ret
< cur_read
) {
2646 memset(buf
, '\0', cur_read
- ret
);
2649 if (write_data(smbd_server_fd(),buf
,cur_read
) != cur_read
) {
2654 startpos
+= cur_read
;
2658 return (ssize_t
)nread
;
2661 /****************************************************************************
2662 Deal with the case of sendfile reading less bytes from the file than
2663 requested. Fill with zeros (all we can do).
2664 ****************************************************************************/
2666 static void sendfile_short_send(files_struct
*fsp
,
2671 if (nread
< headersize
) {
2672 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2673 "header for file %s (%s). Terminating\n",
2674 fsp
->fsp_name
, strerror(errno
) ));
2675 exit_server_cleanly("sendfile_short_send failed");
2678 nread
-= headersize
;
2680 if (nread
< smb_maxcnt
) {
2681 char *buf
= SMB_CALLOC_ARRAY(char, 1024);
2683 exit_server_cleanly("sendfile_short_send: "
2687 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2688 "with zeros !\n", fsp
->fsp_name
));
2690 while (nread
< smb_maxcnt
) {
2692 * We asked for the real file size and told sendfile
2693 * to not go beyond the end of the file. But it can
2694 * happen that in between our fstat call and the
2695 * sendfile call the file was truncated. This is very
2696 * bad because we have already announced the larger
2697 * number of bytes to the client.
2699 * The best we can do now is to send 0-bytes, just as
2700 * a read from a hole in a sparse file would do.
2702 * This should happen rarely enough that I don't care
2703 * about efficiency here :-)
2707 to_write
= MIN(sizeof(buf
), smb_maxcnt
- nread
);
2708 if (write_data(smbd_server_fd(), buf
, to_write
) != to_write
) {
2709 exit_server_cleanly("sendfile_short_send: "
2710 "write_data failed");
2718 /****************************************************************************
2719 Return a readbraw error (4 bytes of zero).
2720 ****************************************************************************/
2722 static void reply_readbraw_error(void)
2726 if (write_data(smbd_server_fd(),header
,4) != 4) {
2731 /****************************************************************************
2732 Use sendfile in readbraw.
2733 ****************************************************************************/
2735 static void send_file_readbraw(connection_struct
*conn
,
2736 struct smb_request
*req
,
2742 char *outbuf
= NULL
;
2745 #if defined(WITH_SENDFILE)
2747 * We can only use sendfile on a non-chained packet
2748 * but we can use on a non-oplocked file. tridge proved this
2749 * on a train in Germany :-). JRA.
2750 * reply_readbraw has already checked the length.
2753 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
2754 (fsp
->wcp
== NULL
) && lp_use_sendfile(SNUM(conn
)) ) {
2755 ssize_t sendfile_read
= -1;
2757 DATA_BLOB header_blob
;
2759 _smb_setlen(header
,nread
);
2760 header_blob
= data_blob_const(header
, 4);
2762 if ((sendfile_read
= SMB_VFS_SENDFILE(smbd_server_fd(), fsp
,
2763 &header_blob
, startpos
, nread
)) == -1) {
2764 /* Returning ENOSYS means no data at all was sent.
2765 * Do this as a normal read. */
2766 if (errno
== ENOSYS
) {
2767 goto normal_readbraw
;
2771 * Special hack for broken Linux with no working sendfile. If we
2772 * return EINTR we sent the header but not the rest of the data.
2773 * Fake this up by doing read/write calls.
2775 if (errno
== EINTR
) {
2776 /* Ensure we don't do this again. */
2777 set_use_sendfile(SNUM(conn
), False
);
2778 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2780 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
2781 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2782 fsp
->fsp_name
, strerror(errno
) ));
2783 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2788 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2789 fsp
->fsp_name
, strerror(errno
) ));
2790 exit_server_cleanly("send_file_readbraw sendfile failed");
2793 /* Deal with possible short send. */
2794 if (sendfile_read
!= 4+nread
) {
2795 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
2803 outbuf
= TALLOC_ARRAY(NULL
, char, nread
+4);
2805 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2806 (unsigned)(nread
+4)));
2807 reply_readbraw_error();
2812 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2813 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2822 _smb_setlen(outbuf
,ret
);
2823 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
2826 TALLOC_FREE(outbuf
);
2829 /****************************************************************************
2830 Reply to a readbraw (core+ protocol).
2831 ****************************************************************************/
2833 void reply_readbraw(struct smb_request
*req
)
2835 connection_struct
*conn
= req
->conn
;
2836 ssize_t maxcount
,mincount
;
2843 START_PROFILE(SMBreadbraw
);
2845 if (srv_is_signing_active() || is_encrypted_packet(req
->inbuf
)) {
2846 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2847 "raw reads/writes are disallowed.");
2851 reply_readbraw_error();
2852 END_PROFILE(SMBreadbraw
);
2857 * Special check if an oplock break has been issued
2858 * and the readraw request croses on the wire, we must
2859 * return a zero length response here.
2862 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
2865 * We have to do a check_fsp by hand here, as
2866 * we must always return 4 zero bytes on error,
2870 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
2871 req
->vuid
!= fsp
->vuid
||
2872 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
2874 * fsp could be NULL here so use the value from the packet. JRA.
2876 DEBUG(3,("reply_readbraw: fnum %d not valid "
2878 (int)SVAL(req
->vwv
+0, 0)));
2879 reply_readbraw_error();
2880 END_PROFILE(SMBreadbraw
);
2884 /* Do a "by hand" version of CHECK_READ. */
2885 if (!(fsp
->can_read
||
2886 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
2887 (fsp
->access_mask
& FILE_EXECUTE
)))) {
2888 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2889 (int)SVAL(req
->vwv
+0, 0)));
2890 reply_readbraw_error();
2891 END_PROFILE(SMBreadbraw
);
2895 flush_write_cache(fsp
, READRAW_FLUSH
);
2897 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
2898 if(req
->wct
== 10) {
2900 * This is a large offset (64 bit) read.
2902 #ifdef LARGE_SMB_OFF_T
2904 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+8, 0)) << 32);
2906 #else /* !LARGE_SMB_OFF_T */
2909 * Ensure we haven't been sent a >32 bit offset.
2912 if(IVAL(req
->vwv
+8, 0) != 0) {
2913 DEBUG(0,("reply_readbraw: large offset "
2914 "(%x << 32) used and we don't support "
2915 "64 bit offsets.\n",
2916 (unsigned int)IVAL(req
->vwv
+8, 0) ));
2917 reply_readbraw_error();
2918 END_PROFILE(SMBreadbraw
);
2922 #endif /* LARGE_SMB_OFF_T */
2925 DEBUG(0,("reply_readbraw: negative 64 bit "
2926 "readraw offset (%.0f) !\n",
2927 (double)startpos
));
2928 reply_readbraw_error();
2929 END_PROFILE(SMBreadbraw
);
2934 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
2935 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
2937 /* ensure we don't overrun the packet size */
2938 maxcount
= MIN(65535,maxcount
);
2940 if (is_locked(fsp
,(uint32
)req
->smbpid
,
2944 reply_readbraw_error();
2945 END_PROFILE(SMBreadbraw
);
2949 if (SMB_VFS_FSTAT(fsp
, &st
) == 0) {
2953 if (startpos
>= size
) {
2956 nread
= MIN(maxcount
,(size
- startpos
));
2959 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2960 if (nread
< mincount
)
2964 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2965 "min=%lu nread=%lu\n",
2966 fsp
->fnum
, (double)startpos
,
2967 (unsigned long)maxcount
,
2968 (unsigned long)mincount
,
2969 (unsigned long)nread
) );
2971 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
2973 DEBUG(5,("reply_readbraw finished\n"));
2974 END_PROFILE(SMBreadbraw
);
2978 #define DBGC_CLASS DBGC_LOCKING
2980 /****************************************************************************
2981 Reply to a lockread (core+ protocol).
2982 ****************************************************************************/
2984 void reply_lockread(struct smb_request
*req
)
2986 connection_struct
*conn
= req
->conn
;
2993 struct byte_range_lock
*br_lck
= NULL
;
2996 START_PROFILE(SMBlockread
);
2999 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3000 END_PROFILE(SMBlockread
);
3004 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3006 if (!check_fsp(conn
, req
, fsp
)) {
3007 END_PROFILE(SMBlockread
);
3011 if (!CHECK_READ(fsp
,req
)) {
3012 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3013 END_PROFILE(SMBlockread
);
3017 numtoread
= SVAL(req
->vwv
+1, 0);
3018 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3020 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3022 reply_outbuf(req
, 5, numtoread
+ 3);
3024 data
= smb_buf(req
->outbuf
) + 3;
3027 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3028 * protocol request that predates the read/write lock concept.
3029 * Thus instead of asking for a read lock here we need to ask
3030 * for a write lock. JRA.
3031 * Note that the requested lock size is unaffected by max_recv.
3034 br_lck
= do_lock(smbd_messaging_context(),
3037 (uint64_t)numtoread
,
3041 False
, /* Non-blocking lock. */
3045 TALLOC_FREE(br_lck
);
3047 if (NT_STATUS_V(status
)) {
3048 reply_nterror(req
, status
);
3049 END_PROFILE(SMBlockread
);
3054 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3057 if (numtoread
> max_recv
) {
3058 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3059 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3060 (unsigned int)numtoread
, (unsigned int)max_recv
));
3061 numtoread
= MIN(numtoread
,max_recv
);
3063 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3066 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3067 END_PROFILE(SMBlockread
);
3071 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3073 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3074 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3075 p
= smb_buf(req
->outbuf
);
3076 SCVAL(p
,0,0); /* pad byte. */
3079 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3080 fsp
->fnum
, (int)numtoread
, (int)nread
));
3082 END_PROFILE(SMBlockread
);
3087 #define DBGC_CLASS DBGC_ALL
3089 /****************************************************************************
3091 ****************************************************************************/
3093 void reply_read(struct smb_request
*req
)
3095 connection_struct
*conn
= req
->conn
;
3103 START_PROFILE(SMBread
);
3106 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3107 END_PROFILE(SMBread
);
3111 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3113 if (!check_fsp(conn
, req
, fsp
)) {
3114 END_PROFILE(SMBread
);
3118 if (!CHECK_READ(fsp
,req
)) {
3119 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3120 END_PROFILE(SMBread
);
3124 numtoread
= SVAL(req
->vwv
+1, 0);
3125 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3127 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3130 * The requested read size cannot be greater than max_recv. JRA.
3132 if (numtoread
> max_recv
) {
3133 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3134 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3135 (unsigned int)numtoread
, (unsigned int)max_recv
));
3136 numtoread
= MIN(numtoread
,max_recv
);
3139 reply_outbuf(req
, 5, numtoread
+3);
3141 data
= smb_buf(req
->outbuf
) + 3;
3143 if (is_locked(fsp
, (uint32
)req
->smbpid
, (uint64_t)numtoread
,
3144 (uint64_t)startpos
, READ_LOCK
)) {
3145 reply_doserror(req
, ERRDOS
,ERRlock
);
3146 END_PROFILE(SMBread
);
3151 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3154 reply_unixerror(req
, ERRDOS
,ERRnoaccess
);
3155 END_PROFILE(SMBread
);
3159 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3161 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3162 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3163 SCVAL(smb_buf(req
->outbuf
),0,1);
3164 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3166 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3167 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3169 END_PROFILE(SMBread
);
3173 /****************************************************************************
3175 ****************************************************************************/
3177 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3183 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3184 data
= smb_buf(outbuf
);
3186 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3188 SCVAL(outbuf
,smb_vwv0
,0xFF);
3189 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3190 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3191 SSVAL(outbuf
,smb_vwv6
,
3193 + 1 /* the wct field */
3194 + 12 * sizeof(uint16_t) /* vwv */
3195 + 2); /* the buflen field */
3196 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3197 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3198 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3199 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3203 /****************************************************************************
3204 Reply to a read and X - possibly using sendfile.
3205 ****************************************************************************/
3207 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3208 files_struct
*fsp
, SMB_OFF_T startpos
,
3211 SMB_STRUCT_STAT sbuf
;
3214 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
3215 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3219 if (startpos
> sbuf
.st_size
) {
3221 } else if (smb_maxcnt
> (sbuf
.st_size
- startpos
)) {
3222 smb_maxcnt
= (sbuf
.st_size
- startpos
);
3225 if (smb_maxcnt
== 0) {
3229 #if defined(WITH_SENDFILE)
3231 * We can only use sendfile on a non-chained packet
3232 * but we can use on a non-oplocked file. tridge proved this
3233 * on a train in Germany :-). JRA.
3236 if (!req_is_in_chain(req
) &&
3237 !is_encrypted_packet(req
->inbuf
) && (fsp
->base_fsp
== NULL
) &&
3238 lp_use_sendfile(SNUM(conn
)) && (fsp
->wcp
== NULL
) ) {
3239 uint8 headerbuf
[smb_size
+ 12 * 2];
3243 * Set up the packet header before send. We
3244 * assume here the sendfile will work (get the
3245 * correct amount of data).
3248 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3250 construct_reply_common_req(req
, (char *)headerbuf
);
3251 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3253 if ((nread
= SMB_VFS_SENDFILE(smbd_server_fd(), fsp
, &header
, startpos
, smb_maxcnt
)) == -1) {
3254 /* Returning ENOSYS means no data at all was sent.
3255 Do this as a normal read. */
3256 if (errno
== ENOSYS
) {
3261 * Special hack for broken Linux with no working sendfile. If we
3262 * return EINTR we sent the header but not the rest of the data.
3263 * Fake this up by doing read/write calls.
3266 if (errno
== EINTR
) {
3267 /* Ensure we don't do this again. */
3268 set_use_sendfile(SNUM(conn
), False
);
3269 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3270 nread
= fake_sendfile(fsp
, startpos
,
3273 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3274 fsp
->fsp_name
, strerror(errno
) ));
3275 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3277 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3278 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3279 /* No outbuf here means successful sendfile. */
3280 TALLOC_FREE(req
->outbuf
);
3284 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3285 fsp
->fsp_name
, strerror(errno
) ));
3286 exit_server_cleanly("send_file_readX sendfile failed");
3289 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3290 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3292 /* Deal with possible short send. */
3293 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3294 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3297 /* No outbuf here means successful sendfile. */
3298 TALLOC_FREE(req
->outbuf
);
3299 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3300 SMB_PERFCOUNT_END(&req
->pcd
);
3307 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3308 uint8 headerbuf
[smb_size
+ 2*12];
3310 construct_reply_common_req(req
, (char *)headerbuf
);
3311 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3313 /* Send out the header. */
3314 if (write_data(smbd_server_fd(), (char *)headerbuf
,
3315 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3316 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3317 fsp
->fsp_name
, strerror(errno
) ));
3318 exit_server_cleanly("send_file_readX sendfile failed");
3320 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3322 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3323 fsp
->fsp_name
, strerror(errno
) ));
3324 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3326 TALLOC_FREE(req
->outbuf
);
3330 reply_outbuf(req
, 12, smb_maxcnt
);
3332 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3334 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3338 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3340 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3341 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3346 /****************************************************************************
3347 Reply to a read and X.
3348 ****************************************************************************/
3350 void reply_read_and_X(struct smb_request
*req
)
3352 connection_struct
*conn
= req
->conn
;
3356 bool big_readX
= False
;
3358 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3361 START_PROFILE(SMBreadX
);
3363 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3364 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3368 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3369 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3370 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3372 /* If it's an IPC, pass off the pipe handler. */
3374 reply_pipe_read_and_X(req
);
3375 END_PROFILE(SMBreadX
);
3379 if (!check_fsp(conn
, req
, fsp
)) {
3380 END_PROFILE(SMBreadX
);
3384 if (!CHECK_READ(fsp
,req
)) {
3385 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3386 END_PROFILE(SMBreadX
);
3390 if (global_client_caps
& CAP_LARGE_READX
) {
3391 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3392 smb_maxcnt
|= (upper_size
<<16);
3393 if (upper_size
> 1) {
3394 /* Can't do this on a chained packet. */
3395 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3396 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3397 END_PROFILE(SMBreadX
);
3400 /* We currently don't do this on signed or sealed data. */
3401 if (srv_is_signing_active() || is_encrypted_packet(req
->inbuf
)) {
3402 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3403 END_PROFILE(SMBreadX
);
3406 /* Is there room in the reply for this data ? */
3407 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3409 NT_STATUS_INVALID_PARAMETER
);
3410 END_PROFILE(SMBreadX
);
3417 if (req
->wct
== 12) {
3418 #ifdef LARGE_SMB_OFF_T
3420 * This is a large offset (64 bit) read.
3422 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+10, 0)) << 32);
3424 #else /* !LARGE_SMB_OFF_T */
3427 * Ensure we haven't been sent a >32 bit offset.
3430 if(IVAL(req
->vwv
+10, 0) != 0) {
3431 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3432 "used and we don't support 64 bit offsets.\n",
3433 (unsigned int)IVAL(req
->vwv
+10, 0) ));
3434 END_PROFILE(SMBreadX
);
3435 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3439 #endif /* LARGE_SMB_OFF_T */
3443 if (is_locked(fsp
, (uint32
)req
->smbpid
, (uint64_t)smb_maxcnt
,
3444 (uint64_t)startpos
, READ_LOCK
)) {
3445 END_PROFILE(SMBreadX
);
3446 reply_doserror(req
, ERRDOS
, ERRlock
);
3451 schedule_aio_read_and_X(conn
, req
, fsp
, startpos
, smb_maxcnt
)) {
3452 END_PROFILE(SMBreadX
);
3456 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3458 END_PROFILE(SMBreadX
);
3462 /****************************************************************************
3463 Error replies to writebraw must have smb_wct == 1. Fix this up.
3464 ****************************************************************************/
3466 void error_to_writebrawerr(struct smb_request
*req
)
3468 uint8
*old_outbuf
= req
->outbuf
;
3470 reply_outbuf(req
, 1, 0);
3472 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3473 TALLOC_FREE(old_outbuf
);
3476 /****************************************************************************
3477 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3478 ****************************************************************************/
3480 void reply_writebraw(struct smb_request
*req
)
3482 connection_struct
*conn
= req
->conn
;
3485 ssize_t total_written
=0;
3486 size_t numtowrite
=0;
3494 START_PROFILE(SMBwritebraw
);
3497 * If we ever reply with an error, it must have the SMB command
3498 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3501 SCVAL(req
->inbuf
,smb_com
,SMBwritec
);
3503 if (srv_is_signing_active()) {
3504 END_PROFILE(SMBwritebraw
);
3505 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3506 "raw reads/writes are disallowed.");
3509 if (req
->wct
< 12) {
3510 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3511 error_to_writebrawerr(req
);
3512 END_PROFILE(SMBwritebraw
);
3516 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3517 if (!check_fsp(conn
, req
, fsp
)) {
3518 error_to_writebrawerr(req
);
3519 END_PROFILE(SMBwritebraw
);
3523 if (!CHECK_WRITE(fsp
)) {
3524 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3525 error_to_writebrawerr(req
);
3526 END_PROFILE(SMBwritebraw
);
3530 tcount
= IVAL(req
->vwv
+1, 0);
3531 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3532 write_through
= BITSETW(req
->vwv
+7,0);
3534 /* We have to deal with slightly different formats depending
3535 on whether we are using the core+ or lanman1.0 protocol */
3537 if(Protocol
<= PROTOCOL_COREPLUS
) {
3538 numtowrite
= SVAL(smb_buf(req
->inbuf
),-2);
3539 data
= smb_buf(req
->inbuf
);
3541 numtowrite
= SVAL(req
->vwv
+10, 0);
3542 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3545 /* Ensure we don't write bytes past the end of this packet. */
3546 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3547 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3548 error_to_writebrawerr(req
);
3549 END_PROFILE(SMBwritebraw
);
3553 if (is_locked(fsp
,(uint32
)req
->smbpid
,(uint64_t)tcount
,
3554 (uint64_t)startpos
, WRITE_LOCK
)) {
3555 reply_doserror(req
, ERRDOS
, ERRlock
);
3556 error_to_writebrawerr(req
);
3557 END_PROFILE(SMBwritebraw
);
3562 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3565 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3566 "wrote=%d sync=%d\n",
3567 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3568 (int)nwritten
, (int)write_through
));
3570 if (nwritten
< (ssize_t
)numtowrite
) {
3571 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3572 error_to_writebrawerr(req
);
3573 END_PROFILE(SMBwritebraw
);
3577 total_written
= nwritten
;
3579 /* Allocate a buffer of 64k + length. */
3580 buf
= TALLOC_ARRAY(NULL
, char, 65540);
3582 reply_doserror(req
, ERRDOS
, ERRnomem
);
3583 error_to_writebrawerr(req
);
3584 END_PROFILE(SMBwritebraw
);
3588 /* Return a SMBwritebraw message to the redirector to tell
3589 * it to send more bytes */
3591 memcpy(buf
, req
->inbuf
, smb_size
);
3592 srv_set_message(buf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
3593 SCVAL(buf
,smb_com
,SMBwritebraw
);
3594 SSVALS(buf
,smb_vwv0
,0xFFFF);
3596 if (!srv_send_smb(smbd_server_fd(),
3598 IS_CONN_ENCRYPTED(conn
),
3600 exit_server_cleanly("reply_writebraw: srv_send_smb "
3604 /* Now read the raw data into the buffer and write it */
3605 status
= read_smb_length(smbd_server_fd(), buf
, SMB_SECONDARY_WAIT
,
3607 if (!NT_STATUS_IS_OK(status
)) {
3608 exit_server_cleanly("secondary writebraw failed");
3611 /* Set up outbuf to return the correct size */
3612 reply_outbuf(req
, 1, 0);
3614 if (numtowrite
!= 0) {
3616 if (numtowrite
> 0xFFFF) {
3617 DEBUG(0,("reply_writebraw: Oversize secondary write "
3618 "raw requested (%u). Terminating\n",
3619 (unsigned int)numtowrite
));
3620 exit_server_cleanly("secondary writebraw failed");
3623 if (tcount
> nwritten
+numtowrite
) {
3624 DEBUG(3,("reply_writebraw: Client overestimated the "
3626 (int)tcount
,(int)nwritten
,(int)numtowrite
));
3629 status
= read_data(smbd_server_fd(), buf
+4, numtowrite
);
3631 if (!NT_STATUS_IS_OK(status
)) {
3632 DEBUG(0,("reply_writebraw: Oversize secondary write "
3633 "raw read failed (%s). Terminating\n",
3634 nt_errstr(status
)));
3635 exit_server_cleanly("secondary writebraw failed");
3638 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
3639 if (nwritten
== -1) {
3641 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3642 error_to_writebrawerr(req
);
3643 END_PROFILE(SMBwritebraw
);
3647 if (nwritten
< (ssize_t
)numtowrite
) {
3648 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
3649 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
3653 total_written
+= nwritten
;
3658 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
3660 status
= sync_file(conn
, fsp
, write_through
);
3661 if (!NT_STATUS_IS_OK(status
)) {
3662 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3663 fsp
->fsp_name
, nt_errstr(status
) ));
3664 reply_nterror(req
, status
);
3665 error_to_writebrawerr(req
);
3666 END_PROFILE(SMBwritebraw
);
3670 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3672 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3673 (int)total_written
));
3675 /* We won't return a status if write through is not selected - this
3676 * follows what WfWg does */
3677 END_PROFILE(SMBwritebraw
);
3679 if (!write_through
&& total_written
==tcount
) {
3681 #if RABBIT_PELLET_FIX
3683 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3684 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3687 if (!send_keepalive(smbd_server_fd())) {
3688 exit_server_cleanly("reply_writebraw: send of "
3689 "keepalive failed");
3692 TALLOC_FREE(req
->outbuf
);
3698 #define DBGC_CLASS DBGC_LOCKING
3700 /****************************************************************************
3701 Reply to a writeunlock (core+).
3702 ****************************************************************************/
3704 void reply_writeunlock(struct smb_request
*req
)
3706 connection_struct
*conn
= req
->conn
;
3707 ssize_t nwritten
= -1;
3711 NTSTATUS status
= NT_STATUS_OK
;
3714 START_PROFILE(SMBwriteunlock
);
3717 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3718 END_PROFILE(SMBwriteunlock
);
3722 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3724 if (!check_fsp(conn
, req
, fsp
)) {
3725 END_PROFILE(SMBwriteunlock
);
3729 if (!CHECK_WRITE(fsp
)) {
3730 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3731 END_PROFILE(SMBwriteunlock
);
3735 numtowrite
= SVAL(req
->vwv
+1, 0);
3736 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3737 data
= (const char *)req
->buf
+ 3;
3740 && is_locked(fsp
, (uint32
)req
->smbpid
, (uint64_t)numtowrite
,
3741 (uint64_t)startpos
, WRITE_LOCK
)) {
3742 reply_doserror(req
, ERRDOS
, ERRlock
);
3743 END_PROFILE(SMBwriteunlock
);
3747 /* The special X/Open SMB protocol handling of
3748 zero length writes is *NOT* done for
3750 if(numtowrite
== 0) {
3753 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3756 status
= sync_file(conn
, fsp
, False
/* write through */);
3757 if (!NT_STATUS_IS_OK(status
)) {
3758 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3759 fsp
->fsp_name
, nt_errstr(status
) ));
3760 reply_nterror(req
, status
);
3761 END_PROFILE(SMBwriteunlock
);
3765 if(((nwritten
< numtowrite
) && (numtowrite
!= 0))||(nwritten
< 0)) {
3766 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3767 END_PROFILE(SMBwriteunlock
);
3772 status
= do_unlock(smbd_messaging_context(),
3775 (uint64_t)numtowrite
,
3779 if (NT_STATUS_V(status
)) {
3780 reply_nterror(req
, status
);
3781 END_PROFILE(SMBwriteunlock
);
3786 reply_outbuf(req
, 1, 0);
3788 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
3790 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3791 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
3793 END_PROFILE(SMBwriteunlock
);
3798 #define DBGC_CLASS DBGC_ALL
3800 /****************************************************************************
3802 ****************************************************************************/
3804 void reply_write(struct smb_request
*req
)
3806 connection_struct
*conn
= req
->conn
;
3808 ssize_t nwritten
= -1;
3814 START_PROFILE(SMBwrite
);
3817 END_PROFILE(SMBwrite
);
3818 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3822 /* If it's an IPC, pass off the pipe handler. */
3824 reply_pipe_write(req
);
3825 END_PROFILE(SMBwrite
);
3829 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3831 if (!check_fsp(conn
, req
, fsp
)) {
3832 END_PROFILE(SMBwrite
);
3836 if (!CHECK_WRITE(fsp
)) {
3837 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3838 END_PROFILE(SMBwrite
);
3842 numtowrite
= SVAL(req
->vwv
+1, 0);
3843 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3844 data
= (const char *)req
->buf
+ 3;
3846 if (is_locked(fsp
, (uint32
)req
->smbpid
, (uint64_t)numtowrite
,
3847 (uint64_t)startpos
, WRITE_LOCK
)) {
3848 reply_doserror(req
, ERRDOS
, ERRlock
);
3849 END_PROFILE(SMBwrite
);
3854 * X/Open SMB protocol says that if smb_vwv1 is
3855 * zero then the file size should be extended or
3856 * truncated to the size given in smb_vwv[2-3].
3859 if(numtowrite
== 0) {
3861 * This is actually an allocate call, and set EOF. JRA.
3863 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
3865 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3866 END_PROFILE(SMBwrite
);
3869 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
3871 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3872 END_PROFILE(SMBwrite
);
3875 trigger_write_time_update_immediate(fsp
);
3877 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3880 status
= sync_file(conn
, fsp
, False
);
3881 if (!NT_STATUS_IS_OK(status
)) {
3882 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3883 fsp
->fsp_name
, nt_errstr(status
) ));
3884 reply_nterror(req
, status
);
3885 END_PROFILE(SMBwrite
);
3889 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
3890 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3891 END_PROFILE(SMBwrite
);
3895 reply_outbuf(req
, 1, 0);
3897 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
3899 if (nwritten
< (ssize_t
)numtowrite
) {
3900 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
3901 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
3904 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
3906 END_PROFILE(SMBwrite
);
3910 /****************************************************************************
3911 Ensure a buffer is a valid writeX for recvfile purposes.
3912 ****************************************************************************/
3914 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3915 (2*14) + /* word count (including bcc) */ \
3918 bool is_valid_writeX_buffer(const uint8_t *inbuf
)
3921 connection_struct
*conn
= NULL
;
3922 unsigned int doff
= 0;
3923 size_t len
= smb_len_large(inbuf
);
3925 if (is_encrypted_packet(inbuf
)) {
3926 /* Can't do this on encrypted
3931 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
3935 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
3936 CVAL(inbuf
,smb_wct
) != 14) {
3937 DEBUG(10,("is_valid_writeX_buffer: chained or "
3938 "invalid word length.\n"));
3942 conn
= conn_find(SVAL(inbuf
, smb_tid
));
3944 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3948 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3951 if (IS_PRINT(conn
)) {
3952 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
3955 doff
= SVAL(inbuf
,smb_vwv11
);
3957 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3959 if (len
> doff
&& len
- doff
> 0xFFFF) {
3960 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
3963 if (numtowrite
== 0) {
3964 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3968 /* Ensure the sizes match up. */
3969 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
3970 /* no pad byte...old smbclient :-( */
3971 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3973 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
3977 if (len
- doff
!= numtowrite
) {
3978 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3979 "len = %u, doff = %u, numtowrite = %u\n",
3982 (unsigned int)numtowrite
));
3986 DEBUG(10,("is_valid_writeX_buffer: true "
3987 "len = %u, doff = %u, numtowrite = %u\n",
3990 (unsigned int)numtowrite
));
3995 /****************************************************************************
3996 Reply to a write and X.
3997 ****************************************************************************/
3999 void reply_write_and_X(struct smb_request
*req
)
4001 connection_struct
*conn
= req
->conn
;
4007 unsigned int smb_doff
;
4008 unsigned int smblen
;
4012 START_PROFILE(SMBwriteX
);
4014 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4015 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4016 END_PROFILE(SMBwriteX
);
4020 numtowrite
= SVAL(req
->vwv
+10, 0);
4021 smb_doff
= SVAL(req
->vwv
+11, 0);
4022 smblen
= smb_len(req
->inbuf
);
4024 if (req
->unread_bytes
> 0xFFFF ||
4025 (smblen
> smb_doff
&&
4026 smblen
- smb_doff
> 0xFFFF)) {
4027 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4030 if (req
->unread_bytes
) {
4031 /* Can't do a recvfile write on IPC$ */
4033 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4034 END_PROFILE(SMBwriteX
);
4037 if (numtowrite
!= req
->unread_bytes
) {
4038 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4039 END_PROFILE(SMBwriteX
);
4043 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4044 smb_doff
+ numtowrite
> smblen
) {
4045 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4046 END_PROFILE(SMBwriteX
);
4051 /* If it's an IPC, pass off the pipe handler. */
4053 if (req
->unread_bytes
) {
4054 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4055 END_PROFILE(SMBwriteX
);
4058 reply_pipe_write_and_X(req
);
4059 END_PROFILE(SMBwriteX
);
4063 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4064 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4065 write_through
= BITSETW(req
->vwv
+7,0);
4067 if (!check_fsp(conn
, req
, fsp
)) {
4068 END_PROFILE(SMBwriteX
);
4072 if (!CHECK_WRITE(fsp
)) {
4073 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4074 END_PROFILE(SMBwriteX
);
4078 data
= smb_base(req
->inbuf
) + smb_doff
;
4080 if(req
->wct
== 14) {
4081 #ifdef LARGE_SMB_OFF_T
4083 * This is a large offset (64 bit) write.
4085 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+12, 0)) << 32);
4087 #else /* !LARGE_SMB_OFF_T */
4090 * Ensure we haven't been sent a >32 bit offset.
4093 if(IVAL(req
->vwv
+12, 0) != 0) {
4094 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4095 "used and we don't support 64 bit offsets.\n",
4096 (unsigned int)IVAL(req
->vwv
+12, 0) ));
4097 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4098 END_PROFILE(SMBwriteX
);
4102 #endif /* LARGE_SMB_OFF_T */
4105 if (is_locked(fsp
,(uint32
)req
->smbpid
,
4106 (uint64_t)numtowrite
,
4107 (uint64_t)startpos
, WRITE_LOCK
)) {
4108 reply_doserror(req
, ERRDOS
, ERRlock
);
4109 END_PROFILE(SMBwriteX
);
4113 /* X/Open SMB protocol says that, unlike SMBwrite
4114 if the length is zero then NO truncation is
4115 done, just a write of zero. To truncate a file,
4118 if(numtowrite
== 0) {
4122 if ((req
->unread_bytes
== 0) &&
4123 schedule_aio_write_and_X(conn
, req
, fsp
, data
, startpos
,
4125 END_PROFILE(SMBwriteX
);
4129 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4132 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4133 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
4134 END_PROFILE(SMBwriteX
);
4138 reply_outbuf(req
, 6, 0);
4139 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4140 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4142 if (nwritten
< (ssize_t
)numtowrite
) {
4143 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4144 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4147 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4148 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4150 status
= sync_file(conn
, fsp
, write_through
);
4151 if (!NT_STATUS_IS_OK(status
)) {
4152 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4153 fsp
->fsp_name
, nt_errstr(status
) ));
4154 reply_nterror(req
, status
);
4155 END_PROFILE(SMBwriteX
);
4159 END_PROFILE(SMBwriteX
);
4164 /****************************************************************************
4166 ****************************************************************************/
4168 void reply_lseek(struct smb_request
*req
)
4170 connection_struct
*conn
= req
->conn
;
4176 START_PROFILE(SMBlseek
);
4179 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4180 END_PROFILE(SMBlseek
);
4184 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4186 if (!check_fsp(conn
, req
, fsp
)) {
4190 flush_write_cache(fsp
, SEEK_FLUSH
);
4192 mode
= SVAL(req
->vwv
+1, 0) & 3;
4193 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4194 startpos
= (SMB_OFF_T
)IVALS(req
->vwv
+2, 0);
4203 res
= fsp
->fh
->pos
+ startpos
;
4214 if (umode
== SEEK_END
) {
4215 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4216 if(errno
== EINVAL
) {
4217 SMB_OFF_T current_pos
= startpos
;
4218 SMB_STRUCT_STAT sbuf
;
4220 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
4221 reply_unixerror(req
, ERRDOS
,
4223 END_PROFILE(SMBlseek
);
4227 current_pos
+= sbuf
.st_size
;
4229 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4234 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
4235 END_PROFILE(SMBlseek
);
4242 reply_outbuf(req
, 2, 0);
4243 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4245 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4246 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4248 END_PROFILE(SMBlseek
);
4252 /****************************************************************************
4254 ****************************************************************************/
4256 void reply_flush(struct smb_request
*req
)
4258 connection_struct
*conn
= req
->conn
;
4262 START_PROFILE(SMBflush
);
4265 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4269 fnum
= SVAL(req
->vwv
+0, 0);
4270 fsp
= file_fsp(req
, fnum
);
4272 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4277 file_sync_all(conn
);
4279 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4280 if (!NT_STATUS_IS_OK(status
)) {
4281 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4282 fsp
->fsp_name
, nt_errstr(status
) ));
4283 reply_nterror(req
, status
);
4284 END_PROFILE(SMBflush
);
4289 reply_outbuf(req
, 0, 0);
4291 DEBUG(3,("flush\n"));
4292 END_PROFILE(SMBflush
);
4296 /****************************************************************************
4298 conn POINTER CAN BE NULL HERE !
4299 ****************************************************************************/
4301 void reply_exit(struct smb_request
*req
)
4303 START_PROFILE(SMBexit
);
4305 file_close_pid(req
->smbpid
, req
->vuid
);
4307 reply_outbuf(req
, 0, 0);
4309 DEBUG(3,("exit\n"));
4311 END_PROFILE(SMBexit
);
4315 /****************************************************************************
4316 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4317 ****************************************************************************/
4319 void reply_close(struct smb_request
*req
)
4321 connection_struct
*conn
= req
->conn
;
4322 NTSTATUS status
= NT_STATUS_OK
;
4323 files_struct
*fsp
= NULL
;
4324 START_PROFILE(SMBclose
);
4327 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4328 END_PROFILE(SMBclose
);
4332 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4335 * We can only use check_fsp if we know it's not a directory.
4338 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= req
->vuid
)) {
4339 reply_doserror(req
, ERRDOS
, ERRbadfid
);
4340 END_PROFILE(SMBclose
);
4344 if(fsp
->is_directory
) {
4346 * Special case - close NT SMB directory handle.
4348 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4349 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4353 * Close ordinary file.
4356 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4357 fsp
->fh
->fd
, fsp
->fnum
,
4358 conn
->num_files_open
));
4361 * Take care of any time sent in the close.
4364 t
= srv_make_unix_date3(req
->vwv
+1);
4365 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4368 * close_file() returns the unix errno if an error
4369 * was detected on close - normally this is due to
4370 * a disk full error. If not then it was probably an I/O error.
4373 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4376 if (!NT_STATUS_IS_OK(status
)) {
4377 reply_nterror(req
, status
);
4378 END_PROFILE(SMBclose
);
4382 reply_outbuf(req
, 0, 0);
4383 END_PROFILE(SMBclose
);
4387 /****************************************************************************
4388 Reply to a writeclose (Core+ protocol).
4389 ****************************************************************************/
4391 void reply_writeclose(struct smb_request
*req
)
4393 connection_struct
*conn
= req
->conn
;
4395 ssize_t nwritten
= -1;
4396 NTSTATUS close_status
= NT_STATUS_OK
;
4399 struct timespec mtime
;
4402 START_PROFILE(SMBwriteclose
);
4405 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4406 END_PROFILE(SMBwriteclose
);
4410 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4412 if (!check_fsp(conn
, req
, fsp
)) {
4413 END_PROFILE(SMBwriteclose
);
4416 if (!CHECK_WRITE(fsp
)) {
4417 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
4418 END_PROFILE(SMBwriteclose
);
4422 numtowrite
= SVAL(req
->vwv
+1, 0);
4423 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4424 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4425 data
= (const char *)req
->buf
+ 1;
4428 && is_locked(fsp
, (uint32
)req
->smbpid
, (uint64_t)numtowrite
,
4429 (uint64_t)startpos
, WRITE_LOCK
)) {
4430 reply_doserror(req
, ERRDOS
,ERRlock
);
4431 END_PROFILE(SMBwriteclose
);
4435 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4437 set_close_write_time(fsp
, mtime
);
4440 * More insanity. W2K only closes the file if writelen > 0.
4445 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4447 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4450 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4451 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4452 conn
->num_files_open
));
4454 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4455 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4456 END_PROFILE(SMBwriteclose
);
4460 if(!NT_STATUS_IS_OK(close_status
)) {
4461 reply_nterror(req
, close_status
);
4462 END_PROFILE(SMBwriteclose
);
4466 reply_outbuf(req
, 1, 0);
4468 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4469 END_PROFILE(SMBwriteclose
);
4474 #define DBGC_CLASS DBGC_LOCKING
4476 /****************************************************************************
4478 ****************************************************************************/
4480 void reply_lock(struct smb_request
*req
)
4482 connection_struct
*conn
= req
->conn
;
4483 uint64_t count
,offset
;
4486 struct byte_range_lock
*br_lck
= NULL
;
4488 START_PROFILE(SMBlock
);
4491 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4492 END_PROFILE(SMBlock
);
4496 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4498 if (!check_fsp(conn
, req
, fsp
)) {
4499 END_PROFILE(SMBlock
);
4503 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
4504 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
4506 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4507 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
4509 br_lck
= do_lock(smbd_messaging_context(),
4516 False
, /* Non-blocking lock. */
4521 TALLOC_FREE(br_lck
);
4523 if (NT_STATUS_V(status
)) {
4524 reply_nterror(req
, status
);
4525 END_PROFILE(SMBlock
);
4529 reply_outbuf(req
, 0, 0);
4531 END_PROFILE(SMBlock
);
4535 /****************************************************************************
4537 ****************************************************************************/
4539 void reply_unlock(struct smb_request
*req
)
4541 connection_struct
*conn
= req
->conn
;
4542 uint64_t count
,offset
;
4546 START_PROFILE(SMBunlock
);
4549 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4550 END_PROFILE(SMBunlock
);
4554 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4556 if (!check_fsp(conn
, req
, fsp
)) {
4557 END_PROFILE(SMBunlock
);
4561 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
4562 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
4564 status
= do_unlock(smbd_messaging_context(),
4571 if (NT_STATUS_V(status
)) {
4572 reply_nterror(req
, status
);
4573 END_PROFILE(SMBunlock
);
4577 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4578 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
4580 reply_outbuf(req
, 0, 0);
4582 END_PROFILE(SMBunlock
);
4587 #define DBGC_CLASS DBGC_ALL
4589 /****************************************************************************
4591 conn POINTER CAN BE NULL HERE !
4592 ****************************************************************************/
4594 void reply_tdis(struct smb_request
*req
)
4596 connection_struct
*conn
= req
->conn
;
4597 START_PROFILE(SMBtdis
);
4600 DEBUG(4,("Invalid connection in tdis\n"));
4601 reply_doserror(req
, ERRSRV
, ERRinvnid
);
4602 END_PROFILE(SMBtdis
);
4608 close_cnum(conn
,req
->vuid
);
4611 reply_outbuf(req
, 0, 0);
4612 END_PROFILE(SMBtdis
);
4616 /****************************************************************************
4618 conn POINTER CAN BE NULL HERE !
4619 ****************************************************************************/
4621 void reply_echo(struct smb_request
*req
)
4623 connection_struct
*conn
= req
->conn
;
4627 START_PROFILE(SMBecho
);
4630 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4631 END_PROFILE(SMBecho
);
4635 smb_reverb
= SVAL(req
->vwv
+0, 0);
4637 reply_outbuf(req
, 1, req
->buflen
);
4639 /* copy any incoming data back out */
4640 if (req
->buflen
> 0) {
4641 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
4644 if (smb_reverb
> 100) {
4645 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
4649 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
4650 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
4652 show_msg((char *)req
->outbuf
);
4653 if (!srv_send_smb(smbd_server_fd(),
4654 (char *)req
->outbuf
,
4655 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
4657 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4660 DEBUG(3,("echo %d times\n", smb_reverb
));
4662 TALLOC_FREE(req
->outbuf
);
4664 END_PROFILE(SMBecho
);
4668 /****************************************************************************
4669 Reply to a printopen.
4670 ****************************************************************************/
4672 void reply_printopen(struct smb_request
*req
)
4674 connection_struct
*conn
= req
->conn
;
4676 SMB_STRUCT_STAT sbuf
;
4679 START_PROFILE(SMBsplopen
);
4682 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4683 END_PROFILE(SMBsplopen
);
4687 if (!CAN_PRINT(conn
)) {
4688 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4689 END_PROFILE(SMBsplopen
);
4693 status
= file_new(req
, conn
, &fsp
);
4694 if(!NT_STATUS_IS_OK(status
)) {
4695 reply_nterror(req
, status
);
4696 END_PROFILE(SMBsplopen
);
4700 /* Open for exclusive use, write only. */
4701 status
= print_fsp_open(req
, conn
, NULL
, req
->vuid
, fsp
, &sbuf
);
4703 if (!NT_STATUS_IS_OK(status
)) {
4704 reply_nterror(req
, status
);
4705 END_PROFILE(SMBsplopen
);
4709 reply_outbuf(req
, 1, 0);
4710 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
4712 DEBUG(3,("openprint fd=%d fnum=%d\n",
4713 fsp
->fh
->fd
, fsp
->fnum
));
4715 END_PROFILE(SMBsplopen
);
4719 /****************************************************************************
4720 Reply to a printclose.
4721 ****************************************************************************/
4723 void reply_printclose(struct smb_request
*req
)
4725 connection_struct
*conn
= req
->conn
;
4729 START_PROFILE(SMBsplclose
);
4732 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4733 END_PROFILE(SMBsplclose
);
4737 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4739 if (!check_fsp(conn
, req
, fsp
)) {
4740 END_PROFILE(SMBsplclose
);
4744 if (!CAN_PRINT(conn
)) {
4745 reply_nterror(req
, NT_STATUS_DOS(ERRSRV
, ERRerror
));
4746 END_PROFILE(SMBsplclose
);
4750 DEBUG(3,("printclose fd=%d fnum=%d\n",
4751 fsp
->fh
->fd
,fsp
->fnum
));
4753 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4755 if(!NT_STATUS_IS_OK(status
)) {
4756 reply_nterror(req
, status
);
4757 END_PROFILE(SMBsplclose
);
4761 reply_outbuf(req
, 0, 0);
4763 END_PROFILE(SMBsplclose
);
4767 /****************************************************************************
4768 Reply to a printqueue.
4769 ****************************************************************************/
4771 void reply_printqueue(struct smb_request
*req
)
4773 connection_struct
*conn
= req
->conn
;
4777 START_PROFILE(SMBsplretq
);
4780 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4781 END_PROFILE(SMBsplretq
);
4785 max_count
= SVAL(req
->vwv
+0, 0);
4786 start_index
= SVAL(req
->vwv
+1, 0);
4788 /* we used to allow the client to get the cnum wrong, but that
4789 is really quite gross and only worked when there was only
4790 one printer - I think we should now only accept it if they
4791 get it right (tridge) */
4792 if (!CAN_PRINT(conn
)) {
4793 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4794 END_PROFILE(SMBsplretq
);
4798 reply_outbuf(req
, 2, 3);
4799 SSVAL(req
->outbuf
,smb_vwv0
,0);
4800 SSVAL(req
->outbuf
,smb_vwv1
,0);
4801 SCVAL(smb_buf(req
->outbuf
),0,1);
4802 SSVAL(smb_buf(req
->outbuf
),1,0);
4804 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4805 start_index
, max_count
));
4808 print_queue_struct
*queue
= NULL
;
4809 print_status_struct status
;
4810 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
4811 int num_to_get
= ABS(max_count
);
4812 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
4818 num_to_get
= MIN(num_to_get
,count
-first
);
4821 for (i
=first
;i
<first
+num_to_get
;i
++) {
4825 srv_put_dos_date2(p
,0,queue
[i
].time
);
4826 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
4827 SSVAL(p
,5, queue
[i
].job
);
4828 SIVAL(p
,7,queue
[i
].size
);
4830 srvstr_push(blob
, req
->flags2
, p
+12,
4831 queue
[i
].fs_user
, 16, STR_ASCII
);
4833 if (message_push_blob(
4836 blob
, sizeof(blob
))) == -1) {
4837 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4838 END_PROFILE(SMBsplretq
);
4844 SSVAL(req
->outbuf
,smb_vwv0
,count
);
4845 SSVAL(req
->outbuf
,smb_vwv1
,
4846 (max_count
>0?first
+count
:first
-1));
4847 SCVAL(smb_buf(req
->outbuf
),0,1);
4848 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
4853 DEBUG(3,("%d entries returned in queue\n",count
));
4856 END_PROFILE(SMBsplretq
);
4860 /****************************************************************************
4861 Reply to a printwrite.
4862 ****************************************************************************/
4864 void reply_printwrite(struct smb_request
*req
)
4866 connection_struct
*conn
= req
->conn
;
4871 START_PROFILE(SMBsplwr
);
4874 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4875 END_PROFILE(SMBsplwr
);
4879 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4881 if (!check_fsp(conn
, req
, fsp
)) {
4882 END_PROFILE(SMBsplwr
);
4886 if (!CAN_PRINT(conn
)) {
4887 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4888 END_PROFILE(SMBsplwr
);
4892 if (!CHECK_WRITE(fsp
)) {
4893 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4894 END_PROFILE(SMBsplwr
);
4898 numtowrite
= SVAL(req
->buf
, 1);
4900 if (req
->buflen
< numtowrite
+ 3) {
4901 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4902 END_PROFILE(SMBsplwr
);
4906 data
= (const char *)req
->buf
+ 3;
4908 if (write_file(req
,fsp
,data
,-1,numtowrite
) != numtowrite
) {
4909 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
4910 END_PROFILE(SMBsplwr
);
4914 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
4916 END_PROFILE(SMBsplwr
);
4920 /****************************************************************************
4922 ****************************************************************************/
4924 void reply_mkdir(struct smb_request
*req
)
4926 connection_struct
*conn
= req
->conn
;
4927 char *directory
= NULL
;
4929 SMB_STRUCT_STAT sbuf
;
4930 TALLOC_CTX
*ctx
= talloc_tos();
4932 START_PROFILE(SMBmkdir
);
4934 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
4935 STR_TERMINATE
, &status
);
4936 if (!NT_STATUS_IS_OK(status
)) {
4937 reply_nterror(req
, status
);
4938 END_PROFILE(SMBmkdir
);
4942 status
= resolve_dfspath(ctx
, conn
,
4943 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
4946 if (!NT_STATUS_IS_OK(status
)) {
4947 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4948 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
4949 ERRSRV
, ERRbadpath
);
4950 END_PROFILE(SMBmkdir
);
4953 reply_nterror(req
, status
);
4954 END_PROFILE(SMBmkdir
);
4958 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
, NULL
, &sbuf
);
4959 if (!NT_STATUS_IS_OK(status
)) {
4960 reply_nterror(req
, status
);
4961 END_PROFILE(SMBmkdir
);
4965 status
= check_name(conn
, directory
);
4966 if (!NT_STATUS_IS_OK(status
)) {
4967 reply_nterror(req
, status
);
4968 END_PROFILE(SMBmkdir
);
4972 status
= create_directory(conn
, req
, directory
);
4974 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
4976 if (!NT_STATUS_IS_OK(status
)) {
4978 if (!use_nt_status()
4979 && NT_STATUS_EQUAL(status
,
4980 NT_STATUS_OBJECT_NAME_COLLISION
)) {
4982 * Yes, in the DOS error code case we get a
4983 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4984 * samba4 torture test.
4986 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
4989 reply_nterror(req
, status
);
4990 END_PROFILE(SMBmkdir
);
4994 reply_outbuf(req
, 0, 0);
4996 DEBUG( 3, ( "mkdir %s\n", directory
) );
4998 END_PROFILE(SMBmkdir
);
5002 /****************************************************************************
5003 Static function used by reply_rmdir to delete an entire directory
5004 tree recursively. Return True on ok, False on fail.
5005 ****************************************************************************/
5007 static bool recursive_rmdir(TALLOC_CTX
*ctx
,
5008 connection_struct
*conn
,
5011 const char *dname
= NULL
;
5015 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
, directory
,
5021 while((dname
= ReadDirName(dir_hnd
, &offset
, &st
))) {
5022 char *fullname
= NULL
;
5024 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5028 if (!is_visible_file(conn
, directory
, dname
, &st
, False
)) {
5032 /* Construct the full name. */
5033 fullname
= talloc_asprintf(ctx
,
5043 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
5048 if(st
.st_mode
& S_IFDIR
) {
5049 if(!recursive_rmdir(ctx
, conn
, fullname
)) {
5053 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
5057 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
5061 TALLOC_FREE(fullname
);
5063 TALLOC_FREE(dir_hnd
);
5067 /****************************************************************************
5068 The internals of the rmdir code - called elsewhere.
5069 ****************************************************************************/
5071 NTSTATUS
rmdir_internals(TALLOC_CTX
*ctx
,
5072 connection_struct
*conn
,
5073 const char *directory
)
5078 /* Might be a symlink. */
5079 if(SMB_VFS_LSTAT(conn
, directory
, &st
) != 0) {
5080 return map_nt_error_from_unix(errno
);
5083 if (S_ISLNK(st
.st_mode
)) {
5084 /* Is what it points to a directory ? */
5085 if(SMB_VFS_STAT(conn
, directory
, &st
) != 0) {
5086 return map_nt_error_from_unix(errno
);
5088 if (!(S_ISDIR(st
.st_mode
))) {
5089 return NT_STATUS_NOT_A_DIRECTORY
;
5091 ret
= SMB_VFS_UNLINK(conn
,directory
);
5093 ret
= SMB_VFS_RMDIR(conn
,directory
);
5096 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5097 FILE_NOTIFY_CHANGE_DIR_NAME
,
5099 return NT_STATUS_OK
;
5102 if(((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
5104 * Check to see if the only thing in this directory are
5105 * vetoed files/directories. If so then delete them and
5106 * retry. If we fail to delete any of them (and we *don't*
5107 * do a recursive delete) then fail the rmdir.
5111 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
,
5112 directory
, NULL
, 0);
5114 if(dir_hnd
== NULL
) {
5119 while ((dname
= ReadDirName(dir_hnd
, &dirpos
, &st
))) {
5120 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
5122 if (!is_visible_file(conn
, directory
, dname
, &st
, False
))
5124 if(!IS_VETO_PATH(conn
, dname
)) {
5125 TALLOC_FREE(dir_hnd
);
5131 /* We only have veto files/directories.
5132 * Are we allowed to delete them ? */
5134 if(!lp_recursive_veto_delete(SNUM(conn
))) {
5135 TALLOC_FREE(dir_hnd
);
5140 /* Do a recursive delete. */
5141 RewindDir(dir_hnd
,&dirpos
);
5142 while ((dname
= ReadDirName(dir_hnd
, &dirpos
, &st
))) {
5143 char *fullname
= NULL
;
5145 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5148 if (!is_visible_file(conn
, directory
, dname
, &st
, False
)) {
5152 fullname
= talloc_asprintf(ctx
,
5162 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
5165 if(st
.st_mode
& S_IFDIR
) {
5166 if(!recursive_rmdir(ctx
, conn
, fullname
)) {
5169 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
5172 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
5175 TALLOC_FREE(fullname
);
5177 TALLOC_FREE(dir_hnd
);
5178 /* Retry the rmdir */
5179 ret
= SMB_VFS_RMDIR(conn
,directory
);
5185 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5186 "%s\n", directory
,strerror(errno
)));
5187 return map_nt_error_from_unix(errno
);
5190 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5191 FILE_NOTIFY_CHANGE_DIR_NAME
,
5194 return NT_STATUS_OK
;
5197 /****************************************************************************
5199 ****************************************************************************/
5201 void reply_rmdir(struct smb_request
*req
)
5203 connection_struct
*conn
= req
->conn
;
5204 char *directory
= NULL
;
5205 SMB_STRUCT_STAT sbuf
;
5207 TALLOC_CTX
*ctx
= talloc_tos();
5209 START_PROFILE(SMBrmdir
);
5211 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5212 STR_TERMINATE
, &status
);
5213 if (!NT_STATUS_IS_OK(status
)) {
5214 reply_nterror(req
, status
);
5215 END_PROFILE(SMBrmdir
);
5219 status
= resolve_dfspath(ctx
, conn
,
5220 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5223 if (!NT_STATUS_IS_OK(status
)) {
5224 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5225 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5226 ERRSRV
, ERRbadpath
);
5227 END_PROFILE(SMBrmdir
);
5230 reply_nterror(req
, status
);
5231 END_PROFILE(SMBrmdir
);
5235 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
,
5237 if (!NT_STATUS_IS_OK(status
)) {
5238 reply_nterror(req
, status
);
5239 END_PROFILE(SMBrmdir
);
5243 status
= check_name(conn
, directory
);
5244 if (!NT_STATUS_IS_OK(status
)) {
5245 reply_nterror(req
, status
);
5246 END_PROFILE(SMBrmdir
);
5250 dptr_closepath(directory
, req
->smbpid
);
5251 status
= rmdir_internals(ctx
, conn
, directory
);
5252 if (!NT_STATUS_IS_OK(status
)) {
5253 reply_nterror(req
, status
);
5254 END_PROFILE(SMBrmdir
);
5258 reply_outbuf(req
, 0, 0);
5260 DEBUG( 3, ( "rmdir %s\n", directory
) );
5262 END_PROFILE(SMBrmdir
);
5266 /*******************************************************************
5267 Resolve wildcards in a filename rename.
5268 ********************************************************************/
5270 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5275 char *name2_copy
= NULL
;
5280 char *p
,*p2
, *pname1
, *pname2
;
5282 name2_copy
= talloc_strdup(ctx
, name2
);
5287 pname1
= strrchr_m(name1
,'/');
5288 pname2
= strrchr_m(name2_copy
,'/');
5290 if (!pname1
|| !pname2
) {
5294 /* Truncate the copy of name2 at the last '/' */
5297 /* Now go past the '/' */
5301 root1
= talloc_strdup(ctx
, pname1
);
5302 root2
= talloc_strdup(ctx
, pname2
);
5304 if (!root1
|| !root2
) {
5308 p
= strrchr_m(root1
,'.');
5311 ext1
= talloc_strdup(ctx
, p
+1);
5313 ext1
= talloc_strdup(ctx
, "");
5315 p
= strrchr_m(root2
,'.');
5318 ext2
= talloc_strdup(ctx
, p
+1);
5320 ext2
= talloc_strdup(ctx
, "");
5323 if (!ext1
|| !ext2
) {
5331 /* Hmmm. Should this be mb-aware ? */
5334 } else if (*p2
== '*') {
5336 root2
= talloc_asprintf(ctx
, "%s%s",
5355 /* Hmmm. Should this be mb-aware ? */
5358 } else if (*p2
== '*') {
5360 ext2
= talloc_asprintf(ctx
, "%s%s",
5376 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5381 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5393 /****************************************************************************
5394 Ensure open files have their names updated. Updated to notify other smbd's
5396 ****************************************************************************/
5398 static void rename_open_files(connection_struct
*conn
,
5399 struct share_mode_lock
*lck
,
5400 const char *newname
)
5403 bool did_rename
= False
;
5405 for(fsp
= file_find_di_first(lck
->id
); fsp
;
5406 fsp
= file_find_di_next(fsp
)) {
5407 /* fsp_name is a relative path under the fsp. To change this for other
5408 sharepaths we need to manipulate relative paths. */
5409 /* TODO - create the absolute path and manipulate the newname
5410 relative to the sharepath. */
5411 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5414 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5415 fsp
->fnum
, file_id_string_tos(&fsp
->file_id
),
5416 fsp
->fsp_name
, newname
));
5417 string_set(&fsp
->fsp_name
, newname
);
5422 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5423 file_id_string_tos(&lck
->id
), newname
));
5426 /* Send messages to all smbd's (not ourself) that the name has changed. */
5427 rename_share_filename(smbd_messaging_context(), lck
, conn
->connectpath
,
5431 /****************************************************************************
5432 We need to check if the source path is a parent directory of the destination
5433 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5434 refuse the rename with a sharing violation. Under UNIX the above call can
5435 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5436 probably need to check that the client is a Windows one before disallowing
5437 this as a UNIX client (one with UNIX extensions) can know the source is a
5438 symlink and make this decision intelligently. Found by an excellent bug
5439 report from <AndyLiebman@aol.com>.
5440 ****************************************************************************/
5442 static bool rename_path_prefix_equal(const char *src
, const char *dest
)
5444 const char *psrc
= src
;
5445 const char *pdst
= dest
;
5448 if (psrc
[0] == '.' && psrc
[1] == '/') {
5451 if (pdst
[0] == '.' && pdst
[1] == '/') {
5454 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5457 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5461 * Do the notify calls from a rename
5464 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5465 const char *oldpath
, const char *newpath
)
5467 char *olddir
, *newdir
;
5468 const char *oldname
, *newname
;
5471 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5472 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5474 if (!parent_dirname(talloc_tos(), oldpath
, &olddir
, &oldname
)
5475 || !parent_dirname(talloc_tos(), newpath
, &newdir
, &newname
)) {
5476 TALLOC_FREE(olddir
);
5480 if (strcmp(olddir
, newdir
) == 0) {
5481 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
, oldpath
);
5482 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
, newpath
);
5485 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
, oldpath
);
5486 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
, newpath
);
5488 TALLOC_FREE(olddir
);
5489 TALLOC_FREE(newdir
);
5491 /* this is a strange one. w2k3 gives an additional event for
5492 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5493 files, but not directories */
5495 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5496 FILE_NOTIFY_CHANGE_ATTRIBUTES
5497 |FILE_NOTIFY_CHANGE_CREATION
,
5502 /****************************************************************************
5503 Rename an open file - given an fsp.
5504 ****************************************************************************/
5506 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
5509 const char *newname_last_component
,
5511 bool replace_if_exists
)
5513 TALLOC_CTX
*ctx
= talloc_tos();
5514 SMB_STRUCT_STAT sbuf
, sbuf1
;
5515 NTSTATUS status
= NT_STATUS_OK
;
5516 struct share_mode_lock
*lck
= NULL
;
5517 bool dst_exists
, old_is_stream
, new_is_stream
;
5521 status
= check_name(conn
, newname
);
5522 if (!NT_STATUS_IS_OK(status
)) {
5526 /* Ensure newname contains a '/' */
5527 if(strrchr_m(newname
,'/') == 0) {
5528 newname
= talloc_asprintf(ctx
,
5532 return NT_STATUS_NO_MEMORY
;
5537 * Check for special case with case preserving and not
5538 * case sensitive. If the old last component differs from the original
5539 * last component only by case, then we should allow
5540 * the rename (user is trying to change the case of the
5544 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
5545 strequal(newname
, fsp
->fsp_name
)) {
5547 char *newname_modified_last_component
= NULL
;
5550 * Get the last component of the modified name.
5551 * Note that we guarantee that newname contains a '/'
5554 p
= strrchr_m(newname
,'/');
5555 newname_modified_last_component
= talloc_strdup(ctx
,
5557 if (!newname_modified_last_component
) {
5558 return NT_STATUS_NO_MEMORY
;
5561 if(strcsequal(newname_modified_last_component
,
5562 newname_last_component
) == False
) {
5564 * Replace the modified last component with
5567 *p
= '\0'; /* Truncate at the '/' */
5568 newname
= talloc_asprintf(ctx
,
5571 newname_last_component
);
5576 * If the src and dest names are identical - including case,
5577 * don't do the rename, just return success.
5580 if (strcsequal(fsp
->fsp_name
, newname
)) {
5581 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5583 return NT_STATUS_OK
;
5586 old_is_stream
= is_ntfs_stream_name(fsp
->fsp_name
);
5587 new_is_stream
= is_ntfs_stream_name(newname
);
5589 /* Return the correct error code if both names aren't streams. */
5590 if (!old_is_stream
&& new_is_stream
) {
5591 return NT_STATUS_OBJECT_NAME_INVALID
;
5594 if (old_is_stream
&& !new_is_stream
) {
5595 return NT_STATUS_INVALID_PARAMETER
;
5599 * Have vfs_object_exist also fill sbuf1
5601 dst_exists
= vfs_object_exist(conn
, newname
, &sbuf1
);
5603 if(!replace_if_exists
&& dst_exists
) {
5604 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5605 fsp
->fsp_name
,newname
));
5606 return NT_STATUS_OBJECT_NAME_COLLISION
;
5610 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, &sbuf1
);
5611 files_struct
*dst_fsp
= file_find_di_first(fileid
);
5612 /* The file can be open when renaming a stream */
5613 if (dst_fsp
&& !new_is_stream
) {
5614 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5615 return NT_STATUS_ACCESS_DENIED
;
5619 /* Ensure we have a valid stat struct for the source. */
5620 if (fsp
->fh
->fd
!= -1) {
5621 if (SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
5622 return map_nt_error_from_unix(errno
);
5626 if (fsp
->posix_open
) {
5627 ret
= SMB_VFS_LSTAT(conn
,fsp
->fsp_name
,&sbuf
);
5629 ret
= SMB_VFS_STAT(conn
,fsp
->fsp_name
,&sbuf
);
5632 return map_nt_error_from_unix(errno
);
5636 status
= can_rename(conn
, fsp
, attrs
, &sbuf
);
5638 if (!NT_STATUS_IS_OK(status
)) {
5639 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5640 nt_errstr(status
), fsp
->fsp_name
,newname
));
5641 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
5642 status
= NT_STATUS_ACCESS_DENIED
;
5646 if (rename_path_prefix_equal(fsp
->fsp_name
, newname
)) {
5647 return NT_STATUS_ACCESS_DENIED
;
5650 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
5654 * We have the file open ourselves, so not being able to get the
5655 * corresponding share mode lock is a fatal error.
5658 SMB_ASSERT(lck
!= NULL
);
5660 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
5661 uint32 create_options
= fsp
->fh
->private_options
;
5663 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5664 fsp
->fsp_name
,newname
));
5666 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
, newname
);
5668 rename_open_files(conn
, lck
, newname
);
5671 * A rename acts as a new file create w.r.t. allowing an initial delete
5672 * on close, probably because in Windows there is a new handle to the
5673 * new file. If initial delete on close was requested but not
5674 * originally set, we need to set it here. This is probably not 100% correct,
5675 * but will work for the CIFSFS client which in non-posix mode
5676 * depends on these semantics. JRA.
5679 if (create_options
& FILE_DELETE_ON_CLOSE
) {
5680 status
= can_set_delete_on_close(fsp
, True
, 0);
5682 if (NT_STATUS_IS_OK(status
)) {
5683 /* Note that here we set the *inital* delete on close flag,
5684 * not the regular one. The magic gets handled in close. */
5685 fsp
->initial_delete_on_close
= True
;
5689 return NT_STATUS_OK
;
5694 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
5695 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
5697 status
= map_nt_error_from_unix(errno
);
5700 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5701 nt_errstr(status
), fsp
->fsp_name
,newname
));
5706 /****************************************************************************
5707 The guts of the rename command, split out so it may be called by the NT SMB
5709 ****************************************************************************/
5711 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
5712 connection_struct
*conn
,
5713 struct smb_request
*req
,
5714 const char *name_in
,
5715 const char *newname_in
,
5717 bool replace_if_exists
,
5720 uint32_t access_mask
)
5722 char *directory
= NULL
;
5724 char *last_component_src
= NULL
;
5725 char *last_component_dest
= NULL
;
5727 char *newname
= NULL
;
5730 NTSTATUS status
= NT_STATUS_OK
;
5731 SMB_STRUCT_STAT sbuf1
, sbuf2
;
5732 struct smb_Dir
*dir_hnd
= NULL
;
5735 int create_options
= 0;
5736 bool posix_pathnames
= lp_posix_pathnames();
5741 status
= unix_convert(ctx
, conn
, name_in
, src_has_wild
, &name
,
5742 &last_component_src
, &sbuf1
);
5743 if (!NT_STATUS_IS_OK(status
)) {
5747 status
= unix_convert(ctx
, conn
, newname_in
, dest_has_wild
, &newname
,
5748 &last_component_dest
, &sbuf2
);
5749 if (!NT_STATUS_IS_OK(status
)) {
5754 * Split the old name into directory and last component
5755 * strings. Note that unix_convert may have stripped off a
5756 * leading ./ from both name and newname if the rename is
5757 * at the root of the share. We need to make sure either both
5758 * name and newname contain a / character or neither of them do
5759 * as this is checked in resolve_wildcards().
5762 p
= strrchr_m(name
,'/');
5764 directory
= talloc_strdup(ctx
, ".");
5766 return NT_STATUS_NO_MEMORY
;
5771 directory
= talloc_strdup(ctx
, name
);
5773 return NT_STATUS_NO_MEMORY
;
5776 *p
= '/'; /* Replace needed for exceptional test below. */
5780 * We should only check the mangled cache
5781 * here if unix_convert failed. This means
5782 * that the path in 'mask' doesn't exist
5783 * on the file system and so we need to look
5784 * for a possible mangle. This patch from
5785 * Tine Smukavec <valentin.smukavec@hermes.si>.
5788 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
)) {
5789 char *new_mask
= NULL
;
5790 mangle_lookup_name_from_8_3(ctx
,
5799 if (!src_has_wild
) {
5803 * No wildcards - just process the one file.
5805 bool is_short_name
= mangle_is_8_3(name
, True
, conn
->params
);
5807 /* Add a terminating '/' to the directory name. */
5808 directory
= talloc_asprintf_append(directory
,
5812 return NT_STATUS_NO_MEMORY
;
5815 /* Ensure newname contains a '/' also */
5816 if(strrchr_m(newname
,'/') == 0) {
5817 newname
= talloc_asprintf(ctx
,
5821 return NT_STATUS_NO_MEMORY
;
5825 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5826 "case_preserve = %d, short case preserve = %d, "
5827 "directory = %s, newname = %s, "
5828 "last_component_dest = %s, is_8_3 = %d\n",
5829 conn
->case_sensitive
, conn
->case_preserve
,
5830 conn
->short_case_preserve
, directory
,
5831 newname
, last_component_dest
, is_short_name
));
5833 /* The dest name still may have wildcards. */
5834 if (dest_has_wild
) {
5835 char *mod_newname
= NULL
;
5836 if (!resolve_wildcards(ctx
,
5837 directory
,newname
,&mod_newname
)) {
5838 DEBUG(6, ("rename_internals: resolve_wildcards "
5842 return NT_STATUS_NO_MEMORY
;
5844 newname
= mod_newname
;
5848 if (posix_pathnames
) {
5849 SMB_VFS_LSTAT(conn
, directory
, &sbuf1
);
5851 SMB_VFS_STAT(conn
, directory
, &sbuf1
);
5854 if (S_ISDIR(sbuf1
.st_mode
)) {
5855 create_options
|= FILE_DIRECTORY_FILE
;
5858 status
= SMB_VFS_CREATE_FILE(
5861 0, /* root_dir_fid */
5862 directory
, /* fname */
5863 0, /* create_file_flags */
5864 access_mask
, /* access_mask */
5865 (FILE_SHARE_READ
| /* share_access */
5867 FILE_OPEN
, /* create_disposition*/
5868 create_options
, /* create_options */
5869 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
5870 0, /* oplock_request */
5871 0, /* allocation_size */
5876 &sbuf1
); /* psbuf */
5878 if (!NT_STATUS_IS_OK(status
)) {
5879 DEBUG(3, ("Could not open rename source %s: %s\n",
5880 directory
, nt_errstr(status
)));
5884 status
= rename_internals_fsp(conn
, fsp
, newname
,
5885 last_component_dest
,
5886 attrs
, replace_if_exists
);
5888 close_file(req
, fsp
, NORMAL_CLOSE
);
5890 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5891 nt_errstr(status
), directory
,newname
));
5897 * Wildcards - process each file that matches.
5899 if (strequal(mask
,"????????.???")) {
5904 status
= check_name(conn
, directory
);
5905 if (!NT_STATUS_IS_OK(status
)) {
5909 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
, attrs
);
5910 if (dir_hnd
== NULL
) {
5911 return map_nt_error_from_unix(errno
);
5914 status
= NT_STATUS_NO_SUCH_FILE
;
5916 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5917 * - gentest fix. JRA
5920 while ((dname
= ReadDirName(dir_hnd
, &offset
, &sbuf1
))) {
5921 files_struct
*fsp
= NULL
;
5923 char *destname
= NULL
;
5924 bool sysdir_entry
= False
;
5926 /* Quick check for "." and ".." */
5927 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5929 sysdir_entry
= True
;
5935 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
)) {
5939 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
5944 status
= NT_STATUS_OBJECT_NAME_INVALID
;
5948 fname
= talloc_asprintf(ctx
,
5953 return NT_STATUS_NO_MEMORY
;
5956 if (!resolve_wildcards(ctx
,
5957 fname
,newname
,&destname
)) {
5958 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5964 return NT_STATUS_NO_MEMORY
;
5968 if (posix_pathnames
) {
5969 SMB_VFS_LSTAT(conn
, fname
, &sbuf1
);
5971 SMB_VFS_STAT(conn
, fname
, &sbuf1
);
5976 if (S_ISDIR(sbuf1
.st_mode
)) {
5977 create_options
|= FILE_DIRECTORY_FILE
;
5980 status
= SMB_VFS_CREATE_FILE(
5983 0, /* root_dir_fid */
5985 0, /* create_file_flags */
5986 access_mask
, /* access_mask */
5987 (FILE_SHARE_READ
| /* share_access */
5989 FILE_OPEN
, /* create_disposition*/
5990 create_options
, /* create_options */
5991 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
5992 0, /* oplock_request */
5993 0, /* allocation_size */
5998 &sbuf1
); /* psbuf */
6000 if (!NT_STATUS_IS_OK(status
)) {
6001 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6002 "returned %s rename %s -> %s\n",
6003 nt_errstr(status
), directory
, newname
));
6007 status
= rename_internals_fsp(conn
, fsp
, destname
, dname
,
6008 attrs
, replace_if_exists
);
6010 close_file(req
, fsp
, NORMAL_CLOSE
);
6012 if (!NT_STATUS_IS_OK(status
)) {
6013 DEBUG(3, ("rename_internals_fsp returned %s for "
6014 "rename %s -> %s\n", nt_errstr(status
),
6015 directory
, newname
));
6021 DEBUG(3,("rename_internals: doing rename on %s -> "
6022 "%s\n",fname
,destname
));
6025 TALLOC_FREE(destname
);
6027 TALLOC_FREE(dir_hnd
);
6029 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6030 status
= map_nt_error_from_unix(errno
);
6036 /****************************************************************************
6038 ****************************************************************************/
6040 void reply_mv(struct smb_request
*req
)
6042 connection_struct
*conn
= req
->conn
;
6044 char *newname
= NULL
;
6048 bool src_has_wcard
= False
;
6049 bool dest_has_wcard
= False
;
6050 TALLOC_CTX
*ctx
= talloc_tos();
6052 START_PROFILE(SMBmv
);
6055 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6060 attrs
= SVAL(req
->vwv
+0, 0);
6062 p
= (const char *)req
->buf
+ 1;
6063 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6064 &status
, &src_has_wcard
);
6065 if (!NT_STATUS_IS_OK(status
)) {
6066 reply_nterror(req
, status
);
6071 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6072 &status
, &dest_has_wcard
);
6073 if (!NT_STATUS_IS_OK(status
)) {
6074 reply_nterror(req
, status
);
6079 status
= resolve_dfspath_wcard(ctx
, conn
,
6080 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6084 if (!NT_STATUS_IS_OK(status
)) {
6085 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6086 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6087 ERRSRV
, ERRbadpath
);
6091 reply_nterror(req
, status
);
6096 status
= resolve_dfspath_wcard(ctx
, conn
,
6097 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6101 if (!NT_STATUS_IS_OK(status
)) {
6102 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6103 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6104 ERRSRV
, ERRbadpath
);
6108 reply_nterror(req
, status
);
6113 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
6115 status
= rename_internals(ctx
, conn
, req
, name
, newname
, attrs
, False
,
6116 src_has_wcard
, dest_has_wcard
, DELETE_ACCESS
);
6117 if (!NT_STATUS_IS_OK(status
)) {
6118 if (open_was_deferred(req
->mid
)) {
6119 /* We have re-scheduled this call. */
6123 reply_nterror(req
, status
);
6128 reply_outbuf(req
, 0, 0);
6134 /*******************************************************************
6135 Copy a file as part of a reply_copy.
6136 ******************************************************************/
6139 * TODO: check error codes on all callers
6142 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6143 connection_struct
*conn
,
6148 bool target_is_directory
)
6150 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
6152 files_struct
*fsp1
,*fsp2
;
6155 uint32 new_create_disposition
;
6158 dest
= talloc_strdup(ctx
, dest1
);
6160 return NT_STATUS_NO_MEMORY
;
6162 if (target_is_directory
) {
6163 const char *p
= strrchr_m(src
,'/');
6169 dest
= talloc_asprintf_append(dest
,
6173 return NT_STATUS_NO_MEMORY
;
6177 if (!vfs_file_exist(conn
,src
,&src_sbuf
)) {
6179 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6182 if (!target_is_directory
&& count
) {
6183 new_create_disposition
= FILE_OPEN
;
6185 if (!map_open_params_to_ntcreate(dest1
,0,ofun
,
6186 NULL
, NULL
, &new_create_disposition
, NULL
)) {
6188 return NT_STATUS_INVALID_PARAMETER
;
6192 status
= SMB_VFS_CREATE_FILE(
6195 0, /* root_dir_fid */
6197 0, /* create_file_flags */
6198 FILE_GENERIC_READ
, /* access_mask */
6199 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6200 FILE_OPEN
, /* create_disposition*/
6201 0, /* create_options */
6202 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6203 INTERNAL_OPEN_ONLY
, /* oplock_request */
6204 0, /* allocation_size */
6209 &src_sbuf
); /* psbuf */
6211 if (!NT_STATUS_IS_OK(status
)) {
6216 dosattrs
= dos_mode(conn
, src
, &src_sbuf
);
6217 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1) {
6218 ZERO_STRUCTP(&sbuf2
);
6221 status
= SMB_VFS_CREATE_FILE(
6224 0, /* root_dir_fid */
6226 0, /* create_file_flags */
6227 FILE_GENERIC_WRITE
, /* access_mask */
6228 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6229 new_create_disposition
, /* create_disposition*/
6230 0, /* create_options */
6231 dosattrs
, /* file_attributes */
6232 INTERNAL_OPEN_ONLY
, /* oplock_request */
6233 0, /* allocation_size */
6238 &sbuf2
); /* psbuf */
6242 if (!NT_STATUS_IS_OK(status
)) {
6243 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6247 if ((ofun
&3) == 1) {
6248 if(SMB_VFS_LSEEK(fsp2
,0,SEEK_END
) == -1) {
6249 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
6251 * Stop the copy from occurring.
6254 src_sbuf
.st_size
= 0;
6258 if (src_sbuf
.st_size
) {
6259 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
6262 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
6264 /* Ensure the modtime is set correctly on the destination file. */
6265 set_close_write_time(fsp2
, get_mtimespec(&src_sbuf
));
6268 * As we are opening fsp1 read-only we only expect
6269 * an error on close on fsp2 if we are out of space.
6270 * Thus we don't look at the error return from the
6273 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
6275 if (!NT_STATUS_IS_OK(status
)) {
6279 if (ret
!= (SMB_OFF_T
)src_sbuf
.st_size
) {
6280 return NT_STATUS_DISK_FULL
;
6283 return NT_STATUS_OK
;
6286 /****************************************************************************
6287 Reply to a file copy.
6288 ****************************************************************************/
6290 void reply_copy(struct smb_request
*req
)
6292 connection_struct
*conn
= req
->conn
;
6294 char *newname
= NULL
;
6295 char *directory
= NULL
;
6296 const char *mask
= NULL
;
6297 const char mask_star
[] = "*";
6300 int error
= ERRnoaccess
;
6305 bool target_is_directory
=False
;
6306 bool source_has_wild
= False
;
6307 bool dest_has_wild
= False
;
6308 SMB_STRUCT_STAT sbuf1
, sbuf2
;
6310 TALLOC_CTX
*ctx
= talloc_tos();
6312 START_PROFILE(SMBcopy
);
6315 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6316 END_PROFILE(SMBcopy
);
6320 tid2
= SVAL(req
->vwv
+0, 0);
6321 ofun
= SVAL(req
->vwv
+1, 0);
6322 flags
= SVAL(req
->vwv
+2, 0);
6324 p
= (const char *)req
->buf
;
6325 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6326 &status
, &source_has_wild
);
6327 if (!NT_STATUS_IS_OK(status
)) {
6328 reply_nterror(req
, status
);
6329 END_PROFILE(SMBcopy
);
6332 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6333 &status
, &dest_has_wild
);
6334 if (!NT_STATUS_IS_OK(status
)) {
6335 reply_nterror(req
, status
);
6336 END_PROFILE(SMBcopy
);
6340 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
6342 if (tid2
!= conn
->cnum
) {
6343 /* can't currently handle inter share copies XXXX */
6344 DEBUG(3,("Rejecting inter-share copy\n"));
6345 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
6346 END_PROFILE(SMBcopy
);
6350 status
= resolve_dfspath_wcard(ctx
, conn
,
6351 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6355 if (!NT_STATUS_IS_OK(status
)) {
6356 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6357 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6358 ERRSRV
, ERRbadpath
);
6359 END_PROFILE(SMBcopy
);
6362 reply_nterror(req
, status
);
6363 END_PROFILE(SMBcopy
);
6367 status
= resolve_dfspath_wcard(ctx
, conn
,
6368 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6372 if (!NT_STATUS_IS_OK(status
)) {
6373 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6374 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6375 ERRSRV
, ERRbadpath
);
6376 END_PROFILE(SMBcopy
);
6379 reply_nterror(req
, status
);
6380 END_PROFILE(SMBcopy
);
6384 status
= unix_convert(ctx
, conn
, name
, source_has_wild
,
6385 &name
, NULL
, &sbuf1
);
6386 if (!NT_STATUS_IS_OK(status
)) {
6387 reply_nterror(req
, status
);
6388 END_PROFILE(SMBcopy
);
6392 status
= unix_convert(ctx
, conn
, newname
, dest_has_wild
,
6393 &newname
, NULL
, &sbuf2
);
6394 if (!NT_STATUS_IS_OK(status
)) {
6395 reply_nterror(req
, status
);
6396 END_PROFILE(SMBcopy
);
6400 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
6402 if ((flags
&1) && target_is_directory
) {
6403 reply_doserror(req
, ERRDOS
, ERRbadfile
);
6404 END_PROFILE(SMBcopy
);
6408 if ((flags
&2) && !target_is_directory
) {
6409 reply_doserror(req
, ERRDOS
, ERRbadpath
);
6410 END_PROFILE(SMBcopy
);
6414 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
6415 /* wants a tree copy! XXXX */
6416 DEBUG(3,("Rejecting tree copy\n"));
6417 reply_doserror(req
, ERRSRV
, ERRerror
);
6418 END_PROFILE(SMBcopy
);
6422 p
= strrchr_m(name
,'/');
6424 directory
= talloc_strndup(ctx
, name
, PTR_DIFF(p
, name
));
6427 directory
= talloc_strdup(ctx
, "./");
6432 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6433 END_PROFILE(SMBcopy
);
6438 * We should only check the mangled cache
6439 * here if unix_convert failed. This means
6440 * that the path in 'mask' doesn't exist
6441 * on the file system and so we need to look
6442 * for a possible mangle. This patch from
6443 * Tine Smukavec <valentin.smukavec@hermes.si>.
6446 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
)) {
6447 char *new_mask
= NULL
;
6448 mangle_lookup_name_from_8_3(ctx
,
6457 if (!source_has_wild
) {
6458 directory
= talloc_asprintf_append(directory
,
6461 if (dest_has_wild
) {
6462 char *mod_newname
= NULL
;
6463 if (!resolve_wildcards(ctx
,
6464 directory
,newname
,&mod_newname
)) {
6465 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6466 END_PROFILE(SMBcopy
);
6469 newname
= mod_newname
;
6472 status
= check_name(conn
, directory
);
6473 if (!NT_STATUS_IS_OK(status
)) {
6474 reply_nterror(req
, status
);
6475 END_PROFILE(SMBcopy
);
6479 status
= check_name(conn
, newname
);
6480 if (!NT_STATUS_IS_OK(status
)) {
6481 reply_nterror(req
, status
);
6482 END_PROFILE(SMBcopy
);
6486 status
= copy_file(ctx
,conn
,directory
,newname
,ofun
,
6487 count
,target_is_directory
);
6489 if(!NT_STATUS_IS_OK(status
)) {
6490 reply_nterror(req
, status
);
6491 END_PROFILE(SMBcopy
);
6497 struct smb_Dir
*dir_hnd
= NULL
;
6498 const char *dname
= NULL
;
6501 if (strequal(mask
,"????????.???")) {
6505 status
= check_name(conn
, directory
);
6506 if (!NT_STATUS_IS_OK(status
)) {
6507 reply_nterror(req
, status
);
6508 END_PROFILE(SMBcopy
);
6512 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
, 0);
6513 if (dir_hnd
== NULL
) {
6514 status
= map_nt_error_from_unix(errno
);
6515 reply_nterror(req
, status
);
6516 END_PROFILE(SMBcopy
);
6522 while ((dname
= ReadDirName(dir_hnd
, &offset
, &sbuf1
))) {
6523 char *destname
= NULL
;
6526 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6530 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
)) {
6534 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
6538 error
= ERRnoaccess
;
6539 fname
= talloc_asprintf(ctx
,
6544 TALLOC_FREE(dir_hnd
);
6545 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6546 END_PROFILE(SMBcopy
);
6550 if (!resolve_wildcards(ctx
,
6551 fname
,newname
,&destname
)) {
6555 TALLOC_FREE(dir_hnd
);
6556 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6557 END_PROFILE(SMBcopy
);
6561 status
= check_name(conn
, fname
);
6562 if (!NT_STATUS_IS_OK(status
)) {
6563 TALLOC_FREE(dir_hnd
);
6564 reply_nterror(req
, status
);
6565 END_PROFILE(SMBcopy
);
6569 status
= check_name(conn
, destname
);
6570 if (!NT_STATUS_IS_OK(status
)) {
6571 TALLOC_FREE(dir_hnd
);
6572 reply_nterror(req
, status
);
6573 END_PROFILE(SMBcopy
);
6577 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
, destname
));
6579 status
= copy_file(ctx
,conn
,fname
,destname
,ofun
,
6580 count
,target_is_directory
);
6581 if (NT_STATUS_IS_OK(status
)) {
6585 TALLOC_FREE(destname
);
6587 TALLOC_FREE(dir_hnd
);
6592 /* Error on close... */
6594 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
6595 END_PROFILE(SMBcopy
);
6599 reply_doserror(req
, ERRDOS
, error
);
6600 END_PROFILE(SMBcopy
);
6604 reply_outbuf(req
, 1, 0);
6605 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6607 END_PROFILE(SMBcopy
);
6612 #define DBGC_CLASS DBGC_LOCKING
6614 /****************************************************************************
6615 Get a lock pid, dealing with large count requests.
6616 ****************************************************************************/
6618 uint32
get_lock_pid(const uint8_t *data
, int data_offset
,
6619 bool large_file_format
)
6621 if(!large_file_format
)
6622 return (uint32
)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
6624 return (uint32
)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
6627 /****************************************************************************
6628 Get a lock count, dealing with large count requests.
6629 ****************************************************************************/
6631 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
6632 bool large_file_format
)
6636 if(!large_file_format
) {
6637 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
6640 #if defined(HAVE_LONGLONG)
6641 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
6642 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
6643 #else /* HAVE_LONGLONG */
6646 * NT4.x seems to be broken in that it sends large file (64 bit)
6647 * lockingX calls even if the CAP_LARGE_FILES was *not*
6648 * negotiated. For boxes without large unsigned ints truncate the
6649 * lock count by dropping the top 32 bits.
6652 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
6653 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6654 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
6655 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
6656 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
6659 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
6660 #endif /* HAVE_LONGLONG */
6666 #if !defined(HAVE_LONGLONG)
6667 /****************************************************************************
6668 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6669 ****************************************************************************/
6671 static uint32
map_lock_offset(uint32 high
, uint32 low
)
6675 uint32 highcopy
= high
;
6678 * Try and find out how many significant bits there are in high.
6681 for(i
= 0; highcopy
; i
++)
6685 * We use 31 bits not 32 here as POSIX
6686 * lock offsets may not be negative.
6689 mask
= (~0) << (31 - i
);
6692 return 0; /* Fail. */
6698 #endif /* !defined(HAVE_LONGLONG) */
6700 /****************************************************************************
6701 Get a lock offset, dealing with large offset requests.
6702 ****************************************************************************/
6704 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
6705 bool large_file_format
, bool *err
)
6707 uint64_t offset
= 0;
6711 if(!large_file_format
) {
6712 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
6715 #if defined(HAVE_LONGLONG)
6716 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
6717 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
6718 #else /* HAVE_LONGLONG */
6721 * NT4.x seems to be broken in that it sends large file (64 bit)
6722 * lockingX calls even if the CAP_LARGE_FILES was *not*
6723 * negotiated. For boxes without large unsigned ints mangle the
6724 * lock offset by mapping the top 32 bits onto the lower 32.
6727 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
6728 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
6729 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
6732 if((new_low
= map_lock_offset(high
, low
)) == 0) {
6734 return (uint64_t)-1;
6737 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6738 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
6739 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
6740 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
6743 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
6744 #endif /* HAVE_LONGLONG */
6750 /****************************************************************************
6751 Reply to a lockingX request.
6752 ****************************************************************************/
6754 void reply_lockingX(struct smb_request
*req
)
6756 connection_struct
*conn
= req
->conn
;
6758 unsigned char locktype
;
6759 unsigned char oplocklevel
;
6762 uint64_t count
= 0, offset
= 0;
6766 const uint8_t *data
;
6767 bool large_file_format
;
6769 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
6771 START_PROFILE(SMBlockingX
);
6774 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6775 END_PROFILE(SMBlockingX
);
6779 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
6780 locktype
= CVAL(req
->vwv
+3, 0);
6781 oplocklevel
= CVAL(req
->vwv
+3, 1);
6782 num_ulocks
= SVAL(req
->vwv
+6, 0);
6783 num_locks
= SVAL(req
->vwv
+7, 0);
6784 lock_timeout
= IVAL(req
->vwv
+4, 0);
6785 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
6787 if (!check_fsp(conn
, req
, fsp
)) {
6788 END_PROFILE(SMBlockingX
);
6794 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
6795 /* we don't support these - and CANCEL_LOCK makes w2k
6796 and XP reboot so I don't really want to be
6797 compatible! (tridge) */
6798 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
6799 END_PROFILE(SMBlockingX
);
6803 /* Check if this is an oplock break on a file
6804 we have granted an oplock on.
6806 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
6807 /* Client can insist on breaking to none. */
6808 bool break_to_none
= (oplocklevel
== 0);
6811 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6812 "for fnum = %d\n", (unsigned int)oplocklevel
,
6816 * Make sure we have granted an exclusive or batch oplock on
6820 if (fsp
->oplock_type
== 0) {
6822 /* The Samba4 nbench simulator doesn't understand
6823 the difference between break to level2 and break
6824 to none from level2 - it sends oplock break
6825 replies in both cases. Don't keep logging an error
6826 message here - just ignore it. JRA. */
6828 DEBUG(5,("reply_lockingX: Error : oplock break from "
6829 "client for fnum = %d (oplock=%d) and no "
6830 "oplock granted on this file (%s).\n",
6831 fsp
->fnum
, fsp
->oplock_type
, fsp
->fsp_name
));
6833 /* if this is a pure oplock break request then don't
6835 if (num_locks
== 0 && num_ulocks
== 0) {
6836 END_PROFILE(SMBlockingX
);
6839 END_PROFILE(SMBlockingX
);
6840 reply_doserror(req
, ERRDOS
, ERRlock
);
6845 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
6847 result
= remove_oplock(fsp
);
6849 result
= downgrade_oplock(fsp
);
6853 DEBUG(0, ("reply_lockingX: error in removing "
6854 "oplock on file %s\n", fsp
->fsp_name
));
6855 /* Hmmm. Is this panic justified? */
6856 smb_panic("internal tdb error");
6859 reply_to_oplock_break_requests(fsp
);
6861 /* if this is a pure oplock break request then don't send a
6863 if (num_locks
== 0 && num_ulocks
== 0) {
6864 /* Sanity check - ensure a pure oplock break is not a
6866 if(CVAL(req
->vwv
+0, 0) != 0xff)
6867 DEBUG(0,("reply_lockingX: Error : pure oplock "
6868 "break is a chained %d request !\n",
6869 (unsigned int)CVAL(req
->vwv
+0, 0)));
6870 END_PROFILE(SMBlockingX
);
6876 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
6877 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6878 END_PROFILE(SMBlockingX
);
6882 /* Data now points at the beginning of the list
6883 of smb_unlkrng structs */
6884 for(i
= 0; i
< (int)num_ulocks
; i
++) {
6885 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
6886 count
= get_lock_count( data
, i
, large_file_format
);
6887 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
6890 * There is no error code marked "stupid client bug".... :-).
6893 END_PROFILE(SMBlockingX
);
6894 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
6898 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6899 "pid %u, file %s\n", (double)offset
, (double)count
,
6900 (unsigned int)lock_pid
, fsp
->fsp_name
));
6902 status
= do_unlock(smbd_messaging_context(),
6909 DEBUG(10, ("reply_lockingX: unlock returned %s\n",
6910 nt_errstr(status
)));
6912 if (NT_STATUS_V(status
)) {
6913 END_PROFILE(SMBlockingX
);
6914 reply_nterror(req
, status
);
6919 /* Setup the timeout in seconds. */
6921 if (!lp_blocking_locks(SNUM(conn
))) {
6925 /* Now do any requested locks */
6926 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
6928 /* Data now points at the beginning of the list
6929 of smb_lkrng structs */
6931 for(i
= 0; i
< (int)num_locks
; i
++) {
6932 enum brl_type lock_type
= ((locktype
& LOCKING_ANDX_SHARED_LOCK
) ?
6933 READ_LOCK
:WRITE_LOCK
);
6934 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
6935 count
= get_lock_count( data
, i
, large_file_format
);
6936 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
6939 * There is no error code marked "stupid client bug".... :-).
6942 END_PROFILE(SMBlockingX
);
6943 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
6947 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6948 "%u, file %s timeout = %d\n", (double)offset
,
6949 (double)count
, (unsigned int)lock_pid
,
6950 fsp
->fsp_name
, (int)lock_timeout
));
6952 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
6953 struct blocking_lock_record
*blr
;
6955 if (lp_blocking_locks(SNUM(conn
))) {
6957 /* Schedule a message to ourselves to
6958 remove the blocking lock record and
6959 return the right error. */
6961 blr
= blocking_lock_cancel(fsp
,
6967 NT_STATUS_FILE_LOCK_CONFLICT
);
6969 END_PROFILE(SMBlockingX
);
6974 ERRcancelviolation
));
6978 /* Remove a matching pending lock. */
6979 status
= do_lock_cancel(fsp
,
6986 bool blocking_lock
= lock_timeout
? True
: False
;
6987 bool defer_lock
= False
;
6988 struct byte_range_lock
*br_lck
;
6989 uint32 block_smbpid
;
6991 br_lck
= do_lock(smbd_messaging_context(),
7003 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7004 /* Windows internal resolution for blocking locks seems
7005 to be about 200ms... Don't wait for less than that. JRA. */
7006 if (lock_timeout
!= -1 && lock_timeout
< lp_lock_spin_time()) {
7007 lock_timeout
= lp_lock_spin_time();
7012 /* This heuristic seems to match W2K3 very well. If a
7013 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7014 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7015 far as I can tell. Replacement for do_lock_spin(). JRA. */
7017 if (br_lck
&& lp_blocking_locks(SNUM(conn
)) && !blocking_lock
&&
7018 NT_STATUS_EQUAL((status
), NT_STATUS_FILE_LOCK_CONFLICT
)) {
7020 lock_timeout
= lp_lock_spin_time();
7023 if (br_lck
&& defer_lock
) {
7025 * A blocking lock was requested. Package up
7026 * this smb into a queued request and push it
7027 * onto the blocking lock queue.
7029 if(push_blocking_lock_request(br_lck
,
7040 TALLOC_FREE(br_lck
);
7041 END_PROFILE(SMBlockingX
);
7046 TALLOC_FREE(br_lck
);
7049 if (NT_STATUS_V(status
)) {
7050 END_PROFILE(SMBlockingX
);
7051 reply_nterror(req
, status
);
7056 /* If any of the above locks failed, then we must unlock
7057 all of the previous locks (X/Open spec). */
7059 if (!(locktype
& LOCKING_ANDX_CANCEL_LOCK
) &&
7063 * Ensure we don't do a remove on the lock that just failed,
7064 * as under POSIX rules, if we have a lock already there, we
7065 * will delete it (and we shouldn't) .....
7067 for(i
--; i
>= 0; i
--) {
7068 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
7069 count
= get_lock_count( data
, i
, large_file_format
);
7070 offset
= get_lock_offset( data
, i
, large_file_format
,
7074 * There is no error code marked "stupid client
7078 END_PROFILE(SMBlockingX
);
7079 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7083 do_unlock(smbd_messaging_context(),
7090 END_PROFILE(SMBlockingX
);
7091 reply_nterror(req
, status
);
7095 reply_outbuf(req
, 2, 0);
7097 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7098 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7100 END_PROFILE(SMBlockingX
);
7105 #define DBGC_CLASS DBGC_ALL
7107 /****************************************************************************
7108 Reply to a SMBreadbmpx (read block multiplex) request.
7109 Always reply with an error, if someone has a platform really needs this,
7110 please contact vl@samba.org
7111 ****************************************************************************/
7113 void reply_readbmpx(struct smb_request
*req
)
7115 START_PROFILE(SMBreadBmpx
);
7116 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7117 END_PROFILE(SMBreadBmpx
);
7121 /****************************************************************************
7122 Reply to a SMBreadbs (read block multiplex secondary) request.
7123 Always reply with an error, if someone has a platform really needs this,
7124 please contact vl@samba.org
7125 ****************************************************************************/
7127 void reply_readbs(struct smb_request
*req
)
7129 START_PROFILE(SMBreadBs
);
7130 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7131 END_PROFILE(SMBreadBs
);
7135 /****************************************************************************
7136 Reply to a SMBsetattrE.
7137 ****************************************************************************/
7139 void reply_setattrE(struct smb_request
*req
)
7141 connection_struct
*conn
= req
->conn
;
7142 struct smb_file_time ft
;
7144 SMB_STRUCT_STAT sbuf
;
7147 START_PROFILE(SMBsetattrE
);
7151 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7152 END_PROFILE(SMBsetattrE
);
7156 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7158 if(!fsp
|| (fsp
->conn
!= conn
)) {
7159 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7160 END_PROFILE(SMBsetattrE
);
7166 * Convert the DOS times into unix times.
7169 ft
.atime
= convert_time_t_to_timespec(
7170 srv_make_unix_date2(req
->vwv
+3));
7171 ft
.mtime
= convert_time_t_to_timespec(
7172 srv_make_unix_date2(req
->vwv
+5));
7173 ft
.create_time
= convert_time_t_to_timespec(
7174 srv_make_unix_date2(req
->vwv
+1));
7176 reply_outbuf(req
, 0, 0);
7179 * Patch from Ray Frush <frush@engr.colostate.edu>
7180 * Sometimes times are sent as zero - ignore them.
7183 /* Ensure we have a valid stat struct for the source. */
7184 if (fsp
->fh
->fd
!= -1) {
7185 if (SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
7186 status
= map_nt_error_from_unix(errno
);
7187 reply_nterror(req
, status
);
7188 END_PROFILE(SMBsetattrE
);
7194 if (fsp
->posix_open
) {
7195 ret
= SMB_VFS_LSTAT(conn
, fsp
->fsp_name
, &sbuf
);
7197 ret
= SMB_VFS_STAT(conn
, fsp
->fsp_name
, &sbuf
);
7200 status
= map_nt_error_from_unix(errno
);
7201 reply_nterror(req
, status
);
7202 END_PROFILE(SMBsetattrE
);
7207 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
,
7209 if (!NT_STATUS_IS_OK(status
)) {
7210 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7211 END_PROFILE(SMBsetattrE
);
7215 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7218 (unsigned int)ft
.atime
.tv_sec
,
7219 (unsigned int)ft
.mtime
.tv_sec
,
7220 (unsigned int)ft
.create_time
.tv_sec
7223 END_PROFILE(SMBsetattrE
);
7228 /* Back from the dead for OS/2..... JRA. */
7230 /****************************************************************************
7231 Reply to a SMBwritebmpx (write block multiplex primary) request.
7232 Always reply with an error, if someone has a platform really needs this,
7233 please contact vl@samba.org
7234 ****************************************************************************/
7236 void reply_writebmpx(struct smb_request
*req
)
7238 START_PROFILE(SMBwriteBmpx
);
7239 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7240 END_PROFILE(SMBwriteBmpx
);
7244 /****************************************************************************
7245 Reply to a SMBwritebs (write block multiplex secondary) request.
7246 Always reply with an error, if someone has a platform really needs this,
7247 please contact vl@samba.org
7248 ****************************************************************************/
7250 void reply_writebs(struct smb_request
*req
)
7252 START_PROFILE(SMBwriteBs
);
7253 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7254 END_PROFILE(SMBwriteBs
);
7258 /****************************************************************************
7259 Reply to a SMBgetattrE.
7260 ****************************************************************************/
7262 void reply_getattrE(struct smb_request
*req
)
7264 connection_struct
*conn
= req
->conn
;
7265 SMB_STRUCT_STAT sbuf
;
7268 struct timespec create_ts
;
7270 START_PROFILE(SMBgetattrE
);
7273 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7274 END_PROFILE(SMBgetattrE
);
7278 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7280 if(!fsp
|| (fsp
->conn
!= conn
)) {
7281 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7282 END_PROFILE(SMBgetattrE
);
7286 /* Do an fstat on this file */
7287 if(fsp_stat(fsp
, &sbuf
)) {
7288 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
7289 END_PROFILE(SMBgetattrE
);
7293 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
7296 * Convert the times into dos times. Set create
7297 * date to be last modify date as UNIX doesn't save
7301 reply_outbuf(req
, 11, 0);
7303 create_ts
= get_create_timespec(&sbuf
,
7304 lp_fake_dir_create_times(SNUM(conn
)));
7305 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
7306 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
, sbuf
.st_atime
);
7307 /* Should we check pending modtime here ? JRA */
7308 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
, sbuf
.st_mtime
);
7311 SIVAL(req
->outbuf
, smb_vwv6
, 0);
7312 SIVAL(req
->outbuf
, smb_vwv8
, 0);
7314 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &sbuf
);
7315 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)sbuf
.st_size
);
7316 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
7318 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
7320 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
7322 END_PROFILE(SMBgetattrE
);