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)
517 int smb_apasslen = 0;
519 int smb_ntpasslen = 0;
520 pstring smb_ntpasswd;
521 BOOL valid_nt_password = False;
525 static BOOL done_sesssetup = False;
526 BOOL doencrypt = SMBENCRYPT();
532 smb_bufsize = SVAL(inbuf,smb_vwv2);
534 if (Protocol < PROTOCOL_NT1) {
535 smb_apasslen = SVAL(inbuf,smb_vwv7);
536 if (smb_apasslen > MAX_PASS_LEN)
538 overflow_attack(smb_apasslen);
541 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
542 smb_apasswd[smb_apasslen] = 0;
543 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
545 if (!doencrypt && (lp_security() != SEC_SERVER)) {
546 smb_apasslen = strlen(smb_apasswd);
549 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
550 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
551 enum remote_arch_types ra_type = get_remote_arch();
552 char *p = smb_buf(inbuf);
554 global_client_caps = IVAL(inbuf,smb_vwv11);
556 /* client_caps is used as final determination if client is NT or Win95.
557 This is needed to return the correct error codes in some
561 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
563 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
564 set_remote_arch( RA_WINNT);
566 set_remote_arch( RA_WIN95);
569 if (passlen1 != 24 && passlen2 != 24)
572 if (passlen1 > MAX_PASS_LEN) {
573 overflow_attack(passlen1);
576 passlen1 = MIN(passlen1, MAX_PASS_LEN);
577 passlen2 = MIN(passlen2, MAX_PASS_LEN);
580 /* both Win95 and WinNT stuff up the password lengths for
581 non-encrypting systems. Uggh.
583 if passlen1==24 its a win95 system, and its setting the
584 password length incorrectly. Luckily it still works with the
585 default code because Win95 will null terminate the password
588 if passlen1>0 and passlen2>0 then maybe its a NT box and its
589 setting passlen2 to some random value which really stuffs
590 things up. we need to fix that one. */
592 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
596 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
597 /* Save the lanman2 password and the NT md4 password. */
598 smb_apasslen = passlen1;
599 memcpy(smb_apasswd,p,smb_apasslen);
600 smb_apasswd[smb_apasslen] = 0;
601 smb_ntpasslen = passlen2;
602 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
603 smb_ntpasswd[smb_ntpasslen] = 0;
605 /* we use the first password that they gave */
606 smb_apasslen = passlen1;
607 StrnCpy(smb_apasswd,p,smb_apasslen);
609 /* trim the password */
610 smb_apasslen = strlen(smb_apasswd);
612 /* wfwg sometimes uses a space instead of a null */
613 if (strequal(smb_apasswd," ")) {
619 p += passlen1 + passlen2;
620 fstrcpy(user,p); p = skip_string(p,1);
623 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
624 domain,skip_string(p,1),skip_string(p,2)));
628 DEBUG(3,("sesssetupX:name=[%s]\n",user));
630 /* If name ends in $ then I think it's asking about whether a */
631 /* computer with that name (minus the $) has access. For now */
632 /* say yes to everything ending in $. */
633 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
635 return session_trust_account(conn, inbuf, outbuf, user,
636 smb_apasswd, smb_apasslen,
637 smb_ntpasswd, smb_ntpasslen);
640 /* If no username is sent use the guest account */
643 pstrcpy(user,lp_guestaccount(-1));
644 /* If no user and no password then set guest flag. */
645 if( *smb_apasswd == 0)
652 * In share level security, only overwrite sesssetup_use if
653 * it's a non null-session share. Helps keep %U and %G
657 if((lp_security() != SEC_SHARE) || (*user && !guest))
658 pstrcpy(sesssetup_user,user);
660 reload_services(True);
663 * Save the username before mapping. We will use
664 * the original username sent to us for security=server
665 * and security=domain checking.
668 pstrcpy( orig_user, user);
670 map_nt_and_unix_username(domain, user);
672 add_session_user(user);
675 * Check if the given username was the guest user with no password.
678 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
682 * Check with orig_user for security=server and
687 !check_server_security(orig_user, domain,
688 smb_apasswd, smb_apasslen,
689 smb_ntpasswd, smb_ntpasslen) &&
690 !check_domain_security(orig_user, domain,
691 smb_apasswd, smb_apasslen,
692 smb_ntpasswd, smb_ntpasslen) &&
693 !check_hosts_equiv(user)
698 * If we get here then the user wasn't guest and the remote
699 * authentication methods failed. Check the authentication
700 * methods on this local server.
702 * If an NT password was supplied try and validate with that
703 * first. This is superior as the passwords are mixed case
704 * 128 length unicode.
709 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
710 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
712 valid_nt_password = True;
715 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL))
717 if (lp_security() >= SEC_USER)
719 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
720 return(ERROR(ERRSRV,ERRbadpw));
722 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
724 if (Get_Pwnam(user,True))
725 return(ERROR(ERRSRV,ERRbadpw));
729 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
730 * Then always map to guest account - as done below.
734 if (*smb_apasswd || !Get_Pwnam(user,True))
735 pstrcpy(user,lp_guestaccount(-1));
736 DEBUG(3,("Registered username %s for guest access\n",user));
741 if (!Get_Pwnam(user,True)) {
742 DEBUG(3,("No such user %s - using guest account\n",user));
743 pstrcpy(user,lp_guestaccount(-1));
747 if (!strequal(user,lp_guestaccount(-1)) &&
748 lp_servicenumber(user) < 0)
750 int homes = lp_servicenumber(HOMES_NAME);
751 char *home = get_home_dir(user);
752 if (homes >= 0 && home)
753 lp_add_home(user,homes,home);
757 /* it's ok - setup a reply */
758 if (Protocol < PROTOCOL_NT1) {
759 set_message(outbuf,3,0,True);
762 set_message(outbuf,3,3,True);
764 pstrcpy(p,"Unix"); p = skip_string(p,1);
765 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
766 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
767 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
768 /* perhaps grab OS version here?? */
771 /* Set the correct uid in the outgoing and incoming packets
772 We will use this on future requests to determine which
773 user we should become.
776 struct passwd *pw = Get_Pwnam(user,False);
778 DEBUG(1,("Username %s is invalid on this system\n",user));
779 return(ERROR(ERRSRV,ERRbadpw));
786 SSVAL(outbuf,smb_vwv2,1);
788 /* register the name and uid as being validated, so further connections
789 to a uid can get through without a password, on the same VC */
790 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
792 SSVAL(outbuf,smb_uid,sess_vuid);
793 SSVAL(inbuf,smb_uid,sess_vuid);
796 max_send = MIN(max_send,smb_bufsize);
798 DEBUG(6,("Client requested max send size of %d\n", max_send));
800 done_sesssetup = True;
802 return chain_reply(inbuf,outbuf,length,bufsize);
806 /****************************************************************************
808 ****************************************************************************/
809 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
815 BOOL bad_path = False;
818 pstrcpy(name,smb_buf(inbuf) + 1);
819 unix_convert(name,conn,0,&bad_path,&st);
821 mode = SVAL(inbuf,smb_vwv0);
823 if (check_name(name,conn)) {
825 ok = S_ISDIR(st.st_mode);
827 ok = dos_directory_exist(name,NULL);
832 /* We special case this - as when a Windows machine
833 is parsing a path is steps through the components
834 one at a time - if a component fails it expects
835 ERRbadpath, not ERRbadfile.
839 unix_ERR_class = ERRDOS;
840 unix_ERR_code = ERRbadpath;
844 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
845 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
846 (get_remote_arch() == RA_WINNT))
848 unix_ERR_class = ERRDOS;
849 unix_ERR_code = ERRbaddirectory;
853 return(UNIXERROR(ERRDOS,ERRbadpath));
856 outsize = set_message(outbuf,0,0,True);
858 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
864 /****************************************************************************
866 ****************************************************************************/
867 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
871 SMB_STRUCT_STAT sbuf;
876 BOOL bad_path = False;
878 pstrcpy(fname,smb_buf(inbuf) + 1);
880 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
881 under WfWg - weird! */
884 mode = aHIDDEN | aDIR;
885 if (!CAN_WRITE(conn)) mode |= aRONLY;
892 unix_convert(fname,conn,0,&bad_path,&sbuf);
893 if (check_name(fname,conn))
895 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
897 mode = dos_mode(conn,fname,&sbuf);
899 mtime = sbuf.st_mtime;
905 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
911 if((errno == ENOENT) && bad_path)
913 unix_ERR_class = ERRDOS;
914 unix_ERR_code = ERRbadpath;
917 return(UNIXERROR(ERRDOS,ERRbadfile));
920 outsize = set_message(outbuf,10,0,True);
922 SSVAL(outbuf,smb_vwv0,mode);
923 if(lp_dos_filetime_resolution(SNUM(conn)) )
924 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
926 put_dos_date3(outbuf,smb_vwv1,mtime);
927 SIVAL(outbuf,smb_vwv3,(uint32)size);
929 if (Protocol >= PROTOCOL_NT1) {
930 char *p = strrchr(fname,'/');
931 uint16 flg2 = SVAL(outbuf,smb_flg2);
933 if (!is_8_3(fname, True))
934 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
937 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
943 /****************************************************************************
945 ****************************************************************************/
946 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
954 BOOL bad_path = False;
956 pstrcpy(fname,smb_buf(inbuf) + 1);
957 unix_convert(fname,conn,0,&bad_path,&st);
959 mode = SVAL(inbuf,smb_vwv0);
960 mtime = make_unix_date3(inbuf+smb_vwv1);
962 if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
964 if (check_name(fname,conn))
965 ok = (file_chmod(conn,fname,mode,NULL) == 0);
967 ok = set_filetime(conn,fname,mtime);
971 if((errno == ENOENT) && bad_path)
973 unix_ERR_class = ERRDOS;
974 unix_ERR_code = ERRbadpath;
977 return(UNIXERROR(ERRDOS,ERRnoaccess));
980 outsize = set_message(outbuf,0,0,True);
982 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
988 /****************************************************************************
990 ****************************************************************************/
991 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
994 SMB_BIG_UINT dfree,dsize,bsize;
996 sys_disk_free(".",&bsize,&dfree,&dsize);
998 outsize = set_message(outbuf,5,0,True);
1000 SSVAL(outbuf,smb_vwv0,dsize);
1001 SSVAL(outbuf,smb_vwv1,bsize/512);
1002 SSVAL(outbuf,smb_vwv2,512);
1003 SSVAL(outbuf,smb_vwv3,dfree);
1005 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1011 /****************************************************************************
1013 Can be called from SMBsearch, SMBffirst or SMBfunique.
1014 ****************************************************************************/
1015 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1026 BOOL finished = False;
1035 BOOL check_descend = False;
1036 BOOL expect_close = False;
1037 BOOL can_open = True;
1038 BOOL bad_path = False;
1040 *mask = *directory = *fname = 0;
1042 /* If we were called as SMBffirst then we must expect close. */
1043 if(CVAL(inbuf,smb_com) == SMBffirst)
1044 expect_close = True;
1046 outsize = set_message(outbuf,1,3,True);
1047 maxentries = SVAL(inbuf,smb_vwv0);
1048 dirtype = SVAL(inbuf,smb_vwv1);
1049 path = smb_buf(inbuf) + 1;
1050 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1053 /* dirtype &= ~aDIR; */
1055 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1058 if (status_len == 0)
1062 pstrcpy(directory,smb_buf(inbuf)+1);
1063 pstrcpy(dir2,smb_buf(inbuf)+1);
1064 unix_convert(directory,conn,0,&bad_path,NULL);
1067 if (!check_name(directory,conn))
1070 p = strrchr(dir2,'/');
1082 p = strrchr(directory,'/');
1088 if (strlen(directory) == 0)
1089 pstrcpy(directory,"./");
1091 CVAL(status,0) = dirtype;
1095 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1096 memcpy(mask,status+1,11);
1098 dirtype = CVAL(status,0) & 0x1F;
1099 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1102 string_set(&conn->dirpath,dptr_path(dptr_num));
1103 if (!case_sensitive)
1107 /* turn strings of spaces into a . */
1109 trim_string(mask,NULL," ");
1110 if ((p = strrchr(mask,' ')))
1115 trim_string(mask,NULL," ");
1121 /* Convert the formatted mask. (This code lives in trans2.c) */
1129 if((skip = skip_multibyte_char( *p )) != 0 )
1135 if (*p != '?' && *p != '*' && !isdoschar(*p))
1137 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1145 if (!strchr(mask,'.') && strlen(mask)>8)
1148 fstrcpy(tmp,&mask[8]);
1154 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1158 p = smb_buf(outbuf) + 3;
1162 if (status_len == 0)
1164 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1169 if((errno == ENOENT) && bad_path)
1171 unix_ERR_class = ERRDOS;
1172 unix_ERR_code = ERRbadpath;
1174 return (UNIXERROR(ERRDOS,ERRnofids));
1176 return(ERROR(ERRDOS,ERRnofids));
1180 DEBUG(4,("dptr_num is %d\n",dptr_num));
1184 if ((dirtype&0x1F) == aVOLID)
1186 memcpy(p,status,21);
1187 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1188 dptr_fill(p+12,dptr_num);
1189 if (dptr_zero(p+12) && (status_len==0))
1193 p += DIR_STRUCT_SIZE;
1197 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1198 conn->dirpath,lp_dontdescend(SNUM(conn))));
1199 if (in_list(conn->dirpath,
1200 lp_dontdescend(SNUM(conn)),True))
1201 check_descend = True;
1203 for (i=numentries;(i<maxentries) && !finished;i++)
1206 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1209 memcpy(p,status,21);
1210 make_dir_struct(p,mask,fname,size,mode,date);
1211 dptr_fill(p+12,dptr_num);
1214 p += DIR_STRUCT_SIZE;
1223 if (numentries == 0 || !ok)
1225 CVAL(outbuf,smb_rcls) = ERRDOS;
1226 SSVAL(outbuf,smb_err,ERRnofiles);
1229 /* If we were called as SMBffirst with smb_search_id == NULL
1230 and no entries were found then return error and close dirptr
1233 if(ok && expect_close && numentries == 0 && status_len == 0)
1235 CVAL(outbuf,smb_rcls) = ERRDOS;
1236 SSVAL(outbuf,smb_err,ERRnofiles);
1237 /* Also close the dptr - we know it's gone */
1238 dptr_close(dptr_num);
1241 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1242 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1243 dptr_close(dptr_num);
1245 SSVAL(outbuf,smb_vwv0,numentries);
1246 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1247 CVAL(smb_buf(outbuf),0) = 5;
1248 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1250 if (Protocol >= PROTOCOL_NT1) {
1251 uint16 flg2 = SVAL(outbuf,smb_flg2);
1252 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1255 outsize += DIR_STRUCT_SIZE*numentries;
1256 smb_setlen(outbuf,outsize - 4);
1258 if ((! *directory) && dptr_path(dptr_num))
1259 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1261 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1262 smb_fn_name(CVAL(inbuf,smb_com)),
1263 mask, directory, dirtype, numentries, maxentries ) );
1269 /****************************************************************************
1270 reply to a fclose (stop directory search)
1271 ****************************************************************************/
1272 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1280 outsize = set_message(outbuf,1,0,True);
1281 path = smb_buf(inbuf) + 1;
1282 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1285 if (status_len == 0)
1286 return(ERROR(ERRSRV,ERRsrverror));
1288 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1290 if(dptr_fetch(status+12,&dptr_num)) {
1291 /* Close the dptr - we know it's gone */
1292 dptr_close(dptr_num);
1295 SSVAL(outbuf,smb_vwv0,0);
1297 DEBUG(3,("search close\n"));
1303 /****************************************************************************
1305 ****************************************************************************/
1307 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1317 SMB_STRUCT_STAT sbuf;
1318 BOOL bad_path = False;
1320 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1322 share_mode = SVAL(inbuf,smb_vwv0);
1324 pstrcpy(fname,smb_buf(inbuf)+1);
1325 unix_convert(fname,conn,0,&bad_path,NULL);
1329 return(ERROR(ERRSRV,ERRnofids));
1331 if (!check_name(fname,conn))
1333 if((errno == ENOENT) && bad_path)
1335 unix_ERR_class = ERRDOS;
1336 unix_ERR_code = ERRbadpath;
1339 return(UNIXERROR(ERRDOS,ERRnoaccess));
1342 unixmode = unix_mode(conn,aARCH);
1344 open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1345 unixmode, oplock_request,&rmode,NULL);
1349 if((errno == ENOENT) && bad_path)
1351 unix_ERR_class = ERRDOS;
1352 unix_ERR_code = ERRbadpath;
1355 return(UNIXERROR(ERRDOS,ERRnoaccess));
1358 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1359 close_file(fsp,False);
1360 return(ERROR(ERRDOS,ERRnoaccess));
1363 size = sbuf.st_size;
1364 fmode = dos_mode(conn,fname,&sbuf);
1365 mtime = sbuf.st_mtime;
1368 DEBUG(3,("attempt to open a directory %s\n",fname));
1369 close_file(fsp,False);
1370 return(ERROR(ERRDOS,ERRnoaccess));
1373 outsize = set_message(outbuf,7,0,True);
1374 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1375 SSVAL(outbuf,smb_vwv1,fmode);
1376 if(lp_dos_filetime_resolution(SNUM(conn)) )
1377 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1379 put_dos_date3(outbuf,smb_vwv2,mtime);
1380 SIVAL(outbuf,smb_vwv4,(uint32)size);
1381 SSVAL(outbuf,smb_vwv6,rmode);
1383 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1384 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1387 if(fsp->granted_oplock)
1388 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1393 /****************************************************************************
1394 reply to an open and X
1395 ****************************************************************************/
1396 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1399 int smb_mode = SVAL(inbuf,smb_vwv3);
1400 int smb_attr = SVAL(inbuf,smb_vwv5);
1401 /* Breakout the oplock request bits so we can set the
1402 reply bits separately. */
1403 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1404 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1405 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1407 int open_flags = SVAL(inbuf,smb_vwv2);
1408 int smb_sattr = SVAL(inbuf,smb_vwv4);
1409 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1411 int smb_ofun = SVAL(inbuf,smb_vwv8);
1414 int fmode=0,mtime=0,rmode=0;
1415 SMB_STRUCT_STAT sbuf;
1417 BOOL bad_path = False;
1420 /* If it's an IPC, pass off the pipe handler. */
1421 if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
1423 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1426 /* XXXX we need to handle passed times, sattr and flags */
1428 pstrcpy(fname,smb_buf(inbuf));
1429 unix_convert(fname,conn,0,&bad_path,NULL);
1433 return(ERROR(ERRSRV,ERRnofids));
1435 if (!check_name(fname,conn))
1437 if((errno == ENOENT) && bad_path)
1439 unix_ERR_class = ERRDOS;
1440 unix_ERR_code = ERRbadpath;
1443 return(UNIXERROR(ERRDOS,ERRnoaccess));
1446 unixmode = unix_mode(conn,smb_attr | aARCH);
1448 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1449 oplock_request, &rmode,&smb_action);
1453 if((errno == ENOENT) && bad_path)
1455 unix_ERR_class = ERRDOS;
1456 unix_ERR_code = ERRbadpath;
1459 return(UNIXERROR(ERRDOS,ERRnoaccess));
1462 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1463 close_file(fsp,False);
1464 return(ERROR(ERRDOS,ERRnoaccess));
1467 size = sbuf.st_size;
1468 fmode = dos_mode(conn,fname,&sbuf);
1469 mtime = sbuf.st_mtime;
1471 close_file(fsp,False);
1472 return(ERROR(ERRDOS,ERRnoaccess));
1475 /* If the caller set the extended oplock request bit
1476 and we granted one (by whatever means) - set the
1477 correct bit for extended oplock reply.
1480 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1481 smb_action |= EXTENDED_OPLOCK_GRANTED;
1484 if(ex_oplock_request && fsp->granted_oplock) {
1485 smb_action |= EXTENDED_OPLOCK_GRANTED;
1488 /* If the caller set the core oplock request bit
1489 and we granted one (by whatever means) - set the
1490 correct bit for core oplock reply.
1493 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1494 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1497 if(core_oplock_request && fsp->granted_oplock) {
1498 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1501 set_message(outbuf,15,0,True);
1502 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1503 SSVAL(outbuf,smb_vwv3,fmode);
1504 if(lp_dos_filetime_resolution(SNUM(conn)) )
1505 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1507 put_dos_date3(outbuf,smb_vwv4,mtime);
1508 SIVAL(outbuf,smb_vwv6,(uint32)size);
1509 SSVAL(outbuf,smb_vwv8,rmode);
1510 SSVAL(outbuf,smb_vwv11,smb_action);
1512 return chain_reply(inbuf,outbuf,length,bufsize);
1516 /****************************************************************************
1517 reply to a SMBulogoffX
1518 ****************************************************************************/
1519 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1521 uint16 vuid = SVAL(inbuf,smb_uid);
1522 user_struct *vuser = get_valid_user_struct(vuid);
1525 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1528 /* in user level security we are supposed to close any files
1529 open by this user */
1530 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1531 file_close_user(vuid);
1534 invalidate_vuid(vuid);
1536 set_message(outbuf,2,0,True);
1538 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1540 return chain_reply(inbuf,outbuf,length,bufsize);
1544 /****************************************************************************
1545 reply to a mknew or a create
1546 ****************************************************************************/
1547 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1555 BOOL bad_path = False;
1557 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1559 com = SVAL(inbuf,smb_com);
1561 createmode = SVAL(inbuf,smb_vwv0);
1562 pstrcpy(fname,smb_buf(inbuf)+1);
1563 unix_convert(fname,conn,0,&bad_path,NULL);
1565 if (createmode & aVOLID)
1567 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1570 unixmode = unix_mode(conn,createmode);
1574 return(ERROR(ERRSRV,ERRnofids));
1576 if (!check_name(fname,conn))
1578 if((errno == ENOENT) && bad_path)
1580 unix_ERR_class = ERRDOS;
1581 unix_ERR_code = ERRbadpath;
1584 return(UNIXERROR(ERRDOS,ERRnoaccess));
1589 /* We should fail if file exists. */
1594 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1598 /* Open file in dos compatibility share mode. */
1599 open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1600 ofun, unixmode, oplock_request, NULL, NULL);
1604 if((errno == ENOENT) && bad_path)
1606 unix_ERR_class = ERRDOS;
1607 unix_ERR_code = ERRbadpath;
1610 return(UNIXERROR(ERRDOS,ERRnoaccess));
1613 outsize = set_message(outbuf,1,0,True);
1614 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1616 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1617 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1620 if(fsp->granted_oplock)
1621 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1623 DEBUG( 2, ( "new file %s\n", fname ) );
1624 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1625 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1631 /****************************************************************************
1632 reply to a create temporary file
1633 ****************************************************************************/
1634 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1641 BOOL bad_path = False;
1643 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1645 createmode = SVAL(inbuf,smb_vwv0);
1646 pstrcpy(fname,smb_buf(inbuf)+1);
1647 pstrcat(fname,"/TMXXXXXX");
1648 unix_convert(fname,conn,0,&bad_path,NULL);
1650 unixmode = unix_mode(conn,createmode);
1654 return(ERROR(ERRSRV,ERRnofids));
1656 if (!check_name(fname,conn))
1658 if((errno == ENOENT) && bad_path)
1660 unix_ERR_class = ERRDOS;
1661 unix_ERR_code = ERRbadpath;
1664 return(UNIXERROR(ERRDOS,ERRnoaccess));
1667 pstrcpy(fname2,(char *)mktemp(fname));
1669 /* Open file in dos compatibility share mode. */
1670 /* We should fail if file exists. */
1671 open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1672 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1676 if((errno == ENOENT) && bad_path)
1678 unix_ERR_class = ERRDOS;
1679 unix_ERR_code = ERRbadpath;
1682 return(UNIXERROR(ERRDOS,ERRnoaccess));
1685 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1686 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1687 CVAL(smb_buf(outbuf),0) = 4;
1688 pstrcpy(smb_buf(outbuf) + 1,fname2);
1690 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1691 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1694 if(fsp->granted_oplock)
1695 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1697 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1698 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1699 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1705 /*******************************************************************
1706 check if a user is allowed to delete a file
1707 ********************************************************************/
1708 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1710 SMB_STRUCT_STAT sbuf;
1713 if (!CAN_WRITE(conn)) return(False);
1715 if (dos_lstat(fname,&sbuf) != 0) return(False);
1716 fmode = dos_mode(conn,fname,&sbuf);
1717 if (fmode & aDIR) return(False);
1718 if (!lp_delete_readonly(SNUM(conn))) {
1719 if (fmode & aRONLY) return(False);
1721 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1723 if (!check_file_sharing(conn,fname,False)) return(False);
1727 /****************************************************************************
1729 ****************************************************************************/
1730 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1739 int error = ERRnoaccess;
1742 BOOL bad_path = False;
1744 *directory = *mask = 0;
1746 dirtype = SVAL(inbuf,smb_vwv0);
1748 pstrcpy(name,smb_buf(inbuf) + 1);
1750 DEBUG(3,("reply_unlink : %s\n",name));
1752 unix_convert(name,conn,0,&bad_path,NULL);
1754 p = strrchr(name,'/');
1756 pstrcpy(directory,"./");
1760 pstrcpy(directory,name);
1764 if (is_mangled(mask))
1765 check_mangled_cache( mask );
1767 has_wild = strchr(mask,'*') || strchr(mask,'?');
1770 pstrcat(directory,"/");
1771 pstrcat(directory,mask);
1772 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
1775 exists = dos_file_exist(directory,NULL);
1777 void *dirptr = NULL;
1780 if (check_name(directory,conn))
1781 dirptr = OpenDir(conn, directory, True);
1783 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1784 the pattern matches against the long name, otherwise the short name
1785 We don't implement this yet XXXX
1792 if (strequal(mask,"????????.???"))
1795 while ((dname = ReadDirName(dirptr)))
1798 pstrcpy(fname,dname);
1800 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1802 error = ERRnoaccess;
1803 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1804 if (!can_delete(fname,conn,dirtype)) continue;
1805 if (!dos_unlink(fname)) count++;
1806 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1814 return(ERROR(ERRDOS,error));
1817 if((errno == ENOENT) && bad_path)
1819 unix_ERR_class = ERRDOS;
1820 unix_ERR_code = ERRbadpath;
1822 return(UNIXERROR(ERRDOS,error));
1826 outsize = set_message(outbuf,0,0,True);
1832 /****************************************************************************
1833 reply to a readbraw (core+ protocol)
1834 ****************************************************************************/
1835 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1837 size_t maxcount,mincount;
1840 char *header = outbuf;
1845 * Special check if an oplock break has been issued
1846 * and the readraw request croses on the wire, we must
1847 * return a zero length response here.
1850 if(global_oplock_break)
1852 _smb_setlen(header,0);
1853 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1854 DEBUG(5,("readbraw - oplock break finished\n"));
1858 fsp = file_fsp(inbuf,smb_vwv0);
1860 startpos = IVAL(inbuf,smb_vwv1);
1861 #ifdef LARGE_SMB_OFF_T
1862 if(CVAL(inbuf,smb_wct) == 10) {
1864 * This is a large offset (64 bit) read.
1866 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1868 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1869 (double)startpos ));
1870 _smb_setlen(header,0);
1871 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1875 #endif /* LARGE_SMB_OFF_T */
1876 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1877 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1879 /* ensure we don't overrun the packet size */
1880 maxcount = MIN(65535,maxcount);
1881 maxcount = MAX(mincount,maxcount);
1883 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1884 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1885 _smb_setlen(header,0);
1886 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1890 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1892 SMB_OFF_T size = fsp->size;
1893 SMB_OFF_T sizeneeded = startpos + maxcount;
1895 if (size < sizeneeded)
1898 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1900 if (!fsp->can_write)
1904 nread = MIN(maxcount,(size - startpos));
1907 if (nread < mincount)
1910 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1911 fsp->fnum, (double)startpos,
1912 maxcount, mincount, nread ) );
1916 BOOL seek_fail = False;
1918 _smb_setlen(header,nread);
1920 #if USE_READ_PREDICTION
1921 if (!fsp->can_write)
1922 predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1923 #endif /* USE_READ_PREDICTION */
1925 if ((nread-predict) > 0) {
1926 if(seek_file(fsp,startpos + predict) == -1) {
1927 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1934 ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,
1935 (SMB_OFF_T)(nread-predict),header,4+predict,
1940 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1941 fsp->fsp_name,startpos,nread,ret));
1943 #else /* UNSAFE_READRAW */
1944 ret = read_file(fsp,header+4,startpos,nread);
1945 if (ret < mincount) ret = 0;
1947 _smb_setlen(header,ret);
1948 transfer_file(0,Client,0,header,4+ret,0);
1949 #endif /* UNSAFE_READRAW */
1951 DEBUG(5,("readbraw finished\n"));
1956 /****************************************************************************
1957 reply to a lockread (core+ protocol)
1958 ****************************************************************************/
1959 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1968 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1970 CHECK_FSP(fsp,conn);
1974 numtoread = SVAL(inbuf,smb_vwv1);
1975 startpos = IVAL(inbuf,smb_vwv2);
1977 outsize = set_message(outbuf,5,3,True);
1978 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1979 data = smb_buf(outbuf) + 3;
1981 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1982 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1984 * A blocking lock was requested. Package up
1985 * this smb into a queued request and push it
1986 * onto the blocking lock queue.
1988 if(push_blocking_lock_request(inbuf, length, -1, 0))
1991 return (ERROR(eclass,ecode));
1994 nread = read_file(fsp,data,startpos,numtoread);
1997 return(UNIXERROR(ERRDOS,ERRnoaccess));
2000 SSVAL(outbuf,smb_vwv0,nread);
2001 SSVAL(outbuf,smb_vwv5,nread+3);
2002 SSVAL(smb_buf(outbuf),1,nread);
2004 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2005 fsp->fnum, numtoread, nread ) );
2011 /****************************************************************************
2013 ****************************************************************************/
2014 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2021 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2023 CHECK_FSP(fsp,conn);
2027 numtoread = SVAL(inbuf,smb_vwv1);
2028 startpos = IVAL(inbuf,smb_vwv2);
2030 outsize = set_message(outbuf,5,3,True);
2031 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2032 data = smb_buf(outbuf) + 3;
2034 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2035 return(ERROR(ERRDOS,ERRlock));
2038 nread = read_file(fsp,data,startpos,numtoread);
2041 return(UNIXERROR(ERRDOS,ERRnoaccess));
2044 SSVAL(outbuf,smb_vwv0,nread);
2045 SSVAL(outbuf,smb_vwv5,nread+3);
2046 CVAL(smb_buf(outbuf),0) = 1;
2047 SSVAL(smb_buf(outbuf),1,nread);
2049 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2050 fsp->fnum, numtoread, nread ) );
2056 /****************************************************************************
2057 reply to a read and X
2058 ****************************************************************************/
2059 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2061 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2062 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2063 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2064 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2068 /* If it's an IPC, pass off the pipe handler. */
2070 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2072 CHECK_FSP(fsp,conn);
2076 set_message(outbuf,12,0,True);
2077 data = smb_buf(outbuf);
2079 #ifdef LARGE_SMB_OFF_T
2080 if(CVAL(inbuf,smb_wct) == 12) {
2082 * This is a large offset (64 bit) read.
2084 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2086 #endif /* LARGE_SMB_OFF_T */
2088 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2089 return(ERROR(ERRDOS,ERRlock));
2090 nread = read_file(fsp,data,startpos,smb_maxcnt);
2093 return(UNIXERROR(ERRDOS,ERRnoaccess));
2095 SSVAL(outbuf,smb_vwv5,nread);
2096 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2097 SSVAL(smb_buf(outbuf),-2,nread);
2099 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2100 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2102 return chain_reply(inbuf,outbuf,length,bufsize);
2105 /****************************************************************************
2106 reply to a writebraw (core+ or LANMAN1.0 protocol)
2107 ****************************************************************************/
2108 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2111 ssize_t total_written=0;
2112 size_t numtowrite=0;
2117 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2120 CHECK_FSP(fsp,conn);
2124 tcount = IVAL(inbuf,smb_vwv1);
2125 startpos = IVAL(inbuf,smb_vwv3);
2126 write_through = BITSETW(inbuf+smb_vwv7,0);
2128 /* We have to deal with slightly different formats depending
2129 on whether we are using the core+ or lanman1.0 protocol */
2130 if(Protocol <= PROTOCOL_COREPLUS) {
2131 numtowrite = SVAL(smb_buf(inbuf),-2);
2132 data = smb_buf(inbuf);
2134 numtowrite = SVAL(inbuf,smb_vwv10);
2135 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2138 /* force the error type */
2139 CVAL(inbuf,smb_com) = SMBwritec;
2140 CVAL(outbuf,smb_com) = SMBwritec;
2142 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2143 return(ERROR(ERRDOS,ERRlock));
2145 if (seek_file(fsp,startpos) == -1) {
2146 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2147 return(UNIXERROR(ERRDOS,ERRnoaccess));
2151 nwritten = write_file(fsp,data,numtowrite);
2153 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2154 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2156 if (nwritten < numtowrite)
2157 return(UNIXERROR(ERRHRD,ERRdiskfull));
2159 total_written = nwritten;
2161 /* Return a message to the redirector to tell it
2162 to send more bytes */
2163 CVAL(outbuf,smb_com) = SMBwritebraw;
2164 SSVALS(outbuf,smb_vwv0,-1);
2165 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2166 send_smb(Client,outbuf);
2168 /* Now read the raw data into the buffer and write it */
2169 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2170 exit_server("secondary writebraw failed");
2173 /* Even though this is not an smb message, smb_len
2174 returns the generic length of an smb message */
2175 numtowrite = smb_len(inbuf);
2177 if (tcount > nwritten+numtowrite) {
2178 DEBUG(3,("Client overestimated the write %d %d %d\n",
2179 tcount,nwritten,numtowrite));
2182 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2184 total_written += nwritten;
2186 /* Set up outbuf to return the correct return */
2187 outsize = set_message(outbuf,1,0,True);
2188 CVAL(outbuf,smb_com) = SMBwritec;
2189 SSVAL(outbuf,smb_vwv0,total_written);
2191 if (nwritten < (ssize_t)numtowrite) {
2192 CVAL(outbuf,smb_rcls) = ERRHRD;
2193 SSVAL(outbuf,smb_err,ERRdiskfull);
2196 if (lp_syncalways(SNUM(conn)) || write_through)
2197 sync_file(conn,fsp);
2199 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2200 fsp->fnum, (double)startpos, numtowrite, total_written));
2202 /* we won't return a status if write through is not selected - this
2203 follows what WfWg does */
2204 if (!write_through && total_written==tcount)
2210 /****************************************************************************
2211 reply to a writeunlock (core+)
2212 ****************************************************************************/
2213 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2215 ssize_t nwritten = -1;
2221 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2224 CHECK_FSP(fsp,conn);
2228 numtowrite = SVAL(inbuf,smb_vwv1);
2229 startpos = IVAL(inbuf,smb_vwv2);
2230 data = smb_buf(inbuf) + 3;
2232 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2233 return(ERROR(ERRDOS,ERRlock));
2235 if(seek_file(fsp,startpos) == -1)
2236 return(UNIXERROR(ERRDOS,ERRnoaccess));
2238 /* The special X/Open SMB protocol handling of
2239 zero length writes is *NOT* done for
2244 nwritten = write_file(fsp,data,numtowrite);
2246 if (lp_syncalways(SNUM(conn)))
2247 sync_file(conn,fsp);
2249 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2250 return(UNIXERROR(ERRDOS,ERRnoaccess));
2252 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2253 return(ERROR(eclass,ecode));
2255 outsize = set_message(outbuf,1,0,True);
2257 SSVAL(outbuf,smb_vwv0,nwritten);
2259 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2260 fsp->fnum, numtowrite, nwritten ) );
2265 /****************************************************************************
2267 ****************************************************************************/
2268 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2271 ssize_t nwritten = -1;
2274 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2277 CHECK_FSP(fsp,conn);
2281 numtowrite = SVAL(inbuf,smb_vwv1);
2282 startpos = IVAL(inbuf,smb_vwv2);
2283 data = smb_buf(inbuf) + 3;
2285 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2286 return(ERROR(ERRDOS,ERRlock));
2288 if(seek_file(fsp,startpos) == -1)
2289 return(UNIXERROR(ERRDOS,ERRnoaccess));
2291 /* X/Open SMB protocol says that if smb_vwv1 is
2292 zero then the file size should be extended or
2293 truncated to the size given in smb_vwv[2-3] */
2295 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2297 nwritten = write_file(fsp,data,numtowrite);
2299 if (lp_syncalways(SNUM(conn)))
2300 sync_file(conn,fsp);
2302 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2303 return(UNIXERROR(ERRDOS,ERRnoaccess));
2305 outsize = set_message(outbuf,1,0,True);
2307 SSVAL(outbuf,smb_vwv0,nwritten);
2309 if (nwritten < (ssize_t)numtowrite) {
2310 CVAL(outbuf,smb_rcls) = ERRHRD;
2311 SSVAL(outbuf,smb_err,ERRdiskfull);
2314 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2315 fsp->fnum, numtowrite, nwritten));
2321 /****************************************************************************
2322 reply to a write and X
2323 ****************************************************************************/
2324 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2326 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2327 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2328 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2329 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2330 ssize_t nwritten = -1;
2331 int smb_doff = SVAL(inbuf,smb_vwv11);
2334 /* If it's an IPC, pass off the pipe handler. */
2336 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2338 CHECK_FSP(fsp,conn);
2342 data = smb_base(inbuf) + smb_doff;
2344 #ifdef LARGE_SMB_OFF_T
2345 if(CVAL(inbuf,smb_wct) == 14) {
2347 * This is a large offset (64 bit) write.
2349 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2351 #endif /* LARGE_SMB_OFF_T */
2353 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2354 return(ERROR(ERRDOS,ERRlock));
2356 if(seek_file(fsp,startpos) == -1)
2357 return(UNIXERROR(ERRDOS,ERRnoaccess));
2359 /* X/Open SMB protocol says that, unlike SMBwrite
2360 if the length is zero then NO truncation is
2361 done, just a write of zero. To truncate a file,
2366 nwritten = write_file(fsp,data,numtowrite);
2368 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2369 return(UNIXERROR(ERRDOS,ERRnoaccess));
2371 set_message(outbuf,6,0,True);
2373 SSVAL(outbuf,smb_vwv2,nwritten);
2375 if (nwritten < (ssize_t)numtowrite) {
2376 CVAL(outbuf,smb_rcls) = ERRHRD;
2377 SSVAL(outbuf,smb_err,ERRdiskfull);
2380 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2381 fsp->fnum, numtowrite, nwritten));
2383 if (lp_syncalways(SNUM(conn)) || write_through)
2384 sync_file(conn,fsp);
2386 return chain_reply(inbuf,outbuf,length,bufsize);
2390 /****************************************************************************
2392 ****************************************************************************/
2393 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2399 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2401 CHECK_FSP(fsp,conn);
2404 mode = SVAL(inbuf,smb_vwv1) & 3;
2405 startpos = IVAL(inbuf,smb_vwv2);
2409 case 0: umode = SEEK_SET; break;
2410 case 1: umode = SEEK_CUR; break;
2411 case 2: umode = SEEK_END; break;
2413 umode = SEEK_SET; break;
2416 if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2417 return(UNIXERROR(ERRDOS,ERRnoaccess));
2421 outsize = set_message(outbuf,2,0,True);
2422 SIVALS(outbuf,smb_vwv0,res);
2424 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2425 fsp->fnum, (double)startpos, mode));
2430 /****************************************************************************
2432 ****************************************************************************/
2433 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2435 int outsize = set_message(outbuf,0,0,True);
2436 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2439 CHECK_FSP(fsp,conn);
2444 file_sync_all(conn);
2446 sync_file(conn,fsp);
2449 DEBUG(3,("flush\n"));
2454 /****************************************************************************
2456 ****************************************************************************/
2457 int reply_exit(connection_struct *conn,
2458 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2460 int outsize = set_message(outbuf,0,0,True);
2461 DEBUG(3,("exit\n"));
2467 /****************************************************************************
2468 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2469 ****************************************************************************/
2470 int reply_close(connection_struct *conn,
2471 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2475 int32 eclass = 0, err = 0;
2476 files_struct *fsp = NULL;
2478 outsize = set_message(outbuf,0,0,True);
2480 /* If it's an IPC, pass off to the pipe handler. */
2482 return reply_pipe_close(conn, inbuf,outbuf);
2485 fsp = file_fsp(inbuf,smb_vwv0);
2488 * We can only use CHECK_FSP if we know it's not a directory.
2491 if(!fsp || !fsp->open || (fsp->conn != conn))
2492 return(ERROR(ERRDOS,ERRbadfid));
2494 if(HAS_CACHED_ERROR(fsp)) {
2495 eclass = fsp->wbmpx_ptr->wr_errclass;
2496 err = fsp->wbmpx_ptr->wr_error;
2499 if(fsp->is_directory) {
2501 * Special case - close NT SMB directory
2504 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2505 close_directory(fsp);
2508 * Close ordinary file.
2512 * If there was a modify time outstanding,
2513 * try and set it here.
2515 if(fsp->pending_modtime)
2516 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2519 * Now take care of any time sent in the close.
2521 mtime = make_unix_date3(inbuf+smb_vwv1);
2523 /* try and set the date */
2524 set_filetime(conn, fsp->fsp_name,mtime);
2526 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2527 fsp->fd_ptr->fd, fsp->fnum,
2528 conn->num_files_open));
2530 close_file(fsp,True);
2533 /* We have a cached error */
2535 return(ERROR(eclass,err));
2541 /****************************************************************************
2542 reply to a writeclose (Core+ protocol)
2543 ****************************************************************************/
2544 int reply_writeclose(connection_struct *conn,
2545 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2548 ssize_t nwritten = -1;
2553 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2555 CHECK_FSP(fsp,conn);
2559 numtowrite = SVAL(inbuf,smb_vwv1);
2560 startpos = IVAL(inbuf,smb_vwv2);
2561 mtime = make_unix_date3(inbuf+smb_vwv4);
2562 data = smb_buf(inbuf) + 1;
2564 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2565 return(ERROR(ERRDOS,ERRlock));
2567 if(seek_file(fsp,startpos) == -1)
2568 return(UNIXERROR(ERRDOS,ERRnoaccess));
2570 nwritten = write_file(fsp,data,numtowrite);
2572 set_filetime(conn, fsp->fsp_name,mtime);
2574 close_file(fsp,True);
2576 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2577 fsp->fnum, numtowrite, nwritten,
2578 conn->num_files_open));
2581 return(UNIXERROR(ERRDOS,ERRnoaccess));
2583 outsize = set_message(outbuf,1,0,True);
2585 SSVAL(outbuf,smb_vwv0,nwritten);
2590 /****************************************************************************
2592 ****************************************************************************/
2593 int reply_lock(connection_struct *conn,
2594 char *inbuf,char *outbuf, int length, int dum_buffsize)
2596 int outsize = set_message(outbuf,0,0,True);
2597 SMB_OFF_T count,offset;
2600 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2602 CHECK_FSP(fsp,conn);
2605 count = IVAL(inbuf,smb_vwv1);
2606 offset = IVAL(inbuf,smb_vwv3);
2608 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2609 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2611 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2612 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2614 * A blocking lock was requested. Package up
2615 * this smb into a queued request and push it
2616 * onto the blocking lock queue.
2618 if(push_blocking_lock_request(inbuf, length, -1, 0))
2621 return (ERROR(eclass,ecode));
2628 /****************************************************************************
2630 ****************************************************************************/
2631 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2633 int outsize = set_message(outbuf,0,0,True);
2634 SMB_OFF_T count,offset;
2637 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2639 CHECK_FSP(fsp,conn);
2642 count = IVAL(inbuf,smb_vwv1);
2643 offset = IVAL(inbuf,smb_vwv3);
2645 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2646 return (ERROR(eclass,ecode));
2648 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2649 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2655 /****************************************************************************
2657 ****************************************************************************/
2658 int reply_tdis(connection_struct *conn,
2659 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2661 int outsize = set_message(outbuf,0,0,True);
2664 vuid = SVAL(inbuf,smb_uid);
2667 DEBUG(4,("Invalid connection in tdis\n"));
2668 return(ERROR(ERRSRV,ERRinvnid));
2673 close_cnum(conn,vuid);
2680 /****************************************************************************
2682 ****************************************************************************/
2683 int reply_echo(connection_struct *conn,
2684 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2686 int smb_reverb = SVAL(inbuf,smb_vwv0);
2688 int data_len = smb_buflen(inbuf);
2689 int outsize = set_message(outbuf,1,data_len,True);
2691 /* copy any incoming data back out */
2693 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2695 if (smb_reverb > 100) {
2696 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2700 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2701 SSVAL(outbuf,smb_vwv0,seq_num);
2703 smb_setlen(outbuf,outsize - 4);
2705 send_smb(Client,outbuf);
2708 DEBUG(3,("echo %d times\n", smb_reverb));
2714 /****************************************************************************
2715 reply to a printopen
2716 ****************************************************************************/
2717 int reply_printopen(connection_struct *conn,
2718 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2725 *fname = *fname2 = 0;
2727 if (!CAN_PRINT(conn))
2728 return(ERROR(ERRDOS,ERRnoaccess));
2733 pstrcpy(s,smb_buf(inbuf)+1);
2736 if (!(isalnum((int)*p) || strchr("._-",*p)))
2741 if (strlen(s) > 10) s[10] = 0;
2743 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2748 return(ERROR(ERRSRV,ERRnofids));
2750 pstrcpy(fname2,(char *)mktemp(fname));
2752 if (!check_name(fname2,conn)) {
2754 return(ERROR(ERRDOS,ERRnoaccess));
2757 /* Open for exclusive use, write only. */
2758 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2759 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2763 return(UNIXERROR(ERRDOS,ERRnoaccess));
2766 /* force it to be a print file */
2767 fsp->print_file = True;
2769 outsize = set_message(outbuf,1,0,True);
2770 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2772 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2773 fname2, fsp->fd_ptr->fd, fsp->fnum));
2779 /****************************************************************************
2780 reply to a printclose
2781 ****************************************************************************/
2782 int reply_printclose(connection_struct *conn,
2783 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2785 int outsize = set_message(outbuf,0,0,True);
2786 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2788 CHECK_FSP(fsp,conn);
2791 if (!CAN_PRINT(conn))
2792 return(ERROR(ERRDOS,ERRnoaccess));
2794 DEBUG(3,("printclose fd=%d fnum=%d\n",
2795 fsp->fd_ptr->fd,fsp->fnum));
2797 close_file(fsp,True);
2803 /****************************************************************************
2804 reply to a printqueue
2805 ****************************************************************************/
2806 int reply_printqueue(connection_struct *conn,
2807 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2809 int outsize = set_message(outbuf,2,3,True);
2810 int max_count = SVAL(inbuf,smb_vwv0);
2811 int start_index = SVAL(inbuf,smb_vwv1);
2813 /* we used to allow the client to get the cnum wrong, but that
2814 is really quite gross and only worked when there was only
2815 one printer - I think we should now only accept it if they
2816 get it right (tridge) */
2817 if (!CAN_PRINT(conn))
2818 return(ERROR(ERRDOS,ERRnoaccess));
2820 SSVAL(outbuf,smb_vwv0,0);
2821 SSVAL(outbuf,smb_vwv1,0);
2822 CVAL(smb_buf(outbuf),0) = 1;
2823 SSVAL(smb_buf(outbuf),1,0);
2825 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2826 start_index, max_count));
2829 print_queue_struct *queue = NULL;
2830 char *p = smb_buf(outbuf) + 3;
2831 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2832 int num_to_get = ABS(max_count);
2833 int first = (max_count>0?start_index:start_index+max_count+1);
2839 num_to_get = MIN(num_to_get,count-first);
2842 for (i=first;i<first+num_to_get;i++) {
2843 put_dos_date2(p,0,queue[i].time);
2844 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2845 SSVAL(p,5,printjob_encode(SNUM(conn),
2847 SIVAL(p,7,queue[i].size);
2849 StrnCpy(p+12,queue[i].user,16);
2854 outsize = set_message(outbuf,2,28*count+3,False);
2855 SSVAL(outbuf,smb_vwv0,count);
2856 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2857 CVAL(smb_buf(outbuf),0) = 1;
2858 SSVAL(smb_buf(outbuf),1,28*count);
2861 if (queue) free(queue);
2863 DEBUG(3,("%d entries returned in queue\n",count));
2870 /****************************************************************************
2871 reply to a printwrite
2872 ****************************************************************************/
2873 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2876 int outsize = set_message(outbuf,0,0,True);
2878 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2880 if (!CAN_PRINT(conn))
2881 return(ERROR(ERRDOS,ERRnoaccess));
2883 CHECK_FSP(fsp,conn);
2887 numtowrite = SVAL(smb_buf(inbuf),1);
2888 data = smb_buf(inbuf) + 3;
2890 if (write_file(fsp,data,numtowrite) != numtowrite)
2891 return(UNIXERROR(ERRDOS,ERRnoaccess));
2893 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2899 /****************************************************************************
2901 ****************************************************************************/
2902 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2905 int outsize,ret= -1;
2906 BOOL bad_path = False;
2908 pstrcpy(directory,smb_buf(inbuf) + 1);
2909 unix_convert(directory,conn,0,&bad_path,NULL);
2911 if (check_name(directory, conn))
2912 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2916 if((errno == ENOENT) && bad_path)
2918 unix_ERR_class = ERRDOS;
2919 unix_ERR_code = ERRbadpath;
2921 return(UNIXERROR(ERRDOS,ERRnoaccess));
2924 outsize = set_message(outbuf,0,0,True);
2926 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2931 /****************************************************************************
2932 Static function used by reply_rmdir to delete an entire directory
2934 ****************************************************************************/
2935 static BOOL recursive_rmdir(char *directory)
2939 void *dirptr = OpenDir(NULL, directory, False);
2944 while((dname = ReadDirName(dirptr)))
2949 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2952 /* Construct the full name. */
2953 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2959 pstrcpy(fullname, directory);
2960 pstrcat(fullname, "/");
2961 pstrcat(fullname, dname);
2963 if(dos_lstat(fullname, &st) != 0)
2969 if(st.st_mode & S_IFDIR)
2971 if(recursive_rmdir(fullname)!=0)
2976 if(dos_rmdir(fullname) != 0)
2982 else if(dos_unlink(fullname) != 0)
2992 /****************************************************************************
2994 ****************************************************************************/
2995 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3000 BOOL bad_path = False;
3002 pstrcpy(directory,smb_buf(inbuf) + 1);
3003 unix_convert(directory,conn, NULL,&bad_path,NULL);
3005 if (check_name(directory,conn))
3008 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3009 ok = (dos_rmdir(directory) == 0);
3010 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
3012 /* Check to see if the only thing in this directory are
3013 vetoed files/directories. If so then delete them and
3014 retry. If we fail to delete any of them (and we *don't*
3015 do a recursive delete) then fail the rmdir. */
3016 BOOL all_veto_files = True;
3018 void *dirptr = OpenDir(conn, directory, False);
3022 int dirpos = TellDir(dirptr);
3023 while ((dname = ReadDirName(dirptr)))
3025 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3027 if(!IS_VETO_PATH(conn, dname))
3029 all_veto_files = False;
3035 SeekDir(dirptr,dirpos);
3036 while ((dname = ReadDirName(dirptr)))
3041 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3044 /* Construct the full name. */
3045 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3050 pstrcpy(fullname, directory);
3051 pstrcat(fullname, "/");
3052 pstrcat(fullname, dname);
3054 if(dos_lstat(fullname, &st) != 0)
3056 if(st.st_mode & S_IFDIR)
3058 if(lp_recursive_veto_delete(SNUM(conn)))
3060 if(recursive_rmdir(fullname) != 0)
3063 if(dos_rmdir(fullname) != 0)
3066 else if(dos_unlink(fullname) != 0)
3070 /* Retry the rmdir */
3071 ok = (dos_rmdir(directory) == 0);
3081 DEBUG(3,("couldn't remove directory %s : %s\n",
3082 directory,strerror(errno)));
3087 if((errno == ENOENT) && bad_path)
3089 unix_ERR_class = ERRDOS;
3090 unix_ERR_code = ERRbadpath;
3092 return(UNIXERROR(ERRDOS,ERRbadpath));
3095 outsize = set_message(outbuf,0,0,True);
3097 DEBUG( 3, ( "rmdir %s\n", directory ) );
3103 /*******************************************************************
3104 resolve wildcards in a filename rename
3105 ********************************************************************/
3106 static BOOL resolve_wildcards(char *name1,char *name2)
3108 fstring root1,root2;
3112 name1 = strrchr(name1,'/');
3113 name2 = strrchr(name2,'/');
3115 if (!name1 || !name2) return(False);
3117 fstrcpy(root1,name1);
3118 fstrcpy(root2,name2);
3119 p = strrchr(root1,'.');
3126 p = strrchr(root2,'.');
3158 pstrcpy(name2,root2);
3161 pstrcat(name2,ext2);
3167 /*******************************************************************
3168 check if a user is allowed to rename a file
3169 ********************************************************************/
3170 static BOOL can_rename(char *fname,connection_struct *conn)
3172 SMB_STRUCT_STAT sbuf;
3174 if (!CAN_WRITE(conn)) return(False);
3176 if (dos_lstat(fname,&sbuf) != 0) return(False);
3177 if (!check_file_sharing(conn,fname,True)) return(False);
3182 /****************************************************************************
3183 The guts of the rename command, split out so it may be called by the NT SMB
3185 ****************************************************************************/
3186 int rename_internals(connection_struct *conn,
3187 char *inbuf, char *outbuf, char *name,
3188 char *newname, BOOL replace_if_exists)
3192 pstring newname_last_component;
3195 BOOL bad_path1 = False;
3196 BOOL bad_path2 = False;
3198 int error = ERRnoaccess;
3201 *directory = *mask = 0;
3203 unix_convert(name,conn,0,&bad_path1,NULL);
3204 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3207 * Split the old name into directory and last component
3208 * strings. Note that unix_convert may have stripped off a
3209 * leading ./ from both name and newname if the rename is
3210 * at the root of the share. We need to make sure either both
3211 * name and newname contain a / character or neither of them do
3212 * as this is checked in resolve_wildcards().
3215 p = strrchr(name,'/');
3217 pstrcpy(directory,".");
3221 pstrcpy(directory,name);
3223 *p = '/'; /* Replace needed for exceptional test below. */
3226 if (is_mangled(mask))
3227 check_mangled_cache( mask );
3229 has_wild = strchr(mask,'*') || strchr(mask,'?');
3233 * No wildcards - just process the one file.
3235 BOOL is_short_name = is_8_3(name, True);
3237 /* Add a terminating '/' to the directory name. */
3238 pstrcat(directory,"/");
3239 pstrcat(directory,mask);
3241 /* Ensure newname contains a '/' also */
3242 if(strrchr(newname,'/') == 0) {
3245 pstrcpy(tmpstr, "./");
3246 pstrcat(tmpstr, newname);
3247 pstrcpy(newname, tmpstr);
3250 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",
3251 case_sensitive, case_preserve, short_case_preserve, directory,
3252 newname, newname_last_component, is_short_name));
3255 * Check for special case with case preserving and not
3256 * case sensitive, if directory and newname are identical,
3257 * and the old last component differs from the original
3258 * last component only by case, then we should allow
3259 * the rename (user is trying to change the case of the
3262 if((case_sensitive == False) &&
3263 (((case_preserve == True) &&
3264 (is_short_name == False)) ||
3265 ((short_case_preserve == True) &&
3266 (is_short_name == True))) &&
3267 strcsequal(directory, newname)) {
3268 pstring newname_modified_last_component;
3271 * Get the last component of the modified name.
3272 * Note that we guarantee that newname contains a '/'
3275 p = strrchr(newname,'/');
3276 pstrcpy(newname_modified_last_component,p+1);
3278 if(strcsequal(newname_modified_last_component,
3279 newname_last_component) == False) {
3281 * Replace the modified last component with
3284 pstrcpy(p+1, newname_last_component);
3288 if(replace_if_exists) {
3290 * NT SMB specific flag - rename can overwrite
3291 * file with the same name so don't check for
3294 if(resolve_wildcards(directory,newname) &&
3295 can_rename(directory,conn) &&
3296 !dos_rename(directory,newname))
3299 if (resolve_wildcards(directory,newname) &&
3300 can_rename(directory,conn) &&
3301 !dos_file_exist(newname,NULL) &&
3302 !dos_rename(directory,newname))
3306 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3307 directory,newname));
3309 if (!count) exists = dos_file_exist(directory,NULL);
3310 if (!count && exists && dos_file_exist(newname,NULL)) {
3316 * Wildcards - process each file that matches.
3318 void *dirptr = NULL;
3322 if (check_name(directory,conn))
3323 dirptr = OpenDir(conn, directory, True);
3328 if (strequal(mask,"????????.???"))
3331 while ((dname = ReadDirName(dirptr))) {
3333 pstrcpy(fname,dname);
3335 if(!mask_match(fname, mask, case_sensitive, False))
3338 error = ERRnoaccess;
3339 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3340 if (!can_rename(fname,conn)) {
3341 DEBUG(6,("rename %s refused\n", fname));
3344 pstrcpy(destname,newname);
3346 if (!resolve_wildcards(fname,destname)) {
3347 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3351 if (!replace_if_exists && dos_file_exist(destname,NULL)) {
3352 DEBUG(6,("dos_file_exist %s\n", destname));
3357 if (!dos_rename(fname,destname))
3359 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3367 return(ERROR(ERRDOS,error));
3369 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3370 unix_ERR_class = ERRDOS;
3371 unix_ERR_code = ERRbadpath;
3373 return(UNIXERROR(ERRDOS,error));
3380 /****************************************************************************
3382 ****************************************************************************/
3384 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3390 pstrcpy(name,smb_buf(inbuf) + 1);
3391 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3393 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3395 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3397 outsize = set_message(outbuf,0,0,True);
3402 /*******************************************************************
3403 copy a file as part of a reply_copy
3404 ******************************************************************/
3406 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3407 int count,BOOL target_is_directory)
3412 files_struct *fsp1,*fsp2;
3415 pstrcpy(dest,dest1);
3416 if (target_is_directory) {
3417 char *p = strrchr(src,'/');
3426 if (!dos_file_exist(src,&st))
3433 open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3434 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3441 if (!target_is_directory && count)
3446 close_file(fsp1,False);
3449 open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3450 ofun,st.st_mode,0,&Access,&action);
3453 close_file(fsp1,False);
3458 if ((ofun&3) == 1) {
3459 if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3460 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3463 * Stop the copy from occurring.
3471 ret = transfer_file(fsp1->fd_ptr->fd,
3472 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3474 close_file(fsp1,False);
3475 close_file(fsp2,False);
3477 return(ret == st.st_size);
3482 /****************************************************************************
3483 reply to a file copy.
3484 ****************************************************************************/
3485 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3490 pstring mask,newname;
3493 int error = ERRnoaccess;
3496 int tid2 = SVAL(inbuf,smb_vwv0);
3497 int ofun = SVAL(inbuf,smb_vwv1);
3498 int flags = SVAL(inbuf,smb_vwv2);
3499 BOOL target_is_directory=False;
3500 BOOL bad_path1 = False;
3501 BOOL bad_path2 = False;
3503 *directory = *mask = 0;
3505 pstrcpy(name,smb_buf(inbuf));
3506 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3508 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3510 if (tid2 != conn->cnum) {
3511 /* can't currently handle inter share copies XXXX */
3512 DEBUG(3,("Rejecting inter-share copy\n"));
3513 return(ERROR(ERRSRV,ERRinvdevice));
3516 unix_convert(name,conn,0,&bad_path1,NULL);
3517 unix_convert(newname,conn,0,&bad_path2,NULL);
3519 target_is_directory = dos_directory_exist(newname,NULL);
3521 if ((flags&1) && target_is_directory) {
3522 return(ERROR(ERRDOS,ERRbadfile));
3525 if ((flags&2) && !target_is_directory) {
3526 return(ERROR(ERRDOS,ERRbadpath));
3529 if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
3530 /* wants a tree copy! XXXX */
3531 DEBUG(3,("Rejecting tree copy\n"));
3532 return(ERROR(ERRSRV,ERRerror));
3535 p = strrchr(name,'/');
3537 pstrcpy(directory,"./");
3541 pstrcpy(directory,name);
3545 if (is_mangled(mask))
3546 check_mangled_cache( mask );
3548 has_wild = strchr(mask,'*') || strchr(mask,'?');
3551 pstrcat(directory,"/");
3552 pstrcat(directory,mask);
3553 if (resolve_wildcards(directory,newname) &&
3554 copy_file(directory,newname,conn,ofun,
3555 count,target_is_directory)) count++;
3556 if (!count) exists = dos_file_exist(directory,NULL);
3558 void *dirptr = NULL;
3562 if (check_name(directory,conn))
3563 dirptr = OpenDir(conn, directory, True);
3569 if (strequal(mask,"????????.???"))
3572 while ((dname = ReadDirName(dirptr)))
3575 pstrcpy(fname,dname);
3577 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3579 error = ERRnoaccess;
3580 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3581 pstrcpy(destname,newname);
3582 if (resolve_wildcards(fname,destname) &&
3583 copy_file(directory,newname,conn,ofun,
3584 count,target_is_directory)) count++;
3585 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3593 return(ERROR(ERRDOS,error));
3596 if((errno == ENOENT) && (bad_path1 || bad_path2))
3598 unix_ERR_class = ERRDOS;
3599 unix_ERR_code = ERRbadpath;
3601 return(UNIXERROR(ERRDOS,error));
3605 outsize = set_message(outbuf,1,0,True);
3606 SSVAL(outbuf,smb_vwv0,count);
3611 /****************************************************************************
3613 ****************************************************************************/
3614 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3622 if (!CAN_SETDIR(snum))
3623 return(ERROR(ERRDOS,ERRnoaccess));
3625 pstrcpy(newdir,smb_buf(inbuf) + 1);
3628 if (strlen(newdir) == 0) {
3631 ok = dos_directory_exist(newdir,NULL);
3633 string_set(&conn->connectpath,newdir);
3638 return(ERROR(ERRDOS,ERRbadpath));
3640 outsize = set_message(outbuf,0,0,True);
3641 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3643 DEBUG(3,("setdir %s\n", newdir));
3648 /****************************************************************************
3649 reply to a lockingX request
3650 ****************************************************************************/
3651 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3653 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3654 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3656 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3658 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3659 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3660 SMB_OFF_T count = 0, offset = 0;
3661 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3664 uint32 ecode=0, dummy2;
3665 int eclass=0, dummy1;
3666 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3667 CHECK_FSP(fsp,conn);
3670 data = smb_buf(inbuf);
3672 /* Check if this is an oplock break on a file
3673 we have granted an oplock on.
3675 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3678 SMB_DEV_T dev = fsp->fd_ptr->dev;
3679 SMB_INO_T inode = fsp->fd_ptr->inode;
3681 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3684 * Make sure we have granted an oplock on this file.
3686 if(!fsp->granted_oplock)
3688 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3689 no oplock granted on this file.\n", fsp->fnum));
3690 return ERROR(ERRDOS,ERRlock);
3693 /* Remove the oplock flag from the sharemode. */
3694 lock_share_entry(fsp->conn, dev, inode, &token);
3695 if(remove_share_oplock(token, fsp)==False) {
3697 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3698 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3700 unlock_share_entry(fsp->conn, dev, inode, token);
3702 unlock_share_entry(fsp->conn, dev, inode, token);
3704 /* Clear the granted flag and return. */
3705 fsp->granted_oplock = False;
3708 /* if this is a pure oplock break request then don't send a reply */
3709 if (num_locks == 0 && num_ulocks == 0)
3711 /* Sanity check - ensure a pure oplock break is not a
3713 if(CVAL(inbuf,smb_vwv0) != 0xff)
3714 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3715 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3720 /* Data now points at the beginning of the list
3721 of smb_unlkrng structs */
3722 for(i = 0; i < (int)num_ulocks; i++) {
3723 if(!large_file_format) {
3724 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3725 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3727 #ifdef LARGE_SMB_OFF_T
3729 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3730 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3731 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3732 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3734 #endif /* LARGE_SMB_OFF_T */
3736 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3737 (double)offset, (double)count, fsp->fsp_name ));
3739 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3740 return ERROR(eclass,ecode);
3743 /* Setup the timeout in seconds. */
3744 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3746 /* Now do any requested locks */
3747 data += ((large_file_format ? 20 : 10)*num_ulocks);
3749 /* Data now points at the beginning of the list
3750 of smb_lkrng structs */
3752 for(i = 0; i < (int)num_locks; i++) {
3753 if(!large_file_format) {
3754 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3755 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3757 #ifdef LARGE_SMB_OFF_T
3759 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3760 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3761 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3762 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3764 #endif /* LARGE_SMB_OFF_T */
3766 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3767 (double)offset, (double)count, fsp->fsp_name ));
3769 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3771 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3773 * A blocking lock was requested. Package up
3774 * this smb into a queued request and push it
3775 * onto the blocking lock queue.
3777 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3784 /* If any of the above locks failed, then we must unlock
3785 all of the previous locks (X/Open spec). */
3786 if(i != num_locks && num_locks != 0) {
3787 for(; i >= 0; i--) {
3788 if(!large_file_format) {
3789 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3790 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3792 #ifdef LARGE_SMB_OFF_T
3794 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3795 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3796 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3797 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3799 #endif /* LARGE_SMB_OFF_T */
3801 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3803 return ERROR(eclass,ecode);
3806 set_message(outbuf,2,0,True);
3808 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3809 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3811 return chain_reply(inbuf,outbuf,length,bufsize);
3815 /****************************************************************************
3816 reply to a SMBreadbmpx (read block multiplex) request
3817 ****************************************************************************/
3818 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3829 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3831 /* this function doesn't seem to work - disable by default */
3833 return(ERROR(ERRSRV,ERRuseSTD));
3835 outsize = set_message(outbuf,8,0,True);
3837 CHECK_FSP(fsp,conn);
3841 startpos = IVAL(inbuf,smb_vwv1);
3842 maxcount = SVAL(inbuf,smb_vwv3);
3844 data = smb_buf(outbuf);
3845 pad = ((long)data)%4;
3846 if (pad) pad = 4 - pad;
3849 max_per_packet = bufsize-(outsize+pad);
3853 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3854 return(ERROR(ERRDOS,ERRlock));
3858 size_t N = MIN(max_per_packet,tcount-total_read);
3860 nread = read_file(fsp,data,startpos,N);
3862 if (nread <= 0) nread = 0;
3864 if (nread < (ssize_t)N)
3865 tcount = total_read + nread;
3867 set_message(outbuf,8,nread,False);
3868 SIVAL(outbuf,smb_vwv0,startpos);
3869 SSVAL(outbuf,smb_vwv2,tcount);
3870 SSVAL(outbuf,smb_vwv6,nread);
3871 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3873 send_smb(Client,outbuf);
3875 total_read += nread;
3878 while (total_read < (ssize_t)tcount);
3883 /****************************************************************************
3884 reply to a SMBwritebmpx (write block multiplex primary) request
3885 ****************************************************************************/
3886 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3889 ssize_t nwritten = -1;
3896 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3898 CHECK_FSP(fsp,conn);
3902 tcount = SVAL(inbuf,smb_vwv1);
3903 startpos = IVAL(inbuf,smb_vwv3);
3904 write_through = BITSETW(inbuf+smb_vwv7,0);
3905 numtowrite = SVAL(inbuf,smb_vwv10);
3906 smb_doff = SVAL(inbuf,smb_vwv11);
3908 data = smb_base(inbuf) + smb_doff;
3910 /* If this fails we need to send an SMBwriteC response,
3911 not an SMBwritebmpx - set this up now so we don't forget */
3912 CVAL(outbuf,smb_com) = SMBwritec;
3914 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3915 return(ERROR(ERRDOS,ERRlock));
3917 if(seek_file(fsp,startpos) == -1)
3918 return(UNIXERROR(ERRDOS,ERRnoaccess));
3920 nwritten = write_file(fsp,data,numtowrite);
3922 if(lp_syncalways(SNUM(conn)) || write_through)
3923 sync_file(conn,fsp);
3925 if(nwritten < (ssize_t)numtowrite)
3926 return(UNIXERROR(ERRHRD,ERRdiskfull));
3928 /* If the maximum to be written to this file
3929 is greater than what we just wrote then set
3930 up a secondary struct to be attached to this
3931 fd, we will use this to cache error messages etc. */
3932 if((ssize_t)tcount > nwritten)
3934 write_bmpx_struct *wbms;
3935 if(fsp->wbmpx_ptr != NULL)
3936 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3938 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3941 DEBUG(0,("Out of memory in reply_readmpx\n"));
3942 return(ERROR(ERRSRV,ERRnoresource));
3944 wbms->wr_mode = write_through;
3945 wbms->wr_discard = False; /* No errors yet */
3946 wbms->wr_total_written = nwritten;
3947 wbms->wr_errclass = 0;
3949 fsp->wbmpx_ptr = wbms;
3952 /* We are returning successfully, set the message type back to
3954 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3956 outsize = set_message(outbuf,1,0,True);
3958 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3960 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3961 fsp->fnum, numtowrite, nwritten ) );
3963 if (write_through && tcount==nwritten) {
3964 /* we need to send both a primary and a secondary response */
3965 smb_setlen(outbuf,outsize - 4);
3966 send_smb(Client,outbuf);
3968 /* now the secondary */
3969 outsize = set_message(outbuf,1,0,True);
3970 CVAL(outbuf,smb_com) = SMBwritec;
3971 SSVAL(outbuf,smb_vwv0,nwritten);
3978 /****************************************************************************
3979 reply to a SMBwritebs (write block multiplex secondary) request
3980 ****************************************************************************/
3981 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3984 ssize_t nwritten = -1;
3991 write_bmpx_struct *wbms;
3992 BOOL send_response = False;
3993 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3995 CHECK_FSP(fsp,conn);
3998 tcount = SVAL(inbuf,smb_vwv1);
3999 startpos = IVAL(inbuf,smb_vwv2);
4000 numtowrite = SVAL(inbuf,smb_vwv6);
4001 smb_doff = SVAL(inbuf,smb_vwv7);
4003 data = smb_base(inbuf) + smb_doff;
4005 /* We need to send an SMBwriteC response, not an SMBwritebs */
4006 CVAL(outbuf,smb_com) = SMBwritec;
4008 /* This fd should have an auxiliary struct attached,
4009 check that it does */
4010 wbms = fsp->wbmpx_ptr;
4011 if(!wbms) return(-1);
4013 /* If write through is set we can return errors, else we must
4015 write_through = wbms->wr_mode;
4017 /* Check for an earlier error */
4018 if(wbms->wr_discard)
4019 return -1; /* Just discard the packet */
4021 if(seek_file(fsp,startpos) == -1)
4025 /* We are returning an error - we can delete the aux struct */
4026 if (wbms) free((char *)wbms);
4027 fsp->wbmpx_ptr = NULL;
4028 return(UNIXERROR(ERRDOS,ERRnoaccess));
4030 return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
4033 nwritten = write_file(fsp,data,numtowrite);
4035 if(lp_syncalways(SNUM(conn)) || write_through)
4036 sync_file(conn,fsp);
4038 if (nwritten < (ssize_t)numtowrite)
4042 /* We are returning an error - we can delete the aux struct */
4043 if (wbms) free((char *)wbms);
4044 fsp->wbmpx_ptr = NULL;
4045 return(ERROR(ERRHRD,ERRdiskfull));
4047 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4050 /* Increment the total written, if this matches tcount
4051 we can discard the auxiliary struct (hurrah !) and return a writeC */
4052 wbms->wr_total_written += nwritten;
4053 if(wbms->wr_total_written >= tcount)
4057 outsize = set_message(outbuf,1,0,True);
4058 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4059 send_response = True;
4063 fsp->wbmpx_ptr = NULL;
4073 /****************************************************************************
4074 reply to a SMBsetattrE
4075 ****************************************************************************/
4076 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4078 struct utimbuf unix_times;
4080 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4082 outsize = set_message(outbuf,0,0,True);
4084 CHECK_FSP(fsp,conn);
4087 /* Convert the DOS times into unix times. Ignore create
4088 time as UNIX can't set this.
4090 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4091 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4094 * Patch from Ray Frush <frush@engr.colostate.edu>
4095 * Sometimes times are sent as zero - ignore them.
4098 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4100 /* Ignore request */
4103 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4104 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4108 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4110 /* set modify time = to access time if modify time was 0 */
4111 unix_times.modtime = unix_times.actime;
4114 /* Set the date on this file */
4115 if(file_utime(conn, fsp->fsp_name, &unix_times))
4116 return(ERROR(ERRDOS,ERRnoaccess));
4118 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4119 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4125 /****************************************************************************
4126 reply to a SMBgetattrE
4127 ****************************************************************************/
4128 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4130 SMB_STRUCT_STAT sbuf;
4133 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4135 outsize = set_message(outbuf,11,0,True);
4137 CHECK_FSP(fsp,conn);
4140 /* Do an fstat on this file */
4141 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4142 return(UNIXERROR(ERRDOS,ERRnoaccess));
4144 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4146 /* Convert the times into dos times. Set create
4147 date to be last modify date as UNIX doesn't save
4149 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4150 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4151 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4154 SIVAL(outbuf,smb_vwv6,0);
4155 SIVAL(outbuf,smb_vwv8,0);
4159 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4160 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4162 SSVAL(outbuf,smb_vwv10, mode);
4164 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));