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 memset(nt_username, 0, sizeof(nt_username));
79 slprintf(nt_username, sizeof(nt_username)-1, "%s\\%s",
84 fstrcpy(nt_username, user);
87 if (lookupsmbpwntnam(nt_username, &gmep))
89 fstrcpy(user, gmep.unix_name);
93 * Pass the user through the unix -> unix user mapping
97 (void)map_username(user);
100 * Do any UNIX username case mangling.
102 (void)Get_Pwnam( user, True);
105 /****************************************************************************
106 reply to an special message
107 ****************************************************************************/
108 int reply_special(char *inbuf,char *outbuf)
111 int msg_type = CVAL(inbuf,0);
112 int msg_flags = CVAL(inbuf,1);
114 extern fstring remote_machine;
115 extern fstring local_machine;
121 bzero(outbuf,smb_size);
123 smb_setlen(outbuf,0);
126 case 0x81: /* session request */
127 CVAL(outbuf,0) = 0x82;
129 if (name_len(inbuf+4) > 50 ||
130 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
131 DEBUG(0,("Invalid name length in session request\n"));
134 name_extract(inbuf,4,name1);
135 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
136 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
139 fstrcpy(remote_machine,name2);
140 remote_machine[15] = 0;
141 trim_string(remote_machine," "," ");
142 strlower(remote_machine);
144 fstrcpy(local_machine,name1);
145 len = strlen(local_machine);
147 name_type = local_machine[15];
148 local_machine[15] = 0;
150 trim_string(local_machine," "," ");
151 strlower(local_machine);
153 if (name_type == 'R') {
154 /* We are being asked for a pathworks session ---
156 CVAL(outbuf, 0) = 0x83;
160 add_session_user(remote_machine);
162 reload_services(True);
166 claim_connection(NULL,"STATUS.",MAXSTATUS,True);
171 case 0x89: /* session keepalive request
172 (some old clients produce this?) */
173 CVAL(outbuf,0) = 0x85;
177 case 0x82: /* positive session response */
178 case 0x83: /* negative session response */
179 case 0x84: /* retarget session response */
180 DEBUG(0,("Unexpected session response\n"));
183 case 0x85: /* session keepalive */
188 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
189 msg_type, msg_flags));
195 /*******************************************************************
196 work out what error to give to a failed connection
197 ********************************************************************/
198 static int connection_error(char *inbuf,char *outbuf,int ecode)
200 if (ecode == ERRnoipc) {
201 return(ERROR(ERRDOS,ERRnoipc));
204 return(ERROR(ERRSRV,ecode));
209 /****************************************************************************
210 parse a share descriptor string
211 ****************************************************************************/
212 static void parse_connect(char *p,char *service,char *user,
213 char *password,int *pwlen,char *dev)
217 DEBUG(4,("parsing connect string %s\n",p));
219 p2 = strrchr(p,'\\');
223 fstrcpy(service,p2+1);
228 *pwlen = strlen(password);
235 p = strchr(service,'%');
246 /****************************************************************************
248 ****************************************************************************/
249 int reply_tcon(connection_struct *conn,
250 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
257 uint16 vuid = SVAL(inbuf,smb_uid);
261 *service = *user = *password = *dev = 0;
263 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
265 map_nt_and_unix_username(global_myworkgroup, user);
267 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
270 return(connection_error(inbuf,outbuf,ecode));
273 outsize = set_message(outbuf,2,0,True);
274 SSVAL(outbuf,smb_vwv0,max_recv);
275 SSVAL(outbuf,smb_vwv1,conn->cnum);
276 SSVAL(outbuf,smb_tid,conn->cnum);
278 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
279 service, user, conn->cnum));
285 /****************************************************************************
286 reply to a tcon and X
287 ****************************************************************************/
288 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
295 uint16 vuid = SVAL(inbuf,smb_uid);
296 int passlen = SVAL(inbuf,smb_vwv3);
300 *service = *user = *password = *devicename = 0;
302 /* we might have to close an old one */
303 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
304 close_cnum(conn,vuid);
307 if (passlen > MAX_PASS_LEN) {
308 overflow_attack(passlen);
311 memcpy(password,smb_buf(inbuf),passlen);
313 path = smb_buf(inbuf) + passlen;
316 if (strequal(password," "))
318 passlen = strlen(password);
321 fstrcpy(service,path+2);
322 p = strchr(service,'\\');
324 return(ERROR(ERRSRV,ERRinvnetname));
326 fstrcpy(service,p+1);
327 p = strchr(service,'%');
332 StrnCpy(devicename,path + strlen(path) + 1,6);
333 DEBUG(4,("Got device type %s\n",devicename));
335 map_nt_and_unix_username(global_myworkgroup, user);
337 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
340 return(connection_error(inbuf,outbuf,ecode));
342 if (Protocol < PROTOCOL_NT1) {
343 set_message(outbuf,2,strlen(devicename)+1,True);
344 pstrcpy(smb_buf(outbuf),devicename);
346 char *fsname = lp_fstype(SNUM(conn));
348 set_message(outbuf,3,3,True);
351 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
352 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
354 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
356 /* what does setting this bit do? It is set by NT4 and
357 may affect the ability to autorun mounted cdroms */
358 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
361 DEBUG(3,("tconX service=%s user=%s\n",
364 /* set the incoming and outgoing tid to the just created one */
365 SSVAL(inbuf,smb_tid,conn->cnum);
366 SSVAL(outbuf,smb_tid,conn->cnum);
368 return chain_reply(inbuf,outbuf,length,bufsize);
372 /****************************************************************************
373 reply to an unknown type
374 ****************************************************************************/
375 int reply_unknown(char *inbuf,char *outbuf)
378 type = CVAL(inbuf,smb_com);
380 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
381 smb_fn_name(type), type, type));
383 return(ERROR(ERRSRV,ERRunknownsmb));
387 /****************************************************************************
389 ****************************************************************************/
390 int reply_ioctl(connection_struct *conn,
391 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
393 DEBUG(3,("ignoring ioctl\n"));
395 /* we just say it succeeds and hope its all OK.
396 some day it would be nice to interpret them individually */
397 return set_message(outbuf,1,0,True);
399 return(ERROR(ERRSRV,ERRnosupport));
403 /****************************************************************************
404 always return an error: it's just a matter of which one...
405 ****************************************************************************/
406 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
407 char *smb_passwd, int smb_passlen,
408 char *smb_nt_passwd, int smb_nt_passlen)
410 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
411 if (lp_security() == SEC_USER)
413 smb_trust_acct = getsmbpwnam(user);
417 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
418 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
419 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
422 if (smb_trust_acct == NULL)
424 /* lkclXXXX: workstation entry doesn't exist */
425 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
426 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
427 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
431 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
433 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
434 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
435 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
438 if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
440 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
441 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
442 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
445 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
447 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
448 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
449 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
452 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
454 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
455 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
456 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
459 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
461 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
462 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
463 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
467 /* don't know what to do: indicate logon failure */
468 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
469 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
472 /****************************************************************************
473 Check for a valid username and password in security=server mode.
474 ****************************************************************************/
476 static BOOL check_server_security(char *orig_user, char *domain,
477 char *smb_apasswd, int smb_apasslen,
478 char *smb_ntpasswd, int smb_ntpasslen)
480 if(lp_security() != SEC_SERVER)
483 return server_validate(orig_user, domain,
484 smb_apasswd, smb_apasslen,
485 smb_ntpasswd, smb_ntpasslen);
488 /****************************************************************************
489 Check for a valid username and password in security=domain mode.
490 ****************************************************************************/
492 static BOOL check_domain_security(char *orig_user, char *domain,
493 char *smb_apasswd, int smb_apasslen,
494 char *smb_ntpasswd, int smb_ntpasslen)
496 if(lp_security() != SEC_DOMAIN)
499 return domain_client_validate(orig_user, domain,
500 smb_apasswd, smb_apasslen,
501 smb_ntpasswd, smb_ntpasslen);
504 /****************************************************************************
505 reply to a session setup command
506 ****************************************************************************/
508 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
514 int smb_apasslen = 0;
516 int smb_ntpasslen = 0;
517 pstring smb_ntpasswd;
518 BOOL valid_nt_password = False;
522 static BOOL done_sesssetup = False;
523 BOOL doencrypt = SMBENCRYPT();
529 smb_bufsize = SVAL(inbuf,smb_vwv2);
531 if (Protocol < PROTOCOL_NT1) {
532 smb_apasslen = SVAL(inbuf,smb_vwv7);
533 if (smb_apasslen > MAX_PASS_LEN)
535 overflow_attack(smb_apasslen);
538 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
539 smb_apasswd[smb_apasslen] = 0;
540 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
542 if (!doencrypt && (lp_security() != SEC_SERVER)) {
543 smb_apasslen = strlen(smb_apasswd);
546 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
547 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
548 enum remote_arch_types ra_type = get_remote_arch();
549 char *p = smb_buf(inbuf);
551 global_client_caps = IVAL(inbuf,smb_vwv11);
553 /* client_caps is used as final determination if client is NT or Win95.
554 This is needed to return the correct error codes in some
558 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
560 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
561 set_remote_arch( RA_WINNT);
563 set_remote_arch( RA_WIN95);
566 if (passlen1 != 24 && passlen2 != 24)
569 if (passlen1 > MAX_PASS_LEN) {
570 overflow_attack(passlen1);
573 passlen1 = MIN(passlen1, MAX_PASS_LEN);
574 passlen2 = MIN(passlen2, MAX_PASS_LEN);
577 /* both Win95 and WinNT stuff up the password lengths for
578 non-encrypting systems. Uggh.
580 if passlen1==24 its a win95 system, and its setting the
581 password length incorrectly. Luckily it still works with the
582 default code because Win95 will null terminate the password
585 if passlen1>0 and passlen2>0 then maybe its a NT box and its
586 setting passlen2 to some random value which really stuffs
587 things up. we need to fix that one. */
589 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
593 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
594 /* Save the lanman2 password and the NT md4 password. */
595 smb_apasslen = passlen1;
596 memcpy(smb_apasswd,p,smb_apasslen);
597 smb_apasswd[smb_apasslen] = 0;
598 smb_ntpasslen = passlen2;
599 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
600 smb_ntpasswd[smb_ntpasslen] = 0;
602 /* we use the first password that they gave */
603 smb_apasslen = passlen1;
604 StrnCpy(smb_apasswd,p,smb_apasslen);
606 /* trim the password */
607 smb_apasslen = strlen(smb_apasswd);
609 /* wfwg sometimes uses a space instead of a null */
610 if (strequal(smb_apasswd," ")) {
616 p += passlen1 + passlen2;
617 fstrcpy(user,p); p = skip_string(p,1);
620 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
621 domain,skip_string(p,1),skip_string(p,2)));
625 DEBUG(3,("sesssetupX:name=[%s]\n",user));
627 /* If name ends in $ then I think it's asking about whether a */
628 /* computer with that name (minus the $) has access. For now */
629 /* say yes to everything ending in $. */
630 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
632 return session_trust_account(conn, inbuf, outbuf, user,
633 smb_apasswd, smb_apasslen,
634 smb_ntpasswd, smb_ntpasslen);
637 /* If no username is sent use the guest account */
640 pstrcpy(user,lp_guestaccount(-1));
641 /* If no user and no password then set guest flag. */
642 if( *smb_apasswd == 0)
649 * In share level security, only overwrite sesssetup_use if
650 * it's a non null-session share. Helps keep %U and %G
654 if((lp_security() != SEC_SHARE) || (*user && !guest))
655 pstrcpy(sesssetup_user,user);
657 reload_services(True);
660 * Save the username before mapping. We will use
661 * the original username sent to us for security=server
662 * and security=domain checking.
665 pstrcpy( orig_user, user);
667 map_nt_and_unix_username(domain, user);
669 add_session_user(user);
672 * Check if the given username was the guest user with no password.
675 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
679 * Check with orig_user for security=server and
684 !check_server_security(orig_user, domain,
685 smb_apasswd, smb_apasslen,
686 smb_ntpasswd, smb_ntpasslen) &&
687 !check_domain_security(orig_user, domain,
688 smb_apasswd, smb_apasslen,
689 smb_ntpasswd, smb_ntpasslen) &&
690 !check_hosts_equiv(user)
695 * If we get here then the user wasn't guest and the remote
696 * authentication methods failed. Check the authentication
697 * methods on this local server.
699 * If an NT password was supplied try and validate with that
700 * first. This is superior as the passwords are mixed case
701 * 128 length unicode.
706 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
707 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
709 valid_nt_password = True;
712 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL))
714 if (lp_security() >= SEC_USER)
716 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
717 return(ERROR(ERRSRV,ERRbadpw));
719 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
721 if (Get_Pwnam(user,True))
722 return(ERROR(ERRSRV,ERRbadpw));
726 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
727 * Then always map to guest account - as done below.
731 if (*smb_apasswd || !Get_Pwnam(user,True))
732 pstrcpy(user,lp_guestaccount(-1));
733 DEBUG(3,("Registered username %s for guest access\n",user));
738 if (!Get_Pwnam(user,True)) {
739 DEBUG(3,("No such user %s - using guest account\n",user));
740 pstrcpy(user,lp_guestaccount(-1));
744 if (!strequal(user,lp_guestaccount(-1)) &&
745 lp_servicenumber(user) < 0)
747 int homes = lp_servicenumber(HOMES_NAME);
748 char *home = get_home_dir(user);
749 if (homes >= 0 && home)
750 lp_add_home(user,homes,home);
754 /* it's ok - setup a reply */
755 if (Protocol < PROTOCOL_NT1) {
756 set_message(outbuf,3,0,True);
759 set_message(outbuf,3,3,True);
761 pstrcpy(p,"Unix"); p = skip_string(p,1);
762 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
763 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
764 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
765 /* perhaps grab OS version here?? */
768 /* Set the correct uid in the outgoing and incoming packets
769 We will use this on future requests to determine which
770 user we should become.
773 struct passwd *pw = Get_Pwnam(user,False);
775 DEBUG(1,("Username %s is invalid on this system\n",user));
776 return(ERROR(ERRSRV,ERRbadpw));
783 SSVAL(outbuf,smb_vwv2,1);
785 /* register the name and uid as being validated, so further connections
786 to a uid can get through without a password, on the same VC */
787 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
789 SSVAL(outbuf,smb_uid,sess_vuid);
790 SSVAL(inbuf,smb_uid,sess_vuid);
793 max_send = MIN(max_send,smb_bufsize);
795 DEBUG(6,("Client requested max send size of %d\n", max_send));
797 done_sesssetup = True;
799 return chain_reply(inbuf,outbuf,length,bufsize);
803 /****************************************************************************
805 ****************************************************************************/
806 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
812 BOOL bad_path = False;
815 pstrcpy(name,smb_buf(inbuf) + 1);
816 unix_convert(name,conn,0,&bad_path,&st);
818 mode = SVAL(inbuf,smb_vwv0);
820 if (check_name(name,conn)) {
822 ok = S_ISDIR(st.st_mode);
824 ok = dos_directory_exist(name,NULL);
829 /* We special case this - as when a Windows machine
830 is parsing a path is steps through the components
831 one at a time - if a component fails it expects
832 ERRbadpath, not ERRbadfile.
836 unix_ERR_class = ERRDOS;
837 unix_ERR_code = ERRbadpath;
841 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
842 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
843 (get_remote_arch() == RA_WINNT))
845 unix_ERR_class = ERRDOS;
846 unix_ERR_code = ERRbaddirectory;
850 return(UNIXERROR(ERRDOS,ERRbadpath));
853 outsize = set_message(outbuf,0,0,True);
855 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
861 /****************************************************************************
863 ****************************************************************************/
864 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
868 SMB_STRUCT_STAT sbuf;
873 BOOL bad_path = False;
875 pstrcpy(fname,smb_buf(inbuf) + 1);
877 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
878 under WfWg - weird! */
881 mode = aHIDDEN | aDIR;
882 if (!CAN_WRITE(conn)) mode |= aRONLY;
889 unix_convert(fname,conn,0,&bad_path,&sbuf);
890 if (check_name(fname,conn))
892 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
894 mode = dos_mode(conn,fname,&sbuf);
896 mtime = sbuf.st_mtime;
902 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
908 if((errno == ENOENT) && bad_path)
910 unix_ERR_class = ERRDOS;
911 unix_ERR_code = ERRbadpath;
914 return(UNIXERROR(ERRDOS,ERRbadfile));
917 outsize = set_message(outbuf,10,0,True);
919 SSVAL(outbuf,smb_vwv0,mode);
920 if(lp_dos_filetime_resolution(SNUM(conn)) )
921 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
923 put_dos_date3(outbuf,smb_vwv1,mtime);
924 SIVAL(outbuf,smb_vwv3,(uint32)size);
926 if (Protocol >= PROTOCOL_NT1) {
927 char *p = strrchr(fname,'/');
928 uint16 flg2 = SVAL(outbuf,smb_flg2);
930 if (!is_8_3(fname, True))
931 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
934 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
940 /****************************************************************************
942 ****************************************************************************/
943 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
951 BOOL bad_path = False;
953 pstrcpy(fname,smb_buf(inbuf) + 1);
954 unix_convert(fname,conn,0,&bad_path,&st);
956 mode = SVAL(inbuf,smb_vwv0);
957 mtime = make_unix_date3(inbuf+smb_vwv1);
959 if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
961 if (check_name(fname,conn))
962 ok = (file_chmod(conn,fname,mode,NULL) == 0);
964 ok = set_filetime(conn,fname,mtime);
968 if((errno == ENOENT) && bad_path)
970 unix_ERR_class = ERRDOS;
971 unix_ERR_code = ERRbadpath;
974 return(UNIXERROR(ERRDOS,ERRnoaccess));
977 outsize = set_message(outbuf,0,0,True);
979 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
985 /****************************************************************************
987 ****************************************************************************/
988 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
991 SMB_BIG_UINT dfree,dsize,bsize;
993 sys_disk_free(".",&bsize,&dfree,&dsize);
995 outsize = set_message(outbuf,5,0,True);
997 SSVAL(outbuf,smb_vwv0,dsize);
998 SSVAL(outbuf,smb_vwv1,bsize/512);
999 SSVAL(outbuf,smb_vwv2,512);
1000 SSVAL(outbuf,smb_vwv3,dfree);
1002 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1008 /****************************************************************************
1010 Can be called from SMBsearch, SMBffirst or SMBfunique.
1011 ****************************************************************************/
1012 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1023 BOOL finished = False;
1032 BOOL check_descend = False;
1033 BOOL expect_close = False;
1034 BOOL can_open = True;
1035 BOOL bad_path = False;
1037 *mask = *directory = *fname = 0;
1039 /* If we were called as SMBffirst then we must expect close. */
1040 if(CVAL(inbuf,smb_com) == SMBffirst)
1041 expect_close = True;
1043 outsize = set_message(outbuf,1,3,True);
1044 maxentries = SVAL(inbuf,smb_vwv0);
1045 dirtype = SVAL(inbuf,smb_vwv1);
1046 path = smb_buf(inbuf) + 1;
1047 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1050 /* dirtype &= ~aDIR; */
1052 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1055 if (status_len == 0)
1059 pstrcpy(directory,smb_buf(inbuf)+1);
1060 pstrcpy(dir2,smb_buf(inbuf)+1);
1061 unix_convert(directory,conn,0,&bad_path,NULL);
1064 if (!check_name(directory,conn))
1067 p = strrchr(dir2,'/');
1079 p = strrchr(directory,'/');
1085 if (strlen(directory) == 0)
1086 pstrcpy(directory,"./");
1088 CVAL(status,0) = dirtype;
1092 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1093 memcpy(mask,status+1,11);
1095 dirtype = CVAL(status,0) & 0x1F;
1096 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1099 string_set(&conn->dirpath,dptr_path(dptr_num));
1100 if (!case_sensitive)
1104 /* turn strings of spaces into a . */
1106 trim_string(mask,NULL," ");
1107 if ((p = strrchr(mask,' ')))
1112 trim_string(mask,NULL," ");
1118 /* Convert the formatted mask. (This code lives in trans2.c) */
1126 if((skip = skip_multibyte_char( *p )) != 0 )
1132 if (*p != '?' && *p != '*' && !isdoschar(*p))
1134 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1142 if (!strchr(mask,'.') && strlen(mask)>8)
1145 fstrcpy(tmp,&mask[8]);
1151 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1155 p = smb_buf(outbuf) + 3;
1159 if (status_len == 0)
1161 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1166 if((errno == ENOENT) && bad_path)
1168 unix_ERR_class = ERRDOS;
1169 unix_ERR_code = ERRbadpath;
1171 return (UNIXERROR(ERRDOS,ERRnofids));
1173 return(ERROR(ERRDOS,ERRnofids));
1177 DEBUG(4,("dptr_num is %d\n",dptr_num));
1181 if ((dirtype&0x1F) == aVOLID)
1183 memcpy(p,status,21);
1184 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1185 dptr_fill(p+12,dptr_num);
1186 if (dptr_zero(p+12) && (status_len==0))
1190 p += DIR_STRUCT_SIZE;
1194 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1195 conn->dirpath,lp_dontdescend(SNUM(conn))));
1196 if (in_list(conn->dirpath,
1197 lp_dontdescend(SNUM(conn)),True))
1198 check_descend = True;
1200 for (i=numentries;(i<maxentries) && !finished;i++)
1203 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1206 memcpy(p,status,21);
1207 make_dir_struct(p,mask,fname,size,mode,date);
1208 dptr_fill(p+12,dptr_num);
1211 p += DIR_STRUCT_SIZE;
1220 if (numentries == 0 || !ok)
1222 CVAL(outbuf,smb_rcls) = ERRDOS;
1223 SSVAL(outbuf,smb_err,ERRnofiles);
1226 /* If we were called as SMBffirst with smb_search_id == NULL
1227 and no entries were found then return error and close dirptr
1230 if(ok && expect_close && numentries == 0 && status_len == 0)
1232 CVAL(outbuf,smb_rcls) = ERRDOS;
1233 SSVAL(outbuf,smb_err,ERRnofiles);
1234 /* Also close the dptr - we know it's gone */
1235 dptr_close(dptr_num);
1238 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1239 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1240 dptr_close(dptr_num);
1242 SSVAL(outbuf,smb_vwv0,numentries);
1243 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1244 CVAL(smb_buf(outbuf),0) = 5;
1245 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1247 if (Protocol >= PROTOCOL_NT1) {
1248 uint16 flg2 = SVAL(outbuf,smb_flg2);
1249 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1252 outsize += DIR_STRUCT_SIZE*numentries;
1253 smb_setlen(outbuf,outsize - 4);
1255 if ((! *directory) && dptr_path(dptr_num))
1256 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1258 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1259 smb_fn_name(CVAL(inbuf,smb_com)),
1260 mask, directory, dirtype, numentries, maxentries ) );
1266 /****************************************************************************
1267 reply to a fclose (stop directory search)
1268 ****************************************************************************/
1269 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1277 outsize = set_message(outbuf,1,0,True);
1278 path = smb_buf(inbuf) + 1;
1279 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1282 if (status_len == 0)
1283 return(ERROR(ERRSRV,ERRsrverror));
1285 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1287 if(dptr_fetch(status+12,&dptr_num)) {
1288 /* Close the dptr - we know it's gone */
1289 dptr_close(dptr_num);
1292 SSVAL(outbuf,smb_vwv0,0);
1294 DEBUG(3,("search close\n"));
1300 /****************************************************************************
1302 ****************************************************************************/
1304 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1314 SMB_STRUCT_STAT sbuf;
1315 BOOL bad_path = False;
1317 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1319 share_mode = SVAL(inbuf,smb_vwv0);
1321 pstrcpy(fname,smb_buf(inbuf)+1);
1322 unix_convert(fname,conn,0,&bad_path,NULL);
1326 return(ERROR(ERRSRV,ERRnofids));
1328 if (!check_name(fname,conn))
1330 if((errno == ENOENT) && bad_path)
1332 unix_ERR_class = ERRDOS;
1333 unix_ERR_code = ERRbadpath;
1336 return(UNIXERROR(ERRDOS,ERRnoaccess));
1339 unixmode = unix_mode(conn,aARCH);
1341 open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1342 unixmode, oplock_request,&rmode,NULL);
1346 if((errno == ENOENT) && bad_path)
1348 unix_ERR_class = ERRDOS;
1349 unix_ERR_code = ERRbadpath;
1352 return(UNIXERROR(ERRDOS,ERRnoaccess));
1355 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1356 close_file(fsp,False);
1357 return(ERROR(ERRDOS,ERRnoaccess));
1360 size = sbuf.st_size;
1361 fmode = dos_mode(conn,fname,&sbuf);
1362 mtime = sbuf.st_mtime;
1365 DEBUG(3,("attempt to open a directory %s\n",fname));
1366 close_file(fsp,False);
1367 return(ERROR(ERRDOS,ERRnoaccess));
1370 outsize = set_message(outbuf,7,0,True);
1371 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1372 SSVAL(outbuf,smb_vwv1,fmode);
1373 if(lp_dos_filetime_resolution(SNUM(conn)) )
1374 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1376 put_dos_date3(outbuf,smb_vwv2,mtime);
1377 SIVAL(outbuf,smb_vwv4,(uint32)size);
1378 SSVAL(outbuf,smb_vwv6,rmode);
1380 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1381 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1384 if(fsp->granted_oplock)
1385 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1390 /****************************************************************************
1391 reply to an open and X
1392 ****************************************************************************/
1393 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1396 int smb_mode = SVAL(inbuf,smb_vwv3);
1397 int smb_attr = SVAL(inbuf,smb_vwv5);
1398 /* Breakout the oplock request bits so we can set the
1399 reply bits separately. */
1400 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1401 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1402 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1404 int open_flags = SVAL(inbuf,smb_vwv2);
1405 int smb_sattr = SVAL(inbuf,smb_vwv4);
1406 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1408 int smb_ofun = SVAL(inbuf,smb_vwv8);
1411 int fmode=0,mtime=0,rmode=0;
1412 SMB_STRUCT_STAT sbuf;
1414 BOOL bad_path = False;
1417 /* If it's an IPC, pass off the pipe handler. */
1418 if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
1420 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1423 /* XXXX we need to handle passed times, sattr and flags */
1425 pstrcpy(fname,smb_buf(inbuf));
1426 unix_convert(fname,conn,0,&bad_path,NULL);
1430 return(ERROR(ERRSRV,ERRnofids));
1432 if (!check_name(fname,conn))
1434 if((errno == ENOENT) && bad_path)
1436 unix_ERR_class = ERRDOS;
1437 unix_ERR_code = ERRbadpath;
1440 return(UNIXERROR(ERRDOS,ERRnoaccess));
1443 unixmode = unix_mode(conn,smb_attr | aARCH);
1445 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1446 oplock_request, &rmode,&smb_action);
1450 if((errno == ENOENT) && bad_path)
1452 unix_ERR_class = ERRDOS;
1453 unix_ERR_code = ERRbadpath;
1456 return(UNIXERROR(ERRDOS,ERRnoaccess));
1459 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1460 close_file(fsp,False);
1461 return(ERROR(ERRDOS,ERRnoaccess));
1464 size = sbuf.st_size;
1465 fmode = dos_mode(conn,fname,&sbuf);
1466 mtime = sbuf.st_mtime;
1468 close_file(fsp,False);
1469 return(ERROR(ERRDOS,ERRnoaccess));
1472 /* If the caller set the extended oplock request bit
1473 and we granted one (by whatever means) - set the
1474 correct bit for extended oplock reply.
1477 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1478 smb_action |= EXTENDED_OPLOCK_GRANTED;
1481 if(ex_oplock_request && fsp->granted_oplock) {
1482 smb_action |= EXTENDED_OPLOCK_GRANTED;
1485 /* If the caller set the core oplock request bit
1486 and we granted one (by whatever means) - set the
1487 correct bit for core oplock reply.
1490 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1491 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1494 if(core_oplock_request && fsp->granted_oplock) {
1495 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1498 set_message(outbuf,15,0,True);
1499 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1500 SSVAL(outbuf,smb_vwv3,fmode);
1501 if(lp_dos_filetime_resolution(SNUM(conn)) )
1502 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1504 put_dos_date3(outbuf,smb_vwv4,mtime);
1505 SIVAL(outbuf,smb_vwv6,(uint32)size);
1506 SSVAL(outbuf,smb_vwv8,rmode);
1507 SSVAL(outbuf,smb_vwv11,smb_action);
1509 return chain_reply(inbuf,outbuf,length,bufsize);
1513 /****************************************************************************
1514 reply to a SMBulogoffX
1515 ****************************************************************************/
1516 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1518 uint16 vuid = SVAL(inbuf,smb_uid);
1519 user_struct *vuser = get_valid_user_struct(vuid);
1522 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1525 /* in user level security we are supposed to close any files
1526 open by this user */
1527 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1528 file_close_user(vuid);
1531 invalidate_vuid(vuid);
1533 set_message(outbuf,2,0,True);
1535 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1537 return chain_reply(inbuf,outbuf,length,bufsize);
1541 /****************************************************************************
1542 reply to a mknew or a create
1543 ****************************************************************************/
1544 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1552 BOOL bad_path = False;
1554 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1556 com = SVAL(inbuf,smb_com);
1558 createmode = SVAL(inbuf,smb_vwv0);
1559 pstrcpy(fname,smb_buf(inbuf)+1);
1560 unix_convert(fname,conn,0,&bad_path,NULL);
1562 if (createmode & aVOLID)
1564 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1567 unixmode = unix_mode(conn,createmode);
1571 return(ERROR(ERRSRV,ERRnofids));
1573 if (!check_name(fname,conn))
1575 if((errno == ENOENT) && bad_path)
1577 unix_ERR_class = ERRDOS;
1578 unix_ERR_code = ERRbadpath;
1581 return(UNIXERROR(ERRDOS,ERRnoaccess));
1586 /* We should fail if file exists. */
1591 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1595 /* Open file in dos compatibility share mode. */
1596 open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1597 ofun, unixmode, oplock_request, NULL, NULL);
1601 if((errno == ENOENT) && bad_path)
1603 unix_ERR_class = ERRDOS;
1604 unix_ERR_code = ERRbadpath;
1607 return(UNIXERROR(ERRDOS,ERRnoaccess));
1610 outsize = set_message(outbuf,1,0,True);
1611 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1613 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1614 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1617 if(fsp->granted_oplock)
1618 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1620 DEBUG( 2, ( "new file %s\n", fname ) );
1621 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1622 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1628 /****************************************************************************
1629 reply to a create temporary file
1630 ****************************************************************************/
1631 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1638 BOOL bad_path = False;
1640 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1642 createmode = SVAL(inbuf,smb_vwv0);
1643 pstrcpy(fname,smb_buf(inbuf)+1);
1644 pstrcat(fname,"/TMXXXXXX");
1645 unix_convert(fname,conn,0,&bad_path,NULL);
1647 unixmode = unix_mode(conn,createmode);
1651 return(ERROR(ERRSRV,ERRnofids));
1653 if (!check_name(fname,conn))
1655 if((errno == ENOENT) && bad_path)
1657 unix_ERR_class = ERRDOS;
1658 unix_ERR_code = ERRbadpath;
1661 return(UNIXERROR(ERRDOS,ERRnoaccess));
1664 pstrcpy(fname2,(char *)mktemp(fname));
1666 /* Open file in dos compatibility share mode. */
1667 /* We should fail if file exists. */
1668 open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1669 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1673 if((errno == ENOENT) && bad_path)
1675 unix_ERR_class = ERRDOS;
1676 unix_ERR_code = ERRbadpath;
1679 return(UNIXERROR(ERRDOS,ERRnoaccess));
1682 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1683 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1684 CVAL(smb_buf(outbuf),0) = 4;
1685 pstrcpy(smb_buf(outbuf) + 1,fname2);
1687 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1688 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1691 if(fsp->granted_oplock)
1692 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1694 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1695 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1696 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1702 /*******************************************************************
1703 check if a user is allowed to delete a file
1704 ********************************************************************/
1705 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1707 SMB_STRUCT_STAT sbuf;
1710 if (!CAN_WRITE(conn)) return(False);
1712 if (dos_lstat(fname,&sbuf) != 0) return(False);
1713 fmode = dos_mode(conn,fname,&sbuf);
1714 if (fmode & aDIR) return(False);
1715 if (!lp_delete_readonly(SNUM(conn))) {
1716 if (fmode & aRONLY) return(False);
1718 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1720 if (!check_file_sharing(conn,fname,False)) return(False);
1724 /****************************************************************************
1726 ****************************************************************************/
1727 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1736 int error = ERRnoaccess;
1739 BOOL bad_path = False;
1741 *directory = *mask = 0;
1743 dirtype = SVAL(inbuf,smb_vwv0);
1745 pstrcpy(name,smb_buf(inbuf) + 1);
1747 DEBUG(3,("reply_unlink : %s\n",name));
1749 unix_convert(name,conn,0,&bad_path,NULL);
1751 p = strrchr(name,'/');
1753 pstrcpy(directory,"./");
1757 pstrcpy(directory,name);
1761 if (is_mangled(mask))
1762 check_mangled_cache( mask );
1764 has_wild = strchr(mask,'*') || strchr(mask,'?');
1767 pstrcat(directory,"/");
1768 pstrcat(directory,mask);
1769 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
1772 exists = dos_file_exist(directory,NULL);
1774 void *dirptr = NULL;
1777 if (check_name(directory,conn))
1778 dirptr = OpenDir(conn, directory, True);
1780 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1781 the pattern matches against the long name, otherwise the short name
1782 We don't implement this yet XXXX
1789 if (strequal(mask,"????????.???"))
1792 while ((dname = ReadDirName(dirptr)))
1795 pstrcpy(fname,dname);
1797 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1799 error = ERRnoaccess;
1800 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1801 if (!can_delete(fname,conn,dirtype)) continue;
1802 if (!dos_unlink(fname)) count++;
1803 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1811 return(ERROR(ERRDOS,error));
1814 if((errno == ENOENT) && bad_path)
1816 unix_ERR_class = ERRDOS;
1817 unix_ERR_code = ERRbadpath;
1819 return(UNIXERROR(ERRDOS,error));
1823 outsize = set_message(outbuf,0,0,True);
1829 /****************************************************************************
1830 reply to a readbraw (core+ protocol)
1831 ****************************************************************************/
1832 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1834 size_t maxcount,mincount;
1837 char *header = outbuf;
1842 * Special check if an oplock break has been issued
1843 * and the readraw request croses on the wire, we must
1844 * return a zero length response here.
1847 if(global_oplock_break)
1849 _smb_setlen(header,0);
1850 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1851 DEBUG(5,("readbraw - oplock break finished\n"));
1855 fsp = file_fsp(inbuf,smb_vwv0);
1857 startpos = IVAL(inbuf,smb_vwv1);
1858 #ifdef LARGE_SMB_OFF_T
1859 if(CVAL(inbuf,smb_wct) == 10) {
1861 * This is a large offset (64 bit) read.
1863 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1865 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1866 (double)startpos ));
1867 _smb_setlen(header,0);
1868 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1872 #endif /* LARGE_SMB_OFF_T */
1873 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1874 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1876 /* ensure we don't overrun the packet size */
1877 maxcount = MIN(65535,maxcount);
1878 maxcount = MAX(mincount,maxcount);
1880 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1881 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1882 _smb_setlen(header,0);
1883 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1887 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1889 SMB_OFF_T size = fsp->size;
1890 SMB_OFF_T sizeneeded = startpos + maxcount;
1892 if (size < sizeneeded)
1895 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1897 if (!fsp->can_write)
1901 nread = MIN(maxcount,(size - startpos));
1904 if (nread < mincount)
1907 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1908 fsp->fnum, (double)startpos,
1909 maxcount, mincount, nread ) );
1913 BOOL seek_fail = False;
1915 _smb_setlen(header,nread);
1917 #if USE_READ_PREDICTION
1918 if (!fsp->can_write)
1919 predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1920 #endif /* USE_READ_PREDICTION */
1922 if ((nread-predict) > 0) {
1923 if(seek_file(fsp,startpos + predict) == -1) {
1924 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1931 ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,
1932 (SMB_OFF_T)(nread-predict),header,4+predict,
1937 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1938 fsp->fsp_name,startpos,nread,ret));
1940 #else /* UNSAFE_READRAW */
1941 ret = read_file(fsp,header+4,startpos,nread);
1942 if (ret < mincount) ret = 0;
1944 _smb_setlen(header,ret);
1945 transfer_file(0,Client,0,header,4+ret,0);
1946 #endif /* UNSAFE_READRAW */
1948 DEBUG(5,("readbraw finished\n"));
1953 /****************************************************************************
1954 reply to a lockread (core+ protocol)
1955 ****************************************************************************/
1956 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1965 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1967 CHECK_FSP(fsp,conn);
1971 numtoread = SVAL(inbuf,smb_vwv1);
1972 startpos = IVAL(inbuf,smb_vwv2);
1974 outsize = set_message(outbuf,5,3,True);
1975 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1976 data = smb_buf(outbuf) + 3;
1978 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1979 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1981 * A blocking lock was requested. Package up
1982 * this smb into a queued request and push it
1983 * onto the blocking lock queue.
1985 if(push_blocking_lock_request(inbuf, length, -1, 0))
1988 return (ERROR(eclass,ecode));
1991 nread = read_file(fsp,data,startpos,numtoread);
1994 return(UNIXERROR(ERRDOS,ERRnoaccess));
1997 SSVAL(outbuf,smb_vwv0,nread);
1998 SSVAL(outbuf,smb_vwv5,nread+3);
1999 SSVAL(smb_buf(outbuf),1,nread);
2001 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2002 fsp->fnum, numtoread, nread ) );
2008 /****************************************************************************
2010 ****************************************************************************/
2011 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2018 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2020 CHECK_FSP(fsp,conn);
2024 numtoread = SVAL(inbuf,smb_vwv1);
2025 startpos = IVAL(inbuf,smb_vwv2);
2027 outsize = set_message(outbuf,5,3,True);
2028 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2029 data = smb_buf(outbuf) + 3;
2031 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2032 return(ERROR(ERRDOS,ERRlock));
2035 nread = read_file(fsp,data,startpos,numtoread);
2038 return(UNIXERROR(ERRDOS,ERRnoaccess));
2041 SSVAL(outbuf,smb_vwv0,nread);
2042 SSVAL(outbuf,smb_vwv5,nread+3);
2043 CVAL(smb_buf(outbuf),0) = 1;
2044 SSVAL(smb_buf(outbuf),1,nread);
2046 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2047 fsp->fnum, numtoread, nread ) );
2053 /****************************************************************************
2054 reply to a read and X
2055 ****************************************************************************/
2056 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2058 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2059 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2060 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2061 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2065 /* If it's an IPC, pass off the pipe handler. */
2067 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2069 CHECK_FSP(fsp,conn);
2073 set_message(outbuf,12,0,True);
2074 data = smb_buf(outbuf);
2076 #ifdef LARGE_SMB_OFF_T
2077 if(CVAL(inbuf,smb_wct) == 12) {
2079 * This is a large offset (64 bit) read.
2081 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2083 #endif /* LARGE_SMB_OFF_T */
2085 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2086 return(ERROR(ERRDOS,ERRlock));
2087 nread = read_file(fsp,data,startpos,smb_maxcnt);
2090 return(UNIXERROR(ERRDOS,ERRnoaccess));
2092 SSVAL(outbuf,smb_vwv5,nread);
2093 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2094 SSVAL(smb_buf(outbuf),-2,nread);
2096 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2097 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2099 return chain_reply(inbuf,outbuf,length,bufsize);
2102 /****************************************************************************
2103 reply to a writebraw (core+ or LANMAN1.0 protocol)
2104 ****************************************************************************/
2105 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2108 ssize_t total_written=0;
2109 size_t numtowrite=0;
2114 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2117 CHECK_FSP(fsp,conn);
2121 tcount = IVAL(inbuf,smb_vwv1);
2122 startpos = IVAL(inbuf,smb_vwv3);
2123 write_through = BITSETW(inbuf+smb_vwv7,0);
2125 /* We have to deal with slightly different formats depending
2126 on whether we are using the core+ or lanman1.0 protocol */
2127 if(Protocol <= PROTOCOL_COREPLUS) {
2128 numtowrite = SVAL(smb_buf(inbuf),-2);
2129 data = smb_buf(inbuf);
2131 numtowrite = SVAL(inbuf,smb_vwv10);
2132 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2135 /* force the error type */
2136 CVAL(inbuf,smb_com) = SMBwritec;
2137 CVAL(outbuf,smb_com) = SMBwritec;
2139 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2140 return(ERROR(ERRDOS,ERRlock));
2142 if (seek_file(fsp,startpos) == -1) {
2143 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2144 return(UNIXERROR(ERRDOS,ERRnoaccess));
2148 nwritten = write_file(fsp,data,numtowrite);
2150 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2151 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2153 if (nwritten < numtowrite)
2154 return(UNIXERROR(ERRHRD,ERRdiskfull));
2156 total_written = nwritten;
2158 /* Return a message to the redirector to tell it
2159 to send more bytes */
2160 CVAL(outbuf,smb_com) = SMBwritebraw;
2161 SSVALS(outbuf,smb_vwv0,-1);
2162 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2163 send_smb(Client,outbuf);
2165 /* Now read the raw data into the buffer and write it */
2166 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2167 exit_server("secondary writebraw failed");
2170 /* Even though this is not an smb message, smb_len
2171 returns the generic length of an smb message */
2172 numtowrite = smb_len(inbuf);
2174 if (tcount > nwritten+numtowrite) {
2175 DEBUG(3,("Client overestimated the write %d %d %d\n",
2176 tcount,nwritten,numtowrite));
2179 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2181 total_written += nwritten;
2183 /* Set up outbuf to return the correct return */
2184 outsize = set_message(outbuf,1,0,True);
2185 CVAL(outbuf,smb_com) = SMBwritec;
2186 SSVAL(outbuf,smb_vwv0,total_written);
2188 if (nwritten < (ssize_t)numtowrite) {
2189 CVAL(outbuf,smb_rcls) = ERRHRD;
2190 SSVAL(outbuf,smb_err,ERRdiskfull);
2193 if (lp_syncalways(SNUM(conn)) || write_through)
2194 sync_file(conn,fsp);
2196 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2197 fsp->fnum, (double)startpos, numtowrite, total_written));
2199 /* we won't return a status if write through is not selected - this
2200 follows what WfWg does */
2201 if (!write_through && total_written==tcount)
2207 /****************************************************************************
2208 reply to a writeunlock (core+)
2209 ****************************************************************************/
2210 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2212 ssize_t nwritten = -1;
2218 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2221 CHECK_FSP(fsp,conn);
2225 numtowrite = SVAL(inbuf,smb_vwv1);
2226 startpos = IVAL(inbuf,smb_vwv2);
2227 data = smb_buf(inbuf) + 3;
2229 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2230 return(ERROR(ERRDOS,ERRlock));
2232 if(seek_file(fsp,startpos) == -1)
2233 return(UNIXERROR(ERRDOS,ERRnoaccess));
2235 /* The special X/Open SMB protocol handling of
2236 zero length writes is *NOT* done for
2241 nwritten = write_file(fsp,data,numtowrite);
2243 if (lp_syncalways(SNUM(conn)))
2244 sync_file(conn,fsp);
2246 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2247 return(UNIXERROR(ERRDOS,ERRnoaccess));
2249 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2250 return(ERROR(eclass,ecode));
2252 outsize = set_message(outbuf,1,0,True);
2254 SSVAL(outbuf,smb_vwv0,nwritten);
2256 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2257 fsp->fnum, numtowrite, nwritten ) );
2262 /****************************************************************************
2264 ****************************************************************************/
2265 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2268 ssize_t nwritten = -1;
2271 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2274 CHECK_FSP(fsp,conn);
2278 numtowrite = SVAL(inbuf,smb_vwv1);
2279 startpos = IVAL(inbuf,smb_vwv2);
2280 data = smb_buf(inbuf) + 3;
2282 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2283 return(ERROR(ERRDOS,ERRlock));
2285 if(seek_file(fsp,startpos) == -1)
2286 return(UNIXERROR(ERRDOS,ERRnoaccess));
2288 /* X/Open SMB protocol says that if smb_vwv1 is
2289 zero then the file size should be extended or
2290 truncated to the size given in smb_vwv[2-3] */
2292 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2294 nwritten = write_file(fsp,data,numtowrite);
2296 if (lp_syncalways(SNUM(conn)))
2297 sync_file(conn,fsp);
2299 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2300 return(UNIXERROR(ERRDOS,ERRnoaccess));
2302 outsize = set_message(outbuf,1,0,True);
2304 SSVAL(outbuf,smb_vwv0,nwritten);
2306 if (nwritten < (ssize_t)numtowrite) {
2307 CVAL(outbuf,smb_rcls) = ERRHRD;
2308 SSVAL(outbuf,smb_err,ERRdiskfull);
2311 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2312 fsp->fnum, numtowrite, nwritten));
2318 /****************************************************************************
2319 reply to a write and X
2320 ****************************************************************************/
2321 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2323 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2324 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2325 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2326 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2327 ssize_t nwritten = -1;
2328 int smb_doff = SVAL(inbuf,smb_vwv11);
2331 /* If it's an IPC, pass off the pipe handler. */
2333 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2335 CHECK_FSP(fsp,conn);
2339 data = smb_base(inbuf) + smb_doff;
2341 #ifdef LARGE_SMB_OFF_T
2342 if(CVAL(inbuf,smb_wct) == 14) {
2344 * This is a large offset (64 bit) write.
2346 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2348 #endif /* LARGE_SMB_OFF_T */
2350 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2351 return(ERROR(ERRDOS,ERRlock));
2353 if(seek_file(fsp,startpos) == -1)
2354 return(UNIXERROR(ERRDOS,ERRnoaccess));
2356 /* X/Open SMB protocol says that, unlike SMBwrite
2357 if the length is zero then NO truncation is
2358 done, just a write of zero. To truncate a file,
2363 nwritten = write_file(fsp,data,numtowrite);
2365 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2366 return(UNIXERROR(ERRDOS,ERRnoaccess));
2368 set_message(outbuf,6,0,True);
2370 SSVAL(outbuf,smb_vwv2,nwritten);
2372 if (nwritten < (ssize_t)numtowrite) {
2373 CVAL(outbuf,smb_rcls) = ERRHRD;
2374 SSVAL(outbuf,smb_err,ERRdiskfull);
2377 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2378 fsp->fnum, numtowrite, nwritten));
2380 if (lp_syncalways(SNUM(conn)) || write_through)
2381 sync_file(conn,fsp);
2383 return chain_reply(inbuf,outbuf,length,bufsize);
2387 /****************************************************************************
2389 ****************************************************************************/
2390 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2396 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2398 CHECK_FSP(fsp,conn);
2401 mode = SVAL(inbuf,smb_vwv1) & 3;
2402 startpos = IVAL(inbuf,smb_vwv2);
2406 case 0: umode = SEEK_SET; break;
2407 case 1: umode = SEEK_CUR; break;
2408 case 2: umode = SEEK_END; break;
2410 umode = SEEK_SET; break;
2413 if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2414 return(UNIXERROR(ERRDOS,ERRnoaccess));
2418 outsize = set_message(outbuf,2,0,True);
2419 SIVALS(outbuf,smb_vwv0,res);
2421 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2422 fsp->fnum, (double)startpos, mode));
2427 /****************************************************************************
2429 ****************************************************************************/
2430 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2432 int outsize = set_message(outbuf,0,0,True);
2433 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2436 CHECK_FSP(fsp,conn);
2441 file_sync_all(conn);
2443 sync_file(conn,fsp);
2446 DEBUG(3,("flush\n"));
2451 /****************************************************************************
2453 ****************************************************************************/
2454 int reply_exit(connection_struct *conn,
2455 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2457 int outsize = set_message(outbuf,0,0,True);
2458 DEBUG(3,("exit\n"));
2464 /****************************************************************************
2465 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2466 ****************************************************************************/
2467 int reply_close(connection_struct *conn,
2468 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2472 int32 eclass = 0, err = 0;
2473 files_struct *fsp = NULL;
2475 outsize = set_message(outbuf,0,0,True);
2477 /* If it's an IPC, pass off to the pipe handler. */
2479 return reply_pipe_close(conn, inbuf,outbuf);
2482 fsp = file_fsp(inbuf,smb_vwv0);
2485 * We can only use CHECK_FSP if we know it's not a directory.
2488 if(!fsp || !fsp->open || (fsp->conn != conn))
2489 return(ERROR(ERRDOS,ERRbadfid));
2491 if(HAS_CACHED_ERROR(fsp)) {
2492 eclass = fsp->wbmpx_ptr->wr_errclass;
2493 err = fsp->wbmpx_ptr->wr_error;
2496 if(fsp->is_directory) {
2498 * Special case - close NT SMB directory
2501 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2502 close_directory(fsp);
2505 * Close ordinary file.
2509 * If there was a modify time outstanding,
2510 * try and set it here.
2512 if(fsp->pending_modtime)
2513 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2516 * Now take care of any time sent in the close.
2518 mtime = make_unix_date3(inbuf+smb_vwv1);
2520 /* try and set the date */
2521 set_filetime(conn, fsp->fsp_name,mtime);
2523 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2524 fsp->fd_ptr->fd, fsp->fnum,
2525 conn->num_files_open));
2527 close_file(fsp,True);
2530 /* We have a cached error */
2532 return(ERROR(eclass,err));
2538 /****************************************************************************
2539 reply to a writeclose (Core+ protocol)
2540 ****************************************************************************/
2541 int reply_writeclose(connection_struct *conn,
2542 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2545 ssize_t nwritten = -1;
2550 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2552 CHECK_FSP(fsp,conn);
2556 numtowrite = SVAL(inbuf,smb_vwv1);
2557 startpos = IVAL(inbuf,smb_vwv2);
2558 mtime = make_unix_date3(inbuf+smb_vwv4);
2559 data = smb_buf(inbuf) + 1;
2561 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2562 return(ERROR(ERRDOS,ERRlock));
2564 if(seek_file(fsp,startpos) == -1)
2565 return(UNIXERROR(ERRDOS,ERRnoaccess));
2567 nwritten = write_file(fsp,data,numtowrite);
2569 set_filetime(conn, fsp->fsp_name,mtime);
2571 close_file(fsp,True);
2573 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2574 fsp->fnum, numtowrite, nwritten,
2575 conn->num_files_open));
2578 return(UNIXERROR(ERRDOS,ERRnoaccess));
2580 outsize = set_message(outbuf,1,0,True);
2582 SSVAL(outbuf,smb_vwv0,nwritten);
2587 /****************************************************************************
2589 ****************************************************************************/
2590 int reply_lock(connection_struct *conn,
2591 char *inbuf,char *outbuf, int length, int dum_buffsize)
2593 int outsize = set_message(outbuf,0,0,True);
2594 SMB_OFF_T count,offset;
2597 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2599 CHECK_FSP(fsp,conn);
2602 count = IVAL(inbuf,smb_vwv1);
2603 offset = IVAL(inbuf,smb_vwv3);
2605 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2606 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2608 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2609 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2611 * A blocking lock was requested. Package up
2612 * this smb into a queued request and push it
2613 * onto the blocking lock queue.
2615 if(push_blocking_lock_request(inbuf, length, -1, 0))
2618 return (ERROR(eclass,ecode));
2625 /****************************************************************************
2627 ****************************************************************************/
2628 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2630 int outsize = set_message(outbuf,0,0,True);
2631 SMB_OFF_T count,offset;
2634 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2636 CHECK_FSP(fsp,conn);
2639 count = IVAL(inbuf,smb_vwv1);
2640 offset = IVAL(inbuf,smb_vwv3);
2642 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2643 return (ERROR(eclass,ecode));
2645 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2646 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2652 /****************************************************************************
2654 ****************************************************************************/
2655 int reply_tdis(connection_struct *conn,
2656 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2658 int outsize = set_message(outbuf,0,0,True);
2661 vuid = SVAL(inbuf,smb_uid);
2664 DEBUG(4,("Invalid connection in tdis\n"));
2665 return(ERROR(ERRSRV,ERRinvnid));
2670 close_cnum(conn,vuid);
2677 /****************************************************************************
2679 ****************************************************************************/
2680 int reply_echo(connection_struct *conn,
2681 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2683 int smb_reverb = SVAL(inbuf,smb_vwv0);
2685 int data_len = smb_buflen(inbuf);
2686 int outsize = set_message(outbuf,1,data_len,True);
2688 /* copy any incoming data back out */
2690 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2692 if (smb_reverb > 100) {
2693 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2697 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2698 SSVAL(outbuf,smb_vwv0,seq_num);
2700 smb_setlen(outbuf,outsize - 4);
2702 send_smb(Client,outbuf);
2705 DEBUG(3,("echo %d times\n", smb_reverb));
2711 /****************************************************************************
2712 reply to a printopen
2713 ****************************************************************************/
2714 int reply_printopen(connection_struct *conn,
2715 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2722 *fname = *fname2 = 0;
2724 if (!CAN_PRINT(conn))
2725 return(ERROR(ERRDOS,ERRnoaccess));
2730 pstrcpy(s,smb_buf(inbuf)+1);
2733 if (!(isalnum((int)*p) || strchr("._-",*p)))
2738 if (strlen(s) > 10) s[10] = 0;
2740 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2745 return(ERROR(ERRSRV,ERRnofids));
2747 pstrcpy(fname2,(char *)mktemp(fname));
2749 if (!check_name(fname2,conn)) {
2751 return(ERROR(ERRDOS,ERRnoaccess));
2754 /* Open for exclusive use, write only. */
2755 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2756 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2760 return(UNIXERROR(ERRDOS,ERRnoaccess));
2763 /* force it to be a print file */
2764 fsp->print_file = True;
2766 outsize = set_message(outbuf,1,0,True);
2767 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2769 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2770 fname2, fsp->fd_ptr->fd, fsp->fnum));
2776 /****************************************************************************
2777 reply to a printclose
2778 ****************************************************************************/
2779 int reply_printclose(connection_struct *conn,
2780 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2782 int outsize = set_message(outbuf,0,0,True);
2783 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2785 CHECK_FSP(fsp,conn);
2788 if (!CAN_PRINT(conn))
2789 return(ERROR(ERRDOS,ERRnoaccess));
2791 DEBUG(3,("printclose fd=%d fnum=%d\n",
2792 fsp->fd_ptr->fd,fsp->fnum));
2794 close_file(fsp,True);
2800 /****************************************************************************
2801 reply to a printqueue
2802 ****************************************************************************/
2803 int reply_printqueue(connection_struct *conn,
2804 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2806 int outsize = set_message(outbuf,2,3,True);
2807 int max_count = SVAL(inbuf,smb_vwv0);
2808 int start_index = SVAL(inbuf,smb_vwv1);
2810 /* we used to allow the client to get the cnum wrong, but that
2811 is really quite gross and only worked when there was only
2812 one printer - I think we should now only accept it if they
2813 get it right (tridge) */
2814 if (!CAN_PRINT(conn))
2815 return(ERROR(ERRDOS,ERRnoaccess));
2817 SSVAL(outbuf,smb_vwv0,0);
2818 SSVAL(outbuf,smb_vwv1,0);
2819 CVAL(smb_buf(outbuf),0) = 1;
2820 SSVAL(smb_buf(outbuf),1,0);
2822 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2823 start_index, max_count));
2826 print_queue_struct *queue = NULL;
2827 char *p = smb_buf(outbuf) + 3;
2828 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2829 int num_to_get = ABS(max_count);
2830 int first = (max_count>0?start_index:start_index+max_count+1);
2836 num_to_get = MIN(num_to_get,count-first);
2839 for (i=first;i<first+num_to_get;i++) {
2840 put_dos_date2(p,0,queue[i].time);
2841 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2842 SSVAL(p,5,printjob_encode(SNUM(conn),
2844 SIVAL(p,7,queue[i].size);
2846 StrnCpy(p+12,queue[i].user,16);
2851 outsize = set_message(outbuf,2,28*count+3,False);
2852 SSVAL(outbuf,smb_vwv0,count);
2853 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2854 CVAL(smb_buf(outbuf),0) = 1;
2855 SSVAL(smb_buf(outbuf),1,28*count);
2858 if (queue) free(queue);
2860 DEBUG(3,("%d entries returned in queue\n",count));
2867 /****************************************************************************
2868 reply to a printwrite
2869 ****************************************************************************/
2870 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2873 int outsize = set_message(outbuf,0,0,True);
2875 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2877 if (!CAN_PRINT(conn))
2878 return(ERROR(ERRDOS,ERRnoaccess));
2880 CHECK_FSP(fsp,conn);
2884 numtowrite = SVAL(smb_buf(inbuf),1);
2885 data = smb_buf(inbuf) + 3;
2887 if (write_file(fsp,data,numtowrite) != numtowrite)
2888 return(UNIXERROR(ERRDOS,ERRnoaccess));
2890 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2896 /****************************************************************************
2898 ****************************************************************************/
2899 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2902 int outsize,ret= -1;
2903 BOOL bad_path = False;
2905 pstrcpy(directory,smb_buf(inbuf) + 1);
2906 unix_convert(directory,conn,0,&bad_path,NULL);
2908 if (check_name(directory, conn))
2909 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2913 if((errno == ENOENT) && bad_path)
2915 unix_ERR_class = ERRDOS;
2916 unix_ERR_code = ERRbadpath;
2918 return(UNIXERROR(ERRDOS,ERRnoaccess));
2921 outsize = set_message(outbuf,0,0,True);
2923 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2928 /****************************************************************************
2929 Static function used by reply_rmdir to delete an entire directory
2931 ****************************************************************************/
2932 static BOOL recursive_rmdir(char *directory)
2936 void *dirptr = OpenDir(NULL, directory, False);
2941 while((dname = ReadDirName(dirptr)))
2946 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2949 /* Construct the full name. */
2950 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2956 pstrcpy(fullname, directory);
2957 pstrcat(fullname, "/");
2958 pstrcat(fullname, dname);
2960 if(dos_lstat(fullname, &st) != 0)
2966 if(st.st_mode & S_IFDIR)
2968 if(recursive_rmdir(fullname)!=0)
2973 if(dos_rmdir(fullname) != 0)
2979 else if(dos_unlink(fullname) != 0)
2989 /****************************************************************************
2991 ****************************************************************************/
2992 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2997 BOOL bad_path = False;
2999 pstrcpy(directory,smb_buf(inbuf) + 1);
3000 unix_convert(directory,conn, NULL,&bad_path,NULL);
3002 if (check_name(directory,conn))
3005 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3006 ok = (dos_rmdir(directory) == 0);
3007 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
3009 /* Check to see if the only thing in this directory are
3010 vetoed files/directories. If so then delete them and
3011 retry. If we fail to delete any of them (and we *don't*
3012 do a recursive delete) then fail the rmdir. */
3013 BOOL all_veto_files = True;
3015 void *dirptr = OpenDir(conn, directory, False);
3019 int dirpos = TellDir(dirptr);
3020 while ((dname = ReadDirName(dirptr)))
3022 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3024 if(!IS_VETO_PATH(conn, dname))
3026 all_veto_files = False;
3032 SeekDir(dirptr,dirpos);
3033 while ((dname = ReadDirName(dirptr)))
3038 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3041 /* Construct the full name. */
3042 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3047 pstrcpy(fullname, directory);
3048 pstrcat(fullname, "/");
3049 pstrcat(fullname, dname);
3051 if(dos_lstat(fullname, &st) != 0)
3053 if(st.st_mode & S_IFDIR)
3055 if(lp_recursive_veto_delete(SNUM(conn)))
3057 if(recursive_rmdir(fullname) != 0)
3060 if(dos_rmdir(fullname) != 0)
3063 else if(dos_unlink(fullname) != 0)
3067 /* Retry the rmdir */
3068 ok = (dos_rmdir(directory) == 0);
3078 DEBUG(3,("couldn't remove directory %s : %s\n",
3079 directory,strerror(errno)));
3084 if((errno == ENOENT) && bad_path)
3086 unix_ERR_class = ERRDOS;
3087 unix_ERR_code = ERRbadpath;
3089 return(UNIXERROR(ERRDOS,ERRbadpath));
3092 outsize = set_message(outbuf,0,0,True);
3094 DEBUG( 3, ( "rmdir %s\n", directory ) );
3100 /*******************************************************************
3101 resolve wildcards in a filename rename
3102 ********************************************************************/
3103 static BOOL resolve_wildcards(char *name1,char *name2)
3105 fstring root1,root2;
3109 name1 = strrchr(name1,'/');
3110 name2 = strrchr(name2,'/');
3112 if (!name1 || !name2) return(False);
3114 fstrcpy(root1,name1);
3115 fstrcpy(root2,name2);
3116 p = strrchr(root1,'.');
3123 p = strrchr(root2,'.');
3155 pstrcpy(name2,root2);
3158 pstrcat(name2,ext2);
3164 /*******************************************************************
3165 check if a user is allowed to rename a file
3166 ********************************************************************/
3167 static BOOL can_rename(char *fname,connection_struct *conn)
3169 SMB_STRUCT_STAT sbuf;
3171 if (!CAN_WRITE(conn)) return(False);
3173 if (dos_lstat(fname,&sbuf) != 0) return(False);
3174 if (!check_file_sharing(conn,fname,True)) return(False);
3179 /****************************************************************************
3180 The guts of the rename command, split out so it may be called by the NT SMB
3182 ****************************************************************************/
3183 int rename_internals(connection_struct *conn,
3184 char *inbuf, char *outbuf, char *name,
3185 char *newname, BOOL replace_if_exists)
3189 pstring newname_last_component;
3192 BOOL bad_path1 = False;
3193 BOOL bad_path2 = False;
3195 int error = ERRnoaccess;
3198 *directory = *mask = 0;
3200 unix_convert(name,conn,0,&bad_path1,NULL);
3201 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3204 * Split the old name into directory and last component
3205 * strings. Note that unix_convert may have stripped off a
3206 * leading ./ from both name and newname if the rename is
3207 * at the root of the share. We need to make sure either both
3208 * name and newname contain a / character or neither of them do
3209 * as this is checked in resolve_wildcards().
3212 p = strrchr(name,'/');
3214 pstrcpy(directory,".");
3218 pstrcpy(directory,name);
3220 *p = '/'; /* Replace needed for exceptional test below. */
3223 if (is_mangled(mask))
3224 check_mangled_cache( mask );
3226 has_wild = strchr(mask,'*') || strchr(mask,'?');
3230 * No wildcards - just process the one file.
3232 BOOL is_short_name = is_8_3(name, True);
3234 /* Add a terminating '/' to the directory name. */
3235 pstrcat(directory,"/");
3236 pstrcat(directory,mask);
3238 /* Ensure newname contains a '/' also */
3239 if(strrchr(newname,'/') == 0) {
3242 pstrcpy(tmpstr, "./");
3243 pstrcat(tmpstr, newname);
3244 pstrcpy(newname, tmpstr);
3247 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",
3248 case_sensitive, case_preserve, short_case_preserve, directory,
3249 newname, newname_last_component, is_short_name));
3252 * Check for special case with case preserving and not
3253 * case sensitive, if directory and newname are identical,
3254 * and the old last component differs from the original
3255 * last component only by case, then we should allow
3256 * the rename (user is trying to change the case of the
3259 if((case_sensitive == False) &&
3260 (((case_preserve == True) &&
3261 (is_short_name == False)) ||
3262 ((short_case_preserve == True) &&
3263 (is_short_name == True))) &&
3264 strcsequal(directory, newname)) {
3265 pstring newname_modified_last_component;
3268 * Get the last component of the modified name.
3269 * Note that we guarantee that newname contains a '/'
3272 p = strrchr(newname,'/');
3273 pstrcpy(newname_modified_last_component,p+1);
3275 if(strcsequal(newname_modified_last_component,
3276 newname_last_component) == False) {
3278 * Replace the modified last component with
3281 pstrcpy(p+1, newname_last_component);
3285 if(replace_if_exists) {
3287 * NT SMB specific flag - rename can overwrite
3288 * file with the same name so don't check for
3291 if(resolve_wildcards(directory,newname) &&
3292 can_rename(directory,conn) &&
3293 !dos_rename(directory,newname))
3296 if (resolve_wildcards(directory,newname) &&
3297 can_rename(directory,conn) &&
3298 !dos_file_exist(newname,NULL) &&
3299 !dos_rename(directory,newname))
3303 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3304 directory,newname));
3306 if (!count) exists = dos_file_exist(directory,NULL);
3307 if (!count && exists && dos_file_exist(newname,NULL)) {
3313 * Wildcards - process each file that matches.
3315 void *dirptr = NULL;
3319 if (check_name(directory,conn))
3320 dirptr = OpenDir(conn, directory, True);
3325 if (strequal(mask,"????????.???"))
3328 while ((dname = ReadDirName(dirptr))) {
3330 pstrcpy(fname,dname);
3332 if(!mask_match(fname, mask, case_sensitive, False))
3335 error = ERRnoaccess;
3336 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3337 if (!can_rename(fname,conn)) {
3338 DEBUG(6,("rename %s refused\n", fname));
3341 pstrcpy(destname,newname);
3343 if (!resolve_wildcards(fname,destname)) {
3344 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3348 if (!replace_if_exists && dos_file_exist(destname,NULL)) {
3349 DEBUG(6,("dos_file_exist %s\n", destname));
3354 if (!dos_rename(fname,destname))
3356 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3364 return(ERROR(ERRDOS,error));
3366 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3367 unix_ERR_class = ERRDOS;
3368 unix_ERR_code = ERRbadpath;
3370 return(UNIXERROR(ERRDOS,error));
3377 /****************************************************************************
3379 ****************************************************************************/
3381 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3387 pstrcpy(name,smb_buf(inbuf) + 1);
3388 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3390 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3392 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3394 outsize = set_message(outbuf,0,0,True);
3399 /*******************************************************************
3400 copy a file as part of a reply_copy
3401 ******************************************************************/
3403 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3404 int count,BOOL target_is_directory)
3409 files_struct *fsp1,*fsp2;
3412 pstrcpy(dest,dest1);
3413 if (target_is_directory) {
3414 char *p = strrchr(src,'/');
3423 if (!dos_file_exist(src,&st))
3430 open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3431 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3438 if (!target_is_directory && count)
3443 close_file(fsp1,False);
3446 open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3447 ofun,st.st_mode,0,&Access,&action);
3450 close_file(fsp1,False);
3455 if ((ofun&3) == 1) {
3456 if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3457 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3460 * Stop the copy from occurring.
3468 ret = transfer_file(fsp1->fd_ptr->fd,
3469 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3471 close_file(fsp1,False);
3472 close_file(fsp2,False);
3474 return(ret == st.st_size);
3479 /****************************************************************************
3480 reply to a file copy.
3481 ****************************************************************************/
3482 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3487 pstring mask,newname;
3490 int error = ERRnoaccess;
3493 int tid2 = SVAL(inbuf,smb_vwv0);
3494 int ofun = SVAL(inbuf,smb_vwv1);
3495 int flags = SVAL(inbuf,smb_vwv2);
3496 BOOL target_is_directory=False;
3497 BOOL bad_path1 = False;
3498 BOOL bad_path2 = False;
3500 *directory = *mask = 0;
3502 pstrcpy(name,smb_buf(inbuf));
3503 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3505 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3507 if (tid2 != conn->cnum) {
3508 /* can't currently handle inter share copies XXXX */
3509 DEBUG(3,("Rejecting inter-share copy\n"));
3510 return(ERROR(ERRSRV,ERRinvdevice));
3513 unix_convert(name,conn,0,&bad_path1,NULL);
3514 unix_convert(newname,conn,0,&bad_path2,NULL);
3516 target_is_directory = dos_directory_exist(newname,NULL);
3518 if ((flags&1) && target_is_directory) {
3519 return(ERROR(ERRDOS,ERRbadfile));
3522 if ((flags&2) && !target_is_directory) {
3523 return(ERROR(ERRDOS,ERRbadpath));
3526 if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
3527 /* wants a tree copy! XXXX */
3528 DEBUG(3,("Rejecting tree copy\n"));
3529 return(ERROR(ERRSRV,ERRerror));
3532 p = strrchr(name,'/');
3534 pstrcpy(directory,"./");
3538 pstrcpy(directory,name);
3542 if (is_mangled(mask))
3543 check_mangled_cache( mask );
3545 has_wild = strchr(mask,'*') || strchr(mask,'?');
3548 pstrcat(directory,"/");
3549 pstrcat(directory,mask);
3550 if (resolve_wildcards(directory,newname) &&
3551 copy_file(directory,newname,conn,ofun,
3552 count,target_is_directory)) count++;
3553 if (!count) exists = dos_file_exist(directory,NULL);
3555 void *dirptr = NULL;
3559 if (check_name(directory,conn))
3560 dirptr = OpenDir(conn, directory, True);
3566 if (strequal(mask,"????????.???"))
3569 while ((dname = ReadDirName(dirptr)))
3572 pstrcpy(fname,dname);
3574 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3576 error = ERRnoaccess;
3577 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3578 pstrcpy(destname,newname);
3579 if (resolve_wildcards(fname,destname) &&
3580 copy_file(directory,newname,conn,ofun,
3581 count,target_is_directory)) count++;
3582 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3590 return(ERROR(ERRDOS,error));
3593 if((errno == ENOENT) && (bad_path1 || bad_path2))
3595 unix_ERR_class = ERRDOS;
3596 unix_ERR_code = ERRbadpath;
3598 return(UNIXERROR(ERRDOS,error));
3602 outsize = set_message(outbuf,1,0,True);
3603 SSVAL(outbuf,smb_vwv0,count);
3608 /****************************************************************************
3610 ****************************************************************************/
3611 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3619 if (!CAN_SETDIR(snum))
3620 return(ERROR(ERRDOS,ERRnoaccess));
3622 pstrcpy(newdir,smb_buf(inbuf) + 1);
3625 if (strlen(newdir) == 0) {
3628 ok = dos_directory_exist(newdir,NULL);
3630 string_set(&conn->connectpath,newdir);
3635 return(ERROR(ERRDOS,ERRbadpath));
3637 outsize = set_message(outbuf,0,0,True);
3638 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3640 DEBUG(3,("setdir %s\n", newdir));
3645 /****************************************************************************
3646 reply to a lockingX request
3647 ****************************************************************************/
3648 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3650 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3651 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3653 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3655 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3656 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3657 SMB_OFF_T count = 0, offset = 0;
3658 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3661 uint32 ecode=0, dummy2;
3662 int eclass=0, dummy1;
3663 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3664 CHECK_FSP(fsp,conn);
3667 data = smb_buf(inbuf);
3669 /* Check if this is an oplock break on a file
3670 we have granted an oplock on.
3672 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3675 SMB_DEV_T dev = fsp->fd_ptr->dev;
3676 SMB_INO_T inode = fsp->fd_ptr->inode;
3678 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3681 * Make sure we have granted an oplock on this file.
3683 if(!fsp->granted_oplock)
3685 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3686 no oplock granted on this file.\n", fsp->fnum));
3687 return ERROR(ERRDOS,ERRlock);
3690 /* Remove the oplock flag from the sharemode. */
3691 lock_share_entry(fsp->conn, dev, inode, &token);
3692 if(remove_share_oplock(token, fsp)==False) {
3694 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3695 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3697 unlock_share_entry(fsp->conn, dev, inode, token);
3699 unlock_share_entry(fsp->conn, dev, inode, token);
3701 /* Clear the granted flag and return. */
3702 fsp->granted_oplock = False;
3705 /* if this is a pure oplock break request then don't send a reply */
3706 if (num_locks == 0 && num_ulocks == 0)
3708 /* Sanity check - ensure a pure oplock break is not a
3710 if(CVAL(inbuf,smb_vwv0) != 0xff)
3711 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3712 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3717 /* Data now points at the beginning of the list
3718 of smb_unlkrng structs */
3719 for(i = 0; i < (int)num_ulocks; i++) {
3720 if(!large_file_format) {
3721 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3722 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3724 #ifdef LARGE_SMB_OFF_T
3726 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3727 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3728 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3729 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3731 #endif /* LARGE_SMB_OFF_T */
3733 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3734 (double)offset, (double)count, fsp->fsp_name ));
3736 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3737 return ERROR(eclass,ecode);
3740 /* Setup the timeout in seconds. */
3741 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3743 /* Now do any requested locks */
3744 data += ((large_file_format ? 20 : 10)*num_ulocks);
3746 /* Data now points at the beginning of the list
3747 of smb_lkrng structs */
3749 for(i = 0; i < (int)num_locks; i++) {
3750 if(!large_file_format) {
3751 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3752 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3754 #ifdef LARGE_SMB_OFF_T
3756 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3757 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3758 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3759 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3761 #endif /* LARGE_SMB_OFF_T */
3763 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3764 (double)offset, (double)count, fsp->fsp_name ));
3766 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3768 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3770 * A blocking lock was requested. Package up
3771 * this smb into a queued request and push it
3772 * onto the blocking lock queue.
3774 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3781 /* If any of the above locks failed, then we must unlock
3782 all of the previous locks (X/Open spec). */
3783 if(i != num_locks && num_locks != 0) {
3784 for(; i >= 0; i--) {
3785 if(!large_file_format) {
3786 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3787 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3789 #ifdef LARGE_SMB_OFF_T
3791 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3792 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3793 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3794 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3796 #endif /* LARGE_SMB_OFF_T */
3798 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3800 return ERROR(eclass,ecode);
3803 set_message(outbuf,2,0,True);
3805 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3806 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3808 return chain_reply(inbuf,outbuf,length,bufsize);
3812 /****************************************************************************
3813 reply to a SMBreadbmpx (read block multiplex) request
3814 ****************************************************************************/
3815 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3826 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3828 /* this function doesn't seem to work - disable by default */
3830 return(ERROR(ERRSRV,ERRuseSTD));
3832 outsize = set_message(outbuf,8,0,True);
3834 CHECK_FSP(fsp,conn);
3838 startpos = IVAL(inbuf,smb_vwv1);
3839 maxcount = SVAL(inbuf,smb_vwv3);
3841 data = smb_buf(outbuf);
3842 pad = ((long)data)%4;
3843 if (pad) pad = 4 - pad;
3846 max_per_packet = bufsize-(outsize+pad);
3850 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3851 return(ERROR(ERRDOS,ERRlock));
3855 size_t N = MIN(max_per_packet,tcount-total_read);
3857 nread = read_file(fsp,data,startpos,N);
3859 if (nread <= 0) nread = 0;
3861 if (nread < (ssize_t)N)
3862 tcount = total_read + nread;
3864 set_message(outbuf,8,nread,False);
3865 SIVAL(outbuf,smb_vwv0,startpos);
3866 SSVAL(outbuf,smb_vwv2,tcount);
3867 SSVAL(outbuf,smb_vwv6,nread);
3868 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3870 send_smb(Client,outbuf);
3872 total_read += nread;
3875 while (total_read < (ssize_t)tcount);
3880 /****************************************************************************
3881 reply to a SMBwritebmpx (write block multiplex primary) request
3882 ****************************************************************************/
3883 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3886 ssize_t nwritten = -1;
3893 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3895 CHECK_FSP(fsp,conn);
3899 tcount = SVAL(inbuf,smb_vwv1);
3900 startpos = IVAL(inbuf,smb_vwv3);
3901 write_through = BITSETW(inbuf+smb_vwv7,0);
3902 numtowrite = SVAL(inbuf,smb_vwv10);
3903 smb_doff = SVAL(inbuf,smb_vwv11);
3905 data = smb_base(inbuf) + smb_doff;
3907 /* If this fails we need to send an SMBwriteC response,
3908 not an SMBwritebmpx - set this up now so we don't forget */
3909 CVAL(outbuf,smb_com) = SMBwritec;
3911 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3912 return(ERROR(ERRDOS,ERRlock));
3914 if(seek_file(fsp,startpos) == -1)
3915 return(UNIXERROR(ERRDOS,ERRnoaccess));
3917 nwritten = write_file(fsp,data,numtowrite);
3919 if(lp_syncalways(SNUM(conn)) || write_through)
3920 sync_file(conn,fsp);
3922 if(nwritten < (ssize_t)numtowrite)
3923 return(UNIXERROR(ERRHRD,ERRdiskfull));
3925 /* If the maximum to be written to this file
3926 is greater than what we just wrote then set
3927 up a secondary struct to be attached to this
3928 fd, we will use this to cache error messages etc. */
3929 if((ssize_t)tcount > nwritten)
3931 write_bmpx_struct *wbms;
3932 if(fsp->wbmpx_ptr != NULL)
3933 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3935 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3938 DEBUG(0,("Out of memory in reply_readmpx\n"));
3939 return(ERROR(ERRSRV,ERRnoresource));
3941 wbms->wr_mode = write_through;
3942 wbms->wr_discard = False; /* No errors yet */
3943 wbms->wr_total_written = nwritten;
3944 wbms->wr_errclass = 0;
3946 fsp->wbmpx_ptr = wbms;
3949 /* We are returning successfully, set the message type back to
3951 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3953 outsize = set_message(outbuf,1,0,True);
3955 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3957 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3958 fsp->fnum, numtowrite, nwritten ) );
3960 if (write_through && tcount==nwritten) {
3961 /* we need to send both a primary and a secondary response */
3962 smb_setlen(outbuf,outsize - 4);
3963 send_smb(Client,outbuf);
3965 /* now the secondary */
3966 outsize = set_message(outbuf,1,0,True);
3967 CVAL(outbuf,smb_com) = SMBwritec;
3968 SSVAL(outbuf,smb_vwv0,nwritten);
3975 /****************************************************************************
3976 reply to a SMBwritebs (write block multiplex secondary) request
3977 ****************************************************************************/
3978 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3981 ssize_t nwritten = -1;
3988 write_bmpx_struct *wbms;
3989 BOOL send_response = False;
3990 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3992 CHECK_FSP(fsp,conn);
3995 tcount = SVAL(inbuf,smb_vwv1);
3996 startpos = IVAL(inbuf,smb_vwv2);
3997 numtowrite = SVAL(inbuf,smb_vwv6);
3998 smb_doff = SVAL(inbuf,smb_vwv7);
4000 data = smb_base(inbuf) + smb_doff;
4002 /* We need to send an SMBwriteC response, not an SMBwritebs */
4003 CVAL(outbuf,smb_com) = SMBwritec;
4005 /* This fd should have an auxiliary struct attached,
4006 check that it does */
4007 wbms = fsp->wbmpx_ptr;
4008 if(!wbms) return(-1);
4010 /* If write through is set we can return errors, else we must
4012 write_through = wbms->wr_mode;
4014 /* Check for an earlier error */
4015 if(wbms->wr_discard)
4016 return -1; /* Just discard the packet */
4018 if(seek_file(fsp,startpos) == -1)
4022 /* We are returning an error - we can delete the aux struct */
4023 if (wbms) free((char *)wbms);
4024 fsp->wbmpx_ptr = NULL;
4025 return(UNIXERROR(ERRDOS,ERRnoaccess));
4027 return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
4030 nwritten = write_file(fsp,data,numtowrite);
4032 if(lp_syncalways(SNUM(conn)) || write_through)
4033 sync_file(conn,fsp);
4035 if (nwritten < (ssize_t)numtowrite)
4039 /* We are returning an error - we can delete the aux struct */
4040 if (wbms) free((char *)wbms);
4041 fsp->wbmpx_ptr = NULL;
4042 return(ERROR(ERRHRD,ERRdiskfull));
4044 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4047 /* Increment the total written, if this matches tcount
4048 we can discard the auxiliary struct (hurrah !) and return a writeC */
4049 wbms->wr_total_written += nwritten;
4050 if(wbms->wr_total_written >= tcount)
4054 outsize = set_message(outbuf,1,0,True);
4055 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4056 send_response = True;
4060 fsp->wbmpx_ptr = NULL;
4070 /****************************************************************************
4071 reply to a SMBsetattrE
4072 ****************************************************************************/
4073 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4075 struct utimbuf unix_times;
4077 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4079 outsize = set_message(outbuf,0,0,True);
4081 CHECK_FSP(fsp,conn);
4084 /* Convert the DOS times into unix times. Ignore create
4085 time as UNIX can't set this.
4087 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4088 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4091 * Patch from Ray Frush <frush@engr.colostate.edu>
4092 * Sometimes times are sent as zero - ignore them.
4095 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4097 /* Ignore request */
4100 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4101 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4105 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4107 /* set modify time = to access time if modify time was 0 */
4108 unix_times.modtime = unix_times.actime;
4111 /* Set the date on this file */
4112 if(file_utime(conn, fsp->fsp_name, &unix_times))
4113 return(ERROR(ERRDOS,ERRnoaccess));
4115 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4116 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4122 /****************************************************************************
4123 reply to a SMBgetattrE
4124 ****************************************************************************/
4125 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4127 SMB_STRUCT_STAT sbuf;
4130 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4132 outsize = set_message(outbuf,11,0,True);
4134 CHECK_FSP(fsp,conn);
4137 /* Do an fstat on this file */
4138 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4139 return(UNIXERROR(ERRDOS,ERRnoaccess));
4141 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4143 /* Convert the times into dos times. Set create
4144 date to be last modify date as UNIX doesn't save
4146 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4147 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4148 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4151 SIVAL(outbuf,smb_vwv6,0);
4152 SIVAL(outbuf,smb_vwv8,0);
4156 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4157 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4159 SSVAL(outbuf,smb_vwv10, mode);
4161 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));