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 BOOL is_unix_charset_unsafe
;
38 extern int global_oplock_break
;
39 unsigned int smb_echo_count
= 0;
41 extern BOOL global_encrypted_passwords_negotiated
;
43 /****************************************************************************
44 Ensure we check the path in *exactly* the same way as W2K.
45 We're assuming here that '/' is not the second byte in any multibyte char
46 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
48 ****************************************************************************/
50 NTSTATUS
check_path_syntax(pstring destname
, const pstring srcname
)
53 const char *s
= srcname
;
54 NTSTATUS ret
= NT_STATUS_OK
;
57 if (IS_DIRECTORY_SEP(*s
)) {
59 * Safe to assume is not the second part of a mb char as this is handled below.
61 /* Eat multiple '/' or '\\' */
62 while (IS_DIRECTORY_SEP(*s
)) {
65 if ((d
!= destname
) && (*s
!= '\0')) {
66 /* We only care about non-leading or trailing '/' or '\\' */
69 } else if ((s
[0] == '.') && (s
[1] == '.') && (IS_DIRECTORY_SEP(s
[2]) || s
[2] == '\0')) {
70 /* Uh oh - "../" or "..\\" or "..\0" ! */
73 * No mb char starts with '.' so we're safe checking the directory separator here.
76 /* If we just added a '/', delete it. */
78 if ((d
> destname
) && (*(d
-1) == '/')) {
80 if (d
== (destname
+ 1)) {
86 /* Are we at the start ? Can't go back further if so. */
88 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
90 /* Go back one level... */
91 while (d
> destname
) {
97 } else if ((s
[0] == '.') && IS_DIRECTORY_SEP(s
[1])) {
100 * No mb char starts with '.' so we're safe checking the directory separator here.
103 /* "./" or ".\\" fails with a different error depending on where it is... */
106 ret
= NT_STATUS_OBJECT_NAME_INVALID
;
109 return NT_STATUS_INVALID_PARAMETER
;
111 ret
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
115 /* Activate this codepath only if we know that Unix charset may contain unsafe '\\' */
116 if ((is_unix_charset_unsafe
== True
) && ((*s
& 0x80) && IS_DIRECTORY_SEP(s
[1]))) {
118 * Potential mb char with second char a directory separator.
119 * All the encodings we care about are 2 byte only, so do a
120 * conversion to unicode. If the one byte char converts then
121 * it really is a directory separator following. Otherwise if
122 * the two byte character converts (and it should or our assumption
123 * about character sets is broken and we return an error) then copy both
124 * bytes as it's a MB character, not a directory separator.
129 if (convert_string(CH_UNIX
, CH_UCS2
, s
, 1, &ucs2_val
, 2, False
) == 2) {
131 } else if (convert_string(CH_UNIX
, CH_UCS2
, s
, 2, &ucs2_val
, 2, False
) == 2) {
134 DEBUG(0,("check_path_syntax: directory separator assumptions invalid !\n"));
135 return NT_STATUS_INVALID_PARAMETER
;
138 /* Just copy the char (or the second byte of the mb char). */
146 /****************************************************************************
147 Pull a string and check the path - provide for error return.
148 ****************************************************************************/
150 size_t srvstr_get_path(char *inbuf
, char *dest
, const char *src
, size_t dest_len
, size_t src_len
, int flags
, NTSTATUS
*err
)
153 char *tmppath_ptr
= tmppath
;
156 SMB_ASSERT(dest_len
== sizeof(pstring
));
160 ret
= srvstr_pull_buf( inbuf
, tmppath_ptr
, src
, dest_len
, flags
);
162 ret
= srvstr_pull( inbuf
, tmppath_ptr
, src
, dest_len
, src_len
, flags
);
164 *err
= check_path_syntax(dest
, tmppath
);
168 /****************************************************************************
169 Reply to a special message.
170 ****************************************************************************/
172 int reply_special(char *inbuf
,char *outbuf
)
175 int msg_type
= CVAL(inbuf
,0);
176 int msg_flags
= CVAL(inbuf
,1);
180 static BOOL already_got_session
= False
;
184 memset(outbuf
,'\0',smb_size
);
186 smb_setlen(outbuf
,0);
189 case 0x81: /* session request */
191 if (already_got_session
) {
192 exit_server("multiple session request not permitted");
195 SCVAL(outbuf
,0,0x82);
197 if (name_len(inbuf
+4) > 50 ||
198 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
199 DEBUG(0,("Invalid name length in session request\n"));
202 name_extract(inbuf
,4,name1
);
203 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
204 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
207 set_local_machine_name(name1
, True
);
208 set_remote_machine_name(name2
, True
);
210 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
211 get_local_machine_name(), get_remote_machine_name(),
214 if (name_type
== 'R') {
215 /* We are being asked for a pathworks session ---
217 SCVAL(outbuf
, 0,0x83);
221 /* only add the client's machine name to the list
222 of possibly valid usernames if we are operating
223 in share mode security */
224 if (lp_security() == SEC_SHARE
) {
225 add_session_user(get_remote_machine_name());
228 reload_services(True
);
231 claim_connection(NULL
,"",0,True
,FLAG_MSG_GENERAL
|FLAG_MSG_SMBD
);
233 already_got_session
= True
;
236 case 0x89: /* session keepalive request
237 (some old clients produce this?) */
238 SCVAL(outbuf
,0,SMBkeepalive
);
242 case 0x82: /* positive session response */
243 case 0x83: /* negative session response */
244 case 0x84: /* retarget session response */
245 DEBUG(0,("Unexpected session response\n"));
248 case SMBkeepalive
: /* session keepalive */
253 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
254 msg_type
, msg_flags
));
259 /****************************************************************************
261 ****************************************************************************/
263 int reply_tcon(connection_struct
*conn
,
264 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
271 uint16 vuid
= SVAL(inbuf
,smb_uid
);
275 DATA_BLOB password_blob
;
277 START_PROFILE(SMBtcon
);
279 *service_buf
= *password
= *dev
= 0;
281 p
= smb_buf(inbuf
)+1;
282 p
+= srvstr_pull_buf(inbuf
, service_buf
, p
, sizeof(service_buf
), STR_TERMINATE
) + 1;
283 pwlen
= srvstr_pull_buf(inbuf
, password
, p
, sizeof(password
), STR_TERMINATE
) + 1;
285 p
+= srvstr_pull_buf(inbuf
, dev
, p
, sizeof(dev
), STR_TERMINATE
) + 1;
287 p
= strrchr_m(service_buf
,'\\');
291 service
= service_buf
;
294 password_blob
= data_blob(password
, pwlen
+1);
296 conn
= make_connection(service
,password_blob
,dev
,vuid
,&nt_status
);
298 data_blob_clear_free(&password_blob
);
301 END_PROFILE(SMBtcon
);
302 return ERROR_NT(nt_status
);
305 outsize
= set_message(outbuf
,2,0,True
);
306 SSVAL(outbuf
,smb_vwv0
,max_recv
);
307 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
308 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
310 DEBUG(3,("tcon service=%s cnum=%d\n",
311 service
, conn
->cnum
));
313 END_PROFILE(SMBtcon
);
317 /****************************************************************************
318 Reply to a tcon and X.
319 ****************************************************************************/
321 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
326 /* what the cleint thinks the device is */
327 fstring client_devicetype
;
328 /* what the server tells the client the share represents */
329 const char *server_devicetype
;
331 uint16 vuid
= SVAL(inbuf
,smb_uid
);
332 int passlen
= SVAL(inbuf
,smb_vwv3
);
335 extern BOOL global_encrypted_passwords_negotiated
;
337 START_PROFILE(SMBtconX
);
339 *service
= *client_devicetype
= 0;
341 /* we might have to close an old one */
342 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
343 close_cnum(conn
,vuid
);
346 if (passlen
> MAX_PASS_LEN
) {
347 return ERROR_DOS(ERRDOS
,ERRbuftoosmall
);
350 if (global_encrypted_passwords_negotiated
) {
351 password
= data_blob(smb_buf(inbuf
),passlen
);
353 password
= data_blob(smb_buf(inbuf
),passlen
+1);
354 /* Ensure correct termination */
355 password
.data
[passlen
]=0;
358 p
= smb_buf(inbuf
) + passlen
;
359 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
362 * the service name can be either: \\server\share
363 * or share directly like on the DELL PowerVault 705
366 q
= strchr_m(path
+2,'\\');
368 END_PROFILE(SMBtconX
);
369 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
371 fstrcpy(service
,q
+1);
374 fstrcpy(service
,path
);
376 p
+= srvstr_pull(inbuf
, client_devicetype
, p
, sizeof(client_devicetype
), 6, STR_ASCII
);
378 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
380 conn
= make_connection(service
,password
,client_devicetype
,vuid
,&nt_status
);
382 data_blob_clear_free(&password
);
385 END_PROFILE(SMBtconX
);
386 return ERROR_NT(nt_status
);
390 server_devicetype
= "IPC";
391 else if ( IS_PRINT(conn
) )
392 server_devicetype
= "LPT1:";
394 server_devicetype
= "A:";
396 if (Protocol
< PROTOCOL_NT1
) {
397 set_message(outbuf
,2,0,True
);
399 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
400 STR_TERMINATE
|STR_ASCII
);
401 set_message_end(outbuf
,p
);
403 /* NT sets the fstype of IPC$ to the null string */
404 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
406 set_message(outbuf
,3,0,True
);
409 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
410 STR_TERMINATE
|STR_ASCII
);
411 p
+= srvstr_push(outbuf
, p
, fstype
, -1,
414 set_message_end(outbuf
,p
);
416 /* what does setting this bit do? It is set by NT4 and
417 may affect the ability to autorun mounted cdroms */
418 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
419 (lp_csc_policy(SNUM(conn
)) << 2));
421 init_dfsroot(conn
, inbuf
, outbuf
);
425 DEBUG(3,("tconX service=%s \n",
428 /* set the incoming and outgoing tid to the just created one */
429 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
430 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
432 END_PROFILE(SMBtconX
);
433 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
436 /****************************************************************************
437 Reply to an unknown type.
438 ****************************************************************************/
440 int reply_unknown(char *inbuf
,char *outbuf
)
443 type
= CVAL(inbuf
,smb_com
);
445 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
446 smb_fn_name(type
), type
, type
));
448 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
451 /****************************************************************************
453 ****************************************************************************/
455 int reply_ioctl(connection_struct
*conn
,
456 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
458 uint16 device
= SVAL(inbuf
,smb_vwv1
);
459 uint16 function
= SVAL(inbuf
,smb_vwv2
);
460 uint32 ioctl_code
= (device
<< 16) + function
;
461 int replysize
, outsize
;
463 START_PROFILE(SMBioctl
);
465 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
467 switch (ioctl_code
) {
468 case IOCTL_QUERY_JOB_INFO
:
472 END_PROFILE(SMBioctl
);
473 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
476 outsize
= set_message(outbuf
,8,replysize
+1,True
);
477 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
478 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
479 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
480 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
482 switch (ioctl_code
) {
483 case IOCTL_QUERY_JOB_INFO
:
485 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
487 END_PROFILE(SMBioctl
);
488 return(UNIXERROR(ERRDOS
,ERRbadfid
));
490 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
491 srvstr_push(outbuf
, p
+2, global_myname(), 15, STR_TERMINATE
|STR_ASCII
);
492 srvstr_push(outbuf
, p
+18, lp_servicename(SNUM(conn
)), 13, STR_TERMINATE
|STR_ASCII
);
497 END_PROFILE(SMBioctl
);
501 /****************************************************************************
503 ****************************************************************************/
505 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
511 BOOL bad_path
= False
;
512 SMB_STRUCT_STAT sbuf
;
515 START_PROFILE(SMBchkpth
);
517 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
);
518 if (!NT_STATUS_IS_OK(status
)) {
519 END_PROFILE(SMBchkpth
);
520 return ERROR_NT(status
);
523 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
525 unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
527 mode
= SVAL(inbuf
,smb_vwv0
);
529 if (check_name(name
,conn
)) {
530 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,name
,&sbuf
) == 0)
531 if (!(ok
= S_ISDIR(sbuf
.st_mode
))) {
532 END_PROFILE(SMBchkpth
);
533 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY
,ERRDOS
,ERRbadpath
);
538 /* We special case this - as when a Windows machine
539 is parsing a path is steps through the components
540 one at a time - if a component fails it expects
541 ERRbadpath, not ERRbadfile.
543 if(errno
== ENOENT
) {
545 * Windows returns different error codes if
546 * the parent directory is valid but not the
547 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
548 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
549 * if the path is invalid.
552 END_PROFILE(SMBchkpth
);
553 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
555 END_PROFILE(SMBchkpth
);
556 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND
);
558 } else if (errno
== ENOTDIR
) {
559 END_PROFILE(SMBchkpth
);
560 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY
);
563 END_PROFILE(SMBchkpth
);
564 return(UNIXERROR(ERRDOS
,ERRbadpath
));
567 outsize
= set_message(outbuf
,0,0,True
);
569 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
571 END_PROFILE(SMBchkpth
);
575 /****************************************************************************
577 ****************************************************************************/
579 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
583 SMB_STRUCT_STAT sbuf
;
588 BOOL bad_path
= False
;
592 START_PROFILE(SMBgetatr
);
594 p
= smb_buf(inbuf
) + 1;
595 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
596 if (!NT_STATUS_IS_OK(status
)) {
597 END_PROFILE(SMBgetatr
);
598 return ERROR_NT(status
);
601 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
603 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
604 under WfWg - weird! */
606 mode
= aHIDDEN
| aDIR
;
607 if (!CAN_WRITE(conn
))
613 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
614 if (check_name(fname
,conn
)) {
615 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,fname
,&sbuf
) == 0) {
616 mode
= dos_mode(conn
,fname
,&sbuf
);
618 mtime
= sbuf
.st_mtime
;
623 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
629 END_PROFILE(SMBgetatr
);
630 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadfile
);
633 outsize
= set_message(outbuf
,10,0,True
);
635 SSVAL(outbuf
,smb_vwv0
,mode
);
636 if(lp_dos_filetime_resolution(SNUM(conn
)) )
637 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
639 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
640 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
642 if (Protocol
>= PROTOCOL_NT1
)
643 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
645 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
647 END_PROFILE(SMBgetatr
);
651 /****************************************************************************
653 ****************************************************************************/
655 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
662 SMB_STRUCT_STAT sbuf
;
663 BOOL bad_path
= False
;
667 START_PROFILE(SMBsetatr
);
669 p
= smb_buf(inbuf
) + 1;
670 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), 0, STR_TERMINATE
, &status
);
671 if (!NT_STATUS_IS_OK(status
)) {
672 END_PROFILE(SMBsetatr
);
673 return ERROR_NT(status
);
676 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
678 mode
= SVAL(inbuf
,smb_vwv0
);
679 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
681 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
682 if (VALID_STAT_OF_DIR(sbuf
))
687 if (check_name(fname
,conn
))
688 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
694 ok
= set_filetime(conn
,fname
,mtime
);
697 END_PROFILE(SMBsetatr
);
698 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
701 outsize
= set_message(outbuf
,0,0,True
);
703 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
705 END_PROFILE(SMBsetatr
);
709 /****************************************************************************
711 ****************************************************************************/
713 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
716 SMB_BIG_UINT dfree
,dsize
,bsize
;
717 START_PROFILE(SMBdskattr
);
719 SMB_VFS_DISK_FREE(conn
,".",True
,&bsize
,&dfree
,&dsize
);
721 outsize
= set_message(outbuf
,5,0,True
);
723 if (Protocol
<= PROTOCOL_LANMAN2
) {
724 double total_space
, free_space
;
725 /* we need to scale this to a number that DOS6 can handle. We
726 use floating point so we can handle large drives on systems
727 that don't have 64 bit integers
729 we end up displaying a maximum of 2G to DOS systems
731 total_space
= dsize
* (double)bsize
;
732 free_space
= dfree
* (double)bsize
;
734 dsize
= (total_space
+63*512) / (64*512);
735 dfree
= (free_space
+63*512) / (64*512);
737 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
738 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
740 SSVAL(outbuf
,smb_vwv0
,dsize
);
741 SSVAL(outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
742 SSVAL(outbuf
,smb_vwv2
,512); /* and this must be 512 */
743 SSVAL(outbuf
,smb_vwv3
,dfree
);
745 SSVAL(outbuf
,smb_vwv0
,dsize
);
746 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
747 SSVAL(outbuf
,smb_vwv2
,512);
748 SSVAL(outbuf
,smb_vwv3
,dfree
);
751 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
753 END_PROFILE(SMBdskattr
);
757 /****************************************************************************
759 Can be called from SMBsearch, SMBffirst or SMBfunique.
760 ****************************************************************************/
762 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
772 unsigned int numentries
= 0;
773 unsigned int maxentries
= 0;
774 BOOL finished
= False
;
781 BOOL check_descend
= False
;
782 BOOL expect_close
= False
;
783 BOOL can_open
= True
;
784 BOOL bad_path
= False
;
786 START_PROFILE(SMBsearch
);
788 *mask
= *directory
= *fname
= 0;
790 /* If we were called as SMBffirst then we must expect close. */
791 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
794 outsize
= set_message(outbuf
,1,3,True
);
795 maxentries
= SVAL(inbuf
,smb_vwv0
);
796 dirtype
= SVAL(inbuf
,smb_vwv1
);
797 p
= smb_buf(inbuf
) + 1;
798 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &nt_status
);
799 if (!NT_STATUS_IS_OK(nt_status
)) {
800 END_PROFILE(SMBsearch
);
801 return ERROR_NT(nt_status
);
804 status_len
= SVAL(p
, 0);
807 /* dirtype &= ~aDIR; */
809 if (status_len
== 0) {
810 SMB_STRUCT_STAT sbuf
;
813 pstrcpy(directory
,path
);
815 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
818 if (!check_name(directory
,conn
))
821 p
= strrchr_m(dir2
,'/');
830 p
= strrchr_m(directory
,'/');
836 if (strlen(directory
) == 0)
837 pstrcpy(directory
,".");
838 memset((char *)status
,'\0',21);
839 SCVAL(status
,0,(dirtype
& 0x1F));
844 status_dirtype
= CVAL(status
,0) & 0x1F;
845 if (status_dirtype
!= (dirtype
& 0x1F))
846 dirtype
= status_dirtype
;
848 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
851 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
852 pstrcpy(mask
, dptr_wcard(dptr_num
));
856 p
= smb_buf(outbuf
) + 3;
859 if (status_len
== 0) {
860 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
863 END_PROFILE(SMBsearch
);
864 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnofids
);
866 END_PROFILE(SMBsearch
);
867 return ERROR_DOS(ERRDOS
,ERRnofids
);
869 dptr_set_wcard(dptr_num
, strdup(mask
));
870 dptr_set_attr(dptr_num
, dirtype
);
872 dirtype
= dptr_attr(dptr_num
);
875 DEBUG(4,("dptr_num is %d\n",dptr_num
));
878 if ((dirtype
&0x1F) == aVOLID
) {
880 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
881 dptr_fill(p
+12,dptr_num
);
882 if (dptr_zero(p
+12) && (status_len
==0))
886 p
+= DIR_STRUCT_SIZE
;
889 maxentries
= MIN(maxentries
, ((BUFFER_SIZE
- (p
- outbuf
))/DIR_STRUCT_SIZE
));
891 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
892 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
893 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
894 check_descend
= True
;
896 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
897 finished
= !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
900 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
901 dptr_fill(p
+12,dptr_num
);
904 p
+= DIR_STRUCT_SIZE
;
913 /* If we were called as SMBffirst with smb_search_id == NULL
914 and no entries were found then return error and close dirptr
917 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0) {
918 if (Protocol
< PROTOCOL_NT1
) {
919 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
920 SSVAL(outbuf
,smb_err
,ERRnofiles
);
922 /* Also close the dptr - we know it's gone */
923 dptr_close(&dptr_num
);
924 } else if (numentries
== 0 || !ok
) {
925 if (Protocol
< PROTOCOL_NT1
) {
926 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
927 SSVAL(outbuf
,smb_err
,ERRnofiles
);
929 dptr_close(&dptr_num
);
932 /* If we were called as SMBfunique, then we can close the dirptr now ! */
933 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
934 dptr_close(&dptr_num
);
936 SSVAL(outbuf
,smb_vwv0
,numentries
);
937 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
938 SCVAL(smb_buf(outbuf
),0,5);
939 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
941 if (Protocol
>= PROTOCOL_NT1
)
942 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
944 outsize
+= DIR_STRUCT_SIZE
*numentries
;
945 smb_setlen(outbuf
,outsize
- 4);
947 if ((! *directory
) && dptr_path(dptr_num
))
948 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
950 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
951 smb_fn_name(CVAL(inbuf
,smb_com
)),
952 mask
, directory
, dirtype
, numentries
, maxentries
) );
954 END_PROFILE(SMBsearch
);
958 /****************************************************************************
959 Reply to a fclose (stop directory search).
960 ****************************************************************************/
962 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
972 START_PROFILE(SMBfclose
);
974 outsize
= set_message(outbuf
,1,0,True
);
975 p
= smb_buf(inbuf
) + 1;
976 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), 0, STR_TERMINATE
, &err
);
977 if (!NT_STATUS_IS_OK(err
)) {
978 END_PROFILE(SMBfclose
);
979 return ERROR_NT(err
);
982 status_len
= SVAL(p
,0);
985 if (status_len
== 0) {
986 END_PROFILE(SMBfclose
);
987 return ERROR_DOS(ERRSRV
,ERRsrverror
);
992 if(dptr_fetch(status
+12,&dptr_num
)) {
993 /* Close the dptr - we know it's gone */
994 dptr_close(&dptr_num
);
997 SSVAL(outbuf
,smb_vwv0
,0);
999 DEBUG(3,("search close\n"));
1001 END_PROFILE(SMBfclose
);
1005 /****************************************************************************
1007 ****************************************************************************/
1009 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1019 SMB_STRUCT_STAT sbuf
;
1020 BOOL bad_path
= False
;
1022 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1024 START_PROFILE(SMBopen
);
1026 share_mode
= SVAL(inbuf
,smb_vwv0
);
1028 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1029 if (!NT_STATUS_IS_OK(status
)) {
1030 END_PROFILE(SMBopen
);
1031 return ERROR_NT(status
);
1034 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1036 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1038 unixmode
= unix_mode(conn
,aARCH
,fname
);
1040 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1041 unixmode
, oplock_request
,&rmode
,NULL
);
1044 END_PROFILE(SMBopen
);
1045 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1048 size
= sbuf
.st_size
;
1049 fmode
= dos_mode(conn
,fname
,&sbuf
);
1050 mtime
= sbuf
.st_mtime
;
1053 DEBUG(3,("attempt to open a directory %s\n",fname
));
1054 close_file(fsp
,False
);
1055 END_PROFILE(SMBopen
);
1056 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1059 outsize
= set_message(outbuf
,7,0,True
);
1060 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1061 SSVAL(outbuf
,smb_vwv1
,fmode
);
1062 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1063 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1065 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1066 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1067 SSVAL(outbuf
,smb_vwv6
,rmode
);
1069 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1070 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1072 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1073 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1074 END_PROFILE(SMBopen
);
1078 /****************************************************************************
1079 Reply to an open and X.
1080 ****************************************************************************/
1082 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1085 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1086 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1087 /* Breakout the oplock request bits so we can set the
1088 reply bits separately. */
1089 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1090 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1091 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1093 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1094 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1095 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1097 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1100 int fmode
=0,mtime
=0,rmode
=0;
1101 SMB_STRUCT_STAT sbuf
;
1103 BOOL bad_path
= False
;
1106 START_PROFILE(SMBopenX
);
1108 /* If it's an IPC, pass off the pipe handler. */
1110 if (lp_nt_pipe_support()) {
1111 END_PROFILE(SMBopenX
);
1112 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1114 END_PROFILE(SMBopenX
);
1115 return ERROR_DOS(ERRSRV
,ERRaccess
);
1119 /* XXXX we need to handle passed times, sattr and flags */
1120 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
), sizeof(fname
), 0, STR_TERMINATE
, &status
);
1121 if (!NT_STATUS_IS_OK(status
)) {
1122 END_PROFILE(SMBopenX
);
1123 return ERROR_NT(status
);
1126 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1128 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1130 unixmode
= unix_mode(conn
,smb_attr
| aARCH
, fname
);
1132 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,unixmode
,
1133 oplock_request
, &rmode
,&smb_action
);
1136 END_PROFILE(SMBopenX
);
1137 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1140 size
= sbuf
.st_size
;
1141 fmode
= dos_mode(conn
,fname
,&sbuf
);
1142 mtime
= sbuf
.st_mtime
;
1144 close_file(fsp
,False
);
1145 END_PROFILE(SMBopenX
);
1146 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1149 /* If the caller set the extended oplock request bit
1150 and we granted one (by whatever means) - set the
1151 correct bit for extended oplock reply.
1154 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1155 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1157 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1158 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1160 /* If the caller set the core oplock request bit
1161 and we granted one (by whatever means) - set the
1162 correct bit for core oplock reply.
1165 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1166 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1168 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1169 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1171 set_message(outbuf
,15,0,True
);
1172 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1173 SSVAL(outbuf
,smb_vwv3
,fmode
);
1174 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1175 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1177 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1178 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1179 SSVAL(outbuf
,smb_vwv8
,rmode
);
1180 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1182 END_PROFILE(SMBopenX
);
1183 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1186 /****************************************************************************
1187 Reply to a SMBulogoffX.
1188 ****************************************************************************/
1190 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1192 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1193 user_struct
*vuser
= get_valid_user_struct(vuid
);
1194 START_PROFILE(SMBulogoffX
);
1197 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1199 /* in user level security we are supposed to close any files
1200 open by this user */
1201 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
))
1202 file_close_user(vuid
);
1204 invalidate_vuid(vuid
);
1206 set_message(outbuf
,2,0,True
);
1208 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1210 END_PROFILE(SMBulogoffX
);
1211 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1214 /****************************************************************************
1215 Reply to a mknew or a create.
1216 ****************************************************************************/
1218 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1226 BOOL bad_path
= False
;
1228 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1229 SMB_STRUCT_STAT sbuf
;
1231 START_PROFILE(SMBcreate
);
1233 com
= SVAL(inbuf
,smb_com
);
1235 createmode
= SVAL(inbuf
,smb_vwv0
);
1236 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
) + 1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1237 if (!NT_STATUS_IS_OK(status
)) {
1238 END_PROFILE(SMBcreate
);
1239 return ERROR_NT(status
);
1242 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1244 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1246 if (createmode
& aVOLID
)
1247 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1249 unixmode
= unix_mode(conn
,createmode
,fname
);
1251 if(com
== SMBmknew
) {
1252 /* We should fail if file exists. */
1253 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1255 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1256 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1259 /* Open file in dos compatibility share mode. */
1260 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1261 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1264 END_PROFILE(SMBcreate
);
1265 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1268 outsize
= set_message(outbuf
,1,0,True
);
1269 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1271 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1272 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1274 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1275 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1277 DEBUG( 2, ( "new file %s\n", fname
) );
1278 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1280 END_PROFILE(SMBcreate
);
1284 /****************************************************************************
1285 Reply to a create temporary file.
1286 ****************************************************************************/
1288 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1294 BOOL bad_path
= False
;
1296 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1298 SMB_STRUCT_STAT sbuf
;
1302 START_PROFILE(SMBctemp
);
1304 createmode
= SVAL(inbuf
,smb_vwv0
);
1305 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), 0, STR_TERMINATE
, &status
);
1306 if (!NT_STATUS_IS_OK(status
)) {
1307 END_PROFILE(SMBctemp
);
1308 return ERROR_NT(status
);
1310 pstrcat(fname
,"\\TMXXXXXX");
1312 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1314 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1316 unixmode
= unix_mode(conn
,createmode
,fname
);
1318 tmpfd
= smb_mkstemp(fname
);
1320 END_PROFILE(SMBctemp
);
1321 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1324 SMB_VFS_STAT(conn
,fname
,&sbuf
);
1326 /* Open file in dos compatibility share mode. */
1327 /* We should fail if file does not exist. */
1328 fsp
= open_file_shared(conn
,fname
,&sbuf
,
1329 SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1330 FILE_EXISTS_OPEN
|FILE_FAIL_IF_NOT_EXIST
,
1331 unixmode
, oplock_request
, NULL
, NULL
);
1333 /* close fd from smb_mkstemp() */
1337 END_PROFILE(SMBctemp
);
1338 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1341 outsize
= set_message(outbuf
,1,0,True
);
1342 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1344 /* the returned filename is relative to the directory */
1345 s
= strrchr_m(fname
, '/');
1351 p
= smb_buf(outbuf
);
1352 SSVALS(p
, 0, -1); /* what is this? not in spec */
1353 SSVAL(p
, 2, strlen(s
));
1355 p
+= srvstr_push(outbuf
, p
, s
, -1, STR_ASCII
);
1356 outsize
= set_message_end(outbuf
, p
);
1358 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1359 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1361 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1362 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1364 DEBUG( 2, ( "created temp file %s\n", fname
) );
1365 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1366 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1368 END_PROFILE(SMBctemp
);
1372 /*******************************************************************
1373 Check if a user is allowed to rename a file.
1374 ********************************************************************/
1376 static NTSTATUS
can_rename(char *fname
,connection_struct
*conn
, SMB_STRUCT_STAT
*pst
)
1382 if (!CAN_WRITE(conn
))
1383 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1385 if (S_ISDIR(pst
->st_mode
))
1386 return NT_STATUS_OK
;
1388 /* We need a better way to return NT status codes from open... */
1392 fsp
= open_file_shared1(conn
, fname
, pst
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1393 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1396 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1397 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1398 ret
= NT_STATUS_SHARING_VIOLATION
;
1401 unix_ERR_ntstatus
= NT_STATUS_OK
;
1404 close_file(fsp
,False
);
1405 return NT_STATUS_OK
;
1408 /*******************************************************************
1409 Check if a user is allowed to delete a file.
1410 ********************************************************************/
1412 static NTSTATUS
can_delete(char *fname
,connection_struct
*conn
, int dirtype
, BOOL bad_path
)
1414 SMB_STRUCT_STAT sbuf
;
1420 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1423 if (!CAN_WRITE(conn
))
1424 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1426 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
) != 0) {
1427 if(errno
== ENOENT
) {
1429 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1431 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1433 return map_nt_error_from_unix(errno
);
1436 fmode
= dos_mode(conn
,fname
,&sbuf
);
1438 /* Can't delete a directory. */
1440 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1442 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
1443 return NT_STATUS_OBJECT_NAME_INVALID
;
1444 #endif /* JRATEST */
1446 if (!lp_delete_readonly(SNUM(conn
))) {
1448 return NT_STATUS_CANNOT_DELETE
;
1450 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1451 return NT_STATUS_NO_SUCH_FILE
;
1453 /* We need a better way to return NT status codes from open... */
1457 fsp
= open_file_shared1(conn
, fname
, &sbuf
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1458 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1461 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1462 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus
))
1463 ret
= unix_ERR_ntstatus
;
1464 else if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1465 ret
= NT_STATUS_SHARING_VIOLATION
;
1468 unix_ERR_ntstatus
= NT_STATUS_OK
;
1471 close_file(fsp
,False
);
1472 return NT_STATUS_OK
;
1475 /****************************************************************************
1476 The guts of the unlink command, split out so it may be called by the NT SMB
1478 ****************************************************************************/
1480 NTSTATUS
unlink_internals(connection_struct
*conn
, int dirtype
, char *name
)
1486 NTSTATUS error
= NT_STATUS_OK
;
1488 BOOL bad_path
= False
;
1490 SMB_STRUCT_STAT sbuf
;
1492 *directory
= *mask
= 0;
1494 /* We must check for wildcards in the name given
1495 * directly by the client - before any unmangling.
1496 * This prevents an unmangling of a UNIX name containing
1497 * a DOS wildcard like '*' or '?' from unmangling into
1498 * a wildcard delete which was not intended.
1499 * FIX for #226. JRA.
1502 has_wild
= ms_has_wild(name
);
1504 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1506 p
= strrchr_m(name
,'/');
1508 pstrcpy(directory
,".");
1512 pstrcpy(directory
,name
);
1517 * We should only check the mangled cache
1518 * here if unix_convert failed. This means
1519 * that the path in 'mask' doesn't exist
1520 * on the file system and so we need to look
1521 * for a possible mangle. This patch from
1522 * Tine Smukavec <valentin.smukavec@hermes.si>.
1525 if (!rc
&& mangle_is_mangled(mask
))
1526 mangle_check_cache( mask
);
1529 pstrcat(directory
,"/");
1530 pstrcat(directory
,mask
);
1531 error
= can_delete(directory
,conn
,dirtype
,bad_path
);
1532 if (!NT_STATUS_IS_OK(error
))
1535 if (SMB_VFS_UNLINK(conn
,directory
) == 0) {
1539 void *dirptr
= NULL
;
1542 if (check_name(directory
,conn
))
1543 dirptr
= OpenDir(conn
, directory
, True
);
1545 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1546 the pattern matches against the long name, otherwise the short name
1547 We don't implement this yet XXXX
1551 error
= NT_STATUS_NO_SUCH_FILE
;
1553 if (strequal(mask
,"????????.???"))
1556 while ((dname
= ReadDirName(dirptr
))) {
1558 BOOL sys_direntry
= False
;
1559 pstrcpy(fname
,dname
);
1561 /* Quick check for "." and ".." */
1562 if (fname
[0] == '.') {
1563 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
1564 if ((dirtype
& aDIR
)) {
1565 sys_direntry
= True
;
1572 if(!mask_match(fname
, mask
, case_sensitive
))
1576 error
= NT_STATUS_OBJECT_NAME_INVALID
;
1580 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1581 error
= can_delete(fname
,conn
,dirtype
,bad_path
);
1582 if (!NT_STATUS_IS_OK(error
))
1584 if (SMB_VFS_UNLINK(conn
,fname
) == 0)
1586 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
1592 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
1593 error
= map_nt_error_from_unix(errno
);
1599 /****************************************************************************
1601 ****************************************************************************/
1603 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
1610 START_PROFILE(SMBunlink
);
1612 dirtype
= SVAL(inbuf
,smb_vwv0
);
1614 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), 0, STR_TERMINATE
, &status
);
1615 if (!NT_STATUS_IS_OK(status
)) {
1616 END_PROFILE(SMBunlink
);
1617 return ERROR_NT(status
);
1620 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
1622 DEBUG(3,("reply_unlink : %s\n",name
));
1624 status
= unlink_internals(conn
, dirtype
, name
);
1625 if (!NT_STATUS_IS_OK(status
))
1626 return ERROR_NT(status
);
1629 * Win2k needs a changenotify request response before it will
1630 * update after a rename..
1632 process_pending_change_notify_queue((time_t)0);
1634 outsize
= set_message(outbuf
,0,0,True
);
1636 END_PROFILE(SMBunlink
);
1640 /****************************************************************************
1642 ****************************************************************************/
1644 void fail_readraw(void)
1647 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1649 exit_server(errstr
);
1652 /****************************************************************************
1653 Use sendfile in readbraw.
1654 ****************************************************************************/
1656 void send_file_readbraw(connection_struct
*conn
, files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
,
1657 ssize_t mincount
, char *outbuf
)
1661 #if defined(WITH_SENDFILE)
1663 * We can only use sendfile on a non-chained packet and on a file
1664 * that is exclusively oplocked. reply_readbraw has already checked the length.
1667 if ((nread
> 0) && (lp_write_cache_size(SNUM(conn
)) == 0) &&
1668 EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) && lp_use_sendfile(SNUM(conn
)) ) {
1671 _smb_setlen(outbuf
,nread
);
1672 header
.data
= outbuf
;
1676 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, nread
) == -1) {
1678 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1679 * return ENOSYS then pretend we just got a normal read.
1681 if (errno
== ENOSYS
)
1684 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1685 fsp
->fsp_name
, strerror(errno
) ));
1686 exit_server("send_file_readbraw sendfile failed");
1695 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
1696 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1705 _smb_setlen(outbuf
,ret
);
1706 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
1710 /****************************************************************************
1711 Reply to a readbraw (core+ protocol).
1712 ****************************************************************************/
1714 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1716 extern struct current_user current_user
;
1717 ssize_t maxcount
,mincount
;
1720 char *header
= outbuf
;
1722 START_PROFILE(SMBreadbraw
);
1724 if (srv_is_signing_active()) {
1725 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1729 * Special check if an oplock break has been issued
1730 * and the readraw request croses on the wire, we must
1731 * return a zero length response here.
1734 if(global_oplock_break
) {
1735 _smb_setlen(header
,0);
1736 if (write_data(smbd_server_fd(),header
,4) != 4)
1738 DEBUG(5,("readbraw - oplock break finished\n"));
1739 END_PROFILE(SMBreadbraw
);
1743 fsp
= file_fsp(inbuf
,smb_vwv0
);
1745 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1747 * fsp could be NULL here so use the value from the packet. JRA.
1749 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
1750 _smb_setlen(header
,0);
1751 if (write_data(smbd_server_fd(),header
,4) != 4)
1753 END_PROFILE(SMBreadbraw
);
1757 CHECK_FSP(fsp
,conn
);
1759 flush_write_cache(fsp
, READRAW_FLUSH
);
1761 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
1762 if(CVAL(inbuf
,smb_wct
) == 10) {
1764 * This is a large offset (64 bit) read.
1766 #ifdef LARGE_SMB_OFF_T
1768 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
1770 #else /* !LARGE_SMB_OFF_T */
1773 * Ensure we haven't been sent a >32 bit offset.
1776 if(IVAL(inbuf
,smb_vwv8
) != 0) {
1777 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1778 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
1779 _smb_setlen(header
,0);
1780 if (write_data(smbd_server_fd(),header
,4) != 4)
1782 END_PROFILE(SMBreadbraw
);
1786 #endif /* LARGE_SMB_OFF_T */
1789 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
1790 _smb_setlen(header
,0);
1791 if (write_data(smbd_server_fd(),header
,4) != 4)
1793 END_PROFILE(SMBreadbraw
);
1797 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
1798 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
1800 /* ensure we don't overrun the packet size */
1801 maxcount
= MIN(65535,maxcount
);
1803 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1804 SMB_OFF_T size
= fsp
->size
;
1805 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
1807 if (size
< sizeneeded
) {
1809 if (SMB_VFS_FSTAT(fsp
,fsp
->fd
,&st
) == 0)
1811 if (!fsp
->can_write
)
1815 if (startpos
>= size
)
1818 nread
= MIN(maxcount
,(size
- startpos
));
1821 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1822 if (nread
< mincount
)
1826 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp
->fnum
, (double)startpos
,
1827 (int)maxcount
, (int)mincount
, (int)nread
) );
1829 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
, outbuf
);
1831 DEBUG(5,("readbraw finished\n"));
1832 END_PROFILE(SMBreadbraw
);
1836 /****************************************************************************
1837 Reply to a lockread (core+ protocol).
1838 ****************************************************************************/
1840 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
1848 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1849 BOOL my_lock_ctx
= False
;
1850 START_PROFILE(SMBlockread
);
1852 CHECK_FSP(fsp
,conn
);
1855 release_level_2_oplocks_on_change(fsp
);
1857 numtoread
= SVAL(inbuf
,smb_vwv1
);
1858 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1860 outsize
= set_message(outbuf
,5,3,True
);
1861 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1862 data
= smb_buf(outbuf
) + 3;
1865 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1866 * protocol request that predates the read/write lock concept.
1867 * Thus instead of asking for a read lock here we need to ask
1868 * for a write lock. JRA.
1869 * Note that the requested lock size is unaffected by max_recv.
1872 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
),
1873 (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
, &my_lock_ctx
);
1875 if (NT_STATUS_V(status
)) {
1878 * We used to make lockread a blocking lock. It turns out
1879 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1883 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
1885 * A blocking lock was requested. Package up
1886 * this smb into a queued request and push it
1887 * onto the blocking lock queue.
1889 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)startpos
,
1890 (SMB_BIG_UINT
)numtoread
)) {
1891 END_PROFILE(SMBlockread
);
1896 END_PROFILE(SMBlockread
);
1897 return ERROR_NT(status
);
1901 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1904 if (numtoread
> max_recv
) {
1905 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1906 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1907 (unsigned int)numtoread
, (unsigned int)max_recv
));
1908 numtoread
= MIN(numtoread
,max_recv
);
1910 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1913 END_PROFILE(SMBlockread
);
1914 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1918 SSVAL(outbuf
,smb_vwv0
,nread
);
1919 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1920 SSVAL(smb_buf(outbuf
),1,nread
);
1922 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1923 fsp
->fnum
, (int)numtoread
, (int)nread
));
1925 END_PROFILE(SMBlockread
);
1929 /****************************************************************************
1931 ****************************************************************************/
1933 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
1940 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1941 START_PROFILE(SMBread
);
1943 CHECK_FSP(fsp
,conn
);
1946 numtoread
= SVAL(inbuf
,smb_vwv1
);
1947 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1949 outsize
= set_message(outbuf
,5,3,True
);
1950 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1952 * The requested read size cannot be greater than max_recv. JRA.
1954 if (numtoread
> max_recv
) {
1955 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1956 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1957 (unsigned int)numtoread
, (unsigned int)max_recv
));
1958 numtoread
= MIN(numtoread
,max_recv
);
1961 data
= smb_buf(outbuf
) + 3;
1963 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1964 END_PROFILE(SMBread
);
1965 return ERROR_DOS(ERRDOS
,ERRlock
);
1969 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1972 END_PROFILE(SMBread
);
1973 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1977 SSVAL(outbuf
,smb_vwv0
,nread
);
1978 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1979 SCVAL(smb_buf(outbuf
),0,1);
1980 SSVAL(smb_buf(outbuf
),1,nread
);
1982 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1983 fsp
->fnum
, (int)numtoread
, (int)nread
) );
1985 END_PROFILE(SMBread
);
1989 /****************************************************************************
1990 Reply to a read and X - possibly using sendfile.
1991 ****************************************************************************/
1993 int send_file_readX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,
1994 files_struct
*fsp
, SMB_OFF_T startpos
, size_t smb_maxcnt
)
1997 char *data
= smb_buf(outbuf
);
1999 #if defined(WITH_SENDFILE)
2001 * We can only use sendfile on a non-chained packet and on a file
2002 * that is exclusively oplocked.
2005 if ((CVAL(inbuf
,smb_vwv0
) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) &&
2006 lp_use_sendfile(SNUM(conn
)) && (lp_write_cache_size(SNUM(conn
)) == 0) ) {
2007 SMB_STRUCT_STAT sbuf
;
2010 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1)
2011 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2013 if (startpos
> sbuf
.st_size
)
2016 if (smb_maxcnt
> (sbuf
.st_size
- startpos
))
2017 smb_maxcnt
= (sbuf
.st_size
- startpos
);
2019 if (smb_maxcnt
== 0)
2023 * Set up the packet header before send. We
2024 * assume here the sendfile will work (get the
2025 * correct amount of data).
2028 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2029 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
2030 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2031 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
2032 SCVAL(outbuf
,smb_vwv0
,0xFF);
2033 set_message(outbuf
,12,smb_maxcnt
,False
);
2034 header
.data
= outbuf
;
2035 header
.length
= data
- outbuf
;
2038 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, smb_maxcnt
) == -1) {
2040 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2041 * return ENOSYS then pretend we just got a normal read.
2043 if (errno
== ENOSYS
)
2046 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2047 fsp
->fsp_name
, strerror(errno
) ));
2048 exit_server("send_file_readX sendfile failed");
2051 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2052 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2060 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2063 END_PROFILE(SMBreadX
);
2064 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2067 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
2068 SSVAL(outbuf
,smb_vwv5
,nread
);
2069 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2070 SSVAL(smb_buf(outbuf
),-2,nread
);
2072 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2073 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2078 /****************************************************************************
2079 Reply to a read and X.
2080 ****************************************************************************/
2082 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2084 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2085 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2087 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2089 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2092 START_PROFILE(SMBreadX
);
2094 /* If it's an IPC, pass off the pipe handler. */
2096 END_PROFILE(SMBreadX
);
2097 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2100 CHECK_FSP(fsp
,conn
);
2103 set_message(outbuf
,12,0,True
);
2105 if(CVAL(inbuf
,smb_wct
) == 12) {
2106 #ifdef LARGE_SMB_OFF_T
2108 * This is a large offset (64 bit) read.
2110 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2112 #else /* !LARGE_SMB_OFF_T */
2115 * Ensure we haven't been sent a >32 bit offset.
2118 if(IVAL(inbuf
,smb_vwv10
) != 0) {
2119 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2120 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
2121 END_PROFILE(SMBreadX
);
2122 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2125 #endif /* LARGE_SMB_OFF_T */
2129 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2130 END_PROFILE(SMBreadX
);
2131 return ERROR_DOS(ERRDOS
,ERRlock
);
2134 nread
= send_file_readX(conn
, inbuf
, outbuf
, length
, fsp
, startpos
, smb_maxcnt
);
2136 nread
= chain_reply(inbuf
,outbuf
,length
,bufsize
);
2138 END_PROFILE(SMBreadX
);
2142 /****************************************************************************
2143 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2144 ****************************************************************************/
2146 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2149 ssize_t total_written
=0;
2150 size_t numtowrite
=0;
2155 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2157 START_PROFILE(SMBwritebraw
);
2159 if (srv_is_signing_active()) {
2160 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2163 CHECK_FSP(fsp
,conn
);
2166 tcount
= IVAL(inbuf
,smb_vwv1
);
2167 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2168 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2170 /* We have to deal with slightly different formats depending
2171 on whether we are using the core+ or lanman1.0 protocol */
2173 if(Protocol
<= PROTOCOL_COREPLUS
) {
2174 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2175 data
= smb_buf(inbuf
);
2177 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2178 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2181 /* force the error type */
2182 SCVAL(inbuf
,smb_com
,SMBwritec
);
2183 SCVAL(outbuf
,smb_com
,SMBwritec
);
2185 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2186 END_PROFILE(SMBwritebraw
);
2187 return(ERROR_DOS(ERRDOS
,ERRlock
));
2191 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2193 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2194 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2196 if (nwritten
< (ssize_t
)numtowrite
) {
2197 END_PROFILE(SMBwritebraw
);
2198 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2201 total_written
= nwritten
;
2203 /* Return a message to the redirector to tell it to send more bytes */
2204 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
2205 SSVALS(outbuf
,smb_vwv0
,-1);
2206 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2207 if (!send_smb(smbd_server_fd(),outbuf
))
2208 exit_server("reply_writebraw: send_smb failed.");
2210 /* Now read the raw data into the buffer and write it */
2211 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2212 exit_server("secondary writebraw failed");
2215 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2216 numtowrite
= smb_len(inbuf
);
2218 /* Set up outbuf to return the correct return */
2219 outsize
= set_message(outbuf
,1,0,True
);
2220 SCVAL(outbuf
,smb_com
,SMBwritec
);
2221 SSVAL(outbuf
,smb_vwv0
,total_written
);
2223 if (numtowrite
!= 0) {
2225 if (numtowrite
> BUFFER_SIZE
) {
2226 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2227 (unsigned int)numtowrite
));
2228 exit_server("secondary writebraw failed");
2231 if (tcount
> nwritten
+numtowrite
) {
2232 DEBUG(3,("Client overestimated the write %d %d %d\n",
2233 (int)tcount
,(int)nwritten
,(int)numtowrite
));
2236 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
2237 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2239 exit_server("secondary writebraw failed");
2242 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
2244 if (nwritten
< (ssize_t
)numtowrite
) {
2245 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2246 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2250 total_written
+= nwritten
;
2253 if ((lp_syncalways(SNUM(conn
)) || write_through
) && lp_strict_sync(SNUM(conn
)))
2254 sync_file(conn
,fsp
);
2256 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2257 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
2259 /* we won't return a status if write through is not selected - this follows what WfWg does */
2260 END_PROFILE(SMBwritebraw
);
2261 if (!write_through
&& total_written
==tcount
) {
2263 #if RABBIT_PELLET_FIX
2265 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2266 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2268 if (!send_keepalive(smbd_server_fd()))
2269 exit_server("reply_writebraw: send of keepalive failed");
2277 /****************************************************************************
2278 Reply to a writeunlock (core+).
2279 ****************************************************************************/
2281 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
,
2282 int size
, int dum_buffsize
)
2284 ssize_t nwritten
= -1;
2288 NTSTATUS status
= NT_STATUS_OK
;
2289 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2291 START_PROFILE(SMBwriteunlock
);
2293 CHECK_FSP(fsp
,conn
);
2296 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2297 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2298 data
= smb_buf(inbuf
) + 3;
2300 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
,
2301 WRITE_LOCK
,False
)) {
2302 END_PROFILE(SMBwriteunlock
);
2303 return ERROR_DOS(ERRDOS
,ERRlock
);
2306 /* The special X/Open SMB protocol handling of
2307 zero length writes is *NOT* done for
2312 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2314 if (lp_syncalways(SNUM(conn
)))
2315 sync_file(conn
,fsp
);
2317 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2318 END_PROFILE(SMBwriteunlock
);
2319 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2323 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)numtowrite
,
2324 (SMB_BIG_UINT
)startpos
);
2325 if (NT_STATUS_V(status
)) {
2326 END_PROFILE(SMBwriteunlock
);
2327 return ERROR_NT(status
);
2331 outsize
= set_message(outbuf
,1,0,True
);
2333 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2335 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2336 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2338 END_PROFILE(SMBwriteunlock
);
2342 /****************************************************************************
2344 ****************************************************************************/
2346 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2349 ssize_t nwritten
= -1;
2352 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2354 START_PROFILE(SMBwrite
);
2356 /* If it's an IPC, pass off the pipe handler. */
2358 END_PROFILE(SMBwrite
);
2359 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2362 CHECK_FSP(fsp
,conn
);
2365 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2366 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2367 data
= smb_buf(inbuf
) + 3;
2369 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2370 END_PROFILE(SMBwrite
);
2371 return ERROR_DOS(ERRDOS
,ERRlock
);
2375 * X/Open SMB protocol says that if smb_vwv1 is
2376 * zero then the file size should be extended or
2377 * truncated to the size given in smb_vwv[2-3].
2380 if(numtowrite
== 0) {
2382 * This is actually an allocate call, and set EOF. JRA.
2384 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2386 END_PROFILE(SMBwrite
);
2387 return ERROR_NT(NT_STATUS_DISK_FULL
);
2389 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2391 END_PROFILE(SMBwrite
);
2392 return ERROR_NT(NT_STATUS_DISK_FULL
);
2395 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2397 if (lp_syncalways(SNUM(conn
)))
2398 sync_file(conn
,fsp
);
2400 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2401 END_PROFILE(SMBwrite
);
2402 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2405 outsize
= set_message(outbuf
,1,0,True
);
2407 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2409 if (nwritten
< (ssize_t
)numtowrite
) {
2410 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2411 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2414 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2416 END_PROFILE(SMBwrite
);
2420 /****************************************************************************
2421 Reply to a write and X.
2422 ****************************************************************************/
2424 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2426 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2427 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2428 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2429 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2430 ssize_t nwritten
= -1;
2431 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2432 unsigned int smblen
= smb_len(inbuf
);
2434 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2435 START_PROFILE(SMBwriteX
);
2437 /* If it's an IPC, pass off the pipe handler. */
2439 END_PROFILE(SMBwriteX
);
2440 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2443 CHECK_FSP(fsp
,conn
);
2446 /* Deal with possible LARGE_WRITEX */
2448 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2450 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2451 END_PROFILE(SMBwriteX
);
2452 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2455 data
= smb_base(inbuf
) + smb_doff
;
2457 if(CVAL(inbuf
,smb_wct
) == 14) {
2458 #ifdef LARGE_SMB_OFF_T
2460 * This is a large offset (64 bit) write.
2462 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2464 #else /* !LARGE_SMB_OFF_T */
2467 * Ensure we haven't been sent a >32 bit offset.
2470 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2471 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2472 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2473 END_PROFILE(SMBwriteX
);
2474 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2477 #endif /* LARGE_SMB_OFF_T */
2480 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2481 END_PROFILE(SMBwriteX
);
2482 return ERROR_DOS(ERRDOS
,ERRlock
);
2485 /* X/Open SMB protocol says that, unlike SMBwrite
2486 if the length is zero then NO truncation is
2487 done, just a write of zero. To truncate a file,
2493 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2495 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2496 END_PROFILE(SMBwriteX
);
2497 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2500 set_message(outbuf
,6,0,True
);
2502 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2504 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2506 if (nwritten
< (ssize_t
)numtowrite
) {
2507 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2508 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2511 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2512 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2514 if (lp_syncalways(SNUM(conn
)) || write_through
)
2515 sync_file(conn
,fsp
);
2517 END_PROFILE(SMBwriteX
);
2518 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2521 /****************************************************************************
2523 ****************************************************************************/
2525 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2531 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2532 START_PROFILE(SMBlseek
);
2534 CHECK_FSP(fsp
,conn
);
2536 flush_write_cache(fsp
, SEEK_FLUSH
);
2538 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2539 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2540 startpos
= (SMB_OFF_T
)IVALS(inbuf
,smb_vwv2
);
2549 res
= fsp
->pos
+ startpos
;
2560 if (umode
== SEEK_END
) {
2561 if((res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
2562 if(errno
== EINVAL
) {
2563 SMB_OFF_T current_pos
= startpos
;
2564 SMB_STRUCT_STAT sbuf
;
2566 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1) {
2567 END_PROFILE(SMBlseek
);
2568 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2571 current_pos
+= sbuf
.st_size
;
2573 res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,0,SEEK_SET
);
2578 END_PROFILE(SMBlseek
);
2579 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2585 outsize
= set_message(outbuf
,2,0,True
);
2586 SIVAL(outbuf
,smb_vwv0
,res
);
2588 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2589 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
2591 END_PROFILE(SMBlseek
);
2595 /****************************************************************************
2597 ****************************************************************************/
2599 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2601 int outsize
= set_message(outbuf
,0,0,True
);
2602 uint16 fnum
= SVAL(inbuf
,smb_vwv0
);
2603 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2604 START_PROFILE(SMBflush
);
2607 CHECK_FSP(fsp
,conn
);
2610 file_sync_all(conn
);
2612 sync_file(conn
,fsp
);
2615 DEBUG(3,("flush\n"));
2616 END_PROFILE(SMBflush
);
2620 /****************************************************************************
2622 ****************************************************************************/
2624 int reply_exit(connection_struct
*conn
,
2625 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2628 START_PROFILE(SMBexit
);
2630 file_close_pid(SVAL(inbuf
,smb_pid
));
2632 outsize
= set_message(outbuf
,0,0,True
);
2634 DEBUG(3,("exit\n"));
2636 END_PROFILE(SMBexit
);
2640 /****************************************************************************
2641 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2642 ****************************************************************************/
2644 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2647 extern struct current_user current_user
;
2650 int32 eclass
= 0, err
= 0;
2651 files_struct
*fsp
= NULL
;
2652 START_PROFILE(SMBclose
);
2654 outsize
= set_message(outbuf
,0,0,True
);
2656 /* If it's an IPC, pass off to the pipe handler. */
2658 END_PROFILE(SMBclose
);
2659 return reply_pipe_close(conn
, inbuf
,outbuf
);
2662 fsp
= file_fsp(inbuf
,smb_vwv0
);
2665 * We can only use CHECK_FSP if we know it's not a directory.
2668 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= current_user
.vuid
)) {
2669 END_PROFILE(SMBclose
);
2670 return ERROR_DOS(ERRDOS
,ERRbadfid
);
2673 if(fsp
->is_directory
) {
2675 * Special case - close NT SMB directory handle.
2677 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
2678 close_file(fsp
,True
);
2681 * Close ordinary file.
2686 /* Save the name for time set in close. */
2687 pstrcpy( file_name
, fsp
->fsp_name
);
2689 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2691 conn
->num_files_open
));
2694 * close_file() returns the unix errno if an error
2695 * was detected on close - normally this is due to
2696 * a disk full error. If not then it was probably an I/O error.
2699 if((close_err
= close_file(fsp
,True
)) != 0) {
2701 END_PROFILE(SMBclose
);
2702 return (UNIXERROR(ERRHRD
,ERRgeneral
));
2706 * Now take care of any time sent in the close.
2709 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2711 /* try and set the date */
2712 set_filetime(conn
, file_name
, mtime
);
2716 /* We have a cached error */
2718 END_PROFILE(SMBclose
);
2719 return ERROR_DOS(eclass
,err
);
2722 END_PROFILE(SMBclose
);
2726 /****************************************************************************
2727 Reply to a writeclose (Core+ protocol).
2728 ****************************************************************************/
2730 int reply_writeclose(connection_struct
*conn
,
2731 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2734 ssize_t nwritten
= -1;
2740 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2741 START_PROFILE(SMBwriteclose
);
2743 CHECK_FSP(fsp
,conn
);
2746 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2747 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2748 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2749 data
= smb_buf(inbuf
) + 1;
2751 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2752 END_PROFILE(SMBwriteclose
);
2753 return ERROR_DOS(ERRDOS
,ERRlock
);
2756 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2758 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2761 * More insanity. W2K only closes the file if writelen > 0.
2766 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2768 close_err
= close_file(fsp
,True
);
2771 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2772 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
2773 conn
->num_files_open
));
2775 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2776 END_PROFILE(SMBwriteclose
);
2777 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2780 if(close_err
!= 0) {
2782 END_PROFILE(SMBwriteclose
);
2783 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2786 outsize
= set_message(outbuf
,1,0,True
);
2788 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2789 END_PROFILE(SMBwriteclose
);
2793 /****************************************************************************
2795 ****************************************************************************/
2797 int reply_lock(connection_struct
*conn
,
2798 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
2800 int outsize
= set_message(outbuf
,0,0,True
);
2801 SMB_BIG_UINT count
,offset
;
2803 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2804 BOOL my_lock_ctx
= False
;
2806 START_PROFILE(SMBlock
);
2808 CHECK_FSP(fsp
,conn
);
2810 release_level_2_oplocks_on_change(fsp
);
2812 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2813 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2815 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2816 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
2818 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
, WRITE_LOCK
, &my_lock_ctx
);
2819 if (NT_STATUS_V(status
)) {
2821 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2822 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
2824 * A blocking lock was requested. Package up
2825 * this smb into a queued request and push it
2826 * onto the blocking lock queue.
2828 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), offset
, count
)) {
2829 END_PROFILE(SMBlock
);
2834 END_PROFILE(SMBlock
);
2835 return ERROR_NT(status
);
2838 END_PROFILE(SMBlock
);
2842 /****************************************************************************
2844 ****************************************************************************/
2846 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2849 int outsize
= set_message(outbuf
,0,0,True
);
2850 SMB_BIG_UINT count
,offset
;
2852 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2853 START_PROFILE(SMBunlock
);
2855 CHECK_FSP(fsp
,conn
);
2857 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2858 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2860 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
);
2861 if (NT_STATUS_V(status
)) {
2862 END_PROFILE(SMBunlock
);
2863 return ERROR_NT(status
);
2866 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2867 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
2869 END_PROFILE(SMBunlock
);
2873 /****************************************************************************
2875 ****************************************************************************/
2877 int reply_tdis(connection_struct
*conn
,
2878 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2880 int outsize
= set_message(outbuf
,0,0,True
);
2882 START_PROFILE(SMBtdis
);
2884 vuid
= SVAL(inbuf
,smb_uid
);
2887 DEBUG(4,("Invalid connection in tdis\n"));
2888 END_PROFILE(SMBtdis
);
2889 return ERROR_DOS(ERRSRV
,ERRinvnid
);
2894 close_cnum(conn
,vuid
);
2896 END_PROFILE(SMBtdis
);
2900 /****************************************************************************
2902 ****************************************************************************/
2904 int reply_echo(connection_struct
*conn
,
2905 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2907 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2909 unsigned int data_len
= smb_buflen(inbuf
);
2910 int outsize
= set_message(outbuf
,1,data_len
,True
);
2911 START_PROFILE(SMBecho
);
2913 if (data_len
> BUFFER_SIZE
) {
2914 DEBUG(0,("reply_echo: data_len too large.\n"));
2915 END_PROFILE(SMBecho
);
2919 /* copy any incoming data back out */
2921 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2923 if (smb_reverb
> 100) {
2924 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2928 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2929 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2931 smb_setlen(outbuf
,outsize
- 4);
2933 if (!send_smb(smbd_server_fd(),outbuf
))
2934 exit_server("reply_echo: send_smb failed.");
2937 DEBUG(3,("echo %d times\n", smb_reverb
));
2941 END_PROFILE(SMBecho
);
2945 /****************************************************************************
2946 Reply to a printopen.
2947 ****************************************************************************/
2949 int reply_printopen(connection_struct
*conn
,
2950 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2954 START_PROFILE(SMBsplopen
);
2956 if (!CAN_PRINT(conn
)) {
2957 END_PROFILE(SMBsplopen
);
2958 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2961 /* Open for exclusive use, write only. */
2962 fsp
= print_fsp_open(conn
, NULL
);
2965 END_PROFILE(SMBsplopen
);
2966 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2969 outsize
= set_message(outbuf
,1,0,True
);
2970 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2972 DEBUG(3,("openprint fd=%d fnum=%d\n",
2973 fsp
->fd
, fsp
->fnum
));
2975 END_PROFILE(SMBsplopen
);
2979 /****************************************************************************
2980 Reply to a printclose.
2981 ****************************************************************************/
2983 int reply_printclose(connection_struct
*conn
,
2984 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2986 int outsize
= set_message(outbuf
,0,0,True
);
2987 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2989 START_PROFILE(SMBsplclose
);
2991 CHECK_FSP(fsp
,conn
);
2993 if (!CAN_PRINT(conn
)) {
2994 END_PROFILE(SMBsplclose
);
2995 return ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
2998 DEBUG(3,("printclose fd=%d fnum=%d\n",
2999 fsp
->fd
,fsp
->fnum
));
3001 close_err
= close_file(fsp
,True
);
3003 if(close_err
!= 0) {
3005 END_PROFILE(SMBsplclose
);
3006 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3009 END_PROFILE(SMBsplclose
);
3013 /****************************************************************************
3014 Reply to a printqueue.
3015 ****************************************************************************/
3017 int reply_printqueue(connection_struct
*conn
,
3018 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3020 int outsize
= set_message(outbuf
,2,3,True
);
3021 int max_count
= SVAL(inbuf
,smb_vwv0
);
3022 int start_index
= SVAL(inbuf
,smb_vwv1
);
3023 START_PROFILE(SMBsplretq
);
3025 /* we used to allow the client to get the cnum wrong, but that
3026 is really quite gross and only worked when there was only
3027 one printer - I think we should now only accept it if they
3028 get it right (tridge) */
3029 if (!CAN_PRINT(conn
)) {
3030 END_PROFILE(SMBsplretq
);
3031 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3034 SSVAL(outbuf
,smb_vwv0
,0);
3035 SSVAL(outbuf
,smb_vwv1
,0);
3036 SCVAL(smb_buf(outbuf
),0,1);
3037 SSVAL(smb_buf(outbuf
),1,0);
3039 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3040 start_index
, max_count
));
3043 print_queue_struct
*queue
= NULL
;
3044 print_status_struct status
;
3045 char *p
= smb_buf(outbuf
) + 3;
3046 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
3047 int num_to_get
= ABS(max_count
);
3048 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
3054 num_to_get
= MIN(num_to_get
,count
-first
);
3057 for (i
=first
;i
<first
+num_to_get
;i
++) {
3058 put_dos_date2(p
,0,queue
[i
].time
);
3059 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
3060 SSVAL(p
,5, queue
[i
].job
);
3061 SIVAL(p
,7,queue
[i
].size
);
3063 srvstr_push(outbuf
, p
+12, queue
[i
].fs_user
, 16, STR_ASCII
);
3068 outsize
= set_message(outbuf
,2,28*count
+3,False
);
3069 SSVAL(outbuf
,smb_vwv0
,count
);
3070 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
3071 SCVAL(smb_buf(outbuf
),0,1);
3072 SSVAL(smb_buf(outbuf
),1,28*count
);
3077 DEBUG(3,("%d entries returned in queue\n",count
));
3080 END_PROFILE(SMBsplretq
);
3084 /****************************************************************************
3085 Reply to a printwrite.
3086 ****************************************************************************/
3088 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3091 int outsize
= set_message(outbuf
,0,0,True
);
3093 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3095 START_PROFILE(SMBsplwr
);
3097 if (!CAN_PRINT(conn
)) {
3098 END_PROFILE(SMBsplwr
);
3099 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3102 CHECK_FSP(fsp
,conn
);
3105 numtowrite
= SVAL(smb_buf(inbuf
),1);
3106 data
= smb_buf(inbuf
) + 3;
3108 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
3109 END_PROFILE(SMBsplwr
);
3110 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3113 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
3115 END_PROFILE(SMBsplwr
);
3119 /****************************************************************************
3120 The guts of the mkdir command, split out so it may be called by the NT SMB
3122 ****************************************************************************/
3124 NTSTATUS
mkdir_internal(connection_struct
*conn
, pstring directory
)
3126 BOOL bad_path
= False
;
3127 SMB_STRUCT_STAT sbuf
;
3130 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3132 if( strchr_m(directory
, ':')) {
3133 return NT_STATUS_NOT_A_DIRECTORY
;
3136 if (ms_has_wild(directory
)) {
3137 return NT_STATUS_OBJECT_NAME_INVALID
;
3140 if (check_name(directory
, conn
))
3141 ret
= vfs_MkDir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3144 if(errno
== ENOENT
) {
3146 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3148 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3150 return map_nt_error_from_unix(errno
);
3153 return NT_STATUS_OK
;
3156 /****************************************************************************
3158 ****************************************************************************/
3160 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3165 START_PROFILE(SMBmkdir
);
3167 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3168 if (!NT_STATUS_IS_OK(status
)) {
3169 END_PROFILE(SMBmkdir
);
3170 return ERROR_NT(status
);
3173 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
);
3175 status
= mkdir_internal(conn
, directory
);
3176 if (!NT_STATUS_IS_OK(status
)) {
3177 END_PROFILE(SMBmkdir
);
3178 return ERROR_NT(status
);
3181 outsize
= set_message(outbuf
,0,0,True
);
3183 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
3185 END_PROFILE(SMBmkdir
);
3189 /****************************************************************************
3190 Static function used by reply_rmdir to delete an entire directory
3191 tree recursively. Return False on ok, True on fail.
3192 ****************************************************************************/
3194 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
3196 const char *dname
= NULL
;
3198 void *dirptr
= OpenDir(conn
, directory
, False
);
3203 while((dname
= ReadDirName(dirptr
))) {
3207 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3210 /* Construct the full name. */
3211 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3217 pstrcpy(fullname
, directory
);
3218 pstrcat(fullname
, "/");
3219 pstrcat(fullname
, dname
);
3221 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
3226 if(st
.st_mode
& S_IFDIR
) {
3227 if(recursive_rmdir(conn
, fullname
)!=0) {
3231 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
3235 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
3244 /****************************************************************************
3245 The internals of the rmdir code - called elsewhere.
3246 ****************************************************************************/
3248 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
3252 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3253 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
3255 * Check to see if the only thing in this directory are
3256 * vetoed files/directories. If so then delete them and
3257 * retry. If we fail to delete any of them (and we *don't*
3258 * do a recursive delete) then fail the rmdir.
3260 BOOL all_veto_files
= True
;
3262 void *dirptr
= OpenDir(conn
, directory
, False
);
3264 if(dirptr
!= NULL
) {
3265 int dirpos
= TellDir(dirptr
);
3266 while ((dname
= ReadDirName(dirptr
))) {
3267 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3269 if(!IS_VETO_PATH(conn
, dname
)) {
3270 all_veto_files
= False
;
3275 if(all_veto_files
) {
3276 SeekDir(dirptr
,dirpos
);
3277 while ((dname
= ReadDirName(dirptr
))) {
3281 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3284 /* Construct the full name. */
3285 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3290 pstrcpy(fullname
, directory
);
3291 pstrcat(fullname
, "/");
3292 pstrcat(fullname
, dname
);
3294 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0)
3296 if(st
.st_mode
& S_IFDIR
) {
3297 if(lp_recursive_veto_delete(SNUM(conn
))) {
3298 if(recursive_rmdir(conn
, fullname
) != 0)
3301 if(SMB_VFS_RMDIR(conn
,fullname
) != 0)
3303 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0)
3307 /* Retry the rmdir */
3308 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3318 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory
,strerror(errno
)));
3323 /****************************************************************************
3325 ****************************************************************************/
3327 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3332 BOOL bad_path
= False
;
3333 SMB_STRUCT_STAT sbuf
;
3335 START_PROFILE(SMBrmdir
);
3337 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), 0, STR_TERMINATE
, &status
);
3338 if (!NT_STATUS_IS_OK(status
)) {
3339 END_PROFILE(SMBrmdir
);
3340 return ERROR_NT(status
);
3343 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3345 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3347 if (check_name(directory
,conn
)) {
3348 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3349 ok
= rmdir_internals(conn
, directory
);
3353 END_PROFILE(SMBrmdir
);
3354 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRbadpath
);
3357 outsize
= set_message(outbuf
,0,0,True
);
3359 DEBUG( 3, ( "rmdir %s\n", directory
) );
3361 END_PROFILE(SMBrmdir
);
3365 /*******************************************************************
3366 Resolve wildcards in a filename rename.
3367 Note that name is in UNIX charset and thus potentially can be more
3368 than fstring buffer (255 bytes) especially in default UTF-8 case.
3369 Therefore, we use pstring inside and all calls should ensure that
3370 name2 is at least pstring-long (they do already)
3371 ********************************************************************/
3373 static BOOL
resolve_wildcards(const char *name1
, char *name2
)
3375 pstring root1
,root2
;
3377 char *p
,*p2
, *pname1
, *pname2
;
3378 int available_space
, actual_space
;
3381 pname1
= strrchr_m(name1
,'/');
3382 pname2
= strrchr_m(name2
,'/');
3384 if (!pname1
|| !pname2
)
3387 pstrcpy(root1
,pname1
);
3388 pstrcpy(root2
,pname2
);
3389 p
= strrchr_m(root1
,'.');
3396 p
= strrchr_m(root2
,'.');
3430 available_space
= sizeof(pstring
) - PTR_DIFF(pname2
, name2
);
3433 actual_space
= snprintf(pname2
, available_space
- 1, "%s.%s", root2
, ext2
);
3434 if (actual_space
>= available_space
- 1) {
3435 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3436 actual_space
- available_space
));
3439 pstrcpy_base(pname2
, root2
, name2
);
3445 /****************************************************************************
3446 Ensure open files have their names updates.
3447 ****************************************************************************/
3449 static void rename_open_files(connection_struct
*conn
, SMB_DEV_T dev
, SMB_INO_T inode
, char *newname
)
3452 BOOL did_rename
= False
;
3454 for(fsp
= file_find_di_first(dev
, inode
); fsp
; fsp
= file_find_di_next(fsp
)) {
3455 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3456 fsp
->fnum
, (unsigned int)fsp
->dev
, (double)fsp
->inode
,
3457 fsp
->fsp_name
, newname
));
3458 string_set(&fsp
->fsp_name
, newname
);
3463 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3464 (unsigned int)dev
, (double)inode
, newname
));
3467 /****************************************************************************
3468 Rename an open file - given an fsp.
3469 ****************************************************************************/
3471 NTSTATUS
rename_internals_fsp(connection_struct
*conn
, files_struct
*fsp
, char *newname
, BOOL replace_if_exists
)
3473 SMB_STRUCT_STAT sbuf
;
3474 BOOL bad_path
= False
;
3475 pstring newname_last_component
;
3476 NTSTATUS error
= NT_STATUS_OK
;
3481 rcdest
= unix_convert(newname
,conn
,newname_last_component
,&bad_path
,&sbuf
);
3483 /* Quick check for "." and ".." */
3484 if (!bad_path
&& newname_last_component
[0] == '.') {
3485 if (!newname_last_component
[1] || (newname_last_component
[1] == '.' && !newname_last_component
[2])) {
3486 return NT_STATUS_ACCESS_DENIED
;
3489 if (!rcdest
&& bad_path
) {
3490 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3493 /* Ensure newname contains a '/' */
3494 if(strrchr_m(newname
,'/') == 0) {
3497 pstrcpy(tmpstr
, "./");
3498 pstrcat(tmpstr
, newname
);
3499 pstrcpy(newname
, tmpstr
);
3503 * Check for special case with case preserving and not
3504 * case sensitive. If the old last component differs from the original
3505 * last component only by case, then we should allow
3506 * the rename (user is trying to change the case of the
3510 if((case_sensitive
== False
) && (case_preserve
== True
) &&
3511 strequal(newname
, fsp
->fsp_name
)) {
3513 pstring newname_modified_last_component
;
3516 * Get the last component of the modified name.
3517 * Note that we guarantee that newname contains a '/'
3520 p
= strrchr_m(newname
,'/');
3521 pstrcpy(newname_modified_last_component
,p
+1);
3523 if(strcsequal(newname_modified_last_component
,
3524 newname_last_component
) == False
) {
3526 * Replace the modified last component with
3529 pstrcpy(p
+1, newname_last_component
);
3534 * If the src and dest names are identical - including case,
3535 * don't do the rename, just return success.
3538 if (strcsequal(fsp
->fsp_name
, newname
)) {
3539 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3541 return NT_STATUS_OK
;
3544 dest_exists
= vfs_object_exist(conn
,newname
,NULL
);
3546 if(!replace_if_exists
&& dest_exists
) {
3547 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3548 fsp
->fsp_name
,newname
));
3549 return NT_STATUS_OBJECT_NAME_COLLISION
;
3552 error
= can_rename(newname
,conn
,&sbuf
);
3554 if (dest_exists
&& !NT_STATUS_IS_OK(error
)) {
3555 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3556 nt_errstr(error
), fsp
->fsp_name
,newname
));
3557 if (NT_STATUS_EQUAL(error
,NT_STATUS_SHARING_VIOLATION
))
3558 error
= NT_STATUS_ACCESS_DENIED
;
3562 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
3563 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3564 fsp
->fsp_name
,newname
));
3565 rename_open_files(conn
, fsp
->dev
, fsp
->inode
, newname
);
3566 return NT_STATUS_OK
;
3569 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3570 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3572 error
= map_nt_error_from_unix(errno
);
3574 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3575 nt_errstr(error
), fsp
->fsp_name
,newname
));
3580 /****************************************************************************
3581 The guts of the rename command, split out so it may be called by the NT SMB
3583 ****************************************************************************/
3585 NTSTATUS
rename_internals(connection_struct
*conn
, char *name
, char *newname
, uint16 attrs
, BOOL replace_if_exists
)
3589 pstring last_component_src
;
3590 pstring last_component_dest
;
3593 BOOL bad_path_src
= False
;
3594 BOOL bad_path_dest
= False
;
3596 NTSTATUS error
= NT_STATUS_OK
;
3599 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3601 *directory
= *mask
= 0;
3606 rc
= unix_convert(name
,conn
,last_component_src
,&bad_path_src
,&sbuf1
);
3607 if (!rc
&& bad_path_src
) {
3608 if (ms_has_wild(last_component_src
))
3609 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3610 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3613 /* Quick check for "." and ".." */
3614 if (last_component_src
[0] == '.') {
3615 if (!last_component_src
[1] || (last_component_src
[1] == '.' && !last_component_src
[2])) {
3616 return NT_STATUS_OBJECT_NAME_INVALID
;
3620 rcdest
= unix_convert(newname
,conn
,last_component_dest
,&bad_path_dest
,&sbuf2
);
3622 /* Quick check for "." and ".." */
3623 if (last_component_dest
[0] == '.') {
3624 if (!last_component_dest
[1] || (last_component_dest
[1] == '.' && !last_component_dest
[2])) {
3625 return NT_STATUS_OBJECT_NAME_INVALID
;
3630 * Split the old name into directory and last component
3631 * strings. Note that unix_convert may have stripped off a
3632 * leading ./ from both name and newname if the rename is
3633 * at the root of the share. We need to make sure either both
3634 * name and newname contain a / character or neither of them do
3635 * as this is checked in resolve_wildcards().
3638 p
= strrchr_m(name
,'/');
3640 pstrcpy(directory
,".");
3644 pstrcpy(directory
,name
);
3646 *p
= '/'; /* Replace needed for exceptional test below. */
3650 * We should only check the mangled cache
3651 * here if unix_convert failed. This means
3652 * that the path in 'mask' doesn't exist
3653 * on the file system and so we need to look
3654 * for a possible mangle. This patch from
3655 * Tine Smukavec <valentin.smukavec@hermes.si>.
3658 if (!rc
&& mangle_is_mangled(mask
))
3659 mangle_check_cache( mask
);
3661 has_wild
= ms_has_wild(mask
);
3665 * No wildcards - just process the one file.
3667 BOOL is_short_name
= mangle_is_8_3(name
, True
);
3669 /* Add a terminating '/' to the directory name. */
3670 pstrcat(directory
,"/");
3671 pstrcat(directory
,mask
);
3673 /* Ensure newname contains a '/' also */
3674 if(strrchr_m(newname
,'/') == 0) {
3677 pstrcpy(tmpstr
, "./");
3678 pstrcat(tmpstr
, newname
);
3679 pstrcpy(newname
, tmpstr
);
3682 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3683 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3684 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3685 newname
, last_component_dest
, is_short_name
));
3688 * Check for special case with case preserving and not
3689 * case sensitive, if directory and newname are identical,
3690 * and the old last component differs from the original
3691 * last component only by case, then we should allow
3692 * the rename (user is trying to change the case of the
3695 if((case_sensitive
== False
) &&
3696 (((case_preserve
== True
) &&
3697 (is_short_name
== False
)) ||
3698 ((short_case_preserve
== True
) &&
3699 (is_short_name
== True
))) &&
3700 strcsequal(directory
, newname
)) {
3701 pstring modified_last_component
;
3704 * Get the last component of the modified name.
3705 * Note that we guarantee that newname contains a '/'
3708 p
= strrchr_m(newname
,'/');
3709 pstrcpy(modified_last_component
,p
+1);
3711 if(strcsequal(modified_last_component
,
3712 last_component_dest
) == False
) {
3714 * Replace the modified last component with
3717 pstrcpy(p
+1, last_component_dest
);
3721 resolve_wildcards(directory
,newname
);
3724 * The source object must exist.
3727 if (!vfs_object_exist(conn
, directory
, &sbuf1
)) {
3728 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3729 directory
,newname
));
3731 if (errno
== ENOTDIR
|| errno
== EISDIR
|| errno
== ENOENT
) {
3733 * Must return different errors depending on whether the parent
3734 * directory existed or not.
3737 p
= strrchr_m(directory
, '/');
3739 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3741 if (vfs_object_exist(conn
, directory
, NULL
))
3742 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3743 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3745 error
= map_nt_error_from_unix(errno
);
3746 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3747 nt_errstr(error
), directory
,newname
));
3752 if (!rcdest
&& bad_path_dest
) {
3753 if (ms_has_wild(last_component_dest
))
3754 return NT_STATUS_OBJECT_NAME_INVALID
;
3755 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3758 error
= can_rename(directory
,conn
,&sbuf1
);
3760 if (!NT_STATUS_IS_OK(error
)) {
3761 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3762 nt_errstr(error
), directory
,newname
));
3767 * If the src and dest names are identical - including case,
3768 * don't do the rename, just return success.
3771 if (strcsequal(directory
, newname
)) {
3772 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3773 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory
));
3774 return NT_STATUS_OK
;
3777 if(!replace_if_exists
&& vfs_object_exist(conn
,newname
,NULL
)) {
3778 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3779 directory
,newname
));
3780 return NT_STATUS_OBJECT_NAME_COLLISION
;
3783 if(SMB_VFS_RENAME(conn
,directory
, newname
) == 0) {
3784 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3785 directory
,newname
));
3786 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3787 return NT_STATUS_OK
;
3790 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3791 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3793 error
= map_nt_error_from_unix(errno
);
3795 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3796 nt_errstr(error
), directory
,newname
));
3801 * Wildcards - process each file that matches.
3803 void *dirptr
= NULL
;
3807 if (check_name(directory
,conn
))
3808 dirptr
= OpenDir(conn
, directory
, True
);
3811 error
= NT_STATUS_NO_SUCH_FILE
;
3812 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3814 if (strequal(mask
,"????????.???"))
3817 while ((dname
= ReadDirName(dirptr
))) {
3819 BOOL sysdir_entry
= False
;
3821 pstrcpy(fname
,dname
);
3823 /* Quick check for "." and ".." */
3824 if (fname
[0] == '.') {
3825 if (!fname
[1] || (fname
[1] == '.' && !fname
[2])) {
3827 sysdir_entry
= True
;
3834 if(!mask_match(fname
, mask
, case_sensitive
))
3838 error
= NT_STATUS_OBJECT_NAME_INVALID
;
3842 error
= NT_STATUS_ACCESS_DENIED
;
3843 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3844 if (!vfs_object_exist(conn
, fname
, &sbuf1
)) {
3845 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3846 DEBUG(6,("rename %s failed. Error %s\n", fname
, nt_errstr(error
)));
3849 error
= can_rename(fname
,conn
,&sbuf1
);
3850 if (!NT_STATUS_IS_OK(error
)) {
3851 DEBUG(6,("rename %s refused\n", fname
));
3854 pstrcpy(destname
,newname
);
3856 if (!resolve_wildcards(fname
,destname
)) {
3857 DEBUG(6,("resolve_wildcards %s %s failed\n",
3862 if (!replace_if_exists
&&
3863 vfs_file_exist(conn
,destname
, NULL
)) {
3864 DEBUG(6,("file_exist %s\n", destname
));
3865 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3869 if (!SMB_VFS_RENAME(conn
,fname
,destname
)) {
3870 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3872 error
= NT_STATUS_OK
;
3874 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3879 if (!NT_STATUS_EQUAL(error
,NT_STATUS_NO_SUCH_FILE
)) {
3880 if (!rcdest
&& bad_path_dest
) {
3881 if (ms_has_wild(last_component_dest
))
3882 return NT_STATUS_OBJECT_NAME_INVALID
;
3883 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3888 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
3889 error
= map_nt_error_from_unix(errno
);
3895 /****************************************************************************
3897 ****************************************************************************/
3899 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
3906 uint16 attrs
= SVAL(inbuf
,smb_vwv0
);
3909 START_PROFILE(SMBmv
);
3911 p
= smb_buf(inbuf
) + 1;
3912 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
);
3913 if (!NT_STATUS_IS_OK(status
)) {
3915 return ERROR_NT(status
);
3918 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
);
3919 if (!NT_STATUS_IS_OK(status
)) {
3921 return ERROR_NT(status
);
3924 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3925 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3927 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3929 status
= rename_internals(conn
, name
, newname
, attrs
, False
);
3930 if (!NT_STATUS_IS_OK(status
)) {
3932 return ERROR_NT(status
);
3936 * Win2k needs a changenotify request response before it will
3937 * update after a rename..
3939 process_pending_change_notify_queue((time_t)0);
3940 outsize
= set_message(outbuf
,0,0,True
);
3946 /*******************************************************************
3947 Copy a file as part of a reply_copy.
3948 ******************************************************************/
3950 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3951 int count
,BOOL target_is_directory
, int *err_ret
)
3954 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
3956 files_struct
*fsp1
,*fsp2
;
3961 pstrcpy(dest
,dest1
);
3962 if (target_is_directory
) {
3963 char *p
= strrchr_m(src
,'/');
3972 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
3975 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3976 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
3981 if (!target_is_directory
&& count
)
3982 ofun
= FILE_EXISTS_OPEN
;
3984 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1)
3985 ZERO_STRUCTP(&sbuf2
);
3987 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3988 ofun
,src_sbuf
.st_mode
,0,&Access
,&action
);
3991 close_file(fsp1
,False
);
3995 if ((ofun
&3) == 1) {
3996 if(SMB_VFS_LSEEK(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
3997 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
3999 * Stop the copy from occurring.
4002 src_sbuf
.st_size
= 0;
4006 if (src_sbuf
.st_size
)
4007 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
4009 close_file(fsp1
,False
);
4011 /* Ensure the modtime is set correctly on the destination file. */
4012 fsp2
->pending_modtime
= src_sbuf
.st_mtime
;
4015 * As we are opening fsp1 read-only we only expect
4016 * an error on close on fsp2 if we are out of space.
4017 * Thus we don't look at the error return from the
4020 *err_ret
= close_file(fsp2
,False
);
4022 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
4025 /****************************************************************************
4026 Reply to a file copy.
4027 ****************************************************************************/
4029 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4034 pstring mask
,newname
;
4037 int error
= ERRnoaccess
;
4041 int tid2
= SVAL(inbuf
,smb_vwv0
);
4042 int ofun
= SVAL(inbuf
,smb_vwv1
);
4043 int flags
= SVAL(inbuf
,smb_vwv2
);
4044 BOOL target_is_directory
=False
;
4045 BOOL bad_path1
= False
;
4046 BOOL bad_path2
= False
;
4048 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4051 START_PROFILE(SMBcopy
);
4053 *directory
= *mask
= 0;
4056 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), 0, STR_TERMINATE
, &status
);
4057 if (!NT_STATUS_IS_OK(status
)) {
4058 END_PROFILE(SMBcopy
);
4059 return ERROR_NT(status
);
4061 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), 0, STR_TERMINATE
, &status
);
4062 if (!NT_STATUS_IS_OK(status
)) {
4063 END_PROFILE(SMBcopy
);
4064 return ERROR_NT(status
);
4067 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
4069 if (tid2
!= conn
->cnum
) {
4070 /* can't currently handle inter share copies XXXX */
4071 DEBUG(3,("Rejecting inter-share copy\n"));
4072 END_PROFILE(SMBcopy
);
4073 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
4076 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
4077 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
4079 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
4080 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
4082 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
4084 if ((flags
&1) && target_is_directory
) {
4085 END_PROFILE(SMBcopy
);
4086 return ERROR_DOS(ERRDOS
,ERRbadfile
);
4089 if ((flags
&2) && !target_is_directory
) {
4090 END_PROFILE(SMBcopy
);
4091 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4094 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
4095 /* wants a tree copy! XXXX */
4096 DEBUG(3,("Rejecting tree copy\n"));
4097 END_PROFILE(SMBcopy
);
4098 return ERROR_DOS(ERRSRV
,ERRerror
);
4101 p
= strrchr_m(name
,'/');
4103 pstrcpy(directory
,"./");
4107 pstrcpy(directory
,name
);
4112 * We should only check the mangled cache
4113 * here if unix_convert failed. This means
4114 * that the path in 'mask' doesn't exist
4115 * on the file system and so we need to look
4116 * for a possible mangle. This patch from
4117 * Tine Smukavec <valentin.smukavec@hermes.si>.
4120 if (!rc
&& mangle_is_mangled(mask
))
4121 mangle_check_cache( mask
);
4123 has_wild
= ms_has_wild(mask
);
4126 pstrcat(directory
,"/");
4127 pstrcat(directory
,mask
);
4128 if (resolve_wildcards(directory
,newname
) &&
4129 copy_file(directory
,newname
,conn
,ofun
, count
,target_is_directory
,&err
))
4133 END_PROFILE(SMBcopy
);
4134 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4137 exists
= vfs_file_exist(conn
,directory
,NULL
);
4140 void *dirptr
= NULL
;
4144 if (check_name(directory
,conn
))
4145 dirptr
= OpenDir(conn
, directory
, True
);
4150 if (strequal(mask
,"????????.???"))
4153 while ((dname
= ReadDirName(dirptr
))) {
4155 pstrcpy(fname
,dname
);
4157 if(!mask_match(fname
, mask
, case_sensitive
))
4160 error
= ERRnoaccess
;
4161 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
4162 pstrcpy(destname
,newname
);
4163 if (resolve_wildcards(fname
,destname
) &&
4164 copy_file(fname
,destname
,conn
,ofun
,
4165 count
,target_is_directory
,&err
))
4167 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
4175 /* Error on close... */
4177 END_PROFILE(SMBcopy
);
4178 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4182 END_PROFILE(SMBcopy
);
4183 return ERROR_DOS(ERRDOS
,error
);
4185 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
)) {
4186 unix_ERR_class
= ERRDOS
;
4187 unix_ERR_code
= ERRbadpath
;
4189 END_PROFILE(SMBcopy
);
4190 return(UNIXERROR(ERRDOS
,error
));
4194 outsize
= set_message(outbuf
,1,0,True
);
4195 SSVAL(outbuf
,smb_vwv0
,count
);
4197 END_PROFILE(SMBcopy
);
4201 /****************************************************************************
4203 ****************************************************************************/
4205 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4213 START_PROFILE(pathworks_setdir
);
4216 if (!CAN_SETDIR(snum
)) {
4217 END_PROFILE(pathworks_setdir
);
4218 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4221 srvstr_get_path(inbuf
, newdir
, smb_buf(inbuf
) + 1, sizeof(newdir
), 0, STR_TERMINATE
, &status
);
4222 if (!NT_STATUS_IS_OK(status
)) {
4223 END_PROFILE(pathworks_setdir
);
4224 return ERROR_NT(status
);
4227 if (strlen(newdir
) == 0) {
4230 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
4232 string_set(&conn
->connectpath
,newdir
);
4236 END_PROFILE(pathworks_setdir
);
4237 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4240 outsize
= set_message(outbuf
,0,0,True
);
4241 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
4243 DEBUG(3,("setdir %s\n", newdir
));
4245 END_PROFILE(pathworks_setdir
);
4249 /****************************************************************************
4250 Get a lock pid, dealing with large count requests.
4251 ****************************************************************************/
4253 uint16
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
4255 if(!large_file_format
)
4256 return SVAL(data
,SMB_LPID_OFFSET(data_offset
));
4258 return SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
4261 /****************************************************************************
4262 Get a lock count, dealing with large count requests.
4263 ****************************************************************************/
4265 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
4267 SMB_BIG_UINT count
= 0;
4269 if(!large_file_format
) {
4270 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
4273 #if defined(HAVE_LONGLONG)
4274 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
4275 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
4276 #else /* HAVE_LONGLONG */
4279 * NT4.x seems to be broken in that it sends large file (64 bit)
4280 * lockingX calls even if the CAP_LARGE_FILES was *not*
4281 * negotiated. For boxes without large unsigned ints truncate the
4282 * lock count by dropping the top 32 bits.
4285 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
4286 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4287 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
4288 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
4289 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
4292 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
4293 #endif /* HAVE_LONGLONG */
4299 #if !defined(HAVE_LONGLONG)
4300 /****************************************************************************
4301 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4302 ****************************************************************************/
4304 static uint32
map_lock_offset(uint32 high
, uint32 low
)
4308 uint32 highcopy
= high
;
4311 * Try and find out how many significant bits there are in high.
4314 for(i
= 0; highcopy
; i
++)
4318 * We use 31 bits not 32 here as POSIX
4319 * lock offsets may not be negative.
4322 mask
= (~0) << (31 - i
);
4325 return 0; /* Fail. */
4331 #endif /* !defined(HAVE_LONGLONG) */
4333 /****************************************************************************
4334 Get a lock offset, dealing with large offset requests.
4335 ****************************************************************************/
4337 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
4339 SMB_BIG_UINT offset
= 0;
4343 if(!large_file_format
) {
4344 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
4347 #if defined(HAVE_LONGLONG)
4348 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
4349 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
4350 #else /* HAVE_LONGLONG */
4353 * NT4.x seems to be broken in that it sends large file (64 bit)
4354 * lockingX calls even if the CAP_LARGE_FILES was *not*
4355 * negotiated. For boxes without large unsigned ints mangle the
4356 * lock offset by mapping the top 32 bits onto the lower 32.
4359 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
4360 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4361 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
4364 if((new_low
= map_lock_offset(high
, low
)) == 0) {
4366 return (SMB_BIG_UINT
)-1;
4369 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4370 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
4371 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
4372 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
4375 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4376 #endif /* HAVE_LONGLONG */
4382 /****************************************************************************
4383 Reply to a lockingX request.
4384 ****************************************************************************/
4386 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4388 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
4389 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
4390 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
4391 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
4392 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
4393 SMB_BIG_UINT count
= 0, offset
= 0;
4395 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
4398 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
4400 BOOL my_lock_ctx
= False
;
4403 START_PROFILE(SMBlockingX
);
4405 CHECK_FSP(fsp
,conn
);
4407 data
= smb_buf(inbuf
);
4409 if (locktype
& (LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_CHANGE_LOCKTYPE
)) {
4410 /* we don't support these - and CANCEL_LOCK makes w2k
4411 and XP reboot so I don't really want to be
4412 compatible! (tridge) */
4413 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
4416 /* Check if this is an oplock break on a file
4417 we have granted an oplock on.
4419 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
4420 /* Client can insist on breaking to none. */
4421 BOOL break_to_none
= (oplocklevel
== 0);
4423 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4424 (unsigned int)oplocklevel
, fsp
->fnum
));
4427 * Make sure we have granted an exclusive or batch oplock on this file.
4430 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
4431 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4432 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
4434 /* if this is a pure oplock break request then don't send a reply */
4435 if (num_locks
== 0 && num_ulocks
== 0) {
4436 END_PROFILE(SMBlockingX
);
4439 END_PROFILE(SMBlockingX
);
4440 return ERROR_DOS(ERRDOS
,ERRlock
);
4444 if (remove_oplock(fsp
, break_to_none
) == False
) {
4445 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4449 /* if this is a pure oplock break request then don't send a reply */
4450 if (num_locks
== 0 && num_ulocks
== 0) {
4451 /* Sanity check - ensure a pure oplock break is not a
4453 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
4454 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4455 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
4456 END_PROFILE(SMBlockingX
);
4462 * We do this check *after* we have checked this is not a oplock break
4463 * response message. JRA.
4466 release_level_2_oplocks_on_change(fsp
);
4468 /* Data now points at the beginning of the list
4469 of smb_unlkrng structs */
4470 for(i
= 0; i
< (int)num_ulocks
; i
++) {
4471 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4472 count
= get_lock_count( data
, i
, large_file_format
);
4473 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4476 * There is no error code marked "stupid client bug".... :-).
4479 END_PROFILE(SMBlockingX
);
4480 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4483 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4484 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
4486 status
= do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4487 if (NT_STATUS_V(status
)) {
4488 END_PROFILE(SMBlockingX
);
4489 return ERROR_NT(status
);
4493 /* Setup the timeout in seconds. */
4495 lock_timeout
= ((lock_timeout
== -1) ? -1 : (lock_timeout
+999)/1000);
4497 /* Now do any requested locks */
4498 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
4500 /* Data now points at the beginning of the list
4501 of smb_lkrng structs */
4503 for(i
= 0; i
< (int)num_locks
; i
++) {
4504 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4505 count
= get_lock_count( data
, i
, large_file_format
);
4506 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4509 * There is no error code marked "stupid client bug".... :-).
4512 END_PROFILE(SMBlockingX
);
4513 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4516 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4517 (double)offset
, (double)count
, (unsigned int)lock_pid
,
4518 fsp
->fsp_name
, (int)lock_timeout
));
4520 status
= do_lock_spin(fsp
,conn
,lock_pid
, count
,offset
,
4521 ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
), &my_lock_ctx
);
4522 if (NT_STATUS_V(status
)) {
4524 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4525 * Even if it's our own lock context, we need to wait here as
4526 * there may be an unlock on the way.
4527 * So I removed a "&& !my_lock_ctx" from the following
4528 * if statement. JRA.
4530 if ((lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
4532 * A blocking lock was requested. Package up
4533 * this smb into a queued request and push it
4534 * onto the blocking lock queue.
4536 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
, lock_pid
, offset
, count
)) {
4537 END_PROFILE(SMBlockingX
);
4545 /* If any of the above locks failed, then we must unlock
4546 all of the previous locks (X/Open spec). */
4547 if (i
!= num_locks
&& num_locks
!= 0) {
4549 * Ensure we don't do a remove on the lock that just failed,
4550 * as under POSIX rules, if we have a lock already there, we
4551 * will delete it (and we shouldn't) .....
4553 for(i
--; i
>= 0; i
--) {
4554 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4555 count
= get_lock_count( data
, i
, large_file_format
);
4556 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4559 * There is no error code marked "stupid client bug".... :-).
4562 END_PROFILE(SMBlockingX
);
4563 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4566 do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4568 END_PROFILE(SMBlockingX
);
4569 return ERROR_NT(status
);
4572 set_message(outbuf
,2,0,True
);
4574 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4575 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4577 END_PROFILE(SMBlockingX
);
4578 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4581 /****************************************************************************
4582 Reply to a SMBreadbmpx (read block multiplex) request.
4583 ****************************************************************************/
4585 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4596 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4597 START_PROFILE(SMBreadBmpx
);
4599 /* this function doesn't seem to work - disable by default */
4600 if (!lp_readbmpx()) {
4601 END_PROFILE(SMBreadBmpx
);
4602 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
4605 outsize
= set_message(outbuf
,8,0,True
);
4607 CHECK_FSP(fsp
,conn
);
4610 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
4611 maxcount
= SVAL(inbuf
,smb_vwv3
);
4613 data
= smb_buf(outbuf
);
4614 pad
= ((long)data
)%4;
4619 max_per_packet
= bufsize
-(outsize
+pad
);
4623 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
4624 END_PROFILE(SMBreadBmpx
);
4625 return ERROR_DOS(ERRDOS
,ERRlock
);
4629 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4631 nread
= read_file(fsp
,data
,startpos
,N
);
4636 if (nread
< (ssize_t
)N
)
4637 tcount
= total_read
+ nread
;
4639 set_message(outbuf
,8,nread
,False
);
4640 SIVAL(outbuf
,smb_vwv0
,startpos
);
4641 SSVAL(outbuf
,smb_vwv2
,tcount
);
4642 SSVAL(outbuf
,smb_vwv6
,nread
);
4643 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4645 if (!send_smb(smbd_server_fd(),outbuf
))
4646 exit_server("reply_readbmpx: send_smb failed.");
4648 total_read
+= nread
;
4650 } while (total_read
< (ssize_t
)tcount
);
4652 END_PROFILE(SMBreadBmpx
);
4656 /****************************************************************************
4657 Reply to a SMBsetattrE.
4658 ****************************************************************************/
4660 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4662 struct utimbuf unix_times
;
4664 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4665 START_PROFILE(SMBsetattrE
);
4667 outsize
= set_message(outbuf
,0,0,True
);
4669 if(!fsp
|| (fsp
->conn
!= conn
)) {
4670 END_PROFILE(SMBgetattrE
);
4671 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4675 * Convert the DOS times into unix times. Ignore create
4676 * time as UNIX can't set this.
4679 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4680 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4683 * Patch from Ray Frush <frush@engr.colostate.edu>
4684 * Sometimes times are sent as zero - ignore them.
4687 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0)) {
4688 /* Ignore request */
4689 if( DEBUGLVL( 3 ) ) {
4690 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4691 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4693 END_PROFILE(SMBsetattrE
);
4695 } else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0)) {
4696 /* set modify time = to access time if modify time was 0 */
4697 unix_times
.modtime
= unix_times
.actime
;
4700 /* Set the date on this file */
4701 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4702 END_PROFILE(SMBsetattrE
);
4703 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4706 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4707 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4709 END_PROFILE(SMBsetattrE
);
4714 /* Back from the dead for OS/2..... JRA. */
4716 /****************************************************************************
4717 Reply to a SMBwritebmpx (write block multiplex primary) request.
4718 ****************************************************************************/
4720 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4723 ssize_t nwritten
= -1;
4730 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4731 START_PROFILE(SMBwriteBmpx
);
4733 CHECK_FSP(fsp
,conn
);
4737 tcount
= SVAL(inbuf
,smb_vwv1
);
4738 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
4739 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
4740 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4741 smb_doff
= SVAL(inbuf
,smb_vwv11
);
4743 data
= smb_base(inbuf
) + smb_doff
;
4745 /* If this fails we need to send an SMBwriteC response,
4746 not an SMBwritebmpx - set this up now so we don't forget */
4747 SCVAL(outbuf
,smb_com
,SMBwritec
);
4749 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
,False
)) {
4750 END_PROFILE(SMBwriteBmpx
);
4751 return(ERROR_DOS(ERRDOS
,ERRlock
));
4754 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4756 if(lp_syncalways(SNUM(conn
)) || write_through
)
4757 sync_file(conn
,fsp
);
4759 if(nwritten
< (ssize_t
)numtowrite
) {
4760 END_PROFILE(SMBwriteBmpx
);
4761 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
4764 /* If the maximum to be written to this file
4765 is greater than what we just wrote then set
4766 up a secondary struct to be attached to this
4767 fd, we will use this to cache error messages etc. */
4769 if((ssize_t
)tcount
> nwritten
) {
4770 write_bmpx_struct
*wbms
;
4771 if(fsp
->wbmpx_ptr
!= NULL
)
4772 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
4774 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
4776 DEBUG(0,("Out of memory in reply_readmpx\n"));
4777 END_PROFILE(SMBwriteBmpx
);
4778 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
4780 wbms
->wr_mode
= write_through
;
4781 wbms
->wr_discard
= False
; /* No errors yet */
4782 wbms
->wr_total_written
= nwritten
;
4783 wbms
->wr_errclass
= 0;
4785 fsp
->wbmpx_ptr
= wbms
;
4788 /* We are returning successfully, set the message type back to
4790 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
4792 outsize
= set_message(outbuf
,1,0,True
);
4794 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
4796 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4797 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
4799 if (write_through
&& tcount
==nwritten
) {
4800 /* We need to send both a primary and a secondary response */
4801 smb_setlen(outbuf
,outsize
- 4);
4802 if (!send_smb(smbd_server_fd(),outbuf
))
4803 exit_server("reply_writebmpx: send_smb failed.");
4805 /* Now the secondary */
4806 outsize
= set_message(outbuf
,1,0,True
);
4807 SCVAL(outbuf
,smb_com
,SMBwritec
);
4808 SSVAL(outbuf
,smb_vwv0
,nwritten
);
4811 END_PROFILE(SMBwriteBmpx
);
4815 /****************************************************************************
4816 Reply to a SMBwritebs (write block multiplex secondary) request.
4817 ****************************************************************************/
4819 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4822 ssize_t nwritten
= -1;
4829 write_bmpx_struct
*wbms
;
4830 BOOL send_response
= False
;
4831 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4832 START_PROFILE(SMBwriteBs
);
4834 CHECK_FSP(fsp
,conn
);
4837 tcount
= SVAL(inbuf
,smb_vwv1
);
4838 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
4839 numtowrite
= SVAL(inbuf
,smb_vwv6
);
4840 smb_doff
= SVAL(inbuf
,smb_vwv7
);
4842 data
= smb_base(inbuf
) + smb_doff
;
4844 /* We need to send an SMBwriteC response, not an SMBwritebs */
4845 SCVAL(outbuf
,smb_com
,SMBwritec
);
4847 /* This fd should have an auxiliary struct attached,
4848 check that it does */
4849 wbms
= fsp
->wbmpx_ptr
;
4851 END_PROFILE(SMBwriteBs
);
4855 /* If write through is set we can return errors, else we must cache them */
4856 write_through
= wbms
->wr_mode
;
4858 /* Check for an earlier error */
4859 if(wbms
->wr_discard
) {
4860 END_PROFILE(SMBwriteBs
);
4861 return -1; /* Just discard the packet */
4864 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4866 if(lp_syncalways(SNUM(conn
)) || write_through
)
4867 sync_file(conn
,fsp
);
4869 if (nwritten
< (ssize_t
)numtowrite
) {
4871 /* We are returning an error - we can delete the aux struct */
4874 fsp
->wbmpx_ptr
= NULL
;
4875 END_PROFILE(SMBwriteBs
);
4876 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
4878 END_PROFILE(SMBwriteBs
);
4879 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4882 /* Increment the total written, if this matches tcount
4883 we can discard the auxiliary struct (hurrah !) and return a writeC */
4884 wbms
->wr_total_written
+= nwritten
;
4885 if(wbms
->wr_total_written
>= tcount
) {
4886 if (write_through
) {
4887 outsize
= set_message(outbuf
,1,0,True
);
4888 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4889 send_response
= True
;
4893 fsp
->wbmpx_ptr
= NULL
;
4897 END_PROFILE(SMBwriteBs
);
4901 END_PROFILE(SMBwriteBs
);
4905 /****************************************************************************
4906 Reply to a SMBgetattrE.
4907 ****************************************************************************/
4909 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4911 SMB_STRUCT_STAT sbuf
;
4914 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4915 START_PROFILE(SMBgetattrE
);
4917 outsize
= set_message(outbuf
,11,0,True
);
4919 if(!fsp
|| (fsp
->conn
!= conn
)) {
4920 END_PROFILE(SMBgetattrE
);
4921 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4924 /* Do an fstat on this file */
4925 if(fsp_stat(fsp
, &sbuf
)) {
4926 END_PROFILE(SMBgetattrE
);
4927 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4930 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4933 * Convert the times into dos times. Set create
4934 * date to be last modify date as UNIX doesn't save
4938 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4939 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4940 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4943 SIVAL(outbuf
,smb_vwv6
,0);
4944 SIVAL(outbuf
,smb_vwv8
,0);
4946 uint32 allocation_size
= get_allocation_size(fsp
, &sbuf
);
4947 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4948 SIVAL(outbuf
,smb_vwv8
,allocation_size
);
4950 SSVAL(outbuf
,smb_vwv10
, mode
);
4952 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
4954 END_PROFILE(SMBgetattrE
);