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 files_struct
*chain_fsp
;
37 extern char magic_char
;
38 extern BOOL case_sensitive
;
39 extern BOOL case_preserve
;
40 extern BOOL short_case_preserve
;
41 extern pstring sesssetup_user
;
42 extern fstring global_myworkgroup
;
44 extern int global_oplock_break
;
46 /****************************************************************************
47 report a possible attack via the password buffer overflow bug
48 ****************************************************************************/
49 static void overflow_attack(int len
)
53 dbgtext( "ERROR: Invalid password length %d.\n", len
);
54 dbgtext( "Your machine may be under attack by someone " );
55 dbgtext( "attempting to exploit an old bug.\n" );
56 dbgtext( "Attack was from IP = %s.\n", client_addr(Client
) );
58 exit_server("possible attack");
62 /****************************************************************************
63 reply to an special message
64 ****************************************************************************/
65 int reply_special(char *inbuf
,char *outbuf
)
68 int msg_type
= CVAL(inbuf
,0);
69 int msg_flags
= CVAL(inbuf
,1);
71 extern fstring remote_machine
;
72 extern fstring local_machine
;
78 bzero(outbuf
,smb_size
);
83 case 0x81: /* session request */
84 CVAL(outbuf
,0) = 0x82;
86 if (name_len(inbuf
+4) > 50 ||
87 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
88 DEBUG(0,("Invalid name length in session request\n"));
91 name_extract(inbuf
,4,name1
);
92 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
93 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
96 fstrcpy(remote_machine
,name2
);
97 remote_machine
[15] = 0;
98 trim_string(remote_machine
," "," ");
99 strlower(remote_machine
);
101 fstrcpy(local_machine
,name1
);
102 len
= strlen(local_machine
);
104 name_type
= local_machine
[15];
105 local_machine
[15] = 0;
107 trim_string(local_machine
," "," ");
108 strlower(local_machine
);
110 if (name_type
== 'R') {
111 /* We are being asked for a pathworks session ---
113 CVAL(outbuf
, 0) = 0x83;
117 add_session_user(remote_machine
);
119 reload_services(True
);
123 claim_connection(NULL
,"STATUS.",MAXSTATUS
,True
);
128 case 0x89: /* session keepalive request
129 (some old clients produce this?) */
130 CVAL(outbuf
,0) = 0x85;
134 case 0x82: /* positive session response */
135 case 0x83: /* negative session response */
136 case 0x84: /* retarget session response */
137 DEBUG(0,("Unexpected session response\n"));
140 case 0x85: /* session keepalive */
145 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
146 msg_type
, msg_flags
));
152 /*******************************************************************
153 work out what error to give to a failed connection
154 ********************************************************************/
155 static int connection_error(char *inbuf
,char *outbuf
,int ecode
)
157 if (ecode
== ERRnoipc
) {
158 return(ERROR(ERRDOS
,ERRnoipc
));
161 return(ERROR(ERRSRV
,ecode
));
166 /****************************************************************************
167 parse a share descriptor string
168 ****************************************************************************/
169 static void parse_connect(char *p
,char *service
,char *user
,
170 char *password
,int *pwlen
,char *dev
)
174 DEBUG(4,("parsing connect string %s\n",p
));
176 p2
= strrchr(p
,'\\');
180 fstrcpy(service
,p2
+1);
185 *pwlen
= strlen(password
);
192 p
= strchr(service
,'%');
203 /****************************************************************************
205 ****************************************************************************/
206 int reply_tcon(connection_struct
*conn
,
207 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
214 uint16 vuid
= SVAL(inbuf
,smb_uid
);
218 *service
= *user
= *password
= *dev
= 0;
220 parse_connect(smb_buf(inbuf
)+1,service
,user
,password
,&pwlen
,dev
);
223 * Pass the user through the NT -> unix user mapping
227 (void)map_username(user
);
230 * Do any UNIX username case mangling.
232 (void)Get_Pwnam( user
, True
);
234 conn
= make_connection(service
,user
,password
,pwlen
,dev
,vuid
,&ecode
);
237 return(connection_error(inbuf
,outbuf
,ecode
));
240 outsize
= set_message(outbuf
,2,0,True
);
241 SSVAL(outbuf
,smb_vwv0
,max_recv
);
242 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
243 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
245 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
246 service
, user
, conn
->cnum
));
252 /****************************************************************************
253 reply to a tcon and X
254 ****************************************************************************/
255 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
262 uint16 vuid
= SVAL(inbuf
,smb_uid
);
263 int passlen
= SVAL(inbuf
,smb_vwv3
);
267 *service
= *user
= *password
= *devicename
= 0;
269 /* we might have to close an old one */
270 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
271 close_cnum(conn
,vuid
);
274 if (passlen
> MAX_PASS_LEN
) {
275 overflow_attack(passlen
);
278 memcpy(password
,smb_buf(inbuf
),passlen
);
280 path
= smb_buf(inbuf
) + passlen
;
283 if (strequal(password
," "))
285 passlen
= strlen(password
);
288 fstrcpy(service
,path
+2);
289 p
= strchr(service
,'\\');
291 return(ERROR(ERRSRV
,ERRinvnetname
));
293 fstrcpy(service
,p
+1);
294 p
= strchr(service
,'%');
299 StrnCpy(devicename
,path
+ strlen(path
) + 1,6);
300 DEBUG(4,("Got device type %s\n",devicename
));
303 * Pass the user through the NT -> unix user mapping
307 (void)map_username(user
);
310 * Do any UNIX username case mangling.
312 (void)Get_Pwnam(user
, True
);
314 conn
= make_connection(service
,user
,password
,passlen
,devicename
,vuid
,&ecode
);
317 return(connection_error(inbuf
,outbuf
,ecode
));
319 if (Protocol
< PROTOCOL_NT1
) {
320 set_message(outbuf
,2,strlen(devicename
)+1,True
);
321 pstrcpy(smb_buf(outbuf
),devicename
);
323 char *fsname
= FSTYPE_STRING
;
325 set_message(outbuf
,3,3,True
);
328 pstrcpy(p
,devicename
); p
= skip_string(p
,1); /* device name */
329 pstrcpy(p
,fsname
); p
= skip_string(p
,1); /* filesystem type e.g NTFS */
331 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
333 SSVAL(outbuf
, smb_vwv2
, 0x0); /* optional support */
336 DEBUG(3,("tconX service=%s user=%s\n",
339 /* set the incoming and outgoing tid to the just created one */
340 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
341 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
343 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
347 /****************************************************************************
348 reply to an unknown type
349 ****************************************************************************/
350 int reply_unknown(char *inbuf
,char *outbuf
)
353 type
= CVAL(inbuf
,smb_com
);
355 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
356 smb_fn_name(type
), type
, type
));
358 return(ERROR(ERRSRV
,ERRunknownsmb
));
362 /****************************************************************************
364 ****************************************************************************/
365 int reply_ioctl(connection_struct
*conn
,
366 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
368 DEBUG(3,("ignoring ioctl\n"));
370 /* we just say it succeeds and hope its all OK.
371 some day it would be nice to interpret them individually */
372 return set_message(outbuf
,1,0,True
);
374 return(ERROR(ERRSRV
,ERRnosupport
));
378 /****************************************************************************
379 always return an error: it's just a matter of which one...
380 ****************************************************************************/
381 static int session_trust_account(connection_struct
*conn
, char *inbuf
, char *outbuf
, char *user
,
382 char *smb_passwd
, int smb_passlen
,
383 char *smb_nt_passwd
, int smb_nt_passlen
)
385 struct smb_passwd
*smb_trust_acct
= NULL
; /* check if trust account exists */
386 if (lp_security() == SEC_USER
)
388 smb_trust_acct
= getsmbpwnam(user
);
392 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user
));
393 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
394 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE
));
397 if (smb_trust_acct
== NULL
)
399 /* lkclXXXX: workstation entry doesn't exist */
400 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user
));
401 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
402 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER
));
406 if ((smb_passlen
!= 24) || (smb_nt_passlen
!= 24))
408 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user
));
409 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
410 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE
));
413 if (!smb_password_ok(smb_trust_acct
, (unsigned char *)smb_passwd
, (unsigned char *)smb_nt_passwd
))
415 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user
));
416 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
417 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE
));
420 if (IS_BITS_SET_ALL(smb_trust_acct
->acct_ctrl
, ACB_DOMTRUST
))
422 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user
));
423 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
424 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT
));
427 if (IS_BITS_SET_ALL(smb_trust_acct
->acct_ctrl
, ACB_SVRTRUST
))
429 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user
));
430 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
431 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT
));
434 if (IS_BITS_SET_ALL(smb_trust_acct
->acct_ctrl
, ACB_WSTRUST
))
436 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user
));
437 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
438 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
));
442 /* don't know what to do: indicate logon failure */
443 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
444 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE
));
448 /****************************************************************************
449 reply to a session setup command
450 ****************************************************************************/
451 int reply_sesssetup_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
460 int smb_apasslen
= 0;
462 int smb_ntpasslen
= 0;
463 pstring smb_ntpasswd
;
464 BOOL valid_nt_password
= False
;
468 static BOOL done_sesssetup
= False
;
469 BOOL doencrypt
= SMBENCRYPT();
475 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
476 smb_mpxmax
= SVAL(inbuf
,smb_vwv3
);
477 smb_vc_num
= SVAL(inbuf
,smb_vwv4
);
478 smb_sesskey
= IVAL(inbuf
,smb_vwv5
);
480 if (Protocol
< PROTOCOL_NT1
) {
481 smb_apasslen
= SVAL(inbuf
,smb_vwv7
);
482 if (smb_apasslen
> MAX_PASS_LEN
)
484 overflow_attack(smb_apasslen
);
487 memcpy(smb_apasswd
,smb_buf(inbuf
),smb_apasslen
);
488 smb_apasswd
[smb_apasslen
] = 0;
489 pstrcpy(user
,smb_buf(inbuf
)+smb_apasslen
);
491 if (!doencrypt
&& (lp_security() != SEC_SERVER
)) {
492 smb_apasslen
= strlen(smb_apasswd
);
495 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
496 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
497 uint32 client_caps
= IVAL(inbuf
,smb_vwv11
);
498 enum remote_arch_types ra_type
= get_remote_arch();
500 char *p
= smb_buf(inbuf
);
502 /* client_caps is used as final determination if client is NT or Win95.
503 This is needed to return the correct error codes in some
507 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN95
)
509 if(client_caps
& (CAP_NT_SMBS
| CAP_STATUS32
))
510 set_remote_arch( RA_WINNT
);
512 set_remote_arch( RA_WIN95
);
515 if (passlen1
!= 24 && passlen2
!= 24)
518 if (passlen1
> MAX_PASS_LEN
) {
519 overflow_attack(passlen1
);
522 passlen1
= MIN(passlen1
, MAX_PASS_LEN
);
523 passlen2
= MIN(passlen2
, MAX_PASS_LEN
);
526 /* both Win95 and WinNT stuff up the password lengths for
527 non-encrypting systems. Uggh.
529 if passlen1==24 its a win95 system, and its setting the
530 password length incorrectly. Luckily it still works with the
531 default code because Win95 will null terminate the password
534 if passlen1>0 and passlen2>0 then maybe its a NT box and its
535 setting passlen2 to some random value which really stuffs
536 things up. we need to fix that one. */
538 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 && passlen2
!= 1)
542 if(doencrypt
|| ((lp_security() == SEC_SERVER
) || (lp_security() == SEC_DOMAIN
))) {
543 /* Save the lanman2 password and the NT md4 password. */
544 smb_apasslen
= passlen1
;
545 memcpy(smb_apasswd
,p
,smb_apasslen
);
546 smb_apasswd
[smb_apasslen
] = 0;
547 smb_ntpasslen
= passlen2
;
548 memcpy(smb_ntpasswd
,p
+passlen1
,smb_ntpasslen
);
549 smb_ntpasswd
[smb_ntpasslen
] = 0;
551 /* we use the first password that they gave */
552 smb_apasslen
= passlen1
;
553 StrnCpy(smb_apasswd
,p
,smb_apasslen
);
555 /* trim the password */
556 smb_apasslen
= strlen(smb_apasswd
);
558 /* wfwg sometimes uses a space instead of a null */
559 if (strequal(smb_apasswd
," ")) {
565 p
+= passlen1
+ passlen2
;
566 fstrcpy(user
,p
); p
= skip_string(p
,1);
569 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
570 domain
,skip_string(p
,1),skip_string(p
,2)));
574 DEBUG(3,("sesssetupX:name=[%s]\n",user
));
576 /* If name ends in $ then I think it's asking about whether a */
577 /* computer with that name (minus the $) has access. For now */
578 /* say yes to everything ending in $. */
579 if ((user
[strlen(user
) - 1] == '$') && (smb_apasslen
== 24) && (smb_ntpasslen
== 24))
581 return session_trust_account(conn
, inbuf
, outbuf
, user
,
582 smb_apasswd
, smb_apasslen
,
583 smb_ntpasswd
, smb_ntpasslen
);
586 /* If no username is sent use the guest account */
589 pstrcpy(user
,lp_guestaccount(-1));
590 /* If no user and no password then set guest flag. */
591 if( *smb_apasswd
== 0)
598 * In share level security, only overwrite sesssetup_use if
599 * it's a non null-session share. Helps keep %U and %G
603 if((lp_security() != SEC_SHARE
) || *user
)
604 pstrcpy(sesssetup_user
,user
);
606 reload_services(True
);
609 * Save the username before mapping. We will use
610 * the original username sent to us for security=server
611 * and security=domain checking.
614 pstrcpy( orig_user
, user
);
617 * Pass the user through the NT -> unix user mapping
621 (void)map_username(user
);
624 * Do any UNIX username case mangling.
626 (void)Get_Pwnam( user
, True
);
628 add_session_user(user
);
631 * Check if the given username was the guest user with no password.
634 if(!guest
&& strequal(user
,lp_guestaccount(-1)) && (*smb_apasswd
== 0))
637 if (!guest
&& !(lp_security() == SEC_SERVER
&&
638 /* Check with orig_user for security=server and
640 server_validate(orig_user
, domain
,
641 smb_apasswd
, smb_apasslen
,
642 smb_ntpasswd
, smb_ntpasslen
)) &&
643 !(lp_security() == SEC_DOMAIN
&&
644 domain_client_validate(orig_user
, domain
,
645 smb_apasswd
, smb_apasslen
,
646 smb_ntpasswd
, smb_ntpasslen
)) &&
647 !check_hosts_equiv(user
)
651 /* now check if it's a valid username/password */
652 /* If an NT password was supplied try and validate with that
653 first. This is superior as the passwords are mixed case
654 128 length unicode */
657 if(!password_ok(user
,smb_ntpasswd
,smb_ntpasslen
,NULL
))
658 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
660 valid_nt_password
= True
;
662 if (!valid_nt_password
&& !password_ok(user
,smb_apasswd
,smb_apasslen
,NULL
))
664 if (lp_security() >= SEC_USER
) {
665 #if (GUEST_SESSSETUP == 0)
666 return(ERROR(ERRSRV
,ERRbadpw
));
668 #if (GUEST_SESSSETUP == 1)
669 if (Get_Pwnam(user
,True
))
670 return(ERROR(ERRSRV
,ERRbadpw
));
673 if (*smb_apasswd
|| !Get_Pwnam(user
,True
))
674 pstrcpy(user
,lp_guestaccount(-1));
675 DEBUG(3,("Registered username %s for guest access\n",user
));
680 if (!Get_Pwnam(user
,True
)) {
681 DEBUG(3,("No such user %s - using guest account\n",user
));
682 pstrcpy(user
,lp_guestaccount(-1));
686 if (!strequal(user
,lp_guestaccount(-1)) &&
687 lp_servicenumber(user
) < 0)
689 int homes
= lp_servicenumber(HOMES_NAME
);
690 char *home
= get_home_dir(user
);
691 if (homes
>= 0 && home
)
692 lp_add_home(user
,homes
,home
);
696 /* it's ok - setup a reply */
697 if (Protocol
< PROTOCOL_NT1
) {
698 set_message(outbuf
,3,0,True
);
701 set_message(outbuf
,3,3,True
);
703 pstrcpy(p
,"Unix"); p
= skip_string(p
,1);
704 pstrcpy(p
,"Samba "); pstrcat(p
,VERSION
); p
= skip_string(p
,1);
705 pstrcpy(p
,global_myworkgroup
); p
= skip_string(p
,1);
706 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
707 /* perhaps grab OS version here?? */
710 /* Set the correct uid in the outgoing and incoming packets
711 We will use this on future requests to determine which
712 user we should become.
715 struct passwd
*pw
= Get_Pwnam(user
,False
);
717 DEBUG(1,("Username %s is invalid on this system\n",user
));
718 return(ERROR(ERRSRV
,ERRbadpw
));
725 SSVAL(outbuf
,smb_vwv2
,1);
727 /* register the name and uid as being validated, so further connections
728 to a uid can get through without a password, on the same VC */
729 sess_vuid
= register_vuid(uid
,gid
,user
,sesssetup_user
,guest
);
731 SSVAL(outbuf
,smb_uid
,sess_vuid
);
732 SSVAL(inbuf
,smb_uid
,sess_vuid
);
735 max_send
= MIN(max_send
,smb_bufsize
);
737 DEBUG(6,("Client requested max send size of %d\n", max_send
));
739 done_sesssetup
= True
;
741 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
745 /****************************************************************************
747 ****************************************************************************/
748 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
754 BOOL bad_path
= False
;
756 pstrcpy(name
,smb_buf(inbuf
) + 1);
757 unix_convert(name
,conn
,0,&bad_path
);
759 mode
= SVAL(inbuf
,smb_vwv0
);
761 if (check_name(name
,conn
))
762 ok
= directory_exist(name
,NULL
);
766 /* We special case this - as when a Windows machine
767 is parsing a path is steps through the components
768 one at a time - if a component fails it expects
769 ERRbadpath, not ERRbadfile.
773 unix_ERR_class
= ERRDOS
;
774 unix_ERR_code
= ERRbadpath
;
778 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
779 if((errno
== ENOTDIR
) && (Protocol
>= PROTOCOL_NT1
) &&
780 (get_remote_arch() == RA_WINNT
))
782 unix_ERR_class
= ERRDOS
;
783 unix_ERR_code
= ERRbaddirectory
;
787 return(UNIXERROR(ERRDOS
,ERRbadpath
));
790 outsize
= set_message(outbuf
,0,0,True
);
792 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
798 /****************************************************************************
800 ****************************************************************************/
801 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
810 BOOL bad_path
= False
;
812 pstrcpy(fname
,smb_buf(inbuf
) + 1);
813 unix_convert(fname
,conn
,0,&bad_path
);
815 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
816 under WfWg - weird! */
819 mode
= aHIDDEN
| aDIR
;
820 if (!CAN_WRITE(conn
)) mode
|= aRONLY
;
826 if (check_name(fname
,conn
))
828 if (sys_stat(fname
,&sbuf
) == 0)
830 mode
= dos_mode(conn
,fname
,&sbuf
);
832 mtime
= sbuf
.st_mtime
;
838 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
843 if((errno
== ENOENT
) && bad_path
)
845 unix_ERR_class
= ERRDOS
;
846 unix_ERR_code
= ERRbadpath
;
849 return(UNIXERROR(ERRDOS
,ERRbadfile
));
852 outsize
= set_message(outbuf
,10,0,True
);
854 SSVAL(outbuf
,smb_vwv0
,mode
);
855 if(lp_dos_filetime_resolution(SNUM(conn
)) )
856 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
858 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
859 SIVAL(outbuf
,smb_vwv3
,size
);
861 if (Protocol
>= PROTOCOL_NT1
) {
862 char *p
= strrchr(fname
,'/');
863 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
865 if (!is_8_3(fname
, True
))
866 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
869 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, size
) );
875 /****************************************************************************
877 ****************************************************************************/
878 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
885 BOOL bad_path
= False
;
887 pstrcpy(fname
,smb_buf(inbuf
) + 1);
888 unix_convert(fname
,conn
,0,&bad_path
);
890 mode
= SVAL(inbuf
,smb_vwv0
);
891 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
893 if (directory_exist(fname
,NULL
))
895 if (check_name(fname
,conn
))
896 ok
= (dos_chmod(conn
,fname
,mode
,NULL
) == 0);
898 ok
= set_filetime(conn
,fname
,mtime
);
902 if((errno
== ENOENT
) && bad_path
)
904 unix_ERR_class
= ERRDOS
;
905 unix_ERR_code
= ERRbadpath
;
908 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
911 outsize
= set_message(outbuf
,0,0,True
);
913 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
919 /****************************************************************************
921 ****************************************************************************/
922 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
925 int dfree
,dsize
,bsize
;
927 sys_disk_free(".",&bsize
,&dfree
,&dsize
);
929 outsize
= set_message(outbuf
,5,0,True
);
931 SSVAL(outbuf
,smb_vwv0
,dsize
);
932 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
933 SSVAL(outbuf
,smb_vwv2
,512);
934 SSVAL(outbuf
,smb_vwv3
,dfree
);
936 DEBUG(3,("dskattr dfree=%d\n", dfree
));
942 /****************************************************************************
944 Can be called from SMBsearch, SMBffirst or SMBfunique.
945 ****************************************************************************/
946 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
956 BOOL finished
= False
;
965 BOOL check_descend
= False
;
966 BOOL expect_close
= False
;
967 BOOL can_open
= True
;
968 BOOL bad_path
= False
;
970 *mask
= *directory
= *fname
= 0;
972 /* If we were called as SMBffirst then we must expect close. */
973 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
976 outsize
= set_message(outbuf
,1,3,True
);
977 maxentries
= SVAL(inbuf
,smb_vwv0
);
978 dirtype
= SVAL(inbuf
,smb_vwv1
);
979 path
= smb_buf(inbuf
) + 1;
980 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
983 /* dirtype &= ~aDIR; */
985 DEBUG(5,("path=%s status_len=%d\n",path
,status_len
));
992 pstrcpy(directory
,smb_buf(inbuf
)+1);
993 pstrcpy(dir2
,smb_buf(inbuf
)+1);
994 unix_convert(directory
,conn
,0,&bad_path
);
997 if (!check_name(directory
,conn
))
1000 p
= strrchr(dir2
,'/');
1012 p
= strrchr(directory
,'/');
1018 if (strlen(directory
) == 0)
1019 pstrcpy(directory
,"./");
1021 CVAL(status
,0) = dirtype
;
1025 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1026 memcpy(mask
,status
+1,11);
1028 dirtype
= CVAL(status
,0) & 0x1F;
1029 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1032 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1033 if (!case_sensitive
)
1037 /* turn strings of spaces into a . */
1039 trim_string(mask
,NULL
," ");
1040 if ((p
= strrchr(mask
,' ')))
1045 trim_string(mask
,NULL
," ");
1051 /* Convert the formatted mask. (This code lives in trans2.c) */
1055 for (p
=mask
; *p
; p
++)
1057 if (*p
!= '?' && *p
!= '*' && !isdoschar(*p
))
1059 DEBUG(5,("Invalid char [%c] in search mask?\n",*p
));
1065 if (!strchr(mask
,'.') && strlen(mask
)>8)
1068 fstrcpy(tmp
,&mask
[8]);
1074 DEBUG(5,("mask=%s directory=%s\n",mask
,directory
));
1078 p
= smb_buf(outbuf
) + 3;
1082 if (status_len
== 0)
1084 dptr_num
= dptr_create(conn
,directory
,expect_close
,SVAL(inbuf
,smb_pid
));
1089 if((errno
== ENOENT
) && bad_path
)
1091 unix_ERR_class
= ERRDOS
;
1092 unix_ERR_code
= ERRbadpath
;
1094 return (UNIXERROR(ERRDOS
,ERRnofids
));
1096 return(ERROR(ERRDOS
,ERRnofids
));
1100 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1104 if ((dirtype
&0x1F) == aVOLID
)
1106 memcpy(p
,status
,21);
1107 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
1108 dptr_fill(p
+12,dptr_num
);
1109 if (dptr_zero(p
+12) && (status_len
==0))
1113 p
+= DIR_STRUCT_SIZE
;
1117 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1118 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1119 if (in_list(conn
->dirpath
,
1120 lp_dontdescend(SNUM(conn
)),True
))
1121 check_descend
= True
;
1123 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
1126 !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
1129 memcpy(p
,status
,21);
1130 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
1131 dptr_fill(p
+12,dptr_num
);
1134 p
+= DIR_STRUCT_SIZE
;
1143 if (numentries
== 0 || !ok
)
1145 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1146 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1149 /* If we were called as SMBffirst with smb_search_id == NULL
1150 and no entries were found then return error and close dirptr
1153 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
1155 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1156 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1157 /* Also close the dptr - we know it's gone */
1158 dptr_close(dptr_num
);
1161 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1162 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
1163 dptr_close(dptr_num
);
1165 SSVAL(outbuf
,smb_vwv0
,numentries
);
1166 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1167 CVAL(smb_buf(outbuf
),0) = 5;
1168 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1170 if (Protocol
>= PROTOCOL_NT1
) {
1171 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
1172 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
1175 outsize
+= DIR_STRUCT_SIZE
*numentries
;
1176 smb_setlen(outbuf
,outsize
- 4);
1178 if ((! *directory
) && dptr_path(dptr_num
))
1179 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1181 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1182 smb_fn_name(CVAL(inbuf
,smb_com
)),
1183 mask
, directory
, dirtype
, numentries
, maxentries
) );
1189 /****************************************************************************
1190 reply to a fclose (stop directory search)
1191 ****************************************************************************/
1192 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1200 outsize
= set_message(outbuf
,1,0,True
);
1201 path
= smb_buf(inbuf
) + 1;
1202 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
1205 if (status_len
== 0)
1206 return(ERROR(ERRSRV
,ERRsrverror
));
1208 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1210 if(dptr_fetch(status
+12,&dptr_num
)) {
1211 /* Close the dptr - we know it's gone */
1212 dptr_close(dptr_num
);
1215 SSVAL(outbuf
,smb_vwv0
,0);
1217 DEBUG(3,("search close\n"));
1223 /****************************************************************************
1225 ****************************************************************************/
1226 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1237 BOOL bad_path
= False
;
1239 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1241 share_mode
= SVAL(inbuf
,smb_vwv0
);
1243 pstrcpy(fname
,smb_buf(inbuf
)+1);
1244 unix_convert(fname
,conn
,0,&bad_path
);
1248 return(ERROR(ERRSRV
,ERRnofids
));
1250 if (!check_name(fname
,conn
))
1252 if((errno
== ENOENT
) && bad_path
)
1254 unix_ERR_class
= ERRDOS
;
1255 unix_ERR_code
= ERRbadpath
;
1258 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1261 unixmode
= unix_mode(conn
,aARCH
);
1263 open_file_shared(fsp
,conn
,fname
,share_mode
,3,unixmode
,
1264 oplock_request
,&rmode
,NULL
);
1268 if((errno
== ENOENT
) && bad_path
)
1270 unix_ERR_class
= ERRDOS
;
1271 unix_ERR_code
= ERRbadpath
;
1274 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1277 if (fstat(fsp
->fd_ptr
->fd
,&sbuf
) != 0) {
1278 close_file(fsp
,False
);
1279 return(ERROR(ERRDOS
,ERRnoaccess
));
1282 size
= sbuf
.st_size
;
1283 fmode
= dos_mode(conn
,fname
,&sbuf
);
1284 mtime
= sbuf
.st_mtime
;
1287 DEBUG(3,("attempt to open a directory %s\n",fname
));
1288 close_file(fsp
,False
);
1289 return(ERROR(ERRDOS
,ERRnoaccess
));
1292 outsize
= set_message(outbuf
,7,0,True
);
1293 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1294 SSVAL(outbuf
,smb_vwv1
,fmode
);
1295 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1296 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1298 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1299 SIVAL(outbuf
,smb_vwv4
,size
);
1300 SSVAL(outbuf
,smb_vwv6
,rmode
);
1302 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1303 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1306 if(fsp
->granted_oplock
)
1307 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1312 /****************************************************************************
1313 reply to an open and X
1314 ****************************************************************************/
1315 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1318 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1319 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1320 /* Breakout the oplock request bits so we can set the
1321 reply bits separately. */
1322 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1323 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1324 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1326 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1327 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1328 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1330 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1332 int size
=0,fmode
=0,mtime
=0,rmode
=0;
1335 BOOL bad_path
= False
;
1338 /* If it's an IPC, pass off the pipe handler. */
1340 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1342 /* XXXX we need to handle passed times, sattr and flags */
1344 pstrcpy(fname
,smb_buf(inbuf
));
1345 unix_convert(fname
,conn
,0,&bad_path
);
1349 return(ERROR(ERRSRV
,ERRnofids
));
1351 if (!check_name(fname
,conn
))
1353 if((errno
== ENOENT
) && bad_path
)
1355 unix_ERR_class
= ERRDOS
;
1356 unix_ERR_code
= ERRbadpath
;
1359 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1362 unixmode
= unix_mode(conn
,smb_attr
| aARCH
);
1364 open_file_shared(fsp
,conn
,fname
,smb_mode
,smb_ofun
,unixmode
,
1365 oplock_request
, &rmode
,&smb_action
);
1369 if((errno
== ENOENT
) && bad_path
)
1371 unix_ERR_class
= ERRDOS
;
1372 unix_ERR_code
= ERRbadpath
;
1375 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1378 if (fstat(fsp
->fd_ptr
->fd
,&sbuf
) != 0) {
1379 close_file(fsp
,False
);
1380 return(ERROR(ERRDOS
,ERRnoaccess
));
1383 size
= sbuf
.st_size
;
1384 fmode
= dos_mode(conn
,fname
,&sbuf
);
1385 mtime
= sbuf
.st_mtime
;
1387 close_file(fsp
,False
);
1388 return(ERROR(ERRDOS
,ERRnoaccess
));
1391 /* If the caller set the extended oplock request bit
1392 and we granted one (by whatever means) - set the
1393 correct bit for extended oplock reply.
1396 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1397 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1400 if(ex_oplock_request
&& fsp
->granted_oplock
) {
1401 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1404 /* If the caller set the core oplock request bit
1405 and we granted one (by whatever means) - set the
1406 correct bit for core oplock reply.
1409 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1410 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1413 if(core_oplock_request
&& fsp
->granted_oplock
) {
1414 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1417 set_message(outbuf
,15,0,True
);
1418 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1419 SSVAL(outbuf
,smb_vwv3
,fmode
);
1420 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1421 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1423 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1424 SIVAL(outbuf
,smb_vwv6
,size
);
1425 SSVAL(outbuf
,smb_vwv8
,rmode
);
1426 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1430 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1434 /****************************************************************************
1435 reply to a SMBulogoffX
1436 ****************************************************************************/
1437 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1439 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1440 user_struct
*vuser
= get_valid_user_struct(vuid
);
1443 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1446 /* in user level security we are supposed to close any files
1447 open by this user */
1448 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1449 file_close_user(vuid
);
1452 invalidate_vuid(vuid
);
1454 set_message(outbuf
,2,0,True
);
1456 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1458 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1462 /****************************************************************************
1463 reply to a mknew or a create
1464 ****************************************************************************/
1465 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1473 BOOL bad_path
= False
;
1475 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1477 com
= SVAL(inbuf
,smb_com
);
1479 createmode
= SVAL(inbuf
,smb_vwv0
);
1480 pstrcpy(fname
,smb_buf(inbuf
)+1);
1481 unix_convert(fname
,conn
,0,&bad_path
);
1483 if (createmode
& aVOLID
)
1485 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1488 unixmode
= unix_mode(conn
,createmode
);
1492 return(ERROR(ERRSRV
,ERRnofids
));
1494 if (!check_name(fname
,conn
))
1496 if((errno
== ENOENT
) && bad_path
)
1498 unix_ERR_class
= ERRDOS
;
1499 unix_ERR_code
= ERRbadpath
;
1502 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1507 /* We should fail if file exists. */
1512 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1516 /* Open file in dos compatibility share mode. */
1517 open_file_shared(fsp
,conn
,fname
,(DENY_FCB
<<4)|0xF, ofun
, unixmode
,
1518 oplock_request
, NULL
, NULL
);
1522 if((errno
== ENOENT
) && bad_path
)
1524 unix_ERR_class
= ERRDOS
;
1525 unix_ERR_code
= ERRbadpath
;
1528 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1531 outsize
= set_message(outbuf
,1,0,True
);
1532 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1534 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1535 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1538 if(fsp
->granted_oplock
)
1539 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1541 DEBUG( 2, ( "new file %s\n", fname
) );
1542 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1543 fname
, fsp
->fd_ptr
->fd
, createmode
, (int)unixmode
) );
1549 /****************************************************************************
1550 reply to a create temporary file
1551 ****************************************************************************/
1552 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1559 BOOL bad_path
= False
;
1561 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1563 createmode
= SVAL(inbuf
,smb_vwv0
);
1564 pstrcpy(fname
,smb_buf(inbuf
)+1);
1565 pstrcat(fname
,"/TMXXXXXX");
1566 unix_convert(fname
,conn
,0,&bad_path
);
1568 unixmode
= unix_mode(conn
,createmode
);
1572 return(ERROR(ERRSRV
,ERRnofids
));
1574 if (!check_name(fname
,conn
))
1576 if((errno
== ENOENT
) && bad_path
)
1578 unix_ERR_class
= ERRDOS
;
1579 unix_ERR_code
= ERRbadpath
;
1582 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1585 pstrcpy(fname2
,(char *)mktemp(fname
));
1587 /* Open file in dos compatibility share mode. */
1588 /* We should fail if file exists. */
1589 open_file_shared(fsp
,conn
,fname2
,(DENY_FCB
<<4)|0xF, 0x10, unixmode
,
1590 oplock_request
, NULL
, NULL
);
1594 if((errno
== ENOENT
) && bad_path
)
1596 unix_ERR_class
= ERRDOS
;
1597 unix_ERR_code
= ERRbadpath
;
1600 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1603 outsize
= set_message(outbuf
,1,2 + strlen(fname2
),True
);
1604 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1605 CVAL(smb_buf(outbuf
),0) = 4;
1606 pstrcpy(smb_buf(outbuf
) + 1,fname2
);
1608 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1609 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1612 if(fsp
->granted_oplock
)
1613 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1615 DEBUG( 2, ( "created temp file %s\n", fname2
) );
1616 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1617 fname2
, fsp
->fd_ptr
->fd
, createmode
, (int)unixmode
) );
1623 /*******************************************************************
1624 check if a user is allowed to delete a file
1625 ********************************************************************/
1626 static BOOL
can_delete(char *fname
,connection_struct
*conn
, int dirtype
)
1631 if (!CAN_WRITE(conn
)) return(False
);
1633 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
1634 fmode
= dos_mode(conn
,fname
,&sbuf
);
1635 if (fmode
& aDIR
) return(False
);
1636 if (!lp_delete_readonly(SNUM(conn
))) {
1637 if (fmode
& aRONLY
) return(False
);
1639 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1641 if (!check_file_sharing(conn
,fname
,False
)) return(False
);
1645 /****************************************************************************
1647 ****************************************************************************/
1648 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1657 int error
= ERRnoaccess
;
1660 BOOL bad_path
= False
;
1662 *directory
= *mask
= 0;
1664 dirtype
= SVAL(inbuf
,smb_vwv0
);
1666 pstrcpy(name
,smb_buf(inbuf
) + 1);
1668 DEBUG(3,("reply_unlink : %s\n",name
));
1670 unix_convert(name
,conn
,0,&bad_path
);
1672 p
= strrchr(name
,'/');
1674 pstrcpy(directory
,"./");
1678 pstrcpy(directory
,name
);
1682 if (is_mangled(mask
))
1683 check_mangled_cache( mask
);
1685 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
1688 pstrcat(directory
,"/");
1689 pstrcat(directory
,mask
);
1690 if (can_delete(directory
,conn
,dirtype
) && !sys_unlink(directory
)) count
++;
1691 if (!count
) exists
= file_exist(directory
,NULL
);
1693 void *dirptr
= NULL
;
1696 if (check_name(directory
,conn
))
1697 dirptr
= OpenDir(conn
, directory
, True
);
1699 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1700 the pattern matches against the long name, otherwise the short name
1701 We don't implement this yet XXXX
1708 if (strequal(mask
,"????????.???"))
1711 while ((dname
= ReadDirName(dirptr
)))
1714 pstrcpy(fname
,dname
);
1716 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
1718 error
= ERRnoaccess
;
1719 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1720 if (!can_delete(fname
,conn
,dirtype
)) continue;
1721 if (!sys_unlink(fname
)) count
++;
1722 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname
));
1730 return(ERROR(ERRDOS
,error
));
1733 if((errno
== ENOENT
) && bad_path
)
1735 unix_ERR_class
= ERRDOS
;
1736 unix_ERR_code
= ERRbadpath
;
1738 return(UNIXERROR(ERRDOS
,error
));
1742 outsize
= set_message(outbuf
,0,0,True
);
1748 /****************************************************************************
1749 reply to a readbraw (core+ protocol)
1750 ****************************************************************************/
1751 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1753 int maxcount
,mincount
;
1756 char *header
= outbuf
;
1763 * Special check if an oplock break has been issued
1764 * and the readraw request croses on the wire, we must
1765 * return a zero length response here.
1768 if(global_oplock_break
)
1770 _smb_setlen(header
,0);
1771 transfer_file(0,Client
,0,header
,4,0);
1772 DEBUG(5,("readbraw - oplock break finished\n"));
1776 fsp
= GETFSP(inbuf
,smb_vwv0
);
1778 startpos
= IVAL(inbuf
,smb_vwv1
);
1779 maxcount
= SVAL(inbuf
,smb_vwv3
);
1780 mincount
= SVAL(inbuf
,smb_vwv4
);
1782 /* ensure we don't overrun the packet size */
1783 maxcount
= MIN(65535,maxcount
);
1784 maxcount
= MAX(mincount
,maxcount
);
1786 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1787 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp
->fnum
));
1788 _smb_setlen(header
,0);
1789 transfer_file(0,Client
,0,header
,4,0);
1792 fd
= fsp
->fd_ptr
->fd
;
1793 fname
= fsp
->fsp_name
;
1797 if (!is_locked(fsp
,conn
,maxcount
,startpos
, F_RDLCK
))
1799 int size
= fsp
->size
;
1800 int sizeneeded
= startpos
+ maxcount
;
1802 if (size
< sizeneeded
) {
1804 if (fstat(fsp
->fd_ptr
->fd
,&st
) == 0)
1806 if (!fsp
->can_write
)
1810 nread
= MIN(maxcount
,(int)(size
- startpos
));
1813 if (nread
< mincount
)
1816 DEBUG( 3, ( "readbraw fnum=%d start=%d max=%d min=%d nread=%d\n",
1817 fsp
->fnum
, startpos
,
1818 maxcount
, mincount
, nread
) );
1823 _smb_setlen(header
,nread
);
1825 #if USE_READ_PREDICTION
1826 if (!fsp
->can_write
)
1827 predict
= read_predict(fd
,startpos
,header
+4,NULL
,nread
);
1830 if ((nread
-predict
) > 0)
1831 seek_file(fsp
,startpos
+ predict
);
1833 ret
= transfer_file(fd
,Client
,nread
-predict
,header
,4+predict
,
1838 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1839 fname
,startpos
,nread
,ret
));
1842 ret
= read_file(fsp
,header
+4,startpos
,nread
);
1843 if (ret
< mincount
) ret
= 0;
1845 _smb_setlen(header
,ret
);
1846 transfer_file(0,Client
,0,header
,4+ret
,0);
1849 DEBUG(5,("readbraw finished\n"));
1854 /****************************************************************************
1855 reply to a lockread (core+ protocol)
1856 ****************************************************************************/
1857 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsiz
)
1862 uint32 startpos
, numtoread
;
1865 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
1867 CHECK_FSP(fsp
,conn
);
1871 numtoread
= SVAL(inbuf
,smb_vwv1
);
1872 startpos
= IVAL(inbuf
,smb_vwv2
);
1874 outsize
= set_message(outbuf
,5,3,True
);
1875 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1876 data
= smb_buf(outbuf
) + 3;
1878 if(!do_lock( fsp
, conn
, numtoread
, startpos
, F_RDLCK
, &eclass
, &ecode
))
1879 return (ERROR(eclass
,ecode
));
1881 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1884 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1887 SSVAL(outbuf
,smb_vwv0
,nread
);
1888 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1889 SSVAL(smb_buf(outbuf
),1,nread
);
1891 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1892 fsp
->fnum
, numtoread
, nread
) );
1898 /****************************************************************************
1900 ****************************************************************************/
1901 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1908 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
1910 CHECK_FSP(fsp
,conn
);
1914 numtoread
= SVAL(inbuf
,smb_vwv1
);
1915 startpos
= IVAL(inbuf
,smb_vwv2
);
1917 outsize
= set_message(outbuf
,5,3,True
);
1918 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1919 data
= smb_buf(outbuf
) + 3;
1921 if (is_locked(fsp
,conn
,numtoread
,startpos
, F_RDLCK
))
1922 return(ERROR(ERRDOS
,ERRlock
));
1925 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1928 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1931 SSVAL(outbuf
,smb_vwv0
,nread
);
1932 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1933 CVAL(smb_buf(outbuf
),0) = 1;
1934 SSVAL(smb_buf(outbuf
),1,nread
);
1936 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1937 fsp
->fnum
, numtoread
, nread
) );
1943 /****************************************************************************
1944 reply to a read and X
1945 ****************************************************************************/
1946 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1948 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv2
);
1949 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
1950 int smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
1951 int smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
1956 /* If it's an IPC, pass off the pipe handler. */
1958 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
1960 CHECK_FSP(fsp
,conn
);
1964 set_message(outbuf
,12,0,True
);
1965 data
= smb_buf(outbuf
);
1967 if (is_locked(fsp
,conn
,smb_maxcnt
,smb_offs
, F_RDLCK
))
1968 return(ERROR(ERRDOS
,ERRlock
));
1969 nread
= read_file(fsp
,data
,smb_offs
,smb_maxcnt
);
1973 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1975 SSVAL(outbuf
,smb_vwv5
,nread
);
1976 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
1977 SSVAL(smb_buf(outbuf
),-2,nread
);
1979 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
1980 fsp
->fnum
, smb_mincnt
, smb_maxcnt
, nread
) );
1984 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1988 /****************************************************************************
1989 reply to a writebraw (core+ or LANMAN1.0 protocol)
1990 ****************************************************************************/
1991 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1994 int total_written
=0;
2001 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
2003 CHECK_FSP(fsp
,conn
);
2007 tcount
= IVAL(inbuf
,smb_vwv1
);
2008 startpos
= IVAL(inbuf
,smb_vwv3
);
2009 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2011 /* We have to deal with slightly different formats depending
2012 on whether we are using the core+ or lanman1.0 protocol */
2013 if(Protocol
<= PROTOCOL_COREPLUS
) {
2014 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2015 data
= smb_buf(inbuf
);
2017 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2018 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2021 /* force the error type */
2022 CVAL(inbuf
,smb_com
) = SMBwritec
;
2023 CVAL(outbuf
,smb_com
) = SMBwritec
;
2025 if (is_locked(fsp
,conn
,tcount
,startpos
, F_WRLCK
))
2026 return(ERROR(ERRDOS
,ERRlock
));
2028 if (seek_file(fsp
,startpos
) != startpos
)
2029 DEBUG(0,("couldn't seek to %ld in writebraw\n",startpos
));
2032 nwritten
= write_file(fsp
,data
,numtowrite
);
2034 DEBUG(3,("writebraw1 fnum=%d start=%ld num=%d wrote=%d sync=%d\n",
2035 fsp
->fnum
, startpos
, numtowrite
, nwritten
, write_through
));
2037 if (nwritten
< numtowrite
)
2038 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2040 total_written
= nwritten
;
2042 /* Return a message to the redirector to tell it
2043 to send more bytes */
2044 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
2045 SSVALS(outbuf
,smb_vwv0
,-1);
2046 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2047 send_smb(Client
,outbuf
);
2049 /* Now read the raw data into the buffer and write it */
2050 if (read_smb_length(Client
,inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2051 exit_server("secondary writebraw failed");
2054 /* Even though this is not an smb message, smb_len
2055 returns the generic length of an smb message */
2056 numtowrite
= smb_len(inbuf
);
2058 if (tcount
> nwritten
+numtowrite
) {
2059 DEBUG(3,("Client overestimated the write %d %d %d\n",
2060 tcount
,nwritten
,numtowrite
));
2063 nwritten
= transfer_file(Client
,fsp
->fd_ptr
->fd
,numtowrite
,NULL
,0,
2065 total_written
+= nwritten
;
2067 /* Set up outbuf to return the correct return */
2068 outsize
= set_message(outbuf
,1,0,True
);
2069 CVAL(outbuf
,smb_com
) = SMBwritec
;
2070 SSVAL(outbuf
,smb_vwv0
,total_written
);
2072 if (nwritten
< numtowrite
) {
2073 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2074 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2077 if (lp_syncalways(SNUM(conn
)) || write_through
)
2078 sync_file(conn
,fsp
);
2080 DEBUG(3,("writebraw2 fnum=%d start=%ld num=%d wrote=%d\n",
2081 fsp
->fnum
, startpos
, numtowrite
, total_written
));
2083 /* we won't return a status if write through is not selected - this
2084 follows what WfWg does */
2085 if (!write_through
&& total_written
==tcount
)
2092 /****************************************************************************
2093 reply to a writeunlock (core+)
2094 ****************************************************************************/
2095 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2100 uint32 numtowrite
,startpos
;
2103 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
2105 CHECK_FSP(fsp
,conn
);
2109 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2110 startpos
= IVAL(inbuf
,smb_vwv2
);
2111 data
= smb_buf(inbuf
) + 3;
2113 if (is_locked(fsp
,conn
,numtowrite
,startpos
, F_WRLCK
))
2114 return(ERROR(ERRDOS
,ERRlock
));
2116 seek_file(fsp
,startpos
);
2118 /* The special X/Open SMB protocol handling of
2119 zero length writes is *NOT* done for
2124 nwritten
= write_file(fsp
,data
,numtowrite
);
2126 if (lp_syncalways(SNUM(conn
)))
2127 sync_file(conn
,fsp
);
2129 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
2130 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2132 if(!do_unlock(fsp
, conn
, numtowrite
, startpos
, &eclass
, &ecode
))
2133 return(ERROR(eclass
,ecode
));
2135 outsize
= set_message(outbuf
,1,0,True
);
2137 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2139 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2140 fsp
->fnum
, numtowrite
, nwritten
) );
2146 /****************************************************************************
2148 ****************************************************************************/
2149 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int dum_size
,int dum_buffsize
)
2156 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
2158 CHECK_FSP(fsp
,conn
);
2162 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2163 startpos
= IVAL(inbuf
,smb_vwv2
);
2164 data
= smb_buf(inbuf
) + 3;
2166 if (is_locked(fsp
,conn
,numtowrite
,startpos
, F_WRLCK
))
2167 return(ERROR(ERRDOS
,ERRlock
));
2169 seek_file(fsp
,startpos
);
2171 /* X/Open SMB protocol says that if smb_vwv1 is
2172 zero then the file size should be extended or
2173 truncated to the size given in smb_vwv[2-3] */
2175 nwritten
= set_filelen(fsp
->fd_ptr
->fd
, startpos
);
2177 nwritten
= write_file(fsp
,data
,numtowrite
);
2179 if (lp_syncalways(SNUM(conn
)))
2180 sync_file(conn
,fsp
);
2182 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
2183 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2185 outsize
= set_message(outbuf
,1,0,True
);
2187 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2189 if (nwritten
< numtowrite
) {
2190 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2191 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2194 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2195 fsp
->fnum
, numtowrite
, nwritten
));
2201 /****************************************************************************
2202 reply to a write and X
2203 ****************************************************************************/
2204 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2206 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv2
);
2207 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
2208 int smb_dsize
= SVAL(inbuf
,smb_vwv10
);
2209 int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2210 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2214 CHECK_FSP(fsp
,conn
);
2218 data
= smb_base(inbuf
) + smb_doff
;
2220 if (is_locked(fsp
,conn
,smb_dsize
,smb_offs
, F_WRLCK
))
2221 return(ERROR(ERRDOS
,ERRlock
));
2223 seek_file(fsp
,smb_offs
);
2225 /* X/Open SMB protocol says that, unlike SMBwrite
2226 if the length is zero then NO truncation is
2227 done, just a write of zero. To truncate a file,
2232 nwritten
= write_file(fsp
,data
,smb_dsize
);
2234 if(((nwritten
== 0) && (smb_dsize
!= 0))||(nwritten
< 0))
2235 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2237 set_message(outbuf
,6,0,True
);
2239 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2241 if (nwritten
< smb_dsize
) {
2242 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2243 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2246 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2247 fsp
->fnum
, smb_dsize
, nwritten
));
2251 if (lp_syncalways(SNUM(conn
)) || write_through
)
2252 sync_file(conn
,fsp
);
2254 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2258 /****************************************************************************
2260 ****************************************************************************/
2261 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2267 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
2269 CHECK_FSP(fsp
,conn
);
2272 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2273 startpos
= IVAL(inbuf
,smb_vwv2
);
2277 case 0: umode
= SEEK_SET
; break;
2278 case 1: umode
= SEEK_CUR
; break;
2279 case 2: umode
= SEEK_END
; break;
2281 umode
= SEEK_SET
; break;
2284 res
= lseek(fsp
->fd_ptr
->fd
,startpos
,umode
);
2287 outsize
= set_message(outbuf
,2,0,True
);
2288 SIVALS(outbuf
,smb_vwv0
,res
);
2290 DEBUG(3,("lseek fnum=%d ofs=%d mode=%d\n",
2291 fsp
->fnum
, startpos
, mode
));
2297 /****************************************************************************
2299 ****************************************************************************/
2300 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2302 int outsize
= set_message(outbuf
,0,0,True
);
2303 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
2306 CHECK_FSP(fsp
,conn
);
2311 file_sync_all(conn
);
2313 sync_file(conn
,fsp
);
2316 DEBUG(3,("flush\n"));
2321 /****************************************************************************
2323 ****************************************************************************/
2324 int reply_exit(connection_struct
*conn
,
2325 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2327 int outsize
= set_message(outbuf
,0,0,True
);
2328 DEBUG(3,("exit\n"));
2334 /****************************************************************************
2335 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2336 ****************************************************************************/
2337 int reply_close(connection_struct
*conn
,
2338 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2342 int32 eclass
= 0, err
= 0;
2343 files_struct
*fsp
= NULL
;
2345 outsize
= set_message(outbuf
,0,0,True
);
2347 /* If it's an IPC, pass off to the pipe handler. */
2349 return reply_pipe_close(conn
, inbuf
,outbuf
);
2352 fsp
= GETFSP(inbuf
,smb_vwv0
);
2355 * We can only use CHECK_FSP if we know it's not a directory.
2358 if(!(fsp
&& fsp
->open
&& fsp
->is_directory
))
2359 CHECK_FSP(fsp
,conn
);
2361 if(HAS_CACHED_ERROR(fsp
)) {
2362 eclass
= fsp
->wbmpx_ptr
->wr_errclass
;
2363 err
= fsp
->wbmpx_ptr
->wr_error
;
2366 if(fsp
->is_directory
) {
2368 * Special case - close NT SMB directory
2371 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
2372 close_directory(fsp
);
2375 * Close ordinary file.
2377 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2379 /* try and set the date */
2380 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2382 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2383 fsp
->fd_ptr
->fd
, fsp
->fnum
,
2384 conn
->num_files_open
));
2386 close_file(fsp
,True
);
2389 /* We have a cached error */
2391 return(ERROR(eclass
,err
));
2397 /****************************************************************************
2398 reply to a writeclose (Core+ protocol)
2399 ****************************************************************************/
2400 int reply_writeclose(connection_struct
*conn
,
2401 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2409 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
2411 CHECK_FSP(fsp
,conn
);
2415 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2416 startpos
= IVAL(inbuf
,smb_vwv2
);
2417 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2418 data
= smb_buf(inbuf
) + 1;
2420 if (is_locked(fsp
,conn
,numtowrite
,startpos
, F_WRLCK
))
2421 return(ERROR(ERRDOS
,ERRlock
));
2423 seek_file(fsp
,startpos
);
2425 nwritten
= write_file(fsp
,data
,numtowrite
);
2427 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2429 close_file(fsp
,True
);
2431 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2432 fsp
->fnum
, numtowrite
, nwritten
,
2433 conn
->num_files_open
));
2436 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2438 outsize
= set_message(outbuf
,1,0,True
);
2440 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2445 /****************************************************************************
2447 ****************************************************************************/
2448 int reply_lock(connection_struct
*conn
,
2449 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2451 int outsize
= set_message(outbuf
,0,0,True
);
2452 uint32 count
,offset
;
2455 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
2457 CHECK_FSP(fsp
,conn
);
2460 count
= IVAL(inbuf
,smb_vwv1
);
2461 offset
= IVAL(inbuf
,smb_vwv3
);
2463 DEBUG(3,("lock fd=%d fnum=%d ofs=%d cnt=%d\n",
2464 fsp
->fd_ptr
->fd
, fsp
->fnum
, offset
, count
));
2466 if (!do_lock(fsp
, conn
, count
, offset
, F_WRLCK
, &eclass
, &ecode
))
2467 return (ERROR(eclass
,ecode
));
2473 /****************************************************************************
2475 ****************************************************************************/
2476 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2478 int outsize
= set_message(outbuf
,0,0,True
);
2479 uint32 count
,offset
;
2482 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
2484 CHECK_FSP(fsp
,conn
);
2487 count
= IVAL(inbuf
,smb_vwv1
);
2488 offset
= IVAL(inbuf
,smb_vwv3
);
2490 if(!do_unlock(fsp
, conn
, count
, offset
, &eclass
, &ecode
))
2491 return (ERROR(eclass
,ecode
));
2493 DEBUG( 3, ( "unlock fd=%d fnum=%d ofs=%d cnt=%d\n",
2494 fsp
->fd_ptr
->fd
, fsp
->fnum
, offset
, count
) );
2500 /****************************************************************************
2502 ****************************************************************************/
2503 int reply_tdis(connection_struct
*conn
,
2504 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2506 int outsize
= set_message(outbuf
,0,0,True
);
2509 vuid
= SVAL(inbuf
,smb_uid
);
2512 DEBUG(4,("Invalid connection in tdis\n"));
2513 return(ERROR(ERRSRV
,ERRinvnid
));
2518 close_cnum(conn
,vuid
);
2525 /****************************************************************************
2527 ****************************************************************************/
2528 int reply_echo(connection_struct
*conn
,
2529 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2531 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2533 int data_len
= smb_buflen(inbuf
);
2534 int outsize
= set_message(outbuf
,1,data_len
,True
);
2536 /* copy any incoming data back out */
2538 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2540 if (smb_reverb
> 100) {
2541 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2545 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2546 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2548 smb_setlen(outbuf
,outsize
- 4);
2550 send_smb(Client
,outbuf
);
2553 DEBUG(3,("echo %d times\n", smb_reverb
));
2559 /****************************************************************************
2560 reply to a printopen
2561 ****************************************************************************/
2562 int reply_printopen(connection_struct
*conn
,
2563 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2570 *fname
= *fname2
= 0;
2572 if (!CAN_PRINT(conn
))
2573 return(ERROR(ERRDOS
,ERRnoaccess
));
2578 pstrcpy(s
,smb_buf(inbuf
)+1);
2581 if (!(isalnum((int)*p
) || strchr("._-",*p
)))
2586 if (strlen(s
) > 10) s
[10] = 0;
2588 slprintf(fname
,sizeof(fname
)-1, "%s.XXXXXX",s
);
2593 return(ERROR(ERRSRV
,ERRnofids
));
2595 pstrcpy(fname2
,(char *)mktemp(fname
));
2597 if (!check_name(fname2
,conn
)) {
2599 return(ERROR(ERRDOS
,ERRnoaccess
));
2602 /* Open for exclusive use, write only. */
2603 open_file_shared(fsp
,conn
,fname2
,
2604 (DENY_ALL
<<4)|1, 0x12, unix_mode(conn
,0),
2609 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2612 /* force it to be a print file */
2613 fsp
->print_file
= True
;
2615 outsize
= set_message(outbuf
,1,0,True
);
2616 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2618 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2619 fname2
, fsp
->fd_ptr
->fd
, fsp
->fnum
));
2625 /****************************************************************************
2626 reply to a printclose
2627 ****************************************************************************/
2628 int reply_printclose(connection_struct
*conn
,
2629 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2631 int outsize
= set_message(outbuf
,0,0,True
);
2632 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
2634 CHECK_FSP(fsp
,conn
);
2637 if (!CAN_PRINT(conn
))
2638 return(ERROR(ERRDOS
,ERRnoaccess
));
2640 DEBUG(3,("printclose fd=%d fnum=%d\n",
2641 fsp
->fd_ptr
->fd
,fsp
->fnum
));
2643 close_file(fsp
,True
);
2649 /****************************************************************************
2650 reply to a printqueue
2651 ****************************************************************************/
2652 int reply_printqueue(connection_struct
*conn
,
2653 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2655 int outsize
= set_message(outbuf
,2,3,True
);
2656 int max_count
= SVAL(inbuf
,smb_vwv0
);
2657 int start_index
= SVAL(inbuf
,smb_vwv1
);
2660 vuid
= SVAL(inbuf
,smb_uid
);
2662 /* we used to allow the client to get the cnum wrong, but that
2663 is really quite gross and only worked when there was only
2664 one printer - I think we should now only accept it if they
2665 get it right (tridge) */
2666 if (!CAN_PRINT(conn
))
2667 return(ERROR(ERRDOS
,ERRnoaccess
));
2669 SSVAL(outbuf
,smb_vwv0
,0);
2670 SSVAL(outbuf
,smb_vwv1
,0);
2671 CVAL(smb_buf(outbuf
),0) = 1;
2672 SSVAL(smb_buf(outbuf
),1,0);
2674 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2675 start_index
, max_count
));
2678 print_queue_struct
*queue
= NULL
;
2679 char *p
= smb_buf(outbuf
) + 3;
2680 int count
= get_printqueue(SNUM(conn
), conn
,&queue
,NULL
);
2681 int num_to_get
= ABS(max_count
);
2682 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
2688 num_to_get
= MIN(num_to_get
,count
-first
);
2691 for (i
=first
;i
<first
+num_to_get
;i
++) {
2692 put_dos_date2(p
,0,queue
[i
].time
);
2693 CVAL(p
,4) = (queue
[i
].status
==LPQ_PRINTING
?2:3);
2694 SSVAL(p
,5,printjob_encode(SNUM(conn
),
2696 SIVAL(p
,7,queue
[i
].size
);
2698 StrnCpy(p
+12,queue
[i
].user
,16);
2703 outsize
= set_message(outbuf
,2,28*count
+3,False
);
2704 SSVAL(outbuf
,smb_vwv0
,count
);
2705 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
2706 CVAL(smb_buf(outbuf
),0) = 1;
2707 SSVAL(smb_buf(outbuf
),1,28*count
);
2710 if (queue
) free(queue
);
2712 DEBUG(3,("%d entries returned in queue\n",count
));
2719 /****************************************************************************
2720 reply to a printwrite
2721 ****************************************************************************/
2722 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2725 int outsize
= set_message(outbuf
,0,0,True
);
2727 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
2729 if (!CAN_PRINT(conn
))
2730 return(ERROR(ERRDOS
,ERRnoaccess
));
2732 CHECK_FSP(fsp
,conn
);
2736 numtowrite
= SVAL(smb_buf(inbuf
),1);
2737 data
= smb_buf(inbuf
) + 3;
2739 if (write_file(fsp
,data
,numtowrite
) != numtowrite
)
2740 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2742 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
2748 /****************************************************************************
2750 ****************************************************************************/
2751 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2754 int outsize
,ret
= -1;
2755 BOOL bad_path
= False
;
2757 pstrcpy(directory
,smb_buf(inbuf
) + 1);
2758 unix_convert(directory
,conn
,0,&bad_path
);
2760 if (check_name(directory
, conn
))
2761 ret
= sys_mkdir(directory
,unix_mode(conn
,aDIR
));
2765 if((errno
== ENOENT
) && bad_path
)
2767 unix_ERR_class
= ERRDOS
;
2768 unix_ERR_code
= ERRbadpath
;
2770 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2773 outsize
= set_message(outbuf
,0,0,True
);
2775 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, ret
) );
2780 /****************************************************************************
2781 Static function used by reply_rmdir to delete an entire directory
2783 ****************************************************************************/
2784 static BOOL
recursive_rmdir(char *directory
)
2788 void *dirptr
= OpenDir(NULL
, directory
, False
);
2793 while((dname
= ReadDirName(dirptr
)))
2798 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2801 /* Construct the full name. */
2802 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
2808 pstrcpy(fullname
, directory
);
2809 pstrcat(fullname
, "/");
2810 pstrcat(fullname
, dname
);
2812 if(sys_lstat(fullname
, &st
) != 0)
2818 if(st
.st_mode
& S_IFDIR
)
2820 if(recursive_rmdir(fullname
)!=0)
2825 if(sys_rmdir(fullname
) != 0)
2831 else if(sys_unlink(fullname
) != 0)
2841 /****************************************************************************
2843 ****************************************************************************/
2844 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2849 BOOL bad_path
= False
;
2851 pstrcpy(directory
,smb_buf(inbuf
) + 1);
2852 unix_convert(directory
,conn
, NULL
,&bad_path
);
2854 if (check_name(directory
,conn
))
2857 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
2858 ok
= (sys_rmdir(directory
) == 0);
2859 if(!ok
&& (errno
== ENOTEMPTY
) && lp_veto_files(SNUM(conn
)))
2861 /* Check to see if the only thing in this directory are
2862 vetoed files/directories. If so then delete them and
2863 retry. If we fail to delete any of them (and we *don't*
2864 do a recursive delete) then fail the rmdir. */
2865 BOOL all_veto_files
= True
;
2867 void *dirptr
= OpenDir(conn
, directory
, False
);
2871 int dirpos
= TellDir(dirptr
);
2872 while ((dname
= ReadDirName(dirptr
)))
2874 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2876 if(!IS_VETO_PATH(conn
, dname
))
2878 all_veto_files
= False
;
2884 SeekDir(dirptr
,dirpos
);
2885 while ((dname
= ReadDirName(dirptr
)))
2890 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2893 /* Construct the full name. */
2894 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
2899 pstrcpy(fullname
, directory
);
2900 pstrcat(fullname
, "/");
2901 pstrcat(fullname
, dname
);
2903 if(sys_lstat(fullname
, &st
) != 0)
2905 if(st
.st_mode
& S_IFDIR
)
2907 if(lp_recursive_veto_delete(SNUM(conn
)))
2909 if(recursive_rmdir(fullname
) != 0)
2912 if(sys_rmdir(fullname
) != 0)
2915 else if(sys_unlink(fullname
) != 0)
2919 /* Retry the rmdir */
2920 ok
= (sys_rmdir(directory
) == 0);
2930 DEBUG(3,("couldn't remove directory %s : %s\n",
2931 directory
,strerror(errno
)));
2936 if((errno
== ENOENT
) && bad_path
)
2938 unix_ERR_class
= ERRDOS
;
2939 unix_ERR_code
= ERRbadpath
;
2941 return(UNIXERROR(ERRDOS
,ERRbadpath
));
2944 outsize
= set_message(outbuf
,0,0,True
);
2946 DEBUG( 3, ( "rmdir %s\n", directory
) );
2952 /*******************************************************************
2953 resolve wildcards in a filename rename
2954 ********************************************************************/
2955 static BOOL
resolve_wildcards(char *name1
,char *name2
)
2957 fstring root1
,root2
;
2961 name1
= strrchr(name1
,'/');
2962 name2
= strrchr(name2
,'/');
2964 if (!name1
|| !name2
) return(False
);
2966 fstrcpy(root1
,name1
);
2967 fstrcpy(root2
,name2
);
2968 p
= strrchr(root1
,'.');
2975 p
= strrchr(root2
,'.');
3007 pstrcpy(name2
,root2
);
3010 pstrcat(name2
,ext2
);
3016 /*******************************************************************
3017 check if a user is allowed to rename a file
3018 ********************************************************************/
3019 static BOOL
can_rename(char *fname
,connection_struct
*conn
)
3023 if (!CAN_WRITE(conn
)) return(False
);
3025 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
3026 if (!check_file_sharing(conn
,fname
,True
)) return(False
);
3031 /****************************************************************************
3032 The guts of the rename command, split out so it may be called by the NT SMB
3034 ****************************************************************************/
3035 int rename_internals(connection_struct
*conn
,
3036 char *inbuf
, char *outbuf
, char *name
,
3037 char *newname
, BOOL replace_if_exists
)
3041 pstring newname_last_component
;
3044 BOOL bad_path1
= False
;
3045 BOOL bad_path2
= False
;
3047 int error
= ERRnoaccess
;
3050 *directory
= *mask
= 0;
3052 unix_convert(name
,conn
,0,&bad_path1
);
3053 unix_convert(newname
,conn
,newname_last_component
,&bad_path2
);
3056 * Split the old name into directory and last component
3057 * strings. Note that unix_convert may have stripped off a
3058 * leading ./ from both name and newname if the rename is
3059 * at the root of the share. We need to make sure either both
3060 * name and newname contain a / character or neither of them do
3061 * as this is checked in resolve_wildcards().
3064 p
= strrchr(name
,'/');
3066 pstrcpy(directory
,".");
3070 pstrcpy(directory
,name
);
3072 *p
= '/'; /* Replace needed for exceptional test below. */
3075 if (is_mangled(mask
))
3076 check_mangled_cache( mask
);
3078 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
3082 * No wildcards - just process the one file.
3084 BOOL is_short_name
= is_8_3(name
, True
);
3086 /* Add a terminating '/' to the directory name. */
3087 pstrcat(directory
,"/");
3088 pstrcat(directory
,mask
);
3090 /* Ensure newname contains a '/' also */
3091 if(strrchr(newname
,'/') == 0) {
3094 pstrcpy(tmpstr
, "./");
3095 pstrcat(tmpstr
, newname
);
3096 pstrcpy(newname
, tmpstr
);
3099 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",
3100 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3101 newname
, newname_last_component
, is_short_name
));
3104 * Check for special case with case preserving and not
3105 * case sensitive, if directory and newname are identical,
3106 * and the old last component differs from the original
3107 * last component only by case, then we should allow
3108 * the rename (user is trying to change the case of the
3111 if((case_sensitive
== False
) &&
3112 (((case_preserve
== True
) &&
3113 (is_short_name
== False
)) ||
3114 ((short_case_preserve
== True
) &&
3115 (is_short_name
== True
))) &&
3116 strcsequal(directory
, newname
)) {
3117 pstring newname_modified_last_component
;
3120 * Get the last component of the modified name.
3121 * Note that we guarantee that newname contains a '/'
3124 p
= strrchr(newname
,'/');
3125 pstrcpy(newname_modified_last_component
,p
+1);
3127 if(strcsequal(newname_modified_last_component
,
3128 newname_last_component
) == False
) {
3130 * Replace the modified last component with
3133 pstrcpy(p
+1, newname_last_component
);
3137 if(replace_if_exists
) {
3139 * NT SMB specific flag - rename can overwrite
3140 * file with the same name so don't check for
3143 if(resolve_wildcards(directory
,newname
) &&
3144 can_rename(directory
,conn
) &&
3145 !sys_rename(directory
,newname
))
3148 if (resolve_wildcards(directory
,newname
) &&
3149 can_rename(directory
,conn
) &&
3150 !file_exist(newname
,NULL
) &&
3151 !sys_rename(directory
,newname
))
3155 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count
!= 0) ? "succeeded" : "failed",
3156 directory
,newname
));
3158 if (!count
) exists
= file_exist(directory
,NULL
);
3159 if (!count
&& exists
&& file_exist(newname
,NULL
)) {
3165 * Wildcards - process each file that matches.
3167 void *dirptr
= NULL
;
3171 if (check_name(directory
,conn
))
3172 dirptr
= OpenDir(conn
, directory
, True
);
3177 if (strequal(mask
,"????????.???"))
3180 while ((dname
= ReadDirName(dirptr
))) {
3182 pstrcpy(fname
,dname
);
3184 if(!mask_match(fname
, mask
, case_sensitive
, False
))
3187 error
= ERRnoaccess
;
3188 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3189 if (!can_rename(fname
,conn
)) {
3190 DEBUG(6,("rename %s refused\n", fname
));
3193 pstrcpy(destname
,newname
);
3195 if (!resolve_wildcards(fname
,destname
)) {
3196 DEBUG(6,("resolve_wildcards %s %s failed\n", fname
, destname
));
3200 if (!replace_if_exists
&& file_exist(destname
,NULL
)) {
3201 DEBUG(6,("file_exist %s\n", destname
));
3206 if (!sys_rename(fname
,destname
))
3208 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3216 return(ERROR(ERRDOS
,error
));
3218 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
)) {
3219 unix_ERR_class
= ERRDOS
;
3220 unix_ERR_code
= ERRbadpath
;
3222 return(UNIXERROR(ERRDOS
,error
));
3229 /****************************************************************************
3231 ****************************************************************************/
3233 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3239 pstrcpy(name
,smb_buf(inbuf
) + 1);
3240 pstrcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
3242 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3244 outsize
= rename_internals(conn
, inbuf
, outbuf
, name
, newname
, False
);
3246 outsize
= set_message(outbuf
,0,0,True
);
3251 /*******************************************************************
3252 copy a file as part of a reply_copy
3253 ******************************************************************/
3254 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3255 int count
,BOOL target_is_directory
)
3260 files_struct
*fsp1
,*fsp2
;
3263 pstrcpy(dest
,dest1
);
3264 if (target_is_directory
) {
3265 char *p
= strrchr(src
,'/');
3274 if (!file_exist(src
,&st
)) return(False
);
3277 if (!fsp1
) return(False
);
3278 open_file_shared(fsp1
,conn
,src
,(DENY_NONE
<<4),
3279 1,0,0,&Access
,&action
);
3282 fsp1
->reserved
= False
;
3286 if (!target_is_directory
&& count
)
3291 close_file(fsp1
,False
);
3294 open_file_shared(fsp2
,conn
,dest
,(DENY_NONE
<<4)|1,
3295 ofun
,st
.st_mode
,0,&Access
,&action
);
3298 close_file(fsp1
,False
);
3299 fsp2
->reserved
= False
;
3303 if ((ofun
&3) == 1) {
3304 lseek(fsp2
->fd_ptr
->fd
,0,SEEK_END
);
3308 ret
= transfer_file(fsp1
->fd_ptr
->fd
,
3309 fsp2
->fd_ptr
->fd
,st
.st_size
,NULL
,0,0);
3311 close_file(fsp1
,False
);
3312 close_file(fsp2
,False
);
3314 return(ret
== st
.st_size
);
3319 /****************************************************************************
3320 reply to a file copy.
3321 ****************************************************************************/
3322 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3327 pstring mask
,newname
;
3330 int error
= ERRnoaccess
;
3333 int tid2
= SVAL(inbuf
,smb_vwv0
);
3334 int ofun
= SVAL(inbuf
,smb_vwv1
);
3335 int flags
= SVAL(inbuf
,smb_vwv2
);
3336 BOOL target_is_directory
=False
;
3337 BOOL bad_path1
= False
;
3338 BOOL bad_path2
= False
;
3340 *directory
= *mask
= 0;
3342 pstrcpy(name
,smb_buf(inbuf
));
3343 pstrcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
3345 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
3347 if (tid2
!= conn
->cnum
) {
3348 /* can't currently handle inter share copies XXXX */
3349 DEBUG(3,("Rejecting inter-share copy\n"));
3350 return(ERROR(ERRSRV
,ERRinvdevice
));
3353 unix_convert(name
,conn
,0,&bad_path1
);
3354 unix_convert(newname
,conn
,0,&bad_path2
);
3356 target_is_directory
= directory_exist(newname
,NULL
);
3358 if ((flags
&1) && target_is_directory
) {
3359 return(ERROR(ERRDOS
,ERRbadfile
));
3362 if ((flags
&2) && !target_is_directory
) {
3363 return(ERROR(ERRDOS
,ERRbadpath
));
3366 if ((flags
&(1<<5)) && directory_exist(name
,NULL
)) {
3367 /* wants a tree copy! XXXX */
3368 DEBUG(3,("Rejecting tree copy\n"));
3369 return(ERROR(ERRSRV
,ERRerror
));
3372 p
= strrchr(name
,'/');
3374 pstrcpy(directory
,"./");
3378 pstrcpy(directory
,name
);
3382 if (is_mangled(mask
))
3383 check_mangled_cache( mask
);
3385 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
3388 pstrcat(directory
,"/");
3389 pstrcat(directory
,mask
);
3390 if (resolve_wildcards(directory
,newname
) &&
3391 copy_file(directory
,newname
,conn
,ofun
,
3392 count
,target_is_directory
)) count
++;
3393 if (!count
) exists
= file_exist(directory
,NULL
);
3395 void *dirptr
= NULL
;
3399 if (check_name(directory
,conn
))
3400 dirptr
= OpenDir(conn
, directory
, True
);
3406 if (strequal(mask
,"????????.???"))
3409 while ((dname
= ReadDirName(dirptr
)))
3412 pstrcpy(fname
,dname
);
3414 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
3416 error
= ERRnoaccess
;
3417 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
3418 pstrcpy(destname
,newname
);
3419 if (resolve_wildcards(fname
,destname
) &&
3420 copy_file(directory
,newname
,conn
,ofun
,
3421 count
,target_is_directory
)) count
++;
3422 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
3430 return(ERROR(ERRDOS
,error
));
3433 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
3435 unix_ERR_class
= ERRDOS
;
3436 unix_ERR_code
= ERRbadpath
;
3438 return(UNIXERROR(ERRDOS
,error
));
3442 outsize
= set_message(outbuf
,1,0,True
);
3443 SSVAL(outbuf
,smb_vwv0
,count
);
3450 /****************************************************************************
3452 ****************************************************************************/
3453 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3461 if (!CAN_SETDIR(snum
))
3462 return(ERROR(ERRDOS
,ERRnoaccess
));
3464 pstrcpy(newdir
,smb_buf(inbuf
) + 1);
3467 if (strlen(newdir
) == 0) {
3470 ok
= directory_exist(newdir
,NULL
);
3472 string_set(&conn
->connectpath
,newdir
);
3477 return(ERROR(ERRDOS
,ERRbadpath
));
3479 outsize
= set_message(outbuf
,0,0,True
);
3480 CVAL(outbuf
,smb_reh
) = CVAL(inbuf
,smb_reh
);
3482 DEBUG(3,("setdir %s\n", newdir
));
3488 /****************************************************************************
3489 reply to a lockingX request
3490 ****************************************************************************/
3491 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
3493 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv2
);
3494 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
3496 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
3498 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
3499 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
3500 uint32 count
, offset
;
3501 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
3504 uint32 ecode
=0, dummy2
;
3505 int eclass
=0, dummy1
;
3507 CHECK_FSP(fsp
,conn
);
3510 data
= smb_buf(inbuf
);
3512 /* Check if this is an oplock break on a file
3513 we have granted an oplock on.
3515 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
))
3518 uint32 dev
= fsp
->fd_ptr
->dev
;
3519 uint32 inode
= fsp
->fd_ptr
->inode
;
3521 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3524 * Make sure we have granted an oplock on this file.
3526 if(!fsp
->granted_oplock
)
3528 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3529 no oplock granted on this file.\n", fsp
->fnum
));
3530 return ERROR(ERRDOS
,ERRlock
);
3533 /* Remove the oplock flag from the sharemode. */
3534 lock_share_entry(fsp
->conn
, dev
, inode
, &token
);
3535 if(remove_share_oplock(fsp
, token
)==False
) {
3536 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3537 dev = %x, inode = %x\n",
3538 fsp
->fnum
, dev
, inode
));
3539 unlock_share_entry(fsp
->conn
, dev
, inode
, token
);
3541 unlock_share_entry(fsp
->conn
, dev
, inode
, token
);
3543 /* Clear the granted flag and return. */
3544 fsp
->granted_oplock
= False
;
3547 /* if this is a pure oplock break request then don't send a reply */
3548 if (num_locks
== 0 && num_ulocks
== 0)
3550 /* Sanity check - ensure a pure oplock break is not a
3552 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
3553 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3554 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
3559 /* Data now points at the beginning of the list
3560 of smb_unlkrng structs */
3561 for(i
= 0; i
< (int)num_ulocks
; i
++) {
3562 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3563 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3564 if(!do_unlock(fsp
,conn
,count
,offset
,&eclass
, &ecode
))
3565 return ERROR(eclass
,ecode
);
3568 /* Setup the timeout in seconds. */
3569 lock_timeout
= ((lock_timeout
== -1) ? -1 : lock_timeout
/1000);
3571 /* Now do any requested locks */
3572 data
+= 10*num_ulocks
;
3573 /* Data now points at the beginning of the list
3574 of smb_lkrng structs */
3575 for(i
= 0; i
< (int)num_locks
; i
++) {
3576 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3577 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3578 if(!do_lock(fsp
,conn
,count
,offset
, ((locktype
& 1) ? F_RDLCK
: F_WRLCK
),
3580 #if 0 /* JRATEST - blocking lock code. */
3581 if((ecode
== ERRlock
) && (lock_timeout
!= 0)) {
3583 * A blocking lock was requested. Package up
3584 * this smb into a queued request and push it
3585 * onto the blocking lock queue.
3587 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
))
3589 #endif /* JRATEST */
3593 /* If any of the above locks failed, then we must unlock
3594 all of the previous locks (X/Open spec). */
3595 if(i
!= num_locks
&& num_locks
!= 0) {
3596 for(; i
>= 0; i
--) {
3597 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3598 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3599 do_unlock(fsp
,conn
,count
,offset
,&dummy1
,&dummy2
);
3601 return ERROR(eclass
,ecode
);
3604 set_message(outbuf
,2,0,True
);
3606 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3607 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
3611 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
3615 /****************************************************************************
3616 reply to a SMBreadbmpx (read block multiplex) request
3617 ****************************************************************************/
3618 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
3624 int outsize
, mincount
, maxcount
;
3628 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
3630 /* this function doesn't seem to work - disable by default */
3632 return(ERROR(ERRSRV
,ERRuseSTD
));
3634 outsize
= set_message(outbuf
,8,0,True
);
3636 CHECK_FSP(fsp
,conn
);
3640 startpos
= IVAL(inbuf
,smb_vwv1
);
3641 maxcount
= SVAL(inbuf
,smb_vwv3
);
3642 mincount
= SVAL(inbuf
,smb_vwv4
);
3644 data
= smb_buf(outbuf
);
3645 pad
= ((long)data
)%4;
3646 if (pad
) pad
= 4 - pad
;
3649 max_per_packet
= bufsize
-(outsize
+pad
);
3653 if (is_locked(fsp
,conn
,maxcount
,startpos
, F_RDLCK
))
3654 return(ERROR(ERRDOS
,ERRlock
));
3658 int N
= MIN(max_per_packet
,tcount
-total_read
);
3660 nread
= read_file(fsp
,data
,startpos
,N
);
3662 if (nread
<= 0) nread
= 0;
3665 tcount
= total_read
+ nread
;
3667 set_message(outbuf
,8,nread
,False
);
3668 SIVAL(outbuf
,smb_vwv0
,startpos
);
3669 SSVAL(outbuf
,smb_vwv2
,tcount
);
3670 SSVAL(outbuf
,smb_vwv6
,nread
);
3671 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
3673 send_smb(Client
,outbuf
);
3675 total_read
+= nread
;
3678 while (total_read
< tcount
);
3684 /****************************************************************************
3685 reply to a SMBwritebmpx (write block multiplex primary) request
3686 ****************************************************************************/
3687 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3693 int tcount
, write_through
, smb_doff
;
3695 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
3697 CHECK_FSP(fsp
,conn
);
3701 tcount
= SVAL(inbuf
,smb_vwv1
);
3702 startpos
= IVAL(inbuf
,smb_vwv3
);
3703 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
3704 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3705 smb_doff
= SVAL(inbuf
,smb_vwv11
);
3707 data
= smb_base(inbuf
) + smb_doff
;
3709 /* If this fails we need to send an SMBwriteC response,
3710 not an SMBwritebmpx - set this up now so we don't forget */
3711 CVAL(outbuf
,smb_com
) = SMBwritec
;
3713 if (is_locked(fsp
,conn
,tcount
,startpos
,F_WRLCK
))
3714 return(ERROR(ERRDOS
,ERRlock
));
3716 seek_file(fsp
,startpos
);
3717 nwritten
= write_file(fsp
,data
,numtowrite
);
3719 if(lp_syncalways(SNUM(conn
)) || write_through
)
3720 sync_file(conn
,fsp
);
3722 if(nwritten
< numtowrite
)
3723 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3725 /* If the maximum to be written to this file
3726 is greater than what we just wrote then set
3727 up a secondary struct to be attached to this
3728 fd, we will use this to cache error messages etc. */
3729 if(tcount
> nwritten
)
3731 write_bmpx_struct
*wbms
;
3732 if(fsp
->wbmpx_ptr
!= NULL
)
3733 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
3735 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
3738 DEBUG(0,("Out of memory in reply_readmpx\n"));
3739 return(ERROR(ERRSRV
,ERRnoresource
));
3741 wbms
->wr_mode
= write_through
;
3742 wbms
->wr_discard
= False
; /* No errors yet */
3743 wbms
->wr_total_written
= nwritten
;
3744 wbms
->wr_errclass
= 0;
3746 fsp
->wbmpx_ptr
= wbms
;
3749 /* We are returning successfully, set the message type back to
3751 CVAL(outbuf
,smb_com
) = SMBwriteBmpx
;
3753 outsize
= set_message(outbuf
,1,0,True
);
3755 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
3757 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3758 fsp
->fnum
, numtowrite
, nwritten
) );
3760 if (write_through
&& tcount
==nwritten
) {
3761 /* we need to send both a primary and a secondary response */
3762 smb_setlen(outbuf
,outsize
- 4);
3763 send_smb(Client
,outbuf
);
3765 /* now the secondary */
3766 outsize
= set_message(outbuf
,1,0,True
);
3767 CVAL(outbuf
,smb_com
) = SMBwritec
;
3768 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3775 /****************************************************************************
3776 reply to a SMBwritebs (write block multiplex secondary) request
3777 ****************************************************************************/
3778 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3784 int tcount
, write_through
, smb_doff
;
3786 write_bmpx_struct
*wbms
;
3787 BOOL send_response
= False
;
3788 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
3790 CHECK_FSP(fsp
,conn
);
3793 tcount
= SVAL(inbuf
,smb_vwv1
);
3794 startpos
= IVAL(inbuf
,smb_vwv2
);
3795 numtowrite
= SVAL(inbuf
,smb_vwv6
);
3796 smb_doff
= SVAL(inbuf
,smb_vwv7
);
3798 data
= smb_base(inbuf
) + smb_doff
;
3800 /* We need to send an SMBwriteC response, not an SMBwritebs */
3801 CVAL(outbuf
,smb_com
) = SMBwritec
;
3803 /* This fd should have an auxiliary struct attached,
3804 check that it does */
3805 wbms
= fsp
->wbmpx_ptr
;
3806 if(!wbms
) return(-1);
3808 /* If write through is set we can return errors, else we must
3810 write_through
= wbms
->wr_mode
;
3812 /* Check for an earlier error */
3813 if(wbms
->wr_discard
)
3814 return -1; /* Just discard the packet */
3816 seek_file(fsp
,startpos
);
3817 nwritten
= write_file(fsp
,data
,numtowrite
);
3819 if(lp_syncalways(SNUM(conn
)) || write_through
)
3820 sync_file(conn
,fsp
);
3822 if (nwritten
< numtowrite
)
3825 /* We are returning an error - we can delete the aux struct */
3826 if (wbms
) free((char *)wbms
);
3827 fsp
->wbmpx_ptr
= NULL
;
3828 return(ERROR(ERRHRD
,ERRdiskfull
));
3830 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
3833 /* Increment the total written, if this matches tcount
3834 we can discard the auxiliary struct (hurrah !) and return a writeC */
3835 wbms
->wr_total_written
+= nwritten
;
3836 if(wbms
->wr_total_written
>= tcount
)
3838 if (write_through
) {
3839 outsize
= set_message(outbuf
,1,0,True
);
3840 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
3841 send_response
= True
;
3845 fsp
->wbmpx_ptr
= NULL
;
3855 /****************************************************************************
3856 reply to a SMBsetattrE
3857 ****************************************************************************/
3858 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3860 struct utimbuf unix_times
;
3862 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
3864 outsize
= set_message(outbuf
,0,0,True
);
3866 CHECK_FSP(fsp
,conn
);
3869 /* Convert the DOS times into unix times. Ignore create
3870 time as UNIX can't set this.
3872 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
3873 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
3876 * Patch from Ray Frush <frush@engr.colostate.edu>
3877 * Sometimes times are sent as zero - ignore them.
3880 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0))
3882 /* Ignore request */
3885 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
3886 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
3890 else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0))
3892 /* set modify time = to access time if modify time was 0 */
3893 unix_times
.modtime
= unix_times
.actime
;
3896 /* Set the date on this file */
3897 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
))
3898 return(ERROR(ERRDOS
,ERRnoaccess
));
3900 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
3901 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
3907 /****************************************************************************
3908 reply to a SMBgetattrE
3909 ****************************************************************************/
3910 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3915 files_struct
*fsp
= GETFSP(inbuf
,smb_vwv0
);
3917 outsize
= set_message(outbuf
,11,0,True
);
3919 CHECK_FSP(fsp
,conn
);
3922 /* Do an fstat on this file */
3923 if(fstat(fsp
->fd_ptr
->fd
, &sbuf
))
3924 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3926 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
3928 /* Convert the times into dos times. Set create
3929 date to be last modify date as UNIX doesn't save
3931 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
3932 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
3933 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
3936 SIVAL(outbuf
,smb_vwv6
,0);
3937 SIVAL(outbuf
,smb_vwv8
,0);
3941 SIVAL(outbuf
,smb_vwv6
,sbuf
.st_size
);
3942 SIVAL(outbuf
,smb_vwv8
,ROUNDUP(sbuf
.st_size
,1024));
3944 SSVAL(outbuf
,smb_vwv10
, mode
);
3946 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));