2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
31 /* look in server.c for some explanation of these variables */
33 extern int DEBUGLEVEL
;
36 extern char magic_char
;
37 extern BOOL case_sensitive
;
38 extern BOOL case_preserve
;
39 extern BOOL short_case_preserve
;
40 extern pstring sesssetup_user
;
41 extern fstring global_myworkgroup
;
43 extern int global_oplock_break
;
44 uint32 global_client_caps
= 0;
47 /****************************************************************************
48 report a possible attack via the password buffer overflow bug
49 ****************************************************************************/
50 static void overflow_attack(int len
)
54 dbgtext( "ERROR: Invalid password length %d.\n", len
);
55 dbgtext( "Your machine may be under attack by someone " );
56 dbgtext( "attempting to exploit an old bug.\n" );
57 dbgtext( "Attack was from IP = %s.\n", client_addr(Client
) );
59 exit_server("possible attack");
63 /****************************************************************************
64 reply to an special message
65 ****************************************************************************/
66 int reply_special(char *inbuf
,char *outbuf
)
69 int msg_type
= CVAL(inbuf
,0);
70 int msg_flags
= CVAL(inbuf
,1);
72 extern fstring remote_machine
;
73 extern fstring local_machine
;
79 bzero(outbuf
,smb_size
);
84 case 0x81: /* session request */
85 CVAL(outbuf
,0) = 0x82;
87 if (name_len(inbuf
+4) > 50 ||
88 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
89 DEBUG(0,("Invalid name length in session request\n"));
92 name_extract(inbuf
,4,name1
);
93 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
94 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
97 fstrcpy(remote_machine
,name2
);
98 remote_machine
[15] = 0;
99 trim_string(remote_machine
," "," ");
100 strlower(remote_machine
);
102 fstrcpy(local_machine
,name1
);
103 len
= strlen(local_machine
);
105 name_type
= local_machine
[15];
106 local_machine
[15] = 0;
108 trim_string(local_machine
," "," ");
109 strlower(local_machine
);
111 if (name_type
== 'R') {
112 /* We are being asked for a pathworks session ---
114 CVAL(outbuf
, 0) = 0x83;
118 add_session_user(remote_machine
);
120 reload_services(True
);
124 claim_connection(NULL
,"STATUS.",MAXSTATUS
,True
);
129 case 0x89: /* session keepalive request
130 (some old clients produce this?) */
131 CVAL(outbuf
,0) = 0x85;
135 case 0x82: /* positive session response */
136 case 0x83: /* negative session response */
137 case 0x84: /* retarget session response */
138 DEBUG(0,("Unexpected session response\n"));
141 case 0x85: /* session keepalive */
146 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
147 msg_type
, msg_flags
));
153 /*******************************************************************
154 work out what error to give to a failed connection
155 ********************************************************************/
156 static int connection_error(char *inbuf
,char *outbuf
,int ecode
)
158 if (ecode
== ERRnoipc
) {
159 return(ERROR(ERRDOS
,ERRnoipc
));
162 return(ERROR(ERRSRV
,ecode
));
167 /****************************************************************************
168 parse a share descriptor string
169 ****************************************************************************/
170 static void parse_connect(char *p
,char *service
,char *user
,
171 char *password
,int *pwlen
,char *dev
)
175 DEBUG(4,("parsing connect string %s\n",p
));
177 p2
= strrchr(p
,'\\');
181 fstrcpy(service
,p2
+1);
186 *pwlen
= strlen(password
);
193 p
= strchr(service
,'%');
204 /****************************************************************************
206 ****************************************************************************/
207 int reply_tcon(connection_struct
*conn
,
208 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
215 uint16 vuid
= SVAL(inbuf
,smb_uid
);
219 *service
= *user
= *password
= *dev
= 0;
221 parse_connect(smb_buf(inbuf
)+1,service
,user
,password
,&pwlen
,dev
);
224 * Pass the user through the NT -> unix user mapping
228 (void)map_username(user
);
231 * Do any UNIX username case mangling.
233 (void)Get_Pwnam( user
, True
);
235 conn
= make_connection(service
,user
,password
,pwlen
,dev
,vuid
,&ecode
);
238 return(connection_error(inbuf
,outbuf
,ecode
));
241 outsize
= set_message(outbuf
,2,0,True
);
242 SSVAL(outbuf
,smb_vwv0
,max_recv
);
243 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
244 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
246 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
247 service
, user
, conn
->cnum
));
253 /****************************************************************************
254 reply to a tcon and X
255 ****************************************************************************/
256 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
263 uint16 vuid
= SVAL(inbuf
,smb_uid
);
264 int passlen
= SVAL(inbuf
,smb_vwv3
);
268 *service
= *user
= *password
= *devicename
= 0;
270 /* we might have to close an old one */
271 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
272 close_cnum(conn
,vuid
);
275 if (passlen
> MAX_PASS_LEN
) {
276 overflow_attack(passlen
);
279 memcpy(password
,smb_buf(inbuf
),passlen
);
281 path
= smb_buf(inbuf
) + passlen
;
284 if (strequal(password
," "))
286 passlen
= strlen(password
);
289 fstrcpy(service
,path
+2);
290 p
= strchr(service
,'\\');
292 return(ERROR(ERRSRV
,ERRinvnetname
));
294 fstrcpy(service
,p
+1);
295 p
= strchr(service
,'%');
300 StrnCpy(devicename
,path
+ strlen(path
) + 1,6);
301 DEBUG(4,("Got device type %s\n",devicename
));
304 * Pass the user through the NT -> unix user mapping
308 (void)map_username(user
);
311 * Do any UNIX username case mangling.
313 (void)Get_Pwnam(user
, True
);
315 conn
= make_connection(service
,user
,password
,passlen
,devicename
,vuid
,&ecode
);
318 return(connection_error(inbuf
,outbuf
,ecode
));
320 if (Protocol
< PROTOCOL_NT1
) {
321 set_message(outbuf
,2,strlen(devicename
)+1,True
);
322 pstrcpy(smb_buf(outbuf
),devicename
);
324 char *fsname
= lp_fstype(SNUM(conn
));
326 set_message(outbuf
,3,3,True
);
329 pstrcpy(p
,devicename
); p
= skip_string(p
,1); /* device name */
330 pstrcpy(p
,fsname
); p
= skip_string(p
,1); /* filesystem type e.g NTFS */
332 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
334 /* what does setting this bit do? It is set by NT4 and
335 may affect the ability to autorun mounted cdroms */
336 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
);
339 DEBUG(3,("tconX service=%s user=%s\n",
342 /* set the incoming and outgoing tid to the just created one */
343 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
344 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
346 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
350 /****************************************************************************
351 reply to an unknown type
352 ****************************************************************************/
353 int reply_unknown(char *inbuf
,char *outbuf
)
356 type
= CVAL(inbuf
,smb_com
);
358 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
359 smb_fn_name(type
), type
, type
));
361 return(ERROR(ERRSRV
,ERRunknownsmb
));
365 /****************************************************************************
367 ****************************************************************************/
368 int reply_ioctl(connection_struct
*conn
,
369 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
371 DEBUG(3,("ignoring ioctl\n"));
373 /* we just say it succeeds and hope its all OK.
374 some day it would be nice to interpret them individually */
375 return set_message(outbuf
,1,0,True
);
377 return(ERROR(ERRSRV
,ERRnosupport
));
381 /****************************************************************************
382 always return an error: it's just a matter of which one...
383 ****************************************************************************/
384 static int session_trust_account(connection_struct
*conn
, char *inbuf
, char *outbuf
, char *user
,
385 char *smb_passwd
, int smb_passlen
,
386 char *smb_nt_passwd
, int smb_nt_passlen
)
388 struct smb_passwd
*smb_trust_acct
= NULL
; /* check if trust account exists */
389 if (lp_security() == SEC_USER
)
391 smb_trust_acct
= getsmbpwnam(user
);
395 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user
));
396 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
397 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE
));
400 if (smb_trust_acct
== NULL
)
402 /* lkclXXXX: workstation entry doesn't exist */
403 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user
));
404 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
405 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER
));
409 if ((smb_passlen
!= 24) || (smb_nt_passlen
!= 24))
411 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user
));
412 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
413 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE
));
416 if (!smb_password_ok(smb_trust_acct
, NULL
, (unsigned char *)smb_passwd
, (unsigned char *)smb_nt_passwd
))
418 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user
));
419 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
420 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE
));
423 if (IS_BITS_SET_ALL(smb_trust_acct
->acct_ctrl
, ACB_DOMTRUST
))
425 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user
));
426 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
427 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT
));
430 if (IS_BITS_SET_ALL(smb_trust_acct
->acct_ctrl
, ACB_SVRTRUST
))
432 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user
));
433 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
434 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT
));
437 if (IS_BITS_SET_ALL(smb_trust_acct
->acct_ctrl
, ACB_WSTRUST
))
439 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user
));
440 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
441 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
));
445 /* don't know what to do: indicate logon failure */
446 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
447 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE
));
450 /****************************************************************************
451 Check for a valid username and password in security=server mode.
452 ****************************************************************************/
454 static BOOL
check_server_security(char *orig_user
, char *domain
,
455 char *smb_apasswd
, int smb_apasslen
,
456 char *smb_ntpasswd
, int smb_ntpasslen
)
458 if(lp_security() != SEC_SERVER
)
461 return server_validate(orig_user
, domain
,
462 smb_apasswd
, smb_apasslen
,
463 smb_ntpasswd
, smb_ntpasslen
);
466 /****************************************************************************
467 Check for a valid username and password in security=domain mode.
468 ****************************************************************************/
470 static BOOL
check_domain_security(char *orig_user
, char *domain
,
471 char *smb_apasswd
, int smb_apasslen
,
472 char *smb_ntpasswd
, int smb_ntpasslen
)
474 if(lp_security() != SEC_DOMAIN
)
477 return domain_client_validate(orig_user
, domain
,
478 smb_apasswd
, smb_apasslen
,
479 smb_ntpasswd
, smb_ntpasslen
);
482 /****************************************************************************
483 reply to a session setup command
484 ****************************************************************************/
486 int reply_sesssetup_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
492 int smb_apasslen
= 0;
494 int smb_ntpasslen
= 0;
495 pstring smb_ntpasswd
;
496 BOOL valid_nt_password
= False
;
500 static BOOL done_sesssetup
= False
;
501 BOOL doencrypt
= SMBENCRYPT();
507 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
509 if (Protocol
< PROTOCOL_NT1
) {
510 smb_apasslen
= SVAL(inbuf
,smb_vwv7
);
511 if (smb_apasslen
> MAX_PASS_LEN
)
513 overflow_attack(smb_apasslen
);
516 memcpy(smb_apasswd
,smb_buf(inbuf
),smb_apasslen
);
517 smb_apasswd
[smb_apasslen
] = 0;
518 pstrcpy(user
,smb_buf(inbuf
)+smb_apasslen
);
520 if (!doencrypt
&& (lp_security() != SEC_SERVER
)) {
521 smb_apasslen
= strlen(smb_apasswd
);
524 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
525 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
526 enum remote_arch_types ra_type
= get_remote_arch();
527 char *p
= smb_buf(inbuf
);
529 global_client_caps
= IVAL(inbuf
,smb_vwv11
);
531 /* client_caps is used as final determination if client is NT or Win95.
532 This is needed to return the correct error codes in some
536 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN95
)
538 if(global_client_caps
& (CAP_NT_SMBS
| CAP_STATUS32
))
539 set_remote_arch( RA_WINNT
);
541 set_remote_arch( RA_WIN95
);
544 if (passlen1
!= 24 && passlen2
!= 24)
547 if (passlen1
> MAX_PASS_LEN
) {
548 overflow_attack(passlen1
);
551 passlen1
= MIN(passlen1
, MAX_PASS_LEN
);
552 passlen2
= MIN(passlen2
, MAX_PASS_LEN
);
555 /* both Win95 and WinNT stuff up the password lengths for
556 non-encrypting systems. Uggh.
558 if passlen1==24 its a win95 system, and its setting the
559 password length incorrectly. Luckily it still works with the
560 default code because Win95 will null terminate the password
563 if passlen1>0 and passlen2>0 then maybe its a NT box and its
564 setting passlen2 to some random value which really stuffs
565 things up. we need to fix that one. */
567 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 && passlen2
!= 1)
571 if(doencrypt
|| ((lp_security() == SEC_SERVER
) || (lp_security() == SEC_DOMAIN
))) {
572 /* Save the lanman2 password and the NT md4 password. */
573 smb_apasslen
= passlen1
;
574 memcpy(smb_apasswd
,p
,smb_apasslen
);
575 smb_apasswd
[smb_apasslen
] = 0;
576 smb_ntpasslen
= passlen2
;
577 memcpy(smb_ntpasswd
,p
+passlen1
,smb_ntpasslen
);
578 smb_ntpasswd
[smb_ntpasslen
] = 0;
580 /* we use the first password that they gave */
581 smb_apasslen
= passlen1
;
582 StrnCpy(smb_apasswd
,p
,smb_apasslen
);
584 /* trim the password */
585 smb_apasslen
= strlen(smb_apasswd
);
587 /* wfwg sometimes uses a space instead of a null */
588 if (strequal(smb_apasswd
," ")) {
594 p
+= passlen1
+ passlen2
;
595 fstrcpy(user
,p
); p
= skip_string(p
,1);
598 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
599 domain
,skip_string(p
,1),skip_string(p
,2)));
603 DEBUG(3,("sesssetupX:name=[%s]\n",user
));
605 /* If name ends in $ then I think it's asking about whether a */
606 /* computer with that name (minus the $) has access. For now */
607 /* say yes to everything ending in $. */
608 if ((user
[strlen(user
) - 1] == '$') && (smb_apasslen
== 24) && (smb_ntpasslen
== 24))
610 return session_trust_account(conn
, inbuf
, outbuf
, user
,
611 smb_apasswd
, smb_apasslen
,
612 smb_ntpasswd
, smb_ntpasslen
);
615 /* If no username is sent use the guest account */
618 pstrcpy(user
,lp_guestaccount(-1));
619 /* If no user and no password then set guest flag. */
620 if( *smb_apasswd
== 0)
627 * In share level security, only overwrite sesssetup_use if
628 * it's a non null-session share. Helps keep %U and %G
632 if((lp_security() != SEC_SHARE
) || (*user
&& !guest
))
633 pstrcpy(sesssetup_user
,user
);
635 reload_services(True
);
638 * Save the username before mapping. We will use
639 * the original username sent to us for security=server
640 * and security=domain checking.
643 pstrcpy( orig_user
, user
);
646 * Pass the user through the NT -> unix user mapping
650 (void)map_username(user
);
653 * Do any UNIX username case mangling.
655 (void)Get_Pwnam( user
, True
);
657 add_session_user(user
);
660 * Check if the given username was the guest user with no password.
663 if(!guest
&& strequal(user
,lp_guestaccount(-1)) && (*smb_apasswd
== 0))
667 * Check with orig_user for security=server and
672 !check_server_security(orig_user
, domain
,
673 smb_apasswd
, smb_apasslen
,
674 smb_ntpasswd
, smb_ntpasslen
) &&
675 !check_domain_security(orig_user
, domain
,
676 smb_apasswd
, smb_apasslen
,
677 smb_ntpasswd
, smb_ntpasslen
) &&
678 !check_hosts_equiv(user
)
683 * If we get here then the user wasn't guest and the remote
684 * authentication methods failed. Check the authentication
685 * methods on this local server.
687 * If an NT password was supplied try and validate with that
688 * first. This is superior as the passwords are mixed case
689 * 128 length unicode.
694 if(!password_ok(user
, smb_ntpasswd
,smb_ntpasslen
,NULL
))
695 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
697 valid_nt_password
= True
;
700 if (!valid_nt_password
&& !password_ok(user
, smb_apasswd
,smb_apasslen
,NULL
))
702 if (lp_security() >= SEC_USER
)
704 #if (GUEST_SESSSETUP == 0)
705 return(ERROR(ERRSRV
,ERRbadpw
));
707 #if (GUEST_SESSSETUP == 1)
708 if (Get_Pwnam(user
,True
))
709 return(ERROR(ERRSRV
,ERRbadpw
));
712 if (*smb_apasswd
|| !Get_Pwnam(user
,True
))
713 pstrcpy(user
,lp_guestaccount(-1));
714 DEBUG(3,("Registered username %s for guest access\n",user
));
719 if (!Get_Pwnam(user
,True
)) {
720 DEBUG(3,("No such user %s - using guest account\n",user
));
721 pstrcpy(user
,lp_guestaccount(-1));
725 if (!strequal(user
,lp_guestaccount(-1)) &&
726 lp_servicenumber(user
) < 0)
728 int homes
= lp_servicenumber(HOMES_NAME
);
729 char *home
= get_home_dir(user
);
730 if (homes
>= 0 && home
)
731 lp_add_home(user
,homes
,home
);
735 /* it's ok - setup a reply */
736 if (Protocol
< PROTOCOL_NT1
) {
737 set_message(outbuf
,3,0,True
);
740 set_message(outbuf
,3,3,True
);
742 pstrcpy(p
,"Unix"); p
= skip_string(p
,1);
743 pstrcpy(p
,"Samba "); pstrcat(p
,VERSION
); p
= skip_string(p
,1);
744 pstrcpy(p
,global_myworkgroup
); p
= skip_string(p
,1);
745 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
746 /* perhaps grab OS version here?? */
749 /* Set the correct uid in the outgoing and incoming packets
750 We will use this on future requests to determine which
751 user we should become.
754 struct passwd
*pw
= Get_Pwnam(user
,False
);
756 DEBUG(1,("Username %s is invalid on this system\n",user
));
757 return(ERROR(ERRSRV
,ERRbadpw
));
764 SSVAL(outbuf
,smb_vwv2
,1);
766 /* register the name and uid as being validated, so further connections
767 to a uid can get through without a password, on the same VC */
768 sess_vuid
= register_vuid(uid
,gid
,user
,sesssetup_user
,guest
);
770 SSVAL(outbuf
,smb_uid
,sess_vuid
);
771 SSVAL(inbuf
,smb_uid
,sess_vuid
);
774 max_send
= MIN(max_send
,smb_bufsize
);
776 DEBUG(6,("Client requested max send size of %d\n", max_send
));
778 done_sesssetup
= True
;
780 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
784 /****************************************************************************
786 ****************************************************************************/
787 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
793 BOOL bad_path
= False
;
796 pstrcpy(name
,smb_buf(inbuf
) + 1);
797 unix_convert(name
,conn
,0,&bad_path
,&st
);
799 mode
= SVAL(inbuf
,smb_vwv0
);
801 if (check_name(name
,conn
)) {
803 ok
= S_ISDIR(st
.st_mode
);
805 ok
= directory_exist(name
,NULL
);
810 /* We special case this - as when a Windows machine
811 is parsing a path is steps through the components
812 one at a time - if a component fails it expects
813 ERRbadpath, not ERRbadfile.
817 unix_ERR_class
= ERRDOS
;
818 unix_ERR_code
= ERRbadpath
;
822 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
823 if((errno
== ENOTDIR
) && (Protocol
>= PROTOCOL_NT1
) &&
824 (get_remote_arch() == RA_WINNT
))
826 unix_ERR_class
= ERRDOS
;
827 unix_ERR_code
= ERRbaddirectory
;
831 return(UNIXERROR(ERRDOS
,ERRbadpath
));
834 outsize
= set_message(outbuf
,0,0,True
);
836 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
842 /****************************************************************************
844 ****************************************************************************/
845 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
849 SMB_STRUCT_STAT sbuf
;
854 BOOL bad_path
= False
;
856 pstrcpy(fname
,smb_buf(inbuf
) + 1);
858 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
859 under WfWg - weird! */
862 mode
= aHIDDEN
| aDIR
;
863 if (!CAN_WRITE(conn
)) mode
|= aRONLY
;
870 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
871 if (check_name(fname
,conn
))
873 if (VALID_STAT(sbuf
) || dos_stat(fname
,&sbuf
) == 0)
875 mode
= dos_mode(conn
,fname
,&sbuf
);
877 mtime
= sbuf
.st_mtime
;
883 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
889 if((errno
== ENOENT
) && bad_path
)
891 unix_ERR_class
= ERRDOS
;
892 unix_ERR_code
= ERRbadpath
;
895 return(UNIXERROR(ERRDOS
,ERRbadfile
));
898 outsize
= set_message(outbuf
,10,0,True
);
900 SSVAL(outbuf
,smb_vwv0
,mode
);
901 if(lp_dos_filetime_resolution(SNUM(conn
)) )
902 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
904 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
905 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
907 if (Protocol
>= PROTOCOL_NT1
) {
908 char *p
= strrchr(fname
,'/');
909 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
911 if (!is_8_3(fname
, True
))
912 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
915 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
921 /****************************************************************************
923 ****************************************************************************/
924 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
932 BOOL bad_path
= False
;
934 pstrcpy(fname
,smb_buf(inbuf
) + 1);
935 unix_convert(fname
,conn
,0,&bad_path
,&st
);
937 mode
= SVAL(inbuf
,smb_vwv0
);
938 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
940 if (VALID_STAT_OF_DIR(st
) || directory_exist(fname
,NULL
))
942 if (check_name(fname
,conn
))
943 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
945 ok
= set_filetime(conn
,fname
,mtime
);
949 if((errno
== ENOENT
) && bad_path
)
951 unix_ERR_class
= ERRDOS
;
952 unix_ERR_code
= ERRbadpath
;
955 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
958 outsize
= set_message(outbuf
,0,0,True
);
960 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
966 /****************************************************************************
968 ****************************************************************************/
969 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
972 SMB_BIG_UINT dfree
,dsize
,bsize
;
974 sys_disk_free(".",&bsize
,&dfree
,&dsize
);
976 outsize
= set_message(outbuf
,5,0,True
);
978 SSVAL(outbuf
,smb_vwv0
,dsize
);
979 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
980 SSVAL(outbuf
,smb_vwv2
,512);
981 SSVAL(outbuf
,smb_vwv3
,dfree
);
983 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
989 /****************************************************************************
991 Can be called from SMBsearch, SMBffirst or SMBfunique.
992 ****************************************************************************/
993 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1004 BOOL finished
= False
;
1013 BOOL check_descend
= False
;
1014 BOOL expect_close
= False
;
1015 BOOL can_open
= True
;
1016 BOOL bad_path
= False
;
1018 *mask
= *directory
= *fname
= 0;
1020 /* If we were called as SMBffirst then we must expect close. */
1021 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
1022 expect_close
= True
;
1024 outsize
= set_message(outbuf
,1,3,True
);
1025 maxentries
= SVAL(inbuf
,smb_vwv0
);
1026 dirtype
= SVAL(inbuf
,smb_vwv1
);
1027 path
= smb_buf(inbuf
) + 1;
1028 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
1031 /* dirtype &= ~aDIR; */
1033 DEBUG(5,("path=%s status_len=%d\n",path
,status_len
));
1036 if (status_len
== 0)
1040 pstrcpy(directory
,smb_buf(inbuf
)+1);
1041 pstrcpy(dir2
,smb_buf(inbuf
)+1);
1042 unix_convert(directory
,conn
,0,&bad_path
,NULL
);
1045 if (!check_name(directory
,conn
))
1048 p
= strrchr(dir2
,'/');
1060 p
= strrchr(directory
,'/');
1066 if (strlen(directory
) == 0)
1067 pstrcpy(directory
,"./");
1069 CVAL(status
,0) = dirtype
;
1073 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1074 memcpy(mask
,status
+1,11);
1076 dirtype
= CVAL(status
,0) & 0x1F;
1077 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1080 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1081 if (!case_sensitive
)
1085 /* turn strings of spaces into a . */
1087 trim_string(mask
,NULL
," ");
1088 if ((p
= strrchr(mask
,' ')))
1093 trim_string(mask
,NULL
," ");
1099 /* Convert the formatted mask. (This code lives in trans2.c) */
1107 if((skip
= skip_multibyte_char( *p
)) != 0 )
1113 if (*p
!= '?' && *p
!= '*' && !isdoschar(*p
))
1115 DEBUG(5,("Invalid char [%c] in search mask?\n",*p
));
1123 if (!strchr(mask
,'.') && strlen(mask
)>8)
1126 fstrcpy(tmp
,&mask
[8]);
1132 DEBUG(5,("mask=%s directory=%s\n",mask
,directory
));
1136 p
= smb_buf(outbuf
) + 3;
1140 if (status_len
== 0)
1142 dptr_num
= dptr_create(conn
,directory
,expect_close
,SVAL(inbuf
,smb_pid
));
1147 if((errno
== ENOENT
) && bad_path
)
1149 unix_ERR_class
= ERRDOS
;
1150 unix_ERR_code
= ERRbadpath
;
1152 return (UNIXERROR(ERRDOS
,ERRnofids
));
1154 return(ERROR(ERRDOS
,ERRnofids
));
1158 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1162 if ((dirtype
&0x1F) == aVOLID
)
1164 memcpy(p
,status
,21);
1165 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
1166 dptr_fill(p
+12,dptr_num
);
1167 if (dptr_zero(p
+12) && (status_len
==0))
1171 p
+= DIR_STRUCT_SIZE
;
1175 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1176 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1177 if (in_list(conn
->dirpath
,
1178 lp_dontdescend(SNUM(conn
)),True
))
1179 check_descend
= True
;
1181 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
1184 !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
1187 memcpy(p
,status
,21);
1188 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
1189 dptr_fill(p
+12,dptr_num
);
1192 p
+= DIR_STRUCT_SIZE
;
1201 if (numentries
== 0 || !ok
)
1203 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1204 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1207 /* If we were called as SMBffirst with smb_search_id == NULL
1208 and no entries were found then return error and close dirptr
1211 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
1213 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1214 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1215 /* Also close the dptr - we know it's gone */
1216 dptr_close(dptr_num
);
1219 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1220 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
1221 dptr_close(dptr_num
);
1223 SSVAL(outbuf
,smb_vwv0
,numentries
);
1224 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1225 CVAL(smb_buf(outbuf
),0) = 5;
1226 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1228 if (Protocol
>= PROTOCOL_NT1
) {
1229 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
1230 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
1233 outsize
+= DIR_STRUCT_SIZE
*numentries
;
1234 smb_setlen(outbuf
,outsize
- 4);
1236 if ((! *directory
) && dptr_path(dptr_num
))
1237 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1239 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1240 smb_fn_name(CVAL(inbuf
,smb_com
)),
1241 mask
, directory
, dirtype
, numentries
, maxentries
) );
1247 /****************************************************************************
1248 reply to a fclose (stop directory search)
1249 ****************************************************************************/
1250 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1258 outsize
= set_message(outbuf
,1,0,True
);
1259 path
= smb_buf(inbuf
) + 1;
1260 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
1263 if (status_len
== 0)
1264 return(ERROR(ERRSRV
,ERRsrverror
));
1266 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1268 if(dptr_fetch(status
+12,&dptr_num
)) {
1269 /* Close the dptr - we know it's gone */
1270 dptr_close(dptr_num
);
1273 SSVAL(outbuf
,smb_vwv0
,0);
1275 DEBUG(3,("search close\n"));
1281 /****************************************************************************
1283 ****************************************************************************/
1285 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1295 SMB_STRUCT_STAT sbuf
;
1296 BOOL bad_path
= False
;
1298 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1300 share_mode
= SVAL(inbuf
,smb_vwv0
);
1302 pstrcpy(fname
,smb_buf(inbuf
)+1);
1303 unix_convert(fname
,conn
,0,&bad_path
,NULL
);
1307 return(ERROR(ERRSRV
,ERRnofids
));
1309 if (!check_name(fname
,conn
))
1311 if((errno
== ENOENT
) && bad_path
)
1313 unix_ERR_class
= ERRDOS
;
1314 unix_ERR_code
= ERRbadpath
;
1317 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1320 unixmode
= unix_mode(conn
,aARCH
);
1322 open_file_shared(fsp
,conn
,fname
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1323 unixmode
, oplock_request
,&rmode
,NULL
);
1327 if((errno
== ENOENT
) && bad_path
)
1329 unix_ERR_class
= ERRDOS
;
1330 unix_ERR_code
= ERRbadpath
;
1333 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1336 if (sys_fstat(fsp
->fd_ptr
->fd
,&sbuf
) != 0) {
1337 close_file(fsp
,False
);
1338 return(ERROR(ERRDOS
,ERRnoaccess
));
1341 size
= sbuf
.st_size
;
1342 fmode
= dos_mode(conn
,fname
,&sbuf
);
1343 mtime
= sbuf
.st_mtime
;
1346 DEBUG(3,("attempt to open a directory %s\n",fname
));
1347 close_file(fsp
,False
);
1348 return(ERROR(ERRDOS
,ERRnoaccess
));
1351 outsize
= set_message(outbuf
,7,0,True
);
1352 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1353 SSVAL(outbuf
,smb_vwv1
,fmode
);
1354 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1355 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1357 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1358 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1359 SSVAL(outbuf
,smb_vwv6
,rmode
);
1361 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1362 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1365 if(fsp
->granted_oplock
)
1366 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1371 /****************************************************************************
1372 reply to an open and X
1373 ****************************************************************************/
1374 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1377 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1378 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1379 /* Breakout the oplock request bits so we can set the
1380 reply bits separately. */
1381 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1382 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1383 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1385 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1386 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1387 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1389 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1392 int fmode
=0,mtime
=0,rmode
=0;
1393 SMB_STRUCT_STAT sbuf
;
1395 BOOL bad_path
= False
;
1398 /* If it's an IPC, pass off the pipe handler. */
1399 if (IS_IPC(conn
) && lp_nt_pipe_support())
1400 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1402 /* XXXX we need to handle passed times, sattr and flags */
1404 pstrcpy(fname
,smb_buf(inbuf
));
1405 unix_convert(fname
,conn
,0,&bad_path
,NULL
);
1409 return(ERROR(ERRSRV
,ERRnofids
));
1411 if (!check_name(fname
,conn
))
1413 if((errno
== ENOENT
) && bad_path
)
1415 unix_ERR_class
= ERRDOS
;
1416 unix_ERR_code
= ERRbadpath
;
1419 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1422 unixmode
= unix_mode(conn
,smb_attr
| aARCH
);
1424 open_file_shared(fsp
,conn
,fname
,smb_mode
,smb_ofun
,unixmode
,
1425 oplock_request
, &rmode
,&smb_action
);
1429 if((errno
== ENOENT
) && bad_path
)
1431 unix_ERR_class
= ERRDOS
;
1432 unix_ERR_code
= ERRbadpath
;
1435 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1438 if (sys_fstat(fsp
->fd_ptr
->fd
,&sbuf
) != 0) {
1439 close_file(fsp
,False
);
1440 return(ERROR(ERRDOS
,ERRnoaccess
));
1443 size
= sbuf
.st_size
;
1444 fmode
= dos_mode(conn
,fname
,&sbuf
);
1445 mtime
= sbuf
.st_mtime
;
1447 close_file(fsp
,False
);
1448 return(ERROR(ERRDOS
,ERRnoaccess
));
1451 /* If the caller set the extended oplock request bit
1452 and we granted one (by whatever means) - set the
1453 correct bit for extended oplock reply.
1456 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1457 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1460 if(ex_oplock_request
&& fsp
->granted_oplock
) {
1461 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1464 /* If the caller set the core oplock request bit
1465 and we granted one (by whatever means) - set the
1466 correct bit for core oplock reply.
1469 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1470 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1473 if(core_oplock_request
&& fsp
->granted_oplock
) {
1474 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1477 set_message(outbuf
,15,0,True
);
1478 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1479 SSVAL(outbuf
,smb_vwv3
,fmode
);
1480 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1481 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1483 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1484 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1485 SSVAL(outbuf
,smb_vwv8
,rmode
);
1486 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1488 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1492 /****************************************************************************
1493 reply to a SMBulogoffX
1494 ****************************************************************************/
1495 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1497 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1498 user_struct
*vuser
= get_valid_user_struct(vuid
);
1501 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1504 /* in user level security we are supposed to close any files
1505 open by this user */
1506 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1507 file_close_user(vuid
);
1510 invalidate_vuid(vuid
);
1512 set_message(outbuf
,2,0,True
);
1514 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1516 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1520 /****************************************************************************
1521 reply to a mknew or a create
1522 ****************************************************************************/
1523 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1531 BOOL bad_path
= False
;
1533 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1535 com
= SVAL(inbuf
,smb_com
);
1537 createmode
= SVAL(inbuf
,smb_vwv0
);
1538 pstrcpy(fname
,smb_buf(inbuf
)+1);
1539 unix_convert(fname
,conn
,0,&bad_path
,NULL
);
1541 if (createmode
& aVOLID
)
1543 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1546 unixmode
= unix_mode(conn
,createmode
);
1550 return(ERROR(ERRSRV
,ERRnofids
));
1552 if (!check_name(fname
,conn
))
1554 if((errno
== ENOENT
) && bad_path
)
1556 unix_ERR_class
= ERRDOS
;
1557 unix_ERR_code
= ERRbadpath
;
1560 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1565 /* We should fail if file exists. */
1570 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1574 /* Open file in dos compatibility share mode. */
1575 open_file_shared(fsp
,conn
,fname
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1576 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1580 if((errno
== ENOENT
) && bad_path
)
1582 unix_ERR_class
= ERRDOS
;
1583 unix_ERR_code
= ERRbadpath
;
1586 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1589 outsize
= set_message(outbuf
,1,0,True
);
1590 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1592 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1593 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1596 if(fsp
->granted_oplock
)
1597 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1599 DEBUG( 2, ( "new file %s\n", fname
) );
1600 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1601 fname
, fsp
->fd_ptr
->fd
, createmode
, (int)unixmode
) );
1607 /****************************************************************************
1608 reply to a create temporary file
1609 ****************************************************************************/
1610 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1617 BOOL bad_path
= False
;
1619 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1621 createmode
= SVAL(inbuf
,smb_vwv0
);
1622 pstrcpy(fname
,smb_buf(inbuf
)+1);
1623 pstrcat(fname
,"/TMXXXXXX");
1624 unix_convert(fname
,conn
,0,&bad_path
,NULL
);
1626 unixmode
= unix_mode(conn
,createmode
);
1630 return(ERROR(ERRSRV
,ERRnofids
));
1632 if (!check_name(fname
,conn
))
1634 if((errno
== ENOENT
) && bad_path
)
1636 unix_ERR_class
= ERRDOS
;
1637 unix_ERR_code
= ERRbadpath
;
1640 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1643 pstrcpy(fname2
,(char *)mktemp(fname
));
1645 /* Open file in dos compatibility share mode. */
1646 /* We should fail if file exists. */
1647 open_file_shared(fsp
,conn
,fname2
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1648 (FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_FAIL
), unixmode
, oplock_request
, NULL
, NULL
);
1652 if((errno
== ENOENT
) && bad_path
)
1654 unix_ERR_class
= ERRDOS
;
1655 unix_ERR_code
= ERRbadpath
;
1658 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1661 outsize
= set_message(outbuf
,1,2 + strlen(fname2
),True
);
1662 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1663 CVAL(smb_buf(outbuf
),0) = 4;
1664 pstrcpy(smb_buf(outbuf
) + 1,fname2
);
1666 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1667 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1670 if(fsp
->granted_oplock
)
1671 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1673 DEBUG( 2, ( "created temp file %s\n", fname2
) );
1674 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1675 fname2
, fsp
->fd_ptr
->fd
, createmode
, (int)unixmode
) );
1681 /*******************************************************************
1682 check if a user is allowed to delete a file
1683 ********************************************************************/
1684 static BOOL
can_delete(char *fname
,connection_struct
*conn
, int dirtype
)
1686 SMB_STRUCT_STAT sbuf
;
1689 if (!CAN_WRITE(conn
)) return(False
);
1691 if (dos_lstat(fname
,&sbuf
) != 0) return(False
);
1692 fmode
= dos_mode(conn
,fname
,&sbuf
);
1693 if (fmode
& aDIR
) return(False
);
1694 if (!lp_delete_readonly(SNUM(conn
))) {
1695 if (fmode
& aRONLY
) return(False
);
1697 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1699 if (!check_file_sharing(conn
,fname
,False
)) return(False
);
1703 /****************************************************************************
1705 ****************************************************************************/
1706 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1715 int error
= ERRnoaccess
;
1718 BOOL bad_path
= False
;
1720 *directory
= *mask
= 0;
1722 dirtype
= SVAL(inbuf
,smb_vwv0
);
1724 pstrcpy(name
,smb_buf(inbuf
) + 1);
1726 DEBUG(3,("reply_unlink : %s\n",name
));
1728 unix_convert(name
,conn
,0,&bad_path
,NULL
);
1730 p
= strrchr(name
,'/');
1732 pstrcpy(directory
,"./");
1736 pstrcpy(directory
,name
);
1740 if (is_mangled(mask
))
1741 check_mangled_cache( mask
);
1743 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
1746 pstrcat(directory
,"/");
1747 pstrcat(directory
,mask
);
1748 if (can_delete(directory
,conn
,dirtype
) && !dos_unlink(directory
))
1751 exists
= file_exist(directory
,NULL
);
1753 void *dirptr
= NULL
;
1756 if (check_name(directory
,conn
))
1757 dirptr
= OpenDir(conn
, directory
, True
);
1759 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1760 the pattern matches against the long name, otherwise the short name
1761 We don't implement this yet XXXX
1768 if (strequal(mask
,"????????.???"))
1771 while ((dname
= ReadDirName(dirptr
)))
1774 pstrcpy(fname
,dname
);
1776 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
1778 error
= ERRnoaccess
;
1779 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1780 if (!can_delete(fname
,conn
,dirtype
)) continue;
1781 if (!dos_unlink(fname
)) count
++;
1782 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname
));
1790 return(ERROR(ERRDOS
,error
));
1793 if((errno
== ENOENT
) && bad_path
)
1795 unix_ERR_class
= ERRDOS
;
1796 unix_ERR_code
= ERRbadpath
;
1798 return(UNIXERROR(ERRDOS
,error
));
1802 outsize
= set_message(outbuf
,0,0,True
);
1808 /****************************************************************************
1809 reply to a readbraw (core+ protocol)
1810 ****************************************************************************/
1811 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1813 size_t maxcount
,mincount
;
1816 char *header
= outbuf
;
1821 * Special check if an oplock break has been issued
1822 * and the readraw request croses on the wire, we must
1823 * return a zero length response here.
1826 if(global_oplock_break
)
1828 _smb_setlen(header
,0);
1829 transfer_file(0,Client
,(SMB_OFF_T
)0,header
,4,0);
1830 DEBUG(5,("readbraw - oplock break finished\n"));
1834 fsp
= file_fsp(inbuf
,smb_vwv0
);
1836 startpos
= IVAL(inbuf
,smb_vwv1
);
1837 #ifdef LARGE_SMB_OFF_T
1838 if(CVAL(inbuf
,smb_wct
) == 10) {
1840 * This is a large offset (64 bit) read.
1842 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
1844 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1845 (double)startpos
));
1846 _smb_setlen(header
,0);
1847 transfer_file(0,Client
,(SMB_OFF_T
)0,header
,4,0);
1851 #endif /* LARGE_SMB_OFF_T */
1852 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
1853 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
1855 /* ensure we don't overrun the packet size */
1856 maxcount
= MIN(65535,maxcount
);
1857 maxcount
= MAX(mincount
,maxcount
);
1859 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1860 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp
->fnum
));
1861 _smb_setlen(header
,0);
1862 transfer_file(0,Client
,(SMB_OFF_T
)0,header
,4,0);
1866 if (!is_locked(fsp
,conn
,maxcount
,startpos
, F_RDLCK
))
1868 SMB_OFF_T size
= fsp
->size
;
1869 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
1871 if (size
< sizeneeded
)
1874 if (sys_fstat(fsp
->fd_ptr
->fd
,&st
) == 0)
1876 if (!fsp
->can_write
)
1880 nread
= MIN(maxcount
,(size
- startpos
));
1883 if (nread
< mincount
)
1886 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1887 fsp
->fnum
, (double)startpos
,
1888 maxcount
, mincount
, nread
) );
1892 BOOL seek_fail
= False
;
1894 _smb_setlen(header
,nread
);
1896 #if USE_READ_PREDICTION
1897 if (!fsp
->can_write
)
1898 predict
= read_predict(fsp
->fd_ptr
->fd
,startpos
,header
+4,NULL
,nread
);
1899 #endif /* USE_READ_PREDICTION */
1901 if ((nread
-predict
) > 0) {
1902 if(seek_file(fsp
,startpos
+ predict
) == -1) {
1903 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1910 ret
= (ssize_t
)transfer_file(fsp
->fd_ptr
->fd
,Client
,
1911 (SMB_OFF_T
)(nread
-predict
),header
,4+predict
,
1916 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1917 fsp
->fsp_name
,startpos
,nread
,ret
));
1919 #else /* UNSAFE_READRAW */
1920 ret
= read_file(fsp
,header
+4,startpos
,nread
);
1921 if (ret
< mincount
) ret
= 0;
1923 _smb_setlen(header
,ret
);
1924 transfer_file(0,Client
,0,header
,4+ret
,0);
1925 #endif /* UNSAFE_READRAW */
1927 DEBUG(5,("readbraw finished\n"));
1932 /****************************************************************************
1933 reply to a lockread (core+ protocol)
1934 ****************************************************************************/
1935 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
1944 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1946 CHECK_FSP(fsp
,conn
);
1950 numtoread
= SVAL(inbuf
,smb_vwv1
);
1951 startpos
= IVAL(inbuf
,smb_vwv2
);
1953 outsize
= set_message(outbuf
,5,3,True
);
1954 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1955 data
= smb_buf(outbuf
) + 3;
1957 if(!do_lock( fsp
, conn
, numtoread
, startpos
, F_RDLCK
, &eclass
, &ecode
)) {
1958 if((ecode
== ERRlock
) && lp_blocking_locks(SNUM(conn
))) {
1960 * A blocking lock was requested. Package up
1961 * this smb into a queued request and push it
1962 * onto the blocking lock queue.
1964 if(push_blocking_lock_request(inbuf
, length
, -1, 0))
1967 return (ERROR(eclass
,ecode
));
1970 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1973 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1976 SSVAL(outbuf
,smb_vwv0
,nread
);
1977 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1978 SSVAL(smb_buf(outbuf
),1,nread
);
1980 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1981 fsp
->fnum
, numtoread
, nread
) );
1987 /****************************************************************************
1989 ****************************************************************************/
1990 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1997 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1999 CHECK_FSP(fsp
,conn
);
2003 numtoread
= SVAL(inbuf
,smb_vwv1
);
2004 startpos
= IVAL(inbuf
,smb_vwv2
);
2006 outsize
= set_message(outbuf
,5,3,True
);
2007 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2008 data
= smb_buf(outbuf
) + 3;
2010 if (is_locked(fsp
,conn
,numtoread
,startpos
, F_RDLCK
))
2011 return(ERROR(ERRDOS
,ERRlock
));
2014 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2017 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2020 SSVAL(outbuf
,smb_vwv0
,nread
);
2021 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2022 CVAL(smb_buf(outbuf
),0) = 1;
2023 SSVAL(smb_buf(outbuf
),1,nread
);
2025 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2026 fsp
->fnum
, numtoread
, nread
) );
2032 /****************************************************************************
2033 reply to a read and X
2034 ****************************************************************************/
2035 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2037 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2038 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2039 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2040 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2044 /* If it's an IPC, pass off the pipe handler. */
2046 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2048 CHECK_FSP(fsp
,conn
);
2052 set_message(outbuf
,12,0,True
);
2053 data
= smb_buf(outbuf
);
2055 #ifdef LARGE_SMB_OFF_T
2056 if(CVAL(inbuf
,smb_wct
) == 12) {
2058 * This is a large offset (64 bit) read.
2060 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2062 #endif /* LARGE_SMB_OFF_T */
2064 if (is_locked(fsp
,conn
,smb_maxcnt
,startpos
, F_RDLCK
))
2065 return(ERROR(ERRDOS
,ERRlock
));
2066 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2069 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2071 SSVAL(outbuf
,smb_vwv5
,nread
);
2072 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2073 SSVAL(smb_buf(outbuf
),-2,nread
);
2075 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2076 fsp
->fnum
, smb_mincnt
, smb_maxcnt
, nread
) );
2078 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2081 /****************************************************************************
2082 reply to a writebraw (core+ or LANMAN1.0 protocol)
2083 ****************************************************************************/
2084 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2087 ssize_t total_written
=0;
2088 size_t numtowrite
=0;
2093 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2096 CHECK_FSP(fsp
,conn
);
2100 tcount
= IVAL(inbuf
,smb_vwv1
);
2101 startpos
= IVAL(inbuf
,smb_vwv3
);
2102 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2104 /* We have to deal with slightly different formats depending
2105 on whether we are using the core+ or lanman1.0 protocol */
2106 if(Protocol
<= PROTOCOL_COREPLUS
) {
2107 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2108 data
= smb_buf(inbuf
);
2110 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2111 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2114 /* force the error type */
2115 CVAL(inbuf
,smb_com
) = SMBwritec
;
2116 CVAL(outbuf
,smb_com
) = SMBwritec
;
2118 if (is_locked(fsp
,conn
,tcount
,startpos
, F_WRLCK
))
2119 return(ERROR(ERRDOS
,ERRlock
));
2121 if (seek_file(fsp
,startpos
) == -1) {
2122 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos
));
2123 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2127 nwritten
= write_file(fsp
,data
,numtowrite
);
2129 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2130 fsp
->fnum
, (double)startpos
, numtowrite
, nwritten
, write_through
));
2132 if (nwritten
< numtowrite
)
2133 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2135 total_written
= nwritten
;
2137 /* Return a message to the redirector to tell it
2138 to send more bytes */
2139 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
2140 SSVALS(outbuf
,smb_vwv0
,-1);
2141 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2142 send_smb(Client
,outbuf
);
2144 /* Now read the raw data into the buffer and write it */
2145 if (read_smb_length(Client
,inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2146 exit_server("secondary writebraw failed");
2149 /* Even though this is not an smb message, smb_len
2150 returns the generic length of an smb message */
2151 numtowrite
= smb_len(inbuf
);
2153 if (tcount
> nwritten
+numtowrite
) {
2154 DEBUG(3,("Client overestimated the write %d %d %d\n",
2155 tcount
,nwritten
,numtowrite
));
2158 nwritten
= transfer_file(Client
,fsp
->fd_ptr
->fd
,(SMB_OFF_T
)numtowrite
,NULL
,0,
2160 total_written
+= nwritten
;
2162 /* Set up outbuf to return the correct return */
2163 outsize
= set_message(outbuf
,1,0,True
);
2164 CVAL(outbuf
,smb_com
) = SMBwritec
;
2165 SSVAL(outbuf
,smb_vwv0
,total_written
);
2167 if (nwritten
< (ssize_t
)numtowrite
) {
2168 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2169 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2172 if (lp_syncalways(SNUM(conn
)) || write_through
)
2173 sync_file(conn
,fsp
);
2175 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2176 fsp
->fnum
, (double)startpos
, numtowrite
, total_written
));
2178 /* we won't return a status if write through is not selected - this
2179 follows what WfWg does */
2180 if (!write_through
&& total_written
==tcount
)
2186 /****************************************************************************
2187 reply to a writeunlock (core+)
2188 ****************************************************************************/
2189 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2191 ssize_t nwritten
= -1;
2197 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2200 CHECK_FSP(fsp
,conn
);
2204 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2205 startpos
= IVAL(inbuf
,smb_vwv2
);
2206 data
= smb_buf(inbuf
) + 3;
2208 if (is_locked(fsp
,conn
,numtowrite
,startpos
, F_WRLCK
))
2209 return(ERROR(ERRDOS
,ERRlock
));
2211 if(seek_file(fsp
,startpos
) == -1)
2212 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2214 /* The special X/Open SMB protocol handling of
2215 zero length writes is *NOT* done for
2220 nwritten
= write_file(fsp
,data
,numtowrite
);
2222 if (lp_syncalways(SNUM(conn
)))
2223 sync_file(conn
,fsp
);
2225 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
2226 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2228 if(!do_unlock(fsp
, conn
, numtowrite
, startpos
, &eclass
, &ecode
))
2229 return(ERROR(eclass
,ecode
));
2231 outsize
= set_message(outbuf
,1,0,True
);
2233 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2235 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2236 fsp
->fnum
, numtowrite
, nwritten
) );
2241 /****************************************************************************
2243 ****************************************************************************/
2244 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int dum_size
,int dum_buffsize
)
2247 ssize_t nwritten
= -1;
2250 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2253 CHECK_FSP(fsp
,conn
);
2257 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2258 startpos
= IVAL(inbuf
,smb_vwv2
);
2259 data
= smb_buf(inbuf
) + 3;
2261 if (is_locked(fsp
,conn
,numtowrite
,startpos
, F_WRLCK
))
2262 return(ERROR(ERRDOS
,ERRlock
));
2264 if(seek_file(fsp
,startpos
) == -1)
2265 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2267 /* X/Open SMB protocol says that if smb_vwv1 is
2268 zero then the file size should be extended or
2269 truncated to the size given in smb_vwv[2-3] */
2271 nwritten
= set_filelen(fsp
->fd_ptr
->fd
, (SMB_OFF_T
)startpos
);
2273 nwritten
= write_file(fsp
,data
,numtowrite
);
2275 if (lp_syncalways(SNUM(conn
)))
2276 sync_file(conn
,fsp
);
2278 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
2279 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2281 outsize
= set_message(outbuf
,1,0,True
);
2283 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2285 if (nwritten
< (ssize_t
)numtowrite
) {
2286 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2287 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2290 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2291 fsp
->fnum
, numtowrite
, nwritten
));
2297 /****************************************************************************
2298 reply to a write and X
2299 ****************************************************************************/
2300 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2302 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2303 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2304 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2305 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2306 ssize_t nwritten
= -1;
2307 int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2310 /* If it's an IPC, pass off the pipe handler. */
2312 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2314 CHECK_FSP(fsp
,conn
);
2318 data
= smb_base(inbuf
) + smb_doff
;
2320 #ifdef LARGE_SMB_OFF_T
2321 if(CVAL(inbuf
,smb_wct
) == 14) {
2323 * This is a large offset (64 bit) write.
2325 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2327 #endif /* LARGE_SMB_OFF_T */
2329 if (is_locked(fsp
,conn
,numtowrite
,startpos
, F_WRLCK
))
2330 return(ERROR(ERRDOS
,ERRlock
));
2332 if(seek_file(fsp
,startpos
) == -1)
2333 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2335 /* X/Open SMB protocol says that, unlike SMBwrite
2336 if the length is zero then NO truncation is
2337 done, just a write of zero. To truncate a file,
2342 nwritten
= write_file(fsp
,data
,numtowrite
);
2344 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
2345 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2347 set_message(outbuf
,6,0,True
);
2349 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2351 if (nwritten
< (ssize_t
)numtowrite
) {
2352 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2353 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2356 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2357 fsp
->fnum
, numtowrite
, nwritten
));
2359 if (lp_syncalways(SNUM(conn
)) || write_through
)
2360 sync_file(conn
,fsp
);
2362 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2366 /****************************************************************************
2368 ****************************************************************************/
2369 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2375 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2377 CHECK_FSP(fsp
,conn
);
2380 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2381 startpos
= IVAL(inbuf
,smb_vwv2
);
2385 case 0: umode
= SEEK_SET
; break;
2386 case 1: umode
= SEEK_CUR
; break;
2387 case 2: umode
= SEEK_END
; break;
2389 umode
= SEEK_SET
; break;
2392 if((res
= sys_lseek(fsp
->fd_ptr
->fd
,startpos
,umode
)) == -1)
2393 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2397 outsize
= set_message(outbuf
,2,0,True
);
2398 SIVALS(outbuf
,smb_vwv0
,res
);
2400 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2401 fsp
->fnum
, (double)startpos
, mode
));
2406 /****************************************************************************
2408 ****************************************************************************/
2409 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2411 int outsize
= set_message(outbuf
,0,0,True
);
2412 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2415 CHECK_FSP(fsp
,conn
);
2420 file_sync_all(conn
);
2422 sync_file(conn
,fsp
);
2425 DEBUG(3,("flush\n"));
2430 /****************************************************************************
2432 ****************************************************************************/
2433 int reply_exit(connection_struct
*conn
,
2434 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2436 int outsize
= set_message(outbuf
,0,0,True
);
2437 DEBUG(3,("exit\n"));
2443 /****************************************************************************
2444 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2445 ****************************************************************************/
2446 int reply_close(connection_struct
*conn
,
2447 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2451 int32 eclass
= 0, err
= 0;
2452 files_struct
*fsp
= NULL
;
2454 outsize
= set_message(outbuf
,0,0,True
);
2456 /* If it's an IPC, pass off to the pipe handler. */
2458 return reply_pipe_close(conn
, inbuf
,outbuf
);
2461 fsp
= file_fsp(inbuf
,smb_vwv0
);
2464 * We can only use CHECK_FSP if we know it's not a directory.
2467 if(!fsp
|| !fsp
->open
|| (fsp
->conn
!= conn
))
2468 return(ERROR(ERRDOS
,ERRbadfid
));
2470 if(HAS_CACHED_ERROR(fsp
)) {
2471 eclass
= fsp
->wbmpx_ptr
->wr_errclass
;
2472 err
= fsp
->wbmpx_ptr
->wr_error
;
2475 if(fsp
->is_directory
) {
2477 * Special case - close NT SMB directory
2480 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
2481 close_directory(fsp
);
2484 * Close ordinary file.
2486 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2488 /* try and set the date */
2489 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2491 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2492 fsp
->fd_ptr
->fd
, fsp
->fnum
,
2493 conn
->num_files_open
));
2495 close_file(fsp
,True
);
2498 /* We have a cached error */
2500 return(ERROR(eclass
,err
));
2506 /****************************************************************************
2507 reply to a writeclose (Core+ protocol)
2508 ****************************************************************************/
2509 int reply_writeclose(connection_struct
*conn
,
2510 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2513 ssize_t nwritten
= -1;
2518 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2520 CHECK_FSP(fsp
,conn
);
2524 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2525 startpos
= IVAL(inbuf
,smb_vwv2
);
2526 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2527 data
= smb_buf(inbuf
) + 1;
2529 if (is_locked(fsp
,conn
,numtowrite
,startpos
, F_WRLCK
))
2530 return(ERROR(ERRDOS
,ERRlock
));
2532 if(seek_file(fsp
,startpos
) == -1)
2533 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2535 nwritten
= write_file(fsp
,data
,numtowrite
);
2537 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2539 close_file(fsp
,True
);
2541 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2542 fsp
->fnum
, numtowrite
, nwritten
,
2543 conn
->num_files_open
));
2546 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2548 outsize
= set_message(outbuf
,1,0,True
);
2550 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2555 /****************************************************************************
2557 ****************************************************************************/
2558 int reply_lock(connection_struct
*conn
,
2559 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
2561 int outsize
= set_message(outbuf
,0,0,True
);
2562 SMB_OFF_T count
,offset
;
2565 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2567 CHECK_FSP(fsp
,conn
);
2570 count
= IVAL(inbuf
,smb_vwv1
);
2571 offset
= IVAL(inbuf
,smb_vwv3
);
2573 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2574 fsp
->fd_ptr
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
2576 if (!do_lock(fsp
, conn
, count
, offset
, F_WRLCK
, &eclass
, &ecode
)) {
2577 if((ecode
== ERRlock
) && lp_blocking_locks(SNUM(conn
))) {
2579 * A blocking lock was requested. Package up
2580 * this smb into a queued request and push it
2581 * onto the blocking lock queue.
2583 if(push_blocking_lock_request(inbuf
, length
, -1, 0))
2586 return (ERROR(eclass
,ecode
));
2593 /****************************************************************************
2595 ****************************************************************************/
2596 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2598 int outsize
= set_message(outbuf
,0,0,True
);
2599 SMB_OFF_T count
,offset
;
2602 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2604 CHECK_FSP(fsp
,conn
);
2607 count
= IVAL(inbuf
,smb_vwv1
);
2608 offset
= IVAL(inbuf
,smb_vwv3
);
2610 if(!do_unlock(fsp
, conn
, count
, offset
, &eclass
, &ecode
))
2611 return (ERROR(eclass
,ecode
));
2613 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2614 fsp
->fd_ptr
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
2620 /****************************************************************************
2622 ****************************************************************************/
2623 int reply_tdis(connection_struct
*conn
,
2624 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2626 int outsize
= set_message(outbuf
,0,0,True
);
2629 vuid
= SVAL(inbuf
,smb_uid
);
2632 DEBUG(4,("Invalid connection in tdis\n"));
2633 return(ERROR(ERRSRV
,ERRinvnid
));
2638 close_cnum(conn
,vuid
);
2645 /****************************************************************************
2647 ****************************************************************************/
2648 int reply_echo(connection_struct
*conn
,
2649 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2651 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2653 int data_len
= smb_buflen(inbuf
);
2654 int outsize
= set_message(outbuf
,1,data_len
,True
);
2656 /* copy any incoming data back out */
2658 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2660 if (smb_reverb
> 100) {
2661 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2665 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2666 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2668 smb_setlen(outbuf
,outsize
- 4);
2670 send_smb(Client
,outbuf
);
2673 DEBUG(3,("echo %d times\n", smb_reverb
));
2679 /****************************************************************************
2680 reply to a printopen
2681 ****************************************************************************/
2682 int reply_printopen(connection_struct
*conn
,
2683 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2690 *fname
= *fname2
= 0;
2692 if (!CAN_PRINT(conn
))
2693 return(ERROR(ERRDOS
,ERRnoaccess
));
2698 pstrcpy(s
,smb_buf(inbuf
)+1);
2701 if (!(isalnum((int)*p
) || strchr("._-",*p
)))
2706 if (strlen(s
) > 10) s
[10] = 0;
2708 slprintf(fname
,sizeof(fname
)-1, "%s.XXXXXX",s
);
2713 return(ERROR(ERRSRV
,ERRnofids
));
2715 pstrcpy(fname2
,(char *)mktemp(fname
));
2717 if (!check_name(fname2
,conn
)) {
2719 return(ERROR(ERRDOS
,ERRnoaccess
));
2722 /* Open for exclusive use, write only. */
2723 open_file_shared(fsp
,conn
,fname2
, SET_DENY_MODE(DENY_ALL
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
2724 (FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
), unix_mode(conn
,0), 0, NULL
, NULL
);
2728 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2731 /* force it to be a print file */
2732 fsp
->print_file
= True
;
2734 outsize
= set_message(outbuf
,1,0,True
);
2735 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2737 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2738 fname2
, fsp
->fd_ptr
->fd
, fsp
->fnum
));
2744 /****************************************************************************
2745 reply to a printclose
2746 ****************************************************************************/
2747 int reply_printclose(connection_struct
*conn
,
2748 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2750 int outsize
= set_message(outbuf
,0,0,True
);
2751 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2753 CHECK_FSP(fsp
,conn
);
2756 if (!CAN_PRINT(conn
))
2757 return(ERROR(ERRDOS
,ERRnoaccess
));
2759 DEBUG(3,("printclose fd=%d fnum=%d\n",
2760 fsp
->fd_ptr
->fd
,fsp
->fnum
));
2762 close_file(fsp
,True
);
2768 /****************************************************************************
2769 reply to a printqueue
2770 ****************************************************************************/
2771 int reply_printqueue(connection_struct
*conn
,
2772 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2774 int outsize
= set_message(outbuf
,2,3,True
);
2775 int max_count
= SVAL(inbuf
,smb_vwv0
);
2776 int start_index
= SVAL(inbuf
,smb_vwv1
);
2778 /* we used to allow the client to get the cnum wrong, but that
2779 is really quite gross and only worked when there was only
2780 one printer - I think we should now only accept it if they
2781 get it right (tridge) */
2782 if (!CAN_PRINT(conn
))
2783 return(ERROR(ERRDOS
,ERRnoaccess
));
2785 SSVAL(outbuf
,smb_vwv0
,0);
2786 SSVAL(outbuf
,smb_vwv1
,0);
2787 CVAL(smb_buf(outbuf
),0) = 1;
2788 SSVAL(smb_buf(outbuf
),1,0);
2790 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2791 start_index
, max_count
));
2794 print_queue_struct
*queue
= NULL
;
2795 char *p
= smb_buf(outbuf
) + 3;
2796 int count
= get_printqueue(SNUM(conn
), conn
,&queue
,NULL
);
2797 int num_to_get
= ABS(max_count
);
2798 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
2804 num_to_get
= MIN(num_to_get
,count
-first
);
2807 for (i
=first
;i
<first
+num_to_get
;i
++) {
2808 put_dos_date2(p
,0,queue
[i
].time
);
2809 CVAL(p
,4) = (queue
[i
].status
==LPQ_PRINTING
?2:3);
2810 SSVAL(p
,5,printjob_encode(SNUM(conn
),
2812 SIVAL(p
,7,queue
[i
].size
);
2814 StrnCpy(p
+12,queue
[i
].user
,16);
2819 outsize
= set_message(outbuf
,2,28*count
+3,False
);
2820 SSVAL(outbuf
,smb_vwv0
,count
);
2821 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
2822 CVAL(smb_buf(outbuf
),0) = 1;
2823 SSVAL(smb_buf(outbuf
),1,28*count
);
2826 if (queue
) free(queue
);
2828 DEBUG(3,("%d entries returned in queue\n",count
));
2835 /****************************************************************************
2836 reply to a printwrite
2837 ****************************************************************************/
2838 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2841 int outsize
= set_message(outbuf
,0,0,True
);
2843 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2845 if (!CAN_PRINT(conn
))
2846 return(ERROR(ERRDOS
,ERRnoaccess
));
2848 CHECK_FSP(fsp
,conn
);
2852 numtowrite
= SVAL(smb_buf(inbuf
),1);
2853 data
= smb_buf(inbuf
) + 3;
2855 if (write_file(fsp
,data
,numtowrite
) != numtowrite
)
2856 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2858 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
2864 /****************************************************************************
2866 ****************************************************************************/
2867 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2870 int outsize
,ret
= -1;
2871 BOOL bad_path
= False
;
2873 pstrcpy(directory
,smb_buf(inbuf
) + 1);
2874 unix_convert(directory
,conn
,0,&bad_path
,NULL
);
2876 if (check_name(directory
, conn
))
2877 ret
= dos_mkdir(directory
,unix_mode(conn
,aDIR
));
2881 if((errno
== ENOENT
) && bad_path
)
2883 unix_ERR_class
= ERRDOS
;
2884 unix_ERR_code
= ERRbadpath
;
2886 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2889 outsize
= set_message(outbuf
,0,0,True
);
2891 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, ret
) );
2896 /****************************************************************************
2897 Static function used by reply_rmdir to delete an entire directory
2899 ****************************************************************************/
2900 static BOOL
recursive_rmdir(char *directory
)
2904 void *dirptr
= OpenDir(NULL
, directory
, False
);
2909 while((dname
= ReadDirName(dirptr
)))
2914 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2917 /* Construct the full name. */
2918 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
2924 pstrcpy(fullname
, directory
);
2925 pstrcat(fullname
, "/");
2926 pstrcat(fullname
, dname
);
2928 if(dos_lstat(fullname
, &st
) != 0)
2934 if(st
.st_mode
& S_IFDIR
)
2936 if(recursive_rmdir(fullname
)!=0)
2941 if(dos_rmdir(fullname
) != 0)
2947 else if(dos_unlink(fullname
) != 0)
2957 /****************************************************************************
2959 ****************************************************************************/
2960 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2965 BOOL bad_path
= False
;
2967 pstrcpy(directory
,smb_buf(inbuf
) + 1);
2968 unix_convert(directory
,conn
, NULL
,&bad_path
,NULL
);
2970 if (check_name(directory
,conn
))
2973 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
2974 ok
= (dos_rmdir(directory
) == 0);
2975 if(!ok
&& (errno
== ENOTEMPTY
) && lp_veto_files(SNUM(conn
)))
2977 /* Check to see if the only thing in this directory are
2978 vetoed files/directories. If so then delete them and
2979 retry. If we fail to delete any of them (and we *don't*
2980 do a recursive delete) then fail the rmdir. */
2981 BOOL all_veto_files
= True
;
2983 void *dirptr
= OpenDir(conn
, directory
, False
);
2987 int dirpos
= TellDir(dirptr
);
2988 while ((dname
= ReadDirName(dirptr
)))
2990 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2992 if(!IS_VETO_PATH(conn
, dname
))
2994 all_veto_files
= False
;
3000 SeekDir(dirptr
,dirpos
);
3001 while ((dname
= ReadDirName(dirptr
)))
3006 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3009 /* Construct the full name. */
3010 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
3015 pstrcpy(fullname
, directory
);
3016 pstrcat(fullname
, "/");
3017 pstrcat(fullname
, dname
);
3019 if(dos_lstat(fullname
, &st
) != 0)
3021 if(st
.st_mode
& S_IFDIR
)
3023 if(lp_recursive_veto_delete(SNUM(conn
)))
3025 if(recursive_rmdir(fullname
) != 0)
3028 if(dos_rmdir(fullname
) != 0)
3031 else if(dos_unlink(fullname
) != 0)
3035 /* Retry the rmdir */
3036 ok
= (dos_rmdir(directory
) == 0);
3046 DEBUG(3,("couldn't remove directory %s : %s\n",
3047 directory
,strerror(errno
)));
3052 if((errno
== ENOENT
) && bad_path
)
3054 unix_ERR_class
= ERRDOS
;
3055 unix_ERR_code
= ERRbadpath
;
3057 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3060 outsize
= set_message(outbuf
,0,0,True
);
3062 DEBUG( 3, ( "rmdir %s\n", directory
) );
3068 /*******************************************************************
3069 resolve wildcards in a filename rename
3070 ********************************************************************/
3071 static BOOL
resolve_wildcards(char *name1
,char *name2
)
3073 fstring root1
,root2
;
3077 name1
= strrchr(name1
,'/');
3078 name2
= strrchr(name2
,'/');
3080 if (!name1
|| !name2
) return(False
);
3082 fstrcpy(root1
,name1
);
3083 fstrcpy(root2
,name2
);
3084 p
= strrchr(root1
,'.');
3091 p
= strrchr(root2
,'.');
3123 pstrcpy(name2
,root2
);
3126 pstrcat(name2
,ext2
);
3132 /*******************************************************************
3133 check if a user is allowed to rename a file
3134 ********************************************************************/
3135 static BOOL
can_rename(char *fname
,connection_struct
*conn
)
3137 SMB_STRUCT_STAT sbuf
;
3139 if (!CAN_WRITE(conn
)) return(False
);
3141 if (dos_lstat(fname
,&sbuf
) != 0) return(False
);
3142 if (!check_file_sharing(conn
,fname
,True
)) return(False
);
3147 /****************************************************************************
3148 The guts of the rename command, split out so it may be called by the NT SMB
3150 ****************************************************************************/
3151 int rename_internals(connection_struct
*conn
,
3152 char *inbuf
, char *outbuf
, char *name
,
3153 char *newname
, BOOL replace_if_exists
)
3157 pstring newname_last_component
;
3160 BOOL bad_path1
= False
;
3161 BOOL bad_path2
= False
;
3163 int error
= ERRnoaccess
;
3166 *directory
= *mask
= 0;
3168 unix_convert(name
,conn
,0,&bad_path1
,NULL
);
3169 unix_convert(newname
,conn
,newname_last_component
,&bad_path2
,NULL
);
3172 * Split the old name into directory and last component
3173 * strings. Note that unix_convert may have stripped off a
3174 * leading ./ from both name and newname if the rename is
3175 * at the root of the share. We need to make sure either both
3176 * name and newname contain a / character or neither of them do
3177 * as this is checked in resolve_wildcards().
3180 p
= strrchr(name
,'/');
3182 pstrcpy(directory
,".");
3186 pstrcpy(directory
,name
);
3188 *p
= '/'; /* Replace needed for exceptional test below. */
3191 if (is_mangled(mask
))
3192 check_mangled_cache( mask
);
3194 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
3198 * No wildcards - just process the one file.
3200 BOOL is_short_name
= is_8_3(name
, True
);
3202 /* Add a terminating '/' to the directory name. */
3203 pstrcat(directory
,"/");
3204 pstrcat(directory
,mask
);
3206 /* Ensure newname contains a '/' also */
3207 if(strrchr(newname
,'/') == 0) {
3210 pstrcpy(tmpstr
, "./");
3211 pstrcat(tmpstr
, newname
);
3212 pstrcpy(newname
, tmpstr
);
3215 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3216 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3217 newname
, newname_last_component
, is_short_name
));
3220 * Check for special case with case preserving and not
3221 * case sensitive, if directory and newname are identical,
3222 * and the old last component differs from the original
3223 * last component only by case, then we should allow
3224 * the rename (user is trying to change the case of the
3227 if((case_sensitive
== False
) &&
3228 (((case_preserve
== True
) &&
3229 (is_short_name
== False
)) ||
3230 ((short_case_preserve
== True
) &&
3231 (is_short_name
== True
))) &&
3232 strcsequal(directory
, newname
)) {
3233 pstring newname_modified_last_component
;
3236 * Get the last component of the modified name.
3237 * Note that we guarantee that newname contains a '/'
3240 p
= strrchr(newname
,'/');
3241 pstrcpy(newname_modified_last_component
,p
+1);
3243 if(strcsequal(newname_modified_last_component
,
3244 newname_last_component
) == False
) {
3246 * Replace the modified last component with
3249 pstrcpy(p
+1, newname_last_component
);
3253 if(replace_if_exists
) {
3255 * NT SMB specific flag - rename can overwrite
3256 * file with the same name so don't check for
3259 if(resolve_wildcards(directory
,newname
) &&
3260 can_rename(directory
,conn
) &&
3261 !dos_rename(directory
,newname
))
3264 if (resolve_wildcards(directory
,newname
) &&
3265 can_rename(directory
,conn
) &&
3266 !file_exist(newname
,NULL
) &&
3267 !dos_rename(directory
,newname
))
3271 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count
!= 0) ? "succeeded" : "failed",
3272 directory
,newname
));
3274 if (!count
) exists
= file_exist(directory
,NULL
);
3275 if (!count
&& exists
&& file_exist(newname
,NULL
)) {
3281 * Wildcards - process each file that matches.
3283 void *dirptr
= NULL
;
3287 if (check_name(directory
,conn
))
3288 dirptr
= OpenDir(conn
, directory
, True
);
3293 if (strequal(mask
,"????????.???"))
3296 while ((dname
= ReadDirName(dirptr
))) {
3298 pstrcpy(fname
,dname
);
3300 if(!mask_match(fname
, mask
, case_sensitive
, False
))
3303 error
= ERRnoaccess
;
3304 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3305 if (!can_rename(fname
,conn
)) {
3306 DEBUG(6,("rename %s refused\n", fname
));
3309 pstrcpy(destname
,newname
);
3311 if (!resolve_wildcards(fname
,destname
)) {
3312 DEBUG(6,("resolve_wildcards %s %s failed\n", fname
, destname
));
3316 if (!replace_if_exists
&& file_exist(destname
,NULL
)) {
3317 DEBUG(6,("file_exist %s\n", destname
));
3322 if (!dos_rename(fname
,destname
))
3324 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3332 return(ERROR(ERRDOS
,error
));
3334 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
)) {
3335 unix_ERR_class
= ERRDOS
;
3336 unix_ERR_code
= ERRbadpath
;
3338 return(UNIXERROR(ERRDOS
,error
));
3345 /****************************************************************************
3347 ****************************************************************************/
3349 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3355 pstrcpy(name
,smb_buf(inbuf
) + 1);
3356 pstrcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
3358 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3360 outsize
= rename_internals(conn
, inbuf
, outbuf
, name
, newname
, False
);
3362 outsize
= set_message(outbuf
,0,0,True
);
3367 /*******************************************************************
3368 copy a file as part of a reply_copy
3369 ******************************************************************/
3371 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3372 int count
,BOOL target_is_directory
)
3377 files_struct
*fsp1
,*fsp2
;
3380 pstrcpy(dest
,dest1
);
3381 if (target_is_directory
) {
3382 char *p
= strrchr(src
,'/');
3391 if (!file_exist(src
,&st
))
3398 open_file_shared(fsp1
,conn
,src
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3399 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
3406 if (!target_is_directory
&& count
)
3411 close_file(fsp1
,False
);
3414 open_file_shared(fsp2
,conn
,dest
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3415 ofun
,st
.st_mode
,0,&Access
,&action
);
3418 close_file(fsp1
,False
);
3423 if ((ofun
&3) == 1) {
3424 if(sys_lseek(fsp2
->fd_ptr
->fd
,0,SEEK_END
) == -1) {
3425 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3428 * Stop the copy from occurring.
3436 ret
= transfer_file(fsp1
->fd_ptr
->fd
,
3437 fsp2
->fd_ptr
->fd
,st
.st_size
,NULL
,0,0);
3439 close_file(fsp1
,False
);
3440 close_file(fsp2
,False
);
3442 return(ret
== st
.st_size
);
3447 /****************************************************************************
3448 reply to a file copy.
3449 ****************************************************************************/
3450 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3455 pstring mask
,newname
;
3458 int error
= ERRnoaccess
;
3461 int tid2
= SVAL(inbuf
,smb_vwv0
);
3462 int ofun
= SVAL(inbuf
,smb_vwv1
);
3463 int flags
= SVAL(inbuf
,smb_vwv2
);
3464 BOOL target_is_directory
=False
;
3465 BOOL bad_path1
= False
;
3466 BOOL bad_path2
= False
;
3468 *directory
= *mask
= 0;
3470 pstrcpy(name
,smb_buf(inbuf
));
3471 pstrcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
3473 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
3475 if (tid2
!= conn
->cnum
) {
3476 /* can't currently handle inter share copies XXXX */
3477 DEBUG(3,("Rejecting inter-share copy\n"));
3478 return(ERROR(ERRSRV
,ERRinvdevice
));
3481 unix_convert(name
,conn
,0,&bad_path1
,NULL
);
3482 unix_convert(newname
,conn
,0,&bad_path2
,NULL
);
3484 target_is_directory
= directory_exist(newname
,NULL
);
3486 if ((flags
&1) && target_is_directory
) {
3487 return(ERROR(ERRDOS
,ERRbadfile
));
3490 if ((flags
&2) && !target_is_directory
) {
3491 return(ERROR(ERRDOS
,ERRbadpath
));
3494 if ((flags
&(1<<5)) && directory_exist(name
,NULL
)) {
3495 /* wants a tree copy! XXXX */
3496 DEBUG(3,("Rejecting tree copy\n"));
3497 return(ERROR(ERRSRV
,ERRerror
));
3500 p
= strrchr(name
,'/');
3502 pstrcpy(directory
,"./");
3506 pstrcpy(directory
,name
);
3510 if (is_mangled(mask
))
3511 check_mangled_cache( mask
);
3513 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
3516 pstrcat(directory
,"/");
3517 pstrcat(directory
,mask
);
3518 if (resolve_wildcards(directory
,newname
) &&
3519 copy_file(directory
,newname
,conn
,ofun
,
3520 count
,target_is_directory
)) count
++;
3521 if (!count
) exists
= file_exist(directory
,NULL
);
3523 void *dirptr
= NULL
;
3527 if (check_name(directory
,conn
))
3528 dirptr
= OpenDir(conn
, directory
, True
);
3534 if (strequal(mask
,"????????.???"))
3537 while ((dname
= ReadDirName(dirptr
)))
3540 pstrcpy(fname
,dname
);
3542 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
3544 error
= ERRnoaccess
;
3545 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
3546 pstrcpy(destname
,newname
);
3547 if (resolve_wildcards(fname
,destname
) &&
3548 copy_file(directory
,newname
,conn
,ofun
,
3549 count
,target_is_directory
)) count
++;
3550 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
3558 return(ERROR(ERRDOS
,error
));
3561 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
3563 unix_ERR_class
= ERRDOS
;
3564 unix_ERR_code
= ERRbadpath
;
3566 return(UNIXERROR(ERRDOS
,error
));
3570 outsize
= set_message(outbuf
,1,0,True
);
3571 SSVAL(outbuf
,smb_vwv0
,count
);
3576 /****************************************************************************
3578 ****************************************************************************/
3579 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3587 if (!CAN_SETDIR(snum
))
3588 return(ERROR(ERRDOS
,ERRnoaccess
));
3590 pstrcpy(newdir
,smb_buf(inbuf
) + 1);
3593 if (strlen(newdir
) == 0) {
3596 ok
= directory_exist(newdir
,NULL
);
3598 string_set(&conn
->connectpath
,newdir
);
3603 return(ERROR(ERRDOS
,ERRbadpath
));
3605 outsize
= set_message(outbuf
,0,0,True
);
3606 CVAL(outbuf
,smb_reh
) = CVAL(inbuf
,smb_reh
);
3608 DEBUG(3,("setdir %s\n", newdir
));
3613 /****************************************************************************
3614 reply to a lockingX request
3615 ****************************************************************************/
3616 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
3618 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
3619 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
3621 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
3623 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
3624 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
3625 SMB_OFF_T count
= 0, offset
= 0;
3626 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
3629 uint32 ecode
=0, dummy2
;
3630 int eclass
=0, dummy1
;
3631 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
);
3632 CHECK_FSP(fsp
,conn
);
3635 data
= smb_buf(inbuf
);
3637 /* Check if this is an oplock break on a file
3638 we have granted an oplock on.
3640 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
))
3643 SMB_DEV_T dev
= fsp
->fd_ptr
->dev
;
3644 SMB_INO_T inode
= fsp
->fd_ptr
->inode
;
3646 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3649 * Make sure we have granted an oplock on this file.
3651 if(!fsp
->granted_oplock
)
3653 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3654 no oplock granted on this file.\n", fsp
->fnum
));
3655 return ERROR(ERRDOS
,ERRlock
);
3658 /* Remove the oplock flag from the sharemode. */
3659 lock_share_entry(fsp
->conn
, dev
, inode
, &token
);
3660 if(remove_share_oplock(token
, fsp
)==False
) {
3662 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3663 dev = %x, inode = %.0f\n", fsp
->fnum
, (unsigned int)dev
, (double)inode
));
3665 unlock_share_entry(fsp
->conn
, dev
, inode
, token
);
3667 unlock_share_entry(fsp
->conn
, dev
, inode
, token
);
3669 /* Clear the granted flag and return. */
3670 fsp
->granted_oplock
= False
;
3673 /* if this is a pure oplock break request then don't send a reply */
3674 if (num_locks
== 0 && num_ulocks
== 0)
3676 /* Sanity check - ensure a pure oplock break is not a
3678 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
3679 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3680 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
3685 /* Data now points at the beginning of the list
3686 of smb_unlkrng structs */
3687 for(i
= 0; i
< (int)num_ulocks
; i
++) {
3688 if(!large_file_format
) {
3689 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3690 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3692 #ifdef LARGE_SMB_OFF_T
3694 count
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(i
))) << 32) |
3695 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(i
)));
3696 offset
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(i
))) << 32) |
3697 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(i
)));
3699 #endif /* LARGE_SMB_OFF_T */
3701 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3702 (double)offset
, (double)count
, fsp
->fsp_name
));
3704 if(!do_unlock(fsp
,conn
,count
,offset
,&eclass
, &ecode
))
3705 return ERROR(eclass
,ecode
);
3708 /* Setup the timeout in seconds. */
3709 lock_timeout
= ((lock_timeout
== -1) ? -1 : lock_timeout
/1000);
3711 /* Now do any requested locks */
3712 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
3714 /* Data now points at the beginning of the list
3715 of smb_lkrng structs */
3717 for(i
= 0; i
< (int)num_locks
; i
++) {
3718 if(!large_file_format
) {
3719 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3720 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3722 #ifdef LARGE_SMB_OFF_T
3724 count
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(i
))) << 32) |
3725 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(i
)));
3726 offset
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(i
))) << 32) |
3727 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(i
)));
3729 #endif /* LARGE_SMB_OFF_T */
3731 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3732 (double)offset
, (double)count
, fsp
->fsp_name
));
3734 if(!do_lock(fsp
,conn
,count
,offset
, ((locktype
& 1) ? F_RDLCK
: F_WRLCK
),
3736 if((ecode
== ERRlock
) && (lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
))) {
3738 * A blocking lock was requested. Package up
3739 * this smb into a queued request and push it
3740 * onto the blocking lock queue.
3742 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
))
3749 /* If any of the above locks failed, then we must unlock
3750 all of the previous locks (X/Open spec). */
3751 if(i
!= num_locks
&& num_locks
!= 0) {
3752 for(; i
>= 0; i
--) {
3753 if(!large_file_format
) {
3754 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3755 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3757 #ifdef LARGE_SMB_OFF_T
3759 count
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(i
))) << 32) |
3760 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(i
)));
3761 offset
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(i
))) << 32) |
3762 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(i
)));
3764 #endif /* LARGE_SMB_OFF_T */
3766 do_unlock(fsp
,conn
,count
,offset
,&dummy1
,&dummy2
);
3768 return ERROR(eclass
,ecode
);
3771 set_message(outbuf
,2,0,True
);
3773 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3774 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
3776 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
3780 /****************************************************************************
3781 reply to a SMBreadbmpx (read block multiplex) request
3782 ****************************************************************************/
3783 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
3794 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3796 /* this function doesn't seem to work - disable by default */
3798 return(ERROR(ERRSRV
,ERRuseSTD
));
3800 outsize
= set_message(outbuf
,8,0,True
);
3802 CHECK_FSP(fsp
,conn
);
3806 startpos
= IVAL(inbuf
,smb_vwv1
);
3807 maxcount
= SVAL(inbuf
,smb_vwv3
);
3809 data
= smb_buf(outbuf
);
3810 pad
= ((long)data
)%4;
3811 if (pad
) pad
= 4 - pad
;
3814 max_per_packet
= bufsize
-(outsize
+pad
);
3818 if (is_locked(fsp
,conn
,maxcount
,startpos
, F_RDLCK
))
3819 return(ERROR(ERRDOS
,ERRlock
));
3823 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
3825 nread
= read_file(fsp
,data
,startpos
,N
);
3827 if (nread
<= 0) nread
= 0;
3829 if (nread
< (ssize_t
)N
)
3830 tcount
= total_read
+ nread
;
3832 set_message(outbuf
,8,nread
,False
);
3833 SIVAL(outbuf
,smb_vwv0
,startpos
);
3834 SSVAL(outbuf
,smb_vwv2
,tcount
);
3835 SSVAL(outbuf
,smb_vwv6
,nread
);
3836 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
3838 send_smb(Client
,outbuf
);
3840 total_read
+= nread
;
3843 while (total_read
< (ssize_t
)tcount
);
3848 /****************************************************************************
3849 reply to a SMBwritebmpx (write block multiplex primary) request
3850 ****************************************************************************/
3851 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3854 ssize_t nwritten
= -1;
3861 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3863 CHECK_FSP(fsp
,conn
);
3867 tcount
= SVAL(inbuf
,smb_vwv1
);
3868 startpos
= IVAL(inbuf
,smb_vwv3
);
3869 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
3870 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3871 smb_doff
= SVAL(inbuf
,smb_vwv11
);
3873 data
= smb_base(inbuf
) + smb_doff
;
3875 /* If this fails we need to send an SMBwriteC response,
3876 not an SMBwritebmpx - set this up now so we don't forget */
3877 CVAL(outbuf
,smb_com
) = SMBwritec
;
3879 if (is_locked(fsp
,conn
,tcount
,startpos
,F_WRLCK
))
3880 return(ERROR(ERRDOS
,ERRlock
));
3882 if(seek_file(fsp
,startpos
) == -1)
3883 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3885 nwritten
= write_file(fsp
,data
,numtowrite
);
3887 if(lp_syncalways(SNUM(conn
)) || write_through
)
3888 sync_file(conn
,fsp
);
3890 if(nwritten
< (ssize_t
)numtowrite
)
3891 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3893 /* If the maximum to be written to this file
3894 is greater than what we just wrote then set
3895 up a secondary struct to be attached to this
3896 fd, we will use this to cache error messages etc. */
3897 if((ssize_t
)tcount
> nwritten
)
3899 write_bmpx_struct
*wbms
;
3900 if(fsp
->wbmpx_ptr
!= NULL
)
3901 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
3903 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
3906 DEBUG(0,("Out of memory in reply_readmpx\n"));
3907 return(ERROR(ERRSRV
,ERRnoresource
));
3909 wbms
->wr_mode
= write_through
;
3910 wbms
->wr_discard
= False
; /* No errors yet */
3911 wbms
->wr_total_written
= nwritten
;
3912 wbms
->wr_errclass
= 0;
3914 fsp
->wbmpx_ptr
= wbms
;
3917 /* We are returning successfully, set the message type back to
3919 CVAL(outbuf
,smb_com
) = SMBwriteBmpx
;
3921 outsize
= set_message(outbuf
,1,0,True
);
3923 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
3925 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3926 fsp
->fnum
, numtowrite
, nwritten
) );
3928 if (write_through
&& tcount
==nwritten
) {
3929 /* we need to send both a primary and a secondary response */
3930 smb_setlen(outbuf
,outsize
- 4);
3931 send_smb(Client
,outbuf
);
3933 /* now the secondary */
3934 outsize
= set_message(outbuf
,1,0,True
);
3935 CVAL(outbuf
,smb_com
) = SMBwritec
;
3936 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3943 /****************************************************************************
3944 reply to a SMBwritebs (write block multiplex secondary) request
3945 ****************************************************************************/
3946 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3949 ssize_t nwritten
= -1;
3956 write_bmpx_struct
*wbms
;
3957 BOOL send_response
= False
;
3958 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3960 CHECK_FSP(fsp
,conn
);
3963 tcount
= SVAL(inbuf
,smb_vwv1
);
3964 startpos
= IVAL(inbuf
,smb_vwv2
);
3965 numtowrite
= SVAL(inbuf
,smb_vwv6
);
3966 smb_doff
= SVAL(inbuf
,smb_vwv7
);
3968 data
= smb_base(inbuf
) + smb_doff
;
3970 /* We need to send an SMBwriteC response, not an SMBwritebs */
3971 CVAL(outbuf
,smb_com
) = SMBwritec
;
3973 /* This fd should have an auxiliary struct attached,
3974 check that it does */
3975 wbms
= fsp
->wbmpx_ptr
;
3976 if(!wbms
) return(-1);
3978 /* If write through is set we can return errors, else we must
3980 write_through
= wbms
->wr_mode
;
3982 /* Check for an earlier error */
3983 if(wbms
->wr_discard
)
3984 return -1; /* Just discard the packet */
3986 if(seek_file(fsp
,startpos
) == -1)
3990 /* We are returning an error - we can delete the aux struct */
3991 if (wbms
) free((char *)wbms
);
3992 fsp
->wbmpx_ptr
= NULL
;
3993 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3995 return(CACHE_ERROR(wbms
,ERRDOS
,ERRnoaccess
));
3998 nwritten
= write_file(fsp
,data
,numtowrite
);
4000 if(lp_syncalways(SNUM(conn
)) || write_through
)
4001 sync_file(conn
,fsp
);
4003 if (nwritten
< (ssize_t
)numtowrite
)
4007 /* We are returning an error - we can delete the aux struct */
4008 if (wbms
) free((char *)wbms
);
4009 fsp
->wbmpx_ptr
= NULL
;
4010 return(ERROR(ERRHRD
,ERRdiskfull
));
4012 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4015 /* Increment the total written, if this matches tcount
4016 we can discard the auxiliary struct (hurrah !) and return a writeC */
4017 wbms
->wr_total_written
+= nwritten
;
4018 if(wbms
->wr_total_written
>= tcount
)
4022 outsize
= set_message(outbuf
,1,0,True
);
4023 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4024 send_response
= True
;
4028 fsp
->wbmpx_ptr
= NULL
;
4038 /****************************************************************************
4039 reply to a SMBsetattrE
4040 ****************************************************************************/
4041 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4043 struct utimbuf unix_times
;
4045 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4047 outsize
= set_message(outbuf
,0,0,True
);
4049 CHECK_FSP(fsp
,conn
);
4052 /* Convert the DOS times into unix times. Ignore create
4053 time as UNIX can't set this.
4055 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4056 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4059 * Patch from Ray Frush <frush@engr.colostate.edu>
4060 * Sometimes times are sent as zero - ignore them.
4063 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0))
4065 /* Ignore request */
4068 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4069 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4073 else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0))
4075 /* set modify time = to access time if modify time was 0 */
4076 unix_times
.modtime
= unix_times
.actime
;
4079 /* Set the date on this file */
4080 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
))
4081 return(ERROR(ERRDOS
,ERRnoaccess
));
4083 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4084 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4090 /****************************************************************************
4091 reply to a SMBgetattrE
4092 ****************************************************************************/
4093 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4095 SMB_STRUCT_STAT sbuf
;
4098 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4100 outsize
= set_message(outbuf
,11,0,True
);
4102 CHECK_FSP(fsp
,conn
);
4105 /* Do an fstat on this file */
4106 if(sys_fstat(fsp
->fd_ptr
->fd
, &sbuf
))
4107 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4109 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4111 /* Convert the times into dos times. Set create
4112 date to be last modify date as UNIX doesn't save
4114 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4115 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4116 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4119 SIVAL(outbuf
,smb_vwv6
,0);
4120 SIVAL(outbuf
,smb_vwv8
,0);
4124 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4125 SIVAL(outbuf
,smb_vwv8
,ROUNDUP(sbuf
.st_size
,1024));
4127 SSVAL(outbuf
,smb_vwv10
, mode
);
4129 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));