2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2004.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
33 extern char magic_char
;
34 extern BOOL case_sensitive
;
35 extern BOOL case_preserve
;
36 extern BOOL short_case_preserve
;
37 extern int global_oplock_break
;
38 unsigned int smb_echo_count
= 0;
40 extern BOOL global_encrypted_passwords_negotiated
;
42 /****************************************************************************
43 Ensure we check the path in *exactly* the same way as W2K.
44 We're assuming here that '/' is not the second byte in any multibyte char
45 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
47 ****************************************************************************/
49 NTSTATUS
check_path_syntax(pstring destname
, const pstring srcname
)
52 const char *s
= srcname
;
53 NTSTATUS ret
= NT_STATUS_OK
;
56 if (IS_DIRECTORY_SEP(*s
)) {
58 * Safe to assume is not the second part of a mb char as this is handled below.
60 /* Eat multiple '/' or '\\' */
61 while (IS_DIRECTORY_SEP(*s
)) {
64 if ((s
[0] == '.') && (s
[1] == '\0')) {
65 ret
= NT_STATUS_OBJECT_NAME_INVALID
;
68 if ((d
!= destname
) && (*s
!= '\0')) {
69 /* We only care about non-leading or trailing '/' or '\\' */
72 } else if ((s
[0] == '.') && (s
[1] == '.') && (IS_DIRECTORY_SEP(s
[2]) || s
[2] == '\0')) {
73 /* Uh oh - "../" or "..\\" or "..\0" ! */
76 * No mb char starts with '.' so we're safe checking the directory separator here.
79 /* If we just added a '/', delete it. */
81 if ((d
> destname
) && (*(d
-1) == '/')) {
83 if (d
== (destname
+ 1)) {
89 /* Are we at the start ? Can't go back further if so. */
91 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
94 /* Go back one level... */
95 /* We know this is safe as '/' cannot be part of a mb sequence. */
96 /* NOTE - if this assumption is invalid we are not in good shape... */
97 while (d
> destname
) {
103 } else if ((s
[0] == '.') && (IS_DIRECTORY_SEP(s
[1]) || (s
[1] == '\0'))) {
106 * No mb char starts with '.' so we're safe checking the directory separator here.
109 /* "./" or ".\\" fails with a different error depending on where it is... */
112 ret
= NT_STATUS_OBJECT_NAME_INVALID
;
115 if (s
[1] != '\0' && s
[2] == '\0') {
116 ret
= NT_STATUS_INVALID_PARAMETER
;
119 ret
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
127 switch(next_mb_char_size(s
)) {
138 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
140 return NT_STATUS_INVALID_PARAMETER
;
149 /****************************************************************************
150 Pull a string and check the path - provide for error return.
151 ****************************************************************************/
153 size_t srvstr_get_path(char *inbuf
, char *dest
, const char *src
, size_t dest_len
, size_t src_len
, int flags
, NTSTATUS
*err
)
156 char *tmppath_ptr
= tmppath
;
159 SMB_ASSERT(dest_len
== sizeof(pstring
));
163 ret
= srvstr_pull_buf( inbuf
, tmppath_ptr
, src
, dest_len
, flags
);
165 ret
= srvstr_pull( inbuf
, tmppath_ptr
, src
, dest_len
, src_len
, flags
);
167 *err
= check_path_syntax(dest
, tmppath
);
171 /****************************************************************************
172 Reply to a special message.
173 ****************************************************************************/
175 int reply_special(char *inbuf
,char *outbuf
)
178 int msg_type
= CVAL(inbuf
,0);
179 int msg_flags
= CVAL(inbuf
,1);
183 static BOOL already_got_session
= False
;
187 memset(outbuf
,'\0',smb_size
);
189 smb_setlen(outbuf
,0);
192 case 0x81: /* session request */
194 if (already_got_session
) {
195 exit_server("multiple session request not permitted");
198 SCVAL(outbuf
,0,0x82);
200 if (name_len(inbuf
+4) > 50 ||
201 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
202 DEBUG(0,("Invalid name length in session request\n"));
205 name_extract(inbuf
,4,name1
);
206 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
207 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
210 set_local_machine_name(name1
, True
);
211 set_remote_machine_name(name2
, True
);
213 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
214 get_local_machine_name(), get_remote_machine_name(),
217 if (name_type
== 'R') {
218 /* We are being asked for a pathworks session ---
220 SCVAL(outbuf
, 0,0x83);
224 /* only add the client's machine name to the list
225 of possibly valid usernames if we are operating
226 in share mode security */
227 if (lp_security() == SEC_SHARE
) {
228 add_session_user(get_remote_machine_name());
231 reload_services(True
);
234 claim_connection(NULL
,"",0,True
,FLAG_MSG_GENERAL
|FLAG_MSG_SMBD
);
236 already_got_session
= True
;
239 case 0x89: /* session keepalive request
240 (some old clients produce this?) */
241 SCVAL(outbuf
,0,SMBkeepalive
);
245 case 0x82: /* positive session response */
246 case 0x83: /* negative session response */
247 case 0x84: /* retarget session response */
248 DEBUG(0,("Unexpected session response\n"));
251 case SMBkeepalive
: /* session keepalive */
256 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
257 msg_type
, msg_flags
));
262 /****************************************************************************
264 ****************************************************************************/
266 int reply_tcon(connection_struct
*conn
,
267 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
274 uint16 vuid
= SVAL(inbuf
,smb_uid
);
278 DATA_BLOB password_blob
;
280 START_PROFILE(SMBtcon
);
282 *service_buf
= *password
= *dev
= 0;
284 p
= smb_buf(inbuf
)+1;
285 p
+= srvstr_pull_buf(inbuf
, service_buf
, p
, sizeof(service_buf
), STR_TERMINATE
) + 1;
286 pwlen
= srvstr_pull_buf(inbuf
, password
, p
, sizeof(password
), STR_TERMINATE
) + 1;
288 p
+= srvstr_pull_buf(inbuf
, dev
, p
, sizeof(dev
), STR_TERMINATE
) + 1;
290 p
= strrchr_m(service_buf
,'\\');
294 service
= service_buf
;
297 password_blob
= data_blob(password
, pwlen
+1);
299 conn
= make_connection(service
,password_blob
,dev
,vuid
,&nt_status
);
301 data_blob_clear_free(&password_blob
);
304 END_PROFILE(SMBtcon
);
305 return ERROR_NT(nt_status
);
308 outsize
= set_message(outbuf
,2,0,True
);
309 SSVAL(outbuf
,smb_vwv0
,max_recv
);
310 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
311 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
313 DEBUG(3,("tcon service=%s cnum=%d\n",
314 service
, conn
->cnum
));
316 END_PROFILE(SMBtcon
);
320 /****************************************************************************
321 Reply to a tcon and X.
322 ****************************************************************************/
324 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
329 /* what the cleint thinks the device is */
330 fstring client_devicetype
;
331 /* what the server tells the client the share represents */
332 const char *server_devicetype
;
334 uint16 vuid
= SVAL(inbuf
,smb_uid
);
335 int passlen
= SVAL(inbuf
,smb_vwv3
);
338 extern BOOL global_encrypted_passwords_negotiated
;
340 START_PROFILE(SMBtconX
);
342 *service
= *client_devicetype
= 0;
344 /* we might have to close an old one */
345 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
346 close_cnum(conn
,vuid
);
349 if (passlen
> MAX_PASS_LEN
) {
350 return ERROR_DOS(ERRDOS
,ERRbuftoosmall
);
353 if (global_encrypted_passwords_negotiated
) {
354 password
= data_blob(smb_buf(inbuf
),passlen
);
356 password
= data_blob(smb_buf(inbuf
),passlen
+1);
357 /* Ensure correct termination */
358 password
.data
[passlen
]=0;
361 p
= smb_buf(inbuf
) + passlen
;
362 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
365 * the service name can be either: \\server\share
366 * or share directly like on the DELL PowerVault 705
369 q
= strchr_m(path
+2,'\\');
371 END_PROFILE(SMBtconX
);
372 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
374 fstrcpy(service
,q
+1);
377 fstrcpy(service
,path
);
379 p
+= srvstr_pull(inbuf
, client_devicetype
, p
, sizeof(client_devicetype
), 6, STR_ASCII
);
381 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
383 conn
= make_connection(service
,password
,client_devicetype
,vuid
,&nt_status
);
385 data_blob_clear_free(&password
);
388 END_PROFILE(SMBtconX
);
389 return ERROR_NT(nt_status
);
393 server_devicetype
= "IPC";
394 else if ( IS_PRINT(conn
) )
395 server_devicetype
= "LPT1:";
397 server_devicetype
= "A:";
399 if (Protocol
< PROTOCOL_NT1
) {
400 set_message(outbuf
,2,0,True
);
402 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
403 STR_TERMINATE
|STR_ASCII
);
404 set_message_end(outbuf
,p
);
406 /* NT sets the fstype of IPC$ to the null string */
407 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
409 set_message(outbuf
,3,0,True
);
412 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
413 STR_TERMINATE
|STR_ASCII
);
414 p
+= srvstr_push(outbuf
, p
, fstype
, -1,
417 set_message_end(outbuf
,p
);
419 /* what does setting this bit do? It is set by NT4 and
420 may affect the ability to autorun mounted cdroms */
421 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
422 (lp_csc_policy(SNUM(conn
)) << 2));
424 init_dfsroot(conn
, inbuf
, outbuf
);
428 DEBUG(3,("tconX service=%s \n",
431 /* set the incoming and outgoing tid to the just created one */
432 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
433 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
435 END_PROFILE(SMBtconX
);
436 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
439 /****************************************************************************
440 Reply to an unknown type.
441 ****************************************************************************/
443 int reply_unknown(char *inbuf
,char *outbuf
)
446 type
= CVAL(inbuf
,smb_com
);
448 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
449 smb_fn_name(type
), type
, type
));
451 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
454 /****************************************************************************
456 ****************************************************************************/
458 int reply_ioctl(connection_struct
*conn
,
459 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
461 uint16 device
= SVAL(inbuf
,smb_vwv1
);
462 uint16 function
= SVAL(inbuf
,smb_vwv2
);
463 uint32 ioctl_code
= (device
<< 16) + function
;
464 int replysize
, outsize
;
466 START_PROFILE(SMBioctl
);
468 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
470 switch (ioctl_code
) {
471 case IOCTL_QUERY_JOB_INFO
:
475 END_PROFILE(SMBioctl
);
476 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
479 outsize
= set_message(outbuf
,8,replysize
+1,True
);
480 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
481 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
482 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
483 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
485 switch (ioctl_code
) {
486 case IOCTL_QUERY_JOB_INFO
:
488 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
490 END_PROFILE(SMBioctl
);
491 return(UNIXERROR(ERRDOS
,ERRbadfid
));
493 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
494 srvstr_push(outbuf
, p
+2, global_myname(), 15, STR_TERMINATE
|STR_ASCII
);
495 srvstr_push(outbuf
, p
+18, lp_servicename(SNUM(conn
)), 13, STR_TERMINATE
|STR_ASCII
);
500 END_PROFILE(SMBioctl
);
504 /****************************************************************************
506 ****************************************************************************/
508 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
514 BOOL bad_path
= False
;
515 SMB_STRUCT_STAT sbuf
;
518 START_PROFILE(SMBchkpth
);
520 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
);
521 if (!NT_STATUS_IS_OK(status
)) {
522 END_PROFILE(SMBchkpth
);
523 return ERROR_NT(status
);
526 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
528 unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
530 mode
= SVAL(inbuf
,smb_vwv0
);
532 if (check_name(name
,conn
)) {
533 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,name
,&sbuf
) == 0)
534 if (!(ok
= S_ISDIR(sbuf
.st_mode
))) {
535 END_PROFILE(SMBchkpth
);
536 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY
,ERRDOS
,ERRbadpath
);
541 /* We special case this - as when a Windows machine
542 is parsing a path is steps through the components
543 one at a time - if a component fails it expects
544 ERRbadpath, not ERRbadfile.
546 if(errno
== ENOENT
) {
548 * Windows returns different error codes if
549 * the parent directory is valid but not the
550 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
551 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
552 * if the path is invalid.
555 END_PROFILE(SMBchkpth
);
556 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
558 END_PROFILE(SMBchkpth
);
559 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND
);
561 } else if (errno
== ENOTDIR
) {
562 END_PROFILE(SMBchkpth
);
563 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY
);
566 END_PROFILE(SMBchkpth
);
567 return(UNIXERROR(ERRDOS
,ERRbadpath
));
570 outsize
= set_message(outbuf
,0,0,True
);
572 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
574 END_PROFILE(SMBchkpth
);
578 /****************************************************************************
580 ****************************************************************************/
582 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
586 SMB_STRUCT_STAT sbuf
;
591 BOOL bad_path
= False
;
595 START_PROFILE(SMBgetatr
);
597 p
= smb_buf(inbuf
) + 1;
598 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
599 if (!NT_STATUS_IS_OK(status
)) {
600 END_PROFILE(SMBgetatr
);
601 return ERROR_NT(status
);
604 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
606 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
607 under WfWg - weird! */
609 mode
= aHIDDEN
| aDIR
;
610 if (!CAN_WRITE(conn
))
616 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
617 if (check_name(fname
,conn
)) {
618 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,fname
,&sbuf
) == 0) {
619 mode
= dos_mode(conn
,fname
,&sbuf
);
621 mtime
= sbuf
.st_mtime
;
626 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
632 END_PROFILE(SMBgetatr
);
633 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadfile
);
636 outsize
= set_message(outbuf
,10,0,True
);
638 SSVAL(outbuf
,smb_vwv0
,mode
);
639 if(lp_dos_filetime_resolution(SNUM(conn
)) )
640 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
642 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
643 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
645 if (Protocol
>= PROTOCOL_NT1
)
646 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
648 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
650 END_PROFILE(SMBgetatr
);
654 /****************************************************************************
656 ****************************************************************************/
658 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
665 SMB_STRUCT_STAT sbuf
;
666 BOOL bad_path
= False
;
670 START_PROFILE(SMBsetatr
);
672 p
= smb_buf(inbuf
) + 1;
673 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
674 if (!NT_STATUS_IS_OK(status
)) {
675 END_PROFILE(SMBsetatr
);
676 return ERROR_NT(status
);
679 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
681 mode
= SVAL(inbuf
,smb_vwv0
);
682 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
684 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
685 if (VALID_STAT_OF_DIR(sbuf
))
690 if (check_name(fname
,conn
)) {
691 ok
= (file_set_dosmode(conn
,fname
,mode
,NULL
) == 0);
698 ok
= set_filetime(conn
,fname
,mtime
);
701 END_PROFILE(SMBsetatr
);
702 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
705 outsize
= set_message(outbuf
,0,0,True
);
707 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
709 END_PROFILE(SMBsetatr
);
713 /****************************************************************************
715 ****************************************************************************/
717 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
720 SMB_BIG_UINT dfree
,dsize
,bsize
;
721 START_PROFILE(SMBdskattr
);
723 SMB_VFS_DISK_FREE(conn
,".",True
,&bsize
,&dfree
,&dsize
);
725 outsize
= set_message(outbuf
,5,0,True
);
727 if (Protocol
<= PROTOCOL_LANMAN2
) {
728 double total_space
, free_space
;
729 /* we need to scale this to a number that DOS6 can handle. We
730 use floating point so we can handle large drives on systems
731 that don't have 64 bit integers
733 we end up displaying a maximum of 2G to DOS systems
735 total_space
= dsize
* (double)bsize
;
736 free_space
= dfree
* (double)bsize
;
738 dsize
= (total_space
+63*512) / (64*512);
739 dfree
= (free_space
+63*512) / (64*512);
741 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
742 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
744 SSVAL(outbuf
,smb_vwv0
,dsize
);
745 SSVAL(outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
746 SSVAL(outbuf
,smb_vwv2
,512); /* and this must be 512 */
747 SSVAL(outbuf
,smb_vwv3
,dfree
);
749 SSVAL(outbuf
,smb_vwv0
,dsize
);
750 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
751 SSVAL(outbuf
,smb_vwv2
,512);
752 SSVAL(outbuf
,smb_vwv3
,dfree
);
755 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
757 END_PROFILE(SMBdskattr
);
761 /****************************************************************************
763 Can be called from SMBsearch, SMBffirst or SMBfunique.
764 ****************************************************************************/
766 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
776 unsigned int numentries
= 0;
777 unsigned int maxentries
= 0;
778 BOOL finished
= False
;
785 BOOL check_descend
= False
;
786 BOOL expect_close
= False
;
787 BOOL can_open
= True
;
788 BOOL bad_path
= False
;
790 START_PROFILE(SMBsearch
);
792 *mask
= *directory
= *fname
= 0;
794 /* If we were called as SMBffirst then we must expect close. */
795 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
798 outsize
= set_message(outbuf
,1,3,True
);
799 maxentries
= SVAL(inbuf
,smb_vwv0
);
800 dirtype
= SVAL(inbuf
,smb_vwv1
);
801 p
= smb_buf(inbuf
) + 1;
802 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &nt_status
);
803 if (!NT_STATUS_IS_OK(nt_status
)) {
804 END_PROFILE(SMBsearch
);
805 return ERROR_NT(nt_status
);
808 status_len
= SVAL(p
, 0);
811 /* dirtype &= ~aDIR; */
813 if (status_len
== 0) {
814 SMB_STRUCT_STAT sbuf
;
817 pstrcpy(directory
,path
);
819 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
822 if (!check_name(directory
,conn
))
825 p
= strrchr_m(dir2
,'/');
834 p
= strrchr_m(directory
,'/');
840 if (strlen(directory
) == 0)
841 pstrcpy(directory
,".");
842 memset((char *)status
,'\0',21);
843 SCVAL(status
,0,(dirtype
& 0x1F));
848 status_dirtype
= CVAL(status
,0) & 0x1F;
849 if (status_dirtype
!= (dirtype
& 0x1F))
850 dirtype
= status_dirtype
;
852 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
855 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
856 pstrcpy(mask
, dptr_wcard(dptr_num
));
860 p
= smb_buf(outbuf
) + 3;
863 if (status_len
== 0) {
864 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
867 END_PROFILE(SMBsearch
);
868 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnofids
);
870 END_PROFILE(SMBsearch
);
871 return ERROR_DOS(ERRDOS
,ERRnofids
);
873 dptr_set_wcard(dptr_num
, strdup(mask
));
874 dptr_set_attr(dptr_num
, dirtype
);
876 dirtype
= dptr_attr(dptr_num
);
879 DEBUG(4,("dptr_num is %d\n",dptr_num
));
882 if ((dirtype
&0x1F) == aVOLID
) {
884 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
885 dptr_fill(p
+12,dptr_num
);
886 if (dptr_zero(p
+12) && (status_len
==0))
890 p
+= DIR_STRUCT_SIZE
;
893 maxentries
= MIN(maxentries
, ((BUFFER_SIZE
- (p
- outbuf
))/DIR_STRUCT_SIZE
));
895 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
896 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
897 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
898 check_descend
= True
;
900 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
901 finished
= !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
904 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
905 dptr_fill(p
+12,dptr_num
);
908 p
+= DIR_STRUCT_SIZE
;
917 /* If we were called as SMBffirst with smb_search_id == NULL
918 and no entries were found then return error and close dirptr
921 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0) {
922 if (Protocol
< PROTOCOL_NT1
) {
923 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
924 SSVAL(outbuf
,smb_err
,ERRnofiles
);
926 /* Also close the dptr - we know it's gone */
927 dptr_close(&dptr_num
);
928 } else if (numentries
== 0 || !ok
) {
929 if (Protocol
< PROTOCOL_NT1
) {
930 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
931 SSVAL(outbuf
,smb_err
,ERRnofiles
);
933 dptr_close(&dptr_num
);
936 /* If we were called as SMBfunique, then we can close the dirptr now ! */
937 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
938 dptr_close(&dptr_num
);
940 SSVAL(outbuf
,smb_vwv0
,numentries
);
941 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
942 SCVAL(smb_buf(outbuf
),0,5);
943 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
945 if (Protocol
>= PROTOCOL_NT1
)
946 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
948 outsize
+= DIR_STRUCT_SIZE
*numentries
;
949 smb_setlen(outbuf
,outsize
- 4);
951 if ((! *directory
) && dptr_path(dptr_num
))
952 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
954 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
955 smb_fn_name(CVAL(inbuf
,smb_com
)),
956 mask
, directory
, dirtype
, numentries
, maxentries
) );
958 END_PROFILE(SMBsearch
);
962 /****************************************************************************
963 Reply to a fclose (stop directory search).
964 ****************************************************************************/
966 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
976 START_PROFILE(SMBfclose
);
978 outsize
= set_message(outbuf
,1,0,True
);
979 p
= smb_buf(inbuf
) + 1;
980 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &err
);
981 if (!NT_STATUS_IS_OK(err
)) {
982 END_PROFILE(SMBfclose
);
983 return ERROR_NT(err
);
986 status_len
= SVAL(p
,0);
989 if (status_len
== 0) {
990 END_PROFILE(SMBfclose
);
991 return ERROR_DOS(ERRSRV
,ERRsrverror
);
996 if(dptr_fetch(status
+12,&dptr_num
)) {
997 /* Close the dptr - we know it's gone */
998 dptr_close(&dptr_num
);
1001 SSVAL(outbuf
,smb_vwv0
,0);
1003 DEBUG(3,("search close\n"));
1005 END_PROFILE(SMBfclose
);
1009 /****************************************************************************
1011 ****************************************************************************/
1013 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1022 SMB_STRUCT_STAT sbuf
;
1023 BOOL bad_path
= False
;
1025 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1026 uint16 dos_attr
= SVAL(inbuf
,smb_vwv1
);
1028 START_PROFILE(SMBopen
);
1030 share_mode
= SVAL(inbuf
,smb_vwv0
);
1032 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1033 if (!NT_STATUS_IS_OK(status
)) {
1034 END_PROFILE(SMBopen
);
1035 return ERROR_NT(status
);
1038 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1040 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1042 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1043 (uint32
)dos_attr
, oplock_request
,&rmode
,NULL
);
1046 END_PROFILE(SMBopen
);
1047 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1050 size
= sbuf
.st_size
;
1051 fmode
= dos_mode(conn
,fname
,&sbuf
);
1052 mtime
= sbuf
.st_mtime
;
1055 DEBUG(3,("attempt to open a directory %s\n",fname
));
1056 close_file(fsp
,False
);
1057 END_PROFILE(SMBopen
);
1058 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1061 outsize
= set_message(outbuf
,7,0,True
);
1062 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1063 SSVAL(outbuf
,smb_vwv1
,fmode
);
1064 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1065 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1067 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1068 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1069 SSVAL(outbuf
,smb_vwv6
,rmode
);
1071 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1072 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1074 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1075 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1076 END_PROFILE(SMBopen
);
1080 /****************************************************************************
1081 Reply to an open and X.
1082 ****************************************************************************/
1084 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1087 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1088 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1089 /* Breakout the oplock request bits so we can set the
1090 reply bits separately. */
1091 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1092 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1093 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1095 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1096 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1097 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1099 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1101 int fmode
=0,mtime
=0,rmode
=0;
1102 SMB_STRUCT_STAT sbuf
;
1104 BOOL bad_path
= False
;
1107 START_PROFILE(SMBopenX
);
1109 /* If it's an IPC, pass off the pipe handler. */
1111 if (lp_nt_pipe_support()) {
1112 END_PROFILE(SMBopenX
);
1113 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1115 END_PROFILE(SMBopenX
);
1116 return ERROR_DOS(ERRSRV
,ERRaccess
);
1120 /* XXXX we need to handle passed times, sattr and flags */
1121 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
), sizeof(fname
), 0, STR_TERMINATE
, &status
);
1122 if (!NT_STATUS_IS_OK(status
)) {
1123 END_PROFILE(SMBopenX
);
1124 return ERROR_NT(status
);
1127 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1129 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1131 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,(uint32
)smb_attr
,
1132 oplock_request
, &rmode
,&smb_action
);
1135 END_PROFILE(SMBopenX
);
1136 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1139 size
= sbuf
.st_size
;
1140 fmode
= dos_mode(conn
,fname
,&sbuf
);
1141 mtime
= sbuf
.st_mtime
;
1143 close_file(fsp
,False
);
1144 END_PROFILE(SMBopenX
);
1145 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1148 /* If the caller set the extended oplock request bit
1149 and we granted one (by whatever means) - set the
1150 correct bit for extended oplock reply.
1153 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1154 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1156 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1157 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1159 /* If the caller set the core oplock request bit
1160 and we granted one (by whatever means) - set the
1161 correct bit for core oplock reply.
1164 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1165 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1167 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1168 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1170 set_message(outbuf
,15,0,True
);
1171 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1172 SSVAL(outbuf
,smb_vwv3
,fmode
);
1173 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1174 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1176 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1177 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1178 SSVAL(outbuf
,smb_vwv8
,rmode
);
1179 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1181 END_PROFILE(SMBopenX
);
1182 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1185 /****************************************************************************
1186 Reply to a SMBulogoffX.
1187 ****************************************************************************/
1189 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1191 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1192 user_struct
*vuser
= get_valid_user_struct(vuid
);
1193 START_PROFILE(SMBulogoffX
);
1196 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1198 /* in user level security we are supposed to close any files
1199 open by this user */
1200 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
))
1201 file_close_user(vuid
);
1203 invalidate_vuid(vuid
);
1205 set_message(outbuf
,2,0,True
);
1207 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1209 END_PROFILE(SMBulogoffX
);
1210 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1213 /****************************************************************************
1214 Reply to a mknew or a create.
1215 ****************************************************************************/
1217 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1224 BOOL bad_path
= False
;
1226 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1227 SMB_STRUCT_STAT sbuf
;
1229 START_PROFILE(SMBcreate
);
1231 com
= SVAL(inbuf
,smb_com
);
1233 createmode
= SVAL(inbuf
,smb_vwv0
);
1234 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
) + 1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1235 if (!NT_STATUS_IS_OK(status
)) {
1236 END_PROFILE(SMBcreate
);
1237 return ERROR_NT(status
);
1240 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1242 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1244 if (createmode
& aVOLID
)
1245 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1247 if(com
== SMBmknew
) {
1248 /* We should fail if file exists. */
1249 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1251 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1252 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1255 /* Open file in dos compatibility share mode. */
1256 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1257 ofun
, (uint32
)createmode
, oplock_request
, NULL
, NULL
);
1260 END_PROFILE(SMBcreate
);
1261 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1264 outsize
= set_message(outbuf
,1,0,True
);
1265 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1267 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1268 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1270 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1271 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1273 DEBUG( 2, ( "new file %s\n", fname
) );
1274 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname
, fsp
->fd
, createmode
) );
1276 END_PROFILE(SMBcreate
);
1280 /****************************************************************************
1281 Reply to a create temporary file.
1282 ****************************************************************************/
1284 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1289 BOOL bad_path
= False
;
1291 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1293 SMB_STRUCT_STAT sbuf
;
1296 unsigned int namelen
;
1298 START_PROFILE(SMBctemp
);
1300 createattr
= SVAL(inbuf
,smb_vwv0
);
1301 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1302 if (!NT_STATUS_IS_OK(status
)) {
1303 END_PROFILE(SMBctemp
);
1304 return ERROR_NT(status
);
1307 pstrcat(fname
,"/TMXXXXXX");
1309 pstrcat(fname
,"TMXXXXXX");
1312 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1314 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1316 tmpfd
= smb_mkstemp(fname
);
1318 END_PROFILE(SMBctemp
);
1319 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1322 SMB_VFS_STAT(conn
,fname
,&sbuf
);
1324 /* Open file in dos compatibility share mode. */
1325 /* We should fail if file does not exist. */
1326 fsp
= open_file_shared(conn
,fname
,&sbuf
,
1327 SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1328 FILE_EXISTS_OPEN
|FILE_FAIL_IF_NOT_EXIST
,
1329 (uint32
)createattr
, oplock_request
, NULL
, NULL
);
1331 /* close fd from smb_mkstemp() */
1335 END_PROFILE(SMBctemp
);
1336 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1339 outsize
= set_message(outbuf
,1,0,True
);
1340 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1342 /* the returned filename is relative to the directory */
1343 s
= strrchr_m(fname
, '/');
1349 p
= smb_buf(outbuf
);
1351 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1352 thing in the byte section. JRA */
1353 SSVALS(p
, 0, -1); /* what is this? not in spec */
1355 namelen
= srvstr_push(outbuf
, p
, s
, -1, STR_ASCII
|STR_TERMINATE
);
1357 outsize
= set_message_end(outbuf
, p
);
1359 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1360 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1362 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1363 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1365 DEBUG( 2, ( "created temp file %s\n", fname
) );
1366 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1367 fname
, fsp
->fd
, sbuf
.st_mode
) );
1369 END_PROFILE(SMBctemp
);
1373 /*******************************************************************
1374 Check if a user is allowed to rename a file.
1375 ********************************************************************/
1377 static NTSTATUS
can_rename(char *fname
,connection_struct
*conn
, SMB_STRUCT_STAT
*pst
)
1383 if (!CAN_WRITE(conn
))
1384 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1386 if (S_ISDIR(pst
->st_mode
))
1387 return NT_STATUS_OK
;
1389 /* We need a better way to return NT status codes from open... */
1393 fsp
= open_file_shared1(conn
, fname
, pst
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1394 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), FILE_ATTRIBUTE_NORMAL
, 0, &access_mode
, &smb_action
);
1397 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1398 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1399 ret
= NT_STATUS_SHARING_VIOLATION
;
1402 unix_ERR_ntstatus
= NT_STATUS_OK
;
1405 close_file(fsp
,False
);
1406 return NT_STATUS_OK
;
1409 /*******************************************************************
1410 Check if a user is allowed to delete a file.
1411 ********************************************************************/
1413 static NTSTATUS
can_delete(char *fname
,connection_struct
*conn
, int dirtype
, BOOL bad_path
)
1415 SMB_STRUCT_STAT sbuf
;
1421 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1424 if (!CAN_WRITE(conn
))
1425 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1427 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
) != 0) {
1428 if(errno
== ENOENT
) {
1430 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1432 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1434 return map_nt_error_from_unix(errno
);
1437 fmode
= dos_mode(conn
,fname
,&sbuf
);
1439 /* Can't delete a directory. */
1441 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1443 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
1444 return NT_STATUS_OBJECT_NAME_INVALID
;
1445 #endif /* JRATEST */
1447 if (!lp_delete_readonly(SNUM(conn
))) {
1449 return NT_STATUS_CANNOT_DELETE
;
1451 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1452 return NT_STATUS_NO_SUCH_FILE
;
1454 /* We need a better way to return NT status codes from open... */
1458 fsp
= open_file_shared1(conn
, fname
, &sbuf
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1459 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), FILE_ATTRIBUTE_NORMAL
, 0, &access_mode
, &smb_action
);
1462 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1463 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus
))
1464 ret
= unix_ERR_ntstatus
;
1465 else if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1466 ret
= NT_STATUS_SHARING_VIOLATION
;
1469 unix_ERR_ntstatus
= NT_STATUS_OK
;
1472 close_file(fsp
,False
);
1473 return NT_STATUS_OK
;
1476 /****************************************************************************
1477 The guts of the unlink command, split out so it may be called by the NT SMB
1479 ****************************************************************************/
1481 NTSTATUS
unlink_internals(connection_struct
*conn
, int dirtype
, char *name
)
1487 NTSTATUS error
= NT_STATUS_OK
;
1489 BOOL bad_path
= False
;
1491 SMB_STRUCT_STAT sbuf
;
1493 *directory
= *mask
= 0;
1495 /* We must check for wildcards in the name given
1496 * directly by the client - before any unmangling.
1497 * This prevents an unmangling of a UNIX name containing
1498 * a DOS wildcard like '*' or '?' from unmangling into
1499 * a wildcard delete which was not intended.
1500 * FIX for #226. JRA.
1503 has_wild
= ms_has_wild(name
);
1505 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1507 p
= strrchr_m(name
,'/');
1509 pstrcpy(directory
,".");
1513 pstrcpy(directory
,name
);
1518 * We should only check the mangled cache
1519 * here if unix_convert failed. This means
1520 * that the path in 'mask' doesn't exist
1521 * on the file system and so we need to look
1522 * for a possible mangle. This patch from
1523 * Tine Smukavec <valentin.smukavec@hermes.si>.
1526 if (!rc
&& mangle_is_mangled(mask
))
1527 mangle_check_cache( mask
);
1530 pstrcat(directory
,"/");
1531 pstrcat(directory
,mask
);
1532 error
= can_delete(directory
,conn
,dirtype
,bad_path
);
1533 if (!NT_STATUS_IS_OK(error
))
1536 if (SMB_VFS_UNLINK(conn
,directory
) == 0) {
1540 void *dirptr
= NULL
;
1543 if (check_name(directory
,conn
))
1544 dirptr
= OpenDir(conn
, directory
, True
);
1546 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1547 the pattern matches against the long name, otherwise the short name
1548 We don't implement this yet XXXX
1552 error
= NT_STATUS_NO_SUCH_FILE
;
1554 if (strequal(mask
,"????????.???"))
1557 while ((dname
= ReadDirName(dirptr
))) {
1559 BOOL sys_direntry
= False
;
1560 pstrcpy(fname
,dname
);
1562 /* Quick check for "." and ".." */
1563 if (fname
[0] == '.') {
1564 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
1565 if ((dirtype
& aDIR
)) {
1566 sys_direntry
= True
;
1573 if(!mask_match(fname
, mask
, case_sensitive
))
1577 error
= NT_STATUS_OBJECT_NAME_INVALID
;
1581 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1582 error
= can_delete(fname
,conn
,dirtype
,bad_path
);
1583 if (!NT_STATUS_IS_OK(error
))
1585 if (SMB_VFS_UNLINK(conn
,fname
) == 0)
1587 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
1593 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
1594 error
= map_nt_error_from_unix(errno
);
1600 /****************************************************************************
1602 ****************************************************************************/
1604 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
1611 START_PROFILE(SMBunlink
);
1613 dirtype
= SVAL(inbuf
,smb_vwv0
);
1615 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
);
1616 if (!NT_STATUS_IS_OK(status
)) {
1617 END_PROFILE(SMBunlink
);
1618 return ERROR_NT(status
);
1621 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
1623 DEBUG(3,("reply_unlink : %s\n",name
));
1625 status
= unlink_internals(conn
, dirtype
, name
);
1626 if (!NT_STATUS_IS_OK(status
))
1627 return ERROR_NT(status
);
1630 * Win2k needs a changenotify request response before it will
1631 * update after a rename..
1633 process_pending_change_notify_queue((time_t)0);
1635 outsize
= set_message(outbuf
,0,0,True
);
1637 END_PROFILE(SMBunlink
);
1641 /****************************************************************************
1643 ****************************************************************************/
1645 void fail_readraw(void)
1648 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1650 exit_server(errstr
);
1653 /****************************************************************************
1654 Use sendfile in readbraw.
1655 ****************************************************************************/
1657 void send_file_readbraw(connection_struct
*conn
, files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
,
1658 ssize_t mincount
, char *outbuf
)
1662 #if defined(WITH_SENDFILE)
1664 * We can only use sendfile on a non-chained packet and on a file
1665 * that is exclusively oplocked. reply_readbraw has already checked the length.
1668 if ((nread
> 0) && (lp_write_cache_size(SNUM(conn
)) == 0) &&
1669 EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) && lp_use_sendfile(SNUM(conn
)) ) {
1672 _smb_setlen(outbuf
,nread
);
1673 header
.data
= outbuf
;
1677 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, nread
) == -1) {
1679 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1680 * return ENOSYS then pretend we just got a normal read.
1682 if (errno
== ENOSYS
)
1685 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1686 fsp
->fsp_name
, strerror(errno
) ));
1687 exit_server("send_file_readbraw sendfile failed");
1696 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
1697 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1706 _smb_setlen(outbuf
,ret
);
1707 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
1711 /****************************************************************************
1712 Reply to a readbraw (core+ protocol).
1713 ****************************************************************************/
1715 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1717 extern struct current_user current_user
;
1718 ssize_t maxcount
,mincount
;
1721 char *header
= outbuf
;
1723 START_PROFILE(SMBreadbraw
);
1725 if (srv_is_signing_active()) {
1726 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1730 * Special check if an oplock break has been issued
1731 * and the readraw request croses on the wire, we must
1732 * return a zero length response here.
1735 if(global_oplock_break
) {
1736 _smb_setlen(header
,0);
1737 if (write_data(smbd_server_fd(),header
,4) != 4)
1739 DEBUG(5,("readbraw - oplock break finished\n"));
1740 END_PROFILE(SMBreadbraw
);
1744 fsp
= file_fsp(inbuf
,smb_vwv0
);
1746 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1748 * fsp could be NULL here so use the value from the packet. JRA.
1750 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
1751 _smb_setlen(header
,0);
1752 if (write_data(smbd_server_fd(),header
,4) != 4)
1754 END_PROFILE(SMBreadbraw
);
1758 CHECK_FSP(fsp
,conn
);
1760 flush_write_cache(fsp
, READRAW_FLUSH
);
1762 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
1763 if(CVAL(inbuf
,smb_wct
) == 10) {
1765 * This is a large offset (64 bit) read.
1767 #ifdef LARGE_SMB_OFF_T
1769 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
1771 #else /* !LARGE_SMB_OFF_T */
1774 * Ensure we haven't been sent a >32 bit offset.
1777 if(IVAL(inbuf
,smb_vwv8
) != 0) {
1778 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1779 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
1780 _smb_setlen(header
,0);
1781 if (write_data(smbd_server_fd(),header
,4) != 4)
1783 END_PROFILE(SMBreadbraw
);
1787 #endif /* LARGE_SMB_OFF_T */
1790 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
1791 _smb_setlen(header
,0);
1792 if (write_data(smbd_server_fd(),header
,4) != 4)
1794 END_PROFILE(SMBreadbraw
);
1798 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
1799 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
1801 /* ensure we don't overrun the packet size */
1802 maxcount
= MIN(65535,maxcount
);
1804 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1805 SMB_OFF_T size
= fsp
->size
;
1806 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
1808 if (size
< sizeneeded
) {
1810 if (SMB_VFS_FSTAT(fsp
,fsp
->fd
,&st
) == 0)
1812 if (!fsp
->can_write
)
1816 if (startpos
>= size
)
1819 nread
= MIN(maxcount
,(size
- startpos
));
1822 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1823 if (nread
< mincount
)
1827 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp
->fnum
, (double)startpos
,
1828 (int)maxcount
, (int)mincount
, (int)nread
) );
1830 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
, outbuf
);
1832 DEBUG(5,("readbraw finished\n"));
1833 END_PROFILE(SMBreadbraw
);
1837 /****************************************************************************
1838 Reply to a lockread (core+ protocol).
1839 ****************************************************************************/
1841 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
1849 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1850 BOOL my_lock_ctx
= False
;
1851 START_PROFILE(SMBlockread
);
1853 CHECK_FSP(fsp
,conn
);
1856 release_level_2_oplocks_on_change(fsp
);
1858 numtoread
= SVAL(inbuf
,smb_vwv1
);
1859 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1861 outsize
= set_message(outbuf
,5,3,True
);
1862 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1863 data
= smb_buf(outbuf
) + 3;
1866 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1867 * protocol request that predates the read/write lock concept.
1868 * Thus instead of asking for a read lock here we need to ask
1869 * for a write lock. JRA.
1870 * Note that the requested lock size is unaffected by max_recv.
1873 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
),
1874 (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
, &my_lock_ctx
);
1876 if (NT_STATUS_V(status
)) {
1879 * We used to make lockread a blocking lock. It turns out
1880 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1884 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
1886 * A blocking lock was requested. Package up
1887 * this smb into a queued request and push it
1888 * onto the blocking lock queue.
1890 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)startpos
,
1891 (SMB_BIG_UINT
)numtoread
)) {
1892 END_PROFILE(SMBlockread
);
1897 END_PROFILE(SMBlockread
);
1898 return ERROR_NT(status
);
1902 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1905 if (numtoread
> max_recv
) {
1906 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1907 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1908 (unsigned int)numtoread
, (unsigned int)max_recv
));
1909 numtoread
= MIN(numtoread
,max_recv
);
1911 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1914 END_PROFILE(SMBlockread
);
1915 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1919 SSVAL(outbuf
,smb_vwv0
,nread
);
1920 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1921 SSVAL(smb_buf(outbuf
),1,nread
);
1923 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1924 fsp
->fnum
, (int)numtoread
, (int)nread
));
1926 END_PROFILE(SMBlockread
);
1930 /****************************************************************************
1932 ****************************************************************************/
1934 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
1941 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1942 START_PROFILE(SMBread
);
1944 CHECK_FSP(fsp
,conn
);
1947 numtoread
= SVAL(inbuf
,smb_vwv1
);
1948 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1950 outsize
= set_message(outbuf
,5,3,True
);
1951 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1953 * The requested read size cannot be greater than max_recv. JRA.
1955 if (numtoread
> max_recv
) {
1956 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1957 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1958 (unsigned int)numtoread
, (unsigned int)max_recv
));
1959 numtoread
= MIN(numtoread
,max_recv
);
1962 data
= smb_buf(outbuf
) + 3;
1964 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1965 END_PROFILE(SMBread
);
1966 return ERROR_DOS(ERRDOS
,ERRlock
);
1970 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1973 END_PROFILE(SMBread
);
1974 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1978 SSVAL(outbuf
,smb_vwv0
,nread
);
1979 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1980 SCVAL(smb_buf(outbuf
),0,1);
1981 SSVAL(smb_buf(outbuf
),1,nread
);
1983 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1984 fsp
->fnum
, (int)numtoread
, (int)nread
) );
1986 END_PROFILE(SMBread
);
1990 /****************************************************************************
1991 Reply to a read and X - possibly using sendfile.
1992 ****************************************************************************/
1994 int send_file_readX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,
1995 files_struct
*fsp
, SMB_OFF_T startpos
, size_t smb_maxcnt
)
1998 char *data
= smb_buf(outbuf
);
2000 #if defined(WITH_SENDFILE)
2002 * We can only use sendfile on a non-chained packet and on a file
2003 * that is exclusively oplocked.
2006 if ((CVAL(inbuf
,smb_vwv0
) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) &&
2007 lp_use_sendfile(SNUM(conn
)) && (lp_write_cache_size(SNUM(conn
)) == 0) ) {
2008 SMB_STRUCT_STAT sbuf
;
2011 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1)
2012 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2014 if (startpos
> sbuf
.st_size
)
2017 if (smb_maxcnt
> (sbuf
.st_size
- startpos
))
2018 smb_maxcnt
= (sbuf
.st_size
- startpos
);
2020 if (smb_maxcnt
== 0)
2024 * Set up the packet header before send. We
2025 * assume here the sendfile will work (get the
2026 * correct amount of data).
2029 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2030 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
2031 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2032 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
2033 SCVAL(outbuf
,smb_vwv0
,0xFF);
2034 set_message(outbuf
,12,smb_maxcnt
,False
);
2035 header
.data
= outbuf
;
2036 header
.length
= data
- outbuf
;
2039 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, smb_maxcnt
) == -1) {
2041 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2042 * return ENOSYS then pretend we just got a normal read.
2044 if (errno
== ENOSYS
)
2047 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2048 fsp
->fsp_name
, strerror(errno
) ));
2049 exit_server("send_file_readX sendfile failed");
2052 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2053 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2061 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2064 END_PROFILE(SMBreadX
);
2065 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2068 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2069 SSVAL(outbuf
,smb_vwv5
,nread
);
2070 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2071 SSVAL(smb_buf(outbuf
),-2,nread
);
2073 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2074 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2079 /****************************************************************************
2080 Reply to a read and X.
2081 ****************************************************************************/
2083 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2085 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2086 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2088 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2090 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2093 START_PROFILE(SMBreadX
);
2095 /* If it's an IPC, pass off the pipe handler. */
2097 END_PROFILE(SMBreadX
);
2098 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2101 CHECK_FSP(fsp
,conn
);
2104 set_message(outbuf
,12,0,True
);
2106 if(CVAL(inbuf
,smb_wct
) == 12) {
2107 #ifdef LARGE_SMB_OFF_T
2109 * This is a large offset (64 bit) read.
2111 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2113 #else /* !LARGE_SMB_OFF_T */
2116 * Ensure we haven't been sent a >32 bit offset.
2119 if(IVAL(inbuf
,smb_vwv10
) != 0) {
2120 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2121 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
2122 END_PROFILE(SMBreadX
);
2123 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2126 #endif /* LARGE_SMB_OFF_T */
2130 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2131 END_PROFILE(SMBreadX
);
2132 return ERROR_DOS(ERRDOS
,ERRlock
);
2135 nread
= send_file_readX(conn
, inbuf
, outbuf
, length
, fsp
, startpos
, smb_maxcnt
);
2137 nread
= chain_reply(inbuf
,outbuf
,length
,bufsize
);
2139 END_PROFILE(SMBreadX
);
2143 /****************************************************************************
2144 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2145 ****************************************************************************/
2147 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2150 ssize_t total_written
=0;
2151 size_t numtowrite
=0;
2156 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2158 START_PROFILE(SMBwritebraw
);
2160 if (srv_is_signing_active()) {
2161 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2164 CHECK_FSP(fsp
,conn
);
2167 tcount
= IVAL(inbuf
,smb_vwv1
);
2168 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2169 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2171 /* We have to deal with slightly different formats depending
2172 on whether we are using the core+ or lanman1.0 protocol */
2174 if(Protocol
<= PROTOCOL_COREPLUS
) {
2175 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2176 data
= smb_buf(inbuf
);
2178 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2179 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2182 /* force the error type */
2183 SCVAL(inbuf
,smb_com
,SMBwritec
);
2184 SCVAL(outbuf
,smb_com
,SMBwritec
);
2186 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2187 END_PROFILE(SMBwritebraw
);
2188 return(ERROR_DOS(ERRDOS
,ERRlock
));
2192 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2194 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2195 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2197 if (nwritten
< (ssize_t
)numtowrite
) {
2198 END_PROFILE(SMBwritebraw
);
2199 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2202 total_written
= nwritten
;
2204 /* Return a message to the redirector to tell it to send more bytes */
2205 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
2206 SSVALS(outbuf
,smb_vwv0
,-1);
2207 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2208 if (!send_smb(smbd_server_fd(),outbuf
))
2209 exit_server("reply_writebraw: send_smb failed.");
2211 /* Now read the raw data into the buffer and write it */
2212 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2213 exit_server("secondary writebraw failed");
2216 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2217 numtowrite
= smb_len(inbuf
);
2219 /* Set up outbuf to return the correct return */
2220 outsize
= set_message(outbuf
,1,0,True
);
2221 SCVAL(outbuf
,smb_com
,SMBwritec
);
2222 SSVAL(outbuf
,smb_vwv0
,total_written
);
2224 if (numtowrite
!= 0) {
2226 if (numtowrite
> BUFFER_SIZE
) {
2227 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2228 (unsigned int)numtowrite
));
2229 exit_server("secondary writebraw failed");
2232 if (tcount
> nwritten
+numtowrite
) {
2233 DEBUG(3,("Client overestimated the write %d %d %d\n",
2234 (int)tcount
,(int)nwritten
,(int)numtowrite
));
2237 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
2238 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2240 exit_server("secondary writebraw failed");
2243 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
2245 if (nwritten
< (ssize_t
)numtowrite
) {
2246 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2247 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2251 total_written
+= nwritten
;
2254 if ((lp_syncalways(SNUM(conn
)) || write_through
) && lp_strict_sync(SNUM(conn
)))
2255 sync_file(conn
,fsp
);
2257 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2258 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
2260 /* we won't return a status if write through is not selected - this follows what WfWg does */
2261 END_PROFILE(SMBwritebraw
);
2262 if (!write_through
&& total_written
==tcount
) {
2264 #if RABBIT_PELLET_FIX
2266 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2267 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2269 if (!send_keepalive(smbd_server_fd()))
2270 exit_server("reply_writebraw: send of keepalive failed");
2278 /****************************************************************************
2279 Reply to a writeunlock (core+).
2280 ****************************************************************************/
2282 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
,
2283 int size
, int dum_buffsize
)
2285 ssize_t nwritten
= -1;
2289 NTSTATUS status
= NT_STATUS_OK
;
2290 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2292 START_PROFILE(SMBwriteunlock
);
2294 CHECK_FSP(fsp
,conn
);
2297 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2298 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2299 data
= smb_buf(inbuf
) + 3;
2301 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
,
2302 WRITE_LOCK
,False
)) {
2303 END_PROFILE(SMBwriteunlock
);
2304 return ERROR_DOS(ERRDOS
,ERRlock
);
2307 /* The special X/Open SMB protocol handling of
2308 zero length writes is *NOT* done for
2313 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2315 if (lp_syncalways(SNUM(conn
)))
2316 sync_file(conn
,fsp
);
2318 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2319 END_PROFILE(SMBwriteunlock
);
2320 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2324 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)numtowrite
,
2325 (SMB_BIG_UINT
)startpos
);
2326 if (NT_STATUS_V(status
)) {
2327 END_PROFILE(SMBwriteunlock
);
2328 return ERROR_NT(status
);
2332 outsize
= set_message(outbuf
,1,0,True
);
2334 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2336 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2337 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2339 END_PROFILE(SMBwriteunlock
);
2343 /****************************************************************************
2345 ****************************************************************************/
2347 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2350 ssize_t nwritten
= -1;
2353 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2355 START_PROFILE(SMBwrite
);
2357 /* If it's an IPC, pass off the pipe handler. */
2359 END_PROFILE(SMBwrite
);
2360 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2363 CHECK_FSP(fsp
,conn
);
2366 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2367 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2368 data
= smb_buf(inbuf
) + 3;
2370 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2371 END_PROFILE(SMBwrite
);
2372 return ERROR_DOS(ERRDOS
,ERRlock
);
2376 * X/Open SMB protocol says that if smb_vwv1 is
2377 * zero then the file size should be extended or
2378 * truncated to the size given in smb_vwv[2-3].
2381 if(numtowrite
== 0) {
2383 * This is actually an allocate call, and set EOF. JRA.
2385 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2387 END_PROFILE(SMBwrite
);
2388 return ERROR_NT(NT_STATUS_DISK_FULL
);
2390 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2392 END_PROFILE(SMBwrite
);
2393 return ERROR_NT(NT_STATUS_DISK_FULL
);
2396 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2398 if (lp_syncalways(SNUM(conn
)))
2399 sync_file(conn
,fsp
);
2401 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2402 END_PROFILE(SMBwrite
);
2403 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2406 outsize
= set_message(outbuf
,1,0,True
);
2408 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2410 if (nwritten
< (ssize_t
)numtowrite
) {
2411 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2412 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2415 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2417 END_PROFILE(SMBwrite
);
2421 /****************************************************************************
2422 Reply to a write and X.
2423 ****************************************************************************/
2425 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2427 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2428 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2429 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2430 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2431 ssize_t nwritten
= -1;
2432 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2433 unsigned int smblen
= smb_len(inbuf
);
2435 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2436 START_PROFILE(SMBwriteX
);
2438 /* If it's an IPC, pass off the pipe handler. */
2440 END_PROFILE(SMBwriteX
);
2441 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2444 CHECK_FSP(fsp
,conn
);
2447 /* Deal with possible LARGE_WRITEX */
2449 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2451 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2452 END_PROFILE(SMBwriteX
);
2453 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2456 data
= smb_base(inbuf
) + smb_doff
;
2458 if(CVAL(inbuf
,smb_wct
) == 14) {
2459 #ifdef LARGE_SMB_OFF_T
2461 * This is a large offset (64 bit) write.
2463 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2465 #else /* !LARGE_SMB_OFF_T */
2468 * Ensure we haven't been sent a >32 bit offset.
2471 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2472 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2473 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2474 END_PROFILE(SMBwriteX
);
2475 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2478 #endif /* LARGE_SMB_OFF_T */
2481 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2482 END_PROFILE(SMBwriteX
);
2483 return ERROR_DOS(ERRDOS
,ERRlock
);
2486 /* X/Open SMB protocol says that, unlike SMBwrite
2487 if the length is zero then NO truncation is
2488 done, just a write of zero. To truncate a file,
2494 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2496 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2497 END_PROFILE(SMBwriteX
);
2498 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2501 set_message(outbuf
,6,0,True
);
2503 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2505 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2507 if (nwritten
< (ssize_t
)numtowrite
) {
2508 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2509 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2512 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2513 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2515 if (lp_syncalways(SNUM(conn
)) || write_through
)
2516 sync_file(conn
,fsp
);
2518 END_PROFILE(SMBwriteX
);
2519 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2522 /****************************************************************************
2524 ****************************************************************************/
2526 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2532 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2533 START_PROFILE(SMBlseek
);
2535 CHECK_FSP(fsp
,conn
);
2537 flush_write_cache(fsp
, SEEK_FLUSH
);
2539 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2540 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2541 startpos
= (SMB_OFF_T
)IVALS(inbuf
,smb_vwv2
);
2550 res
= fsp
->pos
+ startpos
;
2561 if (umode
== SEEK_END
) {
2562 if((res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
2563 if(errno
== EINVAL
) {
2564 SMB_OFF_T current_pos
= startpos
;
2565 SMB_STRUCT_STAT sbuf
;
2567 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1) {
2568 END_PROFILE(SMBlseek
);
2569 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2572 current_pos
+= sbuf
.st_size
;
2574 res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,0,SEEK_SET
);
2579 END_PROFILE(SMBlseek
);
2580 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2586 outsize
= set_message(outbuf
,2,0,True
);
2587 SIVAL(outbuf
,smb_vwv0
,res
);
2589 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2590 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
2592 END_PROFILE(SMBlseek
);
2596 /****************************************************************************
2598 ****************************************************************************/
2600 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2602 int outsize
= set_message(outbuf
,0,0,True
);
2603 uint16 fnum
= SVAL(inbuf
,smb_vwv0
);
2604 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2605 START_PROFILE(SMBflush
);
2608 CHECK_FSP(fsp
,conn
);
2611 file_sync_all(conn
);
2613 sync_file(conn
,fsp
);
2616 DEBUG(3,("flush\n"));
2617 END_PROFILE(SMBflush
);
2621 /****************************************************************************
2623 ****************************************************************************/
2625 int reply_exit(connection_struct
*conn
,
2626 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2629 START_PROFILE(SMBexit
);
2631 file_close_pid(SVAL(inbuf
,smb_pid
));
2633 outsize
= set_message(outbuf
,0,0,True
);
2635 DEBUG(3,("exit\n"));
2637 END_PROFILE(SMBexit
);
2641 /****************************************************************************
2642 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2643 ****************************************************************************/
2645 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2648 extern struct current_user current_user
;
2651 int32 eclass
= 0, err
= 0;
2652 files_struct
*fsp
= NULL
;
2653 START_PROFILE(SMBclose
);
2655 outsize
= set_message(outbuf
,0,0,True
);
2657 /* If it's an IPC, pass off to the pipe handler. */
2659 END_PROFILE(SMBclose
);
2660 return reply_pipe_close(conn
, inbuf
,outbuf
);
2663 fsp
= file_fsp(inbuf
,smb_vwv0
);
2666 * We can only use CHECK_FSP if we know it's not a directory.
2669 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= current_user
.vuid
)) {
2670 END_PROFILE(SMBclose
);
2671 return ERROR_DOS(ERRDOS
,ERRbadfid
);
2674 if(fsp
->is_directory
) {
2676 * Special case - close NT SMB directory handle.
2678 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
2679 close_file(fsp
,True
);
2682 * Close ordinary file.
2687 /* Save the name for time set in close. */
2688 pstrcpy( file_name
, fsp
->fsp_name
);
2690 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2692 conn
->num_files_open
));
2695 * close_file() returns the unix errno if an error
2696 * was detected on close - normally this is due to
2697 * a disk full error. If not then it was probably an I/O error.
2700 if((close_err
= close_file(fsp
,True
)) != 0) {
2702 END_PROFILE(SMBclose
);
2703 return (UNIXERROR(ERRHRD
,ERRgeneral
));
2707 * Now take care of any time sent in the close.
2710 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2712 /* try and set the date */
2713 set_filetime(conn
, file_name
, mtime
);
2717 /* We have a cached error */
2719 END_PROFILE(SMBclose
);
2720 return ERROR_DOS(eclass
,err
);
2723 END_PROFILE(SMBclose
);
2727 /****************************************************************************
2728 Reply to a writeclose (Core+ protocol).
2729 ****************************************************************************/
2731 int reply_writeclose(connection_struct
*conn
,
2732 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2735 ssize_t nwritten
= -1;
2741 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2742 START_PROFILE(SMBwriteclose
);
2744 CHECK_FSP(fsp
,conn
);
2747 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2748 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2749 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2750 data
= smb_buf(inbuf
) + 1;
2752 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2753 END_PROFILE(SMBwriteclose
);
2754 return ERROR_DOS(ERRDOS
,ERRlock
);
2757 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2759 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2762 * More insanity. W2K only closes the file if writelen > 0.
2767 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2769 close_err
= close_file(fsp
,True
);
2772 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2773 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
2774 conn
->num_files_open
));
2776 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2777 END_PROFILE(SMBwriteclose
);
2778 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2781 if(close_err
!= 0) {
2783 END_PROFILE(SMBwriteclose
);
2784 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2787 outsize
= set_message(outbuf
,1,0,True
);
2789 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2790 END_PROFILE(SMBwriteclose
);
2794 /****************************************************************************
2796 ****************************************************************************/
2798 int reply_lock(connection_struct
*conn
,
2799 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
2801 int outsize
= set_message(outbuf
,0,0,True
);
2802 SMB_BIG_UINT count
,offset
;
2804 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2805 BOOL my_lock_ctx
= False
;
2807 START_PROFILE(SMBlock
);
2809 CHECK_FSP(fsp
,conn
);
2811 release_level_2_oplocks_on_change(fsp
);
2813 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2814 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2816 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2817 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
2819 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
, WRITE_LOCK
, &my_lock_ctx
);
2820 if (NT_STATUS_V(status
)) {
2822 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2823 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
2825 * A blocking lock was requested. Package up
2826 * this smb into a queued request and push it
2827 * onto the blocking lock queue.
2829 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), offset
, count
)) {
2830 END_PROFILE(SMBlock
);
2835 END_PROFILE(SMBlock
);
2836 return ERROR_NT(status
);
2839 END_PROFILE(SMBlock
);
2843 /****************************************************************************
2845 ****************************************************************************/
2847 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2850 int outsize
= set_message(outbuf
,0,0,True
);
2851 SMB_BIG_UINT count
,offset
;
2853 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2854 START_PROFILE(SMBunlock
);
2856 CHECK_FSP(fsp
,conn
);
2858 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2859 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2861 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
);
2862 if (NT_STATUS_V(status
)) {
2863 END_PROFILE(SMBunlock
);
2864 return ERROR_NT(status
);
2867 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2868 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
2870 END_PROFILE(SMBunlock
);
2874 /****************************************************************************
2876 ****************************************************************************/
2878 int reply_tdis(connection_struct
*conn
,
2879 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2881 int outsize
= set_message(outbuf
,0,0,True
);
2883 START_PROFILE(SMBtdis
);
2885 vuid
= SVAL(inbuf
,smb_uid
);
2888 DEBUG(4,("Invalid connection in tdis\n"));
2889 END_PROFILE(SMBtdis
);
2890 return ERROR_DOS(ERRSRV
,ERRinvnid
);
2895 close_cnum(conn
,vuid
);
2897 END_PROFILE(SMBtdis
);
2901 /****************************************************************************
2903 ****************************************************************************/
2905 int reply_echo(connection_struct
*conn
,
2906 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2908 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2910 unsigned int data_len
= smb_buflen(inbuf
);
2911 int outsize
= set_message(outbuf
,1,data_len
,True
);
2912 START_PROFILE(SMBecho
);
2914 if (data_len
> BUFFER_SIZE
) {
2915 DEBUG(0,("reply_echo: data_len too large.\n"));
2916 END_PROFILE(SMBecho
);
2920 /* copy any incoming data back out */
2922 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2924 if (smb_reverb
> 100) {
2925 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2929 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2930 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2932 smb_setlen(outbuf
,outsize
- 4);
2934 if (!send_smb(smbd_server_fd(),outbuf
))
2935 exit_server("reply_echo: send_smb failed.");
2938 DEBUG(3,("echo %d times\n", smb_reverb
));
2942 END_PROFILE(SMBecho
);
2946 /****************************************************************************
2947 Reply to a printopen.
2948 ****************************************************************************/
2950 int reply_printopen(connection_struct
*conn
,
2951 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2955 START_PROFILE(SMBsplopen
);
2957 if (!CAN_PRINT(conn
)) {
2958 END_PROFILE(SMBsplopen
);
2959 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2962 /* Open for exclusive use, write only. */
2963 fsp
= print_fsp_open(conn
, NULL
);
2966 END_PROFILE(SMBsplopen
);
2967 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2970 outsize
= set_message(outbuf
,1,0,True
);
2971 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2973 DEBUG(3,("openprint fd=%d fnum=%d\n",
2974 fsp
->fd
, fsp
->fnum
));
2976 END_PROFILE(SMBsplopen
);
2980 /****************************************************************************
2981 Reply to a printclose.
2982 ****************************************************************************/
2984 int reply_printclose(connection_struct
*conn
,
2985 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2987 int outsize
= set_message(outbuf
,0,0,True
);
2988 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2990 START_PROFILE(SMBsplclose
);
2992 CHECK_FSP(fsp
,conn
);
2994 if (!CAN_PRINT(conn
)) {
2995 END_PROFILE(SMBsplclose
);
2996 return ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
2999 DEBUG(3,("printclose fd=%d fnum=%d\n",
3000 fsp
->fd
,fsp
->fnum
));
3002 close_err
= close_file(fsp
,True
);
3004 if(close_err
!= 0) {
3006 END_PROFILE(SMBsplclose
);
3007 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3010 END_PROFILE(SMBsplclose
);
3014 /****************************************************************************
3015 Reply to a printqueue.
3016 ****************************************************************************/
3018 int reply_printqueue(connection_struct
*conn
,
3019 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3021 int outsize
= set_message(outbuf
,2,3,True
);
3022 int max_count
= SVAL(inbuf
,smb_vwv0
);
3023 int start_index
= SVAL(inbuf
,smb_vwv1
);
3024 START_PROFILE(SMBsplretq
);
3026 /* we used to allow the client to get the cnum wrong, but that
3027 is really quite gross and only worked when there was only
3028 one printer - I think we should now only accept it if they
3029 get it right (tridge) */
3030 if (!CAN_PRINT(conn
)) {
3031 END_PROFILE(SMBsplretq
);
3032 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3035 SSVAL(outbuf
,smb_vwv0
,0);
3036 SSVAL(outbuf
,smb_vwv1
,0);
3037 SCVAL(smb_buf(outbuf
),0,1);
3038 SSVAL(smb_buf(outbuf
),1,0);
3040 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3041 start_index
, max_count
));
3044 print_queue_struct
*queue
= NULL
;
3045 print_status_struct status
;
3046 char *p
= smb_buf(outbuf
) + 3;
3047 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
3048 int num_to_get
= ABS(max_count
);
3049 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
3055 num_to_get
= MIN(num_to_get
,count
-first
);
3058 for (i
=first
;i
<first
+num_to_get
;i
++) {
3059 put_dos_date2(p
,0,queue
[i
].time
);
3060 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
3061 SSVAL(p
,5, queue
[i
].job
);
3062 SIVAL(p
,7,queue
[i
].size
);
3064 srvstr_push(outbuf
, p
+12, queue
[i
].fs_user
, 16, STR_ASCII
);
3069 outsize
= set_message(outbuf
,2,28*count
+3,False
);
3070 SSVAL(outbuf
,smb_vwv0
,count
);
3071 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
3072 SCVAL(smb_buf(outbuf
),0,1);
3073 SSVAL(smb_buf(outbuf
),1,28*count
);
3078 DEBUG(3,("%d entries returned in queue\n",count
));
3081 END_PROFILE(SMBsplretq
);
3085 /****************************************************************************
3086 Reply to a printwrite.
3087 ****************************************************************************/
3089 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3092 int outsize
= set_message(outbuf
,0,0,True
);
3094 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3096 START_PROFILE(SMBsplwr
);
3098 if (!CAN_PRINT(conn
)) {
3099 END_PROFILE(SMBsplwr
);
3100 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3103 CHECK_FSP(fsp
,conn
);
3106 numtowrite
= SVAL(smb_buf(inbuf
),1);
3107 data
= smb_buf(inbuf
) + 3;
3109 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
3110 END_PROFILE(SMBsplwr
);
3111 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3114 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
3116 END_PROFILE(SMBsplwr
);
3120 /****************************************************************************
3121 The guts of the mkdir command, split out so it may be called by the NT SMB
3123 ****************************************************************************/
3125 NTSTATUS
mkdir_internal(connection_struct
*conn
, pstring directory
)
3127 BOOL bad_path
= False
;
3128 SMB_STRUCT_STAT sbuf
;
3131 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3133 if( strchr_m(directory
, ':')) {
3134 return NT_STATUS_NOT_A_DIRECTORY
;
3137 if (ms_has_wild(directory
)) {
3138 return NT_STATUS_OBJECT_NAME_INVALID
;
3141 if (check_name(directory
, conn
))
3142 ret
= vfs_MkDir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3145 if(errno
== ENOENT
) {
3147 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3149 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3151 return map_nt_error_from_unix(errno
);
3154 return NT_STATUS_OK
;
3157 /****************************************************************************
3159 ****************************************************************************/
3161 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3166 START_PROFILE(SMBmkdir
);
3168 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3169 if (!NT_STATUS_IS_OK(status
)) {
3170 END_PROFILE(SMBmkdir
);
3171 return ERROR_NT(status
);
3174 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
);
3176 status
= mkdir_internal(conn
, directory
);
3177 if (!NT_STATUS_IS_OK(status
)) {
3178 END_PROFILE(SMBmkdir
);
3179 return ERROR_NT(status
);
3182 outsize
= set_message(outbuf
,0,0,True
);
3184 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
3186 END_PROFILE(SMBmkdir
);
3190 /****************************************************************************
3191 Static function used by reply_rmdir to delete an entire directory
3192 tree recursively. Return False on ok, True on fail.
3193 ****************************************************************************/
3195 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
3197 const char *dname
= NULL
;
3199 void *dirptr
= OpenDir(conn
, directory
, False
);
3204 while((dname
= ReadDirName(dirptr
))) {
3208 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3211 /* Construct the full name. */
3212 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3218 pstrcpy(fullname
, directory
);
3219 pstrcat(fullname
, "/");
3220 pstrcat(fullname
, dname
);
3222 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
3227 if(st
.st_mode
& S_IFDIR
) {
3228 if(recursive_rmdir(conn
, fullname
)!=0) {
3232 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
3236 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
3245 /****************************************************************************
3246 The internals of the rmdir code - called elsewhere.
3247 ****************************************************************************/
3249 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
3253 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3254 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
3256 * Check to see if the only thing in this directory are
3257 * vetoed files/directories. If so then delete them and
3258 * retry. If we fail to delete any of them (and we *don't*
3259 * do a recursive delete) then fail the rmdir.
3261 BOOL all_veto_files
= True
;
3263 void *dirptr
= OpenDir(conn
, directory
, False
);
3265 if(dirptr
!= NULL
) {
3266 int dirpos
= TellDir(dirptr
);
3267 while ((dname
= ReadDirName(dirptr
))) {
3268 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3270 if(!IS_VETO_PATH(conn
, dname
)) {
3271 all_veto_files
= False
;
3276 if(all_veto_files
) {
3277 SeekDir(dirptr
,dirpos
);
3278 while ((dname
= ReadDirName(dirptr
))) {
3282 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3285 /* Construct the full name. */
3286 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3291 pstrcpy(fullname
, directory
);
3292 pstrcat(fullname
, "/");
3293 pstrcat(fullname
, dname
);
3295 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0)
3297 if(st
.st_mode
& S_IFDIR
) {
3298 if(lp_recursive_veto_delete(SNUM(conn
))) {
3299 if(recursive_rmdir(conn
, fullname
) != 0)
3302 if(SMB_VFS_RMDIR(conn
,fullname
) != 0)
3304 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0)
3308 /* Retry the rmdir */
3309 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3319 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory
,strerror(errno
)));
3324 /****************************************************************************
3326 ****************************************************************************/
3328 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3333 BOOL bad_path
= False
;
3334 SMB_STRUCT_STAT sbuf
;
3336 START_PROFILE(SMBrmdir
);
3338 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3339 if (!NT_STATUS_IS_OK(status
)) {
3340 END_PROFILE(SMBrmdir
);
3341 return ERROR_NT(status
);
3344 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3346 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3348 if (check_name(directory
,conn
)) {
3349 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3350 ok
= rmdir_internals(conn
, directory
);
3354 END_PROFILE(SMBrmdir
);
3355 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRbadpath
);
3358 outsize
= set_message(outbuf
,0,0,True
);
3360 DEBUG( 3, ( "rmdir %s\n", directory
) );
3362 END_PROFILE(SMBrmdir
);
3366 /*******************************************************************
3367 Resolve wildcards in a filename rename.
3368 Note that name is in UNIX charset and thus potentially can be more
3369 than fstring buffer (255 bytes) especially in default UTF-8 case.
3370 Therefore, we use pstring inside and all calls should ensure that
3371 name2 is at least pstring-long (they do already)
3372 ********************************************************************/
3374 static BOOL
resolve_wildcards(const char *name1
, char *name2
)
3376 pstring root1
,root2
;
3378 char *p
,*p2
, *pname1
, *pname2
;
3379 int available_space
, actual_space
;
3382 pname1
= strrchr_m(name1
,'/');
3383 pname2
= strrchr_m(name2
,'/');
3385 if (!pname1
|| !pname2
)
3388 pstrcpy(root1
,pname1
);
3389 pstrcpy(root2
,pname2
);
3390 p
= strrchr_m(root1
,'.');
3397 p
= strrchr_m(root2
,'.');
3431 available_space
= sizeof(pstring
) - PTR_DIFF(pname2
, name2
);
3434 actual_space
= snprintf(pname2
, available_space
- 1, "%s.%s", root2
, ext2
);
3435 if (actual_space
>= available_space
- 1) {
3436 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3437 actual_space
- available_space
));
3440 pstrcpy_base(pname2
, root2
, name2
);
3446 /****************************************************************************
3447 Ensure open files have their names updates.
3448 ****************************************************************************/
3450 static void rename_open_files(connection_struct
*conn
, SMB_DEV_T dev
, SMB_INO_T inode
, char *newname
)
3453 BOOL did_rename
= False
;
3455 for(fsp
= file_find_di_first(dev
, inode
); fsp
; fsp
= file_find_di_next(fsp
)) {
3456 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3457 fsp
->fnum
, (unsigned int)fsp
->dev
, (double)fsp
->inode
,
3458 fsp
->fsp_name
, newname
));
3459 string_set(&fsp
->fsp_name
, newname
);
3464 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3465 (unsigned int)dev
, (double)inode
, newname
));
3468 /****************************************************************************
3469 Rename an open file - given an fsp.
3470 ****************************************************************************/
3472 NTSTATUS
rename_internals_fsp(connection_struct
*conn
, files_struct
*fsp
, char *newname
, BOOL replace_if_exists
)
3474 SMB_STRUCT_STAT sbuf
;
3475 BOOL bad_path
= False
;
3476 pstring newname_last_component
;
3477 NTSTATUS error
= NT_STATUS_OK
;
3482 rcdest
= unix_convert(newname
,conn
,newname_last_component
,&bad_path
,&sbuf
);
3484 /* Quick check for "." and ".." */
3485 if (!bad_path
&& newname_last_component
[0] == '.') {
3486 if (!newname_last_component
[1] || (newname_last_component
[1] == '.' && !newname_last_component
[2])) {
3487 return NT_STATUS_ACCESS_DENIED
;
3490 if (!rcdest
&& bad_path
) {
3491 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3494 /* Ensure newname contains a '/' */
3495 if(strrchr_m(newname
,'/') == 0) {
3498 pstrcpy(tmpstr
, "./");
3499 pstrcat(tmpstr
, newname
);
3500 pstrcpy(newname
, tmpstr
);
3504 * Check for special case with case preserving and not
3505 * case sensitive. If the old last component differs from the original
3506 * last component only by case, then we should allow
3507 * the rename (user is trying to change the case of the
3511 if((case_sensitive
== False
) && (case_preserve
== True
) &&
3512 strequal(newname
, fsp
->fsp_name
)) {
3514 pstring newname_modified_last_component
;
3517 * Get the last component of the modified name.
3518 * Note that we guarantee that newname contains a '/'
3521 p
= strrchr_m(newname
,'/');
3522 pstrcpy(newname_modified_last_component
,p
+1);
3524 if(strcsequal(newname_modified_last_component
,
3525 newname_last_component
) == False
) {
3527 * Replace the modified last component with
3530 pstrcpy(p
+1, newname_last_component
);
3535 * If the src and dest names are identical - including case,
3536 * don't do the rename, just return success.
3539 if (strcsequal(fsp
->fsp_name
, newname
)) {
3540 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3542 return NT_STATUS_OK
;
3545 dest_exists
= vfs_object_exist(conn
,newname
,NULL
);
3547 if(!replace_if_exists
&& dest_exists
) {
3548 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3549 fsp
->fsp_name
,newname
));
3550 return NT_STATUS_OBJECT_NAME_COLLISION
;
3553 error
= can_rename(newname
,conn
,&sbuf
);
3555 if (dest_exists
&& !NT_STATUS_IS_OK(error
)) {
3556 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3557 nt_errstr(error
), fsp
->fsp_name
,newname
));
3558 if (NT_STATUS_EQUAL(error
,NT_STATUS_SHARING_VIOLATION
))
3559 error
= NT_STATUS_ACCESS_DENIED
;
3563 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
3564 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3565 fsp
->fsp_name
,newname
));
3566 rename_open_files(conn
, fsp
->dev
, fsp
->inode
, newname
);
3567 return NT_STATUS_OK
;
3570 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3571 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3573 error
= map_nt_error_from_unix(errno
);
3575 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3576 nt_errstr(error
), fsp
->fsp_name
,newname
));
3581 /****************************************************************************
3582 The guts of the rename command, split out so it may be called by the NT SMB
3584 ****************************************************************************/
3586 NTSTATUS
rename_internals(connection_struct
*conn
, char *name
, char *newname
, uint16 attrs
, BOOL replace_if_exists
)
3590 pstring last_component_src
;
3591 pstring last_component_dest
;
3594 BOOL bad_path_src
= False
;
3595 BOOL bad_path_dest
= False
;
3597 NTSTATUS error
= NT_STATUS_OK
;
3600 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3602 *directory
= *mask
= 0;
3607 rc
= unix_convert(name
,conn
,last_component_src
,&bad_path_src
,&sbuf1
);
3608 if (!rc
&& bad_path_src
) {
3609 if (ms_has_wild(last_component_src
))
3610 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3611 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3614 /* Quick check for "." and ".." */
3615 if (last_component_src
[0] == '.') {
3616 if (!last_component_src
[1] || (last_component_src
[1] == '.' && !last_component_src
[2])) {
3617 return NT_STATUS_OBJECT_NAME_INVALID
;
3621 rcdest
= unix_convert(newname
,conn
,last_component_dest
,&bad_path_dest
,&sbuf2
);
3623 /* Quick check for "." and ".." */
3624 if (last_component_dest
[0] == '.') {
3625 if (!last_component_dest
[1] || (last_component_dest
[1] == '.' && !last_component_dest
[2])) {
3626 return NT_STATUS_OBJECT_NAME_INVALID
;
3631 * Split the old name into directory and last component
3632 * strings. Note that unix_convert may have stripped off a
3633 * leading ./ from both name and newname if the rename is
3634 * at the root of the share. We need to make sure either both
3635 * name and newname contain a / character or neither of them do
3636 * as this is checked in resolve_wildcards().
3639 p
= strrchr_m(name
,'/');
3641 pstrcpy(directory
,".");
3645 pstrcpy(directory
,name
);
3647 *p
= '/'; /* Replace needed for exceptional test below. */
3651 * We should only check the mangled cache
3652 * here if unix_convert failed. This means
3653 * that the path in 'mask' doesn't exist
3654 * on the file system and so we need to look
3655 * for a possible mangle. This patch from
3656 * Tine Smukavec <valentin.smukavec@hermes.si>.
3659 if (!rc
&& mangle_is_mangled(mask
))
3660 mangle_check_cache( mask
);
3662 has_wild
= ms_has_wild(mask
);
3666 * No wildcards - just process the one file.
3668 BOOL is_short_name
= mangle_is_8_3(name
, True
);
3670 /* Add a terminating '/' to the directory name. */
3671 pstrcat(directory
,"/");
3672 pstrcat(directory
,mask
);
3674 /* Ensure newname contains a '/' also */
3675 if(strrchr_m(newname
,'/') == 0) {
3678 pstrcpy(tmpstr
, "./");
3679 pstrcat(tmpstr
, newname
);
3680 pstrcpy(newname
, tmpstr
);
3683 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3684 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3685 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3686 newname
, last_component_dest
, is_short_name
));
3689 * Check for special case with case preserving and not
3690 * case sensitive, if directory and newname are identical,
3691 * and the old last component differs from the original
3692 * last component only by case, then we should allow
3693 * the rename (user is trying to change the case of the
3696 if((case_sensitive
== False
) &&
3697 (((case_preserve
== True
) &&
3698 (is_short_name
== False
)) ||
3699 ((short_case_preserve
== True
) &&
3700 (is_short_name
== True
))) &&
3701 strcsequal(directory
, newname
)) {
3702 pstring modified_last_component
;
3705 * Get the last component of the modified name.
3706 * Note that we guarantee that newname contains a '/'
3709 p
= strrchr_m(newname
,'/');
3710 pstrcpy(modified_last_component
,p
+1);
3712 if(strcsequal(modified_last_component
,
3713 last_component_dest
) == False
) {
3715 * Replace the modified last component with
3718 pstrcpy(p
+1, last_component_dest
);
3722 resolve_wildcards(directory
,newname
);
3725 * The source object must exist.
3728 if (!vfs_object_exist(conn
, directory
, &sbuf1
)) {
3729 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3730 directory
,newname
));
3732 if (errno
== ENOTDIR
|| errno
== EISDIR
|| errno
== ENOENT
) {
3734 * Must return different errors depending on whether the parent
3735 * directory existed or not.
3738 p
= strrchr_m(directory
, '/');
3740 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3742 if (vfs_object_exist(conn
, directory
, NULL
))
3743 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3744 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3746 error
= map_nt_error_from_unix(errno
);
3747 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3748 nt_errstr(error
), directory
,newname
));
3753 if (!rcdest
&& bad_path_dest
) {
3754 if (ms_has_wild(last_component_dest
))
3755 return NT_STATUS_OBJECT_NAME_INVALID
;
3756 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3759 error
= can_rename(directory
,conn
,&sbuf1
);
3761 if (!NT_STATUS_IS_OK(error
)) {
3762 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3763 nt_errstr(error
), directory
,newname
));
3768 * If the src and dest names are identical - including case,
3769 * don't do the rename, just return success.
3772 if (strcsequal(directory
, newname
)) {
3773 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3774 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory
));
3775 return NT_STATUS_OK
;
3778 if(!replace_if_exists
&& vfs_object_exist(conn
,newname
,NULL
)) {
3779 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3780 directory
,newname
));
3781 return NT_STATUS_OBJECT_NAME_COLLISION
;
3784 if(SMB_VFS_RENAME(conn
,directory
, newname
) == 0) {
3785 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3786 directory
,newname
));
3787 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3788 return NT_STATUS_OK
;
3791 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3792 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3794 error
= map_nt_error_from_unix(errno
);
3796 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3797 nt_errstr(error
), directory
,newname
));
3802 * Wildcards - process each file that matches.
3804 void *dirptr
= NULL
;
3808 if (check_name(directory
,conn
))
3809 dirptr
= OpenDir(conn
, directory
, True
);
3812 error
= NT_STATUS_NO_SUCH_FILE
;
3813 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3815 if (strequal(mask
,"????????.???"))
3818 while ((dname
= ReadDirName(dirptr
))) {
3820 BOOL sysdir_entry
= False
;
3822 pstrcpy(fname
,dname
);
3824 /* Quick check for "." and ".." */
3825 if (fname
[0] == '.') {
3826 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
3828 sysdir_entry
= True
;
3835 if(!mask_match(fname
, mask
, case_sensitive
))
3839 error
= NT_STATUS_OBJECT_NAME_INVALID
;
3843 error
= NT_STATUS_ACCESS_DENIED
;
3844 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3845 if (!vfs_object_exist(conn
, fname
, &sbuf1
)) {
3846 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3847 DEBUG(6,("rename %s failed. Error %s\n", fname
, nt_errstr(error
)));
3850 error
= can_rename(fname
,conn
,&sbuf1
);
3851 if (!NT_STATUS_IS_OK(error
)) {
3852 DEBUG(6,("rename %s refused\n", fname
));
3855 pstrcpy(destname
,newname
);
3857 if (!resolve_wildcards(fname
,destname
)) {
3858 DEBUG(6,("resolve_wildcards %s %s failed\n",
3863 if (strcsequal(fname
,destname
)) {
3864 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3865 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname
));
3867 error
= NT_STATUS_OK
;
3871 if (!replace_if_exists
&&
3872 vfs_file_exist(conn
,destname
, NULL
)) {
3873 DEBUG(6,("file_exist %s\n", destname
));
3874 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3878 if (!SMB_VFS_RENAME(conn
,fname
,destname
)) {
3879 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3881 error
= NT_STATUS_OK
;
3883 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3888 if (!NT_STATUS_EQUAL(error
,NT_STATUS_NO_SUCH_FILE
)) {
3889 if (!rcdest
&& bad_path_dest
) {
3890 if (ms_has_wild(last_component_dest
))
3891 return NT_STATUS_OBJECT_NAME_INVALID
;
3892 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3897 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
3898 error
= map_nt_error_from_unix(errno
);
3904 /****************************************************************************
3906 ****************************************************************************/
3908 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
3915 uint16 attrs
= SVAL(inbuf
,smb_vwv0
);
3918 START_PROFILE(SMBmv
);
3920 p
= smb_buf(inbuf
) + 1;
3921 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
);
3922 if (!NT_STATUS_IS_OK(status
)) {
3924 return ERROR_NT(status
);
3927 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
);
3928 if (!NT_STATUS_IS_OK(status
)) {
3930 return ERROR_NT(status
);
3933 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3934 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3936 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3938 status
= rename_internals(conn
, name
, newname
, attrs
, False
);
3939 if (!NT_STATUS_IS_OK(status
)) {
3941 return ERROR_NT(status
);
3945 * Win2k needs a changenotify request response before it will
3946 * update after a rename..
3948 process_pending_change_notify_queue((time_t)0);
3949 outsize
= set_message(outbuf
,0,0,True
);
3955 /*******************************************************************
3956 Copy a file as part of a reply_copy.
3957 ******************************************************************/
3959 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3960 int count
,BOOL target_is_directory
, int *err_ret
)
3963 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
3965 files_struct
*fsp1
,*fsp2
;
3971 pstrcpy(dest
,dest1
);
3972 if (target_is_directory
) {
3973 char *p
= strrchr_m(src
,'/');
3982 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
3985 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3986 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),FILE_ATTRIBUTE_NORMAL
,0,&Access
,&action
);
3991 if (!target_is_directory
&& count
)
3992 ofun
= FILE_EXISTS_OPEN
;
3994 dosattrs
= dos_mode(conn
, src
, &src_sbuf
);
3995 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1)
3996 ZERO_STRUCTP(&sbuf2
);
3998 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3999 ofun
,dosattrs
,0,&Access
,&action
);
4002 close_file(fsp1
,False
);
4006 if ((ofun
&3) == 1) {
4007 if(SMB_VFS_LSEEK(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
4008 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
4010 * Stop the copy from occurring.
4013 src_sbuf
.st_size
= 0;
4017 if (src_sbuf
.st_size
)
4018 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
4020 close_file(fsp1
,False
);
4022 /* Ensure the modtime is set correctly on the destination file. */
4023 fsp2
->pending_modtime
= src_sbuf
.st_mtime
;
4026 * As we are opening fsp1 read-only we only expect
4027 * an error on close on fsp2 if we are out of space.
4028 * Thus we don't look at the error return from the
4031 *err_ret
= close_file(fsp2
,False
);
4033 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
4036 /****************************************************************************
4037 Reply to a file copy.
4038 ****************************************************************************/
4040 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4045 pstring mask
,newname
;
4048 int error
= ERRnoaccess
;
4052 int tid2
= SVAL(inbuf
,smb_vwv0
);
4053 int ofun
= SVAL(inbuf
,smb_vwv1
);
4054 int flags
= SVAL(inbuf
,smb_vwv2
);
4055 BOOL target_is_directory
=False
;
4056 BOOL bad_path1
= False
;
4057 BOOL bad_path2
= False
;
4059 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4062 START_PROFILE(SMBcopy
);
4064 *directory
= *mask
= 0;
4067 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
);
4068 if (!NT_STATUS_IS_OK(status
)) {
4069 END_PROFILE(SMBcopy
);
4070 return ERROR_NT(status
);
4072 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
);
4073 if (!NT_STATUS_IS_OK(status
)) {
4074 END_PROFILE(SMBcopy
);
4075 return ERROR_NT(status
);
4078 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
4080 if (tid2
!= conn
->cnum
) {
4081 /* can't currently handle inter share copies XXXX */
4082 DEBUG(3,("Rejecting inter-share copy\n"));
4083 END_PROFILE(SMBcopy
);
4084 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
4087 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
4088 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
4090 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
4091 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
4093 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
4095 if ((flags
&1) && target_is_directory
) {
4096 END_PROFILE(SMBcopy
);
4097 return ERROR_DOS(ERRDOS
,ERRbadfile
);
4100 if ((flags
&2) && !target_is_directory
) {
4101 END_PROFILE(SMBcopy
);
4102 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4105 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
4106 /* wants a tree copy! XXXX */
4107 DEBUG(3,("Rejecting tree copy\n"));
4108 END_PROFILE(SMBcopy
);
4109 return ERROR_DOS(ERRSRV
,ERRerror
);
4112 p
= strrchr_m(name
,'/');
4114 pstrcpy(directory
,"./");
4118 pstrcpy(directory
,name
);
4123 * We should only check the mangled cache
4124 * here if unix_convert failed. This means
4125 * that the path in 'mask' doesn't exist
4126 * on the file system and so we need to look
4127 * for a possible mangle. This patch from
4128 * Tine Smukavec <valentin.smukavec@hermes.si>.
4131 if (!rc
&& mangle_is_mangled(mask
))
4132 mangle_check_cache( mask
);
4134 has_wild
= ms_has_wild(mask
);
4137 pstrcat(directory
,"/");
4138 pstrcat(directory
,mask
);
4139 if (resolve_wildcards(directory
,newname
) &&
4140 copy_file(directory
,newname
,conn
,ofun
, count
,target_is_directory
,&err
))
4144 END_PROFILE(SMBcopy
);
4145 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4148 exists
= vfs_file_exist(conn
,directory
,NULL
);
4151 void *dirptr
= NULL
;
4155 if (check_name(directory
,conn
))
4156 dirptr
= OpenDir(conn
, directory
, True
);
4161 if (strequal(mask
,"????????.???"))
4164 while ((dname
= ReadDirName(dirptr
))) {
4166 pstrcpy(fname
,dname
);
4168 if(!mask_match(fname
, mask
, case_sensitive
))
4171 error
= ERRnoaccess
;
4172 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
4173 pstrcpy(destname
,newname
);
4174 if (resolve_wildcards(fname
,destname
) &&
4175 copy_file(fname
,destname
,conn
,ofun
,
4176 count
,target_is_directory
,&err
))
4178 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
4186 /* Error on close... */
4188 END_PROFILE(SMBcopy
);
4189 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4193 END_PROFILE(SMBcopy
);
4194 return ERROR_DOS(ERRDOS
,error
);
4196 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
)) {
4197 unix_ERR_class
= ERRDOS
;
4198 unix_ERR_code
= ERRbadpath
;
4200 END_PROFILE(SMBcopy
);
4201 return(UNIXERROR(ERRDOS
,error
));
4205 outsize
= set_message(outbuf
,1,0,True
);
4206 SSVAL(outbuf
,smb_vwv0
,count
);
4208 END_PROFILE(SMBcopy
);
4212 /****************************************************************************
4214 ****************************************************************************/
4216 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4224 START_PROFILE(pathworks_setdir
);
4227 if (!CAN_SETDIR(snum
)) {
4228 END_PROFILE(pathworks_setdir
);
4229 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4232 srvstr_get_path(inbuf
, newdir
, smb_buf(inbuf
) + 1, sizeof(newdir
), 0, STR_TERMINATE
, &status
);
4233 if (!NT_STATUS_IS_OK(status
)) {
4234 END_PROFILE(pathworks_setdir
);
4235 return ERROR_NT(status
);
4238 if (strlen(newdir
) == 0) {
4241 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
4243 string_set(&conn
->connectpath
,newdir
);
4247 END_PROFILE(pathworks_setdir
);
4248 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4251 outsize
= set_message(outbuf
,0,0,True
);
4252 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
4254 DEBUG(3,("setdir %s\n", newdir
));
4256 END_PROFILE(pathworks_setdir
);
4260 /****************************************************************************
4261 Get a lock pid, dealing with large count requests.
4262 ****************************************************************************/
4264 uint16
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
4266 if(!large_file_format
)
4267 return SVAL(data
,SMB_LPID_OFFSET(data_offset
));
4269 return SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
4272 /****************************************************************************
4273 Get a lock count, dealing with large count requests.
4274 ****************************************************************************/
4276 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
4278 SMB_BIG_UINT count
= 0;
4280 if(!large_file_format
) {
4281 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
4284 #if defined(HAVE_LONGLONG)
4285 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
4286 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
4287 #else /* HAVE_LONGLONG */
4290 * NT4.x seems to be broken in that it sends large file (64 bit)
4291 * lockingX calls even if the CAP_LARGE_FILES was *not*
4292 * negotiated. For boxes without large unsigned ints truncate the
4293 * lock count by dropping the top 32 bits.
4296 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
4297 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4298 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
4299 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
4300 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
4303 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
4304 #endif /* HAVE_LONGLONG */
4310 #if !defined(HAVE_LONGLONG)
4311 /****************************************************************************
4312 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4313 ****************************************************************************/
4315 static uint32
map_lock_offset(uint32 high
, uint32 low
)
4319 uint32 highcopy
= high
;
4322 * Try and find out how many significant bits there are in high.
4325 for(i
= 0; highcopy
; i
++)
4329 * We use 31 bits not 32 here as POSIX
4330 * lock offsets may not be negative.
4333 mask
= (~0) << (31 - i
);
4336 return 0; /* Fail. */
4342 #endif /* !defined(HAVE_LONGLONG) */
4344 /****************************************************************************
4345 Get a lock offset, dealing with large offset requests.
4346 ****************************************************************************/
4348 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
4350 SMB_BIG_UINT offset
= 0;
4354 if(!large_file_format
) {
4355 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
4358 #if defined(HAVE_LONGLONG)
4359 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
4360 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
4361 #else /* HAVE_LONGLONG */
4364 * NT4.x seems to be broken in that it sends large file (64 bit)
4365 * lockingX calls even if the CAP_LARGE_FILES was *not*
4366 * negotiated. For boxes without large unsigned ints mangle the
4367 * lock offset by mapping the top 32 bits onto the lower 32.
4370 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
4371 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4372 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
4375 if((new_low
= map_lock_offset(high
, low
)) == 0) {
4377 return (SMB_BIG_UINT
)-1;
4380 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4381 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
4382 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
4383 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
4386 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4387 #endif /* HAVE_LONGLONG */
4393 /****************************************************************************
4394 Reply to a lockingX request.
4395 ****************************************************************************/
4397 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4399 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
4400 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
4401 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
4402 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
4403 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
4404 SMB_BIG_UINT count
= 0, offset
= 0;
4406 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
4409 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
4411 BOOL my_lock_ctx
= False
;
4414 START_PROFILE(SMBlockingX
);
4416 CHECK_FSP(fsp
,conn
);
4418 data
= smb_buf(inbuf
);
4420 if (locktype
& (LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_CHANGE_LOCKTYPE
)) {
4421 /* we don't support these - and CANCEL_LOCK makes w2k
4422 and XP reboot so I don't really want to be
4423 compatible! (tridge) */
4424 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
4427 /* Check if this is an oplock break on a file
4428 we have granted an oplock on.
4430 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
4431 /* Client can insist on breaking to none. */
4432 BOOL break_to_none
= (oplocklevel
== 0);
4434 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4435 (unsigned int)oplocklevel
, fsp
->fnum
));
4438 * Make sure we have granted an exclusive or batch oplock on this file.
4441 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
4442 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4443 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
4445 /* if this is a pure oplock break request then don't send a reply */
4446 if (num_locks
== 0 && num_ulocks
== 0) {
4447 END_PROFILE(SMBlockingX
);
4450 END_PROFILE(SMBlockingX
);
4451 return ERROR_DOS(ERRDOS
,ERRlock
);
4455 if (remove_oplock(fsp
, break_to_none
) == False
) {
4456 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4460 /* if this is a pure oplock break request then don't send a reply */
4461 if (num_locks
== 0 && num_ulocks
== 0) {
4462 /* Sanity check - ensure a pure oplock break is not a
4464 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
4465 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4466 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
4467 END_PROFILE(SMBlockingX
);
4473 * We do this check *after* we have checked this is not a oplock break
4474 * response message. JRA.
4477 release_level_2_oplocks_on_change(fsp
);
4479 /* Data now points at the beginning of the list
4480 of smb_unlkrng structs */
4481 for(i
= 0; i
< (int)num_ulocks
; i
++) {
4482 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4483 count
= get_lock_count( data
, i
, large_file_format
);
4484 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4487 * There is no error code marked "stupid client bug".... :-).
4490 END_PROFILE(SMBlockingX
);
4491 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4494 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4495 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
4497 status
= do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4498 if (NT_STATUS_V(status
)) {
4499 END_PROFILE(SMBlockingX
);
4500 return ERROR_NT(status
);
4504 /* Setup the timeout in seconds. */
4506 lock_timeout
= ((lock_timeout
== -1) ? -1 : (lock_timeout
+999)/1000);
4508 /* Now do any requested locks */
4509 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
4511 /* Data now points at the beginning of the list
4512 of smb_lkrng structs */
4514 for(i
= 0; i
< (int)num_locks
; i
++) {
4515 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4516 count
= get_lock_count( data
, i
, large_file_format
);
4517 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4520 * There is no error code marked "stupid client bug".... :-).
4523 END_PROFILE(SMBlockingX
);
4524 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4527 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4528 (double)offset
, (double)count
, (unsigned int)lock_pid
,
4529 fsp
->fsp_name
, (int)lock_timeout
));
4531 status
= do_lock_spin(fsp
,conn
,lock_pid
, count
,offset
,
4532 ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
), &my_lock_ctx
);
4533 if (NT_STATUS_V(status
)) {
4535 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4536 * Even if it's our own lock context, we need to wait here as
4537 * there may be an unlock on the way.
4538 * So I removed a "&& !my_lock_ctx" from the following
4539 * if statement. JRA.
4541 if ((lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
4543 * A blocking lock was requested. Package up
4544 * this smb into a queued request and push it
4545 * onto the blocking lock queue.
4547 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
, lock_pid
, offset
, count
)) {
4548 END_PROFILE(SMBlockingX
);
4556 /* If any of the above locks failed, then we must unlock
4557 all of the previous locks (X/Open spec). */
4558 if (i
!= num_locks
&& num_locks
!= 0) {
4560 * Ensure we don't do a remove on the lock that just failed,
4561 * as under POSIX rules, if we have a lock already there, we
4562 * will delete it (and we shouldn't) .....
4564 for(i
--; i
>= 0; i
--) {
4565 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4566 count
= get_lock_count( data
, i
, large_file_format
);
4567 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4570 * There is no error code marked "stupid client bug".... :-).
4573 END_PROFILE(SMBlockingX
);
4574 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4577 do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4579 END_PROFILE(SMBlockingX
);
4580 return ERROR_NT(status
);
4583 set_message(outbuf
,2,0,True
);
4585 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4586 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4588 END_PROFILE(SMBlockingX
);
4589 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4592 /****************************************************************************
4593 Reply to a SMBreadbmpx (read block multiplex) request.
4594 ****************************************************************************/
4596 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4607 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4608 START_PROFILE(SMBreadBmpx
);
4610 /* this function doesn't seem to work - disable by default */
4611 if (!lp_readbmpx()) {
4612 END_PROFILE(SMBreadBmpx
);
4613 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
4616 outsize
= set_message(outbuf
,8,0,True
);
4618 CHECK_FSP(fsp
,conn
);
4621 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
4622 maxcount
= SVAL(inbuf
,smb_vwv3
);
4624 data
= smb_buf(outbuf
);
4625 pad
= ((long)data
)%4;
4630 max_per_packet
= bufsize
-(outsize
+pad
);
4634 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
4635 END_PROFILE(SMBreadBmpx
);
4636 return ERROR_DOS(ERRDOS
,ERRlock
);
4640 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4642 nread
= read_file(fsp
,data
,startpos
,N
);
4647 if (nread
< (ssize_t
)N
)
4648 tcount
= total_read
+ nread
;
4650 set_message(outbuf
,8,nread
,False
);
4651 SIVAL(outbuf
,smb_vwv0
,startpos
);
4652 SSVAL(outbuf
,smb_vwv2
,tcount
);
4653 SSVAL(outbuf
,smb_vwv6
,nread
);
4654 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4656 if (!send_smb(smbd_server_fd(),outbuf
))
4657 exit_server("reply_readbmpx: send_smb failed.");
4659 total_read
+= nread
;
4661 } while (total_read
< (ssize_t
)tcount
);
4663 END_PROFILE(SMBreadBmpx
);
4667 /****************************************************************************
4668 Reply to a SMBsetattrE.
4669 ****************************************************************************/
4671 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4673 struct utimbuf unix_times
;
4675 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4676 START_PROFILE(SMBsetattrE
);
4678 outsize
= set_message(outbuf
,0,0,True
);
4680 if(!fsp
|| (fsp
->conn
!= conn
)) {
4681 END_PROFILE(SMBgetattrE
);
4682 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4686 * Convert the DOS times into unix times. Ignore create
4687 * time as UNIX can't set this.
4690 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4691 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4694 * Patch from Ray Frush <frush@engr.colostate.edu>
4695 * Sometimes times are sent as zero - ignore them.
4698 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0)) {
4699 /* Ignore request */
4700 if( DEBUGLVL( 3 ) ) {
4701 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4702 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4704 END_PROFILE(SMBsetattrE
);
4706 } else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0)) {
4707 /* set modify time = to access time if modify time was 0 */
4708 unix_times
.modtime
= unix_times
.actime
;
4711 /* Set the date on this file */
4712 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4713 END_PROFILE(SMBsetattrE
);
4714 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4717 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4718 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4720 END_PROFILE(SMBsetattrE
);
4725 /* Back from the dead for OS/2..... JRA. */
4727 /****************************************************************************
4728 Reply to a SMBwritebmpx (write block multiplex primary) request.
4729 ****************************************************************************/
4731 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4734 ssize_t nwritten
= -1;
4741 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4742 START_PROFILE(SMBwriteBmpx
);
4744 CHECK_FSP(fsp
,conn
);
4748 tcount
= SVAL(inbuf
,smb_vwv1
);
4749 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
4750 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
4751 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4752 smb_doff
= SVAL(inbuf
,smb_vwv11
);
4754 data
= smb_base(inbuf
) + smb_doff
;
4756 /* If this fails we need to send an SMBwriteC response,
4757 not an SMBwritebmpx - set this up now so we don't forget */
4758 SCVAL(outbuf
,smb_com
,SMBwritec
);
4760 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
,False
)) {
4761 END_PROFILE(SMBwriteBmpx
);
4762 return(ERROR_DOS(ERRDOS
,ERRlock
));
4765 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4767 if(lp_syncalways(SNUM(conn
)) || write_through
)
4768 sync_file(conn
,fsp
);
4770 if(nwritten
< (ssize_t
)numtowrite
) {
4771 END_PROFILE(SMBwriteBmpx
);
4772 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
4775 /* If the maximum to be written to this file
4776 is greater than what we just wrote then set
4777 up a secondary struct to be attached to this
4778 fd, we will use this to cache error messages etc. */
4780 if((ssize_t
)tcount
> nwritten
) {
4781 write_bmpx_struct
*wbms
;
4782 if(fsp
->wbmpx_ptr
!= NULL
)
4783 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
4785 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
4787 DEBUG(0,("Out of memory in reply_readmpx\n"));
4788 END_PROFILE(SMBwriteBmpx
);
4789 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
4791 wbms
->wr_mode
= write_through
;
4792 wbms
->wr_discard
= False
; /* No errors yet */
4793 wbms
->wr_total_written
= nwritten
;
4794 wbms
->wr_errclass
= 0;
4796 fsp
->wbmpx_ptr
= wbms
;
4799 /* We are returning successfully, set the message type back to
4801 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
4803 outsize
= set_message(outbuf
,1,0,True
);
4805 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
4807 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4808 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
4810 if (write_through
&& tcount
==nwritten
) {
4811 /* We need to send both a primary and a secondary response */
4812 smb_setlen(outbuf
,outsize
- 4);
4813 if (!send_smb(smbd_server_fd(),outbuf
))
4814 exit_server("reply_writebmpx: send_smb failed.");
4816 /* Now the secondary */
4817 outsize
= set_message(outbuf
,1,0,True
);
4818 SCVAL(outbuf
,smb_com
,SMBwritec
);
4819 SSVAL(outbuf
,smb_vwv0
,nwritten
);
4822 END_PROFILE(SMBwriteBmpx
);
4826 /****************************************************************************
4827 Reply to a SMBwritebs (write block multiplex secondary) request.
4828 ****************************************************************************/
4830 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4833 ssize_t nwritten
= -1;
4840 write_bmpx_struct
*wbms
;
4841 BOOL send_response
= False
;
4842 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4843 START_PROFILE(SMBwriteBs
);
4845 CHECK_FSP(fsp
,conn
);
4848 tcount
= SVAL(inbuf
,smb_vwv1
);
4849 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
4850 numtowrite
= SVAL(inbuf
,smb_vwv6
);
4851 smb_doff
= SVAL(inbuf
,smb_vwv7
);
4853 data
= smb_base(inbuf
) + smb_doff
;
4855 /* We need to send an SMBwriteC response, not an SMBwritebs */
4856 SCVAL(outbuf
,smb_com
,SMBwritec
);
4858 /* This fd should have an auxiliary struct attached,
4859 check that it does */
4860 wbms
= fsp
->wbmpx_ptr
;
4862 END_PROFILE(SMBwriteBs
);
4866 /* If write through is set we can return errors, else we must cache them */
4867 write_through
= wbms
->wr_mode
;
4869 /* Check for an earlier error */
4870 if(wbms
->wr_discard
) {
4871 END_PROFILE(SMBwriteBs
);
4872 return -1; /* Just discard the packet */
4875 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4877 if(lp_syncalways(SNUM(conn
)) || write_through
)
4878 sync_file(conn
,fsp
);
4880 if (nwritten
< (ssize_t
)numtowrite
) {
4882 /* We are returning an error - we can delete the aux struct */
4885 fsp
->wbmpx_ptr
= NULL
;
4886 END_PROFILE(SMBwriteBs
);
4887 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
4889 END_PROFILE(SMBwriteBs
);
4890 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4893 /* Increment the total written, if this matches tcount
4894 we can discard the auxiliary struct (hurrah !) and return a writeC */
4895 wbms
->wr_total_written
+= nwritten
;
4896 if(wbms
->wr_total_written
>= tcount
) {
4897 if (write_through
) {
4898 outsize
= set_message(outbuf
,1,0,True
);
4899 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4900 send_response
= True
;
4904 fsp
->wbmpx_ptr
= NULL
;
4908 END_PROFILE(SMBwriteBs
);
4912 END_PROFILE(SMBwriteBs
);
4916 /****************************************************************************
4917 Reply to a SMBgetattrE.
4918 ****************************************************************************/
4920 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4922 SMB_STRUCT_STAT sbuf
;
4925 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4926 START_PROFILE(SMBgetattrE
);
4928 outsize
= set_message(outbuf
,11,0,True
);
4930 if(!fsp
|| (fsp
->conn
!= conn
)) {
4931 END_PROFILE(SMBgetattrE
);
4932 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4935 /* Do an fstat on this file */
4936 if(fsp_stat(fsp
, &sbuf
)) {
4937 END_PROFILE(SMBgetattrE
);
4938 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4941 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4944 * Convert the times into dos times. Set create
4945 * date to be last modify date as UNIX doesn't save
4949 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4950 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4951 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4954 SIVAL(outbuf
,smb_vwv6
,0);
4955 SIVAL(outbuf
,smb_vwv8
,0);
4957 uint32 allocation_size
= get_allocation_size(fsp
, &sbuf
);
4958 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4959 SIVAL(outbuf
,smb_vwv8
,allocation_size
);
4961 SSVAL(outbuf
,smb_vwv10
, mode
);
4963 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
4965 END_PROFILE(SMBgetattrE
);