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
;
116 switch(next_mb_char_size(s
)) {
127 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
128 return NT_STATUS_INVALID_PARAMETER
;
136 /****************************************************************************
137 Pull a string and check the path - provide for error return.
138 ****************************************************************************/
140 size_t srvstr_get_path(char *inbuf
, char *dest
, const char *src
, size_t dest_len
, size_t src_len
, int flags
, NTSTATUS
*err
)
143 char *tmppath_ptr
= tmppath
;
146 SMB_ASSERT(dest_len
== sizeof(pstring
));
150 ret
= srvstr_pull_buf( inbuf
, tmppath_ptr
, src
, dest_len
, flags
);
152 ret
= srvstr_pull( inbuf
, tmppath_ptr
, src
, dest_len
, src_len
, flags
);
154 *err
= check_path_syntax(dest
, tmppath
);
158 /****************************************************************************
159 Reply to a special message.
160 ****************************************************************************/
162 int reply_special(char *inbuf
,char *outbuf
)
165 int msg_type
= CVAL(inbuf
,0);
166 int msg_flags
= CVAL(inbuf
,1);
170 static BOOL already_got_session
= False
;
174 memset(outbuf
,'\0',smb_size
);
176 smb_setlen(outbuf
,0);
179 case 0x81: /* session request */
181 if (already_got_session
) {
182 exit_server("multiple session request not permitted");
185 SCVAL(outbuf
,0,0x82);
187 if (name_len(inbuf
+4) > 50 ||
188 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
189 DEBUG(0,("Invalid name length in session request\n"));
192 name_extract(inbuf
,4,name1
);
193 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
194 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
197 set_local_machine_name(name1
, True
);
198 set_remote_machine_name(name2
, True
);
200 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
201 get_local_machine_name(), get_remote_machine_name(),
204 if (name_type
== 'R') {
205 /* We are being asked for a pathworks session ---
207 SCVAL(outbuf
, 0,0x83);
211 /* only add the client's machine name to the list
212 of possibly valid usernames if we are operating
213 in share mode security */
214 if (lp_security() == SEC_SHARE
) {
215 add_session_user(get_remote_machine_name());
218 reload_services(True
);
221 claim_connection(NULL
,"",0,True
,FLAG_MSG_GENERAL
|FLAG_MSG_SMBD
);
223 already_got_session
= True
;
226 case 0x89: /* session keepalive request
227 (some old clients produce this?) */
228 SCVAL(outbuf
,0,SMBkeepalive
);
232 case 0x82: /* positive session response */
233 case 0x83: /* negative session response */
234 case 0x84: /* retarget session response */
235 DEBUG(0,("Unexpected session response\n"));
238 case SMBkeepalive
: /* session keepalive */
243 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
244 msg_type
, msg_flags
));
249 /****************************************************************************
251 ****************************************************************************/
253 int reply_tcon(connection_struct
*conn
,
254 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
261 uint16 vuid
= SVAL(inbuf
,smb_uid
);
265 DATA_BLOB password_blob
;
267 START_PROFILE(SMBtcon
);
269 *service_buf
= *password
= *dev
= 0;
271 p
= smb_buf(inbuf
)+1;
272 p
+= srvstr_pull_buf(inbuf
, service_buf
, p
, sizeof(service_buf
), STR_TERMINATE
) + 1;
273 pwlen
= srvstr_pull_buf(inbuf
, password
, p
, sizeof(password
), STR_TERMINATE
) + 1;
275 p
+= srvstr_pull_buf(inbuf
, dev
, p
, sizeof(dev
), STR_TERMINATE
) + 1;
277 p
= strrchr_m(service_buf
,'\\');
281 service
= service_buf
;
284 password_blob
= data_blob(password
, pwlen
+1);
286 conn
= make_connection(service
,password_blob
,dev
,vuid
,&nt_status
);
288 data_blob_clear_free(&password_blob
);
291 END_PROFILE(SMBtcon
);
292 return ERROR_NT(nt_status
);
295 outsize
= set_message(outbuf
,2,0,True
);
296 SSVAL(outbuf
,smb_vwv0
,max_recv
);
297 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
298 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
300 DEBUG(3,("tcon service=%s cnum=%d\n",
301 service
, conn
->cnum
));
303 END_PROFILE(SMBtcon
);
307 /****************************************************************************
308 Reply to a tcon and X.
309 ****************************************************************************/
311 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
316 /* what the cleint thinks the device is */
317 fstring client_devicetype
;
318 /* what the server tells the client the share represents */
319 const char *server_devicetype
;
321 uint16 vuid
= SVAL(inbuf
,smb_uid
);
322 int passlen
= SVAL(inbuf
,smb_vwv3
);
325 extern BOOL global_encrypted_passwords_negotiated
;
327 START_PROFILE(SMBtconX
);
329 *service
= *client_devicetype
= 0;
331 /* we might have to close an old one */
332 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
333 close_cnum(conn
,vuid
);
336 if (passlen
> MAX_PASS_LEN
) {
337 return ERROR_DOS(ERRDOS
,ERRbuftoosmall
);
340 if (global_encrypted_passwords_negotiated
) {
341 password
= data_blob(smb_buf(inbuf
),passlen
);
343 password
= data_blob(smb_buf(inbuf
),passlen
+1);
344 /* Ensure correct termination */
345 password
.data
[passlen
]=0;
348 p
= smb_buf(inbuf
) + passlen
;
349 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
352 * the service name can be either: \\server\share
353 * or share directly like on the DELL PowerVault 705
356 q
= strchr_m(path
+2,'\\');
358 END_PROFILE(SMBtconX
);
359 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
361 fstrcpy(service
,q
+1);
364 fstrcpy(service
,path
);
366 p
+= srvstr_pull(inbuf
, client_devicetype
, p
, sizeof(client_devicetype
), 6, STR_ASCII
);
368 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
370 conn
= make_connection(service
,password
,client_devicetype
,vuid
,&nt_status
);
372 data_blob_clear_free(&password
);
375 END_PROFILE(SMBtconX
);
376 return ERROR_NT(nt_status
);
380 server_devicetype
= "IPC";
381 else if ( IS_PRINT(conn
) )
382 server_devicetype
= "LPT1:";
384 server_devicetype
= "A:";
386 if (Protocol
< PROTOCOL_NT1
) {
387 set_message(outbuf
,2,0,True
);
389 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
390 STR_TERMINATE
|STR_ASCII
);
391 set_message_end(outbuf
,p
);
393 /* NT sets the fstype of IPC$ to the null string */
394 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
396 set_message(outbuf
,3,0,True
);
399 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
400 STR_TERMINATE
|STR_ASCII
);
401 p
+= srvstr_push(outbuf
, p
, fstype
, -1,
404 set_message_end(outbuf
,p
);
406 /* what does setting this bit do? It is set by NT4 and
407 may affect the ability to autorun mounted cdroms */
408 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
409 (lp_csc_policy(SNUM(conn
)) << 2));
411 init_dfsroot(conn
, inbuf
, outbuf
);
415 DEBUG(3,("tconX service=%s \n",
418 /* set the incoming and outgoing tid to the just created one */
419 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
420 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
422 END_PROFILE(SMBtconX
);
423 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
426 /****************************************************************************
427 Reply to an unknown type.
428 ****************************************************************************/
430 int reply_unknown(char *inbuf
,char *outbuf
)
433 type
= CVAL(inbuf
,smb_com
);
435 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
436 smb_fn_name(type
), type
, type
));
438 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
441 /****************************************************************************
443 ****************************************************************************/
445 int reply_ioctl(connection_struct
*conn
,
446 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
448 uint16 device
= SVAL(inbuf
,smb_vwv1
);
449 uint16 function
= SVAL(inbuf
,smb_vwv2
);
450 uint32 ioctl_code
= (device
<< 16) + function
;
451 int replysize
, outsize
;
453 START_PROFILE(SMBioctl
);
455 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
457 switch (ioctl_code
) {
458 case IOCTL_QUERY_JOB_INFO
:
462 END_PROFILE(SMBioctl
);
463 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
466 outsize
= set_message(outbuf
,8,replysize
+1,True
);
467 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
468 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
469 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
470 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
472 switch (ioctl_code
) {
473 case IOCTL_QUERY_JOB_INFO
:
475 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
477 END_PROFILE(SMBioctl
);
478 return(UNIXERROR(ERRDOS
,ERRbadfid
));
480 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
481 srvstr_push(outbuf
, p
+2, global_myname(), 15, STR_TERMINATE
|STR_ASCII
);
482 srvstr_push(outbuf
, p
+18, lp_servicename(SNUM(conn
)), 13, STR_TERMINATE
|STR_ASCII
);
487 END_PROFILE(SMBioctl
);
491 /****************************************************************************
493 ****************************************************************************/
495 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
501 BOOL bad_path
= False
;
502 SMB_STRUCT_STAT sbuf
;
505 START_PROFILE(SMBchkpth
);
507 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
);
508 if (!NT_STATUS_IS_OK(status
)) {
509 END_PROFILE(SMBchkpth
);
510 return ERROR_NT(status
);
513 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
515 unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
517 mode
= SVAL(inbuf
,smb_vwv0
);
519 if (check_name(name
,conn
)) {
520 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,name
,&sbuf
) == 0)
521 if (!(ok
= S_ISDIR(sbuf
.st_mode
))) {
522 END_PROFILE(SMBchkpth
);
523 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY
,ERRDOS
,ERRbadpath
);
528 /* We special case this - as when a Windows machine
529 is parsing a path is steps through the components
530 one at a time - if a component fails it expects
531 ERRbadpath, not ERRbadfile.
533 if(errno
== ENOENT
) {
535 * Windows returns different error codes if
536 * the parent directory is valid but not the
537 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
538 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
539 * if the path is invalid.
542 END_PROFILE(SMBchkpth
);
543 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
545 END_PROFILE(SMBchkpth
);
546 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND
);
548 } else if (errno
== ENOTDIR
) {
549 END_PROFILE(SMBchkpth
);
550 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY
);
553 END_PROFILE(SMBchkpth
);
554 return(UNIXERROR(ERRDOS
,ERRbadpath
));
557 outsize
= set_message(outbuf
,0,0,True
);
559 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
561 END_PROFILE(SMBchkpth
);
565 /****************************************************************************
567 ****************************************************************************/
569 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
573 SMB_STRUCT_STAT sbuf
;
578 BOOL bad_path
= False
;
582 START_PROFILE(SMBgetatr
);
584 p
= smb_buf(inbuf
) + 1;
585 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
586 if (!NT_STATUS_IS_OK(status
)) {
587 END_PROFILE(SMBgetatr
);
588 return ERROR_NT(status
);
591 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
593 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
594 under WfWg - weird! */
596 mode
= aHIDDEN
| aDIR
;
597 if (!CAN_WRITE(conn
))
603 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
604 if (check_name(fname
,conn
)) {
605 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,fname
,&sbuf
) == 0) {
606 mode
= dos_mode(conn
,fname
,&sbuf
);
608 mtime
= sbuf
.st_mtime
;
613 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
619 END_PROFILE(SMBgetatr
);
620 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadfile
);
623 outsize
= set_message(outbuf
,10,0,True
);
625 SSVAL(outbuf
,smb_vwv0
,mode
);
626 if(lp_dos_filetime_resolution(SNUM(conn
)) )
627 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
629 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
630 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
632 if (Protocol
>= PROTOCOL_NT1
)
633 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
635 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
637 END_PROFILE(SMBgetatr
);
641 /****************************************************************************
643 ****************************************************************************/
645 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
652 SMB_STRUCT_STAT sbuf
;
653 BOOL bad_path
= False
;
657 START_PROFILE(SMBsetatr
);
659 p
= smb_buf(inbuf
) + 1;
660 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
661 if (!NT_STATUS_IS_OK(status
)) {
662 END_PROFILE(SMBsetatr
);
663 return ERROR_NT(status
);
666 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
668 mode
= SVAL(inbuf
,smb_vwv0
);
669 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
671 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
672 if (VALID_STAT_OF_DIR(sbuf
))
677 if (check_name(fname
,conn
))
678 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
684 ok
= set_filetime(conn
,fname
,mtime
);
687 END_PROFILE(SMBsetatr
);
688 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
691 outsize
= set_message(outbuf
,0,0,True
);
693 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
695 END_PROFILE(SMBsetatr
);
699 /****************************************************************************
701 ****************************************************************************/
703 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
706 SMB_BIG_UINT dfree
,dsize
,bsize
;
707 START_PROFILE(SMBdskattr
);
709 SMB_VFS_DISK_FREE(conn
,".",True
,&bsize
,&dfree
,&dsize
);
711 outsize
= set_message(outbuf
,5,0,True
);
713 if (Protocol
<= PROTOCOL_LANMAN2
) {
714 double total_space
, free_space
;
715 /* we need to scale this to a number that DOS6 can handle. We
716 use floating point so we can handle large drives on systems
717 that don't have 64 bit integers
719 we end up displaying a maximum of 2G to DOS systems
721 total_space
= dsize
* (double)bsize
;
722 free_space
= dfree
* (double)bsize
;
724 dsize
= (total_space
+63*512) / (64*512);
725 dfree
= (free_space
+63*512) / (64*512);
727 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
728 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
730 SSVAL(outbuf
,smb_vwv0
,dsize
);
731 SSVAL(outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
732 SSVAL(outbuf
,smb_vwv2
,512); /* and this must be 512 */
733 SSVAL(outbuf
,smb_vwv3
,dfree
);
735 SSVAL(outbuf
,smb_vwv0
,dsize
);
736 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
737 SSVAL(outbuf
,smb_vwv2
,512);
738 SSVAL(outbuf
,smb_vwv3
,dfree
);
741 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
743 END_PROFILE(SMBdskattr
);
747 /****************************************************************************
749 Can be called from SMBsearch, SMBffirst or SMBfunique.
750 ****************************************************************************/
752 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
762 unsigned int numentries
= 0;
763 unsigned int maxentries
= 0;
764 BOOL finished
= False
;
771 BOOL check_descend
= False
;
772 BOOL expect_close
= False
;
773 BOOL can_open
= True
;
774 BOOL bad_path
= False
;
776 START_PROFILE(SMBsearch
);
778 *mask
= *directory
= *fname
= 0;
780 /* If we were called as SMBffirst then we must expect close. */
781 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
784 outsize
= set_message(outbuf
,1,3,True
);
785 maxentries
= SVAL(inbuf
,smb_vwv0
);
786 dirtype
= SVAL(inbuf
,smb_vwv1
);
787 p
= smb_buf(inbuf
) + 1;
788 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &nt_status
);
789 if (!NT_STATUS_IS_OK(nt_status
)) {
790 END_PROFILE(SMBsearch
);
791 return ERROR_NT(nt_status
);
794 status_len
= SVAL(p
, 0);
797 /* dirtype &= ~aDIR; */
799 if (status_len
== 0) {
800 SMB_STRUCT_STAT sbuf
;
803 pstrcpy(directory
,path
);
805 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
808 if (!check_name(directory
,conn
))
811 p
= strrchr_m(dir2
,'/');
820 p
= strrchr_m(directory
,'/');
826 if (strlen(directory
) == 0)
827 pstrcpy(directory
,".");
828 memset((char *)status
,'\0',21);
829 SCVAL(status
,0,(dirtype
& 0x1F));
834 status_dirtype
= CVAL(status
,0) & 0x1F;
835 if (status_dirtype
!= (dirtype
& 0x1F))
836 dirtype
= status_dirtype
;
838 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
841 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
842 pstrcpy(mask
, dptr_wcard(dptr_num
));
846 p
= smb_buf(outbuf
) + 3;
849 if (status_len
== 0) {
850 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
853 END_PROFILE(SMBsearch
);
854 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnofids
);
856 END_PROFILE(SMBsearch
);
857 return ERROR_DOS(ERRDOS
,ERRnofids
);
859 dptr_set_wcard(dptr_num
, strdup(mask
));
860 dptr_set_attr(dptr_num
, dirtype
);
862 dirtype
= dptr_attr(dptr_num
);
865 DEBUG(4,("dptr_num is %d\n",dptr_num
));
868 if ((dirtype
&0x1F) == aVOLID
) {
870 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
871 dptr_fill(p
+12,dptr_num
);
872 if (dptr_zero(p
+12) && (status_len
==0))
876 p
+= DIR_STRUCT_SIZE
;
879 maxentries
= MIN(maxentries
, ((BUFFER_SIZE
- (p
- outbuf
))/DIR_STRUCT_SIZE
));
881 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
882 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
883 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
884 check_descend
= True
;
886 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
887 finished
= !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
890 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
891 dptr_fill(p
+12,dptr_num
);
894 p
+= DIR_STRUCT_SIZE
;
903 /* If we were called as SMBffirst with smb_search_id == NULL
904 and no entries were found then return error and close dirptr
907 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0) {
908 if (Protocol
< PROTOCOL_NT1
) {
909 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
910 SSVAL(outbuf
,smb_err
,ERRnofiles
);
912 /* Also close the dptr - we know it's gone */
913 dptr_close(&dptr_num
);
914 } else if (numentries
== 0 || !ok
) {
915 if (Protocol
< PROTOCOL_NT1
) {
916 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
917 SSVAL(outbuf
,smb_err
,ERRnofiles
);
919 dptr_close(&dptr_num
);
922 /* If we were called as SMBfunique, then we can close the dirptr now ! */
923 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
924 dptr_close(&dptr_num
);
926 SSVAL(outbuf
,smb_vwv0
,numentries
);
927 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
928 SCVAL(smb_buf(outbuf
),0,5);
929 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
931 if (Protocol
>= PROTOCOL_NT1
)
932 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
934 outsize
+= DIR_STRUCT_SIZE
*numentries
;
935 smb_setlen(outbuf
,outsize
- 4);
937 if ((! *directory
) && dptr_path(dptr_num
))
938 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
940 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
941 smb_fn_name(CVAL(inbuf
,smb_com
)),
942 mask
, directory
, dirtype
, numentries
, maxentries
) );
944 END_PROFILE(SMBsearch
);
948 /****************************************************************************
949 Reply to a fclose (stop directory search).
950 ****************************************************************************/
952 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
962 START_PROFILE(SMBfclose
);
964 outsize
= set_message(outbuf
,1,0,True
);
965 p
= smb_buf(inbuf
) + 1;
966 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &err
);
967 if (!NT_STATUS_IS_OK(err
)) {
968 END_PROFILE(SMBfclose
);
969 return ERROR_NT(err
);
972 status_len
= SVAL(p
,0);
975 if (status_len
== 0) {
976 END_PROFILE(SMBfclose
);
977 return ERROR_DOS(ERRSRV
,ERRsrverror
);
982 if(dptr_fetch(status
+12,&dptr_num
)) {
983 /* Close the dptr - we know it's gone */
984 dptr_close(&dptr_num
);
987 SSVAL(outbuf
,smb_vwv0
,0);
989 DEBUG(3,("search close\n"));
991 END_PROFILE(SMBfclose
);
995 /****************************************************************************
997 ****************************************************************************/
999 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1009 SMB_STRUCT_STAT sbuf
;
1010 BOOL bad_path
= False
;
1012 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1014 START_PROFILE(SMBopen
);
1016 share_mode
= SVAL(inbuf
,smb_vwv0
);
1018 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1019 if (!NT_STATUS_IS_OK(status
)) {
1020 END_PROFILE(SMBopen
);
1021 return ERROR_NT(status
);
1024 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1026 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1028 unixmode
= unix_mode(conn
,aARCH
,fname
);
1030 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1031 unixmode
, oplock_request
,&rmode
,NULL
);
1034 END_PROFILE(SMBopen
);
1035 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1038 size
= sbuf
.st_size
;
1039 fmode
= dos_mode(conn
,fname
,&sbuf
);
1040 mtime
= sbuf
.st_mtime
;
1043 DEBUG(3,("attempt to open a directory %s\n",fname
));
1044 close_file(fsp
,False
);
1045 END_PROFILE(SMBopen
);
1046 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1049 outsize
= set_message(outbuf
,7,0,True
);
1050 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1051 SSVAL(outbuf
,smb_vwv1
,fmode
);
1052 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1053 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1055 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1056 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1057 SSVAL(outbuf
,smb_vwv6
,rmode
);
1059 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1060 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1062 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1063 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1064 END_PROFILE(SMBopen
);
1068 /****************************************************************************
1069 Reply to an open and X.
1070 ****************************************************************************/
1072 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1075 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1076 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1077 /* Breakout the oplock request bits so we can set the
1078 reply bits separately. */
1079 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1080 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1081 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1083 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1084 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1085 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1087 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1090 int fmode
=0,mtime
=0,rmode
=0;
1091 SMB_STRUCT_STAT sbuf
;
1093 BOOL bad_path
= False
;
1096 START_PROFILE(SMBopenX
);
1098 /* If it's an IPC, pass off the pipe handler. */
1100 if (lp_nt_pipe_support()) {
1101 END_PROFILE(SMBopenX
);
1102 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1104 END_PROFILE(SMBopenX
);
1105 return ERROR_DOS(ERRSRV
,ERRaccess
);
1109 /* XXXX we need to handle passed times, sattr and flags */
1110 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
), sizeof(fname
), 0, STR_TERMINATE
, &status
);
1111 if (!NT_STATUS_IS_OK(status
)) {
1112 END_PROFILE(SMBopenX
);
1113 return ERROR_NT(status
);
1116 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1118 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1120 unixmode
= unix_mode(conn
,smb_attr
| aARCH
, fname
);
1122 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,unixmode
,
1123 oplock_request
, &rmode
,&smb_action
);
1126 END_PROFILE(SMBopenX
);
1127 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1130 size
= sbuf
.st_size
;
1131 fmode
= dos_mode(conn
,fname
,&sbuf
);
1132 mtime
= sbuf
.st_mtime
;
1134 close_file(fsp
,False
);
1135 END_PROFILE(SMBopenX
);
1136 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1139 /* If the caller set the extended oplock request bit
1140 and we granted one (by whatever means) - set the
1141 correct bit for extended oplock reply.
1144 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1145 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1147 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1148 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1150 /* If the caller set the core oplock request bit
1151 and we granted one (by whatever means) - set the
1152 correct bit for core oplock reply.
1155 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1156 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1158 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1159 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1161 set_message(outbuf
,15,0,True
);
1162 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1163 SSVAL(outbuf
,smb_vwv3
,fmode
);
1164 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1165 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1167 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1168 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1169 SSVAL(outbuf
,smb_vwv8
,rmode
);
1170 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1172 END_PROFILE(SMBopenX
);
1173 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1176 /****************************************************************************
1177 Reply to a SMBulogoffX.
1178 ****************************************************************************/
1180 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1182 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1183 user_struct
*vuser
= get_valid_user_struct(vuid
);
1184 START_PROFILE(SMBulogoffX
);
1187 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1189 /* in user level security we are supposed to close any files
1190 open by this user */
1191 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
))
1192 file_close_user(vuid
);
1194 invalidate_vuid(vuid
);
1196 set_message(outbuf
,2,0,True
);
1198 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1200 END_PROFILE(SMBulogoffX
);
1201 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1204 /****************************************************************************
1205 Reply to a mknew or a create.
1206 ****************************************************************************/
1208 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1216 BOOL bad_path
= False
;
1218 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1219 SMB_STRUCT_STAT sbuf
;
1221 START_PROFILE(SMBcreate
);
1223 com
= SVAL(inbuf
,smb_com
);
1225 createmode
= SVAL(inbuf
,smb_vwv0
);
1226 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
) + 1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1227 if (!NT_STATUS_IS_OK(status
)) {
1228 END_PROFILE(SMBcreate
);
1229 return ERROR_NT(status
);
1232 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1234 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1236 if (createmode
& aVOLID
)
1237 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1239 unixmode
= unix_mode(conn
,createmode
,fname
);
1241 if(com
== SMBmknew
) {
1242 /* We should fail if file exists. */
1243 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1245 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1246 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1249 /* Open file in dos compatibility share mode. */
1250 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1251 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1254 END_PROFILE(SMBcreate
);
1255 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1258 outsize
= set_message(outbuf
,1,0,True
);
1259 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1261 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1262 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1264 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1265 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1267 DEBUG( 2, ( "new file %s\n", fname
) );
1268 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1270 END_PROFILE(SMBcreate
);
1274 /****************************************************************************
1275 Reply to a create temporary file.
1276 ****************************************************************************/
1278 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1284 BOOL bad_path
= False
;
1286 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1288 SMB_STRUCT_STAT sbuf
;
1292 START_PROFILE(SMBctemp
);
1294 createmode
= SVAL(inbuf
,smb_vwv0
);
1295 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1296 if (!NT_STATUS_IS_OK(status
)) {
1297 END_PROFILE(SMBctemp
);
1298 return ERROR_NT(status
);
1300 pstrcat(fname
,"\\TMXXXXXX");
1302 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1304 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1306 unixmode
= unix_mode(conn
,createmode
,fname
);
1308 tmpfd
= smb_mkstemp(fname
);
1310 END_PROFILE(SMBctemp
);
1311 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1314 SMB_VFS_STAT(conn
,fname
,&sbuf
);
1316 /* Open file in dos compatibility share mode. */
1317 /* We should fail if file does not exist. */
1318 fsp
= open_file_shared(conn
,fname
,&sbuf
,
1319 SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1320 FILE_EXISTS_OPEN
|FILE_FAIL_IF_NOT_EXIST
,
1321 unixmode
, oplock_request
, NULL
, NULL
);
1323 /* close fd from smb_mkstemp() */
1327 END_PROFILE(SMBctemp
);
1328 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1331 outsize
= set_message(outbuf
,1,0,True
);
1332 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1334 /* the returned filename is relative to the directory */
1335 s
= strrchr_m(fname
, '/');
1341 p
= smb_buf(outbuf
);
1342 SSVALS(p
, 0, -1); /* what is this? not in spec */
1343 SSVAL(p
, 2, strlen(s
));
1345 p
+= srvstr_push(outbuf
, p
, s
, -1, STR_ASCII
);
1346 outsize
= set_message_end(outbuf
, p
);
1348 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1349 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1351 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1352 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1354 DEBUG( 2, ( "created temp file %s\n", fname
) );
1355 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1356 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1358 END_PROFILE(SMBctemp
);
1362 /*******************************************************************
1363 Check if a user is allowed to rename a file.
1364 ********************************************************************/
1366 static NTSTATUS
can_rename(char *fname
,connection_struct
*conn
, SMB_STRUCT_STAT
*pst
)
1372 if (!CAN_WRITE(conn
))
1373 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1375 if (S_ISDIR(pst
->st_mode
))
1376 return NT_STATUS_OK
;
1378 /* We need a better way to return NT status codes from open... */
1382 fsp
= open_file_shared1(conn
, fname
, pst
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1383 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1386 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1387 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1388 ret
= NT_STATUS_SHARING_VIOLATION
;
1391 unix_ERR_ntstatus
= NT_STATUS_OK
;
1394 close_file(fsp
,False
);
1395 return NT_STATUS_OK
;
1398 /*******************************************************************
1399 Check if a user is allowed to delete a file.
1400 ********************************************************************/
1402 static NTSTATUS
can_delete(char *fname
,connection_struct
*conn
, int dirtype
, BOOL bad_path
)
1404 SMB_STRUCT_STAT sbuf
;
1410 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1413 if (!CAN_WRITE(conn
))
1414 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1416 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
) != 0) {
1417 if(errno
== ENOENT
) {
1419 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1421 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1423 return map_nt_error_from_unix(errno
);
1426 fmode
= dos_mode(conn
,fname
,&sbuf
);
1428 /* Can't delete a directory. */
1430 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1432 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
1433 return NT_STATUS_OBJECT_NAME_INVALID
;
1434 #endif /* JRATEST */
1436 if (!lp_delete_readonly(SNUM(conn
))) {
1438 return NT_STATUS_CANNOT_DELETE
;
1440 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1441 return NT_STATUS_NO_SUCH_FILE
;
1443 /* We need a better way to return NT status codes from open... */
1447 fsp
= open_file_shared1(conn
, fname
, &sbuf
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1448 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1451 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1452 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus
))
1453 ret
= unix_ERR_ntstatus
;
1454 else if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1455 ret
= NT_STATUS_SHARING_VIOLATION
;
1458 unix_ERR_ntstatus
= NT_STATUS_OK
;
1461 close_file(fsp
,False
);
1462 return NT_STATUS_OK
;
1465 /****************************************************************************
1466 The guts of the unlink command, split out so it may be called by the NT SMB
1468 ****************************************************************************/
1470 NTSTATUS
unlink_internals(connection_struct
*conn
, int dirtype
, char *name
)
1476 NTSTATUS error
= NT_STATUS_OK
;
1478 BOOL bad_path
= False
;
1480 SMB_STRUCT_STAT sbuf
;
1482 *directory
= *mask
= 0;
1484 /* We must check for wildcards in the name given
1485 * directly by the client - before any unmangling.
1486 * This prevents an unmangling of a UNIX name containing
1487 * a DOS wildcard like '*' or '?' from unmangling into
1488 * a wildcard delete which was not intended.
1489 * FIX for #226. JRA.
1492 has_wild
= ms_has_wild(name
);
1494 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1496 p
= strrchr_m(name
,'/');
1498 pstrcpy(directory
,".");
1502 pstrcpy(directory
,name
);
1507 * We should only check the mangled cache
1508 * here if unix_convert failed. This means
1509 * that the path in 'mask' doesn't exist
1510 * on the file system and so we need to look
1511 * for a possible mangle. This patch from
1512 * Tine Smukavec <valentin.smukavec@hermes.si>.
1515 if (!rc
&& mangle_is_mangled(mask
))
1516 mangle_check_cache( mask
);
1519 pstrcat(directory
,"/");
1520 pstrcat(directory
,mask
);
1521 error
= can_delete(directory
,conn
,dirtype
,bad_path
);
1522 if (!NT_STATUS_IS_OK(error
))
1525 if (SMB_VFS_UNLINK(conn
,directory
) == 0) {
1529 void *dirptr
= NULL
;
1532 if (check_name(directory
,conn
))
1533 dirptr
= OpenDir(conn
, directory
, True
);
1535 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1536 the pattern matches against the long name, otherwise the short name
1537 We don't implement this yet XXXX
1541 error
= NT_STATUS_NO_SUCH_FILE
;
1543 if (strequal(mask
,"????????.???"))
1546 while ((dname
= ReadDirName(dirptr
))) {
1548 BOOL sys_direntry
= False
;
1549 pstrcpy(fname
,dname
);
1551 /* Quick check for "." and ".." */
1552 if (fname
[0] == '.') {
1553 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
1554 if ((dirtype
& aDIR
)) {
1555 sys_direntry
= True
;
1562 if(!mask_match(fname
, mask
, case_sensitive
))
1566 error
= NT_STATUS_OBJECT_NAME_INVALID
;
1570 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1571 error
= can_delete(fname
,conn
,dirtype
,bad_path
);
1572 if (!NT_STATUS_IS_OK(error
))
1574 if (SMB_VFS_UNLINK(conn
,fname
) == 0)
1576 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
1582 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
1583 error
= map_nt_error_from_unix(errno
);
1589 /****************************************************************************
1591 ****************************************************************************/
1593 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
1600 START_PROFILE(SMBunlink
);
1602 dirtype
= SVAL(inbuf
,smb_vwv0
);
1604 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
);
1605 if (!NT_STATUS_IS_OK(status
)) {
1606 END_PROFILE(SMBunlink
);
1607 return ERROR_NT(status
);
1610 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
1612 DEBUG(3,("reply_unlink : %s\n",name
));
1614 status
= unlink_internals(conn
, dirtype
, name
);
1615 if (!NT_STATUS_IS_OK(status
))
1616 return ERROR_NT(status
);
1619 * Win2k needs a changenotify request response before it will
1620 * update after a rename..
1622 process_pending_change_notify_queue((time_t)0);
1624 outsize
= set_message(outbuf
,0,0,True
);
1626 END_PROFILE(SMBunlink
);
1630 /****************************************************************************
1632 ****************************************************************************/
1634 void fail_readraw(void)
1637 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1639 exit_server(errstr
);
1642 /****************************************************************************
1643 Use sendfile in readbraw.
1644 ****************************************************************************/
1646 void send_file_readbraw(connection_struct
*conn
, files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
,
1647 ssize_t mincount
, char *outbuf
)
1651 #if defined(WITH_SENDFILE)
1653 * We can only use sendfile on a non-chained packet and on a file
1654 * that is exclusively oplocked. reply_readbraw has already checked the length.
1657 if ((nread
> 0) && (lp_write_cache_size(SNUM(conn
)) == 0) &&
1658 EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) && lp_use_sendfile(SNUM(conn
)) ) {
1661 _smb_setlen(outbuf
,nread
);
1662 header
.data
= outbuf
;
1666 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, nread
) == -1) {
1668 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1669 * return ENOSYS then pretend we just got a normal read.
1671 if (errno
== ENOSYS
)
1674 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1675 fsp
->fsp_name
, strerror(errno
) ));
1676 exit_server("send_file_readbraw sendfile failed");
1685 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
1686 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1695 _smb_setlen(outbuf
,ret
);
1696 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
1700 /****************************************************************************
1701 Reply to a readbraw (core+ protocol).
1702 ****************************************************************************/
1704 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1706 extern struct current_user current_user
;
1707 ssize_t maxcount
,mincount
;
1710 char *header
= outbuf
;
1712 START_PROFILE(SMBreadbraw
);
1714 if (srv_is_signing_active()) {
1715 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1719 * Special check if an oplock break has been issued
1720 * and the readraw request croses on the wire, we must
1721 * return a zero length response here.
1724 if(global_oplock_break
) {
1725 _smb_setlen(header
,0);
1726 if (write_data(smbd_server_fd(),header
,4) != 4)
1728 DEBUG(5,("readbraw - oplock break finished\n"));
1729 END_PROFILE(SMBreadbraw
);
1733 fsp
= file_fsp(inbuf
,smb_vwv0
);
1735 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1737 * fsp could be NULL here so use the value from the packet. JRA.
1739 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
1740 _smb_setlen(header
,0);
1741 if (write_data(smbd_server_fd(),header
,4) != 4)
1743 END_PROFILE(SMBreadbraw
);
1747 CHECK_FSP(fsp
,conn
);
1749 flush_write_cache(fsp
, READRAW_FLUSH
);
1751 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
1752 if(CVAL(inbuf
,smb_wct
) == 10) {
1754 * This is a large offset (64 bit) read.
1756 #ifdef LARGE_SMB_OFF_T
1758 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
1760 #else /* !LARGE_SMB_OFF_T */
1763 * Ensure we haven't been sent a >32 bit offset.
1766 if(IVAL(inbuf
,smb_vwv8
) != 0) {
1767 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1768 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
1769 _smb_setlen(header
,0);
1770 if (write_data(smbd_server_fd(),header
,4) != 4)
1772 END_PROFILE(SMBreadbraw
);
1776 #endif /* LARGE_SMB_OFF_T */
1779 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
1780 _smb_setlen(header
,0);
1781 if (write_data(smbd_server_fd(),header
,4) != 4)
1783 END_PROFILE(SMBreadbraw
);
1787 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
1788 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
1790 /* ensure we don't overrun the packet size */
1791 maxcount
= MIN(65535,maxcount
);
1793 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1794 SMB_OFF_T size
= fsp
->size
;
1795 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
1797 if (size
< sizeneeded
) {
1799 if (SMB_VFS_FSTAT(fsp
,fsp
->fd
,&st
) == 0)
1801 if (!fsp
->can_write
)
1805 if (startpos
>= size
)
1808 nread
= MIN(maxcount
,(size
- startpos
));
1811 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1812 if (nread
< mincount
)
1816 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp
->fnum
, (double)startpos
,
1817 (int)maxcount
, (int)mincount
, (int)nread
) );
1819 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
, outbuf
);
1821 DEBUG(5,("readbraw finished\n"));
1822 END_PROFILE(SMBreadbraw
);
1826 /****************************************************************************
1827 Reply to a lockread (core+ protocol).
1828 ****************************************************************************/
1830 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
1838 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1839 BOOL my_lock_ctx
= False
;
1840 START_PROFILE(SMBlockread
);
1842 CHECK_FSP(fsp
,conn
);
1845 release_level_2_oplocks_on_change(fsp
);
1847 numtoread
= SVAL(inbuf
,smb_vwv1
);
1848 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1850 outsize
= set_message(outbuf
,5,3,True
);
1851 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1852 data
= smb_buf(outbuf
) + 3;
1855 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1856 * protocol request that predates the read/write lock concept.
1857 * Thus instead of asking for a read lock here we need to ask
1858 * for a write lock. JRA.
1859 * Note that the requested lock size is unaffected by max_recv.
1862 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
),
1863 (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
, &my_lock_ctx
);
1865 if (NT_STATUS_V(status
)) {
1868 * We used to make lockread a blocking lock. It turns out
1869 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1873 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
1875 * A blocking lock was requested. Package up
1876 * this smb into a queued request and push it
1877 * onto the blocking lock queue.
1879 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)startpos
,
1880 (SMB_BIG_UINT
)numtoread
)) {
1881 END_PROFILE(SMBlockread
);
1886 END_PROFILE(SMBlockread
);
1887 return ERROR_NT(status
);
1891 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1894 if (numtoread
> max_recv
) {
1895 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1896 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1897 (unsigned int)numtoread
, (unsigned int)max_recv
));
1898 numtoread
= MIN(numtoread
,max_recv
);
1900 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1903 END_PROFILE(SMBlockread
);
1904 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1908 SSVAL(outbuf
,smb_vwv0
,nread
);
1909 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1910 SSVAL(smb_buf(outbuf
),1,nread
);
1912 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1913 fsp
->fnum
, (int)numtoread
, (int)nread
));
1915 END_PROFILE(SMBlockread
);
1919 /****************************************************************************
1921 ****************************************************************************/
1923 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
1930 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1931 START_PROFILE(SMBread
);
1933 CHECK_FSP(fsp
,conn
);
1936 numtoread
= SVAL(inbuf
,smb_vwv1
);
1937 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1939 outsize
= set_message(outbuf
,5,3,True
);
1940 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1942 * The requested read size cannot be greater than max_recv. JRA.
1944 if (numtoread
> max_recv
) {
1945 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1946 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1947 (unsigned int)numtoread
, (unsigned int)max_recv
));
1948 numtoread
= MIN(numtoread
,max_recv
);
1951 data
= smb_buf(outbuf
) + 3;
1953 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1954 END_PROFILE(SMBread
);
1955 return ERROR_DOS(ERRDOS
,ERRlock
);
1959 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1962 END_PROFILE(SMBread
);
1963 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1967 SSVAL(outbuf
,smb_vwv0
,nread
);
1968 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1969 SCVAL(smb_buf(outbuf
),0,1);
1970 SSVAL(smb_buf(outbuf
),1,nread
);
1972 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1973 fsp
->fnum
, (int)numtoread
, (int)nread
) );
1975 END_PROFILE(SMBread
);
1979 /****************************************************************************
1980 Reply to a read and X - possibly using sendfile.
1981 ****************************************************************************/
1983 int send_file_readX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,
1984 files_struct
*fsp
, SMB_OFF_T startpos
, size_t smb_maxcnt
)
1987 char *data
= smb_buf(outbuf
);
1989 #if defined(WITH_SENDFILE)
1991 * We can only use sendfile on a non-chained packet and on a file
1992 * that is exclusively oplocked.
1995 if ((CVAL(inbuf
,smb_vwv0
) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) &&
1996 lp_use_sendfile(SNUM(conn
)) && (lp_write_cache_size(SNUM(conn
)) == 0) ) {
1997 SMB_STRUCT_STAT sbuf
;
2000 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1)
2001 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2003 if (startpos
> sbuf
.st_size
)
2006 if (smb_maxcnt
> (sbuf
.st_size
- startpos
))
2007 smb_maxcnt
= (sbuf
.st_size
- startpos
);
2009 if (smb_maxcnt
== 0)
2013 * Set up the packet header before send. We
2014 * assume here the sendfile will work (get the
2015 * correct amount of data).
2018 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2019 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
2020 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2021 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
2022 SCVAL(outbuf
,smb_vwv0
,0xFF);
2023 set_message(outbuf
,12,smb_maxcnt
,False
);
2024 header
.data
= outbuf
;
2025 header
.length
= data
- outbuf
;
2028 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, smb_maxcnt
) == -1) {
2030 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2031 * return ENOSYS then pretend we just got a normal read.
2033 if (errno
== ENOSYS
)
2036 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2037 fsp
->fsp_name
, strerror(errno
) ));
2038 exit_server("send_file_readX sendfile failed");
2041 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2042 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2050 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2053 END_PROFILE(SMBreadX
);
2054 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2057 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2058 SSVAL(outbuf
,smb_vwv5
,nread
);
2059 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2060 SSVAL(smb_buf(outbuf
),-2,nread
);
2062 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2063 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2068 /****************************************************************************
2069 Reply to a read and X.
2070 ****************************************************************************/
2072 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2074 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2075 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2077 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2079 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2082 START_PROFILE(SMBreadX
);
2084 /* If it's an IPC, pass off the pipe handler. */
2086 END_PROFILE(SMBreadX
);
2087 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2090 CHECK_FSP(fsp
,conn
);
2093 set_message(outbuf
,12,0,True
);
2095 if(CVAL(inbuf
,smb_wct
) == 12) {
2096 #ifdef LARGE_SMB_OFF_T
2098 * This is a large offset (64 bit) read.
2100 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2102 #else /* !LARGE_SMB_OFF_T */
2105 * Ensure we haven't been sent a >32 bit offset.
2108 if(IVAL(inbuf
,smb_vwv10
) != 0) {
2109 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2110 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
2111 END_PROFILE(SMBreadX
);
2112 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2115 #endif /* LARGE_SMB_OFF_T */
2119 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2120 END_PROFILE(SMBreadX
);
2121 return ERROR_DOS(ERRDOS
,ERRlock
);
2124 nread
= send_file_readX(conn
, inbuf
, outbuf
, length
, fsp
, startpos
, smb_maxcnt
);
2126 nread
= chain_reply(inbuf
,outbuf
,length
,bufsize
);
2128 END_PROFILE(SMBreadX
);
2132 /****************************************************************************
2133 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2134 ****************************************************************************/
2136 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2139 ssize_t total_written
=0;
2140 size_t numtowrite
=0;
2145 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2147 START_PROFILE(SMBwritebraw
);
2149 if (srv_is_signing_active()) {
2150 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2153 CHECK_FSP(fsp
,conn
);
2156 tcount
= IVAL(inbuf
,smb_vwv1
);
2157 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2158 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2160 /* We have to deal with slightly different formats depending
2161 on whether we are using the core+ or lanman1.0 protocol */
2163 if(Protocol
<= PROTOCOL_COREPLUS
) {
2164 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2165 data
= smb_buf(inbuf
);
2167 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2168 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2171 /* force the error type */
2172 SCVAL(inbuf
,smb_com
,SMBwritec
);
2173 SCVAL(outbuf
,smb_com
,SMBwritec
);
2175 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2176 END_PROFILE(SMBwritebraw
);
2177 return(ERROR_DOS(ERRDOS
,ERRlock
));
2181 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2183 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2184 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2186 if (nwritten
< (ssize_t
)numtowrite
) {
2187 END_PROFILE(SMBwritebraw
);
2188 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2191 total_written
= nwritten
;
2193 /* Return a message to the redirector to tell it to send more bytes */
2194 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
2195 SSVALS(outbuf
,smb_vwv0
,-1);
2196 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2197 if (!send_smb(smbd_server_fd(),outbuf
))
2198 exit_server("reply_writebraw: send_smb failed.");
2200 /* Now read the raw data into the buffer and write it */
2201 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2202 exit_server("secondary writebraw failed");
2205 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2206 numtowrite
= smb_len(inbuf
);
2208 /* Set up outbuf to return the correct return */
2209 outsize
= set_message(outbuf
,1,0,True
);
2210 SCVAL(outbuf
,smb_com
,SMBwritec
);
2211 SSVAL(outbuf
,smb_vwv0
,total_written
);
2213 if (numtowrite
!= 0) {
2215 if (numtowrite
> BUFFER_SIZE
) {
2216 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2217 (unsigned int)numtowrite
));
2218 exit_server("secondary writebraw failed");
2221 if (tcount
> nwritten
+numtowrite
) {
2222 DEBUG(3,("Client overestimated the write %d %d %d\n",
2223 (int)tcount
,(int)nwritten
,(int)numtowrite
));
2226 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
2227 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2229 exit_server("secondary writebraw failed");
2232 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
2234 if (nwritten
< (ssize_t
)numtowrite
) {
2235 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2236 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2240 total_written
+= nwritten
;
2243 if ((lp_syncalways(SNUM(conn
)) || write_through
) && lp_strict_sync(SNUM(conn
)))
2244 sync_file(conn
,fsp
);
2246 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2247 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
2249 /* we won't return a status if write through is not selected - this follows what WfWg does */
2250 END_PROFILE(SMBwritebraw
);
2251 if (!write_through
&& total_written
==tcount
) {
2253 #if RABBIT_PELLET_FIX
2255 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2256 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2258 if (!send_keepalive(smbd_server_fd()))
2259 exit_server("reply_writebraw: send of keepalive failed");
2267 /****************************************************************************
2268 Reply to a writeunlock (core+).
2269 ****************************************************************************/
2271 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
,
2272 int size
, int dum_buffsize
)
2274 ssize_t nwritten
= -1;
2278 NTSTATUS status
= NT_STATUS_OK
;
2279 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2281 START_PROFILE(SMBwriteunlock
);
2283 CHECK_FSP(fsp
,conn
);
2286 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2287 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2288 data
= smb_buf(inbuf
) + 3;
2290 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
,
2291 WRITE_LOCK
,False
)) {
2292 END_PROFILE(SMBwriteunlock
);
2293 return ERROR_DOS(ERRDOS
,ERRlock
);
2296 /* The special X/Open SMB protocol handling of
2297 zero length writes is *NOT* done for
2302 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2304 if (lp_syncalways(SNUM(conn
)))
2305 sync_file(conn
,fsp
);
2307 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2308 END_PROFILE(SMBwriteunlock
);
2309 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2313 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)numtowrite
,
2314 (SMB_BIG_UINT
)startpos
);
2315 if (NT_STATUS_V(status
)) {
2316 END_PROFILE(SMBwriteunlock
);
2317 return ERROR_NT(status
);
2321 outsize
= set_message(outbuf
,1,0,True
);
2323 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2325 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2326 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2328 END_PROFILE(SMBwriteunlock
);
2332 /****************************************************************************
2334 ****************************************************************************/
2336 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2339 ssize_t nwritten
= -1;
2342 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2344 START_PROFILE(SMBwrite
);
2346 /* If it's an IPC, pass off the pipe handler. */
2348 END_PROFILE(SMBwrite
);
2349 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2352 CHECK_FSP(fsp
,conn
);
2355 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2356 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2357 data
= smb_buf(inbuf
) + 3;
2359 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2360 END_PROFILE(SMBwrite
);
2361 return ERROR_DOS(ERRDOS
,ERRlock
);
2365 * X/Open SMB protocol says that if smb_vwv1 is
2366 * zero then the file size should be extended or
2367 * truncated to the size given in smb_vwv[2-3].
2370 if(numtowrite
== 0) {
2372 * This is actually an allocate call, and set EOF. JRA.
2374 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2376 END_PROFILE(SMBwrite
);
2377 return ERROR_NT(NT_STATUS_DISK_FULL
);
2379 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2381 END_PROFILE(SMBwrite
);
2382 return ERROR_NT(NT_STATUS_DISK_FULL
);
2385 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2387 if (lp_syncalways(SNUM(conn
)))
2388 sync_file(conn
,fsp
);
2390 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2391 END_PROFILE(SMBwrite
);
2392 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2395 outsize
= set_message(outbuf
,1,0,True
);
2397 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2399 if (nwritten
< (ssize_t
)numtowrite
) {
2400 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2401 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2404 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2406 END_PROFILE(SMBwrite
);
2410 /****************************************************************************
2411 Reply to a write and X.
2412 ****************************************************************************/
2414 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2416 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2417 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2418 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2419 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2420 ssize_t nwritten
= -1;
2421 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2422 unsigned int smblen
= smb_len(inbuf
);
2424 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2425 START_PROFILE(SMBwriteX
);
2427 /* If it's an IPC, pass off the pipe handler. */
2429 END_PROFILE(SMBwriteX
);
2430 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2433 CHECK_FSP(fsp
,conn
);
2436 /* Deal with possible LARGE_WRITEX */
2438 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2440 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2441 END_PROFILE(SMBwriteX
);
2442 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2445 data
= smb_base(inbuf
) + smb_doff
;
2447 if(CVAL(inbuf
,smb_wct
) == 14) {
2448 #ifdef LARGE_SMB_OFF_T
2450 * This is a large offset (64 bit) write.
2452 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2454 #else /* !LARGE_SMB_OFF_T */
2457 * Ensure we haven't been sent a >32 bit offset.
2460 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2461 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2462 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2463 END_PROFILE(SMBwriteX
);
2464 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2467 #endif /* LARGE_SMB_OFF_T */
2470 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2471 END_PROFILE(SMBwriteX
);
2472 return ERROR_DOS(ERRDOS
,ERRlock
);
2475 /* X/Open SMB protocol says that, unlike SMBwrite
2476 if the length is zero then NO truncation is
2477 done, just a write of zero. To truncate a file,
2483 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2485 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2486 END_PROFILE(SMBwriteX
);
2487 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2490 set_message(outbuf
,6,0,True
);
2492 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2494 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2496 if (nwritten
< (ssize_t
)numtowrite
) {
2497 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2498 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2501 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2502 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2504 if (lp_syncalways(SNUM(conn
)) || write_through
)
2505 sync_file(conn
,fsp
);
2507 END_PROFILE(SMBwriteX
);
2508 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2511 /****************************************************************************
2513 ****************************************************************************/
2515 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2521 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2522 START_PROFILE(SMBlseek
);
2524 CHECK_FSP(fsp
,conn
);
2526 flush_write_cache(fsp
, SEEK_FLUSH
);
2528 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2529 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2530 startpos
= (SMB_OFF_T
)IVALS(inbuf
,smb_vwv2
);
2539 res
= fsp
->pos
+ startpos
;
2550 if (umode
== SEEK_END
) {
2551 if((res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
2552 if(errno
== EINVAL
) {
2553 SMB_OFF_T current_pos
= startpos
;
2554 SMB_STRUCT_STAT sbuf
;
2556 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1) {
2557 END_PROFILE(SMBlseek
);
2558 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2561 current_pos
+= sbuf
.st_size
;
2563 res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,0,SEEK_SET
);
2568 END_PROFILE(SMBlseek
);
2569 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2575 outsize
= set_message(outbuf
,2,0,True
);
2576 SIVAL(outbuf
,smb_vwv0
,res
);
2578 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2579 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
2581 END_PROFILE(SMBlseek
);
2585 /****************************************************************************
2587 ****************************************************************************/
2589 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2591 int outsize
= set_message(outbuf
,0,0,True
);
2592 uint16 fnum
= SVAL(inbuf
,smb_vwv0
);
2593 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2594 START_PROFILE(SMBflush
);
2597 CHECK_FSP(fsp
,conn
);
2600 file_sync_all(conn
);
2602 sync_file(conn
,fsp
);
2605 DEBUG(3,("flush\n"));
2606 END_PROFILE(SMBflush
);
2610 /****************************************************************************
2612 ****************************************************************************/
2614 int reply_exit(connection_struct
*conn
,
2615 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2618 START_PROFILE(SMBexit
);
2620 file_close_pid(SVAL(inbuf
,smb_pid
));
2622 outsize
= set_message(outbuf
,0,0,True
);
2624 DEBUG(3,("exit\n"));
2626 END_PROFILE(SMBexit
);
2630 /****************************************************************************
2631 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2632 ****************************************************************************/
2634 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2637 extern struct current_user current_user
;
2640 int32 eclass
= 0, err
= 0;
2641 files_struct
*fsp
= NULL
;
2642 START_PROFILE(SMBclose
);
2644 outsize
= set_message(outbuf
,0,0,True
);
2646 /* If it's an IPC, pass off to the pipe handler. */
2648 END_PROFILE(SMBclose
);
2649 return reply_pipe_close(conn
, inbuf
,outbuf
);
2652 fsp
= file_fsp(inbuf
,smb_vwv0
);
2655 * We can only use CHECK_FSP if we know it's not a directory.
2658 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= current_user
.vuid
)) {
2659 END_PROFILE(SMBclose
);
2660 return ERROR_DOS(ERRDOS
,ERRbadfid
);
2663 if(fsp
->is_directory
) {
2665 * Special case - close NT SMB directory handle.
2667 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
2668 close_file(fsp
,True
);
2671 * Close ordinary file.
2676 /* Save the name for time set in close. */
2677 pstrcpy( file_name
, fsp
->fsp_name
);
2679 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2681 conn
->num_files_open
));
2684 * close_file() returns the unix errno if an error
2685 * was detected on close - normally this is due to
2686 * a disk full error. If not then it was probably an I/O error.
2689 if((close_err
= close_file(fsp
,True
)) != 0) {
2691 END_PROFILE(SMBclose
);
2692 return (UNIXERROR(ERRHRD
,ERRgeneral
));
2696 * Now take care of any time sent in the close.
2699 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2701 /* try and set the date */
2702 set_filetime(conn
, file_name
, mtime
);
2706 /* We have a cached error */
2708 END_PROFILE(SMBclose
);
2709 return ERROR_DOS(eclass
,err
);
2712 END_PROFILE(SMBclose
);
2716 /****************************************************************************
2717 Reply to a writeclose (Core+ protocol).
2718 ****************************************************************************/
2720 int reply_writeclose(connection_struct
*conn
,
2721 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2724 ssize_t nwritten
= -1;
2730 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2731 START_PROFILE(SMBwriteclose
);
2733 CHECK_FSP(fsp
,conn
);
2736 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2737 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2738 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2739 data
= smb_buf(inbuf
) + 1;
2741 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2742 END_PROFILE(SMBwriteclose
);
2743 return ERROR_DOS(ERRDOS
,ERRlock
);
2746 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2748 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2751 * More insanity. W2K only closes the file if writelen > 0.
2756 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2758 close_err
= close_file(fsp
,True
);
2761 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2762 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
2763 conn
->num_files_open
));
2765 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2766 END_PROFILE(SMBwriteclose
);
2767 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2770 if(close_err
!= 0) {
2772 END_PROFILE(SMBwriteclose
);
2773 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2776 outsize
= set_message(outbuf
,1,0,True
);
2778 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2779 END_PROFILE(SMBwriteclose
);
2783 /****************************************************************************
2785 ****************************************************************************/
2787 int reply_lock(connection_struct
*conn
,
2788 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
2790 int outsize
= set_message(outbuf
,0,0,True
);
2791 SMB_BIG_UINT count
,offset
;
2793 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2794 BOOL my_lock_ctx
= False
;
2796 START_PROFILE(SMBlock
);
2798 CHECK_FSP(fsp
,conn
);
2800 release_level_2_oplocks_on_change(fsp
);
2802 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2803 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2805 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2806 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
2808 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
, WRITE_LOCK
, &my_lock_ctx
);
2809 if (NT_STATUS_V(status
)) {
2811 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2812 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
2814 * A blocking lock was requested. Package up
2815 * this smb into a queued request and push it
2816 * onto the blocking lock queue.
2818 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), offset
, count
)) {
2819 END_PROFILE(SMBlock
);
2824 END_PROFILE(SMBlock
);
2825 return ERROR_NT(status
);
2828 END_PROFILE(SMBlock
);
2832 /****************************************************************************
2834 ****************************************************************************/
2836 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2839 int outsize
= set_message(outbuf
,0,0,True
);
2840 SMB_BIG_UINT count
,offset
;
2842 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2843 START_PROFILE(SMBunlock
);
2845 CHECK_FSP(fsp
,conn
);
2847 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2848 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2850 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
);
2851 if (NT_STATUS_V(status
)) {
2852 END_PROFILE(SMBunlock
);
2853 return ERROR_NT(status
);
2856 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2857 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
2859 END_PROFILE(SMBunlock
);
2863 /****************************************************************************
2865 ****************************************************************************/
2867 int reply_tdis(connection_struct
*conn
,
2868 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2870 int outsize
= set_message(outbuf
,0,0,True
);
2872 START_PROFILE(SMBtdis
);
2874 vuid
= SVAL(inbuf
,smb_uid
);
2877 DEBUG(4,("Invalid connection in tdis\n"));
2878 END_PROFILE(SMBtdis
);
2879 return ERROR_DOS(ERRSRV
,ERRinvnid
);
2884 close_cnum(conn
,vuid
);
2886 END_PROFILE(SMBtdis
);
2890 /****************************************************************************
2892 ****************************************************************************/
2894 int reply_echo(connection_struct
*conn
,
2895 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2897 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2899 unsigned int data_len
= smb_buflen(inbuf
);
2900 int outsize
= set_message(outbuf
,1,data_len
,True
);
2901 START_PROFILE(SMBecho
);
2903 if (data_len
> BUFFER_SIZE
) {
2904 DEBUG(0,("reply_echo: data_len too large.\n"));
2905 END_PROFILE(SMBecho
);
2909 /* copy any incoming data back out */
2911 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2913 if (smb_reverb
> 100) {
2914 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2918 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2919 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2921 smb_setlen(outbuf
,outsize
- 4);
2923 if (!send_smb(smbd_server_fd(),outbuf
))
2924 exit_server("reply_echo: send_smb failed.");
2927 DEBUG(3,("echo %d times\n", smb_reverb
));
2931 END_PROFILE(SMBecho
);
2935 /****************************************************************************
2936 Reply to a printopen.
2937 ****************************************************************************/
2939 int reply_printopen(connection_struct
*conn
,
2940 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2944 START_PROFILE(SMBsplopen
);
2946 if (!CAN_PRINT(conn
)) {
2947 END_PROFILE(SMBsplopen
);
2948 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2951 /* Open for exclusive use, write only. */
2952 fsp
= print_fsp_open(conn
, NULL
);
2955 END_PROFILE(SMBsplopen
);
2956 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2959 outsize
= set_message(outbuf
,1,0,True
);
2960 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2962 DEBUG(3,("openprint fd=%d fnum=%d\n",
2963 fsp
->fd
, fsp
->fnum
));
2965 END_PROFILE(SMBsplopen
);
2969 /****************************************************************************
2970 Reply to a printclose.
2971 ****************************************************************************/
2973 int reply_printclose(connection_struct
*conn
,
2974 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2976 int outsize
= set_message(outbuf
,0,0,True
);
2977 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2979 START_PROFILE(SMBsplclose
);
2981 CHECK_FSP(fsp
,conn
);
2983 if (!CAN_PRINT(conn
)) {
2984 END_PROFILE(SMBsplclose
);
2985 return ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
2988 DEBUG(3,("printclose fd=%d fnum=%d\n",
2989 fsp
->fd
,fsp
->fnum
));
2991 close_err
= close_file(fsp
,True
);
2993 if(close_err
!= 0) {
2995 END_PROFILE(SMBsplclose
);
2996 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2999 END_PROFILE(SMBsplclose
);
3003 /****************************************************************************
3004 Reply to a printqueue.
3005 ****************************************************************************/
3007 int reply_printqueue(connection_struct
*conn
,
3008 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3010 int outsize
= set_message(outbuf
,2,3,True
);
3011 int max_count
= SVAL(inbuf
,smb_vwv0
);
3012 int start_index
= SVAL(inbuf
,smb_vwv1
);
3013 START_PROFILE(SMBsplretq
);
3015 /* we used to allow the client to get the cnum wrong, but that
3016 is really quite gross and only worked when there was only
3017 one printer - I think we should now only accept it if they
3018 get it right (tridge) */
3019 if (!CAN_PRINT(conn
)) {
3020 END_PROFILE(SMBsplretq
);
3021 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3024 SSVAL(outbuf
,smb_vwv0
,0);
3025 SSVAL(outbuf
,smb_vwv1
,0);
3026 SCVAL(smb_buf(outbuf
),0,1);
3027 SSVAL(smb_buf(outbuf
),1,0);
3029 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3030 start_index
, max_count
));
3033 print_queue_struct
*queue
= NULL
;
3034 print_status_struct status
;
3035 char *p
= smb_buf(outbuf
) + 3;
3036 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
3037 int num_to_get
= ABS(max_count
);
3038 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
3044 num_to_get
= MIN(num_to_get
,count
-first
);
3047 for (i
=first
;i
<first
+num_to_get
;i
++) {
3048 put_dos_date2(p
,0,queue
[i
].time
);
3049 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
3050 SSVAL(p
,5, queue
[i
].job
);
3051 SIVAL(p
,7,queue
[i
].size
);
3053 srvstr_push(outbuf
, p
+12, queue
[i
].fs_user
, 16, STR_ASCII
);
3058 outsize
= set_message(outbuf
,2,28*count
+3,False
);
3059 SSVAL(outbuf
,smb_vwv0
,count
);
3060 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
3061 SCVAL(smb_buf(outbuf
),0,1);
3062 SSVAL(smb_buf(outbuf
),1,28*count
);
3067 DEBUG(3,("%d entries returned in queue\n",count
));
3070 END_PROFILE(SMBsplretq
);
3074 /****************************************************************************
3075 Reply to a printwrite.
3076 ****************************************************************************/
3078 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3081 int outsize
= set_message(outbuf
,0,0,True
);
3083 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3085 START_PROFILE(SMBsplwr
);
3087 if (!CAN_PRINT(conn
)) {
3088 END_PROFILE(SMBsplwr
);
3089 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3092 CHECK_FSP(fsp
,conn
);
3095 numtowrite
= SVAL(smb_buf(inbuf
),1);
3096 data
= smb_buf(inbuf
) + 3;
3098 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
3099 END_PROFILE(SMBsplwr
);
3100 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3103 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
3105 END_PROFILE(SMBsplwr
);
3109 /****************************************************************************
3110 The guts of the mkdir command, split out so it may be called by the NT SMB
3112 ****************************************************************************/
3114 NTSTATUS
mkdir_internal(connection_struct
*conn
, pstring directory
)
3116 BOOL bad_path
= False
;
3117 SMB_STRUCT_STAT sbuf
;
3120 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3122 if( strchr_m(directory
, ':')) {
3123 return NT_STATUS_NOT_A_DIRECTORY
;
3126 if (ms_has_wild(directory
)) {
3127 return NT_STATUS_OBJECT_NAME_INVALID
;
3130 if (check_name(directory
, conn
))
3131 ret
= vfs_MkDir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3134 if(errno
== ENOENT
) {
3136 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3138 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3140 return map_nt_error_from_unix(errno
);
3143 return NT_STATUS_OK
;
3146 /****************************************************************************
3148 ****************************************************************************/
3150 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3155 START_PROFILE(SMBmkdir
);
3157 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3158 if (!NT_STATUS_IS_OK(status
)) {
3159 END_PROFILE(SMBmkdir
);
3160 return ERROR_NT(status
);
3163 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
);
3165 status
= mkdir_internal(conn
, directory
);
3166 if (!NT_STATUS_IS_OK(status
)) {
3167 END_PROFILE(SMBmkdir
);
3168 return ERROR_NT(status
);
3171 outsize
= set_message(outbuf
,0,0,True
);
3173 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
3175 END_PROFILE(SMBmkdir
);
3179 /****************************************************************************
3180 Static function used by reply_rmdir to delete an entire directory
3181 tree recursively. Return False on ok, True on fail.
3182 ****************************************************************************/
3184 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
3186 const char *dname
= NULL
;
3188 void *dirptr
= OpenDir(conn
, directory
, False
);
3193 while((dname
= ReadDirName(dirptr
))) {
3197 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3200 /* Construct the full name. */
3201 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3207 pstrcpy(fullname
, directory
);
3208 pstrcat(fullname
, "/");
3209 pstrcat(fullname
, dname
);
3211 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
3216 if(st
.st_mode
& S_IFDIR
) {
3217 if(recursive_rmdir(conn
, fullname
)!=0) {
3221 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
3225 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
3234 /****************************************************************************
3235 The internals of the rmdir code - called elsewhere.
3236 ****************************************************************************/
3238 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
3242 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3243 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
3245 * Check to see if the only thing in this directory are
3246 * vetoed files/directories. If so then delete them and
3247 * retry. If we fail to delete any of them (and we *don't*
3248 * do a recursive delete) then fail the rmdir.
3250 BOOL all_veto_files
= True
;
3252 void *dirptr
= OpenDir(conn
, directory
, False
);
3254 if(dirptr
!= NULL
) {
3255 int dirpos
= TellDir(dirptr
);
3256 while ((dname
= ReadDirName(dirptr
))) {
3257 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3259 if(!IS_VETO_PATH(conn
, dname
)) {
3260 all_veto_files
= False
;
3265 if(all_veto_files
) {
3266 SeekDir(dirptr
,dirpos
);
3267 while ((dname
= ReadDirName(dirptr
))) {
3271 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3274 /* Construct the full name. */
3275 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3280 pstrcpy(fullname
, directory
);
3281 pstrcat(fullname
, "/");
3282 pstrcat(fullname
, dname
);
3284 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0)
3286 if(st
.st_mode
& S_IFDIR
) {
3287 if(lp_recursive_veto_delete(SNUM(conn
))) {
3288 if(recursive_rmdir(conn
, fullname
) != 0)
3291 if(SMB_VFS_RMDIR(conn
,fullname
) != 0)
3293 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0)
3297 /* Retry the rmdir */
3298 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3308 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory
,strerror(errno
)));
3313 /****************************************************************************
3315 ****************************************************************************/
3317 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3322 BOOL bad_path
= False
;
3323 SMB_STRUCT_STAT sbuf
;
3325 START_PROFILE(SMBrmdir
);
3327 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3328 if (!NT_STATUS_IS_OK(status
)) {
3329 END_PROFILE(SMBrmdir
);
3330 return ERROR_NT(status
);
3333 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3335 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3337 if (check_name(directory
,conn
)) {
3338 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3339 ok
= rmdir_internals(conn
, directory
);
3343 END_PROFILE(SMBrmdir
);
3344 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRbadpath
);
3347 outsize
= set_message(outbuf
,0,0,True
);
3349 DEBUG( 3, ( "rmdir %s\n", directory
) );
3351 END_PROFILE(SMBrmdir
);
3355 /*******************************************************************
3356 Resolve wildcards in a filename rename.
3357 Note that name is in UNIX charset and thus potentially can be more
3358 than fstring buffer (255 bytes) especially in default UTF-8 case.
3359 Therefore, we use pstring inside and all calls should ensure that
3360 name2 is at least pstring-long (they do already)
3361 ********************************************************************/
3363 static BOOL
resolve_wildcards(const char *name1
, char *name2
)
3365 pstring root1
,root2
;
3367 char *p
,*p2
, *pname1
, *pname2
;
3368 int available_space
, actual_space
;
3371 pname1
= strrchr_m(name1
,'/');
3372 pname2
= strrchr_m(name2
,'/');
3374 if (!pname1
|| !pname2
)
3377 pstrcpy(root1
,pname1
);
3378 pstrcpy(root2
,pname2
);
3379 p
= strrchr_m(root1
,'.');
3386 p
= strrchr_m(root2
,'.');
3420 available_space
= sizeof(pstring
) - PTR_DIFF(pname2
, name2
);
3423 actual_space
= snprintf(pname2
, available_space
- 1, "%s.%s", root2
, ext2
);
3424 if (actual_space
>= available_space
- 1) {
3425 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3426 actual_space
- available_space
));
3429 pstrcpy_base(pname2
, root2
, name2
);
3435 /****************************************************************************
3436 Ensure open files have their names updates.
3437 ****************************************************************************/
3439 static void rename_open_files(connection_struct
*conn
, SMB_DEV_T dev
, SMB_INO_T inode
, char *newname
)
3442 BOOL did_rename
= False
;
3444 for(fsp
= file_find_di_first(dev
, inode
); fsp
; fsp
= file_find_di_next(fsp
)) {
3445 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3446 fsp
->fnum
, (unsigned int)fsp
->dev
, (double)fsp
->inode
,
3447 fsp
->fsp_name
, newname
));
3448 string_set(&fsp
->fsp_name
, newname
);
3453 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3454 (unsigned int)dev
, (double)inode
, newname
));
3457 /****************************************************************************
3458 Rename an open file - given an fsp.
3459 ****************************************************************************/
3461 NTSTATUS
rename_internals_fsp(connection_struct
*conn
, files_struct
*fsp
, char *newname
, BOOL replace_if_exists
)
3463 SMB_STRUCT_STAT sbuf
;
3464 BOOL bad_path
= False
;
3465 pstring newname_last_component
;
3466 NTSTATUS error
= NT_STATUS_OK
;
3471 rcdest
= unix_convert(newname
,conn
,newname_last_component
,&bad_path
,&sbuf
);
3473 /* Quick check for "." and ".." */
3474 if (!bad_path
&& newname_last_component
[0] == '.') {
3475 if (!newname_last_component
[1] || (newname_last_component
[1] == '.' && !newname_last_component
[2])) {
3476 return NT_STATUS_ACCESS_DENIED
;
3479 if (!rcdest
&& bad_path
) {
3480 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3483 /* Ensure newname contains a '/' */
3484 if(strrchr_m(newname
,'/') == 0) {
3487 pstrcpy(tmpstr
, "./");
3488 pstrcat(tmpstr
, newname
);
3489 pstrcpy(newname
, tmpstr
);
3493 * Check for special case with case preserving and not
3494 * case sensitive. If the old last component differs from the original
3495 * last component only by case, then we should allow
3496 * the rename (user is trying to change the case of the
3500 if((case_sensitive
== False
) && (case_preserve
== True
) &&
3501 strequal(newname
, fsp
->fsp_name
)) {
3503 pstring newname_modified_last_component
;
3506 * Get the last component of the modified name.
3507 * Note that we guarantee that newname contains a '/'
3510 p
= strrchr_m(newname
,'/');
3511 pstrcpy(newname_modified_last_component
,p
+1);
3513 if(strcsequal(newname_modified_last_component
,
3514 newname_last_component
) == False
) {
3516 * Replace the modified last component with
3519 pstrcpy(p
+1, newname_last_component
);
3524 * If the src and dest names are identical - including case,
3525 * don't do the rename, just return success.
3528 if (strcsequal(fsp
->fsp_name
, newname
)) {
3529 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3531 return NT_STATUS_OK
;
3534 dest_exists
= vfs_object_exist(conn
,newname
,NULL
);
3536 if(!replace_if_exists
&& dest_exists
) {
3537 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3538 fsp
->fsp_name
,newname
));
3539 return NT_STATUS_OBJECT_NAME_COLLISION
;
3542 error
= can_rename(newname
,conn
,&sbuf
);
3544 if (dest_exists
&& !NT_STATUS_IS_OK(error
)) {
3545 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3546 nt_errstr(error
), fsp
->fsp_name
,newname
));
3547 if (NT_STATUS_EQUAL(error
,NT_STATUS_SHARING_VIOLATION
))
3548 error
= NT_STATUS_ACCESS_DENIED
;
3552 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
3553 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3554 fsp
->fsp_name
,newname
));
3555 rename_open_files(conn
, fsp
->dev
, fsp
->inode
, newname
);
3556 return NT_STATUS_OK
;
3559 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3560 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3562 error
= map_nt_error_from_unix(errno
);
3564 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3565 nt_errstr(error
), fsp
->fsp_name
,newname
));
3570 /****************************************************************************
3571 The guts of the rename command, split out so it may be called by the NT SMB
3573 ****************************************************************************/
3575 NTSTATUS
rename_internals(connection_struct
*conn
, char *name
, char *newname
, uint16 attrs
, BOOL replace_if_exists
)
3579 pstring last_component_src
;
3580 pstring last_component_dest
;
3583 BOOL bad_path_src
= False
;
3584 BOOL bad_path_dest
= False
;
3586 NTSTATUS error
= NT_STATUS_OK
;
3589 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3591 *directory
= *mask
= 0;
3596 rc
= unix_convert(name
,conn
,last_component_src
,&bad_path_src
,&sbuf1
);
3597 if (!rc
&& bad_path_src
) {
3598 if (ms_has_wild(last_component_src
))
3599 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3600 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3603 /* Quick check for "." and ".." */
3604 if (last_component_src
[0] == '.') {
3605 if (!last_component_src
[1] || (last_component_src
[1] == '.' && !last_component_src
[2])) {
3606 return NT_STATUS_OBJECT_NAME_INVALID
;
3610 rcdest
= unix_convert(newname
,conn
,last_component_dest
,&bad_path_dest
,&sbuf2
);
3612 /* Quick check for "." and ".." */
3613 if (last_component_dest
[0] == '.') {
3614 if (!last_component_dest
[1] || (last_component_dest
[1] == '.' && !last_component_dest
[2])) {
3615 return NT_STATUS_OBJECT_NAME_INVALID
;
3620 * Split the old name into directory and last component
3621 * strings. Note that unix_convert may have stripped off a
3622 * leading ./ from both name and newname if the rename is
3623 * at the root of the share. We need to make sure either both
3624 * name and newname contain a / character or neither of them do
3625 * as this is checked in resolve_wildcards().
3628 p
= strrchr_m(name
,'/');
3630 pstrcpy(directory
,".");
3634 pstrcpy(directory
,name
);
3636 *p
= '/'; /* Replace needed for exceptional test below. */
3640 * We should only check the mangled cache
3641 * here if unix_convert failed. This means
3642 * that the path in 'mask' doesn't exist
3643 * on the file system and so we need to look
3644 * for a possible mangle. This patch from
3645 * Tine Smukavec <valentin.smukavec@hermes.si>.
3648 if (!rc
&& mangle_is_mangled(mask
))
3649 mangle_check_cache( mask
);
3651 has_wild
= ms_has_wild(mask
);
3655 * No wildcards - just process the one file.
3657 BOOL is_short_name
= mangle_is_8_3(name
, True
);
3659 /* Add a terminating '/' to the directory name. */
3660 pstrcat(directory
,"/");
3661 pstrcat(directory
,mask
);
3663 /* Ensure newname contains a '/' also */
3664 if(strrchr_m(newname
,'/') == 0) {
3667 pstrcpy(tmpstr
, "./");
3668 pstrcat(tmpstr
, newname
);
3669 pstrcpy(newname
, tmpstr
);
3672 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3673 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3674 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3675 newname
, last_component_dest
, is_short_name
));
3678 * Check for special case with case preserving and not
3679 * case sensitive, if directory and newname are identical,
3680 * and the old last component differs from the original
3681 * last component only by case, then we should allow
3682 * the rename (user is trying to change the case of the
3685 if((case_sensitive
== False
) &&
3686 (((case_preserve
== True
) &&
3687 (is_short_name
== False
)) ||
3688 ((short_case_preserve
== True
) &&
3689 (is_short_name
== True
))) &&
3690 strcsequal(directory
, newname
)) {
3691 pstring modified_last_component
;
3694 * Get the last component of the modified name.
3695 * Note that we guarantee that newname contains a '/'
3698 p
= strrchr_m(newname
,'/');
3699 pstrcpy(modified_last_component
,p
+1);
3701 if(strcsequal(modified_last_component
,
3702 last_component_dest
) == False
) {
3704 * Replace the modified last component with
3707 pstrcpy(p
+1, last_component_dest
);
3711 resolve_wildcards(directory
,newname
);
3714 * The source object must exist.
3717 if (!vfs_object_exist(conn
, directory
, &sbuf1
)) {
3718 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3719 directory
,newname
));
3721 if (errno
== ENOTDIR
|| errno
== EISDIR
|| errno
== ENOENT
) {
3723 * Must return different errors depending on whether the parent
3724 * directory existed or not.
3727 p
= strrchr_m(directory
, '/');
3729 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3731 if (vfs_object_exist(conn
, directory
, NULL
))
3732 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3733 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3735 error
= map_nt_error_from_unix(errno
);
3736 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3737 nt_errstr(error
), directory
,newname
));
3742 if (!rcdest
&& bad_path_dest
) {
3743 if (ms_has_wild(last_component_dest
))
3744 return NT_STATUS_OBJECT_NAME_INVALID
;
3745 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3748 error
= can_rename(directory
,conn
,&sbuf1
);
3750 if (!NT_STATUS_IS_OK(error
)) {
3751 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3752 nt_errstr(error
), directory
,newname
));
3757 * If the src and dest names are identical - including case,
3758 * don't do the rename, just return success.
3761 if (strcsequal(directory
, newname
)) {
3762 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3763 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory
));
3764 return NT_STATUS_OK
;
3767 if(!replace_if_exists
&& vfs_object_exist(conn
,newname
,NULL
)) {
3768 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3769 directory
,newname
));
3770 return NT_STATUS_OBJECT_NAME_COLLISION
;
3773 if(SMB_VFS_RENAME(conn
,directory
, newname
) == 0) {
3774 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3775 directory
,newname
));
3776 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3777 return NT_STATUS_OK
;
3780 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3781 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3783 error
= map_nt_error_from_unix(errno
);
3785 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3786 nt_errstr(error
), directory
,newname
));
3791 * Wildcards - process each file that matches.
3793 void *dirptr
= NULL
;
3797 if (check_name(directory
,conn
))
3798 dirptr
= OpenDir(conn
, directory
, True
);
3801 error
= NT_STATUS_NO_SUCH_FILE
;
3802 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3804 if (strequal(mask
,"????????.???"))
3807 while ((dname
= ReadDirName(dirptr
))) {
3809 BOOL sysdir_entry
= False
;
3811 pstrcpy(fname
,dname
);
3813 /* Quick check for "." and ".." */
3814 if (fname
[0] == '.') {
3815 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
3817 sysdir_entry
= True
;
3824 if(!mask_match(fname
, mask
, case_sensitive
))
3828 error
= NT_STATUS_OBJECT_NAME_INVALID
;
3832 error
= NT_STATUS_ACCESS_DENIED
;
3833 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3834 if (!vfs_object_exist(conn
, fname
, &sbuf1
)) {
3835 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3836 DEBUG(6,("rename %s failed. Error %s\n", fname
, nt_errstr(error
)));
3839 error
= can_rename(fname
,conn
,&sbuf1
);
3840 if (!NT_STATUS_IS_OK(error
)) {
3841 DEBUG(6,("rename %s refused\n", fname
));
3844 pstrcpy(destname
,newname
);
3846 if (!resolve_wildcards(fname
,destname
)) {
3847 DEBUG(6,("resolve_wildcards %s %s failed\n",
3852 if (!replace_if_exists
&&
3853 vfs_file_exist(conn
,destname
, NULL
)) {
3854 DEBUG(6,("file_exist %s\n", destname
));
3855 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3859 if (!SMB_VFS_RENAME(conn
,fname
,destname
)) {
3860 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3862 error
= NT_STATUS_OK
;
3864 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3869 if (!NT_STATUS_EQUAL(error
,NT_STATUS_NO_SUCH_FILE
)) {
3870 if (!rcdest
&& bad_path_dest
) {
3871 if (ms_has_wild(last_component_dest
))
3872 return NT_STATUS_OBJECT_NAME_INVALID
;
3873 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3878 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
3879 error
= map_nt_error_from_unix(errno
);
3885 /****************************************************************************
3887 ****************************************************************************/
3889 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
3896 uint16 attrs
= SVAL(inbuf
,smb_vwv0
);
3899 START_PROFILE(SMBmv
);
3901 p
= smb_buf(inbuf
) + 1;
3902 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
);
3903 if (!NT_STATUS_IS_OK(status
)) {
3905 return ERROR_NT(status
);
3908 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
);
3909 if (!NT_STATUS_IS_OK(status
)) {
3911 return ERROR_NT(status
);
3914 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3915 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3917 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3919 status
= rename_internals(conn
, name
, newname
, attrs
, False
);
3920 if (!NT_STATUS_IS_OK(status
)) {
3922 return ERROR_NT(status
);
3926 * Win2k needs a changenotify request response before it will
3927 * update after a rename..
3929 process_pending_change_notify_queue((time_t)0);
3930 outsize
= set_message(outbuf
,0,0,True
);
3936 /*******************************************************************
3937 Copy a file as part of a reply_copy.
3938 ******************************************************************/
3940 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3941 int count
,BOOL target_is_directory
, int *err_ret
)
3944 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
3946 files_struct
*fsp1
,*fsp2
;
3951 pstrcpy(dest
,dest1
);
3952 if (target_is_directory
) {
3953 char *p
= strrchr_m(src
,'/');
3962 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
3965 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3966 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
3971 if (!target_is_directory
&& count
)
3972 ofun
= FILE_EXISTS_OPEN
;
3974 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1)
3975 ZERO_STRUCTP(&sbuf2
);
3977 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3978 ofun
,src_sbuf
.st_mode
,0,&Access
,&action
);
3981 close_file(fsp1
,False
);
3985 if ((ofun
&3) == 1) {
3986 if(SMB_VFS_LSEEK(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
3987 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
3989 * Stop the copy from occurring.
3992 src_sbuf
.st_size
= 0;
3996 if (src_sbuf
.st_size
)
3997 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
3999 close_file(fsp1
,False
);
4001 /* Ensure the modtime is set correctly on the destination file. */
4002 fsp2
->pending_modtime
= src_sbuf
.st_mtime
;
4005 * As we are opening fsp1 read-only we only expect
4006 * an error on close on fsp2 if we are out of space.
4007 * Thus we don't look at the error return from the
4010 *err_ret
= close_file(fsp2
,False
);
4012 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
4015 /****************************************************************************
4016 Reply to a file copy.
4017 ****************************************************************************/
4019 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4024 pstring mask
,newname
;
4027 int error
= ERRnoaccess
;
4031 int tid2
= SVAL(inbuf
,smb_vwv0
);
4032 int ofun
= SVAL(inbuf
,smb_vwv1
);
4033 int flags
= SVAL(inbuf
,smb_vwv2
);
4034 BOOL target_is_directory
=False
;
4035 BOOL bad_path1
= False
;
4036 BOOL bad_path2
= False
;
4038 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4041 START_PROFILE(SMBcopy
);
4043 *directory
= *mask
= 0;
4046 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
);
4047 if (!NT_STATUS_IS_OK(status
)) {
4048 END_PROFILE(SMBcopy
);
4049 return ERROR_NT(status
);
4051 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
);
4052 if (!NT_STATUS_IS_OK(status
)) {
4053 END_PROFILE(SMBcopy
);
4054 return ERROR_NT(status
);
4057 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
4059 if (tid2
!= conn
->cnum
) {
4060 /* can't currently handle inter share copies XXXX */
4061 DEBUG(3,("Rejecting inter-share copy\n"));
4062 END_PROFILE(SMBcopy
);
4063 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
4066 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
4067 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
4069 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
4070 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
4072 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
4074 if ((flags
&1) && target_is_directory
) {
4075 END_PROFILE(SMBcopy
);
4076 return ERROR_DOS(ERRDOS
,ERRbadfile
);
4079 if ((flags
&2) && !target_is_directory
) {
4080 END_PROFILE(SMBcopy
);
4081 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4084 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
4085 /* wants a tree copy! XXXX */
4086 DEBUG(3,("Rejecting tree copy\n"));
4087 END_PROFILE(SMBcopy
);
4088 return ERROR_DOS(ERRSRV
,ERRerror
);
4091 p
= strrchr_m(name
,'/');
4093 pstrcpy(directory
,"./");
4097 pstrcpy(directory
,name
);
4102 * We should only check the mangled cache
4103 * here if unix_convert failed. This means
4104 * that the path in 'mask' doesn't exist
4105 * on the file system and so we need to look
4106 * for a possible mangle. This patch from
4107 * Tine Smukavec <valentin.smukavec@hermes.si>.
4110 if (!rc
&& mangle_is_mangled(mask
))
4111 mangle_check_cache( mask
);
4113 has_wild
= ms_has_wild(mask
);
4116 pstrcat(directory
,"/");
4117 pstrcat(directory
,mask
);
4118 if (resolve_wildcards(directory
,newname
) &&
4119 copy_file(directory
,newname
,conn
,ofun
, count
,target_is_directory
,&err
))
4123 END_PROFILE(SMBcopy
);
4124 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4127 exists
= vfs_file_exist(conn
,directory
,NULL
);
4130 void *dirptr
= NULL
;
4134 if (check_name(directory
,conn
))
4135 dirptr
= OpenDir(conn
, directory
, True
);
4140 if (strequal(mask
,"????????.???"))
4143 while ((dname
= ReadDirName(dirptr
))) {
4145 pstrcpy(fname
,dname
);
4147 if(!mask_match(fname
, mask
, case_sensitive
))
4150 error
= ERRnoaccess
;
4151 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
4152 pstrcpy(destname
,newname
);
4153 if (resolve_wildcards(fname
,destname
) &&
4154 copy_file(fname
,destname
,conn
,ofun
,
4155 count
,target_is_directory
,&err
))
4157 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
4165 /* Error on close... */
4167 END_PROFILE(SMBcopy
);
4168 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4172 END_PROFILE(SMBcopy
);
4173 return ERROR_DOS(ERRDOS
,error
);
4175 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
)) {
4176 unix_ERR_class
= ERRDOS
;
4177 unix_ERR_code
= ERRbadpath
;
4179 END_PROFILE(SMBcopy
);
4180 return(UNIXERROR(ERRDOS
,error
));
4184 outsize
= set_message(outbuf
,1,0,True
);
4185 SSVAL(outbuf
,smb_vwv0
,count
);
4187 END_PROFILE(SMBcopy
);
4191 /****************************************************************************
4193 ****************************************************************************/
4195 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4203 START_PROFILE(pathworks_setdir
);
4206 if (!CAN_SETDIR(snum
)) {
4207 END_PROFILE(pathworks_setdir
);
4208 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4211 srvstr_get_path(inbuf
, newdir
, smb_buf(inbuf
) + 1, sizeof(newdir
), 0, STR_TERMINATE
, &status
);
4212 if (!NT_STATUS_IS_OK(status
)) {
4213 END_PROFILE(pathworks_setdir
);
4214 return ERROR_NT(status
);
4217 if (strlen(newdir
) == 0) {
4220 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
4222 string_set(&conn
->connectpath
,newdir
);
4226 END_PROFILE(pathworks_setdir
);
4227 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4230 outsize
= set_message(outbuf
,0,0,True
);
4231 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
4233 DEBUG(3,("setdir %s\n", newdir
));
4235 END_PROFILE(pathworks_setdir
);
4239 /****************************************************************************
4240 Get a lock pid, dealing with large count requests.
4241 ****************************************************************************/
4243 uint16
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
4245 if(!large_file_format
)
4246 return SVAL(data
,SMB_LPID_OFFSET(data_offset
));
4248 return SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
4251 /****************************************************************************
4252 Get a lock count, dealing with large count requests.
4253 ****************************************************************************/
4255 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
4257 SMB_BIG_UINT count
= 0;
4259 if(!large_file_format
) {
4260 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
4263 #if defined(HAVE_LONGLONG)
4264 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
4265 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
4266 #else /* HAVE_LONGLONG */
4269 * NT4.x seems to be broken in that it sends large file (64 bit)
4270 * lockingX calls even if the CAP_LARGE_FILES was *not*
4271 * negotiated. For boxes without large unsigned ints truncate the
4272 * lock count by dropping the top 32 bits.
4275 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
4276 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4277 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
4278 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
4279 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
4282 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
4283 #endif /* HAVE_LONGLONG */
4289 #if !defined(HAVE_LONGLONG)
4290 /****************************************************************************
4291 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4292 ****************************************************************************/
4294 static uint32
map_lock_offset(uint32 high
, uint32 low
)
4298 uint32 highcopy
= high
;
4301 * Try and find out how many significant bits there are in high.
4304 for(i
= 0; highcopy
; i
++)
4308 * We use 31 bits not 32 here as POSIX
4309 * lock offsets may not be negative.
4312 mask
= (~0) << (31 - i
);
4315 return 0; /* Fail. */
4321 #endif /* !defined(HAVE_LONGLONG) */
4323 /****************************************************************************
4324 Get a lock offset, dealing with large offset requests.
4325 ****************************************************************************/
4327 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
4329 SMB_BIG_UINT offset
= 0;
4333 if(!large_file_format
) {
4334 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
4337 #if defined(HAVE_LONGLONG)
4338 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
4339 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
4340 #else /* HAVE_LONGLONG */
4343 * NT4.x seems to be broken in that it sends large file (64 bit)
4344 * lockingX calls even if the CAP_LARGE_FILES was *not*
4345 * negotiated. For boxes without large unsigned ints mangle the
4346 * lock offset by mapping the top 32 bits onto the lower 32.
4349 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
4350 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4351 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
4354 if((new_low
= map_lock_offset(high
, low
)) == 0) {
4356 return (SMB_BIG_UINT
)-1;
4359 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4360 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
4361 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
4362 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
4365 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4366 #endif /* HAVE_LONGLONG */
4372 /****************************************************************************
4373 Reply to a lockingX request.
4374 ****************************************************************************/
4376 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4378 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
4379 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
4380 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
4381 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
4382 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
4383 SMB_BIG_UINT count
= 0, offset
= 0;
4385 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
4388 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
4390 BOOL my_lock_ctx
= False
;
4393 START_PROFILE(SMBlockingX
);
4395 CHECK_FSP(fsp
,conn
);
4397 data
= smb_buf(inbuf
);
4399 if (locktype
& (LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_CHANGE_LOCKTYPE
)) {
4400 /* we don't support these - and CANCEL_LOCK makes w2k
4401 and XP reboot so I don't really want to be
4402 compatible! (tridge) */
4403 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
4406 /* Check if this is an oplock break on a file
4407 we have granted an oplock on.
4409 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
4410 /* Client can insist on breaking to none. */
4411 BOOL break_to_none
= (oplocklevel
== 0);
4413 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4414 (unsigned int)oplocklevel
, fsp
->fnum
));
4417 * Make sure we have granted an exclusive or batch oplock on this file.
4420 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
4421 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4422 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
4424 /* if this is a pure oplock break request then don't send a reply */
4425 if (num_locks
== 0 && num_ulocks
== 0) {
4426 END_PROFILE(SMBlockingX
);
4429 END_PROFILE(SMBlockingX
);
4430 return ERROR_DOS(ERRDOS
,ERRlock
);
4434 if (remove_oplock(fsp
, break_to_none
) == False
) {
4435 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4439 /* if this is a pure oplock break request then don't send a reply */
4440 if (num_locks
== 0 && num_ulocks
== 0) {
4441 /* Sanity check - ensure a pure oplock break is not a
4443 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
4444 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4445 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
4446 END_PROFILE(SMBlockingX
);
4452 * We do this check *after* we have checked this is not a oplock break
4453 * response message. JRA.
4456 release_level_2_oplocks_on_change(fsp
);
4458 /* Data now points at the beginning of the list
4459 of smb_unlkrng structs */
4460 for(i
= 0; i
< (int)num_ulocks
; i
++) {
4461 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4462 count
= get_lock_count( data
, i
, large_file_format
);
4463 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4466 * There is no error code marked "stupid client bug".... :-).
4469 END_PROFILE(SMBlockingX
);
4470 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4473 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4474 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
4476 status
= do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4477 if (NT_STATUS_V(status
)) {
4478 END_PROFILE(SMBlockingX
);
4479 return ERROR_NT(status
);
4483 /* Setup the timeout in seconds. */
4485 lock_timeout
= ((lock_timeout
== -1) ? -1 : (lock_timeout
+999)/1000);
4487 /* Now do any requested locks */
4488 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
4490 /* Data now points at the beginning of the list
4491 of smb_lkrng structs */
4493 for(i
= 0; i
< (int)num_locks
; i
++) {
4494 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4495 count
= get_lock_count( data
, i
, large_file_format
);
4496 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4499 * There is no error code marked "stupid client bug".... :-).
4502 END_PROFILE(SMBlockingX
);
4503 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4506 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4507 (double)offset
, (double)count
, (unsigned int)lock_pid
,
4508 fsp
->fsp_name
, (int)lock_timeout
));
4510 status
= do_lock_spin(fsp
,conn
,lock_pid
, count
,offset
,
4511 ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
), &my_lock_ctx
);
4512 if (NT_STATUS_V(status
)) {
4514 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4515 * Even if it's our own lock context, we need to wait here as
4516 * there may be an unlock on the way.
4517 * So I removed a "&& !my_lock_ctx" from the following
4518 * if statement. JRA.
4520 if ((lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
4522 * A blocking lock was requested. Package up
4523 * this smb into a queued request and push it
4524 * onto the blocking lock queue.
4526 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
, lock_pid
, offset
, count
)) {
4527 END_PROFILE(SMBlockingX
);
4535 /* If any of the above locks failed, then we must unlock
4536 all of the previous locks (X/Open spec). */
4537 if (i
!= num_locks
&& num_locks
!= 0) {
4539 * Ensure we don't do a remove on the lock that just failed,
4540 * as under POSIX rules, if we have a lock already there, we
4541 * will delete it (and we shouldn't) .....
4543 for(i
--; i
>= 0; i
--) {
4544 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4545 count
= get_lock_count( data
, i
, large_file_format
);
4546 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4549 * There is no error code marked "stupid client bug".... :-).
4552 END_PROFILE(SMBlockingX
);
4553 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4556 do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4558 END_PROFILE(SMBlockingX
);
4559 return ERROR_NT(status
);
4562 set_message(outbuf
,2,0,True
);
4564 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4565 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4567 END_PROFILE(SMBlockingX
);
4568 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4571 /****************************************************************************
4572 Reply to a SMBreadbmpx (read block multiplex) request.
4573 ****************************************************************************/
4575 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4586 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4587 START_PROFILE(SMBreadBmpx
);
4589 /* this function doesn't seem to work - disable by default */
4590 if (!lp_readbmpx()) {
4591 END_PROFILE(SMBreadBmpx
);
4592 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
4595 outsize
= set_message(outbuf
,8,0,True
);
4597 CHECK_FSP(fsp
,conn
);
4600 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
4601 maxcount
= SVAL(inbuf
,smb_vwv3
);
4603 data
= smb_buf(outbuf
);
4604 pad
= ((long)data
)%4;
4609 max_per_packet
= bufsize
-(outsize
+pad
);
4613 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
4614 END_PROFILE(SMBreadBmpx
);
4615 return ERROR_DOS(ERRDOS
,ERRlock
);
4619 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4621 nread
= read_file(fsp
,data
,startpos
,N
);
4626 if (nread
< (ssize_t
)N
)
4627 tcount
= total_read
+ nread
;
4629 set_message(outbuf
,8,nread
,False
);
4630 SIVAL(outbuf
,smb_vwv0
,startpos
);
4631 SSVAL(outbuf
,smb_vwv2
,tcount
);
4632 SSVAL(outbuf
,smb_vwv6
,nread
);
4633 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4635 if (!send_smb(smbd_server_fd(),outbuf
))
4636 exit_server("reply_readbmpx: send_smb failed.");
4638 total_read
+= nread
;
4640 } while (total_read
< (ssize_t
)tcount
);
4642 END_PROFILE(SMBreadBmpx
);
4646 /****************************************************************************
4647 Reply to a SMBsetattrE.
4648 ****************************************************************************/
4650 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4652 struct utimbuf unix_times
;
4654 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4655 START_PROFILE(SMBsetattrE
);
4657 outsize
= set_message(outbuf
,0,0,True
);
4659 if(!fsp
|| (fsp
->conn
!= conn
)) {
4660 END_PROFILE(SMBgetattrE
);
4661 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4665 * Convert the DOS times into unix times. Ignore create
4666 * time as UNIX can't set this.
4669 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4670 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4673 * Patch from Ray Frush <frush@engr.colostate.edu>
4674 * Sometimes times are sent as zero - ignore them.
4677 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0)) {
4678 /* Ignore request */
4679 if( DEBUGLVL( 3 ) ) {
4680 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4681 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4683 END_PROFILE(SMBsetattrE
);
4685 } else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0)) {
4686 /* set modify time = to access time if modify time was 0 */
4687 unix_times
.modtime
= unix_times
.actime
;
4690 /* Set the date on this file */
4691 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4692 END_PROFILE(SMBsetattrE
);
4693 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4696 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4697 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4699 END_PROFILE(SMBsetattrE
);
4704 /* Back from the dead for OS/2..... JRA. */
4706 /****************************************************************************
4707 Reply to a SMBwritebmpx (write block multiplex primary) request.
4708 ****************************************************************************/
4710 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4713 ssize_t nwritten
= -1;
4720 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4721 START_PROFILE(SMBwriteBmpx
);
4723 CHECK_FSP(fsp
,conn
);
4727 tcount
= SVAL(inbuf
,smb_vwv1
);
4728 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
4729 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
4730 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4731 smb_doff
= SVAL(inbuf
,smb_vwv11
);
4733 data
= smb_base(inbuf
) + smb_doff
;
4735 /* If this fails we need to send an SMBwriteC response,
4736 not an SMBwritebmpx - set this up now so we don't forget */
4737 SCVAL(outbuf
,smb_com
,SMBwritec
);
4739 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
,False
)) {
4740 END_PROFILE(SMBwriteBmpx
);
4741 return(ERROR_DOS(ERRDOS
,ERRlock
));
4744 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4746 if(lp_syncalways(SNUM(conn
)) || write_through
)
4747 sync_file(conn
,fsp
);
4749 if(nwritten
< (ssize_t
)numtowrite
) {
4750 END_PROFILE(SMBwriteBmpx
);
4751 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
4754 /* If the maximum to be written to this file
4755 is greater than what we just wrote then set
4756 up a secondary struct to be attached to this
4757 fd, we will use this to cache error messages etc. */
4759 if((ssize_t
)tcount
> nwritten
) {
4760 write_bmpx_struct
*wbms
;
4761 if(fsp
->wbmpx_ptr
!= NULL
)
4762 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
4764 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
4766 DEBUG(0,("Out of memory in reply_readmpx\n"));
4767 END_PROFILE(SMBwriteBmpx
);
4768 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
4770 wbms
->wr_mode
= write_through
;
4771 wbms
->wr_discard
= False
; /* No errors yet */
4772 wbms
->wr_total_written
= nwritten
;
4773 wbms
->wr_errclass
= 0;
4775 fsp
->wbmpx_ptr
= wbms
;
4778 /* We are returning successfully, set the message type back to
4780 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
4782 outsize
= set_message(outbuf
,1,0,True
);
4784 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
4786 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4787 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
4789 if (write_through
&& tcount
==nwritten
) {
4790 /* We need to send both a primary and a secondary response */
4791 smb_setlen(outbuf
,outsize
- 4);
4792 if (!send_smb(smbd_server_fd(),outbuf
))
4793 exit_server("reply_writebmpx: send_smb failed.");
4795 /* Now the secondary */
4796 outsize
= set_message(outbuf
,1,0,True
);
4797 SCVAL(outbuf
,smb_com
,SMBwritec
);
4798 SSVAL(outbuf
,smb_vwv0
,nwritten
);
4801 END_PROFILE(SMBwriteBmpx
);
4805 /****************************************************************************
4806 Reply to a SMBwritebs (write block multiplex secondary) request.
4807 ****************************************************************************/
4809 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4812 ssize_t nwritten
= -1;
4819 write_bmpx_struct
*wbms
;
4820 BOOL send_response
= False
;
4821 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4822 START_PROFILE(SMBwriteBs
);
4824 CHECK_FSP(fsp
,conn
);
4827 tcount
= SVAL(inbuf
,smb_vwv1
);
4828 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
4829 numtowrite
= SVAL(inbuf
,smb_vwv6
);
4830 smb_doff
= SVAL(inbuf
,smb_vwv7
);
4832 data
= smb_base(inbuf
) + smb_doff
;
4834 /* We need to send an SMBwriteC response, not an SMBwritebs */
4835 SCVAL(outbuf
,smb_com
,SMBwritec
);
4837 /* This fd should have an auxiliary struct attached,
4838 check that it does */
4839 wbms
= fsp
->wbmpx_ptr
;
4841 END_PROFILE(SMBwriteBs
);
4845 /* If write through is set we can return errors, else we must cache them */
4846 write_through
= wbms
->wr_mode
;
4848 /* Check for an earlier error */
4849 if(wbms
->wr_discard
) {
4850 END_PROFILE(SMBwriteBs
);
4851 return -1; /* Just discard the packet */
4854 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4856 if(lp_syncalways(SNUM(conn
)) || write_through
)
4857 sync_file(conn
,fsp
);
4859 if (nwritten
< (ssize_t
)numtowrite
) {
4861 /* We are returning an error - we can delete the aux struct */
4864 fsp
->wbmpx_ptr
= NULL
;
4865 END_PROFILE(SMBwriteBs
);
4866 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
4868 END_PROFILE(SMBwriteBs
);
4869 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4872 /* Increment the total written, if this matches tcount
4873 we can discard the auxiliary struct (hurrah !) and return a writeC */
4874 wbms
->wr_total_written
+= nwritten
;
4875 if(wbms
->wr_total_written
>= tcount
) {
4876 if (write_through
) {
4877 outsize
= set_message(outbuf
,1,0,True
);
4878 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4879 send_response
= True
;
4883 fsp
->wbmpx_ptr
= NULL
;
4887 END_PROFILE(SMBwriteBs
);
4891 END_PROFILE(SMBwriteBs
);
4895 /****************************************************************************
4896 Reply to a SMBgetattrE.
4897 ****************************************************************************/
4899 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4901 SMB_STRUCT_STAT sbuf
;
4904 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4905 START_PROFILE(SMBgetattrE
);
4907 outsize
= set_message(outbuf
,11,0,True
);
4909 if(!fsp
|| (fsp
->conn
!= conn
)) {
4910 END_PROFILE(SMBgetattrE
);
4911 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4914 /* Do an fstat on this file */
4915 if(fsp_stat(fsp
, &sbuf
)) {
4916 END_PROFILE(SMBgetattrE
);
4917 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4920 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4923 * Convert the times into dos times. Set create
4924 * date to be last modify date as UNIX doesn't save
4928 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4929 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4930 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4933 SIVAL(outbuf
,smb_vwv6
,0);
4934 SIVAL(outbuf
,smb_vwv8
,0);
4936 uint32 allocation_size
= get_allocation_size(fsp
, &sbuf
);
4937 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4938 SIVAL(outbuf
,smb_vwv8
,allocation_size
);
4940 SSVAL(outbuf
,smb_vwv10
, mode
);
4942 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
4944 END_PROFILE(SMBgetattrE
);