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
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol
;
32 extern uint32 global_client_caps
;
34 extern bool global_encrypted_passwords_negotiated
;
36 /****************************************************************************
37 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
38 path or anything including wildcards.
39 We're assuming here that '/' is not the second byte in any multibyte char
40 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
42 ****************************************************************************/
44 /* Custom version for processing POSIX paths. */
45 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
47 static NTSTATUS
check_path_syntax_internal(char *path
,
49 bool *p_last_component_contains_wcard
)
53 bool start_of_name_component
= True
;
54 bool stream_started
= false;
55 bool check_quota
= false;
57 *p_last_component_contains_wcard
= False
;
64 return NT_STATUS_OBJECT_NAME_INVALID
;
67 return NT_STATUS_OBJECT_NAME_INVALID
;
69 if (strchr_m(&s
[1], ':')) {
70 return NT_STATUS_OBJECT_NAME_INVALID
;
72 if (StrCaseCmp(s
, ":$DATA") != 0) {
79 if (!posix_path
&& !stream_started
&& *s
== ':') {
80 if (*p_last_component_contains_wcard
) {
81 return NT_STATUS_OBJECT_NAME_INVALID
;
83 /* Stream names allow more characters than file names.
84 We're overloading posix_path here to allow a wider
85 range of characters. If stream_started is true this
86 is still a Windows path even if posix_path is true.
89 stream_started
= true;
90 start_of_name_component
= false;
94 return NT_STATUS_OBJECT_NAME_INVALID
;
98 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
100 * Safe to assume is not the second part of a mb char
101 * as this is handled below.
103 /* Eat multiple '/' or '\\' */
104 while (IS_PATH_SEP(*s
,posix_path
)) {
107 if ((d
!= path
) && (*s
!= '\0')) {
108 /* We only care about non-leading or trailing '/' or '\\' */
112 start_of_name_component
= True
;
114 *p_last_component_contains_wcard
= False
;
118 if (start_of_name_component
) {
119 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
120 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
123 * No mb char starts with '.' so we're safe checking the directory separator here.
126 /* If we just added a '/' - delete it */
127 if ((d
> path
) && (*(d
-1) == '/')) {
132 /* Are we at the start ? Can't go back further if so. */
134 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
136 /* Go back one level... */
137 /* We know this is safe as '/' cannot be part of a mb sequence. */
138 /* NOTE - if this assumption is invalid we are not in good shape... */
139 /* Decrement d first as d points to the *next* char to write into. */
140 for (d
--; d
> path
; d
--) {
144 s
+= 2; /* Else go past the .. */
145 /* We're still at the start of a name component, just the previous one. */
148 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
160 if (*s
<= 0x1f || *s
== '|') {
161 return NT_STATUS_OBJECT_NAME_INVALID
;
169 *p_last_component_contains_wcard
= True
;
178 /* Get the size of the next MB character. */
179 next_codepoint(s
,&siz
);
197 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
199 return NT_STATUS_INVALID_PARAMETER
;
202 start_of_name_component
= False
;
208 if (StrCaseCmp(path
, FAKE_FILE_NAME_QUOTA_UNIX
) != 0) {
209 return NT_STATUS_INVALID_PARAMETER
;
216 /****************************************************************************
217 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
218 No wildcards allowed.
219 ****************************************************************************/
221 NTSTATUS
check_path_syntax(char *path
)
224 return check_path_syntax_internal(path
, False
, &ignore
);
227 /****************************************************************************
228 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
229 Wildcards allowed - p_contains_wcard returns true if the last component contained
231 ****************************************************************************/
233 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
235 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
238 /****************************************************************************
239 Check the path for a POSIX client.
240 We're assuming here that '/' is not the second byte in any multibyte char
241 set (a safe assumption).
242 ****************************************************************************/
244 NTSTATUS
check_path_syntax_posix(char *path
)
247 return check_path_syntax_internal(path
, True
, &ignore
);
250 /****************************************************************************
251 Pull a string and check the path allowing a wilcard - provide for error return.
252 ****************************************************************************/
254 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
262 bool *contains_wcard
)
269 ret
= srvstr_pull_buf_talloc(ctx
,
276 ret
= srvstr_pull_talloc(ctx
,
286 *err
= NT_STATUS_INVALID_PARAMETER
;
290 *contains_wcard
= False
;
292 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
294 * For a DFS path the function parse_dfs_path()
295 * will do the path processing, just make a copy.
301 if (lp_posix_pathnames()) {
302 *err
= check_path_syntax_posix(*pp_dest
);
304 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
310 /****************************************************************************
311 Pull a string and check the path - provide for error return.
312 ****************************************************************************/
314 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
328 ret
= srvstr_pull_buf_talloc(ctx
,
335 ret
= srvstr_pull_talloc(ctx
,
345 *err
= NT_STATUS_INVALID_PARAMETER
;
349 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
351 * For a DFS path the function parse_dfs_path()
352 * will do the path processing, just make a copy.
358 if (lp_posix_pathnames()) {
359 *err
= check_path_syntax_posix(*pp_dest
);
361 *err
= check_path_syntax(*pp_dest
);
367 /****************************************************************************
368 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
369 ****************************************************************************/
371 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
374 if (!(fsp
) || !(conn
)) {
375 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
378 if (((conn
) != (fsp
)->conn
) || req
->vuid
!= (fsp
)->vuid
) {
379 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
385 /****************************************************************************
386 Check if we have a correct fsp pointing to a file.
387 ****************************************************************************/
389 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
392 if (!check_fsp_open(conn
, req
, fsp
)) {
395 if ((fsp
)->is_directory
) {
396 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
399 if ((fsp
)->fh
->fd
== -1) {
400 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
403 (fsp
)->num_smb_operations
++;
407 /****************************************************************************
408 Check if we have a correct fsp pointing to a quota fake file. Replacement for
409 the CHECK_NTQUOTA_HANDLE_OK macro.
410 ****************************************************************************/
412 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
415 if (!check_fsp_open(conn
, req
, fsp
)) {
419 if (fsp
->is_directory
) {
423 if (fsp
->fake_file_handle
== NULL
) {
427 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
431 if (fsp
->fake_file_handle
->private_data
== NULL
) {
438 /****************************************************************************
439 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
440 ****************************************************************************/
442 bool fsp_belongs_conn(connection_struct
*conn
, struct smb_request
*req
,
445 if ((fsp
) && (conn
) && ((conn
)==(fsp
)->conn
)
446 && (req
->vuid
== (fsp
)->vuid
)) {
450 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
454 /****************************************************************************
455 Reply to a (netbios-level) special message.
456 ****************************************************************************/
458 void reply_special(char *inbuf
)
460 int msg_type
= CVAL(inbuf
,0);
461 int msg_flags
= CVAL(inbuf
,1);
466 * We only really use 4 bytes of the outbuf, but for the smb_setlen
467 * calculation & friends (srv_send_smb uses that) we need the full smb
470 char outbuf
[smb_size
];
472 static bool already_got_session
= False
;
476 memset(outbuf
, '\0', sizeof(outbuf
));
478 smb_setlen(outbuf
,0);
481 case 0x81: /* session request */
483 if (already_got_session
) {
484 exit_server_cleanly("multiple session request not permitted");
487 SCVAL(outbuf
,0,0x82);
489 if (name_len(inbuf
+4) > 50 ||
490 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
491 DEBUG(0,("Invalid name length in session request\n"));
494 name_extract(inbuf
,4,name1
);
495 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
496 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
499 set_local_machine_name(name1
, True
);
500 set_remote_machine_name(name2
, True
);
502 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
503 get_local_machine_name(), get_remote_machine_name(),
506 if (name_type
== 'R') {
507 /* We are being asked for a pathworks session ---
509 SCVAL(outbuf
, 0,0x83);
513 /* only add the client's machine name to the list
514 of possibly valid usernames if we are operating
515 in share mode security */
516 if (lp_security() == SEC_SHARE
) {
517 add_session_user(get_remote_machine_name());
520 reload_services(True
);
523 already_got_session
= True
;
526 case 0x89: /* session keepalive request
527 (some old clients produce this?) */
528 SCVAL(outbuf
,0,SMBkeepalive
);
532 case 0x82: /* positive session response */
533 case 0x83: /* negative session response */
534 case 0x84: /* retarget session response */
535 DEBUG(0,("Unexpected session response\n"));
538 case SMBkeepalive
: /* session keepalive */
543 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
544 msg_type
, msg_flags
));
546 srv_send_smb(smbd_server_fd(), outbuf
, false);
550 /****************************************************************************
552 conn POINTER CAN BE NULL HERE !
553 ****************************************************************************/
555 void reply_tcon(struct smb_request
*req
)
557 connection_struct
*conn
= req
->conn
;
559 char *service_buf
= NULL
;
560 char *password
= NULL
;
565 DATA_BLOB password_blob
;
566 TALLOC_CTX
*ctx
= talloc_tos();
568 START_PROFILE(SMBtcon
);
570 if (smb_buflen(req
->inbuf
) < 4) {
571 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
572 END_PROFILE(SMBtcon
);
576 p
= smb_buf(req
->inbuf
)+1;
577 p
+= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
,
578 &service_buf
, p
, STR_TERMINATE
) + 1;
579 pwlen
= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
,
580 &password
, p
, STR_TERMINATE
) + 1;
582 p
+= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
,
583 &dev
, p
, STR_TERMINATE
) + 1;
585 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
586 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
587 END_PROFILE(SMBtcon
);
590 p
= strrchr_m(service_buf
,'\\');
594 service
= service_buf
;
597 password_blob
= data_blob(password
, pwlen
+1);
599 conn
= make_connection(service
,password_blob
,dev
,req
->vuid
,&nt_status
);
602 data_blob_clear_free(&password_blob
);
605 reply_nterror(req
, nt_status
);
606 END_PROFILE(SMBtcon
);
610 reply_outbuf(req
, 2, 0);
611 SSVAL(req
->outbuf
,smb_vwv0
,max_recv
);
612 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
613 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
615 DEBUG(3,("tcon service=%s cnum=%d\n",
616 service
, conn
->cnum
));
618 END_PROFILE(SMBtcon
);
622 /****************************************************************************
623 Reply to a tcon and X.
624 conn POINTER CAN BE NULL HERE !
625 ****************************************************************************/
627 void reply_tcon_and_X(struct smb_request
*req
)
629 connection_struct
*conn
= req
->conn
;
630 char *service
= NULL
;
632 TALLOC_CTX
*ctx
= talloc_tos();
633 /* what the cleint thinks the device is */
634 char *client_devicetype
= NULL
;
635 /* what the server tells the client the share represents */
636 const char *server_devicetype
;
643 START_PROFILE(SMBtconX
);
646 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
647 END_PROFILE(SMBtconX
);
651 passlen
= SVAL(req
->inbuf
,smb_vwv3
);
652 tcon_flags
= SVAL(req
->inbuf
,smb_vwv2
);
654 /* we might have to close an old one */
655 if ((tcon_flags
& 0x1) && conn
) {
656 close_cnum(conn
,req
->vuid
);
661 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= smb_buflen(req
->inbuf
))) {
662 reply_doserror(req
, ERRDOS
, ERRbuftoosmall
);
663 END_PROFILE(SMBtconX
);
667 if (global_encrypted_passwords_negotiated
) {
668 password
= data_blob_talloc(talloc_tos(), smb_buf(req
->inbuf
),
670 if (lp_security() == SEC_SHARE
) {
672 * Security = share always has a pad byte
673 * after the password.
675 p
= smb_buf(req
->inbuf
) + passlen
+ 1;
677 p
= smb_buf(req
->inbuf
) + passlen
;
680 password
= data_blob_talloc(talloc_tos(), smb_buf(req
->inbuf
),
682 /* Ensure correct termination */
683 password
.data
[passlen
]=0;
684 p
= smb_buf(req
->inbuf
) + passlen
+ 1;
687 p
+= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
, &path
, p
,
691 data_blob_clear_free(&password
);
692 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
693 END_PROFILE(SMBtconX
);
698 * the service name can be either: \\server\share
699 * or share directly like on the DELL PowerVault 705
702 q
= strchr_m(path
+2,'\\');
704 data_blob_clear_free(&password
);
705 reply_doserror(req
, ERRDOS
, ERRnosuchshare
);
706 END_PROFILE(SMBtconX
);
714 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
715 &client_devicetype
, p
,
716 MIN(6,smb_bufrem(req
->inbuf
, p
)), STR_ASCII
);
718 if (client_devicetype
== NULL
) {
719 data_blob_clear_free(&password
);
720 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
721 END_PROFILE(SMBtconX
);
725 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
727 conn
= make_connection(service
, password
, client_devicetype
,
728 req
->vuid
, &nt_status
);
731 data_blob_clear_free(&password
);
734 reply_nterror(req
, nt_status
);
735 END_PROFILE(SMBtconX
);
740 server_devicetype
= "IPC";
741 else if ( IS_PRINT(conn
) )
742 server_devicetype
= "LPT1:";
744 server_devicetype
= "A:";
746 if (Protocol
< PROTOCOL_NT1
) {
747 reply_outbuf(req
, 2, 0);
748 if (message_push_string(&req
->outbuf
, server_devicetype
,
749 STR_TERMINATE
|STR_ASCII
) == -1) {
750 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
751 END_PROFILE(SMBtconX
);
755 /* NT sets the fstype of IPC$ to the null string */
756 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
758 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
759 /* Return permissions. */
763 reply_outbuf(req
, 7, 0);
766 perm1
= FILE_ALL_ACCESS
;
767 perm2
= FILE_ALL_ACCESS
;
769 perm1
= CAN_WRITE(conn
) ?
774 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
775 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
777 reply_outbuf(req
, 3, 0);
780 if ((message_push_string(&req
->outbuf
, server_devicetype
,
781 STR_TERMINATE
|STR_ASCII
) == -1)
782 || (message_push_string(&req
->outbuf
, fstype
,
783 STR_TERMINATE
) == -1)) {
784 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
785 END_PROFILE(SMBtconX
);
789 /* what does setting this bit do? It is set by NT4 and
790 may affect the ability to autorun mounted cdroms */
791 SSVAL(req
->outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
792 (lp_csc_policy(SNUM(conn
)) << 2));
794 init_dfsroot(conn
, req
->inbuf
, req
->outbuf
);
798 DEBUG(3,("tconX service=%s \n",
801 /* set the incoming and outgoing tid to the just created one */
802 SSVAL(req
->inbuf
,smb_tid
,conn
->cnum
);
803 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
805 END_PROFILE(SMBtconX
);
811 /****************************************************************************
812 Reply to an unknown type.
813 ****************************************************************************/
815 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
817 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
818 smb_fn_name(type
), type
, type
));
819 reply_doserror(req
, ERRSRV
, ERRunknownsmb
);
823 /****************************************************************************
825 conn POINTER CAN BE NULL HERE !
826 ****************************************************************************/
828 void reply_ioctl(struct smb_request
*req
)
830 connection_struct
*conn
= req
->conn
;
837 START_PROFILE(SMBioctl
);
840 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
841 END_PROFILE(SMBioctl
);
845 device
= SVAL(req
->inbuf
,smb_vwv1
);
846 function
= SVAL(req
->inbuf
,smb_vwv2
);
847 ioctl_code
= (device
<< 16) + function
;
849 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
851 switch (ioctl_code
) {
852 case IOCTL_QUERY_JOB_INFO
:
856 reply_doserror(req
, ERRSRV
, ERRnosupport
);
857 END_PROFILE(SMBioctl
);
861 reply_outbuf(req
, 8, replysize
+1);
862 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
863 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
864 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
865 p
= smb_buf(req
->outbuf
);
866 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
867 p
+= 1; /* Allow for alignment */
869 switch (ioctl_code
) {
870 case IOCTL_QUERY_JOB_INFO
:
872 files_struct
*fsp
= file_fsp(SVAL(req
->inbuf
,
875 reply_doserror(req
, ERRDOS
, ERRbadfid
);
876 END_PROFILE(SMBioctl
);
879 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
880 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
882 STR_TERMINATE
|STR_ASCII
);
884 srvstr_push((char *)req
->outbuf
, req
->flags2
,
885 p
+18, lp_servicename(SNUM(conn
)),
886 13, STR_TERMINATE
|STR_ASCII
);
894 END_PROFILE(SMBioctl
);
898 /****************************************************************************
899 Strange checkpath NTSTATUS mapping.
900 ****************************************************************************/
902 static NTSTATUS
map_checkpath_error(const char *inbuf
, NTSTATUS status
)
904 /* Strange DOS error code semantics only for checkpath... */
905 if (!(SVAL(inbuf
,smb_flg2
) & FLAGS2_32_BIT_ERROR_CODES
)) {
906 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
907 /* We need to map to ERRbadpath */
908 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
914 /****************************************************************************
915 Reply to a checkpath.
916 ****************************************************************************/
918 void reply_checkpath(struct smb_request
*req
)
920 connection_struct
*conn
= req
->conn
;
922 SMB_STRUCT_STAT sbuf
;
924 TALLOC_CTX
*ctx
= talloc_tos();
926 START_PROFILE(SMBcheckpath
);
928 srvstr_get_path(ctx
,(char *)req
->inbuf
, req
->flags2
, &name
,
929 smb_buf(req
->inbuf
) + 1, 0,
930 STR_TERMINATE
, &status
);
931 if (!NT_STATUS_IS_OK(status
)) {
932 status
= map_checkpath_error((char *)req
->inbuf
, status
);
933 reply_nterror(req
, status
);
934 END_PROFILE(SMBcheckpath
);
938 status
= resolve_dfspath(ctx
, conn
,
939 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
942 if (!NT_STATUS_IS_OK(status
)) {
943 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
944 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
946 END_PROFILE(SMBcheckpath
);
952 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->inbuf
,smb_vwv0
)));
954 status
= unix_convert(ctx
, conn
, name
, False
, &name
, NULL
, &sbuf
);
955 if (!NT_STATUS_IS_OK(status
)) {
959 status
= check_name(conn
, name
);
960 if (!NT_STATUS_IS_OK(status
)) {
961 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name
,nt_errstr(status
)));
965 if (!VALID_STAT(sbuf
)) {
968 if (lp_posix_pathnames()) {
969 ret
= SMB_VFS_LSTAT(conn
,name
,&sbuf
);
971 ret
= SMB_VFS_STAT(conn
,name
,&sbuf
);
974 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name
,strerror(errno
)));
975 status
= map_nt_error_from_unix(errno
);
980 if (!S_ISDIR(sbuf
.st_mode
)) {
981 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
983 END_PROFILE(SMBcheckpath
);
987 reply_outbuf(req
, 0, 0);
989 END_PROFILE(SMBcheckpath
);
994 END_PROFILE(SMBcheckpath
);
996 /* We special case this - as when a Windows machine
997 is parsing a path is steps through the components
998 one at a time - if a component fails it expects
999 ERRbadpath, not ERRbadfile.
1001 status
= map_checkpath_error((char *)req
->inbuf
, status
);
1002 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1004 * Windows returns different error codes if
1005 * the parent directory is valid but not the
1006 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1007 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1008 * if the path is invalid.
1010 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1011 ERRDOS
, ERRbadpath
);
1015 reply_nterror(req
, status
);
1018 /****************************************************************************
1020 ****************************************************************************/
1022 void reply_getatr(struct smb_request
*req
)
1024 connection_struct
*conn
= req
->conn
;
1026 SMB_STRUCT_STAT sbuf
;
1032 TALLOC_CTX
*ctx
= talloc_tos();
1034 START_PROFILE(SMBgetatr
);
1036 p
= smb_buf(req
->inbuf
) + 1;
1037 p
+= srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
, p
,
1038 0, STR_TERMINATE
, &status
);
1039 if (!NT_STATUS_IS_OK(status
)) {
1040 reply_nterror(req
, status
);
1041 END_PROFILE(SMBgetatr
);
1045 status
= resolve_dfspath(ctx
, conn
,
1046 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1049 if (!NT_STATUS_IS_OK(status
)) {
1050 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1051 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1052 ERRSRV
, ERRbadpath
);
1053 END_PROFILE(SMBgetatr
);
1056 reply_nterror(req
, status
);
1057 END_PROFILE(SMBgetatr
);
1061 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1062 under WfWg - weird! */
1063 if (*fname
== '\0') {
1064 mode
= aHIDDEN
| aDIR
;
1065 if (!CAN_WRITE(conn
)) {
1071 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
,&sbuf
);
1072 if (!NT_STATUS_IS_OK(status
)) {
1073 reply_nterror(req
, status
);
1074 END_PROFILE(SMBgetatr
);
1077 status
= check_name(conn
, fname
);
1078 if (!NT_STATUS_IS_OK(status
)) {
1079 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname
,nt_errstr(status
)));
1080 reply_nterror(req
, status
);
1081 END_PROFILE(SMBgetatr
);
1084 if (!VALID_STAT(sbuf
)) {
1087 if (lp_posix_pathnames()) {
1088 ret
= SMB_VFS_LSTAT(conn
,fname
,&sbuf
);
1090 ret
= SMB_VFS_STAT(conn
,fname
,&sbuf
);
1093 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname
,strerror(errno
)));
1094 reply_unixerror(req
, ERRDOS
,ERRbadfile
);
1095 END_PROFILE(SMBgetatr
);
1100 mode
= dos_mode(conn
,fname
,&sbuf
);
1101 size
= sbuf
.st_size
;
1102 mtime
= sbuf
.st_mtime
;
1108 reply_outbuf(req
, 10, 0);
1110 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1111 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1112 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1114 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1116 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1118 if (Protocol
>= PROTOCOL_NT1
) {
1119 SSVAL(req
->outbuf
, smb_flg2
,
1120 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1123 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname
, mode
, (unsigned int)size
) );
1125 END_PROFILE(SMBgetatr
);
1129 /****************************************************************************
1131 ****************************************************************************/
1133 void reply_setatr(struct smb_request
*req
)
1135 struct timespec ts
[2];
1136 connection_struct
*conn
= req
->conn
;
1140 SMB_STRUCT_STAT sbuf
;
1143 TALLOC_CTX
*ctx
= talloc_tos();
1145 START_PROFILE(SMBsetatr
);
1150 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1154 p
= smb_buf(req
->inbuf
) + 1;
1155 p
+= srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
, p
,
1156 0, STR_TERMINATE
, &status
);
1157 if (!NT_STATUS_IS_OK(status
)) {
1158 reply_nterror(req
, status
);
1159 END_PROFILE(SMBsetatr
);
1163 status
= resolve_dfspath(ctx
, conn
,
1164 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1167 if (!NT_STATUS_IS_OK(status
)) {
1168 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1169 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1170 ERRSRV
, ERRbadpath
);
1171 END_PROFILE(SMBsetatr
);
1174 reply_nterror(req
, status
);
1175 END_PROFILE(SMBsetatr
);
1179 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
1180 if (!NT_STATUS_IS_OK(status
)) {
1181 reply_nterror(req
, status
);
1182 END_PROFILE(SMBsetatr
);
1186 status
= check_name(conn
, fname
);
1187 if (!NT_STATUS_IS_OK(status
)) {
1188 reply_nterror(req
, status
);
1189 END_PROFILE(SMBsetatr
);
1193 if (fname
[0] == '.' && fname
[1] == '\0') {
1195 * Not sure here is the right place to catch this
1196 * condition. Might be moved to somewhere else later -- vl
1198 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1199 END_PROFILE(SMBsetatr
);
1203 mode
= SVAL(req
->inbuf
,smb_vwv0
);
1204 mtime
= srv_make_unix_date3(req
->inbuf
+smb_vwv1
);
1206 ts
[1] = convert_time_t_to_timespec(mtime
);
1207 status
= smb_set_file_time(conn
, NULL
, fname
,
1209 if (!NT_STATUS_IS_OK(status
)) {
1210 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
1211 END_PROFILE(SMBsetatr
);
1215 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1216 if (VALID_STAT_OF_DIR(sbuf
))
1221 if (file_set_dosmode(conn
,fname
,mode
,&sbuf
,NULL
,false) != 0) {
1222 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
1223 END_PROFILE(SMBsetatr
);
1228 reply_outbuf(req
, 0, 0);
1230 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
1232 END_PROFILE(SMBsetatr
);
1236 /****************************************************************************
1238 ****************************************************************************/
1240 void reply_dskattr(struct smb_request
*req
)
1242 connection_struct
*conn
= req
->conn
;
1243 SMB_BIG_UINT dfree
,dsize
,bsize
;
1244 START_PROFILE(SMBdskattr
);
1246 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
1247 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
1248 END_PROFILE(SMBdskattr
);
1252 reply_outbuf(req
, 5, 0);
1254 if (Protocol
<= PROTOCOL_LANMAN2
) {
1255 double total_space
, free_space
;
1256 /* we need to scale this to a number that DOS6 can handle. We
1257 use floating point so we can handle large drives on systems
1258 that don't have 64 bit integers
1260 we end up displaying a maximum of 2G to DOS systems
1262 total_space
= dsize
* (double)bsize
;
1263 free_space
= dfree
* (double)bsize
;
1265 dsize
= (SMB_BIG_UINT
)((total_space
+63*512) / (64*512));
1266 dfree
= (SMB_BIG_UINT
)((free_space
+63*512) / (64*512));
1268 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1269 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1271 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1272 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1273 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1274 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1276 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1277 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1278 SSVAL(req
->outbuf
,smb_vwv2
,512);
1279 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1282 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1284 END_PROFILE(SMBdskattr
);
1288 /****************************************************************************
1290 Can be called from SMBsearch, SMBffirst or SMBfunique.
1291 ****************************************************************************/
1293 void reply_search(struct smb_request
*req
)
1295 connection_struct
*conn
= req
->conn
;
1297 char *directory
= NULL
;
1303 unsigned int numentries
= 0;
1304 unsigned int maxentries
= 0;
1305 bool finished
= False
;
1311 bool check_descend
= False
;
1312 bool expect_close
= False
;
1314 bool mask_contains_wcard
= False
;
1315 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1316 TALLOC_CTX
*ctx
= talloc_tos();
1317 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1319 START_PROFILE(SMBsearch
);
1322 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1323 END_PROFILE(SMBsearch
);
1327 if (lp_posix_pathnames()) {
1328 reply_unknown_new(req
, CVAL(req
->inbuf
, smb_com
));
1329 END_PROFILE(SMBsearch
);
1333 /* If we were called as SMBffirst then we must expect close. */
1334 if(CVAL(req
->inbuf
,smb_com
) == SMBffirst
) {
1335 expect_close
= True
;
1338 reply_outbuf(req
, 1, 3);
1339 maxentries
= SVAL(req
->inbuf
,smb_vwv0
);
1340 dirtype
= SVAL(req
->inbuf
,smb_vwv1
);
1341 p
= smb_buf(req
->inbuf
) + 1;
1342 p
+= srvstr_get_path_wcard(ctx
,
1350 &mask_contains_wcard
);
1351 if (!NT_STATUS_IS_OK(nt_status
)) {
1352 reply_nterror(req
, nt_status
);
1353 END_PROFILE(SMBsearch
);
1357 nt_status
= resolve_dfspath_wcard(ctx
, conn
,
1358 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1361 &mask_contains_wcard
);
1362 if (!NT_STATUS_IS_OK(nt_status
)) {
1363 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1364 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1365 ERRSRV
, ERRbadpath
);
1366 END_PROFILE(SMBsearch
);
1369 reply_nterror(req
, nt_status
);
1370 END_PROFILE(SMBsearch
);
1375 status_len
= SVAL(p
, 0);
1378 /* dirtype &= ~aDIR; */
1380 if (status_len
== 0) {
1381 SMB_STRUCT_STAT sbuf
;
1383 nt_status
= unix_convert(ctx
, conn
, path
, True
,
1384 &directory
, NULL
, &sbuf
);
1385 if (!NT_STATUS_IS_OK(nt_status
)) {
1386 reply_nterror(req
, nt_status
);
1387 END_PROFILE(SMBsearch
);
1391 nt_status
= check_name(conn
, directory
);
1392 if (!NT_STATUS_IS_OK(nt_status
)) {
1393 reply_nterror(req
, nt_status
);
1394 END_PROFILE(SMBsearch
);
1398 p
= strrchr_m(directory
,'/');
1401 directory
= talloc_strdup(ctx
,".");
1403 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1404 END_PROFILE(SMBsearch
);
1412 if (*directory
== '\0') {
1413 directory
= talloc_strdup(ctx
,".");
1415 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1416 END_PROFILE(SMBsearch
);
1420 memset((char *)status
,'\0',21);
1421 SCVAL(status
,0,(dirtype
& 0x1F));
1423 nt_status
= dptr_create(conn
,
1429 mask_contains_wcard
,
1432 if (!NT_STATUS_IS_OK(nt_status
)) {
1433 reply_nterror(req
, nt_status
);
1434 END_PROFILE(SMBsearch
);
1437 dptr_num
= dptr_dnum(conn
->dirptr
);
1441 memcpy(status
,p
,21);
1442 status_dirtype
= CVAL(status
,0) & 0x1F;
1443 if (status_dirtype
!= (dirtype
& 0x1F)) {
1444 dirtype
= status_dirtype
;
1447 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1448 if (!conn
->dirptr
) {
1451 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1452 mask
= dptr_wcard(dptr_num
);
1457 * For a 'continue' search we have no string. So
1458 * check from the initial saved string.
1460 mask_contains_wcard
= ms_has_wild(mask
);
1461 dirtype
= dptr_attr(dptr_num
);
1464 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1466 if ((dirtype
&0x1F) == aVOLID
) {
1467 char buf
[DIR_STRUCT_SIZE
];
1468 memcpy(buf
,status
,21);
1469 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1470 0,aVOLID
,0,!allow_long_path_components
)) {
1471 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1472 END_PROFILE(SMBsearch
);
1475 dptr_fill(buf
+12,dptr_num
);
1476 if (dptr_zero(buf
+12) && (status_len
==0)) {
1481 if (message_push_blob(&req
->outbuf
,
1482 data_blob_const(buf
, sizeof(buf
)))
1484 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1485 END_PROFILE(SMBsearch
);
1493 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1496 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1497 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1498 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
)) {
1499 check_descend
= True
;
1502 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1503 finished
= !get_dir_entry(ctx
,
1514 char buf
[DIR_STRUCT_SIZE
];
1515 memcpy(buf
,status
,21);
1516 if (!make_dir_struct(ctx
,
1523 !allow_long_path_components
)) {
1524 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1525 END_PROFILE(SMBsearch
);
1528 if (!dptr_fill(buf
+12,dptr_num
)) {
1531 if (message_push_blob(&req
->outbuf
,
1532 data_blob_const(buf
, sizeof(buf
)))
1534 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1535 END_PROFILE(SMBsearch
);
1545 /* If we were called as SMBffirst with smb_search_id == NULL
1546 and no entries were found then return error and close dirptr
1549 if (numentries
== 0) {
1550 dptr_close(&dptr_num
);
1551 } else if(expect_close
&& status_len
== 0) {
1552 /* Close the dptr - we know it's gone */
1553 dptr_close(&dptr_num
);
1556 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1557 if(dptr_num
>= 0 && CVAL(req
->inbuf
,smb_com
) == SMBfunique
) {
1558 dptr_close(&dptr_num
);
1561 if ((numentries
== 0) && !mask_contains_wcard
) {
1562 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1563 END_PROFILE(SMBsearch
);
1567 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1568 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1569 SCVAL(smb_buf(req
->outbuf
),0,5);
1570 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1572 /* The replies here are never long name. */
1573 SSVAL(req
->outbuf
, smb_flg2
,
1574 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1575 if (!allow_long_path_components
) {
1576 SSVAL(req
->outbuf
, smb_flg2
,
1577 SVAL(req
->outbuf
, smb_flg2
)
1578 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1581 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1582 SSVAL(req
->outbuf
, smb_flg2
,
1583 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1586 directory
= dptr_path(dptr_num
);
1589 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1590 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
1592 directory
? directory
: "./",
1597 END_PROFILE(SMBsearch
);
1601 /****************************************************************************
1602 Reply to a fclose (stop directory search).
1603 ****************************************************************************/
1605 void reply_fclose(struct smb_request
*req
)
1613 bool path_contains_wcard
= False
;
1614 TALLOC_CTX
*ctx
= talloc_tos();
1616 START_PROFILE(SMBfclose
);
1618 if (lp_posix_pathnames()) {
1619 reply_unknown_new(req
, CVAL(req
->inbuf
, smb_com
));
1620 END_PROFILE(SMBfclose
);
1624 p
= smb_buf(req
->inbuf
) + 1;
1625 p
+= srvstr_get_path_wcard(ctx
,
1633 &path_contains_wcard
);
1634 if (!NT_STATUS_IS_OK(err
)) {
1635 reply_nterror(req
, err
);
1636 END_PROFILE(SMBfclose
);
1640 status_len
= SVAL(p
,0);
1643 if (status_len
== 0) {
1644 reply_doserror(req
, ERRSRV
, ERRsrverror
);
1645 END_PROFILE(SMBfclose
);
1649 memcpy(status
,p
,21);
1651 if(dptr_fetch(status
+12,&dptr_num
)) {
1652 /* Close the dptr - we know it's gone */
1653 dptr_close(&dptr_num
);
1656 reply_outbuf(req
, 1, 0);
1657 SSVAL(req
->outbuf
,smb_vwv0
,0);
1659 DEBUG(3,("search close\n"));
1661 END_PROFILE(SMBfclose
);
1665 /****************************************************************************
1667 ****************************************************************************/
1669 void reply_open(struct smb_request
*req
)
1671 connection_struct
*conn
= req
->conn
;
1677 SMB_STRUCT_STAT sbuf
;
1684 uint32 create_disposition
;
1685 uint32 create_options
= 0;
1687 TALLOC_CTX
*ctx
= talloc_tos();
1689 START_PROFILE(SMBopen
);
1692 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1693 END_PROFILE(SMBopen
);
1697 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1698 deny_mode
= SVAL(req
->inbuf
,smb_vwv0
);
1699 dos_attr
= SVAL(req
->inbuf
,smb_vwv1
);
1701 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
1702 smb_buf(req
->inbuf
)+1, 0,
1703 STR_TERMINATE
, &status
);
1704 if (!NT_STATUS_IS_OK(status
)) {
1705 reply_nterror(req
, status
);
1706 END_PROFILE(SMBopen
);
1710 if (!map_open_params_to_ntcreate(
1711 fname
, deny_mode
, OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1712 &share_mode
, &create_disposition
, &create_options
)) {
1713 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1714 END_PROFILE(SMBopen
);
1718 status
= create_file(conn
, /* conn */
1720 0, /* root_dir_fid */
1722 access_mask
, /* access_mask */
1723 share_mode
, /* share_access */
1724 create_disposition
, /* create_disposition*/
1725 create_options
, /* create_options */
1726 dos_attr
, /* file_attributes */
1727 oplock_request
, /* oplock_request */
1728 0, /* allocation_size */
1735 if (!NT_STATUS_IS_OK(status
)) {
1736 if (open_was_deferred(req
->mid
)) {
1737 /* We have re-scheduled this call. */
1738 END_PROFILE(SMBopen
);
1741 reply_openerror(req
, status
);
1742 END_PROFILE(SMBopen
);
1746 size
= sbuf
.st_size
;
1747 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1748 mtime
= sbuf
.st_mtime
;
1751 DEBUG(3,("attempt to open a directory %s\n",fsp
->fsp_name
));
1752 close_file(fsp
,ERROR_CLOSE
);
1753 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1754 END_PROFILE(SMBopen
);
1758 reply_outbuf(req
, 7, 0);
1759 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1760 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1761 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1762 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1764 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1766 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1767 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1769 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1770 SCVAL(req
->outbuf
,smb_flg
,
1771 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1774 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1775 SCVAL(req
->outbuf
,smb_flg
,
1776 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1778 END_PROFILE(SMBopen
);
1782 /****************************************************************************
1783 Reply to an open and X.
1784 ****************************************************************************/
1786 void reply_open_and_X(struct smb_request
*req
)
1788 connection_struct
*conn
= req
->conn
;
1793 /* Breakout the oplock request bits so we can set the
1794 reply bits separately. */
1795 int ex_oplock_request
;
1796 int core_oplock_request
;
1799 int smb_sattr
= SVAL(req
->inbuf
,smb_vwv4
);
1800 uint32 smb_time
= make_unix_date3(req
->inbuf
+smb_vwv6
);
1805 SMB_STRUCT_STAT sbuf
;
1809 SMB_BIG_UINT allocation_size
;
1810 ssize_t retval
= -1;
1813 uint32 create_disposition
;
1814 uint32 create_options
= 0;
1815 TALLOC_CTX
*ctx
= talloc_tos();
1817 START_PROFILE(SMBopenX
);
1819 if (req
->wct
< 15) {
1820 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1821 END_PROFILE(SMBopenX
);
1825 open_flags
= SVAL(req
->inbuf
,smb_vwv2
);
1826 deny_mode
= SVAL(req
->inbuf
,smb_vwv3
);
1827 smb_attr
= SVAL(req
->inbuf
,smb_vwv5
);
1828 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1829 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1830 oplock_request
= ex_oplock_request
| core_oplock_request
;
1831 smb_ofun
= SVAL(req
->inbuf
,smb_vwv8
);
1832 allocation_size
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv9
);
1834 /* If it's an IPC, pass off the pipe handler. */
1836 if (lp_nt_pipe_support()) {
1837 reply_open_pipe_and_X(conn
, req
);
1839 reply_doserror(req
, ERRSRV
, ERRaccess
);
1841 END_PROFILE(SMBopenX
);
1845 /* XXXX we need to handle passed times, sattr and flags */
1846 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
1847 smb_buf(req
->inbuf
), 0, STR_TERMINATE
,
1849 if (!NT_STATUS_IS_OK(status
)) {
1850 reply_nterror(req
, status
);
1851 END_PROFILE(SMBopenX
);
1855 if (!map_open_params_to_ntcreate(
1856 fname
, deny_mode
, smb_ofun
, &access_mask
,
1857 &share_mode
, &create_disposition
, &create_options
)) {
1858 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1859 END_PROFILE(SMBopenX
);
1863 status
= create_file(conn
, /* conn */
1865 0, /* root_dir_fid */
1867 access_mask
, /* access_mask */
1868 share_mode
, /* share_access */
1869 create_disposition
, /* create_disposition*/
1870 create_options
, /* create_options */
1871 smb_attr
, /* file_attributes */
1872 oplock_request
, /* oplock_request */
1873 0, /* allocation_size */
1877 &smb_action
, /* pinfo */
1880 if (!NT_STATUS_IS_OK(status
)) {
1881 END_PROFILE(SMBopenX
);
1882 if (open_was_deferred(req
->mid
)) {
1883 /* We have re-scheduled this call. */
1886 reply_openerror(req
, status
);
1890 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1891 if the file is truncated or created. */
1892 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1893 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1894 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1895 close_file(fsp
,ERROR_CLOSE
);
1896 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1897 END_PROFILE(SMBopenX
);
1900 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1902 close_file(fsp
,ERROR_CLOSE
);
1903 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1904 END_PROFILE(SMBopenX
);
1907 sbuf
.st_size
= get_allocation_size(conn
,fsp
,&sbuf
);
1910 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1911 mtime
= sbuf
.st_mtime
;
1913 close_file(fsp
,ERROR_CLOSE
);
1914 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
1915 END_PROFILE(SMBopenX
);
1919 /* If the caller set the extended oplock request bit
1920 and we granted one (by whatever means) - set the
1921 correct bit for extended oplock reply.
1924 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1925 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1928 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1929 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1932 /* If the caller set the core oplock request bit
1933 and we granted one (by whatever means) - set the
1934 correct bit for core oplock reply.
1937 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1938 reply_outbuf(req
, 19, 0);
1940 reply_outbuf(req
, 15, 0);
1943 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1944 SCVAL(req
->outbuf
, smb_flg
,
1945 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1948 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1949 SCVAL(req
->outbuf
, smb_flg
,
1950 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1953 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
1954 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
1955 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1956 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
1958 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
1960 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
1961 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
1962 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
1964 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1965 SIVAL(req
->outbuf
, smb_vwv15
, STD_RIGHT_ALL_ACCESS
);
1968 END_PROFILE(SMBopenX
);
1973 /****************************************************************************
1974 Reply to a SMBulogoffX.
1975 ****************************************************************************/
1977 void reply_ulogoffX(struct smb_request
*req
)
1981 START_PROFILE(SMBulogoffX
);
1983 vuser
= get_valid_user_struct(req
->vuid
);
1986 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1990 /* in user level security we are supposed to close any files
1991 open by this user */
1992 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
1993 file_close_user(req
->vuid
);
1996 invalidate_vuid(req
->vuid
);
1998 reply_outbuf(req
, 2, 0);
2000 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
2002 END_PROFILE(SMBulogoffX
);
2006 /****************************************************************************
2007 Reply to a mknew or a create.
2008 ****************************************************************************/
2010 void reply_mknew(struct smb_request
*req
)
2012 connection_struct
*conn
= req
->conn
;
2016 struct timespec ts
[2];
2018 int oplock_request
= 0;
2019 SMB_STRUCT_STAT sbuf
;
2021 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2022 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2023 uint32 create_disposition
;
2024 uint32 create_options
= 0;
2025 TALLOC_CTX
*ctx
= talloc_tos();
2027 START_PROFILE(SMBcreate
);
2030 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2031 END_PROFILE(SMBcreate
);
2035 fattr
= SVAL(req
->inbuf
,smb_vwv0
);
2036 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2037 com
= SVAL(req
->inbuf
,smb_com
);
2039 ts
[1] =convert_time_t_to_timespec(
2040 srv_make_unix_date3(req
->inbuf
+ smb_vwv1
));
2043 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
2044 smb_buf(req
->inbuf
) + 1, 0,
2045 STR_TERMINATE
, &status
);
2046 if (!NT_STATUS_IS_OK(status
)) {
2047 reply_nterror(req
, status
);
2048 END_PROFILE(SMBcreate
);
2052 if (fattr
& aVOLID
) {
2053 DEBUG(0,("Attempt to create file (%s) with volid set - "
2054 "please report this\n", fname
));
2057 if(com
== SMBmknew
) {
2058 /* We should fail if file exists. */
2059 create_disposition
= FILE_CREATE
;
2061 /* Create if file doesn't exist, truncate if it does. */
2062 create_disposition
= FILE_OVERWRITE_IF
;
2065 status
= create_file(conn
, /* conn */
2067 0, /* root_dir_fid */
2069 access_mask
, /* access_mask */
2070 share_mode
, /* share_access */
2071 create_disposition
, /* create_disposition*/
2072 create_options
, /* create_options */
2073 fattr
, /* file_attributes */
2074 oplock_request
, /* oplock_request */
2075 0, /* allocation_size */
2082 if (!NT_STATUS_IS_OK(status
)) {
2083 END_PROFILE(SMBcreate
);
2084 if (open_was_deferred(req
->mid
)) {
2085 /* We have re-scheduled this call. */
2088 reply_openerror(req
, status
);
2092 ts
[0] = get_atimespec(&sbuf
); /* atime. */
2093 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &sbuf
, ts
, true);
2094 if (!NT_STATUS_IS_OK(status
)) {
2095 END_PROFILE(SMBcreate
);
2096 reply_openerror(req
, status
);
2100 reply_outbuf(req
, 1, 0);
2101 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2103 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2104 SCVAL(req
->outbuf
,smb_flg
,
2105 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2108 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2109 SCVAL(req
->outbuf
,smb_flg
,
2110 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2113 DEBUG( 2, ( "reply_mknew: file %s\n", fsp
->fsp_name
) );
2114 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2115 fsp
->fsp_name
, fsp
->fh
->fd
, (unsigned int)fattr
) );
2117 END_PROFILE(SMBcreate
);
2121 /****************************************************************************
2122 Reply to a create temporary file.
2123 ****************************************************************************/
2125 void reply_ctemp(struct smb_request
*req
)
2127 connection_struct
*conn
= req
->conn
;
2133 SMB_STRUCT_STAT sbuf
;
2136 TALLOC_CTX
*ctx
= talloc_tos();
2138 START_PROFILE(SMBctemp
);
2141 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2142 END_PROFILE(SMBctemp
);
2146 fattr
= SVAL(req
->inbuf
,smb_vwv0
);
2147 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2149 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
2150 smb_buf(req
->inbuf
)+1, 0, STR_TERMINATE
,
2152 if (!NT_STATUS_IS_OK(status
)) {
2153 reply_nterror(req
, status
);
2154 END_PROFILE(SMBctemp
);
2158 fname
= talloc_asprintf(ctx
,
2162 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2166 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2167 END_PROFILE(SMBctemp
);
2171 status
= resolve_dfspath(ctx
, conn
,
2172 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2175 if (!NT_STATUS_IS_OK(status
)) {
2176 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2177 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2178 ERRSRV
, ERRbadpath
);
2179 END_PROFILE(SMBctemp
);
2182 reply_nterror(req
, status
);
2183 END_PROFILE(SMBctemp
);
2187 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
2188 if (!NT_STATUS_IS_OK(status
)) {
2189 reply_nterror(req
, status
);
2190 END_PROFILE(SMBctemp
);
2194 status
= check_name(conn
, fname
);
2195 if (!NT_STATUS_IS_OK(status
)) {
2196 reply_nterror(req
, status
);
2197 END_PROFILE(SMBctemp
);
2201 tmpfd
= smb_mkstemp(fname
);
2203 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
2204 END_PROFILE(SMBctemp
);
2208 SMB_VFS_STAT(conn
,fname
,&sbuf
);
2210 /* We should fail if file does not exist. */
2211 status
= open_file_ntcreate(conn
, req
, fname
, &sbuf
,
2212 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
,
2213 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
2220 /* close fd from smb_mkstemp() */
2223 if (!NT_STATUS_IS_OK(status
)) {
2224 if (open_was_deferred(req
->mid
)) {
2225 /* We have re-scheduled this call. */
2226 END_PROFILE(SMBctemp
);
2229 reply_openerror(req
, status
);
2230 END_PROFILE(SMBctemp
);
2234 reply_outbuf(req
, 1, 0);
2235 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2237 /* the returned filename is relative to the directory */
2238 s
= strrchr_m(fsp
->fsp_name
, '/');
2246 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2247 thing in the byte section. JRA */
2248 SSVALS(p
, 0, -1); /* what is this? not in spec */
2250 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2252 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2253 END_PROFILE(SMBctemp
);
2257 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2258 SCVAL(req
->outbuf
, smb_flg
,
2259 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2262 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2263 SCVAL(req
->outbuf
, smb_flg
,
2264 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2267 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp
->fsp_name
) );
2268 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp
->fsp_name
,
2269 fsp
->fh
->fd
, (unsigned int)sbuf
.st_mode
) );
2271 END_PROFILE(SMBctemp
);
2275 /*******************************************************************
2276 Check if a user is allowed to rename a file.
2277 ********************************************************************/
2279 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2280 uint16 dirtype
, SMB_STRUCT_STAT
*pst
)
2284 if (!CAN_WRITE(conn
)) {
2285 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2288 fmode
= dos_mode(conn
, fsp
->fsp_name
, pst
);
2289 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
)) {
2290 return NT_STATUS_NO_SUCH_FILE
;
2293 if (S_ISDIR(pst
->st_mode
)) {
2294 if (fsp
->posix_open
) {
2295 return NT_STATUS_OK
;
2298 /* If no pathnames are open below this
2299 directory, allow the rename. */
2301 if (file_find_subpath(fsp
)) {
2302 return NT_STATUS_ACCESS_DENIED
;
2304 return NT_STATUS_OK
;
2307 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2308 return NT_STATUS_OK
;
2311 return NT_STATUS_ACCESS_DENIED
;
2314 /*******************************************************************
2315 * unlink a file with all relevant access checks
2316 *******************************************************************/
2318 static NTSTATUS
do_unlink(connection_struct
*conn
,
2319 struct smb_request
*req
,
2323 SMB_STRUCT_STAT sbuf
;
2326 uint32 dirtype_orig
= dirtype
;
2327 bool posix_paths
= lp_posix_pathnames();
2331 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname
, dirtype
));
2333 if (!CAN_WRITE(conn
)) {
2334 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2338 ret
= SMB_VFS_LSTAT(conn
,fname
,&sbuf
);
2340 ret
= SMB_VFS_STAT(conn
,fname
,&sbuf
);
2343 return map_nt_error_from_unix(errno
);
2346 fattr
= dos_mode(conn
,fname
,&sbuf
);
2348 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2349 dirtype
= aDIR
|aARCH
|aRONLY
;
2352 dirtype
&= (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
);
2354 return NT_STATUS_NO_SUCH_FILE
;
2357 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2359 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2361 return NT_STATUS_NO_SUCH_FILE
;
2364 if (dirtype_orig
& 0x8000) {
2365 /* These will never be set for POSIX. */
2366 return NT_STATUS_NO_SUCH_FILE
;
2370 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2371 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2374 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2375 return NT_STATUS_NO_SUCH_FILE
;
2378 if (dirtype
& 0xFF00) {
2379 /* These will never be set for POSIX. */
2380 return NT_STATUS_NO_SUCH_FILE
;
2385 return NT_STATUS_NO_SUCH_FILE
;
2388 /* Can't delete a directory. */
2390 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2395 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
2396 return NT_STATUS_OBJECT_NAME_INVALID
;
2397 #endif /* JRATEST */
2399 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2401 On a Windows share, a file with read-only dosmode can be opened with
2402 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2403 fails with NT_STATUS_CANNOT_DELETE error.
2405 This semantic causes a problem that a user can not
2406 rename a file with read-only dosmode on a Samba share
2407 from a Windows command prompt (i.e. cmd.exe, but can rename
2408 from Windows Explorer).
2411 if (!lp_delete_readonly(SNUM(conn
))) {
2412 if (fattr
& aRONLY
) {
2413 return NT_STATUS_CANNOT_DELETE
;
2417 /* On open checks the open itself will check the share mode, so
2418 don't do it here as we'll get it wrong. */
2420 status
= create_file_unixpath
2424 DELETE_ACCESS
, /* access_mask */
2425 FILE_SHARE_NONE
, /* share_access */
2426 FILE_OPEN
, /* create_disposition*/
2427 FILE_NON_DIRECTORY_FILE
, /* create_options */
2428 /* file_attributes */
2429 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2430 FILE_ATTRIBUTE_NORMAL
,
2431 0, /* oplock_request */
2432 0, /* allocation_size */
2439 if (!NT_STATUS_IS_OK(status
)) {
2440 DEBUG(10, ("create_file_unixpath failed: %s\n",
2441 nt_errstr(status
)));
2445 /* The set is across all open files on this dev/inode pair. */
2446 if (!set_delete_on_close(fsp
, True
, &conn
->server_info
->utok
)) {
2447 close_file(fsp
, NORMAL_CLOSE
);
2448 return NT_STATUS_ACCESS_DENIED
;
2451 return close_file(fsp
,NORMAL_CLOSE
);
2454 /****************************************************************************
2455 The guts of the unlink command, split out so it may be called by the NT SMB
2457 ****************************************************************************/
2459 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2460 uint32 dirtype
, const char *name_in
, bool has_wild
)
2462 const char *directory
= NULL
;
2467 NTSTATUS status
= NT_STATUS_OK
;
2468 SMB_STRUCT_STAT sbuf
;
2469 TALLOC_CTX
*ctx
= talloc_tos();
2471 status
= unix_convert(ctx
, conn
, name_in
, has_wild
, &name
, NULL
, &sbuf
);
2472 if (!NT_STATUS_IS_OK(status
)) {
2476 p
= strrchr_m(name
,'/');
2478 directory
= talloc_strdup(ctx
, ".");
2480 return NT_STATUS_NO_MEMORY
;
2490 * We should only check the mangled cache
2491 * here if unix_convert failed. This means
2492 * that the path in 'mask' doesn't exist
2493 * on the file system and so we need to look
2494 * for a possible mangle. This patch from
2495 * Tine Smukavec <valentin.smukavec@hermes.si>.
2498 if (!VALID_STAT(sbuf
) && mangle_is_mangled(mask
,conn
->params
)) {
2499 char *new_mask
= NULL
;
2500 mangle_lookup_name_from_8_3(ctx
,
2510 directory
= talloc_asprintf(ctx
,
2515 return NT_STATUS_NO_MEMORY
;
2518 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2521 status
= check_name(conn
, directory
);
2522 if (!NT_STATUS_IS_OK(status
)) {
2526 status
= do_unlink(conn
, req
, directory
, dirtype
);
2527 if (!NT_STATUS_IS_OK(status
)) {
2533 struct smb_Dir
*dir_hnd
= NULL
;
2537 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == aDIR
) {
2538 return NT_STATUS_OBJECT_NAME_INVALID
;
2541 if (strequal(mask
,"????????.???")) {
2546 status
= check_name(conn
, directory
);
2547 if (!NT_STATUS_IS_OK(status
)) {
2551 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
,
2553 if (dir_hnd
== NULL
) {
2554 return map_nt_error_from_unix(errno
);
2557 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2558 the pattern matches against the long name, otherwise the short name
2559 We don't implement this yet XXXX
2562 status
= NT_STATUS_NO_SUCH_FILE
;
2564 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
2568 if (!is_visible_file(conn
, directory
, dname
, &st
, True
)) {
2572 /* Quick check for "." and ".." */
2573 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2577 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
2581 fname
= talloc_asprintf(ctx
, "%s/%s",
2585 return NT_STATUS_NO_MEMORY
;
2588 status
= check_name(conn
, fname
);
2589 if (!NT_STATUS_IS_OK(status
)) {
2590 TALLOC_FREE(dir_hnd
);
2594 status
= do_unlink(conn
, req
, fname
, dirtype
);
2595 if (!NT_STATUS_IS_OK(status
)) {
2601 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2606 TALLOC_FREE(dir_hnd
);
2609 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2610 status
= map_nt_error_from_unix(errno
);
2616 /****************************************************************************
2618 ****************************************************************************/
2620 void reply_unlink(struct smb_request
*req
)
2622 connection_struct
*conn
= req
->conn
;
2626 bool path_contains_wcard
= False
;
2627 TALLOC_CTX
*ctx
= talloc_tos();
2629 START_PROFILE(SMBunlink
);
2632 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2633 END_PROFILE(SMBunlink
);
2637 dirtype
= SVAL(req
->inbuf
,smb_vwv0
);
2639 srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &name
,
2640 smb_buf(req
->inbuf
) + 1, 0,
2641 STR_TERMINATE
, &status
, &path_contains_wcard
);
2642 if (!NT_STATUS_IS_OK(status
)) {
2643 reply_nterror(req
, status
);
2644 END_PROFILE(SMBunlink
);
2648 status
= resolve_dfspath_wcard(ctx
, conn
,
2649 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2652 &path_contains_wcard
);
2653 if (!NT_STATUS_IS_OK(status
)) {
2654 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2655 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2656 ERRSRV
, ERRbadpath
);
2657 END_PROFILE(SMBunlink
);
2660 reply_nterror(req
, status
);
2661 END_PROFILE(SMBunlink
);
2665 DEBUG(3,("reply_unlink : %s\n",name
));
2667 status
= unlink_internals(conn
, req
, dirtype
, name
,
2668 path_contains_wcard
);
2669 if (!NT_STATUS_IS_OK(status
)) {
2670 if (open_was_deferred(req
->mid
)) {
2671 /* We have re-scheduled this call. */
2672 END_PROFILE(SMBunlink
);
2675 reply_nterror(req
, status
);
2676 END_PROFILE(SMBunlink
);
2680 reply_outbuf(req
, 0, 0);
2681 END_PROFILE(SMBunlink
);
2686 /****************************************************************************
2688 ****************************************************************************/
2690 static void fail_readraw(void)
2692 const char *errstr
= talloc_asprintf(talloc_tos(),
2693 "FAIL ! reply_readbraw: socket write fail (%s)",
2698 exit_server_cleanly(errstr
);
2701 /****************************************************************************
2702 Fake (read/write) sendfile. Returns -1 on read or write fail.
2703 ****************************************************************************/
2705 static ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
,
2709 size_t tosend
= nread
;
2716 bufsize
= MIN(nread
, 65536);
2718 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2722 while (tosend
> 0) {
2726 if (tosend
> bufsize
) {
2731 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2737 /* If we had a short read, fill with zeros. */
2738 if (ret
< cur_read
) {
2739 memset(buf
, '\0', cur_read
- ret
);
2742 if (write_data(smbd_server_fd(),buf
,cur_read
) != cur_read
) {
2747 startpos
+= cur_read
;
2751 return (ssize_t
)nread
;
2754 /****************************************************************************
2755 Return a readbraw error (4 bytes of zero).
2756 ****************************************************************************/
2758 static void reply_readbraw_error(void)
2762 if (write_data(smbd_server_fd(),header
,4) != 4) {
2767 /****************************************************************************
2768 Use sendfile in readbraw.
2769 ****************************************************************************/
2771 void send_file_readbraw(connection_struct
*conn
,
2777 char *outbuf
= NULL
;
2780 #if defined(WITH_SENDFILE)
2782 * We can only use sendfile on a non-chained packet
2783 * but we can use on a non-oplocked file. tridge proved this
2784 * on a train in Germany :-). JRA.
2785 * reply_readbraw has already checked the length.
2788 if ( (chain_size
== 0) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
2789 (fsp
->wcp
== NULL
) && lp_use_sendfile(SNUM(conn
)) ) {
2791 DATA_BLOB header_blob
;
2793 _smb_setlen(header
,nread
);
2794 header_blob
= data_blob_const(header
, 4);
2796 if (SMB_VFS_SENDFILE(smbd_server_fd(), fsp
,
2797 &header_blob
, startpos
, nread
) == -1) {
2798 /* Returning ENOSYS means no data at all was sent.
2799 * Do this as a normal read. */
2800 if (errno
== ENOSYS
) {
2801 goto normal_readbraw
;
2805 * Special hack for broken Linux with no working sendfile. If we
2806 * return EINTR we sent the header but not the rest of the data.
2807 * Fake this up by doing read/write calls.
2809 if (errno
== EINTR
) {
2810 /* Ensure we don't do this again. */
2811 set_use_sendfile(SNUM(conn
), False
);
2812 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2814 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
2815 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2816 fsp
->fsp_name
, strerror(errno
) ));
2817 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2822 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2823 fsp
->fsp_name
, strerror(errno
) ));
2824 exit_server_cleanly("send_file_readbraw sendfile failed");
2833 outbuf
= TALLOC_ARRAY(NULL
, char, nread
+4);
2835 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2836 (unsigned)(nread
+4)));
2837 reply_readbraw_error();
2842 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2843 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2852 _smb_setlen(outbuf
,ret
);
2853 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
2856 TALLOC_FREE(outbuf
);
2859 /****************************************************************************
2860 Reply to a readbraw (core+ protocol).
2861 ****************************************************************************/
2863 void reply_readbraw(struct smb_request
*req
)
2865 connection_struct
*conn
= req
->conn
;
2866 ssize_t maxcount
,mincount
;
2873 START_PROFILE(SMBreadbraw
);
2875 if (srv_is_signing_active() || is_encrypted_packet(req
->inbuf
)) {
2876 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2877 "raw reads/writes are disallowed.");
2881 reply_readbraw_error();
2882 END_PROFILE(SMBreadbraw
);
2887 * Special check if an oplock break has been issued
2888 * and the readraw request croses on the wire, we must
2889 * return a zero length response here.
2892 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
2895 * We have to do a check_fsp by hand here, as
2896 * we must always return 4 zero bytes on error,
2900 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
2901 req
->vuid
!= fsp
->vuid
||
2902 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
2904 * fsp could be NULL here so use the value from the packet. JRA.
2906 DEBUG(3,("reply_readbraw: fnum %d not valid "
2908 (int)SVAL(req
->inbuf
,smb_vwv0
)));
2909 reply_readbraw_error();
2910 END_PROFILE(SMBreadbraw
);
2914 /* Do a "by hand" version of CHECK_READ. */
2915 if (!(fsp
->can_read
||
2916 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
2917 (fsp
->access_mask
& FILE_EXECUTE
)))) {
2918 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2919 (int)SVAL(req
->inbuf
,smb_vwv0
)));
2920 reply_readbraw_error();
2921 END_PROFILE(SMBreadbraw
);
2925 flush_write_cache(fsp
, READRAW_FLUSH
);
2927 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv1
);
2928 if(req
->wct
== 10) {
2930 * This is a large offset (64 bit) read.
2932 #ifdef LARGE_SMB_OFF_T
2934 startpos
|= (((SMB_OFF_T
)IVAL(req
->inbuf
,smb_vwv8
)) << 32);
2936 #else /* !LARGE_SMB_OFF_T */
2939 * Ensure we haven't been sent a >32 bit offset.
2942 if(IVAL(req
->inbuf
,smb_vwv8
) != 0) {
2943 DEBUG(0,("reply_readbraw: large offset "
2944 "(%x << 32) used and we don't support "
2945 "64 bit offsets.\n",
2946 (unsigned int)IVAL(req
->inbuf
,smb_vwv8
) ));
2947 reply_readbraw_error();
2948 END_PROFILE(SMBreadbraw
);
2952 #endif /* LARGE_SMB_OFF_T */
2955 DEBUG(0,("reply_readbraw: negative 64 bit "
2956 "readraw offset (%.0f) !\n",
2957 (double)startpos
));
2958 reply_readbraw_error();
2959 END_PROFILE(SMBreadbraw
);
2964 maxcount
= (SVAL(req
->inbuf
,smb_vwv3
) & 0xFFFF);
2965 mincount
= (SVAL(req
->inbuf
,smb_vwv4
) & 0xFFFF);
2967 /* ensure we don't overrun the packet size */
2968 maxcount
= MIN(65535,maxcount
);
2970 if (is_locked(fsp
,(uint32
)req
->smbpid
,
2971 (SMB_BIG_UINT
)maxcount
,
2972 (SMB_BIG_UINT
)startpos
,
2974 reply_readbraw_error();
2975 END_PROFILE(SMBreadbraw
);
2979 if (SMB_VFS_FSTAT(fsp
, &st
) == 0) {
2983 if (startpos
>= size
) {
2986 nread
= MIN(maxcount
,(size
- startpos
));
2989 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2990 if (nread
< mincount
)
2994 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2995 "min=%lu nread=%lu\n",
2996 fsp
->fnum
, (double)startpos
,
2997 (unsigned long)maxcount
,
2998 (unsigned long)mincount
,
2999 (unsigned long)nread
) );
3001 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
);
3003 DEBUG(5,("reply_readbraw finished\n"));
3004 END_PROFILE(SMBreadbraw
);
3008 #define DBGC_CLASS DBGC_LOCKING
3010 /****************************************************************************
3011 Reply to a lockread (core+ protocol).
3012 ****************************************************************************/
3014 void reply_lockread(struct smb_request
*req
)
3016 connection_struct
*conn
= req
->conn
;
3023 struct byte_range_lock
*br_lck
= NULL
;
3026 START_PROFILE(SMBlockread
);
3029 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3030 END_PROFILE(SMBlockread
);
3034 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3036 if (!check_fsp(conn
, req
, fsp
)) {
3037 END_PROFILE(SMBlockread
);
3041 if (!CHECK_READ(fsp
,req
->inbuf
)) {
3042 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3043 END_PROFILE(SMBlockread
);
3047 release_level_2_oplocks_on_change(fsp
);
3049 numtoread
= SVAL(req
->inbuf
,smb_vwv1
);
3050 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
3052 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3054 reply_outbuf(req
, 5, numtoread
+ 3);
3056 data
= smb_buf(req
->outbuf
) + 3;
3059 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3060 * protocol request that predates the read/write lock concept.
3061 * Thus instead of asking for a read lock here we need to ask
3062 * for a write lock. JRA.
3063 * Note that the requested lock size is unaffected by max_recv.
3066 br_lck
= do_lock(smbd_messaging_context(),
3069 (SMB_BIG_UINT
)numtoread
,
3070 (SMB_BIG_UINT
)startpos
,
3073 False
, /* Non-blocking lock. */
3076 TALLOC_FREE(br_lck
);
3078 if (NT_STATUS_V(status
)) {
3079 reply_nterror(req
, status
);
3080 END_PROFILE(SMBlockread
);
3085 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3088 if (numtoread
> max_recv
) {
3089 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3090 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3091 (unsigned int)numtoread
, (unsigned int)max_recv
));
3092 numtoread
= MIN(numtoread
,max_recv
);
3094 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3097 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3098 END_PROFILE(SMBlockread
);
3102 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3104 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3105 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3106 p
= smb_buf(req
->outbuf
);
3107 SCVAL(p
,0,0); /* pad byte. */
3110 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3111 fsp
->fnum
, (int)numtoread
, (int)nread
));
3113 END_PROFILE(SMBlockread
);
3118 #define DBGC_CLASS DBGC_ALL
3120 /****************************************************************************
3122 ****************************************************************************/
3124 void reply_read(struct smb_request
*req
)
3126 connection_struct
*conn
= req
->conn
;
3134 START_PROFILE(SMBread
);
3137 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3138 END_PROFILE(SMBread
);
3142 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3144 if (!check_fsp(conn
, req
, fsp
)) {
3145 END_PROFILE(SMBread
);
3149 if (!CHECK_READ(fsp
,req
->inbuf
)) {
3150 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3151 END_PROFILE(SMBread
);
3155 numtoread
= SVAL(req
->inbuf
,smb_vwv1
);
3156 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
3158 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3161 * The requested read size cannot be greater than max_recv. JRA.
3163 if (numtoread
> max_recv
) {
3164 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3165 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3166 (unsigned int)numtoread
, (unsigned int)max_recv
));
3167 numtoread
= MIN(numtoread
,max_recv
);
3170 reply_outbuf(req
, 5, numtoread
+3);
3172 data
= smb_buf(req
->outbuf
) + 3;
3174 if (is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtoread
,
3175 (SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
3176 reply_doserror(req
, ERRDOS
,ERRlock
);
3177 END_PROFILE(SMBread
);
3182 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3185 reply_unixerror(req
, ERRDOS
,ERRnoaccess
);
3186 END_PROFILE(SMBread
);
3190 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3192 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3193 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3194 SCVAL(smb_buf(req
->outbuf
),0,1);
3195 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3197 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3198 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3200 END_PROFILE(SMBread
);
3204 /****************************************************************************
3206 ****************************************************************************/
3208 static int setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3213 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3214 data
= smb_buf(outbuf
);
3216 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3218 SCVAL(outbuf
,smb_vwv0
,0xFF);
3219 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3220 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3221 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
3222 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3223 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
3224 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3225 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3229 /****************************************************************************
3230 Reply to a read and X - possibly using sendfile.
3231 ****************************************************************************/
3233 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3234 files_struct
*fsp
, SMB_OFF_T startpos
,
3237 SMB_STRUCT_STAT sbuf
;
3240 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
3241 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3245 if (startpos
> sbuf
.st_size
) {
3247 } else if (smb_maxcnt
> (sbuf
.st_size
- startpos
)) {
3248 smb_maxcnt
= (sbuf
.st_size
- startpos
);
3251 if (smb_maxcnt
== 0) {
3255 #if defined(WITH_SENDFILE)
3257 * We can only use sendfile on a non-chained packet
3258 * but we can use on a non-oplocked file. tridge proved this
3259 * on a train in Germany :-). JRA.
3262 if ((chain_size
== 0) && (CVAL(req
->inbuf
,smb_vwv0
) == 0xFF) &&
3263 !is_encrypted_packet(req
->inbuf
) && (fsp
->base_fsp
== NULL
) &&
3264 lp_use_sendfile(SNUM(conn
)) && (fsp
->wcp
== NULL
) ) {
3265 uint8 headerbuf
[smb_size
+ 12 * 2];
3269 * Set up the packet header before send. We
3270 * assume here the sendfile will work (get the
3271 * correct amount of data).
3274 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3276 construct_reply_common((char *)req
->inbuf
, (char *)headerbuf
);
3277 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3279 if ((nread
= SMB_VFS_SENDFILE(smbd_server_fd(), fsp
, &header
, startpos
, smb_maxcnt
)) == -1) {
3280 /* Returning ENOSYS means no data at all was sent.
3281 Do this as a normal read. */
3282 if (errno
== ENOSYS
) {
3287 * Special hack for broken Linux with no working sendfile. If we
3288 * return EINTR we sent the header but not the rest of the data.
3289 * Fake this up by doing read/write calls.
3292 if (errno
== EINTR
) {
3293 /* Ensure we don't do this again. */
3294 set_use_sendfile(SNUM(conn
), False
);
3295 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3296 nread
= fake_sendfile(fsp
, startpos
,
3299 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3300 fsp
->fsp_name
, strerror(errno
) ));
3301 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3303 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3304 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3305 /* No outbuf here means successful sendfile. */
3306 TALLOC_FREE(req
->outbuf
);
3310 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3311 fsp
->fsp_name
, strerror(errno
) ));
3312 exit_server_cleanly("send_file_readX sendfile failed");
3315 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3316 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3317 /* No outbuf here means successful sendfile. */
3318 TALLOC_FREE(req
->outbuf
);
3325 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3326 uint8 headerbuf
[smb_size
+ 2*12];
3328 construct_reply_common((char *)req
->inbuf
, (char *)headerbuf
);
3329 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3331 /* Send out the header. */
3332 if (write_data(smbd_server_fd(), (char *)headerbuf
,
3333 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3334 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3335 fsp
->fsp_name
, strerror(errno
) ));
3336 exit_server_cleanly("send_file_readX sendfile failed");
3338 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3340 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3341 fsp
->fsp_name
, strerror(errno
) ));
3342 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3344 TALLOC_FREE(req
->outbuf
);
3347 reply_outbuf(req
, 12, smb_maxcnt
);
3349 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
,
3352 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3356 setup_readX_header((char *)req
->outbuf
, nread
);
3358 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3359 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3367 /****************************************************************************
3368 Reply to a read and X.
3369 ****************************************************************************/
3371 void reply_read_and_X(struct smb_request
*req
)
3373 connection_struct
*conn
= req
->conn
;
3377 bool big_readX
= False
;
3379 size_t smb_mincnt
= SVAL(req
->inbuf
,smb_vwv6
);
3382 START_PROFILE(SMBreadX
);
3384 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3385 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3389 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv2
));
3390 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv3
);
3391 smb_maxcnt
= SVAL(req
->inbuf
,smb_vwv5
);
3393 /* If it's an IPC, pass off the pipe handler. */
3395 reply_pipe_read_and_X(req
);
3396 END_PROFILE(SMBreadX
);
3400 if (!check_fsp(conn
, req
, fsp
)) {
3401 END_PROFILE(SMBreadX
);
3405 if (!CHECK_READ(fsp
,req
->inbuf
)) {
3406 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3407 END_PROFILE(SMBreadX
);
3411 if (global_client_caps
& CAP_LARGE_READX
) {
3412 size_t upper_size
= SVAL(req
->inbuf
,smb_vwv7
);
3413 smb_maxcnt
|= (upper_size
<<16);
3414 if (upper_size
> 1) {
3415 /* Can't do this on a chained packet. */
3416 if ((CVAL(req
->inbuf
,smb_vwv0
) != 0xFF)) {
3417 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3418 END_PROFILE(SMBreadX
);
3421 /* We currently don't do this on signed or sealed data. */
3422 if (srv_is_signing_active() || is_encrypted_packet(req
->inbuf
)) {
3423 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3424 END_PROFILE(SMBreadX
);
3427 /* Is there room in the reply for this data ? */
3428 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3430 NT_STATUS_INVALID_PARAMETER
);
3431 END_PROFILE(SMBreadX
);
3438 if (req
->wct
== 12) {
3439 #ifdef LARGE_SMB_OFF_T
3441 * This is a large offset (64 bit) read.
3443 startpos
|= (((SMB_OFF_T
)IVAL(req
->inbuf
,smb_vwv10
)) << 32);
3445 #else /* !LARGE_SMB_OFF_T */
3448 * Ensure we haven't been sent a >32 bit offset.
3451 if(IVAL(req
->inbuf
,smb_vwv10
) != 0) {
3452 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3453 "used and we don't support 64 bit offsets.\n",
3454 (unsigned int)IVAL(req
->inbuf
,smb_vwv10
) ));
3455 END_PROFILE(SMBreadX
);
3456 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3460 #endif /* LARGE_SMB_OFF_T */
3464 if (is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)smb_maxcnt
,
3465 (SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
3466 END_PROFILE(SMBreadX
);
3467 reply_doserror(req
, ERRDOS
, ERRlock
);
3472 schedule_aio_read_and_X(conn
, req
, fsp
, startpos
, smb_maxcnt
)) {
3473 END_PROFILE(SMBreadX
);
3477 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3479 END_PROFILE(SMBreadX
);
3483 /****************************************************************************
3484 Error replies to writebraw must have smb_wct == 1. Fix this up.
3485 ****************************************************************************/
3487 void error_to_writebrawerr(struct smb_request
*req
)
3489 uint8
*old_outbuf
= req
->outbuf
;
3491 reply_outbuf(req
, 1, 0);
3493 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3494 TALLOC_FREE(old_outbuf
);
3497 /****************************************************************************
3498 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3499 ****************************************************************************/
3501 void reply_writebraw(struct smb_request
*req
)
3503 connection_struct
*conn
= req
->conn
;
3506 ssize_t total_written
=0;
3507 size_t numtowrite
=0;
3515 START_PROFILE(SMBwritebraw
);
3518 * If we ever reply with an error, it must have the SMB command
3519 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3522 SCVAL(req
->inbuf
,smb_com
,SMBwritec
);
3524 if (srv_is_signing_active()) {
3525 END_PROFILE(SMBwritebraw
);
3526 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3527 "raw reads/writes are disallowed.");
3530 if (req
->wct
< 12) {
3531 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3532 error_to_writebrawerr(req
);
3533 END_PROFILE(SMBwritebraw
);
3537 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3538 if (!check_fsp(conn
, req
, fsp
)) {
3539 error_to_writebrawerr(req
);
3540 END_PROFILE(SMBwritebraw
);
3544 if (!CHECK_WRITE(fsp
)) {
3545 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3546 error_to_writebrawerr(req
);
3547 END_PROFILE(SMBwritebraw
);
3551 tcount
= IVAL(req
->inbuf
,smb_vwv1
);
3552 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv3
);
3553 write_through
= BITSETW(req
->inbuf
+smb_vwv7
,0);
3555 /* We have to deal with slightly different formats depending
3556 on whether we are using the core+ or lanman1.0 protocol */
3558 if(Protocol
<= PROTOCOL_COREPLUS
) {
3559 numtowrite
= SVAL(smb_buf(req
->inbuf
),-2);
3560 data
= smb_buf(req
->inbuf
);
3562 numtowrite
= SVAL(req
->inbuf
,smb_vwv10
);
3563 data
= smb_base(req
->inbuf
) + SVAL(req
->inbuf
, smb_vwv11
);
3566 /* Ensure we don't write bytes past the end of this packet. */
3567 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3568 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3569 error_to_writebrawerr(req
);
3570 END_PROFILE(SMBwritebraw
);
3574 if (is_locked(fsp
,(uint32
)req
->smbpid
,(SMB_BIG_UINT
)tcount
,
3575 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3576 reply_doserror(req
, ERRDOS
, ERRlock
);
3577 error_to_writebrawerr(req
);
3578 END_PROFILE(SMBwritebraw
);
3583 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3586 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3587 "wrote=%d sync=%d\n",
3588 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3589 (int)nwritten
, (int)write_through
));
3591 if (nwritten
< (ssize_t
)numtowrite
) {
3592 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3593 error_to_writebrawerr(req
);
3594 END_PROFILE(SMBwritebraw
);
3598 total_written
= nwritten
;
3600 /* Allocate a buffer of 64k + length. */
3601 buf
= TALLOC_ARRAY(NULL
, char, 65540);
3603 reply_doserror(req
, ERRDOS
, ERRnomem
);
3604 error_to_writebrawerr(req
);
3605 END_PROFILE(SMBwritebraw
);
3609 /* Return a SMBwritebraw message to the redirector to tell
3610 * it to send more bytes */
3612 memcpy(buf
, req
->inbuf
, smb_size
);
3613 srv_set_message(buf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
3614 SCVAL(buf
,smb_com
,SMBwritebraw
);
3615 SSVALS(buf
,smb_vwv0
,0xFFFF);
3617 if (!srv_send_smb(smbd_server_fd(),
3619 IS_CONN_ENCRYPTED(conn
))) {
3620 exit_server_cleanly("reply_writebraw: srv_send_smb "
3624 /* Now read the raw data into the buffer and write it */
3625 status
= read_smb_length(smbd_server_fd(), buf
, SMB_SECONDARY_WAIT
,
3627 if (!NT_STATUS_IS_OK(status
)) {
3628 exit_server_cleanly("secondary writebraw failed");
3631 /* Set up outbuf to return the correct size */
3632 reply_outbuf(req
, 1, 0);
3634 if (numtowrite
!= 0) {
3636 if (numtowrite
> 0xFFFF) {
3637 DEBUG(0,("reply_writebraw: Oversize secondary write "
3638 "raw requested (%u). Terminating\n",
3639 (unsigned int)numtowrite
));
3640 exit_server_cleanly("secondary writebraw failed");
3643 if (tcount
> nwritten
+numtowrite
) {
3644 DEBUG(3,("reply_writebraw: Client overestimated the "
3646 (int)tcount
,(int)nwritten
,(int)numtowrite
));
3649 status
= read_data(smbd_server_fd(), buf
+4, numtowrite
);
3651 if (!NT_STATUS_IS_OK(status
)) {
3652 DEBUG(0,("reply_writebraw: Oversize secondary write "
3653 "raw read failed (%s). Terminating\n",
3654 nt_errstr(status
)));
3655 exit_server_cleanly("secondary writebraw failed");
3658 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
3659 if (nwritten
== -1) {
3661 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3662 error_to_writebrawerr(req
);
3663 END_PROFILE(SMBwritebraw
);
3667 if (nwritten
< (ssize_t
)numtowrite
) {
3668 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
3669 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
3673 total_written
+= nwritten
;
3678 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
3680 status
= sync_file(conn
, fsp
, write_through
);
3681 if (!NT_STATUS_IS_OK(status
)) {
3682 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3683 fsp
->fsp_name
, nt_errstr(status
) ));
3684 reply_nterror(req
, status
);
3685 error_to_writebrawerr(req
);
3686 END_PROFILE(SMBwritebraw
);
3690 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3692 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3693 (int)total_written
));
3695 /* We won't return a status if write through is not selected - this
3696 * follows what WfWg does */
3697 END_PROFILE(SMBwritebraw
);
3699 if (!write_through
&& total_written
==tcount
) {
3701 #if RABBIT_PELLET_FIX
3703 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3704 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3707 if (!send_keepalive(smbd_server_fd())) {
3708 exit_server_cleanly("reply_writebraw: send of "
3709 "keepalive failed");
3712 TALLOC_FREE(req
->outbuf
);
3718 #define DBGC_CLASS DBGC_LOCKING
3720 /****************************************************************************
3721 Reply to a writeunlock (core+).
3722 ****************************************************************************/
3724 void reply_writeunlock(struct smb_request
*req
)
3726 connection_struct
*conn
= req
->conn
;
3727 ssize_t nwritten
= -1;
3731 NTSTATUS status
= NT_STATUS_OK
;
3734 START_PROFILE(SMBwriteunlock
);
3737 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3738 END_PROFILE(SMBwriteunlock
);
3742 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3744 if (!check_fsp(conn
, req
, fsp
)) {
3745 END_PROFILE(SMBwriteunlock
);
3749 if (!CHECK_WRITE(fsp
)) {
3750 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3751 END_PROFILE(SMBwriteunlock
);
3755 numtowrite
= SVAL(req
->inbuf
,smb_vwv1
);
3756 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
3757 data
= smb_buf(req
->inbuf
) + 3;
3760 && is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtowrite
,
3761 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3762 reply_doserror(req
, ERRDOS
, ERRlock
);
3763 END_PROFILE(SMBwriteunlock
);
3767 /* The special X/Open SMB protocol handling of
3768 zero length writes is *NOT* done for
3770 if(numtowrite
== 0) {
3773 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3776 status
= sync_file(conn
, fsp
, False
/* write through */);
3777 if (!NT_STATUS_IS_OK(status
)) {
3778 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3779 fsp
->fsp_name
, nt_errstr(status
) ));
3780 reply_nterror(req
, status
);
3781 END_PROFILE(SMBwriteunlock
);
3785 if(((nwritten
< numtowrite
) && (numtowrite
!= 0))||(nwritten
< 0)) {
3786 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3787 END_PROFILE(SMBwriteunlock
);
3792 status
= do_unlock(smbd_messaging_context(),
3795 (SMB_BIG_UINT
)numtowrite
,
3796 (SMB_BIG_UINT
)startpos
,
3799 if (NT_STATUS_V(status
)) {
3800 reply_nterror(req
, status
);
3801 END_PROFILE(SMBwriteunlock
);
3806 reply_outbuf(req
, 1, 0);
3808 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
3810 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3811 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
3813 END_PROFILE(SMBwriteunlock
);
3818 #define DBGC_CLASS DBGC_ALL
3820 /****************************************************************************
3822 ****************************************************************************/
3824 void reply_write(struct smb_request
*req
)
3826 connection_struct
*conn
= req
->conn
;
3828 ssize_t nwritten
= -1;
3834 START_PROFILE(SMBwrite
);
3837 END_PROFILE(SMBwrite
);
3838 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3842 /* If it's an IPC, pass off the pipe handler. */
3844 reply_pipe_write(req
);
3845 END_PROFILE(SMBwrite
);
3849 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3851 if (!check_fsp(conn
, req
, fsp
)) {
3852 END_PROFILE(SMBwrite
);
3856 if (!CHECK_WRITE(fsp
)) {
3857 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3858 END_PROFILE(SMBwrite
);
3862 numtowrite
= SVAL(req
->inbuf
,smb_vwv1
);
3863 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
3864 data
= smb_buf(req
->inbuf
) + 3;
3866 if (is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtowrite
,
3867 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3868 reply_doserror(req
, ERRDOS
, ERRlock
);
3869 END_PROFILE(SMBwrite
);
3874 * X/Open SMB protocol says that if smb_vwv1 is
3875 * zero then the file size should be extended or
3876 * truncated to the size given in smb_vwv[2-3].
3879 if(numtowrite
== 0) {
3881 * This is actually an allocate call, and set EOF. JRA.
3883 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
3885 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3886 END_PROFILE(SMBwrite
);
3889 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
3891 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3892 END_PROFILE(SMBwrite
);
3895 trigger_write_time_update_immediate(fsp
);
3897 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3900 status
= sync_file(conn
, fsp
, False
);
3901 if (!NT_STATUS_IS_OK(status
)) {
3902 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3903 fsp
->fsp_name
, nt_errstr(status
) ));
3904 reply_nterror(req
, status
);
3905 END_PROFILE(SMBwrite
);
3909 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
3910 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3911 END_PROFILE(SMBwrite
);
3915 reply_outbuf(req
, 1, 0);
3917 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
3919 if (nwritten
< (ssize_t
)numtowrite
) {
3920 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
3921 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
3924 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
3926 END_PROFILE(SMBwrite
);
3930 /****************************************************************************
3931 Ensure a buffer is a valid writeX for recvfile purposes.
3932 ****************************************************************************/
3934 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3935 (2*14) + /* word count (including bcc) */ \
3938 bool is_valid_writeX_buffer(const uint8_t *inbuf
)
3941 connection_struct
*conn
= NULL
;
3942 unsigned int doff
= 0;
3943 size_t len
= smb_len_large(inbuf
);
3945 if (is_encrypted_packet(inbuf
)) {
3946 /* Can't do this on encrypted
3951 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
3955 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
3956 CVAL(inbuf
,smb_wct
) != 14) {
3957 DEBUG(10,("is_valid_writeX_buffer: chained or "
3958 "invalid word length.\n"));
3962 conn
= conn_find(SVAL(inbuf
, smb_tid
));
3964 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3968 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3971 if (IS_PRINT(conn
)) {
3972 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
3975 doff
= SVAL(inbuf
,smb_vwv11
);
3977 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3979 if (len
> doff
&& len
- doff
> 0xFFFF) {
3980 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
3983 if (numtowrite
== 0) {
3984 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3988 /* Ensure the sizes match up. */
3989 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
3990 /* no pad byte...old smbclient :-( */
3991 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3993 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
3997 if (len
- doff
!= numtowrite
) {
3998 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3999 "len = %u, doff = %u, numtowrite = %u\n",
4002 (unsigned int)numtowrite
));
4006 DEBUG(10,("is_valid_writeX_buffer: true "
4007 "len = %u, doff = %u, numtowrite = %u\n",
4010 (unsigned int)numtowrite
));
4015 /****************************************************************************
4016 Reply to a write and X.
4017 ****************************************************************************/
4019 void reply_write_and_X(struct smb_request
*req
)
4021 connection_struct
*conn
= req
->conn
;
4027 unsigned int smb_doff
;
4028 unsigned int smblen
;
4032 START_PROFILE(SMBwriteX
);
4034 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4035 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4036 END_PROFILE(SMBwriteX
);
4040 numtowrite
= SVAL(req
->inbuf
,smb_vwv10
);
4041 smb_doff
= SVAL(req
->inbuf
,smb_vwv11
);
4042 smblen
= smb_len(req
->inbuf
);
4044 if (req
->unread_bytes
> 0xFFFF ||
4045 (smblen
> smb_doff
&&
4046 smblen
- smb_doff
> 0xFFFF)) {
4047 numtowrite
|= (((size_t)SVAL(req
->inbuf
,smb_vwv9
))<<16);
4050 if (req
->unread_bytes
) {
4051 /* Can't do a recvfile write on IPC$ */
4053 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4054 END_PROFILE(SMBwriteX
);
4057 if (numtowrite
!= req
->unread_bytes
) {
4058 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4059 END_PROFILE(SMBwriteX
);
4063 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4064 smb_doff
+ numtowrite
> smblen
) {
4065 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4066 END_PROFILE(SMBwriteX
);
4071 /* If it's an IPC, pass off the pipe handler. */
4073 if (req
->unread_bytes
) {
4074 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4075 END_PROFILE(SMBwriteX
);
4078 reply_pipe_write_and_X(req
);
4079 END_PROFILE(SMBwriteX
);
4083 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv2
));
4084 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv3
);
4085 write_through
= BITSETW(req
->inbuf
+smb_vwv7
,0);
4087 if (!check_fsp(conn
, req
, fsp
)) {
4088 END_PROFILE(SMBwriteX
);
4092 if (!CHECK_WRITE(fsp
)) {
4093 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4094 END_PROFILE(SMBwriteX
);
4098 data
= smb_base(req
->inbuf
) + smb_doff
;
4100 if(req
->wct
== 14) {
4101 #ifdef LARGE_SMB_OFF_T
4103 * This is a large offset (64 bit) write.
4105 startpos
|= (((SMB_OFF_T
)IVAL(req
->inbuf
,smb_vwv12
)) << 32);
4107 #else /* !LARGE_SMB_OFF_T */
4110 * Ensure we haven't been sent a >32 bit offset.
4113 if(IVAL(req
->inbuf
,smb_vwv12
) != 0) {
4114 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4115 "used and we don't support 64 bit offsets.\n",
4116 (unsigned int)IVAL(req
->inbuf
,smb_vwv12
) ));
4117 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4118 END_PROFILE(SMBwriteX
);
4122 #endif /* LARGE_SMB_OFF_T */
4125 if (is_locked(fsp
,(uint32
)req
->smbpid
,
4126 (SMB_BIG_UINT
)numtowrite
,
4127 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
4128 reply_doserror(req
, ERRDOS
, ERRlock
);
4129 END_PROFILE(SMBwriteX
);
4133 /* X/Open SMB protocol says that, unlike SMBwrite
4134 if the length is zero then NO truncation is
4135 done, just a write of zero. To truncate a file,
4138 if(numtowrite
== 0) {
4142 if ((req
->unread_bytes
== 0) &&
4143 schedule_aio_write_and_X(conn
, req
, fsp
, data
, startpos
,
4145 END_PROFILE(SMBwriteX
);
4149 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4152 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4153 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
4154 END_PROFILE(SMBwriteX
);
4158 reply_outbuf(req
, 6, 0);
4159 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4160 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4162 if (nwritten
< (ssize_t
)numtowrite
) {
4163 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4164 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4167 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4168 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4170 status
= sync_file(conn
, fsp
, write_through
);
4171 if (!NT_STATUS_IS_OK(status
)) {
4172 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4173 fsp
->fsp_name
, nt_errstr(status
) ));
4174 reply_nterror(req
, status
);
4175 END_PROFILE(SMBwriteX
);
4179 END_PROFILE(SMBwriteX
);
4184 /****************************************************************************
4186 ****************************************************************************/
4188 void reply_lseek(struct smb_request
*req
)
4190 connection_struct
*conn
= req
->conn
;
4196 START_PROFILE(SMBlseek
);
4199 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4200 END_PROFILE(SMBlseek
);
4204 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4206 if (!check_fsp(conn
, req
, fsp
)) {
4210 flush_write_cache(fsp
, SEEK_FLUSH
);
4212 mode
= SVAL(req
->inbuf
,smb_vwv1
) & 3;
4213 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4214 startpos
= (SMB_OFF_T
)IVALS(req
->inbuf
,smb_vwv2
);
4223 res
= fsp
->fh
->pos
+ startpos
;
4234 if (umode
== SEEK_END
) {
4235 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4236 if(errno
== EINVAL
) {
4237 SMB_OFF_T current_pos
= startpos
;
4238 SMB_STRUCT_STAT sbuf
;
4240 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
4241 reply_unixerror(req
, ERRDOS
,
4243 END_PROFILE(SMBlseek
);
4247 current_pos
+= sbuf
.st_size
;
4249 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4254 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
4255 END_PROFILE(SMBlseek
);
4262 reply_outbuf(req
, 2, 0);
4263 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4265 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4266 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4268 END_PROFILE(SMBlseek
);
4272 /****************************************************************************
4274 ****************************************************************************/
4276 void reply_flush(struct smb_request
*req
)
4278 connection_struct
*conn
= req
->conn
;
4282 START_PROFILE(SMBflush
);
4285 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4289 fnum
= SVAL(req
->inbuf
,smb_vwv0
);
4290 fsp
= file_fsp(fnum
);
4292 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4297 file_sync_all(conn
);
4299 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4300 if (!NT_STATUS_IS_OK(status
)) {
4301 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4302 fsp
->fsp_name
, nt_errstr(status
) ));
4303 reply_nterror(req
, status
);
4304 END_PROFILE(SMBflush
);
4309 reply_outbuf(req
, 0, 0);
4311 DEBUG(3,("flush\n"));
4312 END_PROFILE(SMBflush
);
4316 /****************************************************************************
4318 conn POINTER CAN BE NULL HERE !
4319 ****************************************************************************/
4321 void reply_exit(struct smb_request
*req
)
4323 START_PROFILE(SMBexit
);
4325 file_close_pid(req
->smbpid
, req
->vuid
);
4327 reply_outbuf(req
, 0, 0);
4329 DEBUG(3,("exit\n"));
4331 END_PROFILE(SMBexit
);
4335 /****************************************************************************
4336 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4337 ****************************************************************************/
4339 void reply_close(struct smb_request
*req
)
4341 connection_struct
*conn
= req
->conn
;
4342 NTSTATUS status
= NT_STATUS_OK
;
4343 files_struct
*fsp
= NULL
;
4344 START_PROFILE(SMBclose
);
4347 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4348 END_PROFILE(SMBclose
);
4352 /* If it's an IPC, pass off to the pipe handler. */
4354 reply_pipe_close(conn
, req
);
4355 END_PROFILE(SMBclose
);
4359 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4362 * We can only use check_fsp if we know it's not a directory.
4365 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= req
->vuid
)) {
4366 reply_doserror(req
, ERRDOS
, ERRbadfid
);
4367 END_PROFILE(SMBclose
);
4371 if(fsp
->is_directory
) {
4373 * Special case - close NT SMB directory handle.
4375 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4376 status
= close_file(fsp
,NORMAL_CLOSE
);
4380 * Close ordinary file.
4383 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4384 fsp
->fh
->fd
, fsp
->fnum
,
4385 conn
->num_files_open
));
4388 * Take care of any time sent in the close.
4391 t
= srv_make_unix_date3(req
->inbuf
+smb_vwv1
);
4392 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4395 * close_file() returns the unix errno if an error
4396 * was detected on close - normally this is due to
4397 * a disk full error. If not then it was probably an I/O error.
4400 status
= close_file(fsp
,NORMAL_CLOSE
);
4403 if (!NT_STATUS_IS_OK(status
)) {
4404 reply_nterror(req
, status
);
4405 END_PROFILE(SMBclose
);
4409 reply_outbuf(req
, 0, 0);
4410 END_PROFILE(SMBclose
);
4414 /****************************************************************************
4415 Reply to a writeclose (Core+ protocol).
4416 ****************************************************************************/
4418 void reply_writeclose(struct smb_request
*req
)
4420 connection_struct
*conn
= req
->conn
;
4422 ssize_t nwritten
= -1;
4423 NTSTATUS close_status
= NT_STATUS_OK
;
4426 struct timespec mtime
;
4429 START_PROFILE(SMBwriteclose
);
4432 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4433 END_PROFILE(SMBwriteclose
);
4437 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4439 if (!check_fsp(conn
, req
, fsp
)) {
4440 END_PROFILE(SMBwriteclose
);
4443 if (!CHECK_WRITE(fsp
)) {
4444 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
4445 END_PROFILE(SMBwriteclose
);
4449 numtowrite
= SVAL(req
->inbuf
,smb_vwv1
);
4450 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
4451 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(
4452 req
->inbuf
+smb_vwv4
));
4453 data
= smb_buf(req
->inbuf
) + 1;
4456 && is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtowrite
,
4457 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
4458 reply_doserror(req
, ERRDOS
,ERRlock
);
4459 END_PROFILE(SMBwriteclose
);
4463 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4465 set_close_write_time(fsp
, mtime
);
4468 * More insanity. W2K only closes the file if writelen > 0.
4473 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4475 close_status
= close_file(fsp
,NORMAL_CLOSE
);
4478 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4479 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4480 conn
->num_files_open
));
4482 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4483 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4484 END_PROFILE(SMBwriteclose
);
4488 if(!NT_STATUS_IS_OK(close_status
)) {
4489 reply_nterror(req
, close_status
);
4490 END_PROFILE(SMBwriteclose
);
4494 reply_outbuf(req
, 1, 0);
4496 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4497 END_PROFILE(SMBwriteclose
);
4502 #define DBGC_CLASS DBGC_LOCKING
4504 /****************************************************************************
4506 ****************************************************************************/
4508 void reply_lock(struct smb_request
*req
)
4510 connection_struct
*conn
= req
->conn
;
4511 SMB_BIG_UINT count
,offset
;
4514 struct byte_range_lock
*br_lck
= NULL
;
4516 START_PROFILE(SMBlock
);
4519 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4520 END_PROFILE(SMBlock
);
4524 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4526 if (!check_fsp(conn
, req
, fsp
)) {
4527 END_PROFILE(SMBlock
);
4531 release_level_2_oplocks_on_change(fsp
);
4533 count
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv1
);
4534 offset
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv3
);
4536 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4537 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
4539 br_lck
= do_lock(smbd_messaging_context(),
4546 False
, /* Non-blocking lock. */
4550 TALLOC_FREE(br_lck
);
4552 if (NT_STATUS_V(status
)) {
4553 reply_nterror(req
, status
);
4554 END_PROFILE(SMBlock
);
4558 reply_outbuf(req
, 0, 0);
4560 END_PROFILE(SMBlock
);
4564 /****************************************************************************
4566 ****************************************************************************/
4568 void reply_unlock(struct smb_request
*req
)
4570 connection_struct
*conn
= req
->conn
;
4571 SMB_BIG_UINT count
,offset
;
4575 START_PROFILE(SMBunlock
);
4578 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4579 END_PROFILE(SMBunlock
);
4583 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4585 if (!check_fsp(conn
, req
, fsp
)) {
4586 END_PROFILE(SMBunlock
);
4590 count
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv1
);
4591 offset
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv3
);
4593 status
= do_unlock(smbd_messaging_context(),
4600 if (NT_STATUS_V(status
)) {
4601 reply_nterror(req
, status
);
4602 END_PROFILE(SMBunlock
);
4606 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4607 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
4609 reply_outbuf(req
, 0, 0);
4611 END_PROFILE(SMBunlock
);
4616 #define DBGC_CLASS DBGC_ALL
4618 /****************************************************************************
4620 conn POINTER CAN BE NULL HERE !
4621 ****************************************************************************/
4623 void reply_tdis(struct smb_request
*req
)
4625 connection_struct
*conn
= req
->conn
;
4626 START_PROFILE(SMBtdis
);
4629 DEBUG(4,("Invalid connection in tdis\n"));
4630 reply_doserror(req
, ERRSRV
, ERRinvnid
);
4631 END_PROFILE(SMBtdis
);
4637 close_cnum(conn
,req
->vuid
);
4640 reply_outbuf(req
, 0, 0);
4641 END_PROFILE(SMBtdis
);
4645 /****************************************************************************
4647 conn POINTER CAN BE NULL HERE !
4648 ****************************************************************************/
4650 void reply_echo(struct smb_request
*req
)
4652 connection_struct
*conn
= req
->conn
;
4655 unsigned int data_len
= smb_buflen(req
->inbuf
);
4657 START_PROFILE(SMBecho
);
4660 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4661 END_PROFILE(SMBecho
);
4665 if (data_len
> BUFFER_SIZE
) {
4666 DEBUG(0,("reply_echo: data_len too large.\n"));
4667 reply_nterror(req
, NT_STATUS_INSUFFICIENT_RESOURCES
);
4668 END_PROFILE(SMBecho
);
4672 smb_reverb
= SVAL(req
->inbuf
,smb_vwv0
);
4674 reply_outbuf(req
, 1, data_len
);
4676 /* copy any incoming data back out */
4678 memcpy(smb_buf(req
->outbuf
),smb_buf(req
->inbuf
),data_len
);
4681 if (smb_reverb
> 100) {
4682 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
4686 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
4687 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
4689 show_msg((char *)req
->outbuf
);
4690 if (!srv_send_smb(smbd_server_fd(),
4691 (char *)req
->outbuf
,
4692 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
))
4693 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4696 DEBUG(3,("echo %d times\n", smb_reverb
));
4698 TALLOC_FREE(req
->outbuf
);
4700 END_PROFILE(SMBecho
);
4704 /****************************************************************************
4705 Reply to a printopen.
4706 ****************************************************************************/
4708 void reply_printopen(struct smb_request
*req
)
4710 connection_struct
*conn
= req
->conn
;
4712 SMB_STRUCT_STAT sbuf
;
4715 START_PROFILE(SMBsplopen
);
4718 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4719 END_PROFILE(SMBsplopen
);
4723 if (!CAN_PRINT(conn
)) {
4724 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4725 END_PROFILE(SMBsplopen
);
4729 status
= file_new(conn
, &fsp
);
4730 if(!NT_STATUS_IS_OK(status
)) {
4731 reply_nterror(req
, status
);
4732 END_PROFILE(SMBsplopen
);
4736 /* Open for exclusive use, write only. */
4737 status
= print_fsp_open(conn
, NULL
, req
->vuid
, fsp
, &sbuf
);
4739 if (!NT_STATUS_IS_OK(status
)) {
4741 reply_nterror(req
, status
);
4742 END_PROFILE(SMBsplopen
);
4746 reply_outbuf(req
, 1, 0);
4747 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
4749 DEBUG(3,("openprint fd=%d fnum=%d\n",
4750 fsp
->fh
->fd
, fsp
->fnum
));
4752 END_PROFILE(SMBsplopen
);
4756 /****************************************************************************
4757 Reply to a printclose.
4758 ****************************************************************************/
4760 void reply_printclose(struct smb_request
*req
)
4762 connection_struct
*conn
= req
->conn
;
4766 START_PROFILE(SMBsplclose
);
4769 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4770 END_PROFILE(SMBsplclose
);
4774 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4776 if (!check_fsp(conn
, req
, fsp
)) {
4777 END_PROFILE(SMBsplclose
);
4781 if (!CAN_PRINT(conn
)) {
4782 reply_nterror(req
, NT_STATUS_DOS(ERRSRV
, ERRerror
));
4783 END_PROFILE(SMBsplclose
);
4787 DEBUG(3,("printclose fd=%d fnum=%d\n",
4788 fsp
->fh
->fd
,fsp
->fnum
));
4790 status
= close_file(fsp
,NORMAL_CLOSE
);
4792 if(!NT_STATUS_IS_OK(status
)) {
4793 reply_nterror(req
, status
);
4794 END_PROFILE(SMBsplclose
);
4798 reply_outbuf(req
, 0, 0);
4800 END_PROFILE(SMBsplclose
);
4804 /****************************************************************************
4805 Reply to a printqueue.
4806 ****************************************************************************/
4808 void reply_printqueue(struct smb_request
*req
)
4810 connection_struct
*conn
= req
->conn
;
4814 START_PROFILE(SMBsplretq
);
4817 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4818 END_PROFILE(SMBsplretq
);
4822 max_count
= SVAL(req
->inbuf
,smb_vwv0
);
4823 start_index
= SVAL(req
->inbuf
,smb_vwv1
);
4825 /* we used to allow the client to get the cnum wrong, but that
4826 is really quite gross and only worked when there was only
4827 one printer - I think we should now only accept it if they
4828 get it right (tridge) */
4829 if (!CAN_PRINT(conn
)) {
4830 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4831 END_PROFILE(SMBsplretq
);
4835 reply_outbuf(req
, 2, 3);
4836 SSVAL(req
->outbuf
,smb_vwv0
,0);
4837 SSVAL(req
->outbuf
,smb_vwv1
,0);
4838 SCVAL(smb_buf(req
->outbuf
),0,1);
4839 SSVAL(smb_buf(req
->outbuf
),1,0);
4841 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4842 start_index
, max_count
));
4845 print_queue_struct
*queue
= NULL
;
4846 print_status_struct status
;
4847 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
4848 int num_to_get
= ABS(max_count
);
4849 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
4855 num_to_get
= MIN(num_to_get
,count
-first
);
4858 for (i
=first
;i
<first
+num_to_get
;i
++) {
4862 srv_put_dos_date2(p
,0,queue
[i
].time
);
4863 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
4864 SSVAL(p
,5, queue
[i
].job
);
4865 SIVAL(p
,7,queue
[i
].size
);
4867 srvstr_push(blob
, req
->flags2
, p
+12,
4868 queue
[i
].fs_user
, 16, STR_ASCII
);
4870 if (message_push_blob(
4873 blob
, sizeof(blob
))) == -1) {
4874 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4875 END_PROFILE(SMBsplretq
);
4881 SSVAL(req
->outbuf
,smb_vwv0
,count
);
4882 SSVAL(req
->outbuf
,smb_vwv1
,
4883 (max_count
>0?first
+count
:first
-1));
4884 SCVAL(smb_buf(req
->outbuf
),0,1);
4885 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
4890 DEBUG(3,("%d entries returned in queue\n",count
));
4893 END_PROFILE(SMBsplretq
);
4897 /****************************************************************************
4898 Reply to a printwrite.
4899 ****************************************************************************/
4901 void reply_printwrite(struct smb_request
*req
)
4903 connection_struct
*conn
= req
->conn
;
4908 START_PROFILE(SMBsplwr
);
4911 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4912 END_PROFILE(SMBsplwr
);
4916 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4918 if (!check_fsp(conn
, req
, fsp
)) {
4919 END_PROFILE(SMBsplwr
);
4923 if (!CAN_PRINT(conn
)) {
4924 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4925 END_PROFILE(SMBsplwr
);
4929 if (!CHECK_WRITE(fsp
)) {
4930 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4931 END_PROFILE(SMBsplwr
);
4935 numtowrite
= SVAL(smb_buf(req
->inbuf
),1);
4937 if (smb_buflen(req
->inbuf
) < numtowrite
+ 3) {
4938 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4939 END_PROFILE(SMBsplwr
);
4943 data
= smb_buf(req
->inbuf
) + 3;
4945 if (write_file(req
,fsp
,data
,-1,numtowrite
) != numtowrite
) {
4946 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
4947 END_PROFILE(SMBsplwr
);
4951 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
4953 END_PROFILE(SMBsplwr
);
4957 /****************************************************************************
4959 ****************************************************************************/
4961 void reply_mkdir(struct smb_request
*req
)
4963 connection_struct
*conn
= req
->conn
;
4964 char *directory
= NULL
;
4966 SMB_STRUCT_STAT sbuf
;
4967 TALLOC_CTX
*ctx
= talloc_tos();
4969 START_PROFILE(SMBmkdir
);
4971 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &directory
,
4972 smb_buf(req
->inbuf
) + 1, 0,
4973 STR_TERMINATE
, &status
);
4974 if (!NT_STATUS_IS_OK(status
)) {
4975 reply_nterror(req
, status
);
4976 END_PROFILE(SMBmkdir
);
4980 status
= resolve_dfspath(ctx
, conn
,
4981 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
4984 if (!NT_STATUS_IS_OK(status
)) {
4985 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4986 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
4987 ERRSRV
, ERRbadpath
);
4988 END_PROFILE(SMBmkdir
);
4991 reply_nterror(req
, status
);
4992 END_PROFILE(SMBmkdir
);
4996 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
, NULL
, &sbuf
);
4997 if (!NT_STATUS_IS_OK(status
)) {
4998 reply_nterror(req
, status
);
4999 END_PROFILE(SMBmkdir
);
5003 status
= check_name(conn
, directory
);
5004 if (!NT_STATUS_IS_OK(status
)) {
5005 reply_nterror(req
, status
);
5006 END_PROFILE(SMBmkdir
);
5010 status
= create_directory(conn
, req
, directory
);
5012 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5014 if (!NT_STATUS_IS_OK(status
)) {
5016 if (!use_nt_status()
5017 && NT_STATUS_EQUAL(status
,
5018 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5020 * Yes, in the DOS error code case we get a
5021 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5022 * samba4 torture test.
5024 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5027 reply_nterror(req
, status
);
5028 END_PROFILE(SMBmkdir
);
5032 reply_outbuf(req
, 0, 0);
5034 DEBUG( 3, ( "mkdir %s\n", directory
) );
5036 END_PROFILE(SMBmkdir
);
5040 /****************************************************************************
5041 Static function used by reply_rmdir to delete an entire directory
5042 tree recursively. Return True on ok, False on fail.
5043 ****************************************************************************/
5045 static bool recursive_rmdir(TALLOC_CTX
*ctx
,
5046 connection_struct
*conn
,
5049 const char *dname
= NULL
;
5052 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
, directory
,
5058 while((dname
= ReadDirName(dir_hnd
, &offset
))) {
5059 char *fullname
= NULL
;
5062 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5066 if (!is_visible_file(conn
, directory
, dname
, &st
, False
)) {
5070 /* Construct the full name. */
5071 fullname
= talloc_asprintf(ctx
,
5081 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
5086 if(st
.st_mode
& S_IFDIR
) {
5087 if(!recursive_rmdir(ctx
, conn
, fullname
)) {
5091 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
5095 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
5099 TALLOC_FREE(fullname
);
5101 TALLOC_FREE(dir_hnd
);
5105 /****************************************************************************
5106 The internals of the rmdir code - called elsewhere.
5107 ****************************************************************************/
5109 NTSTATUS
rmdir_internals(TALLOC_CTX
*ctx
,
5110 connection_struct
*conn
,
5111 const char *directory
)
5116 /* Might be a symlink. */
5117 if(SMB_VFS_LSTAT(conn
, directory
, &st
) != 0) {
5118 return map_nt_error_from_unix(errno
);
5121 if (S_ISLNK(st
.st_mode
)) {
5122 /* Is what it points to a directory ? */
5123 if(SMB_VFS_STAT(conn
, directory
, &st
) != 0) {
5124 return map_nt_error_from_unix(errno
);
5126 if (!(S_ISDIR(st
.st_mode
))) {
5127 return NT_STATUS_NOT_A_DIRECTORY
;
5129 ret
= SMB_VFS_UNLINK(conn
,directory
);
5131 ret
= SMB_VFS_RMDIR(conn
,directory
);
5134 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5135 FILE_NOTIFY_CHANGE_DIR_NAME
,
5137 return NT_STATUS_OK
;
5140 if(((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
5142 * Check to see if the only thing in this directory are
5143 * vetoed files/directories. If so then delete them and
5144 * retry. If we fail to delete any of them (and we *don't*
5145 * do a recursive delete) then fail the rmdir.
5149 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
,
5150 directory
, NULL
, 0);
5152 if(dir_hnd
== NULL
) {
5157 while ((dname
= ReadDirName(dir_hnd
,&dirpos
))) {
5158 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
5160 if (!is_visible_file(conn
, directory
, dname
, &st
, False
))
5162 if(!IS_VETO_PATH(conn
, dname
)) {
5163 TALLOC_FREE(dir_hnd
);
5169 /* We only have veto files/directories.
5170 * Are we allowed to delete them ? */
5172 if(!lp_recursive_veto_delete(SNUM(conn
))) {
5173 TALLOC_FREE(dir_hnd
);
5178 /* Do a recursive delete. */
5179 RewindDir(dir_hnd
,&dirpos
);
5180 while ((dname
= ReadDirName(dir_hnd
,&dirpos
))) {
5181 char *fullname
= NULL
;
5183 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5186 if (!is_visible_file(conn
, directory
, dname
, &st
, False
)) {
5190 fullname
= talloc_asprintf(ctx
,
5200 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
5203 if(st
.st_mode
& S_IFDIR
) {
5204 if(!recursive_rmdir(ctx
, conn
, fullname
)) {
5207 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
5210 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
5213 TALLOC_FREE(fullname
);
5215 TALLOC_FREE(dir_hnd
);
5216 /* Retry the rmdir */
5217 ret
= SMB_VFS_RMDIR(conn
,directory
);
5223 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5224 "%s\n", directory
,strerror(errno
)));
5225 return map_nt_error_from_unix(errno
);
5228 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5229 FILE_NOTIFY_CHANGE_DIR_NAME
,
5232 return NT_STATUS_OK
;
5235 /****************************************************************************
5237 ****************************************************************************/
5239 void reply_rmdir(struct smb_request
*req
)
5241 connection_struct
*conn
= req
->conn
;
5242 char *directory
= NULL
;
5243 SMB_STRUCT_STAT sbuf
;
5245 TALLOC_CTX
*ctx
= talloc_tos();
5247 START_PROFILE(SMBrmdir
);
5249 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &directory
,
5250 smb_buf(req
->inbuf
) + 1, 0,
5251 STR_TERMINATE
, &status
);
5252 if (!NT_STATUS_IS_OK(status
)) {
5253 reply_nterror(req
, status
);
5254 END_PROFILE(SMBrmdir
);
5258 status
= resolve_dfspath(ctx
, conn
,
5259 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5262 if (!NT_STATUS_IS_OK(status
)) {
5263 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5264 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5265 ERRSRV
, ERRbadpath
);
5266 END_PROFILE(SMBrmdir
);
5269 reply_nterror(req
, status
);
5270 END_PROFILE(SMBrmdir
);
5274 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
,
5276 if (!NT_STATUS_IS_OK(status
)) {
5277 reply_nterror(req
, status
);
5278 END_PROFILE(SMBrmdir
);
5282 status
= check_name(conn
, directory
);
5283 if (!NT_STATUS_IS_OK(status
)) {
5284 reply_nterror(req
, status
);
5285 END_PROFILE(SMBrmdir
);
5289 dptr_closepath(directory
, req
->smbpid
);
5290 status
= rmdir_internals(ctx
, conn
, directory
);
5291 if (!NT_STATUS_IS_OK(status
)) {
5292 reply_nterror(req
, status
);
5293 END_PROFILE(SMBrmdir
);
5297 reply_outbuf(req
, 0, 0);
5299 DEBUG( 3, ( "rmdir %s\n", directory
) );
5301 END_PROFILE(SMBrmdir
);
5305 /*******************************************************************
5306 Resolve wildcards in a filename rename.
5307 ********************************************************************/
5309 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5314 char *name2_copy
= NULL
;
5319 char *p
,*p2
, *pname1
, *pname2
;
5321 name2_copy
= talloc_strdup(ctx
, name2
);
5326 pname1
= strrchr_m(name1
,'/');
5327 pname2
= strrchr_m(name2_copy
,'/');
5329 if (!pname1
|| !pname2
) {
5333 /* Truncate the copy of name2 at the last '/' */
5336 /* Now go past the '/' */
5340 root1
= talloc_strdup(ctx
, pname1
);
5341 root2
= talloc_strdup(ctx
, pname2
);
5343 if (!root1
|| !root2
) {
5347 p
= strrchr_m(root1
,'.');
5350 ext1
= talloc_strdup(ctx
, p
+1);
5352 ext1
= talloc_strdup(ctx
, "");
5354 p
= strrchr_m(root2
,'.');
5357 ext2
= talloc_strdup(ctx
, p
+1);
5359 ext2
= talloc_strdup(ctx
, "");
5362 if (!ext1
|| !ext2
) {
5370 /* Hmmm. Should this be mb-aware ? */
5373 } else if (*p2
== '*') {
5375 root2
= talloc_asprintf(ctx
, "%s%s",
5394 /* Hmmm. Should this be mb-aware ? */
5397 } else if (*p2
== '*') {
5399 ext2
= talloc_asprintf(ctx
, "%s%s",
5415 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5420 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5432 /****************************************************************************
5433 Ensure open files have their names updated. Updated to notify other smbd's
5435 ****************************************************************************/
5437 static void rename_open_files(connection_struct
*conn
,
5438 struct share_mode_lock
*lck
,
5439 const char *newname
)
5442 bool did_rename
= False
;
5444 for(fsp
= file_find_di_first(lck
->id
); fsp
;
5445 fsp
= file_find_di_next(fsp
)) {
5446 /* fsp_name is a relative path under the fsp. To change this for other
5447 sharepaths we need to manipulate relative paths. */
5448 /* TODO - create the absolute path and manipulate the newname
5449 relative to the sharepath. */
5450 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5453 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5454 fsp
->fnum
, file_id_string_tos(&fsp
->file_id
),
5455 fsp
->fsp_name
, newname
));
5456 string_set(&fsp
->fsp_name
, newname
);
5461 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5462 file_id_string_tos(&lck
->id
), newname
));
5465 /* Send messages to all smbd's (not ourself) that the name has changed. */
5466 rename_share_filename(smbd_messaging_context(), lck
, conn
->connectpath
,
5470 /****************************************************************************
5471 We need to check if the source path is a parent directory of the destination
5472 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5473 refuse the rename with a sharing violation. Under UNIX the above call can
5474 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5475 probably need to check that the client is a Windows one before disallowing
5476 this as a UNIX client (one with UNIX extensions) can know the source is a
5477 symlink and make this decision intelligently. Found by an excellent bug
5478 report from <AndyLiebman@aol.com>.
5479 ****************************************************************************/
5481 static bool rename_path_prefix_equal(const char *src
, const char *dest
)
5483 const char *psrc
= src
;
5484 const char *pdst
= dest
;
5487 if (psrc
[0] == '.' && psrc
[1] == '/') {
5490 if (pdst
[0] == '.' && pdst
[1] == '/') {
5493 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5496 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5500 * Do the notify calls from a rename
5503 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5504 const char *oldpath
, const char *newpath
)
5506 char *olddir
, *newdir
;
5507 const char *oldname
, *newname
;
5510 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5511 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5513 if (!parent_dirname_talloc(NULL
, oldpath
, &olddir
, &oldname
)
5514 || !parent_dirname_talloc(NULL
, newpath
, &newdir
, &newname
)) {
5515 TALLOC_FREE(olddir
);
5519 if (strcmp(olddir
, newdir
) == 0) {
5520 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
, oldpath
);
5521 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
, newpath
);
5524 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
, oldpath
);
5525 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
, newpath
);
5527 TALLOC_FREE(olddir
);
5528 TALLOC_FREE(newdir
);
5530 /* this is a strange one. w2k3 gives an additional event for
5531 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5532 files, but not directories */
5534 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5535 FILE_NOTIFY_CHANGE_ATTRIBUTES
5536 |FILE_NOTIFY_CHANGE_CREATION
,
5541 /****************************************************************************
5542 Rename an open file - given an fsp.
5543 ****************************************************************************/
5545 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
5548 const char *newname_last_component
,
5550 bool replace_if_exists
)
5552 TALLOC_CTX
*ctx
= talloc_tos();
5553 SMB_STRUCT_STAT sbuf
, sbuf1
;
5554 NTSTATUS status
= NT_STATUS_OK
;
5555 struct share_mode_lock
*lck
= NULL
;
5556 bool dst_exists
, old_is_stream
, new_is_stream
;
5560 status
= check_name(conn
, newname
);
5561 if (!NT_STATUS_IS_OK(status
)) {
5565 /* Ensure newname contains a '/' */
5566 if(strrchr_m(newname
,'/') == 0) {
5567 newname
= talloc_asprintf(ctx
,
5571 return NT_STATUS_NO_MEMORY
;
5576 * Check for special case with case preserving and not
5577 * case sensitive. If the old last component differs from the original
5578 * last component only by case, then we should allow
5579 * the rename (user is trying to change the case of the
5583 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
5584 strequal(newname
, fsp
->fsp_name
)) {
5586 char *newname_modified_last_component
= NULL
;
5589 * Get the last component of the modified name.
5590 * Note that we guarantee that newname contains a '/'
5593 p
= strrchr_m(newname
,'/');
5594 newname_modified_last_component
= talloc_strdup(ctx
,
5596 if (!newname_modified_last_component
) {
5597 return NT_STATUS_NO_MEMORY
;
5600 if(strcsequal(newname_modified_last_component
,
5601 newname_last_component
) == False
) {
5603 * Replace the modified last component with
5606 *p
= '\0'; /* Truncate at the '/' */
5607 newname
= talloc_asprintf(ctx
,
5610 newname_last_component
);
5615 * If the src and dest names are identical - including case,
5616 * don't do the rename, just return success.
5619 if (strcsequal(fsp
->fsp_name
, newname
)) {
5620 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5622 return NT_STATUS_OK
;
5625 old_is_stream
= is_ntfs_stream_name(fsp
->fsp_name
);
5626 new_is_stream
= is_ntfs_stream_name(newname
);
5628 /* Return the correct error code if both names aren't streams. */
5629 if (!old_is_stream
&& new_is_stream
) {
5630 return NT_STATUS_OBJECT_NAME_INVALID
;
5633 if (old_is_stream
&& !new_is_stream
) {
5634 return NT_STATUS_INVALID_PARAMETER
;
5638 * Have vfs_object_exist also fill sbuf1
5640 dst_exists
= vfs_object_exist(conn
, newname
, &sbuf1
);
5642 if(!replace_if_exists
&& dst_exists
) {
5643 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5644 fsp
->fsp_name
,newname
));
5645 return NT_STATUS_OBJECT_NAME_COLLISION
;
5649 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, &sbuf1
);
5650 files_struct
*dst_fsp
= file_find_di_first(fileid
);
5651 /* The file can be open when renaming a stream */
5652 if (dst_fsp
&& !new_is_stream
) {
5653 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5654 return NT_STATUS_ACCESS_DENIED
;
5658 /* Ensure we have a valid stat struct for the source. */
5659 if (fsp
->fh
->fd
!= -1) {
5660 if (SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
5661 return map_nt_error_from_unix(errno
);
5665 if (fsp
->posix_open
) {
5666 ret
= SMB_VFS_LSTAT(conn
,fsp
->fsp_name
,&sbuf
);
5668 ret
= SMB_VFS_STAT(conn
,fsp
->fsp_name
,&sbuf
);
5671 return map_nt_error_from_unix(errno
);
5675 status
= can_rename(conn
, fsp
, attrs
, &sbuf
);
5677 if (!NT_STATUS_IS_OK(status
)) {
5678 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5679 nt_errstr(status
), fsp
->fsp_name
,newname
));
5680 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
5681 status
= NT_STATUS_ACCESS_DENIED
;
5685 if (rename_path_prefix_equal(fsp
->fsp_name
, newname
)) {
5686 return NT_STATUS_ACCESS_DENIED
;
5689 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
5693 * We have the file open ourselves, so not being able to get the
5694 * corresponding share mode lock is a fatal error.
5697 SMB_ASSERT(lck
!= NULL
);
5699 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
5700 uint32 create_options
= fsp
->fh
->private_options
;
5702 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5703 fsp
->fsp_name
,newname
));
5705 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
, newname
);
5707 rename_open_files(conn
, lck
, newname
);
5710 * A rename acts as a new file create w.r.t. allowing an initial delete
5711 * on close, probably because in Windows there is a new handle to the
5712 * new file. If initial delete on close was requested but not
5713 * originally set, we need to set it here. This is probably not 100% correct,
5714 * but will work for the CIFSFS client which in non-posix mode
5715 * depends on these semantics. JRA.
5718 if (create_options
& FILE_DELETE_ON_CLOSE
) {
5719 status
= can_set_delete_on_close(fsp
, True
, 0);
5721 if (NT_STATUS_IS_OK(status
)) {
5722 /* Note that here we set the *inital* delete on close flag,
5723 * not the regular one. The magic gets handled in close. */
5724 fsp
->initial_delete_on_close
= True
;
5728 return NT_STATUS_OK
;
5733 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
5734 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
5736 status
= map_nt_error_from_unix(errno
);
5739 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5740 nt_errstr(status
), fsp
->fsp_name
,newname
));
5745 /****************************************************************************
5746 The guts of the rename command, split out so it may be called by the NT SMB
5748 ****************************************************************************/
5750 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
5751 connection_struct
*conn
,
5752 struct smb_request
*req
,
5753 const char *name_in
,
5754 const char *newname_in
,
5756 bool replace_if_exists
,
5759 uint32_t access_mask
)
5761 char *directory
= NULL
;
5763 char *last_component_src
= NULL
;
5764 char *last_component_dest
= NULL
;
5766 char *newname
= NULL
;
5769 NTSTATUS status
= NT_STATUS_OK
;
5770 SMB_STRUCT_STAT sbuf1
, sbuf2
;
5771 struct smb_Dir
*dir_hnd
= NULL
;
5774 bool posix_pathnames
= lp_posix_pathnames();
5779 status
= unix_convert(ctx
, conn
, name_in
, src_has_wild
, &name
,
5780 &last_component_src
, &sbuf1
);
5781 if (!NT_STATUS_IS_OK(status
)) {
5785 status
= unix_convert(ctx
, conn
, newname_in
, dest_has_wild
, &newname
,
5786 &last_component_dest
, &sbuf2
);
5787 if (!NT_STATUS_IS_OK(status
)) {
5792 * Split the old name into directory and last component
5793 * strings. Note that unix_convert may have stripped off a
5794 * leading ./ from both name and newname if the rename is
5795 * at the root of the share. We need to make sure either both
5796 * name and newname contain a / character or neither of them do
5797 * as this is checked in resolve_wildcards().
5800 p
= strrchr_m(name
,'/');
5802 directory
= talloc_strdup(ctx
, ".");
5804 return NT_STATUS_NO_MEMORY
;
5809 directory
= talloc_strdup(ctx
, name
);
5811 return NT_STATUS_NO_MEMORY
;
5814 *p
= '/'; /* Replace needed for exceptional test below. */
5818 * We should only check the mangled cache
5819 * here if unix_convert failed. This means
5820 * that the path in 'mask' doesn't exist
5821 * on the file system and so we need to look
5822 * for a possible mangle. This patch from
5823 * Tine Smukavec <valentin.smukavec@hermes.si>.
5826 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
)) {
5827 char *new_mask
= NULL
;
5828 mangle_lookup_name_from_8_3(ctx
,
5837 if (!src_has_wild
) {
5841 * No wildcards - just process the one file.
5843 bool is_short_name
= mangle_is_8_3(name
, True
, conn
->params
);
5845 /* Add a terminating '/' to the directory name. */
5846 directory
= talloc_asprintf_append(directory
,
5850 return NT_STATUS_NO_MEMORY
;
5853 /* Ensure newname contains a '/' also */
5854 if(strrchr_m(newname
,'/') == 0) {
5855 newname
= talloc_asprintf(ctx
,
5859 return NT_STATUS_NO_MEMORY
;
5863 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5864 "case_preserve = %d, short case preserve = %d, "
5865 "directory = %s, newname = %s, "
5866 "last_component_dest = %s, is_8_3 = %d\n",
5867 conn
->case_sensitive
, conn
->case_preserve
,
5868 conn
->short_case_preserve
, directory
,
5869 newname
, last_component_dest
, is_short_name
));
5871 /* The dest name still may have wildcards. */
5872 if (dest_has_wild
) {
5873 char *mod_newname
= NULL
;
5874 if (!resolve_wildcards(ctx
,
5875 directory
,newname
,&mod_newname
)) {
5876 DEBUG(6, ("rename_internals: resolve_wildcards "
5880 return NT_STATUS_NO_MEMORY
;
5882 newname
= mod_newname
;
5886 if (posix_pathnames
) {
5887 SMB_VFS_LSTAT(conn
, directory
, &sbuf1
);
5889 SMB_VFS_STAT(conn
, directory
, &sbuf1
);
5892 status
= S_ISDIR(sbuf1
.st_mode
) ?
5893 open_directory(conn
, req
, directory
, &sbuf1
,
5895 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5898 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0,
5901 : open_file_ntcreate(conn
, req
, directory
, &sbuf1
,
5903 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5906 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0,
5911 if (!NT_STATUS_IS_OK(status
)) {
5912 DEBUG(3, ("Could not open rename source %s: %s\n",
5913 directory
, nt_errstr(status
)));
5917 status
= rename_internals_fsp(conn
, fsp
, newname
,
5918 last_component_dest
,
5919 attrs
, replace_if_exists
);
5921 close_file(fsp
, NORMAL_CLOSE
);
5923 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5924 nt_errstr(status
), directory
,newname
));
5930 * Wildcards - process each file that matches.
5932 if (strequal(mask
,"????????.???")) {
5937 status
= check_name(conn
, directory
);
5938 if (!NT_STATUS_IS_OK(status
)) {
5942 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
, attrs
);
5943 if (dir_hnd
== NULL
) {
5944 return map_nt_error_from_unix(errno
);
5947 status
= NT_STATUS_NO_SUCH_FILE
;
5949 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5950 * - gentest fix. JRA
5953 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
5954 files_struct
*fsp
= NULL
;
5956 char *destname
= NULL
;
5957 bool sysdir_entry
= False
;
5959 /* Quick check for "." and ".." */
5960 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5962 sysdir_entry
= True
;
5968 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
)) {
5972 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
5977 status
= NT_STATUS_OBJECT_NAME_INVALID
;
5981 fname
= talloc_asprintf(ctx
,
5986 return NT_STATUS_NO_MEMORY
;
5989 if (!resolve_wildcards(ctx
,
5990 fname
,newname
,&destname
)) {
5991 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5997 return NT_STATUS_NO_MEMORY
;
6001 if (posix_pathnames
) {
6002 SMB_VFS_LSTAT(conn
, fname
, &sbuf1
);
6004 SMB_VFS_STAT(conn
, fname
, &sbuf1
);
6007 status
= S_ISDIR(sbuf1
.st_mode
) ?
6008 open_directory(conn
, req
, fname
, &sbuf1
,
6010 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6013 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0,
6016 : open_file_ntcreate(conn
, req
, fname
, &sbuf1
,
6018 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6021 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0,
6026 if (!NT_STATUS_IS_OK(status
)) {
6027 DEBUG(3,("rename_internals: open_file_ntcreate "
6028 "returned %s rename %s -> %s\n",
6029 nt_errstr(status
), directory
, newname
));
6033 status
= rename_internals_fsp(conn
, fsp
, destname
, dname
,
6034 attrs
, replace_if_exists
);
6036 close_file(fsp
, NORMAL_CLOSE
);
6038 if (!NT_STATUS_IS_OK(status
)) {
6039 DEBUG(3, ("rename_internals_fsp returned %s for "
6040 "rename %s -> %s\n", nt_errstr(status
),
6041 directory
, newname
));
6047 DEBUG(3,("rename_internals: doing rename on %s -> "
6048 "%s\n",fname
,destname
));
6051 TALLOC_FREE(destname
);
6053 TALLOC_FREE(dir_hnd
);
6055 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6056 status
= map_nt_error_from_unix(errno
);
6062 /****************************************************************************
6064 ****************************************************************************/
6066 void reply_mv(struct smb_request
*req
)
6068 connection_struct
*conn
= req
->conn
;
6070 char *newname
= NULL
;
6074 bool src_has_wcard
= False
;
6075 bool dest_has_wcard
= False
;
6076 TALLOC_CTX
*ctx
= talloc_tos();
6078 START_PROFILE(SMBmv
);
6081 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6086 attrs
= SVAL(req
->inbuf
,smb_vwv0
);
6088 p
= smb_buf(req
->inbuf
) + 1;
6089 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &name
, p
,
6090 0, STR_TERMINATE
, &status
,
6092 if (!NT_STATUS_IS_OK(status
)) {
6093 reply_nterror(req
, status
);
6098 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &newname
, p
,
6099 0, STR_TERMINATE
, &status
,
6101 if (!NT_STATUS_IS_OK(status
)) {
6102 reply_nterror(req
, status
);
6107 status
= resolve_dfspath_wcard(ctx
, conn
,
6108 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6112 if (!NT_STATUS_IS_OK(status
)) {
6113 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6114 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6115 ERRSRV
, ERRbadpath
);
6119 reply_nterror(req
, status
);
6124 status
= resolve_dfspath_wcard(ctx
, conn
,
6125 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6129 if (!NT_STATUS_IS_OK(status
)) {
6130 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6131 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6132 ERRSRV
, ERRbadpath
);
6136 reply_nterror(req
, status
);
6141 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
6143 status
= rename_internals(ctx
, conn
, req
, name
, newname
, attrs
, False
,
6144 src_has_wcard
, dest_has_wcard
, DELETE_ACCESS
);
6145 if (!NT_STATUS_IS_OK(status
)) {
6146 if (open_was_deferred(req
->mid
)) {
6147 /* We have re-scheduled this call. */
6151 reply_nterror(req
, status
);
6156 reply_outbuf(req
, 0, 0);
6162 /*******************************************************************
6163 Copy a file as part of a reply_copy.
6164 ******************************************************************/
6167 * TODO: check error codes on all callers
6170 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6171 connection_struct
*conn
,
6176 bool target_is_directory
)
6178 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
6180 files_struct
*fsp1
,*fsp2
;
6183 uint32 new_create_disposition
;
6186 dest
= talloc_strdup(ctx
, dest1
);
6188 return NT_STATUS_NO_MEMORY
;
6190 if (target_is_directory
) {
6191 const char *p
= strrchr_m(src
,'/');
6197 dest
= talloc_asprintf_append(dest
,
6201 return NT_STATUS_NO_MEMORY
;
6205 if (!vfs_file_exist(conn
,src
,&src_sbuf
)) {
6207 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6210 if (!target_is_directory
&& count
) {
6211 new_create_disposition
= FILE_OPEN
;
6213 if (!map_open_params_to_ntcreate(dest1
,0,ofun
,
6214 NULL
, NULL
, &new_create_disposition
, NULL
)) {
6216 return NT_STATUS_INVALID_PARAMETER
;
6220 status
= open_file_ntcreate(conn
, NULL
, src
, &src_sbuf
,
6222 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6225 FILE_ATTRIBUTE_NORMAL
,
6229 if (!NT_STATUS_IS_OK(status
)) {
6234 dosattrs
= dos_mode(conn
, src
, &src_sbuf
);
6235 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1) {
6236 ZERO_STRUCTP(&sbuf2
);
6239 status
= open_file_ntcreate(conn
, NULL
, dest
, &sbuf2
,
6241 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6242 new_create_disposition
,
6250 if (!NT_STATUS_IS_OK(status
)) {
6251 close_file(fsp1
,ERROR_CLOSE
);
6255 if ((ofun
&3) == 1) {
6256 if(SMB_VFS_LSEEK(fsp2
,0,SEEK_END
) == -1) {
6257 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
6259 * Stop the copy from occurring.
6262 src_sbuf
.st_size
= 0;
6266 if (src_sbuf
.st_size
) {
6267 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
6270 close_file(fsp1
,NORMAL_CLOSE
);
6272 /* Ensure the modtime is set correctly on the destination file. */
6273 set_close_write_time(fsp2
, get_mtimespec(&src_sbuf
));
6276 * As we are opening fsp1 read-only we only expect
6277 * an error on close on fsp2 if we are out of space.
6278 * Thus we don't look at the error return from the
6281 status
= close_file(fsp2
,NORMAL_CLOSE
);
6283 if (!NT_STATUS_IS_OK(status
)) {
6287 if (ret
!= (SMB_OFF_T
)src_sbuf
.st_size
) {
6288 return NT_STATUS_DISK_FULL
;
6291 return NT_STATUS_OK
;
6294 /****************************************************************************
6295 Reply to a file copy.
6296 ****************************************************************************/
6298 void reply_copy(struct smb_request
*req
)
6300 connection_struct
*conn
= req
->conn
;
6302 char *newname
= NULL
;
6303 char *directory
= NULL
;
6307 int error
= ERRnoaccess
;
6312 bool target_is_directory
=False
;
6313 bool source_has_wild
= False
;
6314 bool dest_has_wild
= False
;
6315 SMB_STRUCT_STAT sbuf1
, sbuf2
;
6317 TALLOC_CTX
*ctx
= talloc_tos();
6319 START_PROFILE(SMBcopy
);
6322 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6323 END_PROFILE(SMBcopy
);
6327 tid2
= SVAL(req
->inbuf
,smb_vwv0
);
6328 ofun
= SVAL(req
->inbuf
,smb_vwv1
);
6329 flags
= SVAL(req
->inbuf
,smb_vwv2
);
6331 p
= smb_buf(req
->inbuf
);
6332 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &name
, p
,
6333 0, STR_TERMINATE
, &status
,
6335 if (!NT_STATUS_IS_OK(status
)) {
6336 reply_nterror(req
, status
);
6337 END_PROFILE(SMBcopy
);
6340 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &newname
, p
,
6341 0, STR_TERMINATE
, &status
,
6343 if (!NT_STATUS_IS_OK(status
)) {
6344 reply_nterror(req
, status
);
6345 END_PROFILE(SMBcopy
);
6349 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
6351 if (tid2
!= conn
->cnum
) {
6352 /* can't currently handle inter share copies XXXX */
6353 DEBUG(3,("Rejecting inter-share copy\n"));
6354 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
6355 END_PROFILE(SMBcopy
);
6359 status
= resolve_dfspath_wcard(ctx
, conn
,
6360 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6364 if (!NT_STATUS_IS_OK(status
)) {
6365 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6366 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6367 ERRSRV
, ERRbadpath
);
6368 END_PROFILE(SMBcopy
);
6371 reply_nterror(req
, status
);
6372 END_PROFILE(SMBcopy
);
6376 status
= resolve_dfspath_wcard(ctx
, conn
,
6377 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6381 if (!NT_STATUS_IS_OK(status
)) {
6382 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6383 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6384 ERRSRV
, ERRbadpath
);
6385 END_PROFILE(SMBcopy
);
6388 reply_nterror(req
, status
);
6389 END_PROFILE(SMBcopy
);
6393 status
= unix_convert(ctx
, conn
, name
, source_has_wild
,
6394 &name
, NULL
, &sbuf1
);
6395 if (!NT_STATUS_IS_OK(status
)) {
6396 reply_nterror(req
, status
);
6397 END_PROFILE(SMBcopy
);
6401 status
= unix_convert(ctx
, conn
, newname
, dest_has_wild
,
6402 &newname
, NULL
, &sbuf2
);
6403 if (!NT_STATUS_IS_OK(status
)) {
6404 reply_nterror(req
, status
);
6405 END_PROFILE(SMBcopy
);
6409 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
6411 if ((flags
&1) && target_is_directory
) {
6412 reply_doserror(req
, ERRDOS
, ERRbadfile
);
6413 END_PROFILE(SMBcopy
);
6417 if ((flags
&2) && !target_is_directory
) {
6418 reply_doserror(req
, ERRDOS
, ERRbadpath
);
6419 END_PROFILE(SMBcopy
);
6423 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
6424 /* wants a tree copy! XXXX */
6425 DEBUG(3,("Rejecting tree copy\n"));
6426 reply_doserror(req
, ERRSRV
, ERRerror
);
6427 END_PROFILE(SMBcopy
);
6431 p
= strrchr_m(name
,'/');
6433 directory
= talloc_strdup(ctx
, "./");
6435 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6436 END_PROFILE(SMBcopy
);
6442 directory
= talloc_strdup(ctx
, name
);
6444 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6445 END_PROFILE(SMBcopy
);
6452 * We should only check the mangled cache
6453 * here if unix_convert failed. This means
6454 * that the path in 'mask' doesn't exist
6455 * on the file system and so we need to look
6456 * for a possible mangle. This patch from
6457 * Tine Smukavec <valentin.smukavec@hermes.si>.
6460 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
)) {
6461 char *new_mask
= NULL
;
6462 mangle_lookup_name_from_8_3(ctx
,
6471 if (!source_has_wild
) {
6472 directory
= talloc_asprintf_append(directory
,
6475 if (dest_has_wild
) {
6476 char *mod_newname
= NULL
;
6477 if (!resolve_wildcards(ctx
,
6478 directory
,newname
,&mod_newname
)) {
6479 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6480 END_PROFILE(SMBcopy
);
6483 newname
= mod_newname
;
6486 status
= check_name(conn
, directory
);
6487 if (!NT_STATUS_IS_OK(status
)) {
6488 reply_nterror(req
, status
);
6489 END_PROFILE(SMBcopy
);
6493 status
= check_name(conn
, newname
);
6494 if (!NT_STATUS_IS_OK(status
)) {
6495 reply_nterror(req
, status
);
6496 END_PROFILE(SMBcopy
);
6500 status
= copy_file(ctx
,conn
,directory
,newname
,ofun
,
6501 count
,target_is_directory
);
6503 if(!NT_STATUS_IS_OK(status
)) {
6504 reply_nterror(req
, status
);
6505 END_PROFILE(SMBcopy
);
6511 struct smb_Dir
*dir_hnd
= NULL
;
6512 const char *dname
= NULL
;
6515 if (strequal(mask
,"????????.???")) {
6520 status
= check_name(conn
, directory
);
6521 if (!NT_STATUS_IS_OK(status
)) {
6522 reply_nterror(req
, status
);
6523 END_PROFILE(SMBcopy
);
6527 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
, 0);
6528 if (dir_hnd
== NULL
) {
6529 status
= map_nt_error_from_unix(errno
);
6530 reply_nterror(req
, status
);
6531 END_PROFILE(SMBcopy
);
6537 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
6538 char *destname
= NULL
;
6541 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6545 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
)) {
6549 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
6553 error
= ERRnoaccess
;
6554 fname
= talloc_asprintf(ctx
,
6559 TALLOC_FREE(dir_hnd
);
6560 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6561 END_PROFILE(SMBcopy
);
6565 if (!resolve_wildcards(ctx
,
6566 fname
,newname
,&destname
)) {
6570 TALLOC_FREE(dir_hnd
);
6571 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6572 END_PROFILE(SMBcopy
);
6576 status
= check_name(conn
, fname
);
6577 if (!NT_STATUS_IS_OK(status
)) {
6578 TALLOC_FREE(dir_hnd
);
6579 reply_nterror(req
, status
);
6580 END_PROFILE(SMBcopy
);
6584 status
= check_name(conn
, destname
);
6585 if (!NT_STATUS_IS_OK(status
)) {
6586 TALLOC_FREE(dir_hnd
);
6587 reply_nterror(req
, status
);
6588 END_PROFILE(SMBcopy
);
6592 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
, destname
));
6594 status
= copy_file(ctx
,conn
,fname
,destname
,ofun
,
6595 count
,target_is_directory
);
6596 if (NT_STATUS_IS_OK(status
)) {
6600 TALLOC_FREE(destname
);
6602 TALLOC_FREE(dir_hnd
);
6607 /* Error on close... */
6609 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
6610 END_PROFILE(SMBcopy
);
6614 reply_doserror(req
, ERRDOS
, error
);
6615 END_PROFILE(SMBcopy
);
6619 reply_outbuf(req
, 1, 0);
6620 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6622 END_PROFILE(SMBcopy
);
6627 #define DBGC_CLASS DBGC_LOCKING
6629 /****************************************************************************
6630 Get a lock pid, dealing with large count requests.
6631 ****************************************************************************/
6633 uint32
get_lock_pid( char *data
, int data_offset
, bool large_file_format
)
6635 if(!large_file_format
)
6636 return (uint32
)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
6638 return (uint32
)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
6641 /****************************************************************************
6642 Get a lock count, dealing with large count requests.
6643 ****************************************************************************/
6645 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, bool large_file_format
)
6647 SMB_BIG_UINT count
= 0;
6649 if(!large_file_format
) {
6650 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
6653 #if defined(HAVE_LONGLONG)
6654 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
6655 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
6656 #else /* HAVE_LONGLONG */
6659 * NT4.x seems to be broken in that it sends large file (64 bit)
6660 * lockingX calls even if the CAP_LARGE_FILES was *not*
6661 * negotiated. For boxes without large unsigned ints truncate the
6662 * lock count by dropping the top 32 bits.
6665 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
6666 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6667 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
6668 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
6669 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
6672 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
6673 #endif /* HAVE_LONGLONG */
6679 #if !defined(HAVE_LONGLONG)
6680 /****************************************************************************
6681 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6682 ****************************************************************************/
6684 static uint32
map_lock_offset(uint32 high
, uint32 low
)
6688 uint32 highcopy
= high
;
6691 * Try and find out how many significant bits there are in high.
6694 for(i
= 0; highcopy
; i
++)
6698 * We use 31 bits not 32 here as POSIX
6699 * lock offsets may not be negative.
6702 mask
= (~0) << (31 - i
);
6705 return 0; /* Fail. */
6711 #endif /* !defined(HAVE_LONGLONG) */
6713 /****************************************************************************
6714 Get a lock offset, dealing with large offset requests.
6715 ****************************************************************************/
6717 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, bool large_file_format
, bool *err
)
6719 SMB_BIG_UINT offset
= 0;
6723 if(!large_file_format
) {
6724 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
6727 #if defined(HAVE_LONGLONG)
6728 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
6729 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
6730 #else /* HAVE_LONGLONG */
6733 * NT4.x seems to be broken in that it sends large file (64 bit)
6734 * lockingX calls even if the CAP_LARGE_FILES was *not*
6735 * negotiated. For boxes without large unsigned ints mangle the
6736 * lock offset by mapping the top 32 bits onto the lower 32.
6739 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
6740 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
6741 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
6744 if((new_low
= map_lock_offset(high
, low
)) == 0) {
6746 return (SMB_BIG_UINT
)-1;
6749 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6750 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
6751 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
6752 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
6755 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
6756 #endif /* HAVE_LONGLONG */
6762 /****************************************************************************
6763 Reply to a lockingX request.
6764 ****************************************************************************/
6766 void reply_lockingX(struct smb_request
*req
)
6768 connection_struct
*conn
= req
->conn
;
6770 unsigned char locktype
;
6771 unsigned char oplocklevel
;
6774 SMB_BIG_UINT count
= 0, offset
= 0;
6779 bool large_file_format
;
6781 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
6783 START_PROFILE(SMBlockingX
);
6786 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6787 END_PROFILE(SMBlockingX
);
6791 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv2
));
6792 locktype
= CVAL(req
->inbuf
,smb_vwv3
);
6793 oplocklevel
= CVAL(req
->inbuf
,smb_vwv3
+1);
6794 num_ulocks
= SVAL(req
->inbuf
,smb_vwv6
);
6795 num_locks
= SVAL(req
->inbuf
,smb_vwv7
);
6796 lock_timeout
= IVAL(req
->inbuf
,smb_vwv4
);
6797 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
6799 if (!check_fsp(conn
, req
, fsp
)) {
6800 END_PROFILE(SMBlockingX
);
6804 data
= smb_buf(req
->inbuf
);
6806 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
6807 /* we don't support these - and CANCEL_LOCK makes w2k
6808 and XP reboot so I don't really want to be
6809 compatible! (tridge) */
6810 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
6811 END_PROFILE(SMBlockingX
);
6815 /* Check if this is an oplock break on a file
6816 we have granted an oplock on.
6818 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
6819 /* Client can insist on breaking to none. */
6820 bool break_to_none
= (oplocklevel
== 0);
6823 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6824 "for fnum = %d\n", (unsigned int)oplocklevel
,
6828 * Make sure we have granted an exclusive or batch oplock on
6832 if (fsp
->oplock_type
== 0) {
6834 /* The Samba4 nbench simulator doesn't understand
6835 the difference between break to level2 and break
6836 to none from level2 - it sends oplock break
6837 replies in both cases. Don't keep logging an error
6838 message here - just ignore it. JRA. */
6840 DEBUG(5,("reply_lockingX: Error : oplock break from "
6841 "client for fnum = %d (oplock=%d) and no "
6842 "oplock granted on this file (%s).\n",
6843 fsp
->fnum
, fsp
->oplock_type
, fsp
->fsp_name
));
6845 /* if this is a pure oplock break request then don't
6847 if (num_locks
== 0 && num_ulocks
== 0) {
6848 END_PROFILE(SMBlockingX
);
6851 END_PROFILE(SMBlockingX
);
6852 reply_doserror(req
, ERRDOS
, ERRlock
);
6857 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
6859 result
= remove_oplock(fsp
);
6861 result
= downgrade_oplock(fsp
);
6865 DEBUG(0, ("reply_lockingX: error in removing "
6866 "oplock on file %s\n", fsp
->fsp_name
));
6867 /* Hmmm. Is this panic justified? */
6868 smb_panic("internal tdb error");
6871 reply_to_oplock_break_requests(fsp
);
6873 /* if this is a pure oplock break request then don't send a
6875 if (num_locks
== 0 && num_ulocks
== 0) {
6876 /* Sanity check - ensure a pure oplock break is not a
6878 if(CVAL(req
->inbuf
,smb_vwv0
) != 0xff)
6879 DEBUG(0,("reply_lockingX: Error : pure oplock "
6880 "break is a chained %d request !\n",
6881 (unsigned int)CVAL(req
->inbuf
,
6883 END_PROFILE(SMBlockingX
);
6889 * We do this check *after* we have checked this is not a oplock break
6890 * response message. JRA.
6893 release_level_2_oplocks_on_change(fsp
);
6895 if (smb_buflen(req
->inbuf
) <
6896 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
6897 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6898 END_PROFILE(SMBlockingX
);
6902 /* Data now points at the beginning of the list
6903 of smb_unlkrng structs */
6904 for(i
= 0; i
< (int)num_ulocks
; i
++) {
6905 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
6906 count
= get_lock_count( data
, i
, large_file_format
);
6907 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
6910 * There is no error code marked "stupid client bug".... :-).
6913 END_PROFILE(SMBlockingX
);
6914 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
6918 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6919 "pid %u, file %s\n", (double)offset
, (double)count
,
6920 (unsigned int)lock_pid
, fsp
->fsp_name
));
6922 status
= do_unlock(smbd_messaging_context(),
6929 if (NT_STATUS_V(status
)) {
6930 END_PROFILE(SMBlockingX
);
6931 reply_nterror(req
, status
);
6936 /* Setup the timeout in seconds. */
6938 if (!lp_blocking_locks(SNUM(conn
))) {
6942 /* Now do any requested locks */
6943 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
6945 /* Data now points at the beginning of the list
6946 of smb_lkrng structs */
6948 for(i
= 0; i
< (int)num_locks
; i
++) {
6949 enum brl_type lock_type
= ((locktype
& LOCKING_ANDX_SHARED_LOCK
) ?
6950 READ_LOCK
:WRITE_LOCK
);
6951 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
6952 count
= get_lock_count( data
, i
, large_file_format
);
6953 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
6956 * There is no error code marked "stupid client bug".... :-).
6959 END_PROFILE(SMBlockingX
);
6960 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
6964 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6965 "%u, file %s timeout = %d\n", (double)offset
,
6966 (double)count
, (unsigned int)lock_pid
,
6967 fsp
->fsp_name
, (int)lock_timeout
));
6969 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
6970 if (lp_blocking_locks(SNUM(conn
))) {
6972 /* Schedule a message to ourselves to
6973 remove the blocking lock record and
6974 return the right error. */
6976 if (!blocking_lock_cancel(fsp
,
6982 NT_STATUS_FILE_LOCK_CONFLICT
)) {
6983 END_PROFILE(SMBlockingX
);
6988 ERRcancelviolation
));
6992 /* Remove a matching pending lock. */
6993 status
= do_lock_cancel(fsp
,
6999 bool blocking_lock
= lock_timeout
? True
: False
;
7000 bool defer_lock
= False
;
7001 struct byte_range_lock
*br_lck
;
7002 uint32 block_smbpid
;
7004 br_lck
= do_lock(smbd_messaging_context(),
7015 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7016 /* Windows internal resolution for blocking locks seems
7017 to be about 200ms... Don't wait for less than that. JRA. */
7018 if (lock_timeout
!= -1 && lock_timeout
< lp_lock_spin_time()) {
7019 lock_timeout
= lp_lock_spin_time();
7024 /* This heuristic seems to match W2K3 very well. If a
7025 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7026 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7027 far as I can tell. Replacement for do_lock_spin(). JRA. */
7029 if (br_lck
&& lp_blocking_locks(SNUM(conn
)) && !blocking_lock
&&
7030 NT_STATUS_EQUAL((status
), NT_STATUS_FILE_LOCK_CONFLICT
)) {
7032 lock_timeout
= lp_lock_spin_time();
7035 if (br_lck
&& defer_lock
) {
7037 * A blocking lock was requested. Package up
7038 * this smb into a queued request and push it
7039 * onto the blocking lock queue.
7041 if(push_blocking_lock_request(br_lck
,
7052 TALLOC_FREE(br_lck
);
7053 END_PROFILE(SMBlockingX
);
7058 TALLOC_FREE(br_lck
);
7061 if (NT_STATUS_V(status
)) {
7062 END_PROFILE(SMBlockingX
);
7063 reply_nterror(req
, status
);
7068 /* If any of the above locks failed, then we must unlock
7069 all of the previous locks (X/Open spec). */
7071 if (!(locktype
& LOCKING_ANDX_CANCEL_LOCK
) &&
7075 * Ensure we don't do a remove on the lock that just failed,
7076 * as under POSIX rules, if we have a lock already there, we
7077 * will delete it (and we shouldn't) .....
7079 for(i
--; i
>= 0; i
--) {
7080 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
7081 count
= get_lock_count( data
, i
, large_file_format
);
7082 offset
= get_lock_offset( data
, i
, large_file_format
,
7086 * There is no error code marked "stupid client
7090 END_PROFILE(SMBlockingX
);
7091 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7095 do_unlock(smbd_messaging_context(),
7102 END_PROFILE(SMBlockingX
);
7103 reply_nterror(req
, status
);
7107 reply_outbuf(req
, 2, 0);
7109 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7110 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7112 END_PROFILE(SMBlockingX
);
7117 #define DBGC_CLASS DBGC_ALL
7119 /****************************************************************************
7120 Reply to a SMBreadbmpx (read block multiplex) request.
7121 Always reply with an error, if someone has a platform really needs this,
7122 please contact vl@samba.org
7123 ****************************************************************************/
7125 void reply_readbmpx(struct smb_request
*req
)
7127 START_PROFILE(SMBreadBmpx
);
7128 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7129 END_PROFILE(SMBreadBmpx
);
7133 /****************************************************************************
7134 Reply to a SMBreadbs (read block multiplex secondary) request.
7135 Always reply with an error, if someone has a platform really needs this,
7136 please contact vl@samba.org
7137 ****************************************************************************/
7139 void reply_readbs(struct smb_request
*req
)
7141 START_PROFILE(SMBreadBs
);
7142 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7143 END_PROFILE(SMBreadBs
);
7147 /****************************************************************************
7148 Reply to a SMBsetattrE.
7149 ****************************************************************************/
7151 void reply_setattrE(struct smb_request
*req
)
7153 connection_struct
*conn
= req
->conn
;
7154 struct timespec ts
[2];
7156 SMB_STRUCT_STAT sbuf
;
7159 START_PROFILE(SMBsetattrE
);
7162 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7163 END_PROFILE(SMBsetattrE
);
7167 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
7169 if(!fsp
|| (fsp
->conn
!= conn
)) {
7170 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7171 END_PROFILE(SMBsetattrE
);
7177 * Convert the DOS times into unix times. Ignore create
7178 * time as UNIX can't set this.
7181 ts
[0] = convert_time_t_to_timespec(
7182 srv_make_unix_date2(req
->inbuf
+smb_vwv3
)); /* atime. */
7183 ts
[1] = convert_time_t_to_timespec(
7184 srv_make_unix_date2(req
->inbuf
+smb_vwv5
)); /* mtime. */
7186 reply_outbuf(req
, 0, 0);
7189 * Patch from Ray Frush <frush@engr.colostate.edu>
7190 * Sometimes times are sent as zero - ignore them.
7193 /* Ensure we have a valid stat struct for the source. */
7194 if (fsp
->fh
->fd
!= -1) {
7195 if (SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
7196 status
= map_nt_error_from_unix(errno
);
7197 reply_nterror(req
, status
);
7198 END_PROFILE(SMBsetattrE
);
7204 if (fsp
->posix_open
) {
7205 ret
= SMB_VFS_LSTAT(conn
, fsp
->fsp_name
, &sbuf
);
7207 ret
= SMB_VFS_STAT(conn
, fsp
->fsp_name
, &sbuf
);
7210 status
= map_nt_error_from_unix(errno
);
7211 reply_nterror(req
, status
);
7212 END_PROFILE(SMBsetattrE
);
7217 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
,
7219 if (!NT_STATUS_IS_OK(status
)) {
7220 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7221 END_PROFILE(SMBsetattrE
);
7225 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7227 (unsigned int)ts
[0].tv_sec
,
7228 (unsigned int)ts
[1].tv_sec
));
7230 END_PROFILE(SMBsetattrE
);
7235 /* Back from the dead for OS/2..... JRA. */
7237 /****************************************************************************
7238 Reply to a SMBwritebmpx (write block multiplex primary) request.
7239 Always reply with an error, if someone has a platform really needs this,
7240 please contact vl@samba.org
7241 ****************************************************************************/
7243 void reply_writebmpx(struct smb_request
*req
)
7245 START_PROFILE(SMBwriteBmpx
);
7246 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7247 END_PROFILE(SMBwriteBmpx
);
7251 /****************************************************************************
7252 Reply to a SMBwritebs (write block multiplex secondary) request.
7253 Always reply with an error, if someone has a platform really needs this,
7254 please contact vl@samba.org
7255 ****************************************************************************/
7257 void reply_writebs(struct smb_request
*req
)
7259 START_PROFILE(SMBwriteBs
);
7260 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7261 END_PROFILE(SMBwriteBs
);
7265 /****************************************************************************
7266 Reply to a SMBgetattrE.
7267 ****************************************************************************/
7269 void reply_getattrE(struct smb_request
*req
)
7271 connection_struct
*conn
= req
->conn
;
7272 SMB_STRUCT_STAT sbuf
;
7275 struct timespec create_ts
;
7277 START_PROFILE(SMBgetattrE
);
7280 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7281 END_PROFILE(SMBgetattrE
);
7285 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
7287 if(!fsp
|| (fsp
->conn
!= conn
)) {
7288 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7289 END_PROFILE(SMBgetattrE
);
7293 /* Do an fstat on this file */
7294 if(fsp_stat(fsp
, &sbuf
)) {
7295 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
7296 END_PROFILE(SMBgetattrE
);
7300 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
7303 * Convert the times into dos times. Set create
7304 * date to be last modify date as UNIX doesn't save
7308 reply_outbuf(req
, 11, 0);
7310 create_ts
= get_create_timespec(&sbuf
,
7311 lp_fake_dir_create_times(SNUM(conn
)));
7312 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
7313 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
, sbuf
.st_atime
);
7314 /* Should we check pending modtime here ? JRA */
7315 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
, sbuf
.st_mtime
);
7318 SIVAL(req
->outbuf
, smb_vwv6
, 0);
7319 SIVAL(req
->outbuf
, smb_vwv8
, 0);
7321 uint32 allocation_size
= get_allocation_size(conn
,fsp
, &sbuf
);
7322 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)sbuf
.st_size
);
7323 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
7325 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
7327 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
7329 END_PROFILE(SMBgetattrE
);