2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
31 /* look in server.c for some explanation of these variables */
33 extern int DEBUGLEVEL;
36 extern char magic_char;
37 extern BOOL case_sensitive;
38 extern BOOL case_preserve;
39 extern BOOL short_case_preserve;
40 extern pstring sesssetup_user;
41 extern fstring global_myworkgroup;
43 extern int global_oplock_break;
44 uint32 global_client_caps = 0;
47 /****************************************************************************
48 report a possible attack via the password buffer overflow bug
49 ****************************************************************************/
50 static void overflow_attack(int len)
54 dbgtext( "ERROR: Invalid password length %d.\n", len );
55 dbgtext( "Your machine may be under attack by someone " );
56 dbgtext( "attempting to exploit an old bug.\n" );
57 dbgtext( "Attack was from IP = %s.\n", client_addr(Client) );
59 exit_server("possible attack");
63 /****************************************************************************
64 does _both_ nt->unix and unix->unix username remappings.
65 ****************************************************************************/
66 static void map_nt_and_unix_username(const char *domain, char *user)
72 * Pass the user through the NT -> unix user mapping
76 if (lp_server_role() != ROLE_DOMAIN_NONE)
78 memset(nt_username, 0, sizeof(nt_username));
81 slprintf(nt_username, sizeof(nt_username)-1, "%s\\%s",
86 fstrcpy(nt_username, user);
89 if (lookupsmbpwntnam(nt_username, &gmep))
91 fstrcpy(user, gmep.unix_name);
96 * Pass the user through the unix -> unix user mapping
100 (void)map_username(user);
103 * Do any UNIX username case mangling.
105 (void)Get_Pwnam( user, True);
108 /****************************************************************************
109 reply to an special message
110 ****************************************************************************/
111 int reply_special(char *inbuf,char *outbuf)
114 int msg_type = CVAL(inbuf,0);
115 int msg_flags = CVAL(inbuf,1);
117 extern fstring remote_machine;
118 extern fstring local_machine;
124 bzero(outbuf,smb_size);
126 smb_setlen(outbuf,0);
129 case 0x81: /* session request */
130 CVAL(outbuf,0) = 0x82;
132 if (name_len(inbuf+4) > 50 ||
133 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
134 DEBUG(0,("Invalid name length in session request\n"));
137 name_extract(inbuf,4,name1);
138 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
139 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
142 fstrcpy(remote_machine,name2);
143 remote_machine[15] = 0;
144 trim_string(remote_machine," "," ");
145 strlower(remote_machine);
147 fstrcpy(local_machine,name1);
148 len = strlen(local_machine);
150 name_type = local_machine[15];
151 local_machine[15] = 0;
153 trim_string(local_machine," "," ");
154 strlower(local_machine);
156 if (name_type == 'R') {
157 /* We are being asked for a pathworks session ---
159 CVAL(outbuf, 0) = 0x83;
163 add_session_user(remote_machine);
165 reload_services(True);
169 claim_connection(NULL,"STATUS.",MAXSTATUS,True);
174 case 0x89: /* session keepalive request
175 (some old clients produce this?) */
176 CVAL(outbuf,0) = 0x85;
180 case 0x82: /* positive session response */
181 case 0x83: /* negative session response */
182 case 0x84: /* retarget session response */
183 DEBUG(0,("Unexpected session response\n"));
186 case 0x85: /* session keepalive */
191 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
192 msg_type, msg_flags));
198 /*******************************************************************
199 work out what error to give to a failed connection
200 ********************************************************************/
201 static int connection_error(char *inbuf,char *outbuf,int ecode)
203 if (ecode == ERRnoipc) {
204 return(ERROR(ERRDOS,ERRnoipc));
207 return(ERROR(ERRSRV,ecode));
212 /****************************************************************************
213 parse a share descriptor string
214 ****************************************************************************/
215 static void parse_connect(char *p,char *service,char *user,
216 char *password,int *pwlen,char *dev)
220 DEBUG(4,("parsing connect string %s\n",p));
222 p2 = strrchr(p,'\\');
226 fstrcpy(service,p2+1);
231 *pwlen = strlen(password);
238 p = strchr(service,'%');
249 /****************************************************************************
251 ****************************************************************************/
252 int reply_tcon(connection_struct *conn,
253 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
260 uint16 vuid = SVAL(inbuf,smb_uid);
264 *service = *user = *password = *dev = 0;
266 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
268 map_nt_and_unix_username(global_myworkgroup, user);
270 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
273 return(connection_error(inbuf,outbuf,ecode));
276 outsize = set_message(outbuf,2,0,True);
277 SSVAL(outbuf,smb_vwv0,max_recv);
278 SSVAL(outbuf,smb_vwv1,conn->cnum);
279 SSVAL(outbuf,smb_tid,conn->cnum);
281 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
282 service, user, conn->cnum));
288 /****************************************************************************
289 reply to a tcon and X
290 ****************************************************************************/
291 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
298 uint16 vuid = SVAL(inbuf,smb_uid);
299 int passlen = SVAL(inbuf,smb_vwv3);
303 *service = *user = *password = *devicename = 0;
305 /* we might have to close an old one */
306 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
307 close_cnum(conn,vuid);
310 if (passlen > MAX_PASS_LEN) {
311 overflow_attack(passlen);
314 memcpy(password,smb_buf(inbuf),passlen);
316 path = smb_buf(inbuf) + passlen;
319 if (strequal(password," "))
321 passlen = strlen(password);
324 fstrcpy(service,path+2);
325 p = strchr(service,'\\');
327 return(ERROR(ERRSRV,ERRinvnetname));
329 fstrcpy(service,p+1);
330 p = strchr(service,'%');
335 StrnCpy(devicename,path + strlen(path) + 1,6);
336 DEBUG(4,("Got device type %s\n",devicename));
338 map_nt_and_unix_username(global_myworkgroup, user);
340 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
343 return(connection_error(inbuf,outbuf,ecode));
345 if (Protocol < PROTOCOL_NT1) {
346 set_message(outbuf,2,strlen(devicename)+1,True);
347 pstrcpy(smb_buf(outbuf),devicename);
349 char *fsname = lp_fstype(SNUM(conn));
351 set_message(outbuf,3,3,True);
354 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
355 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
357 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
359 /* what does setting this bit do? It is set by NT4 and
360 may affect the ability to autorun mounted cdroms */
361 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
364 DEBUG(3,("tconX service=%s user=%s\n",
367 /* set the incoming and outgoing tid to the just created one */
368 SSVAL(inbuf,smb_tid,conn->cnum);
369 SSVAL(outbuf,smb_tid,conn->cnum);
371 return chain_reply(inbuf,outbuf,length,bufsize);
375 /****************************************************************************
376 reply to an unknown type
377 ****************************************************************************/
378 int reply_unknown(char *inbuf,char *outbuf)
381 type = CVAL(inbuf,smb_com);
383 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
384 smb_fn_name(type), type, type));
386 return(ERROR(ERRSRV,ERRunknownsmb));
390 /****************************************************************************
392 ****************************************************************************/
393 int reply_ioctl(connection_struct *conn,
394 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
396 DEBUG(3,("ignoring ioctl\n"));
398 /* we just say it succeeds and hope its all OK.
399 some day it would be nice to interpret them individually */
400 return set_message(outbuf,1,0,True);
402 return(ERROR(ERRSRV,ERRnosupport));
406 /****************************************************************************
407 always return an error: it's just a matter of which one...
408 ****************************************************************************/
409 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
410 char *smb_passwd, int smb_passlen,
411 char *smb_nt_passwd, int smb_nt_passlen)
413 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
414 if (lp_security() == SEC_USER)
416 smb_trust_acct = getsmbpwnam(user);
420 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
421 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
422 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
425 if (smb_trust_acct == NULL)
427 /* lkclXXXX: workstation entry doesn't exist */
428 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
429 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
430 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
434 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
436 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
437 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
438 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
441 if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
443 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
444 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
445 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
448 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
450 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
451 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
452 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
455 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
457 DEBUG(0,("session_trust_account: Server 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_SERVER_TRUST_ACCOUNT));
462 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
464 DEBUG(4,("session_trust_account: Wksta 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_WORKSTATION_TRUST_ACCOUNT));
470 /* don't know what to do: indicate logon failure */
471 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
472 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
475 /****************************************************************************
476 Check for a valid username and password in security=server mode.
477 ****************************************************************************/
479 static BOOL check_server_security(char *orig_user, char *domain,
480 char *smb_apasswd, int smb_apasslen,
481 char *smb_ntpasswd, int smb_ntpasslen)
483 if(lp_security() != SEC_SERVER)
486 return server_validate(orig_user, domain,
487 smb_apasswd, smb_apasslen,
488 smb_ntpasswd, smb_ntpasslen);
491 /****************************************************************************
492 Check for a valid username and password in security=domain mode.
493 ****************************************************************************/
495 static BOOL check_domain_security(char *orig_user, char *domain,
496 char *smb_apasswd, int smb_apasslen,
497 char *smb_ntpasswd, int smb_ntpasslen)
499 if(lp_security() != SEC_DOMAIN)
502 return domain_client_validate(orig_user, domain,
503 smb_apasswd, smb_apasslen,
504 smb_ntpasswd, smb_ntpasslen);
507 /****************************************************************************
508 reply to a session setup command
509 ****************************************************************************/
511 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
514 uchar user_sess_key[16];
518 int smb_apasslen = 0;
520 int smb_ntpasslen = 0;
521 pstring smb_ntpasswd;
522 BOOL valid_nt_password = False;
526 static BOOL done_sesssetup = False;
527 BOOL doencrypt = SMBENCRYPT();
533 smb_bufsize = SVAL(inbuf,smb_vwv2);
535 if (Protocol < PROTOCOL_NT1) {
536 smb_apasslen = SVAL(inbuf,smb_vwv7);
537 if (smb_apasslen > MAX_PASS_LEN)
539 overflow_attack(smb_apasslen);
542 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
543 smb_apasswd[smb_apasslen] = 0;
544 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
546 if (!doencrypt && (lp_security() != SEC_SERVER)) {
547 smb_apasslen = strlen(smb_apasswd);
550 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
551 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
552 enum remote_arch_types ra_type = get_remote_arch();
553 char *p = smb_buf(inbuf);
555 global_client_caps = IVAL(inbuf,smb_vwv11);
557 /* client_caps is used as final determination if client is NT or Win95.
558 This is needed to return the correct error codes in some
562 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
564 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
565 set_remote_arch( RA_WINNT);
567 set_remote_arch( RA_WIN95);
570 if (passlen1 != 24 && passlen2 != 24)
573 if (passlen1 > MAX_PASS_LEN) {
574 overflow_attack(passlen1);
577 passlen1 = MIN(passlen1, MAX_PASS_LEN);
578 passlen2 = MIN(passlen2, MAX_PASS_LEN);
581 /* both Win95 and WinNT stuff up the password lengths for
582 non-encrypting systems. Uggh.
584 if passlen1==24 its a win95 system, and its setting the
585 password length incorrectly. Luckily it still works with the
586 default code because Win95 will null terminate the password
589 if passlen1>0 and passlen2>0 then maybe its a NT box and its
590 setting passlen2 to some random value which really stuffs
591 things up. we need to fix that one. */
593 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
597 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
598 /* Save the lanman2 password and the NT md4 password. */
599 smb_apasslen = passlen1;
600 memcpy(smb_apasswd,p,smb_apasslen);
601 smb_apasswd[smb_apasslen] = 0;
602 smb_ntpasslen = passlen2;
603 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
604 smb_ntpasswd[smb_ntpasslen] = 0;
606 /* we use the first password that they gave */
607 smb_apasslen = passlen1;
608 StrnCpy(smb_apasswd,p,smb_apasslen);
610 /* trim the password */
611 smb_apasslen = strlen(smb_apasswd);
613 /* wfwg sometimes uses a space instead of a null */
614 if (strequal(smb_apasswd," ")) {
620 p += passlen1 + passlen2;
621 fstrcpy(user,p); p = skip_string(p,1);
624 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
625 domain,skip_string(p,1),skip_string(p,2)));
629 DEBUG(3,("sesssetupX:name=[%s]\n",user));
631 /* If name ends in $ then I think it's asking about whether a */
632 /* computer with that name (minus the $) has access. For now */
633 /* say yes to everything ending in $. */
634 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
636 return session_trust_account(conn, inbuf, outbuf, user,
637 smb_apasswd, smb_apasslen,
638 smb_ntpasswd, smb_ntpasslen);
641 /* If no username is sent use the guest account */
644 pstrcpy(user,lp_guestaccount(-1));
645 /* If no user and no password then set guest flag. */
646 if( *smb_apasswd == 0)
653 * In share level security, only overwrite sesssetup_use if
654 * it's a non null-session share. Helps keep %U and %G
658 if((lp_security() != SEC_SHARE) || (*user && !guest))
659 pstrcpy(sesssetup_user,user);
661 reload_services(True);
664 * Save the username before mapping. We will use
665 * the original username sent to us for security=server
666 * and security=domain checking.
669 pstrcpy( orig_user, user);
671 map_nt_and_unix_username(domain, user);
673 add_session_user(user);
676 * Check if the given username was the guest user with no password.
679 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
683 * Check with orig_user for security=server and
688 !check_server_security(orig_user, domain,
689 smb_apasswd, smb_apasslen,
690 smb_ntpasswd, smb_ntpasslen) &&
691 !check_domain_security(orig_user, domain,
692 smb_apasswd, smb_apasslen,
693 smb_ntpasswd, smb_ntpasslen) &&
694 !check_hosts_equiv(user)
699 * If we get here then the user wasn't guest and the remote
700 * authentication methods failed. Check the authentication
701 * methods on this local server.
703 * If an NT password was supplied try and validate with that
704 * first. This is superior as the passwords are mixed case
705 * 128 length unicode.
710 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key))
711 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
713 valid_nt_password = True;
716 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key))
718 if (lp_security() >= SEC_USER)
720 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
721 return(ERROR(ERRSRV,ERRbadpw));
723 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
725 if (Get_Pwnam(user,True))
726 return(ERROR(ERRSRV,ERRbadpw));
730 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
731 * Then always map to guest account - as done below.
735 if (*smb_apasswd || !Get_Pwnam(user,True))
736 pstrcpy(user,lp_guestaccount(-1));
737 DEBUG(3,("Registered username %s for guest access\n",user));
742 if (!Get_Pwnam(user,True)) {
743 DEBUG(3,("No such user %s - using guest account\n",user));
744 pstrcpy(user,lp_guestaccount(-1));
748 if (!strequal(user,lp_guestaccount(-1)) &&
749 lp_servicenumber(user) < 0)
751 int homes = lp_servicenumber(HOMES_NAME);
752 char *home = get_home_dir(user);
753 if (homes >= 0 && home)
756 fstrcpy(home_dir, home);
757 lp_add_home(user,homes,home_dir);
762 /* it's ok - setup a reply */
763 if (Protocol < PROTOCOL_NT1) {
764 set_message(outbuf,3,0,True);
767 set_message(outbuf,3,3,True);
769 pstrcpy(p,"Unix"); p = skip_string(p,1);
770 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
771 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
772 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
773 /* perhaps grab OS version here?? */
776 /* Set the correct uid in the outgoing and incoming packets
777 We will use this on future requests to determine which
778 user we should become.
781 struct passwd *pw = Get_Pwnam(user,False);
783 DEBUG(1,("Username %s is invalid on this system\n",user));
784 return(ERROR(ERRSRV,ERRbadpw));
791 SSVAL(outbuf,smb_vwv2,1);
793 /* register the name and uid as being validated, so further connections
794 to a uid can get through without a password, on the same VC */
795 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key);
797 SSVAL(outbuf,smb_uid,sess_vuid);
798 SSVAL(inbuf,smb_uid,sess_vuid);
801 max_send = MIN(max_send,smb_bufsize);
803 DEBUG(6,("Client requested max send size of %d\n", max_send));
805 done_sesssetup = True;
807 return chain_reply(inbuf,outbuf,length,bufsize);
811 /****************************************************************************
813 ****************************************************************************/
814 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
820 BOOL bad_path = False;
823 pstrcpy(name,smb_buf(inbuf) + 1);
824 unix_convert(name,conn,0,&bad_path,&st);
826 mode = SVAL(inbuf,smb_vwv0);
828 if (check_name(name,conn)) {
830 ok = S_ISDIR(st.st_mode);
832 ok = dos_directory_exist(name,NULL);
837 /* We special case this - as when a Windows machine
838 is parsing a path is steps through the components
839 one at a time - if a component fails it expects
840 ERRbadpath, not ERRbadfile.
844 unix_ERR_class = ERRDOS;
845 unix_ERR_code = ERRbadpath;
849 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
850 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
851 (get_remote_arch() == RA_WINNT))
853 unix_ERR_class = ERRDOS;
854 unix_ERR_code = ERRbaddirectory;
858 return(UNIXERROR(ERRDOS,ERRbadpath));
861 outsize = set_message(outbuf,0,0,True);
863 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
869 /****************************************************************************
871 ****************************************************************************/
872 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
876 SMB_STRUCT_STAT sbuf;
881 BOOL bad_path = False;
883 pstrcpy(fname,smb_buf(inbuf) + 1);
885 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
886 under WfWg - weird! */
889 mode = aHIDDEN | aDIR;
890 if (!CAN_WRITE(conn)) mode |= aRONLY;
897 unix_convert(fname,conn,0,&bad_path,&sbuf);
898 if (check_name(fname,conn))
900 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
902 mode = dos_mode(conn,fname,&sbuf);
904 mtime = sbuf.st_mtime;
910 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
916 if((errno == ENOENT) && bad_path)
918 unix_ERR_class = ERRDOS;
919 unix_ERR_code = ERRbadpath;
922 return(UNIXERROR(ERRDOS,ERRbadfile));
925 outsize = set_message(outbuf,10,0,True);
927 SSVAL(outbuf,smb_vwv0,mode);
928 if(lp_dos_filetime_resolution(SNUM(conn)) )
929 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
931 put_dos_date3(outbuf,smb_vwv1,mtime);
932 SIVAL(outbuf,smb_vwv3,(uint32)size);
934 if (Protocol >= PROTOCOL_NT1) {
935 char *p = strrchr(fname,'/');
936 uint16 flg2 = SVAL(outbuf,smb_flg2);
938 if (!is_8_3(fname, True))
939 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
942 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
948 /****************************************************************************
950 ****************************************************************************/
951 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
959 BOOL bad_path = False;
961 pstrcpy(fname,smb_buf(inbuf) + 1);
962 unix_convert(fname,conn,0,&bad_path,&st);
964 mode = SVAL(inbuf,smb_vwv0);
965 mtime = make_unix_date3(inbuf+smb_vwv1);
967 if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
969 if (check_name(fname,conn))
970 ok = (file_chmod(conn,fname,mode,NULL) == 0);
972 ok = set_filetime(conn,fname,mtime);
976 if((errno == ENOENT) && bad_path)
978 unix_ERR_class = ERRDOS;
979 unix_ERR_code = ERRbadpath;
982 return(UNIXERROR(ERRDOS,ERRnoaccess));
985 outsize = set_message(outbuf,0,0,True);
987 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
993 /****************************************************************************
995 ****************************************************************************/
996 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
999 SMB_BIG_UINT dfree,dsize,bsize;
1001 sys_disk_free(".",&bsize,&dfree,&dsize);
1003 outsize = set_message(outbuf,5,0,True);
1005 SSVAL(outbuf,smb_vwv0,dsize);
1006 SSVAL(outbuf,smb_vwv1,bsize/512);
1007 SSVAL(outbuf,smb_vwv2,512);
1008 SSVAL(outbuf,smb_vwv3,dfree);
1010 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1016 /****************************************************************************
1018 Can be called from SMBsearch, SMBffirst or SMBfunique.
1019 ****************************************************************************/
1020 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1031 BOOL finished = False;
1040 BOOL check_descend = False;
1041 BOOL expect_close = False;
1042 BOOL can_open = True;
1043 BOOL bad_path = False;
1045 *mask = *directory = *fname = 0;
1047 /* If we were called as SMBffirst then we must expect close. */
1048 if(CVAL(inbuf,smb_com) == SMBffirst)
1049 expect_close = True;
1051 outsize = set_message(outbuf,1,3,True);
1052 maxentries = SVAL(inbuf,smb_vwv0);
1053 dirtype = SVAL(inbuf,smb_vwv1);
1054 path = smb_buf(inbuf) + 1;
1055 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1058 /* dirtype &= ~aDIR; */
1060 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1063 if (status_len == 0)
1067 pstrcpy(directory,smb_buf(inbuf)+1);
1068 pstrcpy(dir2,smb_buf(inbuf)+1);
1069 unix_convert(directory,conn,0,&bad_path,NULL);
1072 if (!check_name(directory,conn))
1075 p = strrchr(dir2,'/');
1087 p = strrchr(directory,'/');
1093 if (strlen(directory) == 0)
1094 pstrcpy(directory,"./");
1096 CVAL(status,0) = dirtype;
1100 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1101 memcpy(mask,status+1,11);
1103 dirtype = CVAL(status,0) & 0x1F;
1104 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1107 string_set(&conn->dirpath,dptr_path(dptr_num));
1108 if (!case_sensitive)
1112 /* turn strings of spaces into a . */
1114 trim_string(mask,NULL," ");
1115 if ((p = strrchr(mask,' ')))
1120 trim_string(mask,NULL," ");
1126 /* Convert the formatted mask. (This code lives in trans2.c) */
1134 if((skip = skip_multibyte_char( *p )) != 0 )
1140 if (*p != '?' && *p != '*' && !isdoschar(*p))
1142 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1150 if (!strchr(mask,'.') && strlen(mask)>8)
1153 fstrcpy(tmp,&mask[8]);
1159 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1163 p = smb_buf(outbuf) + 3;
1167 if (status_len == 0)
1169 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1174 if((errno == ENOENT) && bad_path)
1176 unix_ERR_class = ERRDOS;
1177 unix_ERR_code = ERRbadpath;
1179 return (UNIXERROR(ERRDOS,ERRnofids));
1181 return(ERROR(ERRDOS,ERRnofids));
1185 DEBUG(4,("dptr_num is %d\n",dptr_num));
1189 if ((dirtype&0x1F) == aVOLID)
1191 memcpy(p,status,21);
1192 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1193 dptr_fill(p+12,dptr_num);
1194 if (dptr_zero(p+12) && (status_len==0))
1198 p += DIR_STRUCT_SIZE;
1202 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1203 conn->dirpath,lp_dontdescend(SNUM(conn))));
1204 if (in_list(conn->dirpath,
1205 lp_dontdescend(SNUM(conn)),True))
1206 check_descend = True;
1208 for (i=numentries;(i<maxentries) && !finished;i++)
1211 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1214 memcpy(p,status,21);
1215 make_dir_struct(p,mask,fname,size,mode,date);
1216 dptr_fill(p+12,dptr_num);
1219 p += DIR_STRUCT_SIZE;
1228 if (numentries == 0 || !ok)
1230 CVAL(outbuf,smb_rcls) = ERRDOS;
1231 SSVAL(outbuf,smb_err,ERRnofiles);
1234 /* If we were called as SMBffirst with smb_search_id == NULL
1235 and no entries were found then return error and close dirptr
1238 if(ok && expect_close && numentries == 0 && status_len == 0)
1240 CVAL(outbuf,smb_rcls) = ERRDOS;
1241 SSVAL(outbuf,smb_err,ERRnofiles);
1242 /* Also close the dptr - we know it's gone */
1243 dptr_close(dptr_num);
1246 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1247 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1248 dptr_close(dptr_num);
1250 SSVAL(outbuf,smb_vwv0,numentries);
1251 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1252 CVAL(smb_buf(outbuf),0) = 5;
1253 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1255 if (Protocol >= PROTOCOL_NT1) {
1256 uint16 flg2 = SVAL(outbuf,smb_flg2);
1257 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1260 outsize += DIR_STRUCT_SIZE*numentries;
1261 smb_setlen(outbuf,outsize - 4);
1263 if ((! *directory) && dptr_path(dptr_num))
1264 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1266 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1267 smb_fn_name(CVAL(inbuf,smb_com)),
1268 mask, directory, dirtype, numentries, maxentries ) );
1274 /****************************************************************************
1275 reply to a fclose (stop directory search)
1276 ****************************************************************************/
1277 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1285 outsize = set_message(outbuf,1,0,True);
1286 path = smb_buf(inbuf) + 1;
1287 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1290 if (status_len == 0)
1291 return(ERROR(ERRSRV,ERRsrverror));
1293 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1295 if(dptr_fetch(status+12,&dptr_num)) {
1296 /* Close the dptr - we know it's gone */
1297 dptr_close(dptr_num);
1300 SSVAL(outbuf,smb_vwv0,0);
1302 DEBUG(3,("search close\n"));
1308 /****************************************************************************
1310 ****************************************************************************/
1312 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1322 SMB_STRUCT_STAT sbuf;
1323 BOOL bad_path = False;
1325 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1327 share_mode = SVAL(inbuf,smb_vwv0);
1329 pstrcpy(fname,smb_buf(inbuf)+1);
1330 unix_convert(fname,conn,0,&bad_path,NULL);
1334 return(ERROR(ERRSRV,ERRnofids));
1336 if (!check_name(fname,conn))
1338 if((errno == ENOENT) && bad_path)
1340 unix_ERR_class = ERRDOS;
1341 unix_ERR_code = ERRbadpath;
1344 return(UNIXERROR(ERRDOS,ERRnoaccess));
1347 unixmode = unix_mode(conn,aARCH);
1349 open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1350 unixmode, oplock_request,&rmode,NULL);
1354 if((errno == ENOENT) && bad_path)
1356 unix_ERR_class = ERRDOS;
1357 unix_ERR_code = ERRbadpath;
1360 return(UNIXERROR(ERRDOS,ERRnoaccess));
1363 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1364 close_file(fsp,False);
1365 return(ERROR(ERRDOS,ERRnoaccess));
1368 size = sbuf.st_size;
1369 fmode = dos_mode(conn,fname,&sbuf);
1370 mtime = sbuf.st_mtime;
1373 DEBUG(3,("attempt to open a directory %s\n",fname));
1374 close_file(fsp,False);
1375 return(ERROR(ERRDOS,ERRnoaccess));
1378 outsize = set_message(outbuf,7,0,True);
1379 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1380 SSVAL(outbuf,smb_vwv1,fmode);
1381 if(lp_dos_filetime_resolution(SNUM(conn)) )
1382 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1384 put_dos_date3(outbuf,smb_vwv2,mtime);
1385 SIVAL(outbuf,smb_vwv4,(uint32)size);
1386 SSVAL(outbuf,smb_vwv6,rmode);
1388 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1389 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1392 if(fsp->granted_oplock)
1393 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1398 /****************************************************************************
1399 reply to an open and X
1400 ****************************************************************************/
1401 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1404 int smb_mode = SVAL(inbuf,smb_vwv3);
1405 int smb_attr = SVAL(inbuf,smb_vwv5);
1406 /* Breakout the oplock request bits so we can set the
1407 reply bits separately. */
1408 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1409 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1410 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1412 int open_flags = SVAL(inbuf,smb_vwv2);
1413 int smb_sattr = SVAL(inbuf,smb_vwv4);
1414 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1416 int smb_ofun = SVAL(inbuf,smb_vwv8);
1419 int fmode=0,mtime=0,rmode=0;
1420 SMB_STRUCT_STAT sbuf;
1422 BOOL bad_path = False;
1425 /* If it's an IPC, pass off the pipe handler. */
1426 if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
1428 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1431 /* XXXX we need to handle passed times, sattr and flags */
1433 pstrcpy(fname,smb_buf(inbuf));
1434 unix_convert(fname,conn,0,&bad_path,NULL);
1438 return(ERROR(ERRSRV,ERRnofids));
1440 if (!check_name(fname,conn))
1442 if((errno == ENOENT) && bad_path)
1444 unix_ERR_class = ERRDOS;
1445 unix_ERR_code = ERRbadpath;
1448 return(UNIXERROR(ERRDOS,ERRnoaccess));
1451 unixmode = unix_mode(conn,smb_attr | aARCH);
1453 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1454 oplock_request, &rmode,&smb_action);
1458 if((errno == ENOENT) && bad_path)
1460 unix_ERR_class = ERRDOS;
1461 unix_ERR_code = ERRbadpath;
1464 return(UNIXERROR(ERRDOS,ERRnoaccess));
1467 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1468 close_file(fsp,False);
1469 return(ERROR(ERRDOS,ERRnoaccess));
1472 size = sbuf.st_size;
1473 fmode = dos_mode(conn,fname,&sbuf);
1474 mtime = sbuf.st_mtime;
1476 close_file(fsp,False);
1477 return(ERROR(ERRDOS,ERRnoaccess));
1480 /* If the caller set the extended oplock request bit
1481 and we granted one (by whatever means) - set the
1482 correct bit for extended oplock reply.
1485 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1486 smb_action |= EXTENDED_OPLOCK_GRANTED;
1489 if(ex_oplock_request && fsp->granted_oplock) {
1490 smb_action |= EXTENDED_OPLOCK_GRANTED;
1493 /* If the caller set the core oplock request bit
1494 and we granted one (by whatever means) - set the
1495 correct bit for core oplock reply.
1498 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1499 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1502 if(core_oplock_request && fsp->granted_oplock) {
1503 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1506 set_message(outbuf,15,0,True);
1507 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1508 SSVAL(outbuf,smb_vwv3,fmode);
1509 if(lp_dos_filetime_resolution(SNUM(conn)) )
1510 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1512 put_dos_date3(outbuf,smb_vwv4,mtime);
1513 SIVAL(outbuf,smb_vwv6,(uint32)size);
1514 SSVAL(outbuf,smb_vwv8,rmode);
1515 SSVAL(outbuf,smb_vwv11,smb_action);
1517 return chain_reply(inbuf,outbuf,length,bufsize);
1521 /****************************************************************************
1522 reply to a SMBulogoffX
1523 ****************************************************************************/
1524 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1526 uint16 vuid = SVAL(inbuf,smb_uid);
1527 user_struct *vuser = get_valid_user_struct(vuid);
1530 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1533 /* in user level security we are supposed to close any files
1534 open by this user */
1535 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1536 file_close_user(vuid);
1539 invalidate_vuid(vuid);
1541 set_message(outbuf,2,0,True);
1543 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1545 return chain_reply(inbuf,outbuf,length,bufsize);
1549 /****************************************************************************
1550 reply to a mknew or a create
1551 ****************************************************************************/
1552 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1560 BOOL bad_path = False;
1562 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1564 com = SVAL(inbuf,smb_com);
1566 createmode = SVAL(inbuf,smb_vwv0);
1567 pstrcpy(fname,smb_buf(inbuf)+1);
1568 unix_convert(fname,conn,0,&bad_path,NULL);
1570 if (createmode & aVOLID)
1572 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1575 unixmode = unix_mode(conn,createmode);
1579 return(ERROR(ERRSRV,ERRnofids));
1581 if (!check_name(fname,conn))
1583 if((errno == ENOENT) && bad_path)
1585 unix_ERR_class = ERRDOS;
1586 unix_ERR_code = ERRbadpath;
1589 return(UNIXERROR(ERRDOS,ERRnoaccess));
1594 /* We should fail if file exists. */
1599 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1603 /* Open file in dos compatibility share mode. */
1604 open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1605 ofun, unixmode, oplock_request, NULL, NULL);
1609 if((errno == ENOENT) && bad_path)
1611 unix_ERR_class = ERRDOS;
1612 unix_ERR_code = ERRbadpath;
1615 return(UNIXERROR(ERRDOS,ERRnoaccess));
1618 outsize = set_message(outbuf,1,0,True);
1619 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1621 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1622 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1625 if(fsp->granted_oplock)
1626 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1628 DEBUG( 2, ( "new file %s\n", fname ) );
1629 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1630 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1636 /****************************************************************************
1637 reply to a create temporary file
1638 ****************************************************************************/
1639 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1646 BOOL bad_path = False;
1648 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1650 createmode = SVAL(inbuf,smb_vwv0);
1651 pstrcpy(fname,smb_buf(inbuf)+1);
1652 pstrcat(fname,"/TMXXXXXX");
1653 unix_convert(fname,conn,0,&bad_path,NULL);
1655 unixmode = unix_mode(conn,createmode);
1659 return(ERROR(ERRSRV,ERRnofids));
1661 if (!check_name(fname,conn))
1663 if((errno == ENOENT) && bad_path)
1665 unix_ERR_class = ERRDOS;
1666 unix_ERR_code = ERRbadpath;
1669 return(UNIXERROR(ERRDOS,ERRnoaccess));
1672 pstrcpy(fname2,(char *)mktemp(fname));
1674 /* Open file in dos compatibility share mode. */
1675 /* We should fail if file exists. */
1676 open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1677 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1681 if((errno == ENOENT) && bad_path)
1683 unix_ERR_class = ERRDOS;
1684 unix_ERR_code = ERRbadpath;
1687 return(UNIXERROR(ERRDOS,ERRnoaccess));
1690 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1691 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1692 CVAL(smb_buf(outbuf),0) = 4;
1693 pstrcpy(smb_buf(outbuf) + 1,fname2);
1695 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1696 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1699 if(fsp->granted_oplock)
1700 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1702 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1703 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1704 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1710 /*******************************************************************
1711 check if a user is allowed to delete a file
1712 ********************************************************************/
1713 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1715 SMB_STRUCT_STAT sbuf;
1718 if (!CAN_WRITE(conn)) return(False);
1720 if (dos_lstat(fname,&sbuf) != 0) return(False);
1721 fmode = dos_mode(conn,fname,&sbuf);
1722 if (fmode & aDIR) return(False);
1723 if (!lp_delete_readonly(SNUM(conn))) {
1724 if (fmode & aRONLY) return(False);
1726 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1728 if (!check_file_sharing(conn,fname,False)) return(False);
1732 /****************************************************************************
1734 ****************************************************************************/
1735 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1744 int error = ERRnoaccess;
1747 BOOL bad_path = False;
1749 *directory = *mask = 0;
1751 dirtype = SVAL(inbuf,smb_vwv0);
1753 pstrcpy(name,smb_buf(inbuf) + 1);
1755 DEBUG(3,("reply_unlink : %s\n",name));
1757 unix_convert(name,conn,0,&bad_path,NULL);
1759 p = strrchr(name,'/');
1761 pstrcpy(directory,"./");
1765 pstrcpy(directory,name);
1769 if (is_mangled(mask))
1770 check_mangled_cache( mask );
1772 has_wild = strchr(mask,'*') || strchr(mask,'?');
1775 pstrcat(directory,"/");
1776 pstrcat(directory,mask);
1777 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
1780 exists = dos_file_exist(directory,NULL);
1782 void *dirptr = NULL;
1785 if (check_name(directory,conn))
1786 dirptr = OpenDir(conn, directory, True);
1788 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1789 the pattern matches against the long name, otherwise the short name
1790 We don't implement this yet XXXX
1797 if (strequal(mask,"????????.???"))
1800 while ((dname = ReadDirName(dirptr)))
1803 pstrcpy(fname,dname);
1805 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1807 error = ERRnoaccess;
1808 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1809 if (!can_delete(fname,conn,dirtype)) continue;
1810 if (!dos_unlink(fname)) count++;
1811 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1819 return(ERROR(ERRDOS,error));
1822 if((errno == ENOENT) && bad_path)
1824 unix_ERR_class = ERRDOS;
1825 unix_ERR_code = ERRbadpath;
1827 return(UNIXERROR(ERRDOS,error));
1831 outsize = set_message(outbuf,0,0,True);
1837 /****************************************************************************
1838 reply to a readbraw (core+ protocol)
1839 ****************************************************************************/
1840 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1842 size_t maxcount,mincount;
1845 char *header = outbuf;
1850 * Special check if an oplock break has been issued
1851 * and the readraw request croses on the wire, we must
1852 * return a zero length response here.
1855 if(global_oplock_break)
1857 _smb_setlen(header,0);
1858 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1859 DEBUG(5,("readbraw - oplock break finished\n"));
1863 fsp = file_fsp(inbuf,smb_vwv0);
1865 startpos = IVAL(inbuf,smb_vwv1);
1866 #ifdef LARGE_SMB_OFF_T
1867 if(CVAL(inbuf,smb_wct) == 10) {
1869 * This is a large offset (64 bit) read.
1871 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1873 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1874 (double)startpos ));
1875 _smb_setlen(header,0);
1876 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1880 #endif /* LARGE_SMB_OFF_T */
1881 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1882 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1884 /* ensure we don't overrun the packet size */
1885 maxcount = MIN(65535,maxcount);
1886 maxcount = MAX(mincount,maxcount);
1888 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1889 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1890 _smb_setlen(header,0);
1891 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1895 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1897 SMB_OFF_T size = fsp->size;
1898 SMB_OFF_T sizeneeded = startpos + maxcount;
1900 if (size < sizeneeded)
1903 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1905 if (!fsp->can_write)
1909 nread = MIN(maxcount,(size - startpos));
1912 if (nread < mincount)
1915 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1916 fsp->fnum, (double)startpos,
1917 maxcount, mincount, nread ) );
1921 BOOL seek_fail = False;
1923 _smb_setlen(header,nread);
1925 #if USE_READ_PREDICTION
1926 if (!fsp->can_write)
1927 predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1928 #endif /* USE_READ_PREDICTION */
1930 if ((nread-predict) > 0) {
1931 if(seek_file(fsp,startpos + predict) == -1) {
1932 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1939 ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,
1940 (SMB_OFF_T)(nread-predict),header,4+predict,
1945 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1946 fsp->fsp_name,startpos,nread,ret));
1948 #else /* UNSAFE_READRAW */
1949 ret = read_file(fsp,header+4,startpos,nread);
1950 if (ret < mincount) ret = 0;
1952 _smb_setlen(header,ret);
1953 transfer_file(0,Client,0,header,4+ret,0);
1954 #endif /* UNSAFE_READRAW */
1956 DEBUG(5,("readbraw finished\n"));
1961 /****************************************************************************
1962 reply to a lockread (core+ protocol)
1963 ****************************************************************************/
1964 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1973 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1975 CHECK_FSP(fsp,conn);
1979 numtoread = SVAL(inbuf,smb_vwv1);
1980 startpos = IVAL(inbuf,smb_vwv2);
1982 outsize = set_message(outbuf,5,3,True);
1983 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1984 data = smb_buf(outbuf) + 3;
1986 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1987 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1989 * A blocking lock was requested. Package up
1990 * this smb into a queued request and push it
1991 * onto the blocking lock queue.
1993 if(push_blocking_lock_request(inbuf, length, -1, 0))
1996 return (ERROR(eclass,ecode));
1999 nread = read_file(fsp,data,startpos,numtoread);
2002 return(UNIXERROR(ERRDOS,ERRnoaccess));
2005 SSVAL(outbuf,smb_vwv0,nread);
2006 SSVAL(outbuf,smb_vwv5,nread+3);
2007 SSVAL(smb_buf(outbuf),1,nread);
2009 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2010 fsp->fnum, numtoread, nread ) );
2016 /****************************************************************************
2018 ****************************************************************************/
2019 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2026 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2028 CHECK_FSP(fsp,conn);
2032 numtoread = SVAL(inbuf,smb_vwv1);
2033 startpos = IVAL(inbuf,smb_vwv2);
2035 outsize = set_message(outbuf,5,3,True);
2036 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2037 data = smb_buf(outbuf) + 3;
2039 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2040 return(ERROR(ERRDOS,ERRlock));
2043 nread = read_file(fsp,data,startpos,numtoread);
2046 return(UNIXERROR(ERRDOS,ERRnoaccess));
2049 SSVAL(outbuf,smb_vwv0,nread);
2050 SSVAL(outbuf,smb_vwv5,nread+3);
2051 CVAL(smb_buf(outbuf),0) = 1;
2052 SSVAL(smb_buf(outbuf),1,nread);
2054 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2055 fsp->fnum, numtoread, nread ) );
2061 /****************************************************************************
2062 reply to a read and X
2063 ****************************************************************************/
2064 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2066 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2067 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2068 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2069 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2073 /* If it's an IPC, pass off the pipe handler. */
2075 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2077 CHECK_FSP(fsp,conn);
2081 set_message(outbuf,12,0,True);
2082 data = smb_buf(outbuf);
2084 #ifdef LARGE_SMB_OFF_T
2085 if(CVAL(inbuf,smb_wct) == 12) {
2087 * This is a large offset (64 bit) read.
2089 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2091 #endif /* LARGE_SMB_OFF_T */
2093 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2094 return(ERROR(ERRDOS,ERRlock));
2095 nread = read_file(fsp,data,startpos,smb_maxcnt);
2098 return(UNIXERROR(ERRDOS,ERRnoaccess));
2100 SSVAL(outbuf,smb_vwv5,nread);
2101 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2102 SSVAL(smb_buf(outbuf),-2,nread);
2104 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2105 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2107 return chain_reply(inbuf,outbuf,length,bufsize);
2110 /****************************************************************************
2111 reply to a writebraw (core+ or LANMAN1.0 protocol)
2112 ****************************************************************************/
2113 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2116 ssize_t total_written=0;
2117 size_t numtowrite=0;
2122 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2125 CHECK_FSP(fsp,conn);
2129 tcount = IVAL(inbuf,smb_vwv1);
2130 startpos = IVAL(inbuf,smb_vwv3);
2131 write_through = BITSETW(inbuf+smb_vwv7,0);
2133 /* We have to deal with slightly different formats depending
2134 on whether we are using the core+ or lanman1.0 protocol */
2135 if(Protocol <= PROTOCOL_COREPLUS) {
2136 numtowrite = SVAL(smb_buf(inbuf),-2);
2137 data = smb_buf(inbuf);
2139 numtowrite = SVAL(inbuf,smb_vwv10);
2140 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2143 /* force the error type */
2144 CVAL(inbuf,smb_com) = SMBwritec;
2145 CVAL(outbuf,smb_com) = SMBwritec;
2147 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2148 return(ERROR(ERRDOS,ERRlock));
2150 if (seek_file(fsp,startpos) == -1) {
2151 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2152 return(UNIXERROR(ERRDOS,ERRnoaccess));
2156 nwritten = write_file(fsp,data,numtowrite);
2158 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2159 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2161 if (nwritten < numtowrite)
2162 return(UNIXERROR(ERRHRD,ERRdiskfull));
2164 total_written = nwritten;
2166 /* Return a message to the redirector to tell it
2167 to send more bytes */
2168 CVAL(outbuf,smb_com) = SMBwritebraw;
2169 SSVALS(outbuf,smb_vwv0,-1);
2170 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2171 send_smb(Client,outbuf);
2173 /* Now read the raw data into the buffer and write it */
2174 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2175 exit_server("secondary writebraw failed");
2178 /* Even though this is not an smb message, smb_len
2179 returns the generic length of an smb message */
2180 numtowrite = smb_len(inbuf);
2182 if (tcount > nwritten+numtowrite) {
2183 DEBUG(3,("Client overestimated the write %d %d %d\n",
2184 tcount,nwritten,numtowrite));
2187 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2189 total_written += nwritten;
2191 /* Set up outbuf to return the correct return */
2192 outsize = set_message(outbuf,1,0,True);
2193 CVAL(outbuf,smb_com) = SMBwritec;
2194 SSVAL(outbuf,smb_vwv0,total_written);
2196 if (nwritten < (ssize_t)numtowrite) {
2197 CVAL(outbuf,smb_rcls) = ERRHRD;
2198 SSVAL(outbuf,smb_err,ERRdiskfull);
2201 if (lp_syncalways(SNUM(conn)) || write_through)
2202 sync_file(conn,fsp);
2204 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2205 fsp->fnum, (double)startpos, numtowrite, total_written));
2207 /* we won't return a status if write through is not selected - this
2208 follows what WfWg does */
2209 if (!write_through && total_written==tcount)
2215 /****************************************************************************
2216 reply to a writeunlock (core+)
2217 ****************************************************************************/
2218 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2220 ssize_t nwritten = -1;
2226 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2229 CHECK_FSP(fsp,conn);
2233 numtowrite = SVAL(inbuf,smb_vwv1);
2234 startpos = IVAL(inbuf,smb_vwv2);
2235 data = smb_buf(inbuf) + 3;
2237 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2238 return(ERROR(ERRDOS,ERRlock));
2240 if(seek_file(fsp,startpos) == -1)
2241 return(UNIXERROR(ERRDOS,ERRnoaccess));
2243 /* The special X/Open SMB protocol handling of
2244 zero length writes is *NOT* done for
2249 nwritten = write_file(fsp,data,numtowrite);
2251 if (lp_syncalways(SNUM(conn)))
2252 sync_file(conn,fsp);
2254 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2255 return(UNIXERROR(ERRDOS,ERRnoaccess));
2257 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2258 return(ERROR(eclass,ecode));
2260 outsize = set_message(outbuf,1,0,True);
2262 SSVAL(outbuf,smb_vwv0,nwritten);
2264 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2265 fsp->fnum, numtowrite, nwritten ) );
2270 /****************************************************************************
2272 ****************************************************************************/
2273 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2276 ssize_t nwritten = -1;
2279 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2282 CHECK_FSP(fsp,conn);
2286 numtowrite = SVAL(inbuf,smb_vwv1);
2287 startpos = IVAL(inbuf,smb_vwv2);
2288 data = smb_buf(inbuf) + 3;
2290 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2291 return(ERROR(ERRDOS,ERRlock));
2293 if(seek_file(fsp,startpos) == -1)
2294 return(UNIXERROR(ERRDOS,ERRnoaccess));
2296 /* X/Open SMB protocol says that if smb_vwv1 is
2297 zero then the file size should be extended or
2298 truncated to the size given in smb_vwv[2-3] */
2300 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2302 nwritten = write_file(fsp,data,numtowrite);
2304 if (lp_syncalways(SNUM(conn)))
2305 sync_file(conn,fsp);
2307 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2308 return(UNIXERROR(ERRDOS,ERRnoaccess));
2310 outsize = set_message(outbuf,1,0,True);
2312 SSVAL(outbuf,smb_vwv0,nwritten);
2314 if (nwritten < (ssize_t)numtowrite) {
2315 CVAL(outbuf,smb_rcls) = ERRHRD;
2316 SSVAL(outbuf,smb_err,ERRdiskfull);
2319 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2320 fsp->fnum, numtowrite, nwritten));
2326 /****************************************************************************
2327 reply to a write and X
2328 ****************************************************************************/
2329 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2331 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2332 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2333 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2334 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2335 ssize_t nwritten = -1;
2336 int smb_doff = SVAL(inbuf,smb_vwv11);
2339 /* If it's an IPC, pass off the pipe handler. */
2341 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2343 CHECK_FSP(fsp,conn);
2347 data = smb_base(inbuf) + smb_doff;
2349 #ifdef LARGE_SMB_OFF_T
2350 if(CVAL(inbuf,smb_wct) == 14) {
2352 * This is a large offset (64 bit) write.
2354 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2356 #endif /* LARGE_SMB_OFF_T */
2358 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2359 return(ERROR(ERRDOS,ERRlock));
2361 if(seek_file(fsp,startpos) == -1)
2362 return(UNIXERROR(ERRDOS,ERRnoaccess));
2364 /* X/Open SMB protocol says that, unlike SMBwrite
2365 if the length is zero then NO truncation is
2366 done, just a write of zero. To truncate a file,
2371 nwritten = write_file(fsp,data,numtowrite);
2373 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2374 return(UNIXERROR(ERRDOS,ERRnoaccess));
2376 set_message(outbuf,6,0,True);
2378 SSVAL(outbuf,smb_vwv2,nwritten);
2380 if (nwritten < (ssize_t)numtowrite) {
2381 CVAL(outbuf,smb_rcls) = ERRHRD;
2382 SSVAL(outbuf,smb_err,ERRdiskfull);
2385 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2386 fsp->fnum, numtowrite, nwritten));
2388 if (lp_syncalways(SNUM(conn)) || write_through)
2389 sync_file(conn,fsp);
2391 return chain_reply(inbuf,outbuf,length,bufsize);
2395 /****************************************************************************
2397 ****************************************************************************/
2398 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2404 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2406 CHECK_FSP(fsp,conn);
2409 mode = SVAL(inbuf,smb_vwv1) & 3;
2410 startpos = IVAL(inbuf,smb_vwv2);
2414 case 0: umode = SEEK_SET; break;
2415 case 1: umode = SEEK_CUR; break;
2416 case 2: umode = SEEK_END; break;
2418 umode = SEEK_SET; break;
2421 if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2422 return(UNIXERROR(ERRDOS,ERRnoaccess));
2426 outsize = set_message(outbuf,2,0,True);
2427 SIVALS(outbuf,smb_vwv0,res);
2429 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2430 fsp->fnum, (double)startpos, mode));
2435 /****************************************************************************
2437 ****************************************************************************/
2438 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2440 int outsize = set_message(outbuf,0,0,True);
2441 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2444 CHECK_FSP(fsp,conn);
2449 file_sync_all(conn);
2451 sync_file(conn,fsp);
2454 DEBUG(3,("flush\n"));
2459 /****************************************************************************
2461 ****************************************************************************/
2462 int reply_exit(connection_struct *conn,
2463 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2465 int outsize = set_message(outbuf,0,0,True);
2466 DEBUG(3,("exit\n"));
2472 /****************************************************************************
2473 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2474 ****************************************************************************/
2475 int reply_close(connection_struct *conn,
2476 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2480 int32 eclass = 0, err = 0;
2481 files_struct *fsp = NULL;
2483 outsize = set_message(outbuf,0,0,True);
2485 /* If it's an IPC, pass off to the pipe handler. */
2487 return reply_pipe_close(conn, inbuf,outbuf);
2490 fsp = file_fsp(inbuf,smb_vwv0);
2493 * We can only use CHECK_FSP if we know it's not a directory.
2496 if(!fsp || !fsp->open || (fsp->conn != conn))
2497 return(ERROR(ERRDOS,ERRbadfid));
2499 if(HAS_CACHED_ERROR(fsp)) {
2500 eclass = fsp->wbmpx_ptr->wr_errclass;
2501 err = fsp->wbmpx_ptr->wr_error;
2504 if(fsp->is_directory) {
2506 * Special case - close NT SMB directory
2509 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2510 close_directory(fsp);
2513 * Close ordinary file.
2517 * If there was a modify time outstanding,
2518 * try and set it here.
2520 if(fsp->pending_modtime)
2521 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2524 * Now take care of any time sent in the close.
2526 mtime = make_unix_date3(inbuf+smb_vwv1);
2528 /* try and set the date */
2529 set_filetime(conn, fsp->fsp_name,mtime);
2531 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2532 fsp->fd_ptr->fd, fsp->fnum,
2533 conn->num_files_open));
2535 close_file(fsp,True);
2538 /* We have a cached error */
2540 return(ERROR(eclass,err));
2546 /****************************************************************************
2547 reply to a writeclose (Core+ protocol)
2548 ****************************************************************************/
2549 int reply_writeclose(connection_struct *conn,
2550 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2553 ssize_t nwritten = -1;
2558 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2560 CHECK_FSP(fsp,conn);
2564 numtowrite = SVAL(inbuf,smb_vwv1);
2565 startpos = IVAL(inbuf,smb_vwv2);
2566 mtime = make_unix_date3(inbuf+smb_vwv4);
2567 data = smb_buf(inbuf) + 1;
2569 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2570 return(ERROR(ERRDOS,ERRlock));
2572 if(seek_file(fsp,startpos) == -1)
2573 return(UNIXERROR(ERRDOS,ERRnoaccess));
2575 nwritten = write_file(fsp,data,numtowrite);
2577 set_filetime(conn, fsp->fsp_name,mtime);
2579 close_file(fsp,True);
2581 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2582 fsp->fnum, numtowrite, nwritten,
2583 conn->num_files_open));
2586 return(UNIXERROR(ERRDOS,ERRnoaccess));
2588 outsize = set_message(outbuf,1,0,True);
2590 SSVAL(outbuf,smb_vwv0,nwritten);
2595 /****************************************************************************
2597 ****************************************************************************/
2598 int reply_lock(connection_struct *conn,
2599 char *inbuf,char *outbuf, int length, int dum_buffsize)
2601 int outsize = set_message(outbuf,0,0,True);
2602 SMB_OFF_T count,offset;
2605 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2607 CHECK_FSP(fsp,conn);
2610 count = IVAL(inbuf,smb_vwv1);
2611 offset = IVAL(inbuf,smb_vwv3);
2613 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2614 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2616 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2617 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2619 * A blocking lock was requested. Package up
2620 * this smb into a queued request and push it
2621 * onto the blocking lock queue.
2623 if(push_blocking_lock_request(inbuf, length, -1, 0))
2626 return (ERROR(eclass,ecode));
2633 /****************************************************************************
2635 ****************************************************************************/
2636 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2638 int outsize = set_message(outbuf,0,0,True);
2639 SMB_OFF_T count,offset;
2642 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2644 CHECK_FSP(fsp,conn);
2647 count = IVAL(inbuf,smb_vwv1);
2648 offset = IVAL(inbuf,smb_vwv3);
2650 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2651 return (ERROR(eclass,ecode));
2653 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2654 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2660 /****************************************************************************
2662 ****************************************************************************/
2663 int reply_tdis(connection_struct *conn,
2664 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2666 int outsize = set_message(outbuf,0,0,True);
2669 vuid = SVAL(inbuf,smb_uid);
2672 DEBUG(4,("Invalid connection in tdis\n"));
2673 return(ERROR(ERRSRV,ERRinvnid));
2678 close_cnum(conn,vuid);
2685 /****************************************************************************
2687 ****************************************************************************/
2688 int reply_echo(connection_struct *conn,
2689 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2691 int smb_reverb = SVAL(inbuf,smb_vwv0);
2693 int data_len = smb_buflen(inbuf);
2694 int outsize = set_message(outbuf,1,data_len,True);
2696 /* copy any incoming data back out */
2698 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2700 if (smb_reverb > 100) {
2701 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2705 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2706 SSVAL(outbuf,smb_vwv0,seq_num);
2708 smb_setlen(outbuf,outsize - 4);
2710 send_smb(Client,outbuf);
2713 DEBUG(3,("echo %d times\n", smb_reverb));
2719 /****************************************************************************
2720 reply to a printopen
2721 ****************************************************************************/
2722 int reply_printopen(connection_struct *conn,
2723 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2730 *fname = *fname2 = 0;
2732 if (!CAN_PRINT(conn))
2733 return(ERROR(ERRDOS,ERRnoaccess));
2738 pstrcpy(s,smb_buf(inbuf)+1);
2741 if (!(isalnum((int)*p) || strchr("._-",*p)))
2746 if (strlen(s) > 10) s[10] = 0;
2748 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2753 return(ERROR(ERRSRV,ERRnofids));
2755 pstrcpy(fname2,(char *)mktemp(fname));
2757 if (!check_name(fname2,conn)) {
2759 return(ERROR(ERRDOS,ERRnoaccess));
2762 /* Open for exclusive use, write only. */
2763 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2764 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2768 return(UNIXERROR(ERRDOS,ERRnoaccess));
2771 /* force it to be a print file */
2772 fsp->print_file = True;
2774 outsize = set_message(outbuf,1,0,True);
2775 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2777 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2778 fname2, fsp->fd_ptr->fd, fsp->fnum));
2784 /****************************************************************************
2785 reply to a printclose
2786 ****************************************************************************/
2787 int reply_printclose(connection_struct *conn,
2788 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2790 int outsize = set_message(outbuf,0,0,True);
2791 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2793 CHECK_FSP(fsp,conn);
2796 if (!CAN_PRINT(conn))
2797 return(ERROR(ERRDOS,ERRnoaccess));
2799 DEBUG(3,("printclose fd=%d fnum=%d\n",
2800 fsp->fd_ptr->fd,fsp->fnum));
2802 close_file(fsp,True);
2808 /****************************************************************************
2809 reply to a printqueue
2810 ****************************************************************************/
2811 int reply_printqueue(connection_struct *conn,
2812 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2814 int outsize = set_message(outbuf,2,3,True);
2815 int max_count = SVAL(inbuf,smb_vwv0);
2816 int start_index = SVAL(inbuf,smb_vwv1);
2818 /* we used to allow the client to get the cnum wrong, but that
2819 is really quite gross and only worked when there was only
2820 one printer - I think we should now only accept it if they
2821 get it right (tridge) */
2822 if (!CAN_PRINT(conn))
2823 return(ERROR(ERRDOS,ERRnoaccess));
2825 SSVAL(outbuf,smb_vwv0,0);
2826 SSVAL(outbuf,smb_vwv1,0);
2827 CVAL(smb_buf(outbuf),0) = 1;
2828 SSVAL(smb_buf(outbuf),1,0);
2830 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2831 start_index, max_count));
2834 print_queue_struct *queue = NULL;
2835 char *p = smb_buf(outbuf) + 3;
2836 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2837 int num_to_get = ABS(max_count);
2838 int first = (max_count>0?start_index:start_index+max_count+1);
2844 num_to_get = MIN(num_to_get,count-first);
2847 for (i=first;i<first+num_to_get;i++) {
2848 put_dos_date2(p,0,queue[i].time);
2849 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2850 SSVAL(p,5,printjob_encode(SNUM(conn),
2852 SIVAL(p,7,queue[i].size);
2854 StrnCpy(p+12,queue[i].user,16);
2859 outsize = set_message(outbuf,2,28*count+3,False);
2860 SSVAL(outbuf,smb_vwv0,count);
2861 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2862 CVAL(smb_buf(outbuf),0) = 1;
2863 SSVAL(smb_buf(outbuf),1,28*count);
2866 if (queue) free(queue);
2868 DEBUG(3,("%d entries returned in queue\n",count));
2875 /****************************************************************************
2876 reply to a printwrite
2877 ****************************************************************************/
2878 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2881 int outsize = set_message(outbuf,0,0,True);
2883 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2885 if (!CAN_PRINT(conn))
2886 return(ERROR(ERRDOS,ERRnoaccess));
2888 CHECK_FSP(fsp,conn);
2892 numtowrite = SVAL(smb_buf(inbuf),1);
2893 data = smb_buf(inbuf) + 3;
2895 if (write_file(fsp,data,numtowrite) != numtowrite)
2896 return(UNIXERROR(ERRDOS,ERRnoaccess));
2898 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2904 /****************************************************************************
2906 ****************************************************************************/
2907 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2910 int outsize,ret= -1;
2911 BOOL bad_path = False;
2913 pstrcpy(directory,smb_buf(inbuf) + 1);
2914 unix_convert(directory,conn,0,&bad_path,NULL);
2916 if (check_name(directory, conn))
2917 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2921 if((errno == ENOENT) && bad_path)
2923 unix_ERR_class = ERRDOS;
2924 unix_ERR_code = ERRbadpath;
2926 return(UNIXERROR(ERRDOS,ERRnoaccess));
2929 outsize = set_message(outbuf,0,0,True);
2931 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2936 /****************************************************************************
2937 Static function used by reply_rmdir to delete an entire directory
2939 ****************************************************************************/
2940 static BOOL recursive_rmdir(char *directory)
2944 void *dirptr = OpenDir(NULL, directory, False);
2949 while((dname = ReadDirName(dirptr)))
2954 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2957 /* Construct the full name. */
2958 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2964 pstrcpy(fullname, directory);
2965 pstrcat(fullname, "/");
2966 pstrcat(fullname, dname);
2968 if(dos_lstat(fullname, &st) != 0)
2974 if(st.st_mode & S_IFDIR)
2976 if(recursive_rmdir(fullname)!=0)
2981 if(dos_rmdir(fullname) != 0)
2987 else if(dos_unlink(fullname) != 0)
2997 /****************************************************************************
2999 ****************************************************************************/
3000 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3005 BOOL bad_path = False;
3007 pstrcpy(directory,smb_buf(inbuf) + 1);
3008 unix_convert(directory,conn, NULL,&bad_path,NULL);
3010 if (check_name(directory,conn))
3013 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3014 ok = (dos_rmdir(directory) == 0);
3015 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
3017 /* Check to see if the only thing in this directory are
3018 vetoed files/directories. If so then delete them and
3019 retry. If we fail to delete any of them (and we *don't*
3020 do a recursive delete) then fail the rmdir. */
3021 BOOL all_veto_files = True;
3023 void *dirptr = OpenDir(conn, directory, False);
3027 int dirpos = TellDir(dirptr);
3028 while ((dname = ReadDirName(dirptr)))
3030 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3032 if(!IS_VETO_PATH(conn, dname))
3034 all_veto_files = False;
3040 SeekDir(dirptr,dirpos);
3041 while ((dname = ReadDirName(dirptr)))
3046 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3049 /* Construct the full name. */
3050 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3055 pstrcpy(fullname, directory);
3056 pstrcat(fullname, "/");
3057 pstrcat(fullname, dname);
3059 if(dos_lstat(fullname, &st) != 0)
3061 if(st.st_mode & S_IFDIR)
3063 if(lp_recursive_veto_delete(SNUM(conn)))
3065 if(recursive_rmdir(fullname) != 0)
3068 if(dos_rmdir(fullname) != 0)
3071 else if(dos_unlink(fullname) != 0)
3075 /* Retry the rmdir */
3076 ok = (dos_rmdir(directory) == 0);
3086 DEBUG(3,("couldn't remove directory %s : %s\n",
3087 directory,strerror(errno)));
3092 if((errno == ENOENT) && bad_path)
3094 unix_ERR_class = ERRDOS;
3095 unix_ERR_code = ERRbadpath;
3097 return(UNIXERROR(ERRDOS,ERRbadpath));
3100 outsize = set_message(outbuf,0,0,True);
3102 DEBUG( 3, ( "rmdir %s\n", directory ) );
3108 /*******************************************************************
3109 resolve wildcards in a filename rename
3110 ********************************************************************/
3111 static BOOL resolve_wildcards(char *name1,char *name2)
3113 fstring root1,root2;
3117 name1 = strrchr(name1,'/');
3118 name2 = strrchr(name2,'/');
3120 if (!name1 || !name2) return(False);
3122 fstrcpy(root1,name1);
3123 fstrcpy(root2,name2);
3124 p = strrchr(root1,'.');
3131 p = strrchr(root2,'.');
3163 pstrcpy(name2,root2);
3166 pstrcat(name2,ext2);
3172 /*******************************************************************
3173 check if a user is allowed to rename a file
3174 ********************************************************************/
3175 static BOOL can_rename(char *fname,connection_struct *conn)
3177 SMB_STRUCT_STAT sbuf;
3179 if (!CAN_WRITE(conn)) return(False);
3181 if (dos_lstat(fname,&sbuf) != 0) return(False);
3182 if (!check_file_sharing(conn,fname,True)) return(False);
3187 /****************************************************************************
3188 The guts of the rename command, split out so it may be called by the NT SMB
3190 ****************************************************************************/
3191 int rename_internals(connection_struct *conn,
3192 char *inbuf, char *outbuf, char *name,
3193 char *newname, BOOL replace_if_exists)
3197 pstring newname_last_component;
3200 BOOL bad_path1 = False;
3201 BOOL bad_path2 = False;
3203 int error = ERRnoaccess;
3206 *directory = *mask = 0;
3208 unix_convert(name,conn,0,&bad_path1,NULL);
3209 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3212 * Split the old name into directory and last component
3213 * strings. Note that unix_convert may have stripped off a
3214 * leading ./ from both name and newname if the rename is
3215 * at the root of the share. We need to make sure either both
3216 * name and newname contain a / character or neither of them do
3217 * as this is checked in resolve_wildcards().
3220 p = strrchr(name,'/');
3222 pstrcpy(directory,".");
3226 pstrcpy(directory,name);
3228 *p = '/'; /* Replace needed for exceptional test below. */
3231 if (is_mangled(mask))
3232 check_mangled_cache( mask );
3234 has_wild = strchr(mask,'*') || strchr(mask,'?');
3238 * No wildcards - just process the one file.
3240 BOOL is_short_name = is_8_3(name, True);
3242 /* Add a terminating '/' to the directory name. */
3243 pstrcat(directory,"/");
3244 pstrcat(directory,mask);
3246 /* Ensure newname contains a '/' also */
3247 if(strrchr(newname,'/') == 0) {
3250 pstrcpy(tmpstr, "./");
3251 pstrcat(tmpstr, newname);
3252 pstrcpy(newname, tmpstr);
3255 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",
3256 case_sensitive, case_preserve, short_case_preserve, directory,
3257 newname, newname_last_component, is_short_name));
3260 * Check for special case with case preserving and not
3261 * case sensitive, if directory and newname are identical,
3262 * and the old last component differs from the original
3263 * last component only by case, then we should allow
3264 * the rename (user is trying to change the case of the
3267 if((case_sensitive == False) &&
3268 (((case_preserve == True) &&
3269 (is_short_name == False)) ||
3270 ((short_case_preserve == True) &&
3271 (is_short_name == True))) &&
3272 strcsequal(directory, newname)) {
3273 pstring newname_modified_last_component;
3276 * Get the last component of the modified name.
3277 * Note that we guarantee that newname contains a '/'
3280 p = strrchr(newname,'/');
3281 pstrcpy(newname_modified_last_component,p+1);
3283 if(strcsequal(newname_modified_last_component,
3284 newname_last_component) == False) {
3286 * Replace the modified last component with
3289 pstrcpy(p+1, newname_last_component);
3293 if(replace_if_exists) {
3295 * NT SMB specific flag - rename can overwrite
3296 * file with the same name so don't check for
3299 if(resolve_wildcards(directory,newname) &&
3300 can_rename(directory,conn) &&
3301 !dos_rename(directory,newname))
3304 if (resolve_wildcards(directory,newname) &&
3305 can_rename(directory,conn) &&
3306 !dos_file_exist(newname,NULL) &&
3307 !dos_rename(directory,newname))
3311 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3312 directory,newname));
3314 if (!count) exists = dos_file_exist(directory,NULL);
3315 if (!count && exists && dos_file_exist(newname,NULL)) {
3321 * Wildcards - process each file that matches.
3323 void *dirptr = NULL;
3327 if (check_name(directory,conn))
3328 dirptr = OpenDir(conn, directory, True);
3333 if (strequal(mask,"????????.???"))
3336 while ((dname = ReadDirName(dirptr))) {
3338 pstrcpy(fname,dname);
3340 if(!mask_match(fname, mask, case_sensitive, False))
3343 error = ERRnoaccess;
3344 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3345 if (!can_rename(fname,conn)) {
3346 DEBUG(6,("rename %s refused\n", fname));
3349 pstrcpy(destname,newname);
3351 if (!resolve_wildcards(fname,destname)) {
3352 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3356 if (!replace_if_exists && dos_file_exist(destname,NULL)) {
3357 DEBUG(6,("dos_file_exist %s\n", destname));
3362 if (!dos_rename(fname,destname))
3364 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3372 return(ERROR(ERRDOS,error));
3374 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3375 unix_ERR_class = ERRDOS;
3376 unix_ERR_code = ERRbadpath;
3378 return(UNIXERROR(ERRDOS,error));
3385 /****************************************************************************
3387 ****************************************************************************/
3389 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3395 pstrcpy(name,smb_buf(inbuf) + 1);
3396 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3398 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3400 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3402 outsize = set_message(outbuf,0,0,True);
3407 /*******************************************************************
3408 copy a file as part of a reply_copy
3409 ******************************************************************/
3411 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3412 int count,BOOL target_is_directory)
3417 files_struct *fsp1,*fsp2;
3420 pstrcpy(dest,dest1);
3421 if (target_is_directory) {
3422 char *p = strrchr(src,'/');
3431 if (!dos_file_exist(src,&st))
3438 open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3439 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3446 if (!target_is_directory && count)
3451 close_file(fsp1,False);
3454 open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3455 ofun,st.st_mode,0,&Access,&action);
3458 close_file(fsp1,False);
3463 if ((ofun&3) == 1) {
3464 if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3465 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3468 * Stop the copy from occurring.
3476 ret = transfer_file(fsp1->fd_ptr->fd,
3477 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3479 close_file(fsp1,False);
3480 close_file(fsp2,False);
3482 return(ret == st.st_size);
3487 /****************************************************************************
3488 reply to a file copy.
3489 ****************************************************************************/
3490 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3495 pstring mask,newname;
3498 int error = ERRnoaccess;
3501 int tid2 = SVAL(inbuf,smb_vwv0);
3502 int ofun = SVAL(inbuf,smb_vwv1);
3503 int flags = SVAL(inbuf,smb_vwv2);
3504 BOOL target_is_directory=False;
3505 BOOL bad_path1 = False;
3506 BOOL bad_path2 = False;
3508 *directory = *mask = 0;
3510 pstrcpy(name,smb_buf(inbuf));
3511 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3513 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3515 if (tid2 != conn->cnum) {
3516 /* can't currently handle inter share copies XXXX */
3517 DEBUG(3,("Rejecting inter-share copy\n"));
3518 return(ERROR(ERRSRV,ERRinvdevice));
3521 unix_convert(name,conn,0,&bad_path1,NULL);
3522 unix_convert(newname,conn,0,&bad_path2,NULL);
3524 target_is_directory = dos_directory_exist(newname,NULL);
3526 if ((flags&1) && target_is_directory) {
3527 return(ERROR(ERRDOS,ERRbadfile));
3530 if ((flags&2) && !target_is_directory) {
3531 return(ERROR(ERRDOS,ERRbadpath));
3534 if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
3535 /* wants a tree copy! XXXX */
3536 DEBUG(3,("Rejecting tree copy\n"));
3537 return(ERROR(ERRSRV,ERRerror));
3540 p = strrchr(name,'/');
3542 pstrcpy(directory,"./");
3546 pstrcpy(directory,name);
3550 if (is_mangled(mask))
3551 check_mangled_cache( mask );
3553 has_wild = strchr(mask,'*') || strchr(mask,'?');
3556 pstrcat(directory,"/");
3557 pstrcat(directory,mask);
3558 if (resolve_wildcards(directory,newname) &&
3559 copy_file(directory,newname,conn,ofun,
3560 count,target_is_directory)) count++;
3561 if (!count) exists = dos_file_exist(directory,NULL);
3563 void *dirptr = NULL;
3567 if (check_name(directory,conn))
3568 dirptr = OpenDir(conn, directory, True);
3574 if (strequal(mask,"????????.???"))
3577 while ((dname = ReadDirName(dirptr)))
3580 pstrcpy(fname,dname);
3582 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3584 error = ERRnoaccess;
3585 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3586 pstrcpy(destname,newname);
3587 if (resolve_wildcards(fname,destname) &&
3588 copy_file(directory,newname,conn,ofun,
3589 count,target_is_directory)) count++;
3590 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3598 return(ERROR(ERRDOS,error));
3601 if((errno == ENOENT) && (bad_path1 || bad_path2))
3603 unix_ERR_class = ERRDOS;
3604 unix_ERR_code = ERRbadpath;
3606 return(UNIXERROR(ERRDOS,error));
3610 outsize = set_message(outbuf,1,0,True);
3611 SSVAL(outbuf,smb_vwv0,count);
3616 /****************************************************************************
3618 ****************************************************************************/
3619 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3627 if (!CAN_SETDIR(snum))
3628 return(ERROR(ERRDOS,ERRnoaccess));
3630 pstrcpy(newdir,smb_buf(inbuf) + 1);
3633 if (strlen(newdir) == 0) {
3636 ok = dos_directory_exist(newdir,NULL);
3638 string_set(&conn->connectpath,newdir);
3643 return(ERROR(ERRDOS,ERRbadpath));
3645 outsize = set_message(outbuf,0,0,True);
3646 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3648 DEBUG(3,("setdir %s\n", newdir));
3653 /****************************************************************************
3654 reply to a lockingX request
3655 ****************************************************************************/
3656 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3658 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3659 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3661 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3663 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3664 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3665 SMB_OFF_T count = 0, offset = 0;
3666 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3669 uint32 ecode=0, dummy2;
3670 int eclass=0, dummy1;
3671 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3672 CHECK_FSP(fsp,conn);
3675 data = smb_buf(inbuf);
3677 /* Check if this is an oplock break on a file
3678 we have granted an oplock on.
3680 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3683 SMB_DEV_T dev = fsp->fd_ptr->dev;
3684 SMB_INO_T inode = fsp->fd_ptr->inode;
3686 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3689 * Make sure we have granted an oplock on this file.
3691 if(!fsp->granted_oplock)
3693 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3694 no oplock granted on this file.\n", fsp->fnum));
3695 return ERROR(ERRDOS,ERRlock);
3698 /* Remove the oplock flag from the sharemode. */
3699 lock_share_entry(fsp->conn, dev, inode, &token);
3700 if(remove_share_oplock(token, fsp)==False) {
3702 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3703 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3705 unlock_share_entry(fsp->conn, dev, inode, token);
3707 unlock_share_entry(fsp->conn, dev, inode, token);
3709 /* Clear the granted flag and return. */
3710 fsp->granted_oplock = False;
3713 /* if this is a pure oplock break request then don't send a reply */
3714 if (num_locks == 0 && num_ulocks == 0)
3716 /* Sanity check - ensure a pure oplock break is not a
3718 if(CVAL(inbuf,smb_vwv0) != 0xff)
3719 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3720 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3725 /* Data now points at the beginning of the list
3726 of smb_unlkrng structs */
3727 for(i = 0; i < (int)num_ulocks; i++) {
3728 if(!large_file_format) {
3729 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3730 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3732 #ifdef LARGE_SMB_OFF_T
3734 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3735 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3736 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3737 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3739 #endif /* LARGE_SMB_OFF_T */
3741 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3742 (double)offset, (double)count, fsp->fsp_name ));
3744 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3745 return ERROR(eclass,ecode);
3748 /* Setup the timeout in seconds. */
3749 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3751 /* Now do any requested locks */
3752 data += ((large_file_format ? 20 : 10)*num_ulocks);
3754 /* Data now points at the beginning of the list
3755 of smb_lkrng structs */
3757 for(i = 0; i < (int)num_locks; i++) {
3758 if(!large_file_format) {
3759 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3760 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3762 #ifdef LARGE_SMB_OFF_T
3764 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3765 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3766 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3767 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3769 #endif /* LARGE_SMB_OFF_T */
3771 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3772 (double)offset, (double)count, fsp->fsp_name ));
3774 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3776 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3778 * A blocking lock was requested. Package up
3779 * this smb into a queued request and push it
3780 * onto the blocking lock queue.
3782 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3789 /* If any of the above locks failed, then we must unlock
3790 all of the previous locks (X/Open spec). */
3791 if(i != num_locks && num_locks != 0) {
3792 for(; i >= 0; i--) {
3793 if(!large_file_format) {
3794 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3795 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3797 #ifdef LARGE_SMB_OFF_T
3799 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3800 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3801 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3802 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3804 #endif /* LARGE_SMB_OFF_T */
3806 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3808 return ERROR(eclass,ecode);
3811 set_message(outbuf,2,0,True);
3813 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3814 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3816 return chain_reply(inbuf,outbuf,length,bufsize);
3820 /****************************************************************************
3821 reply to a SMBreadbmpx (read block multiplex) request
3822 ****************************************************************************/
3823 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3834 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3836 /* this function doesn't seem to work - disable by default */
3838 return(ERROR(ERRSRV,ERRuseSTD));
3840 outsize = set_message(outbuf,8,0,True);
3842 CHECK_FSP(fsp,conn);
3846 startpos = IVAL(inbuf,smb_vwv1);
3847 maxcount = SVAL(inbuf,smb_vwv3);
3849 data = smb_buf(outbuf);
3850 pad = ((long)data)%4;
3851 if (pad) pad = 4 - pad;
3854 max_per_packet = bufsize-(outsize+pad);
3858 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3859 return(ERROR(ERRDOS,ERRlock));
3863 size_t N = MIN(max_per_packet,tcount-total_read);
3865 nread = read_file(fsp,data,startpos,N);
3867 if (nread <= 0) nread = 0;
3869 if (nread < (ssize_t)N)
3870 tcount = total_read + nread;
3872 set_message(outbuf,8,nread,False);
3873 SIVAL(outbuf,smb_vwv0,startpos);
3874 SSVAL(outbuf,smb_vwv2,tcount);
3875 SSVAL(outbuf,smb_vwv6,nread);
3876 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3878 send_smb(Client,outbuf);
3880 total_read += nread;
3883 while (total_read < (ssize_t)tcount);
3888 /****************************************************************************
3889 reply to a SMBwritebmpx (write block multiplex primary) request
3890 ****************************************************************************/
3891 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3894 ssize_t nwritten = -1;
3901 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3903 CHECK_FSP(fsp,conn);
3907 tcount = SVAL(inbuf,smb_vwv1);
3908 startpos = IVAL(inbuf,smb_vwv3);
3909 write_through = BITSETW(inbuf+smb_vwv7,0);
3910 numtowrite = SVAL(inbuf,smb_vwv10);
3911 smb_doff = SVAL(inbuf,smb_vwv11);
3913 data = smb_base(inbuf) + smb_doff;
3915 /* If this fails we need to send an SMBwriteC response,
3916 not an SMBwritebmpx - set this up now so we don't forget */
3917 CVAL(outbuf,smb_com) = SMBwritec;
3919 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3920 return(ERROR(ERRDOS,ERRlock));
3922 if(seek_file(fsp,startpos) == -1)
3923 return(UNIXERROR(ERRDOS,ERRnoaccess));
3925 nwritten = write_file(fsp,data,numtowrite);
3927 if(lp_syncalways(SNUM(conn)) || write_through)
3928 sync_file(conn,fsp);
3930 if(nwritten < (ssize_t)numtowrite)
3931 return(UNIXERROR(ERRHRD,ERRdiskfull));
3933 /* If the maximum to be written to this file
3934 is greater than what we just wrote then set
3935 up a secondary struct to be attached to this
3936 fd, we will use this to cache error messages etc. */
3937 if((ssize_t)tcount > nwritten)
3939 write_bmpx_struct *wbms;
3940 if(fsp->wbmpx_ptr != NULL)
3941 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3943 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3946 DEBUG(0,("Out of memory in reply_readmpx\n"));
3947 return(ERROR(ERRSRV,ERRnoresource));
3949 wbms->wr_mode = write_through;
3950 wbms->wr_discard = False; /* No errors yet */
3951 wbms->wr_total_written = nwritten;
3952 wbms->wr_errclass = 0;
3954 fsp->wbmpx_ptr = wbms;
3957 /* We are returning successfully, set the message type back to
3959 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3961 outsize = set_message(outbuf,1,0,True);
3963 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3965 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3966 fsp->fnum, numtowrite, nwritten ) );
3968 if (write_through && tcount==nwritten) {
3969 /* we need to send both a primary and a secondary response */
3970 smb_setlen(outbuf,outsize - 4);
3971 send_smb(Client,outbuf);
3973 /* now the secondary */
3974 outsize = set_message(outbuf,1,0,True);
3975 CVAL(outbuf,smb_com) = SMBwritec;
3976 SSVAL(outbuf,smb_vwv0,nwritten);
3983 /****************************************************************************
3984 reply to a SMBwritebs (write block multiplex secondary) request
3985 ****************************************************************************/
3986 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3989 ssize_t nwritten = -1;
3996 write_bmpx_struct *wbms;
3997 BOOL send_response = False;
3998 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4000 CHECK_FSP(fsp,conn);
4003 tcount = SVAL(inbuf,smb_vwv1);
4004 startpos = IVAL(inbuf,smb_vwv2);
4005 numtowrite = SVAL(inbuf,smb_vwv6);
4006 smb_doff = SVAL(inbuf,smb_vwv7);
4008 data = smb_base(inbuf) + smb_doff;
4010 /* We need to send an SMBwriteC response, not an SMBwritebs */
4011 CVAL(outbuf,smb_com) = SMBwritec;
4013 /* This fd should have an auxiliary struct attached,
4014 check that it does */
4015 wbms = fsp->wbmpx_ptr;
4016 if(!wbms) return(-1);
4018 /* If write through is set we can return errors, else we must
4020 write_through = wbms->wr_mode;
4022 /* Check for an earlier error */
4023 if(wbms->wr_discard)
4024 return -1; /* Just discard the packet */
4026 if(seek_file(fsp,startpos) == -1)
4030 /* We are returning an error - we can delete the aux struct */
4031 if (wbms) free((char *)wbms);
4032 fsp->wbmpx_ptr = NULL;
4033 return(UNIXERROR(ERRDOS,ERRnoaccess));
4035 return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
4038 nwritten = write_file(fsp,data,numtowrite);
4040 if(lp_syncalways(SNUM(conn)) || write_through)
4041 sync_file(conn,fsp);
4043 if (nwritten < (ssize_t)numtowrite)
4047 /* We are returning an error - we can delete the aux struct */
4048 if (wbms) free((char *)wbms);
4049 fsp->wbmpx_ptr = NULL;
4050 return(ERROR(ERRHRD,ERRdiskfull));
4052 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4055 /* Increment the total written, if this matches tcount
4056 we can discard the auxiliary struct (hurrah !) and return a writeC */
4057 wbms->wr_total_written += nwritten;
4058 if(wbms->wr_total_written >= tcount)
4062 outsize = set_message(outbuf,1,0,True);
4063 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4064 send_response = True;
4068 fsp->wbmpx_ptr = NULL;
4078 /****************************************************************************
4079 reply to a SMBsetattrE
4080 ****************************************************************************/
4081 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4083 struct utimbuf unix_times;
4085 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4087 outsize = set_message(outbuf,0,0,True);
4089 CHECK_FSP(fsp,conn);
4092 /* Convert the DOS times into unix times. Ignore create
4093 time as UNIX can't set this.
4095 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4096 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4099 * Patch from Ray Frush <frush@engr.colostate.edu>
4100 * Sometimes times are sent as zero - ignore them.
4103 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4105 /* Ignore request */
4108 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4109 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4113 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4115 /* set modify time = to access time if modify time was 0 */
4116 unix_times.modtime = unix_times.actime;
4119 /* Set the date on this file */
4120 if(file_utime(conn, fsp->fsp_name, &unix_times))
4121 return(ERROR(ERRDOS,ERRnoaccess));
4123 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4124 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4130 /****************************************************************************
4131 reply to a SMBgetattrE
4132 ****************************************************************************/
4133 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4135 SMB_STRUCT_STAT sbuf;
4138 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4140 outsize = set_message(outbuf,11,0,True);
4142 CHECK_FSP(fsp,conn);
4145 /* Do an fstat on this file */
4146 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4147 return(UNIXERROR(ERRDOS,ERRnoaccess));
4149 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4151 /* Convert the times into dos times. Set create
4152 date to be last modify date as UNIX doesn't save
4154 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4155 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4156 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4159 SIVAL(outbuf,smb_vwv6,0);
4160 SIVAL(outbuf,smb_vwv8,0);
4164 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4165 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4167 SSVAL(outbuf,smb_vwv10, mode);
4169 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));