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 NTSTATUS ret
= NT_STATUS_OK
;
54 bool start_of_name_component
= True
;
55 bool stream_started
= 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) {
73 return NT_STATUS_INVALID_PARAMETER
;
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 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
137 /* Go back one level... */
138 /* We know this is safe as '/' cannot be part of a mb sequence. */
139 /* NOTE - if this assumption is invalid we are not in good shape... */
140 /* Decrement d first as d points to the *next* char to write into. */
141 for (d
--; d
> path
; d
--) {
145 s
+= 2; /* Else go past the .. */
146 /* We're still at the start of a name component, just the previous one. */
149 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
161 if (*s
<= 0x1f || *s
== '|') {
162 return NT_STATUS_OBJECT_NAME_INVALID
;
170 *p_last_component_contains_wcard
= True
;
179 /* Get the size of the next MB character. */
180 next_codepoint(s
,&siz
);
198 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
200 return NT_STATUS_INVALID_PARAMETER
;
203 start_of_name_component
= False
;
211 /****************************************************************************
212 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
213 No wildcards allowed.
214 ****************************************************************************/
216 NTSTATUS
check_path_syntax(char *path
)
219 return check_path_syntax_internal(path
, False
, &ignore
);
222 /****************************************************************************
223 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
224 Wildcards allowed - p_contains_wcard returns true if the last component contained
226 ****************************************************************************/
228 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
230 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
233 /****************************************************************************
234 Check the path for a POSIX client.
235 We're assuming here that '/' is not the second byte in any multibyte char
236 set (a safe assumption).
237 ****************************************************************************/
239 NTSTATUS
check_path_syntax_posix(char *path
)
242 return check_path_syntax_internal(path
, True
, &ignore
);
245 /****************************************************************************
246 Pull a string and check the path allowing a wilcard - provide for error return.
247 ****************************************************************************/
249 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
257 bool *contains_wcard
)
264 ret
= srvstr_pull_buf_talloc(ctx
,
271 ret
= srvstr_pull_talloc(ctx
,
281 *err
= NT_STATUS_INVALID_PARAMETER
;
285 *contains_wcard
= False
;
287 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
289 * For a DFS path the function parse_dfs_path()
290 * will do the path processing, just make a copy.
296 if (lp_posix_pathnames()) {
297 *err
= check_path_syntax_posix(*pp_dest
);
299 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
305 /****************************************************************************
306 Pull a string and check the path - provide for error return.
307 ****************************************************************************/
309 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
323 ret
= srvstr_pull_buf_talloc(ctx
,
330 ret
= srvstr_pull_talloc(ctx
,
340 *err
= NT_STATUS_INVALID_PARAMETER
;
344 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
346 * For a DFS path the function parse_dfs_path()
347 * will do the path processing, just make a copy.
353 if (lp_posix_pathnames()) {
354 *err
= check_path_syntax_posix(*pp_dest
);
356 *err
= check_path_syntax(*pp_dest
);
362 /****************************************************************************
363 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
364 ****************************************************************************/
366 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
369 if (!(fsp
) || !(conn
)) {
370 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
373 if (((conn
) != (fsp
)->conn
) || req
->vuid
!= (fsp
)->vuid
) {
374 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
380 /****************************************************************************
381 Check if we have a correct fsp pointing to a file.
382 ****************************************************************************/
384 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
387 if (!check_fsp_open(conn
, req
, fsp
)) {
390 if ((fsp
)->is_directory
) {
391 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
394 if ((fsp
)->fh
->fd
== -1) {
395 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
398 (fsp
)->num_smb_operations
++;
402 /****************************************************************************
403 Check if we have a correct fsp pointing to a quota fake file. Replacement for
404 the CHECK_NTQUOTA_HANDLE_OK macro.
405 ****************************************************************************/
407 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
410 if (!check_fsp_open(conn
, req
, fsp
)) {
414 if (fsp
->is_directory
) {
418 if (fsp
->fake_file_handle
== NULL
) {
422 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
426 if (fsp
->fake_file_handle
->private_data
== NULL
) {
433 /****************************************************************************
434 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
435 ****************************************************************************/
437 bool fsp_belongs_conn(connection_struct
*conn
, struct smb_request
*req
,
440 if ((fsp
) && (conn
) && ((conn
)==(fsp
)->conn
)
441 && (req
->vuid
== (fsp
)->vuid
)) {
445 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
449 /****************************************************************************
450 Reply to a (netbios-level) special message.
451 ****************************************************************************/
453 void reply_special(char *inbuf
)
455 int msg_type
= CVAL(inbuf
,0);
456 int msg_flags
= CVAL(inbuf
,1);
461 * We only really use 4 bytes of the outbuf, but for the smb_setlen
462 * calculation & friends (srv_send_smb uses that) we need the full smb
465 char outbuf
[smb_size
];
467 static bool already_got_session
= False
;
471 memset(outbuf
, '\0', sizeof(outbuf
));
473 smb_setlen(outbuf
,0);
476 case 0x81: /* session request */
478 if (already_got_session
) {
479 exit_server_cleanly("multiple session request not permitted");
482 SCVAL(outbuf
,0,0x82);
484 if (name_len(inbuf
+4) > 50 ||
485 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
486 DEBUG(0,("Invalid name length in session request\n"));
489 name_extract(inbuf
,4,name1
);
490 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
491 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
494 set_local_machine_name(name1
, True
);
495 set_remote_machine_name(name2
, True
);
497 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
498 get_local_machine_name(), get_remote_machine_name(),
501 if (name_type
== 'R') {
502 /* We are being asked for a pathworks session ---
504 SCVAL(outbuf
, 0,0x83);
508 /* only add the client's machine name to the list
509 of possibly valid usernames if we are operating
510 in share mode security */
511 if (lp_security() == SEC_SHARE
) {
512 add_session_user(get_remote_machine_name());
515 reload_services(True
);
518 already_got_session
= True
;
521 case 0x89: /* session keepalive request
522 (some old clients produce this?) */
523 SCVAL(outbuf
,0,SMBkeepalive
);
527 case 0x82: /* positive session response */
528 case 0x83: /* negative session response */
529 case 0x84: /* retarget session response */
530 DEBUG(0,("Unexpected session response\n"));
533 case SMBkeepalive
: /* session keepalive */
538 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
539 msg_type
, msg_flags
));
541 srv_send_smb(smbd_server_fd(), outbuf
, false);
545 /****************************************************************************
547 conn POINTER CAN BE NULL HERE !
548 ****************************************************************************/
550 void reply_tcon(struct smb_request
*req
)
552 connection_struct
*conn
= req
->conn
;
554 char *service_buf
= NULL
;
555 char *password
= NULL
;
560 DATA_BLOB password_blob
;
561 TALLOC_CTX
*ctx
= talloc_tos();
563 START_PROFILE(SMBtcon
);
565 if (smb_buflen(req
->inbuf
) < 4) {
566 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
567 END_PROFILE(SMBtcon
);
571 p
= smb_buf(req
->inbuf
)+1;
572 p
+= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
,
573 &service_buf
, p
, STR_TERMINATE
) + 1;
574 pwlen
= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
,
575 &password
, p
, STR_TERMINATE
) + 1;
577 p
+= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
,
578 &dev
, p
, STR_TERMINATE
) + 1;
580 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
581 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
582 END_PROFILE(SMBtcon
);
585 p
= strrchr_m(service_buf
,'\\');
589 service
= service_buf
;
592 password_blob
= data_blob(password
, pwlen
+1);
594 conn
= make_connection(service
,password_blob
,dev
,req
->vuid
,&nt_status
);
597 data_blob_clear_free(&password_blob
);
600 reply_nterror(req
, nt_status
);
601 END_PROFILE(SMBtcon
);
605 reply_outbuf(req
, 2, 0);
606 SSVAL(req
->outbuf
,smb_vwv0
,max_recv
);
607 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
608 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
610 DEBUG(3,("tcon service=%s cnum=%d\n",
611 service
, conn
->cnum
));
613 END_PROFILE(SMBtcon
);
617 /****************************************************************************
618 Reply to a tcon and X.
619 conn POINTER CAN BE NULL HERE !
620 ****************************************************************************/
622 void reply_tcon_and_X(struct smb_request
*req
)
624 connection_struct
*conn
= req
->conn
;
625 char *service
= NULL
;
627 TALLOC_CTX
*ctx
= talloc_tos();
628 /* what the cleint thinks the device is */
629 char *client_devicetype
= NULL
;
630 /* what the server tells the client the share represents */
631 const char *server_devicetype
;
638 START_PROFILE(SMBtconX
);
641 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
642 END_PROFILE(SMBtconX
);
646 passlen
= SVAL(req
->inbuf
,smb_vwv3
);
647 tcon_flags
= SVAL(req
->inbuf
,smb_vwv2
);
649 /* we might have to close an old one */
650 if ((tcon_flags
& 0x1) && conn
) {
651 close_cnum(conn
,req
->vuid
);
656 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= smb_buflen(req
->inbuf
))) {
657 reply_doserror(req
, ERRDOS
, ERRbuftoosmall
);
658 END_PROFILE(SMBtconX
);
662 if (global_encrypted_passwords_negotiated
) {
663 password
= data_blob_talloc(talloc_tos(), smb_buf(req
->inbuf
),
665 if (lp_security() == SEC_SHARE
) {
667 * Security = share always has a pad byte
668 * after the password.
670 p
= smb_buf(req
->inbuf
) + passlen
+ 1;
672 p
= smb_buf(req
->inbuf
) + passlen
;
675 password
= data_blob_talloc(talloc_tos(), smb_buf(req
->inbuf
),
677 /* Ensure correct termination */
678 password
.data
[passlen
]=0;
679 p
= smb_buf(req
->inbuf
) + passlen
+ 1;
682 p
+= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
, &path
, p
,
686 data_blob_clear_free(&password
);
687 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
688 END_PROFILE(SMBtconX
);
693 * the service name can be either: \\server\share
694 * or share directly like on the DELL PowerVault 705
697 q
= strchr_m(path
+2,'\\');
699 data_blob_clear_free(&password
);
700 reply_doserror(req
, ERRDOS
, ERRnosuchshare
);
701 END_PROFILE(SMBtconX
);
709 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
710 &client_devicetype
, p
,
711 MIN(6,smb_bufrem(req
->inbuf
, p
)), STR_ASCII
);
713 if (client_devicetype
== NULL
) {
714 data_blob_clear_free(&password
);
715 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
716 END_PROFILE(SMBtconX
);
720 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
722 conn
= make_connection(service
, password
, client_devicetype
,
723 req
->vuid
, &nt_status
);
726 data_blob_clear_free(&password
);
729 reply_nterror(req
, nt_status
);
730 END_PROFILE(SMBtconX
);
735 server_devicetype
= "IPC";
736 else if ( IS_PRINT(conn
) )
737 server_devicetype
= "LPT1:";
739 server_devicetype
= "A:";
741 if (Protocol
< PROTOCOL_NT1
) {
742 reply_outbuf(req
, 2, 0);
743 if (message_push_string(&req
->outbuf
, server_devicetype
,
744 STR_TERMINATE
|STR_ASCII
) == -1) {
745 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
746 END_PROFILE(SMBtconX
);
750 /* NT sets the fstype of IPC$ to the null string */
751 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
753 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
754 /* Return permissions. */
758 reply_outbuf(req
, 7, 0);
761 perm1
= FILE_ALL_ACCESS
;
762 perm2
= FILE_ALL_ACCESS
;
764 perm1
= CAN_WRITE(conn
) ?
769 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
770 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
772 reply_outbuf(req
, 3, 0);
775 if ((message_push_string(&req
->outbuf
, server_devicetype
,
776 STR_TERMINATE
|STR_ASCII
) == -1)
777 || (message_push_string(&req
->outbuf
, fstype
,
778 STR_TERMINATE
) == -1)) {
779 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
780 END_PROFILE(SMBtconX
);
784 /* what does setting this bit do? It is set by NT4 and
785 may affect the ability to autorun mounted cdroms */
786 SSVAL(req
->outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
787 (lp_csc_policy(SNUM(conn
)) << 2));
789 init_dfsroot(conn
, req
->inbuf
, req
->outbuf
);
793 DEBUG(3,("tconX service=%s \n",
796 /* set the incoming and outgoing tid to the just created one */
797 SSVAL(req
->inbuf
,smb_tid
,conn
->cnum
);
798 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
800 END_PROFILE(SMBtconX
);
806 /****************************************************************************
807 Reply to an unknown type.
808 ****************************************************************************/
810 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
812 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
813 smb_fn_name(type
), type
, type
));
814 reply_doserror(req
, ERRSRV
, ERRunknownsmb
);
818 /****************************************************************************
820 conn POINTER CAN BE NULL HERE !
821 ****************************************************************************/
823 void reply_ioctl(struct smb_request
*req
)
825 connection_struct
*conn
= req
->conn
;
832 START_PROFILE(SMBioctl
);
835 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
836 END_PROFILE(SMBioctl
);
840 device
= SVAL(req
->inbuf
,smb_vwv1
);
841 function
= SVAL(req
->inbuf
,smb_vwv2
);
842 ioctl_code
= (device
<< 16) + function
;
844 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
846 switch (ioctl_code
) {
847 case IOCTL_QUERY_JOB_INFO
:
851 reply_doserror(req
, ERRSRV
, ERRnosupport
);
852 END_PROFILE(SMBioctl
);
856 reply_outbuf(req
, 8, replysize
+1);
857 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
858 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
859 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
860 p
= smb_buf(req
->outbuf
);
861 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
862 p
+= 1; /* Allow for alignment */
864 switch (ioctl_code
) {
865 case IOCTL_QUERY_JOB_INFO
:
867 files_struct
*fsp
= file_fsp(SVAL(req
->inbuf
,
870 reply_doserror(req
, ERRDOS
, ERRbadfid
);
871 END_PROFILE(SMBioctl
);
874 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
875 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
877 STR_TERMINATE
|STR_ASCII
);
879 srvstr_push((char *)req
->outbuf
, req
->flags2
,
880 p
+18, lp_servicename(SNUM(conn
)),
881 13, STR_TERMINATE
|STR_ASCII
);
889 END_PROFILE(SMBioctl
);
893 /****************************************************************************
894 Strange checkpath NTSTATUS mapping.
895 ****************************************************************************/
897 static NTSTATUS
map_checkpath_error(const char *inbuf
, NTSTATUS status
)
899 /* Strange DOS error code semantics only for checkpath... */
900 if (!(SVAL(inbuf
,smb_flg2
) & FLAGS2_32_BIT_ERROR_CODES
)) {
901 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
902 /* We need to map to ERRbadpath */
903 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
909 /****************************************************************************
910 Reply to a checkpath.
911 ****************************************************************************/
913 void reply_checkpath(struct smb_request
*req
)
915 connection_struct
*conn
= req
->conn
;
917 SMB_STRUCT_STAT sbuf
;
919 TALLOC_CTX
*ctx
= talloc_tos();
921 START_PROFILE(SMBcheckpath
);
923 srvstr_get_path(ctx
,(char *)req
->inbuf
, req
->flags2
, &name
,
924 smb_buf(req
->inbuf
) + 1, 0,
925 STR_TERMINATE
, &status
);
926 if (!NT_STATUS_IS_OK(status
)) {
927 status
= map_checkpath_error((char *)req
->inbuf
, status
);
928 reply_nterror(req
, status
);
929 END_PROFILE(SMBcheckpath
);
933 status
= resolve_dfspath(ctx
, conn
,
934 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
937 if (!NT_STATUS_IS_OK(status
)) {
938 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
939 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
941 END_PROFILE(SMBcheckpath
);
947 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->inbuf
,smb_vwv0
)));
949 status
= unix_convert(ctx
, conn
, name
, False
, &name
, NULL
, &sbuf
);
950 if (!NT_STATUS_IS_OK(status
)) {
954 status
= check_name(conn
, name
);
955 if (!NT_STATUS_IS_OK(status
)) {
956 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name
,nt_errstr(status
)));
960 if (!VALID_STAT(sbuf
) && (SMB_VFS_STAT(conn
,name
,&sbuf
) != 0)) {
961 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name
,strerror(errno
)));
962 status
= map_nt_error_from_unix(errno
);
966 if (!S_ISDIR(sbuf
.st_mode
)) {
967 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
969 END_PROFILE(SMBcheckpath
);
973 reply_outbuf(req
, 0, 0);
975 END_PROFILE(SMBcheckpath
);
980 END_PROFILE(SMBcheckpath
);
982 /* We special case this - as when a Windows machine
983 is parsing a path is steps through the components
984 one at a time - if a component fails it expects
985 ERRbadpath, not ERRbadfile.
987 status
= map_checkpath_error((char *)req
->inbuf
, status
);
988 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
990 * Windows returns different error codes if
991 * the parent directory is valid but not the
992 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
993 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
994 * if the path is invalid.
996 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1001 reply_nterror(req
, status
);
1004 /****************************************************************************
1006 ****************************************************************************/
1008 void reply_getatr(struct smb_request
*req
)
1010 connection_struct
*conn
= req
->conn
;
1012 SMB_STRUCT_STAT sbuf
;
1018 TALLOC_CTX
*ctx
= talloc_tos();
1020 START_PROFILE(SMBgetatr
);
1022 p
= smb_buf(req
->inbuf
) + 1;
1023 p
+= srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
, p
,
1024 0, STR_TERMINATE
, &status
);
1025 if (!NT_STATUS_IS_OK(status
)) {
1026 reply_nterror(req
, status
);
1027 END_PROFILE(SMBgetatr
);
1031 status
= resolve_dfspath(ctx
, conn
,
1032 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1035 if (!NT_STATUS_IS_OK(status
)) {
1036 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1037 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1038 ERRSRV
, ERRbadpath
);
1039 END_PROFILE(SMBgetatr
);
1042 reply_nterror(req
, status
);
1043 END_PROFILE(SMBgetatr
);
1047 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1048 under WfWg - weird! */
1049 if (*fname
== '\0') {
1050 mode
= aHIDDEN
| aDIR
;
1051 if (!CAN_WRITE(conn
)) {
1057 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
,&sbuf
);
1058 if (!NT_STATUS_IS_OK(status
)) {
1059 reply_nterror(req
, status
);
1060 END_PROFILE(SMBgetatr
);
1063 status
= check_name(conn
, fname
);
1064 if (!NT_STATUS_IS_OK(status
)) {
1065 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname
,nt_errstr(status
)));
1066 reply_nterror(req
, status
);
1067 END_PROFILE(SMBgetatr
);
1070 if (!VALID_STAT(sbuf
) && (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0)) {
1071 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname
,strerror(errno
)));
1072 reply_unixerror(req
, ERRDOS
,ERRbadfile
);
1073 END_PROFILE(SMBgetatr
);
1077 mode
= dos_mode(conn
,fname
,&sbuf
);
1078 size
= sbuf
.st_size
;
1079 mtime
= sbuf
.st_mtime
;
1085 reply_outbuf(req
, 10, 0);
1087 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1088 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1089 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1091 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1093 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1095 if (Protocol
>= PROTOCOL_NT1
) {
1096 SSVAL(req
->outbuf
, smb_flg2
,
1097 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1100 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname
, mode
, (unsigned int)size
) );
1102 END_PROFILE(SMBgetatr
);
1106 /****************************************************************************
1108 ****************************************************************************/
1110 void reply_setatr(struct smb_request
*req
)
1112 struct timespec ts
[2];
1113 connection_struct
*conn
= req
->conn
;
1117 SMB_STRUCT_STAT sbuf
;
1120 TALLOC_CTX
*ctx
= talloc_tos();
1122 START_PROFILE(SMBsetatr
);
1127 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1131 p
= smb_buf(req
->inbuf
) + 1;
1132 p
+= srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
, p
,
1133 0, STR_TERMINATE
, &status
);
1134 if (!NT_STATUS_IS_OK(status
)) {
1135 reply_nterror(req
, status
);
1136 END_PROFILE(SMBsetatr
);
1140 status
= resolve_dfspath(ctx
, conn
,
1141 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1144 if (!NT_STATUS_IS_OK(status
)) {
1145 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1146 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1147 ERRSRV
, ERRbadpath
);
1148 END_PROFILE(SMBsetatr
);
1151 reply_nterror(req
, status
);
1152 END_PROFILE(SMBsetatr
);
1156 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
1157 if (!NT_STATUS_IS_OK(status
)) {
1158 reply_nterror(req
, status
);
1159 END_PROFILE(SMBsetatr
);
1163 status
= check_name(conn
, fname
);
1164 if (!NT_STATUS_IS_OK(status
)) {
1165 reply_nterror(req
, status
);
1166 END_PROFILE(SMBsetatr
);
1170 if (fname
[0] == '.' && fname
[1] == '\0') {
1172 * Not sure here is the right place to catch this
1173 * condition. Might be moved to somewhere else later -- vl
1175 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1176 END_PROFILE(SMBsetatr
);
1180 mode
= SVAL(req
->inbuf
,smb_vwv0
);
1181 mtime
= srv_make_unix_date3(req
->inbuf
+smb_vwv1
);
1183 ts
[1] = convert_time_t_to_timespec(mtime
);
1184 status
= smb_set_file_time(conn
, NULL
, fname
,
1186 if (!NT_STATUS_IS_OK(status
)) {
1187 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
1188 END_PROFILE(SMBsetatr
);
1192 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1193 if (VALID_STAT_OF_DIR(sbuf
))
1198 if (file_set_dosmode(conn
,fname
,mode
,&sbuf
,NULL
,false) != 0) {
1199 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
1200 END_PROFILE(SMBsetatr
);
1205 reply_outbuf(req
, 0, 0);
1207 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
1209 END_PROFILE(SMBsetatr
);
1213 /****************************************************************************
1215 ****************************************************************************/
1217 void reply_dskattr(struct smb_request
*req
)
1219 connection_struct
*conn
= req
->conn
;
1220 SMB_BIG_UINT dfree
,dsize
,bsize
;
1221 START_PROFILE(SMBdskattr
);
1223 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
1224 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
1225 END_PROFILE(SMBdskattr
);
1229 reply_outbuf(req
, 5, 0);
1231 if (Protocol
<= PROTOCOL_LANMAN2
) {
1232 double total_space
, free_space
;
1233 /* we need to scale this to a number that DOS6 can handle. We
1234 use floating point so we can handle large drives on systems
1235 that don't have 64 bit integers
1237 we end up displaying a maximum of 2G to DOS systems
1239 total_space
= dsize
* (double)bsize
;
1240 free_space
= dfree
* (double)bsize
;
1242 dsize
= (SMB_BIG_UINT
)((total_space
+63*512) / (64*512));
1243 dfree
= (SMB_BIG_UINT
)((free_space
+63*512) / (64*512));
1245 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1246 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1248 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1249 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1250 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1251 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1253 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1254 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1255 SSVAL(req
->outbuf
,smb_vwv2
,512);
1256 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1259 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1261 END_PROFILE(SMBdskattr
);
1265 /****************************************************************************
1267 Can be called from SMBsearch, SMBffirst or SMBfunique.
1268 ****************************************************************************/
1270 void reply_search(struct smb_request
*req
)
1272 connection_struct
*conn
= req
->conn
;
1274 char *directory
= NULL
;
1280 unsigned int numentries
= 0;
1281 unsigned int maxentries
= 0;
1282 bool finished
= False
;
1288 bool check_descend
= False
;
1289 bool expect_close
= False
;
1291 bool mask_contains_wcard
= False
;
1292 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1293 TALLOC_CTX
*ctx
= talloc_tos();
1294 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1296 START_PROFILE(SMBsearch
);
1299 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1300 END_PROFILE(SMBsearch
);
1304 if (lp_posix_pathnames()) {
1305 reply_unknown_new(req
, CVAL(req
->inbuf
, smb_com
));
1306 END_PROFILE(SMBsearch
);
1310 /* If we were called as SMBffirst then we must expect close. */
1311 if(CVAL(req
->inbuf
,smb_com
) == SMBffirst
) {
1312 expect_close
= True
;
1315 reply_outbuf(req
, 1, 3);
1316 maxentries
= SVAL(req
->inbuf
,smb_vwv0
);
1317 dirtype
= SVAL(req
->inbuf
,smb_vwv1
);
1318 p
= smb_buf(req
->inbuf
) + 1;
1319 p
+= srvstr_get_path_wcard(ctx
,
1327 &mask_contains_wcard
);
1328 if (!NT_STATUS_IS_OK(nt_status
)) {
1329 reply_nterror(req
, nt_status
);
1330 END_PROFILE(SMBsearch
);
1334 nt_status
= resolve_dfspath_wcard(ctx
, conn
,
1335 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1338 &mask_contains_wcard
);
1339 if (!NT_STATUS_IS_OK(nt_status
)) {
1340 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1341 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1342 ERRSRV
, ERRbadpath
);
1343 END_PROFILE(SMBsearch
);
1346 reply_nterror(req
, nt_status
);
1347 END_PROFILE(SMBsearch
);
1352 status_len
= SVAL(p
, 0);
1355 /* dirtype &= ~aDIR; */
1357 if (status_len
== 0) {
1358 SMB_STRUCT_STAT sbuf
;
1360 nt_status
= unix_convert(ctx
, conn
, path
, True
,
1361 &directory
, NULL
, &sbuf
);
1362 if (!NT_STATUS_IS_OK(nt_status
)) {
1363 reply_nterror(req
, nt_status
);
1364 END_PROFILE(SMBsearch
);
1368 nt_status
= check_name(conn
, directory
);
1369 if (!NT_STATUS_IS_OK(nt_status
)) {
1370 reply_nterror(req
, nt_status
);
1371 END_PROFILE(SMBsearch
);
1375 p
= strrchr_m(directory
,'/');
1378 directory
= talloc_strdup(ctx
,".");
1380 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1381 END_PROFILE(SMBsearch
);
1389 if (*directory
== '\0') {
1390 directory
= talloc_strdup(ctx
,".");
1392 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1393 END_PROFILE(SMBsearch
);
1397 memset((char *)status
,'\0',21);
1398 SCVAL(status
,0,(dirtype
& 0x1F));
1400 nt_status
= dptr_create(conn
,
1406 mask_contains_wcard
,
1409 if (!NT_STATUS_IS_OK(nt_status
)) {
1410 reply_nterror(req
, nt_status
);
1411 END_PROFILE(SMBsearch
);
1414 dptr_num
= dptr_dnum(conn
->dirptr
);
1418 memcpy(status
,p
,21);
1419 status_dirtype
= CVAL(status
,0) & 0x1F;
1420 if (status_dirtype
!= (dirtype
& 0x1F)) {
1421 dirtype
= status_dirtype
;
1424 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1425 if (!conn
->dirptr
) {
1428 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1429 mask
= dptr_wcard(dptr_num
);
1434 * For a 'continue' search we have no string. So
1435 * check from the initial saved string.
1437 mask_contains_wcard
= ms_has_wild(mask
);
1438 dirtype
= dptr_attr(dptr_num
);
1441 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1443 if ((dirtype
&0x1F) == aVOLID
) {
1444 char buf
[DIR_STRUCT_SIZE
];
1445 memcpy(buf
,status
,21);
1446 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1447 0,aVOLID
,0,!allow_long_path_components
)) {
1448 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1449 END_PROFILE(SMBsearch
);
1452 dptr_fill(buf
+12,dptr_num
);
1453 if (dptr_zero(buf
+12) && (status_len
==0)) {
1458 if (message_push_blob(&req
->outbuf
,
1459 data_blob_const(buf
, sizeof(buf
)))
1461 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1462 END_PROFILE(SMBsearch
);
1470 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1473 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1474 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1475 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
)) {
1476 check_descend
= True
;
1479 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1480 finished
= !get_dir_entry(ctx
,
1491 char buf
[DIR_STRUCT_SIZE
];
1492 memcpy(buf
,status
,21);
1493 if (!make_dir_struct(ctx
,
1500 !allow_long_path_components
)) {
1501 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1502 END_PROFILE(SMBsearch
);
1505 if (!dptr_fill(buf
+12,dptr_num
)) {
1508 if (message_push_blob(&req
->outbuf
,
1509 data_blob_const(buf
, sizeof(buf
)))
1511 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1512 END_PROFILE(SMBsearch
);
1522 /* If we were called as SMBffirst with smb_search_id == NULL
1523 and no entries were found then return error and close dirptr
1526 if (numentries
== 0) {
1527 dptr_close(&dptr_num
);
1528 } else if(expect_close
&& status_len
== 0) {
1529 /* Close the dptr - we know it's gone */
1530 dptr_close(&dptr_num
);
1533 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1534 if(dptr_num
>= 0 && CVAL(req
->inbuf
,smb_com
) == SMBfunique
) {
1535 dptr_close(&dptr_num
);
1538 if ((numentries
== 0) && !mask_contains_wcard
) {
1539 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1540 END_PROFILE(SMBsearch
);
1544 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1545 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1546 SCVAL(smb_buf(req
->outbuf
),0,5);
1547 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1549 /* The replies here are never long name. */
1550 SSVAL(req
->outbuf
, smb_flg2
,
1551 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1552 if (!allow_long_path_components
) {
1553 SSVAL(req
->outbuf
, smb_flg2
,
1554 SVAL(req
->outbuf
, smb_flg2
)
1555 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1558 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1559 SSVAL(req
->outbuf
, smb_flg2
,
1560 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1563 directory
= dptr_path(dptr_num
);
1566 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1567 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
1569 directory
? directory
: "./",
1574 END_PROFILE(SMBsearch
);
1578 /****************************************************************************
1579 Reply to a fclose (stop directory search).
1580 ****************************************************************************/
1582 void reply_fclose(struct smb_request
*req
)
1590 bool path_contains_wcard
= False
;
1591 TALLOC_CTX
*ctx
= talloc_tos();
1593 START_PROFILE(SMBfclose
);
1595 if (lp_posix_pathnames()) {
1596 reply_unknown_new(req
, CVAL(req
->inbuf
, smb_com
));
1597 END_PROFILE(SMBfclose
);
1601 p
= smb_buf(req
->inbuf
) + 1;
1602 p
+= srvstr_get_path_wcard(ctx
,
1610 &path_contains_wcard
);
1611 if (!NT_STATUS_IS_OK(err
)) {
1612 reply_nterror(req
, err
);
1613 END_PROFILE(SMBfclose
);
1617 status_len
= SVAL(p
,0);
1620 if (status_len
== 0) {
1621 reply_doserror(req
, ERRSRV
, ERRsrverror
);
1622 END_PROFILE(SMBfclose
);
1626 memcpy(status
,p
,21);
1628 if(dptr_fetch(status
+12,&dptr_num
)) {
1629 /* Close the dptr - we know it's gone */
1630 dptr_close(&dptr_num
);
1633 reply_outbuf(req
, 1, 0);
1634 SSVAL(req
->outbuf
,smb_vwv0
,0);
1636 DEBUG(3,("search close\n"));
1638 END_PROFILE(SMBfclose
);
1642 /****************************************************************************
1644 ****************************************************************************/
1646 void reply_open(struct smb_request
*req
)
1648 connection_struct
*conn
= req
->conn
;
1654 SMB_STRUCT_STAT sbuf
;
1661 uint32 create_disposition
;
1662 uint32 create_options
= 0;
1664 TALLOC_CTX
*ctx
= talloc_tos();
1666 START_PROFILE(SMBopen
);
1669 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1670 END_PROFILE(SMBopen
);
1674 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1675 deny_mode
= SVAL(req
->inbuf
,smb_vwv0
);
1676 dos_attr
= SVAL(req
->inbuf
,smb_vwv1
);
1678 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
1679 smb_buf(req
->inbuf
)+1, 0,
1680 STR_TERMINATE
, &status
);
1681 if (!NT_STATUS_IS_OK(status
)) {
1682 reply_nterror(req
, status
);
1683 END_PROFILE(SMBopen
);
1687 if (!map_open_params_to_ntcreate(
1688 fname
, deny_mode
, OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1689 &share_mode
, &create_disposition
, &create_options
)) {
1690 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1691 END_PROFILE(SMBopen
);
1695 status
= create_file(conn
, /* conn */
1697 0, /* root_dir_fid */
1699 access_mask
, /* access_mask */
1700 share_mode
, /* share_access */
1701 create_disposition
, /* create_disposition*/
1702 create_options
, /* create_options */
1703 dos_attr
, /* file_attributes */
1704 oplock_request
, /* oplock_request */
1705 0, /* allocation_size */
1712 if (!NT_STATUS_IS_OK(status
)) {
1713 if (open_was_deferred(req
->mid
)) {
1714 /* We have re-scheduled this call. */
1715 END_PROFILE(SMBopen
);
1718 reply_openerror(req
, status
);
1719 END_PROFILE(SMBopen
);
1723 size
= sbuf
.st_size
;
1724 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1725 mtime
= sbuf
.st_mtime
;
1728 DEBUG(3,("attempt to open a directory %s\n",fsp
->fsp_name
));
1729 close_file(fsp
,ERROR_CLOSE
);
1730 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1731 END_PROFILE(SMBopen
);
1735 reply_outbuf(req
, 7, 0);
1736 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1737 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1738 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1739 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1741 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1743 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1744 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1746 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1747 SCVAL(req
->outbuf
,smb_flg
,
1748 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1751 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1752 SCVAL(req
->outbuf
,smb_flg
,
1753 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1755 END_PROFILE(SMBopen
);
1759 /****************************************************************************
1760 Reply to an open and X.
1761 ****************************************************************************/
1763 void reply_open_and_X(struct smb_request
*req
)
1765 connection_struct
*conn
= req
->conn
;
1770 /* Breakout the oplock request bits so we can set the
1771 reply bits separately. */
1772 int ex_oplock_request
;
1773 int core_oplock_request
;
1776 int smb_sattr
= SVAL(req
->inbuf
,smb_vwv4
);
1777 uint32 smb_time
= make_unix_date3(req
->inbuf
+smb_vwv6
);
1782 SMB_STRUCT_STAT sbuf
;
1786 SMB_BIG_UINT allocation_size
;
1787 ssize_t retval
= -1;
1790 uint32 create_disposition
;
1791 uint32 create_options
= 0;
1792 TALLOC_CTX
*ctx
= talloc_tos();
1794 START_PROFILE(SMBopenX
);
1796 if (req
->wct
< 15) {
1797 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1798 END_PROFILE(SMBopenX
);
1802 open_flags
= SVAL(req
->inbuf
,smb_vwv2
);
1803 deny_mode
= SVAL(req
->inbuf
,smb_vwv3
);
1804 smb_attr
= SVAL(req
->inbuf
,smb_vwv5
);
1805 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1806 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1807 oplock_request
= ex_oplock_request
| core_oplock_request
;
1808 smb_ofun
= SVAL(req
->inbuf
,smb_vwv8
);
1809 allocation_size
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv9
);
1811 /* If it's an IPC, pass off the pipe handler. */
1813 if (lp_nt_pipe_support()) {
1814 reply_open_pipe_and_X(conn
, req
);
1816 reply_doserror(req
, ERRSRV
, ERRaccess
);
1818 END_PROFILE(SMBopenX
);
1822 /* XXXX we need to handle passed times, sattr and flags */
1823 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
1824 smb_buf(req
->inbuf
), 0, STR_TERMINATE
,
1826 if (!NT_STATUS_IS_OK(status
)) {
1827 reply_nterror(req
, status
);
1828 END_PROFILE(SMBopenX
);
1832 if (!map_open_params_to_ntcreate(
1833 fname
, deny_mode
, smb_ofun
, &access_mask
,
1834 &share_mode
, &create_disposition
, &create_options
)) {
1835 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1836 END_PROFILE(SMBopenX
);
1840 status
= create_file(conn
, /* conn */
1842 0, /* root_dir_fid */
1844 access_mask
, /* access_mask */
1845 share_mode
, /* share_access */
1846 create_disposition
, /* create_disposition*/
1847 create_options
, /* create_options */
1848 smb_attr
, /* file_attributes */
1849 oplock_request
, /* oplock_request */
1850 0, /* allocation_size */
1854 &smb_action
, /* pinfo */
1857 if (!NT_STATUS_IS_OK(status
)) {
1858 END_PROFILE(SMBopenX
);
1859 if (open_was_deferred(req
->mid
)) {
1860 /* We have re-scheduled this call. */
1863 reply_openerror(req
, status
);
1867 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1868 if the file is truncated or created. */
1869 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1870 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1871 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1872 close_file(fsp
,ERROR_CLOSE
);
1873 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1874 END_PROFILE(SMBopenX
);
1877 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1879 close_file(fsp
,ERROR_CLOSE
);
1880 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1881 END_PROFILE(SMBopenX
);
1884 sbuf
.st_size
= get_allocation_size(conn
,fsp
,&sbuf
);
1887 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1888 mtime
= sbuf
.st_mtime
;
1890 close_file(fsp
,ERROR_CLOSE
);
1891 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
1892 END_PROFILE(SMBopenX
);
1896 /* If the caller set the extended oplock request bit
1897 and we granted one (by whatever means) - set the
1898 correct bit for extended oplock reply.
1901 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1902 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1905 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1906 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1909 /* If the caller set the core oplock request bit
1910 and we granted one (by whatever means) - set the
1911 correct bit for core oplock reply.
1914 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1915 reply_outbuf(req
, 19, 0);
1917 reply_outbuf(req
, 15, 0);
1920 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1921 SCVAL(req
->outbuf
, smb_flg
,
1922 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1925 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1926 SCVAL(req
->outbuf
, smb_flg
,
1927 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1930 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
1931 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
1932 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1933 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
1935 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
1937 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
1938 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
1939 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
1941 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1942 SIVAL(req
->outbuf
, smb_vwv15
, STD_RIGHT_ALL_ACCESS
);
1945 END_PROFILE(SMBopenX
);
1950 /****************************************************************************
1951 Reply to a SMBulogoffX.
1952 ****************************************************************************/
1954 void reply_ulogoffX(struct smb_request
*req
)
1958 START_PROFILE(SMBulogoffX
);
1960 vuser
= get_valid_user_struct(req
->vuid
);
1963 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1967 /* in user level security we are supposed to close any files
1968 open by this user */
1969 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
1970 file_close_user(req
->vuid
);
1973 invalidate_vuid(req
->vuid
);
1975 reply_outbuf(req
, 2, 0);
1977 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
1979 END_PROFILE(SMBulogoffX
);
1983 /****************************************************************************
1984 Reply to a mknew or a create.
1985 ****************************************************************************/
1987 void reply_mknew(struct smb_request
*req
)
1989 connection_struct
*conn
= req
->conn
;
1993 struct timespec ts
[2];
1995 int oplock_request
= 0;
1996 SMB_STRUCT_STAT sbuf
;
1998 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
1999 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2000 uint32 create_disposition
;
2001 uint32 create_options
= 0;
2002 TALLOC_CTX
*ctx
= talloc_tos();
2004 START_PROFILE(SMBcreate
);
2007 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2008 END_PROFILE(SMBcreate
);
2012 fattr
= SVAL(req
->inbuf
,smb_vwv0
);
2013 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2014 com
= SVAL(req
->inbuf
,smb_com
);
2016 ts
[1] =convert_time_t_to_timespec(
2017 srv_make_unix_date3(req
->inbuf
+ smb_vwv1
));
2020 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
2021 smb_buf(req
->inbuf
) + 1, 0,
2022 STR_TERMINATE
, &status
);
2023 if (!NT_STATUS_IS_OK(status
)) {
2024 reply_nterror(req
, status
);
2025 END_PROFILE(SMBcreate
);
2029 if (fattr
& aVOLID
) {
2030 DEBUG(0,("Attempt to create file (%s) with volid set - "
2031 "please report this\n", fname
));
2034 if(com
== SMBmknew
) {
2035 /* We should fail if file exists. */
2036 create_disposition
= FILE_CREATE
;
2038 /* Create if file doesn't exist, truncate if it does. */
2039 create_disposition
= FILE_OVERWRITE_IF
;
2042 status
= create_file(conn
, /* conn */
2044 0, /* root_dir_fid */
2046 access_mask
, /* access_mask */
2047 share_mode
, /* share_access */
2048 create_disposition
, /* create_disposition*/
2049 create_options
, /* create_options */
2050 fattr
, /* file_attributes */
2051 oplock_request
, /* oplock_request */
2052 0, /* allocation_size */
2059 if (!NT_STATUS_IS_OK(status
)) {
2060 END_PROFILE(SMBcreate
);
2061 if (open_was_deferred(req
->mid
)) {
2062 /* We have re-scheduled this call. */
2065 reply_openerror(req
, status
);
2069 ts
[0] = get_atimespec(&sbuf
); /* atime. */
2070 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &sbuf
, ts
, true);
2071 if (!NT_STATUS_IS_OK(status
)) {
2072 END_PROFILE(SMBcreate
);
2073 reply_openerror(req
, status
);
2077 reply_outbuf(req
, 1, 0);
2078 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2080 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2081 SCVAL(req
->outbuf
,smb_flg
,
2082 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2085 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2086 SCVAL(req
->outbuf
,smb_flg
,
2087 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2090 DEBUG( 2, ( "reply_mknew: file %s\n", fsp
->fsp_name
) );
2091 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2092 fsp
->fsp_name
, fsp
->fh
->fd
, (unsigned int)fattr
) );
2094 END_PROFILE(SMBcreate
);
2098 /****************************************************************************
2099 Reply to a create temporary file.
2100 ****************************************************************************/
2102 void reply_ctemp(struct smb_request
*req
)
2104 connection_struct
*conn
= req
->conn
;
2110 SMB_STRUCT_STAT sbuf
;
2113 TALLOC_CTX
*ctx
= talloc_tos();
2115 START_PROFILE(SMBctemp
);
2118 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2119 END_PROFILE(SMBctemp
);
2123 fattr
= SVAL(req
->inbuf
,smb_vwv0
);
2124 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2126 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
2127 smb_buf(req
->inbuf
)+1, 0, STR_TERMINATE
,
2129 if (!NT_STATUS_IS_OK(status
)) {
2130 reply_nterror(req
, status
);
2131 END_PROFILE(SMBctemp
);
2135 fname
= talloc_asprintf(ctx
,
2139 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2143 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2144 END_PROFILE(SMBctemp
);
2148 status
= resolve_dfspath(ctx
, conn
,
2149 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2152 if (!NT_STATUS_IS_OK(status
)) {
2153 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2154 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2155 ERRSRV
, ERRbadpath
);
2156 END_PROFILE(SMBctemp
);
2159 reply_nterror(req
, status
);
2160 END_PROFILE(SMBctemp
);
2164 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
2165 if (!NT_STATUS_IS_OK(status
)) {
2166 reply_nterror(req
, status
);
2167 END_PROFILE(SMBctemp
);
2171 status
= check_name(conn
, fname
);
2172 if (!NT_STATUS_IS_OK(status
)) {
2173 reply_nterror(req
, status
);
2174 END_PROFILE(SMBctemp
);
2178 tmpfd
= smb_mkstemp(fname
);
2180 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
2181 END_PROFILE(SMBctemp
);
2185 SMB_VFS_STAT(conn
,fname
,&sbuf
);
2187 /* We should fail if file does not exist. */
2188 status
= open_file_ntcreate(conn
, req
, fname
, &sbuf
,
2189 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
,
2190 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
2197 /* close fd from smb_mkstemp() */
2200 if (!NT_STATUS_IS_OK(status
)) {
2201 if (open_was_deferred(req
->mid
)) {
2202 /* We have re-scheduled this call. */
2203 END_PROFILE(SMBctemp
);
2206 reply_openerror(req
, status
);
2207 END_PROFILE(SMBctemp
);
2211 reply_outbuf(req
, 1, 0);
2212 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2214 /* the returned filename is relative to the directory */
2215 s
= strrchr_m(fsp
->fsp_name
, '/');
2223 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2224 thing in the byte section. JRA */
2225 SSVALS(p
, 0, -1); /* what is this? not in spec */
2227 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2229 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2230 END_PROFILE(SMBctemp
);
2234 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2235 SCVAL(req
->outbuf
, smb_flg
,
2236 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2239 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2240 SCVAL(req
->outbuf
, smb_flg
,
2241 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2244 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp
->fsp_name
) );
2245 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp
->fsp_name
,
2246 fsp
->fh
->fd
, (unsigned int)sbuf
.st_mode
) );
2248 END_PROFILE(SMBctemp
);
2252 /*******************************************************************
2253 Check if a user is allowed to rename a file.
2254 ********************************************************************/
2256 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2257 uint16 dirtype
, SMB_STRUCT_STAT
*pst
)
2261 if (!CAN_WRITE(conn
)) {
2262 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2265 fmode
= dos_mode(conn
, fsp
->fsp_name
, pst
);
2266 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
)) {
2267 return NT_STATUS_NO_SUCH_FILE
;
2270 if (S_ISDIR(pst
->st_mode
)) {
2271 if (fsp
->posix_open
) {
2272 return NT_STATUS_OK
;
2275 /* If no pathnames are open below this
2276 directory, allow the rename. */
2278 if (file_find_subpath(fsp
)) {
2279 return NT_STATUS_ACCESS_DENIED
;
2281 return NT_STATUS_OK
;
2284 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2285 return NT_STATUS_OK
;
2288 return NT_STATUS_ACCESS_DENIED
;
2291 /*******************************************************************
2292 * unlink a file with all relevant access checks
2293 *******************************************************************/
2295 static NTSTATUS
do_unlink(connection_struct
*conn
,
2296 struct smb_request
*req
,
2300 SMB_STRUCT_STAT sbuf
;
2303 uint32 dirtype_orig
= dirtype
;
2306 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname
, dirtype
));
2308 if (!CAN_WRITE(conn
)) {
2309 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2312 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
) != 0) {
2313 return map_nt_error_from_unix(errno
);
2316 fattr
= dos_mode(conn
,fname
,&sbuf
);
2318 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2319 dirtype
= aDIR
|aARCH
|aRONLY
;
2322 dirtype
&= (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
);
2324 return NT_STATUS_NO_SUCH_FILE
;
2327 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2329 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2331 return NT_STATUS_NO_SUCH_FILE
;
2334 if (dirtype_orig
& 0x8000) {
2335 /* These will never be set for POSIX. */
2336 return NT_STATUS_NO_SUCH_FILE
;
2340 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2341 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2344 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2345 return NT_STATUS_NO_SUCH_FILE
;
2348 if (dirtype
& 0xFF00) {
2349 /* These will never be set for POSIX. */
2350 return NT_STATUS_NO_SUCH_FILE
;
2355 return NT_STATUS_NO_SUCH_FILE
;
2358 /* Can't delete a directory. */
2360 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2365 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
2366 return NT_STATUS_OBJECT_NAME_INVALID
;
2367 #endif /* JRATEST */
2369 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2371 On a Windows share, a file with read-only dosmode can be opened with
2372 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2373 fails with NT_STATUS_CANNOT_DELETE error.
2375 This semantic causes a problem that a user can not
2376 rename a file with read-only dosmode on a Samba share
2377 from a Windows command prompt (i.e. cmd.exe, but can rename
2378 from Windows Explorer).
2381 if (!lp_delete_readonly(SNUM(conn
))) {
2382 if (fattr
& aRONLY
) {
2383 return NT_STATUS_CANNOT_DELETE
;
2387 /* On open checks the open itself will check the share mode, so
2388 don't do it here as we'll get it wrong. */
2390 status
= create_file_unixpath
2394 DELETE_ACCESS
, /* access_mask */
2395 FILE_SHARE_NONE
, /* share_access */
2396 FILE_OPEN
, /* create_disposition*/
2397 FILE_NON_DIRECTORY_FILE
, /* create_options */
2398 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
2399 0, /* oplock_request */
2400 0, /* allocation_size */
2407 if (!NT_STATUS_IS_OK(status
)) {
2408 DEBUG(10, ("create_file_unixpath failed: %s\n",
2409 nt_errstr(status
)));
2413 /* The set is across all open files on this dev/inode pair. */
2414 if (!set_delete_on_close(fsp
, True
, &conn
->server_info
->utok
)) {
2415 close_file(fsp
, NORMAL_CLOSE
);
2416 return NT_STATUS_ACCESS_DENIED
;
2419 return close_file(fsp
,NORMAL_CLOSE
);
2422 /****************************************************************************
2423 The guts of the unlink command, split out so it may be called by the NT SMB
2425 ****************************************************************************/
2427 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2428 uint32 dirtype
, const char *name_in
, bool has_wild
)
2430 const char *directory
= NULL
;
2435 NTSTATUS status
= NT_STATUS_OK
;
2436 SMB_STRUCT_STAT sbuf
;
2437 TALLOC_CTX
*ctx
= talloc_tos();
2439 status
= unix_convert(ctx
, conn
, name_in
, has_wild
, &name
, NULL
, &sbuf
);
2440 if (!NT_STATUS_IS_OK(status
)) {
2444 p
= strrchr_m(name
,'/');
2446 directory
= talloc_strdup(ctx
, ".");
2448 return NT_STATUS_NO_MEMORY
;
2458 * We should only check the mangled cache
2459 * here if unix_convert failed. This means
2460 * that the path in 'mask' doesn't exist
2461 * on the file system and so we need to look
2462 * for a possible mangle. This patch from
2463 * Tine Smukavec <valentin.smukavec@hermes.si>.
2466 if (!VALID_STAT(sbuf
) && mangle_is_mangled(mask
,conn
->params
)) {
2467 char *new_mask
= NULL
;
2468 mangle_lookup_name_from_8_3(ctx
,
2478 directory
= talloc_asprintf(ctx
,
2483 return NT_STATUS_NO_MEMORY
;
2486 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2489 status
= check_name(conn
, directory
);
2490 if (!NT_STATUS_IS_OK(status
)) {
2494 status
= do_unlink(conn
, req
, directory
, dirtype
);
2495 if (!NT_STATUS_IS_OK(status
)) {
2501 struct smb_Dir
*dir_hnd
= NULL
;
2505 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == aDIR
) {
2506 return NT_STATUS_OBJECT_NAME_INVALID
;
2509 if (strequal(mask
,"????????.???")) {
2514 status
= check_name(conn
, directory
);
2515 if (!NT_STATUS_IS_OK(status
)) {
2519 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
,
2521 if (dir_hnd
== NULL
) {
2522 return map_nt_error_from_unix(errno
);
2525 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2526 the pattern matches against the long name, otherwise the short name
2527 We don't implement this yet XXXX
2530 status
= NT_STATUS_NO_SUCH_FILE
;
2532 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
2536 if (!is_visible_file(conn
, directory
, dname
, &st
, True
)) {
2540 /* Quick check for "." and ".." */
2541 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2545 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
2549 fname
= talloc_asprintf(ctx
, "%s/%s",
2553 return NT_STATUS_NO_MEMORY
;
2556 status
= check_name(conn
, fname
);
2557 if (!NT_STATUS_IS_OK(status
)) {
2558 TALLOC_FREE(dir_hnd
);
2562 status
= do_unlink(conn
, req
, fname
, dirtype
);
2563 if (!NT_STATUS_IS_OK(status
)) {
2569 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2574 TALLOC_FREE(dir_hnd
);
2577 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2578 status
= map_nt_error_from_unix(errno
);
2584 /****************************************************************************
2586 ****************************************************************************/
2588 void reply_unlink(struct smb_request
*req
)
2590 connection_struct
*conn
= req
->conn
;
2594 bool path_contains_wcard
= False
;
2595 TALLOC_CTX
*ctx
= talloc_tos();
2597 START_PROFILE(SMBunlink
);
2600 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2601 END_PROFILE(SMBunlink
);
2605 dirtype
= SVAL(req
->inbuf
,smb_vwv0
);
2607 srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &name
,
2608 smb_buf(req
->inbuf
) + 1, 0,
2609 STR_TERMINATE
, &status
, &path_contains_wcard
);
2610 if (!NT_STATUS_IS_OK(status
)) {
2611 reply_nterror(req
, status
);
2612 END_PROFILE(SMBunlink
);
2616 status
= resolve_dfspath_wcard(ctx
, conn
,
2617 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2620 &path_contains_wcard
);
2621 if (!NT_STATUS_IS_OK(status
)) {
2622 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2623 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2624 ERRSRV
, ERRbadpath
);
2625 END_PROFILE(SMBunlink
);
2628 reply_nterror(req
, status
);
2629 END_PROFILE(SMBunlink
);
2633 DEBUG(3,("reply_unlink : %s\n",name
));
2635 status
= unlink_internals(conn
, req
, dirtype
, name
,
2636 path_contains_wcard
);
2637 if (!NT_STATUS_IS_OK(status
)) {
2638 if (open_was_deferred(req
->mid
)) {
2639 /* We have re-scheduled this call. */
2640 END_PROFILE(SMBunlink
);
2643 reply_nterror(req
, status
);
2644 END_PROFILE(SMBunlink
);
2648 reply_outbuf(req
, 0, 0);
2649 END_PROFILE(SMBunlink
);
2654 /****************************************************************************
2656 ****************************************************************************/
2658 static void fail_readraw(void)
2660 const char *errstr
= talloc_asprintf(talloc_tos(),
2661 "FAIL ! reply_readbraw: socket write fail (%s)",
2666 exit_server_cleanly(errstr
);
2669 /****************************************************************************
2670 Fake (read/write) sendfile. Returns -1 on read or write fail.
2671 ****************************************************************************/
2673 static ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
,
2677 size_t tosend
= nread
;
2684 bufsize
= MIN(nread
, 65536);
2686 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2690 while (tosend
> 0) {
2694 if (tosend
> bufsize
) {
2699 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2705 /* If we had a short read, fill with zeros. */
2706 if (ret
< cur_read
) {
2707 memset(buf
, '\0', cur_read
- ret
);
2710 if (write_data(smbd_server_fd(),buf
,cur_read
) != cur_read
) {
2715 startpos
+= cur_read
;
2719 return (ssize_t
)nread
;
2722 /****************************************************************************
2723 Return a readbraw error (4 bytes of zero).
2724 ****************************************************************************/
2726 static void reply_readbraw_error(void)
2730 if (write_data(smbd_server_fd(),header
,4) != 4) {
2735 /****************************************************************************
2736 Use sendfile in readbraw.
2737 ****************************************************************************/
2739 void send_file_readbraw(connection_struct
*conn
,
2745 char *outbuf
= NULL
;
2748 #if defined(WITH_SENDFILE)
2750 * We can only use sendfile on a non-chained packet
2751 * but we can use on a non-oplocked file. tridge proved this
2752 * on a train in Germany :-). JRA.
2753 * reply_readbraw has already checked the length.
2756 if ( (chain_size
== 0) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
2757 (fsp
->wcp
== NULL
) && lp_use_sendfile(SNUM(conn
)) ) {
2759 DATA_BLOB header_blob
;
2761 _smb_setlen(header
,nread
);
2762 header_blob
= data_blob_const(header
, 4);
2764 if (SMB_VFS_SENDFILE(smbd_server_fd(), fsp
,
2765 &header_blob
, startpos
, nread
) == -1) {
2766 /* Returning ENOSYS means no data at all was sent.
2767 * Do this as a normal read. */
2768 if (errno
== ENOSYS
) {
2769 goto normal_readbraw
;
2773 * Special hack for broken Linux with no working sendfile. If we
2774 * return EINTR we sent the header but not the rest of the data.
2775 * Fake this up by doing read/write calls.
2777 if (errno
== EINTR
) {
2778 /* Ensure we don't do this again. */
2779 set_use_sendfile(SNUM(conn
), False
);
2780 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2782 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
2783 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2784 fsp
->fsp_name
, strerror(errno
) ));
2785 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2790 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2791 fsp
->fsp_name
, strerror(errno
) ));
2792 exit_server_cleanly("send_file_readbraw sendfile failed");
2801 outbuf
= TALLOC_ARRAY(NULL
, char, nread
+4);
2803 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2804 (unsigned)(nread
+4)));
2805 reply_readbraw_error();
2810 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2811 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2820 _smb_setlen(outbuf
,ret
);
2821 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
2824 TALLOC_FREE(outbuf
);
2827 /****************************************************************************
2828 Reply to a readbraw (core+ protocol).
2829 ****************************************************************************/
2831 void reply_readbraw(struct smb_request
*req
)
2833 connection_struct
*conn
= req
->conn
;
2834 ssize_t maxcount
,mincount
;
2841 START_PROFILE(SMBreadbraw
);
2843 if (srv_is_signing_active() || is_encrypted_packet(req
->inbuf
)) {
2844 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2845 "raw reads/writes are disallowed.");
2849 reply_readbraw_error();
2850 END_PROFILE(SMBreadbraw
);
2855 * Special check if an oplock break has been issued
2856 * and the readraw request croses on the wire, we must
2857 * return a zero length response here.
2860 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
2863 * We have to do a check_fsp by hand here, as
2864 * we must always return 4 zero bytes on error,
2868 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
2869 req
->vuid
!= fsp
->vuid
||
2870 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
2872 * fsp could be NULL here so use the value from the packet. JRA.
2874 DEBUG(3,("reply_readbraw: fnum %d not valid "
2876 (int)SVAL(req
->inbuf
,smb_vwv0
)));
2877 reply_readbraw_error();
2878 END_PROFILE(SMBreadbraw
);
2882 /* Do a "by hand" version of CHECK_READ. */
2883 if (!(fsp
->can_read
||
2884 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
2885 (fsp
->access_mask
& FILE_EXECUTE
)))) {
2886 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2887 (int)SVAL(req
->inbuf
,smb_vwv0
)));
2888 reply_readbraw_error();
2889 END_PROFILE(SMBreadbraw
);
2893 flush_write_cache(fsp
, READRAW_FLUSH
);
2895 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv1
);
2896 if(req
->wct
== 10) {
2898 * This is a large offset (64 bit) read.
2900 #ifdef LARGE_SMB_OFF_T
2902 startpos
|= (((SMB_OFF_T
)IVAL(req
->inbuf
,smb_vwv8
)) << 32);
2904 #else /* !LARGE_SMB_OFF_T */
2907 * Ensure we haven't been sent a >32 bit offset.
2910 if(IVAL(req
->inbuf
,smb_vwv8
) != 0) {
2911 DEBUG(0,("reply_readbraw: large offset "
2912 "(%x << 32) used and we don't support "
2913 "64 bit offsets.\n",
2914 (unsigned int)IVAL(req
->inbuf
,smb_vwv8
) ));
2915 reply_readbraw_error();
2916 END_PROFILE(SMBreadbraw
);
2920 #endif /* LARGE_SMB_OFF_T */
2923 DEBUG(0,("reply_readbraw: negative 64 bit "
2924 "readraw offset (%.0f) !\n",
2925 (double)startpos
));
2926 reply_readbraw_error();
2927 END_PROFILE(SMBreadbraw
);
2932 maxcount
= (SVAL(req
->inbuf
,smb_vwv3
) & 0xFFFF);
2933 mincount
= (SVAL(req
->inbuf
,smb_vwv4
) & 0xFFFF);
2935 /* ensure we don't overrun the packet size */
2936 maxcount
= MIN(65535,maxcount
);
2938 if (is_locked(fsp
,(uint32
)req
->smbpid
,
2939 (SMB_BIG_UINT
)maxcount
,
2940 (SMB_BIG_UINT
)startpos
,
2942 reply_readbraw_error();
2943 END_PROFILE(SMBreadbraw
);
2947 if (SMB_VFS_FSTAT(fsp
, &st
) == 0) {
2951 if (startpos
>= size
) {
2954 nread
= MIN(maxcount
,(size
- startpos
));
2957 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2958 if (nread
< mincount
)
2962 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2963 "min=%lu nread=%lu\n",
2964 fsp
->fnum
, (double)startpos
,
2965 (unsigned long)maxcount
,
2966 (unsigned long)mincount
,
2967 (unsigned long)nread
) );
2969 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
);
2971 DEBUG(5,("reply_readbraw finished\n"));
2972 END_PROFILE(SMBreadbraw
);
2976 #define DBGC_CLASS DBGC_LOCKING
2978 /****************************************************************************
2979 Reply to a lockread (core+ protocol).
2980 ****************************************************************************/
2982 void reply_lockread(struct smb_request
*req
)
2984 connection_struct
*conn
= req
->conn
;
2991 struct byte_range_lock
*br_lck
= NULL
;
2994 START_PROFILE(SMBlockread
);
2997 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2998 END_PROFILE(SMBlockread
);
3002 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3004 if (!check_fsp(conn
, req
, fsp
)) {
3005 END_PROFILE(SMBlockread
);
3009 if (!CHECK_READ(fsp
,req
->inbuf
)) {
3010 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3011 END_PROFILE(SMBlockread
);
3015 release_level_2_oplocks_on_change(fsp
);
3017 numtoread
= SVAL(req
->inbuf
,smb_vwv1
);
3018 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
3020 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3022 reply_outbuf(req
, 5, numtoread
+ 3);
3024 data
= smb_buf(req
->outbuf
) + 3;
3027 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3028 * protocol request that predates the read/write lock concept.
3029 * Thus instead of asking for a read lock here we need to ask
3030 * for a write lock. JRA.
3031 * Note that the requested lock size is unaffected by max_recv.
3034 br_lck
= do_lock(smbd_messaging_context(),
3037 (SMB_BIG_UINT
)numtoread
,
3038 (SMB_BIG_UINT
)startpos
,
3041 False
, /* Non-blocking lock. */
3044 TALLOC_FREE(br_lck
);
3046 if (NT_STATUS_V(status
)) {
3047 reply_nterror(req
, status
);
3048 END_PROFILE(SMBlockread
);
3053 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3056 if (numtoread
> max_recv
) {
3057 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3058 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3059 (unsigned int)numtoread
, (unsigned int)max_recv
));
3060 numtoread
= MIN(numtoread
,max_recv
);
3062 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3065 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3066 END_PROFILE(SMBlockread
);
3070 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3072 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3073 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3074 p
= smb_buf(req
->outbuf
);
3075 SCVAL(p
,0,0); /* pad byte. */
3078 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3079 fsp
->fnum
, (int)numtoread
, (int)nread
));
3081 END_PROFILE(SMBlockread
);
3086 #define DBGC_CLASS DBGC_ALL
3088 /****************************************************************************
3090 ****************************************************************************/
3092 void reply_read(struct smb_request
*req
)
3094 connection_struct
*conn
= req
->conn
;
3102 START_PROFILE(SMBread
);
3105 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3106 END_PROFILE(SMBread
);
3110 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3112 if (!check_fsp(conn
, req
, fsp
)) {
3113 END_PROFILE(SMBread
);
3117 if (!CHECK_READ(fsp
,req
->inbuf
)) {
3118 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3119 END_PROFILE(SMBread
);
3123 numtoread
= SVAL(req
->inbuf
,smb_vwv1
);
3124 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
3126 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3129 * The requested read size cannot be greater than max_recv. JRA.
3131 if (numtoread
> max_recv
) {
3132 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3133 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3134 (unsigned int)numtoread
, (unsigned int)max_recv
));
3135 numtoread
= MIN(numtoread
,max_recv
);
3138 reply_outbuf(req
, 5, numtoread
+3);
3140 data
= smb_buf(req
->outbuf
) + 3;
3142 if (is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtoread
,
3143 (SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
3144 reply_doserror(req
, ERRDOS
,ERRlock
);
3145 END_PROFILE(SMBread
);
3150 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3153 reply_unixerror(req
, ERRDOS
,ERRnoaccess
);
3154 END_PROFILE(SMBread
);
3158 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3160 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3161 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3162 SCVAL(smb_buf(req
->outbuf
),0,1);
3163 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3165 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3166 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3168 END_PROFILE(SMBread
);
3172 /****************************************************************************
3174 ****************************************************************************/
3176 static int setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3181 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3182 data
= smb_buf(outbuf
);
3184 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3186 SCVAL(outbuf
,smb_vwv0
,0xFF);
3187 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3188 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3189 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
3190 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3191 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
3192 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3193 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3197 /****************************************************************************
3198 Reply to a read and X - possibly using sendfile.
3199 ****************************************************************************/
3201 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3202 files_struct
*fsp
, SMB_OFF_T startpos
,
3205 SMB_STRUCT_STAT sbuf
;
3208 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
3209 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3213 if (startpos
> sbuf
.st_size
) {
3215 } else if (smb_maxcnt
> (sbuf
.st_size
- startpos
)) {
3216 smb_maxcnt
= (sbuf
.st_size
- startpos
);
3219 if (smb_maxcnt
== 0) {
3223 #if defined(WITH_SENDFILE)
3225 * We can only use sendfile on a non-chained packet
3226 * but we can use on a non-oplocked file. tridge proved this
3227 * on a train in Germany :-). JRA.
3230 if ((chain_size
== 0) && (CVAL(req
->inbuf
,smb_vwv0
) == 0xFF) &&
3231 !is_encrypted_packet(req
->inbuf
) && (fsp
->base_fsp
== NULL
) &&
3232 lp_use_sendfile(SNUM(conn
)) && (fsp
->wcp
== NULL
) ) {
3233 uint8 headerbuf
[smb_size
+ 12 * 2];
3237 * Set up the packet header before send. We
3238 * assume here the sendfile will work (get the
3239 * correct amount of data).
3242 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3244 construct_reply_common((char *)req
->inbuf
, (char *)headerbuf
);
3245 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3247 if ((nread
= SMB_VFS_SENDFILE(smbd_server_fd(), fsp
, &header
, startpos
, smb_maxcnt
)) == -1) {
3248 /* Returning ENOSYS means no data at all was sent.
3249 Do this as a normal read. */
3250 if (errno
== ENOSYS
) {
3255 * Special hack for broken Linux with no working sendfile. If we
3256 * return EINTR we sent the header but not the rest of the data.
3257 * Fake this up by doing read/write calls.
3260 if (errno
== EINTR
) {
3261 /* Ensure we don't do this again. */
3262 set_use_sendfile(SNUM(conn
), False
);
3263 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3264 nread
= fake_sendfile(fsp
, startpos
,
3267 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3268 fsp
->fsp_name
, strerror(errno
) ));
3269 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3271 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3272 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3273 /* No outbuf here means successful sendfile. */
3274 TALLOC_FREE(req
->outbuf
);
3278 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3279 fsp
->fsp_name
, strerror(errno
) ));
3280 exit_server_cleanly("send_file_readX sendfile failed");
3283 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3284 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3285 /* No outbuf here means successful sendfile. */
3286 TALLOC_FREE(req
->outbuf
);
3293 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3294 uint8 headerbuf
[smb_size
+ 2*12];
3296 construct_reply_common((char *)req
->inbuf
, (char *)headerbuf
);
3297 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3299 /* Send out the header. */
3300 if (write_data(smbd_server_fd(), (char *)headerbuf
,
3301 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3302 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3303 fsp
->fsp_name
, strerror(errno
) ));
3304 exit_server_cleanly("send_file_readX sendfile failed");
3306 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3308 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3309 fsp
->fsp_name
, strerror(errno
) ));
3310 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3312 TALLOC_FREE(req
->outbuf
);
3315 reply_outbuf(req
, 12, smb_maxcnt
);
3317 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
,
3320 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3324 setup_readX_header((char *)req
->outbuf
, nread
);
3326 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3327 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3335 /****************************************************************************
3336 Reply to a read and X.
3337 ****************************************************************************/
3339 void reply_read_and_X(struct smb_request
*req
)
3341 connection_struct
*conn
= req
->conn
;
3345 bool big_readX
= False
;
3347 size_t smb_mincnt
= SVAL(req
->inbuf
,smb_vwv6
);
3350 START_PROFILE(SMBreadX
);
3352 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3353 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3357 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv2
));
3358 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv3
);
3359 smb_maxcnt
= SVAL(req
->inbuf
,smb_vwv5
);
3361 /* If it's an IPC, pass off the pipe handler. */
3363 reply_pipe_read_and_X(req
);
3364 END_PROFILE(SMBreadX
);
3368 if (!check_fsp(conn
, req
, fsp
)) {
3369 END_PROFILE(SMBreadX
);
3373 if (!CHECK_READ(fsp
,req
->inbuf
)) {
3374 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3375 END_PROFILE(SMBreadX
);
3379 if (global_client_caps
& CAP_LARGE_READX
) {
3380 size_t upper_size
= SVAL(req
->inbuf
,smb_vwv7
);
3381 smb_maxcnt
|= (upper_size
<<16);
3382 if (upper_size
> 1) {
3383 /* Can't do this on a chained packet. */
3384 if ((CVAL(req
->inbuf
,smb_vwv0
) != 0xFF)) {
3385 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3386 END_PROFILE(SMBreadX
);
3389 /* We currently don't do this on signed or sealed data. */
3390 if (srv_is_signing_active() || is_encrypted_packet(req
->inbuf
)) {
3391 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3392 END_PROFILE(SMBreadX
);
3395 /* Is there room in the reply for this data ? */
3396 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3398 NT_STATUS_INVALID_PARAMETER
);
3399 END_PROFILE(SMBreadX
);
3406 if (req
->wct
== 12) {
3407 #ifdef LARGE_SMB_OFF_T
3409 * This is a large offset (64 bit) read.
3411 startpos
|= (((SMB_OFF_T
)IVAL(req
->inbuf
,smb_vwv10
)) << 32);
3413 #else /* !LARGE_SMB_OFF_T */
3416 * Ensure we haven't been sent a >32 bit offset.
3419 if(IVAL(req
->inbuf
,smb_vwv10
) != 0) {
3420 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3421 "used and we don't support 64 bit offsets.\n",
3422 (unsigned int)IVAL(req
->inbuf
,smb_vwv10
) ));
3423 END_PROFILE(SMBreadX
);
3424 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3428 #endif /* LARGE_SMB_OFF_T */
3432 if (is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)smb_maxcnt
,
3433 (SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
3434 END_PROFILE(SMBreadX
);
3435 reply_doserror(req
, ERRDOS
, ERRlock
);
3440 schedule_aio_read_and_X(conn
, req
, fsp
, startpos
, smb_maxcnt
)) {
3441 END_PROFILE(SMBreadX
);
3445 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3447 END_PROFILE(SMBreadX
);
3451 /****************************************************************************
3452 Error replies to writebraw must have smb_wct == 1. Fix this up.
3453 ****************************************************************************/
3455 void error_to_writebrawerr(struct smb_request
*req
)
3457 uint8
*old_outbuf
= req
->outbuf
;
3459 reply_outbuf(req
, 1, 0);
3461 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3462 TALLOC_FREE(old_outbuf
);
3465 /****************************************************************************
3466 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3467 ****************************************************************************/
3469 void reply_writebraw(struct smb_request
*req
)
3471 connection_struct
*conn
= req
->conn
;
3474 ssize_t total_written
=0;
3475 size_t numtowrite
=0;
3483 START_PROFILE(SMBwritebraw
);
3486 * If we ever reply with an error, it must have the SMB command
3487 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3490 SCVAL(req
->inbuf
,smb_com
,SMBwritec
);
3492 if (srv_is_signing_active()) {
3493 END_PROFILE(SMBwritebraw
);
3494 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3495 "raw reads/writes are disallowed.");
3498 if (req
->wct
< 12) {
3499 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3500 error_to_writebrawerr(req
);
3501 END_PROFILE(SMBwritebraw
);
3505 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3506 if (!check_fsp(conn
, req
, fsp
)) {
3507 error_to_writebrawerr(req
);
3508 END_PROFILE(SMBwritebraw
);
3512 if (!CHECK_WRITE(fsp
)) {
3513 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3514 error_to_writebrawerr(req
);
3515 END_PROFILE(SMBwritebraw
);
3519 tcount
= IVAL(req
->inbuf
,smb_vwv1
);
3520 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv3
);
3521 write_through
= BITSETW(req
->inbuf
+smb_vwv7
,0);
3523 /* We have to deal with slightly different formats depending
3524 on whether we are using the core+ or lanman1.0 protocol */
3526 if(Protocol
<= PROTOCOL_COREPLUS
) {
3527 numtowrite
= SVAL(smb_buf(req
->inbuf
),-2);
3528 data
= smb_buf(req
->inbuf
);
3530 numtowrite
= SVAL(req
->inbuf
,smb_vwv10
);
3531 data
= smb_base(req
->inbuf
) + SVAL(req
->inbuf
, smb_vwv11
);
3534 /* Ensure we don't write bytes past the end of this packet. */
3535 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3536 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3537 error_to_writebrawerr(req
);
3538 END_PROFILE(SMBwritebraw
);
3542 if (is_locked(fsp
,(uint32
)req
->smbpid
,(SMB_BIG_UINT
)tcount
,
3543 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3544 reply_doserror(req
, ERRDOS
, ERRlock
);
3545 error_to_writebrawerr(req
);
3546 END_PROFILE(SMBwritebraw
);
3551 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3554 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3555 "wrote=%d sync=%d\n",
3556 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3557 (int)nwritten
, (int)write_through
));
3559 if (nwritten
< (ssize_t
)numtowrite
) {
3560 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3561 error_to_writebrawerr(req
);
3562 END_PROFILE(SMBwritebraw
);
3566 total_written
= nwritten
;
3568 /* Allocate a buffer of 64k + length. */
3569 buf
= TALLOC_ARRAY(NULL
, char, 65540);
3571 reply_doserror(req
, ERRDOS
, ERRnomem
);
3572 error_to_writebrawerr(req
);
3573 END_PROFILE(SMBwritebraw
);
3577 /* Return a SMBwritebraw message to the redirector to tell
3578 * it to send more bytes */
3580 memcpy(buf
, req
->inbuf
, smb_size
);
3581 srv_set_message(buf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
3582 SCVAL(buf
,smb_com
,SMBwritebraw
);
3583 SSVALS(buf
,smb_vwv0
,0xFFFF);
3585 if (!srv_send_smb(smbd_server_fd(),
3587 IS_CONN_ENCRYPTED(conn
))) {
3588 exit_server_cleanly("reply_writebraw: srv_send_smb "
3592 /* Now read the raw data into the buffer and write it */
3593 status
= read_smb_length(smbd_server_fd(), buf
, SMB_SECONDARY_WAIT
,
3595 if (!NT_STATUS_IS_OK(status
)) {
3596 exit_server_cleanly("secondary writebraw failed");
3599 /* Set up outbuf to return the correct size */
3600 reply_outbuf(req
, 1, 0);
3602 if (numtowrite
!= 0) {
3604 if (numtowrite
> 0xFFFF) {
3605 DEBUG(0,("reply_writebraw: Oversize secondary write "
3606 "raw requested (%u). Terminating\n",
3607 (unsigned int)numtowrite
));
3608 exit_server_cleanly("secondary writebraw failed");
3611 if (tcount
> nwritten
+numtowrite
) {
3612 DEBUG(3,("reply_writebraw: Client overestimated the "
3614 (int)tcount
,(int)nwritten
,(int)numtowrite
));
3617 status
= read_data(smbd_server_fd(), buf
+4, numtowrite
);
3619 if (!NT_STATUS_IS_OK(status
)) {
3620 DEBUG(0,("reply_writebraw: Oversize secondary write "
3621 "raw read failed (%s). Terminating\n",
3622 nt_errstr(status
)));
3623 exit_server_cleanly("secondary writebraw failed");
3626 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
3627 if (nwritten
== -1) {
3629 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3630 error_to_writebrawerr(req
);
3631 END_PROFILE(SMBwritebraw
);
3635 if (nwritten
< (ssize_t
)numtowrite
) {
3636 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
3637 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
3641 total_written
+= nwritten
;
3646 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
3648 status
= sync_file(conn
, fsp
, write_through
);
3649 if (!NT_STATUS_IS_OK(status
)) {
3650 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3651 fsp
->fsp_name
, nt_errstr(status
) ));
3652 reply_nterror(req
, status
);
3653 error_to_writebrawerr(req
);
3654 END_PROFILE(SMBwritebraw
);
3658 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3660 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3661 (int)total_written
));
3663 /* We won't return a status if write through is not selected - this
3664 * follows what WfWg does */
3665 END_PROFILE(SMBwritebraw
);
3667 if (!write_through
&& total_written
==tcount
) {
3669 #if RABBIT_PELLET_FIX
3671 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3672 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3675 if (!send_keepalive(smbd_server_fd())) {
3676 exit_server_cleanly("reply_writebraw: send of "
3677 "keepalive failed");
3680 TALLOC_FREE(req
->outbuf
);
3686 #define DBGC_CLASS DBGC_LOCKING
3688 /****************************************************************************
3689 Reply to a writeunlock (core+).
3690 ****************************************************************************/
3692 void reply_writeunlock(struct smb_request
*req
)
3694 connection_struct
*conn
= req
->conn
;
3695 ssize_t nwritten
= -1;
3699 NTSTATUS status
= NT_STATUS_OK
;
3702 START_PROFILE(SMBwriteunlock
);
3705 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3706 END_PROFILE(SMBwriteunlock
);
3710 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3712 if (!check_fsp(conn
, req
, fsp
)) {
3713 END_PROFILE(SMBwriteunlock
);
3717 if (!CHECK_WRITE(fsp
)) {
3718 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3719 END_PROFILE(SMBwriteunlock
);
3723 numtowrite
= SVAL(req
->inbuf
,smb_vwv1
);
3724 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
3725 data
= smb_buf(req
->inbuf
) + 3;
3728 && is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtowrite
,
3729 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3730 reply_doserror(req
, ERRDOS
, ERRlock
);
3731 END_PROFILE(SMBwriteunlock
);
3735 /* The special X/Open SMB protocol handling of
3736 zero length writes is *NOT* done for
3738 if(numtowrite
== 0) {
3741 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3744 status
= sync_file(conn
, fsp
, False
/* write through */);
3745 if (!NT_STATUS_IS_OK(status
)) {
3746 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3747 fsp
->fsp_name
, nt_errstr(status
) ));
3748 reply_nterror(req
, status
);
3749 END_PROFILE(SMBwriteunlock
);
3753 if(((nwritten
< numtowrite
) && (numtowrite
!= 0))||(nwritten
< 0)) {
3754 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3755 END_PROFILE(SMBwriteunlock
);
3760 status
= do_unlock(smbd_messaging_context(),
3763 (SMB_BIG_UINT
)numtowrite
,
3764 (SMB_BIG_UINT
)startpos
,
3767 if (NT_STATUS_V(status
)) {
3768 reply_nterror(req
, status
);
3769 END_PROFILE(SMBwriteunlock
);
3774 reply_outbuf(req
, 1, 0);
3776 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
3778 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3779 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
3781 END_PROFILE(SMBwriteunlock
);
3786 #define DBGC_CLASS DBGC_ALL
3788 /****************************************************************************
3790 ****************************************************************************/
3792 void reply_write(struct smb_request
*req
)
3794 connection_struct
*conn
= req
->conn
;
3796 ssize_t nwritten
= -1;
3802 START_PROFILE(SMBwrite
);
3805 END_PROFILE(SMBwrite
);
3806 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3810 /* If it's an IPC, pass off the pipe handler. */
3812 reply_pipe_write(req
);
3813 END_PROFILE(SMBwrite
);
3817 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3819 if (!check_fsp(conn
, req
, fsp
)) {
3820 END_PROFILE(SMBwrite
);
3824 if (!CHECK_WRITE(fsp
)) {
3825 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3826 END_PROFILE(SMBwrite
);
3830 numtowrite
= SVAL(req
->inbuf
,smb_vwv1
);
3831 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
3832 data
= smb_buf(req
->inbuf
) + 3;
3834 if (is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtowrite
,
3835 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3836 reply_doserror(req
, ERRDOS
, ERRlock
);
3837 END_PROFILE(SMBwrite
);
3842 * X/Open SMB protocol says that if smb_vwv1 is
3843 * zero then the file size should be extended or
3844 * truncated to the size given in smb_vwv[2-3].
3847 if(numtowrite
== 0) {
3849 * This is actually an allocate call, and set EOF. JRA.
3851 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
3853 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3854 END_PROFILE(SMBwrite
);
3857 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
3859 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3860 END_PROFILE(SMBwrite
);
3863 trigger_write_time_update_immediate(fsp
);
3865 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3868 status
= sync_file(conn
, fsp
, False
);
3869 if (!NT_STATUS_IS_OK(status
)) {
3870 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3871 fsp
->fsp_name
, nt_errstr(status
) ));
3872 reply_nterror(req
, status
);
3873 END_PROFILE(SMBwrite
);
3877 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
3878 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3879 END_PROFILE(SMBwrite
);
3883 reply_outbuf(req
, 1, 0);
3885 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
3887 if (nwritten
< (ssize_t
)numtowrite
) {
3888 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
3889 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
3892 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
3894 END_PROFILE(SMBwrite
);
3898 /****************************************************************************
3899 Ensure a buffer is a valid writeX for recvfile purposes.
3900 ****************************************************************************/
3902 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3903 (2*14) + /* word count (including bcc) */ \
3906 bool is_valid_writeX_buffer(const uint8_t *inbuf
)
3909 connection_struct
*conn
= NULL
;
3910 unsigned int doff
= 0;
3911 size_t len
= smb_len_large(inbuf
);
3913 if (is_encrypted_packet(inbuf
)) {
3914 /* Can't do this on encrypted
3919 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
3923 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
3924 CVAL(inbuf
,smb_wct
) != 14) {
3925 DEBUG(10,("is_valid_writeX_buffer: chained or "
3926 "invalid word length.\n"));
3930 conn
= conn_find(SVAL(inbuf
, smb_tid
));
3932 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3936 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3939 if (IS_PRINT(conn
)) {
3940 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
3943 doff
= SVAL(inbuf
,smb_vwv11
);
3945 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3947 if (len
> doff
&& len
- doff
> 0xFFFF) {
3948 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
3951 if (numtowrite
== 0) {
3952 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3956 /* Ensure the sizes match up. */
3957 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
3958 /* no pad byte...old smbclient :-( */
3959 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3961 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
3965 if (len
- doff
!= numtowrite
) {
3966 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3967 "len = %u, doff = %u, numtowrite = %u\n",
3970 (unsigned int)numtowrite
));
3974 DEBUG(10,("is_valid_writeX_buffer: true "
3975 "len = %u, doff = %u, numtowrite = %u\n",
3978 (unsigned int)numtowrite
));
3983 /****************************************************************************
3984 Reply to a write and X.
3985 ****************************************************************************/
3987 void reply_write_and_X(struct smb_request
*req
)
3989 connection_struct
*conn
= req
->conn
;
3995 unsigned int smb_doff
;
3996 unsigned int smblen
;
4000 START_PROFILE(SMBwriteX
);
4002 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4003 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4004 END_PROFILE(SMBwriteX
);
4008 numtowrite
= SVAL(req
->inbuf
,smb_vwv10
);
4009 smb_doff
= SVAL(req
->inbuf
,smb_vwv11
);
4010 smblen
= smb_len(req
->inbuf
);
4012 if (req
->unread_bytes
> 0xFFFF ||
4013 (smblen
> smb_doff
&&
4014 smblen
- smb_doff
> 0xFFFF)) {
4015 numtowrite
|= (((size_t)SVAL(req
->inbuf
,smb_vwv9
))<<16);
4018 if (req
->unread_bytes
) {
4019 /* Can't do a recvfile write on IPC$ */
4021 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4022 END_PROFILE(SMBwriteX
);
4025 if (numtowrite
!= req
->unread_bytes
) {
4026 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4027 END_PROFILE(SMBwriteX
);
4031 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4032 smb_doff
+ numtowrite
> smblen
) {
4033 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4034 END_PROFILE(SMBwriteX
);
4039 /* If it's an IPC, pass off the pipe handler. */
4041 if (req
->unread_bytes
) {
4042 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4043 END_PROFILE(SMBwriteX
);
4046 reply_pipe_write_and_X(req
);
4047 END_PROFILE(SMBwriteX
);
4051 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv2
));
4052 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv3
);
4053 write_through
= BITSETW(req
->inbuf
+smb_vwv7
,0);
4055 if (!check_fsp(conn
, req
, fsp
)) {
4056 END_PROFILE(SMBwriteX
);
4060 if (!CHECK_WRITE(fsp
)) {
4061 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4062 END_PROFILE(SMBwriteX
);
4066 data
= smb_base(req
->inbuf
) + smb_doff
;
4068 if(req
->wct
== 14) {
4069 #ifdef LARGE_SMB_OFF_T
4071 * This is a large offset (64 bit) write.
4073 startpos
|= (((SMB_OFF_T
)IVAL(req
->inbuf
,smb_vwv12
)) << 32);
4075 #else /* !LARGE_SMB_OFF_T */
4078 * Ensure we haven't been sent a >32 bit offset.
4081 if(IVAL(req
->inbuf
,smb_vwv12
) != 0) {
4082 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4083 "used and we don't support 64 bit offsets.\n",
4084 (unsigned int)IVAL(req
->inbuf
,smb_vwv12
) ));
4085 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4086 END_PROFILE(SMBwriteX
);
4090 #endif /* LARGE_SMB_OFF_T */
4093 if (is_locked(fsp
,(uint32
)req
->smbpid
,
4094 (SMB_BIG_UINT
)numtowrite
,
4095 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
4096 reply_doserror(req
, ERRDOS
, ERRlock
);
4097 END_PROFILE(SMBwriteX
);
4101 /* X/Open SMB protocol says that, unlike SMBwrite
4102 if the length is zero then NO truncation is
4103 done, just a write of zero. To truncate a file,
4106 if(numtowrite
== 0) {
4110 if ((req
->unread_bytes
== 0) &&
4111 schedule_aio_write_and_X(conn
, req
, fsp
, data
, startpos
,
4113 END_PROFILE(SMBwriteX
);
4117 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4120 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4121 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
4122 END_PROFILE(SMBwriteX
);
4126 reply_outbuf(req
, 6, 0);
4127 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4128 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4130 if (nwritten
< (ssize_t
)numtowrite
) {
4131 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4132 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4135 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4136 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4138 status
= sync_file(conn
, fsp
, write_through
);
4139 if (!NT_STATUS_IS_OK(status
)) {
4140 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4141 fsp
->fsp_name
, nt_errstr(status
) ));
4142 reply_nterror(req
, status
);
4143 END_PROFILE(SMBwriteX
);
4147 END_PROFILE(SMBwriteX
);
4152 /****************************************************************************
4154 ****************************************************************************/
4156 void reply_lseek(struct smb_request
*req
)
4158 connection_struct
*conn
= req
->conn
;
4164 START_PROFILE(SMBlseek
);
4167 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4168 END_PROFILE(SMBlseek
);
4172 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4174 if (!check_fsp(conn
, req
, fsp
)) {
4178 flush_write_cache(fsp
, SEEK_FLUSH
);
4180 mode
= SVAL(req
->inbuf
,smb_vwv1
) & 3;
4181 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4182 startpos
= (SMB_OFF_T
)IVALS(req
->inbuf
,smb_vwv2
);
4191 res
= fsp
->fh
->pos
+ startpos
;
4202 if (umode
== SEEK_END
) {
4203 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4204 if(errno
== EINVAL
) {
4205 SMB_OFF_T current_pos
= startpos
;
4206 SMB_STRUCT_STAT sbuf
;
4208 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
4209 reply_unixerror(req
, ERRDOS
,
4211 END_PROFILE(SMBlseek
);
4215 current_pos
+= sbuf
.st_size
;
4217 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4222 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
4223 END_PROFILE(SMBlseek
);
4230 reply_outbuf(req
, 2, 0);
4231 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4233 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4234 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4236 END_PROFILE(SMBlseek
);
4240 /****************************************************************************
4242 ****************************************************************************/
4244 void reply_flush(struct smb_request
*req
)
4246 connection_struct
*conn
= req
->conn
;
4250 START_PROFILE(SMBflush
);
4253 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4257 fnum
= SVAL(req
->inbuf
,smb_vwv0
);
4258 fsp
= file_fsp(fnum
);
4260 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4265 file_sync_all(conn
);
4267 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4268 if (!NT_STATUS_IS_OK(status
)) {
4269 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4270 fsp
->fsp_name
, nt_errstr(status
) ));
4271 reply_nterror(req
, status
);
4272 END_PROFILE(SMBflush
);
4277 reply_outbuf(req
, 0, 0);
4279 DEBUG(3,("flush\n"));
4280 END_PROFILE(SMBflush
);
4284 /****************************************************************************
4286 conn POINTER CAN BE NULL HERE !
4287 ****************************************************************************/
4289 void reply_exit(struct smb_request
*req
)
4291 START_PROFILE(SMBexit
);
4293 file_close_pid(req
->smbpid
, req
->vuid
);
4295 reply_outbuf(req
, 0, 0);
4297 DEBUG(3,("exit\n"));
4299 END_PROFILE(SMBexit
);
4303 /****************************************************************************
4304 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4305 ****************************************************************************/
4307 void reply_close(struct smb_request
*req
)
4309 connection_struct
*conn
= req
->conn
;
4310 NTSTATUS status
= NT_STATUS_OK
;
4311 files_struct
*fsp
= NULL
;
4312 START_PROFILE(SMBclose
);
4315 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4316 END_PROFILE(SMBclose
);
4320 /* If it's an IPC, pass off to the pipe handler. */
4322 reply_pipe_close(conn
, req
);
4323 END_PROFILE(SMBclose
);
4327 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4330 * We can only use check_fsp if we know it's not a directory.
4333 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= req
->vuid
)) {
4334 reply_doserror(req
, ERRDOS
, ERRbadfid
);
4335 END_PROFILE(SMBclose
);
4339 if(fsp
->is_directory
) {
4341 * Special case - close NT SMB directory handle.
4343 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4344 status
= close_file(fsp
,NORMAL_CLOSE
);
4348 * Close ordinary file.
4351 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4352 fsp
->fh
->fd
, fsp
->fnum
,
4353 conn
->num_files_open
));
4356 * Take care of any time sent in the close.
4359 t
= srv_make_unix_date3(req
->inbuf
+smb_vwv1
);
4360 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4363 * close_file() returns the unix errno if an error
4364 * was detected on close - normally this is due to
4365 * a disk full error. If not then it was probably an I/O error.
4368 status
= close_file(fsp
,NORMAL_CLOSE
);
4371 if (!NT_STATUS_IS_OK(status
)) {
4372 reply_nterror(req
, status
);
4373 END_PROFILE(SMBclose
);
4377 reply_outbuf(req
, 0, 0);
4378 END_PROFILE(SMBclose
);
4382 /****************************************************************************
4383 Reply to a writeclose (Core+ protocol).
4384 ****************************************************************************/
4386 void reply_writeclose(struct smb_request
*req
)
4388 connection_struct
*conn
= req
->conn
;
4390 ssize_t nwritten
= -1;
4391 NTSTATUS close_status
= NT_STATUS_OK
;
4394 struct timespec mtime
;
4397 START_PROFILE(SMBwriteclose
);
4400 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4401 END_PROFILE(SMBwriteclose
);
4405 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4407 if (!check_fsp(conn
, req
, fsp
)) {
4408 END_PROFILE(SMBwriteclose
);
4411 if (!CHECK_WRITE(fsp
)) {
4412 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
4413 END_PROFILE(SMBwriteclose
);
4417 numtowrite
= SVAL(req
->inbuf
,smb_vwv1
);
4418 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
4419 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(
4420 req
->inbuf
+smb_vwv4
));
4421 data
= smb_buf(req
->inbuf
) + 1;
4424 && is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtowrite
,
4425 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
4426 reply_doserror(req
, ERRDOS
,ERRlock
);
4427 END_PROFILE(SMBwriteclose
);
4431 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4433 set_close_write_time(fsp
, mtime
);
4436 * More insanity. W2K only closes the file if writelen > 0.
4441 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4443 close_status
= close_file(fsp
,NORMAL_CLOSE
);
4446 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4447 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4448 conn
->num_files_open
));
4450 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4451 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4452 END_PROFILE(SMBwriteclose
);
4456 if(!NT_STATUS_IS_OK(close_status
)) {
4457 reply_nterror(req
, close_status
);
4458 END_PROFILE(SMBwriteclose
);
4462 reply_outbuf(req
, 1, 0);
4464 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4465 END_PROFILE(SMBwriteclose
);
4470 #define DBGC_CLASS DBGC_LOCKING
4472 /****************************************************************************
4474 ****************************************************************************/
4476 void reply_lock(struct smb_request
*req
)
4478 connection_struct
*conn
= req
->conn
;
4479 SMB_BIG_UINT count
,offset
;
4482 struct byte_range_lock
*br_lck
= NULL
;
4484 START_PROFILE(SMBlock
);
4487 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4488 END_PROFILE(SMBlock
);
4492 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4494 if (!check_fsp(conn
, req
, fsp
)) {
4495 END_PROFILE(SMBlock
);
4499 release_level_2_oplocks_on_change(fsp
);
4501 count
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv1
);
4502 offset
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv3
);
4504 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4505 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
4507 br_lck
= do_lock(smbd_messaging_context(),
4514 False
, /* Non-blocking lock. */
4518 TALLOC_FREE(br_lck
);
4520 if (NT_STATUS_V(status
)) {
4521 reply_nterror(req
, status
);
4522 END_PROFILE(SMBlock
);
4526 reply_outbuf(req
, 0, 0);
4528 END_PROFILE(SMBlock
);
4532 /****************************************************************************
4534 ****************************************************************************/
4536 void reply_unlock(struct smb_request
*req
)
4538 connection_struct
*conn
= req
->conn
;
4539 SMB_BIG_UINT count
,offset
;
4543 START_PROFILE(SMBunlock
);
4546 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4547 END_PROFILE(SMBunlock
);
4551 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4553 if (!check_fsp(conn
, req
, fsp
)) {
4554 END_PROFILE(SMBunlock
);
4558 count
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv1
);
4559 offset
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv3
);
4561 status
= do_unlock(smbd_messaging_context(),
4568 if (NT_STATUS_V(status
)) {
4569 reply_nterror(req
, status
);
4570 END_PROFILE(SMBunlock
);
4574 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4575 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
4577 reply_outbuf(req
, 0, 0);
4579 END_PROFILE(SMBunlock
);
4584 #define DBGC_CLASS DBGC_ALL
4586 /****************************************************************************
4588 conn POINTER CAN BE NULL HERE !
4589 ****************************************************************************/
4591 void reply_tdis(struct smb_request
*req
)
4593 connection_struct
*conn
= req
->conn
;
4594 START_PROFILE(SMBtdis
);
4597 DEBUG(4,("Invalid connection in tdis\n"));
4598 reply_doserror(req
, ERRSRV
, ERRinvnid
);
4599 END_PROFILE(SMBtdis
);
4605 close_cnum(conn
,req
->vuid
);
4608 reply_outbuf(req
, 0, 0);
4609 END_PROFILE(SMBtdis
);
4613 /****************************************************************************
4615 conn POINTER CAN BE NULL HERE !
4616 ****************************************************************************/
4618 void reply_echo(struct smb_request
*req
)
4620 connection_struct
*conn
= req
->conn
;
4623 unsigned int data_len
= smb_buflen(req
->inbuf
);
4625 START_PROFILE(SMBecho
);
4628 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4629 END_PROFILE(SMBecho
);
4633 if (data_len
> BUFFER_SIZE
) {
4634 DEBUG(0,("reply_echo: data_len too large.\n"));
4635 reply_nterror(req
, NT_STATUS_INSUFFICIENT_RESOURCES
);
4636 END_PROFILE(SMBecho
);
4640 smb_reverb
= SVAL(req
->inbuf
,smb_vwv0
);
4642 reply_outbuf(req
, 1, data_len
);
4644 /* copy any incoming data back out */
4646 memcpy(smb_buf(req
->outbuf
),smb_buf(req
->inbuf
),data_len
);
4649 if (smb_reverb
> 100) {
4650 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
4654 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
4655 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
4657 show_msg((char *)req
->outbuf
);
4658 if (!srv_send_smb(smbd_server_fd(),
4659 (char *)req
->outbuf
,
4660 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
))
4661 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4664 DEBUG(3,("echo %d times\n", smb_reverb
));
4666 TALLOC_FREE(req
->outbuf
);
4668 END_PROFILE(SMBecho
);
4672 /****************************************************************************
4673 Reply to a printopen.
4674 ****************************************************************************/
4676 void reply_printopen(struct smb_request
*req
)
4678 connection_struct
*conn
= req
->conn
;
4680 SMB_STRUCT_STAT sbuf
;
4683 START_PROFILE(SMBsplopen
);
4686 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4687 END_PROFILE(SMBsplopen
);
4691 if (!CAN_PRINT(conn
)) {
4692 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4693 END_PROFILE(SMBsplopen
);
4697 status
= file_new(conn
, &fsp
);
4698 if(!NT_STATUS_IS_OK(status
)) {
4699 reply_nterror(req
, status
);
4700 END_PROFILE(SMBsplopen
);
4704 /* Open for exclusive use, write only. */
4705 status
= print_fsp_open(conn
, NULL
, req
->vuid
, fsp
, &sbuf
);
4707 if (!NT_STATUS_IS_OK(status
)) {
4709 reply_nterror(req
, status
);
4710 END_PROFILE(SMBsplopen
);
4714 reply_outbuf(req
, 1, 0);
4715 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
4717 DEBUG(3,("openprint fd=%d fnum=%d\n",
4718 fsp
->fh
->fd
, fsp
->fnum
));
4720 END_PROFILE(SMBsplopen
);
4724 /****************************************************************************
4725 Reply to a printclose.
4726 ****************************************************************************/
4728 void reply_printclose(struct smb_request
*req
)
4730 connection_struct
*conn
= req
->conn
;
4734 START_PROFILE(SMBsplclose
);
4737 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4738 END_PROFILE(SMBsplclose
);
4742 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4744 if (!check_fsp(conn
, req
, fsp
)) {
4745 END_PROFILE(SMBsplclose
);
4749 if (!CAN_PRINT(conn
)) {
4750 reply_nterror(req
, NT_STATUS_DOS(ERRSRV
, ERRerror
));
4751 END_PROFILE(SMBsplclose
);
4755 DEBUG(3,("printclose fd=%d fnum=%d\n",
4756 fsp
->fh
->fd
,fsp
->fnum
));
4758 status
= close_file(fsp
,NORMAL_CLOSE
);
4760 if(!NT_STATUS_IS_OK(status
)) {
4761 reply_nterror(req
, status
);
4762 END_PROFILE(SMBsplclose
);
4766 reply_outbuf(req
, 0, 0);
4768 END_PROFILE(SMBsplclose
);
4772 /****************************************************************************
4773 Reply to a printqueue.
4774 ****************************************************************************/
4776 void reply_printqueue(struct smb_request
*req
)
4778 connection_struct
*conn
= req
->conn
;
4782 START_PROFILE(SMBsplretq
);
4785 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4786 END_PROFILE(SMBsplretq
);
4790 max_count
= SVAL(req
->inbuf
,smb_vwv0
);
4791 start_index
= SVAL(req
->inbuf
,smb_vwv1
);
4793 /* we used to allow the client to get the cnum wrong, but that
4794 is really quite gross and only worked when there was only
4795 one printer - I think we should now only accept it if they
4796 get it right (tridge) */
4797 if (!CAN_PRINT(conn
)) {
4798 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4799 END_PROFILE(SMBsplretq
);
4803 reply_outbuf(req
, 2, 3);
4804 SSVAL(req
->outbuf
,smb_vwv0
,0);
4805 SSVAL(req
->outbuf
,smb_vwv1
,0);
4806 SCVAL(smb_buf(req
->outbuf
),0,1);
4807 SSVAL(smb_buf(req
->outbuf
),1,0);
4809 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4810 start_index
, max_count
));
4813 print_queue_struct
*queue
= NULL
;
4814 print_status_struct status
;
4815 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
4816 int num_to_get
= ABS(max_count
);
4817 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
4823 num_to_get
= MIN(num_to_get
,count
-first
);
4826 for (i
=first
;i
<first
+num_to_get
;i
++) {
4830 srv_put_dos_date2(p
,0,queue
[i
].time
);
4831 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
4832 SSVAL(p
,5, queue
[i
].job
);
4833 SIVAL(p
,7,queue
[i
].size
);
4835 srvstr_push(blob
, req
->flags2
, p
+12,
4836 queue
[i
].fs_user
, 16, STR_ASCII
);
4838 if (message_push_blob(
4841 blob
, sizeof(blob
))) == -1) {
4842 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4843 END_PROFILE(SMBsplretq
);
4849 SSVAL(req
->outbuf
,smb_vwv0
,count
);
4850 SSVAL(req
->outbuf
,smb_vwv1
,
4851 (max_count
>0?first
+count
:first
-1));
4852 SCVAL(smb_buf(req
->outbuf
),0,1);
4853 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
4858 DEBUG(3,("%d entries returned in queue\n",count
));
4861 END_PROFILE(SMBsplretq
);
4865 /****************************************************************************
4866 Reply to a printwrite.
4867 ****************************************************************************/
4869 void reply_printwrite(struct smb_request
*req
)
4871 connection_struct
*conn
= req
->conn
;
4876 START_PROFILE(SMBsplwr
);
4879 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4880 END_PROFILE(SMBsplwr
);
4884 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4886 if (!check_fsp(conn
, req
, fsp
)) {
4887 END_PROFILE(SMBsplwr
);
4891 if (!CAN_PRINT(conn
)) {
4892 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4893 END_PROFILE(SMBsplwr
);
4897 if (!CHECK_WRITE(fsp
)) {
4898 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4899 END_PROFILE(SMBsplwr
);
4903 numtowrite
= SVAL(smb_buf(req
->inbuf
),1);
4905 if (smb_buflen(req
->inbuf
) < numtowrite
+ 3) {
4906 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4907 END_PROFILE(SMBsplwr
);
4911 data
= smb_buf(req
->inbuf
) + 3;
4913 if (write_file(req
,fsp
,data
,-1,numtowrite
) != numtowrite
) {
4914 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
4915 END_PROFILE(SMBsplwr
);
4919 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
4921 END_PROFILE(SMBsplwr
);
4925 /****************************************************************************
4927 ****************************************************************************/
4929 void reply_mkdir(struct smb_request
*req
)
4931 connection_struct
*conn
= req
->conn
;
4932 char *directory
= NULL
;
4934 SMB_STRUCT_STAT sbuf
;
4935 TALLOC_CTX
*ctx
= talloc_tos();
4937 START_PROFILE(SMBmkdir
);
4939 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &directory
,
4940 smb_buf(req
->inbuf
) + 1, 0,
4941 STR_TERMINATE
, &status
);
4942 if (!NT_STATUS_IS_OK(status
)) {
4943 reply_nterror(req
, status
);
4944 END_PROFILE(SMBmkdir
);
4948 status
= resolve_dfspath(ctx
, conn
,
4949 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
4952 if (!NT_STATUS_IS_OK(status
)) {
4953 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4954 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
4955 ERRSRV
, ERRbadpath
);
4956 END_PROFILE(SMBmkdir
);
4959 reply_nterror(req
, status
);
4960 END_PROFILE(SMBmkdir
);
4964 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
, NULL
, &sbuf
);
4965 if (!NT_STATUS_IS_OK(status
)) {
4966 reply_nterror(req
, status
);
4967 END_PROFILE(SMBmkdir
);
4971 status
= check_name(conn
, directory
);
4972 if (!NT_STATUS_IS_OK(status
)) {
4973 reply_nterror(req
, status
);
4974 END_PROFILE(SMBmkdir
);
4978 status
= create_directory(conn
, req
, directory
);
4980 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
4982 if (!NT_STATUS_IS_OK(status
)) {
4984 if (!use_nt_status()
4985 && NT_STATUS_EQUAL(status
,
4986 NT_STATUS_OBJECT_NAME_COLLISION
)) {
4988 * Yes, in the DOS error code case we get a
4989 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4990 * samba4 torture test.
4992 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
4995 reply_nterror(req
, status
);
4996 END_PROFILE(SMBmkdir
);
5000 reply_outbuf(req
, 0, 0);
5002 DEBUG( 3, ( "mkdir %s\n", directory
) );
5004 END_PROFILE(SMBmkdir
);
5008 /****************************************************************************
5009 Static function used by reply_rmdir to delete an entire directory
5010 tree recursively. Return True on ok, False on fail.
5011 ****************************************************************************/
5013 static bool recursive_rmdir(TALLOC_CTX
*ctx
,
5014 connection_struct
*conn
,
5017 const char *dname
= NULL
;
5020 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
, directory
,
5026 while((dname
= ReadDirName(dir_hnd
, &offset
))) {
5027 char *fullname
= NULL
;
5030 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5034 if (!is_visible_file(conn
, directory
, dname
, &st
, False
)) {
5038 /* Construct the full name. */
5039 fullname
= talloc_asprintf(ctx
,
5049 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
5054 if(st
.st_mode
& S_IFDIR
) {
5055 if(!recursive_rmdir(ctx
, conn
, fullname
)) {
5059 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
5063 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
5067 TALLOC_FREE(fullname
);
5069 TALLOC_FREE(dir_hnd
);
5073 /****************************************************************************
5074 The internals of the rmdir code - called elsewhere.
5075 ****************************************************************************/
5077 NTSTATUS
rmdir_internals(TALLOC_CTX
*ctx
,
5078 connection_struct
*conn
,
5079 const char *directory
)
5084 /* Might be a symlink. */
5085 if(SMB_VFS_LSTAT(conn
, directory
, &st
) != 0) {
5086 return map_nt_error_from_unix(errno
);
5089 if (S_ISLNK(st
.st_mode
)) {
5090 /* Is what it points to a directory ? */
5091 if(SMB_VFS_STAT(conn
, directory
, &st
) != 0) {
5092 return map_nt_error_from_unix(errno
);
5094 if (!(S_ISDIR(st
.st_mode
))) {
5095 return NT_STATUS_NOT_A_DIRECTORY
;
5097 ret
= SMB_VFS_UNLINK(conn
,directory
);
5099 ret
= SMB_VFS_RMDIR(conn
,directory
);
5102 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5103 FILE_NOTIFY_CHANGE_DIR_NAME
,
5105 return NT_STATUS_OK
;
5108 if(((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
5110 * Check to see if the only thing in this directory are
5111 * vetoed files/directories. If so then delete them and
5112 * retry. If we fail to delete any of them (and we *don't*
5113 * do a recursive delete) then fail the rmdir.
5117 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
,
5118 directory
, NULL
, 0);
5120 if(dir_hnd
== NULL
) {
5125 while ((dname
= ReadDirName(dir_hnd
,&dirpos
))) {
5126 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
5128 if (!is_visible_file(conn
, directory
, dname
, &st
, False
))
5130 if(!IS_VETO_PATH(conn
, dname
)) {
5131 TALLOC_FREE(dir_hnd
);
5137 /* We only have veto files/directories.
5138 * Are we allowed to delete them ? */
5140 if(!lp_recursive_veto_delete(SNUM(conn
))) {
5141 TALLOC_FREE(dir_hnd
);
5146 /* Do a recursive delete. */
5147 RewindDir(dir_hnd
,&dirpos
);
5148 while ((dname
= ReadDirName(dir_hnd
,&dirpos
))) {
5149 char *fullname
= NULL
;
5151 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5154 if (!is_visible_file(conn
, directory
, dname
, &st
, False
)) {
5158 fullname
= talloc_asprintf(ctx
,
5168 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
5171 if(st
.st_mode
& S_IFDIR
) {
5172 if(!recursive_rmdir(ctx
, conn
, fullname
)) {
5175 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
5178 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
5181 TALLOC_FREE(fullname
);
5183 TALLOC_FREE(dir_hnd
);
5184 /* Retry the rmdir */
5185 ret
= SMB_VFS_RMDIR(conn
,directory
);
5191 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5192 "%s\n", directory
,strerror(errno
)));
5193 return map_nt_error_from_unix(errno
);
5196 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5197 FILE_NOTIFY_CHANGE_DIR_NAME
,
5200 return NT_STATUS_OK
;
5203 /****************************************************************************
5205 ****************************************************************************/
5207 void reply_rmdir(struct smb_request
*req
)
5209 connection_struct
*conn
= req
->conn
;
5210 char *directory
= NULL
;
5211 SMB_STRUCT_STAT sbuf
;
5213 TALLOC_CTX
*ctx
= talloc_tos();
5215 START_PROFILE(SMBrmdir
);
5217 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &directory
,
5218 smb_buf(req
->inbuf
) + 1, 0,
5219 STR_TERMINATE
, &status
);
5220 if (!NT_STATUS_IS_OK(status
)) {
5221 reply_nterror(req
, status
);
5222 END_PROFILE(SMBrmdir
);
5226 status
= resolve_dfspath(ctx
, conn
,
5227 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5230 if (!NT_STATUS_IS_OK(status
)) {
5231 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5232 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5233 ERRSRV
, ERRbadpath
);
5234 END_PROFILE(SMBrmdir
);
5237 reply_nterror(req
, status
);
5238 END_PROFILE(SMBrmdir
);
5242 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
,
5244 if (!NT_STATUS_IS_OK(status
)) {
5245 reply_nterror(req
, status
);
5246 END_PROFILE(SMBrmdir
);
5250 status
= check_name(conn
, directory
);
5251 if (!NT_STATUS_IS_OK(status
)) {
5252 reply_nterror(req
, status
);
5253 END_PROFILE(SMBrmdir
);
5257 dptr_closepath(directory
, req
->smbpid
);
5258 status
= rmdir_internals(ctx
, conn
, directory
);
5259 if (!NT_STATUS_IS_OK(status
)) {
5260 reply_nterror(req
, status
);
5261 END_PROFILE(SMBrmdir
);
5265 reply_outbuf(req
, 0, 0);
5267 DEBUG( 3, ( "rmdir %s\n", directory
) );
5269 END_PROFILE(SMBrmdir
);
5273 /*******************************************************************
5274 Resolve wildcards in a filename rename.
5275 ********************************************************************/
5277 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5282 char *name2_copy
= NULL
;
5287 char *p
,*p2
, *pname1
, *pname2
;
5289 name2_copy
= talloc_strdup(ctx
, name2
);
5294 pname1
= strrchr_m(name1
,'/');
5295 pname2
= strrchr_m(name2_copy
,'/');
5297 if (!pname1
|| !pname2
) {
5301 /* Truncate the copy of name2 at the last '/' */
5304 /* Now go past the '/' */
5308 root1
= talloc_strdup(ctx
, pname1
);
5309 root2
= talloc_strdup(ctx
, pname2
);
5311 if (!root1
|| !root2
) {
5315 p
= strrchr_m(root1
,'.');
5318 ext1
= talloc_strdup(ctx
, p
+1);
5320 ext1
= talloc_strdup(ctx
, "");
5322 p
= strrchr_m(root2
,'.');
5325 ext2
= talloc_strdup(ctx
, p
+1);
5327 ext2
= talloc_strdup(ctx
, "");
5330 if (!ext1
|| !ext2
) {
5338 /* Hmmm. Should this be mb-aware ? */
5341 } else if (*p2
== '*') {
5343 root2
= talloc_asprintf(ctx
, "%s%s",
5362 /* Hmmm. Should this be mb-aware ? */
5365 } else if (*p2
== '*') {
5367 ext2
= talloc_asprintf(ctx
, "%s%s",
5383 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5388 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5400 /****************************************************************************
5401 Ensure open files have their names updated. Updated to notify other smbd's
5403 ****************************************************************************/
5405 static void rename_open_files(connection_struct
*conn
,
5406 struct share_mode_lock
*lck
,
5407 const char *newname
)
5410 bool did_rename
= False
;
5412 for(fsp
= file_find_di_first(lck
->id
); fsp
;
5413 fsp
= file_find_di_next(fsp
)) {
5414 /* fsp_name is a relative path under the fsp. To change this for other
5415 sharepaths we need to manipulate relative paths. */
5416 /* TODO - create the absolute path and manipulate the newname
5417 relative to the sharepath. */
5418 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5421 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5422 fsp
->fnum
, file_id_string_tos(&fsp
->file_id
),
5423 fsp
->fsp_name
, newname
));
5424 string_set(&fsp
->fsp_name
, newname
);
5429 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5430 file_id_string_tos(&lck
->id
), newname
));
5433 /* Send messages to all smbd's (not ourself) that the name has changed. */
5434 rename_share_filename(smbd_messaging_context(), lck
, conn
->connectpath
,
5438 /****************************************************************************
5439 We need to check if the source path is a parent directory of the destination
5440 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5441 refuse the rename with a sharing violation. Under UNIX the above call can
5442 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5443 probably need to check that the client is a Windows one before disallowing
5444 this as a UNIX client (one with UNIX extensions) can know the source is a
5445 symlink and make this decision intelligently. Found by an excellent bug
5446 report from <AndyLiebman@aol.com>.
5447 ****************************************************************************/
5449 static bool rename_path_prefix_equal(const char *src
, const char *dest
)
5451 const char *psrc
= src
;
5452 const char *pdst
= dest
;
5455 if (psrc
[0] == '.' && psrc
[1] == '/') {
5458 if (pdst
[0] == '.' && pdst
[1] == '/') {
5461 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5464 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5468 * Do the notify calls from a rename
5471 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5472 const char *oldpath
, const char *newpath
)
5474 char *olddir
, *newdir
;
5475 const char *oldname
, *newname
;
5478 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5479 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5481 if (!parent_dirname_talloc(NULL
, oldpath
, &olddir
, &oldname
)
5482 || !parent_dirname_talloc(NULL
, newpath
, &newdir
, &newname
)) {
5483 TALLOC_FREE(olddir
);
5487 if (strcmp(olddir
, newdir
) == 0) {
5488 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
, oldpath
);
5489 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
, newpath
);
5492 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
, oldpath
);
5493 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
, newpath
);
5495 TALLOC_FREE(olddir
);
5496 TALLOC_FREE(newdir
);
5498 /* this is a strange one. w2k3 gives an additional event for
5499 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5500 files, but not directories */
5502 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5503 FILE_NOTIFY_CHANGE_ATTRIBUTES
5504 |FILE_NOTIFY_CHANGE_CREATION
,
5509 /****************************************************************************
5510 Rename an open file - given an fsp.
5511 ****************************************************************************/
5513 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
5516 const char *newname_last_component
,
5518 bool replace_if_exists
)
5520 TALLOC_CTX
*ctx
= talloc_tos();
5521 SMB_STRUCT_STAT sbuf
, sbuf1
;
5522 NTSTATUS status
= NT_STATUS_OK
;
5523 struct share_mode_lock
*lck
= NULL
;
5524 bool dst_exists
, old_is_stream
, new_is_stream
;
5528 status
= check_name(conn
, newname
);
5529 if (!NT_STATUS_IS_OK(status
)) {
5533 /* Ensure newname contains a '/' */
5534 if(strrchr_m(newname
,'/') == 0) {
5535 newname
= talloc_asprintf(ctx
,
5539 return NT_STATUS_NO_MEMORY
;
5544 * Check for special case with case preserving and not
5545 * case sensitive. If the old last component differs from the original
5546 * last component only by case, then we should allow
5547 * the rename (user is trying to change the case of the
5551 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
5552 strequal(newname
, fsp
->fsp_name
)) {
5554 char *newname_modified_last_component
= NULL
;
5557 * Get the last component of the modified name.
5558 * Note that we guarantee that newname contains a '/'
5561 p
= strrchr_m(newname
,'/');
5562 newname_modified_last_component
= talloc_strdup(ctx
,
5564 if (!newname_modified_last_component
) {
5565 return NT_STATUS_NO_MEMORY
;
5568 if(strcsequal(newname_modified_last_component
,
5569 newname_last_component
) == False
) {
5571 * Replace the modified last component with
5574 *p
= '\0'; /* Truncate at the '/' */
5575 newname
= talloc_asprintf(ctx
,
5578 newname_last_component
);
5583 * If the src and dest names are identical - including case,
5584 * don't do the rename, just return success.
5587 if (strcsequal(fsp
->fsp_name
, newname
)) {
5588 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5590 return NT_STATUS_OK
;
5593 old_is_stream
= is_ntfs_stream_name(fsp
->fsp_name
);
5594 new_is_stream
= is_ntfs_stream_name(newname
);
5596 /* Return the correct error code if both names aren't streams. */
5597 if (!old_is_stream
&& new_is_stream
) {
5598 return NT_STATUS_OBJECT_NAME_INVALID
;
5601 if (old_is_stream
&& !new_is_stream
) {
5602 return NT_STATUS_INVALID_PARAMETER
;
5606 * Have vfs_object_exist also fill sbuf1
5608 dst_exists
= vfs_object_exist(conn
, newname
, &sbuf1
);
5610 if(!replace_if_exists
&& dst_exists
) {
5611 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5612 fsp
->fsp_name
,newname
));
5613 return NT_STATUS_OBJECT_NAME_COLLISION
;
5617 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, &sbuf1
);
5618 files_struct
*dst_fsp
= file_find_di_first(fileid
);
5619 /* The file can be open when renaming a stream */
5620 if (dst_fsp
&& !new_is_stream
) {
5621 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5622 return NT_STATUS_ACCESS_DENIED
;
5626 /* Ensure we have a valid stat struct for the source. */
5627 if (fsp
->fh
->fd
!= -1) {
5628 if (SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
5629 return map_nt_error_from_unix(errno
);
5633 if (fsp
->posix_open
) {
5634 ret
= SMB_VFS_LSTAT(conn
,fsp
->fsp_name
,&sbuf
);
5636 ret
= SMB_VFS_STAT(conn
,fsp
->fsp_name
,&sbuf
);
5639 return map_nt_error_from_unix(errno
);
5643 status
= can_rename(conn
, fsp
, attrs
, &sbuf
);
5645 if (!NT_STATUS_IS_OK(status
)) {
5646 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5647 nt_errstr(status
), fsp
->fsp_name
,newname
));
5648 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
5649 status
= NT_STATUS_ACCESS_DENIED
;
5653 if (rename_path_prefix_equal(fsp
->fsp_name
, newname
)) {
5654 return NT_STATUS_ACCESS_DENIED
;
5657 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
5661 * We have the file open ourselves, so not being able to get the
5662 * corresponding share mode lock is a fatal error.
5665 SMB_ASSERT(lck
!= NULL
);
5667 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
5668 uint32 create_options
= fsp
->fh
->private_options
;
5670 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5671 fsp
->fsp_name
,newname
));
5673 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
, newname
);
5675 rename_open_files(conn
, lck
, newname
);
5678 * A rename acts as a new file create w.r.t. allowing an initial delete
5679 * on close, probably because in Windows there is a new handle to the
5680 * new file. If initial delete on close was requested but not
5681 * originally set, we need to set it here. This is probably not 100% correct,
5682 * but will work for the CIFSFS client which in non-posix mode
5683 * depends on these semantics. JRA.
5686 if (create_options
& FILE_DELETE_ON_CLOSE
) {
5687 status
= can_set_delete_on_close(fsp
, True
, 0);
5689 if (NT_STATUS_IS_OK(status
)) {
5690 /* Note that here we set the *inital* delete on close flag,
5691 * not the regular one. The magic gets handled in close. */
5692 fsp
->initial_delete_on_close
= True
;
5696 return NT_STATUS_OK
;
5701 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
5702 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
5704 status
= map_nt_error_from_unix(errno
);
5707 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5708 nt_errstr(status
), fsp
->fsp_name
,newname
));
5713 /****************************************************************************
5714 The guts of the rename command, split out so it may be called by the NT SMB
5716 ****************************************************************************/
5718 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
5719 connection_struct
*conn
,
5720 struct smb_request
*req
,
5721 const char *name_in
,
5722 const char *newname_in
,
5724 bool replace_if_exists
,
5727 uint32_t access_mask
)
5729 char *directory
= NULL
;
5731 char *last_component_src
= NULL
;
5732 char *last_component_dest
= NULL
;
5734 char *newname
= NULL
;
5737 NTSTATUS status
= NT_STATUS_OK
;
5738 SMB_STRUCT_STAT sbuf1
, sbuf2
;
5739 struct smb_Dir
*dir_hnd
= NULL
;
5742 bool posix_pathnames
= lp_posix_pathnames();
5747 status
= unix_convert(ctx
, conn
, name_in
, src_has_wild
, &name
,
5748 &last_component_src
, &sbuf1
);
5749 if (!NT_STATUS_IS_OK(status
)) {
5753 status
= unix_convert(ctx
, conn
, newname_in
, dest_has_wild
, &newname
,
5754 &last_component_dest
, &sbuf2
);
5755 if (!NT_STATUS_IS_OK(status
)) {
5760 * Split the old name into directory and last component
5761 * strings. Note that unix_convert may have stripped off a
5762 * leading ./ from both name and newname if the rename is
5763 * at the root of the share. We need to make sure either both
5764 * name and newname contain a / character or neither of them do
5765 * as this is checked in resolve_wildcards().
5768 p
= strrchr_m(name
,'/');
5770 directory
= talloc_strdup(ctx
, ".");
5772 return NT_STATUS_NO_MEMORY
;
5777 directory
= talloc_strdup(ctx
, name
);
5779 return NT_STATUS_NO_MEMORY
;
5782 *p
= '/'; /* Replace needed for exceptional test below. */
5786 * We should only check the mangled cache
5787 * here if unix_convert failed. This means
5788 * that the path in 'mask' doesn't exist
5789 * on the file system and so we need to look
5790 * for a possible mangle. This patch from
5791 * Tine Smukavec <valentin.smukavec@hermes.si>.
5794 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
)) {
5795 char *new_mask
= NULL
;
5796 mangle_lookup_name_from_8_3(ctx
,
5805 if (!src_has_wild
) {
5809 * No wildcards - just process the one file.
5811 bool is_short_name
= mangle_is_8_3(name
, True
, conn
->params
);
5813 /* Add a terminating '/' to the directory name. */
5814 directory
= talloc_asprintf_append(directory
,
5818 return NT_STATUS_NO_MEMORY
;
5821 /* Ensure newname contains a '/' also */
5822 if(strrchr_m(newname
,'/') == 0) {
5823 newname
= talloc_asprintf(ctx
,
5827 return NT_STATUS_NO_MEMORY
;
5831 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5832 "case_preserve = %d, short case preserve = %d, "
5833 "directory = %s, newname = %s, "
5834 "last_component_dest = %s, is_8_3 = %d\n",
5835 conn
->case_sensitive
, conn
->case_preserve
,
5836 conn
->short_case_preserve
, directory
,
5837 newname
, last_component_dest
, is_short_name
));
5839 /* The dest name still may have wildcards. */
5840 if (dest_has_wild
) {
5841 char *mod_newname
= NULL
;
5842 if (!resolve_wildcards(ctx
,
5843 directory
,newname
,&mod_newname
)) {
5844 DEBUG(6, ("rename_internals: resolve_wildcards "
5848 return NT_STATUS_NO_MEMORY
;
5850 newname
= mod_newname
;
5854 if (posix_pathnames
) {
5855 SMB_VFS_LSTAT(conn
, directory
, &sbuf1
);
5857 SMB_VFS_STAT(conn
, directory
, &sbuf1
);
5860 status
= S_ISDIR(sbuf1
.st_mode
) ?
5861 open_directory(conn
, req
, directory
, &sbuf1
,
5863 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5866 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0,
5869 : open_file_ntcreate(conn
, req
, directory
, &sbuf1
,
5871 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5874 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0,
5879 if (!NT_STATUS_IS_OK(status
)) {
5880 DEBUG(3, ("Could not open rename source %s: %s\n",
5881 directory
, nt_errstr(status
)));
5885 status
= rename_internals_fsp(conn
, fsp
, newname
,
5886 last_component_dest
,
5887 attrs
, replace_if_exists
);
5889 close_file(fsp
, NORMAL_CLOSE
);
5891 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5892 nt_errstr(status
), directory
,newname
));
5898 * Wildcards - process each file that matches.
5900 if (strequal(mask
,"????????.???")) {
5905 status
= check_name(conn
, directory
);
5906 if (!NT_STATUS_IS_OK(status
)) {
5910 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
, attrs
);
5911 if (dir_hnd
== NULL
) {
5912 return map_nt_error_from_unix(errno
);
5915 status
= NT_STATUS_NO_SUCH_FILE
;
5917 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5918 * - gentest fix. JRA
5921 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
5922 files_struct
*fsp
= NULL
;
5924 char *destname
= NULL
;
5925 bool sysdir_entry
= False
;
5927 /* Quick check for "." and ".." */
5928 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5930 sysdir_entry
= True
;
5936 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
)) {
5940 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
5945 status
= NT_STATUS_OBJECT_NAME_INVALID
;
5949 fname
= talloc_asprintf(ctx
,
5954 return NT_STATUS_NO_MEMORY
;
5957 if (!resolve_wildcards(ctx
,
5958 fname
,newname
,&destname
)) {
5959 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5965 return NT_STATUS_NO_MEMORY
;
5969 if (posix_pathnames
) {
5970 SMB_VFS_LSTAT(conn
, fname
, &sbuf1
);
5972 SMB_VFS_STAT(conn
, fname
, &sbuf1
);
5975 status
= S_ISDIR(sbuf1
.st_mode
) ?
5976 open_directory(conn
, req
, fname
, &sbuf1
,
5978 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5981 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0,
5984 : open_file_ntcreate(conn
, req
, fname
, &sbuf1
,
5986 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5989 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0,
5994 if (!NT_STATUS_IS_OK(status
)) {
5995 DEBUG(3,("rename_internals: open_file_ntcreate "
5996 "returned %s rename %s -> %s\n",
5997 nt_errstr(status
), directory
, newname
));
6001 status
= rename_internals_fsp(conn
, fsp
, destname
, dname
,
6002 attrs
, replace_if_exists
);
6004 close_file(fsp
, NORMAL_CLOSE
);
6006 if (!NT_STATUS_IS_OK(status
)) {
6007 DEBUG(3, ("rename_internals_fsp returned %s for "
6008 "rename %s -> %s\n", nt_errstr(status
),
6009 directory
, newname
));
6015 DEBUG(3,("rename_internals: doing rename on %s -> "
6016 "%s\n",fname
,destname
));
6019 TALLOC_FREE(destname
);
6021 TALLOC_FREE(dir_hnd
);
6023 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6024 status
= map_nt_error_from_unix(errno
);
6030 /****************************************************************************
6032 ****************************************************************************/
6034 void reply_mv(struct smb_request
*req
)
6036 connection_struct
*conn
= req
->conn
;
6038 char *newname
= NULL
;
6042 bool src_has_wcard
= False
;
6043 bool dest_has_wcard
= False
;
6044 TALLOC_CTX
*ctx
= talloc_tos();
6046 START_PROFILE(SMBmv
);
6049 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6054 attrs
= SVAL(req
->inbuf
,smb_vwv0
);
6056 p
= smb_buf(req
->inbuf
) + 1;
6057 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &name
, p
,
6058 0, STR_TERMINATE
, &status
,
6060 if (!NT_STATUS_IS_OK(status
)) {
6061 reply_nterror(req
, status
);
6066 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &newname
, p
,
6067 0, STR_TERMINATE
, &status
,
6069 if (!NT_STATUS_IS_OK(status
)) {
6070 reply_nterror(req
, status
);
6075 status
= resolve_dfspath_wcard(ctx
, conn
,
6076 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6080 if (!NT_STATUS_IS_OK(status
)) {
6081 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6082 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6083 ERRSRV
, ERRbadpath
);
6087 reply_nterror(req
, status
);
6092 status
= resolve_dfspath_wcard(ctx
, conn
,
6093 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6097 if (!NT_STATUS_IS_OK(status
)) {
6098 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6099 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6100 ERRSRV
, ERRbadpath
);
6104 reply_nterror(req
, status
);
6109 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
6111 status
= rename_internals(ctx
, conn
, req
, name
, newname
, attrs
, False
,
6112 src_has_wcard
, dest_has_wcard
, DELETE_ACCESS
);
6113 if (!NT_STATUS_IS_OK(status
)) {
6114 if (open_was_deferred(req
->mid
)) {
6115 /* We have re-scheduled this call. */
6119 reply_nterror(req
, status
);
6124 reply_outbuf(req
, 0, 0);
6130 /*******************************************************************
6131 Copy a file as part of a reply_copy.
6132 ******************************************************************/
6135 * TODO: check error codes on all callers
6138 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6139 connection_struct
*conn
,
6144 bool target_is_directory
)
6146 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
6148 files_struct
*fsp1
,*fsp2
;
6151 uint32 new_create_disposition
;
6154 dest
= talloc_strdup(ctx
, dest1
);
6156 return NT_STATUS_NO_MEMORY
;
6158 if (target_is_directory
) {
6159 const char *p
= strrchr_m(src
,'/');
6165 dest
= talloc_asprintf_append(dest
,
6169 return NT_STATUS_NO_MEMORY
;
6173 if (!vfs_file_exist(conn
,src
,&src_sbuf
)) {
6175 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6178 if (!target_is_directory
&& count
) {
6179 new_create_disposition
= FILE_OPEN
;
6181 if (!map_open_params_to_ntcreate(dest1
,0,ofun
,
6182 NULL
, NULL
, &new_create_disposition
, NULL
)) {
6184 return NT_STATUS_INVALID_PARAMETER
;
6188 status
= open_file_ntcreate(conn
, NULL
, src
, &src_sbuf
,
6190 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6193 FILE_ATTRIBUTE_NORMAL
,
6197 if (!NT_STATUS_IS_OK(status
)) {
6202 dosattrs
= dos_mode(conn
, src
, &src_sbuf
);
6203 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1) {
6204 ZERO_STRUCTP(&sbuf2
);
6207 status
= open_file_ntcreate(conn
, NULL
, dest
, &sbuf2
,
6209 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6210 new_create_disposition
,
6218 if (!NT_STATUS_IS_OK(status
)) {
6219 close_file(fsp1
,ERROR_CLOSE
);
6223 if ((ofun
&3) == 1) {
6224 if(SMB_VFS_LSEEK(fsp2
,0,SEEK_END
) == -1) {
6225 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
6227 * Stop the copy from occurring.
6230 src_sbuf
.st_size
= 0;
6234 if (src_sbuf
.st_size
) {
6235 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
6238 close_file(fsp1
,NORMAL_CLOSE
);
6240 /* Ensure the modtime is set correctly on the destination file. */
6241 set_close_write_time(fsp2
, get_mtimespec(&src_sbuf
));
6244 * As we are opening fsp1 read-only we only expect
6245 * an error on close on fsp2 if we are out of space.
6246 * Thus we don't look at the error return from the
6249 status
= close_file(fsp2
,NORMAL_CLOSE
);
6251 if (!NT_STATUS_IS_OK(status
)) {
6255 if (ret
!= (SMB_OFF_T
)src_sbuf
.st_size
) {
6256 return NT_STATUS_DISK_FULL
;
6259 return NT_STATUS_OK
;
6262 /****************************************************************************
6263 Reply to a file copy.
6264 ****************************************************************************/
6266 void reply_copy(struct smb_request
*req
)
6268 connection_struct
*conn
= req
->conn
;
6270 char *newname
= NULL
;
6271 char *directory
= NULL
;
6275 int error
= ERRnoaccess
;
6280 bool target_is_directory
=False
;
6281 bool source_has_wild
= False
;
6282 bool dest_has_wild
= False
;
6283 SMB_STRUCT_STAT sbuf1
, sbuf2
;
6285 TALLOC_CTX
*ctx
= talloc_tos();
6287 START_PROFILE(SMBcopy
);
6290 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6291 END_PROFILE(SMBcopy
);
6295 tid2
= SVAL(req
->inbuf
,smb_vwv0
);
6296 ofun
= SVAL(req
->inbuf
,smb_vwv1
);
6297 flags
= SVAL(req
->inbuf
,smb_vwv2
);
6299 p
= smb_buf(req
->inbuf
);
6300 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &name
, p
,
6301 0, STR_TERMINATE
, &status
,
6303 if (!NT_STATUS_IS_OK(status
)) {
6304 reply_nterror(req
, status
);
6305 END_PROFILE(SMBcopy
);
6308 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &newname
, p
,
6309 0, STR_TERMINATE
, &status
,
6311 if (!NT_STATUS_IS_OK(status
)) {
6312 reply_nterror(req
, status
);
6313 END_PROFILE(SMBcopy
);
6317 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
6319 if (tid2
!= conn
->cnum
) {
6320 /* can't currently handle inter share copies XXXX */
6321 DEBUG(3,("Rejecting inter-share copy\n"));
6322 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
6323 END_PROFILE(SMBcopy
);
6327 status
= resolve_dfspath_wcard(ctx
, conn
,
6328 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6332 if (!NT_STATUS_IS_OK(status
)) {
6333 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6334 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6335 ERRSRV
, ERRbadpath
);
6336 END_PROFILE(SMBcopy
);
6339 reply_nterror(req
, status
);
6340 END_PROFILE(SMBcopy
);
6344 status
= resolve_dfspath_wcard(ctx
, conn
,
6345 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6349 if (!NT_STATUS_IS_OK(status
)) {
6350 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6351 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6352 ERRSRV
, ERRbadpath
);
6353 END_PROFILE(SMBcopy
);
6356 reply_nterror(req
, status
);
6357 END_PROFILE(SMBcopy
);
6361 status
= unix_convert(ctx
, conn
, name
, source_has_wild
,
6362 &name
, NULL
, &sbuf1
);
6363 if (!NT_STATUS_IS_OK(status
)) {
6364 reply_nterror(req
, status
);
6365 END_PROFILE(SMBcopy
);
6369 status
= unix_convert(ctx
, conn
, newname
, dest_has_wild
,
6370 &newname
, NULL
, &sbuf2
);
6371 if (!NT_STATUS_IS_OK(status
)) {
6372 reply_nterror(req
, status
);
6373 END_PROFILE(SMBcopy
);
6377 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
6379 if ((flags
&1) && target_is_directory
) {
6380 reply_doserror(req
, ERRDOS
, ERRbadfile
);
6381 END_PROFILE(SMBcopy
);
6385 if ((flags
&2) && !target_is_directory
) {
6386 reply_doserror(req
, ERRDOS
, ERRbadpath
);
6387 END_PROFILE(SMBcopy
);
6391 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
6392 /* wants a tree copy! XXXX */
6393 DEBUG(3,("Rejecting tree copy\n"));
6394 reply_doserror(req
, ERRSRV
, ERRerror
);
6395 END_PROFILE(SMBcopy
);
6399 p
= strrchr_m(name
,'/');
6401 directory
= talloc_strdup(ctx
, "./");
6403 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6404 END_PROFILE(SMBcopy
);
6410 directory
= talloc_strdup(ctx
, name
);
6412 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6413 END_PROFILE(SMBcopy
);
6420 * We should only check the mangled cache
6421 * here if unix_convert failed. This means
6422 * that the path in 'mask' doesn't exist
6423 * on the file system and so we need to look
6424 * for a possible mangle. This patch from
6425 * Tine Smukavec <valentin.smukavec@hermes.si>.
6428 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
)) {
6429 char *new_mask
= NULL
;
6430 mangle_lookup_name_from_8_3(ctx
,
6439 if (!source_has_wild
) {
6440 directory
= talloc_asprintf_append(directory
,
6443 if (dest_has_wild
) {
6444 char *mod_newname
= NULL
;
6445 if (!resolve_wildcards(ctx
,
6446 directory
,newname
,&mod_newname
)) {
6447 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6448 END_PROFILE(SMBcopy
);
6451 newname
= mod_newname
;
6454 status
= check_name(conn
, directory
);
6455 if (!NT_STATUS_IS_OK(status
)) {
6456 reply_nterror(req
, status
);
6457 END_PROFILE(SMBcopy
);
6461 status
= check_name(conn
, newname
);
6462 if (!NT_STATUS_IS_OK(status
)) {
6463 reply_nterror(req
, status
);
6464 END_PROFILE(SMBcopy
);
6468 status
= copy_file(ctx
,conn
,directory
,newname
,ofun
,
6469 count
,target_is_directory
);
6471 if(!NT_STATUS_IS_OK(status
)) {
6472 reply_nterror(req
, status
);
6473 END_PROFILE(SMBcopy
);
6479 struct smb_Dir
*dir_hnd
= NULL
;
6480 const char *dname
= NULL
;
6483 if (strequal(mask
,"????????.???")) {
6488 status
= check_name(conn
, directory
);
6489 if (!NT_STATUS_IS_OK(status
)) {
6490 reply_nterror(req
, status
);
6491 END_PROFILE(SMBcopy
);
6495 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
, 0);
6496 if (dir_hnd
== NULL
) {
6497 status
= map_nt_error_from_unix(errno
);
6498 reply_nterror(req
, status
);
6499 END_PROFILE(SMBcopy
);
6505 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
6506 char *destname
= NULL
;
6509 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6513 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
)) {
6517 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
6521 error
= ERRnoaccess
;
6522 fname
= talloc_asprintf(ctx
,
6527 TALLOC_FREE(dir_hnd
);
6528 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6529 END_PROFILE(SMBcopy
);
6533 if (!resolve_wildcards(ctx
,
6534 fname
,newname
,&destname
)) {
6538 TALLOC_FREE(dir_hnd
);
6539 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6540 END_PROFILE(SMBcopy
);
6544 status
= check_name(conn
, fname
);
6545 if (!NT_STATUS_IS_OK(status
)) {
6546 TALLOC_FREE(dir_hnd
);
6547 reply_nterror(req
, status
);
6548 END_PROFILE(SMBcopy
);
6552 status
= check_name(conn
, destname
);
6553 if (!NT_STATUS_IS_OK(status
)) {
6554 TALLOC_FREE(dir_hnd
);
6555 reply_nterror(req
, status
);
6556 END_PROFILE(SMBcopy
);
6560 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
, destname
));
6562 status
= copy_file(ctx
,conn
,fname
,destname
,ofun
,
6563 count
,target_is_directory
);
6564 if (NT_STATUS_IS_OK(status
)) {
6568 TALLOC_FREE(destname
);
6570 TALLOC_FREE(dir_hnd
);
6575 /* Error on close... */
6577 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
6578 END_PROFILE(SMBcopy
);
6582 reply_doserror(req
, ERRDOS
, error
);
6583 END_PROFILE(SMBcopy
);
6587 reply_outbuf(req
, 1, 0);
6588 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6590 END_PROFILE(SMBcopy
);
6595 #define DBGC_CLASS DBGC_LOCKING
6597 /****************************************************************************
6598 Get a lock pid, dealing with large count requests.
6599 ****************************************************************************/
6601 uint32
get_lock_pid( char *data
, int data_offset
, bool large_file_format
)
6603 if(!large_file_format
)
6604 return (uint32
)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
6606 return (uint32
)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
6609 /****************************************************************************
6610 Get a lock count, dealing with large count requests.
6611 ****************************************************************************/
6613 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, bool large_file_format
)
6615 SMB_BIG_UINT count
= 0;
6617 if(!large_file_format
) {
6618 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
6621 #if defined(HAVE_LONGLONG)
6622 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
6623 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
6624 #else /* HAVE_LONGLONG */
6627 * NT4.x seems to be broken in that it sends large file (64 bit)
6628 * lockingX calls even if the CAP_LARGE_FILES was *not*
6629 * negotiated. For boxes without large unsigned ints truncate the
6630 * lock count by dropping the top 32 bits.
6633 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
6634 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6635 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
6636 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
6637 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
6640 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
6641 #endif /* HAVE_LONGLONG */
6647 #if !defined(HAVE_LONGLONG)
6648 /****************************************************************************
6649 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6650 ****************************************************************************/
6652 static uint32
map_lock_offset(uint32 high
, uint32 low
)
6656 uint32 highcopy
= high
;
6659 * Try and find out how many significant bits there are in high.
6662 for(i
= 0; highcopy
; i
++)
6666 * We use 31 bits not 32 here as POSIX
6667 * lock offsets may not be negative.
6670 mask
= (~0) << (31 - i
);
6673 return 0; /* Fail. */
6679 #endif /* !defined(HAVE_LONGLONG) */
6681 /****************************************************************************
6682 Get a lock offset, dealing with large offset requests.
6683 ****************************************************************************/
6685 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, bool large_file_format
, bool *err
)
6687 SMB_BIG_UINT offset
= 0;
6691 if(!large_file_format
) {
6692 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
6695 #if defined(HAVE_LONGLONG)
6696 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
6697 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
6698 #else /* HAVE_LONGLONG */
6701 * NT4.x seems to be broken in that it sends large file (64 bit)
6702 * lockingX calls even if the CAP_LARGE_FILES was *not*
6703 * negotiated. For boxes without large unsigned ints mangle the
6704 * lock offset by mapping the top 32 bits onto the lower 32.
6707 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
6708 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
6709 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
6712 if((new_low
= map_lock_offset(high
, low
)) == 0) {
6714 return (SMB_BIG_UINT
)-1;
6717 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6718 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
6719 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
6720 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
6723 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
6724 #endif /* HAVE_LONGLONG */
6730 /****************************************************************************
6731 Reply to a lockingX request.
6732 ****************************************************************************/
6734 void reply_lockingX(struct smb_request
*req
)
6736 connection_struct
*conn
= req
->conn
;
6738 unsigned char locktype
;
6739 unsigned char oplocklevel
;
6742 SMB_BIG_UINT count
= 0, offset
= 0;
6747 bool large_file_format
;
6749 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
6751 START_PROFILE(SMBlockingX
);
6754 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6755 END_PROFILE(SMBlockingX
);
6759 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv2
));
6760 locktype
= CVAL(req
->inbuf
,smb_vwv3
);
6761 oplocklevel
= CVAL(req
->inbuf
,smb_vwv3
+1);
6762 num_ulocks
= SVAL(req
->inbuf
,smb_vwv6
);
6763 num_locks
= SVAL(req
->inbuf
,smb_vwv7
);
6764 lock_timeout
= IVAL(req
->inbuf
,smb_vwv4
);
6765 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
6767 if (!check_fsp(conn
, req
, fsp
)) {
6768 END_PROFILE(SMBlockingX
);
6772 data
= smb_buf(req
->inbuf
);
6774 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
6775 /* we don't support these - and CANCEL_LOCK makes w2k
6776 and XP reboot so I don't really want to be
6777 compatible! (tridge) */
6778 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
6779 END_PROFILE(SMBlockingX
);
6783 /* Check if this is an oplock break on a file
6784 we have granted an oplock on.
6786 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
6787 /* Client can insist on breaking to none. */
6788 bool break_to_none
= (oplocklevel
== 0);
6791 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6792 "for fnum = %d\n", (unsigned int)oplocklevel
,
6796 * Make sure we have granted an exclusive or batch oplock on
6800 if (fsp
->oplock_type
== 0) {
6802 /* The Samba4 nbench simulator doesn't understand
6803 the difference between break to level2 and break
6804 to none from level2 - it sends oplock break
6805 replies in both cases. Don't keep logging an error
6806 message here - just ignore it. JRA. */
6808 DEBUG(5,("reply_lockingX: Error : oplock break from "
6809 "client for fnum = %d (oplock=%d) and no "
6810 "oplock granted on this file (%s).\n",
6811 fsp
->fnum
, fsp
->oplock_type
, fsp
->fsp_name
));
6813 /* if this is a pure oplock break request then don't
6815 if (num_locks
== 0 && num_ulocks
== 0) {
6816 END_PROFILE(SMBlockingX
);
6819 END_PROFILE(SMBlockingX
);
6820 reply_doserror(req
, ERRDOS
, ERRlock
);
6825 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
6827 result
= remove_oplock(fsp
);
6829 result
= downgrade_oplock(fsp
);
6833 DEBUG(0, ("reply_lockingX: error in removing "
6834 "oplock on file %s\n", fsp
->fsp_name
));
6835 /* Hmmm. Is this panic justified? */
6836 smb_panic("internal tdb error");
6839 reply_to_oplock_break_requests(fsp
);
6841 /* if this is a pure oplock break request then don't send a
6843 if (num_locks
== 0 && num_ulocks
== 0) {
6844 /* Sanity check - ensure a pure oplock break is not a
6846 if(CVAL(req
->inbuf
,smb_vwv0
) != 0xff)
6847 DEBUG(0,("reply_lockingX: Error : pure oplock "
6848 "break is a chained %d request !\n",
6849 (unsigned int)CVAL(req
->inbuf
,
6851 END_PROFILE(SMBlockingX
);
6857 * We do this check *after* we have checked this is not a oplock break
6858 * response message. JRA.
6861 release_level_2_oplocks_on_change(fsp
);
6863 if (smb_buflen(req
->inbuf
) <
6864 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
6865 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6866 END_PROFILE(SMBlockingX
);
6870 /* Data now points at the beginning of the list
6871 of smb_unlkrng structs */
6872 for(i
= 0; i
< (int)num_ulocks
; i
++) {
6873 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
6874 count
= get_lock_count( data
, i
, large_file_format
);
6875 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
6878 * There is no error code marked "stupid client bug".... :-).
6881 END_PROFILE(SMBlockingX
);
6882 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
6886 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6887 "pid %u, file %s\n", (double)offset
, (double)count
,
6888 (unsigned int)lock_pid
, fsp
->fsp_name
));
6890 status
= do_unlock(smbd_messaging_context(),
6897 if (NT_STATUS_V(status
)) {
6898 END_PROFILE(SMBlockingX
);
6899 reply_nterror(req
, status
);
6904 /* Setup the timeout in seconds. */
6906 if (!lp_blocking_locks(SNUM(conn
))) {
6910 /* Now do any requested locks */
6911 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
6913 /* Data now points at the beginning of the list
6914 of smb_lkrng structs */
6916 for(i
= 0; i
< (int)num_locks
; i
++) {
6917 enum brl_type lock_type
= ((locktype
& LOCKING_ANDX_SHARED_LOCK
) ?
6918 READ_LOCK
:WRITE_LOCK
);
6919 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
6920 count
= get_lock_count( data
, i
, large_file_format
);
6921 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
6924 * There is no error code marked "stupid client bug".... :-).
6927 END_PROFILE(SMBlockingX
);
6928 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
6932 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6933 "%u, file %s timeout = %d\n", (double)offset
,
6934 (double)count
, (unsigned int)lock_pid
,
6935 fsp
->fsp_name
, (int)lock_timeout
));
6937 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
6938 if (lp_blocking_locks(SNUM(conn
))) {
6940 /* Schedule a message to ourselves to
6941 remove the blocking lock record and
6942 return the right error. */
6944 if (!blocking_lock_cancel(fsp
,
6950 NT_STATUS_FILE_LOCK_CONFLICT
)) {
6951 END_PROFILE(SMBlockingX
);
6956 ERRcancelviolation
));
6960 /* Remove a matching pending lock. */
6961 status
= do_lock_cancel(fsp
,
6967 bool blocking_lock
= lock_timeout
? True
: False
;
6968 bool defer_lock
= False
;
6969 struct byte_range_lock
*br_lck
;
6970 uint32 block_smbpid
;
6972 br_lck
= do_lock(smbd_messaging_context(),
6983 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6984 /* Windows internal resolution for blocking locks seems
6985 to be about 200ms... Don't wait for less than that. JRA. */
6986 if (lock_timeout
!= -1 && lock_timeout
< lp_lock_spin_time()) {
6987 lock_timeout
= lp_lock_spin_time();
6992 /* This heuristic seems to match W2K3 very well. If a
6993 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6994 it pretends we asked for a timeout of between 150 - 300 milliseconds as
6995 far as I can tell. Replacement for do_lock_spin(). JRA. */
6997 if (br_lck
&& lp_blocking_locks(SNUM(conn
)) && !blocking_lock
&&
6998 NT_STATUS_EQUAL((status
), NT_STATUS_FILE_LOCK_CONFLICT
)) {
7000 lock_timeout
= lp_lock_spin_time();
7003 if (br_lck
&& defer_lock
) {
7005 * A blocking lock was requested. Package up
7006 * this smb into a queued request and push it
7007 * onto the blocking lock queue.
7009 if(push_blocking_lock_request(br_lck
,
7020 TALLOC_FREE(br_lck
);
7021 END_PROFILE(SMBlockingX
);
7026 TALLOC_FREE(br_lck
);
7029 if (NT_STATUS_V(status
)) {
7030 END_PROFILE(SMBlockingX
);
7031 reply_nterror(req
, status
);
7036 /* If any of the above locks failed, then we must unlock
7037 all of the previous locks (X/Open spec). */
7039 if (!(locktype
& LOCKING_ANDX_CANCEL_LOCK
) &&
7043 * Ensure we don't do a remove on the lock that just failed,
7044 * as under POSIX rules, if we have a lock already there, we
7045 * will delete it (and we shouldn't) .....
7047 for(i
--; i
>= 0; i
--) {
7048 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
7049 count
= get_lock_count( data
, i
, large_file_format
);
7050 offset
= get_lock_offset( data
, i
, large_file_format
,
7054 * There is no error code marked "stupid client
7058 END_PROFILE(SMBlockingX
);
7059 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7063 do_unlock(smbd_messaging_context(),
7070 END_PROFILE(SMBlockingX
);
7071 reply_nterror(req
, status
);
7075 reply_outbuf(req
, 2, 0);
7077 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7078 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7080 END_PROFILE(SMBlockingX
);
7085 #define DBGC_CLASS DBGC_ALL
7087 /****************************************************************************
7088 Reply to a SMBreadbmpx (read block multiplex) request.
7089 Always reply with an error, if someone has a platform really needs this,
7090 please contact vl@samba.org
7091 ****************************************************************************/
7093 void reply_readbmpx(struct smb_request
*req
)
7095 START_PROFILE(SMBreadBmpx
);
7096 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7097 END_PROFILE(SMBreadBmpx
);
7101 /****************************************************************************
7102 Reply to a SMBreadbs (read block multiplex secondary) request.
7103 Always reply with an error, if someone has a platform really needs this,
7104 please contact vl@samba.org
7105 ****************************************************************************/
7107 void reply_readbs(struct smb_request
*req
)
7109 START_PROFILE(SMBreadBs
);
7110 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7111 END_PROFILE(SMBreadBs
);
7115 /****************************************************************************
7116 Reply to a SMBsetattrE.
7117 ****************************************************************************/
7119 void reply_setattrE(struct smb_request
*req
)
7121 connection_struct
*conn
= req
->conn
;
7122 struct timespec ts
[2];
7124 SMB_STRUCT_STAT sbuf
;
7127 START_PROFILE(SMBsetattrE
);
7130 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7131 END_PROFILE(SMBsetattrE
);
7135 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
7137 if(!fsp
|| (fsp
->conn
!= conn
)) {
7138 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7139 END_PROFILE(SMBsetattrE
);
7145 * Convert the DOS times into unix times. Ignore create
7146 * time as UNIX can't set this.
7149 ts
[0] = convert_time_t_to_timespec(
7150 srv_make_unix_date2(req
->inbuf
+smb_vwv3
)); /* atime. */
7151 ts
[1] = convert_time_t_to_timespec(
7152 srv_make_unix_date2(req
->inbuf
+smb_vwv5
)); /* mtime. */
7154 reply_outbuf(req
, 0, 0);
7157 * Patch from Ray Frush <frush@engr.colostate.edu>
7158 * Sometimes times are sent as zero - ignore them.
7161 /* Ensure we have a valid stat struct for the source. */
7162 if (fsp
->fh
->fd
!= -1) {
7163 if (SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
7164 status
= map_nt_error_from_unix(errno
);
7165 reply_nterror(req
, status
);
7166 END_PROFILE(SMBsetattrE
);
7172 if (fsp
->posix_open
) {
7173 ret
= SMB_VFS_LSTAT(conn
, fsp
->fsp_name
, &sbuf
);
7175 ret
= SMB_VFS_STAT(conn
, fsp
->fsp_name
, &sbuf
);
7178 status
= map_nt_error_from_unix(errno
);
7179 reply_nterror(req
, status
);
7180 END_PROFILE(SMBsetattrE
);
7185 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
,
7187 if (!NT_STATUS_IS_OK(status
)) {
7188 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7189 END_PROFILE(SMBsetattrE
);
7193 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7195 (unsigned int)ts
[0].tv_sec
,
7196 (unsigned int)ts
[1].tv_sec
));
7198 END_PROFILE(SMBsetattrE
);
7203 /* Back from the dead for OS/2..... JRA. */
7205 /****************************************************************************
7206 Reply to a SMBwritebmpx (write block multiplex primary) request.
7207 Always reply with an error, if someone has a platform really needs this,
7208 please contact vl@samba.org
7209 ****************************************************************************/
7211 void reply_writebmpx(struct smb_request
*req
)
7213 START_PROFILE(SMBwriteBmpx
);
7214 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7215 END_PROFILE(SMBwriteBmpx
);
7219 /****************************************************************************
7220 Reply to a SMBwritebs (write block multiplex secondary) request.
7221 Always reply with an error, if someone has a platform really needs this,
7222 please contact vl@samba.org
7223 ****************************************************************************/
7225 void reply_writebs(struct smb_request
*req
)
7227 START_PROFILE(SMBwriteBs
);
7228 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7229 END_PROFILE(SMBwriteBs
);
7233 /****************************************************************************
7234 Reply to a SMBgetattrE.
7235 ****************************************************************************/
7237 void reply_getattrE(struct smb_request
*req
)
7239 connection_struct
*conn
= req
->conn
;
7240 SMB_STRUCT_STAT sbuf
;
7243 struct timespec create_ts
;
7245 START_PROFILE(SMBgetattrE
);
7248 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7249 END_PROFILE(SMBgetattrE
);
7253 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
7255 if(!fsp
|| (fsp
->conn
!= conn
)) {
7256 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7257 END_PROFILE(SMBgetattrE
);
7261 /* Do an fstat on this file */
7262 if(fsp_stat(fsp
, &sbuf
)) {
7263 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
7264 END_PROFILE(SMBgetattrE
);
7268 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
7271 * Convert the times into dos times. Set create
7272 * date to be last modify date as UNIX doesn't save
7276 reply_outbuf(req
, 11, 0);
7278 create_ts
= get_create_timespec(&sbuf
,
7279 lp_fake_dir_create_times(SNUM(conn
)));
7280 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
7281 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
, sbuf
.st_atime
);
7282 /* Should we check pending modtime here ? JRA */
7283 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
, sbuf
.st_mtime
);
7286 SIVAL(req
->outbuf
, smb_vwv6
, 0);
7287 SIVAL(req
->outbuf
, smb_vwv8
, 0);
7289 uint32 allocation_size
= get_allocation_size(conn
,fsp
, &sbuf
);
7290 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)sbuf
.st_size
);
7291 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
7293 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
7295 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
7297 END_PROFILE(SMBgetattrE
);