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 ((d
!= destname
) && (*s
!= '\0')) {
65 /* We only care about non-leading or trailing '/' or '\\' */
68 } else if ((s
[0] == '.') && (s
[1] == '.') && (IS_DIRECTORY_SEP(s
[2]) || s
[2] == '\0')) {
69 /* Uh oh - "../" or "..\\" or "..\0" ! */
72 * No mb char starts with '.' so we're safe checking the directory separator here.
75 /* If we just added a '/', delete it. */
77 if ((d
> destname
) && (*(d
-1) == '/')) {
79 if (d
== (destname
+ 1)) {
85 /* Are we at the start ? Can't go back further if so. */
87 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
89 /* Go back one level... */
90 /* We know this is safe as '/' cannot be part of a mb sequence. */
91 /* NOTE - if this assumption is invalid we are not in good shape... */
92 while (d
> destname
) {
98 } else if ((s
[0] == '.') && IS_DIRECTORY_SEP(s
[1])) {
101 * No mb char starts with '.' so we're safe checking the directory separator here.
104 /* "./" or ".\\" fails with a different error depending on where it is... */
107 ret
= NT_STATUS_OBJECT_NAME_INVALID
;
110 return NT_STATUS_INVALID_PARAMETER
;
112 ret
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
119 switch(next_mb_char_size(s
)) {
130 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
131 return NT_STATUS_INVALID_PARAMETER
;
140 /****************************************************************************
141 Pull a string and check the path - provide for error return.
142 ****************************************************************************/
144 size_t srvstr_get_path(char *inbuf
, char *dest
, const char *src
, size_t dest_len
, size_t src_len
, int flags
, NTSTATUS
*err
)
147 char *tmppath_ptr
= tmppath
;
150 SMB_ASSERT(dest_len
== sizeof(pstring
));
154 ret
= srvstr_pull_buf( inbuf
, tmppath_ptr
, src
, dest_len
, flags
);
156 ret
= srvstr_pull( inbuf
, tmppath_ptr
, src
, dest_len
, src_len
, flags
);
158 *err
= check_path_syntax(dest
, tmppath
);
162 /****************************************************************************
163 Reply to a special message.
164 ****************************************************************************/
166 int reply_special(char *inbuf
,char *outbuf
)
169 int msg_type
= CVAL(inbuf
,0);
170 int msg_flags
= CVAL(inbuf
,1);
174 static BOOL already_got_session
= False
;
178 memset(outbuf
,'\0',smb_size
);
180 smb_setlen(outbuf
,0);
183 case 0x81: /* session request */
185 if (already_got_session
) {
186 exit_server("multiple session request not permitted");
189 SCVAL(outbuf
,0,0x82);
191 if (name_len(inbuf
+4) > 50 ||
192 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
193 DEBUG(0,("Invalid name length in session request\n"));
196 name_extract(inbuf
,4,name1
);
197 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
198 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
201 set_local_machine_name(name1
, True
);
202 set_remote_machine_name(name2
, True
);
204 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
205 get_local_machine_name(), get_remote_machine_name(),
208 if (name_type
== 'R') {
209 /* We are being asked for a pathworks session ---
211 SCVAL(outbuf
, 0,0x83);
215 /* only add the client's machine name to the list
216 of possibly valid usernames if we are operating
217 in share mode security */
218 if (lp_security() == SEC_SHARE
) {
219 add_session_user(get_remote_machine_name());
222 reload_services(True
);
225 claim_connection(NULL
,"",0,True
,FLAG_MSG_GENERAL
|FLAG_MSG_SMBD
);
227 already_got_session
= True
;
230 case 0x89: /* session keepalive request
231 (some old clients produce this?) */
232 SCVAL(outbuf
,0,SMBkeepalive
);
236 case 0x82: /* positive session response */
237 case 0x83: /* negative session response */
238 case 0x84: /* retarget session response */
239 DEBUG(0,("Unexpected session response\n"));
242 case SMBkeepalive
: /* session keepalive */
247 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
248 msg_type
, msg_flags
));
253 /****************************************************************************
255 ****************************************************************************/
257 int reply_tcon(connection_struct
*conn
,
258 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
265 uint16 vuid
= SVAL(inbuf
,smb_uid
);
269 DATA_BLOB password_blob
;
271 START_PROFILE(SMBtcon
);
273 *service_buf
= *password
= *dev
= 0;
275 p
= smb_buf(inbuf
)+1;
276 p
+= srvstr_pull_buf(inbuf
, service_buf
, p
, sizeof(service_buf
), STR_TERMINATE
) + 1;
277 pwlen
= srvstr_pull_buf(inbuf
, password
, p
, sizeof(password
), STR_TERMINATE
) + 1;
279 p
+= srvstr_pull_buf(inbuf
, dev
, p
, sizeof(dev
), STR_TERMINATE
) + 1;
281 p
= strrchr_m(service_buf
,'\\');
285 service
= service_buf
;
288 password_blob
= data_blob(password
, pwlen
+1);
290 conn
= make_connection(service
,password_blob
,dev
,vuid
,&nt_status
);
292 data_blob_clear_free(&password_blob
);
295 END_PROFILE(SMBtcon
);
296 return ERROR_NT(nt_status
);
299 outsize
= set_message(outbuf
,2,0,True
);
300 SSVAL(outbuf
,smb_vwv0
,max_recv
);
301 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
302 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
304 DEBUG(3,("tcon service=%s cnum=%d\n",
305 service
, conn
->cnum
));
307 END_PROFILE(SMBtcon
);
311 /****************************************************************************
312 Reply to a tcon and X.
313 ****************************************************************************/
315 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
320 /* what the cleint thinks the device is */
321 fstring client_devicetype
;
322 /* what the server tells the client the share represents */
323 const char *server_devicetype
;
325 uint16 vuid
= SVAL(inbuf
,smb_uid
);
326 int passlen
= SVAL(inbuf
,smb_vwv3
);
329 extern BOOL global_encrypted_passwords_negotiated
;
331 START_PROFILE(SMBtconX
);
333 *service
= *client_devicetype
= 0;
335 /* we might have to close an old one */
336 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
337 close_cnum(conn
,vuid
);
340 if (passlen
> MAX_PASS_LEN
) {
341 return ERROR_DOS(ERRDOS
,ERRbuftoosmall
);
344 if (global_encrypted_passwords_negotiated
) {
345 password
= data_blob(smb_buf(inbuf
),passlen
);
347 password
= data_blob(smb_buf(inbuf
),passlen
+1);
348 /* Ensure correct termination */
349 password
.data
[passlen
]=0;
352 p
= smb_buf(inbuf
) + passlen
;
353 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
356 * the service name can be either: \\server\share
357 * or share directly like on the DELL PowerVault 705
360 q
= strchr_m(path
+2,'\\');
362 END_PROFILE(SMBtconX
);
363 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
365 fstrcpy(service
,q
+1);
368 fstrcpy(service
,path
);
370 p
+= srvstr_pull(inbuf
, client_devicetype
, p
, sizeof(client_devicetype
), 6, STR_ASCII
);
372 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
374 conn
= make_connection(service
,password
,client_devicetype
,vuid
,&nt_status
);
376 data_blob_clear_free(&password
);
379 END_PROFILE(SMBtconX
);
380 return ERROR_NT(nt_status
);
384 server_devicetype
= "IPC";
385 else if ( IS_PRINT(conn
) )
386 server_devicetype
= "LPT1:";
388 server_devicetype
= "A:";
390 if (Protocol
< PROTOCOL_NT1
) {
391 set_message(outbuf
,2,0,True
);
393 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
394 STR_TERMINATE
|STR_ASCII
);
395 set_message_end(outbuf
,p
);
397 /* NT sets the fstype of IPC$ to the null string */
398 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
400 set_message(outbuf
,3,0,True
);
403 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
404 STR_TERMINATE
|STR_ASCII
);
405 p
+= srvstr_push(outbuf
, p
, fstype
, -1,
408 set_message_end(outbuf
,p
);
410 /* what does setting this bit do? It is set by NT4 and
411 may affect the ability to autorun mounted cdroms */
412 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
413 (lp_csc_policy(SNUM(conn
)) << 2));
415 init_dfsroot(conn
, inbuf
, outbuf
);
419 DEBUG(3,("tconX service=%s \n",
422 /* set the incoming and outgoing tid to the just created one */
423 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
424 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
426 END_PROFILE(SMBtconX
);
427 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
430 /****************************************************************************
431 Reply to an unknown type.
432 ****************************************************************************/
434 int reply_unknown(char *inbuf
,char *outbuf
)
437 type
= CVAL(inbuf
,smb_com
);
439 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
440 smb_fn_name(type
), type
, type
));
442 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
445 /****************************************************************************
447 ****************************************************************************/
449 int reply_ioctl(connection_struct
*conn
,
450 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
452 uint16 device
= SVAL(inbuf
,smb_vwv1
);
453 uint16 function
= SVAL(inbuf
,smb_vwv2
);
454 uint32 ioctl_code
= (device
<< 16) + function
;
455 int replysize
, outsize
;
457 START_PROFILE(SMBioctl
);
459 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
461 switch (ioctl_code
) {
462 case IOCTL_QUERY_JOB_INFO
:
466 END_PROFILE(SMBioctl
);
467 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
470 outsize
= set_message(outbuf
,8,replysize
+1,True
);
471 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
472 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
473 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
474 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
476 switch (ioctl_code
) {
477 case IOCTL_QUERY_JOB_INFO
:
479 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
481 END_PROFILE(SMBioctl
);
482 return(UNIXERROR(ERRDOS
,ERRbadfid
));
484 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
485 srvstr_push(outbuf
, p
+2, global_myname(), 15, STR_TERMINATE
|STR_ASCII
);
486 srvstr_push(outbuf
, p
+18, lp_servicename(SNUM(conn
)), 13, STR_TERMINATE
|STR_ASCII
);
491 END_PROFILE(SMBioctl
);
495 /****************************************************************************
497 ****************************************************************************/
499 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
505 BOOL bad_path
= False
;
506 SMB_STRUCT_STAT sbuf
;
509 START_PROFILE(SMBchkpth
);
511 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
);
512 if (!NT_STATUS_IS_OK(status
)) {
513 END_PROFILE(SMBchkpth
);
514 return ERROR_NT(status
);
517 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
519 unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
521 mode
= SVAL(inbuf
,smb_vwv0
);
523 if (check_name(name
,conn
)) {
524 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,name
,&sbuf
) == 0)
525 if (!(ok
= S_ISDIR(sbuf
.st_mode
))) {
526 END_PROFILE(SMBchkpth
);
527 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY
,ERRDOS
,ERRbadpath
);
532 /* We special case this - as when a Windows machine
533 is parsing a path is steps through the components
534 one at a time - if a component fails it expects
535 ERRbadpath, not ERRbadfile.
537 if(errno
== ENOENT
) {
539 * Windows returns different error codes if
540 * the parent directory is valid but not the
541 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
542 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
543 * if the path is invalid.
546 END_PROFILE(SMBchkpth
);
547 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
549 END_PROFILE(SMBchkpth
);
550 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND
);
552 } else if (errno
== ENOTDIR
) {
553 END_PROFILE(SMBchkpth
);
554 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY
);
557 END_PROFILE(SMBchkpth
);
558 return(UNIXERROR(ERRDOS
,ERRbadpath
));
561 outsize
= set_message(outbuf
,0,0,True
);
563 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
565 END_PROFILE(SMBchkpth
);
569 /****************************************************************************
571 ****************************************************************************/
573 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
577 SMB_STRUCT_STAT sbuf
;
582 BOOL bad_path
= False
;
586 START_PROFILE(SMBgetatr
);
588 p
= smb_buf(inbuf
) + 1;
589 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
590 if (!NT_STATUS_IS_OK(status
)) {
591 END_PROFILE(SMBgetatr
);
592 return ERROR_NT(status
);
595 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
597 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
598 under WfWg - weird! */
600 mode
= aHIDDEN
| aDIR
;
601 if (!CAN_WRITE(conn
))
607 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
608 if (check_name(fname
,conn
)) {
609 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,fname
,&sbuf
) == 0) {
610 mode
= dos_mode(conn
,fname
,&sbuf
);
612 mtime
= sbuf
.st_mtime
;
617 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
623 END_PROFILE(SMBgetatr
);
624 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadfile
);
627 outsize
= set_message(outbuf
,10,0,True
);
629 SSVAL(outbuf
,smb_vwv0
,mode
);
630 if(lp_dos_filetime_resolution(SNUM(conn
)) )
631 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
633 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
634 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
636 if (Protocol
>= PROTOCOL_NT1
)
637 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
639 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
641 END_PROFILE(SMBgetatr
);
645 /****************************************************************************
647 ****************************************************************************/
649 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
656 SMB_STRUCT_STAT sbuf
;
657 BOOL bad_path
= False
;
661 START_PROFILE(SMBsetatr
);
663 p
= smb_buf(inbuf
) + 1;
664 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
665 if (!NT_STATUS_IS_OK(status
)) {
666 END_PROFILE(SMBsetatr
);
667 return ERROR_NT(status
);
670 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
672 mode
= SVAL(inbuf
,smb_vwv0
);
673 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
675 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
676 if (VALID_STAT_OF_DIR(sbuf
))
681 if (check_name(fname
,conn
))
682 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
688 ok
= set_filetime(conn
,fname
,mtime
);
691 END_PROFILE(SMBsetatr
);
692 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
695 outsize
= set_message(outbuf
,0,0,True
);
697 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
699 END_PROFILE(SMBsetatr
);
703 /****************************************************************************
705 ****************************************************************************/
707 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
710 SMB_BIG_UINT dfree
,dsize
,bsize
;
711 START_PROFILE(SMBdskattr
);
713 SMB_VFS_DISK_FREE(conn
,".",True
,&bsize
,&dfree
,&dsize
);
715 outsize
= set_message(outbuf
,5,0,True
);
717 if (Protocol
<= PROTOCOL_LANMAN2
) {
718 double total_space
, free_space
;
719 /* we need to scale this to a number that DOS6 can handle. We
720 use floating point so we can handle large drives on systems
721 that don't have 64 bit integers
723 we end up displaying a maximum of 2G to DOS systems
725 total_space
= dsize
* (double)bsize
;
726 free_space
= dfree
* (double)bsize
;
728 dsize
= (total_space
+63*512) / (64*512);
729 dfree
= (free_space
+63*512) / (64*512);
731 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
732 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
734 SSVAL(outbuf
,smb_vwv0
,dsize
);
735 SSVAL(outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
736 SSVAL(outbuf
,smb_vwv2
,512); /* and this must be 512 */
737 SSVAL(outbuf
,smb_vwv3
,dfree
);
739 SSVAL(outbuf
,smb_vwv0
,dsize
);
740 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
741 SSVAL(outbuf
,smb_vwv2
,512);
742 SSVAL(outbuf
,smb_vwv3
,dfree
);
745 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
747 END_PROFILE(SMBdskattr
);
751 /****************************************************************************
753 Can be called from SMBsearch, SMBffirst or SMBfunique.
754 ****************************************************************************/
756 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
766 unsigned int numentries
= 0;
767 unsigned int maxentries
= 0;
768 BOOL finished
= False
;
775 BOOL check_descend
= False
;
776 BOOL expect_close
= False
;
777 BOOL can_open
= True
;
778 BOOL bad_path
= False
;
780 START_PROFILE(SMBsearch
);
782 *mask
= *directory
= *fname
= 0;
784 /* If we were called as SMBffirst then we must expect close. */
785 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
788 outsize
= set_message(outbuf
,1,3,True
);
789 maxentries
= SVAL(inbuf
,smb_vwv0
);
790 dirtype
= SVAL(inbuf
,smb_vwv1
);
791 p
= smb_buf(inbuf
) + 1;
792 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &nt_status
);
793 if (!NT_STATUS_IS_OK(nt_status
)) {
794 END_PROFILE(SMBsearch
);
795 return ERROR_NT(nt_status
);
798 status_len
= SVAL(p
, 0);
801 /* dirtype &= ~aDIR; */
803 if (status_len
== 0) {
804 SMB_STRUCT_STAT sbuf
;
807 pstrcpy(directory
,path
);
809 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
812 if (!check_name(directory
,conn
))
815 p
= strrchr_m(dir2
,'/');
824 p
= strrchr_m(directory
,'/');
830 if (strlen(directory
) == 0)
831 pstrcpy(directory
,".");
832 memset((char *)status
,'\0',21);
833 SCVAL(status
,0,(dirtype
& 0x1F));
838 status_dirtype
= CVAL(status
,0) & 0x1F;
839 if (status_dirtype
!= (dirtype
& 0x1F))
840 dirtype
= status_dirtype
;
842 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
845 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
846 pstrcpy(mask
, dptr_wcard(dptr_num
));
850 p
= smb_buf(outbuf
) + 3;
853 if (status_len
== 0) {
854 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
857 END_PROFILE(SMBsearch
);
858 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnofids
);
860 END_PROFILE(SMBsearch
);
861 return ERROR_DOS(ERRDOS
,ERRnofids
);
863 dptr_set_wcard(dptr_num
, strdup(mask
));
864 dptr_set_attr(dptr_num
, dirtype
);
866 dirtype
= dptr_attr(dptr_num
);
869 DEBUG(4,("dptr_num is %d\n",dptr_num
));
872 if ((dirtype
&0x1F) == aVOLID
) {
874 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
875 dptr_fill(p
+12,dptr_num
);
876 if (dptr_zero(p
+12) && (status_len
==0))
880 p
+= DIR_STRUCT_SIZE
;
883 maxentries
= MIN(maxentries
, ((BUFFER_SIZE
- (p
- outbuf
))/DIR_STRUCT_SIZE
));
885 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
886 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
887 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
888 check_descend
= True
;
890 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
891 finished
= !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
894 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
895 dptr_fill(p
+12,dptr_num
);
898 p
+= DIR_STRUCT_SIZE
;
907 /* If we were called as SMBffirst with smb_search_id == NULL
908 and no entries were found then return error and close dirptr
911 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0) {
912 if (Protocol
< PROTOCOL_NT1
) {
913 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
914 SSVAL(outbuf
,smb_err
,ERRnofiles
);
916 /* Also close the dptr - we know it's gone */
917 dptr_close(&dptr_num
);
918 } else if (numentries
== 0 || !ok
) {
919 if (Protocol
< PROTOCOL_NT1
) {
920 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
921 SSVAL(outbuf
,smb_err
,ERRnofiles
);
923 dptr_close(&dptr_num
);
926 /* If we were called as SMBfunique, then we can close the dirptr now ! */
927 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
928 dptr_close(&dptr_num
);
930 SSVAL(outbuf
,smb_vwv0
,numentries
);
931 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
932 SCVAL(smb_buf(outbuf
),0,5);
933 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
935 if (Protocol
>= PROTOCOL_NT1
)
936 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
938 outsize
+= DIR_STRUCT_SIZE
*numentries
;
939 smb_setlen(outbuf
,outsize
- 4);
941 if ((! *directory
) && dptr_path(dptr_num
))
942 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
944 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
945 smb_fn_name(CVAL(inbuf
,smb_com
)),
946 mask
, directory
, dirtype
, numentries
, maxentries
) );
948 END_PROFILE(SMBsearch
);
952 /****************************************************************************
953 Reply to a fclose (stop directory search).
954 ****************************************************************************/
956 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
966 START_PROFILE(SMBfclose
);
968 outsize
= set_message(outbuf
,1,0,True
);
969 p
= smb_buf(inbuf
) + 1;
970 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &err
);
971 if (!NT_STATUS_IS_OK(err
)) {
972 END_PROFILE(SMBfclose
);
973 return ERROR_NT(err
);
976 status_len
= SVAL(p
,0);
979 if (status_len
== 0) {
980 END_PROFILE(SMBfclose
);
981 return ERROR_DOS(ERRSRV
,ERRsrverror
);
986 if(dptr_fetch(status
+12,&dptr_num
)) {
987 /* Close the dptr - we know it's gone */
988 dptr_close(&dptr_num
);
991 SSVAL(outbuf
,smb_vwv0
,0);
993 DEBUG(3,("search close\n"));
995 END_PROFILE(SMBfclose
);
999 /****************************************************************************
1001 ****************************************************************************/
1003 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1013 SMB_STRUCT_STAT sbuf
;
1014 BOOL bad_path
= False
;
1016 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1018 START_PROFILE(SMBopen
);
1020 share_mode
= SVAL(inbuf
,smb_vwv0
);
1022 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1023 if (!NT_STATUS_IS_OK(status
)) {
1024 END_PROFILE(SMBopen
);
1025 return ERROR_NT(status
);
1028 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1030 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1032 unixmode
= unix_mode(conn
,aARCH
,fname
);
1034 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1035 unixmode
, oplock_request
,&rmode
,NULL
);
1038 END_PROFILE(SMBopen
);
1039 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1042 size
= sbuf
.st_size
;
1043 fmode
= dos_mode(conn
,fname
,&sbuf
);
1044 mtime
= sbuf
.st_mtime
;
1047 DEBUG(3,("attempt to open a directory %s\n",fname
));
1048 close_file(fsp
,False
);
1049 END_PROFILE(SMBopen
);
1050 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1053 outsize
= set_message(outbuf
,7,0,True
);
1054 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1055 SSVAL(outbuf
,smb_vwv1
,fmode
);
1056 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1057 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1059 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1060 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1061 SSVAL(outbuf
,smb_vwv6
,rmode
);
1063 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1064 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1066 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1067 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1068 END_PROFILE(SMBopen
);
1072 /****************************************************************************
1073 Reply to an open and X.
1074 ****************************************************************************/
1076 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1079 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1080 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1081 /* Breakout the oplock request bits so we can set the
1082 reply bits separately. */
1083 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1084 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1085 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1087 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1088 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1089 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1091 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1094 int fmode
=0,mtime
=0,rmode
=0;
1095 SMB_STRUCT_STAT sbuf
;
1097 BOOL bad_path
= False
;
1100 START_PROFILE(SMBopenX
);
1102 /* If it's an IPC, pass off the pipe handler. */
1104 if (lp_nt_pipe_support()) {
1105 END_PROFILE(SMBopenX
);
1106 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1108 END_PROFILE(SMBopenX
);
1109 return ERROR_DOS(ERRSRV
,ERRaccess
);
1113 /* XXXX we need to handle passed times, sattr and flags */
1114 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
), sizeof(fname
), 0, STR_TERMINATE
, &status
);
1115 if (!NT_STATUS_IS_OK(status
)) {
1116 END_PROFILE(SMBopenX
);
1117 return ERROR_NT(status
);
1120 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1122 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1124 unixmode
= unix_mode(conn
,smb_attr
| aARCH
, fname
);
1126 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,unixmode
,
1127 oplock_request
, &rmode
,&smb_action
);
1130 END_PROFILE(SMBopenX
);
1131 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1134 size
= sbuf
.st_size
;
1135 fmode
= dos_mode(conn
,fname
,&sbuf
);
1136 mtime
= sbuf
.st_mtime
;
1138 close_file(fsp
,False
);
1139 END_PROFILE(SMBopenX
);
1140 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1143 /* If the caller set the extended oplock request bit
1144 and we granted one (by whatever means) - set the
1145 correct bit for extended oplock reply.
1148 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1149 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1151 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1152 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1154 /* If the caller set the core oplock request bit
1155 and we granted one (by whatever means) - set the
1156 correct bit for core oplock reply.
1159 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1160 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1162 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1163 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1165 set_message(outbuf
,15,0,True
);
1166 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1167 SSVAL(outbuf
,smb_vwv3
,fmode
);
1168 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1169 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1171 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1172 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1173 SSVAL(outbuf
,smb_vwv8
,rmode
);
1174 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1176 END_PROFILE(SMBopenX
);
1177 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1180 /****************************************************************************
1181 Reply to a SMBulogoffX.
1182 ****************************************************************************/
1184 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1186 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1187 user_struct
*vuser
= get_valid_user_struct(vuid
);
1188 START_PROFILE(SMBulogoffX
);
1191 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1193 /* in user level security we are supposed to close any files
1194 open by this user */
1195 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
))
1196 file_close_user(vuid
);
1198 invalidate_vuid(vuid
);
1200 set_message(outbuf
,2,0,True
);
1202 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1204 END_PROFILE(SMBulogoffX
);
1205 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1208 /****************************************************************************
1209 Reply to a mknew or a create.
1210 ****************************************************************************/
1212 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1220 BOOL bad_path
= False
;
1222 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1223 SMB_STRUCT_STAT sbuf
;
1225 START_PROFILE(SMBcreate
);
1227 com
= SVAL(inbuf
,smb_com
);
1229 createmode
= SVAL(inbuf
,smb_vwv0
);
1230 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
) + 1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1231 if (!NT_STATUS_IS_OK(status
)) {
1232 END_PROFILE(SMBcreate
);
1233 return ERROR_NT(status
);
1236 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1238 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1240 if (createmode
& aVOLID
)
1241 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1243 unixmode
= unix_mode(conn
,createmode
,fname
);
1245 if(com
== SMBmknew
) {
1246 /* We should fail if file exists. */
1247 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1249 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1250 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1253 /* Open file in dos compatibility share mode. */
1254 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1255 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1258 END_PROFILE(SMBcreate
);
1259 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1262 outsize
= set_message(outbuf
,1,0,True
);
1263 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1265 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1266 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1268 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1269 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1271 DEBUG( 2, ( "new file %s\n", fname
) );
1272 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1274 END_PROFILE(SMBcreate
);
1278 /****************************************************************************
1279 Reply to a create temporary file.
1280 ****************************************************************************/
1282 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1288 BOOL bad_path
= False
;
1290 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1292 SMB_STRUCT_STAT sbuf
;
1296 START_PROFILE(SMBctemp
);
1298 createmode
= SVAL(inbuf
,smb_vwv0
);
1299 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1300 if (!NT_STATUS_IS_OK(status
)) {
1301 END_PROFILE(SMBctemp
);
1302 return ERROR_NT(status
);
1304 pstrcat(fname
,"\\TMXXXXXX");
1306 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1308 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1310 unixmode
= unix_mode(conn
,createmode
,fname
);
1312 tmpfd
= smb_mkstemp(fname
);
1314 END_PROFILE(SMBctemp
);
1315 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1318 SMB_VFS_STAT(conn
,fname
,&sbuf
);
1320 /* Open file in dos compatibility share mode. */
1321 /* We should fail if file does not exist. */
1322 fsp
= open_file_shared(conn
,fname
,&sbuf
,
1323 SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1324 FILE_EXISTS_OPEN
|FILE_FAIL_IF_NOT_EXIST
,
1325 unixmode
, oplock_request
, NULL
, NULL
);
1327 /* close fd from smb_mkstemp() */
1331 END_PROFILE(SMBctemp
);
1332 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1335 outsize
= set_message(outbuf
,1,0,True
);
1336 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1338 /* the returned filename is relative to the directory */
1339 s
= strrchr_m(fname
, '/');
1345 p
= smb_buf(outbuf
);
1346 SSVALS(p
, 0, -1); /* what is this? not in spec */
1347 SSVAL(p
, 2, strlen(s
));
1349 p
+= srvstr_push(outbuf
, p
, s
, -1, STR_ASCII
);
1350 outsize
= set_message_end(outbuf
, p
);
1352 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1353 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1355 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1356 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1358 DEBUG( 2, ( "created temp file %s\n", fname
) );
1359 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1360 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1362 END_PROFILE(SMBctemp
);
1366 /*******************************************************************
1367 Check if a user is allowed to rename a file.
1368 ********************************************************************/
1370 static NTSTATUS
can_rename(char *fname
,connection_struct
*conn
, SMB_STRUCT_STAT
*pst
)
1376 if (!CAN_WRITE(conn
))
1377 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1379 if (S_ISDIR(pst
->st_mode
))
1380 return NT_STATUS_OK
;
1382 /* We need a better way to return NT status codes from open... */
1386 fsp
= open_file_shared1(conn
, fname
, pst
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1387 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1390 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1391 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1392 ret
= NT_STATUS_SHARING_VIOLATION
;
1395 unix_ERR_ntstatus
= NT_STATUS_OK
;
1398 close_file(fsp
,False
);
1399 return NT_STATUS_OK
;
1402 /*******************************************************************
1403 Check if a user is allowed to delete a file.
1404 ********************************************************************/
1406 static NTSTATUS
can_delete(char *fname
,connection_struct
*conn
, int dirtype
, BOOL bad_path
)
1408 SMB_STRUCT_STAT sbuf
;
1414 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1417 if (!CAN_WRITE(conn
))
1418 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1420 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
) != 0) {
1421 if(errno
== ENOENT
) {
1423 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1425 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1427 return map_nt_error_from_unix(errno
);
1430 fmode
= dos_mode(conn
,fname
,&sbuf
);
1432 /* Can't delete a directory. */
1434 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1436 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
1437 return NT_STATUS_OBJECT_NAME_INVALID
;
1438 #endif /* JRATEST */
1440 if (!lp_delete_readonly(SNUM(conn
))) {
1442 return NT_STATUS_CANNOT_DELETE
;
1444 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1445 return NT_STATUS_NO_SUCH_FILE
;
1447 /* We need a better way to return NT status codes from open... */
1451 fsp
= open_file_shared1(conn
, fname
, &sbuf
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1452 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1455 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1456 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus
))
1457 ret
= unix_ERR_ntstatus
;
1458 else if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1459 ret
= NT_STATUS_SHARING_VIOLATION
;
1462 unix_ERR_ntstatus
= NT_STATUS_OK
;
1465 close_file(fsp
,False
);
1466 return NT_STATUS_OK
;
1469 /****************************************************************************
1470 The guts of the unlink command, split out so it may be called by the NT SMB
1472 ****************************************************************************/
1474 NTSTATUS
unlink_internals(connection_struct
*conn
, int dirtype
, char *name
)
1480 NTSTATUS error
= NT_STATUS_OK
;
1482 BOOL bad_path
= False
;
1484 SMB_STRUCT_STAT sbuf
;
1486 *directory
= *mask
= 0;
1488 /* We must check for wildcards in the name given
1489 * directly by the client - before any unmangling.
1490 * This prevents an unmangling of a UNIX name containing
1491 * a DOS wildcard like '*' or '?' from unmangling into
1492 * a wildcard delete which was not intended.
1493 * FIX for #226. JRA.
1496 has_wild
= ms_has_wild(name
);
1498 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1500 p
= strrchr_m(name
,'/');
1502 pstrcpy(directory
,".");
1506 pstrcpy(directory
,name
);
1511 * We should only check the mangled cache
1512 * here if unix_convert failed. This means
1513 * that the path in 'mask' doesn't exist
1514 * on the file system and so we need to look
1515 * for a possible mangle. This patch from
1516 * Tine Smukavec <valentin.smukavec@hermes.si>.
1519 if (!rc
&& mangle_is_mangled(mask
))
1520 mangle_check_cache( mask
);
1523 pstrcat(directory
,"/");
1524 pstrcat(directory
,mask
);
1525 error
= can_delete(directory
,conn
,dirtype
,bad_path
);
1526 if (!NT_STATUS_IS_OK(error
))
1529 if (SMB_VFS_UNLINK(conn
,directory
) == 0) {
1533 void *dirptr
= NULL
;
1536 if (check_name(directory
,conn
))
1537 dirptr
= OpenDir(conn
, directory
, True
);
1539 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1540 the pattern matches against the long name, otherwise the short name
1541 We don't implement this yet XXXX
1545 error
= NT_STATUS_NO_SUCH_FILE
;
1547 if (strequal(mask
,"????????.???"))
1550 while ((dname
= ReadDirName(dirptr
))) {
1552 BOOL sys_direntry
= False
;
1553 pstrcpy(fname
,dname
);
1555 /* Quick check for "." and ".." */
1556 if (fname
[0] == '.') {
1557 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
1558 if ((dirtype
& aDIR
)) {
1559 sys_direntry
= True
;
1566 if(!mask_match(fname
, mask
, case_sensitive
))
1570 error
= NT_STATUS_OBJECT_NAME_INVALID
;
1574 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1575 error
= can_delete(fname
,conn
,dirtype
,bad_path
);
1576 if (!NT_STATUS_IS_OK(error
))
1578 if (SMB_VFS_UNLINK(conn
,fname
) == 0)
1580 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
1586 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
1587 error
= map_nt_error_from_unix(errno
);
1593 /****************************************************************************
1595 ****************************************************************************/
1597 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
1604 START_PROFILE(SMBunlink
);
1606 dirtype
= SVAL(inbuf
,smb_vwv0
);
1608 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
);
1609 if (!NT_STATUS_IS_OK(status
)) {
1610 END_PROFILE(SMBunlink
);
1611 return ERROR_NT(status
);
1614 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
1616 DEBUG(3,("reply_unlink : %s\n",name
));
1618 status
= unlink_internals(conn
, dirtype
, name
);
1619 if (!NT_STATUS_IS_OK(status
))
1620 return ERROR_NT(status
);
1623 * Win2k needs a changenotify request response before it will
1624 * update after a rename..
1626 process_pending_change_notify_queue((time_t)0);
1628 outsize
= set_message(outbuf
,0,0,True
);
1630 END_PROFILE(SMBunlink
);
1634 /****************************************************************************
1636 ****************************************************************************/
1638 void fail_readraw(void)
1641 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1643 exit_server(errstr
);
1646 /****************************************************************************
1647 Use sendfile in readbraw.
1648 ****************************************************************************/
1650 void send_file_readbraw(connection_struct
*conn
, files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
,
1651 ssize_t mincount
, char *outbuf
)
1655 #if defined(WITH_SENDFILE)
1657 * We can only use sendfile on a non-chained packet and on a file
1658 * that is exclusively oplocked. reply_readbraw has already checked the length.
1661 if ((nread
> 0) && (lp_write_cache_size(SNUM(conn
)) == 0) &&
1662 EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) && lp_use_sendfile(SNUM(conn
)) ) {
1665 _smb_setlen(outbuf
,nread
);
1666 header
.data
= outbuf
;
1670 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, nread
) == -1) {
1672 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1673 * return ENOSYS then pretend we just got a normal read.
1675 if (errno
== ENOSYS
)
1678 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1679 fsp
->fsp_name
, strerror(errno
) ));
1680 exit_server("send_file_readbraw sendfile failed");
1689 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
1690 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1699 _smb_setlen(outbuf
,ret
);
1700 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
1704 /****************************************************************************
1705 Reply to a readbraw (core+ protocol).
1706 ****************************************************************************/
1708 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1710 extern struct current_user current_user
;
1711 ssize_t maxcount
,mincount
;
1714 char *header
= outbuf
;
1716 START_PROFILE(SMBreadbraw
);
1718 if (srv_is_signing_active()) {
1719 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1723 * Special check if an oplock break has been issued
1724 * and the readraw request croses on the wire, we must
1725 * return a zero length response here.
1728 if(global_oplock_break
) {
1729 _smb_setlen(header
,0);
1730 if (write_data(smbd_server_fd(),header
,4) != 4)
1732 DEBUG(5,("readbraw - oplock break finished\n"));
1733 END_PROFILE(SMBreadbraw
);
1737 fsp
= file_fsp(inbuf
,smb_vwv0
);
1739 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1741 * fsp could be NULL here so use the value from the packet. JRA.
1743 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
1744 _smb_setlen(header
,0);
1745 if (write_data(smbd_server_fd(),header
,4) != 4)
1747 END_PROFILE(SMBreadbraw
);
1751 CHECK_FSP(fsp
,conn
);
1753 flush_write_cache(fsp
, READRAW_FLUSH
);
1755 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
1756 if(CVAL(inbuf
,smb_wct
) == 10) {
1758 * This is a large offset (64 bit) read.
1760 #ifdef LARGE_SMB_OFF_T
1762 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
1764 #else /* !LARGE_SMB_OFF_T */
1767 * Ensure we haven't been sent a >32 bit offset.
1770 if(IVAL(inbuf
,smb_vwv8
) != 0) {
1771 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1772 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
1773 _smb_setlen(header
,0);
1774 if (write_data(smbd_server_fd(),header
,4) != 4)
1776 END_PROFILE(SMBreadbraw
);
1780 #endif /* LARGE_SMB_OFF_T */
1783 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
1784 _smb_setlen(header
,0);
1785 if (write_data(smbd_server_fd(),header
,4) != 4)
1787 END_PROFILE(SMBreadbraw
);
1791 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
1792 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
1794 /* ensure we don't overrun the packet size */
1795 maxcount
= MIN(65535,maxcount
);
1797 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1798 SMB_OFF_T size
= fsp
->size
;
1799 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
1801 if (size
< sizeneeded
) {
1803 if (SMB_VFS_FSTAT(fsp
,fsp
->fd
,&st
) == 0)
1805 if (!fsp
->can_write
)
1809 if (startpos
>= size
)
1812 nread
= MIN(maxcount
,(size
- startpos
));
1815 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1816 if (nread
< mincount
)
1820 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp
->fnum
, (double)startpos
,
1821 (int)maxcount
, (int)mincount
, (int)nread
) );
1823 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
, outbuf
);
1825 DEBUG(5,("readbraw finished\n"));
1826 END_PROFILE(SMBreadbraw
);
1830 /****************************************************************************
1831 Reply to a lockread (core+ protocol).
1832 ****************************************************************************/
1834 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
1842 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1843 BOOL my_lock_ctx
= False
;
1844 START_PROFILE(SMBlockread
);
1846 CHECK_FSP(fsp
,conn
);
1849 release_level_2_oplocks_on_change(fsp
);
1851 numtoread
= SVAL(inbuf
,smb_vwv1
);
1852 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1854 outsize
= set_message(outbuf
,5,3,True
);
1855 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1856 data
= smb_buf(outbuf
) + 3;
1859 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1860 * protocol request that predates the read/write lock concept.
1861 * Thus instead of asking for a read lock here we need to ask
1862 * for a write lock. JRA.
1863 * Note that the requested lock size is unaffected by max_recv.
1866 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
),
1867 (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
, &my_lock_ctx
);
1869 if (NT_STATUS_V(status
)) {
1872 * We used to make lockread a blocking lock. It turns out
1873 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1877 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
1879 * A blocking lock was requested. Package up
1880 * this smb into a queued request and push it
1881 * onto the blocking lock queue.
1883 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)startpos
,
1884 (SMB_BIG_UINT
)numtoread
)) {
1885 END_PROFILE(SMBlockread
);
1890 END_PROFILE(SMBlockread
);
1891 return ERROR_NT(status
);
1895 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1898 if (numtoread
> max_recv
) {
1899 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1900 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1901 (unsigned int)numtoread
, (unsigned int)max_recv
));
1902 numtoread
= MIN(numtoread
,max_recv
);
1904 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1907 END_PROFILE(SMBlockread
);
1908 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1912 SSVAL(outbuf
,smb_vwv0
,nread
);
1913 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1914 SSVAL(smb_buf(outbuf
),1,nread
);
1916 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1917 fsp
->fnum
, (int)numtoread
, (int)nread
));
1919 END_PROFILE(SMBlockread
);
1923 /****************************************************************************
1925 ****************************************************************************/
1927 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
1934 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1935 START_PROFILE(SMBread
);
1937 CHECK_FSP(fsp
,conn
);
1940 numtoread
= SVAL(inbuf
,smb_vwv1
);
1941 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1943 outsize
= set_message(outbuf
,5,3,True
);
1944 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1946 * The requested read size cannot be greater than max_recv. JRA.
1948 if (numtoread
> max_recv
) {
1949 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1950 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1951 (unsigned int)numtoread
, (unsigned int)max_recv
));
1952 numtoread
= MIN(numtoread
,max_recv
);
1955 data
= smb_buf(outbuf
) + 3;
1957 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1958 END_PROFILE(SMBread
);
1959 return ERROR_DOS(ERRDOS
,ERRlock
);
1963 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1966 END_PROFILE(SMBread
);
1967 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1971 SSVAL(outbuf
,smb_vwv0
,nread
);
1972 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1973 SCVAL(smb_buf(outbuf
),0,1);
1974 SSVAL(smb_buf(outbuf
),1,nread
);
1976 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1977 fsp
->fnum
, (int)numtoread
, (int)nread
) );
1979 END_PROFILE(SMBread
);
1983 /****************************************************************************
1984 Reply to a read and X - possibly using sendfile.
1985 ****************************************************************************/
1987 int send_file_readX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,
1988 files_struct
*fsp
, SMB_OFF_T startpos
, size_t smb_maxcnt
)
1991 char *data
= smb_buf(outbuf
);
1993 #if defined(WITH_SENDFILE)
1995 * We can only use sendfile on a non-chained packet and on a file
1996 * that is exclusively oplocked.
1999 if ((CVAL(inbuf
,smb_vwv0
) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) &&
2000 lp_use_sendfile(SNUM(conn
)) && (lp_write_cache_size(SNUM(conn
)) == 0) ) {
2001 SMB_STRUCT_STAT sbuf
;
2004 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1)
2005 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2007 if (startpos
> sbuf
.st_size
)
2010 if (smb_maxcnt
> (sbuf
.st_size
- startpos
))
2011 smb_maxcnt
= (sbuf
.st_size
- startpos
);
2013 if (smb_maxcnt
== 0)
2017 * Set up the packet header before send. We
2018 * assume here the sendfile will work (get the
2019 * correct amount of data).
2022 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2023 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
2024 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2025 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
2026 SCVAL(outbuf
,smb_vwv0
,0xFF);
2027 set_message(outbuf
,12,smb_maxcnt
,False
);
2028 header
.data
= outbuf
;
2029 header
.length
= data
- outbuf
;
2032 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, smb_maxcnt
) == -1) {
2034 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2035 * return ENOSYS then pretend we just got a normal read.
2037 if (errno
== ENOSYS
)
2040 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2041 fsp
->fsp_name
, strerror(errno
) ));
2042 exit_server("send_file_readX sendfile failed");
2045 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2046 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2054 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2057 END_PROFILE(SMBreadX
);
2058 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2061 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2062 SSVAL(outbuf
,smb_vwv5
,nread
);
2063 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2064 SSVAL(smb_buf(outbuf
),-2,nread
);
2066 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2067 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2072 /****************************************************************************
2073 Reply to a read and X.
2074 ****************************************************************************/
2076 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2078 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2079 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2081 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2083 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2086 START_PROFILE(SMBreadX
);
2088 /* If it's an IPC, pass off the pipe handler. */
2090 END_PROFILE(SMBreadX
);
2091 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2094 CHECK_FSP(fsp
,conn
);
2097 set_message(outbuf
,12,0,True
);
2099 if(CVAL(inbuf
,smb_wct
) == 12) {
2100 #ifdef LARGE_SMB_OFF_T
2102 * This is a large offset (64 bit) read.
2104 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2106 #else /* !LARGE_SMB_OFF_T */
2109 * Ensure we haven't been sent a >32 bit offset.
2112 if(IVAL(inbuf
,smb_vwv10
) != 0) {
2113 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2114 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
2115 END_PROFILE(SMBreadX
);
2116 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2119 #endif /* LARGE_SMB_OFF_T */
2123 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2124 END_PROFILE(SMBreadX
);
2125 return ERROR_DOS(ERRDOS
,ERRlock
);
2128 nread
= send_file_readX(conn
, inbuf
, outbuf
, length
, fsp
, startpos
, smb_maxcnt
);
2130 nread
= chain_reply(inbuf
,outbuf
,length
,bufsize
);
2132 END_PROFILE(SMBreadX
);
2136 /****************************************************************************
2137 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2138 ****************************************************************************/
2140 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2143 ssize_t total_written
=0;
2144 size_t numtowrite
=0;
2149 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2151 START_PROFILE(SMBwritebraw
);
2153 if (srv_is_signing_active()) {
2154 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2157 CHECK_FSP(fsp
,conn
);
2160 tcount
= IVAL(inbuf
,smb_vwv1
);
2161 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2162 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2164 /* We have to deal with slightly different formats depending
2165 on whether we are using the core+ or lanman1.0 protocol */
2167 if(Protocol
<= PROTOCOL_COREPLUS
) {
2168 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2169 data
= smb_buf(inbuf
);
2171 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2172 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2175 /* force the error type */
2176 SCVAL(inbuf
,smb_com
,SMBwritec
);
2177 SCVAL(outbuf
,smb_com
,SMBwritec
);
2179 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2180 END_PROFILE(SMBwritebraw
);
2181 return(ERROR_DOS(ERRDOS
,ERRlock
));
2185 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2187 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2188 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2190 if (nwritten
< (ssize_t
)numtowrite
) {
2191 END_PROFILE(SMBwritebraw
);
2192 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2195 total_written
= nwritten
;
2197 /* Return a message to the redirector to tell it to send more bytes */
2198 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
2199 SSVALS(outbuf
,smb_vwv0
,-1);
2200 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2201 if (!send_smb(smbd_server_fd(),outbuf
))
2202 exit_server("reply_writebraw: send_smb failed.");
2204 /* Now read the raw data into the buffer and write it */
2205 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2206 exit_server("secondary writebraw failed");
2209 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2210 numtowrite
= smb_len(inbuf
);
2212 /* Set up outbuf to return the correct return */
2213 outsize
= set_message(outbuf
,1,0,True
);
2214 SCVAL(outbuf
,smb_com
,SMBwritec
);
2215 SSVAL(outbuf
,smb_vwv0
,total_written
);
2217 if (numtowrite
!= 0) {
2219 if (numtowrite
> BUFFER_SIZE
) {
2220 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2221 (unsigned int)numtowrite
));
2222 exit_server("secondary writebraw failed");
2225 if (tcount
> nwritten
+numtowrite
) {
2226 DEBUG(3,("Client overestimated the write %d %d %d\n",
2227 (int)tcount
,(int)nwritten
,(int)numtowrite
));
2230 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
2231 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2233 exit_server("secondary writebraw failed");
2236 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
2238 if (nwritten
< (ssize_t
)numtowrite
) {
2239 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2240 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2244 total_written
+= nwritten
;
2247 if ((lp_syncalways(SNUM(conn
)) || write_through
) && lp_strict_sync(SNUM(conn
)))
2248 sync_file(conn
,fsp
);
2250 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2251 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
2253 /* we won't return a status if write through is not selected - this follows what WfWg does */
2254 END_PROFILE(SMBwritebraw
);
2255 if (!write_through
&& total_written
==tcount
) {
2257 #if RABBIT_PELLET_FIX
2259 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2260 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2262 if (!send_keepalive(smbd_server_fd()))
2263 exit_server("reply_writebraw: send of keepalive failed");
2271 /****************************************************************************
2272 Reply to a writeunlock (core+).
2273 ****************************************************************************/
2275 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
,
2276 int size
, int dum_buffsize
)
2278 ssize_t nwritten
= -1;
2282 NTSTATUS status
= NT_STATUS_OK
;
2283 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2285 START_PROFILE(SMBwriteunlock
);
2287 CHECK_FSP(fsp
,conn
);
2290 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2291 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2292 data
= smb_buf(inbuf
) + 3;
2294 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
,
2295 WRITE_LOCK
,False
)) {
2296 END_PROFILE(SMBwriteunlock
);
2297 return ERROR_DOS(ERRDOS
,ERRlock
);
2300 /* The special X/Open SMB protocol handling of
2301 zero length writes is *NOT* done for
2306 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2308 if (lp_syncalways(SNUM(conn
)))
2309 sync_file(conn
,fsp
);
2311 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2312 END_PROFILE(SMBwriteunlock
);
2313 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2317 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)numtowrite
,
2318 (SMB_BIG_UINT
)startpos
);
2319 if (NT_STATUS_V(status
)) {
2320 END_PROFILE(SMBwriteunlock
);
2321 return ERROR_NT(status
);
2325 outsize
= set_message(outbuf
,1,0,True
);
2327 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2329 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2330 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2332 END_PROFILE(SMBwriteunlock
);
2336 /****************************************************************************
2338 ****************************************************************************/
2340 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2343 ssize_t nwritten
= -1;
2346 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2348 START_PROFILE(SMBwrite
);
2350 /* If it's an IPC, pass off the pipe handler. */
2352 END_PROFILE(SMBwrite
);
2353 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2356 CHECK_FSP(fsp
,conn
);
2359 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2360 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2361 data
= smb_buf(inbuf
) + 3;
2363 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2364 END_PROFILE(SMBwrite
);
2365 return ERROR_DOS(ERRDOS
,ERRlock
);
2369 * X/Open SMB protocol says that if smb_vwv1 is
2370 * zero then the file size should be extended or
2371 * truncated to the size given in smb_vwv[2-3].
2374 if(numtowrite
== 0) {
2376 * This is actually an allocate call, and set EOF. JRA.
2378 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2380 END_PROFILE(SMBwrite
);
2381 return ERROR_NT(NT_STATUS_DISK_FULL
);
2383 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2385 END_PROFILE(SMBwrite
);
2386 return ERROR_NT(NT_STATUS_DISK_FULL
);
2389 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2391 if (lp_syncalways(SNUM(conn
)))
2392 sync_file(conn
,fsp
);
2394 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2395 END_PROFILE(SMBwrite
);
2396 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2399 outsize
= set_message(outbuf
,1,0,True
);
2401 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2403 if (nwritten
< (ssize_t
)numtowrite
) {
2404 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2405 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2408 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2410 END_PROFILE(SMBwrite
);
2414 /****************************************************************************
2415 Reply to a write and X.
2416 ****************************************************************************/
2418 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2420 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2421 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2422 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2423 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2424 ssize_t nwritten
= -1;
2425 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2426 unsigned int smblen
= smb_len(inbuf
);
2428 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2429 START_PROFILE(SMBwriteX
);
2431 /* If it's an IPC, pass off the pipe handler. */
2433 END_PROFILE(SMBwriteX
);
2434 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2437 CHECK_FSP(fsp
,conn
);
2440 /* Deal with possible LARGE_WRITEX */
2442 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2444 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2445 END_PROFILE(SMBwriteX
);
2446 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2449 data
= smb_base(inbuf
) + smb_doff
;
2451 if(CVAL(inbuf
,smb_wct
) == 14) {
2452 #ifdef LARGE_SMB_OFF_T
2454 * This is a large offset (64 bit) write.
2456 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2458 #else /* !LARGE_SMB_OFF_T */
2461 * Ensure we haven't been sent a >32 bit offset.
2464 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2465 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2466 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2467 END_PROFILE(SMBwriteX
);
2468 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2471 #endif /* LARGE_SMB_OFF_T */
2474 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2475 END_PROFILE(SMBwriteX
);
2476 return ERROR_DOS(ERRDOS
,ERRlock
);
2479 /* X/Open SMB protocol says that, unlike SMBwrite
2480 if the length is zero then NO truncation is
2481 done, just a write of zero. To truncate a file,
2487 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2489 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2490 END_PROFILE(SMBwriteX
);
2491 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2494 set_message(outbuf
,6,0,True
);
2496 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2498 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2500 if (nwritten
< (ssize_t
)numtowrite
) {
2501 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2502 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2505 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2506 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2508 if (lp_syncalways(SNUM(conn
)) || write_through
)
2509 sync_file(conn
,fsp
);
2511 END_PROFILE(SMBwriteX
);
2512 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2515 /****************************************************************************
2517 ****************************************************************************/
2519 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2525 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2526 START_PROFILE(SMBlseek
);
2528 CHECK_FSP(fsp
,conn
);
2530 flush_write_cache(fsp
, SEEK_FLUSH
);
2532 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2533 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2534 startpos
= (SMB_OFF_T
)IVALS(inbuf
,smb_vwv2
);
2543 res
= fsp
->pos
+ startpos
;
2554 if (umode
== SEEK_END
) {
2555 if((res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
2556 if(errno
== EINVAL
) {
2557 SMB_OFF_T current_pos
= startpos
;
2558 SMB_STRUCT_STAT sbuf
;
2560 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1) {
2561 END_PROFILE(SMBlseek
);
2562 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2565 current_pos
+= sbuf
.st_size
;
2567 res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,0,SEEK_SET
);
2572 END_PROFILE(SMBlseek
);
2573 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2579 outsize
= set_message(outbuf
,2,0,True
);
2580 SIVAL(outbuf
,smb_vwv0
,res
);
2582 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2583 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
2585 END_PROFILE(SMBlseek
);
2589 /****************************************************************************
2591 ****************************************************************************/
2593 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2595 int outsize
= set_message(outbuf
,0,0,True
);
2596 uint16 fnum
= SVAL(inbuf
,smb_vwv0
);
2597 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2598 START_PROFILE(SMBflush
);
2601 CHECK_FSP(fsp
,conn
);
2604 file_sync_all(conn
);
2606 sync_file(conn
,fsp
);
2609 DEBUG(3,("flush\n"));
2610 END_PROFILE(SMBflush
);
2614 /****************************************************************************
2616 ****************************************************************************/
2618 int reply_exit(connection_struct
*conn
,
2619 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2622 START_PROFILE(SMBexit
);
2624 file_close_pid(SVAL(inbuf
,smb_pid
));
2626 outsize
= set_message(outbuf
,0,0,True
);
2628 DEBUG(3,("exit\n"));
2630 END_PROFILE(SMBexit
);
2634 /****************************************************************************
2635 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2636 ****************************************************************************/
2638 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2641 extern struct current_user current_user
;
2644 int32 eclass
= 0, err
= 0;
2645 files_struct
*fsp
= NULL
;
2646 START_PROFILE(SMBclose
);
2648 outsize
= set_message(outbuf
,0,0,True
);
2650 /* If it's an IPC, pass off to the pipe handler. */
2652 END_PROFILE(SMBclose
);
2653 return reply_pipe_close(conn
, inbuf
,outbuf
);
2656 fsp
= file_fsp(inbuf
,smb_vwv0
);
2659 * We can only use CHECK_FSP if we know it's not a directory.
2662 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= current_user
.vuid
)) {
2663 END_PROFILE(SMBclose
);
2664 return ERROR_DOS(ERRDOS
,ERRbadfid
);
2667 if(fsp
->is_directory
) {
2669 * Special case - close NT SMB directory handle.
2671 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
2672 close_file(fsp
,True
);
2675 * Close ordinary file.
2680 /* Save the name for time set in close. */
2681 pstrcpy( file_name
, fsp
->fsp_name
);
2683 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2685 conn
->num_files_open
));
2688 * close_file() returns the unix errno if an error
2689 * was detected on close - normally this is due to
2690 * a disk full error. If not then it was probably an I/O error.
2693 if((close_err
= close_file(fsp
,True
)) != 0) {
2695 END_PROFILE(SMBclose
);
2696 return (UNIXERROR(ERRHRD
,ERRgeneral
));
2700 * Now take care of any time sent in the close.
2703 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2705 /* try and set the date */
2706 set_filetime(conn
, file_name
, mtime
);
2710 /* We have a cached error */
2712 END_PROFILE(SMBclose
);
2713 return ERROR_DOS(eclass
,err
);
2716 END_PROFILE(SMBclose
);
2720 /****************************************************************************
2721 Reply to a writeclose (Core+ protocol).
2722 ****************************************************************************/
2724 int reply_writeclose(connection_struct
*conn
,
2725 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2728 ssize_t nwritten
= -1;
2734 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2735 START_PROFILE(SMBwriteclose
);
2737 CHECK_FSP(fsp
,conn
);
2740 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2741 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2742 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2743 data
= smb_buf(inbuf
) + 1;
2745 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2746 END_PROFILE(SMBwriteclose
);
2747 return ERROR_DOS(ERRDOS
,ERRlock
);
2750 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2752 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2755 * More insanity. W2K only closes the file if writelen > 0.
2760 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2762 close_err
= close_file(fsp
,True
);
2765 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2766 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
2767 conn
->num_files_open
));
2769 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2770 END_PROFILE(SMBwriteclose
);
2771 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2774 if(close_err
!= 0) {
2776 END_PROFILE(SMBwriteclose
);
2777 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2780 outsize
= set_message(outbuf
,1,0,True
);
2782 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2783 END_PROFILE(SMBwriteclose
);
2787 /****************************************************************************
2789 ****************************************************************************/
2791 int reply_lock(connection_struct
*conn
,
2792 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
2794 int outsize
= set_message(outbuf
,0,0,True
);
2795 SMB_BIG_UINT count
,offset
;
2797 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2798 BOOL my_lock_ctx
= False
;
2800 START_PROFILE(SMBlock
);
2802 CHECK_FSP(fsp
,conn
);
2804 release_level_2_oplocks_on_change(fsp
);
2806 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2807 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2809 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2810 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
2812 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
, WRITE_LOCK
, &my_lock_ctx
);
2813 if (NT_STATUS_V(status
)) {
2815 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2816 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
2818 * A blocking lock was requested. Package up
2819 * this smb into a queued request and push it
2820 * onto the blocking lock queue.
2822 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), offset
, count
)) {
2823 END_PROFILE(SMBlock
);
2828 END_PROFILE(SMBlock
);
2829 return ERROR_NT(status
);
2832 END_PROFILE(SMBlock
);
2836 /****************************************************************************
2838 ****************************************************************************/
2840 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2843 int outsize
= set_message(outbuf
,0,0,True
);
2844 SMB_BIG_UINT count
,offset
;
2846 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2847 START_PROFILE(SMBunlock
);
2849 CHECK_FSP(fsp
,conn
);
2851 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2852 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2854 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
);
2855 if (NT_STATUS_V(status
)) {
2856 END_PROFILE(SMBunlock
);
2857 return ERROR_NT(status
);
2860 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2861 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
2863 END_PROFILE(SMBunlock
);
2867 /****************************************************************************
2869 ****************************************************************************/
2871 int reply_tdis(connection_struct
*conn
,
2872 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2874 int outsize
= set_message(outbuf
,0,0,True
);
2876 START_PROFILE(SMBtdis
);
2878 vuid
= SVAL(inbuf
,smb_uid
);
2881 DEBUG(4,("Invalid connection in tdis\n"));
2882 END_PROFILE(SMBtdis
);
2883 return ERROR_DOS(ERRSRV
,ERRinvnid
);
2888 close_cnum(conn
,vuid
);
2890 END_PROFILE(SMBtdis
);
2894 /****************************************************************************
2896 ****************************************************************************/
2898 int reply_echo(connection_struct
*conn
,
2899 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2901 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2903 unsigned int data_len
= smb_buflen(inbuf
);
2904 int outsize
= set_message(outbuf
,1,data_len
,True
);
2905 START_PROFILE(SMBecho
);
2907 if (data_len
> BUFFER_SIZE
) {
2908 DEBUG(0,("reply_echo: data_len too large.\n"));
2909 END_PROFILE(SMBecho
);
2913 /* copy any incoming data back out */
2915 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2917 if (smb_reverb
> 100) {
2918 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2922 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2923 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2925 smb_setlen(outbuf
,outsize
- 4);
2927 if (!send_smb(smbd_server_fd(),outbuf
))
2928 exit_server("reply_echo: send_smb failed.");
2931 DEBUG(3,("echo %d times\n", smb_reverb
));
2935 END_PROFILE(SMBecho
);
2939 /****************************************************************************
2940 Reply to a printopen.
2941 ****************************************************************************/
2943 int reply_printopen(connection_struct
*conn
,
2944 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2948 START_PROFILE(SMBsplopen
);
2950 if (!CAN_PRINT(conn
)) {
2951 END_PROFILE(SMBsplopen
);
2952 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2955 /* Open for exclusive use, write only. */
2956 fsp
= print_fsp_open(conn
, NULL
);
2959 END_PROFILE(SMBsplopen
);
2960 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2963 outsize
= set_message(outbuf
,1,0,True
);
2964 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2966 DEBUG(3,("openprint fd=%d fnum=%d\n",
2967 fsp
->fd
, fsp
->fnum
));
2969 END_PROFILE(SMBsplopen
);
2973 /****************************************************************************
2974 Reply to a printclose.
2975 ****************************************************************************/
2977 int reply_printclose(connection_struct
*conn
,
2978 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2980 int outsize
= set_message(outbuf
,0,0,True
);
2981 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2983 START_PROFILE(SMBsplclose
);
2985 CHECK_FSP(fsp
,conn
);
2987 if (!CAN_PRINT(conn
)) {
2988 END_PROFILE(SMBsplclose
);
2989 return ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
2992 DEBUG(3,("printclose fd=%d fnum=%d\n",
2993 fsp
->fd
,fsp
->fnum
));
2995 close_err
= close_file(fsp
,True
);
2997 if(close_err
!= 0) {
2999 END_PROFILE(SMBsplclose
);
3000 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3003 END_PROFILE(SMBsplclose
);
3007 /****************************************************************************
3008 Reply to a printqueue.
3009 ****************************************************************************/
3011 int reply_printqueue(connection_struct
*conn
,
3012 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3014 int outsize
= set_message(outbuf
,2,3,True
);
3015 int max_count
= SVAL(inbuf
,smb_vwv0
);
3016 int start_index
= SVAL(inbuf
,smb_vwv1
);
3017 START_PROFILE(SMBsplretq
);
3019 /* we used to allow the client to get the cnum wrong, but that
3020 is really quite gross and only worked when there was only
3021 one printer - I think we should now only accept it if they
3022 get it right (tridge) */
3023 if (!CAN_PRINT(conn
)) {
3024 END_PROFILE(SMBsplretq
);
3025 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3028 SSVAL(outbuf
,smb_vwv0
,0);
3029 SSVAL(outbuf
,smb_vwv1
,0);
3030 SCVAL(smb_buf(outbuf
),0,1);
3031 SSVAL(smb_buf(outbuf
),1,0);
3033 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3034 start_index
, max_count
));
3037 print_queue_struct
*queue
= NULL
;
3038 print_status_struct status
;
3039 char *p
= smb_buf(outbuf
) + 3;
3040 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
3041 int num_to_get
= ABS(max_count
);
3042 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
3048 num_to_get
= MIN(num_to_get
,count
-first
);
3051 for (i
=first
;i
<first
+num_to_get
;i
++) {
3052 put_dos_date2(p
,0,queue
[i
].time
);
3053 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
3054 SSVAL(p
,5, queue
[i
].job
);
3055 SIVAL(p
,7,queue
[i
].size
);
3057 srvstr_push(outbuf
, p
+12, queue
[i
].fs_user
, 16, STR_ASCII
);
3062 outsize
= set_message(outbuf
,2,28*count
+3,False
);
3063 SSVAL(outbuf
,smb_vwv0
,count
);
3064 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
3065 SCVAL(smb_buf(outbuf
),0,1);
3066 SSVAL(smb_buf(outbuf
),1,28*count
);
3071 DEBUG(3,("%d entries returned in queue\n",count
));
3074 END_PROFILE(SMBsplretq
);
3078 /****************************************************************************
3079 Reply to a printwrite.
3080 ****************************************************************************/
3082 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3085 int outsize
= set_message(outbuf
,0,0,True
);
3087 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3089 START_PROFILE(SMBsplwr
);
3091 if (!CAN_PRINT(conn
)) {
3092 END_PROFILE(SMBsplwr
);
3093 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3096 CHECK_FSP(fsp
,conn
);
3099 numtowrite
= SVAL(smb_buf(inbuf
),1);
3100 data
= smb_buf(inbuf
) + 3;
3102 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
3103 END_PROFILE(SMBsplwr
);
3104 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3107 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
3109 END_PROFILE(SMBsplwr
);
3113 /****************************************************************************
3114 The guts of the mkdir command, split out so it may be called by the NT SMB
3116 ****************************************************************************/
3118 NTSTATUS
mkdir_internal(connection_struct
*conn
, pstring directory
)
3120 BOOL bad_path
= False
;
3121 SMB_STRUCT_STAT sbuf
;
3124 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3126 if( strchr_m(directory
, ':')) {
3127 return NT_STATUS_NOT_A_DIRECTORY
;
3130 if (ms_has_wild(directory
)) {
3131 return NT_STATUS_OBJECT_NAME_INVALID
;
3134 if (check_name(directory
, conn
))
3135 ret
= vfs_MkDir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3138 if(errno
== ENOENT
) {
3140 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3142 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3144 return map_nt_error_from_unix(errno
);
3147 return NT_STATUS_OK
;
3150 /****************************************************************************
3152 ****************************************************************************/
3154 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3159 START_PROFILE(SMBmkdir
);
3161 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3162 if (!NT_STATUS_IS_OK(status
)) {
3163 END_PROFILE(SMBmkdir
);
3164 return ERROR_NT(status
);
3167 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
);
3169 status
= mkdir_internal(conn
, directory
);
3170 if (!NT_STATUS_IS_OK(status
)) {
3171 END_PROFILE(SMBmkdir
);
3172 return ERROR_NT(status
);
3175 outsize
= set_message(outbuf
,0,0,True
);
3177 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
3179 END_PROFILE(SMBmkdir
);
3183 /****************************************************************************
3184 Static function used by reply_rmdir to delete an entire directory
3185 tree recursively. Return False on ok, True on fail.
3186 ****************************************************************************/
3188 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
3190 const char *dname
= NULL
;
3192 void *dirptr
= OpenDir(conn
, directory
, False
);
3197 while((dname
= ReadDirName(dirptr
))) {
3201 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3204 /* Construct the full name. */
3205 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3211 pstrcpy(fullname
, directory
);
3212 pstrcat(fullname
, "/");
3213 pstrcat(fullname
, dname
);
3215 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
3220 if(st
.st_mode
& S_IFDIR
) {
3221 if(recursive_rmdir(conn
, fullname
)!=0) {
3225 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
3229 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
3238 /****************************************************************************
3239 The internals of the rmdir code - called elsewhere.
3240 ****************************************************************************/
3242 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
3246 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3247 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
3249 * Check to see if the only thing in this directory are
3250 * vetoed files/directories. If so then delete them and
3251 * retry. If we fail to delete any of them (and we *don't*
3252 * do a recursive delete) then fail the rmdir.
3254 BOOL all_veto_files
= True
;
3256 void *dirptr
= OpenDir(conn
, directory
, False
);
3258 if(dirptr
!= NULL
) {
3259 int dirpos
= TellDir(dirptr
);
3260 while ((dname
= ReadDirName(dirptr
))) {
3261 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3263 if(!IS_VETO_PATH(conn
, dname
)) {
3264 all_veto_files
= False
;
3269 if(all_veto_files
) {
3270 SeekDir(dirptr
,dirpos
);
3271 while ((dname
= ReadDirName(dirptr
))) {
3275 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3278 /* Construct the full name. */
3279 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3284 pstrcpy(fullname
, directory
);
3285 pstrcat(fullname
, "/");
3286 pstrcat(fullname
, dname
);
3288 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0)
3290 if(st
.st_mode
& S_IFDIR
) {
3291 if(lp_recursive_veto_delete(SNUM(conn
))) {
3292 if(recursive_rmdir(conn
, fullname
) != 0)
3295 if(SMB_VFS_RMDIR(conn
,fullname
) != 0)
3297 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0)
3301 /* Retry the rmdir */
3302 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3312 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory
,strerror(errno
)));
3317 /****************************************************************************
3319 ****************************************************************************/
3321 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3326 BOOL bad_path
= False
;
3327 SMB_STRUCT_STAT sbuf
;
3329 START_PROFILE(SMBrmdir
);
3331 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3332 if (!NT_STATUS_IS_OK(status
)) {
3333 END_PROFILE(SMBrmdir
);
3334 return ERROR_NT(status
);
3337 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3339 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3341 if (check_name(directory
,conn
)) {
3342 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3343 ok
= rmdir_internals(conn
, directory
);
3347 END_PROFILE(SMBrmdir
);
3348 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRbadpath
);
3351 outsize
= set_message(outbuf
,0,0,True
);
3353 DEBUG( 3, ( "rmdir %s\n", directory
) );
3355 END_PROFILE(SMBrmdir
);
3359 /*******************************************************************
3360 Resolve wildcards in a filename rename.
3361 Note that name is in UNIX charset and thus potentially can be more
3362 than fstring buffer (255 bytes) especially in default UTF-8 case.
3363 Therefore, we use pstring inside and all calls should ensure that
3364 name2 is at least pstring-long (they do already)
3365 ********************************************************************/
3367 static BOOL
resolve_wildcards(const char *name1
, char *name2
)
3369 pstring root1
,root2
;
3371 char *p
,*p2
, *pname1
, *pname2
;
3372 int available_space
, actual_space
;
3375 pname1
= strrchr_m(name1
,'/');
3376 pname2
= strrchr_m(name2
,'/');
3378 if (!pname1
|| !pname2
)
3381 pstrcpy(root1
,pname1
);
3382 pstrcpy(root2
,pname2
);
3383 p
= strrchr_m(root1
,'.');
3390 p
= strrchr_m(root2
,'.');
3424 available_space
= sizeof(pstring
) - PTR_DIFF(pname2
, name2
);
3427 actual_space
= snprintf(pname2
, available_space
- 1, "%s.%s", root2
, ext2
);
3428 if (actual_space
>= available_space
- 1) {
3429 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3430 actual_space
- available_space
));
3433 pstrcpy_base(pname2
, root2
, name2
);
3439 /****************************************************************************
3440 Ensure open files have their names updates.
3441 ****************************************************************************/
3443 static void rename_open_files(connection_struct
*conn
, SMB_DEV_T dev
, SMB_INO_T inode
, char *newname
)
3446 BOOL did_rename
= False
;
3448 for(fsp
= file_find_di_first(dev
, inode
); fsp
; fsp
= file_find_di_next(fsp
)) {
3449 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3450 fsp
->fnum
, (unsigned int)fsp
->dev
, (double)fsp
->inode
,
3451 fsp
->fsp_name
, newname
));
3452 string_set(&fsp
->fsp_name
, newname
);
3457 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3458 (unsigned int)dev
, (double)inode
, newname
));
3461 /****************************************************************************
3462 Rename an open file - given an fsp.
3463 ****************************************************************************/
3465 NTSTATUS
rename_internals_fsp(connection_struct
*conn
, files_struct
*fsp
, char *newname
, BOOL replace_if_exists
)
3467 SMB_STRUCT_STAT sbuf
;
3468 BOOL bad_path
= False
;
3469 pstring newname_last_component
;
3470 NTSTATUS error
= NT_STATUS_OK
;
3475 rcdest
= unix_convert(newname
,conn
,newname_last_component
,&bad_path
,&sbuf
);
3477 /* Quick check for "." and ".." */
3478 if (!bad_path
&& newname_last_component
[0] == '.') {
3479 if (!newname_last_component
[1] || (newname_last_component
[1] == '.' && !newname_last_component
[2])) {
3480 return NT_STATUS_ACCESS_DENIED
;
3483 if (!rcdest
&& bad_path
) {
3484 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3487 /* Ensure newname contains a '/' */
3488 if(strrchr_m(newname
,'/') == 0) {
3491 pstrcpy(tmpstr
, "./");
3492 pstrcat(tmpstr
, newname
);
3493 pstrcpy(newname
, tmpstr
);
3497 * Check for special case with case preserving and not
3498 * case sensitive. If the old last component differs from the original
3499 * last component only by case, then we should allow
3500 * the rename (user is trying to change the case of the
3504 if((case_sensitive
== False
) && (case_preserve
== True
) &&
3505 strequal(newname
, fsp
->fsp_name
)) {
3507 pstring newname_modified_last_component
;
3510 * Get the last component of the modified name.
3511 * Note that we guarantee that newname contains a '/'
3514 p
= strrchr_m(newname
,'/');
3515 pstrcpy(newname_modified_last_component
,p
+1);
3517 if(strcsequal(newname_modified_last_component
,
3518 newname_last_component
) == False
) {
3520 * Replace the modified last component with
3523 pstrcpy(p
+1, newname_last_component
);
3528 * If the src and dest names are identical - including case,
3529 * don't do the rename, just return success.
3532 if (strcsequal(fsp
->fsp_name
, newname
)) {
3533 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3535 return NT_STATUS_OK
;
3538 dest_exists
= vfs_object_exist(conn
,newname
,NULL
);
3540 if(!replace_if_exists
&& dest_exists
) {
3541 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3542 fsp
->fsp_name
,newname
));
3543 return NT_STATUS_OBJECT_NAME_COLLISION
;
3546 error
= can_rename(newname
,conn
,&sbuf
);
3548 if (dest_exists
&& !NT_STATUS_IS_OK(error
)) {
3549 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3550 nt_errstr(error
), fsp
->fsp_name
,newname
));
3551 if (NT_STATUS_EQUAL(error
,NT_STATUS_SHARING_VIOLATION
))
3552 error
= NT_STATUS_ACCESS_DENIED
;
3556 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
3557 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3558 fsp
->fsp_name
,newname
));
3559 rename_open_files(conn
, fsp
->dev
, fsp
->inode
, newname
);
3560 return NT_STATUS_OK
;
3563 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3564 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3566 error
= map_nt_error_from_unix(errno
);
3568 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3569 nt_errstr(error
), fsp
->fsp_name
,newname
));
3574 /****************************************************************************
3575 The guts of the rename command, split out so it may be called by the NT SMB
3577 ****************************************************************************/
3579 NTSTATUS
rename_internals(connection_struct
*conn
, char *name
, char *newname
, uint16 attrs
, BOOL replace_if_exists
)
3583 pstring last_component_src
;
3584 pstring last_component_dest
;
3587 BOOL bad_path_src
= False
;
3588 BOOL bad_path_dest
= False
;
3590 NTSTATUS error
= NT_STATUS_OK
;
3593 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3595 *directory
= *mask
= 0;
3600 rc
= unix_convert(name
,conn
,last_component_src
,&bad_path_src
,&sbuf1
);
3601 if (!rc
&& bad_path_src
) {
3602 if (ms_has_wild(last_component_src
))
3603 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3604 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3607 /* Quick check for "." and ".." */
3608 if (last_component_src
[0] == '.') {
3609 if (!last_component_src
[1] || (last_component_src
[1] == '.' && !last_component_src
[2])) {
3610 return NT_STATUS_OBJECT_NAME_INVALID
;
3614 rcdest
= unix_convert(newname
,conn
,last_component_dest
,&bad_path_dest
,&sbuf2
);
3616 /* Quick check for "." and ".." */
3617 if (last_component_dest
[0] == '.') {
3618 if (!last_component_dest
[1] || (last_component_dest
[1] == '.' && !last_component_dest
[2])) {
3619 return NT_STATUS_OBJECT_NAME_INVALID
;
3624 * Split the old name into directory and last component
3625 * strings. Note that unix_convert may have stripped off a
3626 * leading ./ from both name and newname if the rename is
3627 * at the root of the share. We need to make sure either both
3628 * name and newname contain a / character or neither of them do
3629 * as this is checked in resolve_wildcards().
3632 p
= strrchr_m(name
,'/');
3634 pstrcpy(directory
,".");
3638 pstrcpy(directory
,name
);
3640 *p
= '/'; /* Replace needed for exceptional test below. */
3644 * We should only check the mangled cache
3645 * here if unix_convert failed. This means
3646 * that the path in 'mask' doesn't exist
3647 * on the file system and so we need to look
3648 * for a possible mangle. This patch from
3649 * Tine Smukavec <valentin.smukavec@hermes.si>.
3652 if (!rc
&& mangle_is_mangled(mask
))
3653 mangle_check_cache( mask
);
3655 has_wild
= ms_has_wild(mask
);
3659 * No wildcards - just process the one file.
3661 BOOL is_short_name
= mangle_is_8_3(name
, True
);
3663 /* Add a terminating '/' to the directory name. */
3664 pstrcat(directory
,"/");
3665 pstrcat(directory
,mask
);
3667 /* Ensure newname contains a '/' also */
3668 if(strrchr_m(newname
,'/') == 0) {
3671 pstrcpy(tmpstr
, "./");
3672 pstrcat(tmpstr
, newname
);
3673 pstrcpy(newname
, tmpstr
);
3676 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3677 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3678 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3679 newname
, last_component_dest
, is_short_name
));
3682 * Check for special case with case preserving and not
3683 * case sensitive, if directory and newname are identical,
3684 * and the old last component differs from the original
3685 * last component only by case, then we should allow
3686 * the rename (user is trying to change the case of the
3689 if((case_sensitive
== False
) &&
3690 (((case_preserve
== True
) &&
3691 (is_short_name
== False
)) ||
3692 ((short_case_preserve
== True
) &&
3693 (is_short_name
== True
))) &&
3694 strcsequal(directory
, newname
)) {
3695 pstring modified_last_component
;
3698 * Get the last component of the modified name.
3699 * Note that we guarantee that newname contains a '/'
3702 p
= strrchr_m(newname
,'/');
3703 pstrcpy(modified_last_component
,p
+1);
3705 if(strcsequal(modified_last_component
,
3706 last_component_dest
) == False
) {
3708 * Replace the modified last component with
3711 pstrcpy(p
+1, last_component_dest
);
3715 resolve_wildcards(directory
,newname
);
3718 * The source object must exist.
3721 if (!vfs_object_exist(conn
, directory
, &sbuf1
)) {
3722 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3723 directory
,newname
));
3725 if (errno
== ENOTDIR
|| errno
== EISDIR
|| errno
== ENOENT
) {
3727 * Must return different errors depending on whether the parent
3728 * directory existed or not.
3731 p
= strrchr_m(directory
, '/');
3733 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3735 if (vfs_object_exist(conn
, directory
, NULL
))
3736 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3737 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3739 error
= map_nt_error_from_unix(errno
);
3740 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3741 nt_errstr(error
), directory
,newname
));
3746 if (!rcdest
&& bad_path_dest
) {
3747 if (ms_has_wild(last_component_dest
))
3748 return NT_STATUS_OBJECT_NAME_INVALID
;
3749 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3752 error
= can_rename(directory
,conn
,&sbuf1
);
3754 if (!NT_STATUS_IS_OK(error
)) {
3755 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3756 nt_errstr(error
), directory
,newname
));
3761 * If the src and dest names are identical - including case,
3762 * don't do the rename, just return success.
3765 if (strcsequal(directory
, newname
)) {
3766 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3767 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory
));
3768 return NT_STATUS_OK
;
3771 if(!replace_if_exists
&& vfs_object_exist(conn
,newname
,NULL
)) {
3772 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3773 directory
,newname
));
3774 return NT_STATUS_OBJECT_NAME_COLLISION
;
3777 if(SMB_VFS_RENAME(conn
,directory
, newname
) == 0) {
3778 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3779 directory
,newname
));
3780 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3781 return NT_STATUS_OK
;
3784 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3785 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3787 error
= map_nt_error_from_unix(errno
);
3789 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3790 nt_errstr(error
), directory
,newname
));
3795 * Wildcards - process each file that matches.
3797 void *dirptr
= NULL
;
3801 if (check_name(directory
,conn
))
3802 dirptr
= OpenDir(conn
, directory
, True
);
3805 error
= NT_STATUS_NO_SUCH_FILE
;
3806 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3808 if (strequal(mask
,"????????.???"))
3811 while ((dname
= ReadDirName(dirptr
))) {
3813 BOOL sysdir_entry
= False
;
3815 pstrcpy(fname
,dname
);
3817 /* Quick check for "." and ".." */
3818 if (fname
[0] == '.') {
3819 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
3821 sysdir_entry
= True
;
3828 if(!mask_match(fname
, mask
, case_sensitive
))
3832 error
= NT_STATUS_OBJECT_NAME_INVALID
;
3836 error
= NT_STATUS_ACCESS_DENIED
;
3837 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3838 if (!vfs_object_exist(conn
, fname
, &sbuf1
)) {
3839 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3840 DEBUG(6,("rename %s failed. Error %s\n", fname
, nt_errstr(error
)));
3843 error
= can_rename(fname
,conn
,&sbuf1
);
3844 if (!NT_STATUS_IS_OK(error
)) {
3845 DEBUG(6,("rename %s refused\n", fname
));
3848 pstrcpy(destname
,newname
);
3850 if (!resolve_wildcards(fname
,destname
)) {
3851 DEBUG(6,("resolve_wildcards %s %s failed\n",
3856 if (!replace_if_exists
&&
3857 vfs_file_exist(conn
,destname
, NULL
)) {
3858 DEBUG(6,("file_exist %s\n", destname
));
3859 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3863 if (!SMB_VFS_RENAME(conn
,fname
,destname
)) {
3864 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3866 error
= NT_STATUS_OK
;
3868 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3873 if (!NT_STATUS_EQUAL(error
,NT_STATUS_NO_SUCH_FILE
)) {
3874 if (!rcdest
&& bad_path_dest
) {
3875 if (ms_has_wild(last_component_dest
))
3876 return NT_STATUS_OBJECT_NAME_INVALID
;
3877 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3882 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
3883 error
= map_nt_error_from_unix(errno
);
3889 /****************************************************************************
3891 ****************************************************************************/
3893 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
3900 uint16 attrs
= SVAL(inbuf
,smb_vwv0
);
3903 START_PROFILE(SMBmv
);
3905 p
= smb_buf(inbuf
) + 1;
3906 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
);
3907 if (!NT_STATUS_IS_OK(status
)) {
3909 return ERROR_NT(status
);
3912 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
);
3913 if (!NT_STATUS_IS_OK(status
)) {
3915 return ERROR_NT(status
);
3918 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3919 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3921 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3923 status
= rename_internals(conn
, name
, newname
, attrs
, False
);
3924 if (!NT_STATUS_IS_OK(status
)) {
3926 return ERROR_NT(status
);
3930 * Win2k needs a changenotify request response before it will
3931 * update after a rename..
3933 process_pending_change_notify_queue((time_t)0);
3934 outsize
= set_message(outbuf
,0,0,True
);
3940 /*******************************************************************
3941 Copy a file as part of a reply_copy.
3942 ******************************************************************/
3944 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3945 int count
,BOOL target_is_directory
, int *err_ret
)
3948 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
3950 files_struct
*fsp1
,*fsp2
;
3955 pstrcpy(dest
,dest1
);
3956 if (target_is_directory
) {
3957 char *p
= strrchr_m(src
,'/');
3966 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
3969 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3970 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
3975 if (!target_is_directory
&& count
)
3976 ofun
= FILE_EXISTS_OPEN
;
3978 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1)
3979 ZERO_STRUCTP(&sbuf2
);
3981 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3982 ofun
,src_sbuf
.st_mode
,0,&Access
,&action
);
3985 close_file(fsp1
,False
);
3989 if ((ofun
&3) == 1) {
3990 if(SMB_VFS_LSEEK(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
3991 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
3993 * Stop the copy from occurring.
3996 src_sbuf
.st_size
= 0;
4000 if (src_sbuf
.st_size
)
4001 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
4003 close_file(fsp1
,False
);
4005 /* Ensure the modtime is set correctly on the destination file. */
4006 fsp2
->pending_modtime
= src_sbuf
.st_mtime
;
4009 * As we are opening fsp1 read-only we only expect
4010 * an error on close on fsp2 if we are out of space.
4011 * Thus we don't look at the error return from the
4014 *err_ret
= close_file(fsp2
,False
);
4016 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
4019 /****************************************************************************
4020 Reply to a file copy.
4021 ****************************************************************************/
4023 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4028 pstring mask
,newname
;
4031 int error
= ERRnoaccess
;
4035 int tid2
= SVAL(inbuf
,smb_vwv0
);
4036 int ofun
= SVAL(inbuf
,smb_vwv1
);
4037 int flags
= SVAL(inbuf
,smb_vwv2
);
4038 BOOL target_is_directory
=False
;
4039 BOOL bad_path1
= False
;
4040 BOOL bad_path2
= False
;
4042 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4045 START_PROFILE(SMBcopy
);
4047 *directory
= *mask
= 0;
4050 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
);
4051 if (!NT_STATUS_IS_OK(status
)) {
4052 END_PROFILE(SMBcopy
);
4053 return ERROR_NT(status
);
4055 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
);
4056 if (!NT_STATUS_IS_OK(status
)) {
4057 END_PROFILE(SMBcopy
);
4058 return ERROR_NT(status
);
4061 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
4063 if (tid2
!= conn
->cnum
) {
4064 /* can't currently handle inter share copies XXXX */
4065 DEBUG(3,("Rejecting inter-share copy\n"));
4066 END_PROFILE(SMBcopy
);
4067 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
4070 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
4071 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
4073 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
4074 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
4076 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
4078 if ((flags
&1) && target_is_directory
) {
4079 END_PROFILE(SMBcopy
);
4080 return ERROR_DOS(ERRDOS
,ERRbadfile
);
4083 if ((flags
&2) && !target_is_directory
) {
4084 END_PROFILE(SMBcopy
);
4085 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4088 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
4089 /* wants a tree copy! XXXX */
4090 DEBUG(3,("Rejecting tree copy\n"));
4091 END_PROFILE(SMBcopy
);
4092 return ERROR_DOS(ERRSRV
,ERRerror
);
4095 p
= strrchr_m(name
,'/');
4097 pstrcpy(directory
,"./");
4101 pstrcpy(directory
,name
);
4106 * We should only check the mangled cache
4107 * here if unix_convert failed. This means
4108 * that the path in 'mask' doesn't exist
4109 * on the file system and so we need to look
4110 * for a possible mangle. This patch from
4111 * Tine Smukavec <valentin.smukavec@hermes.si>.
4114 if (!rc
&& mangle_is_mangled(mask
))
4115 mangle_check_cache( mask
);
4117 has_wild
= ms_has_wild(mask
);
4120 pstrcat(directory
,"/");
4121 pstrcat(directory
,mask
);
4122 if (resolve_wildcards(directory
,newname
) &&
4123 copy_file(directory
,newname
,conn
,ofun
, count
,target_is_directory
,&err
))
4127 END_PROFILE(SMBcopy
);
4128 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4131 exists
= vfs_file_exist(conn
,directory
,NULL
);
4134 void *dirptr
= NULL
;
4138 if (check_name(directory
,conn
))
4139 dirptr
= OpenDir(conn
, directory
, True
);
4144 if (strequal(mask
,"????????.???"))
4147 while ((dname
= ReadDirName(dirptr
))) {
4149 pstrcpy(fname
,dname
);
4151 if(!mask_match(fname
, mask
, case_sensitive
))
4154 error
= ERRnoaccess
;
4155 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
4156 pstrcpy(destname
,newname
);
4157 if (resolve_wildcards(fname
,destname
) &&
4158 copy_file(fname
,destname
,conn
,ofun
,
4159 count
,target_is_directory
,&err
))
4161 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
4169 /* Error on close... */
4171 END_PROFILE(SMBcopy
);
4172 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4176 END_PROFILE(SMBcopy
);
4177 return ERROR_DOS(ERRDOS
,error
);
4179 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
)) {
4180 unix_ERR_class
= ERRDOS
;
4181 unix_ERR_code
= ERRbadpath
;
4183 END_PROFILE(SMBcopy
);
4184 return(UNIXERROR(ERRDOS
,error
));
4188 outsize
= set_message(outbuf
,1,0,True
);
4189 SSVAL(outbuf
,smb_vwv0
,count
);
4191 END_PROFILE(SMBcopy
);
4195 /****************************************************************************
4197 ****************************************************************************/
4199 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4207 START_PROFILE(pathworks_setdir
);
4210 if (!CAN_SETDIR(snum
)) {
4211 END_PROFILE(pathworks_setdir
);
4212 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4215 srvstr_get_path(inbuf
, newdir
, smb_buf(inbuf
) + 1, sizeof(newdir
), 0, STR_TERMINATE
, &status
);
4216 if (!NT_STATUS_IS_OK(status
)) {
4217 END_PROFILE(pathworks_setdir
);
4218 return ERROR_NT(status
);
4221 if (strlen(newdir
) == 0) {
4224 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
4226 string_set(&conn
->connectpath
,newdir
);
4230 END_PROFILE(pathworks_setdir
);
4231 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4234 outsize
= set_message(outbuf
,0,0,True
);
4235 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
4237 DEBUG(3,("setdir %s\n", newdir
));
4239 END_PROFILE(pathworks_setdir
);
4243 /****************************************************************************
4244 Get a lock pid, dealing with large count requests.
4245 ****************************************************************************/
4247 uint16
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
4249 if(!large_file_format
)
4250 return SVAL(data
,SMB_LPID_OFFSET(data_offset
));
4252 return SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
4255 /****************************************************************************
4256 Get a lock count, dealing with large count requests.
4257 ****************************************************************************/
4259 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
4261 SMB_BIG_UINT count
= 0;
4263 if(!large_file_format
) {
4264 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
4267 #if defined(HAVE_LONGLONG)
4268 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
4269 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
4270 #else /* HAVE_LONGLONG */
4273 * NT4.x seems to be broken in that it sends large file (64 bit)
4274 * lockingX calls even if the CAP_LARGE_FILES was *not*
4275 * negotiated. For boxes without large unsigned ints truncate the
4276 * lock count by dropping the top 32 bits.
4279 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
4280 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4281 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
4282 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
4283 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
4286 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
4287 #endif /* HAVE_LONGLONG */
4293 #if !defined(HAVE_LONGLONG)
4294 /****************************************************************************
4295 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4296 ****************************************************************************/
4298 static uint32
map_lock_offset(uint32 high
, uint32 low
)
4302 uint32 highcopy
= high
;
4305 * Try and find out how many significant bits there are in high.
4308 for(i
= 0; highcopy
; i
++)
4312 * We use 31 bits not 32 here as POSIX
4313 * lock offsets may not be negative.
4316 mask
= (~0) << (31 - i
);
4319 return 0; /* Fail. */
4325 #endif /* !defined(HAVE_LONGLONG) */
4327 /****************************************************************************
4328 Get a lock offset, dealing with large offset requests.
4329 ****************************************************************************/
4331 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
4333 SMB_BIG_UINT offset
= 0;
4337 if(!large_file_format
) {
4338 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
4341 #if defined(HAVE_LONGLONG)
4342 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
4343 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
4344 #else /* HAVE_LONGLONG */
4347 * NT4.x seems to be broken in that it sends large file (64 bit)
4348 * lockingX calls even if the CAP_LARGE_FILES was *not*
4349 * negotiated. For boxes without large unsigned ints mangle the
4350 * lock offset by mapping the top 32 bits onto the lower 32.
4353 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
4354 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4355 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
4358 if((new_low
= map_lock_offset(high
, low
)) == 0) {
4360 return (SMB_BIG_UINT
)-1;
4363 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4364 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
4365 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
4366 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
4369 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4370 #endif /* HAVE_LONGLONG */
4376 /****************************************************************************
4377 Reply to a lockingX request.
4378 ****************************************************************************/
4380 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4382 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
4383 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
4384 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
4385 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
4386 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
4387 SMB_BIG_UINT count
= 0, offset
= 0;
4389 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
4392 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
4394 BOOL my_lock_ctx
= False
;
4397 START_PROFILE(SMBlockingX
);
4399 CHECK_FSP(fsp
,conn
);
4401 data
= smb_buf(inbuf
);
4403 if (locktype
& (LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_CHANGE_LOCKTYPE
)) {
4404 /* we don't support these - and CANCEL_LOCK makes w2k
4405 and XP reboot so I don't really want to be
4406 compatible! (tridge) */
4407 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
4410 /* Check if this is an oplock break on a file
4411 we have granted an oplock on.
4413 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
4414 /* Client can insist on breaking to none. */
4415 BOOL break_to_none
= (oplocklevel
== 0);
4417 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4418 (unsigned int)oplocklevel
, fsp
->fnum
));
4421 * Make sure we have granted an exclusive or batch oplock on this file.
4424 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
4425 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4426 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
4428 /* if this is a pure oplock break request then don't send a reply */
4429 if (num_locks
== 0 && num_ulocks
== 0) {
4430 END_PROFILE(SMBlockingX
);
4433 END_PROFILE(SMBlockingX
);
4434 return ERROR_DOS(ERRDOS
,ERRlock
);
4438 if (remove_oplock(fsp
, break_to_none
) == False
) {
4439 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4443 /* if this is a pure oplock break request then don't send a reply */
4444 if (num_locks
== 0 && num_ulocks
== 0) {
4445 /* Sanity check - ensure a pure oplock break is not a
4447 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
4448 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4449 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
4450 END_PROFILE(SMBlockingX
);
4456 * We do this check *after* we have checked this is not a oplock break
4457 * response message. JRA.
4460 release_level_2_oplocks_on_change(fsp
);
4462 /* Data now points at the beginning of the list
4463 of smb_unlkrng structs */
4464 for(i
= 0; i
< (int)num_ulocks
; i
++) {
4465 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4466 count
= get_lock_count( data
, i
, large_file_format
);
4467 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4470 * There is no error code marked "stupid client bug".... :-).
4473 END_PROFILE(SMBlockingX
);
4474 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4477 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4478 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
4480 status
= do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4481 if (NT_STATUS_V(status
)) {
4482 END_PROFILE(SMBlockingX
);
4483 return ERROR_NT(status
);
4487 /* Setup the timeout in seconds. */
4489 lock_timeout
= ((lock_timeout
== -1) ? -1 : (lock_timeout
+999)/1000);
4491 /* Now do any requested locks */
4492 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
4494 /* Data now points at the beginning of the list
4495 of smb_lkrng structs */
4497 for(i
= 0; i
< (int)num_locks
; i
++) {
4498 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4499 count
= get_lock_count( data
, i
, large_file_format
);
4500 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4503 * There is no error code marked "stupid client bug".... :-).
4506 END_PROFILE(SMBlockingX
);
4507 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4510 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4511 (double)offset
, (double)count
, (unsigned int)lock_pid
,
4512 fsp
->fsp_name
, (int)lock_timeout
));
4514 status
= do_lock_spin(fsp
,conn
,lock_pid
, count
,offset
,
4515 ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
), &my_lock_ctx
);
4516 if (NT_STATUS_V(status
)) {
4518 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4519 * Even if it's our own lock context, we need to wait here as
4520 * there may be an unlock on the way.
4521 * So I removed a "&& !my_lock_ctx" from the following
4522 * if statement. JRA.
4524 if ((lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
4526 * A blocking lock was requested. Package up
4527 * this smb into a queued request and push it
4528 * onto the blocking lock queue.
4530 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
, lock_pid
, offset
, count
)) {
4531 END_PROFILE(SMBlockingX
);
4539 /* If any of the above locks failed, then we must unlock
4540 all of the previous locks (X/Open spec). */
4541 if (i
!= num_locks
&& num_locks
!= 0) {
4543 * Ensure we don't do a remove on the lock that just failed,
4544 * as under POSIX rules, if we have a lock already there, we
4545 * will delete it (and we shouldn't) .....
4547 for(i
--; i
>= 0; i
--) {
4548 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4549 count
= get_lock_count( data
, i
, large_file_format
);
4550 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4553 * There is no error code marked "stupid client bug".... :-).
4556 END_PROFILE(SMBlockingX
);
4557 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4560 do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4562 END_PROFILE(SMBlockingX
);
4563 return ERROR_NT(status
);
4566 set_message(outbuf
,2,0,True
);
4568 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4569 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4571 END_PROFILE(SMBlockingX
);
4572 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4575 /****************************************************************************
4576 Reply to a SMBreadbmpx (read block multiplex) request.
4577 ****************************************************************************/
4579 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4590 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4591 START_PROFILE(SMBreadBmpx
);
4593 /* this function doesn't seem to work - disable by default */
4594 if (!lp_readbmpx()) {
4595 END_PROFILE(SMBreadBmpx
);
4596 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
4599 outsize
= set_message(outbuf
,8,0,True
);
4601 CHECK_FSP(fsp
,conn
);
4604 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
4605 maxcount
= SVAL(inbuf
,smb_vwv3
);
4607 data
= smb_buf(outbuf
);
4608 pad
= ((long)data
)%4;
4613 max_per_packet
= bufsize
-(outsize
+pad
);
4617 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
4618 END_PROFILE(SMBreadBmpx
);
4619 return ERROR_DOS(ERRDOS
,ERRlock
);
4623 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4625 nread
= read_file(fsp
,data
,startpos
,N
);
4630 if (nread
< (ssize_t
)N
)
4631 tcount
= total_read
+ nread
;
4633 set_message(outbuf
,8,nread
,False
);
4634 SIVAL(outbuf
,smb_vwv0
,startpos
);
4635 SSVAL(outbuf
,smb_vwv2
,tcount
);
4636 SSVAL(outbuf
,smb_vwv6
,nread
);
4637 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4639 if (!send_smb(smbd_server_fd(),outbuf
))
4640 exit_server("reply_readbmpx: send_smb failed.");
4642 total_read
+= nread
;
4644 } while (total_read
< (ssize_t
)tcount
);
4646 END_PROFILE(SMBreadBmpx
);
4650 /****************************************************************************
4651 Reply to a SMBsetattrE.
4652 ****************************************************************************/
4654 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4656 struct utimbuf unix_times
;
4658 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4659 START_PROFILE(SMBsetattrE
);
4661 outsize
= set_message(outbuf
,0,0,True
);
4663 if(!fsp
|| (fsp
->conn
!= conn
)) {
4664 END_PROFILE(SMBgetattrE
);
4665 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4669 * Convert the DOS times into unix times. Ignore create
4670 * time as UNIX can't set this.
4673 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4674 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4677 * Patch from Ray Frush <frush@engr.colostate.edu>
4678 * Sometimes times are sent as zero - ignore them.
4681 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0)) {
4682 /* Ignore request */
4683 if( DEBUGLVL( 3 ) ) {
4684 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4685 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4687 END_PROFILE(SMBsetattrE
);
4689 } else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0)) {
4690 /* set modify time = to access time if modify time was 0 */
4691 unix_times
.modtime
= unix_times
.actime
;
4694 /* Set the date on this file */
4695 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4696 END_PROFILE(SMBsetattrE
);
4697 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4700 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4701 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4703 END_PROFILE(SMBsetattrE
);
4708 /* Back from the dead for OS/2..... JRA. */
4710 /****************************************************************************
4711 Reply to a SMBwritebmpx (write block multiplex primary) request.
4712 ****************************************************************************/
4714 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4717 ssize_t nwritten
= -1;
4724 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4725 START_PROFILE(SMBwriteBmpx
);
4727 CHECK_FSP(fsp
,conn
);
4731 tcount
= SVAL(inbuf
,smb_vwv1
);
4732 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
4733 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
4734 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4735 smb_doff
= SVAL(inbuf
,smb_vwv11
);
4737 data
= smb_base(inbuf
) + smb_doff
;
4739 /* If this fails we need to send an SMBwriteC response,
4740 not an SMBwritebmpx - set this up now so we don't forget */
4741 SCVAL(outbuf
,smb_com
,SMBwritec
);
4743 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
,False
)) {
4744 END_PROFILE(SMBwriteBmpx
);
4745 return(ERROR_DOS(ERRDOS
,ERRlock
));
4748 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4750 if(lp_syncalways(SNUM(conn
)) || write_through
)
4751 sync_file(conn
,fsp
);
4753 if(nwritten
< (ssize_t
)numtowrite
) {
4754 END_PROFILE(SMBwriteBmpx
);
4755 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
4758 /* If the maximum to be written to this file
4759 is greater than what we just wrote then set
4760 up a secondary struct to be attached to this
4761 fd, we will use this to cache error messages etc. */
4763 if((ssize_t
)tcount
> nwritten
) {
4764 write_bmpx_struct
*wbms
;
4765 if(fsp
->wbmpx_ptr
!= NULL
)
4766 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
4768 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
4770 DEBUG(0,("Out of memory in reply_readmpx\n"));
4771 END_PROFILE(SMBwriteBmpx
);
4772 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
4774 wbms
->wr_mode
= write_through
;
4775 wbms
->wr_discard
= False
; /* No errors yet */
4776 wbms
->wr_total_written
= nwritten
;
4777 wbms
->wr_errclass
= 0;
4779 fsp
->wbmpx_ptr
= wbms
;
4782 /* We are returning successfully, set the message type back to
4784 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
4786 outsize
= set_message(outbuf
,1,0,True
);
4788 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
4790 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4791 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
4793 if (write_through
&& tcount
==nwritten
) {
4794 /* We need to send both a primary and a secondary response */
4795 smb_setlen(outbuf
,outsize
- 4);
4796 if (!send_smb(smbd_server_fd(),outbuf
))
4797 exit_server("reply_writebmpx: send_smb failed.");
4799 /* Now the secondary */
4800 outsize
= set_message(outbuf
,1,0,True
);
4801 SCVAL(outbuf
,smb_com
,SMBwritec
);
4802 SSVAL(outbuf
,smb_vwv0
,nwritten
);
4805 END_PROFILE(SMBwriteBmpx
);
4809 /****************************************************************************
4810 Reply to a SMBwritebs (write block multiplex secondary) request.
4811 ****************************************************************************/
4813 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4816 ssize_t nwritten
= -1;
4823 write_bmpx_struct
*wbms
;
4824 BOOL send_response
= False
;
4825 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4826 START_PROFILE(SMBwriteBs
);
4828 CHECK_FSP(fsp
,conn
);
4831 tcount
= SVAL(inbuf
,smb_vwv1
);
4832 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
4833 numtowrite
= SVAL(inbuf
,smb_vwv6
);
4834 smb_doff
= SVAL(inbuf
,smb_vwv7
);
4836 data
= smb_base(inbuf
) + smb_doff
;
4838 /* We need to send an SMBwriteC response, not an SMBwritebs */
4839 SCVAL(outbuf
,smb_com
,SMBwritec
);
4841 /* This fd should have an auxiliary struct attached,
4842 check that it does */
4843 wbms
= fsp
->wbmpx_ptr
;
4845 END_PROFILE(SMBwriteBs
);
4849 /* If write through is set we can return errors, else we must cache them */
4850 write_through
= wbms
->wr_mode
;
4852 /* Check for an earlier error */
4853 if(wbms
->wr_discard
) {
4854 END_PROFILE(SMBwriteBs
);
4855 return -1; /* Just discard the packet */
4858 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4860 if(lp_syncalways(SNUM(conn
)) || write_through
)
4861 sync_file(conn
,fsp
);
4863 if (nwritten
< (ssize_t
)numtowrite
) {
4865 /* We are returning an error - we can delete the aux struct */
4868 fsp
->wbmpx_ptr
= NULL
;
4869 END_PROFILE(SMBwriteBs
);
4870 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
4872 END_PROFILE(SMBwriteBs
);
4873 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4876 /* Increment the total written, if this matches tcount
4877 we can discard the auxiliary struct (hurrah !) and return a writeC */
4878 wbms
->wr_total_written
+= nwritten
;
4879 if(wbms
->wr_total_written
>= tcount
) {
4880 if (write_through
) {
4881 outsize
= set_message(outbuf
,1,0,True
);
4882 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4883 send_response
= True
;
4887 fsp
->wbmpx_ptr
= NULL
;
4891 END_PROFILE(SMBwriteBs
);
4895 END_PROFILE(SMBwriteBs
);
4899 /****************************************************************************
4900 Reply to a SMBgetattrE.
4901 ****************************************************************************/
4903 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4905 SMB_STRUCT_STAT sbuf
;
4908 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4909 START_PROFILE(SMBgetattrE
);
4911 outsize
= set_message(outbuf
,11,0,True
);
4913 if(!fsp
|| (fsp
->conn
!= conn
)) {
4914 END_PROFILE(SMBgetattrE
);
4915 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4918 /* Do an fstat on this file */
4919 if(fsp_stat(fsp
, &sbuf
)) {
4920 END_PROFILE(SMBgetattrE
);
4921 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4924 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4927 * Convert the times into dos times. Set create
4928 * date to be last modify date as UNIX doesn't save
4932 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4933 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4934 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4937 SIVAL(outbuf
,smb_vwv6
,0);
4938 SIVAL(outbuf
,smb_vwv8
,0);
4940 uint32 allocation_size
= get_allocation_size(fsp
, &sbuf
);
4941 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4942 SIVAL(outbuf
,smb_vwv8
,allocation_size
);
4944 SSVAL(outbuf
,smb_vwv10
, mode
);
4946 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
4948 END_PROFILE(SMBgetattrE
);