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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol
;
33 unsigned int smb_echo_count
= 0;
34 extern uint32 global_client_caps
;
36 extern struct current_user current_user
;
37 extern BOOL global_encrypted_passwords_negotiated
;
39 /****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
41 path or anything including wildcards.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
45 ****************************************************************************/
47 NTSTATUS
check_path_syntax_internal(pstring destname
,
48 const pstring srcname
,
50 BOOL
*p_last_component_contains_wcard
)
53 const char *s
= srcname
;
54 NTSTATUS ret
= NT_STATUS_OK
;
55 BOOL start_of_name_component
= True
;
57 *p_last_component_contains_wcard
= False
;
60 if (IS_DIRECTORY_SEP(*s
)) {
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_DIRECTORY_SEP(*s
)) {
69 if ((d
!= destname
) && (*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_DIRECTORY_SEP(s
[2]) || 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
> destname
) && (*(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
> destname
; 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_DIRECTORY_SEP(s
[1]))) {
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(pstring destname
, const pstring srcname
)
180 return check_path_syntax_internal(destname
, srcname
, True
, &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(pstring destname
, const pstring srcname
, BOOL
*p_contains_wcard
)
191 return check_path_syntax_internal(destname
, srcname
, True
, 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 static NTSTATUS
check_path_syntax_posix(pstring destname
, const pstring srcname
)
203 return check_path_syntax_internal(destname
, srcname
, False
, &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(char *inbuf
, char *dest
, const char *src
, size_t dest_len
, size_t src_len
, int flags
,
211 NTSTATUS
*err
, BOOL
*contains_wcard
)
214 char *tmppath_ptr
= tmppath
;
217 SMB_ASSERT(dest_len
== sizeof(pstring
));
221 ret
= srvstr_pull_buf( inbuf
, tmppath_ptr
, src
, dest_len
, flags
);
223 ret
= srvstr_pull( inbuf
, tmppath_ptr
, src
, dest_len
, src_len
, flags
);
226 *contains_wcard
= False
;
228 if (lp_posix_pathnames()) {
229 *err
= check_path_syntax_posix(dest
, tmppath
);
231 *err
= check_path_syntax_wcard(dest
, tmppath
, contains_wcard
);
237 /****************************************************************************
238 Pull a string and check the path - provide for error return.
239 ****************************************************************************/
241 size_t srvstr_get_path(char *inbuf
, char *dest
, const char *src
, size_t dest_len
, size_t src_len
, int flags
, NTSTATUS
*err
)
244 char *tmppath_ptr
= tmppath
;
247 SMB_ASSERT(dest_len
== sizeof(pstring
));
251 ret
= srvstr_pull_buf( inbuf
, tmppath_ptr
, src
, dest_len
, flags
);
253 ret
= srvstr_pull( inbuf
, tmppath_ptr
, src
, dest_len
, src_len
, flags
);
255 if (lp_posix_pathnames()) {
256 *err
= check_path_syntax_posix(dest
, tmppath
);
258 *err
= check_path_syntax(dest
, tmppath
);
264 /****************************************************************************
265 Reply to a special message.
266 ****************************************************************************/
268 int reply_special(char *inbuf
,char *outbuf
)
271 int msg_type
= CVAL(inbuf
,0);
272 int msg_flags
= CVAL(inbuf
,1);
276 static BOOL already_got_session
= False
;
280 memset(outbuf
,'\0',smb_size
);
282 smb_setlen(outbuf
,0);
285 case 0x81: /* session request */
287 if (already_got_session
) {
288 exit_server_cleanly("multiple session request not permitted");
291 SCVAL(outbuf
,0,0x82);
293 if (name_len(inbuf
+4) > 50 ||
294 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
295 DEBUG(0,("Invalid name length in session request\n"));
298 name_extract(inbuf
,4,name1
);
299 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
300 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
303 set_local_machine_name(name1
, True
);
304 set_remote_machine_name(name2
, True
);
306 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
307 get_local_machine_name(), get_remote_machine_name(),
310 if (name_type
== 'R') {
311 /* We are being asked for a pathworks session ---
313 SCVAL(outbuf
, 0,0x83);
317 /* only add the client's machine name to the list
318 of possibly valid usernames if we are operating
319 in share mode security */
320 if (lp_security() == SEC_SHARE
) {
321 add_session_user(get_remote_machine_name());
324 reload_services(True
);
327 already_got_session
= True
;
330 case 0x89: /* session keepalive request
331 (some old clients produce this?) */
332 SCVAL(outbuf
,0,SMBkeepalive
);
336 case 0x82: /* positive session response */
337 case 0x83: /* negative session response */
338 case 0x84: /* retarget session response */
339 DEBUG(0,("Unexpected session response\n"));
342 case SMBkeepalive
: /* session keepalive */
347 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
348 msg_type
, msg_flags
));
353 /****************************************************************************
355 conn POINTER CAN BE NULL HERE !
356 ****************************************************************************/
358 int reply_tcon(connection_struct
*conn
,
359 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
366 uint16 vuid
= SVAL(inbuf
,smb_uid
);
370 DATA_BLOB password_blob
;
372 START_PROFILE(SMBtcon
);
374 *service_buf
= *password
= *dev
= 0;
376 p
= smb_buf(inbuf
)+1;
377 p
+= srvstr_pull_buf(inbuf
, service_buf
, p
, sizeof(service_buf
), STR_TERMINATE
) + 1;
378 pwlen
= srvstr_pull_buf(inbuf
, password
, p
, sizeof(password
), STR_TERMINATE
) + 1;
380 p
+= srvstr_pull_buf(inbuf
, dev
, p
, sizeof(dev
), STR_TERMINATE
) + 1;
382 p
= strrchr_m(service_buf
,'\\');
386 service
= service_buf
;
389 password_blob
= data_blob(password
, pwlen
+1);
391 conn
= make_connection(service
,password_blob
,dev
,vuid
,&nt_status
);
393 data_blob_clear_free(&password_blob
);
396 END_PROFILE(SMBtcon
);
397 return ERROR_NT(nt_status
);
400 outsize
= set_message(outbuf
,2,0,True
);
401 SSVAL(outbuf
,smb_vwv0
,max_recv
);
402 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
403 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
405 DEBUG(3,("tcon service=%s cnum=%d\n",
406 service
, conn
->cnum
));
408 END_PROFILE(SMBtcon
);
412 /****************************************************************************
413 Reply to a tcon and X.
414 conn POINTER CAN BE NULL HERE !
415 ****************************************************************************/
417 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
422 /* what the cleint thinks the device is */
423 fstring client_devicetype
;
424 /* what the server tells the client the share represents */
425 const char *server_devicetype
;
427 uint16 vuid
= SVAL(inbuf
,smb_uid
);
428 int passlen
= SVAL(inbuf
,smb_vwv3
);
432 START_PROFILE(SMBtconX
);
434 *service
= *client_devicetype
= 0;
436 /* we might have to close an old one */
437 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
438 close_cnum(conn
,vuid
);
441 if (passlen
> MAX_PASS_LEN
) {
442 return ERROR_DOS(ERRDOS
,ERRbuftoosmall
);
445 if (global_encrypted_passwords_negotiated
) {
446 password
= data_blob(smb_buf(inbuf
),passlen
);
448 password
= data_blob(smb_buf(inbuf
),passlen
+1);
449 /* Ensure correct termination */
450 password
.data
[passlen
]=0;
453 p
= smb_buf(inbuf
) + passlen
;
454 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
457 * the service name can be either: \\server\share
458 * or share directly like on the DELL PowerVault 705
461 q
= strchr_m(path
+2,'\\');
463 END_PROFILE(SMBtconX
);
464 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
466 fstrcpy(service
,q
+1);
469 fstrcpy(service
,path
);
471 p
+= srvstr_pull(inbuf
, client_devicetype
, p
, sizeof(client_devicetype
), 6, STR_ASCII
);
473 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
475 conn
= make_connection(service
,password
,client_devicetype
,vuid
,&nt_status
);
477 data_blob_clear_free(&password
);
480 END_PROFILE(SMBtconX
);
481 return ERROR_NT(nt_status
);
485 server_devicetype
= "IPC";
486 else if ( IS_PRINT(conn
) )
487 server_devicetype
= "LPT1:";
489 server_devicetype
= "A:";
491 if (Protocol
< PROTOCOL_NT1
) {
492 set_message(outbuf
,2,0,True
);
494 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
495 STR_TERMINATE
|STR_ASCII
);
496 set_message_end(outbuf
,p
);
498 /* NT sets the fstype of IPC$ to the null string */
499 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
501 set_message(outbuf
,3,0,True
);
504 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
505 STR_TERMINATE
|STR_ASCII
);
506 p
+= srvstr_push(outbuf
, p
, fstype
, -1,
509 set_message_end(outbuf
,p
);
511 /* what does setting this bit do? It is set by NT4 and
512 may affect the ability to autorun mounted cdroms */
513 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
514 (lp_csc_policy(SNUM(conn
)) << 2));
516 init_dfsroot(conn
, inbuf
, outbuf
);
520 DEBUG(3,("tconX service=%s \n",
523 /* set the incoming and outgoing tid to the just created one */
524 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
525 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
527 END_PROFILE(SMBtconX
);
528 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
531 /****************************************************************************
532 Reply to an unknown type.
533 ****************************************************************************/
535 int reply_unknown(char *inbuf
,char *outbuf
)
538 type
= CVAL(inbuf
,smb_com
);
540 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
541 smb_fn_name(type
), type
, type
));
543 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
546 /****************************************************************************
548 conn POINTER CAN BE NULL HERE !
549 ****************************************************************************/
551 int reply_ioctl(connection_struct
*conn
,
552 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
554 uint16 device
= SVAL(inbuf
,smb_vwv1
);
555 uint16 function
= SVAL(inbuf
,smb_vwv2
);
556 uint32 ioctl_code
= (device
<< 16) + function
;
557 int replysize
, outsize
;
559 START_PROFILE(SMBioctl
);
561 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
563 switch (ioctl_code
) {
564 case IOCTL_QUERY_JOB_INFO
:
568 END_PROFILE(SMBioctl
);
569 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
572 outsize
= set_message(outbuf
,8,replysize
+1,True
);
573 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
574 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
575 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
576 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
578 switch (ioctl_code
) {
579 case IOCTL_QUERY_JOB_INFO
:
581 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
583 END_PROFILE(SMBioctl
);
584 return(UNIXERROR(ERRDOS
,ERRbadfid
));
586 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
587 srvstr_push(outbuf
, p
+2, global_myname(), 15, STR_TERMINATE
|STR_ASCII
);
589 srvstr_push(outbuf
, p
+18, lp_servicename(SNUM(conn
)), 13, STR_TERMINATE
|STR_ASCII
);
595 END_PROFILE(SMBioctl
);
599 /****************************************************************************
600 Strange checkpath NTSTATUS mapping.
601 ****************************************************************************/
603 static NTSTATUS
map_checkpath_error(const char *inbuf
, NTSTATUS status
)
605 /* Strange DOS error code semantics only for checkpath... */
606 if (!(SVAL(inbuf
,smb_flg2
) & FLAGS2_32_BIT_ERROR_CODES
)) {
607 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
608 /* We need to map to ERRbadpath */
609 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
615 /****************************************************************************
616 Reply to a checkpath.
617 ****************************************************************************/
619 int reply_checkpath(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
623 SMB_STRUCT_STAT sbuf
;
626 START_PROFILE(SMBcheckpath
);
628 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
);
629 if (!NT_STATUS_IS_OK(status
)) {
630 END_PROFILE(SMBcheckpath
);
631 status
= map_checkpath_error(inbuf
, status
);
632 return ERROR_NT(status
);
635 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
637 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(inbuf
,smb_vwv0
)));
639 status
= unix_convert(conn
, name
, False
, NULL
, &sbuf
);
640 if (!NT_STATUS_IS_OK(status
)) {
641 END_PROFILE(SMBcheckpath
);
642 status
= map_checkpath_error(inbuf
, status
);
643 return ERROR_NT(status
);
646 if (check_name(name
,conn
) && (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,name
,&sbuf
) == 0)) {
647 if (!S_ISDIR(sbuf
.st_mode
)) {
648 END_PROFILE(SMBcheckpath
);
649 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY
,ERRDOS
,ERRbadpath
);
652 /* We special case this - as when a Windows machine
653 is parsing a path is steps through the components
654 one at a time - if a component fails it expects
655 ERRbadpath, not ERRbadfile.
657 if(errno
== ENOENT
) {
659 * Windows returns different error codes if
660 * the parent directory is valid but not the
661 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
662 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
663 * if the path is invalid.
665 END_PROFILE(SMBcheckpath
);
666 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND
,ERRDOS
,ERRbadpath
);
669 END_PROFILE(SMBcheckpath
);
670 return(UNIXERROR(ERRDOS
,ERRbadpath
));
673 outsize
= set_message(outbuf
,0,0,False
);
675 END_PROFILE(SMBcheckpath
);
679 /****************************************************************************
681 ****************************************************************************/
683 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
687 SMB_STRUCT_STAT sbuf
;
694 START_PROFILE(SMBgetatr
);
696 p
= smb_buf(inbuf
) + 1;
697 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
698 if (!NT_STATUS_IS_OK(status
)) {
699 END_PROFILE(SMBgetatr
);
700 return ERROR_NT(status
);
703 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
705 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
706 under WfWg - weird! */
707 if (*fname
== '\0') {
708 mode
= aHIDDEN
| aDIR
;
709 if (!CAN_WRITE(conn
)) {
715 status
= unix_convert(conn
, fname
, False
, NULL
,&sbuf
);
716 if (!NT_STATUS_IS_OK(status
)) {
717 END_PROFILE(SMBgetatr
);
718 return ERROR_NT(status
);
720 if (check_name(fname
,conn
) &&
721 (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,fname
,&sbuf
) == 0)) {
722 mode
= dos_mode(conn
,fname
,&sbuf
);
724 mtime
= sbuf
.st_mtime
;
729 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname
,strerror(errno
)));
730 END_PROFILE(SMBgetatr
);
731 return UNIXERROR(ERRDOS
,ERRbadfile
);
735 outsize
= set_message(outbuf
,10,0,True
);
737 SSVAL(outbuf
,smb_vwv0
,mode
);
738 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
739 srv_put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
741 srv_put_dos_date3(outbuf
,smb_vwv1
,mtime
);
743 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
745 if (Protocol
>= PROTOCOL_NT1
) {
746 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
749 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname
, mode
, (unsigned int)size
) );
751 END_PROFILE(SMBgetatr
);
755 /****************************************************************************
757 ****************************************************************************/
759 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
765 SMB_STRUCT_STAT sbuf
;
769 START_PROFILE(SMBsetatr
);
771 p
= smb_buf(inbuf
) + 1;
772 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
773 if (!NT_STATUS_IS_OK(status
)) {
774 END_PROFILE(SMBsetatr
);
775 return ERROR_NT(status
);
778 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
780 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
781 if (!NT_STATUS_IS_OK(status
)) {
782 END_PROFILE(SMBsetatr
);
783 return ERROR_NT(status
);
786 if (fname
[0] == '.' && fname
[1] == '\0') {
788 * Not sure here is the right place to catch this
789 * condition. Might be moved to somewhere else later -- vl
791 END_PROFILE(SMBsetatr
);
792 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
795 if (!check_name(fname
,conn
)) {
796 END_PROFILE(SMBsetatr
);
797 return UNIXERROR(ERRDOS
, ERRnoaccess
);
800 mode
= SVAL(inbuf
,smb_vwv0
);
801 mtime
= srv_make_unix_date3(inbuf
+smb_vwv1
);
803 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
804 if (VALID_STAT_OF_DIR(sbuf
))
809 if (file_set_dosmode(conn
,fname
,mode
,&sbuf
,False
) != 0) {
810 END_PROFILE(SMBsetatr
);
811 return UNIXERROR(ERRDOS
, ERRnoaccess
);
815 if (!set_filetime(conn
,fname
,mtime
)) {
816 END_PROFILE(SMBsetatr
);
817 return UNIXERROR(ERRDOS
, ERRnoaccess
);
820 outsize
= set_message(outbuf
,0,0,False
);
822 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
824 END_PROFILE(SMBsetatr
);
828 /****************************************************************************
830 ****************************************************************************/
832 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
835 SMB_BIG_UINT dfree
,dsize
,bsize
;
836 START_PROFILE(SMBdskattr
);
838 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (SMB_BIG_UINT
)-1) {
839 END_PROFILE(SMBdskattr
);
840 return(UNIXERROR(ERRHRD
,ERRgeneral
));
843 outsize
= set_message(outbuf
,5,0,True
);
845 if (Protocol
<= PROTOCOL_LANMAN2
) {
846 double total_space
, free_space
;
847 /* we need to scale this to a number that DOS6 can handle. We
848 use floating point so we can handle large drives on systems
849 that don't have 64 bit integers
851 we end up displaying a maximum of 2G to DOS systems
853 total_space
= dsize
* (double)bsize
;
854 free_space
= dfree
* (double)bsize
;
856 dsize
= (total_space
+63*512) / (64*512);
857 dfree
= (free_space
+63*512) / (64*512);
859 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
860 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
862 SSVAL(outbuf
,smb_vwv0
,dsize
);
863 SSVAL(outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
864 SSVAL(outbuf
,smb_vwv2
,512); /* and this must be 512 */
865 SSVAL(outbuf
,smb_vwv3
,dfree
);
867 SSVAL(outbuf
,smb_vwv0
,dsize
);
868 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
869 SSVAL(outbuf
,smb_vwv2
,512);
870 SSVAL(outbuf
,smb_vwv3
,dfree
);
873 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
875 END_PROFILE(SMBdskattr
);
879 /****************************************************************************
881 Can be called from SMBsearch, SMBffirst or SMBfunique.
882 ****************************************************************************/
884 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
894 unsigned int numentries
= 0;
895 unsigned int maxentries
= 0;
896 BOOL finished
= False
;
903 BOOL check_descend
= False
;
904 BOOL expect_close
= False
;
905 BOOL can_open
= True
;
907 BOOL mask_contains_wcard
= False
;
908 BOOL allow_long_path_components
= (SVAL(inbuf
,smb_flg2
) & FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
910 START_PROFILE(SMBsearch
);
912 if (lp_posix_pathnames()) {
913 END_PROFILE(SMBsearch
);
914 return reply_unknown(inbuf
, outbuf
);
917 *mask
= *directory
= *fname
= 0;
919 /* If we were called as SMBffirst then we must expect close. */
920 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
923 outsize
= set_message(outbuf
,1,3,True
);
924 maxentries
= SVAL(inbuf
,smb_vwv0
);
925 dirtype
= SVAL(inbuf
,smb_vwv1
);
926 p
= smb_buf(inbuf
) + 1;
927 p
+= srvstr_get_path_wcard(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &nt_status
, &mask_contains_wcard
);
928 if (!NT_STATUS_IS_OK(nt_status
)) {
929 END_PROFILE(SMBsearch
);
930 return ERROR_NT(nt_status
);
933 RESOLVE_DFSPATH_WCARD(path
, conn
, inbuf
, outbuf
);
936 status_len
= SVAL(p
, 0);
939 /* dirtype &= ~aDIR; */
941 if (status_len
== 0) {
942 SMB_STRUCT_STAT sbuf
;
945 pstrcpy(directory
,path
);
947 nt_status
= unix_convert(conn
, directory
, True
, NULL
, &sbuf
);
948 if (!NT_STATUS_IS_OK(nt_status
)) {
949 END_PROFILE(SMBsearch
);
950 return ERROR_NT(nt_status
);
954 if (!check_name(directory
,conn
))
957 p
= strrchr_m(dir2
,'/');
966 p
= strrchr_m(directory
,'/');
972 if (strlen(directory
) == 0)
973 pstrcpy(directory
,".");
974 memset((char *)status
,'\0',21);
975 SCVAL(status
,0,(dirtype
& 0x1F));
980 status_dirtype
= CVAL(status
,0) & 0x1F;
981 if (status_dirtype
!= (dirtype
& 0x1F))
982 dirtype
= status_dirtype
;
984 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
987 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
988 pstrcpy(mask
, dptr_wcard(dptr_num
));
992 p
= smb_buf(outbuf
) + 3;
995 if (status_len
== 0) {
996 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
), mask
, mask_contains_wcard
, dirtype
);
999 END_PROFILE(SMBsearch
);
1000 return UNIXERROR(ERRDOS
, ERRnofids
);
1002 END_PROFILE(SMBsearch
);
1003 return ERROR_DOS(ERRDOS
,ERRnofids
);
1006 dirtype
= dptr_attr(dptr_num
);
1009 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1012 if ((dirtype
&0x1F) == aVOLID
) {
1013 memcpy(p
,status
,21);
1014 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),
1015 0,aVOLID
,0,!allow_long_path_components
);
1016 dptr_fill(p
+12,dptr_num
);
1017 if (dptr_zero(p
+12) && (status_len
==0))
1021 p
+= DIR_STRUCT_SIZE
;
1024 maxentries
= MIN(maxentries
, ((BUFFER_SIZE
- (p
- outbuf
))/DIR_STRUCT_SIZE
));
1026 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1027 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1028 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
1029 check_descend
= True
;
1031 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1032 finished
= !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
1034 memcpy(p
,status
,21);
1035 make_dir_struct(p
,mask
,fname
,size
, mode
,date
,
1036 !allow_long_path_components
);
1037 if (!dptr_fill(p
+12,dptr_num
)) {
1041 p
+= DIR_STRUCT_SIZE
;
1051 /* If we were called as SMBffirst with smb_search_id == NULL
1052 and no entries were found then return error and close dirptr
1055 if (numentries
== 0 || !ok
) {
1056 dptr_close(&dptr_num
);
1057 } else if(ok
&& expect_close
&& status_len
== 0) {
1058 /* Close the dptr - we know it's gone */
1059 dptr_close(&dptr_num
);
1062 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1063 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
) {
1064 dptr_close(&dptr_num
);
1067 if ((numentries
== 0) && !mask_contains_wcard
) {
1068 return ERROR_BOTH(STATUS_NO_MORE_FILES
,ERRDOS
,ERRnofiles
);
1071 SSVAL(outbuf
,smb_vwv0
,numentries
);
1072 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1073 SCVAL(smb_buf(outbuf
),0,5);
1074 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1076 /* The replies here are never long name. */
1077 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1078 if (!allow_long_path_components
) {
1079 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) & (~FLAGS2_LONG_PATH_COMPONENTS
));
1082 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1083 SSVAL(outbuf
,smb_flg2
, (SVAL(outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1085 outsize
+= DIR_STRUCT_SIZE
*numentries
;
1086 smb_setlen(outbuf
,outsize
- 4);
1088 if ((! *directory
) && dptr_path(dptr_num
))
1089 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1091 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1092 smb_fn_name(CVAL(inbuf
,smb_com
)),
1093 mask
, directory
, dirtype
, numentries
, maxentries
) );
1095 END_PROFILE(SMBsearch
);
1099 /****************************************************************************
1100 Reply to a fclose (stop directory search).
1101 ****************************************************************************/
1103 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1112 BOOL path_contains_wcard
= False
;
1114 START_PROFILE(SMBfclose
);
1116 if (lp_posix_pathnames()) {
1117 END_PROFILE(SMBfclose
);
1118 return reply_unknown(inbuf
, outbuf
);
1121 outsize
= set_message(outbuf
,1,0,True
);
1122 p
= smb_buf(inbuf
) + 1;
1123 p
+= srvstr_get_path_wcard(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &err
, &path_contains_wcard
);
1124 if (!NT_STATUS_IS_OK(err
)) {
1125 END_PROFILE(SMBfclose
);
1126 return ERROR_NT(err
);
1129 status_len
= SVAL(p
,0);
1132 if (status_len
== 0) {
1133 END_PROFILE(SMBfclose
);
1134 return ERROR_DOS(ERRSRV
,ERRsrverror
);
1137 memcpy(status
,p
,21);
1139 if(dptr_fetch(status
+12,&dptr_num
)) {
1140 /* Close the dptr - we know it's gone */
1141 dptr_close(&dptr_num
);
1144 SSVAL(outbuf
,smb_vwv0
,0);
1146 DEBUG(3,("search close\n"));
1148 END_PROFILE(SMBfclose
);
1152 /****************************************************************************
1154 ****************************************************************************/
1156 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1164 SMB_STRUCT_STAT sbuf
;
1166 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1168 uint32 dos_attr
= SVAL(inbuf
,smb_vwv1
);
1171 uint32 create_disposition
;
1172 uint32 create_options
= 0;
1174 START_PROFILE(SMBopen
);
1176 deny_mode
= SVAL(inbuf
,smb_vwv0
);
1178 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1179 if (!NT_STATUS_IS_OK(status
)) {
1180 END_PROFILE(SMBopen
);
1181 return ERROR_NT(status
);
1184 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1186 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
1187 if (!NT_STATUS_IS_OK(status
)) {
1188 END_PROFILE(SMBopen
);
1189 return ERROR_NT(status
);
1192 if (!map_open_params_to_ntcreate(fname
, deny_mode
, OPENX_FILE_EXISTS_OPEN
,
1193 &access_mask
, &share_mode
, &create_disposition
, &create_options
)) {
1194 END_PROFILE(SMBopen
);
1195 return ERROR_NT(NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1198 status
= open_file_ntcreate(conn
,fname
,&sbuf
,
1207 if (!NT_STATUS_IS_OK(status
)) {
1208 END_PROFILE(SMBopen
);
1209 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
1210 /* We have re-scheduled this call. */
1213 return ERROR_NT(status
);
1216 size
= sbuf
.st_size
;
1217 fattr
= dos_mode(conn
,fname
,&sbuf
);
1218 mtime
= sbuf
.st_mtime
;
1221 DEBUG(3,("attempt to open a directory %s\n",fname
));
1222 close_file(fsp
,ERROR_CLOSE
);
1223 END_PROFILE(SMBopen
);
1224 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1227 outsize
= set_message(outbuf
,7,0,True
);
1228 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1229 SSVAL(outbuf
,smb_vwv1
,fattr
);
1230 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1231 srv_put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1233 srv_put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1235 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1236 SSVAL(outbuf
,smb_vwv6
,deny_mode
);
1238 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1239 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1242 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1243 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1245 END_PROFILE(SMBopen
);
1249 /****************************************************************************
1250 Reply to an open and X.
1251 ****************************************************************************/
1253 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1256 uint16 open_flags
= SVAL(inbuf
,smb_vwv2
);
1257 int deny_mode
= SVAL(inbuf
,smb_vwv3
);
1258 uint32 smb_attr
= SVAL(inbuf
,smb_vwv5
);
1259 /* Breakout the oplock request bits so we can set the
1260 reply bits separately. */
1261 int ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1262 int core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1263 int oplock_request
= ex_oplock_request
| core_oplock_request
;
1265 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1266 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1268 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1271 SMB_STRUCT_STAT sbuf
;
1275 SMB_BIG_UINT allocation_size
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv9
);
1276 ssize_t retval
= -1;
1279 uint32 create_disposition
;
1280 uint32 create_options
= 0;
1282 START_PROFILE(SMBopenX
);
1284 /* If it's an IPC, pass off the pipe handler. */
1286 if (lp_nt_pipe_support()) {
1287 END_PROFILE(SMBopenX
);
1288 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1290 END_PROFILE(SMBopenX
);
1291 return ERROR_DOS(ERRSRV
,ERRaccess
);
1295 /* XXXX we need to handle passed times, sattr and flags */
1296 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
), sizeof(fname
), 0, STR_TERMINATE
, &status
);
1297 if (!NT_STATUS_IS_OK(status
)) {
1298 END_PROFILE(SMBopenX
);
1299 return ERROR_NT(status
);
1302 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1304 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
1305 if (!NT_STATUS_IS_OK(status
)) {
1306 END_PROFILE(SMBopenX
);
1307 return ERROR_NT(status
);
1310 if (!map_open_params_to_ntcreate(fname
, deny_mode
, smb_ofun
,
1313 &create_disposition
,
1315 END_PROFILE(SMBopenX
);
1316 return ERROR_NT(NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1319 status
= open_file_ntcreate(conn
,fname
,&sbuf
,
1328 if (!NT_STATUS_IS_OK(status
)) {
1329 END_PROFILE(SMBopenX
);
1330 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
1331 /* We have re-scheduled this call. */
1334 return ERROR_NT(status
);
1337 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1338 if the file is truncated or created. */
1339 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1340 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1341 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1342 close_file(fsp
,ERROR_CLOSE
);
1343 END_PROFILE(SMBopenX
);
1344 return ERROR_NT(NT_STATUS_DISK_FULL
);
1346 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1348 close_file(fsp
,ERROR_CLOSE
);
1349 END_PROFILE(SMBopenX
);
1350 return ERROR_NT(NT_STATUS_DISK_FULL
);
1352 sbuf
.st_size
= get_allocation_size(conn
,fsp
,&sbuf
);
1355 fattr
= dos_mode(conn
,fname
,&sbuf
);
1356 mtime
= sbuf
.st_mtime
;
1358 close_file(fsp
,ERROR_CLOSE
);
1359 END_PROFILE(SMBopenX
);
1360 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1363 /* If the caller set the extended oplock request bit
1364 and we granted one (by whatever means) - set the
1365 correct bit for extended oplock reply.
1368 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1369 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1372 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1373 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1376 /* If the caller set the core oplock request bit
1377 and we granted one (by whatever means) - set the
1378 correct bit for core oplock reply.
1381 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1382 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1385 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1386 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1389 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1390 set_message(outbuf
,19,0,True
);
1392 set_message(outbuf
,15,0,True
);
1394 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1395 SSVAL(outbuf
,smb_vwv3
,fattr
);
1396 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1397 srv_put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1399 srv_put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1401 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
1402 SSVAL(outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
1403 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1405 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1406 SIVAL(outbuf
, smb_vwv15
, STD_RIGHT_ALL_ACCESS
);
1409 END_PROFILE(SMBopenX
);
1410 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1413 /****************************************************************************
1414 Reply to a SMBulogoffX.
1415 conn POINTER CAN BE NULL HERE !
1416 ****************************************************************************/
1418 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1420 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1421 user_struct
*vuser
= get_valid_user_struct(vuid
);
1422 START_PROFILE(SMBulogoffX
);
1425 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1427 /* in user level security we are supposed to close any files
1428 open by this user */
1429 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
))
1430 file_close_user(vuid
);
1432 invalidate_vuid(vuid
);
1434 set_message(outbuf
,2,0,True
);
1436 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1438 END_PROFILE(SMBulogoffX
);
1439 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1442 /****************************************************************************
1443 Reply to a mknew or a create.
1444 ****************************************************************************/
1446 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1451 uint32 fattr
= SVAL(inbuf
,smb_vwv0
);
1452 struct utimbuf times
;
1454 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1455 SMB_STRUCT_STAT sbuf
;
1457 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
1458 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
1459 uint32 create_disposition
;
1460 uint32 create_options
= 0;
1462 START_PROFILE(SMBcreate
);
1464 com
= SVAL(inbuf
,smb_com
);
1466 times
.modtime
= srv_make_unix_date3(inbuf
+ smb_vwv1
);
1468 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
) + 1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1469 if (!NT_STATUS_IS_OK(status
)) {
1470 END_PROFILE(SMBcreate
);
1471 return ERROR_NT(status
);
1474 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1476 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
1477 if (!NT_STATUS_IS_OK(status
)) {
1478 END_PROFILE(SMBcreate
);
1479 return ERROR_NT(status
);
1482 if (fattr
& aVOLID
) {
1483 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1486 if(com
== SMBmknew
) {
1487 /* We should fail if file exists. */
1488 create_disposition
= FILE_CREATE
;
1490 /* Create if file doesn't exist, truncate if it does. */
1491 create_disposition
= FILE_OVERWRITE_IF
;
1494 /* Open file using ntcreate. */
1495 status
= open_file_ntcreate(conn
,fname
,&sbuf
,
1504 if (!NT_STATUS_IS_OK(status
)) {
1505 END_PROFILE(SMBcreate
);
1506 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
1507 /* We have re-scheduled this call. */
1510 return ERROR_NT(status
);
1513 times
.actime
= sbuf
.st_atime
;
1514 file_utime(conn
, fname
, ×
);
1516 outsize
= set_message(outbuf
,1,0,True
);
1517 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1519 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1520 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1523 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1524 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1527 DEBUG( 2, ( "reply_mknew: file %s\n", fname
) );
1528 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname
, fsp
->fh
->fd
, (unsigned int)fattr
) );
1530 END_PROFILE(SMBcreate
);
1534 /****************************************************************************
1535 Reply to a create temporary file.
1536 ****************************************************************************/
1538 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1542 uint32 fattr
= SVAL(inbuf
,smb_vwv0
);
1544 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1546 SMB_STRUCT_STAT sbuf
;
1549 unsigned int namelen
;
1551 START_PROFILE(SMBctemp
);
1553 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1554 if (!NT_STATUS_IS_OK(status
)) {
1555 END_PROFILE(SMBctemp
);
1556 return ERROR_NT(status
);
1559 pstrcat(fname
,"/TMXXXXXX");
1561 pstrcat(fname
,"TMXXXXXX");
1564 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1566 status
= unix_convert(conn
, fname
, False
, NULL
, &sbuf
);
1567 if (!NT_STATUS_IS_OK(status
)) {
1568 END_PROFILE(SMBctemp
);
1569 return ERROR_NT(status
);
1572 tmpfd
= smb_mkstemp(fname
);
1574 END_PROFILE(SMBctemp
);
1575 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1578 SMB_VFS_STAT(conn
,fname
,&sbuf
);
1580 /* We should fail if file does not exist. */
1581 status
= open_file_ntcreate(conn
,fname
,&sbuf
,
1582 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
,
1583 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1590 /* close fd from smb_mkstemp() */
1593 if (!NT_STATUS_IS_OK(status
)) {
1594 END_PROFILE(SMBctemp
);
1595 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
1596 /* We have re-scheduled this call. */
1599 return ERROR_NT(status
);
1602 outsize
= set_message(outbuf
,1,0,True
);
1603 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1605 /* the returned filename is relative to the directory */
1606 s
= strrchr_m(fname
, '/');
1613 p
= smb_buf(outbuf
);
1615 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1616 thing in the byte section. JRA */
1617 SSVALS(p
, 0, -1); /* what is this? not in spec */
1619 namelen
= srvstr_push(outbuf
, p
, s
, -1, STR_ASCII
|STR_TERMINATE
);
1621 outsize
= set_message_end(outbuf
, p
);
1623 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1624 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1627 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1628 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1631 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname
) );
1632 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname
, fsp
->fh
->fd
,
1633 (unsigned int)sbuf
.st_mode
) );
1635 END_PROFILE(SMBctemp
);
1639 /*******************************************************************
1640 Check if a user is allowed to rename a file.
1641 ********************************************************************/
1643 static NTSTATUS
can_rename(connection_struct
*conn
, char *fname
, uint16 dirtype
, SMB_STRUCT_STAT
*pst
)
1649 if (!CAN_WRITE(conn
)) {
1650 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1653 fmode
= dos_mode(conn
,fname
,pst
);
1654 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
)) {
1655 return NT_STATUS_NO_SUCH_FILE
;
1658 if (S_ISDIR(pst
->st_mode
)) {
1659 return NT_STATUS_OK
;
1662 status
= open_file_ntcreate(conn
, fname
, pst
,
1664 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1667 FILE_ATTRIBUTE_NORMAL
,
1671 if (!NT_STATUS_IS_OK(status
)) {
1674 close_file(fsp
,NORMAL_CLOSE
);
1675 return NT_STATUS_OK
;
1678 /*******************************************************************
1679 Check if a user is allowed to delete a file.
1680 ********************************************************************/
1682 static NTSTATUS
can_delete(connection_struct
*conn
, char *fname
,
1683 uint32 dirtype
, BOOL can_defer
)
1685 SMB_STRUCT_STAT sbuf
;
1688 uint32 dirtype_orig
= dirtype
;
1691 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname
, dirtype
));
1693 if (!CAN_WRITE(conn
)) {
1694 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1697 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
) != 0) {
1698 return map_nt_error_from_unix(errno
);
1701 fattr
= dos_mode(conn
,fname
,&sbuf
);
1703 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
1704 dirtype
= aDIR
|aARCH
|aRONLY
;
1707 dirtype
&= (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
);
1709 return NT_STATUS_NO_SUCH_FILE
;
1712 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
1714 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1716 return NT_STATUS_NO_SUCH_FILE
;
1719 if (dirtype_orig
& 0x8000) {
1720 /* These will never be set for POSIX. */
1721 return NT_STATUS_NO_SUCH_FILE
;
1725 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
1726 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1729 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
1730 return NT_STATUS_NO_SUCH_FILE
;
1733 if (dirtype
& 0xFF00) {
1734 /* These will never be set for POSIX. */
1735 return NT_STATUS_NO_SUCH_FILE
;
1740 return NT_STATUS_NO_SUCH_FILE
;
1743 /* Can't delete a directory. */
1745 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1750 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
1751 return NT_STATUS_OBJECT_NAME_INVALID
;
1752 #endif /* JRATEST */
1754 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1756 On a Windows share, a file with read-only dosmode can be opened with
1757 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1758 fails with NT_STATUS_CANNOT_DELETE error.
1760 This semantic causes a problem that a user can not
1761 rename a file with read-only dosmode on a Samba share
1762 from a Windows command prompt (i.e. cmd.exe, but can rename
1763 from Windows Explorer).
1766 if (!lp_delete_readonly(SNUM(conn
))) {
1767 if (fattr
& aRONLY
) {
1768 return NT_STATUS_CANNOT_DELETE
;
1772 /* On open checks the open itself will check the share mode, so
1773 don't do it here as we'll get it wrong. */
1775 status
= open_file_ntcreate(conn
, fname
, &sbuf
,
1780 FILE_ATTRIBUTE_NORMAL
,
1781 can_defer
? 0 : INTERNAL_OPEN_ONLY
,
1784 if (NT_STATUS_IS_OK(status
)) {
1785 close_file(fsp
,NORMAL_CLOSE
);
1790 /****************************************************************************
1791 The guts of the unlink command, split out so it may be called by the NT SMB
1793 ****************************************************************************/
1795 NTSTATUS
unlink_internals(connection_struct
*conn
, uint32 dirtype
,
1796 char *name
, BOOL has_wild
, BOOL can_defer
)
1802 NTSTATUS status
= NT_STATUS_OK
;
1803 SMB_STRUCT_STAT sbuf
;
1805 *directory
= *mask
= 0;
1807 status
= unix_convert(conn
, name
, has_wild
, NULL
, &sbuf
);
1808 if (!NT_STATUS_IS_OK(status
)) {
1812 p
= strrchr_m(name
,'/');
1814 pstrcpy(directory
,".");
1818 pstrcpy(directory
,name
);
1823 * We should only check the mangled cache
1824 * here if unix_convert failed. This means
1825 * that the path in 'mask' doesn't exist
1826 * on the file system and so we need to look
1827 * for a possible mangle. This patch from
1828 * Tine Smukavec <valentin.smukavec@hermes.si>.
1831 if (!VALID_STAT(sbuf
) && mangle_is_mangled(mask
,conn
->params
))
1832 mangle_check_cache( mask
, sizeof(pstring
)-1, conn
->params
);
1835 pstrcat(directory
,"/");
1836 pstrcat(directory
,mask
);
1838 dirtype
= FILE_ATTRIBUTE_NORMAL
;
1840 status
= can_delete(conn
,directory
,dirtype
,can_defer
);
1841 if (!NT_STATUS_IS_OK(status
))
1844 if (SMB_VFS_UNLINK(conn
,directory
) == 0) {
1848 struct smb_Dir
*dir_hnd
= NULL
;
1851 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == aDIR
) {
1852 return NT_STATUS_OBJECT_NAME_INVALID
;
1855 if (strequal(mask
,"????????.???"))
1858 if (check_name(directory
,conn
))
1859 dir_hnd
= OpenDir(conn
, directory
, mask
, dirtype
);
1861 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1862 the pattern matches against the long name, otherwise the short name
1863 We don't implement this yet XXXX
1868 status
= NT_STATUS_NO_SUCH_FILE
;
1870 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
1873 pstrcpy(fname
,dname
);
1875 if (!is_visible_file(conn
, directory
, dname
, &st
, True
)) {
1879 /* Quick check for "." and ".." */
1880 if (fname
[0] == '.') {
1881 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
1886 if(!mask_match(fname
, mask
, conn
->case_sensitive
))
1889 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1890 status
= can_delete(conn
, fname
, dirtype
,
1892 if (!NT_STATUS_IS_OK(status
)) {
1895 if (SMB_VFS_UNLINK(conn
,fname
) == 0)
1897 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
1903 if (count
== 0 && NT_STATUS_IS_OK(status
)) {
1904 status
= map_nt_error_from_unix(errno
);
1910 /****************************************************************************
1912 ****************************************************************************/
1914 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
1921 BOOL path_contains_wcard
= False
;
1923 START_PROFILE(SMBunlink
);
1925 dirtype
= SVAL(inbuf
,smb_vwv0
);
1927 srvstr_get_path_wcard(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
, &path_contains_wcard
);
1928 if (!NT_STATUS_IS_OK(status
)) {
1929 END_PROFILE(SMBunlink
);
1930 return ERROR_NT(status
);
1933 RESOLVE_DFSPATH_WCARD(name
, conn
, inbuf
, outbuf
);
1935 DEBUG(3,("reply_unlink : %s\n",name
));
1937 status
= unlink_internals(conn
, dirtype
, name
, path_contains_wcard
,
1939 if (!NT_STATUS_IS_OK(status
)) {
1940 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
1941 /* We have re-scheduled this call. */
1944 return ERROR_NT(status
);
1948 * Win2k needs a changenotify request response before it will
1949 * update after a rename..
1951 process_pending_change_notify_queue((time_t)0);
1953 outsize
= set_message(outbuf
,0,0,False
);
1955 END_PROFILE(SMBunlink
);
1959 /****************************************************************************
1961 ****************************************************************************/
1963 static void fail_readraw(void)
1966 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1968 exit_server_cleanly(errstr
);
1971 #if defined(WITH_SENDFILE)
1972 /****************************************************************************
1973 Fake (read/write) sendfile. Returns -1 on read or write fail.
1974 ****************************************************************************/
1976 static ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
, char *buf
, int bufsize
)
1980 /* Paranioa check... */
1981 if (nread
> bufsize
) {
1986 ret
= read_file(fsp
,buf
,startpos
,nread
);
1992 /* If we had a short read, fill with zeros. */
1994 memset(buf
, '\0', nread
- ret
);
1997 if (write_data(smbd_server_fd(),buf
,nread
) != nread
) {
2001 return (ssize_t
)nread
;
2005 /****************************************************************************
2006 Use sendfile in readbraw.
2007 ****************************************************************************/
2009 void send_file_readbraw(connection_struct
*conn
, files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
,
2010 ssize_t mincount
, char *outbuf
, int out_buffsize
)
2014 #if defined(WITH_SENDFILE)
2016 * We can only use sendfile on a non-chained packet
2017 * but we can use on a non-oplocked file. tridge proved this
2018 * on a train in Germany :-). JRA.
2019 * reply_readbraw has already checked the length.
2022 if ( (chain_size
== 0) && (nread
> 0) &&
2023 (fsp
->wcp
== NULL
) && lp_use_sendfile(SNUM(conn
)) ) {
2026 _smb_setlen(outbuf
,nread
);
2027 header
.data
= (uint8
*)outbuf
;
2031 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fh
->fd
, &header
, startpos
, nread
) == -1) {
2032 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2033 if (errno
== ENOSYS
) {
2034 goto normal_readbraw
;
2038 * Special hack for broken Linux with no working sendfile. If we
2039 * return EINTR we sent the header but not the rest of the data.
2040 * Fake this up by doing read/write calls.
2042 if (errno
== EINTR
) {
2043 /* Ensure we don't do this again. */
2044 set_use_sendfile(SNUM(conn
), False
);
2045 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2047 if (fake_sendfile(fsp
, startpos
, nread
, outbuf
+ 4, out_buffsize
- 4) == -1) {
2048 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2049 fsp
->fsp_name
, strerror(errno
) ));
2050 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2055 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2056 fsp
->fsp_name
, strerror(errno
) ));
2057 exit_server_cleanly("send_file_readbraw sendfile failed");
2067 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2068 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2077 _smb_setlen(outbuf
,ret
);
2078 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
2082 /****************************************************************************
2083 Reply to a readbraw (core+ protocol).
2084 ****************************************************************************/
2086 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int out_buffsize
)
2088 ssize_t maxcount
,mincount
;
2091 char *header
= outbuf
;
2093 START_PROFILE(SMBreadbraw
);
2095 if (srv_is_signing_active()) {
2096 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2100 * Special check if an oplock break has been issued
2101 * and the readraw request croses on the wire, we must
2102 * return a zero length response here.
2105 fsp
= file_fsp(inbuf
,smb_vwv0
);
2107 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
2109 * fsp could be NULL here so use the value from the packet. JRA.
2111 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
2112 _smb_setlen(header
,0);
2113 if (write_data(smbd_server_fd(),header
,4) != 4)
2115 END_PROFILE(SMBreadbraw
);
2119 CHECK_FSP(fsp
,conn
);
2121 flush_write_cache(fsp
, READRAW_FLUSH
);
2123 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
2124 if(CVAL(inbuf
,smb_wct
) == 10) {
2126 * This is a large offset (64 bit) read.
2128 #ifdef LARGE_SMB_OFF_T
2130 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
2132 #else /* !LARGE_SMB_OFF_T */
2135 * Ensure we haven't been sent a >32 bit offset.
2138 if(IVAL(inbuf
,smb_vwv8
) != 0) {
2139 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2140 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
2141 _smb_setlen(header
,0);
2142 if (write_data(smbd_server_fd(),header
,4) != 4)
2144 END_PROFILE(SMBreadbraw
);
2148 #endif /* LARGE_SMB_OFF_T */
2151 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
2152 _smb_setlen(header
,0);
2153 if (write_data(smbd_server_fd(),header
,4) != 4)
2155 END_PROFILE(SMBreadbraw
);
2159 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
2160 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
2162 /* ensure we don't overrun the packet size */
2163 maxcount
= MIN(65535,maxcount
);
2165 if (!is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
2169 if (SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
,&st
) == 0) {
2173 if (startpos
>= size
) {
2176 nread
= MIN(maxcount
,(size
- startpos
));
2180 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2181 if (nread
< mincount
)
2185 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp
->fnum
, (double)startpos
,
2186 (unsigned long)maxcount
, (unsigned long)mincount
, (unsigned long)nread
) );
2188 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
, outbuf
, out_buffsize
);
2190 DEBUG(5,("readbraw finished\n"));
2191 END_PROFILE(SMBreadbraw
);
2196 #define DBGC_CLASS DBGC_LOCKING
2198 /****************************************************************************
2199 Reply to a lockread (core+ protocol).
2200 ****************************************************************************/
2202 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
2210 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2211 struct byte_range_lock
*br_lck
= NULL
;
2212 START_PROFILE(SMBlockread
);
2214 CHECK_FSP(fsp
,conn
);
2215 if (!CHECK_READ(fsp
,inbuf
)) {
2216 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
2219 release_level_2_oplocks_on_change(fsp
);
2221 numtoread
= SVAL(inbuf
,smb_vwv1
);
2222 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2224 outsize
= set_message(outbuf
,5,3,True
);
2225 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2226 data
= smb_buf(outbuf
) + 3;
2229 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2230 * protocol request that predates the read/write lock concept.
2231 * Thus instead of asking for a read lock here we need to ask
2232 * for a write lock. JRA.
2233 * Note that the requested lock size is unaffected by max_recv.
2236 br_lck
= do_lock(fsp
,
2237 (uint32
)SVAL(inbuf
,smb_pid
),
2238 (SMB_BIG_UINT
)numtoread
,
2239 (SMB_BIG_UINT
)startpos
,
2242 False
, /* Non-blocking lock. */
2244 TALLOC_FREE(br_lck
);
2246 if (NT_STATUS_V(status
)) {
2247 END_PROFILE(SMBlockread
);
2248 return ERROR_NT(status
);
2252 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2255 if (numtoread
> max_recv
) {
2256 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2257 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2258 (unsigned int)numtoread
, (unsigned int)max_recv
));
2259 numtoread
= MIN(numtoread
,max_recv
);
2261 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2264 END_PROFILE(SMBlockread
);
2265 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2269 SSVAL(outbuf
,smb_vwv0
,nread
);
2270 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2271 SSVAL(smb_buf(outbuf
),1,nread
);
2273 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2274 fsp
->fnum
, (int)numtoread
, (int)nread
));
2276 END_PROFILE(SMBlockread
);
2281 #define DBGC_CLASS DBGC_ALL
2283 /****************************************************************************
2285 ****************************************************************************/
2287 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2294 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2295 START_PROFILE(SMBread
);
2297 CHECK_FSP(fsp
,conn
);
2298 if (!CHECK_READ(fsp
,inbuf
)) {
2299 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
2302 numtoread
= SVAL(inbuf
,smb_vwv1
);
2303 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2305 outsize
= set_message(outbuf
,5,3,True
);
2306 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2308 * The requested read size cannot be greater than max_recv. JRA.
2310 if (numtoread
> max_recv
) {
2311 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2312 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2313 (unsigned int)numtoread
, (unsigned int)max_recv
));
2314 numtoread
= MIN(numtoread
,max_recv
);
2317 data
= smb_buf(outbuf
) + 3;
2319 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
2320 END_PROFILE(SMBread
);
2321 return ERROR_DOS(ERRDOS
,ERRlock
);
2325 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2328 END_PROFILE(SMBread
);
2329 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2333 SSVAL(outbuf
,smb_vwv0
,nread
);
2334 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2335 SCVAL(smb_buf(outbuf
),0,1);
2336 SSVAL(smb_buf(outbuf
),1,nread
);
2338 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2339 fsp
->fnum
, (int)numtoread
, (int)nread
) );
2341 END_PROFILE(SMBread
);
2345 /****************************************************************************
2346 Reply to a read and X - possibly using sendfile.
2347 ****************************************************************************/
2349 int send_file_readX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
, int len_outbuf
,
2350 files_struct
*fsp
, SMB_OFF_T startpos
, size_t smb_maxcnt
)
2354 char *data
= smb_buf(outbuf
);
2356 #if defined(WITH_SENDFILE)
2358 * We can only use sendfile on a non-chained packet
2359 * but we can use on a non-oplocked file. tridge proved this
2360 * on a train in Germany :-). JRA.
2363 if ((chain_size
== 0) && (CVAL(inbuf
,smb_vwv0
) == 0xFF) &&
2364 lp_use_sendfile(SNUM(conn
)) && (fsp
->wcp
== NULL
) ) {
2365 SMB_STRUCT_STAT sbuf
;
2368 if(SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
, &sbuf
) == -1)
2369 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2371 if (startpos
> sbuf
.st_size
)
2374 if (smb_maxcnt
> (sbuf
.st_size
- startpos
))
2375 smb_maxcnt
= (sbuf
.st_size
- startpos
);
2377 if (smb_maxcnt
== 0)
2381 * Set up the packet header before send. We
2382 * assume here the sendfile will work (get the
2383 * correct amount of data).
2386 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2387 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
2388 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2389 SSVAL(outbuf
,smb_vwv7
,((smb_maxcnt
>> 16) & 1));
2390 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
2391 SCVAL(outbuf
,smb_vwv0
,0xFF);
2392 set_message(outbuf
,12,smb_maxcnt
,False
);
2393 header
.data
= (uint8
*)outbuf
;
2394 header
.length
= data
- outbuf
;
2397 if ((nread
= SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fh
->fd
, &header
, startpos
, smb_maxcnt
)) == -1) {
2398 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2399 if (errno
== ENOSYS
) {
2404 * Special hack for broken Linux with no working sendfile. If we
2405 * return EINTR we sent the header but not the rest of the data.
2406 * Fake this up by doing read/write calls.
2409 if (errno
== EINTR
) {
2410 /* Ensure we don't do this again. */
2411 set_use_sendfile(SNUM(conn
), False
);
2412 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2414 if ((nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
, data
,
2415 len_outbuf
- (data
-outbuf
))) == -1) {
2416 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2417 fsp
->fsp_name
, strerror(errno
) ));
2418 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2420 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2421 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2422 /* Returning -1 here means successful sendfile. */
2426 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2427 fsp
->fsp_name
, strerror(errno
) ));
2428 exit_server_cleanly("send_file_readX sendfile failed");
2431 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2432 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2433 /* Returning -1 here means successful sendfile. */
2441 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2444 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2447 outsize
= set_message(outbuf
,12,nread
,False
);
2448 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2449 SSVAL(outbuf
,smb_vwv5
,nread
);
2450 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2451 SSVAL(outbuf
,smb_vwv7
,((nread
>> 16) & 1));
2452 SSVAL(smb_buf(outbuf
),-2,nread
);
2454 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2455 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2457 /* Returning the number of bytes we want to send back - including header. */
2461 /****************************************************************************
2462 Reply to a read and X.
2463 ****************************************************************************/
2465 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2467 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2468 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2470 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2472 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2475 START_PROFILE(SMBreadX
);
2477 /* If it's an IPC, pass off the pipe handler. */
2479 END_PROFILE(SMBreadX
);
2480 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2483 CHECK_FSP(fsp
,conn
);
2484 if (!CHECK_READ(fsp
,inbuf
)) {
2485 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
2488 set_message(outbuf
,12,0,True
);
2490 if (global_client_caps
& CAP_LARGE_READX
) {
2491 if (SVAL(inbuf
,smb_vwv7
) == 1) {
2492 smb_maxcnt
|= (1<<16);
2494 if (smb_maxcnt
> BUFFER_SIZE
) {
2495 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2496 (unsigned int)smb_maxcnt
, (unsigned int)BUFFER_SIZE
));
2497 END_PROFILE(SMBreadX
);
2498 return ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
2502 if(CVAL(inbuf
,smb_wct
) == 12) {
2503 #ifdef LARGE_SMB_OFF_T
2505 * This is a large offset (64 bit) read.
2507 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2509 #else /* !LARGE_SMB_OFF_T */
2512 * Ensure we haven't been sent a >32 bit offset.
2515 if(IVAL(inbuf
,smb_vwv10
) != 0) {
2516 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2517 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
2518 END_PROFILE(SMBreadX
);
2519 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2522 #endif /* LARGE_SMB_OFF_T */
2526 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
2527 END_PROFILE(SMBreadX
);
2528 return ERROR_DOS(ERRDOS
,ERRlock
);
2531 if (schedule_aio_read_and_X(conn
, inbuf
, outbuf
, length
, bufsize
, fsp
, startpos
, smb_maxcnt
)) {
2532 END_PROFILE(SMBreadX
);
2536 nread
= send_file_readX(conn
, inbuf
, outbuf
, length
, bufsize
, fsp
, startpos
, smb_maxcnt
);
2538 nread
= chain_reply(inbuf
,outbuf
,length
,bufsize
);
2540 END_PROFILE(SMBreadX
);
2544 /****************************************************************************
2545 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2546 ****************************************************************************/
2548 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2551 ssize_t total_written
=0;
2552 size_t numtowrite
=0;
2557 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2559 START_PROFILE(SMBwritebraw
);
2561 if (srv_is_signing_active()) {
2562 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2565 CHECK_FSP(fsp
,conn
);
2566 if (!CHECK_WRITE(fsp
)) {
2567 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
2570 tcount
= IVAL(inbuf
,smb_vwv1
);
2571 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2572 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2574 /* We have to deal with slightly different formats depending
2575 on whether we are using the core+ or lanman1.0 protocol */
2577 if(Protocol
<= PROTOCOL_COREPLUS
) {
2578 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2579 data
= smb_buf(inbuf
);
2581 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2582 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2585 /* force the error type */
2586 SCVAL(inbuf
,smb_com
,SMBwritec
);
2587 SCVAL(outbuf
,smb_com
,SMBwritec
);
2589 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
2590 END_PROFILE(SMBwritebraw
);
2591 return(ERROR_DOS(ERRDOS
,ERRlock
));
2595 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2597 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2598 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2600 if (nwritten
< (ssize_t
)numtowrite
) {
2601 END_PROFILE(SMBwritebraw
);
2602 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2605 total_written
= nwritten
;
2607 /* Return a message to the redirector to tell it to send more bytes */
2608 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
2609 SSVALS(outbuf
,smb_vwv0
,-1);
2610 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2612 if (!send_smb(smbd_server_fd(),outbuf
))
2613 exit_server_cleanly("reply_writebraw: send_smb failed.");
2615 /* Now read the raw data into the buffer and write it */
2616 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2617 exit_server_cleanly("secondary writebraw failed");
2620 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2621 numtowrite
= smb_len(inbuf
);
2623 /* Set up outbuf to return the correct return */
2624 outsize
= set_message(outbuf
,1,0,True
);
2625 SCVAL(outbuf
,smb_com
,SMBwritec
);
2627 if (numtowrite
!= 0) {
2629 if (numtowrite
> BUFFER_SIZE
) {
2630 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2631 (unsigned int)numtowrite
));
2632 exit_server_cleanly("secondary writebraw failed");
2635 if (tcount
> nwritten
+numtowrite
) {
2636 DEBUG(3,("Client overestimated the write %d %d %d\n",
2637 (int)tcount
,(int)nwritten
,(int)numtowrite
));
2640 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
2641 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2643 exit_server_cleanly("secondary writebraw failed");
2646 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
2647 if (nwritten
== -1) {
2648 END_PROFILE(SMBwritebraw
);
2649 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2652 if (nwritten
< (ssize_t
)numtowrite
) {
2653 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2654 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2658 total_written
+= nwritten
;
2661 SSVAL(outbuf
,smb_vwv0
,total_written
);
2663 sync_file(conn
, fsp
, write_through
);
2665 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2666 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
2668 /* we won't return a status if write through is not selected - this follows what WfWg does */
2669 END_PROFILE(SMBwritebraw
);
2670 if (!write_through
&& total_written
==tcount
) {
2672 #if RABBIT_PELLET_FIX
2674 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2675 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2677 if (!send_keepalive(smbd_server_fd()))
2678 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2687 #define DBGC_CLASS DBGC_LOCKING
2689 /****************************************************************************
2690 Reply to a writeunlock (core+).
2691 ****************************************************************************/
2693 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
,
2694 int size
, int dum_buffsize
)
2696 ssize_t nwritten
= -1;
2700 NTSTATUS status
= NT_STATUS_OK
;
2701 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2703 START_PROFILE(SMBwriteunlock
);
2705 CHECK_FSP(fsp
,conn
);
2706 if (!CHECK_WRITE(fsp
)) {
2707 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
2710 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2711 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2712 data
= smb_buf(inbuf
) + 3;
2714 if (numtowrite
&& is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
2715 END_PROFILE(SMBwriteunlock
);
2716 return ERROR_DOS(ERRDOS
,ERRlock
);
2719 /* The special X/Open SMB protocol handling of
2720 zero length writes is *NOT* done for
2722 if(numtowrite
== 0) {
2725 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2728 sync_file(conn
, fsp
, False
/* write through */);
2730 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2731 END_PROFILE(SMBwriteunlock
);
2732 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2736 status
= do_unlock(fsp
,
2737 (uint32
)SVAL(inbuf
,smb_pid
),
2738 (SMB_BIG_UINT
)numtowrite
,
2739 (SMB_BIG_UINT
)startpos
,
2742 if (NT_STATUS_V(status
)) {
2743 END_PROFILE(SMBwriteunlock
);
2744 return ERROR_NT(status
);
2748 outsize
= set_message(outbuf
,1,0,True
);
2750 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2752 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2753 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2755 END_PROFILE(SMBwriteunlock
);
2760 #define DBGC_CLASS DBGC_ALL
2762 /****************************************************************************
2764 ****************************************************************************/
2766 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2769 ssize_t nwritten
= -1;
2772 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2774 START_PROFILE(SMBwrite
);
2776 /* If it's an IPC, pass off the pipe handler. */
2778 END_PROFILE(SMBwrite
);
2779 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2782 CHECK_FSP(fsp
,conn
);
2783 if (!CHECK_WRITE(fsp
)) {
2784 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
2787 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2788 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2789 data
= smb_buf(inbuf
) + 3;
2791 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
2792 END_PROFILE(SMBwrite
);
2793 return ERROR_DOS(ERRDOS
,ERRlock
);
2797 * X/Open SMB protocol says that if smb_vwv1 is
2798 * zero then the file size should be extended or
2799 * truncated to the size given in smb_vwv[2-3].
2802 if(numtowrite
== 0) {
2804 * This is actually an allocate call, and set EOF. JRA.
2806 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2808 END_PROFILE(SMBwrite
);
2809 return ERROR_NT(NT_STATUS_DISK_FULL
);
2811 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2813 END_PROFILE(SMBwrite
);
2814 return ERROR_NT(NT_STATUS_DISK_FULL
);
2817 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2819 sync_file(conn
, fsp
, False
);
2821 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2822 END_PROFILE(SMBwrite
);
2823 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2826 outsize
= set_message(outbuf
,1,0,True
);
2828 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2830 if (nwritten
< (ssize_t
)numtowrite
) {
2831 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2832 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2835 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2837 END_PROFILE(SMBwrite
);
2841 /****************************************************************************
2842 Reply to a write and X.
2843 ****************************************************************************/
2845 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2847 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2848 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2849 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2850 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2851 ssize_t nwritten
= -1;
2852 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2853 unsigned int smblen
= smb_len(inbuf
);
2855 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2856 START_PROFILE(SMBwriteX
);
2858 /* If it's an IPC, pass off the pipe handler. */
2860 END_PROFILE(SMBwriteX
);
2861 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2864 CHECK_FSP(fsp
,conn
);
2865 if (!CHECK_WRITE(fsp
)) {
2866 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
2869 set_message(outbuf
,6,0,True
);
2871 /* Deal with possible LARGE_WRITEX */
2873 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2876 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2877 END_PROFILE(SMBwriteX
);
2878 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2881 data
= smb_base(inbuf
) + smb_doff
;
2883 if(CVAL(inbuf
,smb_wct
) == 14) {
2884 #ifdef LARGE_SMB_OFF_T
2886 * This is a large offset (64 bit) write.
2888 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2890 #else /* !LARGE_SMB_OFF_T */
2893 * Ensure we haven't been sent a >32 bit offset.
2896 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2897 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2898 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2899 END_PROFILE(SMBwriteX
);
2900 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2903 #endif /* LARGE_SMB_OFF_T */
2906 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
2907 END_PROFILE(SMBwriteX
);
2908 return ERROR_DOS(ERRDOS
,ERRlock
);
2911 /* X/Open SMB protocol says that, unlike SMBwrite
2912 if the length is zero then NO truncation is
2913 done, just a write of zero. To truncate a file,
2916 if(numtowrite
== 0) {
2920 if (schedule_aio_write_and_X(conn
, inbuf
, outbuf
, length
, bufsize
,
2921 fsp
,data
,startpos
,numtowrite
)) {
2922 END_PROFILE(SMBwriteX
);
2926 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2929 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2930 END_PROFILE(SMBwriteX
);
2931 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2934 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2936 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2938 if (nwritten
< (ssize_t
)numtowrite
) {
2939 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2940 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2943 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2944 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2946 sync_file(conn
, fsp
, write_through
);
2948 END_PROFILE(SMBwriteX
);
2949 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2952 /****************************************************************************
2954 ****************************************************************************/
2956 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2962 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2963 START_PROFILE(SMBlseek
);
2965 CHECK_FSP(fsp
,conn
);
2967 flush_write_cache(fsp
, SEEK_FLUSH
);
2969 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2970 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2971 startpos
= (SMB_OFF_T
)IVALS(inbuf
,smb_vwv2
);
2980 res
= fsp
->fh
->pos
+ startpos
;
2991 if (umode
== SEEK_END
) {
2992 if((res
= SMB_VFS_LSEEK(fsp
,fsp
->fh
->fd
,startpos
,umode
)) == -1) {
2993 if(errno
== EINVAL
) {
2994 SMB_OFF_T current_pos
= startpos
;
2995 SMB_STRUCT_STAT sbuf
;
2997 if(SMB_VFS_FSTAT(fsp
,fsp
->fh
->fd
, &sbuf
) == -1) {
2998 END_PROFILE(SMBlseek
);
2999 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3002 current_pos
+= sbuf
.st_size
;
3004 res
= SMB_VFS_LSEEK(fsp
,fsp
->fh
->fd
,0,SEEK_SET
);
3009 END_PROFILE(SMBlseek
);
3010 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3016 outsize
= set_message(outbuf
,2,0,True
);
3017 SIVAL(outbuf
,smb_vwv0
,res
);
3019 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3020 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
3022 END_PROFILE(SMBlseek
);
3026 /****************************************************************************
3028 ****************************************************************************/
3030 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
3032 int outsize
= set_message(outbuf
,0,0,False
);
3033 uint16 fnum
= SVAL(inbuf
,smb_vwv0
);
3034 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3035 START_PROFILE(SMBflush
);
3038 CHECK_FSP(fsp
,conn
);
3041 file_sync_all(conn
);
3043 sync_file(conn
,fsp
, True
);
3046 DEBUG(3,("flush\n"));
3047 END_PROFILE(SMBflush
);
3051 /****************************************************************************
3053 conn POINTER CAN BE NULL HERE !
3054 ****************************************************************************/
3056 int reply_exit(connection_struct
*conn
,
3057 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3060 START_PROFILE(SMBexit
);
3062 file_close_pid(SVAL(inbuf
,smb_pid
),SVAL(inbuf
,smb_uid
));
3064 outsize
= set_message(outbuf
,0,0,False
);
3066 DEBUG(3,("exit\n"));
3068 END_PROFILE(SMBexit
);
3072 /****************************************************************************
3073 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3074 ****************************************************************************/
3076 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
3081 int32 eclass
= 0, err
= 0;
3082 files_struct
*fsp
= NULL
;
3083 START_PROFILE(SMBclose
);
3085 outsize
= set_message(outbuf
,0,0,False
);
3087 /* If it's an IPC, pass off to the pipe handler. */
3089 END_PROFILE(SMBclose
);
3090 return reply_pipe_close(conn
, inbuf
,outbuf
);
3093 fsp
= file_fsp(inbuf
,smb_vwv0
);
3096 * We can only use CHECK_FSP if we know it's not a directory.
3099 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= current_user
.vuid
)) {
3100 END_PROFILE(SMBclose
);
3101 return ERROR_DOS(ERRDOS
,ERRbadfid
);
3104 if(fsp
->is_directory
) {
3106 * Special case - close NT SMB directory handle.
3108 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
3109 close_file(fsp
,NORMAL_CLOSE
);
3112 * Close ordinary file.
3116 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3117 fsp
->fh
->fd
, fsp
->fnum
,
3118 conn
->num_files_open
));
3121 * Take care of any time sent in the close.
3124 mtime
= srv_make_unix_date3(inbuf
+smb_vwv1
);
3125 fsp_set_pending_modtime(fsp
, mtime
);
3128 * close_file() returns the unix errno if an error
3129 * was detected on close - normally this is due to
3130 * a disk full error. If not then it was probably an I/O error.
3133 if((close_err
= close_file(fsp
,NORMAL_CLOSE
)) != 0) {
3135 END_PROFILE(SMBclose
);
3136 return (UNIXERROR(ERRHRD
,ERRgeneral
));
3140 /* We have a cached error */
3142 END_PROFILE(SMBclose
);
3143 return ERROR_DOS(eclass
,err
);
3146 END_PROFILE(SMBclose
);
3150 /****************************************************************************
3151 Reply to a writeclose (Core+ protocol).
3152 ****************************************************************************/
3154 int reply_writeclose(connection_struct
*conn
,
3155 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
3158 ssize_t nwritten
= -1;
3164 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3165 START_PROFILE(SMBwriteclose
);
3167 CHECK_FSP(fsp
,conn
);
3168 if (!CHECK_WRITE(fsp
)) {
3169 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
3172 numtowrite
= SVAL(inbuf
,smb_vwv1
);
3173 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
3174 mtime
= srv_make_unix_date3(inbuf
+smb_vwv4
);
3175 data
= smb_buf(inbuf
) + 1;
3177 if (numtowrite
&& is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
3178 END_PROFILE(SMBwriteclose
);
3179 return ERROR_DOS(ERRDOS
,ERRlock
);
3182 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
3184 set_filetime(conn
, fsp
->fsp_name
,mtime
);
3187 * More insanity. W2K only closes the file if writelen > 0.
3192 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3194 close_err
= close_file(fsp
,NORMAL_CLOSE
);
3197 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3198 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
3199 conn
->num_files_open
));
3201 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
3202 END_PROFILE(SMBwriteclose
);
3203 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3206 if(close_err
!= 0) {
3208 END_PROFILE(SMBwriteclose
);
3209 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3212 outsize
= set_message(outbuf
,1,0,True
);
3214 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3215 END_PROFILE(SMBwriteclose
);
3220 #define DBGC_CLASS DBGC_LOCKING
3222 /****************************************************************************
3224 ****************************************************************************/
3226 int reply_lock(connection_struct
*conn
,
3227 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
3229 int outsize
= set_message(outbuf
,0,0,False
);
3230 SMB_BIG_UINT count
,offset
;
3232 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3233 struct byte_range_lock
*br_lck
= NULL
;
3235 START_PROFILE(SMBlock
);
3237 CHECK_FSP(fsp
,conn
);
3239 release_level_2_oplocks_on_change(fsp
);
3241 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
3242 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
3244 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3245 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
3247 br_lck
= do_lock(fsp
,
3248 (uint32
)SVAL(inbuf
,smb_pid
),
3253 False
, /* Non-blocking lock. */
3256 TALLOC_FREE(br_lck
);
3258 if (NT_STATUS_V(status
)) {
3259 END_PROFILE(SMBlock
);
3260 return ERROR_NT(status
);
3263 END_PROFILE(SMBlock
);
3267 /****************************************************************************
3269 ****************************************************************************/
3271 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
3274 int outsize
= set_message(outbuf
,0,0,False
);
3275 SMB_BIG_UINT count
,offset
;
3277 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3278 START_PROFILE(SMBunlock
);
3280 CHECK_FSP(fsp
,conn
);
3282 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
3283 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
3285 status
= do_unlock(fsp
,
3286 (uint32
)SVAL(inbuf
,smb_pid
),
3291 if (NT_STATUS_V(status
)) {
3292 END_PROFILE(SMBunlock
);
3293 return ERROR_NT(status
);
3296 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3297 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
3299 END_PROFILE(SMBunlock
);
3304 #define DBGC_CLASS DBGC_ALL
3306 /****************************************************************************
3308 conn POINTER CAN BE NULL HERE !
3309 ****************************************************************************/
3311 int reply_tdis(connection_struct
*conn
,
3312 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3314 int outsize
= set_message(outbuf
,0,0,False
);
3316 START_PROFILE(SMBtdis
);
3318 vuid
= SVAL(inbuf
,smb_uid
);
3321 DEBUG(4,("Invalid connection in tdis\n"));
3322 END_PROFILE(SMBtdis
);
3323 return ERROR_DOS(ERRSRV
,ERRinvnid
);
3328 close_cnum(conn
,vuid
);
3330 END_PROFILE(SMBtdis
);
3334 /****************************************************************************
3336 conn POINTER CAN BE NULL HERE !
3337 ****************************************************************************/
3339 int reply_echo(connection_struct
*conn
,
3340 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3342 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
3344 unsigned int data_len
= smb_buflen(inbuf
);
3345 int outsize
= set_message(outbuf
,1,data_len
,True
);
3346 START_PROFILE(SMBecho
);
3348 if (data_len
> BUFFER_SIZE
) {
3349 DEBUG(0,("reply_echo: data_len too large.\n"));
3350 END_PROFILE(SMBecho
);
3354 /* copy any incoming data back out */
3356 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
3358 if (smb_reverb
> 100) {
3359 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
3363 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
3364 SSVAL(outbuf
,smb_vwv0
,seq_num
);
3366 smb_setlen(outbuf
,outsize
- 4);
3369 if (!send_smb(smbd_server_fd(),outbuf
))
3370 exit_server_cleanly("reply_echo: send_smb failed.");
3373 DEBUG(3,("echo %d times\n", smb_reverb
));
3377 END_PROFILE(SMBecho
);
3381 /****************************************************************************
3382 Reply to a printopen.
3383 ****************************************************************************/
3385 int reply_printopen(connection_struct
*conn
,
3386 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3392 START_PROFILE(SMBsplopen
);
3394 if (!CAN_PRINT(conn
)) {
3395 END_PROFILE(SMBsplopen
);
3396 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3399 /* Open for exclusive use, write only. */
3400 status
= print_fsp_open(conn
, NULL
, &fsp
);
3402 if (!NT_STATUS_IS_OK(status
)) {
3403 END_PROFILE(SMBsplopen
);
3404 return(ERROR_NT(status
));
3407 outsize
= set_message(outbuf
,1,0,True
);
3408 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
3410 DEBUG(3,("openprint fd=%d fnum=%d\n",
3411 fsp
->fh
->fd
, fsp
->fnum
));
3413 END_PROFILE(SMBsplopen
);
3417 /****************************************************************************
3418 Reply to a printclose.
3419 ****************************************************************************/
3421 int reply_printclose(connection_struct
*conn
,
3422 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3424 int outsize
= set_message(outbuf
,0,0,False
);
3425 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3427 START_PROFILE(SMBsplclose
);
3429 CHECK_FSP(fsp
,conn
);
3431 if (!CAN_PRINT(conn
)) {
3432 END_PROFILE(SMBsplclose
);
3433 return ERROR_NT(NT_STATUS_DOS(ERRSRV
, ERRerror
));
3436 DEBUG(3,("printclose fd=%d fnum=%d\n",
3437 fsp
->fh
->fd
,fsp
->fnum
));
3439 close_err
= close_file(fsp
,NORMAL_CLOSE
);
3441 if(close_err
!= 0) {
3443 END_PROFILE(SMBsplclose
);
3444 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3447 END_PROFILE(SMBsplclose
);
3451 /****************************************************************************
3452 Reply to a printqueue.
3453 ****************************************************************************/
3455 int reply_printqueue(connection_struct
*conn
,
3456 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3458 int outsize
= set_message(outbuf
,2,3,True
);
3459 int max_count
= SVAL(inbuf
,smb_vwv0
);
3460 int start_index
= SVAL(inbuf
,smb_vwv1
);
3461 START_PROFILE(SMBsplretq
);
3463 /* we used to allow the client to get the cnum wrong, but that
3464 is really quite gross and only worked when there was only
3465 one printer - I think we should now only accept it if they
3466 get it right (tridge) */
3467 if (!CAN_PRINT(conn
)) {
3468 END_PROFILE(SMBsplretq
);
3469 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3472 SSVAL(outbuf
,smb_vwv0
,0);
3473 SSVAL(outbuf
,smb_vwv1
,0);
3474 SCVAL(smb_buf(outbuf
),0,1);
3475 SSVAL(smb_buf(outbuf
),1,0);
3477 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3478 start_index
, max_count
));
3481 print_queue_struct
*queue
= NULL
;
3482 print_status_struct status
;
3483 char *p
= smb_buf(outbuf
) + 3;
3484 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
3485 int num_to_get
= ABS(max_count
);
3486 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
3492 num_to_get
= MIN(num_to_get
,count
-first
);
3495 for (i
=first
;i
<first
+num_to_get
;i
++) {
3496 srv_put_dos_date2(p
,0,queue
[i
].time
);
3497 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
3498 SSVAL(p
,5, queue
[i
].job
);
3499 SIVAL(p
,7,queue
[i
].size
);
3501 srvstr_push(outbuf
, p
+12, queue
[i
].fs_user
, 16, STR_ASCII
);
3506 outsize
= set_message(outbuf
,2,28*count
+3,False
);
3507 SSVAL(outbuf
,smb_vwv0
,count
);
3508 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
3509 SCVAL(smb_buf(outbuf
),0,1);
3510 SSVAL(smb_buf(outbuf
),1,28*count
);
3515 DEBUG(3,("%d entries returned in queue\n",count
));
3518 END_PROFILE(SMBsplretq
);
3522 /****************************************************************************
3523 Reply to a printwrite.
3524 ****************************************************************************/
3526 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3529 int outsize
= set_message(outbuf
,0,0,False
);
3531 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3533 START_PROFILE(SMBsplwr
);
3535 if (!CAN_PRINT(conn
)) {
3536 END_PROFILE(SMBsplwr
);
3537 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3540 CHECK_FSP(fsp
,conn
);
3541 if (!CHECK_WRITE(fsp
)) {
3542 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
3545 numtowrite
= SVAL(smb_buf(inbuf
),1);
3546 data
= smb_buf(inbuf
) + 3;
3548 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
3549 END_PROFILE(SMBsplwr
);
3550 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3553 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
3555 END_PROFILE(SMBsplwr
);
3559 /****************************************************************************
3561 ****************************************************************************/
3563 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3568 SMB_STRUCT_STAT sbuf
;
3570 START_PROFILE(SMBmkdir
);
3572 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3573 if (!NT_STATUS_IS_OK(status
)) {
3574 END_PROFILE(SMBmkdir
);
3575 return ERROR_NT(status
);
3578 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
);
3580 status
= unix_convert(conn
, directory
, False
, NULL
, &sbuf
);
3581 if (!NT_STATUS_IS_OK(status
)) {
3582 END_PROFILE(SMBmkdir
);
3583 return ERROR_NT(status
);
3586 status
= create_directory(conn
, directory
);
3588 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
3590 if (!NT_STATUS_IS_OK(status
)) {
3592 if (!use_nt_status()
3593 && NT_STATUS_EQUAL(status
,
3594 NT_STATUS_OBJECT_NAME_COLLISION
)) {
3596 * Yes, in the DOS error code case we get a
3597 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3598 * samba4 torture test.
3600 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
3603 END_PROFILE(SMBmkdir
);
3604 return ERROR_NT(status
);
3607 outsize
= set_message(outbuf
,0,0,False
);
3609 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
3611 END_PROFILE(SMBmkdir
);
3615 /****************************************************************************
3616 Static function used by reply_rmdir to delete an entire directory
3617 tree recursively. Return True on ok, False on fail.
3618 ****************************************************************************/
3620 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
3622 const char *dname
= NULL
;
3625 struct smb_Dir
*dir_hnd
= OpenDir(conn
, directory
, NULL
, 0);
3630 while((dname
= ReadDirName(dir_hnd
, &offset
))) {
3634 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3637 if (!is_visible_file(conn
, directory
, dname
, &st
, False
))
3640 /* Construct the full name. */
3641 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3647 pstrcpy(fullname
, directory
);
3648 pstrcat(fullname
, "/");
3649 pstrcat(fullname
, dname
);
3651 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
3656 if(st
.st_mode
& S_IFDIR
) {
3657 if(!recursive_rmdir(conn
, fullname
)) {
3661 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
3665 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
3674 /****************************************************************************
3675 The internals of the rmdir code - called elsewhere.
3676 ****************************************************************************/
3678 BOOL
rmdir_internals(connection_struct
*conn
, const char *directory
)
3683 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3684 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
3686 * Check to see if the only thing in this directory are
3687 * vetoed files/directories. If so then delete them and
3688 * retry. If we fail to delete any of them (and we *don't*
3689 * do a recursive delete) then fail the rmdir.
3693 struct smb_Dir
*dir_hnd
= OpenDir(conn
, directory
, NULL
, 0);
3695 if(dir_hnd
== NULL
) {
3700 while ((dname
= ReadDirName(dir_hnd
,&dirpos
))) {
3701 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3703 if (!is_visible_file(conn
, directory
, dname
, &st
, False
))
3705 if(!IS_VETO_PATH(conn
, dname
)) {
3712 /* We only have veto files/directories. Recursive delete. */
3714 RewindDir(dir_hnd
,&dirpos
);
3715 while ((dname
= ReadDirName(dir_hnd
,&dirpos
))) {
3718 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3720 if (!is_visible_file(conn
, directory
, dname
, &st
, False
))
3723 /* Construct the full name. */
3724 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3729 pstrcpy(fullname
, directory
);
3730 pstrcat(fullname
, "/");
3731 pstrcat(fullname
, dname
);
3733 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0)
3735 if(st
.st_mode
& S_IFDIR
) {
3736 if(lp_recursive_veto_delete(SNUM(conn
))) {
3737 if(!recursive_rmdir(conn
, fullname
))
3740 if(SMB_VFS_RMDIR(conn
,fullname
) != 0)
3742 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0)
3746 /* Retry the rmdir */
3747 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3753 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
3754 "%s\n", directory
,strerror(errno
)));
3761 /****************************************************************************
3763 ****************************************************************************/
3765 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3770 SMB_STRUCT_STAT sbuf
;
3772 START_PROFILE(SMBrmdir
);
3774 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3775 if (!NT_STATUS_IS_OK(status
)) {
3776 END_PROFILE(SMBrmdir
);
3777 return ERROR_NT(status
);
3780 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3782 status
= unix_convert(conn
, directory
, False
, NULL
, &sbuf
);
3783 if (!NT_STATUS_IS_OK(status
)) {
3784 END_PROFILE(SMBrmdir
);
3785 return ERROR_NT(status
);
3788 if (check_name(directory
,conn
)) {
3789 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3790 ok
= rmdir_internals(conn
, directory
);
3794 END_PROFILE(SMBrmdir
);
3795 return UNIXERROR(ERRDOS
, ERRbadpath
);
3798 outsize
= set_message(outbuf
,0,0,False
);
3800 DEBUG( 3, ( "rmdir %s\n", directory
) );
3802 END_PROFILE(SMBrmdir
);
3806 /*******************************************************************
3807 Resolve wildcards in a filename rename.
3808 Note that name is in UNIX charset and thus potentially can be more
3809 than fstring buffer (255 bytes) especially in default UTF-8 case.
3810 Therefore, we use pstring inside and all calls should ensure that
3811 name2 is at least pstring-long (they do already)
3812 ********************************************************************/
3814 static BOOL
resolve_wildcards(const char *name1
, char *name2
)
3816 pstring root1
,root2
;
3818 char *p
,*p2
, *pname1
, *pname2
;
3819 int available_space
, actual_space
;
3822 pname1
= strrchr_m(name1
,'/');
3823 pname2
= strrchr_m(name2
,'/');
3825 if (!pname1
|| !pname2
)
3828 pstrcpy(root1
,pname1
);
3829 pstrcpy(root2
,pname2
);
3830 p
= strrchr_m(root1
,'.');
3837 p
= strrchr_m(root2
,'.');
3851 } else if (*p2
== '*') {
3867 } else if (*p2
== '*') {
3877 available_space
= sizeof(pstring
) - PTR_DIFF(pname2
, name2
);
3880 actual_space
= snprintf(pname2
, available_space
- 1, "%s.%s", root2
, ext2
);
3881 if (actual_space
>= available_space
- 1) {
3882 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3883 actual_space
- available_space
));
3886 pstrcpy_base(pname2
, root2
, name2
);
3892 /****************************************************************************
3893 Ensure open files have their names updated. Updated to notify other smbd's
3895 ****************************************************************************/
3897 static void rename_open_files(connection_struct
*conn
, struct share_mode_lock
*lck
,
3898 SMB_DEV_T dev
, SMB_INO_T inode
, const char *newname
)
3901 BOOL did_rename
= False
;
3903 for(fsp
= file_find_di_first(dev
, inode
); fsp
; fsp
= file_find_di_next(fsp
)) {
3904 /* fsp_name is a relative path under the fsp. To change this for other
3905 sharepaths we need to manipulate relative paths. */
3906 /* TODO - create the absolute path and manipulate the newname
3907 relative to the sharepath. */
3908 if (fsp
->conn
!= conn
) {
3911 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3912 fsp
->fnum
, (unsigned int)fsp
->dev
, (double)fsp
->inode
,
3913 fsp
->fsp_name
, newname
));
3914 string_set(&fsp
->fsp_name
, newname
);
3919 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3920 (unsigned int)dev
, (double)inode
, newname
));
3923 /* Send messages to all smbd's (not ourself) that the name has changed. */
3924 rename_share_filename(lck
, conn
->connectpath
, newname
);
3927 /****************************************************************************
3928 We need to check if the source path is a parent directory of the destination
3929 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
3930 refuse the rename with a sharing violation. Under UNIX the above call can
3931 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
3932 probably need to check that the client is a Windows one before disallowing
3933 this as a UNIX client (one with UNIX extensions) can know the source is a
3934 symlink and make this decision intelligently. Found by an excellent bug
3935 report from <AndyLiebman@aol.com>.
3936 ****************************************************************************/
3938 static BOOL
rename_path_prefix_equal(const char *src
, const char *dest
)
3940 const char *psrc
= src
;
3941 const char *pdst
= dest
;
3944 if (psrc
[0] == '.' && psrc
[1] == '/') {
3947 if (pdst
[0] == '.' && pdst
[1] == '/') {
3950 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
3953 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
3956 /****************************************************************************
3957 Rename an open file - given an fsp.
3958 ****************************************************************************/
3960 NTSTATUS
rename_internals_fsp(connection_struct
*conn
, files_struct
*fsp
, char *newname
, uint32 attrs
, BOOL replace_if_exists
)
3962 SMB_STRUCT_STAT sbuf
;
3963 pstring newname_last_component
;
3964 NTSTATUS status
= NT_STATUS_OK
;
3966 struct share_mode_lock
*lck
= NULL
;
3970 status
= unix_convert(conn
, newname
, False
, newname_last_component
, &sbuf
);
3971 if (!NT_STATUS_IS_OK(status
)) {
3975 /* Ensure newname contains a '/' */
3976 if(strrchr_m(newname
,'/') == 0) {
3979 pstrcpy(tmpstr
, "./");
3980 pstrcat(tmpstr
, newname
);
3981 pstrcpy(newname
, tmpstr
);
3985 * Check for special case with case preserving and not
3986 * case sensitive. If the old last component differs from the original
3987 * last component only by case, then we should allow
3988 * the rename (user is trying to change the case of the
3992 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
3993 strequal(newname
, fsp
->fsp_name
)) {
3995 pstring newname_modified_last_component
;
3998 * Get the last component of the modified name.
3999 * Note that we guarantee that newname contains a '/'
4002 p
= strrchr_m(newname
,'/');
4003 pstrcpy(newname_modified_last_component
,p
+1);
4005 if(strcsequal(newname_modified_last_component
,
4006 newname_last_component
) == False
) {
4008 * Replace the modified last component with
4011 pstrcpy(p
+1, newname_last_component
);
4016 * If the src and dest names are identical - including case,
4017 * don't do the rename, just return success.
4020 if (strcsequal(fsp
->fsp_name
, newname
)) {
4021 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4023 return NT_STATUS_OK
;
4026 dest_exists
= vfs_object_exist(conn
,newname
,NULL
);
4028 if(!replace_if_exists
&& dest_exists
) {
4029 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4030 fsp
->fsp_name
,newname
));
4031 return NT_STATUS_OBJECT_NAME_COLLISION
;
4034 status
= can_rename(conn
,newname
,attrs
,&sbuf
);
4036 if (dest_exists
&& !NT_STATUS_IS_OK(status
)) {
4037 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4038 nt_errstr(status
), fsp
->fsp_name
,newname
));
4039 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
4040 status
= NT_STATUS_ACCESS_DENIED
;
4044 if (rename_path_prefix_equal(fsp
->fsp_name
, newname
)) {
4045 return NT_STATUS_ACCESS_DENIED
;
4048 lck
= get_share_mode_lock(NULL
, fsp
->dev
, fsp
->inode
, NULL
, NULL
);
4050 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
4051 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4052 fsp
->fsp_name
,newname
));
4053 rename_open_files(conn
, lck
, fsp
->dev
, fsp
->inode
, newname
);
4055 return NT_STATUS_OK
;
4060 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
4061 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
4063 status
= map_nt_error_from_unix(errno
);
4066 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4067 nt_errstr(status
), fsp
->fsp_name
,newname
));
4072 /****************************************************************************
4073 The guts of the rename command, split out so it may be called by the NT SMB
4075 ****************************************************************************/
4077 NTSTATUS
rename_internals(connection_struct
*conn
, char *name
, char *newname
, uint32 attrs
, BOOL replace_if_exists
, BOOL has_wild
)
4081 pstring last_component_src
;
4082 pstring last_component_dest
;
4085 NTSTATUS status
= NT_STATUS_OK
;
4086 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4087 struct share_mode_lock
*lck
= NULL
;
4089 *directory
= *mask
= 0;
4094 status
= unix_convert(conn
, name
, has_wild
, last_component_src
, &sbuf1
);
4095 if (!NT_STATUS_IS_OK(status
)) {
4099 status
= unix_convert(conn
, newname
, True
, last_component_dest
, &sbuf2
);
4100 if (!NT_STATUS_IS_OK(status
)) {
4105 * Split the old name into directory and last component
4106 * strings. Note that unix_convert may have stripped off a
4107 * leading ./ from both name and newname if the rename is
4108 * at the root of the share. We need to make sure either both
4109 * name and newname contain a / character or neither of them do
4110 * as this is checked in resolve_wildcards().
4113 p
= strrchr_m(name
,'/');
4115 pstrcpy(directory
,".");
4119 pstrcpy(directory
,name
);
4121 *p
= '/'; /* Replace needed for exceptional test below. */
4125 * We should only check the mangled cache
4126 * here if unix_convert failed. This means
4127 * that the path in 'mask' doesn't exist
4128 * on the file system and so we need to look
4129 * for a possible mangle. This patch from
4130 * Tine Smukavec <valentin.smukavec@hermes.si>.
4133 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
))
4134 mangle_check_cache( mask
, sizeof(pstring
)-1, conn
->params
);
4138 * No wildcards - just process the one file.
4140 BOOL is_short_name
= mangle_is_8_3(name
, True
, conn
->params
);
4142 /* Add a terminating '/' to the directory name. */
4143 pstrcat(directory
,"/");
4144 pstrcat(directory
,mask
);
4146 /* Ensure newname contains a '/' also */
4147 if(strrchr_m(newname
,'/') == 0) {
4150 pstrcpy(tmpstr
, "./");
4151 pstrcat(tmpstr
, newname
);
4152 pstrcpy(newname
, tmpstr
);
4155 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4156 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4157 conn
->case_sensitive
, conn
->case_preserve
, conn
->short_case_preserve
, directory
,
4158 newname
, last_component_dest
, is_short_name
));
4161 * Check for special case with case preserving and not
4162 * case sensitive, if directory and newname are identical,
4163 * and the old last component differs from the original
4164 * last component only by case, then we should allow
4165 * the rename (user is trying to change the case of the
4168 if((conn
->case_sensitive
== False
) &&
4169 (((conn
->case_preserve
== True
) &&
4170 (is_short_name
== False
)) ||
4171 ((conn
->short_case_preserve
== True
) &&
4172 (is_short_name
== True
))) &&
4173 strcsequal(directory
, newname
)) {
4174 pstring modified_last_component
;
4177 * Get the last component of the modified name.
4178 * Note that we guarantee that newname contains a '/'
4181 p
= strrchr_m(newname
,'/');
4182 pstrcpy(modified_last_component
,p
+1);
4184 if(strcsequal(modified_last_component
,
4185 last_component_dest
) == False
) {
4187 * Replace the modified last component with
4190 pstrcpy(p
+1, last_component_dest
);
4194 resolve_wildcards(directory
,newname
);
4197 * The source object must exist.
4200 if (!vfs_object_exist(conn
, directory
, &sbuf1
)) {
4201 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4202 directory
,newname
));
4204 if (errno
== ENOTDIR
|| errno
== EISDIR
|| errno
== ENOENT
) {
4206 * Must return different errors depending on whether the parent
4207 * directory existed or not.
4210 p
= strrchr_m(directory
, '/');
4212 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4214 if (vfs_object_exist(conn
, directory
, NULL
))
4215 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4216 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
4218 status
= map_nt_error_from_unix(errno
);
4219 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4220 nt_errstr(status
), directory
,newname
));
4225 status
= can_rename(conn
,directory
,attrs
,&sbuf1
);
4227 if (!NT_STATUS_IS_OK(status
)) {
4228 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4229 nt_errstr(status
), directory
,newname
));
4234 * If the src and dest names are identical - including case,
4235 * don't do the rename, just return success.
4238 if (strcsequal(directory
, newname
)) {
4239 rename_open_files(conn
, NULL
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
4240 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory
));
4241 return NT_STATUS_OK
;
4244 if(!replace_if_exists
&& vfs_object_exist(conn
,newname
,NULL
)) {
4245 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4246 directory
,newname
));
4247 return NT_STATUS_OBJECT_NAME_COLLISION
;
4250 if (rename_path_prefix_equal(directory
, newname
)) {
4251 return NT_STATUS_SHARING_VIOLATION
;
4254 lck
= get_share_mode_lock(NULL
, sbuf1
.st_dev
, sbuf1
.st_ino
, NULL
, NULL
);
4256 if(SMB_VFS_RENAME(conn
,directory
, newname
) == 0) {
4257 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4258 directory
,newname
));
4259 rename_open_files(conn
, lck
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
4261 return NT_STATUS_OK
;
4265 if (errno
== ENOTDIR
|| errno
== EISDIR
)
4266 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
4268 status
= map_nt_error_from_unix(errno
);
4270 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4271 nt_errstr(status
), directory
,newname
));
4276 * Wildcards - process each file that matches.
4278 struct smb_Dir
*dir_hnd
= NULL
;
4282 if (strequal(mask
,"????????.???"))
4285 if (check_name(directory
,conn
))
4286 dir_hnd
= OpenDir(conn
, directory
, mask
, attrs
);
4290 status
= NT_STATUS_NO_SUCH_FILE
;
4291 /* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4293 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
4295 BOOL sysdir_entry
= False
;
4297 pstrcpy(fname
,dname
);
4299 /* Quick check for "." and ".." */
4300 if (fname
[0] == '.') {
4301 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
4303 sysdir_entry
= True
;
4310 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
))
4313 if(!mask_match(fname
, mask
, conn
->case_sensitive
))
4317 status
= NT_STATUS_OBJECT_NAME_INVALID
;
4321 status
= NT_STATUS_ACCESS_DENIED
;
4322 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
4323 if (!vfs_object_exist(conn
, fname
, &sbuf1
)) {
4324 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4325 DEBUG(6,("rename %s failed. Error %s\n", fname
, nt_errstr(status
)));
4328 status
= can_rename(conn
,fname
,attrs
,&sbuf1
);
4329 if (!NT_STATUS_IS_OK(status
)) {
4330 DEBUG(6,("rename %s refused\n", fname
));
4333 pstrcpy(destname
,newname
);
4335 if (!resolve_wildcards(fname
,destname
)) {
4336 DEBUG(6,("resolve_wildcards %s %s failed\n",
4341 if (strcsequal(fname
,destname
)) {
4342 rename_open_files(conn
, NULL
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
4343 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname
));
4345 status
= NT_STATUS_OK
;
4349 if (!replace_if_exists
&&
4350 vfs_file_exist(conn
,destname
, NULL
)) {
4351 DEBUG(6,("file_exist %s\n", destname
));
4352 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
4356 if (rename_path_prefix_equal(fname
, destname
)) {
4357 return NT_STATUS_SHARING_VIOLATION
;
4360 lck
= get_share_mode_lock(NULL
, sbuf1
.st_dev
, sbuf1
.st_ino
, NULL
, NULL
);
4362 if (!SMB_VFS_RENAME(conn
,fname
,destname
)) {
4363 rename_open_files(conn
, lck
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
4365 status
= NT_STATUS_OK
;
4368 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
4374 /* Don't think needed any more - JRA. */
4375 if (!NT_STATUS_EQUAL(error
,NT_STATUS_NO_SUCH_FILE
)) {
4376 if (!rcdest
&& bad_path_dest
) {
4377 if (ms_has_wild(last_component_dest
))
4378 return NT_STATUS_OBJECT_NAME_INVALID
;
4379 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
4386 if (count
== 0 && NT_STATUS_IS_OK(status
)) {
4387 status
= map_nt_error_from_unix(errno
);
4393 /****************************************************************************
4395 ****************************************************************************/
4397 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
4404 uint32 attrs
= SVAL(inbuf
,smb_vwv0
);
4406 BOOL path1_contains_wcard
= False
;
4407 BOOL path2_contains_wcard
= False
;
4409 START_PROFILE(SMBmv
);
4411 p
= smb_buf(inbuf
) + 1;
4412 p
+= srvstr_get_path_wcard(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
, &path1_contains_wcard
);
4413 if (!NT_STATUS_IS_OK(status
)) {
4415 return ERROR_NT(status
);
4418 p
+= srvstr_get_path_wcard(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
, &path2_contains_wcard
);
4419 if (!NT_STATUS_IS_OK(status
)) {
4421 return ERROR_NT(status
);
4424 RESOLVE_DFSPATH_WCARD(name
, conn
, inbuf
, outbuf
);
4425 RESOLVE_DFSPATH_WCARD(newname
, conn
, inbuf
, outbuf
);
4427 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
4429 status
= rename_internals(conn
, name
, newname
, attrs
, False
, path1_contains_wcard
);
4430 if (!NT_STATUS_IS_OK(status
)) {
4432 if (open_was_deferred(SVAL(inbuf
,smb_mid
))) {
4433 /* We have re-scheduled this call. */
4436 return ERROR_NT(status
);
4440 * Win2k needs a changenotify request response before it will
4441 * update after a rename..
4443 process_pending_change_notify_queue((time_t)0);
4444 outsize
= set_message(outbuf
,0,0,False
);
4450 /*******************************************************************
4451 Copy a file as part of a reply_copy.
4452 ******************************************************************/
4455 * TODO: check error codes on all callers
4458 NTSTATUS
copy_file(char *src
, char *dest1
,connection_struct
*conn
, int ofun
,
4459 int count
, BOOL target_is_directory
)
4461 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
4463 files_struct
*fsp1
,*fsp2
;
4466 uint32 new_create_disposition
;
4470 pstrcpy(dest
,dest1
);
4471 if (target_is_directory
) {
4472 char *p
= strrchr_m(src
,'/');
4482 if (!vfs_file_exist(conn
,src
,&src_sbuf
)) {
4483 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4486 if (!target_is_directory
&& count
) {
4487 new_create_disposition
= FILE_OPEN
;
4489 if (!map_open_params_to_ntcreate(dest1
,0,ofun
,
4490 NULL
, NULL
, &new_create_disposition
, NULL
)) {
4491 return NT_STATUS_INVALID_PARAMETER
;
4495 status
= open_file_ntcreate(conn
,src
,&src_sbuf
,
4497 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4500 FILE_ATTRIBUTE_NORMAL
,
4504 if (!NT_STATUS_IS_OK(status
)) {
4508 dosattrs
= dos_mode(conn
, src
, &src_sbuf
);
4509 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1) {
4510 ZERO_STRUCTP(&sbuf2
);
4513 status
= open_file_ntcreate(conn
,dest
,&sbuf2
,
4515 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4516 new_create_disposition
,
4522 if (!NT_STATUS_IS_OK(status
)) {
4523 close_file(fsp1
,ERROR_CLOSE
);
4527 if ((ofun
&3) == 1) {
4528 if(SMB_VFS_LSEEK(fsp2
,fsp2
->fh
->fd
,0,SEEK_END
) == -1) {
4529 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
4531 * Stop the copy from occurring.
4534 src_sbuf
.st_size
= 0;
4538 if (src_sbuf
.st_size
) {
4539 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
4542 close_file(fsp1
,NORMAL_CLOSE
);
4544 /* Ensure the modtime is set correctly on the destination file. */
4545 fsp_set_pending_modtime( fsp2
, src_sbuf
.st_mtime
);
4548 * As we are opening fsp1 read-only we only expect
4549 * an error on close on fsp2 if we are out of space.
4550 * Thus we don't look at the error return from the
4553 close_err
= close_file(fsp2
,NORMAL_CLOSE
);
4555 if (close_err
!= 0) {
4556 return map_nt_error_from_unix(close_err
);
4559 if (ret
!= (SMB_OFF_T
)src_sbuf
.st_size
) {
4560 return NT_STATUS_DISK_FULL
;
4563 return NT_STATUS_OK
;
4566 /****************************************************************************
4567 Reply to a file copy.
4568 ****************************************************************************/
4570 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4575 pstring mask
,newname
;
4578 int error
= ERRnoaccess
;
4582 int tid2
= SVAL(inbuf
,smb_vwv0
);
4583 int ofun
= SVAL(inbuf
,smb_vwv1
);
4584 int flags
= SVAL(inbuf
,smb_vwv2
);
4585 BOOL target_is_directory
=False
;
4586 BOOL path_contains_wcard1
= False
;
4587 BOOL path_contains_wcard2
= False
;
4588 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4590 START_PROFILE(SMBcopy
);
4592 *directory
= *mask
= 0;
4595 p
+= srvstr_get_path_wcard(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
, &path_contains_wcard1
);
4596 if (!NT_STATUS_IS_OK(status
)) {
4597 END_PROFILE(SMBcopy
);
4598 return ERROR_NT(status
);
4600 p
+= srvstr_get_path_wcard(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
, &path_contains_wcard2
);
4601 if (!NT_STATUS_IS_OK(status
)) {
4602 END_PROFILE(SMBcopy
);
4603 return ERROR_NT(status
);
4606 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
4608 if (tid2
!= conn
->cnum
) {
4609 /* can't currently handle inter share copies XXXX */
4610 DEBUG(3,("Rejecting inter-share copy\n"));
4611 END_PROFILE(SMBcopy
);
4612 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
4615 RESOLVE_DFSPATH_WCARD(name
, conn
, inbuf
, outbuf
);
4616 RESOLVE_DFSPATH_WCARD(newname
, conn
, inbuf
, outbuf
);
4618 status
= unix_convert(conn
, name
, path_contains_wcard1
, NULL
, &sbuf1
);
4619 if (!NT_STATUS_IS_OK(status
)) {
4620 END_PROFILE(SMBcopy
);
4621 return ERROR_NT(status
);
4624 status
= unix_convert(conn
, newname
, path_contains_wcard2
, NULL
, &sbuf2
);
4625 if (!NT_STATUS_IS_OK(status
)) {
4626 END_PROFILE(SMBcopy
);
4627 return ERROR_NT(status
);
4630 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
4632 if ((flags
&1) && target_is_directory
) {
4633 END_PROFILE(SMBcopy
);
4634 return ERROR_DOS(ERRDOS
,ERRbadfile
);
4637 if ((flags
&2) && !target_is_directory
) {
4638 END_PROFILE(SMBcopy
);
4639 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4642 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
4643 /* wants a tree copy! XXXX */
4644 DEBUG(3,("Rejecting tree copy\n"));
4645 END_PROFILE(SMBcopy
);
4646 return ERROR_DOS(ERRSRV
,ERRerror
);
4649 p
= strrchr_m(name
,'/');
4651 pstrcpy(directory
,"./");
4655 pstrcpy(directory
,name
);
4660 * We should only check the mangled cache
4661 * here if unix_convert failed. This means
4662 * that the path in 'mask' doesn't exist
4663 * on the file system and so we need to look
4664 * for a possible mangle. This patch from
4665 * Tine Smukavec <valentin.smukavec@hermes.si>.
4668 if (!VALID_STAT(sbuf1
) && mangle_is_mangled(mask
, conn
->params
))
4669 mangle_check_cache( mask
, sizeof(pstring
)-1, conn
->params
);
4671 has_wild
= path_contains_wcard1
;
4674 pstrcat(directory
,"/");
4675 pstrcat(directory
,mask
);
4676 if (resolve_wildcards(directory
,newname
)
4677 && NT_STATUS_IS_OK(status
= copy_file(
4678 directory
,newname
,conn
,ofun
,
4679 count
,target_is_directory
)))
4681 if(!count
&& !NT_STATUS_IS_OK(status
)) {
4682 END_PROFILE(SMBcopy
);
4683 return ERROR_NT(status
);
4686 exists
= vfs_file_exist(conn
,directory
,NULL
);
4689 struct smb_Dir
*dir_hnd
= NULL
;
4693 if (strequal(mask
,"????????.???"))
4696 if (check_name(directory
,conn
))
4697 dir_hnd
= OpenDir(conn
, directory
, mask
, 0);
4703 while ((dname
= ReadDirName(dir_hnd
, &offset
))) {
4705 pstrcpy(fname
,dname
);
4707 if (!is_visible_file(conn
, directory
, dname
, &sbuf1
, False
))
4710 if(!mask_match(fname
, mask
, conn
->case_sensitive
))
4713 error
= ERRnoaccess
;
4714 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
4715 pstrcpy(destname
,newname
);
4716 if (resolve_wildcards(fname
,destname
)
4717 && NT_STATUS_IS_OK(status
= copy_file(
4718 fname
,destname
,conn
,ofun
,
4719 count
,target_is_directory
)))
4721 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
4729 /* Error on close... */
4731 END_PROFILE(SMBcopy
);
4732 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4735 END_PROFILE(SMBcopy
);
4736 return ERROR_DOS(ERRDOS
,error
);
4739 outsize
= set_message(outbuf
,1,0,True
);
4740 SSVAL(outbuf
,smb_vwv0
,count
);
4742 END_PROFILE(SMBcopy
);
4746 /****************************************************************************
4748 ****************************************************************************/
4750 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4758 START_PROFILE(pathworks_setdir
);
4761 if (!CAN_SETDIR(snum
)) {
4762 END_PROFILE(pathworks_setdir
);
4763 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4766 srvstr_get_path(inbuf
, newdir
, smb_buf(inbuf
) + 1, sizeof(newdir
), 0, STR_TERMINATE
, &status
);
4767 if (!NT_STATUS_IS_OK(status
)) {
4768 END_PROFILE(pathworks_setdir
);
4769 return ERROR_NT(status
);
4772 RESOLVE_DFSPATH(newdir
, conn
, inbuf
, outbuf
);
4774 if (strlen(newdir
) == 0) {
4777 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
4779 set_conn_connectpath(conn
,newdir
);
4783 END_PROFILE(pathworks_setdir
);
4784 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4787 outsize
= set_message(outbuf
,0,0,False
);
4788 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
4790 DEBUG(3,("setdir %s\n", newdir
));
4792 END_PROFILE(pathworks_setdir
);
4797 #define DBGC_CLASS DBGC_LOCKING
4799 /****************************************************************************
4800 Get a lock pid, dealing with large count requests.
4801 ****************************************************************************/
4803 uint32
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
4805 if(!large_file_format
)
4806 return (uint32
)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
4808 return (uint32
)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
4811 /****************************************************************************
4812 Get a lock count, dealing with large count requests.
4813 ****************************************************************************/
4815 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
4817 SMB_BIG_UINT count
= 0;
4819 if(!large_file_format
) {
4820 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
4823 #if defined(HAVE_LONGLONG)
4824 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
4825 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
4826 #else /* HAVE_LONGLONG */
4829 * NT4.x seems to be broken in that it sends large file (64 bit)
4830 * lockingX calls even if the CAP_LARGE_FILES was *not*
4831 * negotiated. For boxes without large unsigned ints truncate the
4832 * lock count by dropping the top 32 bits.
4835 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
4836 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4837 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
4838 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
4839 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
4842 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
4843 #endif /* HAVE_LONGLONG */
4849 #if !defined(HAVE_LONGLONG)
4850 /****************************************************************************
4851 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4852 ****************************************************************************/
4854 static uint32
map_lock_offset(uint32 high
, uint32 low
)
4858 uint32 highcopy
= high
;
4861 * Try and find out how many significant bits there are in high.
4864 for(i
= 0; highcopy
; i
++)
4868 * We use 31 bits not 32 here as POSIX
4869 * lock offsets may not be negative.
4872 mask
= (~0) << (31 - i
);
4875 return 0; /* Fail. */
4881 #endif /* !defined(HAVE_LONGLONG) */
4883 /****************************************************************************
4884 Get a lock offset, dealing with large offset requests.
4885 ****************************************************************************/
4887 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
4889 SMB_BIG_UINT offset
= 0;
4893 if(!large_file_format
) {
4894 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
4897 #if defined(HAVE_LONGLONG)
4898 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
4899 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
4900 #else /* HAVE_LONGLONG */
4903 * NT4.x seems to be broken in that it sends large file (64 bit)
4904 * lockingX calls even if the CAP_LARGE_FILES was *not*
4905 * negotiated. For boxes without large unsigned ints mangle the
4906 * lock offset by mapping the top 32 bits onto the lower 32.
4909 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
4910 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4911 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
4914 if((new_low
= map_lock_offset(high
, low
)) == 0) {
4916 return (SMB_BIG_UINT
)-1;
4919 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4920 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
4921 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
4922 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
4925 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4926 #endif /* HAVE_LONGLONG */
4932 /****************************************************************************
4933 Reply to a lockingX request.
4934 ****************************************************************************/
4936 int reply_lockingX(connection_struct
*conn
, char *inbuf
, char *outbuf
,
4937 int length
, int bufsize
)
4939 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
4940 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
4941 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
4942 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
4943 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
4944 SMB_BIG_UINT count
= 0, offset
= 0;
4946 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
4949 BOOL large_file_format
=
4950 (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
4952 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
4954 START_PROFILE(SMBlockingX
);
4956 CHECK_FSP(fsp
,conn
);
4958 data
= smb_buf(inbuf
);
4960 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
4961 /* we don't support these - and CANCEL_LOCK makes w2k
4962 and XP reboot so I don't really want to be
4963 compatible! (tridge) */
4964 return ERROR_NT(NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
4967 /* Check if this is an oplock break on a file
4968 we have granted an oplock on.
4970 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
4971 /* Client can insist on breaking to none. */
4972 BOOL break_to_none
= (oplocklevel
== 0);
4975 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
4976 "for fnum = %d\n", (unsigned int)oplocklevel
,
4980 * Make sure we have granted an exclusive or batch oplock on
4984 if (fsp
->oplock_type
== 0) {
4986 /* The Samba4 nbench simulator doesn't understand
4987 the difference between break to level2 and break
4988 to none from level2 - it sends oplock break
4989 replies in both cases. Don't keep logging an error
4990 message here - just ignore it. JRA. */
4992 DEBUG(5,("reply_lockingX: Error : oplock break from "
4993 "client for fnum = %d (oplock=%d) and no "
4994 "oplock granted on this file (%s).\n",
4995 fsp
->fnum
, fsp
->oplock_type
, fsp
->fsp_name
));
4997 /* if this is a pure oplock break request then don't
4999 if (num_locks
== 0 && num_ulocks
== 0) {
5000 END_PROFILE(SMBlockingX
);
5003 END_PROFILE(SMBlockingX
);
5004 return ERROR_DOS(ERRDOS
,ERRlock
);
5008 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
5010 result
= remove_oplock(fsp
);
5012 result
= downgrade_oplock(fsp
);
5016 DEBUG(0, ("reply_lockingX: error in removing "
5017 "oplock on file %s\n", fsp
->fsp_name
));
5018 /* Hmmm. Is this panic justified? */
5019 smb_panic("internal tdb error");
5022 reply_to_oplock_break_requests(fsp
);
5024 /* if this is a pure oplock break request then don't send a
5026 if (num_locks
== 0 && num_ulocks
== 0) {
5027 /* Sanity check - ensure a pure oplock break is not a
5029 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
5030 DEBUG(0,("reply_lockingX: Error : pure oplock "
5031 "break is a chained %d request !\n",
5032 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
5033 END_PROFILE(SMBlockingX
);
5039 * We do this check *after* we have checked this is not a oplock break
5040 * response message. JRA.
5043 release_level_2_oplocks_on_change(fsp
);
5045 /* Data now points at the beginning of the list
5046 of smb_unlkrng structs */
5047 for(i
= 0; i
< (int)num_ulocks
; i
++) {
5048 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
5049 count
= get_lock_count( data
, i
, large_file_format
);
5050 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
5053 * There is no error code marked "stupid client bug".... :-).
5056 END_PROFILE(SMBlockingX
);
5057 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
5060 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5061 "pid %u, file %s\n", (double)offset
, (double)count
,
5062 (unsigned int)lock_pid
, fsp
->fsp_name
));
5064 status
= do_unlock(fsp
,
5070 if (NT_STATUS_V(status
)) {
5071 END_PROFILE(SMBlockingX
);
5072 return ERROR_NT(status
);
5076 /* Setup the timeout in seconds. */
5078 if (!lp_blocking_locks(SNUM(conn
))) {
5082 /* Now do any requested locks */
5083 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
5085 /* Data now points at the beginning of the list
5086 of smb_lkrng structs */
5088 for(i
= 0; i
< (int)num_locks
; i
++) {
5089 enum brl_type lock_type
= ((locktype
& LOCKING_ANDX_SHARED_LOCK
) ?
5090 READ_LOCK
:WRITE_LOCK
);
5091 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
5092 count
= get_lock_count( data
, i
, large_file_format
);
5093 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
5096 * There is no error code marked "stupid client bug".... :-).
5099 END_PROFILE(SMBlockingX
);
5100 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
5103 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5104 "%u, file %s timeout = %d\n", (double)offset
,
5105 (double)count
, (unsigned int)lock_pid
,
5106 fsp
->fsp_name
, (int)lock_timeout
));
5108 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
5109 if (lp_blocking_locks(SNUM(conn
))) {
5111 /* Schedule a message to ourselves to
5112 remove the blocking lock record and
5113 return the right error. */
5115 if (!blocking_lock_cancel(fsp
,
5121 NT_STATUS_FILE_LOCK_CONFLICT
)) {
5122 END_PROFILE(SMBlockingX
);
5123 return ERROR_NT(NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
5126 /* Remove a matching pending lock. */
5127 status
= do_lock_cancel(fsp
,
5133 BOOL blocking_lock
= lock_timeout
? True
: False
;
5134 BOOL defer_lock
= False
;
5135 struct byte_range_lock
*br_lck
;
5137 br_lck
= do_lock(fsp
,
5146 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
5147 /* Windows internal resolution for blocking locks seems
5148 to be about 200ms... Don't wait for less than that. JRA. */
5149 if (lock_timeout
!= -1 && lock_timeout
< lp_lock_spin_time()) {
5150 lock_timeout
= lp_lock_spin_time();
5155 /* This heuristic seems to match W2K3 very well. If a
5156 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5157 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5158 far as I can tell. Replacement for do_lock_spin(). JRA. */
5160 if (br_lck
&& lp_blocking_locks(SNUM(conn
)) && !blocking_lock
&&
5161 NT_STATUS_EQUAL((status
), NT_STATUS_FILE_LOCK_CONFLICT
)) {
5163 lock_timeout
= lp_lock_spin_time();
5166 if (br_lck
&& defer_lock
) {
5168 * A blocking lock was requested. Package up
5169 * this smb into a queued request and push it
5170 * onto the blocking lock queue.
5172 if(push_blocking_lock_request(br_lck
,
5182 TALLOC_FREE(br_lck
);
5183 END_PROFILE(SMBlockingX
);
5188 TALLOC_FREE(br_lck
);
5191 if (NT_STATUS_V(status
)) {
5192 END_PROFILE(SMBlockingX
);
5193 return ERROR_NT(status
);
5197 /* If any of the above locks failed, then we must unlock
5198 all of the previous locks (X/Open spec). */
5200 if (!(locktype
& LOCKING_ANDX_CANCEL_LOCK
) &&
5204 * Ensure we don't do a remove on the lock that just failed,
5205 * as under POSIX rules, if we have a lock already there, we
5206 * will delete it (and we shouldn't) .....
5208 for(i
--; i
>= 0; i
--) {
5209 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
5210 count
= get_lock_count( data
, i
, large_file_format
);
5211 offset
= get_lock_offset( data
, i
, large_file_format
,
5215 * There is no error code marked "stupid client
5219 END_PROFILE(SMBlockingX
);
5220 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
5229 END_PROFILE(SMBlockingX
);
5230 return ERROR_NT(status
);
5233 set_message(outbuf
,2,0,True
);
5235 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5236 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
5238 END_PROFILE(SMBlockingX
);
5239 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
5243 #define DBGC_CLASS DBGC_ALL
5245 /****************************************************************************
5246 Reply to a SMBreadbmpx (read block multiplex) request.
5247 ****************************************************************************/
5249 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
5260 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
5261 START_PROFILE(SMBreadBmpx
);
5263 /* this function doesn't seem to work - disable by default */
5264 if (!lp_readbmpx()) {
5265 END_PROFILE(SMBreadBmpx
);
5266 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
5269 outsize
= set_message(outbuf
,8,0,True
);
5271 CHECK_FSP(fsp
,conn
);
5272 if (!CHECK_READ(fsp
,inbuf
)) {
5273 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
5276 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
5277 maxcount
= SVAL(inbuf
,smb_vwv3
);
5279 data
= smb_buf(outbuf
);
5280 pad
= ((long)data
)%4;
5285 max_per_packet
= bufsize
-(outsize
+pad
);
5289 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
5290 END_PROFILE(SMBreadBmpx
);
5291 return ERROR_DOS(ERRDOS
,ERRlock
);
5295 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
5297 nread
= read_file(fsp
,data
,startpos
,N
);
5302 if (nread
< (ssize_t
)N
)
5303 tcount
= total_read
+ nread
;
5305 set_message(outbuf
,8,nread
+pad
,False
);
5306 SIVAL(outbuf
,smb_vwv0
,startpos
);
5307 SSVAL(outbuf
,smb_vwv2
,tcount
);
5308 SSVAL(outbuf
,smb_vwv6
,nread
);
5309 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
5312 if (!send_smb(smbd_server_fd(),outbuf
))
5313 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5315 total_read
+= nread
;
5317 } while (total_read
< (ssize_t
)tcount
);
5319 END_PROFILE(SMBreadBmpx
);
5323 /****************************************************************************
5324 Reply to a SMBsetattrE.
5325 ****************************************************************************/
5327 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
5329 struct utimbuf unix_times
;
5331 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
5332 START_PROFILE(SMBsetattrE
);
5334 outsize
= set_message(outbuf
,0,0,False
);
5336 if(!fsp
|| (fsp
->conn
!= conn
)) {
5337 END_PROFILE(SMBsetattrE
);
5338 return ERROR_DOS(ERRDOS
,ERRbadfid
);
5342 * Convert the DOS times into unix times. Ignore create
5343 * time as UNIX can't set this.
5346 unix_times
.actime
= srv_make_unix_date2(inbuf
+smb_vwv3
);
5347 unix_times
.modtime
= srv_make_unix_date2(inbuf
+smb_vwv5
);
5350 * Patch from Ray Frush <frush@engr.colostate.edu>
5351 * Sometimes times are sent as zero - ignore them.
5354 if (null_mtime(unix_times
.actime
) && null_mtime(unix_times
.modtime
)) {
5355 /* Ignore request */
5356 if( DEBUGLVL( 3 ) ) {
5357 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
5358 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5360 END_PROFILE(SMBsetattrE
);
5362 } else if (!null_mtime(unix_times
.actime
) && null_mtime(unix_times
.modtime
)) {
5363 /* set modify time = to access time if modify time was unset */
5364 unix_times
.modtime
= unix_times
.actime
;
5367 /* Set the date on this file */
5368 /* Should we set pending modtime here ? JRA */
5369 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
5370 END_PROFILE(SMBsetattrE
);
5371 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
5374 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5375 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
5377 END_PROFILE(SMBsetattrE
);
5382 /* Back from the dead for OS/2..... JRA. */
5384 /****************************************************************************
5385 Reply to a SMBwritebmpx (write block multiplex primary) request.
5386 ****************************************************************************/
5388 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
5391 ssize_t nwritten
= -1;
5398 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
5399 START_PROFILE(SMBwriteBmpx
);
5401 CHECK_FSP(fsp
,conn
);
5402 if (!CHECK_WRITE(fsp
)) {
5403 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
5405 if (HAS_CACHED_ERROR(fsp
)) {
5406 return(CACHED_ERROR(fsp
));
5409 tcount
= SVAL(inbuf
,smb_vwv1
);
5410 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
5411 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
5412 numtowrite
= SVAL(inbuf
,smb_vwv10
);
5413 smb_doff
= SVAL(inbuf
,smb_vwv11
);
5415 data
= smb_base(inbuf
) + smb_doff
;
5417 /* If this fails we need to send an SMBwriteC response,
5418 not an SMBwritebmpx - set this up now so we don't forget */
5419 SCVAL(outbuf
,smb_com
,SMBwritec
);
5421 if (is_locked(fsp
,(uint32
)SVAL(inbuf
,smb_pid
),(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
)) {
5422 END_PROFILE(SMBwriteBmpx
);
5423 return(ERROR_DOS(ERRDOS
,ERRlock
));
5426 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
5428 sync_file(conn
, fsp
, write_through
);
5430 if(nwritten
< (ssize_t
)numtowrite
) {
5431 END_PROFILE(SMBwriteBmpx
);
5432 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
5435 /* If the maximum to be written to this file
5436 is greater than what we just wrote then set
5437 up a secondary struct to be attached to this
5438 fd, we will use this to cache error messages etc. */
5440 if((ssize_t
)tcount
> nwritten
) {
5441 write_bmpx_struct
*wbms
;
5442 if(fsp
->wbmpx_ptr
!= NULL
)
5443 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
5445 wbms
= SMB_MALLOC_P(write_bmpx_struct
);
5447 DEBUG(0,("Out of memory in reply_readmpx\n"));
5448 END_PROFILE(SMBwriteBmpx
);
5449 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
5451 wbms
->wr_mode
= write_through
;
5452 wbms
->wr_discard
= False
; /* No errors yet */
5453 wbms
->wr_total_written
= nwritten
;
5454 wbms
->wr_errclass
= 0;
5456 fsp
->wbmpx_ptr
= wbms
;
5459 /* We are returning successfully, set the message type back to
5461 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
5463 outsize
= set_message(outbuf
,1,0,True
);
5465 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
5467 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5468 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
5470 if (write_through
&& tcount
==nwritten
) {
5471 /* We need to send both a primary and a secondary response */
5472 smb_setlen(outbuf
,outsize
- 4);
5474 if (!send_smb(smbd_server_fd(),outbuf
))
5475 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5477 /* Now the secondary */
5478 outsize
= set_message(outbuf
,1,0,True
);
5479 SCVAL(outbuf
,smb_com
,SMBwritec
);
5480 SSVAL(outbuf
,smb_vwv0
,nwritten
);
5483 END_PROFILE(SMBwriteBmpx
);
5487 /****************************************************************************
5488 Reply to a SMBwritebs (write block multiplex secondary) request.
5489 ****************************************************************************/
5491 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
5494 ssize_t nwritten
= -1;
5501 write_bmpx_struct
*wbms
;
5502 BOOL send_response
= False
;
5503 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
5504 START_PROFILE(SMBwriteBs
);
5506 CHECK_FSP(fsp
,conn
);
5507 if (!CHECK_WRITE(fsp
)) {
5508 return(ERROR_DOS(ERRDOS
,ERRbadaccess
));
5511 tcount
= SVAL(inbuf
,smb_vwv1
);
5512 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
5513 numtowrite
= SVAL(inbuf
,smb_vwv6
);
5514 smb_doff
= SVAL(inbuf
,smb_vwv7
);
5516 data
= smb_base(inbuf
) + smb_doff
;
5518 /* We need to send an SMBwriteC response, not an SMBwritebs */
5519 SCVAL(outbuf
,smb_com
,SMBwritec
);
5521 /* This fd should have an auxiliary struct attached,
5522 check that it does */
5523 wbms
= fsp
->wbmpx_ptr
;
5525 END_PROFILE(SMBwriteBs
);
5529 /* If write through is set we can return errors, else we must cache them */
5530 write_through
= wbms
->wr_mode
;
5532 /* Check for an earlier error */
5533 if(wbms
->wr_discard
) {
5534 END_PROFILE(SMBwriteBs
);
5535 return -1; /* Just discard the packet */
5538 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
5540 sync_file(conn
, fsp
, write_through
);
5542 if (nwritten
< (ssize_t
)numtowrite
) {
5544 /* We are returning an error - we can delete the aux struct */
5547 fsp
->wbmpx_ptr
= NULL
;
5548 END_PROFILE(SMBwriteBs
);
5549 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
5551 wbms
->wr_errclass
= ERRHRD
;
5552 wbms
->wr_error
= ERRdiskfull
;
5553 wbms
->wr_status
= NT_STATUS_DISK_FULL
;
5554 wbms
->wr_discard
= True
;
5555 END_PROFILE(SMBwriteBs
);
5559 /* Increment the total written, if this matches tcount
5560 we can discard the auxiliary struct (hurrah !) and return a writeC */
5561 wbms
->wr_total_written
+= nwritten
;
5562 if(wbms
->wr_total_written
>= tcount
) {
5563 if (write_through
) {
5564 outsize
= set_message(outbuf
,1,0,True
);
5565 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
5566 send_response
= True
;
5570 fsp
->wbmpx_ptr
= NULL
;
5574 END_PROFILE(SMBwriteBs
);
5578 END_PROFILE(SMBwriteBs
);
5582 /****************************************************************************
5583 Reply to a SMBgetattrE.
5584 ****************************************************************************/
5586 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
5588 SMB_STRUCT_STAT sbuf
;
5591 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
5592 START_PROFILE(SMBgetattrE
);
5594 outsize
= set_message(outbuf
,11,0,True
);
5596 if(!fsp
|| (fsp
->conn
!= conn
)) {
5597 END_PROFILE(SMBgetattrE
);
5598 return ERROR_DOS(ERRDOS
,ERRbadfid
);
5601 /* Do an fstat on this file */
5602 if(fsp_stat(fsp
, &sbuf
)) {
5603 END_PROFILE(SMBgetattrE
);
5604 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
5607 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
5610 * Convert the times into dos times. Set create
5611 * date to be last modify date as UNIX doesn't save
5615 srv_put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
5616 srv_put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
5617 /* Should we check pending modtime here ? JRA */
5618 srv_put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
5621 SIVAL(outbuf
,smb_vwv6
,0);
5622 SIVAL(outbuf
,smb_vwv8
,0);
5624 uint32 allocation_size
= get_allocation_size(conn
,fsp
, &sbuf
);
5625 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
5626 SIVAL(outbuf
,smb_vwv8
,allocation_size
);
5628 SSVAL(outbuf
,smb_vwv10
, mode
);
5630 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
5632 END_PROFILE(SMBgetattrE
);