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.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
28 /* look in server.c for some explanation of these variables */
29 extern enum protocol_types Protocol
;
31 unsigned int smb_echo_count
= 0;
32 extern uint32 global_client_caps
;
34 extern struct current_user current_user
;
35 extern BOOL global_encrypted_passwords_negotiated
;
37 /****************************************************************************
38 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
39 path or anything including wildcards.
40 We're assuming here that '/' is not the second byte in any multibyte char
41 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
43 ****************************************************************************/
45 /* Custom version for processing POSIX paths. */
46 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
48 static NTSTATUS
check_path_syntax_internal(char *path
,
50 BOOL
*p_last_component_contains_wcard
)
54 NTSTATUS ret
= NT_STATUS_OK
;
55 BOOL start_of_name_component
= True
;
57 *p_last_component_contains_wcard
= False
;
60 if (IS_PATH_SEP(*s
,posix_path
)) {
62 * Safe to assume is not the second part of a mb char
63 * as this is handled below.
65 /* Eat multiple '/' or '\\' */
66 while (IS_PATH_SEP(*s
,posix_path
)) {
69 if ((d
!= path
) && (*s
!= '\0')) {
70 /* We only care about non-leading or trailing '/' or '\\' */
74 start_of_name_component
= True
;
76 *p_last_component_contains_wcard
= False
;
80 if (start_of_name_component
) {
81 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
82 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
85 * No mb char starts with '.' so we're safe checking the directory separator here.
88 /* If we just added a '/' - delete it */
89 if ((d
> path
) && (*(d
-1) == '/')) {
94 /* Are we at the start ? Can't go back further if so. */
96 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
99 /* Go back one level... */
100 /* We know this is safe as '/' cannot be part of a mb sequence. */
101 /* NOTE - if this assumption is invalid we are not in good shape... */
102 /* Decrement d first as d points to the *next* char to write into. */
103 for (d
--; d
> path
; d
--) {
107 s
+= 2; /* Else go past the .. */
108 /* We're still at the start of a name component, just the previous one. */
111 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
124 return NT_STATUS_OBJECT_NAME_INVALID
;
132 *p_last_component_contains_wcard
= True
;
141 /* Get the size of the next MB character. */
142 next_codepoint(s
,&siz
);
160 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
162 return NT_STATUS_INVALID_PARAMETER
;
165 start_of_name_component
= False
;
172 /****************************************************************************
173 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
174 No wildcards allowed.
175 ****************************************************************************/
177 NTSTATUS
check_path_syntax(char *path
)
180 return check_path_syntax_internal(path
, False
, &ignore
);
183 /****************************************************************************
184 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
185 Wildcards allowed - p_contains_wcard returns true if the last component contained
187 ****************************************************************************/
189 NTSTATUS
check_path_syntax_wcard(char *path
, BOOL
*p_contains_wcard
)
191 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
194 /****************************************************************************
195 Check the path for a POSIX client.
196 We're assuming here that '/' is not the second byte in any multibyte char
197 set (a safe assumption).
198 ****************************************************************************/
200 NTSTATUS
check_path_syntax_posix(char *path
)
203 return check_path_syntax_internal(path
, True
, &ignore
);
206 /****************************************************************************
207 Pull a string and check the path allowing a wilcard - provide for error return.
208 ****************************************************************************/
210 size_t srvstr_get_path_wcard(const char *inbuf
, uint16 smb_flags2
, char *dest
,
211 const char *src
, size_t dest_len
, size_t src_len
,
212 int flags
, NTSTATUS
*err
, BOOL
*contains_wcard
)
216 SMB_ASSERT(dest_len
== sizeof(pstring
));
220 ret
= srvstr_pull_buf(inbuf
, smb_flags2
, dest
, src
,
223 ret
= srvstr_pull(inbuf
, smb_flags2
, dest
, src
,
224 dest_len
, src_len
, flags
);
227 *contains_wcard
= False
;
229 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
231 * For a DFS path the function parse_dfs_path()
232 * will do the path processing, just make a copy.
238 if (lp_posix_pathnames()) {
239 *err
= check_path_syntax_posix(dest
);
241 *err
= check_path_syntax_wcard(dest
, contains_wcard
);
247 /****************************************************************************
248 Pull a string and check the path - provide for error return.
249 ****************************************************************************/
251 size_t srvstr_get_path(const char *inbuf
, uint16 smb_flags2
, char *dest
,
252 const char *src
, size_t dest_len
, size_t src_len
,
253 int flags
, NTSTATUS
*err
)
257 SMB_ASSERT(dest_len
== sizeof(pstring
));
261 ret
= srvstr_pull_buf(inbuf
, smb_flags2
, dest
, src
,
264 ret
= srvstr_pull(inbuf
, smb_flags2
, dest
, src
,
265 dest_len
, src_len
, flags
);
268 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
270 * For a DFS path the function parse_dfs_path()
271 * will do the path processing, just make a copy.
277 if (lp_posix_pathnames()) {
278 *err
= check_path_syntax_posix(dest
);
280 *err
= check_path_syntax(dest
);
286 /****************************************************************************
287 Reply to a (netbios-level) special message.
288 ****************************************************************************/
290 void reply_special(char *inbuf
)
292 int msg_type
= CVAL(inbuf
,0);
293 int msg_flags
= CVAL(inbuf
,1);
298 * We only really use 4 bytes of the outbuf, but for the smb_setlen
299 * calculation & friends (send_smb uses that) we need the full smb
302 char outbuf
[smb_size
];
304 static BOOL already_got_session
= False
;
308 memset(outbuf
, '\0', sizeof(outbuf
));
310 smb_setlen(inbuf
,outbuf
,0);
313 case 0x81: /* session request */
315 if (already_got_session
) {
316 exit_server_cleanly("multiple session request not permitted");
319 SCVAL(outbuf
,0,0x82);
321 if (name_len(inbuf
+4) > 50 ||
322 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
323 DEBUG(0,("Invalid name length in session request\n"));
326 name_extract(inbuf
,4,name1
);
327 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
328 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
331 set_local_machine_name(name1
, True
);
332 set_remote_machine_name(name2
, True
);
334 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
335 get_local_machine_name(), get_remote_machine_name(),
338 if (name_type
== 'R') {
339 /* We are being asked for a pathworks session ---
341 SCVAL(outbuf
, 0,0x83);
345 /* only add the client's machine name to the list
346 of possibly valid usernames if we are operating
347 in share mode security */
348 if (lp_security() == SEC_SHARE
) {
349 add_session_user(get_remote_machine_name());
352 reload_services(True
);
355 already_got_session
= True
;
358 case 0x89: /* session keepalive request
359 (some old clients produce this?) */
360 SCVAL(outbuf
,0,SMBkeepalive
);
364 case 0x82: /* positive session response */
365 case 0x83: /* negative session response */
366 case 0x84: /* retarget session response */
367 DEBUG(0,("Unexpected session response\n"));
370 case SMBkeepalive
: /* session keepalive */
375 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
376 msg_type
, msg_flags
));
378 send_smb(smbd_server_fd(), outbuf
);
382 /****************************************************************************
384 conn POINTER CAN BE NULL HERE !
385 ****************************************************************************/
387 int reply_tcon(connection_struct
*conn
,
388 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
392 char *service_buf
= NULL
;
393 char *password
= NULL
;
396 uint16 vuid
= SVAL(inbuf
,smb_uid
);
400 DATA_BLOB password_blob
;
402 START_PROFILE(SMBtcon
);
404 ctx
= talloc_init("reply_tcon");
406 END_PROFILE(SMBtcon
);
407 return ERROR_NT(NT_STATUS_NO_MEMORY
);
410 p
= smb_buf(inbuf
)+1;
411 p
+= srvstr_pull_buf_talloc(ctx
, inbuf
, SVAL(inbuf
, smb_flg2
),
412 &service_buf
, p
, STR_TERMINATE
) + 1;
413 pwlen
= srvstr_pull_buf_talloc(ctx
, inbuf
, SVAL(inbuf
, smb_flg2
),
414 &password
, p
, STR_TERMINATE
) + 1;
416 p
+= srvstr_pull_buf_talloc(ctx
, inbuf
, SVAL(inbuf
, smb_flg2
),
417 &dev
, p
, STR_TERMINATE
) + 1;
419 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
421 END_PROFILE(SMBtcon
);
422 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
424 p
= strrchr_m(service_buf
,'\\');
428 service
= service_buf
;
431 password_blob
= data_blob(password
, pwlen
+1);
433 conn
= make_connection(service
,password_blob
,dev
,vuid
,&nt_status
);
435 data_blob_clear_free(&password_blob
);
439 END_PROFILE(SMBtcon
);
440 return ERROR_NT(nt_status
);
443 outsize
= set_message(inbuf
,outbuf
,2,0,True
);
444 SSVAL(outbuf
,smb_vwv0
,max_recv
);
445 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
446 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
448 DEBUG(3,("tcon service=%s cnum=%d\n",
449 service
, conn
->cnum
));
451 END_PROFILE(SMBtcon
);
456 /****************************************************************************
457 Reply to a tcon and X.
458 conn POINTER CAN BE NULL HERE !
459 ****************************************************************************/
461 void reply_tcon_and_X(connection_struct
*conn
, struct smb_request
*req
)
463 char *service
= NULL
;
466 TALLOC_CTX
*ctx
= NULL
;
467 /* what the cleint thinks the device is */
468 char *client_devicetype
= NULL
;
469 /* what the server tells the client the share represents */
470 const char *server_devicetype
;
477 START_PROFILE(SMBtconX
);
480 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
481 END_PROFILE(SMBtconX
);
485 passlen
= SVAL(req
->inbuf
,smb_vwv3
);
486 tcon_flags
= SVAL(req
->inbuf
,smb_vwv2
);
488 /* we might have to close an old one */
489 if ((tcon_flags
& 0x1) && conn
) {
490 close_cnum(conn
,req
->vuid
);
493 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= smb_buflen(req
->inbuf
))) {
494 reply_doserror(req
, ERRDOS
, ERRbuftoosmall
);
495 END_PROFILE(SMBtconX
);
499 if (global_encrypted_passwords_negotiated
) {
500 password
= data_blob(smb_buf(req
->inbuf
),passlen
);
501 if (lp_security() == SEC_SHARE
) {
503 * Security = share always has a pad byte
504 * after the password.
506 p
= smb_buf(req
->inbuf
) + passlen
+ 1;
508 p
= smb_buf(req
->inbuf
) + passlen
;
511 password
= data_blob(smb_buf(req
->inbuf
),passlen
+1);
512 /* Ensure correct termination */
513 password
.data
[passlen
]=0;
514 p
= smb_buf(req
->inbuf
) + passlen
+ 1;
517 ctx
= talloc_init("reply_tcon_and_X");
519 data_blob_clear_free(&password
);
520 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
521 END_PROFILE(SMBtconX
);
524 p
+= srvstr_pull_buf_talloc(ctx
, req
->inbuf
, req
->flags2
, &path
, p
,
528 data_blob_clear_free(&password
);
530 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
531 END_PROFILE(SMBtconX
);
536 * the service name can be either: \\server\share
537 * or share directly like on the DELL PowerVault 705
540 q
= strchr_m(path
+2,'\\');
542 data_blob_clear_free(&password
);
544 reply_doserror(req
, ERRDOS
, ERRnosuchshare
);
545 END_PROFILE(SMBtconX
);
553 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
554 &client_devicetype
, p
,
555 MIN(6,smb_bufrem(req
->inbuf
, p
)), STR_ASCII
);
557 if (client_devicetype
== NULL
) {
558 data_blob_clear_free(&password
);
560 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
561 END_PROFILE(SMBtconX
);
565 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
567 conn
= make_connection(service
, password
, client_devicetype
,
568 req
->vuid
, &nt_status
);
570 data_blob_clear_free(&password
);
574 reply_nterror(req
, nt_status
);
575 END_PROFILE(SMBtconX
);
580 server_devicetype
= "IPC";
581 else if ( IS_PRINT(conn
) )
582 server_devicetype
= "LPT1:";
584 server_devicetype
= "A:";
586 if (Protocol
< PROTOCOL_NT1
) {
587 reply_outbuf(req
, 2, 0);
588 if (message_push_string(&req
->outbuf
, server_devicetype
,
589 STR_TERMINATE
|STR_ASCII
) == -1) {
591 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
592 END_PROFILE(SMBtconX
);
596 /* NT sets the fstype of IPC$ to the null string */
597 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
599 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
600 /* Return permissions. */
604 reply_outbuf(req
, 7, 0);
607 perm1
= FILE_ALL_ACCESS
;
608 perm2
= FILE_ALL_ACCESS
;
610 perm1
= CAN_WRITE(conn
) ?
615 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
616 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
618 reply_outbuf(req
, 3, 0);
621 if ((message_push_string(&req
->outbuf
, server_devicetype
,
622 STR_TERMINATE
|STR_ASCII
) == -1)
623 || (message_push_string(&req
->outbuf
, fstype
,
624 STR_TERMINATE
) == -1)) {
626 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
627 END_PROFILE(SMBtconX
);
631 /* what does setting this bit do? It is set by NT4 and
632 may affect the ability to autorun mounted cdroms */
633 SSVAL(req
->outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
634 (lp_csc_policy(SNUM(conn
)) << 2));
636 init_dfsroot(conn
, req
->inbuf
, req
->outbuf
);
640 DEBUG(3,("tconX service=%s \n",
643 /* set the incoming and outgoing tid to the just created one */
644 SSVAL(req
->inbuf
,smb_tid
,conn
->cnum
);
645 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
648 END_PROFILE(SMBtconX
);
650 chain_reply_new(req
);
654 /****************************************************************************
655 Reply to an unknown type.
656 ****************************************************************************/
658 int reply_unknown(char *inbuf
,char *outbuf
)
661 type
= CVAL(inbuf
,smb_com
);
663 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
664 smb_fn_name(type
), type
, type
));
666 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
669 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
671 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
672 smb_fn_name(type
), type
, type
));
673 reply_doserror(req
, ERRSRV
, ERRunknownsmb
);
677 /****************************************************************************
679 conn POINTER CAN BE NULL HERE !
680 ****************************************************************************/
682 int reply_ioctl(connection_struct
*conn
,
683 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
685 uint16 device
= SVAL(inbuf
,smb_vwv1
);
686 uint16 function
= SVAL(inbuf
,smb_vwv2
);
687 uint32 ioctl_code
= (device
<< 16) + function
;
688 int replysize
, outsize
;
690 START_PROFILE(SMBioctl
);
692 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
694 switch (ioctl_code
) {
695 case IOCTL_QUERY_JOB_INFO
:
699 END_PROFILE(SMBioctl
);
700 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
703 outsize
= set_message(inbuf
,outbuf
,8,replysize
+1,True
);
704 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
705 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
706 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
707 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
709 switch (ioctl_code
) {
710 case IOCTL_QUERY_JOB_INFO
:
712 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
714 END_PROFILE(SMBioctl
);
715 return(UNIXERROR(ERRDOS
,ERRbadfid
));
717 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
718 srvstr_push(outbuf
, p
+2, global_myname(), 15, STR_TERMINATE
|STR_ASCII
);
720 srvstr_push(outbuf
, p
+18, lp_servicename(SNUM(conn
)), 13, STR_TERMINATE
|STR_ASCII
);
726 END_PROFILE(SMBioctl
);
730 /****************************************************************************
731 Strange checkpath NTSTATUS mapping.
732 ****************************************************************************/
734 static NTSTATUS
map_checkpath_error(const char *inbuf
, NTSTATUS status
)
736 /* Strange DOS error code semantics only for checkpath... */
737 if (!(SVAL(inbuf
,smb_flg2
) & FLAGS2_32_BIT_ERROR_CODES
)) {
738 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
739 /* We need to map to ERRbadpath */
740 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
746 /****************************************************************************
747 Reply to a checkpath.
748 ****************************************************************************/
750 void reply_checkpath(connection_struct
*conn
, struct smb_request
*req
)
753 SMB_STRUCT_STAT sbuf
;
756 START_PROFILE(SMBcheckpath
);
758 srvstr_get_path((char *)req
->inbuf
, req
->flags2
, name
,
759 smb_buf(req
->inbuf
) + 1, sizeof(name
), 0,
760 STR_TERMINATE
, &status
);
761 if (!NT_STATUS_IS_OK(status
)) {
762 status
= map_checkpath_error((char *)req
->inbuf
, status
);
763 reply_nterror(req
, status
);
764 END_PROFILE(SMBcheckpath
);
768 status
= resolve_dfspath(conn
, req
->flags2
& FLAGS2_DFS_PATHNAMES
, name
);
769 if (!NT_STATUS_IS_OK(status
)) {
770 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
771 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
773 END_PROFILE(SMBcheckpath
);
779 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->inbuf
,smb_vwv0
)));
781 status
= unix_convert(conn
, name
, False
, NULL
, &sbuf
);
782 if (!NT_STATUS_IS_OK(status
)) {
786 status
= check_name(conn
, name
);
787 if (!NT_STATUS_IS_OK(status
)) {
788 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name
,nt_errstr(status
)));
792 if (!VALID_STAT(sbuf
) && (SMB_VFS_STAT(conn
,name
,&sbuf
) != 0)) {
793 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name
,strerror(errno
)));
794 status
= map_nt_error_from_unix(errno
);
798 if (!S_ISDIR(sbuf
.st_mode
)) {
799 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
801 END_PROFILE(SMBcheckpath
);
805 reply_outbuf(req
, 0, 0);
807 END_PROFILE(SMBcheckpath
);
812 END_PROFILE(SMBcheckpath
);
814 /* We special case this - as when a Windows machine
815 is parsing a path is steps through the components
816 one at a time - if a component fails it expects
817 ERRbadpath, not ERRbadfile.
819 status
= map_checkpath_error((char *)req
->inbuf
, status
);
820 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
822 * Windows returns different error codes if
823 * the parent directory is valid but not the
824 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
825 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
826 * if the path is invalid.
828 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
833 reply_nterror(req
, status
);
836 /****************************************************************************
838 ****************************************************************************/
840 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
844 SMB_STRUCT_STAT sbuf
;
851 START_PROFILE(SMBgetatr
);
853 p
= smb_buf(inbuf
) + 1;
854 p
+= srvstr_get_path(inbuf
, SVAL(inbuf
,smb_flg2
), fname
, p
,
855 sizeof(fname
), 0, STR_TERMINATE
, &status
);
856 if (!NT_STATUS_IS_OK(status
)) {
857 END_PROFILE(SMBgetatr
);
858 return ERROR_NT(status
);
861 status
= resolve_dfspath(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, fname
);
862 if (!NT_STATUS_IS_OK(status
)) {
863 END_PROFILE(SMBgetatr
);
864 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
865 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
867 return ERROR_NT(status
);
870 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
871 under WfWg - weird! */
872 if (*fname
== '\0') {
873 mode
= aHIDDEN
| aDIR
;
874 if (!CAN_WRITE(conn
)) {
880 status
= unix_convert(conn
, fname
, False
, NULL
,&sbuf
);
881 if (!NT_STATUS_IS_OK(status
)) {
882 END_PROFILE(SMBgetatr
);
883 return ERROR_NT(status
);
885 status
= check_name(conn
, fname
);
886 if (!NT_STATUS_IS_OK(status
)) {
887 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname
,nt_errstr(status
)));
888 END_PROFILE(SMBgetatr
);
889 return ERROR_NT(status
);
891 if (!VALID_STAT(sbuf
) && (SMB_VFS_STAT(conn
,fname
,&sbuf
) != 0)) {
892 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname
,strerror(errno
)));
893 return UNIXERROR(ERRDOS
,ERRbadfile
);
896 mode
= dos_mode(conn
,fname
,&sbuf
);
898 mtime
= sbuf
.st_mtime
;
904 outsize
= set_message(inbuf
,outbuf
,10,0,True
);
906 SSVAL(outbuf
,smb_vwv0
,mode
);
907 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
908 srv_put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
910 srv_put_dos_date3(outbuf
,smb_vwv1
,mtime
);
912 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
914 if (Protocol
>= PROTOCOL_NT1
) {
915 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
918 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname
, mode
, (unsigned int)size
) );
920 END_PROFILE(SMBgetatr
);
924 /****************************************************************************
926 ****************************************************************************/
928 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
934 SMB_STRUCT_STAT sbuf
;
938 START_PROFILE(SMBsetatr
);
940 p
= smb_buf(inbuf
) + 1;
941 p
+= srvstr_get_path(inbuf
, SVAL(inbuf
,smb_flg2
), fname
, p
,
942 sizeof(fname
), 0, STR_TERMINATE
, &status
);
943 if (!NT_STATUS_IS_OK(status
)) {
944 END_PROFILE(SMBsetatr
);
945 return ERROR_NT(status
);
948 status
= resolve_dfspath(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, fname
);
949 if (!NT_STATUS_IS_OK(status
)) {
950 END_PROFILE(SMBsetatr
);
951 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
952 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
954 return ERROR_NT(status
);
957 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
958 if (!NT_STATUS_IS_OK(status
)) {
959 END_PROFILE(SMBsetatr
);
960 return ERROR_NT(status
);
963 status
= check_name(conn
, fname
);
964 if (!NT_STATUS_IS_OK(status
)) {
965 END_PROFILE(SMBsetatr
);
966 return ERROR_NT(status
);
969 if (fname
[0] == '.' && fname
[1] == '\0') {
971 * Not sure here is the right place to catch this
972 * condition. Might be moved to somewhere else later -- vl
974 END_PROFILE(SMBsetatr
);
975 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
978 mode
= SVAL(inbuf
,smb_vwv0
);
979 mtime
= srv_make_unix_date3(inbuf
+smb_vwv1
);
981 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
982 if (VALID_STAT_OF_DIR(sbuf
))
987 if (file_set_dosmode(conn
,fname
,mode
,&sbuf
,False
) != 0) {
988 END_PROFILE(SMBsetatr
);
989 return UNIXERROR(ERRDOS
, ERRnoaccess
);
993 if (!set_filetime(conn
,fname
,convert_time_t_to_timespec(mtime
))) {
994 END_PROFILE(SMBsetatr
);
995 return UNIXERROR(ERRDOS
, ERRnoaccess
);
998 outsize
= set_message(inbuf
,outbuf
,0,0,False
);
1000 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
1002 END_PROFILE(SMBsetatr
);
1006 /****************************************************************************
1008 ****************************************************************************/
1010 void reply_dskattr(connection_struct
*conn
, struct smb_request
*req
)
1012 SMB_BIG_UINT dfree
,dsize
,bsize
;
1013 START_PROFILE(SMBdskattr
);
1015 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
1016 reply_unixerror(req
, ERRHRD
, ERRgeneral
);
1017 END_PROFILE(SMBdskattr
);
1021 reply_outbuf(req
, 5, 0);
1023 if (Protocol
<= PROTOCOL_LANMAN2
) {
1024 double total_space
, free_space
;
1025 /* we need to scale this to a number that DOS6 can handle. We
1026 use floating point so we can handle large drives on systems
1027 that don't have 64 bit integers
1029 we end up displaying a maximum of 2G to DOS systems
1031 total_space
= dsize
* (double)bsize
;
1032 free_space
= dfree
* (double)bsize
;
1034 dsize
= (total_space
+63*512) / (64*512);
1035 dfree
= (free_space
+63*512) / (64*512);
1037 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1038 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1040 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1041 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1042 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1043 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1045 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1046 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1047 SSVAL(req
->outbuf
,smb_vwv2
,512);
1048 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1051 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1053 END_PROFILE(SMBdskattr
);
1057 /****************************************************************************
1059 Can be called from SMBsearch, SMBffirst or SMBfunique.
1060 ****************************************************************************/
1062 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1072 unsigned int numentries
= 0;
1073 unsigned int maxentries
= 0;
1074 BOOL finished
= False
;
1080 BOOL check_descend
= False
;
1081 BOOL expect_close
= False
;
1083 BOOL mask_contains_wcard
= False
;
1084 BOOL allow_long_path_components
= (SVAL(inbuf
,smb_flg2
) & FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1086 START_PROFILE(SMBsearch
);
1088 if (lp_posix_pathnames()) {
1089 END_PROFILE(SMBsearch
);
1090 return reply_unknown(inbuf
, outbuf
);
1093 *mask
= *directory
= *fname
= 0;
1095 /* If we were called as SMBffirst then we must expect close. */
1096 if(CVAL(inbuf
,smb_com
) == SMBffirst
) {
1097 expect_close
= True
;
1100 outsize
= set_message(inbuf
,outbuf
,1,3,True
);
1101 maxentries
= SVAL(inbuf
,smb_vwv0
);
1102 dirtype
= SVAL(inbuf
,smb_vwv1
);
1103 p
= smb_buf(inbuf
) + 1;
1104 p
+= srvstr_get_path_wcard(inbuf
, SVAL(inbuf
,smb_flg2
), path
, p
,
1105 sizeof(path
), 0, STR_TERMINATE
, &nt_status
,
1106 &mask_contains_wcard
);
1107 if (!NT_STATUS_IS_OK(nt_status
)) {
1108 END_PROFILE(SMBsearch
);
1109 return ERROR_NT(nt_status
);
1112 nt_status
= resolve_dfspath_wcard(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, path
, &mask_contains_wcard
);
1113 if (!NT_STATUS_IS_OK(nt_status
)) {
1114 END_PROFILE(SMBsearch
);
1115 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1116 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
1118 return ERROR_NT(nt_status
);
1122 status_len
= SVAL(p
, 0);
1125 /* dirtype &= ~aDIR; */
1127 if (status_len
== 0) {
1128 SMB_STRUCT_STAT sbuf
;
1130 pstrcpy(directory
,path
);
1131 nt_status
= unix_convert(conn
, directory
, True
, NULL
, &sbuf
);
1132 if (!NT_STATUS_IS_OK(nt_status
)) {
1133 END_PROFILE(SMBsearch
);
1134 return ERROR_NT(nt_status
);
1137 nt_status
= check_name(conn
, directory
);
1138 if (!NT_STATUS_IS_OK(nt_status
)) {
1139 END_PROFILE(SMBsearch
);
1140 return ERROR_NT(nt_status
);
1143 p
= strrchr_m(directory
,'/');
1145 pstrcpy(mask
,directory
);
1146 pstrcpy(directory
,".");
1152 if (*directory
== '\0') {
1153 pstrcpy(directory
,".");
1155 memset((char *)status
,'\0',21);
1156 SCVAL(status
,0,(dirtype
& 0x1F));
1160 memcpy(status
,p
,21);
1161 status_dirtype
= CVAL(status
,0) & 0x1F;
1162 if (status_dirtype
!= (dirtype
& 0x1F)) {
1163 dirtype
= status_dirtype
;
1166 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1167 if (!conn
->dirptr
) {
1170 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1171 pstrcpy(mask
, dptr_wcard(dptr_num
));
1173 * For a 'continue' search we have no string. So
1174 * check from the initial saved string.
1176 mask_contains_wcard
= ms_has_wild(mask
);
1179 p
= smb_buf(outbuf
) + 3;
1181 if (status_len
== 0) {
1182 nt_status
= dptr_create(conn
,
1186 SVAL(inbuf
,smb_pid
),
1188 mask_contains_wcard
,
1191 if (!NT_STATUS_IS_OK(nt_status
)) {
1192 return ERROR_NT(nt_status
);
1194 dptr_num
= dptr_dnum(conn
->dirptr
);
1196 dirtype
= dptr_attr(dptr_num
);
1199 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1201 if ((dirtype
&0x1F) == aVOLID
) {
1202 memcpy(p
,status
,21);
1203 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),
1204 0,aVOLID
,0,!allow_long_path_components
);
1205 dptr_fill(p
+12,dptr_num
);
1206 if (dptr_zero(p
+12) && (status_len
==0)) {
1211 p
+= DIR_STRUCT_SIZE
;
1214 maxentries
= MIN(maxentries
, ((BUFFER_SIZE
- (p
- outbuf
))/DIR_STRUCT_SIZE
));
1216 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1217 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1218 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
)) {
1219 check_descend
= True
;
1222 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1223 finished
= !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
1225 memcpy(p
,status
,21);
1226 make_dir_struct(p
,mask
,fname
,size
, mode
,date
,
1227 !allow_long_path_components
);
1228 if (!dptr_fill(p
+12,dptr_num
)) {
1232 p
+= DIR_STRUCT_SIZE
;
1239 /* If we were called as SMBffirst with smb_search_id == NULL
1240 and no entries were found then return error and close dirptr
1243 if (numentries
== 0) {
1244 dptr_close(&dptr_num
);
1245 } else if(expect_close
&& status_len
== 0) {
1246 /* Close the dptr - we know it's gone */
1247 dptr_close(&dptr_num
);
1250 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1251 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
) {
1252 dptr_close(&dptr_num
);
1255 if ((numentries
== 0) && !mask_contains_wcard
) {
1256 return ERROR_BOTH(STATUS_NO_MORE_FILES
,ERRDOS
,ERRnofiles
);
1259 SSVAL(outbuf
,smb_vwv0
,numentries
);
1260 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1261 SCVAL(smb_buf(outbuf
),0,5);
1262 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1264 /* The replies here are never long name. */
1265 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1266 if (!allow_long_path_components
) {
1267 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) & (~FLAGS2_LONG_PATH_COMPONENTS
));
1270 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1271 SSVAL(outbuf
,smb_flg2
, (SVAL(outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1273 outsize
+= DIR_STRUCT_SIZE
*numentries
;
1274 smb_setlen(inbuf
,outbuf
,outsize
- 4);
1276 if ((! *directory
) && dptr_path(dptr_num
))
1277 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1279 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1280 smb_fn_name(CVAL(inbuf
,smb_com
)),
1281 mask
, directory
, dirtype
, numentries
, maxentries
) );
1283 END_PROFILE(SMBsearch
);
1287 /****************************************************************************
1288 Reply to a fclose (stop directory search).
1289 ****************************************************************************/
1291 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1300 BOOL path_contains_wcard
= False
;
1302 START_PROFILE(SMBfclose
);
1304 if (lp_posix_pathnames()) {
1305 END_PROFILE(SMBfclose
);
1306 return reply_unknown(inbuf
, outbuf
);
1309 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
1310 p
= smb_buf(inbuf
) + 1;
1311 p
+= srvstr_get_path_wcard(inbuf
, SVAL(inbuf
,smb_flg2
), path
, p
,
1312 sizeof(path
), 0, STR_TERMINATE
, &err
,
1313 &path_contains_wcard
);
1314 if (!NT_STATUS_IS_OK(err
)) {
1315 END_PROFILE(SMBfclose
);
1316 return ERROR_NT(err
);
1319 status_len
= SVAL(p
,0);
1322 if (status_len
== 0) {
1323 END_PROFILE(SMBfclose
);
1324 return ERROR_DOS(ERRSRV
,ERRsrverror
);
1327 memcpy(status
,p
,21);
1329 if(dptr_fetch(status
+12,&dptr_num
)) {
1330 /* Close the dptr - we know it's gone */
1331 dptr_close(&dptr_num
);
1334 SSVAL(outbuf
,smb_vwv0
,0);
1336 DEBUG(3,("search close\n"));
1338 END_PROFILE(SMBfclose
);
1342 /****************************************************************************
1344 ****************************************************************************/
1346 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1354 SMB_STRUCT_STAT sbuf
;
1356 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1358 uint32 dos_attr
= SVAL(inbuf
,smb_vwv1
);
1361 uint32 create_disposition
;
1362 uint32 create_options
= 0;
1364 struct smb_request req
;
1366 START_PROFILE(SMBopen
);
1368 init_smb_request(&req
, (uint8
*)inbuf
);
1370 deny_mode
= SVAL(inbuf
,smb_vwv0
);
1372 srvstr_get_path(inbuf
, SVAL(inbuf
,smb_flg2
), fname
, smb_buf(inbuf
)+1,
1373 sizeof(fname
), 0, STR_TERMINATE
, &status
);
1374 if (!NT_STATUS_IS_OK(status
)) {
1375 END_PROFILE(SMBopen
);
1376 return ERROR_NT(status
);
1379 status
= resolve_dfspath(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, fname
);
1380 if (!NT_STATUS_IS_OK(status
)) {
1381 END_PROFILE(SMBopen
);
1382 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1383 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
1385 return ERROR_NT(status
);
1388 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
1389 if (!NT_STATUS_IS_OK(status
)) {
1390 END_PROFILE(SMBopen
);
1391 return ERROR_NT(status
);
1394 status
= check_name(conn
, fname
);
1395 if (!NT_STATUS_IS_OK(status
)) {
1396 END_PROFILE(SMBopen
);
1397 return ERROR_NT(status
);
1400 if (!map_open_params_to_ntcreate(fname
, deny_mode
, OPENX_FILE_EXISTS_OPEN
,
1401 &access_mask
, &share_mode
, &create_disposition
, &create_options
)) {
1402 END_PROFILE(SMBopen
);
1403 return ERROR_NT(NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1406 status
= open_file_ntcreate(conn
, &req
, fname
, &sbuf
,
1415 if (!NT_STATUS_IS_OK(status
)) {
1416 END_PROFILE(SMBopen
);
1417 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
1418 /* We have re-scheduled this call. */
1421 return ERROR_NT(status
);
1424 size
= sbuf
.st_size
;
1425 fattr
= dos_mode(conn
,fname
,&sbuf
);
1426 mtime
= sbuf
.st_mtime
;
1429 DEBUG(3,("attempt to open a directory %s\n",fname
));
1430 close_file(fsp
,ERROR_CLOSE
);
1431 END_PROFILE(SMBopen
);
1432 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1435 outsize
= set_message(inbuf
,outbuf
,7,0,True
);
1436 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1437 SSVAL(outbuf
,smb_vwv1
,fattr
);
1438 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1439 srv_put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1441 srv_put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1443 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1444 SSVAL(outbuf
,smb_vwv6
,deny_mode
);
1446 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1447 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1450 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1451 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1453 END_PROFILE(SMBopen
);
1457 /****************************************************************************
1458 Reply to an open and X.
1459 ****************************************************************************/
1461 void reply_open_and_X(connection_struct
*conn
, struct smb_request
*req
)
1467 /* Breakout the oplock request bits so we can set the
1468 reply bits separately. */
1469 int ex_oplock_request
;
1470 int core_oplock_request
;
1473 int smb_sattr
= SVAL(req
->inbuf
,smb_vwv4
);
1474 uint32 smb_time
= make_unix_date3(req
->inbuf
+smb_vwv6
);
1479 SMB_STRUCT_STAT sbuf
;
1483 SMB_BIG_UINT allocation_size
;
1484 ssize_t retval
= -1;
1487 uint32 create_disposition
;
1488 uint32 create_options
= 0;
1490 START_PROFILE(SMBopenX
);
1492 if (req
->wct
< 15) {
1493 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1494 END_PROFILE(SMBopenX
);
1498 open_flags
= SVAL(req
->inbuf
,smb_vwv2
);
1499 deny_mode
= SVAL(req
->inbuf
,smb_vwv3
);
1500 smb_attr
= SVAL(req
->inbuf
,smb_vwv5
);
1501 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1502 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1503 oplock_request
= ex_oplock_request
| core_oplock_request
;
1504 smb_ofun
= SVAL(req
->inbuf
,smb_vwv8
);
1505 allocation_size
= (SMB_BIG_UINT
)IVAL(req
->inbuf
,smb_vwv9
);
1507 /* If it's an IPC, pass off the pipe handler. */
1509 if (lp_nt_pipe_support()) {
1510 reply_open_pipe_and_X(conn
, req
);
1512 reply_doserror(req
, ERRSRV
, ERRaccess
);
1514 END_PROFILE(SMBopenX
);
1518 /* XXXX we need to handle passed times, sattr and flags */
1519 srvstr_get_path((char *)req
->inbuf
, req
->flags2
, fname
,
1520 smb_buf(req
->inbuf
), sizeof(fname
), 0, STR_TERMINATE
,
1522 if (!NT_STATUS_IS_OK(status
)) {
1523 reply_nterror(req
, status
);
1524 END_PROFILE(SMBopenX
);
1528 status
= resolve_dfspath(conn
, req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1530 if (!NT_STATUS_IS_OK(status
)) {
1531 END_PROFILE(SMBopenX
);
1532 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1533 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1534 ERRSRV
, ERRbadpath
);
1537 reply_nterror(req
, status
);
1541 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
1542 if (!NT_STATUS_IS_OK(status
)) {
1543 reply_nterror(req
, status
);
1544 END_PROFILE(SMBopenX
);
1548 status
= check_name(conn
, fname
);
1549 if (!NT_STATUS_IS_OK(status
)) {
1550 reply_nterror(req
, status
);
1551 END_PROFILE(SMBopenX
);
1555 if (!map_open_params_to_ntcreate(fname
, deny_mode
, smb_ofun
,
1558 &create_disposition
,
1560 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1561 END_PROFILE(SMBopenX
);
1565 status
= open_file_ntcreate(conn
, req
, fname
, &sbuf
,
1574 if (!NT_STATUS_IS_OK(status
)) {
1575 END_PROFILE(SMBopenX
);
1576 if (open_was_deferred(req
->mid
)) {
1577 /* We have re-scheduled this call. */
1580 reply_nterror(req
, status
);
1584 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1585 if the file is truncated or created. */
1586 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1587 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1588 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1589 close_file(fsp
,ERROR_CLOSE
);
1590 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1591 END_PROFILE(SMBopenX
);
1594 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1596 close_file(fsp
,ERROR_CLOSE
);
1597 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1598 END_PROFILE(SMBopenX
);
1601 sbuf
.st_size
= get_allocation_size(conn
,fsp
,&sbuf
);
1604 fattr
= dos_mode(conn
,fname
,&sbuf
);
1605 mtime
= sbuf
.st_mtime
;
1607 close_file(fsp
,ERROR_CLOSE
);
1608 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
1609 END_PROFILE(SMBopenX
);
1613 /* If the caller set the extended oplock request bit
1614 and we granted one (by whatever means) - set the
1615 correct bit for extended oplock reply.
1618 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1619 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1622 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1623 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1626 /* If the caller set the core oplock request bit
1627 and we granted one (by whatever means) - set the
1628 correct bit for core oplock reply.
1631 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1632 reply_outbuf(req
, 19, 0);
1634 reply_outbuf(req
, 15, 0);
1637 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1638 SCVAL(req
->outbuf
, smb_flg
,
1639 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1642 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1643 SCVAL(req
->outbuf
, smb_flg
,
1644 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1647 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
1648 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
1649 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1650 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
1652 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
1654 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
1655 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
1656 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
1658 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1659 SIVAL(req
->outbuf
, smb_vwv15
, STD_RIGHT_ALL_ACCESS
);
1662 END_PROFILE(SMBopenX
);
1663 chain_reply_new(req
);
1667 /****************************************************************************
1668 Reply to a SMBulogoffX.
1669 conn POINTER CAN BE NULL HERE !
1670 ****************************************************************************/
1672 void reply_ulogoffX(connection_struct
*conn
, struct smb_request
*req
)
1676 START_PROFILE(SMBulogoffX
);
1678 vuser
= get_valid_user_struct(req
->vuid
);
1681 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1685 /* in user level security we are supposed to close any files
1686 open by this user */
1687 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
1688 file_close_user(req
->vuid
);
1691 invalidate_vuid(req
->vuid
);
1693 reply_outbuf(req
, 2, 0);
1695 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
1697 END_PROFILE(SMBulogoffX
);
1698 chain_reply_new(req
);
1701 /****************************************************************************
1702 Reply to a mknew or a create.
1703 ****************************************************************************/
1705 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1710 uint32 fattr
= SVAL(inbuf
,smb_vwv0
);
1711 struct timespec ts
[2];
1713 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1714 SMB_STRUCT_STAT sbuf
;
1716 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
1717 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
1718 uint32 create_disposition
;
1719 uint32 create_options
= 0;
1720 struct smb_request req
;
1722 START_PROFILE(SMBcreate
);
1724 init_smb_request(&req
, (uint8
*)inbuf
);
1726 com
= SVAL(inbuf
,smb_com
);
1728 ts
[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf
+ smb_vwv1
)); /* mtime. */
1730 srvstr_get_path(inbuf
, SVAL(inbuf
,smb_flg2
), fname
, smb_buf(inbuf
) + 1,
1731 sizeof(fname
), 0, STR_TERMINATE
, &status
);
1732 if (!NT_STATUS_IS_OK(status
)) {
1733 END_PROFILE(SMBcreate
);
1734 return ERROR_NT(status
);
1737 status
= resolve_dfspath(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, fname
);
1738 if (!NT_STATUS_IS_OK(status
)) {
1739 END_PROFILE(SMBcreate
);
1740 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1741 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
1743 return ERROR_NT(status
);
1746 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
1747 if (!NT_STATUS_IS_OK(status
)) {
1748 END_PROFILE(SMBcreate
);
1749 return ERROR_NT(status
);
1752 status
= check_name(conn
, fname
);
1753 if (!NT_STATUS_IS_OK(status
)) {
1754 END_PROFILE(SMBcreate
);
1755 return ERROR_NT(status
);
1758 if (fattr
& aVOLID
) {
1759 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1762 if(com
== SMBmknew
) {
1763 /* We should fail if file exists. */
1764 create_disposition
= FILE_CREATE
;
1766 /* Create if file doesn't exist, truncate if it does. */
1767 create_disposition
= FILE_OVERWRITE_IF
;
1770 /* Open file using ntcreate. */
1771 status
= open_file_ntcreate(conn
, &req
, fname
, &sbuf
,
1780 if (!NT_STATUS_IS_OK(status
)) {
1781 END_PROFILE(SMBcreate
);
1782 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
1783 /* We have re-scheduled this call. */
1786 return ERROR_NT(status
);
1789 ts
[0] = get_atimespec(&sbuf
); /* atime. */
1790 file_ntimes(conn
, fname
, ts
);
1792 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
1793 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1795 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1796 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1799 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1800 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1803 DEBUG( 2, ( "reply_mknew: file %s\n", fname
) );
1804 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname
, fsp
->fh
->fd
, (unsigned int)fattr
) );
1806 END_PROFILE(SMBcreate
);
1810 /****************************************************************************
1811 Reply to a create temporary file.
1812 ****************************************************************************/
1814 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1818 uint32 fattr
= SVAL(inbuf
,smb_vwv0
);
1820 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1822 SMB_STRUCT_STAT sbuf
;
1825 unsigned int namelen
;
1826 struct smb_request req
;
1828 START_PROFILE(SMBctemp
);
1830 init_smb_request(&req
, (uint8
*)inbuf
);
1832 srvstr_get_path(inbuf
, SVAL(inbuf
,smb_flg2
), fname
, smb_buf(inbuf
)+1,
1833 sizeof(fname
), 0, STR_TERMINATE
, &status
);
1834 if (!NT_STATUS_IS_OK(status
)) {
1835 END_PROFILE(SMBctemp
);
1836 return ERROR_NT(status
);
1839 pstrcat(fname
,"/TMXXXXXX");
1841 pstrcat(fname
,"TMXXXXXX");
1844 status
= resolve_dfspath(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, fname
);
1845 if (!NT_STATUS_IS_OK(status
)) {
1846 END_PROFILE(SMBctemp
);
1847 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1848 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
1850 return ERROR_NT(status
);
1853 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
1854 if (!NT_STATUS_IS_OK(status
)) {
1855 END_PROFILE(SMBctemp
);
1856 return ERROR_NT(status
);
1859 status
= check_name(conn
, fname
);
1860 if (!NT_STATUS_IS_OK(status
)) {
1861 END_PROFILE(SMBctemp
);
1862 return ERROR_NT(status
);
1865 tmpfd
= smb_mkstemp(fname
);
1867 END_PROFILE(SMBctemp
);
1868 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1871 SMB_VFS_STAT(conn
,fname
,&sbuf
);
1873 /* We should fail if file does not exist. */
1874 status
= open_file_ntcreate(conn
, &req
, fname
, &sbuf
,
1875 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
,
1876 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1883 /* close fd from smb_mkstemp() */
1886 if (!NT_STATUS_IS_OK(status
)) {
1887 END_PROFILE(SMBctemp
);
1888 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
1889 /* We have re-scheduled this call. */
1892 return ERROR_NT(status
);
1895 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
1896 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1898 /* the returned filename is relative to the directory */
1899 s
= strrchr_m(fname
, '/');
1906 p
= smb_buf(outbuf
);
1908 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1909 thing in the byte section. JRA */
1910 SSVALS(p
, 0, -1); /* what is this? not in spec */
1912 namelen
= srvstr_push(outbuf
, p
, s
, -1, STR_ASCII
|STR_TERMINATE
);
1914 outsize
= set_message_end(inbuf
,outbuf
, p
);
1916 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1917 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1920 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1921 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1924 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname
) );
1925 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname
, fsp
->fh
->fd
,
1926 (unsigned int)sbuf
.st_mode
) );
1928 END_PROFILE(SMBctemp
);
1932 /*******************************************************************
1933 Check if a user is allowed to rename a file.
1934 ********************************************************************/
1936 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
1937 uint16 dirtype
, SMB_STRUCT_STAT
*pst
)
1941 if (!CAN_WRITE(conn
)) {
1942 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1945 fmode
= dos_mode(conn
, fsp
->fsp_name
, pst
);
1946 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
)) {
1947 return NT_STATUS_NO_SUCH_FILE
;
1950 if (S_ISDIR(pst
->st_mode
)) {
1951 return NT_STATUS_OK
;
1954 if (fsp
->access_mask
& DELETE_ACCESS
) {
1955 return NT_STATUS_OK
;
1958 return NT_STATUS_ACCESS_DENIED
;
1961 /*******************************************************************
1962 * unlink a file with all relevant access checks
1963 *******************************************************************/
1965 static NTSTATUS
do_unlink(connection_struct
*conn
, struct smb_request
*req
,
1966 char *fname
, uint32 dirtype
)
1968 SMB_STRUCT_STAT sbuf
;
1971 uint32 dirtype_orig
= dirtype
;
1974 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname
, dirtype
));
1976 if (!CAN_WRITE(conn
)) {
1977 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1980 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
) != 0) {
1981 return map_nt_error_from_unix(errno
);
1984 fattr
= dos_mode(conn
,fname
,&sbuf
);
1986 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
1987 dirtype
= aDIR
|aARCH
|aRONLY
;
1990 dirtype
&= (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
);
1992 return NT_STATUS_NO_SUCH_FILE
;
1995 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
1997 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1999 return NT_STATUS_NO_SUCH_FILE
;
2002 if (dirtype_orig
& 0x8000) {
2003 /* These will never be set for POSIX. */
2004 return NT_STATUS_NO_SUCH_FILE
;
2008 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2009 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2012 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2013 return NT_STATUS_NO_SUCH_FILE
;
2016 if (dirtype
& 0xFF00) {
2017 /* These will never be set for POSIX. */
2018 return NT_STATUS_NO_SUCH_FILE
;
2023 return NT_STATUS_NO_SUCH_FILE
;
2026 /* Can't delete a directory. */
2028 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2033 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
2034 return NT_STATUS_OBJECT_NAME_INVALID
;
2035 #endif /* JRATEST */
2037 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2039 On a Windows share, a file with read-only dosmode can be opened with
2040 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2041 fails with NT_STATUS_CANNOT_DELETE error.
2043 This semantic causes a problem that a user can not
2044 rename a file with read-only dosmode on a Samba share
2045 from a Windows command prompt (i.e. cmd.exe, but can rename
2046 from Windows Explorer).
2049 if (!lp_delete_readonly(SNUM(conn
))) {
2050 if (fattr
& aRONLY
) {
2051 return NT_STATUS_CANNOT_DELETE
;
2055 /* On open checks the open itself will check the share mode, so
2056 don't do it here as we'll get it wrong. */
2058 status
= open_file_ntcreate(conn
, req
, fname
, &sbuf
,
2063 FILE_ATTRIBUTE_NORMAL
,
2064 req
!= NULL
? 0 : INTERNAL_OPEN_ONLY
,
2067 if (!NT_STATUS_IS_OK(status
)) {
2068 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2069 nt_errstr(status
)));
2073 /* The set is across all open files on this dev/inode pair. */
2074 if (!set_delete_on_close(fsp
, True
, ¤t_user
.ut
)) {
2075 close_file(fsp
, NORMAL_CLOSE
);
2076 return NT_STATUS_ACCESS_DENIED
;
2079 return close_file(fsp
,NORMAL_CLOSE
);
2082 /****************************************************************************
2083 The guts of the unlink command, split out so it may be called by the NT SMB
2085 ****************************************************************************/
2087 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2088 uint32 dirtype
, char *name
, BOOL has_wild
)
2094 NTSTATUS status
= NT_STATUS_OK
;
2095 SMB_STRUCT_STAT sbuf
;
2097 *directory
= *mask
= 0;
2099 status
= unix_convert(conn
, name
, has_wild
, NULL
, &sbuf
);
2100 if (!NT_STATUS_IS_OK(status
)) {
2104 p
= strrchr_m(name
,'/');
2106 pstrcpy(directory
,".");
2110 pstrcpy(directory
,name
);
2115 * We should only check the mangled cache
2116 * here if unix_convert failed. This means
2117 * that the path in 'mask' doesn't exist
2118 * on the file system and so we need to look
2119 * for a possible mangle. This patch from
2120 * Tine Smukavec <valentin.smukavec@hermes.si>.
2123 if (!VALID_STAT(sbuf
) && mangle_is_mangled(mask
,conn
->params
))
2124 mangle_check_cache( mask
, sizeof(pstring
)-1, conn
->params
);
2127 pstrcat(directory
,"/");
2128 pstrcat(directory
,mask
);
2130 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2133 status
= check_name(conn
, directory
);
2134 if (!NT_STATUS_IS_OK(status
)) {
2138 status
= do_unlink(conn
, req
, directory
, dirtype
);
2139 if (!NT_STATUS_IS_OK(status
)) {
2145 struct smb_Dir
*dir_hnd
= NULL
;
2149 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == aDIR
) {
2150 return NT_STATUS_OBJECT_NAME_INVALID
;
2153 if (strequal(mask
,"????????.???")) {
2157 status
= check_name(conn
, directory
);
2158 if (!NT_STATUS_IS_OK(status
)) {
2162 dir_hnd
= OpenDir(conn
, directory
, mask
, dirtype
);
2163 if (dir_hnd
== NULL
) {
2164 return map_nt_error_from_unix(errno
);
2167 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2168 the pattern matches against the long name, otherwise the short name
2169 We don't implement this yet XXXX
2172 status
= NT_STATUS_NO_SUCH_FILE
;
2174 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
2177 pstrcpy(fname
,dname
);
2179 if (!is_visible_file(conn
, directory
, dname
, &st
, True
)) {
2183 /* Quick check for "." and ".." */
2184 if (fname
[0] == '.') {
2185 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
2190 if(!mask_match(fname
, mask
, conn
->case_sensitive
)) {
2194 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
2196 status
= check_name(conn
, fname
);
2197 if (!NT_STATUS_IS_OK(status
)) {
2202 status
= do_unlink(conn
, req
, fname
, dirtype
);
2203 if (!NT_STATUS_IS_OK(status
)) {
2208 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2214 if (count
== 0 && NT_STATUS_IS_OK(status
)) {
2215 status
= map_nt_error_from_unix(errno
);
2221 /****************************************************************************
2223 ****************************************************************************/
2225 void reply_unlink(connection_struct
*conn
, struct smb_request
*req
)
2230 BOOL path_contains_wcard
= False
;
2232 START_PROFILE(SMBunlink
);
2235 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2236 END_PROFILE(SMBunlink
);
2240 dirtype
= SVAL(req
->inbuf
,smb_vwv0
);
2242 srvstr_get_path_wcard((char *)req
->inbuf
, req
->flags2
, name
,
2243 smb_buf(req
->inbuf
) + 1, sizeof(name
), 0,
2244 STR_TERMINATE
, &status
, &path_contains_wcard
);
2245 if (!NT_STATUS_IS_OK(status
)) {
2246 reply_nterror(req
, status
);
2247 END_PROFILE(SMBunlink
);
2251 status
= resolve_dfspath_wcard(conn
,
2252 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2253 name
, &path_contains_wcard
);
2254 if (!NT_STATUS_IS_OK(status
)) {
2255 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2256 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2257 ERRSRV
, ERRbadpath
);
2258 END_PROFILE(SMBunlink
);
2261 reply_nterror(req
, status
);
2262 END_PROFILE(SMBunlink
);
2266 DEBUG(3,("reply_unlink : %s\n",name
));
2268 status
= unlink_internals(conn
, req
, dirtype
, name
,
2269 path_contains_wcard
);
2270 if (!NT_STATUS_IS_OK(status
)) {
2271 if (open_was_deferred(req
->mid
)) {
2272 /* We have re-scheduled this call. */
2273 END_PROFILE(SMBunlink
);
2276 reply_nterror(req
, status
);
2277 END_PROFILE(SMBunlink
);
2281 reply_outbuf(req
, 0, 0);
2282 END_PROFILE(SMBunlink
);
2287 /****************************************************************************
2289 ****************************************************************************/
2291 static void fail_readraw(void)
2294 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2296 exit_server_cleanly(errstr
);
2299 /****************************************************************************
2300 Fake (read/write) sendfile. Returns -1 on read or write fail.
2301 ****************************************************************************/
2303 static ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
, char *buf
, size_t bufsize
)
2305 size_t tosend
= nread
;
2307 while (tosend
> 0) {
2311 if (tosend
> bufsize
) {
2316 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2321 /* If we had a short read, fill with zeros. */
2322 if (ret
< cur_read
) {
2323 memset(buf
, '\0', cur_read
- ret
);
2326 if (write_data(smbd_server_fd(),buf
,cur_read
) != cur_read
) {
2330 startpos
+= cur_read
;
2333 return (ssize_t
)nread
;
2336 /****************************************************************************
2337 Use sendfile in readbraw.
2338 ****************************************************************************/
2340 void send_file_readbraw(connection_struct
*conn
, files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
,
2341 ssize_t mincount
, char *outbuf
, int out_buffsize
)
2345 #if defined(WITH_SENDFILE)
2347 * We can only use sendfile on a non-chained packet
2348 * but we can use on a non-oplocked file. tridge proved this
2349 * on a train in Germany :-). JRA.
2350 * reply_readbraw has already checked the length.
2353 if ( (chain_size
== 0) && (nread
> 0) &&
2354 (fsp
->wcp
== NULL
) && lp_use_sendfile(SNUM(conn
)) ) {
2357 _smb_setlen(outbuf
,nread
);
2358 header
.data
= (uint8
*)outbuf
;
2362 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fh
->fd
, &header
, startpos
, nread
) == -1) {
2363 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2364 if (errno
== ENOSYS
) {
2365 goto normal_readbraw
;
2369 * Special hack for broken Linux with no working sendfile. If we
2370 * return EINTR we sent the header but not the rest of the data.
2371 * Fake this up by doing read/write calls.
2373 if (errno
== EINTR
) {
2374 /* Ensure we don't do this again. */
2375 set_use_sendfile(SNUM(conn
), False
);
2376 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2378 if (fake_sendfile(fsp
, startpos
, nread
, outbuf
+ 4, out_buffsize
- 4) == -1) {
2379 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2380 fsp
->fsp_name
, strerror(errno
) ));
2381 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2386 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2387 fsp
->fsp_name
, strerror(errno
) ));
2388 exit_server_cleanly("send_file_readbraw sendfile failed");
2398 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2399 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2408 _smb_setlen(outbuf
,ret
);
2409 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
2413 /****************************************************************************
2414 Reply to a readbraw (core+ protocol).
2415 ****************************************************************************/
2417 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int out_buffsize
)
2419 ssize_t maxcount
,mincount
;
2422 char *header
= outbuf
;
2424 START_PROFILE(SMBreadbraw
);
2426 if (srv_is_signing_active()) {
2427 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2431 * Special check if an oplock break has been issued
2432 * and the readraw request croses on the wire, we must
2433 * return a zero length response here.
2436 fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
2438 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
2440 * fsp could be NULL here so use the value from the packet. JRA.
2442 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
2443 _smb_setlen(header
,0);
2444 if (write_data(smbd_server_fd(),header
,4) != 4)
2446 END_PROFILE(SMBreadbraw
);
2450 CHECK_FSP(fsp
,conn
);
2452 flush_write_cache(fsp
, READRAW_FLUSH
);
2454 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
2455 if(CVAL(inbuf
,smb_wct
) == 10) {
2457 * This is a large offset (64 bit) read.
2459 #ifdef LARGE_SMB_OFF_T
2461 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
2463 #else /* !LARGE_SMB_OFF_T */
2466 * Ensure we haven't been sent a >32 bit offset.
2469 if(IVAL(inbuf
,smb_vwv8
) != 0) {
2470 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2471 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
2472 _smb_setlen(header
,0);
2473 if (write_data(smbd_server_fd(),header
,4) != 4)
2475 END_PROFILE(SMBreadbraw
);
2479 #endif /* LARGE_SMB_OFF_T */
2482 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
2483 _smb_setlen(header
,0);
2484 if (write_data(smbd_server_fd(),header
,4) != 4)
2486 END_PROFILE(SMBreadbraw
);
2490 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
2491 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
2493 /* ensure we don't overrun the packet size */
2494 maxcount
= MIN(65535,maxcount
);
2496 if (!is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
2500 if (SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
,&st
) == 0) {
2504 if (startpos
>= size
) {
2507 nread
= MIN(maxcount
,(size
- startpos
));
2511 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2512 if (nread
< mincount
)
2516 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp
->fnum
, (double)startpos
,
2517 (unsigned long)maxcount
, (unsigned long)mincount
, (unsigned long)nread
) );
2519 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
, outbuf
, out_buffsize
);
2521 DEBUG(5,("readbraw finished\n"));
2522 END_PROFILE(SMBreadbraw
);
2527 #define DBGC_CLASS DBGC_LOCKING
2529 /****************************************************************************
2530 Reply to a lockread (core+ protocol).
2531 ****************************************************************************/
2533 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
2541 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
2542 struct byte_range_lock
*br_lck
= NULL
;
2543 START_PROFILE(SMBlockread
);
2545 CHECK_FSP(fsp
,conn
);
2546 if (!CHECK_READ(fsp
,inbuf
)) {
2547 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
2550 release_level_2_oplocks_on_change(fsp
);
2552 numtoread
= SVAL(inbuf
,smb_vwv1
);
2553 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2555 outsize
= set_message(inbuf
,outbuf
,5,3,True
);
2556 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2557 data
= smb_buf(outbuf
) + 3;
2560 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2561 * protocol request that predates the read/write lock concept.
2562 * Thus instead of asking for a read lock here we need to ask
2563 * for a write lock. JRA.
2564 * Note that the requested lock size is unaffected by max_recv.
2567 br_lck
= do_lock(smbd_messaging_context(),
2569 (uint32
)SVAL(inbuf
,smb_pid
),
2570 (SMB_BIG_UINT
)numtoread
,
2571 (SMB_BIG_UINT
)startpos
,
2574 False
, /* Non-blocking lock. */
2577 TALLOC_FREE(br_lck
);
2579 if (NT_STATUS_V(status
)) {
2580 END_PROFILE(SMBlockread
);
2581 return ERROR_NT(status
);
2585 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2588 if (numtoread
> max_recv
) {
2589 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2590 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2591 (unsigned int)numtoread
, (unsigned int)max_recv
));
2592 numtoread
= MIN(numtoread
,max_recv
);
2594 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2597 END_PROFILE(SMBlockread
);
2598 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2602 SSVAL(outbuf
,smb_vwv0
,nread
);
2603 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2604 SSVAL(smb_buf(outbuf
),1,nread
);
2606 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2607 fsp
->fnum
, (int)numtoread
, (int)nread
));
2609 END_PROFILE(SMBlockread
);
2614 #define DBGC_CLASS DBGC_ALL
2616 /****************************************************************************
2618 ****************************************************************************/
2620 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2627 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
2628 START_PROFILE(SMBread
);
2630 CHECK_FSP(fsp
,conn
);
2631 if (!CHECK_READ(fsp
,inbuf
)) {
2632 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
2635 numtoread
= SVAL(inbuf
,smb_vwv1
);
2636 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2638 outsize
= set_message(inbuf
,outbuf
,5,3,True
);
2639 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2641 * The requested read size cannot be greater than max_recv. JRA.
2643 if (numtoread
> max_recv
) {
2644 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2645 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2646 (unsigned int)numtoread
, (unsigned int)max_recv
));
2647 numtoread
= MIN(numtoread
,max_recv
);
2650 data
= smb_buf(outbuf
) + 3;
2652 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
2653 END_PROFILE(SMBread
);
2654 return ERROR_DOS(ERRDOS
,ERRlock
);
2658 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2661 END_PROFILE(SMBread
);
2662 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2666 SSVAL(outbuf
,smb_vwv0
,nread
);
2667 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2668 SCVAL(smb_buf(outbuf
),0,1);
2669 SSVAL(smb_buf(outbuf
),1,nread
);
2671 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2672 fsp
->fnum
, (int)numtoread
, (int)nread
) );
2674 END_PROFILE(SMBread
);
2678 /****************************************************************************
2680 ****************************************************************************/
2682 static int setup_readX_header(char *inbuf
, char *outbuf
, size_t smb_maxcnt
)
2685 char *data
= smb_buf(outbuf
);
2687 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2688 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
2689 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2690 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
2691 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
2692 SCVAL(outbuf
,smb_vwv0
,0xFF);
2693 outsize
= set_message(inbuf
, outbuf
,12,smb_maxcnt
,False
);
2694 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2695 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
2699 /****************************************************************************
2700 Reply to a read and X - possibly using sendfile.
2701 ****************************************************************************/
2703 int send_file_readX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
, int len_outbuf
,
2704 files_struct
*fsp
, SMB_OFF_T startpos
, size_t smb_maxcnt
)
2706 SMB_STRUCT_STAT sbuf
;
2709 char *data
= smb_buf(outbuf
);
2711 if(SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
, &sbuf
) == -1) {
2712 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2715 if (startpos
> sbuf
.st_size
) {
2717 } else if (smb_maxcnt
> (sbuf
.st_size
- startpos
)) {
2718 smb_maxcnt
= (sbuf
.st_size
- startpos
);
2721 if (smb_maxcnt
== 0) {
2725 #if defined(WITH_SENDFILE)
2727 * We can only use sendfile on a non-chained packet
2728 * but we can use on a non-oplocked file. tridge proved this
2729 * on a train in Germany :-). JRA.
2732 if ((chain_size
== 0) && (CVAL(inbuf
,smb_vwv0
) == 0xFF) &&
2733 lp_use_sendfile(SNUM(conn
)) && (fsp
->wcp
== NULL
) ) {
2737 * Set up the packet header before send. We
2738 * assume here the sendfile will work (get the
2739 * correct amount of data).
2742 setup_readX_header(inbuf
,outbuf
,smb_maxcnt
);
2743 set_message(inbuf
,outbuf
,12,smb_maxcnt
,False
);
2744 header
.data
= (uint8
*)outbuf
;
2745 header
.length
= data
- outbuf
;
2748 if ((nread
= SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fh
->fd
, &header
, startpos
, smb_maxcnt
)) == -1) {
2749 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2750 if (errno
== ENOSYS
) {
2755 * Special hack for broken Linux with no working sendfile. If we
2756 * return EINTR we sent the header but not the rest of the data.
2757 * Fake this up by doing read/write calls.
2760 if (errno
== EINTR
) {
2761 /* Ensure we don't do this again. */
2762 set_use_sendfile(SNUM(conn
), False
);
2763 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2765 if ((nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
, data
,
2766 len_outbuf
- (data
-outbuf
))) == -1) {
2767 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2768 fsp
->fsp_name
, strerror(errno
) ));
2769 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2771 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2772 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2773 /* Returning -1 here means successful sendfile. */
2777 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2778 fsp
->fsp_name
, strerror(errno
) ));
2779 exit_server_cleanly("send_file_readX sendfile failed");
2782 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2783 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2784 /* Returning -1 here means successful sendfile. */
2792 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
2793 int sendlen
= setup_readX_header(inbuf
,outbuf
,smb_maxcnt
) - smb_maxcnt
;
2794 /* Send out the header. */
2795 if (write_data(smbd_server_fd(),outbuf
,sendlen
) != sendlen
) {
2796 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2797 fsp
->fsp_name
, strerror(errno
) ));
2798 exit_server_cleanly("send_file_readX sendfile failed");
2800 if ((nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
, data
,
2801 len_outbuf
- (data
-outbuf
))) == -1) {
2802 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2803 fsp
->fsp_name
, strerror(errno
) ));
2804 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2808 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2811 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2814 outsize
= setup_readX_header(inbuf
, outbuf
,nread
);
2816 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2817 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2819 /* Returning the number of bytes we want to send back - including header. */
2824 /****************************************************************************
2825 Reply to a read and X.
2826 ****************************************************************************/
2828 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2830 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv2
));
2831 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2833 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2834 BOOL big_readX
= False
;
2836 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2839 START_PROFILE(SMBreadX
);
2841 /* If it's an IPC, pass off the pipe handler. */
2843 END_PROFILE(SMBreadX
);
2844 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2847 CHECK_FSP(fsp
,conn
);
2848 if (!CHECK_READ(fsp
,inbuf
)) {
2849 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
2852 set_message(inbuf
,outbuf
,12,0,True
);
2854 if (global_client_caps
& CAP_LARGE_READX
) {
2855 size_t upper_size
= SVAL(inbuf
,smb_vwv7
);
2856 smb_maxcnt
|= (upper_size
<<16);
2857 if (upper_size
> 1) {
2858 /* Can't do this on a chained packet. */
2859 if ((CVAL(inbuf
,smb_vwv0
) != 0xFF)) {
2860 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
2862 /* We currently don't do this on signed or sealed data. */
2863 if (srv_is_signing_active() || srv_encryption_on()) {
2864 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
2866 /* Is there room in the reply for this data ? */
2867 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
2868 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2874 if(CVAL(inbuf
,smb_wct
) == 12) {
2875 #ifdef LARGE_SMB_OFF_T
2877 * This is a large offset (64 bit) read.
2879 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2881 #else /* !LARGE_SMB_OFF_T */
2884 * Ensure we haven't been sent a >32 bit offset.
2887 if(IVAL(inbuf
,smb_vwv10
) != 0) {
2888 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2889 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
2890 END_PROFILE(SMBreadX
);
2891 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2894 #endif /* LARGE_SMB_OFF_T */
2898 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
2899 END_PROFILE(SMBreadX
);
2900 return ERROR_DOS(ERRDOS
,ERRlock
);
2903 if (!big_readX
&& schedule_aio_read_and_X(conn
, inbuf
, outbuf
, length
, bufsize
, fsp
, startpos
, smb_maxcnt
)) {
2904 END_PROFILE(SMBreadX
);
2908 nread
= send_file_readX(conn
, inbuf
, outbuf
, length
, bufsize
, fsp
, startpos
, smb_maxcnt
);
2909 /* Only call chain_reply if not an error. */
2910 if (nread
!= -1 && SVAL(outbuf
,smb_rcls
) == 0) {
2911 nread
= chain_reply(inbuf
,&outbuf
,length
,bufsize
);
2914 END_PROFILE(SMBreadX
);
2918 /****************************************************************************
2919 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2920 ****************************************************************************/
2922 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2925 ssize_t total_written
=0;
2926 size_t numtowrite
=0;
2931 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
2934 START_PROFILE(SMBwritebraw
);
2936 if (srv_is_signing_active()) {
2937 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2940 CHECK_FSP(fsp
,conn
);
2941 if (!CHECK_WRITE(fsp
)) {
2942 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
2945 tcount
= IVAL(inbuf
,smb_vwv1
);
2946 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2947 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2949 /* We have to deal with slightly different formats depending
2950 on whether we are using the core+ or lanman1.0 protocol */
2952 if(Protocol
<= PROTOCOL_COREPLUS
) {
2953 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2954 data
= smb_buf(inbuf
);
2956 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2957 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2960 /* force the error type */
2961 SCVAL(inbuf
,smb_com
,SMBwritec
);
2962 SCVAL(outbuf
,smb_com
,SMBwritec
);
2964 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
2965 END_PROFILE(SMBwritebraw
);
2966 return(ERROR_DOS(ERRDOS
,ERRlock
));
2970 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2972 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2973 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2975 if (nwritten
< (ssize_t
)numtowrite
) {
2976 END_PROFILE(SMBwritebraw
);
2977 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2980 total_written
= nwritten
;
2982 /* Return a message to the redirector to tell it to send more bytes */
2983 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
2984 SSVALS(outbuf
,smb_vwv0
,-1);
2985 outsize
= set_message(inbuf
,outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2987 if (!send_smb(smbd_server_fd(),outbuf
))
2988 exit_server_cleanly("reply_writebraw: send_smb failed.");
2990 /* Now read the raw data into the buffer and write it */
2991 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2992 exit_server_cleanly("secondary writebraw failed");
2995 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2996 numtowrite
= smb_len(inbuf
);
2998 /* Set up outbuf to return the correct return */
2999 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
3000 SCVAL(outbuf
,smb_com
,SMBwritec
);
3002 if (numtowrite
!= 0) {
3004 if (numtowrite
> BUFFER_SIZE
) {
3005 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
3006 (unsigned int)numtowrite
));
3007 exit_server_cleanly("secondary writebraw failed");
3010 if (tcount
> nwritten
+numtowrite
) {
3011 DEBUG(3,("Client overestimated the write %d %d %d\n",
3012 (int)tcount
,(int)nwritten
,(int)numtowrite
));
3015 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
3016 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
3018 exit_server_cleanly("secondary writebraw failed");
3021 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
3022 if (nwritten
== -1) {
3023 END_PROFILE(SMBwritebraw
);
3024 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3027 if (nwritten
< (ssize_t
)numtowrite
) {
3028 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
3029 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
3033 total_written
+= nwritten
;
3036 SSVAL(outbuf
,smb_vwv0
,total_written
);
3038 status
= sync_file(conn
, fsp
, write_through
);
3039 if (!NT_STATUS_IS_OK(status
)) {
3040 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3041 fsp
->fsp_name
, nt_errstr(status
) ));
3042 END_PROFILE(SMBwritebraw
);
3043 return ERROR_NT(status
);
3046 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
3047 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
3049 /* we won't return a status if write through is not selected - this follows what WfWg does */
3050 END_PROFILE(SMBwritebraw
);
3051 if (!write_through
&& total_written
==tcount
) {
3053 #if RABBIT_PELLET_FIX
3055 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3056 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
3058 if (!send_keepalive(smbd_server_fd()))
3059 exit_server_cleanly("reply_writebraw: send of keepalive failed");
3068 #define DBGC_CLASS DBGC_LOCKING
3070 /****************************************************************************
3071 Reply to a writeunlock (core+).
3072 ****************************************************************************/
3074 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
,
3075 int size
, int dum_buffsize
)
3077 ssize_t nwritten
= -1;
3081 NTSTATUS status
= NT_STATUS_OK
;
3082 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
3084 START_PROFILE(SMBwriteunlock
);
3086 CHECK_FSP(fsp
,conn
);
3087 if (!CHECK_WRITE(fsp
)) {
3088 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
3091 numtowrite
= SVAL(inbuf
,smb_vwv1
);
3092 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
3093 data
= smb_buf(inbuf
) + 3;
3095 if (numtowrite
&& is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3096 END_PROFILE(SMBwriteunlock
);
3097 return ERROR_DOS(ERRDOS
,ERRlock
);
3100 /* The special X/Open SMB protocol handling of
3101 zero length writes is *NOT* done for
3103 if(numtowrite
== 0) {
3106 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
3109 status
= sync_file(conn
, fsp
, False
/* write through */);
3110 if (!NT_STATUS_IS_OK(status
)) {
3111 END_PROFILE(SMBwriteunlock
);
3112 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3113 fsp
->fsp_name
, nt_errstr(status
) ));
3114 return ERROR_NT(status
);
3117 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
3118 END_PROFILE(SMBwriteunlock
);
3119 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3123 status
= do_unlock(smbd_messaging_context(),
3125 (uint32
)SVAL(inbuf
,smb_pid
),
3126 (SMB_BIG_UINT
)numtowrite
,
3127 (SMB_BIG_UINT
)startpos
,
3130 if (NT_STATUS_V(status
)) {
3131 END_PROFILE(SMBwriteunlock
);
3132 return ERROR_NT(status
);
3136 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
3138 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3140 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3141 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
3143 END_PROFILE(SMBwriteunlock
);
3148 #define DBGC_CLASS DBGC_ALL
3150 /****************************************************************************
3152 ****************************************************************************/
3154 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
3157 ssize_t nwritten
= -1;
3160 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
3163 START_PROFILE(SMBwrite
);
3165 /* If it's an IPC, pass off the pipe handler. */
3167 END_PROFILE(SMBwrite
);
3168 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
3171 CHECK_FSP(fsp
,conn
);
3172 if (!CHECK_WRITE(fsp
)) {
3173 END_PROFILE(SMBwrite
);
3174 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
3177 numtowrite
= SVAL(inbuf
,smb_vwv1
);
3178 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
3179 data
= smb_buf(inbuf
) + 3;
3181 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3182 END_PROFILE(SMBwrite
);
3183 return ERROR_DOS(ERRDOS
,ERRlock
);
3187 * X/Open SMB protocol says that if smb_vwv1 is
3188 * zero then the file size should be extended or
3189 * truncated to the size given in smb_vwv[2-3].
3192 if(numtowrite
== 0) {
3194 * This is actually an allocate call, and set EOF. JRA.
3196 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
3198 END_PROFILE(SMBwrite
);
3199 return ERROR_NT(NT_STATUS_DISK_FULL
);
3201 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
3203 END_PROFILE(SMBwrite
);
3204 return ERROR_NT(NT_STATUS_DISK_FULL
);
3207 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
3209 status
= sync_file(conn
, fsp
, False
);
3210 if (!NT_STATUS_IS_OK(status
)) {
3211 END_PROFILE(SMBwrite
);
3212 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3213 fsp
->fsp_name
, nt_errstr(status
) ));
3214 return ERROR_NT(status
);
3217 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
3218 END_PROFILE(SMBwrite
);
3219 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3222 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
3224 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3226 if (nwritten
< (ssize_t
)numtowrite
) {
3227 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
3228 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
3231 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
3233 END_PROFILE(SMBwrite
);
3237 /****************************************************************************
3238 Reply to a write and X.
3239 ****************************************************************************/
3241 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
3243 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv2
));
3244 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
3245 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
3246 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
3247 ssize_t nwritten
= -1;
3248 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
3249 unsigned int smblen
= smb_len(inbuf
);
3251 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
3253 START_PROFILE(SMBwriteX
);
3255 /* If it's an IPC, pass off the pipe handler. */
3257 END_PROFILE(SMBwriteX
);
3258 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
3261 CHECK_FSP(fsp
,conn
);
3262 if (!CHECK_WRITE(fsp
)) {
3263 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
3266 set_message(inbuf
,outbuf
,6,0,True
);
3268 /* Deal with possible LARGE_WRITEX */
3270 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
3273 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
3274 END_PROFILE(SMBwriteX
);
3275 return ERROR_DOS(ERRDOS
,ERRbadmem
);
3278 data
= smb_base(inbuf
) + smb_doff
;
3280 if(CVAL(inbuf
,smb_wct
) == 14) {
3281 #ifdef LARGE_SMB_OFF_T
3283 * This is a large offset (64 bit) write.
3285 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
3287 #else /* !LARGE_SMB_OFF_T */
3290 * Ensure we haven't been sent a >32 bit offset.
3293 if(IVAL(inbuf
,smb_vwv12
) != 0) {
3294 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3295 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
3296 END_PROFILE(SMBwriteX
);
3297 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
3300 #endif /* LARGE_SMB_OFF_T */
3303 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3304 END_PROFILE(SMBwriteX
);
3305 return ERROR_DOS(ERRDOS
,ERRlock
);
3308 /* X/Open SMB protocol says that, unlike SMBwrite
3309 if the length is zero then NO truncation is
3310 done, just a write of zero. To truncate a file,
3313 if(numtowrite
== 0) {
3317 if (schedule_aio_write_and_X(conn
, inbuf
, outbuf
, length
, bufsize
,
3318 fsp
,data
,startpos
,numtowrite
)) {
3319 END_PROFILE(SMBwriteX
);
3323 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
3326 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
3327 END_PROFILE(SMBwriteX
);
3328 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3331 SSVAL(outbuf
,smb_vwv2
,nwritten
);
3333 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
3335 if (nwritten
< (ssize_t
)numtowrite
) {
3336 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
3337 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
3340 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3341 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
3343 status
= sync_file(conn
, fsp
, write_through
);
3344 if (!NT_STATUS_IS_OK(status
)) {
3345 END_PROFILE(SMBwriteX
);
3346 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3347 fsp
->fsp_name
, nt_errstr(status
) ));
3348 return ERROR_NT(status
);
3351 END_PROFILE(SMBwriteX
);
3352 return chain_reply(inbuf
,&outbuf
,length
,bufsize
);
3355 /****************************************************************************
3357 ****************************************************************************/
3359 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
3365 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
3366 START_PROFILE(SMBlseek
);
3368 CHECK_FSP(fsp
,conn
);
3370 flush_write_cache(fsp
, SEEK_FLUSH
);
3372 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
3373 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3374 startpos
= (SMB_OFF_T
)IVALS(inbuf
,smb_vwv2
);
3383 res
= fsp
->fh
->pos
+ startpos
;
3394 if (umode
== SEEK_END
) {
3395 if((res
= SMB_VFS_LSEEK(fsp
,fsp
->fh
->fd
,startpos
,umode
)) == -1) {
3396 if(errno
== EINVAL
) {
3397 SMB_OFF_T current_pos
= startpos
;
3398 SMB_STRUCT_STAT sbuf
;
3400 if(SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
, &sbuf
) == -1) {
3401 END_PROFILE(SMBlseek
);
3402 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3405 current_pos
+= sbuf
.st_size
;
3407 res
= SMB_VFS_LSEEK(fsp
,fsp
->fh
->fd
,0,SEEK_SET
);
3412 END_PROFILE(SMBlseek
);
3413 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3419 outsize
= set_message(inbuf
,outbuf
,2,0,True
);
3420 SIVAL(outbuf
,smb_vwv0
,res
);
3422 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3423 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
3425 END_PROFILE(SMBlseek
);
3429 /****************************************************************************
3431 ****************************************************************************/
3433 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
3435 int outsize
= set_message(inbuf
,outbuf
,0,0,False
);
3436 uint16 fnum
= SVAL(inbuf
,smb_vwv0
);
3437 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
3438 START_PROFILE(SMBflush
);
3441 CHECK_FSP(fsp
,conn
);
3444 file_sync_all(conn
);
3446 NTSTATUS status
= sync_file(conn
, fsp
, True
);
3447 if (!NT_STATUS_IS_OK(status
)) {
3448 END_PROFILE(SMBflush
);
3449 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3450 fsp
->fsp_name
, nt_errstr(status
) ));
3451 return ERROR_NT(status
);
3455 DEBUG(3,("flush\n"));
3456 END_PROFILE(SMBflush
);
3460 /****************************************************************************
3462 conn POINTER CAN BE NULL HERE !
3463 ****************************************************************************/
3465 void reply_exit(connection_struct
*conn
, struct smb_request
*req
)
3467 START_PROFILE(SMBexit
);
3469 file_close_pid(req
->smbpid
, req
->vuid
);
3471 reply_outbuf(req
, 0, 0);
3473 DEBUG(3,("exit\n"));
3475 END_PROFILE(SMBexit
);
3479 /****************************************************************************
3480 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3481 ****************************************************************************/
3483 void reply_close(connection_struct
*conn
, struct smb_request
*req
)
3485 NTSTATUS status
= NT_STATUS_OK
;
3486 files_struct
*fsp
= NULL
;
3487 START_PROFILE(SMBclose
);
3490 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3491 END_PROFILE(SMBclose
);
3495 /* If it's an IPC, pass off to the pipe handler. */
3497 reply_pipe_close(conn
, req
);
3498 END_PROFILE(SMBclose
);
3502 fsp
= file_fsp(SVAL(req
->inbuf
,smb_vwv0
));
3505 * We can only use CHECK_FSP if we know it's not a directory.
3508 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= current_user
.vuid
)) {
3509 reply_doserror(req
, ERRDOS
, ERRbadfid
);
3510 END_PROFILE(SMBclose
);
3514 if(fsp
->is_directory
) {
3516 * Special case - close NT SMB directory handle.
3518 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
3519 status
= close_file(fsp
,NORMAL_CLOSE
);
3522 * Close ordinary file.
3525 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3526 fsp
->fh
->fd
, fsp
->fnum
,
3527 conn
->num_files_open
));
3530 * Take care of any time sent in the close.
3533 fsp_set_pending_modtime(fsp
, convert_time_t_to_timespec(
3534 srv_make_unix_date3(
3535 req
->inbuf
+smb_vwv1
)));
3538 * close_file() returns the unix errno if an error
3539 * was detected on close - normally this is due to
3540 * a disk full error. If not then it was probably an I/O error.
3543 status
= close_file(fsp
,NORMAL_CLOSE
);
3546 if (!NT_STATUS_IS_OK(status
)) {
3547 reply_nterror(req
, status
);
3548 END_PROFILE(SMBclose
);
3552 reply_outbuf(req
, 0, 0);
3553 END_PROFILE(SMBclose
);
3557 /****************************************************************************
3558 Reply to a writeclose (Core+ protocol).
3559 ****************************************************************************/
3561 int reply_writeclose(connection_struct
*conn
,
3562 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
3565 ssize_t nwritten
= -1;
3567 NTSTATUS close_status
= NT_STATUS_OK
;
3570 struct timespec mtime
;
3571 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
3572 START_PROFILE(SMBwriteclose
);
3574 CHECK_FSP(fsp
,conn
);
3575 if (!CHECK_WRITE(fsp
)) {
3576 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
3579 numtowrite
= SVAL(inbuf
,smb_vwv1
);
3580 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
3581 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(inbuf
+smb_vwv4
));
3582 data
= smb_buf(inbuf
) + 1;
3584 if (numtowrite
&& is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3585 END_PROFILE(SMBwriteclose
);
3586 return ERROR_DOS(ERRDOS
,ERRlock
);
3589 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
3591 set_filetime(conn
, fsp
->fsp_name
, mtime
);
3594 * More insanity. W2K only closes the file if writelen > 0.
3599 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3601 close_status
= close_file(fsp
,NORMAL_CLOSE
);
3604 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3605 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
3606 conn
->num_files_open
));
3608 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
3609 END_PROFILE(SMBwriteclose
);
3610 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3613 if(!NT_STATUS_IS_OK(close_status
)) {
3614 END_PROFILE(SMBwriteclose
);
3615 return ERROR_NT(close_status
);
3618 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
3620 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3621 END_PROFILE(SMBwriteclose
);
3626 #define DBGC_CLASS DBGC_LOCKING
3628 /****************************************************************************
3630 ****************************************************************************/
3632 int reply_lock(connection_struct
*conn
,
3633 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
3635 int outsize
= set_message(inbuf
,outbuf
,0,0,False
);
3636 SMB_BIG_UINT count
,offset
;
3638 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
3639 struct byte_range_lock
*br_lck
= NULL
;
3641 START_PROFILE(SMBlock
);
3643 CHECK_FSP(fsp
,conn
);
3645 release_level_2_oplocks_on_change(fsp
);
3647 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
3648 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
3650 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3651 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
3653 br_lck
= do_lock(smbd_messaging_context(),
3655 (uint32
)SVAL(inbuf
,smb_pid
),
3660 False
, /* Non-blocking lock. */
3664 TALLOC_FREE(br_lck
);
3666 if (NT_STATUS_V(status
)) {
3667 END_PROFILE(SMBlock
);
3668 return ERROR_NT(status
);
3671 END_PROFILE(SMBlock
);
3675 /****************************************************************************
3677 ****************************************************************************/
3679 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
3682 int outsize
= set_message(inbuf
,outbuf
,0,0,False
);
3683 SMB_BIG_UINT count
,offset
;
3685 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
3686 START_PROFILE(SMBunlock
);
3688 CHECK_FSP(fsp
,conn
);
3690 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
3691 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
3693 status
= do_unlock(smbd_messaging_context(),
3695 (uint32
)SVAL(inbuf
,smb_pid
),
3700 if (NT_STATUS_V(status
)) {
3701 END_PROFILE(SMBunlock
);
3702 return ERROR_NT(status
);
3705 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3706 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
3708 END_PROFILE(SMBunlock
);
3713 #define DBGC_CLASS DBGC_ALL
3715 /****************************************************************************
3717 conn POINTER CAN BE NULL HERE !
3718 ****************************************************************************/
3720 void reply_tdis(connection_struct
*conn
, struct smb_request
*req
)
3722 START_PROFILE(SMBtdis
);
3725 DEBUG(4,("Invalid connection in tdis\n"));
3726 reply_doserror(req
, ERRSRV
, ERRinvnid
);
3727 END_PROFILE(SMBtdis
);
3733 close_cnum(conn
,req
->vuid
);
3735 reply_outbuf(req
, 0, 0);
3736 END_PROFILE(SMBtdis
);
3740 /****************************************************************************
3742 conn POINTER CAN BE NULL HERE !
3743 ****************************************************************************/
3745 int reply_echo(connection_struct
*conn
,
3746 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3748 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
3750 unsigned int data_len
= smb_buflen(inbuf
);
3751 int outsize
= set_message(inbuf
,outbuf
,1,data_len
,True
);
3752 START_PROFILE(SMBecho
);
3754 if (data_len
> BUFFER_SIZE
) {
3755 DEBUG(0,("reply_echo: data_len too large.\n"));
3756 END_PROFILE(SMBecho
);
3760 /* copy any incoming data back out */
3762 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
3764 if (smb_reverb
> 100) {
3765 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
3769 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
3770 SSVAL(outbuf
,smb_vwv0
,seq_num
);
3772 smb_setlen(inbuf
,outbuf
,outsize
- 4);
3775 if (!send_smb(smbd_server_fd(),outbuf
))
3776 exit_server_cleanly("reply_echo: send_smb failed.");
3779 DEBUG(3,("echo %d times\n", smb_reverb
));
3783 END_PROFILE(SMBecho
);
3787 /****************************************************************************
3788 Reply to a printopen.
3789 ****************************************************************************/
3791 int reply_printopen(connection_struct
*conn
,
3792 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3798 START_PROFILE(SMBsplopen
);
3800 if (!CAN_PRINT(conn
)) {
3801 END_PROFILE(SMBsplopen
);
3802 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3805 /* Open for exclusive use, write only. */
3806 status
= print_fsp_open(conn
, NULL
, &fsp
);
3808 if (!NT_STATUS_IS_OK(status
)) {
3809 END_PROFILE(SMBsplopen
);
3810 return(ERROR_NT(status
));
3813 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
3814 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
3816 DEBUG(3,("openprint fd=%d fnum=%d\n",
3817 fsp
->fh
->fd
, fsp
->fnum
));
3819 END_PROFILE(SMBsplopen
);
3823 /****************************************************************************
3824 Reply to a printclose.
3825 ****************************************************************************/
3827 int reply_printclose(connection_struct
*conn
,
3828 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3830 int outsize
= set_message(inbuf
,outbuf
,0,0,False
);
3831 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
3833 START_PROFILE(SMBsplclose
);
3835 CHECK_FSP(fsp
,conn
);
3837 if (!CAN_PRINT(conn
)) {
3838 END_PROFILE(SMBsplclose
);
3839 return ERROR_NT(NT_STATUS_DOS(ERRSRV
, ERRerror
));
3842 DEBUG(3,("printclose fd=%d fnum=%d\n",
3843 fsp
->fh
->fd
,fsp
->fnum
));
3845 status
= close_file(fsp
,NORMAL_CLOSE
);
3847 if(!NT_STATUS_IS_OK(status
)) {
3848 END_PROFILE(SMBsplclose
);
3849 return ERROR_NT(status
);
3852 END_PROFILE(SMBsplclose
);
3856 /****************************************************************************
3857 Reply to a printqueue.
3858 ****************************************************************************/
3860 int reply_printqueue(connection_struct
*conn
,
3861 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3863 int outsize
= set_message(inbuf
,outbuf
,2,3,True
);
3864 int max_count
= SVAL(inbuf
,smb_vwv0
);
3865 int start_index
= SVAL(inbuf
,smb_vwv1
);
3866 START_PROFILE(SMBsplretq
);
3868 /* we used to allow the client to get the cnum wrong, but that
3869 is really quite gross and only worked when there was only
3870 one printer - I think we should now only accept it if they
3871 get it right (tridge) */
3872 if (!CAN_PRINT(conn
)) {
3873 END_PROFILE(SMBsplretq
);
3874 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3877 SSVAL(outbuf
,smb_vwv0
,0);
3878 SSVAL(outbuf
,smb_vwv1
,0);
3879 SCVAL(smb_buf(outbuf
),0,1);
3880 SSVAL(smb_buf(outbuf
),1,0);
3882 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3883 start_index
, max_count
));
3886 print_queue_struct
*queue
= NULL
;
3887 print_status_struct status
;
3888 char *p
= smb_buf(outbuf
) + 3;
3889 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
3890 int num_to_get
= ABS(max_count
);
3891 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
3897 num_to_get
= MIN(num_to_get
,count
-first
);
3900 for (i
=first
;i
<first
+num_to_get
;i
++) {
3901 srv_put_dos_date2(p
,0,queue
[i
].time
);
3902 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
3903 SSVAL(p
,5, queue
[i
].job
);
3904 SIVAL(p
,7,queue
[i
].size
);
3906 srvstr_push(outbuf
, p
+12, queue
[i
].fs_user
, 16, STR_ASCII
);
3911 outsize
= set_message(inbuf
,outbuf
,2,28*count
+3,False
);
3912 SSVAL(outbuf
,smb_vwv0
,count
);
3913 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
3914 SCVAL(smb_buf(outbuf
),0,1);
3915 SSVAL(smb_buf(outbuf
),1,28*count
);
3920 DEBUG(3,("%d entries returned in queue\n",count
));
3923 END_PROFILE(SMBsplretq
);
3927 /****************************************************************************
3928 Reply to a printwrite.
3929 ****************************************************************************/
3931 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3934 int outsize
= set_message(inbuf
,outbuf
,0,0,False
);
3936 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
3938 START_PROFILE(SMBsplwr
);
3940 if (!CAN_PRINT(conn
)) {
3941 END_PROFILE(SMBsplwr
);
3942 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3945 CHECK_FSP(fsp
,conn
);
3946 if (!CHECK_WRITE(fsp
)) {
3947 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
3950 numtowrite
= SVAL(smb_buf(inbuf
),1);
3951 data
= smb_buf(inbuf
) + 3;
3953 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
3954 END_PROFILE(SMBsplwr
);
3955 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3958 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
3960 END_PROFILE(SMBsplwr
);
3964 /****************************************************************************
3966 ****************************************************************************/
3968 void reply_mkdir(connection_struct
*conn
, struct smb_request
*req
)
3972 SMB_STRUCT_STAT sbuf
;
3974 START_PROFILE(SMBmkdir
);
3976 srvstr_get_path((char *)req
->inbuf
, req
->flags2
, directory
,
3977 smb_buf(req
->inbuf
) + 1, sizeof(directory
), 0,
3978 STR_TERMINATE
, &status
);
3979 if (!NT_STATUS_IS_OK(status
)) {
3980 reply_nterror(req
, status
);
3981 END_PROFILE(SMBmkdir
);
3985 status
= resolve_dfspath(conn
,
3986 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3988 if (!NT_STATUS_IS_OK(status
)) {
3989 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3990 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3991 ERRSRV
, ERRbadpath
);
3992 END_PROFILE(SMBmkdir
);
3995 reply_nterror(req
, status
);
3996 END_PROFILE(SMBmkdir
);
4000 status
= unix_convert(conn
, directory
, False
, NULL
, &sbuf
);
4001 if (!NT_STATUS_IS_OK(status
)) {
4002 reply_nterror(req
, status
);
4003 END_PROFILE(SMBmkdir
);
4007 status
= check_name(conn
, directory
);
4008 if (!NT_STATUS_IS_OK(status
)) {
4009 reply_nterror(req
, status
);
4010 END_PROFILE(SMBmkdir
);
4014 status
= create_directory(conn
, directory
);
4016 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
4018 if (!NT_STATUS_IS_OK(status
)) {
4020 if (!use_nt_status()
4021 && NT_STATUS_EQUAL(status
,
4022 NT_STATUS_OBJECT_NAME_COLLISION
)) {
4024 * Yes, in the DOS error code case we get a
4025 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4026 * samba4 torture test.
4028 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
4031 reply_nterror(req
, status
);
4032 END_PROFILE(SMBmkdir
);
4036 reply_outbuf(req
, 0, 0);
4038 DEBUG( 3, ( "mkdir %s\n", directory
) );
4040 END_PROFILE(SMBmkdir
);
4044 /****************************************************************************
4045 Static function used by reply_rmdir to delete an entire directory
4046 tree recursively. Return True on ok, False on fail.
4047 ****************************************************************************/
4049 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
4051 const char *dname
= NULL
;
4054 struct smb_Dir
*dir_hnd
= OpenDir(conn
, directory
, NULL
, 0);
4059 while((dname
= ReadDirName(dir_hnd
, &offset
))) {
4063 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
4066 if (!is_visible_file(conn
, directory
, dname
, &st
, False
))
4069 /* Construct the full name. */
4070 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
4076 pstrcpy(fullname
, directory
);
4077 pstrcat(fullname
, "/");
4078 pstrcat(fullname
, dname
);
4080 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
4085 if(st
.st_mode
& S_IFDIR
) {
4086 if(!recursive_rmdir(conn
, fullname
)) {
4090 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
4094 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
4103 /****************************************************************************
4104 The internals of the rmdir code - called elsewhere.
4105 ****************************************************************************/
4107 NTSTATUS
rmdir_internals(connection_struct
*conn
, const char *directory
)
4112 /* Might be a symlink. */
4113 if(SMB_VFS_LSTAT(conn
, directory
, &st
) != 0) {
4114 return map_nt_error_from_unix(errno
);
4117 if (S_ISLNK(st
.st_mode
)) {
4118 /* Is what it points to a directory ? */
4119 if(SMB_VFS_STAT(conn
, directory
, &st
) != 0) {
4120 return map_nt_error_from_unix(errno
);
4122 if (!(S_ISDIR(st
.st_mode
))) {
4123 return NT_STATUS_NOT_A_DIRECTORY
;
4125 ret
= SMB_VFS_UNLINK(conn
,directory
);
4127 ret
= SMB_VFS_RMDIR(conn
,directory
);
4130 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
4131 FILE_NOTIFY_CHANGE_DIR_NAME
,
4133 return NT_STATUS_OK
;
4136 if(((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
4138 * Check to see if the only thing in this directory are
4139 * vetoed files/directories. If so then delete them and
4140 * retry. If we fail to delete any of them (and we *don't*
4141 * do a recursive delete) then fail the rmdir.
4145 struct smb_Dir
*dir_hnd
= OpenDir(conn
, directory
, NULL
, 0);
4147 if(dir_hnd
== NULL
) {
4152 while ((dname
= ReadDirName(dir_hnd
,&dirpos
))) {
4153 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
4155 if (!is_visible_file(conn
, directory
, dname
, &st
, False
))
4157 if(!IS_VETO_PATH(conn
, dname
)) {
4164 /* We only have veto files/directories. Recursive delete. */
4166 RewindDir(dir_hnd
,&dirpos
);
4167 while ((dname
= ReadDirName(dir_hnd
,&dirpos
))) {
4170 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
4172 if (!is_visible_file(conn
, directory
, dname
, &st
, False
))
4175 /* Construct the full name. */
4176 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
4181 pstrcpy(fullname
, directory
);
4182 pstrcat(fullname
, "/");
4183 pstrcat(fullname
, dname
);
4185 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0)
4187 if(st
.st_mode
& S_IFDIR
) {
4188 if(lp_recursive_veto_delete(SNUM(conn
))) {
4189 if(!recursive_rmdir(conn
, fullname
))
4192 if(SMB_VFS_RMDIR(conn
,fullname
) != 0)
4194 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0)
4198 /* Retry the rmdir */
4199 ret
= SMB_VFS_RMDIR(conn
,directory
);
4205 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4206 "%s\n", directory
,strerror(errno
)));
4207 return map_nt_error_from_unix(errno
);
4210 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
4211 FILE_NOTIFY_CHANGE_DIR_NAME
,
4214 return NT_STATUS_OK
;
4217 /****************************************************************************
4219 ****************************************************************************/
4221 void reply_rmdir(connection_struct
*conn
, struct smb_request
*req
)
4224 SMB_STRUCT_STAT sbuf
;
4226 START_PROFILE(SMBrmdir
);
4228 srvstr_get_path((char *)req
->inbuf
, req
->flags2
, directory
,
4229 smb_buf(req
->inbuf
) + 1, sizeof(directory
), 0,
4230 STR_TERMINATE
, &status
);
4231 if (!NT_STATUS_IS_OK(status
)) {
4232 reply_nterror(req
, status
);
4233 END_PROFILE(SMBrmdir
);
4237 status
= resolve_dfspath(conn
,
4238 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
4240 if (!NT_STATUS_IS_OK(status
)) {
4241 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4242 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
4243 ERRSRV
, ERRbadpath
);
4244 END_PROFILE(SMBrmdir
);
4247 reply_nterror(req
, status
);
4248 END_PROFILE(SMBrmdir
);
4252 status
= unix_convert(conn
, directory
, False
, NULL
, &sbuf
);
4253 if (!NT_STATUS_IS_OK(status
)) {
4254 reply_nterror(req
, status
);
4255 END_PROFILE(SMBrmdir
);
4259 status
= check_name(conn
, directory
);
4260 if (!NT_STATUS_IS_OK(status
)) {
4261 reply_nterror(req
, status
);
4262 END_PROFILE(SMBrmdir
);
4266 dptr_closepath(directory
, req
->smbpid
);
4267 status
= rmdir_internals(conn
, directory
);
4268 if (!NT_STATUS_IS_OK(status
)) {
4269 reply_nterror(req
, status
);
4270 END_PROFILE(SMBrmdir
);
4274 reply_outbuf(req
, 0, 0);
4276 DEBUG( 3, ( "rmdir %s\n", directory
) );
4278 END_PROFILE(SMBrmdir
);
4282 /*******************************************************************
4283 Resolve wildcards in a filename rename.
4284 Note that name is in UNIX charset and thus potentially can be more
4285 than fstring buffer (255 bytes) especially in default UTF-8 case.
4286 Therefore, we use pstring inside and all calls should ensure that
4287 name2 is at least pstring-long (they do already)
4288 ********************************************************************/
4290 static BOOL
resolve_wildcards(const char *name1
, char *name2
)
4292 pstring root1
,root2
;
4294 char *p
,*p2
, *pname1
, *pname2
;
4295 int available_space
, actual_space
;
4297 pname1
= strrchr_m(name1
,'/');
4298 pname2
= strrchr_m(name2
,'/');
4300 if (!pname1
|| !pname2
)
4303 pstrcpy(root1
,pname1
);
4304 pstrcpy(root2
,pname2
);
4305 p
= strrchr_m(root1
,'.');
4312 p
= strrchr_m(root2
,'.');
4326 } else if (*p2
== '*') {
4342 } else if (*p2
== '*') {
4352 available_space
= sizeof(pstring
) - PTR_DIFF(pname2
, name2
);
4355 actual_space
= snprintf(pname2
, available_space
- 1, "%s.%s", root2
, ext2
);
4356 if (actual_space
>= available_space
- 1) {
4357 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4358 actual_space
- available_space
));
4361 pstrcpy_base(pname2
, root2
, name2
);
4367 /****************************************************************************
4368 Ensure open files have their names updated. Updated to notify other smbd's
4370 ****************************************************************************/
4372 static void rename_open_files(connection_struct
*conn
,
4373 struct share_mode_lock
*lck
,
4374 const char *newname
)
4377 BOOL did_rename
= False
;
4379 for(fsp
= file_find_di_first(lck
->id
); fsp
;
4380 fsp
= file_find_di_next(fsp
)) {
4381 /* fsp_name is a relative path under the fsp. To change this for other
4382 sharepaths we need to manipulate relative paths. */
4383 /* TODO - create the absolute path and manipulate the newname
4384 relative to the sharepath. */
4385 if (fsp
->conn
!= conn
) {
4388 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4389 fsp
->fnum
, file_id_static_string(&fsp
->file_id
),
4390 fsp
->fsp_name
, newname
));
4391 string_set(&fsp
->fsp_name
, newname
);
4396 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4397 file_id_static_string(&lck
->id
), newname
));
4400 /* Send messages to all smbd's (not ourself) that the name has changed. */
4401 rename_share_filename(smbd_messaging_context(), lck
, conn
->connectpath
,
4405 /****************************************************************************
4406 We need to check if the source path is a parent directory of the destination
4407 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4408 refuse the rename with a sharing violation. Under UNIX the above call can
4409 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4410 probably need to check that the client is a Windows one before disallowing
4411 this as a UNIX client (one with UNIX extensions) can know the source is a
4412 symlink and make this decision intelligently. Found by an excellent bug
4413 report from <AndyLiebman@aol.com>.
4414 ****************************************************************************/
4416 static BOOL
rename_path_prefix_equal(const char *src
, const char *dest
)
4418 const char *psrc
= src
;
4419 const char *pdst
= dest
;
4422 if (psrc
[0] == '.' && psrc
[1] == '/') {
4425 if (pdst
[0] == '.' && pdst
[1] == '/') {
4428 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
4431 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
4435 * Do the notify calls from a rename
4438 static void notify_rename(connection_struct
*conn
, BOOL is_dir
,
4439 const char *oldpath
, const char *newpath
)
4441 char *olddir
, *newdir
;
4442 const char *oldname
, *newname
;
4445 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
4446 : FILE_NOTIFY_CHANGE_FILE_NAME
;
4448 if (!parent_dirname_talloc(NULL
, oldpath
, &olddir
, &oldname
)
4449 || !parent_dirname_talloc(NULL
, newpath
, &newdir
, &newname
)) {
4450 TALLOC_FREE(olddir
);
4454 if (strcmp(olddir
, newdir
) == 0) {
4455 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
, oldpath
);
4456 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
, newpath
);
4459 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
, oldpath
);
4460 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
, newpath
);
4462 TALLOC_FREE(olddir
);
4463 TALLOC_FREE(newdir
);
4465 /* this is a strange one. w2k3 gives an additional event for
4466 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4467 files, but not directories */
4469 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
4470 FILE_NOTIFY_CHANGE_ATTRIBUTES
4471 |FILE_NOTIFY_CHANGE_CREATION
,
4476 /****************************************************************************
4477 Rename an open file - given an fsp.
4478 ****************************************************************************/
4480 NTSTATUS
rename_internals_fsp(connection_struct
*conn
, files_struct
*fsp
, pstring newname
, uint32 attrs
, BOOL replace_if_exists
)
4482 SMB_STRUCT_STAT sbuf
, sbuf1
;
4483 pstring newname_last_component
;
4484 NTSTATUS status
= NT_STATUS_OK
;
4485 struct share_mode_lock
*lck
= NULL
;
4490 status
= unix_convert(conn
, newname
, False
, newname_last_component
, &sbuf
);
4492 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4494 if (!NT_STATUS_IS_OK(status
) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
, status
)) {
4498 status
= check_name(conn
, newname
);
4499 if (!NT_STATUS_IS_OK(status
)) {
4503 /* Ensure newname contains a '/' */
4504 if(strrchr_m(newname
,'/') == 0) {
4507 pstrcpy(tmpstr
, "./");
4508 pstrcat(tmpstr
, newname
);
4509 pstrcpy(newname
, tmpstr
);
4513 * Check for special case with case preserving and not
4514 * case sensitive. If the old last component differs from the original
4515 * last component only by case, then we should allow
4516 * the rename (user is trying to change the case of the
4520 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
4521 strequal(newname
, fsp
->fsp_name
)) {
4523 pstring newname_modified_last_component
;
4526 * Get the last component of the modified name.
4527 * Note that we guarantee that newname contains a '/'
4530 p
= strrchr_m(newname
,'/');
4531 pstrcpy(newname_modified_last_component
,p
+1);
4533 if(strcsequal(newname_modified_last_component
,
4534 newname_last_component
) == False
) {
4536 * Replace the modified last component with
4539 pstrcpy(p
+1, newname_last_component
);
4544 * If the src and dest names are identical - including case,
4545 * don't do the rename, just return success.
4548 if (strcsequal(fsp
->fsp_name
, newname
)) {
4549 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4551 return NT_STATUS_OK
;
4555 * Have vfs_object_exist also fill sbuf1
4557 dst_exists
= vfs_object_exist(conn
, newname
, &sbuf1
);
4559 if(!replace_if_exists
&& dst_exists
) {
4560 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4561 fsp
->fsp_name
,newname
));
4562 return NT_STATUS_OBJECT_NAME_COLLISION
;
4566 files_struct
*dst_fsp
= file_find_di_first(file_id_sbuf(&sbuf1
));
4568 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4569 return NT_STATUS_ACCESS_DENIED
;
4573 /* Ensure we have a valid stat struct for the source. */
4574 if (fsp
->fh
->fd
!= -1) {
4575 if (SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
,&sbuf
) == -1) {
4576 return map_nt_error_from_unix(errno
);
4579 if (SMB_VFS_STAT(conn
,fsp
->fsp_name
,&sbuf
) == -1) {
4580 return map_nt_error_from_unix(errno
);
4584 status
= can_rename(conn
, fsp
, attrs
, &sbuf
);
4586 if (!NT_STATUS_IS_OK(status
)) {
4587 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4588 nt_errstr(status
), fsp
->fsp_name
,newname
));
4589 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
4590 status
= NT_STATUS_ACCESS_DENIED
;
4594 if (rename_path_prefix_equal(fsp
->fsp_name
, newname
)) {
4595 return NT_STATUS_ACCESS_DENIED
;
4598 lck
= get_share_mode_lock(NULL
, fsp
->file_id
, NULL
, NULL
);
4601 * We have the file open ourselves, so not being able to get the
4602 * corresponding share mode lock is a fatal error.
4605 SMB_ASSERT(lck
!= NULL
);
4607 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
4608 uint32 create_options
= fsp
->fh
->private_options
;
4610 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4611 fsp
->fsp_name
,newname
));
4613 rename_open_files(conn
, lck
, newname
);
4615 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
, newname
);
4618 * A rename acts as a new file create w.r.t. allowing an initial delete
4619 * on close, probably because in Windows there is a new handle to the
4620 * new file. If initial delete on close was requested but not
4621 * originally set, we need to set it here. This is probably not 100% correct,
4622 * but will work for the CIFSFS client which in non-posix mode
4623 * depends on these semantics. JRA.
4626 set_allow_initial_delete_on_close(lck
, fsp
, True
);
4628 if (create_options
& FILE_DELETE_ON_CLOSE
) {
4629 status
= can_set_delete_on_close(fsp
, True
, 0);
4631 if (NT_STATUS_IS_OK(status
)) {
4632 /* Note that here we set the *inital* delete on close flag,
4633 * not the regular one. The magic gets handled in close. */
4634 fsp
->initial_delete_on_close
= True
;
4638 return NT_STATUS_OK
;
4643 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
4644 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
4646 status
= map_nt_error_from_unix(errno
);
4649 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4650 nt_errstr(status
), fsp
->fsp_name
,newname
));
4655 /****************************************************************************
4656 The guts of the rename command, split out so it may be called by the NT SMB
4658 ****************************************************************************/
4660 NTSTATUS
rename_internals(connection_struct
*conn
, struct smb_request
*req
,
4664 BOOL replace_if_exists
,
4670 pstring last_component_src
;
4671 pstring last_component_dest
;
4674 NTSTATUS status
= NT_STATUS_OK
;
4675 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4676 struct smb_Dir
*dir_hnd
= NULL
;
4681 *directory
= *mask
= 0;
4686 status
= unix_convert(conn
, name
, src_has_wild
, last_component_src
, &sbuf1
);
4687 if (!NT_STATUS_IS_OK(status
)) {
4691 status
= unix_convert(conn
, newname
, dest_has_wild
, last_component_dest
, &sbuf2
);
4692 if (!NT_STATUS_IS_OK(status
)) {
4697 * Split the old name into directory and last component
4698 * strings. Note that unix_convert may have stripped off a
4699 * leading ./ from both name and newname if the rename is
4700 * at the root of the share. We need to make sure either both
4701 * name and newname contain a / character or neither of them do
4702 * as this is checked in resolve_wildcards().
4705 p
= strrchr_m(name
,'/');
4707 pstrcpy(directory
,".");
4711 pstrcpy(directory
,name
);
4713 *p
= '/'; /* Replace needed for exceptional test below. */
4717 * We should only check the mangled cache
4718 * here if unix_convert failed. This means
4719 * that the path in 'mask' doesn't exist
4720 * on the file system and so we need to look
4721 * for a possible mangle. This patch from
4722 * Tine Smukavec <valentin.smukavec@hermes.si>.
4725 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
)) {
4726 mangle_check_cache( mask
, sizeof(pstring
)-1, conn
->params
);
4729 if (!src_has_wild
) {
4733 * No wildcards - just process the one file.
4735 BOOL is_short_name
= mangle_is_8_3(name
, True
, conn
->params
);
4737 /* Add a terminating '/' to the directory name. */
4738 pstrcat(directory
,"/");
4739 pstrcat(directory
,mask
);
4741 /* Ensure newname contains a '/' also */
4742 if(strrchr_m(newname
,'/') == 0) {
4745 pstrcpy(tmpstr
, "./");
4746 pstrcat(tmpstr
, newname
);
4747 pstrcpy(newname
, tmpstr
);
4750 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4751 "case_preserve = %d, short case preserve = %d, "
4752 "directory = %s, newname = %s, "
4753 "last_component_dest = %s, is_8_3 = %d\n",
4754 conn
->case_sensitive
, conn
->case_preserve
,
4755 conn
->short_case_preserve
, directory
,
4756 newname
, last_component_dest
, is_short_name
));
4758 /* The dest name still may have wildcards. */
4759 if (dest_has_wild
) {
4760 if (!resolve_wildcards(directory
,newname
)) {
4761 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4762 directory
,newname
));
4763 return NT_STATUS_NO_MEMORY
;
4768 SMB_VFS_STAT(conn
, directory
, &sbuf1
);
4770 status
= S_ISDIR(sbuf1
.st_mode
) ?
4771 open_directory(conn
, req
, directory
, &sbuf1
,
4773 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4774 FILE_OPEN
, 0, 0, NULL
,
4776 : open_file_ntcreate(conn
, req
, directory
, &sbuf1
,
4778 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4779 FILE_OPEN
, 0, 0, 0, NULL
,
4782 if (!NT_STATUS_IS_OK(status
)) {
4783 DEBUG(3, ("Could not open rename source %s: %s\n",
4784 directory
, nt_errstr(status
)));
4788 status
= rename_internals_fsp(conn
, fsp
, newname
, attrs
,
4791 close_file(fsp
, NORMAL_CLOSE
);
4793 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4794 nt_errstr(status
), directory
,newname
));
4800 * Wildcards - process each file that matches.
4802 if (strequal(mask
,"????????.???")) {
4806 status
= check_name(conn
, directory
);
4807 if (!NT_STATUS_IS_OK(status
)) {
4811 dir_hnd
= OpenDir(conn
, directory
, mask
, attrs
);
4812 if (dir_hnd
== NULL
) {
4813 return map_nt_error_from_unix(errno
);
4816 status
= NT_STATUS_NO_SUCH_FILE
;
4818 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4819 * - gentest fix. JRA
4822 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
4825 BOOL sysdir_entry
= False
;
4827 pstrcpy(fname
,dname
);
4829 /* Quick check for "." and ".." */
4830 if (fname
[0] == '.') {
4831 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
4833 sysdir_entry
= True
;
4840 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
)) {
4844 if(!mask_match(fname
, mask
, conn
->case_sensitive
)) {
4849 status
= NT_STATUS_OBJECT_NAME_INVALID
;
4853 slprintf(fname
, sizeof(fname
)-1, "%s/%s", directory
, dname
);
4855 pstrcpy(destname
,newname
);
4857 if (!resolve_wildcards(fname
,destname
)) {
4858 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4864 SMB_VFS_STAT(conn
, fname
, &sbuf1
);
4866 status
= S_ISDIR(sbuf1
.st_mode
) ?
4867 open_directory(conn
, req
, fname
, &sbuf1
,
4869 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4870 FILE_OPEN
, 0, 0, NULL
,
4872 : open_file_ntcreate(conn
, req
, fname
, &sbuf1
,
4874 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4875 FILE_OPEN
, 0, 0, 0, NULL
,
4878 if (!NT_STATUS_IS_OK(status
)) {
4879 DEBUG(3,("rename_internals: open_file_ntcreate "
4880 "returned %s rename %s -> %s\n",
4881 nt_errstr(status
), directory
, newname
));
4885 status
= rename_internals_fsp(conn
, fsp
, destname
, attrs
,
4888 close_file(fsp
, NORMAL_CLOSE
);
4890 if (!NT_STATUS_IS_OK(status
)) {
4891 DEBUG(3, ("rename_internals_fsp returned %s for "
4892 "rename %s -> %s\n", nt_errstr(status
),
4893 directory
, newname
));
4899 DEBUG(3,("rename_internals: doing rename on %s -> "
4900 "%s\n",fname
,destname
));
4904 if (count
== 0 && NT_STATUS_IS_OK(status
)) {
4905 status
= map_nt_error_from_unix(errno
);
4911 /****************************************************************************
4913 ****************************************************************************/
4915 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
4922 uint32 attrs
= SVAL(inbuf
,smb_vwv0
);
4924 BOOL src_has_wcard
= False
;
4925 BOOL dest_has_wcard
= False
;
4926 struct smb_request req
;
4928 START_PROFILE(SMBmv
);
4930 init_smb_request(&req
, (uint8
*)inbuf
);
4932 p
= smb_buf(inbuf
) + 1;
4933 p
+= srvstr_get_path_wcard(inbuf
, SVAL(inbuf
,smb_flg2
), name
, p
,
4934 sizeof(name
), 0, STR_TERMINATE
, &status
,
4936 if (!NT_STATUS_IS_OK(status
)) {
4938 return ERROR_NT(status
);
4941 p
+= srvstr_get_path_wcard(inbuf
, SVAL(inbuf
,smb_flg2
), newname
, p
,
4942 sizeof(newname
), 0, STR_TERMINATE
, &status
,
4944 if (!NT_STATUS_IS_OK(status
)) {
4946 return ERROR_NT(status
);
4949 status
= resolve_dfspath_wcard(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, name
, &src_has_wcard
);
4950 if (!NT_STATUS_IS_OK(status
)) {
4952 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4953 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
4955 return ERROR_NT(status
);
4958 status
= resolve_dfspath_wcard(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, newname
, &dest_has_wcard
);
4959 if (!NT_STATUS_IS_OK(status
)) {
4961 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
4962 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
4964 return ERROR_NT(status
);
4967 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
4969 status
= rename_internals(conn
, &req
, name
, newname
, attrs
, False
,
4970 src_has_wcard
, dest_has_wcard
);
4971 if (!NT_STATUS_IS_OK(status
)) {
4973 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
4974 /* We have re-scheduled this call. */
4977 return ERROR_NT(status
);
4980 outsize
= set_message(inbuf
,outbuf
,0,0,False
);
4986 /*******************************************************************
4987 Copy a file as part of a reply_copy.
4988 ******************************************************************/
4991 * TODO: check error codes on all callers
4994 NTSTATUS
copy_file(connection_struct
*conn
,
4999 BOOL target_is_directory
)
5001 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
5003 files_struct
*fsp1
,*fsp2
;
5006 uint32 new_create_disposition
;
5009 pstrcpy(dest
,dest1
);
5010 if (target_is_directory
) {
5011 char *p
= strrchr_m(src
,'/');
5021 if (!vfs_file_exist(conn
,src
,&src_sbuf
)) {
5022 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5025 if (!target_is_directory
&& count
) {
5026 new_create_disposition
= FILE_OPEN
;
5028 if (!map_open_params_to_ntcreate(dest1
,0,ofun
,
5029 NULL
, NULL
, &new_create_disposition
, NULL
)) {
5030 return NT_STATUS_INVALID_PARAMETER
;
5034 status
= open_file_ntcreate(conn
, NULL
, src
, &src_sbuf
,
5036 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5039 FILE_ATTRIBUTE_NORMAL
,
5043 if (!NT_STATUS_IS_OK(status
)) {
5047 dosattrs
= dos_mode(conn
, src
, &src_sbuf
);
5048 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1) {
5049 ZERO_STRUCTP(&sbuf2
);
5052 status
= open_file_ntcreate(conn
, NULL
, dest
, &sbuf2
,
5054 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5055 new_create_disposition
,
5061 if (!NT_STATUS_IS_OK(status
)) {
5062 close_file(fsp1
,ERROR_CLOSE
);
5066 if ((ofun
&3) == 1) {
5067 if(SMB_VFS_LSEEK(fsp2
,fsp2
->fh
->fd
,0,SEEK_END
) == -1) {
5068 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
5070 * Stop the copy from occurring.
5073 src_sbuf
.st_size
= 0;
5077 if (src_sbuf
.st_size
) {
5078 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
5081 close_file(fsp1
,NORMAL_CLOSE
);
5083 /* Ensure the modtime is set correctly on the destination file. */
5084 fsp_set_pending_modtime( fsp2
, get_mtimespec(&src_sbuf
));
5087 * As we are opening fsp1 read-only we only expect
5088 * an error on close on fsp2 if we are out of space.
5089 * Thus we don't look at the error return from the
5092 status
= close_file(fsp2
,NORMAL_CLOSE
);
5094 if (!NT_STATUS_IS_OK(status
)) {
5098 if (ret
!= (SMB_OFF_T
)src_sbuf
.st_size
) {
5099 return NT_STATUS_DISK_FULL
;
5102 return NT_STATUS_OK
;
5105 /****************************************************************************
5106 Reply to a file copy.
5107 ****************************************************************************/
5109 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
5114 pstring mask
,newname
;
5117 int error
= ERRnoaccess
;
5119 int tid2
= SVAL(inbuf
,smb_vwv0
);
5120 int ofun
= SVAL(inbuf
,smb_vwv1
);
5121 int flags
= SVAL(inbuf
,smb_vwv2
);
5122 BOOL target_is_directory
=False
;
5123 BOOL source_has_wild
= False
;
5124 BOOL dest_has_wild
= False
;
5125 SMB_STRUCT_STAT sbuf1
, sbuf2
;
5127 START_PROFILE(SMBcopy
);
5129 *directory
= *mask
= 0;
5132 p
+= srvstr_get_path_wcard(inbuf
, SVAL(inbuf
,smb_flg2
), name
, p
,
5133 sizeof(name
), 0, STR_TERMINATE
, &status
,
5135 if (!NT_STATUS_IS_OK(status
)) {
5136 END_PROFILE(SMBcopy
);
5137 return ERROR_NT(status
);
5139 p
+= srvstr_get_path_wcard(inbuf
, SVAL(inbuf
,smb_flg2
), newname
, p
,
5140 sizeof(newname
), 0, STR_TERMINATE
, &status
,
5142 if (!NT_STATUS_IS_OK(status
)) {
5143 END_PROFILE(SMBcopy
);
5144 return ERROR_NT(status
);
5147 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
5149 if (tid2
!= conn
->cnum
) {
5150 /* can't currently handle inter share copies XXXX */
5151 DEBUG(3,("Rejecting inter-share copy\n"));
5152 END_PROFILE(SMBcopy
);
5153 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
5156 status
= resolve_dfspath_wcard(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, name
, &source_has_wild
);
5157 if (!NT_STATUS_IS_OK(status
)) {
5158 END_PROFILE(SMBcopy
);
5159 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5160 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
5162 return ERROR_NT(status
);
5165 status
= resolve_dfspath_wcard(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, newname
, &dest_has_wild
);
5166 if (!NT_STATUS_IS_OK(status
)) {
5167 END_PROFILE(SMBcopy
);
5168 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5169 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
5171 return ERROR_NT(status
);
5174 status
= unix_convert(conn
, name
, source_has_wild
, NULL
, &sbuf1
);
5175 if (!NT_STATUS_IS_OK(status
)) {
5176 END_PROFILE(SMBcopy
);
5177 return ERROR_NT(status
);
5180 status
= unix_convert(conn
, newname
, dest_has_wild
, NULL
, &sbuf2
);
5181 if (!NT_STATUS_IS_OK(status
)) {
5182 END_PROFILE(SMBcopy
);
5183 return ERROR_NT(status
);
5186 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
5188 if ((flags
&1) && target_is_directory
) {
5189 END_PROFILE(SMBcopy
);
5190 return ERROR_DOS(ERRDOS
,ERRbadfile
);
5193 if ((flags
&2) && !target_is_directory
) {
5194 END_PROFILE(SMBcopy
);
5195 return ERROR_DOS(ERRDOS
,ERRbadpath
);
5198 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
5199 /* wants a tree copy! XXXX */
5200 DEBUG(3,("Rejecting tree copy\n"));
5201 END_PROFILE(SMBcopy
);
5202 return ERROR_DOS(ERRSRV
,ERRerror
);
5205 p
= strrchr_m(name
,'/');
5207 pstrcpy(directory
,"./");
5211 pstrcpy(directory
,name
);
5216 * We should only check the mangled cache
5217 * here if unix_convert failed. This means
5218 * that the path in 'mask' doesn't exist
5219 * on the file system and so we need to look
5220 * for a possible mangle. This patch from
5221 * Tine Smukavec <valentin.smukavec@hermes.si>.
5224 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
)) {
5225 mangle_check_cache( mask
, sizeof(pstring
)-1, conn
->params
);
5228 if (!source_has_wild
) {
5229 pstrcat(directory
,"/");
5230 pstrcat(directory
,mask
);
5231 if (dest_has_wild
) {
5232 if (!resolve_wildcards(directory
,newname
)) {
5233 END_PROFILE(SMBcopy
);
5234 return ERROR_NT(NT_STATUS_NO_MEMORY
);
5238 status
= check_name(conn
, directory
);
5239 if (!NT_STATUS_IS_OK(status
)) {
5240 return ERROR_NT(status
);
5243 status
= check_name(conn
, newname
);
5244 if (!NT_STATUS_IS_OK(status
)) {
5245 return ERROR_NT(status
);
5248 status
= copy_file(conn
,directory
,newname
,ofun
,
5249 count
,target_is_directory
);
5251 if(!NT_STATUS_IS_OK(status
)) {
5252 END_PROFILE(SMBcopy
);
5253 return ERROR_NT(status
);
5258 struct smb_Dir
*dir_hnd
= NULL
;
5263 if (strequal(mask
,"????????.???"))
5266 status
= check_name(conn
, directory
);
5267 if (!NT_STATUS_IS_OK(status
)) {
5268 return ERROR_NT(status
);
5271 dir_hnd
= OpenDir(conn
, directory
, mask
, 0);
5272 if (dir_hnd
== NULL
) {
5273 status
= map_nt_error_from_unix(errno
);
5274 return ERROR_NT(status
);
5279 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
5281 pstrcpy(fname
,dname
);
5283 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
)) {
5287 if(!mask_match(fname
, mask
, conn
->case_sensitive
)) {
5291 error
= ERRnoaccess
;
5292 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
5293 pstrcpy(destname
,newname
);
5294 if (!resolve_wildcards(fname
,destname
)) {
5298 status
= check_name(conn
, fname
);
5299 if (!NT_STATUS_IS_OK(status
)) {
5300 return ERROR_NT(status
);
5303 status
= check_name(conn
, destname
);
5304 if (!NT_STATUS_IS_OK(status
)) {
5305 return ERROR_NT(status
);
5308 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
, destname
));
5310 status
= copy_file(conn
,fname
,destname
,ofun
,
5311 count
,target_is_directory
);
5312 if (NT_STATUS_IS_OK(status
)) {
5321 /* Error on close... */
5323 END_PROFILE(SMBcopy
);
5324 return(UNIXERROR(ERRHRD
,ERRgeneral
));
5327 END_PROFILE(SMBcopy
);
5328 return ERROR_DOS(ERRDOS
,error
);
5331 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
5332 SSVAL(outbuf
,smb_vwv0
,count
);
5334 END_PROFILE(SMBcopy
);
5338 /****************************************************************************
5340 ****************************************************************************/
5342 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
5349 START_PROFILE(pathworks_setdir
);
5352 if (!CAN_SETDIR(snum
)) {
5353 END_PROFILE(pathworks_setdir
);
5354 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
5357 srvstr_get_path(inbuf
, SVAL(inbuf
,smb_flg2
), newdir
,
5358 smb_buf(inbuf
) + 1, sizeof(newdir
), 0, STR_TERMINATE
,
5360 if (!NT_STATUS_IS_OK(status
)) {
5361 END_PROFILE(pathworks_setdir
);
5362 return ERROR_NT(status
);
5365 status
= resolve_dfspath(conn
, SVAL(inbuf
,smb_flg2
) & FLAGS2_DFS_PATHNAMES
, newdir
);
5366 if (!NT_STATUS_IS_OK(status
)) {
5367 END_PROFILE(pathworks_setdir
);
5368 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5369 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED
, ERRSRV
, ERRbadpath
);
5371 return ERROR_NT(status
);
5374 if (strlen(newdir
) != 0) {
5375 if (!vfs_directory_exist(conn
,newdir
,NULL
)) {
5376 END_PROFILE(pathworks_setdir
);
5377 return ERROR_DOS(ERRDOS
,ERRbadpath
);
5379 set_conn_connectpath(conn
,newdir
);
5382 outsize
= set_message(inbuf
,outbuf
,0,0,False
);
5383 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
5385 DEBUG(3,("setdir %s\n", newdir
));
5387 END_PROFILE(pathworks_setdir
);
5392 #define DBGC_CLASS DBGC_LOCKING
5394 /****************************************************************************
5395 Get a lock pid, dealing with large count requests.
5396 ****************************************************************************/
5398 uint32
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
5400 if(!large_file_format
)
5401 return (uint32
)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
5403 return (uint32
)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
5406 /****************************************************************************
5407 Get a lock count, dealing with large count requests.
5408 ****************************************************************************/
5410 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
5412 SMB_BIG_UINT count
= 0;
5414 if(!large_file_format
) {
5415 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
5418 #if defined(HAVE_LONGLONG)
5419 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
5420 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
5421 #else /* HAVE_LONGLONG */
5424 * NT4.x seems to be broken in that it sends large file (64 bit)
5425 * lockingX calls even if the CAP_LARGE_FILES was *not*
5426 * negotiated. For boxes without large unsigned ints truncate the
5427 * lock count by dropping the top 32 bits.
5430 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
5431 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5432 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
5433 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
5434 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
5437 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
5438 #endif /* HAVE_LONGLONG */
5444 #if !defined(HAVE_LONGLONG)
5445 /****************************************************************************
5446 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5447 ****************************************************************************/
5449 static uint32
map_lock_offset(uint32 high
, uint32 low
)
5453 uint32 highcopy
= high
;
5456 * Try and find out how many significant bits there are in high.
5459 for(i
= 0; highcopy
; i
++)
5463 * We use 31 bits not 32 here as POSIX
5464 * lock offsets may not be negative.
5467 mask
= (~0) << (31 - i
);
5470 return 0; /* Fail. */
5476 #endif /* !defined(HAVE_LONGLONG) */
5478 /****************************************************************************
5479 Get a lock offset, dealing with large offset requests.
5480 ****************************************************************************/
5482 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
5484 SMB_BIG_UINT offset
= 0;
5488 if(!large_file_format
) {
5489 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
5492 #if defined(HAVE_LONGLONG)
5493 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
5494 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
5495 #else /* HAVE_LONGLONG */
5498 * NT4.x seems to be broken in that it sends large file (64 bit)
5499 * lockingX calls even if the CAP_LARGE_FILES was *not*
5500 * negotiated. For boxes without large unsigned ints mangle the
5501 * lock offset by mapping the top 32 bits onto the lower 32.
5504 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
5505 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
5506 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
5509 if((new_low
= map_lock_offset(high
, low
)) == 0) {
5511 return (SMB_BIG_UINT
)-1;
5514 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5515 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
5516 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
5517 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
5520 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
5521 #endif /* HAVE_LONGLONG */
5527 /****************************************************************************
5528 Reply to a lockingX request.
5529 ****************************************************************************/
5531 int reply_lockingX(connection_struct
*conn
, char *inbuf
, char *outbuf
,
5532 int length
, int bufsize
)
5534 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv2
));
5535 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
5536 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
5537 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
5538 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
5539 SMB_BIG_UINT count
= 0, offset
= 0;
5541 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
5544 BOOL large_file_format
=
5545 (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
5547 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
5549 START_PROFILE(SMBlockingX
);
5551 CHECK_FSP(fsp
,conn
);
5553 data
= smb_buf(inbuf
);
5555 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
5556 /* we don't support these - and CANCEL_LOCK makes w2k
5557 and XP reboot so I don't really want to be
5558 compatible! (tridge) */
5559 return ERROR_NT(NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
5562 /* Check if this is an oplock break on a file
5563 we have granted an oplock on.
5565 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
5566 /* Client can insist on breaking to none. */
5567 BOOL break_to_none
= (oplocklevel
== 0);
5570 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5571 "for fnum = %d\n", (unsigned int)oplocklevel
,
5575 * Make sure we have granted an exclusive or batch oplock on
5579 if (fsp
->oplock_type
== 0) {
5581 /* The Samba4 nbench simulator doesn't understand
5582 the difference between break to level2 and break
5583 to none from level2 - it sends oplock break
5584 replies in both cases. Don't keep logging an error
5585 message here - just ignore it. JRA. */
5587 DEBUG(5,("reply_lockingX: Error : oplock break from "
5588 "client for fnum = %d (oplock=%d) and no "
5589 "oplock granted on this file (%s).\n",
5590 fsp
->fnum
, fsp
->oplock_type
, fsp
->fsp_name
));
5592 /* if this is a pure oplock break request then don't
5594 if (num_locks
== 0 && num_ulocks
== 0) {
5595 END_PROFILE(SMBlockingX
);
5598 END_PROFILE(SMBlockingX
);
5599 return ERROR_DOS(ERRDOS
,ERRlock
);
5603 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
5605 result
= remove_oplock(fsp
);
5607 result
= downgrade_oplock(fsp
);
5611 DEBUG(0, ("reply_lockingX: error in removing "
5612 "oplock on file %s\n", fsp
->fsp_name
));
5613 /* Hmmm. Is this panic justified? */
5614 smb_panic("internal tdb error");
5617 reply_to_oplock_break_requests(fsp
);
5619 /* if this is a pure oplock break request then don't send a
5621 if (num_locks
== 0 && num_ulocks
== 0) {
5622 /* Sanity check - ensure a pure oplock break is not a
5624 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
5625 DEBUG(0,("reply_lockingX: Error : pure oplock "
5626 "break is a chained %d request !\n",
5627 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
5628 END_PROFILE(SMBlockingX
);
5634 * We do this check *after* we have checked this is not a oplock break
5635 * response message. JRA.
5638 release_level_2_oplocks_on_change(fsp
);
5640 /* Data now points at the beginning of the list
5641 of smb_unlkrng structs */
5642 for(i
= 0; i
< (int)num_ulocks
; i
++) {
5643 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
5644 count
= get_lock_count( data
, i
, large_file_format
);
5645 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
5648 * There is no error code marked "stupid client bug".... :-).
5651 END_PROFILE(SMBlockingX
);
5652 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
5655 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5656 "pid %u, file %s\n", (double)offset
, (double)count
,
5657 (unsigned int)lock_pid
, fsp
->fsp_name
));
5659 status
= do_unlock(smbd_messaging_context(),
5666 if (NT_STATUS_V(status
)) {
5667 END_PROFILE(SMBlockingX
);
5668 return ERROR_NT(status
);
5672 /* Setup the timeout in seconds. */
5674 if (!lp_blocking_locks(SNUM(conn
))) {
5678 /* Now do any requested locks */
5679 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
5681 /* Data now points at the beginning of the list
5682 of smb_lkrng structs */
5684 for(i
= 0; i
< (int)num_locks
; i
++) {
5685 enum brl_type lock_type
= ((locktype
& LOCKING_ANDX_SHARED_LOCK
) ?
5686 READ_LOCK
:WRITE_LOCK
);
5687 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
5688 count
= get_lock_count( data
, i
, large_file_format
);
5689 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
5692 * There is no error code marked "stupid client bug".... :-).
5695 END_PROFILE(SMBlockingX
);
5696 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
5699 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5700 "%u, file %s timeout = %d\n", (double)offset
,
5701 (double)count
, (unsigned int)lock_pid
,
5702 fsp
->fsp_name
, (int)lock_timeout
));
5704 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
5705 if (lp_blocking_locks(SNUM(conn
))) {
5707 /* Schedule a message to ourselves to
5708 remove the blocking lock record and
5709 return the right error. */
5711 if (!blocking_lock_cancel(fsp
,
5717 NT_STATUS_FILE_LOCK_CONFLICT
)) {
5718 END_PROFILE(SMBlockingX
);
5719 return ERROR_NT(NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
5722 /* Remove a matching pending lock. */
5723 status
= do_lock_cancel(fsp
,
5729 BOOL blocking_lock
= lock_timeout
? True
: False
;
5730 BOOL defer_lock
= False
;
5731 struct byte_range_lock
*br_lck
;
5732 uint32 block_smbpid
;
5734 br_lck
= do_lock(smbd_messaging_context(),
5745 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
5746 /* Windows internal resolution for blocking locks seems
5747 to be about 200ms... Don't wait for less than that. JRA. */
5748 if (lock_timeout
!= -1 && lock_timeout
< lp_lock_spin_time()) {
5749 lock_timeout
= lp_lock_spin_time();
5754 /* This heuristic seems to match W2K3 very well. If a
5755 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5756 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5757 far as I can tell. Replacement for do_lock_spin(). JRA. */
5759 if (br_lck
&& lp_blocking_locks(SNUM(conn
)) && !blocking_lock
&&
5760 NT_STATUS_EQUAL((status
), NT_STATUS_FILE_LOCK_CONFLICT
)) {
5762 lock_timeout
= lp_lock_spin_time();
5765 if (br_lck
&& defer_lock
) {
5767 * A blocking lock was requested. Package up
5768 * this smb into a queued request and push it
5769 * onto the blocking lock queue.
5771 if(push_blocking_lock_request(br_lck
,
5782 TALLOC_FREE(br_lck
);
5783 END_PROFILE(SMBlockingX
);
5788 TALLOC_FREE(br_lck
);
5791 if (NT_STATUS_V(status
)) {
5792 END_PROFILE(SMBlockingX
);
5793 return ERROR_NT(status
);
5797 /* If any of the above locks failed, then we must unlock
5798 all of the previous locks (X/Open spec). */
5800 if (!(locktype
& LOCKING_ANDX_CANCEL_LOCK
) &&
5804 * Ensure we don't do a remove on the lock that just failed,
5805 * as under POSIX rules, if we have a lock already there, we
5806 * will delete it (and we shouldn't) .....
5808 for(i
--; i
>= 0; i
--) {
5809 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
5810 count
= get_lock_count( data
, i
, large_file_format
);
5811 offset
= get_lock_offset( data
, i
, large_file_format
,
5815 * There is no error code marked "stupid client
5819 END_PROFILE(SMBlockingX
);
5820 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
5823 do_unlock(smbd_messaging_context(),
5830 END_PROFILE(SMBlockingX
);
5831 return ERROR_NT(status
);
5834 set_message(inbuf
,outbuf
,2,0,True
);
5836 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5837 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
5839 END_PROFILE(SMBlockingX
);
5840 return chain_reply(inbuf
,&outbuf
,length
,bufsize
);
5844 #define DBGC_CLASS DBGC_ALL
5846 /****************************************************************************
5847 Reply to a SMBreadbmpx (read block multiplex) request.
5848 ****************************************************************************/
5850 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
5861 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
5862 START_PROFILE(SMBreadBmpx
);
5864 /* this function doesn't seem to work - disable by default */
5865 if (!lp_readbmpx()) {
5866 END_PROFILE(SMBreadBmpx
);
5867 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
5870 outsize
= set_message(inbuf
,outbuf
,8,0,True
);
5872 CHECK_FSP(fsp
,conn
);
5873 if (!CHECK_READ(fsp
,inbuf
)) {
5874 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
5877 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
5878 maxcount
= SVAL(inbuf
,smb_vwv3
);
5880 data
= smb_buf(outbuf
);
5881 pad
= ((long)data
)%4;
5886 max_per_packet
= bufsize
-(outsize
+pad
);
5890 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
5891 END_PROFILE(SMBreadBmpx
);
5892 return ERROR_DOS(ERRDOS
,ERRlock
);
5896 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
5898 nread
= read_file(fsp
,data
,startpos
,N
);
5903 if (nread
< (ssize_t
)N
)
5904 tcount
= total_read
+ nread
;
5906 set_message(inbuf
,outbuf
,8,nread
+pad
,False
);
5907 SIVAL(outbuf
,smb_vwv0
,startpos
);
5908 SSVAL(outbuf
,smb_vwv2
,tcount
);
5909 SSVAL(outbuf
,smb_vwv6
,nread
);
5910 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
5913 if (!send_smb(smbd_server_fd(),outbuf
))
5914 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5916 total_read
+= nread
;
5918 } while (total_read
< (ssize_t
)tcount
);
5920 END_PROFILE(SMBreadBmpx
);
5924 /****************************************************************************
5925 Reply to a SMBsetattrE.
5926 ****************************************************************************/
5928 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
5930 struct timespec ts
[2];
5932 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
5933 START_PROFILE(SMBsetattrE
);
5935 outsize
= set_message(inbuf
,outbuf
,0,0,False
);
5937 if(!fsp
|| (fsp
->conn
!= conn
)) {
5938 END_PROFILE(SMBsetattrE
);
5939 return ERROR_DOS(ERRDOS
,ERRbadfid
);
5943 * Convert the DOS times into unix times. Ignore create
5944 * time as UNIX can't set this.
5947 ts
[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf
+smb_vwv3
)); /* atime. */
5948 ts
[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf
+smb_vwv5
)); /* mtime. */
5951 * Patch from Ray Frush <frush@engr.colostate.edu>
5952 * Sometimes times are sent as zero - ignore them.
5955 if (null_timespec(ts
[0]) && null_timespec(ts
[1])) {
5956 /* Ignore request */
5957 if( DEBUGLVL( 3 ) ) {
5958 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
5959 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5961 END_PROFILE(SMBsetattrE
);
5963 } else if (!null_timespec(ts
[0]) && null_timespec(ts
[1])) {
5964 /* set modify time = to access time if modify time was unset */
5968 /* Set the date on this file */
5969 /* Should we set pending modtime here ? JRA */
5970 if(file_ntimes(conn
, fsp
->fsp_name
, ts
)) {
5971 END_PROFILE(SMBsetattrE
);
5972 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
5975 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5977 (unsigned int)ts
[0].tv_sec
,
5978 (unsigned int)ts
[1].tv_sec
));
5980 END_PROFILE(SMBsetattrE
);
5985 /* Back from the dead for OS/2..... JRA. */
5987 /****************************************************************************
5988 Reply to a SMBwritebmpx (write block multiplex primary) request.
5989 ****************************************************************************/
5991 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
5994 ssize_t nwritten
= -1;
6001 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
6003 START_PROFILE(SMBwriteBmpx
);
6005 CHECK_FSP(fsp
,conn
);
6006 if (!CHECK_WRITE(fsp
)) {
6007 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
6009 if (HAS_CACHED_ERROR(fsp
)) {
6010 return(CACHED_ERROR(fsp
));
6013 tcount
= SVAL(inbuf
,smb_vwv1
);
6014 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
6015 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
6016 numtowrite
= SVAL(inbuf
,smb_vwv10
);
6017 smb_doff
= SVAL(inbuf
,smb_vwv11
);
6019 data
= smb_base(inbuf
) + smb_doff
;
6021 /* If this fails we need to send an SMBwriteC response,
6022 not an SMBwritebmpx - set this up now so we don't forget */
6023 SCVAL(outbuf
,smb_com
,SMBwritec
);
6025 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
)) {
6026 END_PROFILE(SMBwriteBmpx
);
6027 return(ERROR_DOS(ERRDOS
,ERRlock
));
6030 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
6032 status
= sync_file(conn
, fsp
, write_through
);
6033 if (!NT_STATUS_IS_OK(status
)) {
6034 END_PROFILE(SMBwriteBmpx
);
6035 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6036 fsp
->fsp_name
, nt_errstr(status
) ));
6037 return ERROR_NT(status
);
6040 if(nwritten
< (ssize_t
)numtowrite
) {
6041 END_PROFILE(SMBwriteBmpx
);
6042 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
6045 /* If the maximum to be written to this file
6046 is greater than what we just wrote then set
6047 up a secondary struct to be attached to this
6048 fd, we will use this to cache error messages etc. */
6050 if((ssize_t
)tcount
> nwritten
) {
6051 write_bmpx_struct
*wbms
;
6052 if(fsp
->wbmpx_ptr
!= NULL
)
6053 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
6055 wbms
= SMB_MALLOC_P(write_bmpx_struct
);
6057 DEBUG(0,("Out of memory in reply_readmpx\n"));
6058 END_PROFILE(SMBwriteBmpx
);
6059 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
6061 wbms
->wr_mode
= write_through
;
6062 wbms
->wr_discard
= False
; /* No errors yet */
6063 wbms
->wr_total_written
= nwritten
;
6064 wbms
->wr_errclass
= 0;
6066 fsp
->wbmpx_ptr
= wbms
;
6069 /* We are returning successfully, set the message type back to
6071 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
6073 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
6075 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
6077 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6078 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
6080 if (write_through
&& tcount
==nwritten
) {
6081 /* We need to send both a primary and a secondary response */
6082 smb_setlen(inbuf
,outbuf
,outsize
- 4);
6084 if (!send_smb(smbd_server_fd(),outbuf
))
6085 exit_server_cleanly("reply_writebmpx: send_smb failed.");
6087 /* Now the secondary */
6088 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
6089 SCVAL(outbuf
,smb_com
,SMBwritec
);
6090 SSVAL(outbuf
,smb_vwv0
,nwritten
);
6093 END_PROFILE(SMBwriteBmpx
);
6097 /****************************************************************************
6098 Reply to a SMBwritebs (write block multiplex secondary) request.
6099 ****************************************************************************/
6101 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
6104 ssize_t nwritten
= -1;
6111 write_bmpx_struct
*wbms
;
6112 BOOL send_response
= False
;
6113 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
6115 START_PROFILE(SMBwriteBs
);
6117 CHECK_FSP(fsp
,conn
);
6118 if (!CHECK_WRITE(fsp
)) {
6119 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
6122 tcount
= SVAL(inbuf
,smb_vwv1
);
6123 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
6124 numtowrite
= SVAL(inbuf
,smb_vwv6
);
6125 smb_doff
= SVAL(inbuf
,smb_vwv7
);
6127 data
= smb_base(inbuf
) + smb_doff
;
6129 /* We need to send an SMBwriteC response, not an SMBwritebs */
6130 SCVAL(outbuf
,smb_com
,SMBwritec
);
6132 /* This fd should have an auxiliary struct attached,
6133 check that it does */
6134 wbms
= fsp
->wbmpx_ptr
;
6136 END_PROFILE(SMBwriteBs
);
6140 /* If write through is set we can return errors, else we must cache them */
6141 write_through
= wbms
->wr_mode
;
6143 /* Check for an earlier error */
6144 if(wbms
->wr_discard
) {
6145 END_PROFILE(SMBwriteBs
);
6146 return -1; /* Just discard the packet */
6149 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
6151 status
= sync_file(conn
, fsp
, write_through
);
6153 if (nwritten
< (ssize_t
)numtowrite
|| !NT_STATUS_IS_OK(status
)) {
6155 /* We are returning an error - we can delete the aux struct */
6158 fsp
->wbmpx_ptr
= NULL
;
6159 END_PROFILE(SMBwriteBs
);
6160 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
6162 wbms
->wr_errclass
= ERRHRD
;
6163 wbms
->wr_error
= ERRdiskfull
;
6164 wbms
->wr_status
= NT_STATUS_DISK_FULL
;
6165 wbms
->wr_discard
= True
;
6166 END_PROFILE(SMBwriteBs
);
6170 /* Increment the total written, if this matches tcount
6171 we can discard the auxiliary struct (hurrah !) and return a writeC */
6172 wbms
->wr_total_written
+= nwritten
;
6173 if(wbms
->wr_total_written
>= tcount
) {
6174 if (write_through
) {
6175 outsize
= set_message(inbuf
,outbuf
,1,0,True
);
6176 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
6177 send_response
= True
;
6181 fsp
->wbmpx_ptr
= NULL
;
6185 END_PROFILE(SMBwriteBs
);
6189 END_PROFILE(SMBwriteBs
);
6193 /****************************************************************************
6194 Reply to a SMBgetattrE.
6195 ****************************************************************************/
6197 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
6199 SMB_STRUCT_STAT sbuf
;
6202 files_struct
*fsp
= file_fsp(SVAL(inbuf
,smb_vwv0
));
6203 START_PROFILE(SMBgetattrE
);
6205 outsize
= set_message(inbuf
,outbuf
,11,0,True
);
6207 if(!fsp
|| (fsp
->conn
!= conn
)) {
6208 END_PROFILE(SMBgetattrE
);
6209 return ERROR_DOS(ERRDOS
,ERRbadfid
);
6212 /* Do an fstat on this file */
6213 if(fsp_stat(fsp
, &sbuf
)) {
6214 END_PROFILE(SMBgetattrE
);
6215 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
6218 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
6221 * Convert the times into dos times. Set create
6222 * date to be last modify date as UNIX doesn't save
6226 srv_put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
6227 srv_put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
6228 /* Should we check pending modtime here ? JRA */
6229 srv_put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
6232 SIVAL(outbuf
,smb_vwv6
,0);
6233 SIVAL(outbuf
,smb_vwv8
,0);
6235 uint32 allocation_size
= get_allocation_size(conn
,fsp
, &sbuf
);
6236 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
6237 SIVAL(outbuf
,smb_vwv8
,allocation_size
);
6239 SSVAL(outbuf
,smb_vwv10
, mode
);
6241 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
6243 END_PROFILE(SMBgetattrE
);