if we are adding a new sambaAccount, make sure that we add a
[Samba.git] / source / smbd / reply.c
blob50b31d7d6810e272924b3af2d956482a4e2cdb8e
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
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
27 #include "includes.h"
29 /* look in server.c for some explanation of these variables */
30 extern int Protocol;
31 extern int max_send;
32 extern int max_recv;
33 extern char magic_char;
34 extern BOOL case_sensitive;
35 extern BOOL case_preserve;
36 extern BOOL short_case_preserve;
37 extern userdom_struct current_user_info;
38 extern pstring global_myname;
39 extern fstring global_myworkgroup;
40 extern int global_oplock_break;
41 uint32 global_client_caps = 0;
42 unsigned int smb_echo_count = 0;
44 /****************************************************************************
45 report a possible attack via the password buffer overflow bug
46 ****************************************************************************/
48 static void overflow_attack(int len)
50 if( DEBUGLVL( 0 ) ) {
51 dbgtext( "ERROR: Invalid password length %d.\n", len );
52 dbgtext( "Your machine may be under attack by someone " );
53 dbgtext( "attempting to exploit an old bug.\n" );
54 dbgtext( "Attack was from IP = %s.\n", client_addr() );
59 /****************************************************************************
60 reply to an special message
61 ****************************************************************************/
63 int reply_special(char *inbuf,char *outbuf)
65 int outsize = 4;
66 int msg_type = CVAL(inbuf,0);
67 int msg_flags = CVAL(inbuf,1);
68 pstring name1,name2;
69 extern fstring remote_machine;
70 extern fstring local_machine;
71 int len;
72 char name_type = 0;
74 *name1 = *name2 = 0;
76 memset(outbuf,'\0',smb_size);
78 smb_setlen(outbuf,0);
80 switch (msg_type) {
81 case 0x81: /* session request */
82 SCVAL(outbuf,0,0x82);
83 SCVAL(outbuf,3,0);
84 if (name_len(inbuf+4) > 50 ||
85 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
86 DEBUG(0,("Invalid name length in session request\n"));
87 return(0);
89 name_extract(inbuf,4,name1);
90 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
91 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
92 name1,name2));
94 fstrcpy(remote_machine,name2);
95 remote_machine[15] = 0;
96 trim_string(remote_machine," "," ");
97 strlower(remote_machine);
98 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
100 fstrcpy(local_machine,name1);
101 len = strlen(local_machine);
102 if (len == 16) {
103 name_type = local_machine[15];
104 local_machine[15] = 0;
106 trim_string(local_machine," "," ");
107 strlower(local_machine);
108 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
110 DEBUG(2,("netbios connect: local=%s remote=%s\n",
111 local_machine, remote_machine ));
113 if (name_type == 'R') {
114 /* We are being asked for a pathworks session ---
115 no thanks! */
116 SCVAL(outbuf, 0, 0x83);
117 break;
120 /* add it as a possible user name if we
121 are in share mode security */
122 if (lp_security() == SEC_SHARE) {
123 add_session_user(remote_machine);
126 reload_services(True);
127 reopen_logs();
129 if (lp_status(-1))
130 claim_connection(NULL,"",0,True);
132 break;
134 case 0x89: /* session keepalive request
135 (some old clients produce this?) */
136 SCVAL(outbuf,0,0x85);
137 SCVAL(outbuf,3,0);
138 break;
140 case 0x82: /* positive session response */
141 case 0x83: /* negative session response */
142 case 0x84: /* retarget session response */
143 DEBUG(0,("Unexpected session response\n"));
144 break;
146 case 0x85: /* session keepalive */
147 default:
148 return(0);
151 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
152 msg_type, msg_flags));
154 return(outsize);
158 /*******************************************************************
159 work out what error to give to a failed connection
160 ********************************************************************/
162 static int connection_error(char *outbuf, int ecode)
164 if (ecode == ERRnoipc || ecode == ERRnosuchshare)
165 return(ERROR_DOS(ERRDOS,ecode));
167 return(ERROR_DOS(ERRSRV,ecode));
170 /****************************************************************************
171 parse a share descriptor string
172 ****************************************************************************/
174 static void parse_connect(char *p,char *service,char *user,
175 char *password,int *pwlen,char *dev)
177 char *p2;
179 DEBUG(4,("parsing connect string %s\n",p));
181 p2 = strrchr(p,'\\');
182 if (p2 == NULL)
183 fstrcpy(service,p);
184 else
185 fstrcpy(service,p2+1);
187 p += strlen(p) + 2;
189 fstrcpy(password,p);
190 *pwlen = strlen(password);
192 p += strlen(p) + 2;
194 fstrcpy(dev,p);
196 *user = 0;
197 p = strchr(service,'%');
198 if (p != NULL)
200 *p = 0;
201 fstrcpy(user,p+1);
205 /****************************************************************************
206 Reply to a tcon.
207 ****************************************************************************/
209 int reply_tcon(connection_struct *conn,
210 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
212 BOOL doencrypt = SMBENCRYPT();
213 pstring service;
214 pstring user;
215 pstring password;
216 pstring dev;
217 int outsize = 0;
218 uint16 vuid = SVAL(inbuf,smb_uid);
219 int pwlen=0;
220 int ecode = -1;
221 START_PROFILE(SMBtcon);
223 *service = *user = *password = *dev = 0;
225 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
228 * If the vuid is valid, we should be using that....
231 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
232 pstrcpy(user,validated_username(vuid));
236 * Ensure the user and password names are in UNIX codepage format.
239 pstrcpy(user,dos_to_unix_static(user));
240 if (!doencrypt)
241 pstrcpy(password,dos_to_unix_static(password));
244 * Pass the user through the NT -> unix user mapping
245 * function.
248 (void)map_username(user);
251 * Do any UNIX username case mangling.
253 (void)Get_Pwnam( user, True);
255 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
257 if (!conn) {
258 END_PROFILE(SMBtcon);
259 return(connection_error(outbuf,ecode));
262 outsize = set_message(outbuf,2,0,True);
263 SSVAL(outbuf,smb_vwv0,max_recv);
264 SSVAL(outbuf,smb_vwv1,conn->cnum);
265 SSVAL(outbuf,smb_tid,conn->cnum);
267 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
268 service, user, conn->cnum));
270 END_PROFILE(SMBtcon);
271 return(outsize);
274 /****************************************************************************
275 Reply to a tcon and X.
276 ****************************************************************************/
278 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
280 fstring service;
281 pstring user;
282 pstring password;
283 pstring devicename;
284 BOOL doencrypt = SMBENCRYPT();
285 int ecode = -1;
286 uint16 vuid = SVAL(inbuf,smb_uid);
287 int passlen = SVAL(inbuf,smb_vwv3);
288 char *path;
289 char *p;
290 START_PROFILE(SMBtconX);
292 *service = *user = *password = *devicename = 0;
294 /* we might have to close an old one */
295 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
296 close_cnum(conn,vuid);
299 if (passlen > MAX_PASS_LEN) {
300 overflow_attack(passlen);
301 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
304 memcpy(password,smb_buf(inbuf),passlen);
305 password[passlen]=0;
306 path = smb_buf(inbuf) + passlen;
308 if (passlen != 24) {
309 if (strequal(password," "))
310 *password = 0;
311 passlen = strlen(password);
315 * the service name can be either: \\server\share
316 * or share directly like on the DELL PowerVault 705
318 if (*path=='\\') {
319 p = strchr(path+2,'\\');
320 if (!p) {
321 END_PROFILE(SMBtconX);
322 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
324 fstrcpy(service,p+1);
326 else
327 fstrcpy(service,path);
329 p = strchr(service,'%');
330 if (p) {
331 *p++ = 0;
332 fstrcpy(user,p);
334 StrnCpy(devicename,path + strlen(path) + 1,6);
335 DEBUG(4,("Got device type %s\n",devicename));
338 * If the vuid is valid, we should be using that....
341 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
342 pstrcpy(user,validated_username(vuid));
346 * Ensure the user and password names are in UNIX codepage format.
349 pstrcpy(user,dos_to_unix_static(user));
350 if (!doencrypt)
351 pstrcpy(password,dos_to_unix_static(password));
354 * Pass the user through the NT -> unix user mapping
355 * function.
358 (void)map_username(user);
361 * Do any UNIX username case mangling.
363 (void)Get_Pwnam(user, True);
365 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
367 if (!conn) {
368 END_PROFILE(SMBtconX);
369 return(connection_error(outbuf,ecode));
372 if (Protocol < PROTOCOL_NT1) {
373 set_message(outbuf,2,strlen(devicename)+1,True);
374 pstrcpy(smb_buf(outbuf),devicename);
375 } else {
376 char *fsname = lp_fstype(SNUM(conn));
378 set_message(outbuf,3,3,True);
380 p = smb_buf(outbuf);
381 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
382 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
384 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
386 /* what does setting this bit do? It is set by NT4 and
387 may affect the ability to autorun mounted cdroms */
388 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
389 (lp_csc_policy(SNUM(conn)) << 2));
391 init_dfsroot(conn, inbuf, outbuf);
395 DEBUG(3,("tconX service=%s user=%s\n",
396 service, user));
398 /* set the incoming and outgoing tid to the just created one */
399 SSVAL(inbuf,smb_tid,conn->cnum);
400 SSVAL(outbuf,smb_tid,conn->cnum);
402 END_PROFILE(SMBtconX);
403 return chain_reply(inbuf,outbuf,length,bufsize);
407 /****************************************************************************
408 reply to an unknown type
409 ****************************************************************************/
410 int reply_unknown(char *inbuf,char *outbuf)
412 int type;
413 type = CVAL(inbuf,smb_com);
415 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
416 smb_fn_name(type), type, type));
418 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
421 /****************************************************************************
422 reply to an ioctl
423 ****************************************************************************/
424 int reply_ioctl(connection_struct *conn,
425 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
427 uint16 device = SVAL(inbuf,smb_vwv1);
428 uint16 function = SVAL(inbuf,smb_vwv2);
429 uint32 ioctl_code = (device << 16) + function;
430 int replysize, outsize;
431 char *p;
432 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
433 START_PROFILE(SMBioctl);
435 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
437 switch (ioctl_code)
439 case IOCTL_QUERY_JOB_INFO:
440 replysize = 32;
441 break;
442 default:
443 END_PROFILE(SMBioctl);
444 return(ERROR_DOS(ERRSRV,ERRnosupport));
447 outsize = set_message(outbuf,8,replysize+1,True);
448 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
449 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
450 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
451 p = smb_buf(outbuf) + 1; /* Allow for alignment */
453 switch (ioctl_code)
455 case IOCTL_QUERY_JOB_INFO:
456 SSVAL(p,0,fsp->print_jobid); /* Job number */
457 StrnCpy(p+2, global_myname, 15); /* Our NetBIOS name */
458 StrnCpy(p+18, lp_servicename(SNUM(conn)), 13); /* Service name */
459 break;
462 END_PROFILE(SMBioctl);
463 return outsize;
466 /****************************************************************************
467 Always return an error: it's just a matter of which one...
468 ****************************************************************************/
470 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
471 char *smb_passwd, int smb_passlen,
472 char *smb_nt_passwd, int smb_nt_passlen)
474 SAM_ACCOUNT *sam_trust_acct = NULL; /* check if trust account exists */
475 uint16 acct_ctrl;
477 if (lp_security() == SEC_USER) {
478 pdb_init_sam(&sam_trust_acct);
479 pdb_getsampwnam(sam_trust_acct, user);
480 } else {
481 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
482 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw));
485 if (sam_trust_acct == NULL) {
486 /* lkclXXXX: workstation entry doesn't exist */
487 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
488 return(ERROR_BOTH(NT_STATUS_NO_SUCH_USER,ERRDOS,1317));
489 } else {
490 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
491 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
492 pdb_free_sam(sam_trust_acct);
493 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw));
496 if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) {
497 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
498 pdb_free_sam(sam_trust_acct);
499 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw));
502 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
503 if (acct_ctrl & ACB_DOMTRUST) {
504 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
505 pdb_free_sam(sam_trust_acct);
506 return(ERROR_BOTH(NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT,ERRDOS,1807));
509 if (acct_ctrl & ACB_SVRTRUST) {
510 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
511 pdb_free_sam(sam_trust_acct);
512 return(ERROR_BOTH(NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT,ERRDOS,1809));
515 if (acct_ctrl & ACB_WSTRUST) {
516 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
517 pdb_free_sam(sam_trust_acct);
518 return(ERROR_BOTH(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT,ERRDOS,1808));
522 /* don't know what to do: indicate logon failure */
523 pdb_free_sam(sam_trust_acct);
524 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRDOS,1326));
527 /****************************************************************************
528 Create a UNIX user on demand.
529 ****************************************************************************/
531 int smb_create_user(char *unix_user, char *homedir)
533 pstring add_script;
534 int ret;
536 pstrcpy(add_script, lp_adduser_script());
537 if (! *add_script)
538 return -1;
539 all_string_sub(add_script, "%u", unix_user, sizeof(pstring));
540 if (homedir)
541 all_string_sub(add_script, "%H", homedir, sizeof(pstring));
542 ret = smbrun(add_script,NULL);
543 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
544 return ret;
547 /****************************************************************************
548 Delete a UNIX user on demand.
549 ****************************************************************************/
551 static int smb_delete_user(char *unix_user)
553 pstring del_script;
554 int ret;
557 * Sanity check -- do not delete 'root' account
560 if (StrCaseCmp("root", unix_user) == 0) {
561 DEBUG(0,("smb_delete_user: Will not delete the [%s] user account!\n", unix_user));
562 return -1;
565 pstrcpy(del_script, lp_deluser_script());
566 if (! *del_script)
567 return -1;
568 all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
569 ret = smbrun(del_script,NULL);
570 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
571 return ret;
574 /****************************************************************************
575 Check user is in correct domain if required
576 ****************************************************************************/
578 static BOOL check_domain_match(char *user, char *domain)
581 * If we aren't serving to trusted domains, we must make sure that
582 * the validation request comes from an account in the same domain
583 * as the Samba server
586 if (!lp_allow_trusted_domains() &&
587 !strequal(lp_workgroup(), domain) ) {
588 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
589 return False;
590 } else {
591 return True;
595 /****************************************************************************
596 Check for a valid username and password in security=server mode.
597 ****************************************************************************/
599 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
600 char *smb_apasswd, int smb_apasslen,
601 char *smb_ntpasswd, int smb_ntpasslen)
603 BOOL ret = False;
605 if(lp_security() != SEC_SERVER)
606 return False;
608 if (!check_domain_match(orig_user, domain))
609 return False;
611 ret = server_validate(orig_user, domain,
612 smb_apasswd, smb_apasslen,
613 smb_ntpasswd, smb_ntpasslen);
615 if(ret) {
617 * User validated ok against Domain controller.
618 * If the admin wants us to try and create a UNIX
619 * user on the fly, do so.
620 * Note that we can never delete users when in server
621 * level security as we never know if it was a failure
622 * due to a bad password, or the user really doesn't exist.
625 if(lp_adduser_script() && !smb_getpwnam(unix_user,True))
626 smb_create_user(unix_user, NULL);
629 return ret;
632 /****************************************************************************
633 Check for a valid username and password in security=domain mode.
634 ****************************************************************************/
636 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
637 char *smb_apasswd, int smb_apasslen,
638 char *smb_ntpasswd, int smb_ntpasslen, NT_USER_TOKEN **pptoken)
640 BOOL ret = False;
641 BOOL user_exists = True;
642 struct passwd *pwd = NULL;
644 if(lp_security() != SEC_DOMAIN)
645 return False;
647 if (!check_domain_match(orig_user, domain))
648 return False;
650 ret = domain_client_validate(orig_user, domain,
651 smb_apasswd, smb_apasslen,
652 smb_ntpasswd, smb_ntpasslen,
653 &user_exists, pptoken);
655 if(ret) {
657 * User validated ok against Domain controller.
658 * If the admin wants us to try and create a UNIX
659 * user on the fly, do so.
661 if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
662 smb_create_user(unix_user, NULL);
665 if(lp_adduser_script() && pwd) {
666 SMB_STRUCT_STAT st;
669 * Also call smb_create_user if the users home directory
670 * doesn't exist. Used with winbindd to allow the script to
671 * create the home directory for a user mapped with winbindd.
674 if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
675 smb_create_user(unix_user, pwd->pw_dir);
678 } else {
680 * User failed to validate ok against Domain controller.
681 * If the failure was "user doesn't exist" and admin
682 * wants us to try and delete that UNIX user on the fly,
683 * do so.
685 if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) {
686 smb_delete_user(unix_user);
690 return ret;
693 /****************************************************************************
694 Reply to a session setup command.
695 ****************************************************************************/
697 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
699 int sess_vuid;
700 gid_t gid;
701 uid_t uid;
702 int smb_bufsize;
703 int smb_apasslen = 0;
704 pstring smb_apasswd;
705 int smb_ntpasslen = 0;
706 pstring smb_ntpasswd;
707 BOOL valid_nt_password = False;
708 BOOL valid_lm_password = False;
709 pstring user;
710 pstring orig_user;
711 BOOL guest=False;
712 static BOOL done_sesssetup = False;
713 BOOL doencrypt = SMBENCRYPT();
714 fstring domain;
715 NT_USER_TOKEN *ptok = NULL;
717 START_PROFILE(SMBsesssetupX);
719 *smb_apasswd = 0;
720 *smb_ntpasswd = 0;
721 *domain = 0;
723 smb_bufsize = SVAL(inbuf,smb_vwv2);
725 if (Protocol < PROTOCOL_NT1) {
726 smb_apasslen = SVAL(inbuf,smb_vwv7);
727 if (smb_apasslen > MAX_PASS_LEN) {
728 overflow_attack(smb_apasslen);
729 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
732 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
733 smb_apasswd[smb_apasslen] = 0;
734 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
736 * Incoming user is in DOS codepage format. Convert
737 * to UNIX.
739 pstrcpy(user,dos_to_unix_static(user));
741 if (!doencrypt && (lp_security() != SEC_SERVER)) {
742 smb_apasslen = strlen(smb_apasswd);
744 } else {
745 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
746 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
747 enum remote_arch_types ra_type = get_remote_arch();
748 char *p = smb_buf(inbuf);
750 if(global_client_caps == 0)
751 global_client_caps = IVAL(inbuf,smb_vwv11);
753 /* client_caps is used as final determination if client is NT or Win95.
754 This is needed to return the correct error codes in some
755 circumstances.
758 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
759 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
760 set_remote_arch( RA_WIN95);
764 if (passlen1 != 24 && passlen2 != 24)
765 doencrypt = False;
767 if (passlen1 > MAX_PASS_LEN) {
768 overflow_attack(passlen1);
769 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
772 passlen1 = MIN(passlen1, MAX_PASS_LEN);
773 passlen2 = MIN(passlen2, MAX_PASS_LEN);
775 if(!doencrypt) {
776 /* both Win95 and WinNT stuff up the password lengths for
777 non-encrypting systems. Uggh.
779 if passlen1==24 its a win95 system, and its setting the
780 password length incorrectly. Luckily it still works with the
781 default code because Win95 will null terminate the password
782 anyway
784 if passlen1>0 and passlen2>0 then maybe its a NT box and its
785 setting passlen2 to some random value which really stuffs
786 things up. we need to fix that one. */
788 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
789 passlen2 = 0;
792 if (lp_restrict_anonymous()) {
793 /* there seems to be no reason behind the differences in MS clients formatting
794 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
795 * in particular seems to have an extra null byte between the username and the
796 * domain, or the password length calculation is wrong, which throws off the
797 * string extraction routines below. This makes the value of domain be the
798 * empty string, which fails the restrict anonymous check further down.
799 * This compensates for that, and allows browsing to work in mixed NT and
800 * win95 environments even when restrict anonymous is true. AAB
802 dump_data(100, p, 0x70);
803 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
804 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
805 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
806 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
807 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
808 passlen1 = 1;
812 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
813 /* Save the lanman2 password and the NT md4 password. */
814 smb_apasslen = passlen1;
815 memcpy(smb_apasswd,p,smb_apasslen);
816 smb_apasswd[smb_apasslen] = 0;
817 smb_ntpasslen = passlen2;
818 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
819 smb_ntpasswd[smb_ntpasslen] = 0;
822 * Ensure the plaintext passwords are in UNIX format.
824 if(!doencrypt) {
825 pstrcpy(smb_apasswd,dos_to_unix_static(smb_apasswd));
826 pstrcpy(smb_ntpasswd,dos_to_unix_static(smb_ntpasswd));
829 } else {
830 /* we use the first password that they gave */
831 smb_apasslen = passlen1;
832 StrnCpy(smb_apasswd,p,smb_apasslen);
834 * Ensure the plaintext password is in UNIX format.
836 pstrcpy(smb_apasswd,dos_to_unix_static(smb_apasswd));
838 /* trim the password */
839 smb_apasslen = strlen(smb_apasswd);
841 /* wfwg sometimes uses a space instead of a null */
842 if (strequal(smb_apasswd," ")) {
843 smb_apasslen = 0;
844 *smb_apasswd = 0;
848 p += passlen1 + passlen2;
849 fstrcpy(user,p);
850 p = skip_string(p,1);
852 * Incoming user and domain are in DOS codepage format. Convert
853 * to UNIX.
855 pstrcpy(user,dos_to_unix_static(user));
856 fstrcpy(domain, dos_to_unix_static(p));
857 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
858 domain,skip_string(p,1),skip_string(p,2)));
861 /* don't allow strange characters in usernames or domains */
862 alpha_strcpy(user, user, ". _-$", sizeof(user));
863 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
864 if (strstr(user, "..") || strstr(domain,"..")) {
865 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
868 DEBUG(3,("sesssetupX:name=[%s]\n",user));
870 /* If name ends in $ then I think it's asking about whether a */
871 /* computer with that name (minus the $) has access. For now */
872 /* say yes to everything ending in $. */
874 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
875 END_PROFILE(SMBsesssetupX);
876 return session_trust_account(conn, inbuf, outbuf, user,
877 smb_apasswd, smb_apasslen,
878 smb_ntpasswd, smb_ntpasslen);
881 if (done_sesssetup && lp_restrict_anonymous()) {
882 /* tests show that even if browsing is done over already validated connections
883 * without a username and password the domain is still provided, which it
884 * wouldn't be if it was a purely anonymous connection. So, in order to
885 * restrict anonymous, we only deny connections that have no session
886 * information. If a domain has been provided, then it's not a purely
887 * anonymous connection. AAB
889 if (!*user && !*smb_apasswd && !*domain) {
890 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
891 END_PROFILE(SMBsesssetupX);
892 return(ERROR_DOS(ERRDOS,ERRnoaccess));
896 /* If no username is sent use the guest account */
897 if (!*user) {
898 pstrcpy(user,lp_guestaccount(-1));
899 guest = True;
902 pstrcpy(current_user_info.smb_name,user);
904 reload_services(True);
907 * Save the username before mapping. We will use
908 * the original username sent to us for security=server
909 * and security=domain checking.
912 pstrcpy( orig_user, user);
915 * Always try the "DOMAIN\user" lookup first, as this is the most
916 * specific case. If this fails then try the simple "user" lookup.
920 pstring dom_user;
922 /* Work out who's who */
924 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
925 domain, lp_winbind_separator(), user);
927 if (sys_getpwnam(dom_user) != NULL) {
928 pstrcpy(user, dom_user);
929 DEBUG(3,("Using unix username %s\n", dom_user));
934 * Pass the user through the NT -> unix user mapping
935 * function.
938 (void)map_username(user);
941 * Do any UNIX username case mangling.
943 smb_getpwnam(user, True);
945 add_session_user(user);
948 * Check with orig_user for security=server and
949 * security=domain.
952 if (!guest && !check_server_security(orig_user, domain, user,
953 smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
954 !check_domain_security(orig_user, domain, user, smb_apasswd,
955 smb_apasslen, smb_ntpasswd, smb_ntpasslen, &ptok) &&
956 !check_hosts_equiv(user))
960 * If we get here then the user wasn't guest and the remote
961 * authentication methods failed. Check the authentication
962 * methods on this local server.
964 * If an NT password was supplied try and validate with that
965 * first. This is superior as the passwords are mixed case
966 * 128 length unicode.
969 if(smb_ntpasslen)
971 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
972 DEBUG(2,("NT Password did not match for user '%s'!\n", user));
973 else
974 valid_nt_password = True;
978 /* check the LanMan password only if necessary and if allowed
979 by lp_lanman_auth() */
980 if (!valid_nt_password && lp_lanman_auth())
982 DEBUG(2,("Defaulting to Lanman password for %s\n", user));
983 valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen,NULL);
987 /* The true branch will be executed if
988 (1) the NT password failed (or was not tried), and
989 (2) LanMan authentication failed (or was disabled)
991 if (!valid_nt_password && !valid_lm_password)
993 if (lp_security() >= SEC_USER)
995 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
997 delete_nt_token(&ptok);
998 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
999 END_PROFILE(SMBsesssetupX);
1000 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
1003 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
1005 SAM_ACCOUNT *sampass = NULL;
1007 pdb_init_sam(&sampass);
1010 * This is really bad form. We know that password_ok() failed,
1011 * but the return value can't distinguish between a non-existent user
1012 * and a bad password. So we try to look the user up again here
1013 * to see if he or she exists. We must look up the user in the
1014 * "smb passwd file" and not /etc/passwd so that we don't
1015 * get confused when the two don't have a one-to-one correspondence.
1016 * e.g. a standard UNIX account such as "operator" --jerry
1019 if (pdb_getsampwnam(sampass, user))
1021 delete_nt_token(&ptok);
1022 DEBUG(1,("Rejecting user '%s': bad password\n", user));
1023 END_PROFILE(SMBsesssetupX);
1024 pdb_free_sam(sampass);
1025 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
1028 pdb_free_sam(sampass);
1032 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
1033 * Then always map to guest account - as done below.
1037 if (*smb_apasswd || !smb_getpwnam(user,True))
1038 pstrcpy(user,lp_guestaccount(-1));
1039 DEBUG(3,("Registered username %s for guest access\n",user));
1040 guest = True;
1044 if (!smb_getpwnam(user,True)) {
1045 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
1046 pstrcpy(user,lp_guestaccount(-1));
1047 guest = True;
1050 if (!strequal(user,lp_guestaccount(-1)) &&
1051 lp_servicenumber(user) < 0)
1053 add_home_service(user,get_user_service_home_dir(user));
1057 /* it's ok - setup a reply */
1058 if (Protocol < PROTOCOL_NT1) {
1059 set_message(outbuf,3,0,True);
1060 } else {
1061 char *p;
1062 set_message(outbuf,3,3,True);
1063 p = smb_buf(outbuf);
1064 pstrcpy(p,"Unix"); p = skip_string(p,1);
1065 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
1066 pstrcpy(p,global_myworkgroup); unix_to_dos(p); p = skip_string(p,1);
1067 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
1068 /* perhaps grab OS version here?? */
1071 /* Set the correct uid in the outgoing and incoming packets
1072 We will use this on future requests to determine which
1073 user we should become.
1076 const struct passwd *pw = smb_getpwnam(user,False);
1077 if (!pw) {
1078 delete_nt_token(&ptok);
1079 DEBUG(1,("Username %s is invalid on this system\n",user));
1080 END_PROFILE(SMBsesssetupX);
1081 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
1083 gid = pw->pw_gid;
1084 uid = pw->pw_uid;
1087 if (guest)
1088 SSVAL(outbuf,smb_vwv2,1);
1090 /* register the name and uid as being validated, so further connections
1091 to a uid can get through without a password, on the same VC */
1093 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest,&ptok);
1095 delete_nt_token(&ptok);
1097 if (sess_vuid == -1) {
1098 END_PROFILE(SMBsesssetupX);
1099 return(ERROR_DOS(ERRDOS,ERRnoaccess));
1102 SSVAL(outbuf,smb_uid,sess_vuid);
1103 SSVAL(inbuf,smb_uid,sess_vuid);
1105 if (!done_sesssetup)
1106 max_send = MIN(max_send,smb_bufsize);
1108 DEBUG(6,("Client requested max send size of %d\n", max_send));
1110 done_sesssetup = True;
1112 END_PROFILE(SMBsesssetupX);
1113 return chain_reply(inbuf,outbuf,length,bufsize);
1117 /****************************************************************************
1118 reply to a chkpth
1119 ****************************************************************************/
1120 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1122 int outsize = 0;
1123 int mode;
1124 pstring name;
1125 BOOL ok = False;
1126 BOOL bad_path = False;
1127 SMB_STRUCT_STAT sbuf;
1128 START_PROFILE(SMBchkpth);
1130 pstrcpy(name,smb_buf(inbuf) + 1);
1132 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1134 unix_convert(name,conn,0,&bad_path,&sbuf);
1136 mode = SVAL(inbuf,smb_vwv0);
1138 if (check_name(name,conn)) {
1139 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
1140 ok = S_ISDIR(sbuf.st_mode);
1143 if (!ok) {
1144 /* We special case this - as when a Windows machine
1145 is parsing a path is steps through the components
1146 one at a time - if a component fails it expects
1147 ERRbadpath, not ERRbadfile.
1149 if(errno == ENOENT) {
1150 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1153 return(UNIXERROR(ERRDOS,ERRbadpath));
1156 outsize = set_message(outbuf,0,0,True);
1158 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1160 END_PROFILE(SMBchkpth);
1161 return(outsize);
1165 /****************************************************************************
1166 reply to a getatr
1167 ****************************************************************************/
1168 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1170 pstring fname;
1171 int outsize = 0;
1172 SMB_STRUCT_STAT sbuf;
1173 BOOL ok = False;
1174 int mode=0;
1175 SMB_OFF_T size=0;
1176 time_t mtime=0;
1177 BOOL bad_path = False;
1178 START_PROFILE(SMBgetatr);
1180 pstrcpy(fname,smb_buf(inbuf) + 1);
1182 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1184 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1185 under WfWg - weird! */
1186 if (! (*fname))
1188 mode = aHIDDEN | aDIR;
1189 if (!CAN_WRITE(conn)) mode |= aRONLY;
1190 size = 0;
1191 mtime = 0;
1192 ok = True;
1194 else
1196 unix_convert(fname,conn,0,&bad_path,&sbuf);
1197 if (check_name(fname,conn))
1199 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1201 mode = dos_mode(conn,fname,&sbuf);
1202 size = sbuf.st_size;
1203 mtime = sbuf.st_mtime;
1204 if (mode & aDIR)
1205 size = 0;
1206 ok = True;
1208 else
1209 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1213 if (!ok)
1215 set_bad_path_error(errno, bad_path);
1216 END_PROFILE(SMBgetatr);
1217 return(UNIXERROR(ERRDOS,ERRbadfile));
1220 outsize = set_message(outbuf,10,0,True);
1222 SSVAL(outbuf,smb_vwv0,mode);
1223 if(lp_dos_filetime_resolution(SNUM(conn)) )
1224 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1225 else
1226 put_dos_date3(outbuf,smb_vwv1,mtime);
1227 SIVAL(outbuf,smb_vwv3,(uint32)size);
1229 if (Protocol >= PROTOCOL_NT1)
1230 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1232 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1234 END_PROFILE(SMBgetatr);
1235 return(outsize);
1239 /****************************************************************************
1240 reply to a setatr
1241 ****************************************************************************/
1242 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1244 pstring fname;
1245 int outsize = 0;
1246 BOOL ok=False;
1247 int mode;
1248 time_t mtime;
1249 SMB_STRUCT_STAT sbuf;
1250 BOOL bad_path = False;
1251 START_PROFILE(SMBsetatr);
1253 pstrcpy(fname,smb_buf(inbuf) + 1);
1254 unix_convert(fname,conn,0,&bad_path,&sbuf);
1256 mode = SVAL(inbuf,smb_vwv0);
1257 mtime = make_unix_date3(inbuf+smb_vwv1);
1259 if (VALID_STAT_OF_DIR(sbuf))
1260 mode |= aDIR;
1261 else
1262 mode &= ~aDIR;
1264 if (check_name(fname,conn))
1265 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1266 if (ok)
1267 ok = set_filetime(conn,fname,mtime);
1269 if (!ok)
1271 set_bad_path_error(errno, bad_path);
1272 END_PROFILE(SMBsetatr);
1273 return(UNIXERROR(ERRDOS,ERRnoaccess));
1276 outsize = set_message(outbuf,0,0,True);
1278 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1280 END_PROFILE(SMBsetatr);
1281 return(outsize);
1285 /****************************************************************************
1286 reply to a dskattr
1287 ****************************************************************************/
1288 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1290 int outsize = 0;
1291 SMB_BIG_UINT dfree,dsize,bsize;
1292 START_PROFILE(SMBdskattr);
1294 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1296 outsize = set_message(outbuf,5,0,True);
1298 if (Protocol <= PROTOCOL_LANMAN2) {
1299 double total_space, free_space;
1300 /* we need to scale this to a number that DOS6 can handle. We
1301 use floating point so we can handle large drives on systems
1302 that don't have 64 bit integers
1304 we end up displaying a maximum of 2G to DOS systems
1306 total_space = dsize * (double)bsize;
1307 free_space = dfree * (double)bsize;
1309 dsize = (total_space+63*512) / (64*512);
1310 dfree = (free_space+63*512) / (64*512);
1312 if (dsize > 0xFFFF) dsize = 0xFFFF;
1313 if (dfree > 0xFFFF) dfree = 0xFFFF;
1315 SSVAL(outbuf,smb_vwv0,dsize);
1316 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1317 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
1318 SSVAL(outbuf,smb_vwv3,dfree);
1319 } else {
1320 SSVAL(outbuf,smb_vwv0,dsize);
1321 SSVAL(outbuf,smb_vwv1,bsize/512);
1322 SSVAL(outbuf,smb_vwv2,512);
1323 SSVAL(outbuf,smb_vwv3,dfree);
1326 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1328 END_PROFILE(SMBdskattr);
1329 return(outsize);
1333 /****************************************************************************
1334 reply to a search
1335 Can be called from SMBsearch, SMBffirst or SMBfunique.
1336 ****************************************************************************/
1337 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1339 pstring mask;
1340 pstring directory;
1341 pstring fname;
1342 SMB_OFF_T size;
1343 int mode;
1344 time_t date;
1345 int dirtype;
1346 int outsize = 0;
1347 int numentries = 0;
1348 BOOL finished = False;
1349 int maxentries;
1350 int i;
1351 char *p;
1352 BOOL ok = False;
1353 int status_len;
1354 char *path;
1355 char status[21];
1356 int dptr_num= -1;
1357 BOOL check_descend = False;
1358 BOOL expect_close = False;
1359 BOOL can_open = True;
1360 BOOL bad_path = False;
1361 START_PROFILE(SMBsearch);
1363 *mask = *directory = *fname = 0;
1365 /* If we were called as SMBffirst then we must expect close. */
1366 if(CVAL(inbuf,smb_com) == SMBffirst)
1367 expect_close = True;
1369 outsize = set_message(outbuf,1,3,True);
1370 maxentries = SVAL(inbuf,smb_vwv0);
1371 dirtype = SVAL(inbuf,smb_vwv1);
1372 path = smb_buf(inbuf) + 1;
1373 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1375 RESOLVE_DFSPATH(path, conn, inbuf, outbuf);
1376 /* dirtype &= ~aDIR; */
1378 if (status_len == 0)
1380 SMB_STRUCT_STAT sbuf;
1381 pstring dir2;
1383 pstrcpy(directory,smb_buf(inbuf)+1);
1384 pstrcpy(dir2,smb_buf(inbuf)+1);
1385 unix_convert(directory,conn,0,&bad_path,&sbuf);
1386 unix_format(dir2);
1388 if (!check_name(directory,conn))
1389 can_open = False;
1391 p = strrchr(dir2,'/');
1392 if (p == NULL)
1394 pstrcpy(mask,dir2);
1395 *dir2 = 0;
1397 else
1399 *p = 0;
1400 pstrcpy(mask,p+1);
1403 p = strrchr(directory,'/');
1404 if (!p)
1405 *directory = 0;
1406 else
1407 *p = 0;
1409 if (strlen(directory) == 0)
1410 pstrcpy(directory,"./");
1411 memset((char *)status,'\0',21);
1412 SCVAL(status,0,dirtype);
1414 else
1416 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1417 dirtype = CVAL(status,0) & 0x1F;
1418 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1419 if (!conn->dirptr)
1420 goto SearchEmpty;
1421 string_set(&conn->dirpath,dptr_path(dptr_num));
1422 fstrcpy(mask, dptr_wcard(dptr_num));
1425 if (can_open)
1427 p = smb_buf(outbuf) + 3;
1429 ok = True;
1431 if (status_len == 0)
1433 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1434 if (dptr_num < 0)
1436 if(dptr_num == -2)
1438 set_bad_path_error(errno, bad_path);
1439 END_PROFILE(SMBsearch);
1440 return (UNIXERROR(ERRDOS,ERRnofids));
1442 END_PROFILE(SMBsearch);
1443 return ERROR_DOS(ERRDOS,ERRnofids);
1445 dptr_set_wcard(dptr_num, strdup(mask));
1448 DEBUG(4,("dptr_num is %d\n",dptr_num));
1450 if (ok)
1452 if ((dirtype&0x1F) == aVOLID)
1454 memcpy(p,status,21);
1455 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1456 dptr_fill(p+12,dptr_num);
1457 if (dptr_zero(p+12) && (status_len==0))
1458 numentries = 1;
1459 else
1460 numentries = 0;
1461 p += DIR_STRUCT_SIZE;
1463 else
1465 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1466 conn->dirpath,lp_dontdescend(SNUM(conn))));
1467 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1468 check_descend = True;
1470 for (i=numentries;(i<maxentries) && !finished;i++)
1472 finished =
1473 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1474 if (!finished)
1476 memcpy(p,status,21);
1477 make_dir_struct(p,mask,fname,size,mode,date);
1478 dptr_fill(p+12,dptr_num);
1479 numentries++;
1481 p += DIR_STRUCT_SIZE;
1484 } /* if (ok ) */
1488 SearchEmpty:
1490 if ( (numentries == 0) || !ok)
1492 SCVAL(outbuf,smb_rcls,ERRDOS);
1493 SSVAL(outbuf,smb_err,ERRnofiles);
1494 dptr_close(&dptr_num);
1497 /* If we were called as SMBffirst with smb_search_id == NULL
1498 and no entries were found then return error and close dirptr
1499 (X/Open spec) */
1501 if(ok && expect_close && numentries == 0 && status_len == 0)
1503 SCVAL(outbuf,smb_rcls,ERRDOS);
1504 SSVAL(outbuf,smb_err,ERRnofiles);
1505 /* Also close the dptr - we know it's gone */
1506 dptr_close(&dptr_num);
1509 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1510 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1511 dptr_close(&dptr_num);
1513 SSVAL(outbuf,smb_vwv0,numentries);
1514 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1515 SCVAL(smb_buf(outbuf),0,5);
1516 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1518 if (Protocol >= PROTOCOL_NT1)
1519 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1521 outsize += DIR_STRUCT_SIZE*numentries;
1522 smb_setlen(outbuf,outsize - 4);
1524 if ((! *directory) && dptr_path(dptr_num))
1525 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1527 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1528 smb_fn_name(CVAL(inbuf,smb_com)),
1529 mask, directory, dirtype, numentries, maxentries ) );
1531 END_PROFILE(SMBsearch);
1532 return(outsize);
1536 /****************************************************************************
1537 reply to a fclose (stop directory search)
1538 ****************************************************************************/
1539 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1541 int outsize = 0;
1542 int status_len;
1543 char *path;
1544 char status[21];
1545 int dptr_num= -2;
1546 START_PROFILE(SMBfclose);
1548 outsize = set_message(outbuf,1,0,True);
1549 path = smb_buf(inbuf) + 1;
1550 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1553 if (status_len == 0) {
1554 END_PROFILE(SMBfclose);
1555 return ERROR_DOS(ERRSRV,ERRsrverror);
1558 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1560 if(dptr_fetch(status+12,&dptr_num)) {
1561 /* Close the dptr - we know it's gone */
1562 dptr_close(&dptr_num);
1565 SSVAL(outbuf,smb_vwv0,0);
1567 DEBUG(3,("search close\n"));
1569 END_PROFILE(SMBfclose);
1570 return(outsize);
1574 /****************************************************************************
1575 reply to an open
1576 ****************************************************************************/
1578 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1580 pstring fname;
1581 int outsize = 0;
1582 int fmode=0;
1583 int share_mode;
1584 SMB_OFF_T size = 0;
1585 time_t mtime=0;
1586 mode_t unixmode;
1587 int rmode=0;
1588 SMB_STRUCT_STAT sbuf;
1589 BOOL bad_path = False;
1590 files_struct *fsp;
1591 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1592 START_PROFILE(SMBopen);
1594 share_mode = SVAL(inbuf,smb_vwv0);
1596 pstrcpy(fname,smb_buf(inbuf)+1);
1598 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1600 unix_convert(fname,conn,0,&bad_path,&sbuf);
1602 unixmode = unix_mode(conn,aARCH,fname);
1604 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1605 unixmode, oplock_request,&rmode,NULL);
1607 if (!fsp)
1609 set_bad_path_error(errno, bad_path);
1610 END_PROFILE(SMBopen);
1611 return(UNIXERROR(ERRDOS,ERRnoaccess));
1614 size = sbuf.st_size;
1615 fmode = dos_mode(conn,fname,&sbuf);
1616 mtime = sbuf.st_mtime;
1618 if (fmode & aDIR) {
1619 DEBUG(3,("attempt to open a directory %s\n",fname));
1620 close_file(fsp,False);
1621 END_PROFILE(SMBopen);
1622 return ERROR_DOS(ERRDOS,ERRnoaccess);
1625 outsize = set_message(outbuf,7,0,True);
1626 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1627 SSVAL(outbuf,smb_vwv1,fmode);
1628 if(lp_dos_filetime_resolution(SNUM(conn)) )
1629 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1630 else
1631 put_dos_date3(outbuf,smb_vwv2,mtime);
1632 SIVAL(outbuf,smb_vwv4,(uint32)size);
1633 SSVAL(outbuf,smb_vwv6,rmode);
1635 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1636 SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1639 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1640 SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1641 END_PROFILE(SMBopen);
1642 return(outsize);
1646 /****************************************************************************
1647 reply to an open and X
1648 ****************************************************************************/
1649 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1651 pstring fname;
1652 int smb_mode = SVAL(inbuf,smb_vwv3);
1653 int smb_attr = SVAL(inbuf,smb_vwv5);
1654 /* Breakout the oplock request bits so we can set the
1655 reply bits separately. */
1656 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1657 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1658 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1659 #if 0
1660 int open_flags = SVAL(inbuf,smb_vwv2);
1661 int smb_sattr = SVAL(inbuf,smb_vwv4);
1662 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1663 #endif
1664 int smb_ofun = SVAL(inbuf,smb_vwv8);
1665 mode_t unixmode;
1666 SMB_OFF_T size=0;
1667 int fmode=0,mtime=0,rmode=0;
1668 SMB_STRUCT_STAT sbuf;
1669 int smb_action = 0;
1670 BOOL bad_path = False;
1671 files_struct *fsp;
1672 START_PROFILE(SMBopenX);
1674 /* If it's an IPC, pass off the pipe handler. */
1675 if (IS_IPC(conn)) {
1676 if (lp_nt_pipe_support()) {
1677 END_PROFILE(SMBopenX);
1678 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1679 } else {
1680 END_PROFILE(SMBopenX);
1681 return ERROR_DOS(ERRSRV,ERRaccess);
1685 /* XXXX we need to handle passed times, sattr and flags */
1687 pstrcpy(fname,smb_buf(inbuf));
1689 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1691 unix_convert(fname,conn,0,&bad_path,&sbuf);
1693 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1695 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1696 oplock_request, &rmode,&smb_action);
1698 if (!fsp)
1700 set_bad_path_error(errno, bad_path);
1701 END_PROFILE(SMBopenX);
1702 return(UNIXERROR(ERRDOS,ERRnoaccess));
1705 size = sbuf.st_size;
1706 fmode = dos_mode(conn,fname,&sbuf);
1707 mtime = sbuf.st_mtime;
1708 if (fmode & aDIR) {
1709 close_file(fsp,False);
1710 END_PROFILE(SMBopenX);
1711 return ERROR_DOS(ERRDOS,ERRnoaccess);
1714 /* If the caller set the extended oplock request bit
1715 and we granted one (by whatever means) - set the
1716 correct bit for extended oplock reply.
1719 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1720 smb_action |= EXTENDED_OPLOCK_GRANTED;
1723 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1724 smb_action |= EXTENDED_OPLOCK_GRANTED;
1727 /* If the caller set the core oplock request bit
1728 and we granted one (by whatever means) - set the
1729 correct bit for core oplock reply.
1732 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1733 SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1736 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1737 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1740 set_message(outbuf,15,0,True);
1741 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1742 SSVAL(outbuf,smb_vwv3,fmode);
1743 if(lp_dos_filetime_resolution(SNUM(conn)) )
1744 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1745 else
1746 put_dos_date3(outbuf,smb_vwv4,mtime);
1747 SIVAL(outbuf,smb_vwv6,(uint32)size);
1748 SSVAL(outbuf,smb_vwv8,rmode);
1749 SSVAL(outbuf,smb_vwv11,smb_action);
1751 END_PROFILE(SMBopenX);
1752 return chain_reply(inbuf,outbuf,length,bufsize);
1756 /****************************************************************************
1757 reply to a SMBulogoffX
1758 ****************************************************************************/
1759 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1761 uint16 vuid = SVAL(inbuf,smb_uid);
1762 user_struct *vuser = get_valid_user_struct(vuid);
1763 START_PROFILE(SMBulogoffX);
1765 if(vuser == 0) {
1766 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1769 /* in user level security we are supposed to close any files
1770 open by this user */
1771 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1772 file_close_user(vuid);
1775 invalidate_vuid(vuid);
1777 set_message(outbuf,2,0,True);
1779 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1781 END_PROFILE(SMBulogoffX);
1782 return chain_reply(inbuf,outbuf,length,bufsize);
1786 /****************************************************************************
1787 reply to a mknew or a create
1788 ****************************************************************************/
1789 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1791 pstring fname;
1792 int com;
1793 int outsize = 0;
1794 int createmode;
1795 mode_t unixmode;
1796 int ofun = 0;
1797 BOOL bad_path = False;
1798 files_struct *fsp;
1799 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1800 SMB_STRUCT_STAT sbuf;
1801 START_PROFILE(SMBcreate);
1803 com = SVAL(inbuf,smb_com);
1805 createmode = SVAL(inbuf,smb_vwv0);
1806 pstrcpy(fname,smb_buf(inbuf)+1);
1808 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1810 unix_convert(fname,conn,0,&bad_path,&sbuf);
1812 if (createmode & aVOLID) {
1813 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1816 unixmode = unix_mode(conn,createmode,fname);
1818 if(com == SMBmknew)
1820 /* We should fail if file exists. */
1821 ofun = FILE_CREATE_IF_NOT_EXIST;
1823 else
1825 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1826 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1829 /* Open file in dos compatibility share mode. */
1830 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1831 ofun, unixmode, oplock_request, NULL, NULL);
1833 if (!fsp)
1835 set_bad_path_error(errno, bad_path);
1836 END_PROFILE(SMBcreate);
1837 return(UNIXERROR(ERRDOS,ERRnoaccess));
1840 outsize = set_message(outbuf,1,0,True);
1841 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1843 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1844 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1847 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1848 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1850 DEBUG( 2, ( "new file %s\n", fname ) );
1851 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1852 fname, fsp->fd, createmode, (int)unixmode ) );
1854 END_PROFILE(SMBcreate);
1855 return(outsize);
1859 /****************************************************************************
1860 reply to a create temporary file
1861 ****************************************************************************/
1862 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1864 pstring fname;
1865 int outsize = 0;
1866 int createmode;
1867 mode_t unixmode;
1868 BOOL bad_path = False;
1869 files_struct *fsp;
1870 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1871 int tmpfd;
1872 SMB_STRUCT_STAT sbuf;
1873 char *p, *s;
1875 START_PROFILE(SMBctemp);
1877 createmode = SVAL(inbuf,smb_vwv0);
1878 pstrcpy(fname,smb_buf(inbuf)+1);
1879 pstrcat(fname,"\\TMXXXXXX");
1881 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1883 unix_convert(fname,conn,0,&bad_path,&sbuf);
1885 unixmode = unix_mode(conn,createmode,fname);
1887 tmpfd = smb_mkstemp(fname);
1888 if (tmpfd == -1) {
1889 END_PROFILE(SMBctemp);
1890 return(UNIXERROR(ERRDOS,ERRnoaccess));
1893 vfs_stat(conn,fname,&sbuf);
1895 /* Open file in dos compatibility share mode. */
1896 /* We should fail if file does not exist. */
1897 fsp = open_file_shared(conn,fname,&sbuf,
1898 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1899 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1900 unixmode, oplock_request, NULL, NULL);
1901 /* close fd from smb_mkstemp() */
1902 close(tmpfd);
1904 if (!fsp) {
1905 set_bad_path_error(errno, bad_path);
1906 END_PROFILE(SMBctemp);
1907 return(UNIXERROR(ERRDOS,ERRnoaccess));
1910 /* the returned filename is relative to the directory */
1911 s = strrchr(fname, '/');
1912 if (!s)
1913 s = fname;
1914 else
1915 s++;
1917 outsize = set_message(outbuf,1,4+ strlen(fname),True);
1918 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1920 p = smb_buf(outbuf);
1921 SSVALS(p, 0, -1); /* what is this? not in spec */
1922 SSVAL(p, 2, strlen(s));
1923 p += 4;
1924 pstrcpy(p,s);
1926 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1927 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1930 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1931 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1933 DEBUG( 2, ( "created temp file %s\n", fname ) );
1934 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1935 fname, fsp->fd, createmode, (int)unixmode ) );
1937 END_PROFILE(SMBctemp);
1938 return(outsize);
1941 /*******************************************************************
1942 Check if a user is allowed to rename a file.
1943 ********************************************************************/
1945 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1947 int smb_action;
1948 int access_mode;
1949 files_struct *fsp;
1951 if (!CAN_WRITE(conn))
1952 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1954 if (S_ISDIR(pst->st_mode))
1955 return NT_STATUS_OK;
1957 /* We need a better way to return NT status codes from open... */
1958 unix_ERR_class = 0;
1959 unix_ERR_code = 0;
1961 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1962 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1964 if (!fsp) {
1965 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1966 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1967 ret = NT_STATUS_SHARING_VIOLATION;
1968 unix_ERR_class = 0;
1969 unix_ERR_code = 0;
1970 return ret;
1972 close_file(fsp,False);
1973 return NT_STATUS_OK;
1976 /*******************************************************************
1977 Check if a user is allowed to delete a file.
1978 ********************************************************************/
1980 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1982 SMB_STRUCT_STAT sbuf;
1983 int fmode;
1984 int smb_action;
1985 int access_mode;
1986 files_struct *fsp;
1988 if (!CAN_WRITE(conn))
1989 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1991 if (conn->vfs_ops.lstat(conn,dos_to_unix_static(fname),&sbuf) != 0)
1992 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1994 fmode = dos_mode(conn,fname,&sbuf);
1995 if (fmode & aDIR)
1996 return NT_STATUS_FILE_IS_A_DIRECTORY;
1997 if (!lp_delete_readonly(SNUM(conn))) {
1998 if (fmode & aRONLY)
1999 return NT_STATUS_CANNOT_DELETE;
2002 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
2003 return NT_STATUS_CANNOT_DELETE;
2005 /* We need a better way to return NT status codes from open... */
2006 unix_ERR_class = 0;
2007 unix_ERR_code = 0;
2009 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
2010 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
2012 if (!fsp) {
2013 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
2014 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
2015 ret = NT_STATUS_SHARING_VIOLATION;
2016 unix_ERR_class = 0;
2017 unix_ERR_code = 0;
2018 return ret;
2020 close_file(fsp,False);
2021 return NT_STATUS_OK;
2024 /****************************************************************************
2025 The guts of the unlink command, split out so it may be called by the NT SMB
2026 code.
2027 ****************************************************************************/
2029 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
2031 pstring directory;
2032 pstring mask;
2033 char *p;
2034 int count=0;
2035 NTSTATUS error = NT_STATUS_OK;
2036 BOOL has_wild;
2037 BOOL bad_path = False;
2038 BOOL rc = True;
2039 SMB_STRUCT_STAT sbuf;
2041 *directory = *mask = 0;
2043 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
2045 p = strrchr(name,'/');
2046 if (!p) {
2047 pstrcpy(directory,".");
2048 pstrcpy(mask,name);
2049 } else {
2050 *p = 0;
2051 pstrcpy(directory,name);
2052 pstrcpy(mask,p+1);
2056 * We should only check the mangled cache
2057 * here if unix_convert failed. This means
2058 * that the path in 'mask' doesn't exist
2059 * on the file system and so we need to look
2060 * for a possible mangle. This patch from
2061 * Tine Smukavec <valentin.smukavec@hermes.si>.
2064 if (!rc && mangle_is_mangled(mask))
2065 mangle_check_cache( mask );
2067 has_wild = ms_has_wild(mask);
2069 if (!has_wild) {
2070 pstrcat(directory,"/");
2071 pstrcat(directory,mask);
2072 error = can_delete(directory,conn,dirtype);
2073 if (!NT_STATUS_IS_OK(error))
2074 return error;
2076 if (vfs_unlink(conn,directory) == 0)
2077 count++;
2078 } else {
2079 void *dirptr = NULL;
2080 char *dname;
2081 if (check_name(directory,conn))
2082 dirptr = OpenDir(conn, directory, True);
2084 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2085 the pattern matches against the long name, otherwise the short name
2086 We don't implement this yet XXXX
2089 if (dirptr) {
2090 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2092 if (strequal(mask,"????????.???"))
2093 pstrcpy(mask,"*");
2095 while ((dname = ReadDirName(dirptr))) {
2096 pstring fname;
2097 pstrcpy(fname,dname);
2099 if(!mask_match(fname, mask, case_sensitive))
2100 continue;
2102 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2103 error = can_delete(fname,conn,dirtype);
2104 if (!NT_STATUS_IS_OK(error))
2105 continue;
2106 if (vfs_unlink(conn,fname) == 0)
2107 count++;
2108 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2110 CloseDir(dirptr);
2114 if (count == 0 && NT_STATUS_IS_OK(error))
2115 error = map_nt_error_from_unix(errno);
2117 return error;
2120 /****************************************************************************
2121 Reply to a unlink
2122 ****************************************************************************/
2124 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2126 int outsize = 0;
2127 pstring name;
2128 int dirtype;
2129 NTSTATUS status;
2131 START_PROFILE(SMBunlink);
2133 dirtype = SVAL(inbuf,smb_vwv0);
2135 pstrcpy(name,smb_buf(inbuf) + 1);
2137 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
2139 DEBUG(3,("reply_unlink : %s\n",name));
2141 status = unlink_internals(conn, dirtype, name);
2142 if (!NT_STATUS_IS_OK(status))
2143 return ERROR_NT(status);
2146 * Win2k needs a changenotify request response before it will
2147 * update after a rename..
2150 process_pending_change_notify_queue((time_t)0);
2152 outsize = set_message(outbuf,0,0,True);
2154 END_PROFILE(SMBunlink);
2155 return outsize;
2158 /****************************************************************************
2159 Fail for readbraw.
2160 ****************************************************************************/
2162 void fail_readraw(void)
2164 pstring errstr;
2165 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2166 strerror(errno) );
2167 exit_server(errstr);
2170 /****************************************************************************
2171 Reply to a readbraw (core+ protocol).
2172 ****************************************************************************/
2174 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2176 ssize_t maxcount,mincount;
2177 size_t nread = 0;
2178 SMB_OFF_T startpos;
2179 char *header = outbuf;
2180 ssize_t ret=0;
2181 files_struct *fsp;
2182 START_PROFILE(SMBreadbraw);
2185 * Special check if an oplock break has been issued
2186 * and the readraw request croses on the wire, we must
2187 * return a zero length response here.
2190 if(global_oplock_break) {
2191 _smb_setlen(header,0);
2192 if (write_data(smbd_server_fd(),header,4) != 4)
2193 fail_readraw();
2194 DEBUG(5,("readbraw - oplock break finished\n"));
2195 END_PROFILE(SMBreadbraw);
2196 return -1;
2199 fsp = file_fsp(inbuf,smb_vwv0);
2201 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2203 * fsp could be NULL here so use the value from the packet. JRA.
2205 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2206 _smb_setlen(header,0);
2207 if (write_data(smbd_server_fd(),header,4) != 4)
2208 fail_readraw();
2209 END_PROFILE(SMBreadbraw);
2210 return(-1);
2213 CHECK_FSP(fsp,conn);
2215 flush_write_cache(fsp, READRAW_FLUSH);
2217 startpos = IVAL(inbuf,smb_vwv1);
2218 if(CVAL(inbuf,smb_wct) == 10) {
2220 * This is a large offset (64 bit) read.
2222 #ifdef LARGE_SMB_OFF_T
2224 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2226 #else /* !LARGE_SMB_OFF_T */
2229 * Ensure we haven't been sent a >32 bit offset.
2232 if(IVAL(inbuf,smb_vwv8) != 0) {
2233 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2234 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2235 _smb_setlen(header,0);
2236 if (write_data(smbd_server_fd(),header,4) != 4)
2237 fail_readraw();
2238 END_PROFILE(SMBreadbraw);
2239 return(-1);
2242 #endif /* LARGE_SMB_OFF_T */
2244 if(startpos < 0) {
2245 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2246 _smb_setlen(header,0);
2247 if (write_data(smbd_server_fd(),header,4) != 4)
2248 fail_readraw();
2249 END_PROFILE(SMBreadbraw);
2250 return(-1);
2253 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2254 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2256 /* ensure we don't overrun the packet size */
2257 maxcount = MIN(65535,maxcount);
2258 maxcount = MAX(mincount,maxcount);
2260 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2261 SMB_OFF_T size = fsp->size;
2262 SMB_OFF_T sizeneeded = startpos + maxcount;
2264 if (size < sizeneeded) {
2265 SMB_STRUCT_STAT st;
2266 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2267 fsp->size = size = st.st_size;
2270 if (startpos >= size)
2271 nread = 0;
2272 else
2273 nread = MIN(maxcount,(size - startpos));
2276 if (nread < mincount)
2277 nread = 0;
2279 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2280 (int)maxcount, (int)mincount, (int)nread ) );
2282 if (nread > 0) {
2283 ret = read_file(fsp,header+4,startpos,nread);
2284 if (ret < mincount)
2285 ret = 0;
2288 _smb_setlen(header,ret);
2289 if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
2290 fail_readraw();
2292 DEBUG(5,("readbraw finished\n"));
2293 END_PROFILE(SMBreadbraw);
2294 return -1;
2298 /****************************************************************************
2299 reply to a lockread (core+ protocol)
2300 ****************************************************************************/
2301 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2303 ssize_t nread = -1;
2304 char *data;
2305 int outsize = 0;
2306 SMB_OFF_T startpos;
2307 size_t numtoread;
2308 NTSTATUS status;
2309 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2310 START_PROFILE(SMBlockread);
2312 CHECK_FSP(fsp,conn);
2313 CHECK_READ(fsp);
2315 release_level_2_oplocks_on_change(fsp);
2317 numtoread = SVAL(inbuf,smb_vwv1);
2318 startpos = IVAL(inbuf,smb_vwv2);
2320 outsize = set_message(outbuf,5,3,True);
2321 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2322 data = smb_buf(outbuf) + 3;
2325 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2326 * protocol request that predates the read/write lock concept.
2327 * Thus instead of asking for a read lock here we need to ask
2328 * for a write lock. JRA.
2331 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2332 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
2334 if (NT_STATUS_V(status)) {
2335 if (lp_blocking_locks(SNUM(conn))) {
2337 * A blocking lock was requested. Package up
2338 * this smb into a queued request and push it
2339 * onto the blocking lock queue.
2341 if(push_blocking_lock_request(inbuf, length, -1, 0))
2342 END_PROFILE(SMBlockread);
2343 return -1;
2345 END_PROFILE(SMBlockread);
2346 return ERROR_NT(status);
2349 nread = read_file(fsp,data,startpos,numtoread);
2351 if (nread < 0) {
2352 END_PROFILE(SMBlockread);
2353 return(UNIXERROR(ERRDOS,ERRnoaccess));
2356 outsize += nread;
2357 SSVAL(outbuf,smb_vwv0,nread);
2358 SSVAL(outbuf,smb_vwv5,nread+3);
2359 SSVAL(smb_buf(outbuf),1,nread);
2361 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2362 fsp->fnum, (int)numtoread, (int)nread ) );
2364 END_PROFILE(SMBlockread);
2365 return(outsize);
2369 /****************************************************************************
2370 reply to a read
2371 ****************************************************************************/
2373 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2375 size_t numtoread;
2376 ssize_t nread = 0;
2377 char *data;
2378 SMB_OFF_T startpos;
2379 int outsize = 0;
2380 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2381 START_PROFILE(SMBread);
2383 CHECK_FSP(fsp,conn);
2384 CHECK_READ(fsp);
2386 numtoread = SVAL(inbuf,smb_vwv1);
2387 startpos = IVAL(inbuf,smb_vwv2);
2389 outsize = set_message(outbuf,5,3,True);
2390 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2391 data = smb_buf(outbuf) + 3;
2393 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2394 END_PROFILE(SMBread);
2395 return ERROR_DOS(ERRDOS,ERRlock);
2398 if (numtoread > 0)
2399 nread = read_file(fsp,data,startpos,numtoread);
2401 if (nread < 0) {
2402 END_PROFILE(SMBread);
2403 return(UNIXERROR(ERRDOS,ERRnoaccess));
2406 outsize += nread;
2407 SSVAL(outbuf,smb_vwv0,nread);
2408 SSVAL(outbuf,smb_vwv5,nread+3);
2409 SCVAL(smb_buf(outbuf),0,1);
2410 SSVAL(smb_buf(outbuf),1,nread);
2412 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2413 fsp->fnum, (int)numtoread, (int)nread ) );
2415 END_PROFILE(SMBread);
2416 return(outsize);
2420 /****************************************************************************
2421 reply to a read and X
2422 ****************************************************************************/
2423 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2425 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2426 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2427 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2428 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2429 ssize_t nread = -1;
2430 char *data;
2431 START_PROFILE(SMBreadX);
2433 /* If it's an IPC, pass off the pipe handler. */
2434 if (IS_IPC(conn)) {
2435 END_PROFILE(SMBreadX);
2436 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2439 CHECK_FSP(fsp,conn);
2440 CHECK_READ(fsp);
2442 set_message(outbuf,12,0,True);
2443 data = smb_buf(outbuf);
2445 if(CVAL(inbuf,smb_wct) == 12) {
2446 #ifdef LARGE_SMB_OFF_T
2448 * This is a large offset (64 bit) read.
2450 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2452 #else /* !LARGE_SMB_OFF_T */
2455 * Ensure we haven't been sent a >32 bit offset.
2458 if(IVAL(inbuf,smb_vwv10) != 0) {
2459 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2460 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2461 END_PROFILE(SMBreadX);
2462 return ERROR_DOS(ERRDOS,ERRbadaccess);
2465 #endif /* LARGE_SMB_OFF_T */
2469 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2470 END_PROFILE(SMBreadX);
2471 return ERROR_DOS(ERRDOS,ERRlock);
2473 nread = read_file(fsp,data,startpos,smb_maxcnt);
2475 if (nread < 0) {
2476 END_PROFILE(SMBreadX);
2477 return(UNIXERROR(ERRDOS,ERRnoaccess));
2480 SSVAL(outbuf,smb_vwv5,nread);
2481 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2482 SSVAL(smb_buf(outbuf),-2,nread);
2484 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2485 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2487 END_PROFILE(SMBreadX);
2488 return chain_reply(inbuf,outbuf,length,bufsize);
2491 /****************************************************************************
2492 reply to a writebraw (core+ or LANMAN1.0 protocol)
2493 ****************************************************************************/
2495 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2497 ssize_t nwritten=0;
2498 ssize_t total_written=0;
2499 size_t numtowrite=0;
2500 size_t tcount;
2501 SMB_OFF_T startpos;
2502 char *data=NULL;
2503 BOOL write_through;
2504 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2505 int outsize = 0;
2506 START_PROFILE(SMBwritebraw);
2508 CHECK_FSP(fsp,conn);
2509 CHECK_WRITE(fsp);
2511 tcount = IVAL(inbuf,smb_vwv1);
2512 startpos = IVAL(inbuf,smb_vwv3);
2513 write_through = BITSETW(inbuf+smb_vwv7,0);
2515 /* We have to deal with slightly different formats depending
2516 on whether we are using the core+ or lanman1.0 protocol */
2518 if(Protocol <= PROTOCOL_COREPLUS) {
2519 numtowrite = SVAL(smb_buf(inbuf),-2);
2520 data = smb_buf(inbuf);
2521 } else {
2522 numtowrite = SVAL(inbuf,smb_vwv10);
2523 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2526 /* force the error type */
2527 SCVAL(inbuf,smb_com,SMBwritec);
2528 SCVAL(outbuf,smb_com,SMBwritec);
2530 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2531 END_PROFILE(SMBwritebraw);
2532 return(ERROR_DOS(ERRDOS,ERRlock));
2535 if (numtowrite>0)
2536 nwritten = write_file(fsp,data,startpos,numtowrite);
2538 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2539 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2541 if (nwritten < numtowrite) {
2542 END_PROFILE(SMBwritebraw);
2543 return(UNIXERROR(ERRHRD,ERRdiskfull));
2546 total_written = nwritten;
2548 /* Return a message to the redirector to tell it to send more bytes */
2549 SCVAL(outbuf,smb_com,SMBwritebraw);
2550 SSVALS(outbuf,smb_vwv0,-1);
2551 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2552 if (!send_smb(smbd_server_fd(),outbuf))
2553 exit_server("reply_writebraw: send_smb failed.");
2555 /* Now read the raw data into the buffer and write it */
2556 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2557 exit_server("secondary writebraw failed");
2560 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2561 numtowrite = smb_len(inbuf);
2563 /* Set up outbuf to return the correct return */
2564 outsize = set_message(outbuf,1,0,True);
2565 SCVAL(outbuf,smb_com,SMBwritec);
2566 SSVAL(outbuf,smb_vwv0,total_written);
2568 if (numtowrite != 0) {
2570 if (numtowrite > BUFFER_SIZE) {
2571 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2572 (unsigned int)numtowrite ));
2573 exit_server("secondary writebraw failed");
2576 if (tcount > nwritten+numtowrite) {
2577 DEBUG(3,("Client overestimated the write %d %d %d\n",
2578 (int)tcount,(int)nwritten,(int)numtowrite));
2581 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2582 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2583 strerror(errno) ));
2584 exit_server("secondary writebraw failed");
2587 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2589 if (nwritten < (ssize_t)numtowrite) {
2590 SCVAL(outbuf,smb_rcls,ERRHRD);
2591 SSVAL(outbuf,smb_err,ERRdiskfull);
2594 if (nwritten > 0)
2595 total_written += nwritten;
2598 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2599 sync_file(conn,fsp);
2601 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2602 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2604 /* we won't return a status if write through is not selected - this follows what WfWg does */
2605 END_PROFILE(SMBwritebraw);
2606 if (!write_through && total_written==tcount) {
2608 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2609 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2611 if (!send_keepalive(smbd_server_fd()))
2612 exit_server("reply_writebraw: send of keepalive failed");
2613 return(-1);
2616 return(outsize);
2619 /****************************************************************************
2620 reply to a writeunlock (core+)
2621 ****************************************************************************/
2623 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2625 ssize_t nwritten = -1;
2626 size_t numtowrite;
2627 SMB_OFF_T startpos;
2628 char *data;
2629 NTSTATUS status;
2630 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2631 int outsize = 0;
2632 START_PROFILE(SMBwriteunlock);
2634 CHECK_FSP(fsp,conn);
2635 CHECK_WRITE(fsp);
2637 numtowrite = SVAL(inbuf,smb_vwv1);
2638 startpos = IVAL(inbuf,smb_vwv2);
2639 data = smb_buf(inbuf) + 3;
2641 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2642 WRITE_LOCK,False)) {
2643 END_PROFILE(SMBwriteunlock);
2644 return ERROR_DOS(ERRDOS,ERRlock);
2647 /* The special X/Open SMB protocol handling of
2648 zero length writes is *NOT* done for
2649 this call */
2650 if(numtowrite == 0)
2651 nwritten = 0;
2652 else
2653 nwritten = write_file(fsp,data,startpos,numtowrite);
2655 if (lp_syncalways(SNUM(conn)))
2656 sync_file(conn,fsp);
2658 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2659 END_PROFILE(SMBwriteunlock);
2660 return(UNIXERROR(ERRDOS,ERRnoaccess));
2663 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2664 (SMB_BIG_UINT)startpos);
2665 if (NT_STATUS_V(status)) {
2666 END_PROFILE(SMBwriteunlock);
2667 return ERROR_NT(status);
2670 outsize = set_message(outbuf,1,0,True);
2672 SSVAL(outbuf,smb_vwv0,nwritten);
2674 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2675 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2677 END_PROFILE(SMBwriteunlock);
2678 return(outsize);
2682 /****************************************************************************
2683 Reply to a write.
2684 ****************************************************************************/
2686 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2688 size_t numtowrite;
2689 ssize_t nwritten = -1;
2690 SMB_OFF_T startpos;
2691 char *data;
2692 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2693 int outsize = 0;
2694 START_PROFILE(SMBwrite);
2696 /* If it's an IPC, pass off the pipe handler. */
2697 if (IS_IPC(conn)) {
2698 END_PROFILE(SMBwrite);
2699 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2702 CHECK_FSP(fsp,conn);
2703 CHECK_WRITE(fsp);
2705 numtowrite = SVAL(inbuf,smb_vwv1);
2706 startpos = IVAL(inbuf,smb_vwv2);
2707 data = smb_buf(inbuf) + 3;
2709 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2710 END_PROFILE(SMBwrite);
2711 return ERROR_DOS(ERRDOS,ERRlock);
2715 * X/Open SMB protocol says that if smb_vwv1 is
2716 * zero then the file size should be extended or
2717 * truncated to the size given in smb_vwv[2-3].
2720 if(numtowrite == 0) {
2722 * This is actually an allocate call, and set EOF. JRA.
2724 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2725 if (nwritten < 0) {
2726 END_PROFILE(SMBwrite);
2727 return ERROR_NT(NT_STATUS_DISK_FULL);
2729 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2730 if (nwritten < 0) {
2731 END_PROFILE(SMBwrite);
2732 return ERROR_NT(NT_STATUS_DISK_FULL);
2734 } else
2735 nwritten = write_file(fsp,data,startpos,numtowrite);
2737 if (lp_syncalways(SNUM(conn)))
2738 sync_file(conn,fsp);
2740 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2741 END_PROFILE(SMBwrite);
2742 return(UNIXERROR(ERRDOS,ERRnoaccess));
2745 outsize = set_message(outbuf,1,0,True);
2747 SSVAL(outbuf,smb_vwv0,nwritten);
2749 if (nwritten < (ssize_t)numtowrite) {
2750 SCVAL(outbuf,smb_rcls,ERRHRD);
2751 SSVAL(outbuf,smb_err,ERRdiskfull);
2754 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2756 END_PROFILE(SMBwrite);
2757 return(outsize);
2761 /****************************************************************************
2762 reply to a write and X
2763 ****************************************************************************/
2764 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2766 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2767 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2768 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2769 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2770 ssize_t nwritten = -1;
2771 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2772 unsigned int smblen = smb_len(inbuf);
2773 char *data;
2774 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2775 START_PROFILE(SMBwriteX);
2777 /* If it's an IPC, pass off the pipe handler. */
2778 if (IS_IPC(conn)) {
2779 END_PROFILE(SMBwriteX);
2780 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2783 CHECK_FSP(fsp,conn);
2784 CHECK_WRITE(fsp);
2786 /* Deal with possible LARGE_WRITEX */
2787 if (large_writeX)
2788 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2790 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2791 END_PROFILE(SMBwriteX);
2792 return ERROR_DOS(ERRDOS,ERRbadmem);
2795 data = smb_base(inbuf) + smb_doff;
2797 if(CVAL(inbuf,smb_wct) == 14) {
2798 #ifdef LARGE_SMB_OFF_T
2800 * This is a large offset (64 bit) write.
2802 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2804 #else /* !LARGE_SMB_OFF_T */
2807 * Ensure we haven't been sent a >32 bit offset.
2810 if(IVAL(inbuf,smb_vwv12) != 0) {
2811 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2812 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2813 END_PROFILE(SMBwriteX);
2814 return ERROR_DOS(ERRDOS,ERRbadaccess);
2817 #endif /* LARGE_SMB_OFF_T */
2820 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2821 END_PROFILE(SMBwriteX);
2822 return ERROR_DOS(ERRDOS,ERRlock);
2825 /* X/Open SMB protocol says that, unlike SMBwrite
2826 if the length is zero then NO truncation is
2827 done, just a write of zero. To truncate a file,
2828 use SMBwrite. */
2829 if(numtowrite == 0)
2830 nwritten = 0;
2831 else
2832 nwritten = write_file(fsp,data,startpos,numtowrite);
2834 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2835 END_PROFILE(SMBwriteX);
2836 return(UNIXERROR(ERRDOS,ERRnoaccess));
2839 set_message(outbuf,6,0,True);
2841 SSVAL(outbuf,smb_vwv2,nwritten);
2842 if (large_writeX)
2843 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2845 if (nwritten < (ssize_t)numtowrite) {
2846 SCVAL(outbuf,smb_rcls,ERRHRD);
2847 SSVAL(outbuf,smb_err,ERRdiskfull);
2850 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2851 fsp->fnum, (int)numtowrite, (int)nwritten));
2853 if (lp_syncalways(SNUM(conn)) || write_through)
2854 sync_file(conn,fsp);
2856 END_PROFILE(SMBwriteX);
2857 return chain_reply(inbuf,outbuf,length,bufsize);
2861 /****************************************************************************
2862 reply to a lseek
2863 ****************************************************************************/
2865 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2867 SMB_OFF_T startpos;
2868 SMB_OFF_T res= -1;
2869 int mode,umode;
2870 int outsize = 0;
2871 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2872 START_PROFILE(SMBlseek);
2874 CHECK_FSP(fsp,conn);
2876 flush_write_cache(fsp, SEEK_FLUSH);
2878 mode = SVAL(inbuf,smb_vwv1) & 3;
2879 startpos = IVALS(inbuf,smb_vwv2);
2881 switch (mode) {
2882 case 0: umode = SEEK_SET; break;
2883 case 1: umode = SEEK_CUR; break;
2884 case 2: umode = SEEK_END; break;
2885 default:
2886 umode = SEEK_SET; break;
2889 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2891 * Check for the special case where a seek before the start
2892 * of the file sets the offset to zero. Added in the CIFS spec,
2893 * section 4.2.7.
2896 if(errno == EINVAL) {
2897 SMB_OFF_T current_pos = startpos;
2899 if(umode == SEEK_CUR) {
2901 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2902 END_PROFILE(SMBlseek);
2903 return(UNIXERROR(ERRDOS,ERRnoaccess));
2906 current_pos += startpos;
2908 } else if (umode == SEEK_END) {
2910 SMB_STRUCT_STAT sbuf;
2912 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2913 END_PROFILE(SMBlseek);
2914 return(UNIXERROR(ERRDOS,ERRnoaccess));
2917 current_pos += sbuf.st_size;
2920 if(current_pos < 0)
2921 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2924 if(res == -1) {
2925 END_PROFILE(SMBlseek);
2926 return(UNIXERROR(ERRDOS,ERRnoaccess));
2930 fsp->pos = res;
2932 outsize = set_message(outbuf,2,0,True);
2933 SIVAL(outbuf,smb_vwv0,res);
2935 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2936 fsp->fnum, (double)startpos, (double)res, mode));
2938 END_PROFILE(SMBlseek);
2939 return(outsize);
2942 /****************************************************************************
2943 Reply to a flush.
2944 ****************************************************************************/
2946 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2948 int outsize = set_message(outbuf,0,0,True);
2949 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2950 START_PROFILE(SMBflush);
2952 CHECK_FSP(fsp,conn);
2954 if (!fsp) {
2955 file_sync_all(conn);
2956 } else {
2957 sync_file(conn,fsp);
2960 DEBUG(3,("flush\n"));
2961 END_PROFILE(SMBflush);
2962 return(outsize);
2965 /****************************************************************************
2966 reply to a exit
2967 ****************************************************************************/
2968 int reply_exit(connection_struct *conn,
2969 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2971 int outsize;
2972 START_PROFILE(SMBexit);
2973 outsize = set_message(outbuf,0,0,True);
2975 DEBUG(3,("exit\n"));
2977 END_PROFILE(SMBexit);
2978 return(outsize);
2982 /****************************************************************************
2983 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2984 ****************************************************************************/
2985 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2986 int dum_buffsize)
2988 int outsize = 0;
2989 time_t mtime;
2990 files_struct *fsp = NULL;
2991 START_PROFILE(SMBclose);
2993 outsize = set_message(outbuf,0,0,True);
2995 /* If it's an IPC, pass off to the pipe handler. */
2996 if (IS_IPC(conn)) {
2997 END_PROFILE(SMBclose);
2998 return reply_pipe_close(conn, inbuf,outbuf);
3001 fsp = file_fsp(inbuf,smb_vwv0);
3004 * We can only use CHECK_FSP if we know it's not a directory.
3007 if(!fsp || (fsp->conn != conn)) {
3008 END_PROFILE(SMBclose);
3009 return ERROR_DOS(ERRDOS,ERRbadfid);
3012 if(fsp->is_directory) {
3014 * Special case - close NT SMB directory handle.
3016 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3017 close_file(fsp,True);
3018 } else {
3020 * Close ordinary file.
3022 int close_err;
3023 pstring file_name;
3025 /* Save the name for time set in close. */
3026 pstrcpy( file_name, fsp->fsp_name);
3028 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3029 fsp->fd, fsp->fnum,
3030 conn->num_files_open));
3033 * close_file() returns the unix errno if an error
3034 * was detected on close - normally this is due to
3035 * a disk full error. If not then it was probably an I/O error.
3038 if((close_err = close_file(fsp,True)) != 0) {
3039 errno = close_err;
3040 END_PROFILE(SMBclose);
3041 return (UNIXERROR(ERRHRD,ERRgeneral));
3045 * Now take care of any time sent in the close.
3048 mtime = make_unix_date3(inbuf+smb_vwv1);
3050 /* try and set the date */
3051 set_filetime(conn, file_name, mtime);
3055 END_PROFILE(SMBclose);
3056 return(outsize);
3060 /****************************************************************************
3061 reply to a writeclose (Core+ protocol)
3062 ****************************************************************************/
3064 int reply_writeclose(connection_struct *conn,
3065 char *inbuf,char *outbuf, int size, int dum_buffsize)
3067 size_t numtowrite;
3068 ssize_t nwritten = -1;
3069 int outsize = 0;
3070 int close_err = 0;
3071 SMB_OFF_T startpos;
3072 char *data;
3073 time_t mtime;
3074 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3075 START_PROFILE(SMBwriteclose);
3077 CHECK_FSP(fsp,conn);
3078 CHECK_WRITE(fsp);
3080 numtowrite = SVAL(inbuf,smb_vwv1);
3081 startpos = IVAL(inbuf,smb_vwv2);
3082 mtime = make_unix_date3(inbuf+smb_vwv4);
3083 data = smb_buf(inbuf) + 1;
3085 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
3086 END_PROFILE(SMBwriteclose);
3087 return ERROR_DOS(ERRDOS,ERRlock);
3090 nwritten = write_file(fsp,data,startpos,numtowrite);
3092 set_filetime(conn, fsp->fsp_name,mtime);
3094 close_err = close_file(fsp,True);
3096 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3097 fsp->fnum, (int)numtowrite, (int)nwritten,
3098 conn->num_files_open));
3100 if (nwritten <= 0) {
3101 END_PROFILE(SMBwriteclose);
3102 return(UNIXERROR(ERRDOS,ERRnoaccess));
3105 if(close_err != 0) {
3106 errno = close_err;
3107 END_PROFILE(SMBwriteclose);
3108 return(UNIXERROR(ERRHRD,ERRgeneral));
3111 outsize = set_message(outbuf,1,0,True);
3113 SSVAL(outbuf,smb_vwv0,nwritten);
3114 END_PROFILE(SMBwriteclose);
3115 return(outsize);
3119 /****************************************************************************
3120 reply to a lock
3121 ****************************************************************************/
3122 int reply_lock(connection_struct *conn,
3123 char *inbuf,char *outbuf, int length, int dum_buffsize)
3125 int outsize = set_message(outbuf,0,0,True);
3126 SMB_BIG_UINT count,offset;
3127 NTSTATUS status;
3128 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3129 START_PROFILE(SMBlock);
3131 CHECK_FSP(fsp,conn);
3133 release_level_2_oplocks_on_change(fsp);
3135 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3136 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3138 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3139 fsp->fd, fsp->fnum, (double)offset, (double)count));
3141 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
3142 if (NT_STATUS_V(status)) {
3143 if (lp_blocking_locks(SNUM(conn))) {
3145 * A blocking lock was requested. Package up
3146 * this smb into a queued request and push it
3147 * onto the blocking lock queue.
3149 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
3150 END_PROFILE(SMBlock);
3151 return -1;
3154 END_PROFILE(SMBlock);
3155 return ERROR_NT(status);
3158 END_PROFILE(SMBlock);
3159 return(outsize);
3163 /****************************************************************************
3164 reply to a unlock
3165 ****************************************************************************/
3166 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3168 int outsize = set_message(outbuf,0,0,True);
3169 SMB_BIG_UINT count,offset;
3170 NTSTATUS status;
3171 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3172 START_PROFILE(SMBunlock);
3174 CHECK_FSP(fsp,conn);
3176 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3177 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3179 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3180 if (NT_STATUS_V(status)) {
3181 END_PROFILE(SMBunlock);
3182 return ERROR_NT(status);
3185 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3186 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3188 END_PROFILE(SMBunlock);
3189 return(outsize);
3193 /****************************************************************************
3194 reply to a tdis
3195 ****************************************************************************/
3196 int reply_tdis(connection_struct *conn,
3197 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3199 int outsize = set_message(outbuf,0,0,True);
3200 uint16 vuid;
3201 START_PROFILE(SMBtdis);
3203 vuid = SVAL(inbuf,smb_uid);
3205 if (!conn) {
3206 DEBUG(4,("Invalid connection in tdis\n"));
3207 END_PROFILE(SMBtdis);
3208 return ERROR_DOS(ERRSRV,ERRinvnid);
3211 conn->used = False;
3213 close_cnum(conn,vuid);
3215 END_PROFILE(SMBtdis);
3216 return outsize;
3221 /****************************************************************************
3222 reply to a echo
3223 ****************************************************************************/
3224 int reply_echo(connection_struct *conn,
3225 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3227 int smb_reverb = SVAL(inbuf,smb_vwv0);
3228 int seq_num;
3229 unsigned int data_len = smb_buflen(inbuf);
3230 int outsize = set_message(outbuf,1,data_len,True);
3231 START_PROFILE(SMBecho);
3233 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3235 /* copy any incoming data back out */
3236 if (data_len > 0)
3237 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3239 if (smb_reverb > 100) {
3240 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3241 smb_reverb = 100;
3244 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3245 SSVAL(outbuf,smb_vwv0,seq_num);
3247 smb_setlen(outbuf,outsize - 4);
3249 if (!send_smb(smbd_server_fd(),outbuf))
3250 exit_server("reply_echo: send_smb failed.");
3253 DEBUG(3,("echo %d times\n", smb_reverb));
3255 smb_echo_count++;
3257 END_PROFILE(SMBecho);
3258 return -1;
3262 /****************************************************************************
3263 reply to a printopen
3264 ****************************************************************************/
3265 int reply_printopen(connection_struct *conn,
3266 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3268 int outsize = 0;
3269 files_struct *fsp;
3270 START_PROFILE(SMBsplopen);
3272 if (!CAN_PRINT(conn)) {
3273 END_PROFILE(SMBsplopen);
3274 return ERROR_DOS(ERRDOS,ERRnoaccess);
3277 /* Open for exclusive use, write only. */
3278 fsp = print_fsp_open(conn, NULL);
3280 if (!fsp) {
3281 END_PROFILE(SMBsplopen);
3282 return(UNIXERROR(ERRDOS,ERRnoaccess));
3285 outsize = set_message(outbuf,1,0,True);
3286 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3288 DEBUG(3,("openprint fd=%d fnum=%d\n",
3289 fsp->fd, fsp->fnum));
3291 END_PROFILE(SMBsplopen);
3292 return(outsize);
3296 /****************************************************************************
3297 reply to a printclose
3298 ****************************************************************************/
3299 int reply_printclose(connection_struct *conn,
3300 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3302 int outsize = set_message(outbuf,0,0,True);
3303 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3304 int close_err = 0;
3305 START_PROFILE(SMBsplclose);
3307 CHECK_FSP(fsp,conn);
3309 if (!CAN_PRINT(conn)) {
3310 END_PROFILE(SMBsplclose);
3311 return ERROR_DOS(ERRDOS,ERRnoaccess);
3314 DEBUG(3,("printclose fd=%d fnum=%d\n",
3315 fsp->fd,fsp->fnum));
3317 close_err = close_file(fsp,True);
3319 if(close_err != 0) {
3320 errno = close_err;
3321 END_PROFILE(SMBsplclose);
3322 return(UNIXERROR(ERRHRD,ERRgeneral));
3325 END_PROFILE(SMBsplclose);
3326 return(outsize);
3330 /****************************************************************************
3331 reply to a printqueue
3332 ****************************************************************************/
3333 int reply_printqueue(connection_struct *conn,
3334 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3336 int outsize = set_message(outbuf,2,3,True);
3337 int max_count = SVAL(inbuf,smb_vwv0);
3338 int start_index = SVAL(inbuf,smb_vwv1);
3339 START_PROFILE(SMBsplretq);
3341 /* we used to allow the client to get the cnum wrong, but that
3342 is really quite gross and only worked when there was only
3343 one printer - I think we should now only accept it if they
3344 get it right (tridge) */
3345 if (!CAN_PRINT(conn)) {
3346 END_PROFILE(SMBsplretq);
3347 return ERROR_DOS(ERRDOS,ERRnoaccess);
3350 SSVAL(outbuf,smb_vwv0,0);
3351 SSVAL(outbuf,smb_vwv1,0);
3352 SCVAL(smb_buf(outbuf),0,1);
3353 SSVAL(smb_buf(outbuf),1,0);
3355 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3356 start_index, max_count));
3359 print_queue_struct *queue = NULL;
3360 print_status_struct status;
3361 char *p = smb_buf(outbuf) + 3;
3362 int count = print_queue_status(SNUM(conn), &queue, &status);
3363 int num_to_get = ABS(max_count);
3364 int first = (max_count>0?start_index:start_index+max_count+1);
3365 int i;
3367 if (first >= count)
3368 num_to_get = 0;
3369 else
3370 num_to_get = MIN(num_to_get,count-first);
3373 for (i=first;i<first+num_to_get;i++) {
3374 put_dos_date2(p,0,queue[i].time);
3375 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3376 SSVAL(p,5, queue[i].job);
3377 SIVAL(p,7,queue[i].size);
3378 SCVAL(p,11,0);
3379 StrnCpy(p+12,queue[i].fs_user,16);
3380 p += 28;
3383 if (count > 0) {
3384 outsize = set_message(outbuf,2,28*count+3,False);
3385 SSVAL(outbuf,smb_vwv0,count);
3386 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3387 SCVAL(smb_buf(outbuf),0,1);
3388 SSVAL(smb_buf(outbuf),1,28*count);
3391 SAFE_FREE(queue);
3393 DEBUG(3,("%d entries returned in queue\n",count));
3396 END_PROFILE(SMBsplretq);
3397 return(outsize);
3401 /****************************************************************************
3402 reply to a printwrite
3403 ****************************************************************************/
3404 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3406 int numtowrite;
3407 int outsize = set_message(outbuf,0,0,True);
3408 char *data;
3409 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3410 START_PROFILE(SMBsplwr);
3412 if (!CAN_PRINT(conn)) {
3413 END_PROFILE(SMBsplwr);
3414 return ERROR_DOS(ERRDOS,ERRnoaccess);
3417 CHECK_FSP(fsp,conn);
3418 CHECK_WRITE(fsp);
3420 numtowrite = SVAL(smb_buf(inbuf),1);
3421 data = smb_buf(inbuf) + 3;
3423 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3424 END_PROFILE(SMBsplwr);
3425 return(UNIXERROR(ERRDOS,ERRnoaccess));
3428 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3430 END_PROFILE(SMBsplwr);
3431 return(outsize);
3435 /****************************************************************************
3436 The guts of the mkdir command, split out so it may be called by the NT SMB
3437 code.
3438 ****************************************************************************/
3439 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3441 BOOL bad_path = False;
3442 SMB_STRUCT_STAT sbuf;
3443 int ret= -1;
3445 unix_convert(directory,conn,0,&bad_path,&sbuf);
3447 if (check_name(directory, conn))
3448 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3450 if (ret == -1) {
3451 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
3452 if (!NT_STATUS_IS_OK(nterr))
3453 return nterr;
3454 return map_nt_error_from_unix(errno);
3457 return NT_STATUS_OK;
3460 /****************************************************************************
3461 Reply to a mkdir.
3462 ****************************************************************************/
3464 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3466 pstring directory;
3467 int outsize;
3468 NTSTATUS status;
3469 START_PROFILE(SMBmkdir);
3471 pstrcpy(directory,smb_buf(inbuf) + 1);
3473 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3475 status = mkdir_internal(conn, directory);
3476 if (!NT_STATUS_IS_OK(status))
3477 return ERROR_NT(status);
3479 outsize = set_message(outbuf,0,0,True);
3481 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3483 END_PROFILE(SMBmkdir);
3484 return(outsize);
3487 /****************************************************************************
3488 Static function used by reply_rmdir to delete an entire directory
3489 tree recursively. Return False on ok, True on fail.
3490 ****************************************************************************/
3492 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3494 char *dname = NULL;
3495 BOOL ret = False;
3496 void *dirptr = OpenDir(conn, directory, False);
3498 if(dirptr == NULL)
3499 return True;
3501 while((dname = ReadDirName(dirptr))) {
3502 pstring fullname;
3503 SMB_STRUCT_STAT st;
3505 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3506 continue;
3508 /* Construct the full name. */
3509 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3510 errno = ENOMEM;
3511 ret = True;
3512 break;
3515 pstrcpy(fullname, directory);
3516 pstrcat(fullname, "/");
3517 pstrcat(fullname, dname);
3519 if(conn->vfs_ops.lstat(conn,dos_to_unix_static(fullname), &st) != 0) {
3520 ret = True;
3521 break;
3524 if(st.st_mode & S_IFDIR) {
3525 if(recursive_rmdir(conn, fullname)!=0) {
3526 ret = True;
3527 break;
3529 if(vfs_rmdir(conn,fullname) != 0) {
3530 ret = True;
3531 break;
3533 } else if(vfs_unlink(conn,fullname) != 0) {
3534 ret = True;
3535 break;
3539 CloseDir(dirptr);
3540 return ret;
3543 /****************************************************************************
3544 The internals of the rmdir code - called elsewhere.
3545 ****************************************************************************/
3547 BOOL rmdir_internals(connection_struct *conn, char *directory)
3549 BOOL ok;
3551 ok = (vfs_rmdir(conn,directory) == 0);
3552 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3554 * Check to see if the only thing in this directory are
3555 * vetoed files/directories. If so then delete them and
3556 * retry. If we fail to delete any of them (and we *don't*
3557 * do a recursive delete) then fail the rmdir.
3559 BOOL all_veto_files = True;
3560 char *dname;
3561 void *dirptr = OpenDir(conn, directory, False);
3563 if(dirptr != NULL) {
3564 int dirpos = TellDir(dirptr);
3565 while ((dname = ReadDirName(dirptr))) {
3566 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3567 continue;
3568 if(!IS_VETO_PATH(conn, dname)) {
3569 all_veto_files = False;
3570 break;
3573 if(all_veto_files) {
3574 SeekDir(dirptr,dirpos);
3575 while ((dname = ReadDirName(dirptr))) {
3576 pstring fullname;
3577 SMB_STRUCT_STAT st;
3579 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3580 continue;
3582 /* Construct the full name. */
3583 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3584 errno = ENOMEM;
3585 break;
3587 pstrcpy(fullname, directory);
3588 pstrcat(fullname, "/");
3589 pstrcat(fullname, dname);
3591 if(conn->vfs_ops.lstat(conn,dos_to_unix_static(fullname), &st) != 0)
3592 break;
3593 if(st.st_mode & S_IFDIR) {
3594 if(lp_recursive_veto_delete(SNUM(conn))) {
3595 if(recursive_rmdir(conn, fullname) != 0)
3596 break;
3598 if(vfs_rmdir(conn,fullname) != 0)
3599 break;
3600 } else if(vfs_unlink(conn,fullname) != 0)
3601 break;
3603 CloseDir(dirptr);
3604 /* Retry the rmdir */
3605 ok = (vfs_rmdir(conn,directory) == 0);
3606 } else {
3607 CloseDir(dirptr);
3609 } else {
3610 errno = ENOTEMPTY;
3614 if (!ok)
3615 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3617 return ok;
3620 /****************************************************************************
3621 Reply to a rmdir.
3622 ****************************************************************************/
3624 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3626 pstring directory;
3627 int outsize = 0;
3628 BOOL ok = False;
3629 BOOL bad_path = False;
3630 SMB_STRUCT_STAT sbuf;
3631 START_PROFILE(SMBrmdir);
3633 pstrcpy(directory,smb_buf(inbuf) + 1);
3635 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3637 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3639 if (check_name(directory,conn))
3641 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3642 ok = rmdir_internals(conn, directory);
3645 if (!ok)
3647 set_bad_path_error(errno, bad_path);
3648 END_PROFILE(SMBrmdir);
3649 return(UNIXERROR(ERRDOS,ERRbadpath));
3652 outsize = set_message(outbuf,0,0,True);
3654 DEBUG( 3, ( "rmdir %s\n", directory ) );
3656 END_PROFILE(SMBrmdir);
3657 return(outsize);
3661 /*******************************************************************
3662 resolve wildcards in a filename rename
3663 ********************************************************************/
3664 static BOOL resolve_wildcards(char *name1,char *name2)
3666 fstring root1,root2;
3667 fstring ext1,ext2;
3668 char *p,*p2;
3670 name1 = strrchr(name1,'/');
3671 name2 = strrchr(name2,'/');
3673 if (!name1 || !name2) return(False);
3675 fstrcpy(root1,name1);
3676 fstrcpy(root2,name2);
3677 p = strrchr(root1,'.');
3678 if (p) {
3679 *p = 0;
3680 fstrcpy(ext1,p+1);
3681 } else {
3682 fstrcpy(ext1,"");
3684 p = strrchr(root2,'.');
3685 if (p) {
3686 *p = 0;
3687 fstrcpy(ext2,p+1);
3688 } else {
3689 fstrcpy(ext2,"");
3692 p = root1;
3693 p2 = root2;
3694 while (*p2) {
3695 if (*p2 == '?') {
3696 *p2 = *p;
3697 p2++;
3698 } else {
3699 p2++;
3701 if (*p) p++;
3704 p = ext1;
3705 p2 = ext2;
3706 while (*p2) {
3707 if (*p2 == '?') {
3708 *p2 = *p;
3709 p2++;
3710 } else {
3711 p2++;
3713 if (*p) p++;
3716 pstrcpy(name2,root2);
3717 if (ext2[0]) {
3718 pstrcat(name2,".");
3719 pstrcat(name2,ext2);
3722 return(True);
3725 /****************************************************************************
3726 The guts of the rename command, split out so it may be called by the NT SMB
3727 code.
3728 ****************************************************************************/
3730 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3732 pstring directory;
3733 pstring mask;
3734 pstring newname_last_component;
3735 char *p;
3736 BOOL has_wild;
3737 BOOL bad_path1 = False;
3738 BOOL bad_path2 = False;
3739 int count=0;
3740 NTSTATUS error = NT_STATUS_OK;
3741 BOOL rc = True;
3742 SMB_STRUCT_STAT sbuf1, sbuf2;
3744 *directory = *mask = 0;
3746 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3747 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3750 * Split the old name into directory and last component
3751 * strings. Note that unix_convert may have stripped off a
3752 * leading ./ from both name and newname if the rename is
3753 * at the root of the share. We need to make sure either both
3754 * name and newname contain a / character or neither of them do
3755 * as this is checked in resolve_wildcards().
3758 p = strrchr(name,'/');
3759 if (!p) {
3760 pstrcpy(directory,".");
3761 pstrcpy(mask,name);
3762 } else {
3763 *p = 0;
3764 pstrcpy(directory,name);
3765 pstrcpy(mask,p+1);
3766 *p = '/'; /* Replace needed for exceptional test below. */
3770 * We should only check the mangled cache
3771 * here if unix_convert failed. This means
3772 * that the path in 'mask' doesn't exist
3773 * on the file system and so we need to look
3774 * for a possible mangle. This patch from
3775 * Tine Smukavec <valentin.smukavec@hermes.si>.
3778 if (!rc && mangle_is_mangled(mask))
3779 mangle_check_cache( mask );
3781 has_wild = ms_has_wild(mask);
3783 if (!has_wild) {
3784 pstring zdirectory;
3785 pstring znewname;
3788 * No wildcards - just process the one file.
3790 BOOL is_short_name = mangle_is_8_3(name, True);
3792 /* Add a terminating '/' to the directory name. */
3793 pstrcat(directory,"/");
3794 pstrcat(directory,mask);
3796 /* Ensure newname contains a '/' also */
3797 if(strrchr(newname,'/') == 0) {
3798 pstring tmpstr;
3800 pstrcpy(tmpstr, "./");
3801 pstrcat(tmpstr, newname);
3802 pstrcpy(newname, tmpstr);
3805 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3806 directory = %s, newname = %s, newname_last_component = %s, mangle_is_8_3 = %d\n",
3807 case_sensitive, case_preserve, short_case_preserve, directory,
3808 newname, newname_last_component, is_short_name));
3811 * Check for special case with case preserving and not
3812 * case sensitive, if directory and newname are identical,
3813 * and the old last component differs from the original
3814 * last component only by case, then we should allow
3815 * the rename (user is trying to change the case of the
3816 * filename).
3818 if((case_sensitive == False) &&
3819 (((case_preserve == True) &&
3820 (is_short_name == False)) ||
3821 ((short_case_preserve == True) &&
3822 (is_short_name == True))) &&
3823 strcsequal(directory, newname)) {
3824 pstring newname_modified_last_component;
3827 * Get the last component of the modified name.
3828 * Note that we guarantee that newname contains a '/'
3829 * character above.
3831 p = strrchr(newname,'/');
3832 pstrcpy(newname_modified_last_component,p+1);
3834 if(strcsequal(newname_modified_last_component,
3835 newname_last_component) == False) {
3837 * Replace the modified last component with
3838 * the original.
3840 pstrcpy(p+1, newname_last_component);
3845 resolve_wildcards(directory,newname);
3848 * The source object must exist.
3851 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3852 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3853 directory,newname));
3855 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3857 * Must return different errors depending on whether the parent
3858 * directory existed or not.
3861 p = strrchr(directory, '/');
3862 if (!p)
3863 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3864 *p = '\0';
3865 if (vfs_object_exist(conn, directory, NULL))
3866 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3867 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3869 error = map_nt_error_from_unix(errno);
3870 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3871 get_nt_error_msg(error), directory,newname));
3873 return error;
3876 error = can_rename(directory,conn,&sbuf1);
3878 if (!NT_STATUS_IS_OK(error)) {
3879 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3880 get_nt_error_msg(error), directory,newname));
3881 return error;
3884 pstrcpy(zdirectory, dos_to_unix_static(directory));
3885 pstrcpy(znewname, dos_to_unix_static(newname));
3888 * If the src and dest names are identical - including case,
3889 * don't do the rename, just return success.
3892 if (strcsequal(zdirectory, znewname)) {
3893 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3894 return NT_STATUS_OK;
3897 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3898 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3899 directory,newname));
3900 return NT_STATUS_OBJECT_NAME_COLLISION;
3903 if(conn->vfs_ops.rename(conn,zdirectory, znewname) == 0) {
3904 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3905 directory,newname));
3906 return NT_STATUS_OK;
3909 if (errno == ENOTDIR || errno == EISDIR)
3910 error = NT_STATUS_OBJECT_NAME_COLLISION;
3911 else
3912 error = map_nt_error_from_unix(errno);
3914 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3915 get_nt_error_msg(error), directory,newname));
3917 return error;
3918 } else {
3921 * Wildcards - process each file that matches.
3923 void *dirptr = NULL;
3924 char *dname;
3925 pstring destname;
3927 if (check_name(directory,conn))
3928 dirptr = OpenDir(conn, directory, True);
3930 if (dirptr) {
3931 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3933 if (strequal(mask,"????????.???"))
3934 pstrcpy(mask,"*");
3936 while ((dname = ReadDirName(dirptr))) {
3937 pstring fname;
3939 pstrcpy(fname,dname);
3941 if(!mask_match(fname, mask, case_sensitive))
3942 continue;
3944 error = NT_STATUS_ACCESS_DENIED;
3945 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3946 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3947 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3948 DEBUG(6,("rename %s failed. Error %s\n", fname, get_nt_error_msg(error)));
3949 continue;
3951 error = can_rename(fname,conn,&sbuf1);
3952 if (!NT_STATUS_IS_OK(error)) {
3953 DEBUG(6,("rename %s failed. Error %s\n", fname, get_nt_error_msg(error)));
3954 continue;
3956 pstrcpy(destname,newname);
3958 if (!resolve_wildcards(fname,destname)) {
3959 DEBUG(6,("resolve_wildcards %s %s failed\n",
3960 fname, destname));
3961 continue;
3964 if (!replace_if_exists &&
3965 vfs_object_exist(conn,destname, NULL)) {
3966 DEBUG(6,("file_exist %s\n", destname));
3967 error = NT_STATUS_OBJECT_NAME_COLLISION;
3968 continue;
3971 if (!conn->vfs_ops.rename(conn,dos_to_unix_static(fname),
3972 dos_to_unix_static(destname)))
3973 count++;
3974 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3976 CloseDir(dirptr);
3980 if (count == 0 && NT_STATUS_IS_OK(error)) {
3981 error = map_nt_error_from_unix(errno);
3984 return error;
3987 /****************************************************************************
3988 Reply to a mv.
3989 ****************************************************************************/
3991 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3993 int outsize = 0;
3994 pstring name;
3995 pstring newname;
3996 NTSTATUS status;
3997 START_PROFILE(SMBmv);
3999 pstrcpy(name,smb_buf(inbuf) + 1);
4000 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
4002 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4003 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4005 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4007 status = rename_internals(conn, name, newname, False);
4008 if (!NT_STATUS_IS_OK(status)) {
4009 return ERROR_NT(status);
4013 * Win2k needs a changenotify request response before it will
4014 * update after a rename..
4016 process_pending_change_notify_queue((time_t)0);
4017 outsize = set_message(outbuf,0,0,True);
4019 END_PROFILE(SMBmv);
4020 return(outsize);
4023 /*******************************************************************
4024 Copy a file as part of a reply_copy.
4025 ******************************************************************/
4027 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4028 int count,BOOL target_is_directory, int *err_ret)
4030 int Access,action;
4031 SMB_STRUCT_STAT src_sbuf, sbuf2;
4032 SMB_OFF_T ret=-1;
4033 files_struct *fsp1,*fsp2;
4034 pstring dest;
4036 *err_ret = 0;
4038 pstrcpy(dest,dest1);
4039 if (target_is_directory) {
4040 char *p = strrchr(src,'/');
4041 if (p)
4042 p++;
4043 else
4044 p = src;
4045 pstrcat(dest,"/");
4046 pstrcat(dest,p);
4049 if (!vfs_file_exist(conn,src,&src_sbuf))
4050 return(False);
4052 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4053 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
4055 if (!fsp1)
4056 return(False);
4058 if (!target_is_directory && count)
4059 ofun = FILE_EXISTS_OPEN;
4061 if (vfs_stat(conn,dest,&sbuf2) == -1)
4062 ZERO_STRUCTP(&sbuf2);
4064 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4065 ofun,src_sbuf.st_mode,0,&Access,&action);
4067 if (!fsp2) {
4068 close_file(fsp1,False);
4069 return(False);
4072 if ((ofun&3) == 1) {
4073 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4074 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4076 * Stop the copy from occurring.
4078 ret = -1;
4079 src_sbuf.st_size = 0;
4083 if (src_sbuf.st_size)
4084 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4086 close_file(fsp1,False);
4088 /* Ensure the modtime is set correctly on the destination file. */
4089 fsp2->pending_modtime = src_sbuf.st_mtime;
4092 * As we are opening fsp1 read-only we only expect
4093 * an error on close on fsp2 if we are out of space.
4094 * Thus we don't look at the error return from the
4095 * close of fsp1.
4097 *err_ret = close_file(fsp2,False);
4099 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4104 /****************************************************************************
4105 reply to a file copy.
4106 ****************************************************************************/
4107 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4109 int outsize = 0;
4110 pstring name;
4111 pstring directory;
4112 pstring mask,newname;
4113 char *p;
4114 int count=0;
4115 int error = ERRnoaccess;
4116 int err = 0;
4117 BOOL has_wild;
4118 BOOL exists=False;
4119 int tid2 = SVAL(inbuf,smb_vwv0);
4120 int ofun = SVAL(inbuf,smb_vwv1);
4121 int flags = SVAL(inbuf,smb_vwv2);
4122 BOOL target_is_directory=False;
4123 BOOL bad_path1 = False;
4124 BOOL bad_path2 = False;
4125 BOOL rc = True;
4126 SMB_STRUCT_STAT sbuf1, sbuf2;
4127 START_PROFILE(SMBcopy);
4129 *directory = *mask = 0;
4131 pstrcpy(name,smb_buf(inbuf));
4132 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
4134 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4136 if (tid2 != conn->cnum) {
4137 /* can't currently handle inter share copies XXXX */
4138 DEBUG(3,("Rejecting inter-share copy\n"));
4139 END_PROFILE(SMBcopy);
4140 return ERROR_DOS(ERRSRV,ERRinvdevice);
4143 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4144 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4146 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4147 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4149 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4151 if ((flags&1) && target_is_directory) {
4152 END_PROFILE(SMBcopy);
4153 return ERROR_DOS(ERRDOS,ERRbadfile);
4156 if ((flags&2) && !target_is_directory) {
4157 END_PROFILE(SMBcopy);
4158 return ERROR_DOS(ERRDOS,ERRbadpath);
4161 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4162 /* wants a tree copy! XXXX */
4163 DEBUG(3,("Rejecting tree copy\n"));
4164 END_PROFILE(SMBcopy);
4165 return ERROR_DOS(ERRSRV,ERRerror);
4168 p = strrchr(name,'/');
4169 if (!p) {
4170 pstrcpy(directory,"./");
4171 pstrcpy(mask,name);
4172 } else {
4173 *p = 0;
4174 pstrcpy(directory,name);
4175 pstrcpy(mask,p+1);
4179 * We should only check the mangled cache
4180 * here if unix_convert failed. This means
4181 * that the path in 'mask' doesn't exist
4182 * on the file system and so we need to look
4183 * for a possible mangle. This patch from
4184 * Tine Smukavec <valentin.smukavec@hermes.si>.
4187 if (!rc && mangle_is_mangled(mask))
4188 mangle_check_cache( mask );
4190 has_wild = ms_has_wild(mask);
4192 if (!has_wild) {
4193 pstrcat(directory,"/");
4194 pstrcat(directory,mask);
4195 if (resolve_wildcards(directory,newname) &&
4196 copy_file(directory,newname,conn,ofun,
4197 count,target_is_directory,&err)) count++;
4198 if(!count && err) {
4199 errno = err;
4200 END_PROFILE(SMBcopy);
4201 return(UNIXERROR(ERRHRD,ERRgeneral));
4203 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4204 } else {
4205 void *dirptr = NULL;
4206 char *dname;
4207 pstring destname;
4209 if (check_name(directory,conn))
4210 dirptr = OpenDir(conn, directory, True);
4212 if (dirptr) {
4213 error = ERRbadfile;
4215 if (strequal(mask,"????????.???"))
4216 pstrcpy(mask,"*");
4218 while ((dname = ReadDirName(dirptr))) {
4219 pstring fname;
4220 pstrcpy(fname,dname);
4222 if(!mask_match(fname, mask, case_sensitive))
4223 continue;
4225 error = ERRnoaccess;
4226 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4227 pstrcpy(destname,newname);
4228 if (resolve_wildcards(fname,destname) &&
4229 copy_file(fname,destname,conn,ofun,
4230 count,target_is_directory,&err)) count++;
4231 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4233 CloseDir(dirptr);
4237 if (count == 0) {
4238 if(err) {
4239 /* Error on close... */
4240 errno = err;
4241 END_PROFILE(SMBcopy);
4242 return(UNIXERROR(ERRHRD,ERRgeneral));
4245 if (exists) {
4246 END_PROFILE(SMBcopy);
4247 return ERROR_DOS(ERRDOS,error);
4248 } else
4250 if((errno == ENOENT) && (bad_path1 || bad_path2))
4252 unix_ERR_class = ERRDOS;
4253 unix_ERR_code = ERRbadpath;
4255 END_PROFILE(SMBcopy);
4256 return(UNIXERROR(ERRDOS,error));
4260 outsize = set_message(outbuf,1,0,True);
4261 SSVAL(outbuf,smb_vwv0,count);
4263 END_PROFILE(SMBcopy);
4264 return(outsize);
4267 /****************************************************************************
4268 reply to a setdir
4269 ****************************************************************************/
4270 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4272 int snum;
4273 int outsize = 0;
4274 BOOL ok = False;
4275 pstring newdir;
4276 START_PROFILE(pathworks_setdir);
4278 snum = SNUM(conn);
4279 if (!CAN_SETDIR(snum)) {
4280 END_PROFILE(pathworks_setdir);
4281 return ERROR_DOS(ERRDOS,ERRnoaccess);
4284 pstrcpy(newdir,smb_buf(inbuf) + 1);
4285 strlower(newdir);
4287 if (strlen(newdir) == 0) {
4288 ok = True;
4289 } else {
4290 ok = vfs_directory_exist(conn,newdir,NULL);
4291 if (ok) {
4292 string_set(&conn->connectpath,newdir);
4296 if (!ok) {
4297 END_PROFILE(pathworks_setdir);
4298 return ERROR_DOS(ERRDOS,ERRbadpath);
4301 outsize = set_message(outbuf,0,0,True);
4302 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4304 DEBUG(3,("setdir %s\n", newdir));
4306 END_PROFILE(pathworks_setdir);
4307 return(outsize);
4310 /****************************************************************************
4311 Get a lock pid, dealing with large count requests.
4312 ****************************************************************************/
4314 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4316 if(!large_file_format)
4317 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4318 else
4319 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4322 /****************************************************************************
4323 Get a lock count, dealing with large count requests.
4324 ****************************************************************************/
4326 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4328 SMB_BIG_UINT count = 0;
4330 if(!large_file_format) {
4331 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4332 } else {
4334 #if defined(HAVE_LONGLONG)
4335 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4336 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4337 #else /* HAVE_LONGLONG */
4340 * NT4.x seems to be broken in that it sends large file (64 bit)
4341 * lockingX calls even if the CAP_LARGE_FILES was *not*
4342 * negotiated. For boxes without large unsigned ints truncate the
4343 * lock count by dropping the top 32 bits.
4346 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4347 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4348 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4349 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4350 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4353 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4354 #endif /* HAVE_LONGLONG */
4357 return count;
4360 #if !defined(HAVE_LONGLONG)
4361 /****************************************************************************
4362 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4363 ****************************************************************************/
4365 static uint32 map_lock_offset(uint32 high, uint32 low)
4367 unsigned int i;
4368 uint32 mask = 0;
4369 uint32 highcopy = high;
4372 * Try and find out how many significant bits there are in high.
4375 for(i = 0; highcopy; i++)
4376 highcopy >>= 1;
4379 * We use 31 bits not 32 here as POSIX
4380 * lock offsets may not be negative.
4383 mask = (~0) << (31 - i);
4385 if(low & mask)
4386 return 0; /* Fail. */
4388 high <<= (31 - i);
4390 return (high|low);
4392 #endif /* !defined(HAVE_LONGLONG) */
4394 /****************************************************************************
4395 Get a lock offset, dealing with large offset requests.
4396 ****************************************************************************/
4398 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4400 SMB_BIG_UINT offset = 0;
4402 *err = False;
4404 if(!large_file_format) {
4405 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4406 } else {
4408 #if defined(HAVE_LONGLONG)
4409 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4410 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4411 #else /* HAVE_LONGLONG */
4414 * NT4.x seems to be broken in that it sends large file (64 bit)
4415 * lockingX calls even if the CAP_LARGE_FILES was *not*
4416 * negotiated. For boxes without large unsigned ints mangle the
4417 * lock offset by mapping the top 32 bits onto the lower 32.
4420 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4421 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4422 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4423 uint32 new_low = 0;
4425 if((new_low = map_lock_offset(high, low)) == 0) {
4426 *err = True;
4427 return (SMB_BIG_UINT)-1;
4430 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4431 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4432 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4433 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4436 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4437 #endif /* HAVE_LONGLONG */
4440 return offset;
4443 /****************************************************************************
4444 reply to a lockingX request
4445 ****************************************************************************/
4447 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4449 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4450 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4451 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4452 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4453 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4454 SMB_BIG_UINT count = 0, offset = 0;
4455 uint16 lock_pid;
4456 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4457 int i;
4458 char *data;
4459 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4460 BOOL err;
4461 NTSTATUS status;
4463 START_PROFILE(SMBlockingX);
4465 CHECK_FSP(fsp,conn);
4467 data = smb_buf(inbuf);
4469 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4470 /* we don't support these - and CANCEL_LOCK makes w2k
4471 and XP reboot so I don't really want to be
4472 compatible! (tridge) */
4473 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4476 /* Check if this is an oplock break on a file
4477 we have granted an oplock on.
4479 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4480 /* Client can insist on breaking to none. */
4481 BOOL break_to_none = (oplocklevel == 0);
4483 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4484 (unsigned int)oplocklevel, fsp->fnum ));
4487 * Make sure we have granted an exclusive or batch oplock on this file.
4490 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4491 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4492 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4494 /* if this is a pure oplock break request then don't send a reply */
4495 if (num_locks == 0 && num_ulocks == 0) {
4496 END_PROFILE(SMBlockingX);
4497 return -1;
4498 } else {
4499 END_PROFILE(SMBlockingX);
4500 return ERROR_DOS(ERRDOS,ERRlock);
4504 if (remove_oplock(fsp, break_to_none) == False) {
4505 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4506 fsp->fsp_name ));
4509 /* if this is a pure oplock break request then don't send a reply */
4510 if (num_locks == 0 && num_ulocks == 0) {
4511 /* Sanity check - ensure a pure oplock break is not a
4512 chained request. */
4513 if(CVAL(inbuf,smb_vwv0) != 0xff)
4514 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4515 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4516 END_PROFILE(SMBlockingX);
4517 return -1;
4522 * We do this check *after* we have checked this is not a oplock break
4523 * response message. JRA.
4526 release_level_2_oplocks_on_change(fsp);
4528 /* Data now points at the beginning of the list
4529 of smb_unlkrng structs */
4530 for(i = 0; i < (int)num_ulocks; i++) {
4531 lock_pid = get_lock_pid( data, i, large_file_format);
4532 count = get_lock_count( data, i, large_file_format);
4533 offset = get_lock_offset( data, i, large_file_format, &err);
4536 * There is no error code marked "stupid client bug".... :-).
4538 if(err) {
4539 END_PROFILE(SMBlockingX);
4540 return ERROR_DOS(ERRDOS,ERRnoaccess);
4543 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4544 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4546 status = do_unlock(fsp,conn,lock_pid,count,offset);
4547 if (NT_STATUS_V(status)) {
4548 END_PROFILE(SMBlockingX);
4549 return ERROR_NT(status);
4553 /* Setup the timeout in seconds. */
4555 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4557 /* Now do any requested locks */
4558 data += ((large_file_format ? 20 : 10)*num_ulocks);
4560 /* Data now points at the beginning of the list
4561 of smb_lkrng structs */
4563 for(i = 0; i < (int)num_locks; i++) {
4564 lock_pid = get_lock_pid( data, i, large_file_format);
4565 count = get_lock_count( data, i, large_file_format);
4566 offset = get_lock_offset( data, i, large_file_format, &err);
4569 * There is no error code marked "stupid client bug".... :-).
4571 if(err) {
4572 END_PROFILE(SMBlockingX);
4573 return ERROR_DOS(ERRDOS,ERRnoaccess);
4576 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4577 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name,
4578 (int)lock_timeout ));
4580 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4581 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
4583 if (NT_STATUS_V(status)) {
4584 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4586 * A blocking lock was requested. Package up
4587 * this smb into a queued request and push it
4588 * onto the blocking lock queue.
4590 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4591 END_PROFILE(SMBlockingX);
4592 return -1;
4595 break;
4599 /* If any of the above locks failed, then we must unlock
4600 all of the previous locks (X/Open spec). */
4601 if(i != num_locks && num_locks != 0) {
4603 * Ensure we don't do a remove on the lock that just failed,
4604 * as under POSIX rules, if we have a lock already there, we
4605 * will delete it (and we shouldn't) .....
4607 for(i--; i >= 0; i--) {
4608 lock_pid = get_lock_pid( data, i, large_file_format);
4609 count = get_lock_count( data, i, large_file_format);
4610 offset = get_lock_offset( data, i, large_file_format, &err);
4613 * There is no error code marked "stupid client bug".... :-).
4615 if(err) {
4616 END_PROFILE(SMBlockingX);
4617 return ERROR_DOS(ERRDOS,ERRnoaccess);
4620 do_unlock(fsp,conn,lock_pid,count,offset);
4622 END_PROFILE(SMBlockingX);
4623 return ERROR_NT(status);
4626 set_message(outbuf,2,0,True);
4628 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4629 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4631 END_PROFILE(SMBlockingX);
4632 return chain_reply(inbuf,outbuf,length,bufsize);
4635 /* Back from the dead for OS/2..... JRA. */
4637 /****************************************************************************
4638 Reply to a SMBreadbmpx (read block multiplex) request
4639 ****************************************************************************/
4641 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4643 ssize_t nread = -1;
4644 ssize_t total_read;
4645 char *data;
4646 SMB_OFF_T startpos;
4647 int outsize;
4648 size_t maxcount;
4649 int max_per_packet;
4650 size_t tcount;
4651 int pad;
4652 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4653 START_PROFILE(SMBreadBmpx);
4655 /* this function doesn't seem to work - disable by default */
4656 if (!lp_readbmpx()) {
4657 END_PROFILE(SMBreadBmpx);
4658 return ERROR_DOS(ERRSRV,ERRuseSTD);
4661 outsize = set_message(outbuf,8,0,True);
4663 CHECK_FSP(fsp,conn);
4664 CHECK_READ(fsp);
4665 CHECK_ERROR(fsp);
4667 startpos = IVAL(inbuf,smb_vwv1);
4668 maxcount = SVAL(inbuf,smb_vwv3);
4670 data = smb_buf(outbuf);
4671 pad = ((long)data)%4;
4672 if (pad)
4673 pad = 4 - pad;
4674 data += pad;
4676 max_per_packet = bufsize-(outsize+pad);
4677 tcount = maxcount;
4678 total_read = 0;
4680 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK, False)) {
4681 END_PROFILE(SMBreadBmpx);
4682 return ERROR_DOS(ERRDOS,ERRlock);
4685 do {
4686 size_t N = MIN(max_per_packet,tcount-total_read);
4688 nread = read_file(fsp,data,startpos,N);
4690 if (nread <= 0)
4691 nread = 0;
4693 if (nread < (ssize_t)N)
4694 tcount = total_read + nread;
4696 set_message(outbuf,8,nread,False);
4697 SIVAL(outbuf,smb_vwv0,startpos);
4698 SSVAL(outbuf,smb_vwv2,tcount);
4699 SSVAL(outbuf,smb_vwv6,nread);
4700 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4702 if (!send_smb(smbd_server_fd(),outbuf))
4703 exit_server("reply_readbmpx: send_smb failed.");
4705 total_read += nread;
4706 startpos += nread;
4707 } while (total_read < (ssize_t)tcount);
4709 END_PROFILE(SMBreadBmpx);
4710 return(-1);
4713 /****************************************************************************
4714 Reply to a SMBsetattrE.
4715 ****************************************************************************/
4717 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4719 struct utimbuf unix_times;
4720 int outsize = 0;
4721 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4722 START_PROFILE(SMBsetattrE);
4724 outsize = set_message(outbuf,0,0,True);
4726 if(!fsp || (fsp->conn != conn)) {
4727 END_PROFILE(SMBgetattrE);
4728 return ERROR_DOS(ERRDOS,ERRbadfid);
4732 * Convert the DOS times into unix times. Ignore create
4733 * time as UNIX can't set this.
4735 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4736 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4739 * Patch from Ray Frush <frush@engr.colostate.edu>
4740 * Sometimes times are sent as zero - ignore them.
4743 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4744 /* Ignore request */
4745 if( DEBUGLVL( 3 ) ) {
4746 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4747 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4749 END_PROFILE(SMBsetattrE);
4750 return(outsize);
4751 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4752 /* set modify time = to access time if modify time was 0 */
4753 unix_times.modtime = unix_times.actime;
4756 /* Set the date on this file */
4757 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4758 END_PROFILE(SMBsetattrE);
4759 return ERROR_DOS(ERRDOS,ERRnoaccess);
4762 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4763 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4765 END_PROFILE(SMBsetattrE);
4766 return(outsize);
4770 /* Back from the dead for OS/2..... JRA. */
4772 /****************************************************************************
4773 Reply to a SMBwritebmpx (write block multiplex primary) request.
4774 ****************************************************************************/
4776 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4778 size_t numtowrite;
4779 ssize_t nwritten = -1;
4780 int outsize = 0;
4781 SMB_OFF_T startpos;
4782 size_t tcount;
4783 BOOL write_through;
4784 int smb_doff;
4785 char *data;
4786 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4787 START_PROFILE(SMBwriteBmpx);
4789 CHECK_FSP(fsp,conn);
4790 CHECK_WRITE(fsp);
4791 CHECK_ERROR(fsp);
4793 tcount = SVAL(inbuf,smb_vwv1);
4794 startpos = IVAL(inbuf,smb_vwv3);
4795 write_through = BITSETW(inbuf+smb_vwv7,0);
4796 numtowrite = SVAL(inbuf,smb_vwv10);
4797 smb_doff = SVAL(inbuf,smb_vwv11);
4799 data = smb_base(inbuf) + smb_doff;
4801 /* If this fails we need to send an SMBwriteC response,
4802 not an SMBwritebmpx - set this up now so we don't forget */
4803 SCVAL(outbuf,smb_com,SMBwritec);
4805 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4806 END_PROFILE(SMBwriteBmpx);
4807 return(ERROR_DOS(ERRDOS,ERRlock));
4810 nwritten = write_file(fsp,data,startpos,numtowrite);
4812 if(lp_syncalways(SNUM(conn)) || write_through)
4813 sync_file(conn,fsp);
4815 if(nwritten < (ssize_t)numtowrite) {
4816 END_PROFILE(SMBwriteBmpx);
4817 return(UNIXERROR(ERRHRD,ERRdiskfull));
4820 /* If the maximum to be written to this file
4821 is greater than what we just wrote then set
4822 up a secondary struct to be attached to this
4823 fd, we will use this to cache error messages etc. */
4825 if((ssize_t)tcount > nwritten) {
4826 write_bmpx_struct *wbms;
4827 if(fsp->wbmpx_ptr != NULL)
4828 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4829 else
4830 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4832 if(!wbms) {
4833 DEBUG(0,("Out of memory in reply_readmpx\n"));
4834 END_PROFILE(SMBwriteBmpx);
4835 return(ERROR_DOS(ERRSRV,ERRnoresource));
4837 wbms->wr_mode = write_through;
4838 wbms->wr_discard = False; /* No errors yet */
4839 wbms->wr_total_written = nwritten;
4840 wbms->wr_errclass = 0;
4841 wbms->wr_error = 0;
4842 fsp->wbmpx_ptr = wbms;
4845 /* We are returning successfully, set the message type back to
4846 SMBwritebmpx */
4847 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4849 outsize = set_message(outbuf,1,0,True);
4851 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4853 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4854 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4856 if (write_through && tcount==nwritten) {
4857 /* We need to send both a primary and a secondary response */
4858 smb_setlen(outbuf,outsize - 4);
4859 if (!send_smb(smbd_server_fd(),outbuf))
4860 exit_server("reply_writebmpx: send_smb failed.");
4862 /* Now the secondary */
4863 outsize = set_message(outbuf,1,0,True);
4864 SCVAL(outbuf,smb_com,SMBwritec);
4865 SSVAL(outbuf,smb_vwv0,nwritten);
4868 END_PROFILE(SMBwriteBmpx);
4869 return(outsize);
4872 /****************************************************************************
4873 Reply to a SMBwritebs (write block multiplex secondary) request.
4874 ****************************************************************************/
4876 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4878 size_t numtowrite;
4879 ssize_t nwritten = -1;
4880 int outsize = 0;
4881 SMB_OFF_T startpos;
4882 size_t tcount;
4883 BOOL write_through;
4884 int smb_doff;
4885 char *data;
4886 write_bmpx_struct *wbms;
4887 BOOL send_response = False;
4888 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4889 START_PROFILE(SMBwriteBs);
4891 CHECK_FSP(fsp,conn);
4892 CHECK_WRITE(fsp);
4894 tcount = SVAL(inbuf,smb_vwv1);
4895 startpos = IVAL(inbuf,smb_vwv2);
4896 numtowrite = SVAL(inbuf,smb_vwv6);
4897 smb_doff = SVAL(inbuf,smb_vwv7);
4899 data = smb_base(inbuf) + smb_doff;
4901 /* We need to send an SMBwriteC response, not an SMBwritebs */
4902 SCVAL(outbuf,smb_com,SMBwritec);
4904 /* This fd should have an auxiliary struct attached,
4905 check that it does */
4906 wbms = fsp->wbmpx_ptr;
4907 if(!wbms) {
4908 END_PROFILE(SMBwriteBs);
4909 return(-1);
4912 /* If write through is set we can return errors, else we must cache them */
4913 write_through = wbms->wr_mode;
4915 /* Check for an earlier error */
4916 if(wbms->wr_discard) {
4917 END_PROFILE(SMBwriteBs);
4918 return -1; /* Just discard the packet */
4921 nwritten = write_file(fsp,data,startpos,numtowrite);
4923 if(lp_syncalways(SNUM(conn)) || write_through)
4924 sync_file(conn,fsp);
4926 if (nwritten < (ssize_t)numtowrite) {
4927 if(write_through) {
4928 /* We are returning an error - we can delete the aux struct */
4929 SAFE_FREE(wbms);
4930 fsp->wbmpx_ptr = NULL;
4931 END_PROFILE(SMBwriteBs);
4932 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4934 END_PROFILE(SMBwriteBs);
4935 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4938 /* Increment the total written, if this matches tcount
4939 we can discard the auxiliary struct (hurrah !) and return a writeC */
4940 wbms->wr_total_written += nwritten;
4941 if(wbms->wr_total_written >= tcount) {
4942 if (write_through) {
4943 outsize = set_message(outbuf,1,0,True);
4944 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4945 send_response = True;
4948 SAFE_FREE(wbms);
4949 fsp->wbmpx_ptr = NULL;
4952 if(send_response) {
4953 END_PROFILE(SMBwriteBs);
4954 return(outsize);
4957 END_PROFILE(SMBwriteBs);
4958 return(-1);
4961 /****************************************************************************
4962 Reply to a SMBgetattrE.
4963 ****************************************************************************/
4965 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4967 SMB_STRUCT_STAT sbuf;
4968 int outsize = 0;
4969 int mode;
4970 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4971 START_PROFILE(SMBgetattrE);
4973 outsize = set_message(outbuf,11,0,True);
4975 if(!fsp || (fsp->conn != conn)) {
4976 END_PROFILE(SMBgetattrE);
4977 return ERROR_DOS(ERRDOS,ERRbadfid);
4980 /* Do an stat on this file */
4982 if(fsp_stat(fsp, &sbuf)) {
4983 END_PROFILE(SMBgetattrE);
4984 return(UNIXERROR(ERRDOS,ERRnoaccess));
4987 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4989 /* Convert the times into dos times. Set create
4990 * date to be last modify date as UNIX doesn't save
4991 * this.
4994 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4995 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4996 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4997 if (mode & aDIR) {
4998 SIVAL(outbuf,smb_vwv6,0);
4999 SIVAL(outbuf,smb_vwv8,0);
5000 } else {
5001 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5002 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
5004 SSVAL(outbuf,smb_vwv10, mode);
5006 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5008 END_PROFILE(SMBgetattrE);
5009 return(outsize);