2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
28 /* look in server.c for some explanation of these variables */
32 extern char magic_char
;
33 extern BOOL case_sensitive
;
34 extern BOOL case_preserve
;
35 extern BOOL short_case_preserve
;
36 extern int global_oplock_break
;
37 unsigned int smb_echo_count
= 0;
39 extern BOOL global_encrypted_passwords_negotiated
;
41 /****************************************************************************
42 Ensure we check the path in *exactly* the same way as W2K.
43 We're assuming here that '/' is not the second byte in any multibyte char
44 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
46 ****************************************************************************/
48 static NTSTATUS
check_path_syntax(pstring destname
, const pstring srcname
)
51 const char *s
= srcname
;
52 NTSTATUS ret
= NT_STATUS_OK
;
55 if (IS_DIRECTORY_SEP(*s
)) {
57 * Safe to assume is not the second part of a mb char as this is handled below.
59 /* Eat multiple '/' or '\\' */
60 while (IS_DIRECTORY_SEP(*s
)) {
63 if ((d
!= destname
) && (*s
!= '\0')) {
64 /* We only care about non-leading or trailing '/' or '\\' */
67 } else if ((s
[0] == '.') && (s
[1] == '.') && (IS_DIRECTORY_SEP(s
[2]) || s
[2] == '\0')) {
68 /* Uh oh - "../" or "..\\" or "..\0" ! */
71 * No mb char starts with '.' so we're safe checking the directory separator here.
74 /* If we just added a '/', delete it. */
76 if ((d
> destname
) && (*(d
-1) == '/')) {
78 if (d
== (destname
+ 1)) {
84 /* Are we at the start ? Can't go back further if so. */
86 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
88 /* Go back one level... */
89 while (d
> destname
) {
95 } else if ((s
[0] == '.') && IS_DIRECTORY_SEP(s
[1])) {
98 * No mb char starts with '.' so we're safe checking the directory separator here.
101 /* "./" or ".\\" fails with a different error depending on where it is... */
104 ret
= NT_STATUS_OBJECT_NAME_INVALID
;
107 return NT_STATUS_INVALID_PARAMETER
;
109 ret
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
113 if ((*s
& 0x80) && IS_DIRECTORY_SEP(s
[1])) {
115 * Potential mb char with second char a directory separator.
116 * All the encodings we care about are 2 byte only, so do a
117 * conversion to unicode. If the 2 byte char won't convert then
118 * it's probably a one byte char with a real directory separator
119 * following, so only copy one byte. If it will convert then
123 if (convert_string(CH_UNIX
, CH_UCS2
, s
, 2, &ucs2_val
, 2) == 2) {
127 /* Just copy the char (or the second byte of the mb char). */
135 /****************************************************************************
136 Pull a string and check the path - provide for error return.
137 ****************************************************************************/
139 size_t srvstr_get_path(char *inbuf
, char *dest
, const char *src
, size_t dest_len
, size_t src_len
, int flags
, NTSTATUS
*err
)
142 char *tmppath_ptr
= tmppath
;
144 SMB_ASSERT(dest_len
== sizeof(pstring
));
149 ret
= srvstr_pull_buf( inbuf
, tmppath_ptr
, src
, dest_len
, flags
);
151 ret
= srvstr_pull( inbuf
, tmppath_ptr
, src
, dest_len
, src_len
, flags
);
153 *err
= check_path_syntax(dest
, tmppath
);
157 /****************************************************************************
158 Reply to a special message.
159 ****************************************************************************/
161 int reply_special(char *inbuf
,char *outbuf
)
164 int msg_type
= CVAL(inbuf
,0);
165 int msg_flags
= CVAL(inbuf
,1);
169 static BOOL already_got_session
= False
;
173 memset(outbuf
,'\0',smb_size
);
175 smb_setlen(outbuf
,0);
178 case 0x81: /* session request */
180 if (already_got_session
) {
181 exit_server("multiple session request not permitted");
184 SCVAL(outbuf
,0,0x82);
186 if (name_len(inbuf
+4) > 50 ||
187 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
188 DEBUG(0,("Invalid name length in session request\n"));
191 name_extract(inbuf
,4,name1
);
192 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
193 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
196 set_local_machine_name(name1
, True
);
197 set_remote_machine_name(name2
, True
);
199 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
200 get_local_machine_name(), get_remote_machine_name(),
203 if (name_type
== 'R') {
204 /* We are being asked for a pathworks session ---
206 SCVAL(outbuf
, 0,0x83);
210 /* only add the client's machine name to the list
211 of possibly valid usernames if we are operating
212 in share mode security */
213 if (lp_security() == SEC_SHARE
) {
214 add_session_user(get_remote_machine_name());
217 reload_services(True
);
220 claim_connection(NULL
,"",0,True
,FLAG_MSG_GENERAL
|FLAG_MSG_SMBD
);
222 already_got_session
= True
;
225 case 0x89: /* session keepalive request
226 (some old clients produce this?) */
227 SCVAL(outbuf
,0,SMBkeepalive
);
231 case 0x82: /* positive session response */
232 case 0x83: /* negative session response */
233 case 0x84: /* retarget session response */
234 DEBUG(0,("Unexpected session response\n"));
237 case SMBkeepalive
: /* session keepalive */
242 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
243 msg_type
, msg_flags
));
248 /****************************************************************************
250 ****************************************************************************/
252 int reply_tcon(connection_struct
*conn
,
253 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
260 uint16 vuid
= SVAL(inbuf
,smb_uid
);
264 DATA_BLOB password_blob
;
266 START_PROFILE(SMBtcon
);
268 *service_buf
= *password
= *dev
= 0;
270 p
= smb_buf(inbuf
)+1;
271 p
+= srvstr_pull_buf(inbuf
, service_buf
, p
, sizeof(service_buf
), STR_TERMINATE
) + 1;
272 pwlen
= srvstr_pull_buf(inbuf
, password
, p
, sizeof(password
), STR_TERMINATE
) + 1;
274 p
+= srvstr_pull_buf(inbuf
, dev
, p
, sizeof(dev
), STR_TERMINATE
) + 1;
276 p
= strrchr_m(service_buf
,'\\');
280 service
= service_buf
;
283 password_blob
= data_blob(password
, pwlen
+1);
285 conn
= make_connection(service
,password_blob
,dev
,vuid
,&nt_status
);
287 data_blob_clear_free(&password_blob
);
290 END_PROFILE(SMBtcon
);
291 return ERROR_NT(nt_status
);
294 outsize
= set_message(outbuf
,2,0,True
);
295 SSVAL(outbuf
,smb_vwv0
,max_recv
);
296 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
297 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
299 DEBUG(3,("tcon service=%s cnum=%d\n",
300 service
, conn
->cnum
));
302 END_PROFILE(SMBtcon
);
306 /****************************************************************************
307 Reply to a tcon and X.
308 ****************************************************************************/
310 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
315 /* what the cleint thinks the device is */
316 fstring client_devicetype
;
317 /* what the server tells the client the share represents */
318 const char *server_devicetype
;
320 uint16 vuid
= SVAL(inbuf
,smb_uid
);
321 int passlen
= SVAL(inbuf
,smb_vwv3
);
324 extern BOOL global_encrypted_passwords_negotiated
;
326 START_PROFILE(SMBtconX
);
328 *service
= *client_devicetype
= 0;
330 /* we might have to close an old one */
331 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
332 close_cnum(conn
,vuid
);
335 if (passlen
> MAX_PASS_LEN
) {
336 return ERROR_DOS(ERRDOS
,ERRbuftoosmall
);
339 if (global_encrypted_passwords_negotiated
) {
340 password
= data_blob(smb_buf(inbuf
),passlen
);
342 password
= data_blob(smb_buf(inbuf
),passlen
+1);
343 /* Ensure correct termination */
344 password
.data
[passlen
]=0;
347 p
= smb_buf(inbuf
) + passlen
;
348 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
351 * the service name can be either: \\server\share
352 * or share directly like on the DELL PowerVault 705
355 q
= strchr_m(path
+2,'\\');
357 END_PROFILE(SMBtconX
);
358 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
360 fstrcpy(service
,q
+1);
363 fstrcpy(service
,path
);
365 p
+= srvstr_pull(inbuf
, client_devicetype
, p
, sizeof(client_devicetype
), 6, STR_ASCII
);
367 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
369 conn
= make_connection(service
,password
,client_devicetype
,vuid
,&nt_status
);
371 data_blob_clear_free(&password
);
374 END_PROFILE(SMBtconX
);
375 return ERROR_NT(nt_status
);
379 server_devicetype
= "IPC";
380 else if ( IS_PRINT(conn
) )
381 server_devicetype
= "LPT1:";
383 server_devicetype
= "A:";
385 if (Protocol
< PROTOCOL_NT1
) {
386 set_message(outbuf
,2,0,True
);
388 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
389 STR_TERMINATE
|STR_ASCII
);
390 set_message_end(outbuf
,p
);
392 /* NT sets the fstype of IPC$ to the null string */
393 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
395 set_message(outbuf
,3,0,True
);
398 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
399 STR_TERMINATE
|STR_ASCII
);
400 p
+= srvstr_push(outbuf
, p
, fstype
, -1,
403 set_message_end(outbuf
,p
);
405 /* what does setting this bit do? It is set by NT4 and
406 may affect the ability to autorun mounted cdroms */
407 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
408 (lp_csc_policy(SNUM(conn
)) << 2));
410 init_dfsroot(conn
, inbuf
, outbuf
);
414 DEBUG(3,("tconX service=%s \n",
417 /* set the incoming and outgoing tid to the just created one */
418 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
419 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
421 END_PROFILE(SMBtconX
);
422 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
425 /****************************************************************************
426 Reply to an unknown type.
427 ****************************************************************************/
429 int reply_unknown(char *inbuf
,char *outbuf
)
432 type
= CVAL(inbuf
,smb_com
);
434 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
435 smb_fn_name(type
), type
, type
));
437 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
440 /****************************************************************************
442 ****************************************************************************/
444 int reply_ioctl(connection_struct
*conn
,
445 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
447 uint16 device
= SVAL(inbuf
,smb_vwv1
);
448 uint16 function
= SVAL(inbuf
,smb_vwv2
);
449 uint32 ioctl_code
= (device
<< 16) + function
;
450 int replysize
, outsize
;
452 START_PROFILE(SMBioctl
);
454 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
456 switch (ioctl_code
) {
457 case IOCTL_QUERY_JOB_INFO
:
461 END_PROFILE(SMBioctl
);
462 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
465 outsize
= set_message(outbuf
,8,replysize
+1,True
);
466 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
467 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
468 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
469 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
471 switch (ioctl_code
) {
472 case IOCTL_QUERY_JOB_INFO
:
474 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
476 END_PROFILE(SMBioctl
);
477 return(UNIXERROR(ERRDOS
,ERRbadfid
));
479 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
480 srvstr_push(outbuf
, p
+2, global_myname(), 15, STR_TERMINATE
|STR_ASCII
);
481 srvstr_push(outbuf
, p
+18, lp_servicename(SNUM(conn
)), 13, STR_TERMINATE
|STR_ASCII
);
486 END_PROFILE(SMBioctl
);
490 /****************************************************************************
492 ****************************************************************************/
494 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
500 BOOL bad_path
= False
;
501 SMB_STRUCT_STAT sbuf
;
504 START_PROFILE(SMBchkpth
);
506 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
);
507 if (!NT_STATUS_IS_OK(status
)) {
508 END_PROFILE(SMBchkpth
);
509 return ERROR_NT(status
);
512 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
514 unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
516 mode
= SVAL(inbuf
,smb_vwv0
);
518 if (check_name(name
,conn
)) {
519 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,name
,&sbuf
) == 0)
520 if (!(ok
= S_ISDIR(sbuf
.st_mode
))) {
521 END_PROFILE(SMBchkpth
);
522 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY
,ERRDOS
,ERRbadpath
);
527 /* We special case this - as when a Windows machine
528 is parsing a path is steps through the components
529 one at a time - if a component fails it expects
530 ERRbadpath, not ERRbadfile.
532 if(errno
== ENOENT
) {
534 * Windows returns different error codes if
535 * the parent directory is valid but not the
536 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
537 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
538 * if the path is invalid.
541 END_PROFILE(SMBchkpth
);
542 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
544 END_PROFILE(SMBchkpth
);
545 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND
);
547 } else if (errno
== ENOTDIR
) {
548 END_PROFILE(SMBchkpth
);
549 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY
);
552 END_PROFILE(SMBchkpth
);
553 return(UNIXERROR(ERRDOS
,ERRbadpath
));
556 outsize
= set_message(outbuf
,0,0,True
);
558 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
560 END_PROFILE(SMBchkpth
);
564 /****************************************************************************
566 ****************************************************************************/
568 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
572 SMB_STRUCT_STAT sbuf
;
577 BOOL bad_path
= False
;
581 START_PROFILE(SMBgetatr
);
583 p
= smb_buf(inbuf
) + 1;
584 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
585 if (!NT_STATUS_IS_OK(status
)) {
586 END_PROFILE(SMBgetatr
);
587 return ERROR_NT(status
);
590 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
592 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
593 under WfWg - weird! */
595 mode
= aHIDDEN
| aDIR
;
596 if (!CAN_WRITE(conn
))
602 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
603 if (check_name(fname
,conn
)) {
604 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,fname
,&sbuf
) == 0) {
605 mode
= dos_mode(conn
,fname
,&sbuf
);
607 mtime
= sbuf
.st_mtime
;
612 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
618 END_PROFILE(SMBgetatr
);
619 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadfile
);
622 outsize
= set_message(outbuf
,10,0,True
);
624 SSVAL(outbuf
,smb_vwv0
,mode
);
625 if(lp_dos_filetime_resolution(SNUM(conn
)) )
626 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
628 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
629 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
631 if (Protocol
>= PROTOCOL_NT1
)
632 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
634 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
636 END_PROFILE(SMBgetatr
);
640 /****************************************************************************
642 ****************************************************************************/
644 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
651 SMB_STRUCT_STAT sbuf
;
652 BOOL bad_path
= False
;
656 START_PROFILE(SMBsetatr
);
658 p
= smb_buf(inbuf
) + 1;
659 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
660 if (!NT_STATUS_IS_OK(status
)) {
661 END_PROFILE(SMBsetatr
);
662 return ERROR_NT(status
);
665 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
667 mode
= SVAL(inbuf
,smb_vwv0
);
668 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
670 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
671 if (VALID_STAT_OF_DIR(sbuf
))
676 if (check_name(fname
,conn
))
677 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
683 ok
= set_filetime(conn
,fname
,mtime
);
686 END_PROFILE(SMBsetatr
);
687 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
690 outsize
= set_message(outbuf
,0,0,True
);
692 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
694 END_PROFILE(SMBsetatr
);
698 /****************************************************************************
700 ****************************************************************************/
702 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
705 SMB_BIG_UINT dfree
,dsize
,bsize
;
706 START_PROFILE(SMBdskattr
);
708 SMB_VFS_DISK_FREE(conn
,".",True
,&bsize
,&dfree
,&dsize
);
710 outsize
= set_message(outbuf
,5,0,True
);
712 if (Protocol
<= PROTOCOL_LANMAN2
) {
713 double total_space
, free_space
;
714 /* we need to scale this to a number that DOS6 can handle. We
715 use floating point so we can handle large drives on systems
716 that don't have 64 bit integers
718 we end up displaying a maximum of 2G to DOS systems
720 total_space
= dsize
* (double)bsize
;
721 free_space
= dfree
* (double)bsize
;
723 dsize
= (total_space
+63*512) / (64*512);
724 dfree
= (free_space
+63*512) / (64*512);
726 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
727 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
729 SSVAL(outbuf
,smb_vwv0
,dsize
);
730 SSVAL(outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
731 SSVAL(outbuf
,smb_vwv2
,512); /* and this must be 512 */
732 SSVAL(outbuf
,smb_vwv3
,dfree
);
734 SSVAL(outbuf
,smb_vwv0
,dsize
);
735 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
736 SSVAL(outbuf
,smb_vwv2
,512);
737 SSVAL(outbuf
,smb_vwv3
,dfree
);
740 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
742 END_PROFILE(SMBdskattr
);
746 /****************************************************************************
748 Can be called from SMBsearch, SMBffirst or SMBfunique.
749 ****************************************************************************/
751 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
761 unsigned int numentries
= 0;
762 unsigned int maxentries
= 0;
763 BOOL finished
= False
;
770 BOOL check_descend
= False
;
771 BOOL expect_close
= False
;
772 BOOL can_open
= True
;
773 BOOL bad_path
= False
;
775 START_PROFILE(SMBsearch
);
777 *mask
= *directory
= *fname
= 0;
779 /* If we were called as SMBffirst then we must expect close. */
780 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
783 outsize
= set_message(outbuf
,1,3,True
);
784 maxentries
= SVAL(inbuf
,smb_vwv0
);
785 dirtype
= SVAL(inbuf
,smb_vwv1
);
786 p
= smb_buf(inbuf
) + 1;
787 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &nt_status
);
788 if (!NT_STATUS_IS_OK(nt_status
)) {
789 END_PROFILE(SMBsearch
);
790 return ERROR_NT(nt_status
);
793 status_len
= SVAL(p
, 0);
796 /* dirtype &= ~aDIR; */
798 if (status_len
== 0) {
799 SMB_STRUCT_STAT sbuf
;
802 pstrcpy(directory
,path
);
804 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
807 if (!check_name(directory
,conn
))
810 p
= strrchr_m(dir2
,'/');
819 p
= strrchr_m(directory
,'/');
825 if (strlen(directory
) == 0)
826 pstrcpy(directory
,".");
827 memset((char *)status
,'\0',21);
828 SCVAL(status
,0,(dirtype
& 0x1F));
833 status_dirtype
= CVAL(status
,0) & 0x1F;
834 if (status_dirtype
!= (dirtype
& 0x1F))
835 dirtype
= status_dirtype
;
837 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
840 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
841 pstrcpy(mask
, dptr_wcard(dptr_num
));
845 p
= smb_buf(outbuf
) + 3;
848 if (status_len
== 0) {
849 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
852 END_PROFILE(SMBsearch
);
853 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnofids
);
855 END_PROFILE(SMBsearch
);
856 return ERROR_DOS(ERRDOS
,ERRnofids
);
858 dptr_set_wcard(dptr_num
, strdup(mask
));
859 dptr_set_attr(dptr_num
, dirtype
);
861 dirtype
= dptr_attr(dptr_num
);
864 DEBUG(4,("dptr_num is %d\n",dptr_num
));
867 if ((dirtype
&0x1F) == aVOLID
) {
869 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
870 dptr_fill(p
+12,dptr_num
);
871 if (dptr_zero(p
+12) && (status_len
==0))
875 p
+= DIR_STRUCT_SIZE
;
878 maxentries
= MIN(maxentries
, ((BUFFER_SIZE
- (p
- outbuf
))/DIR_STRUCT_SIZE
));
880 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
881 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
882 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
883 check_descend
= True
;
885 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
886 finished
= !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
889 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
890 dptr_fill(p
+12,dptr_num
);
893 p
+= DIR_STRUCT_SIZE
;
902 /* If we were called as SMBffirst with smb_search_id == NULL
903 and no entries were found then return error and close dirptr
906 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0) {
907 if (Protocol
< PROTOCOL_NT1
) {
908 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
909 SSVAL(outbuf
,smb_err
,ERRnofiles
);
911 /* Also close the dptr - we know it's gone */
912 dptr_close(&dptr_num
);
913 } else if (numentries
== 0 || !ok
) {
914 if (Protocol
< PROTOCOL_NT1
) {
915 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
916 SSVAL(outbuf
,smb_err
,ERRnofiles
);
918 dptr_close(&dptr_num
);
921 /* If we were called as SMBfunique, then we can close the dirptr now ! */
922 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
923 dptr_close(&dptr_num
);
925 SSVAL(outbuf
,smb_vwv0
,numentries
);
926 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
927 SCVAL(smb_buf(outbuf
),0,5);
928 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
930 if (Protocol
>= PROTOCOL_NT1
)
931 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
933 outsize
+= DIR_STRUCT_SIZE
*numentries
;
934 smb_setlen(outbuf
,outsize
- 4);
936 if ((! *directory
) && dptr_path(dptr_num
))
937 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
939 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
940 smb_fn_name(CVAL(inbuf
,smb_com
)),
941 mask
, directory
, dirtype
, numentries
, maxentries
) );
943 END_PROFILE(SMBsearch
);
947 /****************************************************************************
948 Reply to a fclose (stop directory search).
949 ****************************************************************************/
951 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
961 START_PROFILE(SMBfclose
);
963 outsize
= set_message(outbuf
,1,0,True
);
964 p
= smb_buf(inbuf
) + 1;
965 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &err
);
966 if (!NT_STATUS_IS_OK(err
)) {
967 END_PROFILE(SMBfclose
);
968 return ERROR_NT(err
);
971 status_len
= SVAL(p
,0);
974 if (status_len
== 0) {
975 END_PROFILE(SMBfclose
);
976 return ERROR_DOS(ERRSRV
,ERRsrverror
);
981 if(dptr_fetch(status
+12,&dptr_num
)) {
982 /* Close the dptr - we know it's gone */
983 dptr_close(&dptr_num
);
986 SSVAL(outbuf
,smb_vwv0
,0);
988 DEBUG(3,("search close\n"));
990 END_PROFILE(SMBfclose
);
994 /****************************************************************************
996 ****************************************************************************/
998 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1008 SMB_STRUCT_STAT sbuf
;
1009 BOOL bad_path
= False
;
1011 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1013 START_PROFILE(SMBopen
);
1015 share_mode
= SVAL(inbuf
,smb_vwv0
);
1017 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1018 if (!NT_STATUS_IS_OK(status
)) {
1019 END_PROFILE(SMBopen
);
1020 return ERROR_NT(status
);
1023 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1025 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1027 unixmode
= unix_mode(conn
,aARCH
,fname
);
1029 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1030 unixmode
, oplock_request
,&rmode
,NULL
);
1033 END_PROFILE(SMBopen
);
1034 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1037 size
= sbuf
.st_size
;
1038 fmode
= dos_mode(conn
,fname
,&sbuf
);
1039 mtime
= sbuf
.st_mtime
;
1042 DEBUG(3,("attempt to open a directory %s\n",fname
));
1043 close_file(fsp
,False
);
1044 END_PROFILE(SMBopen
);
1045 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1048 outsize
= set_message(outbuf
,7,0,True
);
1049 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1050 SSVAL(outbuf
,smb_vwv1
,fmode
);
1051 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1052 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1054 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1055 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1056 SSVAL(outbuf
,smb_vwv6
,rmode
);
1058 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1059 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1061 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1062 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1063 END_PROFILE(SMBopen
);
1067 /****************************************************************************
1068 Reply to an open and X.
1069 ****************************************************************************/
1071 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1074 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1075 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1076 /* Breakout the oplock request bits so we can set the
1077 reply bits separately. */
1078 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1079 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1080 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1082 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1083 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1084 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1086 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1089 int fmode
=0,mtime
=0,rmode
=0;
1090 SMB_STRUCT_STAT sbuf
;
1092 BOOL bad_path
= False
;
1095 START_PROFILE(SMBopenX
);
1097 /* If it's an IPC, pass off the pipe handler. */
1099 if (lp_nt_pipe_support()) {
1100 END_PROFILE(SMBopenX
);
1101 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1103 END_PROFILE(SMBopenX
);
1104 return ERROR_DOS(ERRSRV
,ERRaccess
);
1108 /* XXXX we need to handle passed times, sattr and flags */
1109 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
), sizeof(fname
), 0, STR_TERMINATE
, &status
);
1110 if (!NT_STATUS_IS_OK(status
)) {
1111 END_PROFILE(SMBopenX
);
1112 return ERROR_NT(status
);
1115 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1117 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1119 unixmode
= unix_mode(conn
,smb_attr
| aARCH
, fname
);
1121 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,unixmode
,
1122 oplock_request
, &rmode
,&smb_action
);
1125 END_PROFILE(SMBopenX
);
1126 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1129 size
= sbuf
.st_size
;
1130 fmode
= dos_mode(conn
,fname
,&sbuf
);
1131 mtime
= sbuf
.st_mtime
;
1133 close_file(fsp
,False
);
1134 END_PROFILE(SMBopenX
);
1135 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1138 /* If the caller set the extended oplock request bit
1139 and we granted one (by whatever means) - set the
1140 correct bit for extended oplock reply.
1143 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1144 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1146 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1147 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1149 /* If the caller set the core oplock request bit
1150 and we granted one (by whatever means) - set the
1151 correct bit for core oplock reply.
1154 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1155 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1157 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1158 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1160 set_message(outbuf
,15,0,True
);
1161 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1162 SSVAL(outbuf
,smb_vwv3
,fmode
);
1163 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1164 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1166 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1167 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1168 SSVAL(outbuf
,smb_vwv8
,rmode
);
1169 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1171 END_PROFILE(SMBopenX
);
1172 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1175 /****************************************************************************
1176 Reply to a SMBulogoffX.
1177 ****************************************************************************/
1179 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1181 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1182 user_struct
*vuser
= get_valid_user_struct(vuid
);
1183 START_PROFILE(SMBulogoffX
);
1186 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1188 /* in user level security we are supposed to close any files
1189 open by this user */
1190 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
))
1191 file_close_user(vuid
);
1193 invalidate_vuid(vuid
);
1195 set_message(outbuf
,2,0,True
);
1197 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1199 END_PROFILE(SMBulogoffX
);
1200 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1203 /****************************************************************************
1204 Reply to a mknew or a create.
1205 ****************************************************************************/
1207 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1215 BOOL bad_path
= False
;
1217 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1218 SMB_STRUCT_STAT sbuf
;
1220 START_PROFILE(SMBcreate
);
1222 com
= SVAL(inbuf
,smb_com
);
1224 createmode
= SVAL(inbuf
,smb_vwv0
);
1225 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
) + 1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1226 if (!NT_STATUS_IS_OK(status
)) {
1227 END_PROFILE(SMBcreate
);
1228 return ERROR_NT(status
);
1231 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1233 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1235 if (createmode
& aVOLID
)
1236 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1238 unixmode
= unix_mode(conn
,createmode
,fname
);
1240 if(com
== SMBmknew
) {
1241 /* We should fail if file exists. */
1242 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1244 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1245 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1248 /* Open file in dos compatibility share mode. */
1249 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1250 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1253 END_PROFILE(SMBcreate
);
1254 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1257 outsize
= set_message(outbuf
,1,0,True
);
1258 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1260 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1261 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1263 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1264 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1266 DEBUG( 2, ( "new file %s\n", fname
) );
1267 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1269 END_PROFILE(SMBcreate
);
1273 /****************************************************************************
1274 Reply to a create temporary file.
1275 ****************************************************************************/
1277 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1283 BOOL bad_path
= False
;
1285 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1287 SMB_STRUCT_STAT sbuf
;
1291 START_PROFILE(SMBctemp
);
1293 createmode
= SVAL(inbuf
,smb_vwv0
);
1294 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1295 if (!NT_STATUS_IS_OK(status
)) {
1296 END_PROFILE(SMBctemp
);
1297 return ERROR_NT(status
);
1299 pstrcat(fname
,"\\TMXXXXXX");
1301 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1303 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1305 unixmode
= unix_mode(conn
,createmode
,fname
);
1307 tmpfd
= smb_mkstemp(fname
);
1309 END_PROFILE(SMBctemp
);
1310 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1313 SMB_VFS_STAT(conn
,fname
,&sbuf
);
1315 /* Open file in dos compatibility share mode. */
1316 /* We should fail if file does not exist. */
1317 fsp
= open_file_shared(conn
,fname
,&sbuf
,
1318 SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1319 FILE_EXISTS_OPEN
|FILE_FAIL_IF_NOT_EXIST
,
1320 unixmode
, oplock_request
, NULL
, NULL
);
1322 /* close fd from smb_mkstemp() */
1326 END_PROFILE(SMBctemp
);
1327 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1330 outsize
= set_message(outbuf
,1,0,True
);
1331 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1333 /* the returned filename is relative to the directory */
1334 s
= strrchr_m(fname
, '/');
1340 p
= smb_buf(outbuf
);
1341 SSVALS(p
, 0, -1); /* what is this? not in spec */
1342 SSVAL(p
, 2, strlen(s
));
1344 p
+= srvstr_push(outbuf
, p
, s
, -1, STR_ASCII
);
1345 outsize
= set_message_end(outbuf
, p
);
1347 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1348 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1350 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1351 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1353 DEBUG( 2, ( "created temp file %s\n", fname
) );
1354 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1355 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1357 END_PROFILE(SMBctemp
);
1361 /*******************************************************************
1362 Check if a user is allowed to rename a file.
1363 ********************************************************************/
1365 static NTSTATUS
can_rename(char *fname
,connection_struct
*conn
, SMB_STRUCT_STAT
*pst
)
1371 if (!CAN_WRITE(conn
))
1372 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1374 if (S_ISDIR(pst
->st_mode
))
1375 return NT_STATUS_OK
;
1377 /* We need a better way to return NT status codes from open... */
1381 fsp
= open_file_shared1(conn
, fname
, pst
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1382 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1385 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1386 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1387 ret
= NT_STATUS_SHARING_VIOLATION
;
1390 unix_ERR_ntstatus
= NT_STATUS_OK
;
1393 close_file(fsp
,False
);
1394 return NT_STATUS_OK
;
1397 /*******************************************************************
1398 Check if a user is allowed to delete a file.
1399 ********************************************************************/
1401 static NTSTATUS
can_delete(char *fname
,connection_struct
*conn
, int dirtype
, BOOL bad_path
)
1403 SMB_STRUCT_STAT sbuf
;
1409 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1412 if (!CAN_WRITE(conn
))
1413 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1415 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
) != 0) {
1416 if(errno
== ENOENT
) {
1418 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1420 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1422 return map_nt_error_from_unix(errno
);
1425 fmode
= dos_mode(conn
,fname
,&sbuf
);
1427 /* Can't delete a directory. */
1429 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1431 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
1432 return NT_STATUS_OBJECT_NAME_INVALID
;
1433 #endif /* JRATEST */
1435 if (!lp_delete_readonly(SNUM(conn
))) {
1437 return NT_STATUS_CANNOT_DELETE
;
1439 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1440 return NT_STATUS_NO_SUCH_FILE
;
1442 /* We need a better way to return NT status codes from open... */
1446 fsp
= open_file_shared1(conn
, fname
, &sbuf
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1447 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1450 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1451 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus
))
1452 ret
= unix_ERR_ntstatus
;
1453 else if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1454 ret
= NT_STATUS_SHARING_VIOLATION
;
1457 unix_ERR_ntstatus
= NT_STATUS_OK
;
1460 close_file(fsp
,False
);
1461 return NT_STATUS_OK
;
1464 /****************************************************************************
1465 The guts of the unlink command, split out so it may be called by the NT SMB
1467 ****************************************************************************/
1469 NTSTATUS
unlink_internals(connection_struct
*conn
, int dirtype
, char *name
)
1475 NTSTATUS error
= NT_STATUS_OK
;
1477 BOOL bad_path
= False
;
1479 SMB_STRUCT_STAT sbuf
;
1481 *directory
= *mask
= 0;
1483 /* We must check for wildcards in the name given
1484 * directly by the client - before any unmangling.
1485 * This prevents an unmangling of a UNIX name containing
1486 * a DOS wildcard like '*' or '?' from unmangling into
1487 * a wildcard delete which was not intended.
1488 * FIX for #226. JRA.
1491 has_wild
= ms_has_wild(name
);
1493 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1495 p
= strrchr_m(name
,'/');
1497 pstrcpy(directory
,".");
1501 pstrcpy(directory
,name
);
1506 * We should only check the mangled cache
1507 * here if unix_convert failed. This means
1508 * that the path in 'mask' doesn't exist
1509 * on the file system and so we need to look
1510 * for a possible mangle. This patch from
1511 * Tine Smukavec <valentin.smukavec@hermes.si>.
1514 if (!rc
&& mangle_is_mangled(mask
))
1515 mangle_check_cache( mask
);
1518 pstrcat(directory
,"/");
1519 pstrcat(directory
,mask
);
1520 error
= can_delete(directory
,conn
,dirtype
,bad_path
);
1521 if (!NT_STATUS_IS_OK(error
))
1524 if (SMB_VFS_UNLINK(conn
,directory
) == 0) {
1528 void *dirptr
= NULL
;
1531 if (check_name(directory
,conn
))
1532 dirptr
= OpenDir(conn
, directory
, True
);
1534 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1535 the pattern matches against the long name, otherwise the short name
1536 We don't implement this yet XXXX
1540 error
= NT_STATUS_NO_SUCH_FILE
;
1542 if (strequal(mask
,"????????.???"))
1545 while ((dname
= ReadDirName(dirptr
))) {
1547 BOOL sys_direntry
= False
;
1548 pstrcpy(fname
,dname
);
1550 /* Quick check for "." and ".." */
1551 if (fname
[0] == '.') {
1552 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
1553 if ((dirtype
& aDIR
)) {
1554 sys_direntry
= True
;
1561 if(!mask_match(fname
, mask
, case_sensitive
))
1565 error
= NT_STATUS_OBJECT_NAME_INVALID
;
1569 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1570 error
= can_delete(fname
,conn
,dirtype
,bad_path
);
1571 if (!NT_STATUS_IS_OK(error
))
1573 if (SMB_VFS_UNLINK(conn
,fname
) == 0)
1575 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
1581 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
1582 error
= map_nt_error_from_unix(errno
);
1588 /****************************************************************************
1590 ****************************************************************************/
1592 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
1599 START_PROFILE(SMBunlink
);
1601 dirtype
= SVAL(inbuf
,smb_vwv0
);
1603 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
);
1604 if (!NT_STATUS_IS_OK(status
)) {
1605 END_PROFILE(SMBunlink
);
1606 return ERROR_NT(status
);
1609 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
1611 DEBUG(3,("reply_unlink : %s\n",name
));
1613 status
= unlink_internals(conn
, dirtype
, name
);
1614 if (!NT_STATUS_IS_OK(status
))
1615 return ERROR_NT(status
);
1618 * Win2k needs a changenotify request response before it will
1619 * update after a rename..
1621 process_pending_change_notify_queue((time_t)0);
1623 outsize
= set_message(outbuf
,0,0,True
);
1625 END_PROFILE(SMBunlink
);
1629 /****************************************************************************
1631 ****************************************************************************/
1633 void fail_readraw(void)
1636 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1638 exit_server(errstr
);
1641 /****************************************************************************
1642 Use sendfile in readbraw.
1643 ****************************************************************************/
1645 void send_file_readbraw(connection_struct
*conn
, files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
,
1646 ssize_t mincount
, char *outbuf
)
1650 #if defined(WITH_SENDFILE)
1652 * We can only use sendfile on a non-chained packet and on a file
1653 * that is exclusively oplocked. reply_readbraw has already checked the length.
1656 if ((nread
> 0) && (lp_write_cache_size(SNUM(conn
)) == 0) &&
1657 EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) && lp_use_sendfile(SNUM(conn
)) ) {
1660 _smb_setlen(outbuf
,nread
);
1661 header
.data
= outbuf
;
1665 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, nread
) == -1) {
1667 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1668 * return ENOSYS then pretend we just got a normal read.
1670 if (errno
== ENOSYS
)
1673 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1674 fsp
->fsp_name
, strerror(errno
) ));
1675 exit_server("send_file_readbraw sendfile failed");
1684 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
1685 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1694 _smb_setlen(outbuf
,ret
);
1695 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
1699 /****************************************************************************
1700 Reply to a readbraw (core+ protocol).
1701 ****************************************************************************/
1703 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1705 extern struct current_user current_user
;
1706 ssize_t maxcount
,mincount
;
1709 char *header
= outbuf
;
1711 START_PROFILE(SMBreadbraw
);
1713 if (srv_is_signing_active()) {
1714 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1718 * Special check if an oplock break has been issued
1719 * and the readraw request croses on the wire, we must
1720 * return a zero length response here.
1723 if(global_oplock_break
) {
1724 _smb_setlen(header
,0);
1725 if (write_data(smbd_server_fd(),header
,4) != 4)
1727 DEBUG(5,("readbraw - oplock break finished\n"));
1728 END_PROFILE(SMBreadbraw
);
1732 fsp
= file_fsp(inbuf
,smb_vwv0
);
1734 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1736 * fsp could be NULL here so use the value from the packet. JRA.
1738 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
1739 _smb_setlen(header
,0);
1740 if (write_data(smbd_server_fd(),header
,4) != 4)
1742 END_PROFILE(SMBreadbraw
);
1746 CHECK_FSP(fsp
,conn
);
1748 flush_write_cache(fsp
, READRAW_FLUSH
);
1750 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
1751 if(CVAL(inbuf
,smb_wct
) == 10) {
1753 * This is a large offset (64 bit) read.
1755 #ifdef LARGE_SMB_OFF_T
1757 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
1759 #else /* !LARGE_SMB_OFF_T */
1762 * Ensure we haven't been sent a >32 bit offset.
1765 if(IVAL(inbuf
,smb_vwv8
) != 0) {
1766 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1767 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
1768 _smb_setlen(header
,0);
1769 if (write_data(smbd_server_fd(),header
,4) != 4)
1771 END_PROFILE(SMBreadbraw
);
1775 #endif /* LARGE_SMB_OFF_T */
1778 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
1779 _smb_setlen(header
,0);
1780 if (write_data(smbd_server_fd(),header
,4) != 4)
1782 END_PROFILE(SMBreadbraw
);
1786 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
1787 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
1789 /* ensure we don't overrun the packet size */
1790 maxcount
= MIN(65535,maxcount
);
1792 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1793 SMB_OFF_T size
= fsp
->size
;
1794 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
1796 if (size
< sizeneeded
) {
1798 if (SMB_VFS_FSTAT(fsp
,fsp
->fd
,&st
) == 0)
1800 if (!fsp
->can_write
)
1804 if (startpos
>= size
)
1807 nread
= MIN(maxcount
,(size
- startpos
));
1810 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1811 if (nread
< mincount
)
1815 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp
->fnum
, (double)startpos
,
1816 (int)maxcount
, (int)mincount
, (int)nread
) );
1818 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
, outbuf
);
1820 DEBUG(5,("readbraw finished\n"));
1821 END_PROFILE(SMBreadbraw
);
1825 /****************************************************************************
1826 Reply to a lockread (core+ protocol).
1827 ****************************************************************************/
1829 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
1837 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1838 BOOL my_lock_ctx
= False
;
1839 START_PROFILE(SMBlockread
);
1841 CHECK_FSP(fsp
,conn
);
1844 release_level_2_oplocks_on_change(fsp
);
1846 numtoread
= SVAL(inbuf
,smb_vwv1
);
1847 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1849 outsize
= set_message(outbuf
,5,3,True
);
1850 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1851 data
= smb_buf(outbuf
) + 3;
1854 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1855 * protocol request that predates the read/write lock concept.
1856 * Thus instead of asking for a read lock here we need to ask
1857 * for a write lock. JRA.
1858 * Note that the requested lock size is unaffected by max_recv.
1861 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
),
1862 (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
, &my_lock_ctx
);
1864 if (NT_STATUS_V(status
)) {
1867 * We used to make lockread a blocking lock. It turns out
1868 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1872 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
1874 * A blocking lock was requested. Package up
1875 * this smb into a queued request and push it
1876 * onto the blocking lock queue.
1878 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)startpos
,
1879 (SMB_BIG_UINT
)numtoread
)) {
1880 END_PROFILE(SMBlockread
);
1885 END_PROFILE(SMBlockread
);
1886 return ERROR_NT(status
);
1890 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1893 if (numtoread
> max_recv
) {
1894 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1895 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1896 (unsigned int)numtoread
, (unsigned int)max_recv
));
1897 numtoread
= MIN(numtoread
,max_recv
);
1899 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1902 END_PROFILE(SMBlockread
);
1903 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1907 SSVAL(outbuf
,smb_vwv0
,nread
);
1908 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1909 SSVAL(smb_buf(outbuf
),1,nread
);
1911 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1912 fsp
->fnum
, (int)numtoread
, (int)nread
));
1914 END_PROFILE(SMBlockread
);
1918 /****************************************************************************
1920 ****************************************************************************/
1922 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
1929 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1930 START_PROFILE(SMBread
);
1932 CHECK_FSP(fsp
,conn
);
1935 numtoread
= SVAL(inbuf
,smb_vwv1
);
1936 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1938 outsize
= set_message(outbuf
,5,3,True
);
1939 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1941 * The requested read size cannot be greater than max_recv. JRA.
1943 if (numtoread
> max_recv
) {
1944 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1945 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1946 (unsigned int)numtoread
, (unsigned int)max_recv
));
1947 numtoread
= MIN(numtoread
,max_recv
);
1950 data
= smb_buf(outbuf
) + 3;
1952 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1953 END_PROFILE(SMBread
);
1954 return ERROR_DOS(ERRDOS
,ERRlock
);
1958 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1961 END_PROFILE(SMBread
);
1962 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1966 SSVAL(outbuf
,smb_vwv0
,nread
);
1967 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1968 SCVAL(smb_buf(outbuf
),0,1);
1969 SSVAL(smb_buf(outbuf
),1,nread
);
1971 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1972 fsp
->fnum
, (int)numtoread
, (int)nread
) );
1974 END_PROFILE(SMBread
);
1978 /****************************************************************************
1979 Reply to a read and X - possibly using sendfile.
1980 ****************************************************************************/
1982 int send_file_readX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,
1983 files_struct
*fsp
, SMB_OFF_T startpos
, size_t smb_maxcnt
)
1986 char *data
= smb_buf(outbuf
);
1988 #if defined(WITH_SENDFILE)
1990 * We can only use sendfile on a non-chained packet and on a file
1991 * that is exclusively oplocked.
1994 if ((CVAL(inbuf
,smb_vwv0
) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) &&
1995 lp_use_sendfile(SNUM(conn
)) && (lp_write_cache_size(SNUM(conn
)) == 0) ) {
1996 SMB_STRUCT_STAT sbuf
;
1999 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1)
2000 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2002 if (startpos
> sbuf
.st_size
)
2005 if (smb_maxcnt
> (sbuf
.st_size
- startpos
))
2006 smb_maxcnt
= (sbuf
.st_size
- startpos
);
2008 if (smb_maxcnt
== 0)
2012 * Set up the packet header before send. We
2013 * assume here the sendfile will work (get the
2014 * correct amount of data).
2017 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2018 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
2019 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2020 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
2021 SCVAL(outbuf
,smb_vwv0
,0xFF);
2022 set_message(outbuf
,12,smb_maxcnt
,False
);
2023 header
.data
= outbuf
;
2024 header
.length
= data
- outbuf
;
2027 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, smb_maxcnt
) == -1) {
2029 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2030 * return ENOSYS then pretend we just got a normal read.
2032 if (errno
== ENOSYS
)
2035 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2036 fsp
->fsp_name
, strerror(errno
) ));
2037 exit_server("send_file_readX sendfile failed");
2040 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2041 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2049 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2052 END_PROFILE(SMBreadX
);
2053 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2056 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2057 SSVAL(outbuf
,smb_vwv5
,nread
);
2058 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2059 SSVAL(smb_buf(outbuf
),-2,nread
);
2061 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2062 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2067 /****************************************************************************
2068 Reply to a read and X.
2069 ****************************************************************************/
2071 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2073 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2074 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2076 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2078 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2081 START_PROFILE(SMBreadX
);
2083 /* If it's an IPC, pass off the pipe handler. */
2085 END_PROFILE(SMBreadX
);
2086 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2089 CHECK_FSP(fsp
,conn
);
2092 set_message(outbuf
,12,0,True
);
2094 if(CVAL(inbuf
,smb_wct
) == 12) {
2095 #ifdef LARGE_SMB_OFF_T
2097 * This is a large offset (64 bit) read.
2099 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2101 #else /* !LARGE_SMB_OFF_T */
2104 * Ensure we haven't been sent a >32 bit offset.
2107 if(IVAL(inbuf
,smb_vwv10
) != 0) {
2108 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2109 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
2110 END_PROFILE(SMBreadX
);
2111 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2114 #endif /* LARGE_SMB_OFF_T */
2118 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2119 END_PROFILE(SMBreadX
);
2120 return ERROR_DOS(ERRDOS
,ERRlock
);
2123 nread
= send_file_readX(conn
, inbuf
, outbuf
, length
, fsp
, startpos
, smb_maxcnt
);
2125 nread
= chain_reply(inbuf
,outbuf
,length
,bufsize
);
2127 END_PROFILE(SMBreadX
);
2131 /****************************************************************************
2132 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2133 ****************************************************************************/
2135 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2138 ssize_t total_written
=0;
2139 size_t numtowrite
=0;
2144 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2146 START_PROFILE(SMBwritebraw
);
2148 if (srv_is_signing_active()) {
2149 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2152 CHECK_FSP(fsp
,conn
);
2155 tcount
= IVAL(inbuf
,smb_vwv1
);
2156 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2157 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2159 /* We have to deal with slightly different formats depending
2160 on whether we are using the core+ or lanman1.0 protocol */
2162 if(Protocol
<= PROTOCOL_COREPLUS
) {
2163 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2164 data
= smb_buf(inbuf
);
2166 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2167 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2170 /* force the error type */
2171 SCVAL(inbuf
,smb_com
,SMBwritec
);
2172 SCVAL(outbuf
,smb_com
,SMBwritec
);
2174 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2175 END_PROFILE(SMBwritebraw
);
2176 return(ERROR_DOS(ERRDOS
,ERRlock
));
2180 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2182 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2183 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2185 if (nwritten
< (ssize_t
)numtowrite
) {
2186 END_PROFILE(SMBwritebraw
);
2187 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2190 total_written
= nwritten
;
2192 /* Return a message to the redirector to tell it to send more bytes */
2193 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
2194 SSVALS(outbuf
,smb_vwv0
,-1);
2195 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2196 if (!send_smb(smbd_server_fd(),outbuf
))
2197 exit_server("reply_writebraw: send_smb failed.");
2199 /* Now read the raw data into the buffer and write it */
2200 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2201 exit_server("secondary writebraw failed");
2204 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2205 numtowrite
= smb_len(inbuf
);
2207 /* Set up outbuf to return the correct return */
2208 outsize
= set_message(outbuf
,1,0,True
);
2209 SCVAL(outbuf
,smb_com
,SMBwritec
);
2210 SSVAL(outbuf
,smb_vwv0
,total_written
);
2212 if (numtowrite
!= 0) {
2214 if (numtowrite
> BUFFER_SIZE
) {
2215 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2216 (unsigned int)numtowrite
));
2217 exit_server("secondary writebraw failed");
2220 if (tcount
> nwritten
+numtowrite
) {
2221 DEBUG(3,("Client overestimated the write %d %d %d\n",
2222 (int)tcount
,(int)nwritten
,(int)numtowrite
));
2225 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
2226 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2228 exit_server("secondary writebraw failed");
2231 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
2233 if (nwritten
< (ssize_t
)numtowrite
) {
2234 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2235 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2239 total_written
+= nwritten
;
2242 if ((lp_syncalways(SNUM(conn
)) || write_through
) && lp_strict_sync(SNUM(conn
)))
2243 sync_file(conn
,fsp
);
2245 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2246 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
2248 /* we won't return a status if write through is not selected - this follows what WfWg does */
2249 END_PROFILE(SMBwritebraw
);
2250 if (!write_through
&& total_written
==tcount
) {
2252 #if RABBIT_PELLET_FIX
2254 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2255 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2257 if (!send_keepalive(smbd_server_fd()))
2258 exit_server("reply_writebraw: send of keepalive failed");
2266 /****************************************************************************
2267 Reply to a writeunlock (core+).
2268 ****************************************************************************/
2270 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
,
2271 int size
, int dum_buffsize
)
2273 ssize_t nwritten
= -1;
2277 NTSTATUS status
= NT_STATUS_OK
;
2278 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2280 START_PROFILE(SMBwriteunlock
);
2282 CHECK_FSP(fsp
,conn
);
2285 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2286 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2287 data
= smb_buf(inbuf
) + 3;
2289 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
,
2290 WRITE_LOCK
,False
)) {
2291 END_PROFILE(SMBwriteunlock
);
2292 return ERROR_DOS(ERRDOS
,ERRlock
);
2295 /* The special X/Open SMB protocol handling of
2296 zero length writes is *NOT* done for
2301 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2303 if (lp_syncalways(SNUM(conn
)))
2304 sync_file(conn
,fsp
);
2306 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2307 END_PROFILE(SMBwriteunlock
);
2308 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2312 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)numtowrite
,
2313 (SMB_BIG_UINT
)startpos
);
2314 if (NT_STATUS_V(status
)) {
2315 END_PROFILE(SMBwriteunlock
);
2316 return ERROR_NT(status
);
2320 outsize
= set_message(outbuf
,1,0,True
);
2322 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2324 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2325 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2327 END_PROFILE(SMBwriteunlock
);
2331 /****************************************************************************
2333 ****************************************************************************/
2335 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2338 ssize_t nwritten
= -1;
2341 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2343 START_PROFILE(SMBwrite
);
2345 /* If it's an IPC, pass off the pipe handler. */
2347 END_PROFILE(SMBwrite
);
2348 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2351 CHECK_FSP(fsp
,conn
);
2354 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2355 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2356 data
= smb_buf(inbuf
) + 3;
2358 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2359 END_PROFILE(SMBwrite
);
2360 return ERROR_DOS(ERRDOS
,ERRlock
);
2364 * X/Open SMB protocol says that if smb_vwv1 is
2365 * zero then the file size should be extended or
2366 * truncated to the size given in smb_vwv[2-3].
2369 if(numtowrite
== 0) {
2371 * This is actually an allocate call, and set EOF. JRA.
2373 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2375 END_PROFILE(SMBwrite
);
2376 return ERROR_NT(NT_STATUS_DISK_FULL
);
2378 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2380 END_PROFILE(SMBwrite
);
2381 return ERROR_NT(NT_STATUS_DISK_FULL
);
2384 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2386 if (lp_syncalways(SNUM(conn
)))
2387 sync_file(conn
,fsp
);
2389 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2390 END_PROFILE(SMBwrite
);
2391 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2394 outsize
= set_message(outbuf
,1,0,True
);
2396 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2398 if (nwritten
< (ssize_t
)numtowrite
) {
2399 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2400 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2403 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2405 END_PROFILE(SMBwrite
);
2409 /****************************************************************************
2410 Reply to a write and X.
2411 ****************************************************************************/
2413 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2415 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2416 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2417 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2418 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2419 ssize_t nwritten
= -1;
2420 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2421 unsigned int smblen
= smb_len(inbuf
);
2423 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2424 START_PROFILE(SMBwriteX
);
2426 /* If it's an IPC, pass off the pipe handler. */
2428 END_PROFILE(SMBwriteX
);
2429 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2432 CHECK_FSP(fsp
,conn
);
2435 /* Deal with possible LARGE_WRITEX */
2437 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2439 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2440 END_PROFILE(SMBwriteX
);
2441 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2444 data
= smb_base(inbuf
) + smb_doff
;
2446 if(CVAL(inbuf
,smb_wct
) == 14) {
2447 #ifdef LARGE_SMB_OFF_T
2449 * This is a large offset (64 bit) write.
2451 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2453 #else /* !LARGE_SMB_OFF_T */
2456 * Ensure we haven't been sent a >32 bit offset.
2459 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2460 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2461 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2462 END_PROFILE(SMBwriteX
);
2463 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2466 #endif /* LARGE_SMB_OFF_T */
2469 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2470 END_PROFILE(SMBwriteX
);
2471 return ERROR_DOS(ERRDOS
,ERRlock
);
2474 /* X/Open SMB protocol says that, unlike SMBwrite
2475 if the length is zero then NO truncation is
2476 done, just a write of zero. To truncate a file,
2482 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2484 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2485 END_PROFILE(SMBwriteX
);
2486 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2489 set_message(outbuf
,6,0,True
);
2491 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2493 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2495 if (nwritten
< (ssize_t
)numtowrite
) {
2496 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2497 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2500 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2501 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2503 if (lp_syncalways(SNUM(conn
)) || write_through
)
2504 sync_file(conn
,fsp
);
2506 END_PROFILE(SMBwriteX
);
2507 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2510 /****************************************************************************
2512 ****************************************************************************/
2514 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2520 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2521 START_PROFILE(SMBlseek
);
2523 CHECK_FSP(fsp
,conn
);
2525 flush_write_cache(fsp
, SEEK_FLUSH
);
2527 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2528 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2529 startpos
= (SMB_OFF_T
)IVALS(inbuf
,smb_vwv2
);
2538 res
= fsp
->pos
+ startpos
;
2549 if (umode
== SEEK_END
) {
2550 if((res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
2551 if(errno
== EINVAL
) {
2552 SMB_OFF_T current_pos
= startpos
;
2553 SMB_STRUCT_STAT sbuf
;
2555 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1) {
2556 END_PROFILE(SMBlseek
);
2557 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2560 current_pos
+= sbuf
.st_size
;
2562 res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,0,SEEK_SET
);
2567 END_PROFILE(SMBlseek
);
2568 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2574 outsize
= set_message(outbuf
,2,0,True
);
2575 SIVAL(outbuf
,smb_vwv0
,res
);
2577 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2578 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
2580 END_PROFILE(SMBlseek
);
2584 /****************************************************************************
2586 ****************************************************************************/
2588 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2590 int outsize
= set_message(outbuf
,0,0,True
);
2591 uint16 fnum
= SVAL(inbuf
,smb_vwv0
);
2592 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2593 START_PROFILE(SMBflush
);
2596 CHECK_FSP(fsp
,conn
);
2599 file_sync_all(conn
);
2601 sync_file(conn
,fsp
);
2604 DEBUG(3,("flush\n"));
2605 END_PROFILE(SMBflush
);
2609 /****************************************************************************
2611 ****************************************************************************/
2613 int reply_exit(connection_struct
*conn
,
2614 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2617 START_PROFILE(SMBexit
);
2619 file_close_pid(SVAL(inbuf
,smb_pid
));
2621 outsize
= set_message(outbuf
,0,0,True
);
2623 DEBUG(3,("exit\n"));
2625 END_PROFILE(SMBexit
);
2629 /****************************************************************************
2630 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2631 ****************************************************************************/
2633 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2636 extern struct current_user current_user
;
2639 int32 eclass
= 0, err
= 0;
2640 files_struct
*fsp
= NULL
;
2641 START_PROFILE(SMBclose
);
2643 outsize
= set_message(outbuf
,0,0,True
);
2645 /* If it's an IPC, pass off to the pipe handler. */
2647 END_PROFILE(SMBclose
);
2648 return reply_pipe_close(conn
, inbuf
,outbuf
);
2651 fsp
= file_fsp(inbuf
,smb_vwv0
);
2654 * We can only use CHECK_FSP if we know it's not a directory.
2657 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= current_user
.vuid
)) {
2658 END_PROFILE(SMBclose
);
2659 return ERROR_DOS(ERRDOS
,ERRbadfid
);
2662 if(fsp
->is_directory
) {
2664 * Special case - close NT SMB directory handle.
2666 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
2667 close_file(fsp
,True
);
2670 * Close ordinary file.
2675 /* Save the name for time set in close. */
2676 pstrcpy( file_name
, fsp
->fsp_name
);
2678 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2680 conn
->num_files_open
));
2683 * close_file() returns the unix errno if an error
2684 * was detected on close - normally this is due to
2685 * a disk full error. If not then it was probably an I/O error.
2688 if((close_err
= close_file(fsp
,True
)) != 0) {
2690 END_PROFILE(SMBclose
);
2691 return (UNIXERROR(ERRHRD
,ERRgeneral
));
2695 * Now take care of any time sent in the close.
2698 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2700 /* try and set the date */
2701 set_filetime(conn
, file_name
, mtime
);
2705 /* We have a cached error */
2707 END_PROFILE(SMBclose
);
2708 return ERROR_DOS(eclass
,err
);
2711 END_PROFILE(SMBclose
);
2715 /****************************************************************************
2716 Reply to a writeclose (Core+ protocol).
2717 ****************************************************************************/
2719 int reply_writeclose(connection_struct
*conn
,
2720 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2723 ssize_t nwritten
= -1;
2729 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2730 START_PROFILE(SMBwriteclose
);
2732 CHECK_FSP(fsp
,conn
);
2735 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2736 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2737 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2738 data
= smb_buf(inbuf
) + 1;
2740 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2741 END_PROFILE(SMBwriteclose
);
2742 return ERROR_DOS(ERRDOS
,ERRlock
);
2745 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2747 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2750 * More insanity. W2K only closes the file if writelen > 0.
2755 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2757 close_err
= close_file(fsp
,True
);
2760 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2761 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
2762 conn
->num_files_open
));
2764 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2765 END_PROFILE(SMBwriteclose
);
2766 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2769 if(close_err
!= 0) {
2771 END_PROFILE(SMBwriteclose
);
2772 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2775 outsize
= set_message(outbuf
,1,0,True
);
2777 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2778 END_PROFILE(SMBwriteclose
);
2782 /****************************************************************************
2784 ****************************************************************************/
2786 int reply_lock(connection_struct
*conn
,
2787 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
2789 int outsize
= set_message(outbuf
,0,0,True
);
2790 SMB_BIG_UINT count
,offset
;
2792 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2793 BOOL my_lock_ctx
= False
;
2795 START_PROFILE(SMBlock
);
2797 CHECK_FSP(fsp
,conn
);
2799 release_level_2_oplocks_on_change(fsp
);
2801 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2802 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2804 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2805 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
2807 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
, WRITE_LOCK
, &my_lock_ctx
);
2808 if (NT_STATUS_V(status
)) {
2810 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2811 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
2813 * A blocking lock was requested. Package up
2814 * this smb into a queued request and push it
2815 * onto the blocking lock queue.
2817 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), offset
, count
)) {
2818 END_PROFILE(SMBlock
);
2823 END_PROFILE(SMBlock
);
2824 return ERROR_NT(status
);
2827 END_PROFILE(SMBlock
);
2831 /****************************************************************************
2833 ****************************************************************************/
2835 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2838 int outsize
= set_message(outbuf
,0,0,True
);
2839 SMB_BIG_UINT count
,offset
;
2841 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2842 START_PROFILE(SMBunlock
);
2844 CHECK_FSP(fsp
,conn
);
2846 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2847 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2849 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
);
2850 if (NT_STATUS_V(status
)) {
2851 END_PROFILE(SMBunlock
);
2852 return ERROR_NT(status
);
2855 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2856 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
2858 END_PROFILE(SMBunlock
);
2862 /****************************************************************************
2864 ****************************************************************************/
2866 int reply_tdis(connection_struct
*conn
,
2867 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2869 int outsize
= set_message(outbuf
,0,0,True
);
2871 START_PROFILE(SMBtdis
);
2873 vuid
= SVAL(inbuf
,smb_uid
);
2876 DEBUG(4,("Invalid connection in tdis\n"));
2877 END_PROFILE(SMBtdis
);
2878 return ERROR_DOS(ERRSRV
,ERRinvnid
);
2883 close_cnum(conn
,vuid
);
2885 END_PROFILE(SMBtdis
);
2889 /****************************************************************************
2891 ****************************************************************************/
2893 int reply_echo(connection_struct
*conn
,
2894 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2896 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2898 unsigned int data_len
= smb_buflen(inbuf
);
2899 int outsize
= set_message(outbuf
,1,data_len
,True
);
2900 START_PROFILE(SMBecho
);
2902 if (data_len
> BUFFER_SIZE
) {
2903 DEBUG(0,("reply_echo: data_len too large.\n"));
2904 END_PROFILE(SMBecho
);
2908 /* copy any incoming data back out */
2910 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2912 if (smb_reverb
> 100) {
2913 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2917 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2918 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2920 smb_setlen(outbuf
,outsize
- 4);
2922 if (!send_smb(smbd_server_fd(),outbuf
))
2923 exit_server("reply_echo: send_smb failed.");
2926 DEBUG(3,("echo %d times\n", smb_reverb
));
2930 END_PROFILE(SMBecho
);
2934 /****************************************************************************
2935 Reply to a printopen.
2936 ****************************************************************************/
2938 int reply_printopen(connection_struct
*conn
,
2939 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2943 START_PROFILE(SMBsplopen
);
2945 if (!CAN_PRINT(conn
)) {
2946 END_PROFILE(SMBsplopen
);
2947 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2950 /* Open for exclusive use, write only. */
2951 fsp
= print_fsp_open(conn
, NULL
);
2954 END_PROFILE(SMBsplopen
);
2955 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2958 outsize
= set_message(outbuf
,1,0,True
);
2959 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2961 DEBUG(3,("openprint fd=%d fnum=%d\n",
2962 fsp
->fd
, fsp
->fnum
));
2964 END_PROFILE(SMBsplopen
);
2968 /****************************************************************************
2969 Reply to a printclose.
2970 ****************************************************************************/
2972 int reply_printclose(connection_struct
*conn
,
2973 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2975 int outsize
= set_message(outbuf
,0,0,True
);
2976 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2978 START_PROFILE(SMBsplclose
);
2980 CHECK_FSP(fsp
,conn
);
2982 if (!CAN_PRINT(conn
)) {
2983 END_PROFILE(SMBsplclose
);
2984 return ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
2987 DEBUG(3,("printclose fd=%d fnum=%d\n",
2988 fsp
->fd
,fsp
->fnum
));
2990 close_err
= close_file(fsp
,True
);
2992 if(close_err
!= 0) {
2994 END_PROFILE(SMBsplclose
);
2995 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2998 END_PROFILE(SMBsplclose
);
3002 /****************************************************************************
3003 Reply to a printqueue.
3004 ****************************************************************************/
3006 int reply_printqueue(connection_struct
*conn
,
3007 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3009 int outsize
= set_message(outbuf
,2,3,True
);
3010 int max_count
= SVAL(inbuf
,smb_vwv0
);
3011 int start_index
= SVAL(inbuf
,smb_vwv1
);
3012 START_PROFILE(SMBsplretq
);
3014 /* we used to allow the client to get the cnum wrong, but that
3015 is really quite gross and only worked when there was only
3016 one printer - I think we should now only accept it if they
3017 get it right (tridge) */
3018 if (!CAN_PRINT(conn
)) {
3019 END_PROFILE(SMBsplretq
);
3020 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3023 SSVAL(outbuf
,smb_vwv0
,0);
3024 SSVAL(outbuf
,smb_vwv1
,0);
3025 SCVAL(smb_buf(outbuf
),0,1);
3026 SSVAL(smb_buf(outbuf
),1,0);
3028 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3029 start_index
, max_count
));
3032 print_queue_struct
*queue
= NULL
;
3033 print_status_struct status
;
3034 char *p
= smb_buf(outbuf
) + 3;
3035 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
3036 int num_to_get
= ABS(max_count
);
3037 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
3043 num_to_get
= MIN(num_to_get
,count
-first
);
3046 for (i
=first
;i
<first
+num_to_get
;i
++) {
3047 put_dos_date2(p
,0,queue
[i
].time
);
3048 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
3049 SSVAL(p
,5, queue
[i
].job
);
3050 SIVAL(p
,7,queue
[i
].size
);
3052 srvstr_push(outbuf
, p
+12, queue
[i
].fs_user
, 16, STR_ASCII
);
3057 outsize
= set_message(outbuf
,2,28*count
+3,False
);
3058 SSVAL(outbuf
,smb_vwv0
,count
);
3059 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
3060 SCVAL(smb_buf(outbuf
),0,1);
3061 SSVAL(smb_buf(outbuf
),1,28*count
);
3066 DEBUG(3,("%d entries returned in queue\n",count
));
3069 END_PROFILE(SMBsplretq
);
3073 /****************************************************************************
3074 Reply to a printwrite.
3075 ****************************************************************************/
3077 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3080 int outsize
= set_message(outbuf
,0,0,True
);
3082 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3084 START_PROFILE(SMBsplwr
);
3086 if (!CAN_PRINT(conn
)) {
3087 END_PROFILE(SMBsplwr
);
3088 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3091 CHECK_FSP(fsp
,conn
);
3094 numtowrite
= SVAL(smb_buf(inbuf
),1);
3095 data
= smb_buf(inbuf
) + 3;
3097 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
3098 END_PROFILE(SMBsplwr
);
3099 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3102 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
3104 END_PROFILE(SMBsplwr
);
3108 /****************************************************************************
3109 The guts of the mkdir command, split out so it may be called by the NT SMB
3111 ****************************************************************************/
3113 NTSTATUS
mkdir_internal(connection_struct
*conn
, pstring directory
)
3115 BOOL bad_path
= False
;
3116 SMB_STRUCT_STAT sbuf
;
3119 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3121 if( strchr_m(directory
, ':')) {
3122 return NT_STATUS_NOT_A_DIRECTORY
;
3125 if (ms_has_wild(directory
)) {
3126 return NT_STATUS_OBJECT_NAME_INVALID
;
3129 if (check_name(directory
, conn
))
3130 ret
= vfs_MkDir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3133 if(errno
== ENOENT
) {
3135 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3137 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3139 return map_nt_error_from_unix(errno
);
3142 return NT_STATUS_OK
;
3145 /****************************************************************************
3147 ****************************************************************************/
3149 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3154 START_PROFILE(SMBmkdir
);
3156 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3157 if (!NT_STATUS_IS_OK(status
)) {
3158 END_PROFILE(SMBmkdir
);
3159 return ERROR_NT(status
);
3162 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
);
3164 status
= mkdir_internal(conn
, directory
);
3165 if (!NT_STATUS_IS_OK(status
)) {
3166 END_PROFILE(SMBmkdir
);
3167 return ERROR_NT(status
);
3170 outsize
= set_message(outbuf
,0,0,True
);
3172 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
3174 END_PROFILE(SMBmkdir
);
3178 /****************************************************************************
3179 Static function used by reply_rmdir to delete an entire directory
3180 tree recursively. Return False on ok, True on fail.
3181 ****************************************************************************/
3183 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
3185 const char *dname
= NULL
;
3187 void *dirptr
= OpenDir(conn
, directory
, False
);
3192 while((dname
= ReadDirName(dirptr
))) {
3196 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3199 /* Construct the full name. */
3200 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3206 pstrcpy(fullname
, directory
);
3207 pstrcat(fullname
, "/");
3208 pstrcat(fullname
, dname
);
3210 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
3215 if(st
.st_mode
& S_IFDIR
) {
3216 if(recursive_rmdir(conn
, fullname
)!=0) {
3220 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
3224 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
3233 /****************************************************************************
3234 The internals of the rmdir code - called elsewhere.
3235 ****************************************************************************/
3237 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
3241 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3242 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
3244 * Check to see if the only thing in this directory are
3245 * vetoed files/directories. If so then delete them and
3246 * retry. If we fail to delete any of them (and we *don't*
3247 * do a recursive delete) then fail the rmdir.
3249 BOOL all_veto_files
= True
;
3251 void *dirptr
= OpenDir(conn
, directory
, False
);
3253 if(dirptr
!= NULL
) {
3254 int dirpos
= TellDir(dirptr
);
3255 while ((dname
= ReadDirName(dirptr
))) {
3256 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3258 if(!IS_VETO_PATH(conn
, dname
)) {
3259 all_veto_files
= False
;
3264 if(all_veto_files
) {
3265 SeekDir(dirptr
,dirpos
);
3266 while ((dname
= ReadDirName(dirptr
))) {
3270 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3273 /* Construct the full name. */
3274 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3279 pstrcpy(fullname
, directory
);
3280 pstrcat(fullname
, "/");
3281 pstrcat(fullname
, dname
);
3283 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0)
3285 if(st
.st_mode
& S_IFDIR
) {
3286 if(lp_recursive_veto_delete(SNUM(conn
))) {
3287 if(recursive_rmdir(conn
, fullname
) != 0)
3290 if(SMB_VFS_RMDIR(conn
,fullname
) != 0)
3292 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0)
3296 /* Retry the rmdir */
3297 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3307 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory
,strerror(errno
)));
3312 /****************************************************************************
3314 ****************************************************************************/
3316 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3321 BOOL bad_path
= False
;
3322 SMB_STRUCT_STAT sbuf
;
3324 START_PROFILE(SMBrmdir
);
3326 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3327 if (!NT_STATUS_IS_OK(status
)) {
3328 END_PROFILE(SMBrmdir
);
3329 return ERROR_NT(status
);
3332 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3334 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3336 if (check_name(directory
,conn
)) {
3337 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3338 ok
= rmdir_internals(conn
, directory
);
3342 END_PROFILE(SMBrmdir
);
3343 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRbadpath
);
3346 outsize
= set_message(outbuf
,0,0,True
);
3348 DEBUG( 3, ( "rmdir %s\n", directory
) );
3350 END_PROFILE(SMBrmdir
);
3354 /*******************************************************************
3355 Resolve wildcards in a filename rename.
3356 ********************************************************************/
3358 static BOOL
resolve_wildcards(const char *name1
, char *name2
)
3360 fstring root1
,root2
;
3362 char *p
,*p2
, *pname1
, *pname2
;
3363 int available_space
;
3366 pname1
= strrchr_m(name1
,'/');
3367 pname2
= strrchr_m(name2
,'/');
3369 if (!pname1
|| !pname2
)
3372 fstrcpy(root1
,pname1
);
3373 fstrcpy(root2
,pname2
);
3374 p
= strrchr_m(root1
,'.');
3381 p
= strrchr_m(root2
,'.');
3415 available_space
= sizeof(pstring
) - PTR_DIFF(pname2
, name2
);
3418 snprintf(pname2
, available_space
- 1, "%s.%s", root2
, ext2
);
3420 pstrcpy_base(pname2
, root2
, name2
);
3426 /****************************************************************************
3427 Ensure open files have their names updates.
3428 ****************************************************************************/
3430 static void rename_open_files(connection_struct
*conn
, SMB_DEV_T dev
, SMB_INO_T inode
, char *newname
)
3433 BOOL did_rename
= False
;
3435 for(fsp
= file_find_di_first(dev
, inode
); fsp
; fsp
= file_find_di_next(fsp
)) {
3436 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3437 fsp
->fnum
, (unsigned int)fsp
->dev
, (double)fsp
->inode
,
3438 fsp
->fsp_name
, newname
));
3439 string_set(&fsp
->fsp_name
, newname
);
3444 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3445 (unsigned int)dev
, (double)inode
, newname
));
3448 /****************************************************************************
3449 Rename an open file - given an fsp.
3450 ****************************************************************************/
3452 NTSTATUS
rename_internals_fsp(connection_struct
*conn
, files_struct
*fsp
, char *newname
, BOOL replace_if_exists
)
3454 SMB_STRUCT_STAT sbuf
;
3455 BOOL bad_path
= False
;
3456 pstring newname_last_component
;
3457 NTSTATUS error
= NT_STATUS_OK
;
3462 rcdest
= unix_convert(newname
,conn
,newname_last_component
,&bad_path
,&sbuf
);
3464 /* Quick check for "." and ".." */
3465 if (!bad_path
&& newname_last_component
[0] == '.') {
3466 if (!newname_last_component
[1] || (newname_last_component
[1] == '.' && !newname_last_component
[2])) {
3467 return NT_STATUS_ACCESS_DENIED
;
3470 if (!rcdest
&& bad_path
) {
3471 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3474 /* Ensure newname contains a '/' */
3475 if(strrchr_m(newname
,'/') == 0) {
3478 pstrcpy(tmpstr
, "./");
3479 pstrcat(tmpstr
, newname
);
3480 pstrcpy(newname
, tmpstr
);
3484 * Check for special case with case preserving and not
3485 * case sensitive. If the old last component differs from the original
3486 * last component only by case, then we should allow
3487 * the rename (user is trying to change the case of the
3491 if((case_sensitive
== False
) && (case_preserve
== True
) &&
3492 strequal(newname
, fsp
->fsp_name
)) {
3494 pstring newname_modified_last_component
;
3497 * Get the last component of the modified name.
3498 * Note that we guarantee that newname contains a '/'
3501 p
= strrchr_m(newname
,'/');
3502 pstrcpy(newname_modified_last_component
,p
+1);
3504 if(strcsequal(newname_modified_last_component
,
3505 newname_last_component
) == False
) {
3507 * Replace the modified last component with
3510 pstrcpy(p
+1, newname_last_component
);
3515 * If the src and dest names are identical - including case,
3516 * don't do the rename, just return success.
3519 if (strcsequal(fsp
->fsp_name
, newname
)) {
3520 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3522 return NT_STATUS_OK
;
3525 dest_exists
= vfs_object_exist(conn
,newname
,NULL
);
3527 if(!replace_if_exists
&& dest_exists
) {
3528 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3529 fsp
->fsp_name
,newname
));
3530 return NT_STATUS_OBJECT_NAME_COLLISION
;
3533 error
= can_rename(newname
,conn
,&sbuf
);
3535 if (dest_exists
&& !NT_STATUS_IS_OK(error
)) {
3536 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3537 nt_errstr(error
), fsp
->fsp_name
,newname
));
3538 if (NT_STATUS_EQUAL(error
,NT_STATUS_SHARING_VIOLATION
))
3539 error
= NT_STATUS_ACCESS_DENIED
;
3543 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
3544 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3545 fsp
->fsp_name
,newname
));
3546 rename_open_files(conn
, fsp
->dev
, fsp
->inode
, newname
);
3547 return NT_STATUS_OK
;
3550 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3551 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3553 error
= map_nt_error_from_unix(errno
);
3555 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3556 nt_errstr(error
), fsp
->fsp_name
,newname
));
3561 /****************************************************************************
3562 The guts of the rename command, split out so it may be called by the NT SMB
3564 ****************************************************************************/
3566 NTSTATUS
rename_internals(connection_struct
*conn
, char *name
, char *newname
, uint16 attrs
, BOOL replace_if_exists
)
3570 pstring last_component_src
;
3571 pstring last_component_dest
;
3574 BOOL bad_path_src
= False
;
3575 BOOL bad_path_dest
= False
;
3577 NTSTATUS error
= NT_STATUS_OK
;
3580 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3582 *directory
= *mask
= 0;
3587 rc
= unix_convert(name
,conn
,last_component_src
,&bad_path_src
,&sbuf1
);
3588 if (!rc
&& bad_path_src
) {
3589 if (ms_has_wild(last_component_src
))
3590 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3591 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3594 /* Quick check for "." and ".." */
3595 if (last_component_src
[0] == '.') {
3596 if (!last_component_src
[1] || (last_component_src
[1] == '.' && !last_component_src
[2])) {
3597 return NT_STATUS_OBJECT_NAME_INVALID
;
3601 rcdest
= unix_convert(newname
,conn
,last_component_dest
,&bad_path_dest
,&sbuf2
);
3603 /* Quick check for "." and ".." */
3604 if (last_component_dest
[0] == '.') {
3605 if (!last_component_dest
[1] || (last_component_dest
[1] == '.' && !last_component_dest
[2])) {
3606 return NT_STATUS_OBJECT_NAME_INVALID
;
3611 * Split the old name into directory and last component
3612 * strings. Note that unix_convert may have stripped off a
3613 * leading ./ from both name and newname if the rename is
3614 * at the root of the share. We need to make sure either both
3615 * name and newname contain a / character or neither of them do
3616 * as this is checked in resolve_wildcards().
3619 p
= strrchr_m(name
,'/');
3621 pstrcpy(directory
,".");
3625 pstrcpy(directory
,name
);
3627 *p
= '/'; /* Replace needed for exceptional test below. */
3631 * We should only check the mangled cache
3632 * here if unix_convert failed. This means
3633 * that the path in 'mask' doesn't exist
3634 * on the file system and so we need to look
3635 * for a possible mangle. This patch from
3636 * Tine Smukavec <valentin.smukavec@hermes.si>.
3639 if (!rc
&& mangle_is_mangled(mask
))
3640 mangle_check_cache( mask
);
3642 has_wild
= ms_has_wild(mask
);
3646 * No wildcards - just process the one file.
3648 BOOL is_short_name
= mangle_is_8_3(name
, True
);
3650 /* Add a terminating '/' to the directory name. */
3651 pstrcat(directory
,"/");
3652 pstrcat(directory
,mask
);
3654 /* Ensure newname contains a '/' also */
3655 if(strrchr_m(newname
,'/') == 0) {
3658 pstrcpy(tmpstr
, "./");
3659 pstrcat(tmpstr
, newname
);
3660 pstrcpy(newname
, tmpstr
);
3663 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3664 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3665 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3666 newname
, last_component_dest
, is_short_name
));
3669 * Check for special case with case preserving and not
3670 * case sensitive, if directory and newname are identical,
3671 * and the old last component differs from the original
3672 * last component only by case, then we should allow
3673 * the rename (user is trying to change the case of the
3676 if((case_sensitive
== False
) &&
3677 (((case_preserve
== True
) &&
3678 (is_short_name
== False
)) ||
3679 ((short_case_preserve
== True
) &&
3680 (is_short_name
== True
))) &&
3681 strcsequal(directory
, newname
)) {
3682 pstring modified_last_component
;
3685 * Get the last component of the modified name.
3686 * Note that we guarantee that newname contains a '/'
3689 p
= strrchr_m(newname
,'/');
3690 pstrcpy(modified_last_component
,p
+1);
3692 if(strcsequal(modified_last_component
,
3693 last_component_dest
) == False
) {
3695 * Replace the modified last component with
3698 pstrcpy(p
+1, last_component_dest
);
3702 resolve_wildcards(directory
,newname
);
3705 * The source object must exist.
3708 if (!vfs_object_exist(conn
, directory
, &sbuf1
)) {
3709 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3710 directory
,newname
));
3712 if (errno
== ENOTDIR
|| errno
== EISDIR
|| errno
== ENOENT
) {
3714 * Must return different errors depending on whether the parent
3715 * directory existed or not.
3718 p
= strrchr_m(directory
, '/');
3720 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3722 if (vfs_object_exist(conn
, directory
, NULL
))
3723 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3724 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3726 error
= map_nt_error_from_unix(errno
);
3727 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3728 nt_errstr(error
), directory
,newname
));
3733 if (!rcdest
&& bad_path_dest
) {
3734 if (ms_has_wild(last_component_dest
))
3735 return NT_STATUS_OBJECT_NAME_INVALID
;
3736 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3739 error
= can_rename(directory
,conn
,&sbuf1
);
3741 if (!NT_STATUS_IS_OK(error
)) {
3742 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3743 nt_errstr(error
), directory
,newname
));
3748 * If the src and dest names are identical - including case,
3749 * don't do the rename, just return success.
3752 if (strcsequal(directory
, newname
)) {
3753 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3754 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory
));
3755 return NT_STATUS_OK
;
3758 if(!replace_if_exists
&& vfs_object_exist(conn
,newname
,NULL
)) {
3759 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3760 directory
,newname
));
3761 return NT_STATUS_OBJECT_NAME_COLLISION
;
3764 if(SMB_VFS_RENAME(conn
,directory
, newname
) == 0) {
3765 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3766 directory
,newname
));
3767 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3768 return NT_STATUS_OK
;
3771 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3772 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3774 error
= map_nt_error_from_unix(errno
);
3776 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3777 nt_errstr(error
), directory
,newname
));
3782 * Wildcards - process each file that matches.
3784 void *dirptr
= NULL
;
3788 if (check_name(directory
,conn
))
3789 dirptr
= OpenDir(conn
, directory
, True
);
3792 error
= NT_STATUS_NO_SUCH_FILE
;
3793 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3795 if (strequal(mask
,"????????.???"))
3798 while ((dname
= ReadDirName(dirptr
))) {
3800 BOOL sysdir_entry
= False
;
3802 pstrcpy(fname
,dname
);
3804 /* Quick check for "." and ".." */
3805 if (fname
[0] == '.') {
3806 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
3808 sysdir_entry
= True
;
3815 if(!mask_match(fname
, mask
, case_sensitive
))
3819 error
= NT_STATUS_OBJECT_NAME_INVALID
;
3823 error
= NT_STATUS_ACCESS_DENIED
;
3824 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3825 if (!vfs_object_exist(conn
, fname
, &sbuf1
)) {
3826 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3827 DEBUG(6,("rename %s failed. Error %s\n", fname
, nt_errstr(error
)));
3830 error
= can_rename(fname
,conn
,&sbuf1
);
3831 if (!NT_STATUS_IS_OK(error
)) {
3832 DEBUG(6,("rename %s refused\n", fname
));
3835 pstrcpy(destname
,newname
);
3837 if (!resolve_wildcards(fname
,destname
)) {
3838 DEBUG(6,("resolve_wildcards %s %s failed\n",
3843 if (!replace_if_exists
&&
3844 vfs_file_exist(conn
,destname
, NULL
)) {
3845 DEBUG(6,("file_exist %s\n", destname
));
3846 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3850 if (!SMB_VFS_RENAME(conn
,fname
,destname
)) {
3851 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3853 error
= NT_STATUS_OK
;
3855 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3860 if (!NT_STATUS_EQUAL(error
,NT_STATUS_NO_SUCH_FILE
)) {
3861 if (!rcdest
&& bad_path_dest
) {
3862 if (ms_has_wild(last_component_dest
))
3863 return NT_STATUS_OBJECT_NAME_INVALID
;
3864 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3869 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
3870 error
= map_nt_error_from_unix(errno
);
3876 /****************************************************************************
3878 ****************************************************************************/
3880 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
3887 uint16 attrs
= SVAL(inbuf
,smb_vwv0
);
3890 START_PROFILE(SMBmv
);
3892 p
= smb_buf(inbuf
) + 1;
3893 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
);
3894 if (!NT_STATUS_IS_OK(status
)) {
3896 return ERROR_NT(status
);
3899 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
);
3900 if (!NT_STATUS_IS_OK(status
)) {
3902 return ERROR_NT(status
);
3905 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3906 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3908 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3910 status
= rename_internals(conn
, name
, newname
, attrs
, False
);
3911 if (!NT_STATUS_IS_OK(status
)) {
3913 return ERROR_NT(status
);
3917 * Win2k needs a changenotify request response before it will
3918 * update after a rename..
3920 process_pending_change_notify_queue((time_t)0);
3921 outsize
= set_message(outbuf
,0,0,True
);
3927 /*******************************************************************
3928 Copy a file as part of a reply_copy.
3929 ******************************************************************/
3931 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3932 int count
,BOOL target_is_directory
, int *err_ret
)
3935 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
3937 files_struct
*fsp1
,*fsp2
;
3942 pstrcpy(dest
,dest1
);
3943 if (target_is_directory
) {
3944 char *p
= strrchr_m(src
,'/');
3953 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
3956 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3957 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
3962 if (!target_is_directory
&& count
)
3963 ofun
= FILE_EXISTS_OPEN
;
3965 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1)
3966 ZERO_STRUCTP(&sbuf2
);
3968 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3969 ofun
,src_sbuf
.st_mode
,0,&Access
,&action
);
3972 close_file(fsp1
,False
);
3976 if ((ofun
&3) == 1) {
3977 if(SMB_VFS_LSEEK(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
3978 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
3980 * Stop the copy from occurring.
3983 src_sbuf
.st_size
= 0;
3987 if (src_sbuf
.st_size
)
3988 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
3990 close_file(fsp1
,False
);
3992 /* Ensure the modtime is set correctly on the destination file. */
3993 fsp2
->pending_modtime
= src_sbuf
.st_mtime
;
3996 * As we are opening fsp1 read-only we only expect
3997 * an error on close on fsp2 if we are out of space.
3998 * Thus we don't look at the error return from the
4001 *err_ret
= close_file(fsp2
,False
);
4003 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
4006 /****************************************************************************
4007 Reply to a file copy.
4008 ****************************************************************************/
4010 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4015 pstring mask
,newname
;
4018 int error
= ERRnoaccess
;
4022 int tid2
= SVAL(inbuf
,smb_vwv0
);
4023 int ofun
= SVAL(inbuf
,smb_vwv1
);
4024 int flags
= SVAL(inbuf
,smb_vwv2
);
4025 BOOL target_is_directory
=False
;
4026 BOOL bad_path1
= False
;
4027 BOOL bad_path2
= False
;
4029 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4032 START_PROFILE(SMBcopy
);
4034 *directory
= *mask
= 0;
4037 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
);
4038 if (!NT_STATUS_IS_OK(status
)) {
4039 END_PROFILE(SMBcopy
);
4040 return ERROR_NT(status
);
4042 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
);
4043 if (!NT_STATUS_IS_OK(status
)) {
4044 END_PROFILE(SMBcopy
);
4045 return ERROR_NT(status
);
4048 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
4050 if (tid2
!= conn
->cnum
) {
4051 /* can't currently handle inter share copies XXXX */
4052 DEBUG(3,("Rejecting inter-share copy\n"));
4053 END_PROFILE(SMBcopy
);
4054 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
4057 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
4058 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
4060 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
4061 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
4063 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
4065 if ((flags
&1) && target_is_directory
) {
4066 END_PROFILE(SMBcopy
);
4067 return ERROR_DOS(ERRDOS
,ERRbadfile
);
4070 if ((flags
&2) && !target_is_directory
) {
4071 END_PROFILE(SMBcopy
);
4072 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4075 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
4076 /* wants a tree copy! XXXX */
4077 DEBUG(3,("Rejecting tree copy\n"));
4078 END_PROFILE(SMBcopy
);
4079 return ERROR_DOS(ERRSRV
,ERRerror
);
4082 p
= strrchr_m(name
,'/');
4084 pstrcpy(directory
,"./");
4088 pstrcpy(directory
,name
);
4093 * We should only check the mangled cache
4094 * here if unix_convert failed. This means
4095 * that the path in 'mask' doesn't exist
4096 * on the file system and so we need to look
4097 * for a possible mangle. This patch from
4098 * Tine Smukavec <valentin.smukavec@hermes.si>.
4101 if (!rc
&& mangle_is_mangled(mask
))
4102 mangle_check_cache( mask
);
4104 has_wild
= ms_has_wild(mask
);
4107 pstrcat(directory
,"/");
4108 pstrcat(directory
,mask
);
4109 if (resolve_wildcards(directory
,newname
) &&
4110 copy_file(directory
,newname
,conn
,ofun
, count
,target_is_directory
,&err
))
4114 END_PROFILE(SMBcopy
);
4115 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4118 exists
= vfs_file_exist(conn
,directory
,NULL
);
4121 void *dirptr
= NULL
;
4125 if (check_name(directory
,conn
))
4126 dirptr
= OpenDir(conn
, directory
, True
);
4131 if (strequal(mask
,"????????.???"))
4134 while ((dname
= ReadDirName(dirptr
))) {
4136 pstrcpy(fname
,dname
);
4138 if(!mask_match(fname
, mask
, case_sensitive
))
4141 error
= ERRnoaccess
;
4142 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
4143 pstrcpy(destname
,newname
);
4144 if (resolve_wildcards(fname
,destname
) &&
4145 copy_file(fname
,destname
,conn
,ofun
,
4146 count
,target_is_directory
,&err
))
4148 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
4156 /* Error on close... */
4158 END_PROFILE(SMBcopy
);
4159 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4163 END_PROFILE(SMBcopy
);
4164 return ERROR_DOS(ERRDOS
,error
);
4166 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
)) {
4167 unix_ERR_class
= ERRDOS
;
4168 unix_ERR_code
= ERRbadpath
;
4170 END_PROFILE(SMBcopy
);
4171 return(UNIXERROR(ERRDOS
,error
));
4175 outsize
= set_message(outbuf
,1,0,True
);
4176 SSVAL(outbuf
,smb_vwv0
,count
);
4178 END_PROFILE(SMBcopy
);
4182 /****************************************************************************
4184 ****************************************************************************/
4186 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4194 START_PROFILE(pathworks_setdir
);
4197 if (!CAN_SETDIR(snum
)) {
4198 END_PROFILE(pathworks_setdir
);
4199 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4202 srvstr_get_path(inbuf
, newdir
, smb_buf(inbuf
) + 1, sizeof(newdir
), 0, STR_TERMINATE
, &status
);
4203 if (!NT_STATUS_IS_OK(status
)) {
4204 END_PROFILE(pathworks_setdir
);
4205 return ERROR_NT(status
);
4208 if (strlen(newdir
) == 0) {
4211 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
4213 string_set(&conn
->connectpath
,newdir
);
4217 END_PROFILE(pathworks_setdir
);
4218 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4221 outsize
= set_message(outbuf
,0,0,True
);
4222 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
4224 DEBUG(3,("setdir %s\n", newdir
));
4226 END_PROFILE(pathworks_setdir
);
4230 /****************************************************************************
4231 Get a lock pid, dealing with large count requests.
4232 ****************************************************************************/
4234 uint16
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
4236 if(!large_file_format
)
4237 return SVAL(data
,SMB_LPID_OFFSET(data_offset
));
4239 return SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
4242 /****************************************************************************
4243 Get a lock count, dealing with large count requests.
4244 ****************************************************************************/
4246 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
4248 SMB_BIG_UINT count
= 0;
4250 if(!large_file_format
) {
4251 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
4254 #if defined(HAVE_LONGLONG)
4255 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
4256 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
4257 #else /* HAVE_LONGLONG */
4260 * NT4.x seems to be broken in that it sends large file (64 bit)
4261 * lockingX calls even if the CAP_LARGE_FILES was *not*
4262 * negotiated. For boxes without large unsigned ints truncate the
4263 * lock count by dropping the top 32 bits.
4266 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
4267 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4268 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
4269 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
4270 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
4273 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
4274 #endif /* HAVE_LONGLONG */
4280 #if !defined(HAVE_LONGLONG)
4281 /****************************************************************************
4282 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4283 ****************************************************************************/
4285 static uint32
map_lock_offset(uint32 high
, uint32 low
)
4289 uint32 highcopy
= high
;
4292 * Try and find out how many significant bits there are in high.
4295 for(i
= 0; highcopy
; i
++)
4299 * We use 31 bits not 32 here as POSIX
4300 * lock offsets may not be negative.
4303 mask
= (~0) << (31 - i
);
4306 return 0; /* Fail. */
4312 #endif /* !defined(HAVE_LONGLONG) */
4314 /****************************************************************************
4315 Get a lock offset, dealing with large offset requests.
4316 ****************************************************************************/
4318 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
4320 SMB_BIG_UINT offset
= 0;
4324 if(!large_file_format
) {
4325 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
4328 #if defined(HAVE_LONGLONG)
4329 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
4330 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
4331 #else /* HAVE_LONGLONG */
4334 * NT4.x seems to be broken in that it sends large file (64 bit)
4335 * lockingX calls even if the CAP_LARGE_FILES was *not*
4336 * negotiated. For boxes without large unsigned ints mangle the
4337 * lock offset by mapping the top 32 bits onto the lower 32.
4340 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
4341 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4342 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
4345 if((new_low
= map_lock_offset(high
, low
)) == 0) {
4347 return (SMB_BIG_UINT
)-1;
4350 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4351 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
4352 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
4353 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
4356 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4357 #endif /* HAVE_LONGLONG */
4363 /****************************************************************************
4364 Reply to a lockingX request.
4365 ****************************************************************************/
4367 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4369 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
4370 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
4371 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
4372 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
4373 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
4374 SMB_BIG_UINT count
= 0, offset
= 0;
4376 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
4379 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
4381 BOOL my_lock_ctx
= False
;
4384 START_PROFILE(SMBlockingX
);
4386 CHECK_FSP(fsp
,conn
);
4388 data
= smb_buf(inbuf
);
4390 if (locktype
& (LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_CHANGE_LOCKTYPE
)) {
4391 /* we don't support these - and CANCEL_LOCK makes w2k
4392 and XP reboot so I don't really want to be
4393 compatible! (tridge) */
4394 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
4397 /* Check if this is an oplock break on a file
4398 we have granted an oplock on.
4400 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
4401 /* Client can insist on breaking to none. */
4402 BOOL break_to_none
= (oplocklevel
== 0);
4404 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4405 (unsigned int)oplocklevel
, fsp
->fnum
));
4408 * Make sure we have granted an exclusive or batch oplock on this file.
4411 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
4412 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4413 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
4415 /* if this is a pure oplock break request then don't send a reply */
4416 if (num_locks
== 0 && num_ulocks
== 0) {
4417 END_PROFILE(SMBlockingX
);
4420 END_PROFILE(SMBlockingX
);
4421 return ERROR_DOS(ERRDOS
,ERRlock
);
4425 if (remove_oplock(fsp
, break_to_none
) == False
) {
4426 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4430 /* if this is a pure oplock break request then don't send a reply */
4431 if (num_locks
== 0 && num_ulocks
== 0) {
4432 /* Sanity check - ensure a pure oplock break is not a
4434 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
4435 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4436 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
4437 END_PROFILE(SMBlockingX
);
4443 * We do this check *after* we have checked this is not a oplock break
4444 * response message. JRA.
4447 release_level_2_oplocks_on_change(fsp
);
4449 /* Data now points at the beginning of the list
4450 of smb_unlkrng structs */
4451 for(i
= 0; i
< (int)num_ulocks
; i
++) {
4452 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4453 count
= get_lock_count( data
, i
, large_file_format
);
4454 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4457 * There is no error code marked "stupid client bug".... :-).
4460 END_PROFILE(SMBlockingX
);
4461 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4464 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4465 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
4467 status
= do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4468 if (NT_STATUS_V(status
)) {
4469 END_PROFILE(SMBlockingX
);
4470 return ERROR_NT(status
);
4474 /* Setup the timeout in seconds. */
4476 lock_timeout
= ((lock_timeout
== -1) ? -1 : (lock_timeout
+999)/1000);
4478 /* Now do any requested locks */
4479 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
4481 /* Data now points at the beginning of the list
4482 of smb_lkrng structs */
4484 for(i
= 0; i
< (int)num_locks
; i
++) {
4485 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4486 count
= get_lock_count( data
, i
, large_file_format
);
4487 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4490 * There is no error code marked "stupid client bug".... :-).
4493 END_PROFILE(SMBlockingX
);
4494 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4497 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4498 (double)offset
, (double)count
, (unsigned int)lock_pid
,
4499 fsp
->fsp_name
, (int)lock_timeout
));
4501 status
= do_lock_spin(fsp
,conn
,lock_pid
, count
,offset
,
4502 ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
), &my_lock_ctx
);
4503 if (NT_STATUS_V(status
)) {
4505 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4506 * Even if it's our own lock context, we need to wait here as
4507 * there may be an unlock on the way.
4508 * So I removed a "&& !my_lock_ctx" from the following
4509 * if statement. JRA.
4511 if ((lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
4513 * A blocking lock was requested. Package up
4514 * this smb into a queued request and push it
4515 * onto the blocking lock queue.
4517 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
, lock_pid
, offset
, count
)) {
4518 END_PROFILE(SMBlockingX
);
4526 /* If any of the above locks failed, then we must unlock
4527 all of the previous locks (X/Open spec). */
4528 if (i
!= num_locks
&& num_locks
!= 0) {
4530 * Ensure we don't do a remove on the lock that just failed,
4531 * as under POSIX rules, if we have a lock already there, we
4532 * will delete it (and we shouldn't) .....
4534 for(i
--; i
>= 0; i
--) {
4535 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4536 count
= get_lock_count( data
, i
, large_file_format
);
4537 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4540 * There is no error code marked "stupid client bug".... :-).
4543 END_PROFILE(SMBlockingX
);
4544 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4547 do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4549 END_PROFILE(SMBlockingX
);
4550 return ERROR_NT(status
);
4553 set_message(outbuf
,2,0,True
);
4555 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4556 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4558 END_PROFILE(SMBlockingX
);
4559 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4562 /****************************************************************************
4563 Reply to a SMBreadbmpx (read block multiplex) request.
4564 ****************************************************************************/
4566 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4577 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4578 START_PROFILE(SMBreadBmpx
);
4580 /* this function doesn't seem to work - disable by default */
4581 if (!lp_readbmpx()) {
4582 END_PROFILE(SMBreadBmpx
);
4583 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
4586 outsize
= set_message(outbuf
,8,0,True
);
4588 CHECK_FSP(fsp
,conn
);
4591 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
4592 maxcount
= SVAL(inbuf
,smb_vwv3
);
4594 data
= smb_buf(outbuf
);
4595 pad
= ((long)data
)%4;
4600 max_per_packet
= bufsize
-(outsize
+pad
);
4604 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
4605 END_PROFILE(SMBreadBmpx
);
4606 return ERROR_DOS(ERRDOS
,ERRlock
);
4610 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4612 nread
= read_file(fsp
,data
,startpos
,N
);
4617 if (nread
< (ssize_t
)N
)
4618 tcount
= total_read
+ nread
;
4620 set_message(outbuf
,8,nread
,False
);
4621 SIVAL(outbuf
,smb_vwv0
,startpos
);
4622 SSVAL(outbuf
,smb_vwv2
,tcount
);
4623 SSVAL(outbuf
,smb_vwv6
,nread
);
4624 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4626 if (!send_smb(smbd_server_fd(),outbuf
))
4627 exit_server("reply_readbmpx: send_smb failed.");
4629 total_read
+= nread
;
4631 } while (total_read
< (ssize_t
)tcount
);
4633 END_PROFILE(SMBreadBmpx
);
4637 /****************************************************************************
4638 Reply to a SMBsetattrE.
4639 ****************************************************************************/
4641 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4643 struct utimbuf unix_times
;
4645 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4646 START_PROFILE(SMBsetattrE
);
4648 outsize
= set_message(outbuf
,0,0,True
);
4650 if(!fsp
|| (fsp
->conn
!= conn
)) {
4651 END_PROFILE(SMBgetattrE
);
4652 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4656 * Convert the DOS times into unix times. Ignore create
4657 * time as UNIX can't set this.
4660 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4661 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4664 * Patch from Ray Frush <frush@engr.colostate.edu>
4665 * Sometimes times are sent as zero - ignore them.
4668 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0)) {
4669 /* Ignore request */
4670 if( DEBUGLVL( 3 ) ) {
4671 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4672 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4674 END_PROFILE(SMBsetattrE
);
4676 } else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0)) {
4677 /* set modify time = to access time if modify time was 0 */
4678 unix_times
.modtime
= unix_times
.actime
;
4681 /* Set the date on this file */
4682 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4683 END_PROFILE(SMBsetattrE
);
4684 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4687 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4688 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4690 END_PROFILE(SMBsetattrE
);
4695 /* Back from the dead for OS/2..... JRA. */
4697 /****************************************************************************
4698 Reply to a SMBwritebmpx (write block multiplex primary) request.
4699 ****************************************************************************/
4701 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4704 ssize_t nwritten
= -1;
4711 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4712 START_PROFILE(SMBwriteBmpx
);
4714 CHECK_FSP(fsp
,conn
);
4718 tcount
= SVAL(inbuf
,smb_vwv1
);
4719 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
4720 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
4721 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4722 smb_doff
= SVAL(inbuf
,smb_vwv11
);
4724 data
= smb_base(inbuf
) + smb_doff
;
4726 /* If this fails we need to send an SMBwriteC response,
4727 not an SMBwritebmpx - set this up now so we don't forget */
4728 SCVAL(outbuf
,smb_com
,SMBwritec
);
4730 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
,False
)) {
4731 END_PROFILE(SMBwriteBmpx
);
4732 return(ERROR_DOS(ERRDOS
,ERRlock
));
4735 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4737 if(lp_syncalways(SNUM(conn
)) || write_through
)
4738 sync_file(conn
,fsp
);
4740 if(nwritten
< (ssize_t
)numtowrite
) {
4741 END_PROFILE(SMBwriteBmpx
);
4742 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
4745 /* If the maximum to be written to this file
4746 is greater than what we just wrote then set
4747 up a secondary struct to be attached to this
4748 fd, we will use this to cache error messages etc. */
4750 if((ssize_t
)tcount
> nwritten
) {
4751 write_bmpx_struct
*wbms
;
4752 if(fsp
->wbmpx_ptr
!= NULL
)
4753 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
4755 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
4757 DEBUG(0,("Out of memory in reply_readmpx\n"));
4758 END_PROFILE(SMBwriteBmpx
);
4759 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
4761 wbms
->wr_mode
= write_through
;
4762 wbms
->wr_discard
= False
; /* No errors yet */
4763 wbms
->wr_total_written
= nwritten
;
4764 wbms
->wr_errclass
= 0;
4766 fsp
->wbmpx_ptr
= wbms
;
4769 /* We are returning successfully, set the message type back to
4771 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
4773 outsize
= set_message(outbuf
,1,0,True
);
4775 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
4777 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4778 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
4780 if (write_through
&& tcount
==nwritten
) {
4781 /* We need to send both a primary and a secondary response */
4782 smb_setlen(outbuf
,outsize
- 4);
4783 if (!send_smb(smbd_server_fd(),outbuf
))
4784 exit_server("reply_writebmpx: send_smb failed.");
4786 /* Now the secondary */
4787 outsize
= set_message(outbuf
,1,0,True
);
4788 SCVAL(outbuf
,smb_com
,SMBwritec
);
4789 SSVAL(outbuf
,smb_vwv0
,nwritten
);
4792 END_PROFILE(SMBwriteBmpx
);
4796 /****************************************************************************
4797 Reply to a SMBwritebs (write block multiplex secondary) request.
4798 ****************************************************************************/
4800 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4803 ssize_t nwritten
= -1;
4810 write_bmpx_struct
*wbms
;
4811 BOOL send_response
= False
;
4812 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4813 START_PROFILE(SMBwriteBs
);
4815 CHECK_FSP(fsp
,conn
);
4818 tcount
= SVAL(inbuf
,smb_vwv1
);
4819 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
4820 numtowrite
= SVAL(inbuf
,smb_vwv6
);
4821 smb_doff
= SVAL(inbuf
,smb_vwv7
);
4823 data
= smb_base(inbuf
) + smb_doff
;
4825 /* We need to send an SMBwriteC response, not an SMBwritebs */
4826 SCVAL(outbuf
,smb_com
,SMBwritec
);
4828 /* This fd should have an auxiliary struct attached,
4829 check that it does */
4830 wbms
= fsp
->wbmpx_ptr
;
4832 END_PROFILE(SMBwriteBs
);
4836 /* If write through is set we can return errors, else we must cache them */
4837 write_through
= wbms
->wr_mode
;
4839 /* Check for an earlier error */
4840 if(wbms
->wr_discard
) {
4841 END_PROFILE(SMBwriteBs
);
4842 return -1; /* Just discard the packet */
4845 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4847 if(lp_syncalways(SNUM(conn
)) || write_through
)
4848 sync_file(conn
,fsp
);
4850 if (nwritten
< (ssize_t
)numtowrite
) {
4852 /* We are returning an error - we can delete the aux struct */
4855 fsp
->wbmpx_ptr
= NULL
;
4856 END_PROFILE(SMBwriteBs
);
4857 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
4859 END_PROFILE(SMBwriteBs
);
4860 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4863 /* Increment the total written, if this matches tcount
4864 we can discard the auxiliary struct (hurrah !) and return a writeC */
4865 wbms
->wr_total_written
+= nwritten
;
4866 if(wbms
->wr_total_written
>= tcount
) {
4867 if (write_through
) {
4868 outsize
= set_message(outbuf
,1,0,True
);
4869 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4870 send_response
= True
;
4874 fsp
->wbmpx_ptr
= NULL
;
4878 END_PROFILE(SMBwriteBs
);
4882 END_PROFILE(SMBwriteBs
);
4886 /****************************************************************************
4887 Reply to a SMBgetattrE.
4888 ****************************************************************************/
4890 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4892 SMB_STRUCT_STAT sbuf
;
4895 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4896 START_PROFILE(SMBgetattrE
);
4898 outsize
= set_message(outbuf
,11,0,True
);
4900 if(!fsp
|| (fsp
->conn
!= conn
)) {
4901 END_PROFILE(SMBgetattrE
);
4902 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4905 /* Do an fstat on this file */
4906 if(fsp_stat(fsp
, &sbuf
)) {
4907 END_PROFILE(SMBgetattrE
);
4908 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4911 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4914 * Convert the times into dos times. Set create
4915 * date to be last modify date as UNIX doesn't save
4919 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4920 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4921 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4924 SIVAL(outbuf
,smb_vwv6
,0);
4925 SIVAL(outbuf
,smb_vwv8
,0);
4927 uint32 allocation_size
= get_allocation_size(fsp
, &sbuf
);
4928 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4929 SIVAL(outbuf
,smb_vwv8
,allocation_size
);
4931 SSVAL(outbuf
,smb_vwv10
, mode
);
4933 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
4935 END_PROFILE(SMBgetattrE
);