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 unsigned int smb_echo_count
= 0;
33 extern uint32 global_client_caps
;
35 extern struct current_user current_user
;
36 extern bool global_encrypted_passwords_negotiated
;
38 /****************************************************************************
39 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
40 path or anything including wildcards.
41 We're assuming here that '/' is not the second byte in any multibyte char
42 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44 ****************************************************************************/
46 /* Custom version for processing POSIX paths. */
47 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
49 static NTSTATUS
check_path_syntax_internal(char *path
,
51 bool *p_last_component_contains_wcard
)
55 NTSTATUS ret
= NT_STATUS_OK
;
56 bool start_of_name_component
= True
;
57 bool stream_started
= false;
59 *p_last_component_contains_wcard
= False
;
66 return NT_STATUS_OBJECT_NAME_INVALID
;
69 return NT_STATUS_OBJECT_NAME_INVALID
;
71 if (strchr_m(&s
[1], ':')) {
72 return NT_STATUS_OBJECT_NAME_INVALID
;
74 if (StrCaseCmp(s
, ":$DATA") != 0) {
75 return NT_STATUS_INVALID_PARAMETER
;
81 if (!posix_path
&& !stream_started
&& *s
== ':') {
82 if (*p_last_component_contains_wcard
) {
83 return NT_STATUS_OBJECT_NAME_INVALID
;
85 /* Stream names allow more characters than file names.
86 We're overloading posix_path here to allow a wider
87 range of characters. If stream_started is true this
88 is still a Windows path even if posix_path is true.
91 stream_started
= true;
92 start_of_name_component
= false;
96 return NT_STATUS_OBJECT_NAME_INVALID
;
100 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
102 * Safe to assume is not the second part of a mb char
103 * as this is handled below.
105 /* Eat multiple '/' or '\\' */
106 while (IS_PATH_SEP(*s
,posix_path
)) {
109 if ((d
!= path
) && (*s
!= '\0')) {
110 /* We only care about non-leading or trailing '/' or '\\' */
114 start_of_name_component
= True
;
116 *p_last_component_contains_wcard
= False
;
120 if (start_of_name_component
) {
121 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
122 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
125 * No mb char starts with '.' so we're safe checking the directory separator here.
128 /* If we just added a '/' - delete it */
129 if ((d
> path
) && (*(d
-1) == '/')) {
134 /* Are we at the start ? Can't go back further if so. */
136 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
139 /* Go back one level... */
140 /* We know this is safe as '/' cannot be part of a mb sequence. */
141 /* NOTE - if this assumption is invalid we are not in good shape... */
142 /* Decrement d first as d points to the *next* char to write into. */
143 for (d
--; d
> path
; d
--) {
147 s
+= 2; /* Else go past the .. */
148 /* We're still at the start of a name component, just the previous one. */
151 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
163 if (*s
<= 0x1f || *s
== '|') {
164 return NT_STATUS_OBJECT_NAME_INVALID
;
172 *p_last_component_contains_wcard
= True
;
181 /* Get the size of the next MB character. */
182 next_codepoint(s
,&siz
);
200 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
202 return NT_STATUS_INVALID_PARAMETER
;
205 start_of_name_component
= False
;
213 /****************************************************************************
214 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
215 No wildcards allowed.
216 ****************************************************************************/
218 NTSTATUS
check_path_syntax(char *path
)
221 return check_path_syntax_internal(path
, False
, &ignore
);
224 /****************************************************************************
225 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
226 Wildcards allowed - p_contains_wcard returns true if the last component contained
228 ****************************************************************************/
230 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
232 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
235 /****************************************************************************
236 Check the path for a POSIX client.
237 We're assuming here that '/' is not the second byte in any multibyte char
238 set (a safe assumption).
239 ****************************************************************************/
241 NTSTATUS
check_path_syntax_posix(char *path
)
244 return check_path_syntax_internal(path
, True
, &ignore
);
247 /****************************************************************************
248 Pull a string and check the path allowing a wilcard - provide for error return.
249 ****************************************************************************/
251 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
259 bool *contains_wcard
)
266 ret
= srvstr_pull_buf_talloc(ctx
,
273 ret
= srvstr_pull_talloc(ctx
,
283 *err
= NT_STATUS_INVALID_PARAMETER
;
287 *contains_wcard
= False
;
289 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
291 * For a DFS path the function parse_dfs_path()
292 * will do the path processing, just make a copy.
298 if (lp_posix_pathnames()) {
299 *err
= check_path_syntax_posix(*pp_dest
);
301 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
307 /****************************************************************************
308 Pull a string and check the path - provide for error return.
309 ****************************************************************************/
311 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
325 ret
= srvstr_pull_buf_talloc(ctx
,
332 ret
= srvstr_pull_talloc(ctx
,
342 *err
= NT_STATUS_INVALID_PARAMETER
;
346 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
348 * For a DFS path the function parse_dfs_path()
349 * will do the path processing, just make a copy.
355 if (lp_posix_pathnames()) {
356 *err
= check_path_syntax_posix(*pp_dest
);
358 *err
= check_path_syntax(*pp_dest
);
364 /****************************************************************************
365 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
366 ****************************************************************************/
368 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
369 files_struct
*fsp
, struct current_user
*user
)
371 if (!(fsp
) || !(conn
)) {
372 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
375 if (((conn
) != (fsp
)->conn
) || user
->vuid
!= (fsp
)->vuid
) {
376 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
382 /****************************************************************************
383 Check if we have a correct fsp pointing to a file. Replacement for the
385 ****************************************************************************/
387 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
388 files_struct
*fsp
, struct current_user
*user
)
390 if (!check_fsp_open(conn
, req
, fsp
, user
)) {
393 if ((fsp
)->is_directory
) {
394 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
397 if ((fsp
)->fh
->fd
== -1) {
398 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
401 (fsp
)->num_smb_operations
++;
405 /****************************************************************************
406 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
407 ****************************************************************************/
409 bool fsp_belongs_conn(connection_struct
*conn
, struct smb_request
*req
,
410 files_struct
*fsp
, struct current_user
*user
)
412 if ((fsp
) && (conn
) && ((conn
)==(fsp
)->conn
)
413 && (current_user
.vuid
==(fsp
)->vuid
)) {
417 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
421 /****************************************************************************
422 Reply to a (netbios-level) special message.
423 ****************************************************************************/
425 void reply_special(char *inbuf
)
427 int msg_type
= CVAL(inbuf
,0);
428 int msg_flags
= CVAL(inbuf
,1);
433 * We only really use 4 bytes of the outbuf, but for the smb_setlen
434 * calculation & friends (srv_send_smb uses that) we need the full smb
437 char outbuf
[smb_size
];
439 static bool already_got_session
= False
;
443 memset(outbuf
, '\0', sizeof(outbuf
));
445 smb_setlen(outbuf
,0);
448 case 0x81: /* session request */
450 if (already_got_session
) {
451 exit_server_cleanly("multiple session request not permitted");
454 SCVAL(outbuf
,0,0x82);
456 if (name_len(inbuf
+4) > 50 ||
457 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
458 DEBUG(0,("Invalid name length in session request\n"));
461 name_extract(inbuf
,4,name1
);
462 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
463 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
466 set_local_machine_name(name1
, True
);
467 set_remote_machine_name(name2
, True
);
469 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
470 get_local_machine_name(), get_remote_machine_name(),
473 if (name_type
== 'R') {
474 /* We are being asked for a pathworks session ---
476 SCVAL(outbuf
, 0,0x83);
480 /* only add the client's machine name to the list
481 of possibly valid usernames if we are operating
482 in share mode security */
483 if (lp_security() == SEC_SHARE
) {
484 add_session_user(get_remote_machine_name());
487 reload_services(True
);
490 already_got_session
= True
;
493 case 0x89: /* session keepalive request
494 (some old clients produce this?) */
495 SCVAL(outbuf
,0,SMBkeepalive
);
499 case 0x82: /* positive session response */
500 case 0x83: /* negative session response */
501 case 0x84: /* retarget session response */
502 DEBUG(0,("Unexpected session response\n"));
505 case SMBkeepalive
: /* session keepalive */
510 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
511 msg_type
, msg_flags
));
513 srv_send_smb(smbd_server_fd(), outbuf
, false);
517 /****************************************************************************
519 conn POINTER CAN BE NULL HERE !
520 ****************************************************************************/
522 void reply_tcon(struct smb_request
*req
)
524 connection_struct
*conn
= req
->conn
;
526 char *service_buf
= NULL
;
527 char *password
= NULL
;
532 DATA_BLOB password_blob
;
533 TALLOC_CTX
*ctx
= talloc_tos();
535 START_PROFILE(SMBtcon
);
537 if (smb_buflen(req
->inbuf
) < 4) {
538 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
539 END_PROFILE(SMBtcon
);
543 p
= smb_buf(req
->inbuf
)+1;
544 p
+= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
,
545 &service_buf
, p
, STR_TERMINATE
) + 1;
546 pwlen
= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
,
547 &password
, p
, STR_TERMINATE
) + 1;
549 p
+= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
,
550 &dev
, p
, STR_TERMINATE
) + 1;
552 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
553 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
554 END_PROFILE(SMBtcon
);
557 p
= strrchr_m(service_buf
,'\\');
561 service
= service_buf
;
564 password_blob
= data_blob(password
, pwlen
+1);
566 conn
= make_connection(service
,password_blob
,dev
,req
->vuid
,&nt_status
);
569 data_blob_clear_free(&password_blob
);
572 reply_nterror(req
, nt_status
);
573 END_PROFILE(SMBtcon
);
577 reply_outbuf(req
, 2, 0);
578 SSVAL(req
->outbuf
,smb_vwv0
,max_recv
);
579 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
580 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
582 DEBUG(3,("tcon service=%s cnum=%d\n",
583 service
, conn
->cnum
));
585 END_PROFILE(SMBtcon
);
589 /****************************************************************************
590 Reply to a tcon and X.
591 conn POINTER CAN BE NULL HERE !
592 ****************************************************************************/
594 void reply_tcon_and_X(struct smb_request
*req
)
596 connection_struct
*conn
= req
->conn
;
597 char *service
= NULL
;
599 TALLOC_CTX
*ctx
= talloc_tos();
600 /* what the cleint thinks the device is */
601 char *client_devicetype
= NULL
;
602 /* what the server tells the client the share represents */
603 const char *server_devicetype
;
610 START_PROFILE(SMBtconX
);
613 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
614 END_PROFILE(SMBtconX
);
618 passlen
= SVAL(req
->inbuf
,smb_vwv3
);
619 tcon_flags
= SVAL(req
->inbuf
,smb_vwv2
);
621 /* we might have to close an old one */
622 if ((tcon_flags
& 0x1) && conn
) {
623 close_cnum(conn
,req
->vuid
);
628 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= smb_buflen(req
->inbuf
))) {
629 reply_doserror(req
, ERRDOS
, ERRbuftoosmall
);
630 END_PROFILE(SMBtconX
);
634 if (global_encrypted_passwords_negotiated
) {
635 password
= data_blob_talloc(talloc_tos(), smb_buf(req
->inbuf
),
637 if (lp_security() == SEC_SHARE
) {
639 * Security = share always has a pad byte
640 * after the password.
642 p
= smb_buf(req
->inbuf
) + passlen
+ 1;
644 p
= smb_buf(req
->inbuf
) + passlen
;
647 password
= data_blob_talloc(talloc_tos(), smb_buf(req
->inbuf
),
649 /* Ensure correct termination */
650 password
.data
[passlen
]=0;
651 p
= smb_buf(req
->inbuf
) + passlen
+ 1;
654 p
+= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
, &path
, p
,
658 data_blob_clear_free(&password
);
659 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
660 END_PROFILE(SMBtconX
);
665 * the service name can be either: \\server\share
666 * or share directly like on the DELL PowerVault 705
669 q
= strchr_m(path
+2,'\\');
671 data_blob_clear_free(&password
);
672 reply_doserror(req
, ERRDOS
, ERRnosuchshare
);
673 END_PROFILE(SMBtconX
);
681 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
682 &client_devicetype
, p
,
683 MIN(6,smb_bufrem(req
->inbuf
, p
)), STR_ASCII
);
685 if (client_devicetype
== NULL
) {
686 data_blob_clear_free(&password
);
687 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
688 END_PROFILE(SMBtconX
);
692 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
694 conn
= make_connection(service
, password
, client_devicetype
,
695 req
->vuid
, &nt_status
);
698 data_blob_clear_free(&password
);
701 reply_nterror(req
, nt_status
);
702 END_PROFILE(SMBtconX
);
707 server_devicetype
= "IPC";
708 else if ( IS_PRINT(conn
) )
709 server_devicetype
= "LPT1:";
711 server_devicetype
= "A:";
713 if (Protocol
< PROTOCOL_NT1
) {
714 reply_outbuf(req
, 2, 0);
715 if (message_push_string(&req
->outbuf
, server_devicetype
,
716 STR_TERMINATE
|STR_ASCII
) == -1) {
717 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
718 END_PROFILE(SMBtconX
);
722 /* NT sets the fstype of IPC$ to the null string */
723 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
725 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
726 /* Return permissions. */
730 reply_outbuf(req
, 7, 0);
733 perm1
= FILE_ALL_ACCESS
;
734 perm2
= FILE_ALL_ACCESS
;
736 perm1
= CAN_WRITE(conn
) ?
741 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
742 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
744 reply_outbuf(req
, 3, 0);
747 if ((message_push_string(&req
->outbuf
, server_devicetype
,
748 STR_TERMINATE
|STR_ASCII
) == -1)
749 || (message_push_string(&req
->outbuf
, fstype
,
750 STR_TERMINATE
) == -1)) {
751 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
752 END_PROFILE(SMBtconX
);
756 /* what does setting this bit do? It is set by NT4 and
757 may affect the ability to autorun mounted cdroms */
758 SSVAL(req
->outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
759 (lp_csc_policy(SNUM(conn
)) << 2));
761 init_dfsroot(conn
, req
->inbuf
, req
->outbuf
);
765 DEBUG(3,("tconX service=%s \n",
768 /* set the incoming and outgoing tid to the just created one */
769 SSVAL(req
->inbuf
,smb_tid
,conn
->cnum
);
770 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
772 END_PROFILE(SMBtconX
);
778 /****************************************************************************
779 Reply to an unknown type.
780 ****************************************************************************/
782 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
784 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
785 smb_fn_name(type
), type
, type
));
786 reply_doserror(req
, ERRSRV
, ERRunknownsmb
);
790 /****************************************************************************
792 conn POINTER CAN BE NULL HERE !
793 ****************************************************************************/
795 void reply_ioctl(struct smb_request
*req
)
797 connection_struct
*conn
= req
->conn
;
804 START_PROFILE(SMBioctl
);
807 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
808 END_PROFILE(SMBioctl
);
812 device
= SVAL(req
->inbuf
,smb_vwv1
);
813 function
= SVAL(req
->inbuf
,smb_vwv2
);
814 ioctl_code
= (device
<< 16) + function
;
816 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
818 switch (ioctl_code
) {
819 case IOCTL_QUERY_JOB_INFO
:
823 reply_doserror(req
, ERRSRV
, ERRnosupport
);
824 END_PROFILE(SMBioctl
);
828 reply_outbuf(req
, 8, replysize
+1);
829 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
830 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
831 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
832 p
= smb_buf(req
->outbuf
);
833 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
834 p
+= 1; /* Allow for alignment */
836 switch (ioctl_code
) {
837 case IOCTL_QUERY_JOB_INFO
:
839 files_struct
*fsp
= file_fsp(SVAL(req
->inbuf
,
842 reply_doserror(req
, ERRDOS
, ERRbadfid
);
843 END_PROFILE(SMBioctl
);
846 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
847 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
849 STR_TERMINATE
|STR_ASCII
);
851 srvstr_push((char *)req
->outbuf
, req
->flags2
,
852 p
+18, lp_servicename(SNUM(conn
)),
853 13, STR_TERMINATE
|STR_ASCII
);
861 END_PROFILE(SMBioctl
);
865 /****************************************************************************
866 Strange checkpath NTSTATUS mapping.
867 ****************************************************************************/
869 static NTSTATUS
map_checkpath_error(const char *inbuf
, NTSTATUS status
)
871 /* Strange DOS error code semantics only for checkpath... */
872 if (!(SVAL(inbuf
,smb_flg2
) & FLAGS2_32_BIT_ERROR_CODES
)) {
873 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
874 /* We need to map to ERRbadpath */
875 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
881 /****************************************************************************
882 Reply to a checkpath.
883 ****************************************************************************/
885 void reply_checkpath(struct smb_request
*req
)
887 connection_struct
*conn
= req
->conn
;
889 SMB_STRUCT_STAT sbuf
;
891 TALLOC_CTX
*ctx
= talloc_tos();
893 START_PROFILE(SMBcheckpath
);
895 srvstr_get_path(ctx
,(char *)req
->inbuf
, req
->flags2
, &name
,
896 smb_buf(req
->inbuf
) + 1, 0,
897 STR_TERMINATE
, &status
);
898 if (!NT_STATUS_IS_OK(status
)) {
899 status
= map_checkpath_error((char *)req
->inbuf
, status
);
900 reply_nterror(req
, status
);
901 END_PROFILE(SMBcheckpath
);
905 status
= resolve_dfspath(ctx
, conn
,
906 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
909 if (!NT_STATUS_IS_OK(status
)) {
910 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
911 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
913 END_PROFILE(SMBcheckpath
);
919 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->inbuf
,smb_vwv0
)));
921 status
= unix_convert(ctx
, conn
, name
, False
, &name
, NULL
, &sbuf
);
922 if (!NT_STATUS_IS_OK(status
)) {
926 status
= check_name(conn
, name
);
927 if (!NT_STATUS_IS_OK(status
)) {
928 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name
,nt_errstr(status
)));
932 if (!VALID_STAT(sbuf
) && (SMB_VFS_STAT(conn
,name
,&sbuf
) != 0)) {
933 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name
,strerror(errno
)));
934 status
= map_nt_error_from_unix(errno
);
938 if (!S_ISDIR(sbuf
.st_mode
)) {
939 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
941 END_PROFILE(SMBcheckpath
);
945 reply_outbuf(req
, 0, 0);
947 END_PROFILE(SMBcheckpath
);
952 END_PROFILE(SMBcheckpath
);
954 /* We special case this - as when a Windows machine
955 is parsing a path is steps through the components
956 one at a time - if a component fails it expects
957 ERRbadpath, not ERRbadfile.
959 status
= map_checkpath_error((char *)req
->inbuf
, status
);
960 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
962 * Windows returns different error codes if
963 * the parent directory is valid but not the
964 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
965 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
966 * if the path is invalid.
968 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
973 reply_nterror(req
, status
);
976 /****************************************************************************
978 ****************************************************************************/
980 void reply_getatr(struct smb_request
*req
)
982 connection_struct
*conn
= req
->conn
;
984 SMB_STRUCT_STAT sbuf
;
990 TALLOC_CTX
*ctx
= talloc_tos();
992 START_PROFILE(SMBgetatr
);
994 p
= smb_buf(req
->inbuf
) + 1;
995 p
+= srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
, p
,
996 0, STR_TERMINATE
, &status
);
997 if (!NT_STATUS_IS_OK(status
)) {
998 reply_nterror(req
, status
);
999 END_PROFILE(SMBgetatr
);
1003 status
= resolve_dfspath(ctx
, conn
,
1004 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1007 if (!NT_STATUS_IS_OK(status
)) {
1008 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1009 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1010 ERRSRV
, ERRbadpath
);
1011 END_PROFILE(SMBgetatr
);
1014 reply_nterror(req
, status
);
1015 END_PROFILE(SMBgetatr
);
1019 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1020 under WfWg - weird! */
1021 if (*fname
== '\0') {
1022 mode
= aHIDDEN
| aDIR
;
1023 if (!CAN_WRITE(conn
)) {
1029 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
,&sbuf
);
1030 if (!NT_STATUS_IS_OK(status
)) {
1031 reply_nterror(req
, status
);
1032 END_PROFILE(SMBgetatr
);
1035 status
= check_name(conn
, fname
);
1036 if (!NT_STATUS_IS_OK(status
)) {
1037 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname
,nt_errstr(status
)));
1038 reply_nterror(req
, status
);
1039 END_PROFILE(SMBgetatr
);
1042 if (!VALID_STAT(sbuf
) && (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0)) {
1043 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname
,strerror(errno
)));
1044 reply_unixerror(req
, ERRDOS
,ERRbadfile
);
1045 END_PROFILE(SMBgetatr
);
1049 mode
= dos_mode(conn
,fname
,&sbuf
);
1050 size
= sbuf
.st_size
;
1051 mtime
= sbuf
.st_mtime
;
1057 reply_outbuf(req
, 10, 0);
1059 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1060 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1061 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1063 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1065 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1067 if (Protocol
>= PROTOCOL_NT1
) {
1068 SSVAL(req
->outbuf
, smb_flg2
,
1069 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1072 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname
, mode
, (unsigned int)size
) );
1074 END_PROFILE(SMBgetatr
);
1078 /****************************************************************************
1080 ****************************************************************************/
1082 void reply_setatr(struct smb_request
*req
)
1084 struct timespec ts
[2];
1085 connection_struct
*conn
= req
->conn
;
1089 SMB_STRUCT_STAT sbuf
;
1092 TALLOC_CTX
*ctx
= talloc_tos();
1094 START_PROFILE(SMBsetatr
);
1099 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1103 p
= smb_buf(req
->inbuf
) + 1;
1104 p
+= srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
, p
,
1105 0, STR_TERMINATE
, &status
);
1106 if (!NT_STATUS_IS_OK(status
)) {
1107 reply_nterror(req
, status
);
1108 END_PROFILE(SMBsetatr
);
1112 status
= resolve_dfspath(ctx
, conn
,
1113 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1116 if (!NT_STATUS_IS_OK(status
)) {
1117 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1118 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1119 ERRSRV
, ERRbadpath
);
1120 END_PROFILE(SMBsetatr
);
1123 reply_nterror(req
, status
);
1124 END_PROFILE(SMBsetatr
);
1128 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
1129 if (!NT_STATUS_IS_OK(status
)) {
1130 reply_nterror(req
, status
);
1131 END_PROFILE(SMBsetatr
);
1135 status
= check_name(conn
, fname
);
1136 if (!NT_STATUS_IS_OK(status
)) {
1137 reply_nterror(req
, status
);
1138 END_PROFILE(SMBsetatr
);
1142 if (fname
[0] == '.' && fname
[1] == '\0') {
1144 * Not sure here is the right place to catch this
1145 * condition. Might be moved to somewhere else later -- vl
1147 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1148 END_PROFILE(SMBsetatr
);
1152 mode
= SVAL(req
->inbuf
,smb_vwv0
);
1153 mtime
= srv_make_unix_date3(req
->inbuf
+smb_vwv1
);
1155 ts
[1] = convert_time_t_to_timespec(mtime
);
1156 status
= smb_set_file_time(conn
, NULL
, fname
,
1158 if (!NT_STATUS_IS_OK(status
)) {
1159 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
1160 END_PROFILE(SMBsetatr
);
1164 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1165 if (VALID_STAT_OF_DIR(sbuf
))
1170 if (file_set_dosmode(conn
,fname
,mode
,&sbuf
,NULL
,false) != 0) {
1171 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
1172 END_PROFILE(SMBsetatr
);
1177 reply_outbuf(req
, 0, 0);
1179 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
1181 END_PROFILE(SMBsetatr
);
1185 /****************************************************************************
1187 ****************************************************************************/
1189 void reply_dskattr(struct smb_request
*req
)
1191 connection_struct
*conn
= req
->conn
;
1192 SMB_BIG_UINT dfree
,dsize
,bsize
;
1193 START_PROFILE(SMBdskattr
);
1195 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
1196 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
1197 END_PROFILE(SMBdskattr
);
1201 reply_outbuf(req
, 5, 0);
1203 if (Protocol
<= PROTOCOL_LANMAN2
) {
1204 double total_space
, free_space
;
1205 /* we need to scale this to a number that DOS6 can handle. We
1206 use floating point so we can handle large drives on systems
1207 that don't have 64 bit integers
1209 we end up displaying a maximum of 2G to DOS systems
1211 total_space
= dsize
* (double)bsize
;
1212 free_space
= dfree
* (double)bsize
;
1214 dsize
= (SMB_BIG_UINT
)((total_space
+63*512) / (64*512));
1215 dfree
= (SMB_BIG_UINT
)((free_space
+63*512) / (64*512));
1217 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1218 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1220 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1221 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1222 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1223 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1225 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1226 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1227 SSVAL(req
->outbuf
,smb_vwv2
,512);
1228 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1231 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1233 END_PROFILE(SMBdskattr
);
1237 /****************************************************************************
1239 Can be called from SMBsearch, SMBffirst or SMBfunique.
1240 ****************************************************************************/
1242 void reply_search(struct smb_request
*req
)
1244 connection_struct
*conn
= req
->conn
;
1246 char *directory
= NULL
;
1252 unsigned int numentries
= 0;
1253 unsigned int maxentries
= 0;
1254 bool finished
= False
;
1260 bool check_descend
= False
;
1261 bool expect_close
= False
;
1263 bool mask_contains_wcard
= False
;
1264 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1265 TALLOC_CTX
*ctx
= talloc_tos();
1266 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1268 START_PROFILE(SMBsearch
);
1271 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1272 END_PROFILE(SMBsearch
);
1276 if (lp_posix_pathnames()) {
1277 reply_unknown_new(req
, CVAL(req
->inbuf
, smb_com
));
1278 END_PROFILE(SMBsearch
);
1282 /* If we were called as SMBffirst then we must expect close. */
1283 if(CVAL(req
->inbuf
,smb_com
) == SMBffirst
) {
1284 expect_close
= True
;
1287 reply_outbuf(req
, 1, 3);
1288 maxentries
= SVAL(req
->inbuf
,smb_vwv0
);
1289 dirtype
= SVAL(req
->inbuf
,smb_vwv1
);
1290 p
= smb_buf(req
->inbuf
) + 1;
1291 p
+= srvstr_get_path_wcard(ctx
,
1299 &mask_contains_wcard
);
1300 if (!NT_STATUS_IS_OK(nt_status
)) {
1301 reply_nterror(req
, nt_status
);
1302 END_PROFILE(SMBsearch
);
1306 nt_status
= resolve_dfspath_wcard(ctx
, conn
,
1307 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1310 &mask_contains_wcard
);
1311 if (!NT_STATUS_IS_OK(nt_status
)) {
1312 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1313 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1314 ERRSRV
, ERRbadpath
);
1315 END_PROFILE(SMBsearch
);
1318 reply_nterror(req
, nt_status
);
1319 END_PROFILE(SMBsearch
);
1324 status_len
= SVAL(p
, 0);
1327 /* dirtype &= ~aDIR; */
1329 if (status_len
== 0) {
1330 SMB_STRUCT_STAT sbuf
;
1332 nt_status
= unix_convert(ctx
, conn
, path
, True
,
1333 &directory
, NULL
, &sbuf
);
1334 if (!NT_STATUS_IS_OK(nt_status
)) {
1335 reply_nterror(req
, nt_status
);
1336 END_PROFILE(SMBsearch
);
1340 nt_status
= check_name(conn
, directory
);
1341 if (!NT_STATUS_IS_OK(nt_status
)) {
1342 reply_nterror(req
, nt_status
);
1343 END_PROFILE(SMBsearch
);
1347 p
= strrchr_m(directory
,'/');
1350 directory
= talloc_strdup(ctx
,".");
1352 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1353 END_PROFILE(SMBsearch
);
1361 if (*directory
== '\0') {
1362 directory
= talloc_strdup(ctx
,".");
1364 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1365 END_PROFILE(SMBsearch
);
1369 memset((char *)status
,'\0',21);
1370 SCVAL(status
,0,(dirtype
& 0x1F));
1372 nt_status
= dptr_create(conn
,
1378 mask_contains_wcard
,
1381 if (!NT_STATUS_IS_OK(nt_status
)) {
1382 reply_nterror(req
, nt_status
);
1383 END_PROFILE(SMBsearch
);
1386 dptr_num
= dptr_dnum(conn
->dirptr
);
1390 memcpy(status
,p
,21);
1391 status_dirtype
= CVAL(status
,0) & 0x1F;
1392 if (status_dirtype
!= (dirtype
& 0x1F)) {
1393 dirtype
= status_dirtype
;
1396 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1397 if (!conn
->dirptr
) {
1400 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1401 mask
= dptr_wcard(dptr_num
);
1406 * For a 'continue' search we have no string. So
1407 * check from the initial saved string.
1409 mask_contains_wcard
= ms_has_wild(mask
);
1410 dirtype
= dptr_attr(dptr_num
);
1413 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1415 if ((dirtype
&0x1F) == aVOLID
) {
1416 char buf
[DIR_STRUCT_SIZE
];
1417 memcpy(buf
,status
,21);
1418 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1419 0,aVOLID
,0,!allow_long_path_components
)) {
1420 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1421 END_PROFILE(SMBsearch
);
1424 dptr_fill(buf
+12,dptr_num
);
1425 if (dptr_zero(buf
+12) && (status_len
==0)) {
1430 if (message_push_blob(&req
->outbuf
,
1431 data_blob_const(buf
, sizeof(buf
)))
1433 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1434 END_PROFILE(SMBsearch
);
1442 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1445 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1446 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1447 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
)) {
1448 check_descend
= True
;
1451 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1452 finished
= !get_dir_entry(ctx
,
1463 char buf
[DIR_STRUCT_SIZE
];
1464 memcpy(buf
,status
,21);
1465 if (!make_dir_struct(ctx
,
1472 !allow_long_path_components
)) {
1473 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1474 END_PROFILE(SMBsearch
);
1477 if (!dptr_fill(buf
+12,dptr_num
)) {
1480 if (message_push_blob(&req
->outbuf
,
1481 data_blob_const(buf
, sizeof(buf
)))
1483 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1484 END_PROFILE(SMBsearch
);
1494 /* If we were called as SMBffirst with smb_search_id == NULL
1495 and no entries were found then return error and close dirptr
1498 if (numentries
== 0) {
1499 dptr_close(&dptr_num
);
1500 } else if(expect_close
&& status_len
== 0) {
1501 /* Close the dptr - we know it's gone */
1502 dptr_close(&dptr_num
);
1505 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1506 if(dptr_num
>= 0 && CVAL(req
->inbuf
,smb_com
) == SMBfunique
) {
1507 dptr_close(&dptr_num
);
1510 if ((numentries
== 0) && !mask_contains_wcard
) {
1511 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1512 END_PROFILE(SMBsearch
);
1516 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1517 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1518 SCVAL(smb_buf(req
->outbuf
),0,5);
1519 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1521 /* The replies here are never long name. */
1522 SSVAL(req
->outbuf
, smb_flg2
,
1523 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1524 if (!allow_long_path_components
) {
1525 SSVAL(req
->outbuf
, smb_flg2
,
1526 SVAL(req
->outbuf
, smb_flg2
)
1527 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1530 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1531 SSVAL(req
->outbuf
, smb_flg2
,
1532 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1535 directory
= dptr_path(dptr_num
);
1538 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1539 smb_fn_name(CVAL(req
->inbuf
,smb_com
)),
1541 directory
? directory
: "./",
1546 END_PROFILE(SMBsearch
);
1550 /****************************************************************************
1551 Reply to a fclose (stop directory search).
1552 ****************************************************************************/
1554 void reply_fclose(struct smb_request
*req
)
1562 bool path_contains_wcard
= False
;
1563 TALLOC_CTX
*ctx
= talloc_tos();
1565 START_PROFILE(SMBfclose
);
1567 if (lp_posix_pathnames()) {
1568 reply_unknown_new(req
, CVAL(req
->inbuf
, smb_com
));
1569 END_PROFILE(SMBfclose
);
1573 p
= smb_buf(req
->inbuf
) + 1;
1574 p
+= srvstr_get_path_wcard(ctx
,
1582 &path_contains_wcard
);
1583 if (!NT_STATUS_IS_OK(err
)) {
1584 reply_nterror(req
, err
);
1585 END_PROFILE(SMBfclose
);
1589 status_len
= SVAL(p
,0);
1592 if (status_len
== 0) {
1593 reply_doserror(req
, ERRSRV
, ERRsrverror
);
1594 END_PROFILE(SMBfclose
);
1598 memcpy(status
,p
,21);
1600 if(dptr_fetch(status
+12,&dptr_num
)) {
1601 /* Close the dptr - we know it's gone */
1602 dptr_close(&dptr_num
);
1605 reply_outbuf(req
, 1, 0);
1606 SSVAL(req
->outbuf
,smb_vwv0
,0);
1608 DEBUG(3,("search close\n"));
1610 END_PROFILE(SMBfclose
);
1614 /****************************************************************************
1616 ****************************************************************************/
1618 void reply_open(struct smb_request
*req
)
1620 connection_struct
*conn
= req
->conn
;
1626 SMB_STRUCT_STAT sbuf
;
1633 uint32 create_disposition
;
1634 uint32 create_options
= 0;
1636 TALLOC_CTX
*ctx
= talloc_tos();
1638 START_PROFILE(SMBopen
);
1641 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1642 END_PROFILE(SMBopen
);
1646 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1647 deny_mode
= SVAL(req
->inbuf
,smb_vwv0
);
1648 dos_attr
= SVAL(req
->inbuf
,smb_vwv1
);
1650 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
1651 smb_buf(req
->inbuf
)+1, 0,
1652 STR_TERMINATE
, &status
);
1653 if (!NT_STATUS_IS_OK(status
)) {
1654 reply_nterror(req
, status
);
1655 END_PROFILE(SMBopen
);
1659 if (!map_open_params_to_ntcreate(
1660 fname
, deny_mode
, OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1661 &share_mode
, &create_disposition
, &create_options
)) {
1662 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1663 END_PROFILE(SMBopen
);
1667 status
= create_file(conn
, /* conn */
1669 0, /* root_dir_fid */
1671 access_mask
, /* access_mask */
1672 share_mode
, /* share_access */
1673 create_disposition
, /* create_disposition*/
1674 create_options
, /* create_options */
1675 dos_attr
, /* file_attributes */
1676 oplock_request
, /* oplock_request */
1677 0, /* allocation_size */
1684 if (!NT_STATUS_IS_OK(status
)) {
1685 if (open_was_deferred(req
->mid
)) {
1686 /* We have re-scheduled this call. */
1687 END_PROFILE(SMBopen
);
1690 reply_openerror(req
, status
);
1691 END_PROFILE(SMBopen
);
1695 size
= sbuf
.st_size
;
1696 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1697 mtime
= sbuf
.st_mtime
;
1700 DEBUG(3,("attempt to open a directory %s\n",fsp
->fsp_name
));
1701 close_file(fsp
,ERROR_CLOSE
);
1702 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1703 END_PROFILE(SMBopen
);
1707 reply_outbuf(req
, 7, 0);
1708 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1709 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1710 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1711 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1713 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1715 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1716 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1718 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1719 SCVAL(req
->outbuf
,smb_flg
,
1720 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1723 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1724 SCVAL(req
->outbuf
,smb_flg
,
1725 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1727 END_PROFILE(SMBopen
);
1731 /****************************************************************************
1732 Reply to an open and X.
1733 ****************************************************************************/
1735 void reply_open_and_X(struct smb_request
*req
)
1737 connection_struct
*conn
= req
->conn
;
1742 /* Breakout the oplock request bits so we can set the
1743 reply bits separately. */
1744 int ex_oplock_request
;
1745 int core_oplock_request
;
1748 int smb_sattr
= SVAL(req
->inbuf
,smb_vwv4
);
1749 uint32 smb_time
= make_unix_date3(req
->inbuf
+smb_vwv6
);
1754 SMB_STRUCT_STAT sbuf
;
1758 SMB_BIG_UINT allocation_size
;
1759 ssize_t retval
= -1;
1762 uint32 create_disposition
;
1763 uint32 create_options
= 0;
1764 TALLOC_CTX
*ctx
= talloc_tos();
1766 START_PROFILE(SMBopenX
);
1768 if (req
->wct
< 15) {
1769 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1770 END_PROFILE(SMBopenX
);
1774 open_flags
= SVAL(req
->inbuf
,smb_vwv2
);
1775 deny_mode
= SVAL(req
->inbuf
,smb_vwv3
);
1776 smb_attr
= SVAL(req
->inbuf
,smb_vwv5
);
1777 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1778 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1779 oplock_request
= ex_oplock_request
| core_oplock_request
;
1780 smb_ofun
= SVAL(req
->inbuf
,smb_vwv8
);
1781 allocation_size
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv9
);
1783 /* If it's an IPC, pass off the pipe handler. */
1785 if (lp_nt_pipe_support()) {
1786 reply_open_pipe_and_X(conn
, req
);
1788 reply_doserror(req
, ERRSRV
, ERRaccess
);
1790 END_PROFILE(SMBopenX
);
1794 /* XXXX we need to handle passed times, sattr and flags */
1795 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
1796 smb_buf(req
->inbuf
), 0, STR_TERMINATE
,
1798 if (!NT_STATUS_IS_OK(status
)) {
1799 reply_nterror(req
, status
);
1800 END_PROFILE(SMBopenX
);
1804 if (!map_open_params_to_ntcreate(
1805 fname
, deny_mode
, smb_ofun
, &access_mask
,
1806 &share_mode
, &create_disposition
, &create_options
)) {
1807 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1808 END_PROFILE(SMBopenX
);
1812 status
= create_file(conn
, /* conn */
1814 0, /* root_dir_fid */
1816 access_mask
, /* access_mask */
1817 share_mode
, /* share_access */
1818 create_disposition
, /* create_disposition*/
1819 create_options
, /* create_options */
1820 smb_attr
, /* file_attributes */
1821 oplock_request
, /* oplock_request */
1822 0, /* allocation_size */
1826 &smb_action
, /* pinfo */
1829 if (!NT_STATUS_IS_OK(status
)) {
1830 END_PROFILE(SMBopenX
);
1831 if (open_was_deferred(req
->mid
)) {
1832 /* We have re-scheduled this call. */
1835 reply_openerror(req
, status
);
1839 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1840 if the file is truncated or created. */
1841 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1842 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1843 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1844 close_file(fsp
,ERROR_CLOSE
);
1845 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1846 END_PROFILE(SMBopenX
);
1849 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1851 close_file(fsp
,ERROR_CLOSE
);
1852 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1853 END_PROFILE(SMBopenX
);
1856 sbuf
.st_size
= get_allocation_size(conn
,fsp
,&sbuf
);
1859 fattr
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
1860 mtime
= sbuf
.st_mtime
;
1862 close_file(fsp
,ERROR_CLOSE
);
1863 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
1864 END_PROFILE(SMBopenX
);
1868 /* If the caller set the extended oplock request bit
1869 and we granted one (by whatever means) - set the
1870 correct bit for extended oplock reply.
1873 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1874 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1877 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1878 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1881 /* If the caller set the core oplock request bit
1882 and we granted one (by whatever means) - set the
1883 correct bit for core oplock reply.
1886 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1887 reply_outbuf(req
, 19, 0);
1889 reply_outbuf(req
, 15, 0);
1892 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1893 SCVAL(req
->outbuf
, smb_flg
,
1894 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1897 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1898 SCVAL(req
->outbuf
, smb_flg
,
1899 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1902 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
1903 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
1904 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1905 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
1907 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
1909 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
1910 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
1911 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
1913 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1914 SIVAL(req
->outbuf
, smb_vwv15
, STD_RIGHT_ALL_ACCESS
);
1917 END_PROFILE(SMBopenX
);
1922 /****************************************************************************
1923 Reply to a SMBulogoffX.
1924 ****************************************************************************/
1926 void reply_ulogoffX(struct smb_request
*req
)
1930 START_PROFILE(SMBulogoffX
);
1932 vuser
= get_valid_user_struct(req
->vuid
);
1935 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1939 /* in user level security we are supposed to close any files
1940 open by this user */
1941 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
1942 file_close_user(req
->vuid
);
1945 invalidate_vuid(req
->vuid
);
1947 reply_outbuf(req
, 2, 0);
1949 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
1951 END_PROFILE(SMBulogoffX
);
1955 /****************************************************************************
1956 Reply to a mknew or a create.
1957 ****************************************************************************/
1959 void reply_mknew(struct smb_request
*req
)
1961 connection_struct
*conn
= req
->conn
;
1965 struct timespec ts
[2];
1967 int oplock_request
= 0;
1968 SMB_STRUCT_STAT sbuf
;
1970 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
1971 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
1972 uint32 create_disposition
;
1973 uint32 create_options
= 0;
1974 TALLOC_CTX
*ctx
= talloc_tos();
1976 START_PROFILE(SMBcreate
);
1979 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1980 END_PROFILE(SMBcreate
);
1984 fattr
= SVAL(req
->inbuf
,smb_vwv0
);
1985 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1986 com
= SVAL(req
->inbuf
,smb_com
);
1988 ts
[1] =convert_time_t_to_timespec(
1989 srv_make_unix_date3(req
->inbuf
+ smb_vwv1
));
1992 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
1993 smb_buf(req
->inbuf
) + 1, 0,
1994 STR_TERMINATE
, &status
);
1995 if (!NT_STATUS_IS_OK(status
)) {
1996 reply_nterror(req
, status
);
1997 END_PROFILE(SMBcreate
);
2001 if (fattr
& aVOLID
) {
2002 DEBUG(0,("Attempt to create file (%s) with volid set - "
2003 "please report this\n", fname
));
2006 if(com
== SMBmknew
) {
2007 /* We should fail if file exists. */
2008 create_disposition
= FILE_CREATE
;
2010 /* Create if file doesn't exist, truncate if it does. */
2011 create_disposition
= FILE_OVERWRITE_IF
;
2014 status
= create_file(conn
, /* conn */
2016 0, /* root_dir_fid */
2018 access_mask
, /* access_mask */
2019 share_mode
, /* share_access */
2020 create_disposition
, /* create_disposition*/
2021 create_options
, /* create_options */
2022 fattr
, /* file_attributes */
2023 oplock_request
, /* oplock_request */
2024 0, /* allocation_size */
2031 if (!NT_STATUS_IS_OK(status
)) {
2032 END_PROFILE(SMBcreate
);
2033 if (open_was_deferred(req
->mid
)) {
2034 /* We have re-scheduled this call. */
2037 reply_openerror(req
, status
);
2041 ts
[0] = get_atimespec(&sbuf
); /* atime. */
2042 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &sbuf
, ts
, true);
2043 if (!NT_STATUS_IS_OK(status
)) {
2044 END_PROFILE(SMBcreate
);
2045 reply_openerror(req
, status
);
2049 reply_outbuf(req
, 1, 0);
2050 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2052 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2053 SCVAL(req
->outbuf
,smb_flg
,
2054 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2057 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2058 SCVAL(req
->outbuf
,smb_flg
,
2059 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2062 DEBUG( 2, ( "reply_mknew: file %s\n", fsp
->fsp_name
) );
2063 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2064 fsp
->fsp_name
, fsp
->fh
->fd
, (unsigned int)fattr
) );
2066 END_PROFILE(SMBcreate
);
2070 /****************************************************************************
2071 Reply to a create temporary file.
2072 ****************************************************************************/
2074 void reply_ctemp(struct smb_request
*req
)
2076 connection_struct
*conn
= req
->conn
;
2082 SMB_STRUCT_STAT sbuf
;
2085 TALLOC_CTX
*ctx
= talloc_tos();
2087 START_PROFILE(SMBctemp
);
2090 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2091 END_PROFILE(SMBctemp
);
2095 fattr
= SVAL(req
->inbuf
,smb_vwv0
);
2096 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2098 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &fname
,
2099 smb_buf(req
->inbuf
)+1, 0, STR_TERMINATE
,
2101 if (!NT_STATUS_IS_OK(status
)) {
2102 reply_nterror(req
, status
);
2103 END_PROFILE(SMBctemp
);
2107 fname
= talloc_asprintf(ctx
,
2111 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2115 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2116 END_PROFILE(SMBctemp
);
2120 status
= resolve_dfspath(ctx
, conn
,
2121 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2124 if (!NT_STATUS_IS_OK(status
)) {
2125 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2126 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2127 ERRSRV
, ERRbadpath
);
2128 END_PROFILE(SMBctemp
);
2131 reply_nterror(req
, status
);
2132 END_PROFILE(SMBctemp
);
2136 status
= unix_convert(ctx
, conn
, fname
, False
, &fname
, NULL
, &sbuf
);
2137 if (!NT_STATUS_IS_OK(status
)) {
2138 reply_nterror(req
, status
);
2139 END_PROFILE(SMBctemp
);
2143 status
= check_name(conn
, CONST_DISCARD(char *,fname
));
2144 if (!NT_STATUS_IS_OK(status
)) {
2145 reply_nterror(req
, status
);
2146 END_PROFILE(SMBctemp
);
2150 tmpfd
= smb_mkstemp(fname
);
2152 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
2153 END_PROFILE(SMBctemp
);
2157 SMB_VFS_STAT(conn
,fname
,&sbuf
);
2159 /* We should fail if file does not exist. */
2160 status
= open_file_ntcreate(conn
, req
, fname
, &sbuf
,
2161 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
,
2162 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
2169 /* close fd from smb_mkstemp() */
2172 if (!NT_STATUS_IS_OK(status
)) {
2173 if (open_was_deferred(req
->mid
)) {
2174 /* We have re-scheduled this call. */
2175 END_PROFILE(SMBctemp
);
2178 reply_openerror(req
, status
);
2179 END_PROFILE(SMBctemp
);
2183 reply_outbuf(req
, 1, 0);
2184 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2186 /* the returned filename is relative to the directory */
2187 s
= strrchr_m(fsp
->fsp_name
, '/');
2195 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2196 thing in the byte section. JRA */
2197 SSVALS(p
, 0, -1); /* what is this? not in spec */
2199 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2201 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2202 END_PROFILE(SMBctemp
);
2206 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2207 SCVAL(req
->outbuf
, smb_flg
,
2208 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2211 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2212 SCVAL(req
->outbuf
, smb_flg
,
2213 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2216 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp
->fsp_name
) );
2217 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp
->fsp_name
,
2218 fsp
->fh
->fd
, (unsigned int)sbuf
.st_mode
) );
2220 END_PROFILE(SMBctemp
);
2224 /*******************************************************************
2225 Check if a user is allowed to rename a file.
2226 ********************************************************************/
2228 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2229 uint16 dirtype
, SMB_STRUCT_STAT
*pst
)
2233 if (!CAN_WRITE(conn
)) {
2234 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2237 fmode
= dos_mode(conn
, fsp
->fsp_name
, pst
);
2238 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
)) {
2239 return NT_STATUS_NO_SUCH_FILE
;
2242 if (S_ISDIR(pst
->st_mode
)) {
2243 return NT_STATUS_OK
;
2246 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2247 return NT_STATUS_OK
;
2250 return NT_STATUS_ACCESS_DENIED
;
2253 /*******************************************************************
2254 * unlink a file with all relevant access checks
2255 *******************************************************************/
2257 static NTSTATUS
do_unlink(connection_struct
*conn
,
2258 struct smb_request
*req
,
2262 SMB_STRUCT_STAT sbuf
;
2265 uint32 dirtype_orig
= dirtype
;
2268 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname
, dirtype
));
2270 if (!CAN_WRITE(conn
)) {
2271 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2274 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
) != 0) {
2275 return map_nt_error_from_unix(errno
);
2278 fattr
= dos_mode(conn
,fname
,&sbuf
);
2280 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2281 dirtype
= aDIR
|aARCH
|aRONLY
;
2284 dirtype
&= (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
);
2286 return NT_STATUS_NO_SUCH_FILE
;
2289 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2291 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2293 return NT_STATUS_NO_SUCH_FILE
;
2296 if (dirtype_orig
& 0x8000) {
2297 /* These will never be set for POSIX. */
2298 return NT_STATUS_NO_SUCH_FILE
;
2302 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2303 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2306 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2307 return NT_STATUS_NO_SUCH_FILE
;
2310 if (dirtype
& 0xFF00) {
2311 /* These will never be set for POSIX. */
2312 return NT_STATUS_NO_SUCH_FILE
;
2317 return NT_STATUS_NO_SUCH_FILE
;
2320 /* Can't delete a directory. */
2322 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2327 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
2328 return NT_STATUS_OBJECT_NAME_INVALID
;
2329 #endif /* JRATEST */
2331 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2333 On a Windows share, a file with read-only dosmode can be opened with
2334 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2335 fails with NT_STATUS_CANNOT_DELETE error.
2337 This semantic causes a problem that a user can not
2338 rename a file with read-only dosmode on a Samba share
2339 from a Windows command prompt (i.e. cmd.exe, but can rename
2340 from Windows Explorer).
2343 if (!lp_delete_readonly(SNUM(conn
))) {
2344 if (fattr
& aRONLY
) {
2345 return NT_STATUS_CANNOT_DELETE
;
2349 /* On open checks the open itself will check the share mode, so
2350 don't do it here as we'll get it wrong. */
2352 status
= create_file_unixpath
2356 DELETE_ACCESS
, /* access_mask */
2357 FILE_SHARE_NONE
, /* share_access */
2358 FILE_OPEN
, /* create_disposition*/
2359 FILE_NON_DIRECTORY_FILE
, /* create_options */
2360 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
2361 0, /* oplock_request */
2362 0, /* allocation_size */
2369 if (!NT_STATUS_IS_OK(status
)) {
2370 DEBUG(10, ("create_file_unixpath failed: %s\n",
2371 nt_errstr(status
)));
2375 /* The set is across all open files on this dev/inode pair. */
2376 if (!set_delete_on_close(fsp
, True
, ¤t_user
.ut
)) {
2377 close_file(fsp
, NORMAL_CLOSE
);
2378 return NT_STATUS_ACCESS_DENIED
;
2381 return close_file(fsp
,NORMAL_CLOSE
);
2384 /****************************************************************************
2385 The guts of the unlink command, split out so it may be called by the NT SMB
2387 ****************************************************************************/
2389 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2390 uint32 dirtype
, const char *name_in
, bool has_wild
)
2392 const char *directory
= NULL
;
2397 NTSTATUS status
= NT_STATUS_OK
;
2398 SMB_STRUCT_STAT sbuf
;
2399 TALLOC_CTX
*ctx
= talloc_tos();
2401 status
= unix_convert(ctx
, conn
, name_in
, has_wild
, &name
, NULL
, &sbuf
);
2402 if (!NT_STATUS_IS_OK(status
)) {
2406 p
= strrchr_m(name
,'/');
2408 directory
= talloc_strdup(ctx
, ".");
2410 return NT_STATUS_NO_MEMORY
;
2420 * We should only check the mangled cache
2421 * here if unix_convert failed. This means
2422 * that the path in 'mask' doesn't exist
2423 * on the file system and so we need to look
2424 * for a possible mangle. This patch from
2425 * Tine Smukavec <valentin.smukavec@hermes.si>.
2428 if (!VALID_STAT(sbuf
) && mangle_is_mangled(mask
,conn
->params
)) {
2429 char *new_mask
= NULL
;
2430 mangle_lookup_name_from_8_3(ctx
,
2440 directory
= talloc_asprintf(ctx
,
2445 return NT_STATUS_NO_MEMORY
;
2448 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2451 status
= check_name(conn
, directory
);
2452 if (!NT_STATUS_IS_OK(status
)) {
2456 status
= do_unlink(conn
, req
, directory
, dirtype
);
2457 if (!NT_STATUS_IS_OK(status
)) {
2463 struct smb_Dir
*dir_hnd
= NULL
;
2467 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == aDIR
) {
2468 return NT_STATUS_OBJECT_NAME_INVALID
;
2471 if (strequal(mask
,"????????.???")) {
2476 status
= check_name(conn
, directory
);
2477 if (!NT_STATUS_IS_OK(status
)) {
2481 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
,
2483 if (dir_hnd
== NULL
) {
2484 return map_nt_error_from_unix(errno
);
2487 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2488 the pattern matches against the long name, otherwise the short name
2489 We don't implement this yet XXXX
2492 status
= NT_STATUS_NO_SUCH_FILE
;
2494 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
2498 if (!is_visible_file(conn
, directory
, dname
, &st
, True
)) {
2502 /* Quick check for "." and ".." */
2503 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2507 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
2511 fname
= talloc_asprintf(ctx
, "%s/%s",
2515 return NT_STATUS_NO_MEMORY
;
2518 status
= check_name(conn
, fname
);
2519 if (!NT_STATUS_IS_OK(status
)) {
2520 TALLOC_FREE(dir_hnd
);
2524 status
= do_unlink(conn
, req
, fname
, dirtype
);
2525 if (!NT_STATUS_IS_OK(status
)) {
2531 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2536 TALLOC_FREE(dir_hnd
);
2539 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2540 status
= map_nt_error_from_unix(errno
);
2546 /****************************************************************************
2548 ****************************************************************************/
2550 void reply_unlink(struct smb_request
*req
)
2552 connection_struct
*conn
= req
->conn
;
2556 bool path_contains_wcard
= False
;
2557 TALLOC_CTX
*ctx
= talloc_tos();
2559 START_PROFILE(SMBunlink
);
2562 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2563 END_PROFILE(SMBunlink
);
2567 dirtype
= SVAL(req
->inbuf
,smb_vwv0
);
2569 srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &name
,
2570 smb_buf(req
->inbuf
) + 1, 0,
2571 STR_TERMINATE
, &status
, &path_contains_wcard
);
2572 if (!NT_STATUS_IS_OK(status
)) {
2573 reply_nterror(req
, status
);
2574 END_PROFILE(SMBunlink
);
2578 status
= resolve_dfspath_wcard(ctx
, conn
,
2579 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2582 &path_contains_wcard
);
2583 if (!NT_STATUS_IS_OK(status
)) {
2584 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2585 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2586 ERRSRV
, ERRbadpath
);
2587 END_PROFILE(SMBunlink
);
2590 reply_nterror(req
, status
);
2591 END_PROFILE(SMBunlink
);
2595 DEBUG(3,("reply_unlink : %s\n",name
));
2597 status
= unlink_internals(conn
, req
, dirtype
, name
,
2598 path_contains_wcard
);
2599 if (!NT_STATUS_IS_OK(status
)) {
2600 if (open_was_deferred(req
->mid
)) {
2601 /* We have re-scheduled this call. */
2602 END_PROFILE(SMBunlink
);
2605 reply_nterror(req
, status
);
2606 END_PROFILE(SMBunlink
);
2610 reply_outbuf(req
, 0, 0);
2611 END_PROFILE(SMBunlink
);
2616 /****************************************************************************
2618 ****************************************************************************/
2620 static void fail_readraw(void)
2622 const char *errstr
= talloc_asprintf(talloc_tos(),
2623 "FAIL ! reply_readbraw: socket write fail (%s)",
2628 exit_server_cleanly(errstr
);
2631 /****************************************************************************
2632 Fake (read/write) sendfile. Returns -1 on read or write fail.
2633 ****************************************************************************/
2635 static ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
,
2639 size_t tosend
= nread
;
2646 bufsize
= MIN(nread
, 65536);
2648 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2652 while (tosend
> 0) {
2656 if (tosend
> bufsize
) {
2661 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2667 /* If we had a short read, fill with zeros. */
2668 if (ret
< cur_read
) {
2669 memset(buf
, '\0', cur_read
- ret
);
2672 if (write_data(smbd_server_fd(),buf
,cur_read
) != cur_read
) {
2677 startpos
+= cur_read
;
2681 return (ssize_t
)nread
;
2684 /****************************************************************************
2685 Return a readbraw error (4 bytes of zero).
2686 ****************************************************************************/
2688 static void reply_readbraw_error(void)
2692 if (write_data(smbd_server_fd(),header
,4) != 4) {
2697 /****************************************************************************
2698 Use sendfile in readbraw.
2699 ****************************************************************************/
2701 void send_file_readbraw(connection_struct
*conn
,
2707 char *outbuf
= NULL
;
2710 #if defined(WITH_SENDFILE)
2712 * We can only use sendfile on a non-chained packet
2713 * but we can use on a non-oplocked file. tridge proved this
2714 * on a train in Germany :-). JRA.
2715 * reply_readbraw has already checked the length.
2718 if ( (chain_size
== 0) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
2719 (fsp
->wcp
== NULL
) && lp_use_sendfile(SNUM(conn
)) ) {
2721 DATA_BLOB header_blob
;
2723 _smb_setlen(header
,nread
);
2724 header_blob
= data_blob_const(header
, 4);
2726 if (SMB_VFS_SENDFILE(smbd_server_fd(), fsp
,
2727 &header_blob
, startpos
, nread
) == -1) {
2728 /* Returning ENOSYS means no data at all was sent.
2729 * Do this as a normal read. */
2730 if (errno
== ENOSYS
) {
2731 goto normal_readbraw
;
2735 * Special hack for broken Linux with no working sendfile. If we
2736 * return EINTR we sent the header but not the rest of the data.
2737 * Fake this up by doing read/write calls.
2739 if (errno
== EINTR
) {
2740 /* Ensure we don't do this again. */
2741 set_use_sendfile(SNUM(conn
), False
);
2742 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2744 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
2745 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2746 fsp
->fsp_name
, strerror(errno
) ));
2747 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2752 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2753 fsp
->fsp_name
, strerror(errno
) ));
2754 exit_server_cleanly("send_file_readbraw sendfile failed");
2763 outbuf
= TALLOC_ARRAY(NULL
, char, nread
+4);
2765 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2766 (unsigned)(nread
+4)));
2767 reply_readbraw_error();
2772 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2773 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2782 _smb_setlen(outbuf
,ret
);
2783 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
2786 TALLOC_FREE(outbuf
);
2789 /****************************************************************************
2790 Reply to a readbraw (core+ protocol).
2791 ****************************************************************************/
2793 void reply_readbraw(struct smb_request
*req
)
2795 connection_struct
*conn
= req
->conn
;
2796 ssize_t maxcount
,mincount
;
2803 START_PROFILE(SMBreadbraw
);
2805 if (srv_is_signing_active() || is_encrypted_packet(req
->inbuf
)) {
2806 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2807 "raw reads/writes are disallowed.");
2811 reply_readbraw_error();
2812 END_PROFILE(SMBreadbraw
);
2817 * Special check if an oplock break has been issued
2818 * and the readraw request croses on the wire, we must
2819 * return a zero length response here.
2822 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
2825 * We have to do a check_fsp by hand here, as
2826 * we must always return 4 zero bytes on error,
2830 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
2831 current_user
.vuid
!= fsp
->vuid
||
2832 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
2834 * fsp could be NULL here so use the value from the packet. JRA.
2836 DEBUG(3,("reply_readbraw: fnum %d not valid "
2838 (int)SVAL(req
->inbuf
,smb_vwv0
)));
2839 reply_readbraw_error();
2840 END_PROFILE(SMBreadbraw
);
2844 /* Do a "by hand" version of CHECK_READ. */
2845 if (!(fsp
->can_read
||
2846 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
2847 (fsp
->access_mask
& FILE_EXECUTE
)))) {
2848 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2849 (int)SVAL(req
->inbuf
,smb_vwv0
)));
2850 reply_readbraw_error();
2851 END_PROFILE(SMBreadbraw
);
2855 flush_write_cache(fsp
, READRAW_FLUSH
);
2857 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv1
);
2858 if(req
->wct
== 10) {
2860 * This is a large offset (64 bit) read.
2862 #ifdef LARGE_SMB_OFF_T
2864 startpos
|= (((SMB_OFF_T
)IVAL(req
->inbuf
,smb_vwv8
)) << 32);
2866 #else /* !LARGE_SMB_OFF_T */
2869 * Ensure we haven't been sent a >32 bit offset.
2872 if(IVAL(req
->inbuf
,smb_vwv8
) != 0) {
2873 DEBUG(0,("reply_readbraw: large offset "
2874 "(%x << 32) used and we don't support "
2875 "64 bit offsets.\n",
2876 (unsigned int)IVAL(req
->inbuf
,smb_vwv8
) ));
2877 reply_readbraw_error();
2878 END_PROFILE(SMBreadbraw
);
2882 #endif /* LARGE_SMB_OFF_T */
2885 DEBUG(0,("reply_readbraw: negative 64 bit "
2886 "readraw offset (%.0f) !\n",
2887 (double)startpos
));
2888 reply_readbraw_error();
2889 END_PROFILE(SMBreadbraw
);
2894 maxcount
= (SVAL(req
->inbuf
,smb_vwv3
) & 0xFFFF);
2895 mincount
= (SVAL(req
->inbuf
,smb_vwv4
) & 0xFFFF);
2897 /* ensure we don't overrun the packet size */
2898 maxcount
= MIN(65535,maxcount
);
2900 if (is_locked(fsp
,(uint32
)req
->smbpid
,
2901 (SMB_BIG_UINT
)maxcount
,
2902 (SMB_BIG_UINT
)startpos
,
2904 reply_readbraw_error();
2905 END_PROFILE(SMBreadbraw
);
2909 if (SMB_VFS_FSTAT(fsp
, &st
) == 0) {
2913 if (startpos
>= size
) {
2916 nread
= MIN(maxcount
,(size
- startpos
));
2919 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2920 if (nread
< mincount
)
2924 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2925 "min=%lu nread=%lu\n",
2926 fsp
->fnum
, (double)startpos
,
2927 (unsigned long)maxcount
,
2928 (unsigned long)mincount
,
2929 (unsigned long)nread
) );
2931 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
);
2933 DEBUG(5,("reply_readbraw finished\n"));
2934 END_PROFILE(SMBreadbraw
);
2938 #define DBGC_CLASS DBGC_LOCKING
2940 /****************************************************************************
2941 Reply to a lockread (core+ protocol).
2942 ****************************************************************************/
2944 void reply_lockread(struct smb_request
*req
)
2946 connection_struct
*conn
= req
->conn
;
2953 struct byte_range_lock
*br_lck
= NULL
;
2956 START_PROFILE(SMBlockread
);
2959 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2960 END_PROFILE(SMBlockread
);
2964 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
2966 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
2967 END_PROFILE(SMBlockread
);
2971 if (!CHECK_READ(fsp
,req
->inbuf
)) {
2972 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
2973 END_PROFILE(SMBlockread
);
2977 release_level_2_oplocks_on_change(fsp
);
2979 numtoread
= SVAL(req
->inbuf
,smb_vwv1
);
2980 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
2982 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
2984 reply_outbuf(req
, 5, numtoread
+ 3);
2986 data
= smb_buf(req
->outbuf
) + 3;
2989 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2990 * protocol request that predates the read/write lock concept.
2991 * Thus instead of asking for a read lock here we need to ask
2992 * for a write lock. JRA.
2993 * Note that the requested lock size is unaffected by max_recv.
2996 br_lck
= do_lock(smbd_messaging_context(),
2999 (SMB_BIG_UINT
)numtoread
,
3000 (SMB_BIG_UINT
)startpos
,
3003 False
, /* Non-blocking lock. */
3006 TALLOC_FREE(br_lck
);
3008 if (NT_STATUS_V(status
)) {
3009 reply_nterror(req
, status
);
3010 END_PROFILE(SMBlockread
);
3015 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3018 if (numtoread
> max_recv
) {
3019 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3020 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3021 (unsigned int)numtoread
, (unsigned int)max_recv
));
3022 numtoread
= MIN(numtoread
,max_recv
);
3024 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3027 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3028 END_PROFILE(SMBlockread
);
3032 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3034 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3035 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3036 p
= smb_buf(req
->outbuf
);
3037 SCVAL(p
,0,0); /* pad byte. */
3040 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3041 fsp
->fnum
, (int)numtoread
, (int)nread
));
3043 END_PROFILE(SMBlockread
);
3048 #define DBGC_CLASS DBGC_ALL
3050 /****************************************************************************
3052 ****************************************************************************/
3054 void reply_read(struct smb_request
*req
)
3056 connection_struct
*conn
= req
->conn
;
3064 START_PROFILE(SMBread
);
3067 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3068 END_PROFILE(SMBread
);
3072 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3074 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
3075 END_PROFILE(SMBread
);
3079 if (!CHECK_READ(fsp
,req
->inbuf
)) {
3080 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3081 END_PROFILE(SMBread
);
3085 numtoread
= SVAL(req
->inbuf
,smb_vwv1
);
3086 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
3088 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3091 * The requested read size cannot be greater than max_recv. JRA.
3093 if (numtoread
> max_recv
) {
3094 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3095 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3096 (unsigned int)numtoread
, (unsigned int)max_recv
));
3097 numtoread
= MIN(numtoread
,max_recv
);
3100 reply_outbuf(req
, 5, numtoread
+3);
3102 data
= smb_buf(req
->outbuf
) + 3;
3104 if (is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtoread
,
3105 (SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
3106 reply_doserror(req
, ERRDOS
,ERRlock
);
3107 END_PROFILE(SMBread
);
3112 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3115 reply_unixerror(req
, ERRDOS
,ERRnoaccess
);
3116 END_PROFILE(SMBread
);
3120 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3122 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3123 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3124 SCVAL(smb_buf(req
->outbuf
),0,1);
3125 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3127 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3128 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3130 END_PROFILE(SMBread
);
3134 /****************************************************************************
3136 ****************************************************************************/
3138 static int setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3143 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3144 data
= smb_buf(outbuf
);
3146 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3148 SCVAL(outbuf
,smb_vwv0
,0xFF);
3149 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3150 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3151 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
3152 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3153 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
3154 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3155 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3159 /****************************************************************************
3160 Reply to a read and X - possibly using sendfile.
3161 ****************************************************************************/
3163 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3164 files_struct
*fsp
, SMB_OFF_T startpos
,
3167 SMB_STRUCT_STAT sbuf
;
3170 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
3171 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3175 if (startpos
> sbuf
.st_size
) {
3177 } else if (smb_maxcnt
> (sbuf
.st_size
- startpos
)) {
3178 smb_maxcnt
= (sbuf
.st_size
- startpos
);
3181 if (smb_maxcnt
== 0) {
3185 #if defined(WITH_SENDFILE)
3187 * We can only use sendfile on a non-chained packet
3188 * but we can use on a non-oplocked file. tridge proved this
3189 * on a train in Germany :-). JRA.
3192 if ((chain_size
== 0) && (CVAL(req
->inbuf
,smb_vwv0
) == 0xFF) &&
3193 !is_encrypted_packet(req
->inbuf
) && (fsp
->base_fsp
== NULL
) &&
3194 lp_use_sendfile(SNUM(conn
)) && (fsp
->wcp
== NULL
) ) {
3195 uint8 headerbuf
[smb_size
+ 12 * 2];
3199 * Set up the packet header before send. We
3200 * assume here the sendfile will work (get the
3201 * correct amount of data).
3204 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3206 construct_reply_common((char *)req
->inbuf
, (char *)headerbuf
);
3207 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3209 if ((nread
= SMB_VFS_SENDFILE(smbd_server_fd(), fsp
, &header
, startpos
, smb_maxcnt
)) == -1) {
3210 /* Returning ENOSYS means no data at all was sent.
3211 Do this as a normal read. */
3212 if (errno
== ENOSYS
) {
3217 * Special hack for broken Linux with no working sendfile. If we
3218 * return EINTR we sent the header but not the rest of the data.
3219 * Fake this up by doing read/write calls.
3222 if (errno
== EINTR
) {
3223 /* Ensure we don't do this again. */
3224 set_use_sendfile(SNUM(conn
), False
);
3225 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3226 nread
= fake_sendfile(fsp
, startpos
,
3229 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3230 fsp
->fsp_name
, strerror(errno
) ));
3231 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3233 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3234 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3235 /* No outbuf here means successful sendfile. */
3236 TALLOC_FREE(req
->outbuf
);
3240 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3241 fsp
->fsp_name
, strerror(errno
) ));
3242 exit_server_cleanly("send_file_readX sendfile failed");
3245 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3246 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3247 /* No outbuf here means successful sendfile. */
3248 TALLOC_FREE(req
->outbuf
);
3255 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3256 uint8 headerbuf
[smb_size
+ 2*12];
3258 construct_reply_common((char *)req
->inbuf
, (char *)headerbuf
);
3259 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3261 /* Send out the header. */
3262 if (write_data(smbd_server_fd(), (char *)headerbuf
,
3263 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3264 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3265 fsp
->fsp_name
, strerror(errno
) ));
3266 exit_server_cleanly("send_file_readX sendfile failed");
3268 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3270 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3271 fsp
->fsp_name
, strerror(errno
) ));
3272 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3274 TALLOC_FREE(req
->outbuf
);
3277 reply_outbuf(req
, 12, smb_maxcnt
);
3279 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
,
3282 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
3286 setup_readX_header((char *)req
->outbuf
, nread
);
3288 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3289 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3297 /****************************************************************************
3298 Reply to a read and X.
3299 ****************************************************************************/
3301 void reply_read_and_X(struct smb_request
*req
)
3303 connection_struct
*conn
= req
->conn
;
3307 bool big_readX
= False
;
3309 size_t smb_mincnt
= SVAL(req
->inbuf
,smb_vwv6
);
3312 START_PROFILE(SMBreadX
);
3314 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3315 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3319 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv2
));
3320 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv3
);
3321 smb_maxcnt
= SVAL(req
->inbuf
,smb_vwv5
);
3323 /* If it's an IPC, pass off the pipe handler. */
3325 reply_pipe_read_and_X(req
);
3326 END_PROFILE(SMBreadX
);
3330 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
3331 END_PROFILE(SMBreadX
);
3335 if (!CHECK_READ(fsp
,req
->inbuf
)) {
3336 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3337 END_PROFILE(SMBreadX
);
3341 if (global_client_caps
& CAP_LARGE_READX
) {
3342 size_t upper_size
= SVAL(req
->inbuf
,smb_vwv7
);
3343 smb_maxcnt
|= (upper_size
<<16);
3344 if (upper_size
> 1) {
3345 /* Can't do this on a chained packet. */
3346 if ((CVAL(req
->inbuf
,smb_vwv0
) != 0xFF)) {
3347 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3348 END_PROFILE(SMBreadX
);
3351 /* We currently don't do this on signed or sealed data. */
3352 if (srv_is_signing_active() || is_encrypted_packet(req
->inbuf
)) {
3353 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3354 END_PROFILE(SMBreadX
);
3357 /* Is there room in the reply for this data ? */
3358 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3360 NT_STATUS_INVALID_PARAMETER
);
3361 END_PROFILE(SMBreadX
);
3368 if (req
->wct
== 12) {
3369 #ifdef LARGE_SMB_OFF_T
3371 * This is a large offset (64 bit) read.
3373 startpos
|= (((SMB_OFF_T
)IVAL(req
->inbuf
,smb_vwv10
)) << 32);
3375 #else /* !LARGE_SMB_OFF_T */
3378 * Ensure we haven't been sent a >32 bit offset.
3381 if(IVAL(req
->inbuf
,smb_vwv10
) != 0) {
3382 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3383 "used and we don't support 64 bit offsets.\n",
3384 (unsigned int)IVAL(req
->inbuf
,smb_vwv10
) ));
3385 END_PROFILE(SMBreadX
);
3386 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3390 #endif /* LARGE_SMB_OFF_T */
3394 if (is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)smb_maxcnt
,
3395 (SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
3396 END_PROFILE(SMBreadX
);
3397 reply_doserror(req
, ERRDOS
, ERRlock
);
3402 schedule_aio_read_and_X(conn
, req
, fsp
, startpos
, smb_maxcnt
)) {
3403 END_PROFILE(SMBreadX
);
3407 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3409 END_PROFILE(SMBreadX
);
3413 /****************************************************************************
3414 Error replies to writebraw must have smb_wct == 1. Fix this up.
3415 ****************************************************************************/
3417 void error_to_writebrawerr(struct smb_request
*req
)
3419 uint8
*old_outbuf
= req
->outbuf
;
3421 reply_outbuf(req
, 1, 0);
3423 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3424 TALLOC_FREE(old_outbuf
);
3427 /****************************************************************************
3428 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3429 ****************************************************************************/
3431 void reply_writebraw(struct smb_request
*req
)
3433 connection_struct
*conn
= req
->conn
;
3436 ssize_t total_written
=0;
3437 size_t numtowrite
=0;
3445 START_PROFILE(SMBwritebraw
);
3448 * If we ever reply with an error, it must have the SMB command
3449 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3452 SCVAL(req
->inbuf
,smb_com
,SMBwritec
);
3454 if (srv_is_signing_active()) {
3455 END_PROFILE(SMBwritebraw
);
3456 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3457 "raw reads/writes are disallowed.");
3460 if (req
->wct
< 12) {
3461 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3462 error_to_writebrawerr(req
);
3463 END_PROFILE(SMBwritebraw
);
3467 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3468 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
3469 error_to_writebrawerr(req
);
3470 END_PROFILE(SMBwritebraw
);
3474 if (!CHECK_WRITE(fsp
)) {
3475 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3476 error_to_writebrawerr(req
);
3477 END_PROFILE(SMBwritebraw
);
3481 tcount
= IVAL(req
->inbuf
,smb_vwv1
);
3482 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv3
);
3483 write_through
= BITSETW(req
->inbuf
+smb_vwv7
,0);
3485 /* We have to deal with slightly different formats depending
3486 on whether we are using the core+ or lanman1.0 protocol */
3488 if(Protocol
<= PROTOCOL_COREPLUS
) {
3489 numtowrite
= SVAL(smb_buf(req
->inbuf
),-2);
3490 data
= smb_buf(req
->inbuf
);
3492 numtowrite
= SVAL(req
->inbuf
,smb_vwv10
);
3493 data
= smb_base(req
->inbuf
) + SVAL(req
->inbuf
, smb_vwv11
);
3496 /* Ensure we don't write bytes past the end of this packet. */
3497 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3498 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3499 error_to_writebrawerr(req
);
3500 END_PROFILE(SMBwritebraw
);
3504 if (is_locked(fsp
,(uint32
)req
->smbpid
,(SMB_BIG_UINT
)tcount
,
3505 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3506 reply_doserror(req
, ERRDOS
, ERRlock
);
3507 error_to_writebrawerr(req
);
3508 END_PROFILE(SMBwritebraw
);
3513 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3516 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3517 "wrote=%d sync=%d\n",
3518 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3519 (int)nwritten
, (int)write_through
));
3521 if (nwritten
< (ssize_t
)numtowrite
) {
3522 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3523 error_to_writebrawerr(req
);
3524 END_PROFILE(SMBwritebraw
);
3528 total_written
= nwritten
;
3530 /* Allocate a buffer of 64k + length. */
3531 buf
= TALLOC_ARRAY(NULL
, char, 65540);
3533 reply_doserror(req
, ERRDOS
, ERRnomem
);
3534 error_to_writebrawerr(req
);
3535 END_PROFILE(SMBwritebraw
);
3539 /* Return a SMBwritebraw message to the redirector to tell
3540 * it to send more bytes */
3542 memcpy(buf
, req
->inbuf
, smb_size
);
3543 srv_set_message(buf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
3544 SCVAL(buf
,smb_com
,SMBwritebraw
);
3545 SSVALS(buf
,smb_vwv0
,0xFFFF);
3547 if (!srv_send_smb(smbd_server_fd(),
3549 IS_CONN_ENCRYPTED(conn
))) {
3550 exit_server_cleanly("reply_writebraw: srv_send_smb "
3554 /* Now read the raw data into the buffer and write it */
3555 status
= read_smb_length(smbd_server_fd(), buf
, SMB_SECONDARY_WAIT
,
3557 if (!NT_STATUS_IS_OK(status
)) {
3558 exit_server_cleanly("secondary writebraw failed");
3561 /* Set up outbuf to return the correct size */
3562 reply_outbuf(req
, 1, 0);
3564 if (numtowrite
!= 0) {
3566 if (numtowrite
> 0xFFFF) {
3567 DEBUG(0,("reply_writebraw: Oversize secondary write "
3568 "raw requested (%u). Terminating\n",
3569 (unsigned int)numtowrite
));
3570 exit_server_cleanly("secondary writebraw failed");
3573 if (tcount
> nwritten
+numtowrite
) {
3574 DEBUG(3,("reply_writebraw: Client overestimated the "
3576 (int)tcount
,(int)nwritten
,(int)numtowrite
));
3579 status
= read_data(smbd_server_fd(), buf
+4, numtowrite
);
3581 if (!NT_STATUS_IS_OK(status
)) {
3582 DEBUG(0,("reply_writebraw: Oversize secondary write "
3583 "raw read failed (%s). Terminating\n",
3584 nt_errstr(status
)));
3585 exit_server_cleanly("secondary writebraw failed");
3588 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
3589 if (nwritten
== -1) {
3591 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3592 error_to_writebrawerr(req
);
3593 END_PROFILE(SMBwritebraw
);
3597 if (nwritten
< (ssize_t
)numtowrite
) {
3598 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
3599 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
3603 total_written
+= nwritten
;
3608 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
3610 status
= sync_file(conn
, fsp
, write_through
);
3611 if (!NT_STATUS_IS_OK(status
)) {
3612 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3613 fsp
->fsp_name
, nt_errstr(status
) ));
3614 reply_nterror(req
, status
);
3615 error_to_writebrawerr(req
);
3616 END_PROFILE(SMBwritebraw
);
3620 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3622 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3623 (int)total_written
));
3625 /* We won't return a status if write through is not selected - this
3626 * follows what WfWg does */
3627 END_PROFILE(SMBwritebraw
);
3629 if (!write_through
&& total_written
==tcount
) {
3631 #if RABBIT_PELLET_FIX
3633 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3634 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3637 if (!send_keepalive(smbd_server_fd())) {
3638 exit_server_cleanly("reply_writebraw: send of "
3639 "keepalive failed");
3642 TALLOC_FREE(req
->outbuf
);
3648 #define DBGC_CLASS DBGC_LOCKING
3650 /****************************************************************************
3651 Reply to a writeunlock (core+).
3652 ****************************************************************************/
3654 void reply_writeunlock(struct smb_request
*req
)
3656 connection_struct
*conn
= req
->conn
;
3657 ssize_t nwritten
= -1;
3661 NTSTATUS status
= NT_STATUS_OK
;
3664 START_PROFILE(SMBwriteunlock
);
3667 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3668 END_PROFILE(SMBwriteunlock
);
3672 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3674 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
3675 END_PROFILE(SMBwriteunlock
);
3679 if (!CHECK_WRITE(fsp
)) {
3680 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3681 END_PROFILE(SMBwriteunlock
);
3685 numtowrite
= SVAL(req
->inbuf
,smb_vwv1
);
3686 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
3687 data
= smb_buf(req
->inbuf
) + 3;
3690 && is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtowrite
,
3691 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3692 reply_doserror(req
, ERRDOS
, ERRlock
);
3693 END_PROFILE(SMBwriteunlock
);
3697 /* The special X/Open SMB protocol handling of
3698 zero length writes is *NOT* done for
3700 if(numtowrite
== 0) {
3703 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3706 status
= sync_file(conn
, fsp
, False
/* write through */);
3707 if (!NT_STATUS_IS_OK(status
)) {
3708 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3709 fsp
->fsp_name
, nt_errstr(status
) ));
3710 reply_nterror(req
, status
);
3711 END_PROFILE(SMBwriteunlock
);
3715 if(((nwritten
< numtowrite
) && (numtowrite
!= 0))||(nwritten
< 0)) {
3716 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3717 END_PROFILE(SMBwriteunlock
);
3722 status
= do_unlock(smbd_messaging_context(),
3725 (SMB_BIG_UINT
)numtowrite
,
3726 (SMB_BIG_UINT
)startpos
,
3729 if (NT_STATUS_V(status
)) {
3730 reply_nterror(req
, status
);
3731 END_PROFILE(SMBwriteunlock
);
3736 reply_outbuf(req
, 1, 0);
3738 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
3740 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3741 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
3743 END_PROFILE(SMBwriteunlock
);
3748 #define DBGC_CLASS DBGC_ALL
3750 /****************************************************************************
3752 ****************************************************************************/
3754 void reply_write(struct smb_request
*req
)
3756 connection_struct
*conn
= req
->conn
;
3758 ssize_t nwritten
= -1;
3764 START_PROFILE(SMBwrite
);
3767 END_PROFILE(SMBwrite
);
3768 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3772 /* If it's an IPC, pass off the pipe handler. */
3774 reply_pipe_write(req
);
3775 END_PROFILE(SMBwrite
);
3779 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3781 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
3782 END_PROFILE(SMBwrite
);
3786 if (!CHECK_WRITE(fsp
)) {
3787 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3788 END_PROFILE(SMBwrite
);
3792 numtowrite
= SVAL(req
->inbuf
,smb_vwv1
);
3793 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
3794 data
= smb_buf(req
->inbuf
) + 3;
3796 if (is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtowrite
,
3797 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3798 reply_doserror(req
, ERRDOS
, ERRlock
);
3799 END_PROFILE(SMBwrite
);
3804 * X/Open SMB protocol says that if smb_vwv1 is
3805 * zero then the file size should be extended or
3806 * truncated to the size given in smb_vwv[2-3].
3809 if(numtowrite
== 0) {
3811 * This is actually an allocate call, and set EOF. JRA.
3813 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
3815 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3816 END_PROFILE(SMBwrite
);
3819 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
3821 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3822 END_PROFILE(SMBwrite
);
3825 trigger_write_time_update_immediate(fsp
);
3827 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3830 status
= sync_file(conn
, fsp
, False
);
3831 if (!NT_STATUS_IS_OK(status
)) {
3832 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3833 fsp
->fsp_name
, nt_errstr(status
) ));
3834 reply_nterror(req
, status
);
3835 END_PROFILE(SMBwrite
);
3839 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
3840 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
3841 END_PROFILE(SMBwrite
);
3845 reply_outbuf(req
, 1, 0);
3847 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
3849 if (nwritten
< (ssize_t
)numtowrite
) {
3850 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
3851 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
3854 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
3856 END_PROFILE(SMBwrite
);
3860 /****************************************************************************
3861 Ensure a buffer is a valid writeX for recvfile purposes.
3862 ****************************************************************************/
3864 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3865 (2*14) + /* word count (including bcc) */ \
3868 bool is_valid_writeX_buffer(const uint8_t *inbuf
)
3871 connection_struct
*conn
= NULL
;
3872 unsigned int doff
= 0;
3873 size_t len
= smb_len_large(inbuf
);
3875 if (is_encrypted_packet(inbuf
)) {
3876 /* Can't do this on encrypted
3881 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
3885 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
3886 CVAL(inbuf
,smb_wct
) != 14) {
3887 DEBUG(10,("is_valid_writeX_buffer: chained or "
3888 "invalid word length.\n"));
3892 conn
= conn_find(SVAL(inbuf
, smb_tid
));
3894 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3898 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3901 if (IS_PRINT(conn
)) {
3902 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
3905 doff
= SVAL(inbuf
,smb_vwv11
);
3907 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3909 if (len
> doff
&& len
- doff
> 0xFFFF) {
3910 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
3913 if (numtowrite
== 0) {
3914 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3918 /* Ensure the sizes match up. */
3919 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
3920 /* no pad byte...old smbclient :-( */
3921 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3923 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
3927 if (len
- doff
!= numtowrite
) {
3928 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3929 "len = %u, doff = %u, numtowrite = %u\n",
3932 (unsigned int)numtowrite
));
3936 DEBUG(10,("is_valid_writeX_buffer: true "
3937 "len = %u, doff = %u, numtowrite = %u\n",
3940 (unsigned int)numtowrite
));
3945 /****************************************************************************
3946 Reply to a write and X.
3947 ****************************************************************************/
3949 void reply_write_and_X(struct smb_request
*req
)
3951 connection_struct
*conn
= req
->conn
;
3957 unsigned int smb_doff
;
3958 unsigned int smblen
;
3962 START_PROFILE(SMBwriteX
);
3964 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
3965 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3966 END_PROFILE(SMBwriteX
);
3970 numtowrite
= SVAL(req
->inbuf
,smb_vwv10
);
3971 smb_doff
= SVAL(req
->inbuf
,smb_vwv11
);
3972 smblen
= smb_len(req
->inbuf
);
3974 if (req
->unread_bytes
> 0xFFFF ||
3975 (smblen
> smb_doff
&&
3976 smblen
- smb_doff
> 0xFFFF)) {
3977 numtowrite
|= (((size_t)SVAL(req
->inbuf
,smb_vwv9
))<<16);
3980 if (req
->unread_bytes
) {
3981 /* Can't do a recvfile write on IPC$ */
3983 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3984 END_PROFILE(SMBwriteX
);
3987 if (numtowrite
!= req
->unread_bytes
) {
3988 reply_doserror(req
, ERRDOS
, ERRbadmem
);
3989 END_PROFILE(SMBwriteX
);
3993 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
3994 smb_doff
+ numtowrite
> smblen
) {
3995 reply_doserror(req
, ERRDOS
, ERRbadmem
);
3996 END_PROFILE(SMBwriteX
);
4001 /* If it's an IPC, pass off the pipe handler. */
4003 if (req
->unread_bytes
) {
4004 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4005 END_PROFILE(SMBwriteX
);
4008 reply_pipe_write_and_X(req
);
4009 END_PROFILE(SMBwriteX
);
4013 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv2
));
4014 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv3
);
4015 write_through
= BITSETW(req
->inbuf
+smb_vwv7
,0);
4017 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
4018 END_PROFILE(SMBwriteX
);
4022 if (!CHECK_WRITE(fsp
)) {
4023 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4024 END_PROFILE(SMBwriteX
);
4028 data
= smb_base(req
->inbuf
) + smb_doff
;
4030 if(req
->wct
== 14) {
4031 #ifdef LARGE_SMB_OFF_T
4033 * This is a large offset (64 bit) write.
4035 startpos
|= (((SMB_OFF_T
)IVAL(req
->inbuf
,smb_vwv12
)) << 32);
4037 #else /* !LARGE_SMB_OFF_T */
4040 * Ensure we haven't been sent a >32 bit offset.
4043 if(IVAL(req
->inbuf
,smb_vwv12
) != 0) {
4044 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4045 "used and we don't support 64 bit offsets.\n",
4046 (unsigned int)IVAL(req
->inbuf
,smb_vwv12
) ));
4047 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4048 END_PROFILE(SMBwriteX
);
4052 #endif /* LARGE_SMB_OFF_T */
4055 if (is_locked(fsp
,(uint32
)req
->smbpid
,
4056 (SMB_BIG_UINT
)numtowrite
,
4057 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
4058 reply_doserror(req
, ERRDOS
, ERRlock
);
4059 END_PROFILE(SMBwriteX
);
4063 /* X/Open SMB protocol says that, unlike SMBwrite
4064 if the length is zero then NO truncation is
4065 done, just a write of zero. To truncate a file,
4068 if(numtowrite
== 0) {
4072 if ((req
->unread_bytes
== 0) &&
4073 schedule_aio_write_and_X(conn
, req
, fsp
, data
, startpos
,
4075 END_PROFILE(SMBwriteX
);
4079 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4082 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4083 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
4084 END_PROFILE(SMBwriteX
);
4088 reply_outbuf(req
, 6, 0);
4089 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4090 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4092 if (nwritten
< (ssize_t
)numtowrite
) {
4093 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4094 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4097 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4098 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4100 status
= sync_file(conn
, fsp
, write_through
);
4101 if (!NT_STATUS_IS_OK(status
)) {
4102 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4103 fsp
->fsp_name
, nt_errstr(status
) ));
4104 reply_nterror(req
, status
);
4105 END_PROFILE(SMBwriteX
);
4109 END_PROFILE(SMBwriteX
);
4114 /****************************************************************************
4116 ****************************************************************************/
4118 void reply_lseek(struct smb_request
*req
)
4120 connection_struct
*conn
= req
->conn
;
4126 START_PROFILE(SMBlseek
);
4129 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4130 END_PROFILE(SMBlseek
);
4134 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4136 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
4140 flush_write_cache(fsp
, SEEK_FLUSH
);
4142 mode
= SVAL(req
->inbuf
,smb_vwv1
) & 3;
4143 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4144 startpos
= (SMB_OFF_T
)IVALS(req
->inbuf
,smb_vwv2
);
4153 res
= fsp
->fh
->pos
+ startpos
;
4164 if (umode
== SEEK_END
) {
4165 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4166 if(errno
== EINVAL
) {
4167 SMB_OFF_T current_pos
= startpos
;
4168 SMB_STRUCT_STAT sbuf
;
4170 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
4171 reply_unixerror(req
, ERRDOS
,
4173 END_PROFILE(SMBlseek
);
4177 current_pos
+= sbuf
.st_size
;
4179 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4184 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
4185 END_PROFILE(SMBlseek
);
4192 reply_outbuf(req
, 2, 0);
4193 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4195 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4196 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4198 END_PROFILE(SMBlseek
);
4202 /****************************************************************************
4204 ****************************************************************************/
4206 void reply_flush(struct smb_request
*req
)
4208 connection_struct
*conn
= req
->conn
;
4212 START_PROFILE(SMBflush
);
4215 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4219 fnum
= SVAL(req
->inbuf
,smb_vwv0
);
4220 fsp
= file_fsp(fnum
);
4222 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
, ¤t_user
)) {
4227 file_sync_all(conn
);
4229 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4230 if (!NT_STATUS_IS_OK(status
)) {
4231 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4232 fsp
->fsp_name
, nt_errstr(status
) ));
4233 reply_nterror(req
, status
);
4234 END_PROFILE(SMBflush
);
4239 reply_outbuf(req
, 0, 0);
4241 DEBUG(3,("flush\n"));
4242 END_PROFILE(SMBflush
);
4246 /****************************************************************************
4248 conn POINTER CAN BE NULL HERE !
4249 ****************************************************************************/
4251 void reply_exit(struct smb_request
*req
)
4253 START_PROFILE(SMBexit
);
4255 file_close_pid(req
->smbpid
, req
->vuid
);
4257 reply_outbuf(req
, 0, 0);
4259 DEBUG(3,("exit\n"));
4261 END_PROFILE(SMBexit
);
4265 /****************************************************************************
4266 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4267 ****************************************************************************/
4269 void reply_close(struct smb_request
*req
)
4271 connection_struct
*conn
= req
->conn
;
4272 NTSTATUS status
= NT_STATUS_OK
;
4273 files_struct
*fsp
= NULL
;
4274 START_PROFILE(SMBclose
);
4277 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4278 END_PROFILE(SMBclose
);
4282 /* If it's an IPC, pass off to the pipe handler. */
4284 reply_pipe_close(conn
, req
);
4285 END_PROFILE(SMBclose
);
4289 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4292 * We can only use CHECK_FSP if we know it's not a directory.
4295 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= current_user
.vuid
)) {
4296 reply_doserror(req
, ERRDOS
, ERRbadfid
);
4297 END_PROFILE(SMBclose
);
4301 if(fsp
->is_directory
) {
4303 * Special case - close NT SMB directory handle.
4305 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4306 status
= close_file(fsp
,NORMAL_CLOSE
);
4310 * Close ordinary file.
4313 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4314 fsp
->fh
->fd
, fsp
->fnum
,
4315 conn
->num_files_open
));
4318 * Take care of any time sent in the close.
4321 t
= srv_make_unix_date3(req
->inbuf
+smb_vwv1
);
4322 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4325 * close_file() returns the unix errno if an error
4326 * was detected on close - normally this is due to
4327 * a disk full error. If not then it was probably an I/O error.
4330 status
= close_file(fsp
,NORMAL_CLOSE
);
4333 if (!NT_STATUS_IS_OK(status
)) {
4334 reply_nterror(req
, status
);
4335 END_PROFILE(SMBclose
);
4339 reply_outbuf(req
, 0, 0);
4340 END_PROFILE(SMBclose
);
4344 /****************************************************************************
4345 Reply to a writeclose (Core+ protocol).
4346 ****************************************************************************/
4348 void reply_writeclose(struct smb_request
*req
)
4350 connection_struct
*conn
= req
->conn
;
4352 ssize_t nwritten
= -1;
4353 NTSTATUS close_status
= NT_STATUS_OK
;
4356 struct timespec mtime
;
4359 START_PROFILE(SMBwriteclose
);
4362 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4363 END_PROFILE(SMBwriteclose
);
4367 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4369 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
4370 END_PROFILE(SMBwriteclose
);
4373 if (!CHECK_WRITE(fsp
)) {
4374 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
4375 END_PROFILE(SMBwriteclose
);
4379 numtowrite
= SVAL(req
->inbuf
,smb_vwv1
);
4380 startpos
= IVAL_TO_SMB_OFF_T(req
->inbuf
,smb_vwv2
);
4381 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(
4382 req
->inbuf
+smb_vwv4
));
4383 data
= smb_buf(req
->inbuf
) + 1;
4386 && is_locked(fsp
, (uint32
)req
->smbpid
, (SMB_BIG_UINT
)numtowrite
,
4387 (SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
4388 reply_doserror(req
, ERRDOS
,ERRlock
);
4389 END_PROFILE(SMBwriteclose
);
4393 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4395 set_close_write_time(fsp
, mtime
);
4398 * More insanity. W2K only closes the file if writelen > 0.
4403 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4405 close_status
= close_file(fsp
,NORMAL_CLOSE
);
4408 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4409 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4410 conn
->num_files_open
));
4412 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4413 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4414 END_PROFILE(SMBwriteclose
);
4418 if(!NT_STATUS_IS_OK(close_status
)) {
4419 reply_nterror(req
, close_status
);
4420 END_PROFILE(SMBwriteclose
);
4424 reply_outbuf(req
, 1, 0);
4426 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4427 END_PROFILE(SMBwriteclose
);
4432 #define DBGC_CLASS DBGC_LOCKING
4434 /****************************************************************************
4436 ****************************************************************************/
4438 void reply_lock(struct smb_request
*req
)
4440 connection_struct
*conn
= req
->conn
;
4441 SMB_BIG_UINT count
,offset
;
4444 struct byte_range_lock
*br_lck
= NULL
;
4446 START_PROFILE(SMBlock
);
4449 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4450 END_PROFILE(SMBlock
);
4454 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4456 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
4457 END_PROFILE(SMBlock
);
4461 release_level_2_oplocks_on_change(fsp
);
4463 count
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv1
);
4464 offset
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv3
);
4466 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4467 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
4469 br_lck
= do_lock(smbd_messaging_context(),
4476 False
, /* Non-blocking lock. */
4480 TALLOC_FREE(br_lck
);
4482 if (NT_STATUS_V(status
)) {
4483 reply_nterror(req
, status
);
4484 END_PROFILE(SMBlock
);
4488 reply_outbuf(req
, 0, 0);
4490 END_PROFILE(SMBlock
);
4494 /****************************************************************************
4496 ****************************************************************************/
4498 void reply_unlock(struct smb_request
*req
)
4500 connection_struct
*conn
= req
->conn
;
4501 SMB_BIG_UINT count
,offset
;
4505 START_PROFILE(SMBunlock
);
4508 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4509 END_PROFILE(SMBunlock
);
4513 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4515 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
4516 END_PROFILE(SMBunlock
);
4520 count
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv1
);
4521 offset
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv3
);
4523 status
= do_unlock(smbd_messaging_context(),
4530 if (NT_STATUS_V(status
)) {
4531 reply_nterror(req
, status
);
4532 END_PROFILE(SMBunlock
);
4536 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4537 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
4539 reply_outbuf(req
, 0, 0);
4541 END_PROFILE(SMBunlock
);
4546 #define DBGC_CLASS DBGC_ALL
4548 /****************************************************************************
4550 conn POINTER CAN BE NULL HERE !
4551 ****************************************************************************/
4553 void reply_tdis(struct smb_request
*req
)
4555 connection_struct
*conn
= req
->conn
;
4556 START_PROFILE(SMBtdis
);
4559 DEBUG(4,("Invalid connection in tdis\n"));
4560 reply_doserror(req
, ERRSRV
, ERRinvnid
);
4561 END_PROFILE(SMBtdis
);
4567 close_cnum(conn
,req
->vuid
);
4570 reply_outbuf(req
, 0, 0);
4571 END_PROFILE(SMBtdis
);
4575 /****************************************************************************
4577 conn POINTER CAN BE NULL HERE !
4578 ****************************************************************************/
4580 void reply_echo(struct smb_request
*req
)
4582 connection_struct
*conn
= req
->conn
;
4585 unsigned int data_len
= smb_buflen(req
->inbuf
);
4587 START_PROFILE(SMBecho
);
4590 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4591 END_PROFILE(SMBecho
);
4595 if (data_len
> BUFFER_SIZE
) {
4596 DEBUG(0,("reply_echo: data_len too large.\n"));
4597 reply_nterror(req
, NT_STATUS_INSUFFICIENT_RESOURCES
);
4598 END_PROFILE(SMBecho
);
4602 smb_reverb
= SVAL(req
->inbuf
,smb_vwv0
);
4604 reply_outbuf(req
, 1, data_len
);
4606 /* copy any incoming data back out */
4608 memcpy(smb_buf(req
->outbuf
),smb_buf(req
->inbuf
),data_len
);
4611 if (smb_reverb
> 100) {
4612 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
4616 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
4617 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
4619 show_msg((char *)req
->outbuf
);
4620 if (!srv_send_smb(smbd_server_fd(),
4621 (char *)req
->outbuf
,
4622 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
))
4623 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4626 DEBUG(3,("echo %d times\n", smb_reverb
));
4628 TALLOC_FREE(req
->outbuf
);
4632 END_PROFILE(SMBecho
);
4636 /****************************************************************************
4637 Reply to a printopen.
4638 ****************************************************************************/
4640 void reply_printopen(struct smb_request
*req
)
4642 connection_struct
*conn
= req
->conn
;
4645 SMB_STRUCT_STAT sbuf
;
4647 START_PROFILE(SMBsplopen
);
4650 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4651 END_PROFILE(SMBsplopen
);
4655 if (!CAN_PRINT(conn
)) {
4656 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4657 END_PROFILE(SMBsplopen
);
4661 status
= file_new(conn
, &fsp
);
4662 if(!NT_STATUS_IS_OK(status
)) {
4663 reply_nterror(req
, status
);
4664 END_PROFILE(SMBsplopen
);
4668 /* Open for exclusive use, write only. */
4669 status
= print_fsp_open(conn
, NULL
, fsp
, &sbuf
);
4671 if (!NT_STATUS_IS_OK(status
)) {
4673 reply_nterror(req
, status
);
4674 END_PROFILE(SMBsplopen
);
4678 reply_outbuf(req
, 1, 0);
4679 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
4681 DEBUG(3,("openprint fd=%d fnum=%d\n",
4682 fsp
->fh
->fd
, fsp
->fnum
));
4684 END_PROFILE(SMBsplopen
);
4688 /****************************************************************************
4689 Reply to a printclose.
4690 ****************************************************************************/
4692 void reply_printclose(struct smb_request
*req
)
4694 connection_struct
*conn
= req
->conn
;
4698 START_PROFILE(SMBsplclose
);
4701 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4702 END_PROFILE(SMBsplclose
);
4706 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4708 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
4709 END_PROFILE(SMBsplclose
);
4713 if (!CAN_PRINT(conn
)) {
4714 reply_nterror(req
, NT_STATUS_DOS(ERRSRV
, ERRerror
));
4715 END_PROFILE(SMBsplclose
);
4719 DEBUG(3,("printclose fd=%d fnum=%d\n",
4720 fsp
->fh
->fd
,fsp
->fnum
));
4722 status
= close_file(fsp
,NORMAL_CLOSE
);
4724 if(!NT_STATUS_IS_OK(status
)) {
4725 reply_nterror(req
, status
);
4726 END_PROFILE(SMBsplclose
);
4730 reply_outbuf(req
, 0, 0);
4732 END_PROFILE(SMBsplclose
);
4736 /****************************************************************************
4737 Reply to a printqueue.
4738 ****************************************************************************/
4740 void reply_printqueue(struct smb_request
*req
)
4742 connection_struct
*conn
= req
->conn
;
4746 START_PROFILE(SMBsplretq
);
4749 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4750 END_PROFILE(SMBsplretq
);
4754 max_count
= SVAL(req
->inbuf
,smb_vwv0
);
4755 start_index
= SVAL(req
->inbuf
,smb_vwv1
);
4757 /* we used to allow the client to get the cnum wrong, but that
4758 is really quite gross and only worked when there was only
4759 one printer - I think we should now only accept it if they
4760 get it right (tridge) */
4761 if (!CAN_PRINT(conn
)) {
4762 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4763 END_PROFILE(SMBsplretq
);
4767 reply_outbuf(req
, 2, 3);
4768 SSVAL(req
->outbuf
,smb_vwv0
,0);
4769 SSVAL(req
->outbuf
,smb_vwv1
,0);
4770 SCVAL(smb_buf(req
->outbuf
),0,1);
4771 SSVAL(smb_buf(req
->outbuf
),1,0);
4773 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4774 start_index
, max_count
));
4777 print_queue_struct
*queue
= NULL
;
4778 print_status_struct status
;
4779 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
4780 int num_to_get
= ABS(max_count
);
4781 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
4787 num_to_get
= MIN(num_to_get
,count
-first
);
4790 for (i
=first
;i
<first
+num_to_get
;i
++) {
4794 srv_put_dos_date2(p
,0,queue
[i
].time
);
4795 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
4796 SSVAL(p
,5, queue
[i
].job
);
4797 SIVAL(p
,7,queue
[i
].size
);
4799 srvstr_push(blob
, req
->flags2
, p
+12,
4800 queue
[i
].fs_user
, 16, STR_ASCII
);
4802 if (message_push_blob(
4805 blob
, sizeof(blob
))) == -1) {
4806 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4807 END_PROFILE(SMBsplretq
);
4813 SSVAL(req
->outbuf
,smb_vwv0
,count
);
4814 SSVAL(req
->outbuf
,smb_vwv1
,
4815 (max_count
>0?first
+count
:first
-1));
4816 SCVAL(smb_buf(req
->outbuf
),0,1);
4817 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
4822 DEBUG(3,("%d entries returned in queue\n",count
));
4825 END_PROFILE(SMBsplretq
);
4829 /****************************************************************************
4830 Reply to a printwrite.
4831 ****************************************************************************/
4833 void reply_printwrite(struct smb_request
*req
)
4835 connection_struct
*conn
= req
->conn
;
4840 START_PROFILE(SMBsplwr
);
4843 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4844 END_PROFILE(SMBsplwr
);
4848 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
4850 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
4851 END_PROFILE(SMBsplwr
);
4855 if (!CAN_PRINT(conn
)) {
4856 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4857 END_PROFILE(SMBsplwr
);
4861 if (!CHECK_WRITE(fsp
)) {
4862 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4863 END_PROFILE(SMBsplwr
);
4867 numtowrite
= SVAL(smb_buf(req
->inbuf
),1);
4869 if (smb_buflen(req
->inbuf
) < numtowrite
+ 3) {
4870 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4871 END_PROFILE(SMBsplwr
);
4875 data
= smb_buf(req
->inbuf
) + 3;
4877 if (write_file(req
,fsp
,data
,-1,numtowrite
) != numtowrite
) {
4878 reply_unixerror(req
, ERRHRD
, ERRdiskfull
);
4879 END_PROFILE(SMBsplwr
);
4883 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
4885 END_PROFILE(SMBsplwr
);
4889 /****************************************************************************
4891 ****************************************************************************/
4893 void reply_mkdir(struct smb_request
*req
)
4895 connection_struct
*conn
= req
->conn
;
4896 char *directory
= NULL
;
4898 SMB_STRUCT_STAT sbuf
;
4899 TALLOC_CTX
*ctx
= talloc_tos();
4901 START_PROFILE(SMBmkdir
);
4903 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &directory
,
4904 smb_buf(req
->inbuf
) + 1, 0,
4905 STR_TERMINATE
, &status
);
4906 if (!NT_STATUS_IS_OK(status
)) {
4907 reply_nterror(req
, status
);
4908 END_PROFILE(SMBmkdir
);
4912 status
= resolve_dfspath(ctx
, conn
,
4913 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
4916 if (!NT_STATUS_IS_OK(status
)) {
4917 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4918 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
4919 ERRSRV
, ERRbadpath
);
4920 END_PROFILE(SMBmkdir
);
4923 reply_nterror(req
, status
);
4924 END_PROFILE(SMBmkdir
);
4928 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
, NULL
, &sbuf
);
4929 if (!NT_STATUS_IS_OK(status
)) {
4930 reply_nterror(req
, status
);
4931 END_PROFILE(SMBmkdir
);
4935 status
= check_name(conn
, directory
);
4936 if (!NT_STATUS_IS_OK(status
)) {
4937 reply_nterror(req
, status
);
4938 END_PROFILE(SMBmkdir
);
4942 status
= create_directory(conn
, req
, directory
);
4944 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
4946 if (!NT_STATUS_IS_OK(status
)) {
4948 if (!use_nt_status()
4949 && NT_STATUS_EQUAL(status
,
4950 NT_STATUS_OBJECT_NAME_COLLISION
)) {
4952 * Yes, in the DOS error code case we get a
4953 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4954 * samba4 torture test.
4956 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
4959 reply_nterror(req
, status
);
4960 END_PROFILE(SMBmkdir
);
4964 reply_outbuf(req
, 0, 0);
4966 DEBUG( 3, ( "mkdir %s\n", directory
) );
4968 END_PROFILE(SMBmkdir
);
4972 /****************************************************************************
4973 Static function used by reply_rmdir to delete an entire directory
4974 tree recursively. Return True on ok, False on fail.
4975 ****************************************************************************/
4977 static bool recursive_rmdir(TALLOC_CTX
*ctx
,
4978 connection_struct
*conn
,
4981 const char *dname
= NULL
;
4984 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
, directory
,
4990 while((dname
= ReadDirName(dir_hnd
, &offset
))) {
4991 char *fullname
= NULL
;
4994 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
4998 if (!is_visible_file(conn
, directory
, dname
, &st
, False
)) {
5002 /* Construct the full name. */
5003 fullname
= talloc_asprintf(ctx
,
5013 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
5018 if(st
.st_mode
& S_IFDIR
) {
5019 if(!recursive_rmdir(ctx
, conn
, fullname
)) {
5023 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
5027 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
5031 TALLOC_FREE(fullname
);
5033 TALLOC_FREE(dir_hnd
);
5037 /****************************************************************************
5038 The internals of the rmdir code - called elsewhere.
5039 ****************************************************************************/
5041 NTSTATUS
rmdir_internals(TALLOC_CTX
*ctx
,
5042 connection_struct
*conn
,
5043 const char *directory
)
5048 /* Might be a symlink. */
5049 if(SMB_VFS_LSTAT(conn
, directory
, &st
) != 0) {
5050 return map_nt_error_from_unix(errno
);
5053 if (S_ISLNK(st
.st_mode
)) {
5054 /* Is what it points to a directory ? */
5055 if(SMB_VFS_STAT(conn
, directory
, &st
) != 0) {
5056 return map_nt_error_from_unix(errno
);
5058 if (!(S_ISDIR(st
.st_mode
))) {
5059 return NT_STATUS_NOT_A_DIRECTORY
;
5061 ret
= SMB_VFS_UNLINK(conn
,directory
);
5063 ret
= SMB_VFS_RMDIR(conn
,directory
);
5066 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5067 FILE_NOTIFY_CHANGE_DIR_NAME
,
5069 return NT_STATUS_OK
;
5072 if(((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
5074 * Check to see if the only thing in this directory are
5075 * vetoed files/directories. If so then delete them and
5076 * retry. If we fail to delete any of them (and we *don't*
5077 * do a recursive delete) then fail the rmdir.
5081 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
,
5082 directory
, NULL
, 0);
5084 if(dir_hnd
== NULL
) {
5089 while ((dname
= ReadDirName(dir_hnd
,&dirpos
))) {
5090 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
5092 if (!is_visible_file(conn
, directory
, dname
, &st
, False
))
5094 if(!IS_VETO_PATH(conn
, dname
)) {
5095 TALLOC_FREE(dir_hnd
);
5101 /* We only have veto files/directories.
5102 * Are we allowed to delete them ? */
5104 if(!lp_recursive_veto_delete(SNUM(conn
))) {
5105 TALLOC_FREE(dir_hnd
);
5110 /* Do a recursive delete. */
5111 RewindDir(dir_hnd
,&dirpos
);
5112 while ((dname
= ReadDirName(dir_hnd
,&dirpos
))) {
5113 char *fullname
= NULL
;
5115 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5118 if (!is_visible_file(conn
, directory
, dname
, &st
, False
)) {
5122 fullname
= talloc_asprintf(ctx
,
5132 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
5135 if(st
.st_mode
& S_IFDIR
) {
5136 if(!recursive_rmdir(ctx
, conn
, fullname
)) {
5139 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
5142 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
5145 TALLOC_FREE(fullname
);
5147 TALLOC_FREE(dir_hnd
);
5148 /* Retry the rmdir */
5149 ret
= SMB_VFS_RMDIR(conn
,directory
);
5155 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5156 "%s\n", directory
,strerror(errno
)));
5157 return map_nt_error_from_unix(errno
);
5160 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5161 FILE_NOTIFY_CHANGE_DIR_NAME
,
5164 return NT_STATUS_OK
;
5167 /****************************************************************************
5169 ****************************************************************************/
5171 void reply_rmdir(struct smb_request
*req
)
5173 connection_struct
*conn
= req
->conn
;
5174 char *directory
= NULL
;
5175 SMB_STRUCT_STAT sbuf
;
5177 TALLOC_CTX
*ctx
= talloc_tos();
5179 START_PROFILE(SMBrmdir
);
5181 srvstr_get_path(ctx
, (char *)req
->inbuf
, req
->flags2
, &directory
,
5182 smb_buf(req
->inbuf
) + 1, 0,
5183 STR_TERMINATE
, &status
);
5184 if (!NT_STATUS_IS_OK(status
)) {
5185 reply_nterror(req
, status
);
5186 END_PROFILE(SMBrmdir
);
5190 status
= resolve_dfspath(ctx
, conn
,
5191 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5194 if (!NT_STATUS_IS_OK(status
)) {
5195 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5196 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5197 ERRSRV
, ERRbadpath
);
5198 END_PROFILE(SMBrmdir
);
5201 reply_nterror(req
, status
);
5202 END_PROFILE(SMBrmdir
);
5206 status
= unix_convert(ctx
, conn
, directory
, False
, &directory
,
5208 if (!NT_STATUS_IS_OK(status
)) {
5209 reply_nterror(req
, status
);
5210 END_PROFILE(SMBrmdir
);
5214 status
= check_name(conn
, directory
);
5215 if (!NT_STATUS_IS_OK(status
)) {
5216 reply_nterror(req
, status
);
5217 END_PROFILE(SMBrmdir
);
5221 dptr_closepath(directory
, req
->smbpid
);
5222 status
= rmdir_internals(ctx
, conn
, directory
);
5223 if (!NT_STATUS_IS_OK(status
)) {
5224 reply_nterror(req
, status
);
5225 END_PROFILE(SMBrmdir
);
5229 reply_outbuf(req
, 0, 0);
5231 DEBUG( 3, ( "rmdir %s\n", directory
) );
5233 END_PROFILE(SMBrmdir
);
5237 /*******************************************************************
5238 Resolve wildcards in a filename rename.
5239 ********************************************************************/
5241 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5246 char *name2_copy
= NULL
;
5251 char *p
,*p2
, *pname1
, *pname2
;
5253 name2_copy
= talloc_strdup(ctx
, name2
);
5258 pname1
= strrchr_m(name1
,'/');
5259 pname2
= strrchr_m(name2_copy
,'/');
5261 if (!pname1
|| !pname2
) {
5265 /* Truncate the copy of name2 at the last '/' */
5268 /* Now go past the '/' */
5272 root1
= talloc_strdup(ctx
, pname1
);
5273 root2
= talloc_strdup(ctx
, pname2
);
5275 if (!root1
|| !root2
) {
5279 p
= strrchr_m(root1
,'.');
5282 ext1
= talloc_strdup(ctx
, p
+1);
5284 ext1
= talloc_strdup(ctx
, "");
5286 p
= strrchr_m(root2
,'.');
5289 ext2
= talloc_strdup(ctx
, p
+1);
5291 ext2
= talloc_strdup(ctx
, "");
5294 if (!ext1
|| !ext2
) {
5302 /* Hmmm. Should this be mb-aware ? */
5305 } else if (*p2
== '*') {
5307 root2
= talloc_asprintf(ctx
, "%s%s",
5326 /* Hmmm. Should this be mb-aware ? */
5329 } else if (*p2
== '*') {
5331 ext2
= talloc_asprintf(ctx
, "%s%s",
5347 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5352 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5364 /****************************************************************************
5365 Ensure open files have their names updated. Updated to notify other smbd's
5367 ****************************************************************************/
5369 static void rename_open_files(connection_struct
*conn
,
5370 struct share_mode_lock
*lck
,
5371 const char *newname
)
5374 bool did_rename
= False
;
5376 for(fsp
= file_find_di_first(lck
->id
); fsp
;
5377 fsp
= file_find_di_next(fsp
)) {
5378 /* fsp_name is a relative path under the fsp. To change this for other
5379 sharepaths we need to manipulate relative paths. */
5380 /* TODO - create the absolute path and manipulate the newname
5381 relative to the sharepath. */
5382 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5385 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5386 fsp
->fnum
, file_id_string_tos(&fsp
->file_id
),
5387 fsp
->fsp_name
, newname
));
5388 string_set(&fsp
->fsp_name
, newname
);
5393 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5394 file_id_string_tos(&lck
->id
), newname
));
5397 /* Send messages to all smbd's (not ourself) that the name has changed. */
5398 rename_share_filename(smbd_messaging_context(), lck
, conn
->connectpath
,
5402 /****************************************************************************
5403 We need to check if the source path is a parent directory of the destination
5404 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5405 refuse the rename with a sharing violation. Under UNIX the above call can
5406 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5407 probably need to check that the client is a Windows one before disallowing
5408 this as a UNIX client (one with UNIX extensions) can know the source is a
5409 symlink and make this decision intelligently. Found by an excellent bug
5410 report from <AndyLiebman@aol.com>.
5411 ****************************************************************************/
5413 static bool rename_path_prefix_equal(const char *src
, const char *dest
)
5415 const char *psrc
= src
;
5416 const char *pdst
= dest
;
5419 if (psrc
[0] == '.' && psrc
[1] == '/') {
5422 if (pdst
[0] == '.' && pdst
[1] == '/') {
5425 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5428 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5432 * Do the notify calls from a rename
5435 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5436 const char *oldpath
, const char *newpath
)
5438 char *olddir
, *newdir
;
5439 const char *oldname
, *newname
;
5442 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5443 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5445 if (!parent_dirname_talloc(NULL
, oldpath
, &olddir
, &oldname
)
5446 || !parent_dirname_talloc(NULL
, newpath
, &newdir
, &newname
)) {
5447 TALLOC_FREE(olddir
);
5451 if (strcmp(olddir
, newdir
) == 0) {
5452 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
, oldpath
);
5453 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
, newpath
);
5456 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
, oldpath
);
5457 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
, newpath
);
5459 TALLOC_FREE(olddir
);
5460 TALLOC_FREE(newdir
);
5462 /* this is a strange one. w2k3 gives an additional event for
5463 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5464 files, but not directories */
5466 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5467 FILE_NOTIFY_CHANGE_ATTRIBUTES
5468 |FILE_NOTIFY_CHANGE_CREATION
,
5473 /****************************************************************************
5474 Rename an open file - given an fsp.
5475 ****************************************************************************/
5477 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
5480 const char *newname_last_component
,
5482 bool replace_if_exists
)
5484 TALLOC_CTX
*ctx
= talloc_tos();
5485 SMB_STRUCT_STAT sbuf
, sbuf1
;
5486 NTSTATUS status
= NT_STATUS_OK
;
5487 struct share_mode_lock
*lck
= NULL
;
5488 bool dst_exists
, old_is_stream
, new_is_stream
;
5492 status
= check_name(conn
, newname
);
5493 if (!NT_STATUS_IS_OK(status
)) {
5497 /* Ensure newname contains a '/' */
5498 if(strrchr_m(newname
,'/') == 0) {
5499 newname
= talloc_asprintf(ctx
,
5503 return NT_STATUS_NO_MEMORY
;
5508 * Check for special case with case preserving and not
5509 * case sensitive. If the old last component differs from the original
5510 * last component only by case, then we should allow
5511 * the rename (user is trying to change the case of the
5515 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
5516 strequal(newname
, fsp
->fsp_name
)) {
5518 char *newname_modified_last_component
= NULL
;
5521 * Get the last component of the modified name.
5522 * Note that we guarantee that newname contains a '/'
5525 p
= strrchr_m(newname
,'/');
5526 newname_modified_last_component
= talloc_strdup(ctx
,
5528 if (!newname_modified_last_component
) {
5529 return NT_STATUS_NO_MEMORY
;
5532 if(strcsequal(newname_modified_last_component
,
5533 newname_last_component
) == False
) {
5535 * Replace the modified last component with
5538 *p
= '\0'; /* Truncate at the '/' */
5539 newname
= talloc_asprintf(ctx
,
5542 newname_last_component
);
5547 * If the src and dest names are identical - including case,
5548 * don't do the rename, just return success.
5551 if (strcsequal(fsp
->fsp_name
, newname
)) {
5552 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5554 return NT_STATUS_OK
;
5557 old_is_stream
= is_ntfs_stream_name(fsp
->fsp_name
);
5558 new_is_stream
= is_ntfs_stream_name(newname
);
5560 /* Return the correct error code if both names aren't streams. */
5561 if (!old_is_stream
&& new_is_stream
) {
5562 return NT_STATUS_OBJECT_NAME_INVALID
;
5565 if (old_is_stream
&& !new_is_stream
) {
5566 return NT_STATUS_INVALID_PARAMETER
;
5570 * Have vfs_object_exist also fill sbuf1
5572 dst_exists
= vfs_object_exist(conn
, newname
, &sbuf1
);
5574 if(!replace_if_exists
&& dst_exists
) {
5575 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5576 fsp
->fsp_name
,newname
));
5577 return NT_STATUS_OBJECT_NAME_COLLISION
;
5581 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, &sbuf1
);
5582 files_struct
*dst_fsp
= file_find_di_first(fileid
);
5583 /* The file can be open when renaming a stream */
5584 if (dst_fsp
&& !new_is_stream
) {
5585 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5586 return NT_STATUS_ACCESS_DENIED
;
5590 /* Ensure we have a valid stat struct for the source. */
5591 if (fsp
->fh
->fd
!= -1) {
5592 if (SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
5593 return map_nt_error_from_unix(errno
);
5596 if (SMB_VFS_STAT(conn
,fsp
->fsp_name
,&sbuf
) == -1) {
5597 return map_nt_error_from_unix(errno
);
5601 status
= can_rename(conn
, fsp
, attrs
, &sbuf
);
5603 if (!NT_STATUS_IS_OK(status
)) {
5604 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5605 nt_errstr(status
), fsp
->fsp_name
,newname
));
5606 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
5607 status
= NT_STATUS_ACCESS_DENIED
;
5611 if (rename_path_prefix_equal(fsp
->fsp_name
, newname
)) {
5612 return NT_STATUS_ACCESS_DENIED
;
5615 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
5619 * We have the file open ourselves, so not being able to get the
5620 * corresponding share mode lock is a fatal error.
5623 SMB_ASSERT(lck
!= NULL
);
5625 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
5626 uint32 create_options
= fsp
->fh
->private_options
;
5628 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5629 fsp
->fsp_name
,newname
));
5631 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
, newname
);
5633 rename_open_files(conn
, lck
, newname
);
5636 * A rename acts as a new file create w.r.t. allowing an initial delete
5637 * on close, probably because in Windows there is a new handle to the
5638 * new file. If initial delete on close was requested but not
5639 * originally set, we need to set it here. This is probably not 100% correct,
5640 * but will work for the CIFSFS client which in non-posix mode
5641 * depends on these semantics. JRA.
5644 if (create_options
& FILE_DELETE_ON_CLOSE
) {
5645 status
= can_set_delete_on_close(fsp
, True
, 0);
5647 if (NT_STATUS_IS_OK(status
)) {
5648 /* Note that here we set the *inital* delete on close flag,
5649 * not the regular one. The magic gets handled in close. */
5650 fsp
->initial_delete_on_close
= True
;
5654 return NT_STATUS_OK
;
5659 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
5660 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
5662 status
= map_nt_error_from_unix(errno
);
5665 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5666 nt_errstr(status
), fsp
->fsp_name
,newname
));
5671 /****************************************************************************
5672 The guts of the rename command, split out so it may be called by the NT SMB
5674 ****************************************************************************/
5676 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
5677 connection_struct
*conn
,
5678 struct smb_request
*req
,
5679 const char *name_in
,
5680 const char *newname_in
,
5682 bool replace_if_exists
,
5685 uint32_t access_mask
)
5687 char *directory
= NULL
;
5689 char *last_component_src
= NULL
;
5690 char *last_component_dest
= NULL
;
5692 char *newname
= NULL
;
5695 NTSTATUS status
= NT_STATUS_OK
;
5696 SMB_STRUCT_STAT sbuf1
, sbuf2
;
5697 struct smb_Dir
*dir_hnd
= NULL
;
5704 status
= unix_convert(ctx
, conn
, name_in
, src_has_wild
, &name
,
5705 &last_component_src
, &sbuf1
);
5706 if (!NT_STATUS_IS_OK(status
)) {
5710 status
= unix_convert(ctx
, conn
, newname_in
, dest_has_wild
, &newname
,
5711 &last_component_dest
, &sbuf2
);
5712 if (!NT_STATUS_IS_OK(status
)) {
5717 * Split the old name into directory and last component
5718 * strings. Note that unix_convert may have stripped off a
5719 * leading ./ from both name and newname if the rename is
5720 * at the root of the share. We need to make sure either both
5721 * name and newname contain a / character or neither of them do
5722 * as this is checked in resolve_wildcards().
5725 p
= strrchr_m(name
,'/');
5727 directory
= talloc_strdup(ctx
, ".");
5729 return NT_STATUS_NO_MEMORY
;
5734 directory
= talloc_strdup(ctx
, name
);
5736 return NT_STATUS_NO_MEMORY
;
5739 *p
= '/'; /* Replace needed for exceptional test below. */
5743 * We should only check the mangled cache
5744 * here if unix_convert failed. This means
5745 * that the path in 'mask' doesn't exist
5746 * on the file system and so we need to look
5747 * for a possible mangle. This patch from
5748 * Tine Smukavec <valentin.smukavec@hermes.si>.
5751 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
)) {
5752 char *new_mask
= NULL
;
5753 mangle_lookup_name_from_8_3(ctx
,
5762 if (!src_has_wild
) {
5766 * No wildcards - just process the one file.
5768 bool is_short_name
= mangle_is_8_3(name
, True
, conn
->params
);
5770 /* Add a terminating '/' to the directory name. */
5771 directory
= talloc_asprintf_append(directory
,
5775 return NT_STATUS_NO_MEMORY
;
5778 /* Ensure newname contains a '/' also */
5779 if(strrchr_m(newname
,'/') == 0) {
5780 newname
= talloc_asprintf(ctx
,
5784 return NT_STATUS_NO_MEMORY
;
5788 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5789 "case_preserve = %d, short case preserve = %d, "
5790 "directory = %s, newname = %s, "
5791 "last_component_dest = %s, is_8_3 = %d\n",
5792 conn
->case_sensitive
, conn
->case_preserve
,
5793 conn
->short_case_preserve
, directory
,
5794 newname
, last_component_dest
, is_short_name
));
5796 /* The dest name still may have wildcards. */
5797 if (dest_has_wild
) {
5798 char *mod_newname
= NULL
;
5799 if (!resolve_wildcards(ctx
,
5800 directory
,newname
,&mod_newname
)) {
5801 DEBUG(6, ("rename_internals: resolve_wildcards "
5805 return NT_STATUS_NO_MEMORY
;
5807 newname
= mod_newname
;
5811 SMB_VFS_STAT(conn
, directory
, &sbuf1
);
5813 status
= S_ISDIR(sbuf1
.st_mode
) ?
5814 open_directory(conn
, req
, directory
, &sbuf1
,
5816 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5817 FILE_OPEN
, 0, 0, NULL
,
5819 : open_file_ntcreate(conn
, req
, directory
, &sbuf1
,
5821 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5822 FILE_OPEN
, 0, 0, 0, NULL
,
5825 if (!NT_STATUS_IS_OK(status
)) {
5826 DEBUG(3, ("Could not open rename source %s: %s\n",
5827 directory
, nt_errstr(status
)));
5831 status
= rename_internals_fsp(conn
, fsp
, newname
,
5832 last_component_dest
,
5833 attrs
, replace_if_exists
);
5835 close_file(fsp
, NORMAL_CLOSE
);
5837 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5838 nt_errstr(status
), directory
,newname
));
5844 * Wildcards - process each file that matches.
5846 if (strequal(mask
,"????????.???")) {
5851 status
= check_name(conn
, directory
);
5852 if (!NT_STATUS_IS_OK(status
)) {
5856 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
, attrs
);
5857 if (dir_hnd
== NULL
) {
5858 return map_nt_error_from_unix(errno
);
5861 status
= NT_STATUS_NO_SUCH_FILE
;
5863 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5864 * - gentest fix. JRA
5867 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
5868 files_struct
*fsp
= NULL
;
5870 char *destname
= NULL
;
5871 bool sysdir_entry
= False
;
5873 /* Quick check for "." and ".." */
5874 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5876 sysdir_entry
= True
;
5882 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
)) {
5886 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
5891 status
= NT_STATUS_OBJECT_NAME_INVALID
;
5895 fname
= talloc_asprintf(ctx
,
5900 return NT_STATUS_NO_MEMORY
;
5903 if (!resolve_wildcards(ctx
,
5904 fname
,newname
,&destname
)) {
5905 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5911 return NT_STATUS_NO_MEMORY
;
5915 SMB_VFS_STAT(conn
, fname
, &sbuf1
);
5917 status
= S_ISDIR(sbuf1
.st_mode
) ?
5918 open_directory(conn
, req
, fname
, &sbuf1
,
5920 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5921 FILE_OPEN
, 0, 0, NULL
,
5923 : open_file_ntcreate(conn
, req
, fname
, &sbuf1
,
5925 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5926 FILE_OPEN
, 0, 0, 0, NULL
,
5929 if (!NT_STATUS_IS_OK(status
)) {
5930 DEBUG(3,("rename_internals: open_file_ntcreate "
5931 "returned %s rename %s -> %s\n",
5932 nt_errstr(status
), directory
, newname
));
5936 status
= rename_internals_fsp(conn
, fsp
, destname
, dname
,
5937 attrs
, replace_if_exists
);
5939 close_file(fsp
, NORMAL_CLOSE
);
5941 if (!NT_STATUS_IS_OK(status
)) {
5942 DEBUG(3, ("rename_internals_fsp returned %s for "
5943 "rename %s -> %s\n", nt_errstr(status
),
5944 directory
, newname
));
5950 DEBUG(3,("rename_internals: doing rename on %s -> "
5951 "%s\n",fname
,destname
));
5954 TALLOC_FREE(destname
);
5956 TALLOC_FREE(dir_hnd
);
5958 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
5959 status
= map_nt_error_from_unix(errno
);
5965 /****************************************************************************
5967 ****************************************************************************/
5969 void reply_mv(struct smb_request
*req
)
5971 connection_struct
*conn
= req
->conn
;
5973 char *newname
= NULL
;
5977 bool src_has_wcard
= False
;
5978 bool dest_has_wcard
= False
;
5979 TALLOC_CTX
*ctx
= talloc_tos();
5981 START_PROFILE(SMBmv
);
5984 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5989 attrs
= SVAL(req
->inbuf
,smb_vwv0
);
5991 p
= smb_buf(req
->inbuf
) + 1;
5992 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &name
, p
,
5993 0, STR_TERMINATE
, &status
,
5995 if (!NT_STATUS_IS_OK(status
)) {
5996 reply_nterror(req
, status
);
6001 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &newname
, p
,
6002 0, STR_TERMINATE
, &status
,
6004 if (!NT_STATUS_IS_OK(status
)) {
6005 reply_nterror(req
, status
);
6010 status
= resolve_dfspath_wcard(ctx
, conn
,
6011 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6015 if (!NT_STATUS_IS_OK(status
)) {
6016 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6017 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6018 ERRSRV
, ERRbadpath
);
6022 reply_nterror(req
, status
);
6027 status
= resolve_dfspath_wcard(ctx
, conn
,
6028 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6032 if (!NT_STATUS_IS_OK(status
)) {
6033 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6034 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6035 ERRSRV
, ERRbadpath
);
6039 reply_nterror(req
, status
);
6044 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
6046 status
= rename_internals(ctx
, conn
, req
, name
, newname
, attrs
, False
,
6047 src_has_wcard
, dest_has_wcard
, DELETE_ACCESS
);
6048 if (!NT_STATUS_IS_OK(status
)) {
6049 if (open_was_deferred(req
->mid
)) {
6050 /* We have re-scheduled this call. */
6054 reply_nterror(req
, status
);
6059 reply_outbuf(req
, 0, 0);
6065 /*******************************************************************
6066 Copy a file as part of a reply_copy.
6067 ******************************************************************/
6070 * TODO: check error codes on all callers
6073 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6074 connection_struct
*conn
,
6079 bool target_is_directory
)
6081 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
6083 files_struct
*fsp1
,*fsp2
;
6086 uint32 new_create_disposition
;
6089 dest
= talloc_strdup(ctx
, dest1
);
6091 return NT_STATUS_NO_MEMORY
;
6093 if (target_is_directory
) {
6094 const char *p
= strrchr_m(src
,'/');
6100 dest
= talloc_asprintf_append(dest
,
6104 return NT_STATUS_NO_MEMORY
;
6108 if (!vfs_file_exist(conn
,src
,&src_sbuf
)) {
6110 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6113 if (!target_is_directory
&& count
) {
6114 new_create_disposition
= FILE_OPEN
;
6116 if (!map_open_params_to_ntcreate(dest1
,0,ofun
,
6117 NULL
, NULL
, &new_create_disposition
, NULL
)) {
6119 return NT_STATUS_INVALID_PARAMETER
;
6123 status
= open_file_ntcreate(conn
, NULL
, src
, &src_sbuf
,
6125 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6128 FILE_ATTRIBUTE_NORMAL
,
6132 if (!NT_STATUS_IS_OK(status
)) {
6137 dosattrs
= dos_mode(conn
, src
, &src_sbuf
);
6138 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1) {
6139 ZERO_STRUCTP(&sbuf2
);
6142 status
= open_file_ntcreate(conn
, NULL
, dest
, &sbuf2
,
6144 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6145 new_create_disposition
,
6153 if (!NT_STATUS_IS_OK(status
)) {
6154 close_file(fsp1
,ERROR_CLOSE
);
6158 if ((ofun
&3) == 1) {
6159 if(SMB_VFS_LSEEK(fsp2
,0,SEEK_END
) == -1) {
6160 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
6162 * Stop the copy from occurring.
6165 src_sbuf
.st_size
= 0;
6169 if (src_sbuf
.st_size
) {
6170 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
6173 close_file(fsp1
,NORMAL_CLOSE
);
6175 /* Ensure the modtime is set correctly on the destination file. */
6176 set_close_write_time(fsp2
, get_mtimespec(&src_sbuf
));
6179 * As we are opening fsp1 read-only we only expect
6180 * an error on close on fsp2 if we are out of space.
6181 * Thus we don't look at the error return from the
6184 status
= close_file(fsp2
,NORMAL_CLOSE
);
6186 if (!NT_STATUS_IS_OK(status
)) {
6190 if (ret
!= (SMB_OFF_T
)src_sbuf
.st_size
) {
6191 return NT_STATUS_DISK_FULL
;
6194 return NT_STATUS_OK
;
6197 /****************************************************************************
6198 Reply to a file copy.
6199 ****************************************************************************/
6201 void reply_copy(struct smb_request
*req
)
6203 connection_struct
*conn
= req
->conn
;
6205 char *newname
= NULL
;
6206 char *directory
= NULL
;
6210 int error
= ERRnoaccess
;
6215 bool target_is_directory
=False
;
6216 bool source_has_wild
= False
;
6217 bool dest_has_wild
= False
;
6218 SMB_STRUCT_STAT sbuf1
, sbuf2
;
6220 TALLOC_CTX
*ctx
= talloc_tos();
6222 START_PROFILE(SMBcopy
);
6225 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6226 END_PROFILE(SMBcopy
);
6230 tid2
= SVAL(req
->inbuf
,smb_vwv0
);
6231 ofun
= SVAL(req
->inbuf
,smb_vwv1
);
6232 flags
= SVAL(req
->inbuf
,smb_vwv2
);
6234 p
= smb_buf(req
->inbuf
);
6235 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &name
, p
,
6236 0, STR_TERMINATE
, &status
,
6238 if (!NT_STATUS_IS_OK(status
)) {
6239 reply_nterror(req
, status
);
6240 END_PROFILE(SMBcopy
);
6243 p
+= srvstr_get_path_wcard(ctx
, (char *)req
->inbuf
, req
->flags2
, &newname
, p
,
6244 0, STR_TERMINATE
, &status
,
6246 if (!NT_STATUS_IS_OK(status
)) {
6247 reply_nterror(req
, status
);
6248 END_PROFILE(SMBcopy
);
6252 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
6254 if (tid2
!= conn
->cnum
) {
6255 /* can't currently handle inter share copies XXXX */
6256 DEBUG(3,("Rejecting inter-share copy\n"));
6257 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
6258 END_PROFILE(SMBcopy
);
6262 status
= resolve_dfspath_wcard(ctx
, conn
,
6263 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6267 if (!NT_STATUS_IS_OK(status
)) {
6268 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6269 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6270 ERRSRV
, ERRbadpath
);
6271 END_PROFILE(SMBcopy
);
6274 reply_nterror(req
, status
);
6275 END_PROFILE(SMBcopy
);
6279 status
= resolve_dfspath_wcard(ctx
, conn
,
6280 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6284 if (!NT_STATUS_IS_OK(status
)) {
6285 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6286 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6287 ERRSRV
, ERRbadpath
);
6288 END_PROFILE(SMBcopy
);
6291 reply_nterror(req
, status
);
6292 END_PROFILE(SMBcopy
);
6296 status
= unix_convert(ctx
, conn
, name
, source_has_wild
,
6297 &name
, NULL
, &sbuf1
);
6298 if (!NT_STATUS_IS_OK(status
)) {
6299 reply_nterror(req
, status
);
6300 END_PROFILE(SMBcopy
);
6304 status
= unix_convert(ctx
, conn
, newname
, dest_has_wild
,
6305 &newname
, NULL
, &sbuf2
);
6306 if (!NT_STATUS_IS_OK(status
)) {
6307 reply_nterror(req
, status
);
6308 END_PROFILE(SMBcopy
);
6312 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
6314 if ((flags
&1) && target_is_directory
) {
6315 reply_doserror(req
, ERRDOS
, ERRbadfile
);
6316 END_PROFILE(SMBcopy
);
6320 if ((flags
&2) && !target_is_directory
) {
6321 reply_doserror(req
, ERRDOS
, ERRbadpath
);
6322 END_PROFILE(SMBcopy
);
6326 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
6327 /* wants a tree copy! XXXX */
6328 DEBUG(3,("Rejecting tree copy\n"));
6329 reply_doserror(req
, ERRSRV
, ERRerror
);
6330 END_PROFILE(SMBcopy
);
6334 p
= strrchr_m(name
,'/');
6336 directory
= talloc_strdup(ctx
, "./");
6338 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6339 END_PROFILE(SMBcopy
);
6345 directory
= talloc_strdup(ctx
, name
);
6347 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6348 END_PROFILE(SMBcopy
);
6355 * We should only check the mangled cache
6356 * here if unix_convert failed. This means
6357 * that the path in 'mask' doesn't exist
6358 * on the file system and so we need to look
6359 * for a possible mangle. This patch from
6360 * Tine Smukavec <valentin.smukavec@hermes.si>.
6363 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
)) {
6364 char *new_mask
= NULL
;
6365 mangle_lookup_name_from_8_3(ctx
,
6374 if (!source_has_wild
) {
6375 directory
= talloc_asprintf_append(directory
,
6378 if (dest_has_wild
) {
6379 char *mod_newname
= NULL
;
6380 if (!resolve_wildcards(ctx
,
6381 directory
,newname
,&mod_newname
)) {
6382 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6383 END_PROFILE(SMBcopy
);
6386 newname
= mod_newname
;
6389 status
= check_name(conn
, directory
);
6390 if (!NT_STATUS_IS_OK(status
)) {
6391 reply_nterror(req
, status
);
6392 END_PROFILE(SMBcopy
);
6396 status
= check_name(conn
, newname
);
6397 if (!NT_STATUS_IS_OK(status
)) {
6398 reply_nterror(req
, status
);
6399 END_PROFILE(SMBcopy
);
6403 status
= copy_file(ctx
,conn
,directory
,newname
,ofun
,
6404 count
,target_is_directory
);
6406 if(!NT_STATUS_IS_OK(status
)) {
6407 reply_nterror(req
, status
);
6408 END_PROFILE(SMBcopy
);
6414 struct smb_Dir
*dir_hnd
= NULL
;
6415 const char *dname
= NULL
;
6418 if (strequal(mask
,"????????.???")) {
6423 status
= check_name(conn
, directory
);
6424 if (!NT_STATUS_IS_OK(status
)) {
6425 reply_nterror(req
, status
);
6426 END_PROFILE(SMBcopy
);
6430 dir_hnd
= OpenDir(talloc_tos(), conn
, directory
, mask
, 0);
6431 if (dir_hnd
== NULL
) {
6432 status
= map_nt_error_from_unix(errno
);
6433 reply_nterror(req
, status
);
6434 END_PROFILE(SMBcopy
);
6440 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
6441 char *destname
= NULL
;
6444 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6448 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
)) {
6452 if(!mask_match(dname
, mask
, conn
->case_sensitive
)) {
6456 error
= ERRnoaccess
;
6457 fname
= talloc_asprintf(ctx
,
6462 TALLOC_FREE(dir_hnd
);
6463 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6464 END_PROFILE(SMBcopy
);
6468 if (!resolve_wildcards(ctx
,
6469 fname
,newname
,&destname
)) {
6473 TALLOC_FREE(dir_hnd
);
6474 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6475 END_PROFILE(SMBcopy
);
6479 status
= check_name(conn
, fname
);
6480 if (!NT_STATUS_IS_OK(status
)) {
6481 TALLOC_FREE(dir_hnd
);
6482 reply_nterror(req
, status
);
6483 END_PROFILE(SMBcopy
);
6487 status
= check_name(conn
, destname
);
6488 if (!NT_STATUS_IS_OK(status
)) {
6489 TALLOC_FREE(dir_hnd
);
6490 reply_nterror(req
, status
);
6491 END_PROFILE(SMBcopy
);
6495 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
, destname
));
6497 status
= copy_file(ctx
,conn
,fname
,destname
,ofun
,
6498 count
,target_is_directory
);
6499 if (NT_STATUS_IS_OK(status
)) {
6503 TALLOC_FREE(destname
);
6505 TALLOC_FREE(dir_hnd
);
6510 /* Error on close... */
6512 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
6513 END_PROFILE(SMBcopy
);
6517 reply_doserror(req
, ERRDOS
, error
);
6518 END_PROFILE(SMBcopy
);
6522 reply_outbuf(req
, 1, 0);
6523 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6525 END_PROFILE(SMBcopy
);
6530 #define DBGC_CLASS DBGC_LOCKING
6532 /****************************************************************************
6533 Get a lock pid, dealing with large count requests.
6534 ****************************************************************************/
6536 uint32
get_lock_pid( char *data
, int data_offset
, bool large_file_format
)
6538 if(!large_file_format
)
6539 return (uint32
)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
6541 return (uint32
)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
6544 /****************************************************************************
6545 Get a lock count, dealing with large count requests.
6546 ****************************************************************************/
6548 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, bool large_file_format
)
6550 SMB_BIG_UINT count
= 0;
6552 if(!large_file_format
) {
6553 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
6556 #if defined(HAVE_LONGLONG)
6557 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
6558 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
6559 #else /* HAVE_LONGLONG */
6562 * NT4.x seems to be broken in that it sends large file (64 bit)
6563 * lockingX calls even if the CAP_LARGE_FILES was *not*
6564 * negotiated. For boxes without large unsigned ints truncate the
6565 * lock count by dropping the top 32 bits.
6568 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
6569 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6570 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
6571 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
6572 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
6575 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
6576 #endif /* HAVE_LONGLONG */
6582 #if !defined(HAVE_LONGLONG)
6583 /****************************************************************************
6584 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6585 ****************************************************************************/
6587 static uint32
map_lock_offset(uint32 high
, uint32 low
)
6591 uint32 highcopy
= high
;
6594 * Try and find out how many significant bits there are in high.
6597 for(i
= 0; highcopy
; i
++)
6601 * We use 31 bits not 32 here as POSIX
6602 * lock offsets may not be negative.
6605 mask
= (~0) << (31 - i
);
6608 return 0; /* Fail. */
6614 #endif /* !defined(HAVE_LONGLONG) */
6616 /****************************************************************************
6617 Get a lock offset, dealing with large offset requests.
6618 ****************************************************************************/
6620 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, bool large_file_format
, bool *err
)
6622 SMB_BIG_UINT offset
= 0;
6626 if(!large_file_format
) {
6627 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
6630 #if defined(HAVE_LONGLONG)
6631 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
6632 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
6633 #else /* HAVE_LONGLONG */
6636 * NT4.x seems to be broken in that it sends large file (64 bit)
6637 * lockingX calls even if the CAP_LARGE_FILES was *not*
6638 * negotiated. For boxes without large unsigned ints mangle the
6639 * lock offset by mapping the top 32 bits onto the lower 32.
6642 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
6643 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
6644 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
6647 if((new_low
= map_lock_offset(high
, low
)) == 0) {
6649 return (SMB_BIG_UINT
)-1;
6652 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6653 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
6654 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
6655 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
6658 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
6659 #endif /* HAVE_LONGLONG */
6665 /****************************************************************************
6666 Reply to a lockingX request.
6667 ****************************************************************************/
6669 void reply_lockingX(struct smb_request
*req
)
6671 connection_struct
*conn
= req
->conn
;
6673 unsigned char locktype
;
6674 unsigned char oplocklevel
;
6677 SMB_BIG_UINT count
= 0, offset
= 0;
6682 bool large_file_format
;
6684 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
6686 START_PROFILE(SMBlockingX
);
6689 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6690 END_PROFILE(SMBlockingX
);
6694 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv2
));
6695 locktype
= CVAL(req
->inbuf
,smb_vwv3
);
6696 oplocklevel
= CVAL(req
->inbuf
,smb_vwv3
+1);
6697 num_ulocks
= SVAL(req
->inbuf
,smb_vwv6
);
6698 num_locks
= SVAL(req
->inbuf
,smb_vwv7
);
6699 lock_timeout
= IVAL(req
->inbuf
,smb_vwv4
);
6700 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
6702 if (!check_fsp(conn
, req
, fsp
, ¤t_user
)) {
6703 END_PROFILE(SMBlockingX
);
6707 data
= smb_buf(req
->inbuf
);
6709 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
6710 /* we don't support these - and CANCEL_LOCK makes w2k
6711 and XP reboot so I don't really want to be
6712 compatible! (tridge) */
6713 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
6714 END_PROFILE(SMBlockingX
);
6718 /* Check if this is an oplock break on a file
6719 we have granted an oplock on.
6721 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
6722 /* Client can insist on breaking to none. */
6723 bool break_to_none
= (oplocklevel
== 0);
6726 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6727 "for fnum = %d\n", (unsigned int)oplocklevel
,
6731 * Make sure we have granted an exclusive or batch oplock on
6735 if (fsp
->oplock_type
== 0) {
6737 /* The Samba4 nbench simulator doesn't understand
6738 the difference between break to level2 and break
6739 to none from level2 - it sends oplock break
6740 replies in both cases. Don't keep logging an error
6741 message here - just ignore it. JRA. */
6743 DEBUG(5,("reply_lockingX: Error : oplock break from "
6744 "client for fnum = %d (oplock=%d) and no "
6745 "oplock granted on this file (%s).\n",
6746 fsp
->fnum
, fsp
->oplock_type
, fsp
->fsp_name
));
6748 /* if this is a pure oplock break request then don't
6750 if (num_locks
== 0 && num_ulocks
== 0) {
6751 END_PROFILE(SMBlockingX
);
6754 END_PROFILE(SMBlockingX
);
6755 reply_doserror(req
, ERRDOS
, ERRlock
);
6760 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
6762 result
= remove_oplock(fsp
);
6764 result
= downgrade_oplock(fsp
);
6768 DEBUG(0, ("reply_lockingX: error in removing "
6769 "oplock on file %s\n", fsp
->fsp_name
));
6770 /* Hmmm. Is this panic justified? */
6771 smb_panic("internal tdb error");
6774 reply_to_oplock_break_requests(fsp
);
6776 /* if this is a pure oplock break request then don't send a
6778 if (num_locks
== 0 && num_ulocks
== 0) {
6779 /* Sanity check - ensure a pure oplock break is not a
6781 if(CVAL(req
->inbuf
,smb_vwv0
) != 0xff)
6782 DEBUG(0,("reply_lockingX: Error : pure oplock "
6783 "break is a chained %d request !\n",
6784 (unsigned int)CVAL(req
->inbuf
,
6786 END_PROFILE(SMBlockingX
);
6792 * We do this check *after* we have checked this is not a oplock break
6793 * response message. JRA.
6796 release_level_2_oplocks_on_change(fsp
);
6798 if (smb_buflen(req
->inbuf
) <
6799 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
6800 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6801 END_PROFILE(SMBlockingX
);
6805 /* Data now points at the beginning of the list
6806 of smb_unlkrng structs */
6807 for(i
= 0; i
< (int)num_ulocks
; i
++) {
6808 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
6809 count
= get_lock_count( data
, i
, large_file_format
);
6810 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
6813 * There is no error code marked "stupid client bug".... :-).
6816 END_PROFILE(SMBlockingX
);
6817 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
6821 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6822 "pid %u, file %s\n", (double)offset
, (double)count
,
6823 (unsigned int)lock_pid
, fsp
->fsp_name
));
6825 status
= do_unlock(smbd_messaging_context(),
6832 if (NT_STATUS_V(status
)) {
6833 END_PROFILE(SMBlockingX
);
6834 reply_nterror(req
, status
);
6839 /* Setup the timeout in seconds. */
6841 if (!lp_blocking_locks(SNUM(conn
))) {
6845 /* Now do any requested locks */
6846 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
6848 /* Data now points at the beginning of the list
6849 of smb_lkrng structs */
6851 for(i
= 0; i
< (int)num_locks
; i
++) {
6852 enum brl_type lock_type
= ((locktype
& LOCKING_ANDX_SHARED_LOCK
) ?
6853 READ_LOCK
:WRITE_LOCK
);
6854 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
6855 count
= get_lock_count( data
, i
, large_file_format
);
6856 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
6859 * There is no error code marked "stupid client bug".... :-).
6862 END_PROFILE(SMBlockingX
);
6863 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
6867 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6868 "%u, file %s timeout = %d\n", (double)offset
,
6869 (double)count
, (unsigned int)lock_pid
,
6870 fsp
->fsp_name
, (int)lock_timeout
));
6872 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
6873 if (lp_blocking_locks(SNUM(conn
))) {
6875 /* Schedule a message to ourselves to
6876 remove the blocking lock record and
6877 return the right error. */
6879 if (!blocking_lock_cancel(fsp
,
6885 NT_STATUS_FILE_LOCK_CONFLICT
)) {
6886 END_PROFILE(SMBlockingX
);
6891 ERRcancelviolation
));
6895 /* Remove a matching pending lock. */
6896 status
= do_lock_cancel(fsp
,
6902 bool blocking_lock
= lock_timeout
? True
: False
;
6903 bool defer_lock
= False
;
6904 struct byte_range_lock
*br_lck
;
6905 uint32 block_smbpid
;
6907 br_lck
= do_lock(smbd_messaging_context(),
6918 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6919 /* Windows internal resolution for blocking locks seems
6920 to be about 200ms... Don't wait for less than that. JRA. */
6921 if (lock_timeout
!= -1 && lock_timeout
< lp_lock_spin_time()) {
6922 lock_timeout
= lp_lock_spin_time();
6927 /* This heuristic seems to match W2K3 very well. If a
6928 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6929 it pretends we asked for a timeout of between 150 - 300 milliseconds as
6930 far as I can tell. Replacement for do_lock_spin(). JRA. */
6932 if (br_lck
&& lp_blocking_locks(SNUM(conn
)) && !blocking_lock
&&
6933 NT_STATUS_EQUAL((status
), NT_STATUS_FILE_LOCK_CONFLICT
)) {
6935 lock_timeout
= lp_lock_spin_time();
6938 if (br_lck
&& defer_lock
) {
6940 * A blocking lock was requested. Package up
6941 * this smb into a queued request and push it
6942 * onto the blocking lock queue.
6944 if(push_blocking_lock_request(br_lck
,
6955 TALLOC_FREE(br_lck
);
6956 END_PROFILE(SMBlockingX
);
6961 TALLOC_FREE(br_lck
);
6964 if (NT_STATUS_V(status
)) {
6965 END_PROFILE(SMBlockingX
);
6966 reply_nterror(req
, status
);
6971 /* If any of the above locks failed, then we must unlock
6972 all of the previous locks (X/Open spec). */
6974 if (!(locktype
& LOCKING_ANDX_CANCEL_LOCK
) &&
6978 * Ensure we don't do a remove on the lock that just failed,
6979 * as under POSIX rules, if we have a lock already there, we
6980 * will delete it (and we shouldn't) .....
6982 for(i
--; i
>= 0; i
--) {
6983 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
6984 count
= get_lock_count( data
, i
, large_file_format
);
6985 offset
= get_lock_offset( data
, i
, large_file_format
,
6989 * There is no error code marked "stupid client
6993 END_PROFILE(SMBlockingX
);
6994 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
6998 do_unlock(smbd_messaging_context(),
7005 END_PROFILE(SMBlockingX
);
7006 reply_nterror(req
, status
);
7010 reply_outbuf(req
, 2, 0);
7012 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7013 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7015 END_PROFILE(SMBlockingX
);
7020 #define DBGC_CLASS DBGC_ALL
7022 /****************************************************************************
7023 Reply to a SMBreadbmpx (read block multiplex) request.
7024 Always reply with an error, if someone has a platform really needs this,
7025 please contact vl@samba.org
7026 ****************************************************************************/
7028 void reply_readbmpx(struct smb_request
*req
)
7030 START_PROFILE(SMBreadBmpx
);
7031 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7032 END_PROFILE(SMBreadBmpx
);
7036 /****************************************************************************
7037 Reply to a SMBreadbs (read block multiplex secondary) request.
7038 Always reply with an error, if someone has a platform really needs this,
7039 please contact vl@samba.org
7040 ****************************************************************************/
7042 void reply_readbs(struct smb_request
*req
)
7044 START_PROFILE(SMBreadBs
);
7045 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7046 END_PROFILE(SMBreadBs
);
7050 /****************************************************************************
7051 Reply to a SMBsetattrE.
7052 ****************************************************************************/
7054 void reply_setattrE(struct smb_request
*req
)
7056 connection_struct
*conn
= req
->conn
;
7057 struct timespec ts
[2];
7059 SMB_STRUCT_STAT sbuf
;
7062 START_PROFILE(SMBsetattrE
);
7065 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7066 END_PROFILE(SMBsetattrE
);
7070 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
7072 if(!fsp
|| (fsp
->conn
!= conn
)) {
7073 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7074 END_PROFILE(SMBsetattrE
);
7080 * Convert the DOS times into unix times. Ignore create
7081 * time as UNIX can't set this.
7084 ts
[0] = convert_time_t_to_timespec(
7085 srv_make_unix_date2(req
->inbuf
+smb_vwv3
)); /* atime. */
7086 ts
[1] = convert_time_t_to_timespec(
7087 srv_make_unix_date2(req
->inbuf
+smb_vwv5
)); /* mtime. */
7089 reply_outbuf(req
, 0, 0);
7092 * Patch from Ray Frush <frush@engr.colostate.edu>
7093 * Sometimes times are sent as zero - ignore them.
7096 /* Ensure we have a valid stat struct for the source. */
7097 if (fsp
->fh
->fd
!= -1) {
7098 if (SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
7099 status
= map_nt_error_from_unix(errno
);
7100 reply_nterror(req
, status
);
7101 END_PROFILE(SMBsetattrE
);
7105 if (SMB_VFS_STAT(conn
, fsp
->fsp_name
, &sbuf
) == -1) {
7106 status
= map_nt_error_from_unix(errno
);
7107 reply_nterror(req
, status
);
7108 END_PROFILE(SMBsetattrE
);
7113 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
,
7115 if (!NT_STATUS_IS_OK(status
)) {
7116 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7117 END_PROFILE(SMBsetattrE
);
7121 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7123 (unsigned int)ts
[0].tv_sec
,
7124 (unsigned int)ts
[1].tv_sec
));
7126 END_PROFILE(SMBsetattrE
);
7131 /* Back from the dead for OS/2..... JRA. */
7133 /****************************************************************************
7134 Reply to a SMBwritebmpx (write block multiplex primary) request.
7135 Always reply with an error, if someone has a platform really needs this,
7136 please contact vl@samba.org
7137 ****************************************************************************/
7139 void reply_writebmpx(struct smb_request
*req
)
7141 START_PROFILE(SMBwriteBmpx
);
7142 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7143 END_PROFILE(SMBwriteBmpx
);
7147 /****************************************************************************
7148 Reply to a SMBwritebs (write block multiplex secondary) request.
7149 Always reply with an error, if someone has a platform really needs this,
7150 please contact vl@samba.org
7151 ****************************************************************************/
7153 void reply_writebs(struct smb_request
*req
)
7155 START_PROFILE(SMBwriteBs
);
7156 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7157 END_PROFILE(SMBwriteBs
);
7161 /****************************************************************************
7162 Reply to a SMBgetattrE.
7163 ****************************************************************************/
7165 void reply_getattrE(struct smb_request
*req
)
7167 connection_struct
*conn
= req
->conn
;
7168 SMB_STRUCT_STAT sbuf
;
7171 struct timespec create_ts
;
7173 START_PROFILE(SMBgetattrE
);
7176 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7177 END_PROFILE(SMBgetattrE
);
7181 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
7183 if(!fsp
|| (fsp
->conn
!= conn
)) {
7184 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7185 END_PROFILE(SMBgetattrE
);
7189 /* Do an fstat on this file */
7190 if(fsp_stat(fsp
, &sbuf
)) {
7191 reply_unixerror(req
, ERRDOS
, ERRnoaccess
);
7192 END_PROFILE(SMBgetattrE
);
7196 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
7199 * Convert the times into dos times. Set create
7200 * date to be last modify date as UNIX doesn't save
7204 reply_outbuf(req
, 11, 0);
7206 create_ts
= get_create_timespec(&sbuf
,
7207 lp_fake_dir_create_times(SNUM(conn
)));
7208 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
7209 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
, sbuf
.st_atime
);
7210 /* Should we check pending modtime here ? JRA */
7211 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
, sbuf
.st_mtime
);
7214 SIVAL(req
->outbuf
, smb_vwv6
, 0);
7215 SIVAL(req
->outbuf
, smb_vwv8
, 0);
7217 uint32 allocation_size
= get_allocation_size(conn
,fsp
, &sbuf
);
7218 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)sbuf
.st_size
);
7219 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
7221 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
7223 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
7225 END_PROFILE(SMBgetattrE
);