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 (lp_map_to_guest() == NEVER_MAP_TO_GUEST
)
705 return(ERROR(ERRSRV
,ERRbadpw
));
707 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER
)
709 if (Get_Pwnam(user
,True
))
710 return(ERROR(ERRSRV
,ERRbadpw
));
714 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
715 * Then always map to guest account - as done below.
719 if (*smb_apasswd
|| !Get_Pwnam(user
,True
))
720 pstrcpy(user
,lp_guestaccount(-1));
721 DEBUG(3,("Registered username %s for guest access\n",user
));
726 if (!Get_Pwnam(user
,True
)) {
727 DEBUG(3,("No such user %s - using guest account\n",user
));
728 pstrcpy(user
,lp_guestaccount(-1));
732 if (!strequal(user
,lp_guestaccount(-1)) &&
733 lp_servicenumber(user
) < 0)
735 int homes
= lp_servicenumber(HOMES_NAME
);
736 char *home
= get_home_dir(user
);
737 if (homes
>= 0 && home
)
738 lp_add_home(user
,homes
,home
);
742 /* it's ok - setup a reply */
743 if (Protocol
< PROTOCOL_NT1
) {
744 set_message(outbuf
,3,0,True
);
747 set_message(outbuf
,3,3,True
);
749 pstrcpy(p
,"Unix"); p
= skip_string(p
,1);
750 pstrcpy(p
,"Samba "); pstrcat(p
,VERSION
); p
= skip_string(p
,1);
751 pstrcpy(p
,global_myworkgroup
); p
= skip_string(p
,1);
752 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
753 /* perhaps grab OS version here?? */
756 /* Set the correct uid in the outgoing and incoming packets
757 We will use this on future requests to determine which
758 user we should become.
761 struct passwd
*pw
= Get_Pwnam(user
,False
);
763 DEBUG(1,("Username %s is invalid on this system\n",user
));
764 return(ERROR(ERRSRV
,ERRbadpw
));
771 SSVAL(outbuf
,smb_vwv2
,1);
773 /* register the name and uid as being validated, so further connections
774 to a uid can get through without a password, on the same VC */
775 sess_vuid
= register_vuid(uid
,gid
,user
,sesssetup_user
,guest
);
777 SSVAL(outbuf
,smb_uid
,sess_vuid
);
778 SSVAL(inbuf
,smb_uid
,sess_vuid
);
781 max_send
= MIN(max_send
,smb_bufsize
);
783 DEBUG(6,("Client requested max send size of %d\n", max_send
));
785 done_sesssetup
= True
;
787 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
791 /****************************************************************************
793 ****************************************************************************/
794 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
800 BOOL bad_path
= False
;
803 pstrcpy(name
,smb_buf(inbuf
) + 1);
804 unix_convert(name
,conn
,0,&bad_path
,&st
);
806 mode
= SVAL(inbuf
,smb_vwv0
);
808 if (check_name(name
,conn
)) {
810 ok
= S_ISDIR(st
.st_mode
);
812 ok
= dos_directory_exist(name
,NULL
);
817 /* We special case this - as when a Windows machine
818 is parsing a path is steps through the components
819 one at a time - if a component fails it expects
820 ERRbadpath, not ERRbadfile.
824 unix_ERR_class
= ERRDOS
;
825 unix_ERR_code
= ERRbadpath
;
829 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
830 if((errno
== ENOTDIR
) && (Protocol
>= PROTOCOL_NT1
) &&
831 (get_remote_arch() == RA_WINNT
))
833 unix_ERR_class
= ERRDOS
;
834 unix_ERR_code
= ERRbaddirectory
;
838 return(UNIXERROR(ERRDOS
,ERRbadpath
));
841 outsize
= set_message(outbuf
,0,0,True
);
843 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
849 /****************************************************************************
851 ****************************************************************************/
852 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
856 SMB_STRUCT_STAT sbuf
;
861 BOOL bad_path
= False
;
863 pstrcpy(fname
,smb_buf(inbuf
) + 1);
865 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
866 under WfWg - weird! */
869 mode
= aHIDDEN
| aDIR
;
870 if (!CAN_WRITE(conn
)) mode
|= aRONLY
;
877 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
878 if (check_name(fname
,conn
))
880 if (VALID_STAT(sbuf
) || dos_stat(fname
,&sbuf
) == 0)
882 mode
= dos_mode(conn
,fname
,&sbuf
);
884 mtime
= sbuf
.st_mtime
;
890 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
896 if((errno
== ENOENT
) && bad_path
)
898 unix_ERR_class
= ERRDOS
;
899 unix_ERR_code
= ERRbadpath
;
902 return(UNIXERROR(ERRDOS
,ERRbadfile
));
905 outsize
= set_message(outbuf
,10,0,True
);
907 SSVAL(outbuf
,smb_vwv0
,mode
);
908 if(lp_dos_filetime_resolution(SNUM(conn
)) )
909 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
911 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
912 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
914 if (Protocol
>= PROTOCOL_NT1
) {
915 char *p
= strrchr(fname
,'/');
916 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
918 if (!is_8_3(fname
, True
))
919 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
922 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
928 /****************************************************************************
930 ****************************************************************************/
931 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
939 BOOL bad_path
= False
;
941 pstrcpy(fname
,smb_buf(inbuf
) + 1);
942 unix_convert(fname
,conn
,0,&bad_path
,&st
);
944 mode
= SVAL(inbuf
,smb_vwv0
);
945 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
947 if (VALID_STAT_OF_DIR(st
) || dos_directory_exist(fname
,NULL
))
949 if (check_name(fname
,conn
))
950 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
952 ok
= set_filetime(conn
,fname
,mtime
);
956 if((errno
== ENOENT
) && bad_path
)
958 unix_ERR_class
= ERRDOS
;
959 unix_ERR_code
= ERRbadpath
;
962 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
965 outsize
= set_message(outbuf
,0,0,True
);
967 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
973 /****************************************************************************
975 ****************************************************************************/
976 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
979 SMB_BIG_UINT dfree
,dsize
,bsize
;
981 sys_disk_free(".",&bsize
,&dfree
,&dsize
);
983 outsize
= set_message(outbuf
,5,0,True
);
985 SSVAL(outbuf
,smb_vwv0
,dsize
);
986 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
987 SSVAL(outbuf
,smb_vwv2
,512);
988 SSVAL(outbuf
,smb_vwv3
,dfree
);
990 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
996 /****************************************************************************
998 Can be called from SMBsearch, SMBffirst or SMBfunique.
999 ****************************************************************************/
1000 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1011 BOOL finished
= False
;
1020 BOOL check_descend
= False
;
1021 BOOL expect_close
= False
;
1022 BOOL can_open
= True
;
1023 BOOL bad_path
= False
;
1025 *mask
= *directory
= *fname
= 0;
1027 /* If we were called as SMBffirst then we must expect close. */
1028 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
1029 expect_close
= True
;
1031 outsize
= set_message(outbuf
,1,3,True
);
1032 maxentries
= SVAL(inbuf
,smb_vwv0
);
1033 dirtype
= SVAL(inbuf
,smb_vwv1
);
1034 path
= smb_buf(inbuf
) + 1;
1035 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
1038 /* dirtype &= ~aDIR; */
1040 DEBUG(5,("path=%s status_len=%d\n",path
,status_len
));
1043 if (status_len
== 0)
1047 pstrcpy(directory
,smb_buf(inbuf
)+1);
1048 pstrcpy(dir2
,smb_buf(inbuf
)+1);
1049 unix_convert(directory
,conn
,0,&bad_path
,NULL
);
1052 if (!check_name(directory
,conn
))
1055 p
= strrchr(dir2
,'/');
1067 p
= strrchr(directory
,'/');
1073 if (strlen(directory
) == 0)
1074 pstrcpy(directory
,"./");
1076 CVAL(status
,0) = dirtype
;
1080 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1081 memcpy(mask
,status
+1,11);
1083 dirtype
= CVAL(status
,0) & 0x1F;
1084 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1087 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1088 if (!case_sensitive
)
1092 /* turn strings of spaces into a . */
1094 trim_string(mask
,NULL
," ");
1095 if ((p
= strrchr(mask
,' ')))
1100 trim_string(mask
,NULL
," ");
1106 /* Convert the formatted mask. (This code lives in trans2.c) */
1114 if((skip
= skip_multibyte_char( *p
)) != 0 )
1120 if (*p
!= '?' && *p
!= '*' && !isdoschar(*p
))
1122 DEBUG(5,("Invalid char [%c] in search mask?\n",*p
));
1130 if (!strchr(mask
,'.') && strlen(mask
)>8)
1133 fstrcpy(tmp
,&mask
[8]);
1139 DEBUG(5,("mask=%s directory=%s\n",mask
,directory
));
1143 p
= smb_buf(outbuf
) + 3;
1147 if (status_len
== 0)
1149 dptr_num
= dptr_create(conn
,directory
,expect_close
,SVAL(inbuf
,smb_pid
));
1154 if((errno
== ENOENT
) && bad_path
)
1156 unix_ERR_class
= ERRDOS
;
1157 unix_ERR_code
= ERRbadpath
;
1159 return (UNIXERROR(ERRDOS
,ERRnofids
));
1161 return(ERROR(ERRDOS
,ERRnofids
));
1165 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1169 if ((dirtype
&0x1F) == aVOLID
)
1171 memcpy(p
,status
,21);
1172 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
1173 dptr_fill(p
+12,dptr_num
);
1174 if (dptr_zero(p
+12) && (status_len
==0))
1178 p
+= DIR_STRUCT_SIZE
;
1182 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1183 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1184 if (in_list(conn
->dirpath
,
1185 lp_dontdescend(SNUM(conn
)),True
))
1186 check_descend
= True
;
1188 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
1191 !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
1194 memcpy(p
,status
,21);
1195 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
1196 dptr_fill(p
+12,dptr_num
);
1199 p
+= DIR_STRUCT_SIZE
;
1208 if (numentries
== 0 || !ok
)
1210 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1211 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1214 /* If we were called as SMBffirst with smb_search_id == NULL
1215 and no entries were found then return error and close dirptr
1218 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
1220 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1221 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1222 /* Also close the dptr - we know it's gone */
1223 dptr_close(dptr_num
);
1226 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1227 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
1228 dptr_close(dptr_num
);
1230 SSVAL(outbuf
,smb_vwv0
,numentries
);
1231 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1232 CVAL(smb_buf(outbuf
),0) = 5;
1233 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1235 if (Protocol
>= PROTOCOL_NT1
) {
1236 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
1237 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
1240 outsize
+= DIR_STRUCT_SIZE
*numentries
;
1241 smb_setlen(outbuf
,outsize
- 4);
1243 if ((! *directory
) && dptr_path(dptr_num
))
1244 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1246 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1247 smb_fn_name(CVAL(inbuf
,smb_com
)),
1248 mask
, directory
, dirtype
, numentries
, maxentries
) );
1254 /****************************************************************************
1255 reply to a fclose (stop directory search)
1256 ****************************************************************************/
1257 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1265 outsize
= set_message(outbuf
,1,0,True
);
1266 path
= smb_buf(inbuf
) + 1;
1267 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
1270 if (status_len
== 0)
1271 return(ERROR(ERRSRV
,ERRsrverror
));
1273 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1275 if(dptr_fetch(status
+12,&dptr_num
)) {
1276 /* Close the dptr - we know it's gone */
1277 dptr_close(dptr_num
);
1280 SSVAL(outbuf
,smb_vwv0
,0);
1282 DEBUG(3,("search close\n"));
1288 /****************************************************************************
1290 ****************************************************************************/
1292 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1302 SMB_STRUCT_STAT sbuf
;
1303 BOOL bad_path
= False
;
1305 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1307 share_mode
= SVAL(inbuf
,smb_vwv0
);
1309 pstrcpy(fname
,smb_buf(inbuf
)+1);
1310 unix_convert(fname
,conn
,0,&bad_path
,NULL
);
1314 return(ERROR(ERRSRV
,ERRnofids
));
1316 if (!check_name(fname
,conn
))
1318 if((errno
== ENOENT
) && bad_path
)
1320 unix_ERR_class
= ERRDOS
;
1321 unix_ERR_code
= ERRbadpath
;
1324 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1327 unixmode
= unix_mode(conn
,aARCH
);
1329 open_file_shared(fsp
,conn
,fname
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1330 unixmode
, oplock_request
,&rmode
,NULL
);
1334 if((errno
== ENOENT
) && bad_path
)
1336 unix_ERR_class
= ERRDOS
;
1337 unix_ERR_code
= ERRbadpath
;
1340 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1343 if (sys_fstat(fsp
->fd_ptr
->fd
,&sbuf
) != 0) {
1344 close_file(fsp
,False
);
1345 return(ERROR(ERRDOS
,ERRnoaccess
));
1348 size
= sbuf
.st_size
;
1349 fmode
= dos_mode(conn
,fname
,&sbuf
);
1350 mtime
= sbuf
.st_mtime
;
1353 DEBUG(3,("attempt to open a directory %s\n",fname
));
1354 close_file(fsp
,False
);
1355 return(ERROR(ERRDOS
,ERRnoaccess
));
1358 outsize
= set_message(outbuf
,7,0,True
);
1359 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1360 SSVAL(outbuf
,smb_vwv1
,fmode
);
1361 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1362 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1364 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1365 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1366 SSVAL(outbuf
,smb_vwv6
,rmode
);
1368 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1369 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1372 if(fsp
->granted_oplock
)
1373 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1378 /****************************************************************************
1379 reply to an open and X
1380 ****************************************************************************/
1381 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1384 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1385 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1386 /* Breakout the oplock request bits so we can set the
1387 reply bits separately. */
1388 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1389 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1390 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1392 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1393 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1394 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1396 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1399 int fmode
=0,mtime
=0,rmode
=0;
1400 SMB_STRUCT_STAT sbuf
;
1402 BOOL bad_path
= False
;
1405 /* If it's an IPC, pass off the pipe handler. */
1406 if (IS_IPC(conn
) && lp_nt_pipe_support() && lp_security() != SEC_SHARE
)
1408 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1411 /* XXXX we need to handle passed times, sattr and flags */
1413 pstrcpy(fname
,smb_buf(inbuf
));
1414 unix_convert(fname
,conn
,0,&bad_path
,NULL
);
1418 return(ERROR(ERRSRV
,ERRnofids
));
1420 if (!check_name(fname
,conn
))
1422 if((errno
== ENOENT
) && bad_path
)
1424 unix_ERR_class
= ERRDOS
;
1425 unix_ERR_code
= ERRbadpath
;
1428 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1431 unixmode
= unix_mode(conn
,smb_attr
| aARCH
);
1433 open_file_shared(fsp
,conn
,fname
,smb_mode
,smb_ofun
,unixmode
,
1434 oplock_request
, &rmode
,&smb_action
);
1438 if((errno
== ENOENT
) && bad_path
)
1440 unix_ERR_class
= ERRDOS
;
1441 unix_ERR_code
= ERRbadpath
;
1444 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1447 if (sys_fstat(fsp
->fd_ptr
->fd
,&sbuf
) != 0) {
1448 close_file(fsp
,False
);
1449 return(ERROR(ERRDOS
,ERRnoaccess
));
1452 size
= sbuf
.st_size
;
1453 fmode
= dos_mode(conn
,fname
,&sbuf
);
1454 mtime
= sbuf
.st_mtime
;
1456 close_file(fsp
,False
);
1457 return(ERROR(ERRDOS
,ERRnoaccess
));
1460 /* If the caller set the extended oplock request bit
1461 and we granted one (by whatever means) - set the
1462 correct bit for extended oplock reply.
1465 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1466 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1469 if(ex_oplock_request
&& fsp
->granted_oplock
) {
1470 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1473 /* If the caller set the core oplock request bit
1474 and we granted one (by whatever means) - set the
1475 correct bit for core oplock reply.
1478 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1479 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1482 if(core_oplock_request
&& fsp
->granted_oplock
) {
1483 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1486 set_message(outbuf
,15,0,True
);
1487 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1488 SSVAL(outbuf
,smb_vwv3
,fmode
);
1489 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1490 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1492 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1493 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1494 SSVAL(outbuf
,smb_vwv8
,rmode
);
1495 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1497 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1501 /****************************************************************************
1502 reply to a SMBulogoffX
1503 ****************************************************************************/
1504 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1506 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1507 user_struct
*vuser
= get_valid_user_struct(vuid
);
1510 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1513 /* in user level security we are supposed to close any files
1514 open by this user */
1515 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1516 file_close_user(vuid
);
1519 invalidate_vuid(vuid
);
1521 set_message(outbuf
,2,0,True
);
1523 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1525 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1529 /****************************************************************************
1530 reply to a mknew or a create
1531 ****************************************************************************/
1532 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1540 BOOL bad_path
= False
;
1542 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1544 com
= SVAL(inbuf
,smb_com
);
1546 createmode
= SVAL(inbuf
,smb_vwv0
);
1547 pstrcpy(fname
,smb_buf(inbuf
)+1);
1548 unix_convert(fname
,conn
,0,&bad_path
,NULL
);
1550 if (createmode
& aVOLID
)
1552 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1555 unixmode
= unix_mode(conn
,createmode
);
1559 return(ERROR(ERRSRV
,ERRnofids
));
1561 if (!check_name(fname
,conn
))
1563 if((errno
== ENOENT
) && bad_path
)
1565 unix_ERR_class
= ERRDOS
;
1566 unix_ERR_code
= ERRbadpath
;
1569 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1574 /* We should fail if file exists. */
1579 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1583 /* Open file in dos compatibility share mode. */
1584 open_file_shared(fsp
,conn
,fname
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1585 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1589 if((errno
== ENOENT
) && bad_path
)
1591 unix_ERR_class
= ERRDOS
;
1592 unix_ERR_code
= ERRbadpath
;
1595 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1598 outsize
= set_message(outbuf
,1,0,True
);
1599 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1601 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1602 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1605 if(fsp
->granted_oplock
)
1606 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1608 DEBUG( 2, ( "new file %s\n", fname
) );
1609 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1610 fname
, fsp
->fd_ptr
->fd
, createmode
, (int)unixmode
) );
1616 /****************************************************************************
1617 reply to a create temporary file
1618 ****************************************************************************/
1619 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1626 BOOL bad_path
= False
;
1628 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1630 createmode
= SVAL(inbuf
,smb_vwv0
);
1631 pstrcpy(fname
,smb_buf(inbuf
)+1);
1632 pstrcat(fname
,"/TMXXXXXX");
1633 unix_convert(fname
,conn
,0,&bad_path
,NULL
);
1635 unixmode
= unix_mode(conn
,createmode
);
1639 return(ERROR(ERRSRV
,ERRnofids
));
1641 if (!check_name(fname
,conn
))
1643 if((errno
== ENOENT
) && bad_path
)
1645 unix_ERR_class
= ERRDOS
;
1646 unix_ERR_code
= ERRbadpath
;
1649 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1652 pstrcpy(fname2
,(char *)mktemp(fname
));
1654 /* Open file in dos compatibility share mode. */
1655 /* We should fail if file exists. */
1656 open_file_shared(fsp
,conn
,fname2
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1657 (FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_FAIL
), unixmode
, oplock_request
, NULL
, NULL
);
1661 if((errno
== ENOENT
) && bad_path
)
1663 unix_ERR_class
= ERRDOS
;
1664 unix_ERR_code
= ERRbadpath
;
1667 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1670 outsize
= set_message(outbuf
,1,2 + strlen(fname2
),True
);
1671 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1672 CVAL(smb_buf(outbuf
),0) = 4;
1673 pstrcpy(smb_buf(outbuf
) + 1,fname2
);
1675 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1676 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1679 if(fsp
->granted_oplock
)
1680 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1682 DEBUG( 2, ( "created temp file %s\n", fname2
) );
1683 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1684 fname2
, fsp
->fd_ptr
->fd
, createmode
, (int)unixmode
) );
1690 /*******************************************************************
1691 check if a user is allowed to delete a file
1692 ********************************************************************/
1693 static BOOL
can_delete(char *fname
,connection_struct
*conn
, int dirtype
)
1695 SMB_STRUCT_STAT sbuf
;
1698 if (!CAN_WRITE(conn
)) return(False
);
1700 if (dos_lstat(fname
,&sbuf
) != 0) return(False
);
1701 fmode
= dos_mode(conn
,fname
,&sbuf
);
1702 if (fmode
& aDIR
) return(False
);
1703 if (!lp_delete_readonly(SNUM(conn
))) {
1704 if (fmode
& aRONLY
) return(False
);
1706 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1708 if (!check_file_sharing(conn
,fname
,False
)) return(False
);
1712 /****************************************************************************
1714 ****************************************************************************/
1715 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1724 int error
= ERRnoaccess
;
1727 BOOL bad_path
= False
;
1729 *directory
= *mask
= 0;
1731 dirtype
= SVAL(inbuf
,smb_vwv0
);
1733 pstrcpy(name
,smb_buf(inbuf
) + 1);
1735 DEBUG(3,("reply_unlink : %s\n",name
));
1737 unix_convert(name
,conn
,0,&bad_path
,NULL
);
1739 p
= strrchr(name
,'/');
1741 pstrcpy(directory
,"./");
1745 pstrcpy(directory
,name
);
1749 if (is_mangled(mask
))
1750 check_mangled_cache( mask
);
1752 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
1755 pstrcat(directory
,"/");
1756 pstrcat(directory
,mask
);
1757 if (can_delete(directory
,conn
,dirtype
) && !dos_unlink(directory
))
1760 exists
= dos_file_exist(directory
,NULL
);
1762 void *dirptr
= NULL
;
1765 if (check_name(directory
,conn
))
1766 dirptr
= OpenDir(conn
, directory
, True
);
1768 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1769 the pattern matches against the long name, otherwise the short name
1770 We don't implement this yet XXXX
1777 if (strequal(mask
,"????????.???"))
1780 while ((dname
= ReadDirName(dirptr
)))
1783 pstrcpy(fname
,dname
);
1785 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
1787 error
= ERRnoaccess
;
1788 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1789 if (!can_delete(fname
,conn
,dirtype
)) continue;
1790 if (!dos_unlink(fname
)) count
++;
1791 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname
));
1799 return(ERROR(ERRDOS
,error
));
1802 if((errno
== ENOENT
) && bad_path
)
1804 unix_ERR_class
= ERRDOS
;
1805 unix_ERR_code
= ERRbadpath
;
1807 return(UNIXERROR(ERRDOS
,error
));
1811 outsize
= set_message(outbuf
,0,0,True
);
1817 /****************************************************************************
1818 reply to a readbraw (core+ protocol)
1819 ****************************************************************************/
1820 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1822 size_t maxcount
,mincount
;
1825 char *header
= outbuf
;
1830 * Special check if an oplock break has been issued
1831 * and the readraw request croses on the wire, we must
1832 * return a zero length response here.
1835 if(global_oplock_break
)
1837 _smb_setlen(header
,0);
1838 transfer_file(0,Client
,(SMB_OFF_T
)0,header
,4,0);
1839 DEBUG(5,("readbraw - oplock break finished\n"));
1843 fsp
= file_fsp(inbuf
,smb_vwv0
);
1845 startpos
= IVAL(inbuf
,smb_vwv1
);
1846 #ifdef LARGE_SMB_OFF_T
1847 if(CVAL(inbuf
,smb_wct
) == 10) {
1849 * This is a large offset (64 bit) read.
1851 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
1853 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1854 (double)startpos
));
1855 _smb_setlen(header
,0);
1856 transfer_file(0,Client
,(SMB_OFF_T
)0,header
,4,0);
1860 #endif /* LARGE_SMB_OFF_T */
1861 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
1862 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
1864 /* ensure we don't overrun the packet size */
1865 maxcount
= MIN(65535,maxcount
);
1866 maxcount
= MAX(mincount
,maxcount
);
1868 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1869 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp
->fnum
));
1870 _smb_setlen(header
,0);
1871 transfer_file(0,Client
,(SMB_OFF_T
)0,header
,4,0);
1875 if (!is_locked(fsp
,conn
,maxcount
,startpos
, F_RDLCK
))
1877 SMB_OFF_T size
= fsp
->size
;
1878 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
1880 if (size
< sizeneeded
)
1883 if (sys_fstat(fsp
->fd_ptr
->fd
,&st
) == 0)
1885 if (!fsp
->can_write
)
1889 nread
= MIN(maxcount
,(size
- startpos
));
1892 if (nread
< mincount
)
1895 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1896 fsp
->fnum
, (double)startpos
,
1897 maxcount
, mincount
, nread
) );
1901 BOOL seek_fail
= False
;
1903 _smb_setlen(header
,nread
);
1905 #if USE_READ_PREDICTION
1906 if (!fsp
->can_write
)
1907 predict
= read_predict(fsp
->fd_ptr
->fd
,startpos
,header
+4,NULL
,nread
);
1908 #endif /* USE_READ_PREDICTION */
1910 if ((nread
-predict
) > 0) {
1911 if(seek_file(fsp
,startpos
+ predict
) == -1) {
1912 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1919 ret
= (ssize_t
)transfer_file(fsp
->fd_ptr
->fd
,Client
,
1920 (SMB_OFF_T
)(nread
-predict
),header
,4+predict
,
1925 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1926 fsp
->fsp_name
,startpos
,nread
,ret
));
1928 #else /* UNSAFE_READRAW */
1929 ret
= read_file(fsp
,header
+4,startpos
,nread
);
1930 if (ret
< mincount
) ret
= 0;
1932 _smb_setlen(header
,ret
);
1933 transfer_file(0,Client
,0,header
,4+ret
,0);
1934 #endif /* UNSAFE_READRAW */
1936 DEBUG(5,("readbraw finished\n"));
1941 /****************************************************************************
1942 reply to a lockread (core+ protocol)
1943 ****************************************************************************/
1944 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
1953 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1955 CHECK_FSP(fsp
,conn
);
1959 numtoread
= SVAL(inbuf
,smb_vwv1
);
1960 startpos
= IVAL(inbuf
,smb_vwv2
);
1962 outsize
= set_message(outbuf
,5,3,True
);
1963 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1964 data
= smb_buf(outbuf
) + 3;
1966 if(!do_lock( fsp
, conn
, numtoread
, startpos
, F_RDLCK
, &eclass
, &ecode
)) {
1967 if((ecode
== ERRlock
) && lp_blocking_locks(SNUM(conn
))) {
1969 * A blocking lock was requested. Package up
1970 * this smb into a queued request and push it
1971 * onto the blocking lock queue.
1973 if(push_blocking_lock_request(inbuf
, length
, -1, 0))
1976 return (ERROR(eclass
,ecode
));
1979 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1982 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1985 SSVAL(outbuf
,smb_vwv0
,nread
);
1986 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1987 SSVAL(smb_buf(outbuf
),1,nread
);
1989 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1990 fsp
->fnum
, numtoread
, nread
) );
1996 /****************************************************************************
1998 ****************************************************************************/
1999 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2006 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2008 CHECK_FSP(fsp
,conn
);
2012 numtoread
= SVAL(inbuf
,smb_vwv1
);
2013 startpos
= IVAL(inbuf
,smb_vwv2
);
2015 outsize
= set_message(outbuf
,5,3,True
);
2016 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2017 data
= smb_buf(outbuf
) + 3;
2019 if (is_locked(fsp
,conn
,numtoread
,startpos
, F_RDLCK
))
2020 return(ERROR(ERRDOS
,ERRlock
));
2023 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2026 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2029 SSVAL(outbuf
,smb_vwv0
,nread
);
2030 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2031 CVAL(smb_buf(outbuf
),0) = 1;
2032 SSVAL(smb_buf(outbuf
),1,nread
);
2034 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2035 fsp
->fnum
, numtoread
, nread
) );
2041 /****************************************************************************
2042 reply to a read and X
2043 ****************************************************************************/
2044 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2046 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2047 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2048 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2049 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2053 /* If it's an IPC, pass off the pipe handler. */
2055 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2057 CHECK_FSP(fsp
,conn
);
2061 set_message(outbuf
,12,0,True
);
2062 data
= smb_buf(outbuf
);
2064 #ifdef LARGE_SMB_OFF_T
2065 if(CVAL(inbuf
,smb_wct
) == 12) {
2067 * This is a large offset (64 bit) read.
2069 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2071 #endif /* LARGE_SMB_OFF_T */
2073 if (is_locked(fsp
,conn
,smb_maxcnt
,startpos
, F_RDLCK
))
2074 return(ERROR(ERRDOS
,ERRlock
));
2075 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2078 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2080 SSVAL(outbuf
,smb_vwv5
,nread
);
2081 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2082 SSVAL(smb_buf(outbuf
),-2,nread
);
2084 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2085 fsp
->fnum
, smb_mincnt
, smb_maxcnt
, nread
) );
2087 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2090 /****************************************************************************
2091 reply to a writebraw (core+ or LANMAN1.0 protocol)
2092 ****************************************************************************/
2093 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2096 ssize_t total_written
=0;
2097 size_t numtowrite
=0;
2102 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2105 CHECK_FSP(fsp
,conn
);
2109 tcount
= IVAL(inbuf
,smb_vwv1
);
2110 startpos
= IVAL(inbuf
,smb_vwv3
);
2111 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2113 /* We have to deal with slightly different formats depending
2114 on whether we are using the core+ or lanman1.0 protocol */
2115 if(Protocol
<= PROTOCOL_COREPLUS
) {
2116 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2117 data
= smb_buf(inbuf
);
2119 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2120 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2123 /* force the error type */
2124 CVAL(inbuf
,smb_com
) = SMBwritec
;
2125 CVAL(outbuf
,smb_com
) = SMBwritec
;
2127 if (is_locked(fsp
,conn
,tcount
,startpos
, F_WRLCK
))
2128 return(ERROR(ERRDOS
,ERRlock
));
2130 if (seek_file(fsp
,startpos
) == -1) {
2131 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos
));
2132 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2136 nwritten
= write_file(fsp
,data
,numtowrite
);
2138 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2139 fsp
->fnum
, (double)startpos
, numtowrite
, nwritten
, write_through
));
2141 if (nwritten
< numtowrite
)
2142 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2144 total_written
= nwritten
;
2146 /* Return a message to the redirector to tell it
2147 to send more bytes */
2148 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
2149 SSVALS(outbuf
,smb_vwv0
,-1);
2150 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2151 send_smb(Client
,outbuf
);
2153 /* Now read the raw data into the buffer and write it */
2154 if (read_smb_length(Client
,inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2155 exit_server("secondary writebraw failed");
2158 /* Even though this is not an smb message, smb_len
2159 returns the generic length of an smb message */
2160 numtowrite
= smb_len(inbuf
);
2162 if (tcount
> nwritten
+numtowrite
) {
2163 DEBUG(3,("Client overestimated the write %d %d %d\n",
2164 tcount
,nwritten
,numtowrite
));
2167 nwritten
= transfer_file(Client
,fsp
->fd_ptr
->fd
,(SMB_OFF_T
)numtowrite
,NULL
,0,
2169 total_written
+= nwritten
;
2171 /* Set up outbuf to return the correct return */
2172 outsize
= set_message(outbuf
,1,0,True
);
2173 CVAL(outbuf
,smb_com
) = SMBwritec
;
2174 SSVAL(outbuf
,smb_vwv0
,total_written
);
2176 if (nwritten
< (ssize_t
)numtowrite
) {
2177 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2178 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2181 if (lp_syncalways(SNUM(conn
)) || write_through
)
2182 sync_file(conn
,fsp
);
2184 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2185 fsp
->fnum
, (double)startpos
, numtowrite
, total_written
));
2187 /* we won't return a status if write through is not selected - this
2188 follows what WfWg does */
2189 if (!write_through
&& total_written
==tcount
)
2195 /****************************************************************************
2196 reply to a writeunlock (core+)
2197 ****************************************************************************/
2198 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2200 ssize_t nwritten
= -1;
2206 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2209 CHECK_FSP(fsp
,conn
);
2213 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2214 startpos
= IVAL(inbuf
,smb_vwv2
);
2215 data
= smb_buf(inbuf
) + 3;
2217 if (is_locked(fsp
,conn
,numtowrite
,startpos
, F_WRLCK
))
2218 return(ERROR(ERRDOS
,ERRlock
));
2220 if(seek_file(fsp
,startpos
) == -1)
2221 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2223 /* The special X/Open SMB protocol handling of
2224 zero length writes is *NOT* done for
2229 nwritten
= write_file(fsp
,data
,numtowrite
);
2231 if (lp_syncalways(SNUM(conn
)))
2232 sync_file(conn
,fsp
);
2234 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
2235 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2237 if(!do_unlock(fsp
, conn
, numtowrite
, startpos
, &eclass
, &ecode
))
2238 return(ERROR(eclass
,ecode
));
2240 outsize
= set_message(outbuf
,1,0,True
);
2242 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2244 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2245 fsp
->fnum
, numtowrite
, nwritten
) );
2250 /****************************************************************************
2252 ****************************************************************************/
2253 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int dum_size
,int dum_buffsize
)
2256 ssize_t nwritten
= -1;
2259 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2262 CHECK_FSP(fsp
,conn
);
2266 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2267 startpos
= IVAL(inbuf
,smb_vwv2
);
2268 data
= smb_buf(inbuf
) + 3;
2270 if (is_locked(fsp
,conn
,numtowrite
,startpos
, F_WRLCK
))
2271 return(ERROR(ERRDOS
,ERRlock
));
2273 if(seek_file(fsp
,startpos
) == -1)
2274 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2276 /* X/Open SMB protocol says that if smb_vwv1 is
2277 zero then the file size should be extended or
2278 truncated to the size given in smb_vwv[2-3] */
2280 nwritten
= set_filelen(fsp
->fd_ptr
->fd
, (SMB_OFF_T
)startpos
);
2282 nwritten
= write_file(fsp
,data
,numtowrite
);
2284 if (lp_syncalways(SNUM(conn
)))
2285 sync_file(conn
,fsp
);
2287 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
2288 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2290 outsize
= set_message(outbuf
,1,0,True
);
2292 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2294 if (nwritten
< (ssize_t
)numtowrite
) {
2295 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2296 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2299 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2300 fsp
->fnum
, numtowrite
, nwritten
));
2306 /****************************************************************************
2307 reply to a write and X
2308 ****************************************************************************/
2309 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2311 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2312 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2313 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2314 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2315 ssize_t nwritten
= -1;
2316 int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2319 /* If it's an IPC, pass off the pipe handler. */
2321 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2323 CHECK_FSP(fsp
,conn
);
2327 data
= smb_base(inbuf
) + smb_doff
;
2329 #ifdef LARGE_SMB_OFF_T
2330 if(CVAL(inbuf
,smb_wct
) == 14) {
2332 * This is a large offset (64 bit) write.
2334 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2336 #endif /* LARGE_SMB_OFF_T */
2338 if (is_locked(fsp
,conn
,numtowrite
,startpos
, F_WRLCK
))
2339 return(ERROR(ERRDOS
,ERRlock
));
2341 if(seek_file(fsp
,startpos
) == -1)
2342 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2344 /* X/Open SMB protocol says that, unlike SMBwrite
2345 if the length is zero then NO truncation is
2346 done, just a write of zero. To truncate a file,
2351 nwritten
= write_file(fsp
,data
,numtowrite
);
2353 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
2354 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2356 set_message(outbuf
,6,0,True
);
2358 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2360 if (nwritten
< (ssize_t
)numtowrite
) {
2361 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2362 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2365 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2366 fsp
->fnum
, numtowrite
, nwritten
));
2368 if (lp_syncalways(SNUM(conn
)) || write_through
)
2369 sync_file(conn
,fsp
);
2371 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2375 /****************************************************************************
2377 ****************************************************************************/
2378 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2384 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2386 CHECK_FSP(fsp
,conn
);
2389 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2390 startpos
= IVAL(inbuf
,smb_vwv2
);
2394 case 0: umode
= SEEK_SET
; break;
2395 case 1: umode
= SEEK_CUR
; break;
2396 case 2: umode
= SEEK_END
; break;
2398 umode
= SEEK_SET
; break;
2401 if((res
= sys_lseek(fsp
->fd_ptr
->fd
,startpos
,umode
)) == -1)
2402 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2406 outsize
= set_message(outbuf
,2,0,True
);
2407 SIVALS(outbuf
,smb_vwv0
,res
);
2409 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2410 fsp
->fnum
, (double)startpos
, mode
));
2415 /****************************************************************************
2417 ****************************************************************************/
2418 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2420 int outsize
= set_message(outbuf
,0,0,True
);
2421 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2424 CHECK_FSP(fsp
,conn
);
2429 file_sync_all(conn
);
2431 sync_file(conn
,fsp
);
2434 DEBUG(3,("flush\n"));
2439 /****************************************************************************
2441 ****************************************************************************/
2442 int reply_exit(connection_struct
*conn
,
2443 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2445 int outsize
= set_message(outbuf
,0,0,True
);
2446 DEBUG(3,("exit\n"));
2452 /****************************************************************************
2453 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2454 ****************************************************************************/
2455 int reply_close(connection_struct
*conn
,
2456 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2460 int32 eclass
= 0, err
= 0;
2461 files_struct
*fsp
= NULL
;
2463 outsize
= set_message(outbuf
,0,0,True
);
2465 /* If it's an IPC, pass off to the pipe handler. */
2467 return reply_pipe_close(conn
, inbuf
,outbuf
);
2470 fsp
= file_fsp(inbuf
,smb_vwv0
);
2473 * We can only use CHECK_FSP if we know it's not a directory.
2476 if(!fsp
|| !fsp
->open
|| (fsp
->conn
!= conn
))
2477 return(ERROR(ERRDOS
,ERRbadfid
));
2479 if(HAS_CACHED_ERROR(fsp
)) {
2480 eclass
= fsp
->wbmpx_ptr
->wr_errclass
;
2481 err
= fsp
->wbmpx_ptr
->wr_error
;
2484 if(fsp
->is_directory
) {
2486 * Special case - close NT SMB directory
2489 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
2490 close_directory(fsp
);
2493 * Close ordinary file.
2497 * If there was a modify time outstanding,
2498 * try and set it here.
2500 if(fsp
->pending_modtime
)
2501 set_filetime(conn
, fsp
->fsp_name
, fsp
->pending_modtime
);
2504 * Now take care of any time sent in the close.
2506 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2508 /* try and set the date */
2509 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2511 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2512 fsp
->fd_ptr
->fd
, fsp
->fnum
,
2513 conn
->num_files_open
));
2515 close_file(fsp
,True
);
2518 /* We have a cached error */
2520 return(ERROR(eclass
,err
));
2526 /****************************************************************************
2527 reply to a writeclose (Core+ protocol)
2528 ****************************************************************************/
2529 int reply_writeclose(connection_struct
*conn
,
2530 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2533 ssize_t nwritten
= -1;
2538 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2540 CHECK_FSP(fsp
,conn
);
2544 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2545 startpos
= IVAL(inbuf
,smb_vwv2
);
2546 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2547 data
= smb_buf(inbuf
) + 1;
2549 if (is_locked(fsp
,conn
,numtowrite
,startpos
, F_WRLCK
))
2550 return(ERROR(ERRDOS
,ERRlock
));
2552 if(seek_file(fsp
,startpos
) == -1)
2553 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2555 nwritten
= write_file(fsp
,data
,numtowrite
);
2557 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2559 close_file(fsp
,True
);
2561 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2562 fsp
->fnum
, numtowrite
, nwritten
,
2563 conn
->num_files_open
));
2566 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2568 outsize
= set_message(outbuf
,1,0,True
);
2570 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2575 /****************************************************************************
2577 ****************************************************************************/
2578 int reply_lock(connection_struct
*conn
,
2579 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
2581 int outsize
= set_message(outbuf
,0,0,True
);
2582 SMB_OFF_T count
,offset
;
2585 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2587 CHECK_FSP(fsp
,conn
);
2590 count
= IVAL(inbuf
,smb_vwv1
);
2591 offset
= IVAL(inbuf
,smb_vwv3
);
2593 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2594 fsp
->fd_ptr
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
2596 if (!do_lock(fsp
, conn
, count
, offset
, F_WRLCK
, &eclass
, &ecode
)) {
2597 if((ecode
== ERRlock
) && lp_blocking_locks(SNUM(conn
))) {
2599 * A blocking lock was requested. Package up
2600 * this smb into a queued request and push it
2601 * onto the blocking lock queue.
2603 if(push_blocking_lock_request(inbuf
, length
, -1, 0))
2606 return (ERROR(eclass
,ecode
));
2613 /****************************************************************************
2615 ****************************************************************************/
2616 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2618 int outsize
= set_message(outbuf
,0,0,True
);
2619 SMB_OFF_T count
,offset
;
2622 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2624 CHECK_FSP(fsp
,conn
);
2627 count
= IVAL(inbuf
,smb_vwv1
);
2628 offset
= IVAL(inbuf
,smb_vwv3
);
2630 if(!do_unlock(fsp
, conn
, count
, offset
, &eclass
, &ecode
))
2631 return (ERROR(eclass
,ecode
));
2633 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2634 fsp
->fd_ptr
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
2640 /****************************************************************************
2642 ****************************************************************************/
2643 int reply_tdis(connection_struct
*conn
,
2644 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2646 int outsize
= set_message(outbuf
,0,0,True
);
2649 vuid
= SVAL(inbuf
,smb_uid
);
2652 DEBUG(4,("Invalid connection in tdis\n"));
2653 return(ERROR(ERRSRV
,ERRinvnid
));
2658 close_cnum(conn
,vuid
);
2665 /****************************************************************************
2667 ****************************************************************************/
2668 int reply_echo(connection_struct
*conn
,
2669 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2671 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2673 int data_len
= smb_buflen(inbuf
);
2674 int outsize
= set_message(outbuf
,1,data_len
,True
);
2676 /* copy any incoming data back out */
2678 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2680 if (smb_reverb
> 100) {
2681 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2685 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2686 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2688 smb_setlen(outbuf
,outsize
- 4);
2690 send_smb(Client
,outbuf
);
2693 DEBUG(3,("echo %d times\n", smb_reverb
));
2699 /****************************************************************************
2700 reply to a printopen
2701 ****************************************************************************/
2702 int reply_printopen(connection_struct
*conn
,
2703 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2710 *fname
= *fname2
= 0;
2712 if (!CAN_PRINT(conn
))
2713 return(ERROR(ERRDOS
,ERRnoaccess
));
2718 pstrcpy(s
,smb_buf(inbuf
)+1);
2721 if (!(isalnum((int)*p
) || strchr("._-",*p
)))
2726 if (strlen(s
) > 10) s
[10] = 0;
2728 slprintf(fname
,sizeof(fname
)-1, "%s.XXXXXX",s
);
2733 return(ERROR(ERRSRV
,ERRnofids
));
2735 pstrcpy(fname2
,(char *)mktemp(fname
));
2737 if (!check_name(fname2
,conn
)) {
2739 return(ERROR(ERRDOS
,ERRnoaccess
));
2742 /* Open for exclusive use, write only. */
2743 open_file_shared(fsp
,conn
,fname2
, SET_DENY_MODE(DENY_ALL
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
2744 (FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_FAIL
), unix_mode(conn
,0), 0, NULL
, NULL
);
2748 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2751 /* force it to be a print file */
2752 fsp
->print_file
= True
;
2754 outsize
= set_message(outbuf
,1,0,True
);
2755 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2757 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2758 fname2
, fsp
->fd_ptr
->fd
, fsp
->fnum
));
2764 /****************************************************************************
2765 reply to a printclose
2766 ****************************************************************************/
2767 int reply_printclose(connection_struct
*conn
,
2768 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2770 int outsize
= set_message(outbuf
,0,0,True
);
2771 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2773 CHECK_FSP(fsp
,conn
);
2776 if (!CAN_PRINT(conn
))
2777 return(ERROR(ERRDOS
,ERRnoaccess
));
2779 DEBUG(3,("printclose fd=%d fnum=%d\n",
2780 fsp
->fd_ptr
->fd
,fsp
->fnum
));
2782 close_file(fsp
,True
);
2788 /****************************************************************************
2789 reply to a printqueue
2790 ****************************************************************************/
2791 int reply_printqueue(connection_struct
*conn
,
2792 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2794 int outsize
= set_message(outbuf
,2,3,True
);
2795 int max_count
= SVAL(inbuf
,smb_vwv0
);
2796 int start_index
= SVAL(inbuf
,smb_vwv1
);
2798 /* we used to allow the client to get the cnum wrong, but that
2799 is really quite gross and only worked when there was only
2800 one printer - I think we should now only accept it if they
2801 get it right (tridge) */
2802 if (!CAN_PRINT(conn
))
2803 return(ERROR(ERRDOS
,ERRnoaccess
));
2805 SSVAL(outbuf
,smb_vwv0
,0);
2806 SSVAL(outbuf
,smb_vwv1
,0);
2807 CVAL(smb_buf(outbuf
),0) = 1;
2808 SSVAL(smb_buf(outbuf
),1,0);
2810 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2811 start_index
, max_count
));
2814 print_queue_struct
*queue
= NULL
;
2815 char *p
= smb_buf(outbuf
) + 3;
2816 int count
= get_printqueue(SNUM(conn
), conn
,&queue
,NULL
);
2817 int num_to_get
= ABS(max_count
);
2818 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
2824 num_to_get
= MIN(num_to_get
,count
-first
);
2827 for (i
=first
;i
<first
+num_to_get
;i
++) {
2828 put_dos_date2(p
,0,queue
[i
].time
);
2829 CVAL(p
,4) = (queue
[i
].status
==LPQ_PRINTING
?2:3);
2830 SSVAL(p
,5,printjob_encode(SNUM(conn
),
2832 SIVAL(p
,7,queue
[i
].size
);
2834 StrnCpy(p
+12,queue
[i
].user
,16);
2839 outsize
= set_message(outbuf
,2,28*count
+3,False
);
2840 SSVAL(outbuf
,smb_vwv0
,count
);
2841 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
2842 CVAL(smb_buf(outbuf
),0) = 1;
2843 SSVAL(smb_buf(outbuf
),1,28*count
);
2846 if (queue
) free(queue
);
2848 DEBUG(3,("%d entries returned in queue\n",count
));
2855 /****************************************************************************
2856 reply to a printwrite
2857 ****************************************************************************/
2858 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2861 int outsize
= set_message(outbuf
,0,0,True
);
2863 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2865 if (!CAN_PRINT(conn
))
2866 return(ERROR(ERRDOS
,ERRnoaccess
));
2868 CHECK_FSP(fsp
,conn
);
2872 numtowrite
= SVAL(smb_buf(inbuf
),1);
2873 data
= smb_buf(inbuf
) + 3;
2875 if (write_file(fsp
,data
,numtowrite
) != numtowrite
)
2876 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2878 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
2884 /****************************************************************************
2886 ****************************************************************************/
2887 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2890 int outsize
,ret
= -1;
2891 BOOL bad_path
= False
;
2893 pstrcpy(directory
,smb_buf(inbuf
) + 1);
2894 unix_convert(directory
,conn
,0,&bad_path
,NULL
);
2896 if (check_name(directory
, conn
))
2897 ret
= dos_mkdir(directory
,unix_mode(conn
,aDIR
));
2901 if((errno
== ENOENT
) && bad_path
)
2903 unix_ERR_class
= ERRDOS
;
2904 unix_ERR_code
= ERRbadpath
;
2906 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2909 outsize
= set_message(outbuf
,0,0,True
);
2911 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, ret
) );
2916 /****************************************************************************
2917 Static function used by reply_rmdir to delete an entire directory
2919 ****************************************************************************/
2920 static BOOL
recursive_rmdir(char *directory
)
2924 void *dirptr
= OpenDir(NULL
, directory
, False
);
2929 while((dname
= ReadDirName(dirptr
)))
2934 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2937 /* Construct the full name. */
2938 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
2944 pstrcpy(fullname
, directory
);
2945 pstrcat(fullname
, "/");
2946 pstrcat(fullname
, dname
);
2948 if(dos_lstat(fullname
, &st
) != 0)
2954 if(st
.st_mode
& S_IFDIR
)
2956 if(recursive_rmdir(fullname
)!=0)
2961 if(dos_rmdir(fullname
) != 0)
2967 else if(dos_unlink(fullname
) != 0)
2977 /****************************************************************************
2979 ****************************************************************************/
2980 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2985 BOOL bad_path
= False
;
2987 pstrcpy(directory
,smb_buf(inbuf
) + 1);
2988 unix_convert(directory
,conn
, NULL
,&bad_path
,NULL
);
2990 if (check_name(directory
,conn
))
2993 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
2994 ok
= (dos_rmdir(directory
) == 0);
2995 if(!ok
&& (errno
== ENOTEMPTY
) && lp_veto_files(SNUM(conn
)))
2997 /* Check to see if the only thing in this directory are
2998 vetoed files/directories. If so then delete them and
2999 retry. If we fail to delete any of them (and we *don't*
3000 do a recursive delete) then fail the rmdir. */
3001 BOOL all_veto_files
= True
;
3003 void *dirptr
= OpenDir(conn
, directory
, False
);
3007 int dirpos
= TellDir(dirptr
);
3008 while ((dname
= ReadDirName(dirptr
)))
3010 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3012 if(!IS_VETO_PATH(conn
, dname
))
3014 all_veto_files
= False
;
3020 SeekDir(dirptr
,dirpos
);
3021 while ((dname
= ReadDirName(dirptr
)))
3026 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3029 /* Construct the full name. */
3030 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
3035 pstrcpy(fullname
, directory
);
3036 pstrcat(fullname
, "/");
3037 pstrcat(fullname
, dname
);
3039 if(dos_lstat(fullname
, &st
) != 0)
3041 if(st
.st_mode
& S_IFDIR
)
3043 if(lp_recursive_veto_delete(SNUM(conn
)))
3045 if(recursive_rmdir(fullname
) != 0)
3048 if(dos_rmdir(fullname
) != 0)
3051 else if(dos_unlink(fullname
) != 0)
3055 /* Retry the rmdir */
3056 ok
= (dos_rmdir(directory
) == 0);
3066 DEBUG(3,("couldn't remove directory %s : %s\n",
3067 directory
,strerror(errno
)));
3072 if((errno
== ENOENT
) && bad_path
)
3074 unix_ERR_class
= ERRDOS
;
3075 unix_ERR_code
= ERRbadpath
;
3077 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3080 outsize
= set_message(outbuf
,0,0,True
);
3082 DEBUG( 3, ( "rmdir %s\n", directory
) );
3088 /*******************************************************************
3089 resolve wildcards in a filename rename
3090 ********************************************************************/
3091 static BOOL
resolve_wildcards(char *name1
,char *name2
)
3093 fstring root1
,root2
;
3097 name1
= strrchr(name1
,'/');
3098 name2
= strrchr(name2
,'/');
3100 if (!name1
|| !name2
) return(False
);
3102 fstrcpy(root1
,name1
);
3103 fstrcpy(root2
,name2
);
3104 p
= strrchr(root1
,'.');
3111 p
= strrchr(root2
,'.');
3143 pstrcpy(name2
,root2
);
3146 pstrcat(name2
,ext2
);
3152 /*******************************************************************
3153 check if a user is allowed to rename a file
3154 ********************************************************************/
3155 static BOOL
can_rename(char *fname
,connection_struct
*conn
)
3157 SMB_STRUCT_STAT sbuf
;
3159 if (!CAN_WRITE(conn
)) return(False
);
3161 if (dos_lstat(fname
,&sbuf
) != 0) return(False
);
3162 if (!check_file_sharing(conn
,fname
,True
)) return(False
);
3167 /****************************************************************************
3168 The guts of the rename command, split out so it may be called by the NT SMB
3170 ****************************************************************************/
3171 int rename_internals(connection_struct
*conn
,
3172 char *inbuf
, char *outbuf
, char *name
,
3173 char *newname
, BOOL replace_if_exists
)
3177 pstring newname_last_component
;
3180 BOOL bad_path1
= False
;
3181 BOOL bad_path2
= False
;
3183 int error
= ERRnoaccess
;
3186 *directory
= *mask
= 0;
3188 unix_convert(name
,conn
,0,&bad_path1
,NULL
);
3189 unix_convert(newname
,conn
,newname_last_component
,&bad_path2
,NULL
);
3192 * Split the old name into directory and last component
3193 * strings. Note that unix_convert may have stripped off a
3194 * leading ./ from both name and newname if the rename is
3195 * at the root of the share. We need to make sure either both
3196 * name and newname contain a / character or neither of them do
3197 * as this is checked in resolve_wildcards().
3200 p
= strrchr(name
,'/');
3202 pstrcpy(directory
,".");
3206 pstrcpy(directory
,name
);
3208 *p
= '/'; /* Replace needed for exceptional test below. */
3211 if (is_mangled(mask
))
3212 check_mangled_cache( mask
);
3214 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
3218 * No wildcards - just process the one file.
3220 BOOL is_short_name
= is_8_3(name
, True
);
3222 /* Add a terminating '/' to the directory name. */
3223 pstrcat(directory
,"/");
3224 pstrcat(directory
,mask
);
3226 /* Ensure newname contains a '/' also */
3227 if(strrchr(newname
,'/') == 0) {
3230 pstrcpy(tmpstr
, "./");
3231 pstrcat(tmpstr
, newname
);
3232 pstrcpy(newname
, tmpstr
);
3235 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",
3236 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3237 newname
, newname_last_component
, is_short_name
));
3240 * Check for special case with case preserving and not
3241 * case sensitive, if directory and newname are identical,
3242 * and the old last component differs from the original
3243 * last component only by case, then we should allow
3244 * the rename (user is trying to change the case of the
3247 if((case_sensitive
== False
) &&
3248 (((case_preserve
== True
) &&
3249 (is_short_name
== False
)) ||
3250 ((short_case_preserve
== True
) &&
3251 (is_short_name
== True
))) &&
3252 strcsequal(directory
, newname
)) {
3253 pstring newname_modified_last_component
;
3256 * Get the last component of the modified name.
3257 * Note that we guarantee that newname contains a '/'
3260 p
= strrchr(newname
,'/');
3261 pstrcpy(newname_modified_last_component
,p
+1);
3263 if(strcsequal(newname_modified_last_component
,
3264 newname_last_component
) == False
) {
3266 * Replace the modified last component with
3269 pstrcpy(p
+1, newname_last_component
);
3273 if(replace_if_exists
) {
3275 * NT SMB specific flag - rename can overwrite
3276 * file with the same name so don't check for
3279 if(resolve_wildcards(directory
,newname
) &&
3280 can_rename(directory
,conn
) &&
3281 !dos_rename(directory
,newname
))
3284 if (resolve_wildcards(directory
,newname
) &&
3285 can_rename(directory
,conn
) &&
3286 !dos_file_exist(newname
,NULL
) &&
3287 !dos_rename(directory
,newname
))
3291 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count
!= 0) ? "succeeded" : "failed",
3292 directory
,newname
));
3294 if (!count
) exists
= dos_file_exist(directory
,NULL
);
3295 if (!count
&& exists
&& dos_file_exist(newname
,NULL
)) {
3301 * Wildcards - process each file that matches.
3303 void *dirptr
= NULL
;
3307 if (check_name(directory
,conn
))
3308 dirptr
= OpenDir(conn
, directory
, True
);
3313 if (strequal(mask
,"????????.???"))
3316 while ((dname
= ReadDirName(dirptr
))) {
3318 pstrcpy(fname
,dname
);
3320 if(!mask_match(fname
, mask
, case_sensitive
, False
))
3323 error
= ERRnoaccess
;
3324 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3325 if (!can_rename(fname
,conn
)) {
3326 DEBUG(6,("rename %s refused\n", fname
));
3329 pstrcpy(destname
,newname
);
3331 if (!resolve_wildcards(fname
,destname
)) {
3332 DEBUG(6,("resolve_wildcards %s %s failed\n", fname
, destname
));
3336 if (!replace_if_exists
&& dos_file_exist(destname
,NULL
)) {
3337 DEBUG(6,("dos_file_exist %s\n", destname
));
3342 if (!dos_rename(fname
,destname
))
3344 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3352 return(ERROR(ERRDOS
,error
));
3354 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
)) {
3355 unix_ERR_class
= ERRDOS
;
3356 unix_ERR_code
= ERRbadpath
;
3358 return(UNIXERROR(ERRDOS
,error
));
3365 /****************************************************************************
3367 ****************************************************************************/
3369 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3375 pstrcpy(name
,smb_buf(inbuf
) + 1);
3376 pstrcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
3378 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3380 outsize
= rename_internals(conn
, inbuf
, outbuf
, name
, newname
, False
);
3382 outsize
= set_message(outbuf
,0,0,True
);
3387 /*******************************************************************
3388 copy a file as part of a reply_copy
3389 ******************************************************************/
3391 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3392 int count
,BOOL target_is_directory
)
3397 files_struct
*fsp1
,*fsp2
;
3400 pstrcpy(dest
,dest1
);
3401 if (target_is_directory
) {
3402 char *p
= strrchr(src
,'/');
3411 if (!dos_file_exist(src
,&st
))
3418 open_file_shared(fsp1
,conn
,src
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3419 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
3426 if (!target_is_directory
&& count
)
3431 close_file(fsp1
,False
);
3434 open_file_shared(fsp2
,conn
,dest
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3435 ofun
,st
.st_mode
,0,&Access
,&action
);
3438 close_file(fsp1
,False
);
3443 if ((ofun
&3) == 1) {
3444 if(sys_lseek(fsp2
->fd_ptr
->fd
,0,SEEK_END
) == -1) {
3445 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3448 * Stop the copy from occurring.
3456 ret
= transfer_file(fsp1
->fd_ptr
->fd
,
3457 fsp2
->fd_ptr
->fd
,st
.st_size
,NULL
,0,0);
3459 close_file(fsp1
,False
);
3460 close_file(fsp2
,False
);
3462 return(ret
== st
.st_size
);
3467 /****************************************************************************
3468 reply to a file copy.
3469 ****************************************************************************/
3470 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3475 pstring mask
,newname
;
3478 int error
= ERRnoaccess
;
3481 int tid2
= SVAL(inbuf
,smb_vwv0
);
3482 int ofun
= SVAL(inbuf
,smb_vwv1
);
3483 int flags
= SVAL(inbuf
,smb_vwv2
);
3484 BOOL target_is_directory
=False
;
3485 BOOL bad_path1
= False
;
3486 BOOL bad_path2
= False
;
3488 *directory
= *mask
= 0;
3490 pstrcpy(name
,smb_buf(inbuf
));
3491 pstrcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
3493 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
3495 if (tid2
!= conn
->cnum
) {
3496 /* can't currently handle inter share copies XXXX */
3497 DEBUG(3,("Rejecting inter-share copy\n"));
3498 return(ERROR(ERRSRV
,ERRinvdevice
));
3501 unix_convert(name
,conn
,0,&bad_path1
,NULL
);
3502 unix_convert(newname
,conn
,0,&bad_path2
,NULL
);
3504 target_is_directory
= dos_directory_exist(newname
,NULL
);
3506 if ((flags
&1) && target_is_directory
) {
3507 return(ERROR(ERRDOS
,ERRbadfile
));
3510 if ((flags
&2) && !target_is_directory
) {
3511 return(ERROR(ERRDOS
,ERRbadpath
));
3514 if ((flags
&(1<<5)) && dos_directory_exist(name
,NULL
)) {
3515 /* wants a tree copy! XXXX */
3516 DEBUG(3,("Rejecting tree copy\n"));
3517 return(ERROR(ERRSRV
,ERRerror
));
3520 p
= strrchr(name
,'/');
3522 pstrcpy(directory
,"./");
3526 pstrcpy(directory
,name
);
3530 if (is_mangled(mask
))
3531 check_mangled_cache( mask
);
3533 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
3536 pstrcat(directory
,"/");
3537 pstrcat(directory
,mask
);
3538 if (resolve_wildcards(directory
,newname
) &&
3539 copy_file(directory
,newname
,conn
,ofun
,
3540 count
,target_is_directory
)) count
++;
3541 if (!count
) exists
= dos_file_exist(directory
,NULL
);
3543 void *dirptr
= NULL
;
3547 if (check_name(directory
,conn
))
3548 dirptr
= OpenDir(conn
, directory
, True
);
3554 if (strequal(mask
,"????????.???"))
3557 while ((dname
= ReadDirName(dirptr
)))
3560 pstrcpy(fname
,dname
);
3562 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
3564 error
= ERRnoaccess
;
3565 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
3566 pstrcpy(destname
,newname
);
3567 if (resolve_wildcards(fname
,destname
) &&
3568 copy_file(directory
,newname
,conn
,ofun
,
3569 count
,target_is_directory
)) count
++;
3570 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
3578 return(ERROR(ERRDOS
,error
));
3581 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
3583 unix_ERR_class
= ERRDOS
;
3584 unix_ERR_code
= ERRbadpath
;
3586 return(UNIXERROR(ERRDOS
,error
));
3590 outsize
= set_message(outbuf
,1,0,True
);
3591 SSVAL(outbuf
,smb_vwv0
,count
);
3596 /****************************************************************************
3598 ****************************************************************************/
3599 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3607 if (!CAN_SETDIR(snum
))
3608 return(ERROR(ERRDOS
,ERRnoaccess
));
3610 pstrcpy(newdir
,smb_buf(inbuf
) + 1);
3613 if (strlen(newdir
) == 0) {
3616 ok
= dos_directory_exist(newdir
,NULL
);
3618 string_set(&conn
->connectpath
,newdir
);
3623 return(ERROR(ERRDOS
,ERRbadpath
));
3625 outsize
= set_message(outbuf
,0,0,True
);
3626 CVAL(outbuf
,smb_reh
) = CVAL(inbuf
,smb_reh
);
3628 DEBUG(3,("setdir %s\n", newdir
));
3633 /****************************************************************************
3634 reply to a lockingX request
3635 ****************************************************************************/
3636 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
3638 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
3639 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
3641 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
3643 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
3644 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
3645 SMB_OFF_T count
= 0, offset
= 0;
3646 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
3649 uint32 ecode
=0, dummy2
;
3650 int eclass
=0, dummy1
;
3651 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
);
3652 CHECK_FSP(fsp
,conn
);
3655 data
= smb_buf(inbuf
);
3657 /* Check if this is an oplock break on a file
3658 we have granted an oplock on.
3660 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
))
3663 SMB_DEV_T dev
= fsp
->fd_ptr
->dev
;
3664 SMB_INO_T inode
= fsp
->fd_ptr
->inode
;
3666 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3669 * Make sure we have granted an oplock on this file.
3671 if(!fsp
->granted_oplock
)
3673 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3674 no oplock granted on this file.\n", fsp
->fnum
));
3675 return ERROR(ERRDOS
,ERRlock
);
3678 /* Remove the oplock flag from the sharemode. */
3679 lock_share_entry(fsp
->conn
, dev
, inode
, &token
);
3680 if(remove_share_oplock(token
, fsp
)==False
) {
3682 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3683 dev = %x, inode = %.0f\n", fsp
->fnum
, (unsigned int)dev
, (double)inode
));
3685 unlock_share_entry(fsp
->conn
, dev
, inode
, token
);
3687 unlock_share_entry(fsp
->conn
, dev
, inode
, token
);
3689 /* Clear the granted flag and return. */
3690 fsp
->granted_oplock
= False
;
3693 /* if this is a pure oplock break request then don't send a reply */
3694 if (num_locks
== 0 && num_ulocks
== 0)
3696 /* Sanity check - ensure a pure oplock break is not a
3698 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
3699 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3700 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
3705 /* Data now points at the beginning of the list
3706 of smb_unlkrng structs */
3707 for(i
= 0; i
< (int)num_ulocks
; i
++) {
3708 if(!large_file_format
) {
3709 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3710 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3712 #ifdef LARGE_SMB_OFF_T
3714 count
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(i
))) << 32) |
3715 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(i
)));
3716 offset
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(i
))) << 32) |
3717 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(i
)));
3719 #endif /* LARGE_SMB_OFF_T */
3721 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3722 (double)offset
, (double)count
, fsp
->fsp_name
));
3724 if(!do_unlock(fsp
,conn
,count
,offset
,&eclass
, &ecode
))
3725 return ERROR(eclass
,ecode
);
3728 /* Setup the timeout in seconds. */
3729 lock_timeout
= ((lock_timeout
== -1) ? -1 : lock_timeout
/1000);
3731 /* Now do any requested locks */
3732 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
3734 /* Data now points at the beginning of the list
3735 of smb_lkrng structs */
3737 for(i
= 0; i
< (int)num_locks
; i
++) {
3738 if(!large_file_format
) {
3739 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3740 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3742 #ifdef LARGE_SMB_OFF_T
3744 count
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(i
))) << 32) |
3745 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(i
)));
3746 offset
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(i
))) << 32) |
3747 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(i
)));
3749 #endif /* LARGE_SMB_OFF_T */
3751 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3752 (double)offset
, (double)count
, fsp
->fsp_name
));
3754 if(!do_lock(fsp
,conn
,count
,offset
, ((locktype
& 1) ? F_RDLCK
: F_WRLCK
),
3756 if((ecode
== ERRlock
) && (lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
))) {
3758 * A blocking lock was requested. Package up
3759 * this smb into a queued request and push it
3760 * onto the blocking lock queue.
3762 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
))
3769 /* If any of the above locks failed, then we must unlock
3770 all of the previous locks (X/Open spec). */
3771 if(i
!= num_locks
&& num_locks
!= 0) {
3772 for(; i
>= 0; i
--) {
3773 if(!large_file_format
) {
3774 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3775 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3777 #ifdef LARGE_SMB_OFF_T
3779 count
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(i
))) << 32) |
3780 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(i
)));
3781 offset
= (((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(i
))) << 32) |
3782 ((SMB_OFF_T
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(i
)));
3784 #endif /* LARGE_SMB_OFF_T */
3786 do_unlock(fsp
,conn
,count
,offset
,&dummy1
,&dummy2
);
3788 return ERROR(eclass
,ecode
);
3791 set_message(outbuf
,2,0,True
);
3793 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3794 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
3796 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
3800 /****************************************************************************
3801 reply to a SMBreadbmpx (read block multiplex) request
3802 ****************************************************************************/
3803 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
3814 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3816 /* this function doesn't seem to work - disable by default */
3818 return(ERROR(ERRSRV
,ERRuseSTD
));
3820 outsize
= set_message(outbuf
,8,0,True
);
3822 CHECK_FSP(fsp
,conn
);
3826 startpos
= IVAL(inbuf
,smb_vwv1
);
3827 maxcount
= SVAL(inbuf
,smb_vwv3
);
3829 data
= smb_buf(outbuf
);
3830 pad
= ((long)data
)%4;
3831 if (pad
) pad
= 4 - pad
;
3834 max_per_packet
= bufsize
-(outsize
+pad
);
3838 if (is_locked(fsp
,conn
,maxcount
,startpos
, F_RDLCK
))
3839 return(ERROR(ERRDOS
,ERRlock
));
3843 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
3845 nread
= read_file(fsp
,data
,startpos
,N
);
3847 if (nread
<= 0) nread
= 0;
3849 if (nread
< (ssize_t
)N
)
3850 tcount
= total_read
+ nread
;
3852 set_message(outbuf
,8,nread
,False
);
3853 SIVAL(outbuf
,smb_vwv0
,startpos
);
3854 SSVAL(outbuf
,smb_vwv2
,tcount
);
3855 SSVAL(outbuf
,smb_vwv6
,nread
);
3856 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
3858 send_smb(Client
,outbuf
);
3860 total_read
+= nread
;
3863 while (total_read
< (ssize_t
)tcount
);
3868 /****************************************************************************
3869 reply to a SMBwritebmpx (write block multiplex primary) request
3870 ****************************************************************************/
3871 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3874 ssize_t nwritten
= -1;
3881 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3883 CHECK_FSP(fsp
,conn
);
3887 tcount
= SVAL(inbuf
,smb_vwv1
);
3888 startpos
= IVAL(inbuf
,smb_vwv3
);
3889 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
3890 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3891 smb_doff
= SVAL(inbuf
,smb_vwv11
);
3893 data
= smb_base(inbuf
) + smb_doff
;
3895 /* If this fails we need to send an SMBwriteC response,
3896 not an SMBwritebmpx - set this up now so we don't forget */
3897 CVAL(outbuf
,smb_com
) = SMBwritec
;
3899 if (is_locked(fsp
,conn
,tcount
,startpos
,F_WRLCK
))
3900 return(ERROR(ERRDOS
,ERRlock
));
3902 if(seek_file(fsp
,startpos
) == -1)
3903 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3905 nwritten
= write_file(fsp
,data
,numtowrite
);
3907 if(lp_syncalways(SNUM(conn
)) || write_through
)
3908 sync_file(conn
,fsp
);
3910 if(nwritten
< (ssize_t
)numtowrite
)
3911 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3913 /* If the maximum to be written to this file
3914 is greater than what we just wrote then set
3915 up a secondary struct to be attached to this
3916 fd, we will use this to cache error messages etc. */
3917 if((ssize_t
)tcount
> nwritten
)
3919 write_bmpx_struct
*wbms
;
3920 if(fsp
->wbmpx_ptr
!= NULL
)
3921 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
3923 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
3926 DEBUG(0,("Out of memory in reply_readmpx\n"));
3927 return(ERROR(ERRSRV
,ERRnoresource
));
3929 wbms
->wr_mode
= write_through
;
3930 wbms
->wr_discard
= False
; /* No errors yet */
3931 wbms
->wr_total_written
= nwritten
;
3932 wbms
->wr_errclass
= 0;
3934 fsp
->wbmpx_ptr
= wbms
;
3937 /* We are returning successfully, set the message type back to
3939 CVAL(outbuf
,smb_com
) = SMBwriteBmpx
;
3941 outsize
= set_message(outbuf
,1,0,True
);
3943 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
3945 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3946 fsp
->fnum
, numtowrite
, nwritten
) );
3948 if (write_through
&& tcount
==nwritten
) {
3949 /* we need to send both a primary and a secondary response */
3950 smb_setlen(outbuf
,outsize
- 4);
3951 send_smb(Client
,outbuf
);
3953 /* now the secondary */
3954 outsize
= set_message(outbuf
,1,0,True
);
3955 CVAL(outbuf
,smb_com
) = SMBwritec
;
3956 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3963 /****************************************************************************
3964 reply to a SMBwritebs (write block multiplex secondary) request
3965 ****************************************************************************/
3966 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3969 ssize_t nwritten
= -1;
3976 write_bmpx_struct
*wbms
;
3977 BOOL send_response
= False
;
3978 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3980 CHECK_FSP(fsp
,conn
);
3983 tcount
= SVAL(inbuf
,smb_vwv1
);
3984 startpos
= IVAL(inbuf
,smb_vwv2
);
3985 numtowrite
= SVAL(inbuf
,smb_vwv6
);
3986 smb_doff
= SVAL(inbuf
,smb_vwv7
);
3988 data
= smb_base(inbuf
) + smb_doff
;
3990 /* We need to send an SMBwriteC response, not an SMBwritebs */
3991 CVAL(outbuf
,smb_com
) = SMBwritec
;
3993 /* This fd should have an auxiliary struct attached,
3994 check that it does */
3995 wbms
= fsp
->wbmpx_ptr
;
3996 if(!wbms
) return(-1);
3998 /* If write through is set we can return errors, else we must
4000 write_through
= wbms
->wr_mode
;
4002 /* Check for an earlier error */
4003 if(wbms
->wr_discard
)
4004 return -1; /* Just discard the packet */
4006 if(seek_file(fsp
,startpos
) == -1)
4010 /* We are returning an error - we can delete the aux struct */
4011 if (wbms
) free((char *)wbms
);
4012 fsp
->wbmpx_ptr
= NULL
;
4013 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4015 return(CACHE_ERROR(wbms
,ERRDOS
,ERRnoaccess
));
4018 nwritten
= write_file(fsp
,data
,numtowrite
);
4020 if(lp_syncalways(SNUM(conn
)) || write_through
)
4021 sync_file(conn
,fsp
);
4023 if (nwritten
< (ssize_t
)numtowrite
)
4027 /* We are returning an error - we can delete the aux struct */
4028 if (wbms
) free((char *)wbms
);
4029 fsp
->wbmpx_ptr
= NULL
;
4030 return(ERROR(ERRHRD
,ERRdiskfull
));
4032 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4035 /* Increment the total written, if this matches tcount
4036 we can discard the auxiliary struct (hurrah !) and return a writeC */
4037 wbms
->wr_total_written
+= nwritten
;
4038 if(wbms
->wr_total_written
>= tcount
)
4042 outsize
= set_message(outbuf
,1,0,True
);
4043 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4044 send_response
= True
;
4048 fsp
->wbmpx_ptr
= NULL
;
4058 /****************************************************************************
4059 reply to a SMBsetattrE
4060 ****************************************************************************/
4061 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4063 struct utimbuf unix_times
;
4065 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4067 outsize
= set_message(outbuf
,0,0,True
);
4069 CHECK_FSP(fsp
,conn
);
4072 /* Convert the DOS times into unix times. Ignore create
4073 time as UNIX can't set this.
4075 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4076 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4079 * Patch from Ray Frush <frush@engr.colostate.edu>
4080 * Sometimes times are sent as zero - ignore them.
4083 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0))
4085 /* Ignore request */
4088 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4089 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4093 else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0))
4095 /* set modify time = to access time if modify time was 0 */
4096 unix_times
.modtime
= unix_times
.actime
;
4099 /* Set the date on this file */
4100 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
))
4101 return(ERROR(ERRDOS
,ERRnoaccess
));
4103 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4104 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4110 /****************************************************************************
4111 reply to a SMBgetattrE
4112 ****************************************************************************/
4113 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4115 SMB_STRUCT_STAT sbuf
;
4118 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4120 outsize
= set_message(outbuf
,11,0,True
);
4122 CHECK_FSP(fsp
,conn
);
4125 /* Do an fstat on this file */
4126 if(sys_fstat(fsp
->fd_ptr
->fd
, &sbuf
))
4127 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4129 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4131 /* Convert the times into dos times. Set create
4132 date to be last modify date as UNIX doesn't save
4134 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4135 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4136 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4139 SIVAL(outbuf
,smb_vwv6
,0);
4140 SIVAL(outbuf
,smb_vwv8
,0);
4144 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4145 SIVAL(outbuf
,smb_vwv8
,SMB_ROUNDUP(sbuf
.st_size
,1024));
4147 SSVAL(outbuf
,smb_vwv10
, mode
);
4149 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));