debian packagin updates from Eloy
[Samba.git] / source / smbd / reply.c
blob78294952c1874178349af5b8a67c68eb05a931ed
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 dos_to_unix_static(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 status = mkdir_internal(conn, directory);
3474 if (!NT_STATUS_IS_OK(status))
3475 return ERROR_NT(status);
3477 outsize = set_message(outbuf,0,0,True);
3479 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3481 END_PROFILE(SMBmkdir);
3482 return(outsize);
3485 /****************************************************************************
3486 Static function used by reply_rmdir to delete an entire directory
3487 tree recursively. Return False on ok, True on fail.
3488 ****************************************************************************/
3490 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3492 char *dname = NULL;
3493 BOOL ret = False;
3494 void *dirptr = OpenDir(conn, directory, False);
3496 if(dirptr == NULL)
3497 return True;
3499 while((dname = ReadDirName(dirptr))) {
3500 pstring fullname;
3501 SMB_STRUCT_STAT st;
3503 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3504 continue;
3506 /* Construct the full name. */
3507 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3508 errno = ENOMEM;
3509 ret = True;
3510 break;
3513 pstrcpy(fullname, directory);
3514 pstrcat(fullname, "/");
3515 pstrcat(fullname, dname);
3517 if(conn->vfs_ops.lstat(conn,dos_to_unix_static(fullname), &st) != 0) {
3518 ret = True;
3519 break;
3522 if(st.st_mode & S_IFDIR) {
3523 if(recursive_rmdir(conn, fullname)!=0) {
3524 ret = True;
3525 break;
3527 if(vfs_rmdir(conn,fullname) != 0) {
3528 ret = True;
3529 break;
3531 } else if(vfs_unlink(conn,fullname) != 0) {
3532 ret = True;
3533 break;
3537 CloseDir(dirptr);
3538 return ret;
3541 /****************************************************************************
3542 The internals of the rmdir code - called elsewhere.
3543 ****************************************************************************/
3545 BOOL rmdir_internals(connection_struct *conn, char *directory)
3547 BOOL ok;
3549 ok = (vfs_rmdir(conn,directory) == 0);
3550 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3552 * Check to see if the only thing in this directory are
3553 * vetoed files/directories. If so then delete them and
3554 * retry. If we fail to delete any of them (and we *don't*
3555 * do a recursive delete) then fail the rmdir.
3557 BOOL all_veto_files = True;
3558 char *dname;
3559 void *dirptr = OpenDir(conn, directory, False);
3561 if(dirptr != NULL) {
3562 int dirpos = TellDir(dirptr);
3563 while ((dname = ReadDirName(dirptr))) {
3564 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3565 continue;
3566 if(!IS_VETO_PATH(conn, dname)) {
3567 all_veto_files = False;
3568 break;
3571 if(all_veto_files) {
3572 SeekDir(dirptr,dirpos);
3573 while ((dname = ReadDirName(dirptr))) {
3574 pstring fullname;
3575 SMB_STRUCT_STAT st;
3577 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3578 continue;
3580 /* Construct the full name. */
3581 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3582 errno = ENOMEM;
3583 break;
3585 pstrcpy(fullname, directory);
3586 pstrcat(fullname, "/");
3587 pstrcat(fullname, dname);
3589 if(conn->vfs_ops.lstat(conn,dos_to_unix_static(fullname), &st) != 0)
3590 break;
3591 if(st.st_mode & S_IFDIR) {
3592 if(lp_recursive_veto_delete(SNUM(conn))) {
3593 if(recursive_rmdir(conn, fullname) != 0)
3594 break;
3596 if(vfs_rmdir(conn,fullname) != 0)
3597 break;
3598 } else if(vfs_unlink(conn,fullname) != 0)
3599 break;
3601 CloseDir(dirptr);
3602 /* Retry the rmdir */
3603 ok = (vfs_rmdir(conn,directory) == 0);
3604 } else {
3605 CloseDir(dirptr);
3607 } else {
3608 errno = ENOTEMPTY;
3612 if (!ok)
3613 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3615 return ok;
3618 /****************************************************************************
3619 Reply to a rmdir.
3620 ****************************************************************************/
3622 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3624 pstring directory;
3625 int outsize = 0;
3626 BOOL ok = False;
3627 BOOL bad_path = False;
3628 SMB_STRUCT_STAT sbuf;
3629 START_PROFILE(SMBrmdir);
3631 pstrcpy(directory,smb_buf(inbuf) + 1);
3633 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3635 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3637 if (check_name(directory,conn))
3639 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3640 ok = rmdir_internals(conn, directory);
3643 if (!ok)
3645 set_bad_path_error(errno, bad_path);
3646 END_PROFILE(SMBrmdir);
3647 return(UNIXERROR(ERRDOS,ERRbadpath));
3650 outsize = set_message(outbuf,0,0,True);
3652 DEBUG( 3, ( "rmdir %s\n", directory ) );
3654 END_PROFILE(SMBrmdir);
3655 return(outsize);
3659 /*******************************************************************
3660 resolve wildcards in a filename rename
3661 ********************************************************************/
3662 static BOOL resolve_wildcards(char *name1,char *name2)
3664 fstring root1,root2;
3665 fstring ext1,ext2;
3666 char *p,*p2;
3668 name1 = strrchr(name1,'/');
3669 name2 = strrchr(name2,'/');
3671 if (!name1 || !name2) return(False);
3673 fstrcpy(root1,name1);
3674 fstrcpy(root2,name2);
3675 p = strrchr(root1,'.');
3676 if (p) {
3677 *p = 0;
3678 fstrcpy(ext1,p+1);
3679 } else {
3680 fstrcpy(ext1,"");
3682 p = strrchr(root2,'.');
3683 if (p) {
3684 *p = 0;
3685 fstrcpy(ext2,p+1);
3686 } else {
3687 fstrcpy(ext2,"");
3690 p = root1;
3691 p2 = root2;
3692 while (*p2) {
3693 if (*p2 == '?') {
3694 *p2 = *p;
3695 p2++;
3696 } else {
3697 p2++;
3699 if (*p) p++;
3702 p = ext1;
3703 p2 = ext2;
3704 while (*p2) {
3705 if (*p2 == '?') {
3706 *p2 = *p;
3707 p2++;
3708 } else {
3709 p2++;
3711 if (*p) p++;
3714 pstrcpy(name2,root2);
3715 if (ext2[0]) {
3716 pstrcat(name2,".");
3717 pstrcat(name2,ext2);
3720 return(True);
3723 /****************************************************************************
3724 The guts of the rename command, split out so it may be called by the NT SMB
3725 code.
3726 ****************************************************************************/
3728 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3730 pstring directory;
3731 pstring mask;
3732 pstring newname_last_component;
3733 char *p;
3734 BOOL has_wild;
3735 BOOL bad_path1 = False;
3736 BOOL bad_path2 = False;
3737 int count=0;
3738 NTSTATUS error = NT_STATUS_OK;
3739 BOOL rc = True;
3740 SMB_STRUCT_STAT sbuf1, sbuf2;
3742 *directory = *mask = 0;
3744 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3745 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3748 * Split the old name into directory and last component
3749 * strings. Note that unix_convert may have stripped off a
3750 * leading ./ from both name and newname if the rename is
3751 * at the root of the share. We need to make sure either both
3752 * name and newname contain a / character or neither of them do
3753 * as this is checked in resolve_wildcards().
3756 p = strrchr(name,'/');
3757 if (!p) {
3758 pstrcpy(directory,".");
3759 pstrcpy(mask,name);
3760 } else {
3761 *p = 0;
3762 pstrcpy(directory,name);
3763 pstrcpy(mask,p+1);
3764 *p = '/'; /* Replace needed for exceptional test below. */
3768 * We should only check the mangled cache
3769 * here if unix_convert failed. This means
3770 * that the path in 'mask' doesn't exist
3771 * on the file system and so we need to look
3772 * for a possible mangle. This patch from
3773 * Tine Smukavec <valentin.smukavec@hermes.si>.
3776 if (!rc && mangle_is_mangled(mask))
3777 mangle_check_cache( mask );
3779 has_wild = ms_has_wild(mask);
3781 if (!has_wild) {
3782 pstring zdirectory;
3783 pstring znewname;
3786 * No wildcards - just process the one file.
3788 BOOL is_short_name = mangle_is_8_3(name, True);
3790 /* Add a terminating '/' to the directory name. */
3791 pstrcat(directory,"/");
3792 pstrcat(directory,mask);
3794 /* Ensure newname contains a '/' also */
3795 if(strrchr(newname,'/') == 0) {
3796 pstring tmpstr;
3798 pstrcpy(tmpstr, "./");
3799 pstrcat(tmpstr, newname);
3800 pstrcpy(newname, tmpstr);
3803 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3804 directory = %s, newname = %s, newname_last_component = %s, mangle_is_8_3 = %d\n",
3805 case_sensitive, case_preserve, short_case_preserve, directory,
3806 newname, newname_last_component, is_short_name));
3809 * Check for special case with case preserving and not
3810 * case sensitive, if directory and newname are identical,
3811 * and the old last component differs from the original
3812 * last component only by case, then we should allow
3813 * the rename (user is trying to change the case of the
3814 * filename).
3816 if((case_sensitive == False) &&
3817 (((case_preserve == True) &&
3818 (is_short_name == False)) ||
3819 ((short_case_preserve == True) &&
3820 (is_short_name == True))) &&
3821 strcsequal(directory, newname)) {
3822 pstring newname_modified_last_component;
3825 * Get the last component of the modified name.
3826 * Note that we guarantee that newname contains a '/'
3827 * character above.
3829 p = strrchr(newname,'/');
3830 pstrcpy(newname_modified_last_component,p+1);
3832 if(strcsequal(newname_modified_last_component,
3833 newname_last_component) == False) {
3835 * Replace the modified last component with
3836 * the original.
3838 pstrcpy(p+1, newname_last_component);
3843 resolve_wildcards(directory,newname);
3846 * The source object must exist.
3849 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3850 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3851 directory,newname));
3853 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3855 * Must return different errors depending on whether the parent
3856 * directory existed or not.
3859 p = strrchr(directory, '/');
3860 if (!p)
3861 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3862 *p = '\0';
3863 if (vfs_object_exist(conn, directory, NULL))
3864 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3865 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3867 error = map_nt_error_from_unix(errno);
3868 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3869 get_nt_error_msg(error), directory,newname));
3871 return error;
3874 error = can_rename(directory,conn,&sbuf1);
3876 if (!NT_STATUS_IS_OK(error)) {
3877 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3878 get_nt_error_msg(error), directory,newname));
3879 return error;
3882 pstrcpy(zdirectory, dos_to_unix_static(directory));
3883 pstrcpy(znewname, dos_to_unix_static(newname));
3886 * If the src and dest names are identical - including case,
3887 * don't do the rename, just return success.
3890 if (strcsequal(zdirectory, znewname)) {
3891 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3892 return NT_STATUS_OK;
3895 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3896 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3897 directory,newname));
3898 return NT_STATUS_OBJECT_NAME_COLLISION;
3901 if(conn->vfs_ops.rename(conn,zdirectory, znewname) == 0) {
3902 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3903 directory,newname));
3904 return NT_STATUS_OK;
3907 if (errno == ENOTDIR || errno == EISDIR)
3908 error = NT_STATUS_OBJECT_NAME_COLLISION;
3909 else
3910 error = map_nt_error_from_unix(errno);
3912 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3913 get_nt_error_msg(error), directory,newname));
3915 return error;
3916 } else {
3919 * Wildcards - process each file that matches.
3921 void *dirptr = NULL;
3922 char *dname;
3923 pstring destname;
3925 if (check_name(directory,conn))
3926 dirptr = OpenDir(conn, directory, True);
3928 if (dirptr) {
3929 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3931 if (strequal(mask,"????????.???"))
3932 pstrcpy(mask,"*");
3934 while ((dname = ReadDirName(dirptr))) {
3935 pstring fname;
3937 pstrcpy(fname,dname);
3939 if(!mask_match(fname, mask, case_sensitive))
3940 continue;
3942 error = NT_STATUS_ACCESS_DENIED;
3943 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3944 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3945 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3946 DEBUG(6,("rename %s failed. Error %s\n", fname, get_nt_error_msg(error)));
3947 continue;
3949 error = can_rename(fname,conn,&sbuf1);
3950 if (!NT_STATUS_IS_OK(error)) {
3951 DEBUG(6,("rename %s failed. Error %s\n", fname, get_nt_error_msg(error)));
3952 continue;
3954 pstrcpy(destname,newname);
3956 if (!resolve_wildcards(fname,destname)) {
3957 DEBUG(6,("resolve_wildcards %s %s failed\n",
3958 fname, destname));
3959 continue;
3962 if (!replace_if_exists &&
3963 vfs_object_exist(conn,destname, NULL)) {
3964 DEBUG(6,("file_exist %s\n", destname));
3965 error = NT_STATUS_OBJECT_NAME_COLLISION;
3966 continue;
3969 if (!conn->vfs_ops.rename(conn,dos_to_unix_static(fname),
3970 dos_to_unix_static(destname)))
3971 count++;
3972 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3974 CloseDir(dirptr);
3978 if (count == 0 && NT_STATUS_IS_OK(error)) {
3979 error = map_nt_error_from_unix(errno);
3982 return error;
3985 /****************************************************************************
3986 Reply to a mv.
3987 ****************************************************************************/
3989 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3991 int outsize = 0;
3992 pstring name;
3993 pstring newname;
3994 NTSTATUS status;
3995 START_PROFILE(SMBmv);
3997 pstrcpy(name,smb_buf(inbuf) + 1);
3998 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
4000 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4001 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4003 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4005 status = rename_internals(conn, name, newname, False);
4006 if (!NT_STATUS_IS_OK(status)) {
4007 return ERROR_NT(status);
4011 * Win2k needs a changenotify request response before it will
4012 * update after a rename..
4014 process_pending_change_notify_queue((time_t)0);
4015 outsize = set_message(outbuf,0,0,True);
4017 END_PROFILE(SMBmv);
4018 return(outsize);
4021 /*******************************************************************
4022 Copy a file as part of a reply_copy.
4023 ******************************************************************/
4025 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4026 int count,BOOL target_is_directory, int *err_ret)
4028 int Access,action;
4029 SMB_STRUCT_STAT src_sbuf, sbuf2;
4030 SMB_OFF_T ret=-1;
4031 files_struct *fsp1,*fsp2;
4032 pstring dest;
4034 *err_ret = 0;
4036 pstrcpy(dest,dest1);
4037 if (target_is_directory) {
4038 char *p = strrchr(src,'/');
4039 if (p)
4040 p++;
4041 else
4042 p = src;
4043 pstrcat(dest,"/");
4044 pstrcat(dest,p);
4047 if (!vfs_file_exist(conn,src,&src_sbuf))
4048 return(False);
4050 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4051 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
4053 if (!fsp1)
4054 return(False);
4056 if (!target_is_directory && count)
4057 ofun = FILE_EXISTS_OPEN;
4059 if (vfs_stat(conn,dest,&sbuf2) == -1)
4060 ZERO_STRUCTP(&sbuf2);
4062 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4063 ofun,src_sbuf.st_mode,0,&Access,&action);
4065 if (!fsp2) {
4066 close_file(fsp1,False);
4067 return(False);
4070 if ((ofun&3) == 1) {
4071 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4072 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4074 * Stop the copy from occurring.
4076 ret = -1;
4077 src_sbuf.st_size = 0;
4081 if (src_sbuf.st_size)
4082 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4084 close_file(fsp1,False);
4086 /* Ensure the modtime is set correctly on the destination file. */
4087 fsp2->pending_modtime = src_sbuf.st_mtime;
4090 * As we are opening fsp1 read-only we only expect
4091 * an error on close on fsp2 if we are out of space.
4092 * Thus we don't look at the error return from the
4093 * close of fsp1.
4095 *err_ret = close_file(fsp2,False);
4097 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4102 /****************************************************************************
4103 reply to a file copy.
4104 ****************************************************************************/
4105 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4107 int outsize = 0;
4108 pstring name;
4109 pstring directory;
4110 pstring mask,newname;
4111 char *p;
4112 int count=0;
4113 int error = ERRnoaccess;
4114 int err = 0;
4115 BOOL has_wild;
4116 BOOL exists=False;
4117 int tid2 = SVAL(inbuf,smb_vwv0);
4118 int ofun = SVAL(inbuf,smb_vwv1);
4119 int flags = SVAL(inbuf,smb_vwv2);
4120 BOOL target_is_directory=False;
4121 BOOL bad_path1 = False;
4122 BOOL bad_path2 = False;
4123 BOOL rc = True;
4124 SMB_STRUCT_STAT sbuf1, sbuf2;
4125 START_PROFILE(SMBcopy);
4127 *directory = *mask = 0;
4129 pstrcpy(name,smb_buf(inbuf));
4130 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
4132 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4134 if (tid2 != conn->cnum) {
4135 /* can't currently handle inter share copies XXXX */
4136 DEBUG(3,("Rejecting inter-share copy\n"));
4137 END_PROFILE(SMBcopy);
4138 return ERROR_DOS(ERRSRV,ERRinvdevice);
4141 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4142 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4144 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4145 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4147 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4149 if ((flags&1) && target_is_directory) {
4150 END_PROFILE(SMBcopy);
4151 return ERROR_DOS(ERRDOS,ERRbadfile);
4154 if ((flags&2) && !target_is_directory) {
4155 END_PROFILE(SMBcopy);
4156 return ERROR_DOS(ERRDOS,ERRbadpath);
4159 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4160 /* wants a tree copy! XXXX */
4161 DEBUG(3,("Rejecting tree copy\n"));
4162 END_PROFILE(SMBcopy);
4163 return ERROR_DOS(ERRSRV,ERRerror);
4166 p = strrchr(name,'/');
4167 if (!p) {
4168 pstrcpy(directory,"./");
4169 pstrcpy(mask,name);
4170 } else {
4171 *p = 0;
4172 pstrcpy(directory,name);
4173 pstrcpy(mask,p+1);
4177 * We should only check the mangled cache
4178 * here if unix_convert failed. This means
4179 * that the path in 'mask' doesn't exist
4180 * on the file system and so we need to look
4181 * for a possible mangle. This patch from
4182 * Tine Smukavec <valentin.smukavec@hermes.si>.
4185 if (!rc && mangle_is_mangled(mask))
4186 mangle_check_cache( mask );
4188 has_wild = ms_has_wild(mask);
4190 if (!has_wild) {
4191 pstrcat(directory,"/");
4192 pstrcat(directory,mask);
4193 if (resolve_wildcards(directory,newname) &&
4194 copy_file(directory,newname,conn,ofun,
4195 count,target_is_directory,&err)) count++;
4196 if(!count && err) {
4197 errno = err;
4198 END_PROFILE(SMBcopy);
4199 return(UNIXERROR(ERRHRD,ERRgeneral));
4201 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4202 } else {
4203 void *dirptr = NULL;
4204 char *dname;
4205 pstring destname;
4207 if (check_name(directory,conn))
4208 dirptr = OpenDir(conn, directory, True);
4210 if (dirptr) {
4211 error = ERRbadfile;
4213 if (strequal(mask,"????????.???"))
4214 pstrcpy(mask,"*");
4216 while ((dname = ReadDirName(dirptr))) {
4217 pstring fname;
4218 pstrcpy(fname,dname);
4220 if(!mask_match(fname, mask, case_sensitive))
4221 continue;
4223 error = ERRnoaccess;
4224 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4225 pstrcpy(destname,newname);
4226 if (resolve_wildcards(fname,destname) &&
4227 copy_file(fname,destname,conn,ofun,
4228 count,target_is_directory,&err)) count++;
4229 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4231 CloseDir(dirptr);
4235 if (count == 0) {
4236 if(err) {
4237 /* Error on close... */
4238 errno = err;
4239 END_PROFILE(SMBcopy);
4240 return(UNIXERROR(ERRHRD,ERRgeneral));
4243 if (exists) {
4244 END_PROFILE(SMBcopy);
4245 return ERROR_DOS(ERRDOS,error);
4246 } else
4248 if((errno == ENOENT) && (bad_path1 || bad_path2))
4250 unix_ERR_class = ERRDOS;
4251 unix_ERR_code = ERRbadpath;
4253 END_PROFILE(SMBcopy);
4254 return(UNIXERROR(ERRDOS,error));
4258 outsize = set_message(outbuf,1,0,True);
4259 SSVAL(outbuf,smb_vwv0,count);
4261 END_PROFILE(SMBcopy);
4262 return(outsize);
4265 /****************************************************************************
4266 reply to a setdir
4267 ****************************************************************************/
4268 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4270 int snum;
4271 int outsize = 0;
4272 BOOL ok = False;
4273 pstring newdir;
4274 START_PROFILE(pathworks_setdir);
4276 snum = SNUM(conn);
4277 if (!CAN_SETDIR(snum)) {
4278 END_PROFILE(pathworks_setdir);
4279 return ERROR_DOS(ERRDOS,ERRnoaccess);
4282 pstrcpy(newdir,smb_buf(inbuf) + 1);
4283 strlower(newdir);
4285 if (strlen(newdir) == 0) {
4286 ok = True;
4287 } else {
4288 ok = vfs_directory_exist(conn,newdir,NULL);
4289 if (ok) {
4290 string_set(&conn->connectpath,newdir);
4294 if (!ok) {
4295 END_PROFILE(pathworks_setdir);
4296 return ERROR_DOS(ERRDOS,ERRbadpath);
4299 outsize = set_message(outbuf,0,0,True);
4300 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4302 DEBUG(3,("setdir %s\n", newdir));
4304 END_PROFILE(pathworks_setdir);
4305 return(outsize);
4308 /****************************************************************************
4309 Get a lock pid, dealing with large count requests.
4310 ****************************************************************************/
4312 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4314 if(!large_file_format)
4315 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4316 else
4317 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4320 /****************************************************************************
4321 Get a lock count, dealing with large count requests.
4322 ****************************************************************************/
4324 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4326 SMB_BIG_UINT count = 0;
4328 if(!large_file_format) {
4329 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4330 } else {
4332 #if defined(HAVE_LONGLONG)
4333 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4334 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4335 #else /* HAVE_LONGLONG */
4338 * NT4.x seems to be broken in that it sends large file (64 bit)
4339 * lockingX calls even if the CAP_LARGE_FILES was *not*
4340 * negotiated. For boxes without large unsigned ints truncate the
4341 * lock count by dropping the top 32 bits.
4344 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4345 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4346 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4347 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4348 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4351 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4352 #endif /* HAVE_LONGLONG */
4355 return count;
4358 #if !defined(HAVE_LONGLONG)
4359 /****************************************************************************
4360 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4361 ****************************************************************************/
4363 static uint32 map_lock_offset(uint32 high, uint32 low)
4365 unsigned int i;
4366 uint32 mask = 0;
4367 uint32 highcopy = high;
4370 * Try and find out how many significant bits there are in high.
4373 for(i = 0; highcopy; i++)
4374 highcopy >>= 1;
4377 * We use 31 bits not 32 here as POSIX
4378 * lock offsets may not be negative.
4381 mask = (~0) << (31 - i);
4383 if(low & mask)
4384 return 0; /* Fail. */
4386 high <<= (31 - i);
4388 return (high|low);
4390 #endif /* !defined(HAVE_LONGLONG) */
4392 /****************************************************************************
4393 Get a lock offset, dealing with large offset requests.
4394 ****************************************************************************/
4396 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4398 SMB_BIG_UINT offset = 0;
4400 *err = False;
4402 if(!large_file_format) {
4403 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4404 } else {
4406 #if defined(HAVE_LONGLONG)
4407 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4408 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4409 #else /* HAVE_LONGLONG */
4412 * NT4.x seems to be broken in that it sends large file (64 bit)
4413 * lockingX calls even if the CAP_LARGE_FILES was *not*
4414 * negotiated. For boxes without large unsigned ints mangle the
4415 * lock offset by mapping the top 32 bits onto the lower 32.
4418 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4419 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4420 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4421 uint32 new_low = 0;
4423 if((new_low = map_lock_offset(high, low)) == 0) {
4424 *err = True;
4425 return (SMB_BIG_UINT)-1;
4428 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4429 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4430 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4431 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4434 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4435 #endif /* HAVE_LONGLONG */
4438 return offset;
4441 /****************************************************************************
4442 reply to a lockingX request
4443 ****************************************************************************/
4445 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4447 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4448 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4449 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4450 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4451 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4452 SMB_BIG_UINT count = 0, offset = 0;
4453 uint16 lock_pid;
4454 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4455 int i;
4456 char *data;
4457 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4458 BOOL err;
4459 NTSTATUS status;
4461 START_PROFILE(SMBlockingX);
4463 CHECK_FSP(fsp,conn);
4465 data = smb_buf(inbuf);
4467 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4468 /* we don't support these - and CANCEL_LOCK makes w2k
4469 and XP reboot so I don't really want to be
4470 compatible! (tridge) */
4471 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4474 /* Check if this is an oplock break on a file
4475 we have granted an oplock on.
4477 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4478 /* Client can insist on breaking to none. */
4479 BOOL break_to_none = (oplocklevel == 0);
4481 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4482 (unsigned int)oplocklevel, fsp->fnum ));
4485 * Make sure we have granted an exclusive or batch oplock on this file.
4488 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4489 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4490 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4492 /* if this is a pure oplock break request then don't send a reply */
4493 if (num_locks == 0 && num_ulocks == 0) {
4494 END_PROFILE(SMBlockingX);
4495 return -1;
4496 } else {
4497 END_PROFILE(SMBlockingX);
4498 return ERROR_DOS(ERRDOS,ERRlock);
4502 if (remove_oplock(fsp, break_to_none) == False) {
4503 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4504 fsp->fsp_name ));
4507 /* if this is a pure oplock break request then don't send a reply */
4508 if (num_locks == 0 && num_ulocks == 0) {
4509 /* Sanity check - ensure a pure oplock break is not a
4510 chained request. */
4511 if(CVAL(inbuf,smb_vwv0) != 0xff)
4512 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4513 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4514 END_PROFILE(SMBlockingX);
4515 return -1;
4520 * We do this check *after* we have checked this is not a oplock break
4521 * response message. JRA.
4524 release_level_2_oplocks_on_change(fsp);
4526 /* Data now points at the beginning of the list
4527 of smb_unlkrng structs */
4528 for(i = 0; i < (int)num_ulocks; i++) {
4529 lock_pid = get_lock_pid( data, i, large_file_format);
4530 count = get_lock_count( data, i, large_file_format);
4531 offset = get_lock_offset( data, i, large_file_format, &err);
4534 * There is no error code marked "stupid client bug".... :-).
4536 if(err) {
4537 END_PROFILE(SMBlockingX);
4538 return ERROR_DOS(ERRDOS,ERRnoaccess);
4541 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4542 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4544 status = do_unlock(fsp,conn,lock_pid,count,offset);
4545 if (NT_STATUS_V(status)) {
4546 END_PROFILE(SMBlockingX);
4547 return ERROR_NT(status);
4551 /* Setup the timeout in seconds. */
4553 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4555 /* Now do any requested locks */
4556 data += ((large_file_format ? 20 : 10)*num_ulocks);
4558 /* Data now points at the beginning of the list
4559 of smb_lkrng structs */
4561 for(i = 0; i < (int)num_locks; i++) {
4562 lock_pid = get_lock_pid( data, i, large_file_format);
4563 count = get_lock_count( data, i, large_file_format);
4564 offset = get_lock_offset( data, i, large_file_format, &err);
4567 * There is no error code marked "stupid client bug".... :-).
4569 if(err) {
4570 END_PROFILE(SMBlockingX);
4571 return ERROR_DOS(ERRDOS,ERRnoaccess);
4574 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4575 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name,
4576 (int)lock_timeout ));
4578 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4579 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
4581 if (NT_STATUS_V(status)) {
4582 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4584 * A blocking lock was requested. Package up
4585 * this smb into a queued request and push it
4586 * onto the blocking lock queue.
4588 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4589 END_PROFILE(SMBlockingX);
4590 return -1;
4593 break;
4597 /* If any of the above locks failed, then we must unlock
4598 all of the previous locks (X/Open spec). */
4599 if(i != num_locks && num_locks != 0) {
4601 * Ensure we don't do a remove on the lock that just failed,
4602 * as under POSIX rules, if we have a lock already there, we
4603 * will delete it (and we shouldn't) .....
4605 for(i--; i >= 0; i--) {
4606 lock_pid = get_lock_pid( data, i, large_file_format);
4607 count = get_lock_count( data, i, large_file_format);
4608 offset = get_lock_offset( data, i, large_file_format, &err);
4611 * There is no error code marked "stupid client bug".... :-).
4613 if(err) {
4614 END_PROFILE(SMBlockingX);
4615 return ERROR_DOS(ERRDOS,ERRnoaccess);
4618 do_unlock(fsp,conn,lock_pid,count,offset);
4620 END_PROFILE(SMBlockingX);
4621 return ERROR_NT(status);
4624 set_message(outbuf,2,0,True);
4626 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4627 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4629 END_PROFILE(SMBlockingX);
4630 return chain_reply(inbuf,outbuf,length,bufsize);
4633 /* Back from the dead for OS/2..... JRA. */
4635 /****************************************************************************
4636 Reply to a SMBreadbmpx (read block multiplex) request
4637 ****************************************************************************/
4639 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4641 ssize_t nread = -1;
4642 ssize_t total_read;
4643 char *data;
4644 SMB_OFF_T startpos;
4645 int outsize;
4646 size_t maxcount;
4647 int max_per_packet;
4648 size_t tcount;
4649 int pad;
4650 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4651 START_PROFILE(SMBreadBmpx);
4653 /* this function doesn't seem to work - disable by default */
4654 if (!lp_readbmpx()) {
4655 END_PROFILE(SMBreadBmpx);
4656 return ERROR_DOS(ERRSRV,ERRuseSTD);
4659 outsize = set_message(outbuf,8,0,True);
4661 CHECK_FSP(fsp,conn);
4662 CHECK_READ(fsp);
4663 CHECK_ERROR(fsp);
4665 startpos = IVAL(inbuf,smb_vwv1);
4666 maxcount = SVAL(inbuf,smb_vwv3);
4668 data = smb_buf(outbuf);
4669 pad = ((long)data)%4;
4670 if (pad)
4671 pad = 4 - pad;
4672 data += pad;
4674 max_per_packet = bufsize-(outsize+pad);
4675 tcount = maxcount;
4676 total_read = 0;
4678 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK, False)) {
4679 END_PROFILE(SMBreadBmpx);
4680 return ERROR_DOS(ERRDOS,ERRlock);
4683 do {
4684 size_t N = MIN(max_per_packet,tcount-total_read);
4686 nread = read_file(fsp,data,startpos,N);
4688 if (nread <= 0)
4689 nread = 0;
4691 if (nread < (ssize_t)N)
4692 tcount = total_read + nread;
4694 set_message(outbuf,8,nread,False);
4695 SIVAL(outbuf,smb_vwv0,startpos);
4696 SSVAL(outbuf,smb_vwv2,tcount);
4697 SSVAL(outbuf,smb_vwv6,nread);
4698 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4700 if (!send_smb(smbd_server_fd(),outbuf))
4701 exit_server("reply_readbmpx: send_smb failed.");
4703 total_read += nread;
4704 startpos += nread;
4705 } while (total_read < (ssize_t)tcount);
4707 END_PROFILE(SMBreadBmpx);
4708 return(-1);
4711 /****************************************************************************
4712 Reply to a SMBsetattrE.
4713 ****************************************************************************/
4715 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4717 struct utimbuf unix_times;
4718 int outsize = 0;
4719 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4720 START_PROFILE(SMBsetattrE);
4722 outsize = set_message(outbuf,0,0,True);
4724 if(!fsp || (fsp->conn != conn)) {
4725 END_PROFILE(SMBgetattrE);
4726 return ERROR_DOS(ERRDOS,ERRbadfid);
4730 * Convert the DOS times into unix times. Ignore create
4731 * time as UNIX can't set this.
4733 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4734 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4737 * Patch from Ray Frush <frush@engr.colostate.edu>
4738 * Sometimes times are sent as zero - ignore them.
4741 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4742 /* Ignore request */
4743 if( DEBUGLVL( 3 ) ) {
4744 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4745 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4747 END_PROFILE(SMBsetattrE);
4748 return(outsize);
4749 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4750 /* set modify time = to access time if modify time was 0 */
4751 unix_times.modtime = unix_times.actime;
4754 /* Set the date on this file */
4755 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4756 END_PROFILE(SMBsetattrE);
4757 return ERROR_DOS(ERRDOS,ERRnoaccess);
4760 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4761 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4763 END_PROFILE(SMBsetattrE);
4764 return(outsize);
4768 /* Back from the dead for OS/2..... JRA. */
4770 /****************************************************************************
4771 Reply to a SMBwritebmpx (write block multiplex primary) request.
4772 ****************************************************************************/
4774 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4776 size_t numtowrite;
4777 ssize_t nwritten = -1;
4778 int outsize = 0;
4779 SMB_OFF_T startpos;
4780 size_t tcount;
4781 BOOL write_through;
4782 int smb_doff;
4783 char *data;
4784 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4785 START_PROFILE(SMBwriteBmpx);
4787 CHECK_FSP(fsp,conn);
4788 CHECK_WRITE(fsp);
4789 CHECK_ERROR(fsp);
4791 tcount = SVAL(inbuf,smb_vwv1);
4792 startpos = IVAL(inbuf,smb_vwv3);
4793 write_through = BITSETW(inbuf+smb_vwv7,0);
4794 numtowrite = SVAL(inbuf,smb_vwv10);
4795 smb_doff = SVAL(inbuf,smb_vwv11);
4797 data = smb_base(inbuf) + smb_doff;
4799 /* If this fails we need to send an SMBwriteC response,
4800 not an SMBwritebmpx - set this up now so we don't forget */
4801 SCVAL(outbuf,smb_com,SMBwritec);
4803 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4804 END_PROFILE(SMBwriteBmpx);
4805 return(ERROR_DOS(ERRDOS,ERRlock));
4808 nwritten = write_file(fsp,data,startpos,numtowrite);
4810 if(lp_syncalways(SNUM(conn)) || write_through)
4811 sync_file(conn,fsp);
4813 if(nwritten < (ssize_t)numtowrite) {
4814 END_PROFILE(SMBwriteBmpx);
4815 return(UNIXERROR(ERRHRD,ERRdiskfull));
4818 /* If the maximum to be written to this file
4819 is greater than what we just wrote then set
4820 up a secondary struct to be attached to this
4821 fd, we will use this to cache error messages etc. */
4823 if((ssize_t)tcount > nwritten) {
4824 write_bmpx_struct *wbms;
4825 if(fsp->wbmpx_ptr != NULL)
4826 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4827 else
4828 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4830 if(!wbms) {
4831 DEBUG(0,("Out of memory in reply_readmpx\n"));
4832 END_PROFILE(SMBwriteBmpx);
4833 return(ERROR_DOS(ERRSRV,ERRnoresource));
4835 wbms->wr_mode = write_through;
4836 wbms->wr_discard = False; /* No errors yet */
4837 wbms->wr_total_written = nwritten;
4838 wbms->wr_errclass = 0;
4839 wbms->wr_error = 0;
4840 fsp->wbmpx_ptr = wbms;
4843 /* We are returning successfully, set the message type back to
4844 SMBwritebmpx */
4845 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4847 outsize = set_message(outbuf,1,0,True);
4849 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4851 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4852 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4854 if (write_through && tcount==nwritten) {
4855 /* We need to send both a primary and a secondary response */
4856 smb_setlen(outbuf,outsize - 4);
4857 if (!send_smb(smbd_server_fd(),outbuf))
4858 exit_server("reply_writebmpx: send_smb failed.");
4860 /* Now the secondary */
4861 outsize = set_message(outbuf,1,0,True);
4862 SCVAL(outbuf,smb_com,SMBwritec);
4863 SSVAL(outbuf,smb_vwv0,nwritten);
4866 END_PROFILE(SMBwriteBmpx);
4867 return(outsize);
4870 /****************************************************************************
4871 Reply to a SMBwritebs (write block multiplex secondary) request.
4872 ****************************************************************************/
4874 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4876 size_t numtowrite;
4877 ssize_t nwritten = -1;
4878 int outsize = 0;
4879 SMB_OFF_T startpos;
4880 size_t tcount;
4881 BOOL write_through;
4882 int smb_doff;
4883 char *data;
4884 write_bmpx_struct *wbms;
4885 BOOL send_response = False;
4886 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4887 START_PROFILE(SMBwriteBs);
4889 CHECK_FSP(fsp,conn);
4890 CHECK_WRITE(fsp);
4892 tcount = SVAL(inbuf,smb_vwv1);
4893 startpos = IVAL(inbuf,smb_vwv2);
4894 numtowrite = SVAL(inbuf,smb_vwv6);
4895 smb_doff = SVAL(inbuf,smb_vwv7);
4897 data = smb_base(inbuf) + smb_doff;
4899 /* We need to send an SMBwriteC response, not an SMBwritebs */
4900 SCVAL(outbuf,smb_com,SMBwritec);
4902 /* This fd should have an auxiliary struct attached,
4903 check that it does */
4904 wbms = fsp->wbmpx_ptr;
4905 if(!wbms) {
4906 END_PROFILE(SMBwriteBs);
4907 return(-1);
4910 /* If write through is set we can return errors, else we must cache them */
4911 write_through = wbms->wr_mode;
4913 /* Check for an earlier error */
4914 if(wbms->wr_discard) {
4915 END_PROFILE(SMBwriteBs);
4916 return -1; /* Just discard the packet */
4919 nwritten = write_file(fsp,data,startpos,numtowrite);
4921 if(lp_syncalways(SNUM(conn)) || write_through)
4922 sync_file(conn,fsp);
4924 if (nwritten < (ssize_t)numtowrite) {
4925 if(write_through) {
4926 /* We are returning an error - we can delete the aux struct */
4927 SAFE_FREE(wbms);
4928 fsp->wbmpx_ptr = NULL;
4929 END_PROFILE(SMBwriteBs);
4930 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4932 END_PROFILE(SMBwriteBs);
4933 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4936 /* Increment the total written, if this matches tcount
4937 we can discard the auxiliary struct (hurrah !) and return a writeC */
4938 wbms->wr_total_written += nwritten;
4939 if(wbms->wr_total_written >= tcount) {
4940 if (write_through) {
4941 outsize = set_message(outbuf,1,0,True);
4942 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4943 send_response = True;
4946 SAFE_FREE(wbms);
4947 fsp->wbmpx_ptr = NULL;
4950 if(send_response) {
4951 END_PROFILE(SMBwriteBs);
4952 return(outsize);
4955 END_PROFILE(SMBwriteBs);
4956 return(-1);
4959 /****************************************************************************
4960 Reply to a SMBgetattrE.
4961 ****************************************************************************/
4963 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4965 SMB_STRUCT_STAT sbuf;
4966 int outsize = 0;
4967 int mode;
4968 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4969 START_PROFILE(SMBgetattrE);
4971 outsize = set_message(outbuf,11,0,True);
4973 if(!fsp || (fsp->conn != conn)) {
4974 END_PROFILE(SMBgetattrE);
4975 return ERROR_DOS(ERRDOS,ERRbadfid);
4978 /* Do an stat on this file */
4980 if(fsp_stat(fsp, &sbuf)) {
4981 END_PROFILE(SMBgetattrE);
4982 return(UNIXERROR(ERRDOS,ERRnoaccess));
4985 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4987 /* Convert the times into dos times. Set create
4988 * date to be last modify date as UNIX doesn't save
4989 * this.
4992 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4993 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4994 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4995 if (mode & aDIR) {
4996 SIVAL(outbuf,smb_vwv6,0);
4997 SIVAL(outbuf,smb_vwv8,0);
4998 } else {
4999 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5000 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
5002 SSVAL(outbuf,smb_vwv10, mode);
5004 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5006 END_PROFILE(SMBgetattrE);
5007 return(outsize);