2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
31 /* look in server.c for some explanation of these variables */
33 extern int DEBUGLEVEL;
36 extern char magic_char;
37 extern BOOL case_sensitive;
38 extern BOOL case_preserve;
39 extern BOOL short_case_preserve;
40 extern pstring sesssetup_user;
41 extern fstring global_myworkgroup;
42 extern fstring global_myname;
44 extern int global_oplock_break;
45 uint32 global_client_caps = 0;
48 /****************************************************************************
49 report a possible attack via the password buffer overflow bug
50 ****************************************************************************/
51 static void overflow_attack(int len)
55 dbgtext( "ERROR: Invalid password length %d.\n", len );
56 dbgtext( "Your machine may be under attack by someone " );
57 dbgtext( "attempting to exploit an old bug.\n" );
58 dbgtext( "Attack was from IP = %s.\n", client_addr(Client) );
60 exit_server("possible attack");
64 /****************************************************************************
65 does _both_ nt->unix and unix->unix username remappings.
66 ****************************************************************************/
67 static void map_nt_and_unix_username(const char *domain, char *user)
73 * Pass the user through the NT -> unix user mapping
77 if (lp_server_role() != ROLE_DOMAIN_NONE)
79 memset(nt_username, 0, sizeof(nt_username));
82 slprintf(nt_username, sizeof(nt_username)-1, "%s\\%s",
87 fstrcpy(nt_username, user);
90 if (lookupsmbpwntnam(nt_username, &gmep))
92 fstrcpy(user, gmep.unix_name);
97 * Pass the user through the unix -> unix user mapping
101 (void)map_username(user);
104 * Do any UNIX username case mangling.
106 (void)Get_Pwnam( user, True);
109 /****************************************************************************
110 reply to an special message
111 ****************************************************************************/
112 int reply_special(char *inbuf,char *outbuf)
115 int msg_type = CVAL(inbuf,0);
116 int msg_flags = CVAL(inbuf,1);
118 extern fstring remote_machine;
119 extern fstring local_machine;
125 bzero(outbuf,smb_size);
127 smb_setlen(outbuf,0);
129 DEBUG(20,("NBT message\n"));
130 dump_data(20, inbuf, smb_len(inbuf));
133 case 0x81: /* session request */
134 CVAL(outbuf,0) = 0x82;
136 if (name_len(inbuf+4) > 50 ||
137 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
138 DEBUG(0,("Invalid name length in session request\n"));
141 name_extract(inbuf,4,name1);
142 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
143 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
146 fstrcpy(remote_machine,name2);
147 remote_machine[15] = 0;
148 trim_string(remote_machine," "," ");
149 strlower(remote_machine);
151 fstrcpy(local_machine,name1);
152 len = strlen(local_machine);
154 name_type = local_machine[15];
155 local_machine[15] = 0;
157 trim_string(local_machine," "," ");
158 strlower(local_machine);
160 if (name_type == 'R') {
161 /* We are being asked for a pathworks session ---
163 CVAL(outbuf, 0) = 0x83;
167 add_session_user(remote_machine);
169 reload_services(True);
173 claim_connection(NULL,"STATUS.",MAXSTATUS,True);
178 case 0x89: /* session keepalive request
179 (some old clients produce this?) */
180 CVAL(outbuf,0) = 0x85;
184 case 0x82: /* positive session response */
185 case 0x83: /* negative session response */
186 case 0x84: /* retarget session response */
187 DEBUG(0,("Unexpected session response\n"));
190 case 0x85: /* session keepalive */
195 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
196 msg_type, msg_flags));
202 /*******************************************************************
203 work out what error to give to a failed connection
204 ********************************************************************/
205 static int connection_error(char *inbuf,char *outbuf,int ecode)
207 if (ecode == ERRnoipc) {
208 return(ERROR(ERRDOS,ERRnoipc));
211 return(ERROR(ERRSRV,ecode));
216 /****************************************************************************
217 parse a share descriptor string
218 ****************************************************************************/
219 static void parse_connect(char *p,char *service,char *user,
220 char *password,int *pwlen,char *dev)
224 DEBUG(4,("parsing connect string %s\n",p));
226 p2 = strrchr(p,'\\');
230 fstrcpy(service,p2+1);
235 *pwlen = strlen(password);
242 p = strchr(service,'%');
253 /****************************************************************************
255 ****************************************************************************/
256 int reply_tcon(connection_struct *conn,
257 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
264 uint16 vuid = SVAL(inbuf,smb_uid);
268 *service = *user = *password = *dev = 0;
270 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
272 map_nt_and_unix_username(global_myworkgroup, user);
274 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
277 return(connection_error(inbuf,outbuf,ecode));
280 outsize = set_message(outbuf,2,0,True);
281 SSVAL(outbuf,smb_vwv0,max_recv);
282 SSVAL(outbuf,smb_vwv1,conn->cnum);
283 SSVAL(outbuf,smb_tid,conn->cnum);
285 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
286 service, user, conn->cnum));
292 /****************************************************************************
293 reply to a tcon and X
294 ****************************************************************************/
295 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
302 uint16 vuid = SVAL(inbuf,smb_uid);
303 int passlen = SVAL(inbuf,smb_vwv3);
307 *service = *user = *password = *devicename = 0;
309 /* we might have to close an old one */
310 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
311 close_cnum(conn,vuid);
314 if (passlen > MAX_PASS_LEN) {
315 overflow_attack(passlen);
318 memcpy(password,smb_buf(inbuf),passlen);
320 path = smb_buf(inbuf) + passlen;
323 if (strequal(password," "))
325 passlen = strlen(password);
328 fstrcpy(service,path+2);
329 p = strchr(service,'\\');
331 return(ERROR(ERRSRV,ERRinvnetname));
333 fstrcpy(service,p+1);
334 p = strchr(service,'%');
339 StrnCpy(devicename,path + strlen(path) + 1,6);
340 DEBUG(4,("Got device type %s\n",devicename));
342 map_nt_and_unix_username(global_myworkgroup, user);
344 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
347 return(connection_error(inbuf,outbuf,ecode));
349 if (Protocol < PROTOCOL_NT1) {
350 set_message(outbuf,2,strlen(devicename)+1,True);
351 pstrcpy(smb_buf(outbuf),devicename);
353 char *fsname = lp_fstype(SNUM(conn));
355 set_message(outbuf,3,3,True);
358 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
359 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
361 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
363 /* what does setting this bit do? It is set by NT4 and
364 may affect the ability to autorun mounted cdroms */
365 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
368 DEBUG(3,("tconX service=%s user=%s\n",
371 /* set the incoming and outgoing tid to the just created one */
372 SSVAL(inbuf,smb_tid,conn->cnum);
373 SSVAL(outbuf,smb_tid,conn->cnum);
375 return chain_reply(inbuf,outbuf,length,bufsize);
379 /****************************************************************************
380 reply to an unknown type
381 ****************************************************************************/
382 int reply_unknown(char *inbuf,char *outbuf)
385 type = CVAL(inbuf,smb_com);
387 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
388 smb_fn_name(type), type, type));
390 return(ERROR(ERRSRV,ERRunknownsmb));
394 /****************************************************************************
396 ****************************************************************************/
397 int reply_ioctl(connection_struct *conn,
398 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
400 DEBUG(3,("ignoring ioctl\n"));
402 /* we just say it succeeds and hope its all OK.
403 some day it would be nice to interpret them individually */
404 return set_message(outbuf,1,0,True);
406 return(ERROR(ERRSRV,ERRnosupport));
410 /****************************************************************************
411 always return an error: it's just a matter of which one...
412 ****************************************************************************/
413 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
414 char *smb_passwd, int smb_passlen,
415 char *smb_nt_passwd, int smb_nt_passlen)
417 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
419 if (lp_security() == SEC_USER)
421 smb_trust_acct = getsmbpwnam(user);
425 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
426 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
427 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
430 if (smb_trust_acct == NULL)
432 /* lkclXXXX: workstation entry doesn't exist */
433 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
434 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
435 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
439 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
441 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
442 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
443 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
445 if (!last_challenge(last_chal) ||
446 !smb_password_ok(smb_trust_acct, last_chal, NULL, NULL,
447 (unsigned char *)smb_passwd, smb_passlen,
448 (unsigned char *)smb_nt_passwd, smb_nt_passlen, NULL))
450 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
451 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
452 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
455 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
457 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
458 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
459 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
462 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
464 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
465 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
466 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
469 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
471 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
472 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
473 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
477 /* don't know what to do: indicate logon failure */
478 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
479 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
482 /****************************************************************************
483 Check for a valid username and password in security=server mode.
484 ****************************************************************************/
486 static BOOL check_server_security(char *orig_user, char *domain,
487 char *smb_apasswd, int smb_apasslen,
488 char *smb_ntpasswd, int smb_ntpasslen)
490 if(lp_security() != SEC_SERVER)
493 return server_validate(orig_user, domain,
494 smb_apasswd, smb_apasslen,
495 smb_ntpasswd, smb_ntpasslen);
498 /****************************************************************************
499 Check for a valid username and password in security=domain mode.
500 ****************************************************************************/
502 static BOOL check_domain_security(char *orig_user, char *domain,
503 char *smb_apasswd, int smb_apasslen,
504 char *smb_ntpasswd, int smb_ntpasslen,
505 uchar user_sess_key[16])
508 uint16 acct_type = 0;
510 if (lp_security() == SEC_SHARE || lp_security() == SEC_SERVER)
515 if (lp_security() == SEC_DOMAIN && strequal(domain, global_myworkgroup))
517 fstrcpy(acct_name, global_myname);
518 acct_type = SEC_CHAN_WKSTA;
522 fstrcpy(acct_name, global_myworkgroup);
523 acct_type = SEC_CHAN_DOMAIN;
526 return domain_client_validate(orig_user, domain,
527 acct_name, acct_type,
528 smb_apasswd, smb_apasslen,
529 smb_ntpasswd, smb_ntpasslen,
533 /****************************************************************************
534 reply to a session setup command
535 ****************************************************************************/
537 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
540 uchar user_sess_key[16];
544 int smb_apasslen = 0;
546 int smb_ntpasslen = 0;
547 pstring smb_ntpasswd;
548 BOOL valid_nt_password = False;
552 static BOOL done_sesssetup = False;
553 BOOL doencrypt = SMBENCRYPT();
559 smb_bufsize = SVAL(inbuf,smb_vwv2);
561 if (Protocol < PROTOCOL_NT1)
563 smb_apasslen = SVAL(inbuf,smb_vwv7);
564 if (smb_apasslen > MAX_PASS_LEN)
566 overflow_attack(smb_apasslen);
569 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
570 smb_apasswd[smb_apasslen] = 0;
571 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
573 if (!doencrypt && (lp_security() != SEC_SERVER)) {
574 smb_apasslen = strlen(smb_apasswd);
577 if (lp_server_ntlmv2() == True)
579 DEBUG(1,("NTLMv2-only accepted with NT LANMAN 1.0 and above.\n\
580 user %s attempted down-level SMB connection\n", user));
581 return(ERROR(ERRSRV,ERRbadpw));
586 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
587 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
588 enum remote_arch_types ra_type = get_remote_arch();
589 char *p = smb_buf(inbuf);
591 global_client_caps = IVAL(inbuf,smb_vwv11);
593 /* client_caps is used as final determination if client is NT or Win95.
594 This is needed to return the correct error codes in some
598 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
600 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
601 set_remote_arch( RA_WINNT);
603 set_remote_arch( RA_WIN95);
606 if (passlen1 != 24 && passlen2 <= 24)
609 if (passlen1 > MAX_PASS_LEN) {
610 overflow_attack(passlen1);
613 passlen1 = MIN(passlen1, MAX_PASS_LEN);
614 passlen2 = MIN(passlen2, MAX_PASS_LEN);
617 /* both Win95 and WinNT stuff up the password lengths for
618 non-encrypting systems. Uggh.
620 if passlen1==24 its a win95 system, and its setting the
621 password length incorrectly. Luckily it still works with the
622 default code because Win95 will null terminate the password
625 if passlen1>0 and passlen2>0 then maybe its a NT box and its
626 setting passlen2 to some random value which really stuffs
627 things up. we need to fix that one.
629 LKCLXXXX: the random value can be random 16 bit. old test
630 used to have ... && passlen <= 24) which of course fails
634 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 1)
638 if (doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
639 /* Save the lanman2 password and the NT md4 password. */
640 smb_apasslen = passlen1;
641 memcpy(smb_apasswd,p,smb_apasslen);
642 smb_apasswd[smb_apasslen] = 0;
643 smb_ntpasslen = passlen2;
644 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
645 smb_ntpasswd[smb_ntpasslen] = 0;
647 /* we use the first password that they gave */
648 smb_apasslen = passlen1;
649 StrnCpy(smb_apasswd,p,smb_apasslen);
651 /* trim the password */
652 smb_apasslen = strlen(smb_apasswd);
654 /* wfwg sometimes uses a space instead of a null */
655 if (strequal(smb_apasswd," ")) {
661 if (passlen2 == 0 && smb_apasslen == 0 && ra_type == RA_WIN95)
663 /* work-around for win95 NULL sessions, where NULL password is
664 actually put in the data stream before the domain name etc */
669 p += passlen1 + passlen2;
672 fstrcpy(user,p); p = skip_string(p,1);
675 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
676 domain, skip_string(p,1), skip_string(p,2)));
679 DEBUG(3,("sesssetupX:name=[%s]\n",user));
681 /* If name ends in $ then I think it's asking about whether a */
682 /* computer with that name (minus the $) has access. For now */
683 /* say yes to everything ending in $. */
684 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
686 return session_trust_account(conn, inbuf, outbuf, user,
687 smb_apasswd, smb_apasslen,
688 smb_ntpasswd, smb_ntpasslen);
691 /* If no username is sent use the guest account */
694 pstrcpy(user,lp_guestaccount(-1));
695 /* If no user and no password then set guest flag. */
696 if( *smb_apasswd == 0)
702 * In share level security, only overwrite sesssetup_use if
703 * it's a non null-session share. Helps keep %U and %G
707 if((lp_security() != SEC_SHARE) || (*user && !guest))
708 pstrcpy(sesssetup_user,user);
709 reload_services(True);
712 * Save the username before mapping. We will use
713 * the original username sent to us for security=server
714 * and security=domain checking.
717 pstrcpy( orig_user, user);
719 map_nt_and_unix_username(domain, user);
721 add_session_user(user);
724 * Check if the given username was the guest user with no password.
727 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
731 * Check with orig_user for security=server and
736 !check_server_security(orig_user, domain,
737 smb_apasswd, smb_apasslen,
738 smb_ntpasswd, smb_ntpasslen) &&
739 !check_domain_security(orig_user, domain,
740 smb_apasswd, smb_apasslen,
741 smb_ntpasswd, smb_ntpasslen, user_sess_key) &&
742 !check_hosts_equiv(user)
747 * If we get here then the user wasn't guest and the remote
748 * authentication methods failed. Check the authentication
749 * methods on this local server.
751 * If an NT password was supplied try and validate with that
752 * first. This is superior as the passwords are mixed case
753 * 128 length unicode.
758 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key))
759 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
761 valid_nt_password = True;
764 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key))
766 if (lp_security() >= SEC_USER)
768 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
769 return(ERROR(ERRSRV,ERRbadpw));
771 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
773 if (Get_Pwnam(user,True))
774 return(ERROR(ERRSRV,ERRbadpw));
778 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
779 * Then always map to guest account - as done below.
783 if (*smb_apasswd || !Get_Pwnam(user,True))
784 pstrcpy(user,lp_guestaccount(-1));
785 DEBUG(3,("Registered username %s for guest access\n",user));
790 if (!Get_Pwnam(user,True)) {
791 DEBUG(3,("No such user %s - using guest account\n",user));
792 pstrcpy(user,lp_guestaccount(-1));
796 if (!strequal(user,lp_guestaccount(-1)) &&
797 lp_servicenumber(user) < 0)
799 int homes = lp_servicenumber(HOMES_NAME);
800 char *home = get_home_dir(user);
801 if (homes >= 0 && home)
804 fstrcpy(home_dir, home);
805 lp_add_home(user,homes,home_dir);
809 /* it's ok - setup a reply */
810 if (Protocol < PROTOCOL_NT1) {
811 set_message(outbuf,3,0,True);
814 set_message(outbuf,3,3,True);
816 pstrcpy(p,"Unix"); p = skip_string(p,1);
817 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
818 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
819 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
820 /* perhaps grab OS version here?? */
823 /* Set the correct uid in the outgoing and incoming packets
824 We will use this on future requests to determine which
825 user we should become.
828 const struct passwd *pw = Get_Pwnam(user,False);
830 DEBUG(1,("Username %s is invalid on this system\n",user));
831 return(ERROR(ERRSRV,ERRbadpw));
838 SSVAL(outbuf,smb_vwv2,1);
840 /* register the name and uid as being validated, so further connections
841 to a uid can get through without a password, on the same VC */
842 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key);
844 SSVAL(outbuf,smb_uid,sess_vuid);
845 SSVAL(inbuf,smb_uid,sess_vuid);
848 max_send = MIN(max_send,smb_bufsize);
850 DEBUG(6,("Client requested max send size of %d\n", max_send));
852 done_sesssetup = True;
854 return chain_reply(inbuf,outbuf,length,bufsize);
858 /****************************************************************************
860 ****************************************************************************/
861 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
867 BOOL bad_path = False;
870 pstrcpy(name,smb_buf(inbuf) + 1);
871 if (!unix_dfs_convert(name,conn,0,&bad_path,&st))
873 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
874 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
877 mode = SVAL(inbuf,smb_vwv0);
879 if (check_name(name,conn)) {
881 ok = S_ISDIR(st.st_mode);
883 ok = dos_directory_exist(name,NULL);
888 /* We special case this - as when a Windows machine
889 is parsing a path is steps through the components
890 one at a time - if a component fails it expects
891 ERRbadpath, not ERRbadfile.
895 unix_ERR_class = ERRDOS;
896 unix_ERR_code = ERRbadpath;
900 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
901 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
902 (get_remote_arch() == RA_WINNT))
904 unix_ERR_class = ERRDOS;
905 unix_ERR_code = ERRbaddirectory;
909 return(UNIXERROR(ERRDOS,ERRbadpath));
912 outsize = set_message(outbuf,0,0,True);
914 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
920 /****************************************************************************
922 ****************************************************************************/
923 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
927 SMB_STRUCT_STAT sbuf;
932 BOOL bad_path = False;
934 pstrcpy(fname,smb_buf(inbuf) + 1);
936 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
937 under WfWg - weird! */
940 mode = aHIDDEN | aDIR;
941 if (!CAN_WRITE(conn)) mode |= aRONLY;
948 if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf))
950 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
951 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
953 if (check_name(fname,conn))
955 if (VALID_STAT(sbuf) || conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == 0)
957 mode = dos_mode(conn,fname,&sbuf);
959 mtime = sbuf.st_mtime;
965 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
971 if((errno == ENOENT) && bad_path)
973 unix_ERR_class = ERRDOS;
974 unix_ERR_code = ERRbadpath;
977 return(UNIXERROR(ERRDOS,ERRbadfile));
980 outsize = set_message(outbuf,10,0,True);
982 SSVAL(outbuf,smb_vwv0,mode);
983 if(lp_dos_filetime_resolution(SNUM(conn)) )
984 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
986 put_dos_date3(outbuf,smb_vwv1,mtime);
987 SIVAL(outbuf,smb_vwv3,(uint32)size);
989 if (Protocol >= PROTOCOL_NT1) {
990 char *p = strrchr(fname,'/');
991 uint16 flg2 = SVAL(outbuf,smb_flg2);
993 if (!is_8_3(fname, True))
994 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
997 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1003 /****************************************************************************
1005 ****************************************************************************/
1006 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1014 BOOL bad_path = False;
1016 pstrcpy(fname,smb_buf(inbuf) + 1);
1017 if (!unix_dfs_convert(fname,conn,0,&bad_path,&st))
1019 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1020 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1023 mode = SVAL(inbuf,smb_vwv0);
1024 mtime = make_unix_date3(inbuf+smb_vwv1);
1026 if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
1028 if (check_name(fname,conn))
1029 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1031 ok = set_filetime(conn,fname,mtime);
1035 if((errno == ENOENT) && bad_path)
1037 unix_ERR_class = ERRDOS;
1038 unix_ERR_code = ERRbadpath;
1041 return(UNIXERROR(ERRDOS,ERRnoaccess));
1044 outsize = set_message(outbuf,0,0,True);
1046 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1052 /****************************************************************************
1054 ****************************************************************************/
1055 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1058 SMB_BIG_UINT dfree,dsize,bsize;
1060 conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);
1062 outsize = set_message(outbuf,5,0,True);
1064 SSVAL(outbuf,smb_vwv0,dsize);
1065 SSVAL(outbuf,smb_vwv1,bsize/512);
1066 SSVAL(outbuf,smb_vwv2,512);
1067 SSVAL(outbuf,smb_vwv3,dfree);
1069 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1075 /****************************************************************************
1077 Can be called from SMBsearch, SMBffirst or SMBfunique.
1078 ****************************************************************************/
1079 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1090 BOOL finished = False;
1099 BOOL check_descend = False;
1100 BOOL expect_close = False;
1101 BOOL can_open = True;
1102 BOOL bad_path = False;
1104 *mask = *directory = *fname = 0;
1106 /* If we were called as SMBffirst then we must expect close. */
1107 if(CVAL(inbuf,smb_com) == SMBffirst)
1108 expect_close = True;
1110 outsize = set_message(outbuf,1,3,True);
1111 maxentries = SVAL(inbuf,smb_vwv0);
1112 dirtype = SVAL(inbuf,smb_vwv1);
1113 path = smb_buf(inbuf) + 1;
1114 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1117 /* dirtype &= ~aDIR; */
1119 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1122 if (status_len == 0)
1126 pstrcpy(directory,smb_buf(inbuf)+1);
1127 pstrcpy(dir2,smb_buf(inbuf)+1);
1128 if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL))
1130 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1131 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1135 if (!check_name(directory,conn))
1138 p = strrchr(dir2,'/');
1150 p = strrchr(directory,'/');
1156 if (strlen(directory) == 0)
1157 pstrcpy(directory,"./");
1159 CVAL(status,0) = dirtype;
1163 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1164 memcpy(mask,status+1,11);
1166 dirtype = CVAL(status,0) & 0x1F;
1167 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1170 string_set(&conn->dirpath,dptr_path(dptr_num));
1171 if (!case_sensitive)
1175 /* turn strings of spaces into a . */
1177 trim_string(mask,NULL," ");
1178 if ((p = strrchr(mask,' ')))
1183 trim_string(mask,NULL," ");
1189 /* Convert the formatted mask. (This code lives in trans2.c) */
1197 if((skip = skip_multibyte_char( *p )) != 0 )
1203 if (*p != '?' && *p != '*' && !isdoschar(*p))
1205 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1213 if (!strchr(mask,'.') && strlen(mask)>8)
1216 fstrcpy(tmp,&mask[8]);
1222 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1226 p = smb_buf(outbuf) + 3;
1230 if (status_len == 0)
1232 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1237 if((errno == ENOENT) && bad_path)
1239 unix_ERR_class = ERRDOS;
1240 unix_ERR_code = ERRbadpath;
1242 return (UNIXERROR(ERRDOS,ERRnofids));
1244 return(ERROR(ERRDOS,ERRnofids));
1248 DEBUG(4,("dptr_num is %d\n",dptr_num));
1252 if ((dirtype&0x1F) == aVOLID)
1254 memcpy(p,status,21);
1255 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1256 dptr_fill(p+12,dptr_num);
1257 if (dptr_zero(p+12) && (status_len==0))
1261 p += DIR_STRUCT_SIZE;
1265 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1266 conn->dirpath,lp_dontdescend(SNUM(conn))));
1267 if (in_list(conn->dirpath,
1268 lp_dontdescend(SNUM(conn)),True))
1269 check_descend = True;
1271 for (i=numentries;(i<maxentries) && !finished;i++)
1274 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1277 memcpy(p,status,21);
1278 make_dir_struct(p,mask,fname,size,mode,date);
1279 dptr_fill(p+12,dptr_num);
1282 p += DIR_STRUCT_SIZE;
1291 if (numentries == 0 || !ok)
1293 CVAL(outbuf,smb_rcls) = ERRDOS;
1294 SSVAL(outbuf,smb_err,ERRnofiles);
1297 /* If we were called as SMBffirst with smb_search_id == NULL
1298 and no entries were found then return error and close dirptr
1301 if(ok && expect_close && numentries == 0 && status_len == 0)
1303 CVAL(outbuf,smb_rcls) = ERRDOS;
1304 SSVAL(outbuf,smb_err,ERRnofiles);
1305 /* Also close the dptr - we know it's gone */
1306 dptr_close(dptr_num);
1309 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1310 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1311 dptr_close(dptr_num);
1313 SSVAL(outbuf,smb_vwv0,numentries);
1314 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1315 CVAL(smb_buf(outbuf),0) = 5;
1316 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1318 if (Protocol >= PROTOCOL_NT1) {
1319 uint16 flg2 = SVAL(outbuf,smb_flg2);
1320 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1323 outsize += DIR_STRUCT_SIZE*numentries;
1324 smb_setlen(outbuf,outsize - 4);
1326 if ((! *directory) && dptr_path(dptr_num))
1327 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1329 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1330 smb_fn_name(CVAL(inbuf,smb_com)),
1331 mask, directory, dirtype, numentries, maxentries ) );
1337 /****************************************************************************
1338 reply to a fclose (stop directory search)
1339 ****************************************************************************/
1340 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1348 outsize = set_message(outbuf,1,0,True);
1349 path = smb_buf(inbuf) + 1;
1350 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1353 if (status_len == 0)
1354 return(ERROR(ERRSRV,ERRsrverror));
1356 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1358 if(dptr_fetch(status+12,&dptr_num)) {
1359 /* Close the dptr - we know it's gone */
1360 dptr_close(dptr_num);
1363 SSVAL(outbuf,smb_vwv0,0);
1365 DEBUG(3,("search close\n"));
1371 /****************************************************************************
1373 ****************************************************************************/
1375 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1385 SMB_STRUCT_STAT sbuf;
1386 BOOL bad_path = False;
1388 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1390 share_mode = SVAL(inbuf,smb_vwv0);
1392 pstrcpy(fname,smb_buf(inbuf)+1);
1393 if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL))
1395 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1396 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1401 return(ERROR(ERRSRV,ERRnofids));
1403 if (!check_name(fname,conn))
1405 if((errno == ENOENT) && bad_path)
1407 unix_ERR_class = ERRDOS;
1408 unix_ERR_code = ERRbadpath;
1411 return(UNIXERROR(ERRDOS,ERRnoaccess));
1414 unixmode = unix_mode(conn,aARCH);
1416 open_file_shared(fsp, conn, fname, share_mode,
1417 (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN),
1418 unixmode, oplock_request, &rmode, NULL);
1422 if((errno == ENOENT) && bad_path)
1424 unix_ERR_class = ERRDOS;
1425 unix_ERR_code = ERRbadpath;
1428 return(UNIXERROR(ERRDOS,ERRnoaccess));
1431 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1432 close_file(fsp,False);
1433 return(ERROR(ERRDOS,ERRnoaccess));
1436 size = sbuf.st_size;
1437 fmode = dos_mode(conn,fname,&sbuf);
1438 mtime = sbuf.st_mtime;
1441 DEBUG(3,("attempt to open a directory %s\n",fname));
1442 close_file(fsp,False);
1443 return(ERROR(ERRDOS,ERRnoaccess));
1446 outsize = set_message(outbuf,7,0,True);
1447 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1448 SSVAL(outbuf,smb_vwv1,fmode);
1449 if(lp_dos_filetime_resolution(SNUM(conn)) )
1450 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1452 put_dos_date3(outbuf,smb_vwv2,mtime);
1453 SIVAL(outbuf,smb_vwv4,(uint32)size);
1454 SSVAL(outbuf,smb_vwv6,rmode);
1456 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1457 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1460 if(fsp->granted_oplock)
1461 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1466 /****************************************************************************
1467 reply to an open and X
1468 ****************************************************************************/
1469 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1472 int smb_mode = SVAL(inbuf,smb_vwv3);
1473 int smb_attr = SVAL(inbuf,smb_vwv5);
1474 /* Breakout the oplock request bits so we can set the
1475 reply bits separately. */
1476 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1477 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1478 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1480 int open_flags = SVAL(inbuf,smb_vwv2);
1481 int smb_sattr = SVAL(inbuf,smb_vwv4);
1482 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1484 int smb_ofun = SVAL(inbuf,smb_vwv8);
1487 int fmode=0,mtime=0,rmode=0;
1488 SMB_STRUCT_STAT sbuf;
1490 BOOL bad_path = False;
1493 /* If it's an IPC, pass off the pipe handler. */
1494 if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
1496 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1499 /* XXXX we need to handle passed times, sattr and flags */
1501 pstrcpy(fname,smb_buf(inbuf));
1502 if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL))
1504 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1505 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1510 return(ERROR(ERRSRV,ERRnofids));
1512 if (!check_name(fname,conn))
1514 if((errno == ENOENT) && bad_path)
1516 unix_ERR_class = ERRDOS;
1517 unix_ERR_code = ERRbadpath;
1520 return(UNIXERROR(ERRDOS,ERRnoaccess));
1523 unixmode = unix_mode(conn,smb_attr | aARCH);
1525 open_file_shared(fsp, conn, fname, smb_mode, smb_ofun, unixmode,
1526 oplock_request, &rmode, &smb_action);
1530 if((errno == ENOENT) && bad_path)
1532 unix_ERR_class = ERRDOS;
1533 unix_ERR_code = ERRbadpath;
1536 return(UNIXERROR(ERRDOS,ERRnoaccess));
1539 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1540 close_file(fsp,False);
1541 return(ERROR(ERRDOS,ERRnoaccess));
1544 size = sbuf.st_size;
1545 fmode = dos_mode(conn,fname,&sbuf);
1546 mtime = sbuf.st_mtime;
1548 close_file(fsp,False);
1549 return(ERROR(ERRDOS,ERRnoaccess));
1552 /* If the caller set the extended oplock request bit
1553 and we granted one (by whatever means) - set the
1554 correct bit for extended oplock reply.
1557 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1558 smb_action |= EXTENDED_OPLOCK_GRANTED;
1561 if(ex_oplock_request && fsp->granted_oplock) {
1562 smb_action |= EXTENDED_OPLOCK_GRANTED;
1565 /* If the caller set the core oplock request bit
1566 and we granted one (by whatever means) - set the
1567 correct bit for core oplock reply.
1570 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1571 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1574 if(core_oplock_request && fsp->granted_oplock) {
1575 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1578 set_message(outbuf,15,0,True);
1579 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1580 SSVAL(outbuf,smb_vwv3,fmode);
1581 if(lp_dos_filetime_resolution(SNUM(conn)) )
1582 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1584 put_dos_date3(outbuf,smb_vwv4,mtime);
1585 SIVAL(outbuf,smb_vwv6,(uint32)size);
1586 SSVAL(outbuf,smb_vwv8,rmode);
1587 SSVAL(outbuf,smb_vwv11,smb_action);
1589 return chain_reply(inbuf,outbuf,length,bufsize);
1593 /****************************************************************************
1594 reply to a SMBulogoffX
1595 ****************************************************************************/
1596 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1598 uint16 vuid = SVAL(inbuf,smb_uid);
1599 user_struct *vuser = get_valid_user_struct(vuid);
1602 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1605 /* in user level security we are supposed to close any files
1606 open by this user */
1607 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1608 file_close_user(vuid);
1611 invalidate_vuid(vuid);
1613 set_message(outbuf,2,0,True);
1615 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1617 return chain_reply(inbuf,outbuf,length,bufsize);
1621 /****************************************************************************
1622 reply to a mknew or a create
1623 ****************************************************************************/
1624 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1632 BOOL bad_path = False;
1634 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1636 com = SVAL(inbuf,smb_com);
1638 createmode = SVAL(inbuf,smb_vwv0);
1639 pstrcpy(fname,smb_buf(inbuf)+1);
1640 if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL))
1642 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1643 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1646 if (createmode & aVOLID)
1648 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1651 unixmode = unix_mode(conn,createmode);
1655 return(ERROR(ERRSRV,ERRnofids));
1657 if (!check_name(fname,conn))
1659 if((errno == ENOENT) && bad_path)
1661 unix_ERR_class = ERRDOS;
1662 unix_ERR_code = ERRbadpath;
1665 return(UNIXERROR(ERRDOS,ERRnoaccess));
1670 /* We should fail if file exists. */
1675 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1679 /* Open file in dos compatibility share mode. */
1680 open_file_shared(fsp, conn, fname,
1681 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1682 ofun, unixmode, oplock_request, NULL, NULL);
1686 if((errno == ENOENT) && bad_path)
1688 unix_ERR_class = ERRDOS;
1689 unix_ERR_code = ERRbadpath;
1692 return(UNIXERROR(ERRDOS,ERRnoaccess));
1695 outsize = set_message(outbuf,1,0,True);
1696 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1698 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1699 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1702 if(fsp->granted_oplock)
1703 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1705 DEBUG( 2, ( "new file %s\n", fname ) );
1706 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1707 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1713 /****************************************************************************
1714 reply to a create temporary file
1715 ****************************************************************************/
1716 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1723 BOOL bad_path = False;
1725 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1727 createmode = SVAL(inbuf,smb_vwv0);
1728 pstrcpy(fname,smb_buf(inbuf)+1);
1729 pstrcat(fname,"/TMXXXXXX");
1730 if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL))
1732 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1733 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1736 unixmode = unix_mode(conn,createmode);
1740 return(ERROR(ERRSRV,ERRnofids));
1742 if (!check_name(fname,conn))
1744 if((errno == ENOENT) && bad_path)
1746 unix_ERR_class = ERRDOS;
1747 unix_ERR_code = ERRbadpath;
1750 return(UNIXERROR(ERRDOS,ERRnoaccess));
1753 pstrcpy(fname2,(char *)mktemp(fname));
1755 /* Open file in dos compatibility share mode. */
1756 /* We should fail if file exists. */
1757 open_file_shared(fsp,conn,fname2,
1758 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1759 (FILE_CREATE_IF_NOT_EXIST | FILE_EXISTS_FAIL),
1760 unixmode, oplock_request, NULL, NULL);
1764 if((errno == ENOENT) && bad_path)
1766 unix_ERR_class = ERRDOS;
1767 unix_ERR_code = ERRbadpath;
1770 return(UNIXERROR(ERRDOS,ERRnoaccess));
1773 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1774 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1775 CVAL(smb_buf(outbuf),0) = 4;
1776 pstrcpy(smb_buf(outbuf) + 1,fname2);
1778 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1779 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1782 if(fsp->granted_oplock)
1783 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1785 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1786 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1787 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1793 /*******************************************************************
1794 check if a user is allowed to delete a file
1795 ********************************************************************/
1796 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1798 SMB_STRUCT_STAT sbuf;
1801 if (!CAN_WRITE(conn)) return(False);
1803 if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False);
1804 fmode = dos_mode(conn,fname,&sbuf);
1805 if (fmode & aDIR) return(False);
1806 if (!lp_delete_readonly(SNUM(conn))) {
1807 if (fmode & aRONLY) return(False);
1809 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1811 if (!check_file_sharing(conn,fname,False)) return(False);
1815 /****************************************************************************
1817 ****************************************************************************/
1818 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1827 int error = ERRnoaccess;
1830 BOOL bad_path = False;
1832 *directory = *mask = 0;
1834 dirtype = SVAL(inbuf,smb_vwv0);
1836 pstrcpy(name,smb_buf(inbuf) + 1);
1838 DEBUG(3,("reply_unlink : %s\n",name));
1840 if (!unix_dfs_convert(name,conn,0,&bad_path,NULL))
1842 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1843 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1846 p = strrchr(name,'/');
1848 pstrcpy(directory,"./");
1852 pstrcpy(directory,name);
1856 if (is_mangled(mask))
1857 check_mangled_cache( mask );
1859 has_wild = strchr(mask,'*') || strchr(mask,'?');
1862 pstrcat(directory,"/");
1863 pstrcat(directory,mask);
1864 if (can_delete(directory,conn,dirtype) && !conn->vfs_ops.unlink(directory))
1867 exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
1869 void *dirptr = NULL;
1872 if (check_name(directory,conn))
1873 dirptr = OpenDir(conn, directory, True);
1875 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1876 the pattern matches against the long name, otherwise the short name
1877 We don't implement this yet XXXX
1884 if (strequal(mask,"????????.???"))
1887 while ((dname = ReadDirName(dirptr)))
1890 pstrcpy(fname,dname);
1892 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1894 error = ERRnoaccess;
1895 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1896 if (!can_delete(fname,conn,dirtype)) continue;
1897 if (!conn->vfs_ops.unlink(fname)) count++;
1898 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1906 return(ERROR(ERRDOS,error));
1909 if((errno == ENOENT) && bad_path)
1911 unix_ERR_class = ERRDOS;
1912 unix_ERR_code = ERRbadpath;
1914 return(UNIXERROR(ERRDOS,error));
1918 outsize = set_message(outbuf,0,0,True);
1924 /****************************************************************************
1925 reply to a readbraw (core+ protocol)
1926 ****************************************************************************/
1927 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1929 size_t maxcount,mincount;
1932 char *header = outbuf;
1937 * Special check if an oplock break has been issued
1938 * and the readraw request croses on the wire, we must
1939 * return a zero length response here.
1942 if(global_oplock_break)
1944 _smb_setlen(header,0);
1945 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1946 DEBUG(5,("readbraw - oplock break finished\n"));
1950 fsp = file_fsp(inbuf,smb_vwv0);
1952 startpos = IVAL(inbuf,smb_vwv1);
1953 #ifdef LARGE_SMB_OFF_T
1954 if(CVAL(inbuf,smb_wct) == 10) {
1956 * This is a large offset (64 bit) read.
1958 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1960 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1961 (double)startpos ));
1962 _smb_setlen(header,0);
1963 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1967 #endif /* LARGE_SMB_OFF_T */
1968 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1969 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1971 /* ensure we don't overrun the packet size */
1972 maxcount = MIN(65535,maxcount);
1973 maxcount = MAX(mincount,maxcount);
1975 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1976 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1977 _smb_setlen(header,0);
1978 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1982 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1984 SMB_OFF_T size = fsp->size;
1985 SMB_OFF_T sizeneeded = startpos + maxcount;
1987 if (size < sizeneeded)
1990 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0)
1992 if (!fsp->can_write)
1996 nread = MIN(maxcount,(size - startpos));
1999 if (nread < mincount)
2002 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2003 fsp->fnum, (double)startpos,
2004 maxcount, mincount, nread ) );
2008 BOOL seek_fail = False;
2010 _smb_setlen(header,nread);
2012 #if USE_READ_PREDICTION
2013 if (!fsp->can_write)
2014 predict = read_predict(fsp, fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
2015 #endif /* USE_READ_PREDICTION */
2017 if ((nread-predict) > 0) {
2018 if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) {
2019 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2026 ret = (ssize_t)vfs_transfer_file(-1, fsp->fd_ptr->fd, Client, NULL,
2027 (SMB_OFF_T)(nread-predict),header,4+predict,
2032 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2033 fsp->fsp_name,startpos,nread,ret));
2035 #else /* UNSAFE_READRAW */
2036 ret = read_file(fsp,header+4,startpos,nread);
2037 if (ret < mincount) ret = 0;
2039 _smb_setlen(header,ret);
2040 transfer_file(0,Client,0,header,4+ret,0);
2041 #endif /* UNSAFE_READRAW */
2043 DEBUG(5,("readbraw finished\n"));
2048 /****************************************************************************
2049 reply to a lockread (core+ protocol)
2050 ****************************************************************************/
2051 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2060 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2062 CHECK_FSP(fsp,conn);
2066 numtoread = SVAL(inbuf,smb_vwv1);
2067 startpos = IVAL(inbuf,smb_vwv2);
2069 outsize = set_message(outbuf,5,3,True);
2070 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2071 data = smb_buf(outbuf) + 3;
2073 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
2074 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2076 * A blocking lock was requested. Package up
2077 * this smb into a queued request and push it
2078 * onto the blocking lock queue.
2080 if(push_blocking_lock_request(inbuf, length, -1, 0))
2083 return (ERROR(eclass,ecode));
2086 nread = read_file(fsp,data,startpos,numtoread);
2089 return(UNIXERROR(ERRDOS,ERRnoaccess));
2092 SSVAL(outbuf,smb_vwv0,nread);
2093 SSVAL(outbuf,smb_vwv5,nread+3);
2094 SSVAL(smb_buf(outbuf),1,nread);
2096 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2097 fsp->fnum, numtoread, nread ) );
2103 /****************************************************************************
2105 ****************************************************************************/
2106 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2113 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2115 CHECK_FSP(fsp,conn);
2119 numtoread = SVAL(inbuf,smb_vwv1);
2120 startpos = IVAL(inbuf,smb_vwv2);
2122 outsize = set_message(outbuf,5,3,True);
2123 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2124 data = smb_buf(outbuf) + 3;
2126 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2127 return(ERROR(ERRDOS,ERRlock));
2129 if (numtoread > 0) {
2130 nread = read_file(fsp,data,startpos,numtoread);
2134 return(UNIXERROR(ERRDOS,ERRnoaccess));
2137 SSVAL(outbuf,smb_vwv0,nread);
2138 SSVAL(outbuf,smb_vwv5,nread+3);
2139 CVAL(smb_buf(outbuf),0) = 1;
2140 SSVAL(smb_buf(outbuf),1,nread);
2142 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2143 fsp->fnum, numtoread, nread ) );
2149 /****************************************************************************
2150 reply to a read and X
2151 ****************************************************************************/
2152 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2154 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2155 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2156 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2157 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2161 /* If it's an IPC, pass off the pipe handler. */
2163 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2165 CHECK_FSP(fsp,conn);
2169 set_message(outbuf,12,0,True);
2170 data = smb_buf(outbuf);
2172 #ifdef LARGE_SMB_OFF_T
2173 if(CVAL(inbuf,smb_wct) == 12) {
2175 * This is a large offset (64 bit) read.
2177 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2179 #endif /* LARGE_SMB_OFF_T */
2181 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2182 return(ERROR(ERRDOS,ERRlock));
2183 nread = read_file(fsp,data,startpos,smb_maxcnt);
2186 return(UNIXERROR(ERRDOS,ERRnoaccess));
2188 SSVAL(outbuf,smb_vwv5,nread);
2189 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2190 SSVAL(smb_buf(outbuf),-2,nread);
2192 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2193 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2195 return chain_reply(inbuf,outbuf,length,bufsize);
2198 /****************************************************************************
2199 reply to a writebraw (core+ or LANMAN1.0 protocol)
2200 ****************************************************************************/
2201 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2204 ssize_t total_written=0;
2205 size_t numtowrite=0;
2210 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2213 CHECK_FSP(fsp,conn);
2217 tcount = IVAL(inbuf,smb_vwv1);
2218 startpos = IVAL(inbuf,smb_vwv3);
2219 write_through = BITSETW(inbuf+smb_vwv7,0);
2221 /* We have to deal with slightly different formats depending
2222 on whether we are using the core+ or lanman1.0 protocol */
2223 if(Protocol <= PROTOCOL_COREPLUS) {
2224 numtowrite = SVAL(smb_buf(inbuf),-2);
2225 data = smb_buf(inbuf);
2227 numtowrite = SVAL(inbuf,smb_vwv10);
2228 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2231 /* force the error type */
2232 CVAL(inbuf,smb_com) = SMBwritec;
2233 CVAL(outbuf,smb_com) = SMBwritec;
2235 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2236 return(ERROR(ERRDOS,ERRlock));
2238 if (seek_file(fsp,startpos) == -1) {
2239 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2240 return(UNIXERROR(ERRDOS,ERRnoaccess));
2244 nwritten = write_file(fsp,data,numtowrite);
2246 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2247 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2249 if (nwritten < numtowrite)
2250 return(UNIXERROR(ERRHRD,ERRdiskfull));
2252 total_written = nwritten;
2254 /* Return a message to the redirector to tell it
2255 to send more bytes */
2256 CVAL(outbuf,smb_com) = SMBwritebraw;
2257 SSVALS(outbuf,smb_vwv0,-1);
2258 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2259 send_smb(Client,outbuf);
2261 /* Now read the raw data into the buffer and write it */
2262 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2263 exit_server("secondary writebraw failed");
2266 /* Even though this is not an smb message, smb_len
2267 returns the generic length of an smb message */
2268 numtowrite = smb_len(inbuf);
2270 if (tcount > nwritten+numtowrite) {
2271 DEBUG(3,("Client overestimated the write %d %d %d\n",
2272 tcount,nwritten,numtowrite));
2275 nwritten = vfs_transfer_file(Client, NULL, -1, fsp,
2276 (SMB_OFF_T)numtowrite,NULL,0,
2278 total_written += nwritten;
2280 /* Set up outbuf to return the correct return */
2281 outsize = set_message(outbuf,1,0,True);
2282 CVAL(outbuf,smb_com) = SMBwritec;
2283 SSVAL(outbuf,smb_vwv0,total_written);
2285 if (nwritten < (ssize_t)numtowrite) {
2286 CVAL(outbuf,smb_rcls) = ERRHRD;
2287 SSVAL(outbuf,smb_err,ERRdiskfull);
2290 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2291 lp_strict_sync(SNUM(conn)))
2292 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2294 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2295 fsp->fnum, (double)startpos, numtowrite, total_written));
2297 /* we won't return a status if write through is not selected - this
2298 follows what WfWg does */
2299 if (!write_through && total_written==tcount)
2305 /****************************************************************************
2306 reply to a writeunlock (core+)
2307 ****************************************************************************/
2308 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2310 ssize_t nwritten = -1;
2316 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2319 CHECK_FSP(fsp,conn);
2323 numtowrite = SVAL(inbuf,smb_vwv1);
2324 startpos = IVAL(inbuf,smb_vwv2);
2325 data = smb_buf(inbuf) + 3;
2327 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2328 return(ERROR(ERRDOS,ERRlock));
2330 if(seek_file(fsp,startpos) == -1)
2331 return(UNIXERROR(ERRDOS,ERRnoaccess));
2333 /* The special X/Open SMB protocol handling of
2334 zero length writes is *NOT* done for
2339 nwritten = write_file(fsp,data,numtowrite);
2341 if (lp_syncalways(SNUM(conn)) && lp_strict_sync(SNUM(conn)))
2342 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2344 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2345 return(UNIXERROR(ERRDOS,ERRnoaccess));
2347 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2348 return(ERROR(eclass,ecode));
2350 outsize = set_message(outbuf,1,0,True);
2352 SSVAL(outbuf,smb_vwv0,nwritten);
2354 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2355 fsp->fnum, numtowrite, nwritten ) );
2360 /****************************************************************************
2362 ****************************************************************************/
2363 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2366 ssize_t nwritten = -1;
2369 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2372 /* If it's an IPC, pass off the pipe handler. */
2374 return reply_pipe_write(inbuf,outbuf,dum_size,dum_buffsize);
2376 CHECK_FSP(fsp,conn);
2380 numtowrite = SVAL(inbuf,smb_vwv1);
2381 startpos = IVAL(inbuf,smb_vwv2);
2382 data = smb_buf(inbuf) + 3;
2384 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2385 return(ERROR(ERRDOS,ERRlock));
2387 if(seek_file(fsp,startpos) == -1)
2388 return(UNIXERROR(ERRDOS,ERRnoaccess));
2390 /* X/Open SMB protocol says that if smb_vwv1 is
2391 zero then the file size should be extended or
2392 truncated to the size given in smb_vwv[2-3] */
2394 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2396 nwritten = write_file(fsp,data,numtowrite);
2398 if (lp_syncalways(SNUM(conn)) && lp_strict_sync(SNUM(conn)))
2399 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2401 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2402 return(UNIXERROR(ERRDOS,ERRnoaccess));
2404 outsize = set_message(outbuf,1,0,True);
2406 SSVAL(outbuf,smb_vwv0,nwritten);
2408 if (nwritten < (ssize_t)numtowrite) {
2409 CVAL(outbuf,smb_rcls) = ERRHRD;
2410 SSVAL(outbuf,smb_err,ERRdiskfull);
2413 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2414 fsp->fnum, numtowrite, nwritten));
2420 /****************************************************************************
2421 reply to a write and X
2422 ****************************************************************************/
2423 int reply_write_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 numtowrite = SVAL(inbuf,smb_vwv10);
2428 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2429 ssize_t nwritten = -1;
2430 int smb_doff = SVAL(inbuf,smb_vwv11);
2433 /* If it's an IPC, pass off the pipe handler. */
2435 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2437 CHECK_FSP(fsp,conn);
2441 data = smb_base(inbuf) + smb_doff;
2443 #ifdef LARGE_SMB_OFF_T
2444 if(CVAL(inbuf,smb_wct) == 14) {
2446 * This is a large offset (64 bit) write.
2448 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2450 #endif /* LARGE_SMB_OFF_T */
2452 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2453 return(ERROR(ERRDOS,ERRlock));
2455 if(seek_file(fsp,startpos) == -1)
2456 return(UNIXERROR(ERRDOS,ERRnoaccess));
2458 /* X/Open SMB protocol says that, unlike SMBwrite
2459 if the length is zero then NO truncation is
2460 done, just a write of zero. To truncate a file,
2465 nwritten = write_file(fsp,data,numtowrite);
2467 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2468 return(UNIXERROR(ERRDOS,ERRnoaccess));
2470 set_message(outbuf,6,0,True);
2472 SSVAL(outbuf,smb_vwv2,nwritten);
2474 if (nwritten < (ssize_t)numtowrite) {
2475 CVAL(outbuf,smb_rcls) = ERRHRD;
2476 SSVAL(outbuf,smb_err,ERRdiskfull);
2479 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2480 fsp->fnum, numtowrite, nwritten));
2482 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2483 lp_strict_sync(SNUM(conn)))
2484 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2486 return chain_reply(inbuf,outbuf,length,bufsize);
2490 /****************************************************************************
2492 ****************************************************************************/
2493 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2499 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2501 CHECK_FSP(fsp,conn);
2504 mode = SVAL(inbuf,smb_vwv1) & 3;
2505 startpos = IVAL(inbuf,smb_vwv2);
2509 case 0: umode = SEEK_SET; break;
2510 case 1: umode = SEEK_CUR; break;
2511 case 2: umode = SEEK_END; break;
2513 umode = SEEK_SET; break;
2516 if((res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2517 return(UNIXERROR(ERRDOS,ERRnoaccess));
2521 outsize = set_message(outbuf,2,0,True);
2522 SIVALS(outbuf,smb_vwv0,res);
2524 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2525 fsp->fnum, (double)startpos, mode));
2530 /****************************************************************************
2532 ****************************************************************************/
2533 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2535 int outsize = set_message(outbuf,0,0,True);
2536 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2539 CHECK_FSP(fsp,conn);
2544 file_sync_all(conn);
2546 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2549 DEBUG(3,("flush\n"));
2554 /****************************************************************************
2556 ****************************************************************************/
2557 int reply_exit(connection_struct *conn,
2558 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2560 int outsize = set_message(outbuf,0,0,True);
2561 DEBUG(3,("exit\n"));
2567 /****************************************************************************
2568 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2569 ****************************************************************************/
2570 int reply_close(connection_struct *conn,
2571 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2575 int32 eclass = 0, err = 0;
2576 files_struct *fsp = NULL;
2578 outsize = set_message(outbuf,0,0,True);
2580 /* If it's an IPC, pass off to the pipe handler. */
2582 return reply_pipe_close(conn, inbuf,outbuf);
2585 fsp = file_fsp(inbuf,smb_vwv0);
2588 * We can only use CHECK_FSP if we know it's not a directory.
2591 if(!fsp || !fsp->open || (fsp->conn != conn))
2592 return(ERROR(ERRDOS,ERRbadfid));
2594 if(HAS_CACHED_ERROR(fsp)) {
2595 eclass = fsp->wbmpx_ptr->wr_errclass;
2596 err = fsp->wbmpx_ptr->wr_error;
2599 if(fsp->is_directory) {
2601 * Special case - close NT SMB directory
2604 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2605 close_directory(fsp);
2608 * Close ordinary file.
2612 * If there was a modify time outstanding,
2613 * try and set it here.
2615 if(fsp->pending_modtime)
2616 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2619 * Now take care of any time sent in the close.
2621 mtime = make_unix_date3(inbuf+smb_vwv1);
2623 /* try and set the date */
2624 set_filetime(conn, fsp->fsp_name,mtime);
2626 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2627 fsp->fd_ptr->fd, fsp->fnum,
2628 conn->num_files_open));
2630 close_file(fsp,True);
2633 /* We have a cached error */
2635 return(ERROR(eclass,err));
2641 /****************************************************************************
2642 reply to a writeclose (Core+ protocol)
2643 ****************************************************************************/
2644 int reply_writeclose(connection_struct *conn,
2645 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2648 ssize_t nwritten = -1;
2653 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2655 CHECK_FSP(fsp,conn);
2659 numtowrite = SVAL(inbuf,smb_vwv1);
2660 startpos = IVAL(inbuf,smb_vwv2);
2661 mtime = make_unix_date3(inbuf+smb_vwv4);
2662 data = smb_buf(inbuf) + 1;
2664 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2665 return(ERROR(ERRDOS,ERRlock));
2667 if(seek_file(fsp,startpos) == -1)
2668 return(UNIXERROR(ERRDOS,ERRnoaccess));
2670 nwritten = write_file(fsp,data,numtowrite);
2672 set_filetime(conn, fsp->fsp_name,mtime);
2674 close_file(fsp,True);
2676 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2677 fsp->fnum, numtowrite, nwritten,
2678 conn->num_files_open));
2681 return(UNIXERROR(ERRDOS,ERRnoaccess));
2683 outsize = set_message(outbuf,1,0,True);
2685 SSVAL(outbuf,smb_vwv0,nwritten);
2690 /****************************************************************************
2692 ****************************************************************************/
2693 int reply_lock(connection_struct *conn,
2694 char *inbuf,char *outbuf, int length, int dum_buffsize)
2696 int outsize = set_message(outbuf,0,0,True);
2697 SMB_OFF_T count,offset;
2700 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2702 CHECK_FSP(fsp,conn);
2705 count = IVAL(inbuf,smb_vwv1);
2706 offset = IVAL(inbuf,smb_vwv3);
2708 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2709 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2711 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2712 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2714 * A blocking lock was requested. Package up
2715 * this smb into a queued request and push it
2716 * onto the blocking lock queue.
2718 if(push_blocking_lock_request(inbuf, length, -1, 0))
2721 return (ERROR(eclass,ecode));
2728 /****************************************************************************
2730 ****************************************************************************/
2731 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2733 int outsize = set_message(outbuf,0,0,True);
2734 SMB_OFF_T count,offset;
2737 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2739 CHECK_FSP(fsp,conn);
2742 count = IVAL(inbuf,smb_vwv1);
2743 offset = IVAL(inbuf,smb_vwv3);
2745 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2746 return (ERROR(eclass,ecode));
2748 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2749 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2755 /****************************************************************************
2757 ****************************************************************************/
2758 int reply_tdis(connection_struct *conn,
2759 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2761 int outsize = set_message(outbuf,0,0,True);
2764 vuid = SVAL(inbuf,smb_uid);
2767 DEBUG(4,("Invalid connection in tdis\n"));
2768 return(ERROR(ERRSRV,ERRinvnid));
2773 close_cnum(conn,vuid);
2780 /****************************************************************************
2782 ****************************************************************************/
2783 int reply_echo(connection_struct *conn,
2784 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2786 int smb_reverb = SVAL(inbuf,smb_vwv0);
2788 int data_len = smb_buflen(inbuf);
2789 int outsize = set_message(outbuf,1,data_len,True);
2791 /* copy any incoming data back out */
2793 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2795 if (smb_reverb > 100) {
2796 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2800 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2801 SSVAL(outbuf,smb_vwv0,seq_num);
2803 smb_setlen(outbuf,outsize - 4);
2805 send_smb(Client,outbuf);
2808 DEBUG(3,("echo %d times\n", smb_reverb));
2814 /****************************************************************************
2815 reply to a printopen
2816 ****************************************************************************/
2817 int reply_printopen(connection_struct *conn,
2818 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2825 *fname = *fname2 = 0;
2827 if (!CAN_PRINT(conn))
2828 return(ERROR(ERRDOS,ERRnoaccess));
2833 pstrcpy(s,smb_buf(inbuf)+1);
2836 if (!(isalnum((int)*p) || strchr("._-",*p)))
2841 if (strlen(s) > 10) s[10] = 0;
2843 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2848 return(ERROR(ERRSRV,ERRnofids));
2850 pstrcpy(fname2,(char *)mktemp(fname));
2852 if (!check_name(fname2,conn)) {
2854 return(ERROR(ERRDOS,ERRnoaccess));
2857 /* Open for exclusive use, write only. */
2858 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2859 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2863 return(UNIXERROR(ERRDOS,ERRnoaccess));
2866 /* force it to be a print file */
2867 fsp->print_file = True;
2869 outsize = set_message(outbuf,1,0,True);
2870 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2872 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2873 fname2, fsp->fd_ptr->fd, fsp->fnum));
2879 /****************************************************************************
2880 reply to a printclose
2881 ****************************************************************************/
2882 int reply_printclose(connection_struct *conn,
2883 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2885 int outsize = set_message(outbuf,0,0,True);
2886 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2888 CHECK_FSP(fsp,conn);
2891 if (!CAN_PRINT(conn))
2892 return(ERROR(ERRDOS,ERRnoaccess));
2894 DEBUG(3,("printclose fd=%d fnum=%d\n",
2895 fsp->fd_ptr->fd,fsp->fnum));
2897 close_file(fsp,True);
2903 /****************************************************************************
2904 reply to a printqueue
2905 ****************************************************************************/
2906 int reply_printqueue(connection_struct *conn,
2907 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2909 int outsize = set_message(outbuf,2,3,True);
2910 int max_count = SVAL(inbuf,smb_vwv0);
2911 int start_index = SVAL(inbuf,smb_vwv1);
2913 /* we used to allow the client to get the cnum wrong, but that
2914 is really quite gross and only worked when there was only
2915 one printer - I think we should now only accept it if they
2916 get it right (tridge) */
2917 if (!CAN_PRINT(conn))
2918 return(ERROR(ERRDOS,ERRnoaccess));
2920 SSVAL(outbuf,smb_vwv0,0);
2921 SSVAL(outbuf,smb_vwv1,0);
2922 CVAL(smb_buf(outbuf),0) = 1;
2923 SSVAL(smb_buf(outbuf),1,0);
2925 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2926 start_index, max_count));
2929 print_queue_struct *queue = NULL;
2930 char *p = smb_buf(outbuf) + 3;
2931 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2932 int num_to_get = ABS(max_count);
2933 int first = (max_count>0?start_index:start_index+max_count+1);
2939 num_to_get = MIN(num_to_get,count-first);
2942 for (i=first;i<first+num_to_get;i++) {
2943 put_dos_date2(p,0,queue[i].time);
2944 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2945 SSVAL(p,5,printjob_encode(SNUM(conn),
2947 SIVAL(p,7,queue[i].size);
2949 StrnCpy(p+12,queue[i].user,16);
2954 outsize = set_message(outbuf,2,28*count+3,False);
2955 SSVAL(outbuf,smb_vwv0,count);
2956 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2957 CVAL(smb_buf(outbuf),0) = 1;
2958 SSVAL(smb_buf(outbuf),1,28*count);
2961 if (queue) free(queue);
2963 DEBUG(3,("%d entries returned in queue\n",count));
2970 /****************************************************************************
2971 reply to a printwrite
2972 ****************************************************************************/
2973 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2976 int outsize = set_message(outbuf,0,0,True);
2978 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2980 if (!CAN_PRINT(conn))
2981 return(ERROR(ERRDOS,ERRnoaccess));
2983 CHECK_FSP(fsp,conn);
2987 numtowrite = SVAL(smb_buf(inbuf),1);
2988 data = smb_buf(inbuf) + 3;
2990 if (write_file(fsp,data,numtowrite) != numtowrite)
2991 return(UNIXERROR(ERRDOS,ERRnoaccess));
2993 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2999 /****************************************************************************
3001 ****************************************************************************/
3002 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3005 int outsize,ret= -1;
3006 BOOL bad_path = False;
3008 pstrcpy(directory,smb_buf(inbuf) + 1);
3009 if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL))
3011 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
3012 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
3015 if (check_name(directory, conn))
3016 ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
3017 unix_mode(conn,aDIR));
3021 if((errno == ENOENT) && bad_path)
3023 unix_ERR_class = ERRDOS;
3024 unix_ERR_code = ERRbadpath;
3026 return(UNIXERROR(ERRDOS,ERRnoaccess));
3029 outsize = set_message(outbuf,0,0,True);
3031 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
3036 /****************************************************************************
3037 Static function used by reply_rmdir to delete an entire directory
3039 ****************************************************************************/
3040 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3044 void *dirptr = OpenDir(conn, directory, False);
3049 while((dname = ReadDirName(dirptr)))
3054 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3057 /* Construct the full name. */
3058 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3064 pstrcpy(fullname, directory);
3065 pstrcat(fullname, "/");
3066 pstrcat(fullname, dname);
3068 if(conn->vfs_ops.lstat(fullname, &st) != 0)
3074 if(st.st_mode & S_IFDIR)
3076 if(recursive_rmdir(conn, fullname)!=0)
3081 if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
3087 else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
3097 /****************************************************************************
3099 ****************************************************************************/
3100 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3105 BOOL bad_path = False;
3107 pstrcpy(directory,smb_buf(inbuf) + 1);
3108 if (!unix_dfs_convert(directory,conn, NULL,&bad_path,NULL))
3110 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
3111 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
3114 if (check_name(directory,conn))
3117 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3118 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0);
3119 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
3121 /* Check to see if the only thing in this directory are
3122 vetoed files/directories. If so then delete them and
3123 retry. If we fail to delete any of them (and we *don't*
3124 do a recursive delete) then fail the rmdir. */
3125 BOOL all_veto_files = True;
3127 void *dirptr = OpenDir(conn, directory, False);
3131 int dirpos = TellDir(dirptr);
3132 while ((dname = ReadDirName(dirptr)))
3134 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3136 if(!IS_VETO_PATH(conn, dname))
3138 all_veto_files = False;
3144 SeekDir(dirptr,dirpos);
3145 while ((dname = ReadDirName(dirptr)))
3150 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3153 /* Construct the full name. */
3154 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3159 pstrcpy(fullname, directory);
3160 pstrcat(fullname, "/");
3161 pstrcat(fullname, dname);
3163 if(conn->vfs_ops.lstat(fullname, &st) != 0)
3165 if(st.st_mode & S_IFDIR)
3167 if(lp_recursive_veto_delete(SNUM(conn)))
3169 DEBUG(0, ("ERROR: recursive_rmdir()\n"));
3170 if(recursive_rmdir(conn, fullname) != 0)
3173 if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
3176 else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
3180 /* Retry the rmdir */
3181 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0);
3191 DEBUG(3,("couldn't remove directory %s : %s\n",
3192 directory,strerror(errno)));
3197 if((errno == ENOENT) && bad_path)
3199 unix_ERR_class = ERRDOS;
3200 unix_ERR_code = ERRbadpath;
3202 return(UNIXERROR(ERRDOS,ERRbadpath));
3205 outsize = set_message(outbuf,0,0,True);
3207 DEBUG( 3, ( "rmdir %s\n", directory ) );
3213 /*******************************************************************
3214 resolve wildcards in a filename rename
3215 ********************************************************************/
3216 static BOOL resolve_wildcards(char *name1,char *name2)
3218 fstring root1,root2;
3222 name1 = strrchr(name1,'/');
3223 name2 = strrchr(name2,'/');
3225 if (!name1 || !name2) return(False);
3227 fstrcpy(root1,name1);
3228 fstrcpy(root2,name2);
3229 p = strrchr(root1,'.');
3236 p = strrchr(root2,'.');
3268 pstrcpy(name2,root2);
3271 pstrcat(name2,ext2);
3277 /*******************************************************************
3278 check if a user is allowed to rename a file
3279 ********************************************************************/
3280 static BOOL can_rename(char *fname,connection_struct *conn)
3282 SMB_STRUCT_STAT sbuf;
3284 if (!CAN_WRITE(conn)) return(False);
3286 if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False);
3287 if (!check_file_sharing(conn,fname,True)) return(False);
3292 /****************************************************************************
3293 The guts of the rename command, split out so it may be called by the NT SMB
3295 ****************************************************************************/
3296 int rename_internals(connection_struct *conn,
3297 char *inbuf, char *outbuf, char *name,
3298 char *newname, BOOL replace_if_exists)
3302 pstring newname_last_component;
3305 BOOL bad_path1 = False;
3306 BOOL bad_path2 = False;
3308 int error = ERRnoaccess;
3311 *directory = *mask = 0;
3313 if (!unix_dfs_convert(name,conn,0,&bad_path1,NULL))
3315 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
3316 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
3318 if (!unix_dfs_convert(newname,conn,newname_last_component,&bad_path2,NULL))
3320 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
3321 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
3325 * Split the old name into directory and last component
3326 * strings. Note that if (!unix_dfs_convert may have stripped off a
3327 * leading ./ from both name and newname if the rename is
3328 * at the root of the share. We need to make sure either both
3329 * name and newname contain a / character or neither of them do
3330 * as this is checked in resolve_wildcards().
3333 p = strrchr(name,'/');
3335 pstrcpy(directory,".");
3339 pstrcpy(directory,name);
3341 *p = '/'; /* Replace needed for exceptional test below. */
3344 if (is_mangled(mask))
3345 check_mangled_cache( mask );
3347 has_wild = strchr(mask,'*') || strchr(mask,'?');
3351 * No wildcards - just process the one file.
3353 BOOL is_short_name = is_8_3(name, True);
3355 /* Add a terminating '/' to the directory name. */
3356 pstrcat(directory,"/");
3357 pstrcat(directory,mask);
3359 /* Ensure newname contains a '/' also */
3360 if(strrchr(newname,'/') == 0) {
3363 pstrcpy(tmpstr, "./");
3364 pstrcat(tmpstr, newname);
3365 pstrcpy(newname, tmpstr);
3368 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3369 case_sensitive, case_preserve, short_case_preserve, directory,
3370 newname, newname_last_component, is_short_name));
3373 * Check for special case with case preserving and not
3374 * case sensitive, if directory and newname are identical,
3375 * and the old last component differs from the original
3376 * last component only by case, then we should allow
3377 * the rename (user is trying to change the case of the
3380 if((case_sensitive == False) &&
3381 (((case_preserve == True) &&
3382 (is_short_name == False)) ||
3383 ((short_case_preserve == True) &&
3384 (is_short_name == True))) &&
3385 strcsequal(directory, newname)) {
3386 pstring newname_modified_last_component;
3389 * Get the last component of the modified name.
3390 * Note that we guarantee that newname contains a '/'
3393 p = strrchr(newname,'/');
3394 pstrcpy(newname_modified_last_component,p+1);
3396 if(strcsequal(newname_modified_last_component,
3397 newname_last_component) == False) {
3399 * Replace the modified last component with
3402 pstrcpy(p+1, newname_last_component);
3406 if(replace_if_exists) {
3408 * NT SMB specific flag - rename can overwrite
3409 * file with the same name so don't check for
3412 if(resolve_wildcards(directory,newname) &&
3413 can_rename(directory,conn) &&
3414 !conn->vfs_ops.rename(dos_to_unix(directory,False),
3418 if (resolve_wildcards(directory,newname) &&
3419 can_rename(directory,conn) &&
3420 !vfs_file_exist(conn,dos_to_unix(newname,False),NULL) &&
3421 !conn->vfs_ops.rename(dos_to_unix(directory,False),
3426 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3427 directory,newname));
3429 if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
3430 if (!count && exists && vfs_file_exist(conn,dos_to_unix(newname,False),NULL)) {
3436 * Wildcards - process each file that matches.
3438 void *dirptr = NULL;
3442 if (check_name(directory,conn))
3443 dirptr = OpenDir(conn, directory, True);
3448 if (strequal(mask,"????????.???"))
3451 while ((dname = ReadDirName(dirptr))) {
3453 pstrcpy(fname,dname);
3455 if(!mask_match(fname, mask, case_sensitive, False))
3458 error = ERRnoaccess;
3459 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3460 if (!can_rename(fname,conn)) {
3461 DEBUG(6,("rename %s refused\n", fname));
3464 pstrcpy(destname,newname);
3466 if (!resolve_wildcards(fname,destname)) {
3467 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3471 if (!replace_if_exists && vfs_file_exist(conn,dos_to_unix(destname,False),NULL)) {
3472 DEBUG(6,("file_exist %s\n", destname));
3477 if (!conn->vfs_ops.rename(dos_to_unix(fname,False),destname))
3479 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3487 return(ERROR(ERRDOS,error));
3489 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3490 unix_ERR_class = ERRDOS;
3491 unix_ERR_code = ERRbadpath;
3493 return(UNIXERROR(ERRDOS,error));
3500 /****************************************************************************
3502 ****************************************************************************/
3504 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3510 pstrcpy(name,smb_buf(inbuf) + 1);
3511 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3513 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3515 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3517 outsize = set_message(outbuf,0,0,True);
3522 /*******************************************************************
3523 copy a file as part of a reply_copy
3524 ******************************************************************/
3526 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3527 int count,BOOL target_is_directory)
3532 files_struct *fsp1,*fsp2;
3535 pstrcpy(dest,dest1);
3536 if (target_is_directory) {
3537 char *p = strrchr(src,'/');
3546 if (!vfs_file_exist(conn,dos_to_unix(src,False),&st))
3553 open_file_shared(fsp1, conn, src,
3554 SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_RDONLY),
3555 (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN), 0, 0, &Access, &action);
3562 if (!target_is_directory && count)
3567 close_file(fsp1,False);
3570 open_file_shared(fsp2, conn, dest,
3571 SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_WRONLY),
3572 ofun, st.st_mode, 0, &Access, &action);
3575 close_file(fsp1,False);
3580 if ((ofun&3) == 1) {
3581 if(conn->vfs_ops.lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3582 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3585 * Stop the copy from occurring.
3593 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0);
3595 close_file(fsp1,False);
3596 close_file(fsp2,False);
3598 return(ret == st.st_size);
3603 /****************************************************************************
3604 reply to a file copy.
3605 ****************************************************************************/
3606 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3611 pstring mask,newname;
3614 int error = ERRnoaccess;
3617 int tid2 = SVAL(inbuf,smb_vwv0);
3618 int ofun = SVAL(inbuf,smb_vwv1);
3619 int flags = SVAL(inbuf,smb_vwv2);
3620 BOOL target_is_directory=False;
3621 BOOL bad_path1 = False;
3622 BOOL bad_path2 = False;
3624 *directory = *mask = 0;
3626 pstrcpy(name,smb_buf(inbuf));
3627 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3629 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3631 if (tid2 != conn->cnum) {
3632 /* can't currently handle inter share copies XXXX */
3633 DEBUG(3,("Rejecting inter-share copy\n"));
3634 return(ERROR(ERRSRV,ERRinvdevice));
3637 if (!unix_dfs_convert(name,conn,0,&bad_path1,NULL))
3639 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
3640 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
3642 if (!unix_dfs_convert(newname,conn,0,&bad_path2,NULL))
3644 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
3645 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
3648 target_is_directory = dos_directory_exist(newname,NULL);
3650 if ((flags&1) && target_is_directory) {
3651 return(ERROR(ERRDOS,ERRbadfile));
3654 if ((flags&2) && !target_is_directory) {
3655 return(ERROR(ERRDOS,ERRbadpath));
3658 if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
3659 /* wants a tree copy! XXXX */
3660 DEBUG(3,("Rejecting tree copy\n"));
3661 return(ERROR(ERRSRV,ERRerror));
3664 p = strrchr(name,'/');
3666 pstrcpy(directory,"./");
3670 pstrcpy(directory,name);
3674 if (is_mangled(mask))
3675 check_mangled_cache( mask );
3677 has_wild = strchr(mask,'*') || strchr(mask,'?');
3680 pstrcat(directory,"/");
3681 pstrcat(directory,mask);
3682 if (resolve_wildcards(directory,newname) &&
3683 copy_file(directory,newname,conn,ofun,
3684 count,target_is_directory)) count++;
3685 if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
3687 void *dirptr = NULL;
3691 if (check_name(directory,conn))
3692 dirptr = OpenDir(conn, directory, True);
3698 if (strequal(mask,"????????.???"))
3701 while ((dname = ReadDirName(dirptr)))
3704 pstrcpy(fname,dname);
3706 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3708 error = ERRnoaccess;
3709 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3710 pstrcpy(destname,newname);
3711 if (resolve_wildcards(fname,destname) &&
3712 copy_file(directory,newname,conn,ofun,
3713 count,target_is_directory)) count++;
3714 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3722 return(ERROR(ERRDOS,error));
3725 if((errno == ENOENT) && (bad_path1 || bad_path2))
3727 unix_ERR_class = ERRDOS;
3728 unix_ERR_code = ERRbadpath;
3730 return(UNIXERROR(ERRDOS,error));
3734 outsize = set_message(outbuf,1,0,True);
3735 SSVAL(outbuf,smb_vwv0,count);
3740 /****************************************************************************
3742 ****************************************************************************/
3743 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3751 if (!CAN_SETDIR(snum))
3752 return(ERROR(ERRDOS,ERRnoaccess));
3754 pstrcpy(newdir,smb_buf(inbuf) + 1);
3757 if (strlen(newdir) == 0) {
3760 ok = dos_directory_exist(newdir,NULL);
3762 string_set(&conn->connectpath,newdir);
3767 return(ERROR(ERRDOS,ERRbadpath));
3769 outsize = set_message(outbuf,0,0,True);
3770 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3772 DEBUG(3,("setdir %s\n", newdir));
3777 /****************************************************************************
3778 reply to a lockingX request
3779 ****************************************************************************/
3780 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3782 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3783 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3785 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3787 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3788 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3789 SMB_OFF_T count = 0, offset = 0;
3790 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3793 uint32 ecode=0, dummy2;
3794 int eclass=0, dummy1;
3795 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3796 CHECK_FSP(fsp,conn);
3799 data = smb_buf(inbuf);
3801 /* Check if this is an oplock break on a file
3802 we have granted an oplock on.
3804 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3807 SMB_DEV_T dev = fsp->fd_ptr->dev;
3808 SMB_INO_T inode = fsp->fd_ptr->inode;
3810 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3813 * Make sure we have granted an oplock on this file.
3815 if(!fsp->granted_oplock)
3817 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3818 no oplock granted on this file.\n", fsp->fnum));
3819 return ERROR(ERRDOS,ERRlock);
3822 /* Remove the oplock flag from the sharemode. */
3823 lock_share_entry(fsp->conn, dev, inode, &token);
3824 if(remove_share_oplock(token, fsp)==False) {
3826 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3827 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3829 unlock_share_entry(fsp->conn, dev, inode, token);
3831 unlock_share_entry(fsp->conn, dev, inode, token);
3833 /* Clear the granted flag and return. */
3834 fsp->granted_oplock = False;
3837 /* if this is a pure oplock break request then don't send a reply */
3838 if (num_locks == 0 && num_ulocks == 0)
3840 /* Sanity check - ensure a pure oplock break is not a
3842 if(CVAL(inbuf,smb_vwv0) != 0xff)
3843 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3844 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3849 /* Data now points at the beginning of the list
3850 of smb_unlkrng structs */
3851 for(i = 0; i < (int)num_ulocks; i++) {
3852 if(!large_file_format) {
3853 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3854 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3856 #ifdef LARGE_SMB_OFF_T
3858 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3859 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3860 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3861 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3863 #endif /* LARGE_SMB_OFF_T */
3865 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3866 (double)offset, (double)count, fsp->fsp_name ));
3868 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3869 return ERROR(eclass,ecode);
3872 /* Setup the timeout in seconds. */
3873 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3875 /* Now do any requested locks */
3876 data += ((large_file_format ? 20 : 10)*num_ulocks);
3878 /* Data now points at the beginning of the list
3879 of smb_lkrng structs */
3881 for(i = 0; i < (int)num_locks; i++) {
3882 if(!large_file_format) {
3883 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3884 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3886 #ifdef LARGE_SMB_OFF_T
3888 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3889 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3890 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3891 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3893 #endif /* LARGE_SMB_OFF_T */
3895 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3896 (double)offset, (double)count, fsp->fsp_name ));
3898 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3900 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3902 * A blocking lock was requested. Package up
3903 * this smb into a queued request and push it
3904 * onto the blocking lock queue.
3906 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3913 /* If any of the above locks failed, then we must unlock
3914 all of the previous locks (X/Open spec). */
3915 if(i != num_locks && num_locks != 0) {
3916 for(; i >= 0; i--) {
3917 if(!large_file_format) {
3918 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3919 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3921 #ifdef LARGE_SMB_OFF_T
3923 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3924 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3925 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3926 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3928 #endif /* LARGE_SMB_OFF_T */
3930 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3932 return ERROR(eclass,ecode);
3935 set_message(outbuf,2,0,True);
3937 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3938 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3940 return chain_reply(inbuf,outbuf,length,bufsize);
3944 /****************************************************************************
3945 reply to a SMBreadbmpx (read block multiplex) request
3946 ****************************************************************************/
3947 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3958 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3960 /* this function doesn't seem to work - disable by default */
3962 return(ERROR(ERRSRV,ERRuseSTD));
3964 outsize = set_message(outbuf,8,0,True);
3966 CHECK_FSP(fsp,conn);
3970 startpos = IVAL(inbuf,smb_vwv1);
3971 maxcount = SVAL(inbuf,smb_vwv3);
3973 data = smb_buf(outbuf);
3974 pad = ((long)data)%4;
3975 if (pad) pad = 4 - pad;
3978 max_per_packet = bufsize-(outsize+pad);
3982 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3983 return(ERROR(ERRDOS,ERRlock));
3987 size_t N = MIN(max_per_packet,tcount-total_read);
3989 nread = read_file(fsp,data,startpos,N);
3991 if (nread <= 0) nread = 0;
3993 if (nread < (ssize_t)N)
3994 tcount = total_read + nread;
3996 set_message(outbuf,8,nread,False);
3997 SIVAL(outbuf,smb_vwv0,startpos);
3998 SSVAL(outbuf,smb_vwv2,tcount);
3999 SSVAL(outbuf,smb_vwv6,nread);
4000 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4002 send_smb(Client,outbuf);
4004 total_read += nread;
4007 while (total_read < (ssize_t)tcount);
4012 /****************************************************************************
4013 reply to a SMBwritebmpx (write block multiplex primary) request
4014 ****************************************************************************/
4015 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4018 ssize_t nwritten = -1;
4025 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4027 CHECK_FSP(fsp,conn);
4031 tcount = SVAL(inbuf,smb_vwv1);
4032 startpos = IVAL(inbuf,smb_vwv3);
4033 write_through = BITSETW(inbuf+smb_vwv7,0);
4034 numtowrite = SVAL(inbuf,smb_vwv10);
4035 smb_doff = SVAL(inbuf,smb_vwv11);
4037 data = smb_base(inbuf) + smb_doff;
4039 /* If this fails we need to send an SMBwriteC response,
4040 not an SMBwritebmpx - set this up now so we don't forget */
4041 CVAL(outbuf,smb_com) = SMBwritec;
4043 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
4044 return(ERROR(ERRDOS,ERRlock));
4046 if(seek_file(fsp,startpos) == -1)
4047 return(UNIXERROR(ERRDOS,ERRnoaccess));
4049 nwritten = write_file(fsp,data,numtowrite);
4051 if((lp_syncalways(SNUM(conn)) || write_through) &&
4052 lp_strict_sync(SNUM(conn)))
4053 conn->vfs_ops.sync(fsp->fd_ptr->fd);
4055 if(nwritten < (ssize_t)numtowrite)
4056 return(UNIXERROR(ERRHRD,ERRdiskfull));
4058 /* If the maximum to be written to this file
4059 is greater than what we just wrote then set
4060 up a secondary struct to be attached to this
4061 fd, we will use this to cache error messages etc. */
4062 if((ssize_t)tcount > nwritten)
4064 write_bmpx_struct *wbms;
4065 if(fsp->wbmpx_ptr != NULL)
4066 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4068 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4071 DEBUG(0,("Out of memory in reply_readmpx\n"));
4072 return(ERROR(ERRSRV,ERRnoresource));
4074 wbms->wr_mode = write_through;
4075 wbms->wr_discard = False; /* No errors yet */
4076 wbms->wr_total_written = nwritten;
4077 wbms->wr_errclass = 0;
4079 fsp->wbmpx_ptr = wbms;
4082 /* We are returning successfully, set the message type back to
4084 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4086 outsize = set_message(outbuf,1,0,True);
4088 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4090 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4091 fsp->fnum, numtowrite, nwritten ) );
4093 if (write_through && tcount==nwritten) {
4094 /* we need to send both a primary and a secondary response */
4095 smb_setlen(outbuf,outsize - 4);
4096 send_smb(Client,outbuf);
4098 /* now the secondary */
4099 outsize = set_message(outbuf,1,0,True);
4100 CVAL(outbuf,smb_com) = SMBwritec;
4101 SSVAL(outbuf,smb_vwv0,nwritten);
4108 /****************************************************************************
4109 reply to a SMBwritebs (write block multiplex secondary) request
4110 ****************************************************************************/
4111 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4114 ssize_t nwritten = -1;
4121 write_bmpx_struct *wbms;
4122 BOOL send_response = False;
4123 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4125 CHECK_FSP(fsp,conn);
4128 tcount = SVAL(inbuf,smb_vwv1);
4129 startpos = IVAL(inbuf,smb_vwv2);
4130 numtowrite = SVAL(inbuf,smb_vwv6);
4131 smb_doff = SVAL(inbuf,smb_vwv7);
4133 data = smb_base(inbuf) + smb_doff;
4135 /* We need to send an SMBwriteC response, not an SMBwritebs */
4136 CVAL(outbuf,smb_com) = SMBwritec;
4138 /* This fd should have an auxiliary struct attached,
4139 check that it does */
4140 wbms = fsp->wbmpx_ptr;
4141 if(!wbms) return(-1);
4143 /* If write through is set we can return errors, else we must
4145 write_through = wbms->wr_mode;
4147 /* Check for an earlier error */
4148 if(wbms->wr_discard)
4149 return -1; /* Just discard the packet */
4151 if(seek_file(fsp,startpos) == -1)
4155 /* We are returning an error - we can delete the aux struct */
4156 if (wbms) free((char *)wbms);
4157 fsp->wbmpx_ptr = NULL;
4158 return(UNIXERROR(ERRDOS,ERRnoaccess));
4160 return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
4163 nwritten = write_file(fsp,data,numtowrite);
4165 if((lp_syncalways(SNUM(conn)) || write_through) &&
4166 lp_strict_sync(SNUM(conn)))
4167 conn->vfs_ops.sync(fsp->fd_ptr->fd);
4169 if (nwritten < (ssize_t)numtowrite)
4173 /* We are returning an error - we can delete the aux struct */
4174 if (wbms) free((char *)wbms);
4175 fsp->wbmpx_ptr = NULL;
4176 return(ERROR(ERRHRD,ERRdiskfull));
4178 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4181 /* Increment the total written, if this matches tcount
4182 we can discard the auxiliary struct (hurrah !) and return a writeC */
4183 wbms->wr_total_written += nwritten;
4184 if(wbms->wr_total_written >= tcount)
4188 outsize = set_message(outbuf,1,0,True);
4189 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4190 send_response = True;
4194 fsp->wbmpx_ptr = NULL;
4204 /****************************************************************************
4205 reply to a SMBsetattrE
4206 ****************************************************************************/
4207 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4209 struct utimbuf unix_times;
4211 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4213 outsize = set_message(outbuf,0,0,True);
4215 CHECK_FSP(fsp,conn);
4218 /* Convert the DOS times into unix times. Ignore create
4219 time as UNIX can't set this.
4221 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4222 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4225 * Patch from Ray Frush <frush@engr.colostate.edu>
4226 * Sometimes times are sent as zero - ignore them.
4229 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4231 /* Ignore request */
4234 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4235 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4239 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4241 /* set modify time = to access time if modify time was 0 */
4242 unix_times.modtime = unix_times.actime;
4245 /* Set the date on this file */
4246 if(file_utime(conn, fsp->fsp_name, &unix_times))
4247 return(ERROR(ERRDOS,ERRnoaccess));
4249 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4250 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4256 /****************************************************************************
4257 reply to a SMBgetattrE
4258 ****************************************************************************/
4259 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4261 SMB_STRUCT_STAT sbuf;
4264 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4266 outsize = set_message(outbuf,11,0,True);
4268 CHECK_FSP(fsp,conn);
4271 /* Do an fstat on this file */
4272 if(fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf))
4273 return(UNIXERROR(ERRDOS,ERRnoaccess));
4275 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4277 /* Convert the times into dos times. Set create
4278 date to be last modify date as UNIX doesn't save
4280 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4281 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4282 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4285 SIVAL(outbuf,smb_vwv6,0);
4286 SIVAL(outbuf,smb_vwv8,0);
4290 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4291 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4293 SSVAL(outbuf,smb_vwv10, mode);
4295 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));