2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
31 /* look in server.c for some explanation of these variables */
33 extern int DEBUGLEVEL;
36 extern char magic_char;
37 extern BOOL case_sensitive;
38 extern BOOL case_preserve;
39 extern BOOL short_case_preserve;
40 extern pstring sesssetup_user;
41 extern fstring global_myworkgroup;
43 extern int global_oplock_break;
44 uint32 global_client_caps = 0;
47 /****************************************************************************
48 report a possible attack via the password buffer overflow bug
49 ****************************************************************************/
50 static void overflow_attack(int len)
54 dbgtext( "ERROR: Invalid password length %d.\n", len );
55 dbgtext( "Your machine may be under attack by someone " );
56 dbgtext( "attempting to exploit an old bug.\n" );
57 dbgtext( "Attack was from IP = %s.\n", client_addr(Client) );
59 exit_server("possible attack");
63 /****************************************************************************
64 does _both_ nt->unix and unix->unix username remappings.
65 ****************************************************************************/
66 static void map_nt_and_unix_username(const char *domain, char *user)
72 * Pass the user through the NT -> unix user mapping
76 if (lp_server_role() != ROLE_DOMAIN_NONE)
78 memset(nt_username, 0, sizeof(nt_username));
81 slprintf(nt_username, sizeof(nt_username)-1, "%s\\%s",
86 fstrcpy(nt_username, user);
89 if (lookupsmbpwntnam(nt_username, &gmep))
91 fstrcpy(user, gmep.unix_name);
96 * Pass the user through the unix -> unix user mapping
100 (void)map_username(user);
103 * Do any UNIX username case mangling.
105 (void)Get_Pwnam( user, True);
108 /****************************************************************************
109 reply to an special message
110 ****************************************************************************/
111 int reply_special(char *inbuf,char *outbuf)
114 int msg_type = CVAL(inbuf,0);
115 int msg_flags = CVAL(inbuf,1);
117 extern fstring remote_machine;
118 extern fstring local_machine;
124 bzero(outbuf,smb_size);
126 smb_setlen(outbuf,0);
129 case 0x81: /* session request */
130 CVAL(outbuf,0) = 0x82;
132 if (name_len(inbuf+4) > 50 ||
133 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
134 DEBUG(0,("Invalid name length in session request\n"));
137 name_extract(inbuf,4,name1);
138 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
139 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
142 fstrcpy(remote_machine,name2);
143 remote_machine[15] = 0;
144 trim_string(remote_machine," "," ");
145 strlower(remote_machine);
147 fstrcpy(local_machine,name1);
148 len = strlen(local_machine);
150 name_type = local_machine[15];
151 local_machine[15] = 0;
153 trim_string(local_machine," "," ");
154 strlower(local_machine);
156 if (name_type == 'R') {
157 /* We are being asked for a pathworks session ---
159 CVAL(outbuf, 0) = 0x83;
163 add_session_user(remote_machine);
165 reload_services(True);
169 claim_connection(NULL,"STATUS.",MAXSTATUS,True);
174 case 0x89: /* session keepalive request
175 (some old clients produce this?) */
176 CVAL(outbuf,0) = 0x85;
180 case 0x82: /* positive session response */
181 case 0x83: /* negative session response */
182 case 0x84: /* retarget session response */
183 DEBUG(0,("Unexpected session response\n"));
186 case 0x85: /* session keepalive */
191 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
192 msg_type, msg_flags));
198 /*******************************************************************
199 work out what error to give to a failed connection
200 ********************************************************************/
201 static int connection_error(char *inbuf,char *outbuf,int ecode)
203 if (ecode == ERRnoipc) {
204 return(ERROR(ERRDOS,ERRnoipc));
207 return(ERROR(ERRSRV,ecode));
212 /****************************************************************************
213 parse a share descriptor string
214 ****************************************************************************/
215 static void parse_connect(char *p,char *service,char *user,
216 char *password,int *pwlen,char *dev)
220 DEBUG(4,("parsing connect string %s\n",p));
222 p2 = strrchr(p,'\\');
226 fstrcpy(service,p2+1);
231 *pwlen = strlen(password);
238 p = strchr(service,'%');
249 /****************************************************************************
251 ****************************************************************************/
252 int reply_tcon(connection_struct *conn,
253 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
260 uint16 vuid = SVAL(inbuf,smb_uid);
264 *service = *user = *password = *dev = 0;
266 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
268 map_nt_and_unix_username(global_myworkgroup, user);
270 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
273 return(connection_error(inbuf,outbuf,ecode));
276 outsize = set_message(outbuf,2,0,True);
277 SSVAL(outbuf,smb_vwv0,max_recv);
278 SSVAL(outbuf,smb_vwv1,conn->cnum);
279 SSVAL(outbuf,smb_tid,conn->cnum);
281 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
282 service, user, conn->cnum));
288 /****************************************************************************
289 reply to a tcon and X
290 ****************************************************************************/
291 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
298 uint16 vuid = SVAL(inbuf,smb_uid);
299 int passlen = SVAL(inbuf,smb_vwv3);
303 *service = *user = *password = *devicename = 0;
305 /* we might have to close an old one */
306 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
307 close_cnum(conn,vuid);
310 if (passlen > MAX_PASS_LEN) {
311 overflow_attack(passlen);
314 memcpy(password,smb_buf(inbuf),passlen);
316 path = smb_buf(inbuf) + passlen;
319 if (strequal(password," "))
321 passlen = strlen(password);
324 fstrcpy(service,path+2);
325 p = strchr(service,'\\');
327 return(ERROR(ERRSRV,ERRinvnetname));
329 fstrcpy(service,p+1);
330 p = strchr(service,'%');
335 StrnCpy(devicename,path + strlen(path) + 1,6);
336 DEBUG(4,("Got device type %s\n",devicename));
338 map_nt_and_unix_username(global_myworkgroup, user);
340 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
343 return(connection_error(inbuf,outbuf,ecode));
345 if (Protocol < PROTOCOL_NT1) {
346 set_message(outbuf,2,strlen(devicename)+1,True);
347 pstrcpy(smb_buf(outbuf),devicename);
349 char *fsname = lp_fstype(SNUM(conn));
351 set_message(outbuf,3,3,True);
354 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
355 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
357 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
359 /* what does setting this bit do? It is set by NT4 and
360 may affect the ability to autorun mounted cdroms */
361 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
364 DEBUG(3,("tconX service=%s user=%s\n",
367 /* set the incoming and outgoing tid to the just created one */
368 SSVAL(inbuf,smb_tid,conn->cnum);
369 SSVAL(outbuf,smb_tid,conn->cnum);
371 return chain_reply(inbuf,outbuf,length,bufsize);
375 /****************************************************************************
376 reply to an unknown type
377 ****************************************************************************/
378 int reply_unknown(char *inbuf,char *outbuf)
381 type = CVAL(inbuf,smb_com);
383 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
384 smb_fn_name(type), type, type));
386 return(ERROR(ERRSRV,ERRunknownsmb));
390 /****************************************************************************
392 ****************************************************************************/
393 int reply_ioctl(connection_struct *conn,
394 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
396 DEBUG(3,("ignoring ioctl\n"));
398 /* we just say it succeeds and hope its all OK.
399 some day it would be nice to interpret them individually */
400 return set_message(outbuf,1,0,True);
402 return(ERROR(ERRSRV,ERRnosupport));
406 /****************************************************************************
407 always return an error: it's just a matter of which one...
408 ****************************************************************************/
409 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
410 char *smb_passwd, int smb_passlen,
411 char *smb_nt_passwd, int smb_nt_passlen)
413 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
414 if (lp_security() == SEC_USER)
416 smb_trust_acct = getsmbpwnam(user);
420 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
421 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
422 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
425 if (smb_trust_acct == NULL)
427 /* lkclXXXX: workstation entry doesn't exist */
428 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
429 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
430 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
434 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
436 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
437 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
438 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
441 if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
443 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
444 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
445 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
448 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
450 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
451 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
452 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
455 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
457 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
458 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
459 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
462 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
464 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
465 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
466 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
470 /* don't know what to do: indicate logon failure */
471 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
472 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
475 /****************************************************************************
476 Check for a valid username and password in security=server mode.
477 ****************************************************************************/
479 static BOOL check_server_security(char *orig_user, char *domain,
480 char *smb_apasswd, int smb_apasslen,
481 char *smb_ntpasswd, int smb_ntpasslen)
483 if(lp_security() != SEC_SERVER)
486 return server_validate(orig_user, domain,
487 smb_apasswd, smb_apasslen,
488 smb_ntpasswd, smb_ntpasslen);
491 /****************************************************************************
492 Check for a valid username and password in security=domain mode.
493 ****************************************************************************/
495 static BOOL check_domain_security(char *orig_user, char *domain,
496 char *smb_apasswd, int smb_apasslen,
497 char *smb_ntpasswd, int smb_ntpasslen)
499 if(lp_security() != SEC_DOMAIN)
502 return domain_client_validate(orig_user, domain,
503 smb_apasswd, smb_apasslen,
504 smb_ntpasswd, smb_ntpasslen);
507 /****************************************************************************
508 reply to a session setup command
509 ****************************************************************************/
511 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
514 uchar user_sess_key[16];
518 int smb_apasslen = 0;
520 int smb_ntpasslen = 0;
521 pstring smb_ntpasswd;
522 BOOL valid_nt_password = False;
526 static BOOL done_sesssetup = False;
527 BOOL doencrypt = SMBENCRYPT();
533 smb_bufsize = SVAL(inbuf,smb_vwv2);
535 if (Protocol < PROTOCOL_NT1) {
536 smb_apasslen = SVAL(inbuf,smb_vwv7);
537 if (smb_apasslen > MAX_PASS_LEN)
539 overflow_attack(smb_apasslen);
542 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
543 smb_apasswd[smb_apasslen] = 0;
544 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
546 if (!doencrypt && (lp_security() != SEC_SERVER)) {
547 smb_apasslen = strlen(smb_apasswd);
550 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
551 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
552 enum remote_arch_types ra_type = get_remote_arch();
553 char *p = smb_buf(inbuf);
555 global_client_caps = IVAL(inbuf,smb_vwv11);
557 /* client_caps is used as final determination if client is NT or Win95.
558 This is needed to return the correct error codes in some
562 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
564 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
565 set_remote_arch( RA_WINNT);
567 set_remote_arch( RA_WIN95);
570 if (passlen1 != 24 && passlen2 != 24)
573 if (passlen1 > MAX_PASS_LEN) {
574 overflow_attack(passlen1);
577 passlen1 = MIN(passlen1, MAX_PASS_LEN);
578 passlen2 = MIN(passlen2, MAX_PASS_LEN);
581 /* both Win95 and WinNT stuff up the password lengths for
582 non-encrypting systems. Uggh.
584 if passlen1==24 its a win95 system, and its setting the
585 password length incorrectly. Luckily it still works with the
586 default code because Win95 will null terminate the password
589 if passlen1>0 and passlen2>0 then maybe its a NT box and its
590 setting passlen2 to some random value which really stuffs
591 things up. we need to fix that one. */
593 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
597 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
598 /* Save the lanman2 password and the NT md4 password. */
599 smb_apasslen = passlen1;
600 memcpy(smb_apasswd,p,smb_apasslen);
601 smb_apasswd[smb_apasslen] = 0;
602 smb_ntpasslen = passlen2;
603 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
604 smb_ntpasswd[smb_ntpasslen] = 0;
606 /* we use the first password that they gave */
607 smb_apasslen = passlen1;
608 StrnCpy(smb_apasswd,p,smb_apasslen);
610 /* trim the password */
611 smb_apasslen = strlen(smb_apasswd);
613 /* wfwg sometimes uses a space instead of a null */
614 if (strequal(smb_apasswd," ")) {
620 p += passlen1 + passlen2;
621 fstrcpy(user,p); p = skip_string(p,1);
624 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
625 domain,skip_string(p,1),skip_string(p,2)));
628 DEBUG(3,("sesssetupX:name=[%s]\n",user));
630 /* If name ends in $ then I think it's asking about whether a */
631 /* computer with that name (minus the $) has access. For now */
632 /* say yes to everything ending in $. */
633 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
635 return session_trust_account(conn, inbuf, outbuf, user,
636 smb_apasswd, smb_apasslen,
637 smb_ntpasswd, smb_ntpasslen);
640 /* If no username is sent use the guest account */
643 pstrcpy(user,lp_guestaccount(-1));
644 /* If no user and no password then set guest flag. */
645 if( *smb_apasswd == 0)
651 * In share level security, only overwrite sesssetup_use if
652 * it's a non null-session share. Helps keep %U and %G
656 if((lp_security() != SEC_SHARE) || (*user && !guest))
657 pstrcpy(sesssetup_user,user);
658 reload_services(True);
661 * Save the username before mapping. We will use
662 * the original username sent to us for security=server
663 * and security=domain checking.
666 pstrcpy( orig_user, user);
668 map_nt_and_unix_username(domain, user);
670 add_session_user(user);
673 * Check if the given username was the guest user with no password.
676 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
680 * Check with orig_user for security=server and
685 !check_server_security(orig_user, domain,
686 smb_apasswd, smb_apasslen,
687 smb_ntpasswd, smb_ntpasslen) &&
688 !check_domain_security(orig_user, domain,
689 smb_apasswd, smb_apasslen,
690 smb_ntpasswd, smb_ntpasslen) &&
691 !check_hosts_equiv(user)
696 * If we get here then the user wasn't guest and the remote
697 * authentication methods failed. Check the authentication
698 * methods on this local server.
700 * If an NT password was supplied try and validate with that
701 * first. This is superior as the passwords are mixed case
702 * 128 length unicode.
707 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key))
708 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
710 valid_nt_password = True;
713 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key))
715 if (lp_security() >= SEC_USER)
717 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
718 return(ERROR(ERRSRV,ERRbadpw));
720 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
722 if (Get_Pwnam(user,True))
723 return(ERROR(ERRSRV,ERRbadpw));
727 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
728 * Then always map to guest account - as done below.
732 if (*smb_apasswd || !Get_Pwnam(user,True))
733 pstrcpy(user,lp_guestaccount(-1));
734 DEBUG(3,("Registered username %s for guest access\n",user));
739 if (!Get_Pwnam(user,True)) {
740 DEBUG(3,("No such user %s - using guest account\n",user));
741 pstrcpy(user,lp_guestaccount(-1));
745 if (!strequal(user,lp_guestaccount(-1)) &&
746 lp_servicenumber(user) < 0)
748 int homes = lp_servicenumber(HOMES_NAME);
749 char *home = get_home_dir(user);
750 if (homes >= 0 && home)
753 fstrcpy(home_dir, home);
754 lp_add_home(user,homes,home_dir);
758 /* it's ok - setup a reply */
759 if (Protocol < PROTOCOL_NT1) {
760 set_message(outbuf,3,0,True);
763 set_message(outbuf,3,3,True);
765 pstrcpy(p,"Unix"); p = skip_string(p,1);
766 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
767 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
768 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
769 /* perhaps grab OS version here?? */
772 /* Set the correct uid in the outgoing and incoming packets
773 We will use this on future requests to determine which
774 user we should become.
777 struct passwd *pw = Get_Pwnam(user,False);
779 DEBUG(1,("Username %s is invalid on this system\n",user));
780 return(ERROR(ERRSRV,ERRbadpw));
787 SSVAL(outbuf,smb_vwv2,1);
789 /* register the name and uid as being validated, so further connections
790 to a uid can get through without a password, on the same VC */
791 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key);
793 SSVAL(outbuf,smb_uid,sess_vuid);
794 SSVAL(inbuf,smb_uid,sess_vuid);
797 max_send = MIN(max_send,smb_bufsize);
799 DEBUG(6,("Client requested max send size of %d\n", max_send));
801 done_sesssetup = True;
803 return chain_reply(inbuf,outbuf,length,bufsize);
807 /****************************************************************************
809 ****************************************************************************/
810 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
816 BOOL bad_path = False;
819 pstrcpy(name,smb_buf(inbuf) + 1);
820 unix_convert(name,conn,0,&bad_path,&st);
822 mode = SVAL(inbuf,smb_vwv0);
824 if (check_name(name,conn)) {
826 ok = S_ISDIR(st.st_mode);
828 ok = dos_directory_exist(name,NULL);
833 /* We special case this - as when a Windows machine
834 is parsing a path is steps through the components
835 one at a time - if a component fails it expects
836 ERRbadpath, not ERRbadfile.
840 unix_ERR_class = ERRDOS;
841 unix_ERR_code = ERRbadpath;
845 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
846 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
847 (get_remote_arch() == RA_WINNT))
849 unix_ERR_class = ERRDOS;
850 unix_ERR_code = ERRbaddirectory;
854 return(UNIXERROR(ERRDOS,ERRbadpath));
857 outsize = set_message(outbuf,0,0,True);
859 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
865 /****************************************************************************
867 ****************************************************************************/
868 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
872 SMB_STRUCT_STAT sbuf;
877 BOOL bad_path = False;
879 pstrcpy(fname,smb_buf(inbuf) + 1);
881 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
882 under WfWg - weird! */
885 mode = aHIDDEN | aDIR;
886 if (!CAN_WRITE(conn)) mode |= aRONLY;
893 unix_convert(fname,conn,0,&bad_path,&sbuf);
894 if (check_name(fname,conn))
896 if (VALID_STAT(sbuf) || conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == 0)
898 mode = dos_mode(conn,fname,&sbuf);
900 mtime = sbuf.st_mtime;
906 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
912 if((errno == ENOENT) && bad_path)
914 unix_ERR_class = ERRDOS;
915 unix_ERR_code = ERRbadpath;
918 return(UNIXERROR(ERRDOS,ERRbadfile));
921 outsize = set_message(outbuf,10,0,True);
923 SSVAL(outbuf,smb_vwv0,mode);
924 if(lp_dos_filetime_resolution(SNUM(conn)) )
925 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
927 put_dos_date3(outbuf,smb_vwv1,mtime);
928 SIVAL(outbuf,smb_vwv3,(uint32)size);
930 if (Protocol >= PROTOCOL_NT1) {
931 char *p = strrchr(fname,'/');
932 uint16 flg2 = SVAL(outbuf,smb_flg2);
934 if (!is_8_3(fname, True))
935 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
938 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
944 /****************************************************************************
946 ****************************************************************************/
947 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
955 BOOL bad_path = False;
957 pstrcpy(fname,smb_buf(inbuf) + 1);
958 unix_convert(fname,conn,0,&bad_path,&st);
960 mode = SVAL(inbuf,smb_vwv0);
961 mtime = make_unix_date3(inbuf+smb_vwv1);
963 if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
965 if (check_name(fname,conn))
966 ok = (file_chmod(conn,fname,mode,NULL) == 0);
968 ok = set_filetime(conn,fname,mtime);
972 if((errno == ENOENT) && bad_path)
974 unix_ERR_class = ERRDOS;
975 unix_ERR_code = ERRbadpath;
978 return(UNIXERROR(ERRDOS,ERRnoaccess));
981 outsize = set_message(outbuf,0,0,True);
983 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
989 /****************************************************************************
991 ****************************************************************************/
992 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
995 SMB_BIG_UINT dfree,dsize,bsize;
997 conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);
999 outsize = set_message(outbuf,5,0,True);
1001 SSVAL(outbuf,smb_vwv0,dsize);
1002 SSVAL(outbuf,smb_vwv1,bsize/512);
1003 SSVAL(outbuf,smb_vwv2,512);
1004 SSVAL(outbuf,smb_vwv3,dfree);
1006 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1012 /****************************************************************************
1014 Can be called from SMBsearch, SMBffirst or SMBfunique.
1015 ****************************************************************************/
1016 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1027 BOOL finished = False;
1036 BOOL check_descend = False;
1037 BOOL expect_close = False;
1038 BOOL can_open = True;
1039 BOOL bad_path = False;
1041 *mask = *directory = *fname = 0;
1043 /* If we were called as SMBffirst then we must expect close. */
1044 if(CVAL(inbuf,smb_com) == SMBffirst)
1045 expect_close = True;
1047 outsize = set_message(outbuf,1,3,True);
1048 maxentries = SVAL(inbuf,smb_vwv0);
1049 dirtype = SVAL(inbuf,smb_vwv1);
1050 path = smb_buf(inbuf) + 1;
1051 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1054 /* dirtype &= ~aDIR; */
1056 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1059 if (status_len == 0)
1063 pstrcpy(directory,smb_buf(inbuf)+1);
1064 pstrcpy(dir2,smb_buf(inbuf)+1);
1065 unix_convert(directory,conn,0,&bad_path,NULL);
1068 if (!check_name(directory,conn))
1071 p = strrchr(dir2,'/');
1083 p = strrchr(directory,'/');
1089 if (strlen(directory) == 0)
1090 pstrcpy(directory,"./");
1092 CVAL(status,0) = dirtype;
1096 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1097 memcpy(mask,status+1,11);
1099 dirtype = CVAL(status,0) & 0x1F;
1100 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1103 string_set(&conn->dirpath,dptr_path(dptr_num));
1104 if (!case_sensitive)
1108 /* turn strings of spaces into a . */
1110 trim_string(mask,NULL," ");
1111 if ((p = strrchr(mask,' ')))
1116 trim_string(mask,NULL," ");
1122 /* Convert the formatted mask. (This code lives in trans2.c) */
1130 if((skip = skip_multibyte_char( *p )) != 0 )
1136 if (*p != '?' && *p != '*' && !isdoschar(*p))
1138 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1146 if (!strchr(mask,'.') && strlen(mask)>8)
1149 fstrcpy(tmp,&mask[8]);
1155 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1159 p = smb_buf(outbuf) + 3;
1163 if (status_len == 0)
1165 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1170 if((errno == ENOENT) && bad_path)
1172 unix_ERR_class = ERRDOS;
1173 unix_ERR_code = ERRbadpath;
1175 return (UNIXERROR(ERRDOS,ERRnofids));
1177 return(ERROR(ERRDOS,ERRnofids));
1181 DEBUG(4,("dptr_num is %d\n",dptr_num));
1185 if ((dirtype&0x1F) == aVOLID)
1187 memcpy(p,status,21);
1188 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1189 dptr_fill(p+12,dptr_num);
1190 if (dptr_zero(p+12) && (status_len==0))
1194 p += DIR_STRUCT_SIZE;
1198 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1199 conn->dirpath,lp_dontdescend(SNUM(conn))));
1200 if (in_list(conn->dirpath,
1201 lp_dontdescend(SNUM(conn)),True))
1202 check_descend = True;
1204 for (i=numentries;(i<maxentries) && !finished;i++)
1207 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1210 memcpy(p,status,21);
1211 make_dir_struct(p,mask,fname,size,mode,date);
1212 dptr_fill(p+12,dptr_num);
1215 p += DIR_STRUCT_SIZE;
1224 if (numentries == 0 || !ok)
1226 CVAL(outbuf,smb_rcls) = ERRDOS;
1227 SSVAL(outbuf,smb_err,ERRnofiles);
1230 /* If we were called as SMBffirst with smb_search_id == NULL
1231 and no entries were found then return error and close dirptr
1234 if(ok && expect_close && numentries == 0 && status_len == 0)
1236 CVAL(outbuf,smb_rcls) = ERRDOS;
1237 SSVAL(outbuf,smb_err,ERRnofiles);
1238 /* Also close the dptr - we know it's gone */
1239 dptr_close(dptr_num);
1242 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1243 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1244 dptr_close(dptr_num);
1246 SSVAL(outbuf,smb_vwv0,numentries);
1247 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1248 CVAL(smb_buf(outbuf),0) = 5;
1249 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1251 if (Protocol >= PROTOCOL_NT1) {
1252 uint16 flg2 = SVAL(outbuf,smb_flg2);
1253 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1256 outsize += DIR_STRUCT_SIZE*numentries;
1257 smb_setlen(outbuf,outsize - 4);
1259 if ((! *directory) && dptr_path(dptr_num))
1260 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1262 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1263 smb_fn_name(CVAL(inbuf,smb_com)),
1264 mask, directory, dirtype, numentries, maxentries ) );
1270 /****************************************************************************
1271 reply to a fclose (stop directory search)
1272 ****************************************************************************/
1273 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1281 outsize = set_message(outbuf,1,0,True);
1282 path = smb_buf(inbuf) + 1;
1283 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1286 if (status_len == 0)
1287 return(ERROR(ERRSRV,ERRsrverror));
1289 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1291 if(dptr_fetch(status+12,&dptr_num)) {
1292 /* Close the dptr - we know it's gone */
1293 dptr_close(dptr_num);
1296 SSVAL(outbuf,smb_vwv0,0);
1298 DEBUG(3,("search close\n"));
1304 /****************************************************************************
1306 ****************************************************************************/
1308 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1318 SMB_STRUCT_STAT sbuf;
1319 BOOL bad_path = False;
1321 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1323 share_mode = SVAL(inbuf,smb_vwv0);
1325 pstrcpy(fname,smb_buf(inbuf)+1);
1326 unix_convert(fname,conn,0,&bad_path,NULL);
1330 return(ERROR(ERRSRV,ERRnofids));
1332 if (!check_name(fname,conn))
1334 if((errno == ENOENT) && bad_path)
1336 unix_ERR_class = ERRDOS;
1337 unix_ERR_code = ERRbadpath;
1340 return(UNIXERROR(ERRDOS,ERRnoaccess));
1343 unixmode = unix_mode(conn,aARCH);
1345 open_file_shared(fsp, conn, fname, share_mode,
1346 (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN),
1347 unixmode, oplock_request, &rmode, NULL);
1351 if((errno == ENOENT) && bad_path)
1353 unix_ERR_class = ERRDOS;
1354 unix_ERR_code = ERRbadpath;
1357 return(UNIXERROR(ERRDOS,ERRnoaccess));
1360 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1361 close_file(fsp,False);
1362 return(ERROR(ERRDOS,ERRnoaccess));
1365 size = sbuf.st_size;
1366 fmode = dos_mode(conn,fname,&sbuf);
1367 mtime = sbuf.st_mtime;
1370 DEBUG(3,("attempt to open a directory %s\n",fname));
1371 close_file(fsp,False);
1372 return(ERROR(ERRDOS,ERRnoaccess));
1375 outsize = set_message(outbuf,7,0,True);
1376 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1377 SSVAL(outbuf,smb_vwv1,fmode);
1378 if(lp_dos_filetime_resolution(SNUM(conn)) )
1379 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1381 put_dos_date3(outbuf,smb_vwv2,mtime);
1382 SIVAL(outbuf,smb_vwv4,(uint32)size);
1383 SSVAL(outbuf,smb_vwv6,rmode);
1385 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1386 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1389 if(fsp->granted_oplock)
1390 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1395 /****************************************************************************
1396 reply to an open and X
1397 ****************************************************************************/
1398 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1401 int smb_mode = SVAL(inbuf,smb_vwv3);
1402 int smb_attr = SVAL(inbuf,smb_vwv5);
1403 /* Breakout the oplock request bits so we can set the
1404 reply bits separately. */
1405 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1406 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1407 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1409 int open_flags = SVAL(inbuf,smb_vwv2);
1410 int smb_sattr = SVAL(inbuf,smb_vwv4);
1411 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1413 int smb_ofun = SVAL(inbuf,smb_vwv8);
1416 int fmode=0,mtime=0,rmode=0;
1417 SMB_STRUCT_STAT sbuf;
1419 BOOL bad_path = False;
1422 /* If it's an IPC, pass off the pipe handler. */
1423 if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
1425 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1428 /* XXXX we need to handle passed times, sattr and flags */
1430 pstrcpy(fname,smb_buf(inbuf));
1431 unix_convert(fname,conn,0,&bad_path,NULL);
1435 return(ERROR(ERRSRV,ERRnofids));
1437 if (!check_name(fname,conn))
1439 if((errno == ENOENT) && bad_path)
1441 unix_ERR_class = ERRDOS;
1442 unix_ERR_code = ERRbadpath;
1445 return(UNIXERROR(ERRDOS,ERRnoaccess));
1448 unixmode = unix_mode(conn,smb_attr | aARCH);
1450 open_file_shared(fsp, conn, fname, smb_mode, smb_ofun, unixmode,
1451 oplock_request, &rmode, &smb_action);
1455 if((errno == ENOENT) && bad_path)
1457 unix_ERR_class = ERRDOS;
1458 unix_ERR_code = ERRbadpath;
1461 return(UNIXERROR(ERRDOS,ERRnoaccess));
1464 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1465 close_file(fsp,False);
1466 return(ERROR(ERRDOS,ERRnoaccess));
1469 size = sbuf.st_size;
1470 fmode = dos_mode(conn,fname,&sbuf);
1471 mtime = sbuf.st_mtime;
1473 close_file(fsp,False);
1474 return(ERROR(ERRDOS,ERRnoaccess));
1477 /* If the caller set the extended oplock request bit
1478 and we granted one (by whatever means) - set the
1479 correct bit for extended oplock reply.
1482 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1483 smb_action |= EXTENDED_OPLOCK_GRANTED;
1486 if(ex_oplock_request && fsp->granted_oplock) {
1487 smb_action |= EXTENDED_OPLOCK_GRANTED;
1490 /* If the caller set the core oplock request bit
1491 and we granted one (by whatever means) - set the
1492 correct bit for core oplock reply.
1495 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1496 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1499 if(core_oplock_request && fsp->granted_oplock) {
1500 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1503 set_message(outbuf,15,0,True);
1504 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1505 SSVAL(outbuf,smb_vwv3,fmode);
1506 if(lp_dos_filetime_resolution(SNUM(conn)) )
1507 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1509 put_dos_date3(outbuf,smb_vwv4,mtime);
1510 SIVAL(outbuf,smb_vwv6,(uint32)size);
1511 SSVAL(outbuf,smb_vwv8,rmode);
1512 SSVAL(outbuf,smb_vwv11,smb_action);
1514 return chain_reply(inbuf,outbuf,length,bufsize);
1518 /****************************************************************************
1519 reply to a SMBulogoffX
1520 ****************************************************************************/
1521 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1523 uint16 vuid = SVAL(inbuf,smb_uid);
1524 user_struct *vuser = get_valid_user_struct(vuid);
1527 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1530 /* in user level security we are supposed to close any files
1531 open by this user */
1532 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1533 file_close_user(vuid);
1536 invalidate_vuid(vuid);
1538 set_message(outbuf,2,0,True);
1540 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1542 return chain_reply(inbuf,outbuf,length,bufsize);
1546 /****************************************************************************
1547 reply to a mknew or a create
1548 ****************************************************************************/
1549 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1557 BOOL bad_path = False;
1559 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1561 com = SVAL(inbuf,smb_com);
1563 createmode = SVAL(inbuf,smb_vwv0);
1564 pstrcpy(fname,smb_buf(inbuf)+1);
1565 unix_convert(fname,conn,0,&bad_path,NULL);
1567 if (createmode & aVOLID)
1569 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1572 unixmode = unix_mode(conn,createmode);
1576 return(ERROR(ERRSRV,ERRnofids));
1578 if (!check_name(fname,conn))
1580 if((errno == ENOENT) && bad_path)
1582 unix_ERR_class = ERRDOS;
1583 unix_ERR_code = ERRbadpath;
1586 return(UNIXERROR(ERRDOS,ERRnoaccess));
1591 /* We should fail if file exists. */
1596 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1600 /* Open file in dos compatibility share mode. */
1601 open_file_shared(fsp, conn, fname,
1602 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1603 ofun, unixmode, oplock_request, NULL, NULL);
1607 if((errno == ENOENT) && bad_path)
1609 unix_ERR_class = ERRDOS;
1610 unix_ERR_code = ERRbadpath;
1613 return(UNIXERROR(ERRDOS,ERRnoaccess));
1616 outsize = set_message(outbuf,1,0,True);
1617 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1619 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1620 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1623 if(fsp->granted_oplock)
1624 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1626 DEBUG( 2, ( "new file %s\n", fname ) );
1627 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1628 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1634 /****************************************************************************
1635 reply to a create temporary file
1636 ****************************************************************************/
1637 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1644 BOOL bad_path = False;
1646 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1648 createmode = SVAL(inbuf,smb_vwv0);
1649 pstrcpy(fname,smb_buf(inbuf)+1);
1650 pstrcat(fname,"/TMXXXXXX");
1651 unix_convert(fname,conn,0,&bad_path,NULL);
1653 unixmode = unix_mode(conn,createmode);
1657 return(ERROR(ERRSRV,ERRnofids));
1659 if (!check_name(fname,conn))
1661 if((errno == ENOENT) && bad_path)
1663 unix_ERR_class = ERRDOS;
1664 unix_ERR_code = ERRbadpath;
1667 return(UNIXERROR(ERRDOS,ERRnoaccess));
1670 pstrcpy(fname2,(char *)mktemp(fname));
1672 /* Open file in dos compatibility share mode. */
1673 /* We should fail if file exists. */
1674 open_file_shared(fsp,conn,fname2,
1675 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1676 (FILE_CREATE_IF_NOT_EXIST | FILE_EXISTS_FAIL),
1677 unixmode, oplock_request, NULL, NULL);
1681 if((errno == ENOENT) && bad_path)
1683 unix_ERR_class = ERRDOS;
1684 unix_ERR_code = ERRbadpath;
1687 return(UNIXERROR(ERRDOS,ERRnoaccess));
1690 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1691 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1692 CVAL(smb_buf(outbuf),0) = 4;
1693 pstrcpy(smb_buf(outbuf) + 1,fname2);
1695 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1696 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1699 if(fsp->granted_oplock)
1700 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1702 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1703 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1704 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1710 /*******************************************************************
1711 check if a user is allowed to delete a file
1712 ********************************************************************/
1713 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1715 SMB_STRUCT_STAT sbuf;
1718 if (!CAN_WRITE(conn)) return(False);
1720 if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False);
1721 fmode = dos_mode(conn,fname,&sbuf);
1722 if (fmode & aDIR) return(False);
1723 if (!lp_delete_readonly(SNUM(conn))) {
1724 if (fmode & aRONLY) return(False);
1726 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1728 if (!check_file_sharing(conn,fname,False)) return(False);
1732 /****************************************************************************
1734 ****************************************************************************/
1735 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1744 int error = ERRnoaccess;
1747 BOOL bad_path = False;
1749 *directory = *mask = 0;
1751 dirtype = SVAL(inbuf,smb_vwv0);
1753 pstrcpy(name,smb_buf(inbuf) + 1);
1755 DEBUG(3,("reply_unlink : %s\n",name));
1757 unix_convert(name,conn,0,&bad_path,NULL);
1759 p = strrchr(name,'/');
1761 pstrcpy(directory,"./");
1765 pstrcpy(directory,name);
1769 if (is_mangled(mask))
1770 check_mangled_cache( mask );
1772 has_wild = strchr(mask,'*') || strchr(mask,'?');
1775 pstrcat(directory,"/");
1776 pstrcat(directory,mask);
1777 if (can_delete(directory,conn,dirtype) && !conn->vfs_ops.unlink(directory))
1780 exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
1782 void *dirptr = NULL;
1785 if (check_name(directory,conn))
1786 dirptr = OpenDir(conn, directory, True);
1788 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1789 the pattern matches against the long name, otherwise the short name
1790 We don't implement this yet XXXX
1797 if (strequal(mask,"????????.???"))
1800 while ((dname = ReadDirName(dirptr)))
1803 pstrcpy(fname,dname);
1805 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1807 error = ERRnoaccess;
1808 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1809 if (!can_delete(fname,conn,dirtype)) continue;
1810 if (!conn->vfs_ops.unlink(fname)) count++;
1811 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1819 return(ERROR(ERRDOS,error));
1822 if((errno == ENOENT) && bad_path)
1824 unix_ERR_class = ERRDOS;
1825 unix_ERR_code = ERRbadpath;
1827 return(UNIXERROR(ERRDOS,error));
1831 outsize = set_message(outbuf,0,0,True);
1837 /****************************************************************************
1838 reply to a readbraw (core+ protocol)
1839 ****************************************************************************/
1840 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1842 size_t maxcount,mincount;
1845 char *header = outbuf;
1850 * Special check if an oplock break has been issued
1851 * and the readraw request croses on the wire, we must
1852 * return a zero length response here.
1855 if(global_oplock_break)
1857 _smb_setlen(header,0);
1858 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1859 DEBUG(5,("readbraw - oplock break finished\n"));
1863 fsp = file_fsp(inbuf,smb_vwv0);
1865 startpos = IVAL(inbuf,smb_vwv1);
1866 #ifdef LARGE_SMB_OFF_T
1867 if(CVAL(inbuf,smb_wct) == 10) {
1869 * This is a large offset (64 bit) read.
1871 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1873 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1874 (double)startpos ));
1875 _smb_setlen(header,0);
1876 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1880 #endif /* LARGE_SMB_OFF_T */
1881 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1882 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1884 /* ensure we don't overrun the packet size */
1885 maxcount = MIN(65535,maxcount);
1886 maxcount = MAX(mincount,maxcount);
1888 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1889 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1890 _smb_setlen(header,0);
1891 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1895 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1897 SMB_OFF_T size = fsp->size;
1898 SMB_OFF_T sizeneeded = startpos + maxcount;
1900 if (size < sizeneeded)
1903 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0)
1905 if (!fsp->can_write)
1909 nread = MIN(maxcount,(size - startpos));
1912 if (nread < mincount)
1915 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1916 fsp->fnum, (double)startpos,
1917 maxcount, mincount, nread ) );
1921 BOOL seek_fail = False;
1923 _smb_setlen(header,nread);
1925 #if USE_READ_PREDICTION
1926 if (!fsp->can_write)
1927 predict = read_predict(fsp, fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1928 #endif /* USE_READ_PREDICTION */
1930 if ((nread-predict) > 0) {
1931 if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) {
1932 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1939 ret = (ssize_t)vfs_transfer_file(-1, fsp->fd_ptr->fd, Client, NULL,
1940 (SMB_OFF_T)(nread-predict),header,4+predict,
1945 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1946 fsp->fsp_name,startpos,nread,ret));
1948 #else /* UNSAFE_READRAW */
1949 ret = read_file(fsp,header+4,startpos,nread);
1950 if (ret < mincount) ret = 0;
1952 _smb_setlen(header,ret);
1953 transfer_file(0,Client,0,header,4+ret,0);
1954 #endif /* UNSAFE_READRAW */
1956 DEBUG(5,("readbraw finished\n"));
1961 /****************************************************************************
1962 reply to a lockread (core+ protocol)
1963 ****************************************************************************/
1964 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1973 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1975 CHECK_FSP(fsp,conn);
1979 numtoread = SVAL(inbuf,smb_vwv1);
1980 startpos = IVAL(inbuf,smb_vwv2);
1982 outsize = set_message(outbuf,5,3,True);
1983 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1984 data = smb_buf(outbuf) + 3;
1986 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1987 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1989 * A blocking lock was requested. Package up
1990 * this smb into a queued request and push it
1991 * onto the blocking lock queue.
1993 if(push_blocking_lock_request(inbuf, length, -1, 0))
1996 return (ERROR(eclass,ecode));
1999 nread = read_file(fsp,data,startpos,numtoread);
2002 return(UNIXERROR(ERRDOS,ERRnoaccess));
2005 SSVAL(outbuf,smb_vwv0,nread);
2006 SSVAL(outbuf,smb_vwv5,nread+3);
2007 SSVAL(smb_buf(outbuf),1,nread);
2009 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2010 fsp->fnum, numtoread, nread ) );
2016 /****************************************************************************
2018 ****************************************************************************/
2019 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2026 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2028 CHECK_FSP(fsp,conn);
2032 numtoread = SVAL(inbuf,smb_vwv1);
2033 startpos = IVAL(inbuf,smb_vwv2);
2035 outsize = set_message(outbuf,5,3,True);
2036 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2037 data = smb_buf(outbuf) + 3;
2039 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2040 return(ERROR(ERRDOS,ERRlock));
2042 if (numtoread > 0) {
2043 nread = read_file(fsp,data,startpos,numtoread);
2047 return(UNIXERROR(ERRDOS,ERRnoaccess));
2050 SSVAL(outbuf,smb_vwv0,nread);
2051 SSVAL(outbuf,smb_vwv5,nread+3);
2052 CVAL(smb_buf(outbuf),0) = 1;
2053 SSVAL(smb_buf(outbuf),1,nread);
2055 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2056 fsp->fnum, numtoread, nread ) );
2062 /****************************************************************************
2063 reply to a read and X
2064 ****************************************************************************/
2065 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2067 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2068 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2069 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2070 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2074 /* If it's an IPC, pass off the pipe handler. */
2076 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2078 CHECK_FSP(fsp,conn);
2082 set_message(outbuf,12,0,True);
2083 data = smb_buf(outbuf);
2085 #ifdef LARGE_SMB_OFF_T
2086 if(CVAL(inbuf,smb_wct) == 12) {
2088 * This is a large offset (64 bit) read.
2090 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2092 #endif /* LARGE_SMB_OFF_T */
2094 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2095 return(ERROR(ERRDOS,ERRlock));
2096 nread = read_file(fsp,data,startpos,smb_maxcnt);
2099 return(UNIXERROR(ERRDOS,ERRnoaccess));
2101 SSVAL(outbuf,smb_vwv5,nread);
2102 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2103 SSVAL(smb_buf(outbuf),-2,nread);
2105 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2106 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2108 return chain_reply(inbuf,outbuf,length,bufsize);
2111 /****************************************************************************
2112 reply to a writebraw (core+ or LANMAN1.0 protocol)
2113 ****************************************************************************/
2114 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2117 ssize_t total_written=0;
2118 size_t numtowrite=0;
2123 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2126 CHECK_FSP(fsp,conn);
2130 tcount = IVAL(inbuf,smb_vwv1);
2131 startpos = IVAL(inbuf,smb_vwv3);
2132 write_through = BITSETW(inbuf+smb_vwv7,0);
2134 /* We have to deal with slightly different formats depending
2135 on whether we are using the core+ or lanman1.0 protocol */
2136 if(Protocol <= PROTOCOL_COREPLUS) {
2137 numtowrite = SVAL(smb_buf(inbuf),-2);
2138 data = smb_buf(inbuf);
2140 numtowrite = SVAL(inbuf,smb_vwv10);
2141 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2144 /* force the error type */
2145 CVAL(inbuf,smb_com) = SMBwritec;
2146 CVAL(outbuf,smb_com) = SMBwritec;
2148 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2149 return(ERROR(ERRDOS,ERRlock));
2151 if (seek_file(fsp,startpos) == -1) {
2152 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2153 return(UNIXERROR(ERRDOS,ERRnoaccess));
2157 nwritten = write_file(fsp,data,numtowrite);
2159 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2160 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2162 if (nwritten < numtowrite)
2163 return(UNIXERROR(ERRHRD,ERRdiskfull));
2165 total_written = nwritten;
2167 /* Return a message to the redirector to tell it
2168 to send more bytes */
2169 CVAL(outbuf,smb_com) = SMBwritebraw;
2170 SSVALS(outbuf,smb_vwv0,-1);
2171 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2172 send_smb(Client,outbuf);
2174 /* Now read the raw data into the buffer and write it */
2175 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2176 exit_server("secondary writebraw failed");
2179 /* Even though this is not an smb message, smb_len
2180 returns the generic length of an smb message */
2181 numtowrite = smb_len(inbuf);
2183 if (tcount > nwritten+numtowrite) {
2184 DEBUG(3,("Client overestimated the write %d %d %d\n",
2185 tcount,nwritten,numtowrite));
2188 nwritten = vfs_transfer_file(Client, NULL, -1, fsp,
2189 (SMB_OFF_T)numtowrite,NULL,0,
2191 total_written += nwritten;
2193 /* Set up outbuf to return the correct return */
2194 outsize = set_message(outbuf,1,0,True);
2195 CVAL(outbuf,smb_com) = SMBwritec;
2196 SSVAL(outbuf,smb_vwv0,total_written);
2198 if (nwritten < (ssize_t)numtowrite) {
2199 CVAL(outbuf,smb_rcls) = ERRHRD;
2200 SSVAL(outbuf,smb_err,ERRdiskfull);
2203 if (lp_syncalways(SNUM(conn)) || write_through)
2204 conn->vfs_ops.sync(conn, fsp);
2206 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2207 fsp->fnum, (double)startpos, numtowrite, total_written));
2209 /* we won't return a status if write through is not selected - this
2210 follows what WfWg does */
2211 if (!write_through && total_written==tcount)
2217 /****************************************************************************
2218 reply to a writeunlock (core+)
2219 ****************************************************************************/
2220 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2222 ssize_t nwritten = -1;
2228 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2231 CHECK_FSP(fsp,conn);
2235 numtowrite = SVAL(inbuf,smb_vwv1);
2236 startpos = IVAL(inbuf,smb_vwv2);
2237 data = smb_buf(inbuf) + 3;
2239 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2240 return(ERROR(ERRDOS,ERRlock));
2242 if(seek_file(fsp,startpos) == -1)
2243 return(UNIXERROR(ERRDOS,ERRnoaccess));
2245 /* The special X/Open SMB protocol handling of
2246 zero length writes is *NOT* done for
2251 nwritten = write_file(fsp,data,numtowrite);
2253 if (lp_syncalways(SNUM(conn)))
2254 conn->vfs_ops.sync(conn, fsp);
2256 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2257 return(UNIXERROR(ERRDOS,ERRnoaccess));
2259 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2260 return(ERROR(eclass,ecode));
2262 outsize = set_message(outbuf,1,0,True);
2264 SSVAL(outbuf,smb_vwv0,nwritten);
2266 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2267 fsp->fnum, numtowrite, nwritten ) );
2272 /****************************************************************************
2274 ****************************************************************************/
2275 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2278 ssize_t nwritten = -1;
2281 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2284 CHECK_FSP(fsp,conn);
2288 numtowrite = SVAL(inbuf,smb_vwv1);
2289 startpos = IVAL(inbuf,smb_vwv2);
2290 data = smb_buf(inbuf) + 3;
2292 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2293 return(ERROR(ERRDOS,ERRlock));
2295 if(seek_file(fsp,startpos) == -1)
2296 return(UNIXERROR(ERRDOS,ERRnoaccess));
2298 /* X/Open SMB protocol says that if smb_vwv1 is
2299 zero then the file size should be extended or
2300 truncated to the size given in smb_vwv[2-3] */
2302 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2304 nwritten = write_file(fsp,data,numtowrite);
2306 if (lp_syncalways(SNUM(conn)))
2307 conn->vfs_ops.sync(conn, fsp);
2309 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2310 return(UNIXERROR(ERRDOS,ERRnoaccess));
2312 outsize = set_message(outbuf,1,0,True);
2314 SSVAL(outbuf,smb_vwv0,nwritten);
2316 if (nwritten < (ssize_t)numtowrite) {
2317 CVAL(outbuf,smb_rcls) = ERRHRD;
2318 SSVAL(outbuf,smb_err,ERRdiskfull);
2321 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2322 fsp->fnum, numtowrite, nwritten));
2328 /****************************************************************************
2329 reply to a write and X
2330 ****************************************************************************/
2331 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2333 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2334 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2335 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2336 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2337 ssize_t nwritten = -1;
2338 int smb_doff = SVAL(inbuf,smb_vwv11);
2341 /* If it's an IPC, pass off the pipe handler. */
2343 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2345 CHECK_FSP(fsp,conn);
2349 data = smb_base(inbuf) + smb_doff;
2351 #ifdef LARGE_SMB_OFF_T
2352 if(CVAL(inbuf,smb_wct) == 14) {
2354 * This is a large offset (64 bit) write.
2356 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2358 #endif /* LARGE_SMB_OFF_T */
2360 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2361 return(ERROR(ERRDOS,ERRlock));
2363 if(seek_file(fsp,startpos) == -1)
2364 return(UNIXERROR(ERRDOS,ERRnoaccess));
2366 /* X/Open SMB protocol says that, unlike SMBwrite
2367 if the length is zero then NO truncation is
2368 done, just a write of zero. To truncate a file,
2373 nwritten = write_file(fsp,data,numtowrite);
2375 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2376 return(UNIXERROR(ERRDOS,ERRnoaccess));
2378 set_message(outbuf,6,0,True);
2380 SSVAL(outbuf,smb_vwv2,nwritten);
2382 if (nwritten < (ssize_t)numtowrite) {
2383 CVAL(outbuf,smb_rcls) = ERRHRD;
2384 SSVAL(outbuf,smb_err,ERRdiskfull);
2387 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2388 fsp->fnum, numtowrite, nwritten));
2390 if (lp_syncalways(SNUM(conn)) || write_through)
2391 conn->vfs_ops.sync(conn, fsp);
2393 return chain_reply(inbuf,outbuf,length,bufsize);
2397 /****************************************************************************
2399 ****************************************************************************/
2400 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2406 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2408 CHECK_FSP(fsp,conn);
2411 mode = SVAL(inbuf,smb_vwv1) & 3;
2412 startpos = IVAL(inbuf,smb_vwv2);
2416 case 0: umode = SEEK_SET; break;
2417 case 1: umode = SEEK_CUR; break;
2418 case 2: umode = SEEK_END; break;
2420 umode = SEEK_SET; break;
2423 if((res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2424 return(UNIXERROR(ERRDOS,ERRnoaccess));
2428 outsize = set_message(outbuf,2,0,True);
2429 SIVALS(outbuf,smb_vwv0,res);
2431 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2432 fsp->fnum, (double)startpos, mode));
2437 /****************************************************************************
2439 ****************************************************************************/
2440 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2442 int outsize = set_message(outbuf,0,0,True);
2443 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2446 CHECK_FSP(fsp,conn);
2451 file_sync_all(conn);
2453 conn->vfs_ops.sync(conn, fsp);
2456 DEBUG(3,("flush\n"));
2461 /****************************************************************************
2463 ****************************************************************************/
2464 int reply_exit(connection_struct *conn,
2465 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2467 int outsize = set_message(outbuf,0,0,True);
2468 DEBUG(3,("exit\n"));
2474 /****************************************************************************
2475 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2476 ****************************************************************************/
2477 int reply_close(connection_struct *conn,
2478 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2482 int32 eclass = 0, err = 0;
2483 files_struct *fsp = NULL;
2485 outsize = set_message(outbuf,0,0,True);
2487 /* If it's an IPC, pass off to the pipe handler. */
2489 return reply_pipe_close(conn, inbuf,outbuf);
2492 fsp = file_fsp(inbuf,smb_vwv0);
2495 * We can only use CHECK_FSP if we know it's not a directory.
2498 if(!fsp || !fsp->open || (fsp->conn != conn))
2499 return(ERROR(ERRDOS,ERRbadfid));
2501 if(HAS_CACHED_ERROR(fsp)) {
2502 eclass = fsp->wbmpx_ptr->wr_errclass;
2503 err = fsp->wbmpx_ptr->wr_error;
2506 if(fsp->is_directory) {
2508 * Special case - close NT SMB directory
2511 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2512 close_directory(fsp);
2515 * Close ordinary file.
2519 * If there was a modify time outstanding,
2520 * try and set it here.
2522 if(fsp->pending_modtime)
2523 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2526 * Now take care of any time sent in the close.
2528 mtime = make_unix_date3(inbuf+smb_vwv1);
2530 /* try and set the date */
2531 set_filetime(conn, fsp->fsp_name,mtime);
2533 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2534 fsp->fd_ptr->fd, fsp->fnum,
2535 conn->num_files_open));
2537 close_file(fsp,True);
2540 /* We have a cached error */
2542 return(ERROR(eclass,err));
2548 /****************************************************************************
2549 reply to a writeclose (Core+ protocol)
2550 ****************************************************************************/
2551 int reply_writeclose(connection_struct *conn,
2552 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2555 ssize_t nwritten = -1;
2560 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2562 CHECK_FSP(fsp,conn);
2566 numtowrite = SVAL(inbuf,smb_vwv1);
2567 startpos = IVAL(inbuf,smb_vwv2);
2568 mtime = make_unix_date3(inbuf+smb_vwv4);
2569 data = smb_buf(inbuf) + 1;
2571 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2572 return(ERROR(ERRDOS,ERRlock));
2574 if(seek_file(fsp,startpos) == -1)
2575 return(UNIXERROR(ERRDOS,ERRnoaccess));
2577 nwritten = write_file(fsp,data,numtowrite);
2579 set_filetime(conn, fsp->fsp_name,mtime);
2581 close_file(fsp,True);
2583 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2584 fsp->fnum, numtowrite, nwritten,
2585 conn->num_files_open));
2588 return(UNIXERROR(ERRDOS,ERRnoaccess));
2590 outsize = set_message(outbuf,1,0,True);
2592 SSVAL(outbuf,smb_vwv0,nwritten);
2597 /****************************************************************************
2599 ****************************************************************************/
2600 int reply_lock(connection_struct *conn,
2601 char *inbuf,char *outbuf, int length, int dum_buffsize)
2603 int outsize = set_message(outbuf,0,0,True);
2604 SMB_OFF_T count,offset;
2607 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2609 CHECK_FSP(fsp,conn);
2612 count = IVAL(inbuf,smb_vwv1);
2613 offset = IVAL(inbuf,smb_vwv3);
2615 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2616 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2618 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2619 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2621 * A blocking lock was requested. Package up
2622 * this smb into a queued request and push it
2623 * onto the blocking lock queue.
2625 if(push_blocking_lock_request(inbuf, length, -1, 0))
2628 return (ERROR(eclass,ecode));
2635 /****************************************************************************
2637 ****************************************************************************/
2638 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2640 int outsize = set_message(outbuf,0,0,True);
2641 SMB_OFF_T count,offset;
2644 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2646 CHECK_FSP(fsp,conn);
2649 count = IVAL(inbuf,smb_vwv1);
2650 offset = IVAL(inbuf,smb_vwv3);
2652 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2653 return (ERROR(eclass,ecode));
2655 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2656 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2662 /****************************************************************************
2664 ****************************************************************************/
2665 int reply_tdis(connection_struct *conn,
2666 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2668 int outsize = set_message(outbuf,0,0,True);
2671 vuid = SVAL(inbuf,smb_uid);
2674 DEBUG(4,("Invalid connection in tdis\n"));
2675 return(ERROR(ERRSRV,ERRinvnid));
2680 close_cnum(conn,vuid);
2687 /****************************************************************************
2689 ****************************************************************************/
2690 int reply_echo(connection_struct *conn,
2691 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2693 int smb_reverb = SVAL(inbuf,smb_vwv0);
2695 int data_len = smb_buflen(inbuf);
2696 int outsize = set_message(outbuf,1,data_len,True);
2698 /* copy any incoming data back out */
2700 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2702 if (smb_reverb > 100) {
2703 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2707 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2708 SSVAL(outbuf,smb_vwv0,seq_num);
2710 smb_setlen(outbuf,outsize - 4);
2712 send_smb(Client,outbuf);
2715 DEBUG(3,("echo %d times\n", smb_reverb));
2721 /****************************************************************************
2722 reply to a printopen
2723 ****************************************************************************/
2724 int reply_printopen(connection_struct *conn,
2725 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2732 *fname = *fname2 = 0;
2734 if (!CAN_PRINT(conn))
2735 return(ERROR(ERRDOS,ERRnoaccess));
2740 pstrcpy(s,smb_buf(inbuf)+1);
2743 if (!(isalnum((int)*p) || strchr("._-",*p)))
2748 if (strlen(s) > 10) s[10] = 0;
2750 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2755 return(ERROR(ERRSRV,ERRnofids));
2757 pstrcpy(fname2,(char *)mktemp(fname));
2759 if (!check_name(fname2,conn)) {
2761 return(ERROR(ERRDOS,ERRnoaccess));
2764 /* Open for exclusive use, write only. */
2765 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2766 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2770 return(UNIXERROR(ERRDOS,ERRnoaccess));
2773 /* force it to be a print file */
2774 fsp->print_file = True;
2776 outsize = set_message(outbuf,1,0,True);
2777 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2779 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2780 fname2, fsp->fd_ptr->fd, fsp->fnum));
2786 /****************************************************************************
2787 reply to a printclose
2788 ****************************************************************************/
2789 int reply_printclose(connection_struct *conn,
2790 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2792 int outsize = set_message(outbuf,0,0,True);
2793 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2795 CHECK_FSP(fsp,conn);
2798 if (!CAN_PRINT(conn))
2799 return(ERROR(ERRDOS,ERRnoaccess));
2801 DEBUG(3,("printclose fd=%d fnum=%d\n",
2802 fsp->fd_ptr->fd,fsp->fnum));
2804 close_file(fsp,True);
2810 /****************************************************************************
2811 reply to a printqueue
2812 ****************************************************************************/
2813 int reply_printqueue(connection_struct *conn,
2814 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2816 int outsize = set_message(outbuf,2,3,True);
2817 int max_count = SVAL(inbuf,smb_vwv0);
2818 int start_index = SVAL(inbuf,smb_vwv1);
2820 /* we used to allow the client to get the cnum wrong, but that
2821 is really quite gross and only worked when there was only
2822 one printer - I think we should now only accept it if they
2823 get it right (tridge) */
2824 if (!CAN_PRINT(conn))
2825 return(ERROR(ERRDOS,ERRnoaccess));
2827 SSVAL(outbuf,smb_vwv0,0);
2828 SSVAL(outbuf,smb_vwv1,0);
2829 CVAL(smb_buf(outbuf),0) = 1;
2830 SSVAL(smb_buf(outbuf),1,0);
2832 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2833 start_index, max_count));
2836 print_queue_struct *queue = NULL;
2837 char *p = smb_buf(outbuf) + 3;
2838 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2839 int num_to_get = ABS(max_count);
2840 int first = (max_count>0?start_index:start_index+max_count+1);
2846 num_to_get = MIN(num_to_get,count-first);
2849 for (i=first;i<first+num_to_get;i++) {
2850 put_dos_date2(p,0,queue[i].time);
2851 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2852 SSVAL(p,5,printjob_encode(SNUM(conn),
2854 SIVAL(p,7,queue[i].size);
2856 StrnCpy(p+12,queue[i].user,16);
2861 outsize = set_message(outbuf,2,28*count+3,False);
2862 SSVAL(outbuf,smb_vwv0,count);
2863 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2864 CVAL(smb_buf(outbuf),0) = 1;
2865 SSVAL(smb_buf(outbuf),1,28*count);
2868 if (queue) free(queue);
2870 DEBUG(3,("%d entries returned in queue\n",count));
2877 /****************************************************************************
2878 reply to a printwrite
2879 ****************************************************************************/
2880 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2883 int outsize = set_message(outbuf,0,0,True);
2885 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2887 if (!CAN_PRINT(conn))
2888 return(ERROR(ERRDOS,ERRnoaccess));
2890 CHECK_FSP(fsp,conn);
2894 numtowrite = SVAL(smb_buf(inbuf),1);
2895 data = smb_buf(inbuf) + 3;
2897 if (write_file(fsp,data,numtowrite) != numtowrite)
2898 return(UNIXERROR(ERRDOS,ERRnoaccess));
2900 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2906 /****************************************************************************
2908 ****************************************************************************/
2909 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2912 int outsize,ret= -1;
2913 BOOL bad_path = False;
2915 pstrcpy(directory,smb_buf(inbuf) + 1);
2916 unix_convert(directory,conn,0,&bad_path,NULL);
2918 if (check_name(directory, conn))
2919 ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
2920 unix_mode(conn,aDIR));
2924 if((errno == ENOENT) && bad_path)
2926 unix_ERR_class = ERRDOS;
2927 unix_ERR_code = ERRbadpath;
2929 return(UNIXERROR(ERRDOS,ERRnoaccess));
2932 outsize = set_message(outbuf,0,0,True);
2934 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2939 /****************************************************************************
2940 Static function used by reply_rmdir to delete an entire directory
2942 ****************************************************************************/
2943 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2947 void *dirptr = OpenDir(conn, directory, False);
2952 while((dname = ReadDirName(dirptr)))
2957 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2960 /* Construct the full name. */
2961 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2967 pstrcpy(fullname, directory);
2968 pstrcat(fullname, "/");
2969 pstrcat(fullname, dname);
2971 if(conn->vfs_ops.lstat(fullname, &st) != 0)
2977 if(st.st_mode & S_IFDIR)
2979 if(recursive_rmdir(conn, fullname)!=0)
2984 if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
2990 else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
3000 /****************************************************************************
3002 ****************************************************************************/
3003 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3008 BOOL bad_path = False;
3010 pstrcpy(directory,smb_buf(inbuf) + 1);
3011 unix_convert(directory,conn, NULL,&bad_path,NULL);
3013 if (check_name(directory,conn))
3016 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3017 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0);
3018 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
3020 /* Check to see if the only thing in this directory are
3021 vetoed files/directories. If so then delete them and
3022 retry. If we fail to delete any of them (and we *don't*
3023 do a recursive delete) then fail the rmdir. */
3024 BOOL all_veto_files = True;
3026 void *dirptr = OpenDir(conn, directory, False);
3030 int dirpos = TellDir(dirptr);
3031 while ((dname = ReadDirName(dirptr)))
3033 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3035 if(!IS_VETO_PATH(conn, dname))
3037 all_veto_files = False;
3043 SeekDir(dirptr,dirpos);
3044 while ((dname = ReadDirName(dirptr)))
3049 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3052 /* Construct the full name. */
3053 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3058 pstrcpy(fullname, directory);
3059 pstrcat(fullname, "/");
3060 pstrcat(fullname, dname);
3062 if(conn->vfs_ops.lstat(fullname, &st) != 0)
3064 if(st.st_mode & S_IFDIR)
3066 if(lp_recursive_veto_delete(SNUM(conn)))
3068 DEBUG(0, ("ERROR: recursive_rmdir()\n"));
3069 if(recursive_rmdir(conn, fullname) != 0)
3072 if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
3075 else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
3079 /* Retry the rmdir */
3080 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0);
3090 DEBUG(3,("couldn't remove directory %s : %s\n",
3091 directory,strerror(errno)));
3096 if((errno == ENOENT) && bad_path)
3098 unix_ERR_class = ERRDOS;
3099 unix_ERR_code = ERRbadpath;
3101 return(UNIXERROR(ERRDOS,ERRbadpath));
3104 outsize = set_message(outbuf,0,0,True);
3106 DEBUG( 3, ( "rmdir %s\n", directory ) );
3112 /*******************************************************************
3113 resolve wildcards in a filename rename
3114 ********************************************************************/
3115 static BOOL resolve_wildcards(char *name1,char *name2)
3117 fstring root1,root2;
3121 name1 = strrchr(name1,'/');
3122 name2 = strrchr(name2,'/');
3124 if (!name1 || !name2) return(False);
3126 fstrcpy(root1,name1);
3127 fstrcpy(root2,name2);
3128 p = strrchr(root1,'.');
3135 p = strrchr(root2,'.');
3167 pstrcpy(name2,root2);
3170 pstrcat(name2,ext2);
3176 /*******************************************************************
3177 check if a user is allowed to rename a file
3178 ********************************************************************/
3179 static BOOL can_rename(char *fname,connection_struct *conn)
3181 SMB_STRUCT_STAT sbuf;
3183 if (!CAN_WRITE(conn)) return(False);
3185 if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False);
3186 if (!check_file_sharing(conn,fname,True)) return(False);
3191 /****************************************************************************
3192 The guts of the rename command, split out so it may be called by the NT SMB
3194 ****************************************************************************/
3195 int rename_internals(connection_struct *conn,
3196 char *inbuf, char *outbuf, char *name,
3197 char *newname, BOOL replace_if_exists)
3201 pstring newname_last_component;
3204 BOOL bad_path1 = False;
3205 BOOL bad_path2 = False;
3207 int error = ERRnoaccess;
3210 *directory = *mask = 0;
3212 unix_convert(name,conn,0,&bad_path1,NULL);
3213 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3216 * Split the old name into directory and last component
3217 * strings. Note that unix_convert may have stripped off a
3218 * leading ./ from both name and newname if the rename is
3219 * at the root of the share. We need to make sure either both
3220 * name and newname contain a / character or neither of them do
3221 * as this is checked in resolve_wildcards().
3224 p = strrchr(name,'/');
3226 pstrcpy(directory,".");
3230 pstrcpy(directory,name);
3232 *p = '/'; /* Replace needed for exceptional test below. */
3235 if (is_mangled(mask))
3236 check_mangled_cache( mask );
3238 has_wild = strchr(mask,'*') || strchr(mask,'?');
3242 * No wildcards - just process the one file.
3244 BOOL is_short_name = is_8_3(name, True);
3246 /* Add a terminating '/' to the directory name. */
3247 pstrcat(directory,"/");
3248 pstrcat(directory,mask);
3250 /* Ensure newname contains a '/' also */
3251 if(strrchr(newname,'/') == 0) {
3254 pstrcpy(tmpstr, "./");
3255 pstrcat(tmpstr, newname);
3256 pstrcpy(newname, tmpstr);
3259 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",
3260 case_sensitive, case_preserve, short_case_preserve, directory,
3261 newname, newname_last_component, is_short_name));
3264 * Check for special case with case preserving and not
3265 * case sensitive, if directory and newname are identical,
3266 * and the old last component differs from the original
3267 * last component only by case, then we should allow
3268 * the rename (user is trying to change the case of the
3271 if((case_sensitive == False) &&
3272 (((case_preserve == True) &&
3273 (is_short_name == False)) ||
3274 ((short_case_preserve == True) &&
3275 (is_short_name == True))) &&
3276 strcsequal(directory, newname)) {
3277 pstring newname_modified_last_component;
3280 * Get the last component of the modified name.
3281 * Note that we guarantee that newname contains a '/'
3284 p = strrchr(newname,'/');
3285 pstrcpy(newname_modified_last_component,p+1);
3287 if(strcsequal(newname_modified_last_component,
3288 newname_last_component) == False) {
3290 * Replace the modified last component with
3293 pstrcpy(p+1, newname_last_component);
3297 if(replace_if_exists) {
3299 * NT SMB specific flag - rename can overwrite
3300 * file with the same name so don't check for
3303 if(resolve_wildcards(directory,newname) &&
3304 can_rename(directory,conn) &&
3305 !conn->vfs_ops.rename(dos_to_unix(directory,False),
3309 if (resolve_wildcards(directory,newname) &&
3310 can_rename(directory,conn) &&
3311 !vfs_file_exist(conn,dos_to_unix(newname,False),NULL) &&
3312 !conn->vfs_ops.rename(dos_to_unix(directory,False),
3317 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3318 directory,newname));
3320 if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
3321 if (!count && exists && vfs_file_exist(conn,dos_to_unix(newname,False),NULL)) {
3327 * Wildcards - process each file that matches.
3329 void *dirptr = NULL;
3333 if (check_name(directory,conn))
3334 dirptr = OpenDir(conn, directory, True);
3339 if (strequal(mask,"????????.???"))
3342 while ((dname = ReadDirName(dirptr))) {
3344 pstrcpy(fname,dname);
3346 if(!mask_match(fname, mask, case_sensitive, False))
3349 error = ERRnoaccess;
3350 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3351 if (!can_rename(fname,conn)) {
3352 DEBUG(6,("rename %s refused\n", fname));
3355 pstrcpy(destname,newname);
3357 if (!resolve_wildcards(fname,destname)) {
3358 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3362 if (!replace_if_exists && vfs_file_exist(conn,dos_to_unix(destname,False),NULL)) {
3363 DEBUG(6,("file_exist %s\n", destname));
3368 if (!conn->vfs_ops.rename(dos_to_unix(fname,False),destname))
3370 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3378 return(ERROR(ERRDOS,error));
3380 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3381 unix_ERR_class = ERRDOS;
3382 unix_ERR_code = ERRbadpath;
3384 return(UNIXERROR(ERRDOS,error));
3391 /****************************************************************************
3393 ****************************************************************************/
3395 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3401 pstrcpy(name,smb_buf(inbuf) + 1);
3402 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3404 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3406 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3408 outsize = set_message(outbuf,0,0,True);
3413 /*******************************************************************
3414 copy a file as part of a reply_copy
3415 ******************************************************************/
3417 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3418 int count,BOOL target_is_directory)
3423 files_struct *fsp1,*fsp2;
3426 pstrcpy(dest,dest1);
3427 if (target_is_directory) {
3428 char *p = strrchr(src,'/');
3437 if (!vfs_file_exist(conn,dos_to_unix(src,False),&st))
3444 open_file_shared(fsp1, conn, src,
3445 SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_RDONLY),
3446 (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN), 0, 0, &Access, &action);
3453 if (!target_is_directory && count)
3458 close_file(fsp1,False);
3461 open_file_shared(fsp2, conn, dest,
3462 SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_WRONLY),
3463 ofun, st.st_mode, 0, &Access, &action);
3466 close_file(fsp1,False);
3471 if ((ofun&3) == 1) {
3472 if(conn->vfs_ops.lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3473 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3476 * Stop the copy from occurring.
3484 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0);
3486 close_file(fsp1,False);
3487 close_file(fsp2,False);
3489 return(ret == st.st_size);
3494 /****************************************************************************
3495 reply to a file copy.
3496 ****************************************************************************/
3497 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3502 pstring mask,newname;
3505 int error = ERRnoaccess;
3508 int tid2 = SVAL(inbuf,smb_vwv0);
3509 int ofun = SVAL(inbuf,smb_vwv1);
3510 int flags = SVAL(inbuf,smb_vwv2);
3511 BOOL target_is_directory=False;
3512 BOOL bad_path1 = False;
3513 BOOL bad_path2 = False;
3515 *directory = *mask = 0;
3517 pstrcpy(name,smb_buf(inbuf));
3518 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3520 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3522 if (tid2 != conn->cnum) {
3523 /* can't currently handle inter share copies XXXX */
3524 DEBUG(3,("Rejecting inter-share copy\n"));
3525 return(ERROR(ERRSRV,ERRinvdevice));
3528 unix_convert(name,conn,0,&bad_path1,NULL);
3529 unix_convert(newname,conn,0,&bad_path2,NULL);
3531 target_is_directory = dos_directory_exist(newname,NULL);
3533 if ((flags&1) && target_is_directory) {
3534 return(ERROR(ERRDOS,ERRbadfile));
3537 if ((flags&2) && !target_is_directory) {
3538 return(ERROR(ERRDOS,ERRbadpath));
3541 if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
3542 /* wants a tree copy! XXXX */
3543 DEBUG(3,("Rejecting tree copy\n"));
3544 return(ERROR(ERRSRV,ERRerror));
3547 p = strrchr(name,'/');
3549 pstrcpy(directory,"./");
3553 pstrcpy(directory,name);
3557 if (is_mangled(mask))
3558 check_mangled_cache( mask );
3560 has_wild = strchr(mask,'*') || strchr(mask,'?');
3563 pstrcat(directory,"/");
3564 pstrcat(directory,mask);
3565 if (resolve_wildcards(directory,newname) &&
3566 copy_file(directory,newname,conn,ofun,
3567 count,target_is_directory)) count++;
3568 if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
3570 void *dirptr = NULL;
3574 if (check_name(directory,conn))
3575 dirptr = OpenDir(conn, directory, True);
3581 if (strequal(mask,"????????.???"))
3584 while ((dname = ReadDirName(dirptr)))
3587 pstrcpy(fname,dname);
3589 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3591 error = ERRnoaccess;
3592 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3593 pstrcpy(destname,newname);
3594 if (resolve_wildcards(fname,destname) &&
3595 copy_file(directory,newname,conn,ofun,
3596 count,target_is_directory)) count++;
3597 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3605 return(ERROR(ERRDOS,error));
3608 if((errno == ENOENT) && (bad_path1 || bad_path2))
3610 unix_ERR_class = ERRDOS;
3611 unix_ERR_code = ERRbadpath;
3613 return(UNIXERROR(ERRDOS,error));
3617 outsize = set_message(outbuf,1,0,True);
3618 SSVAL(outbuf,smb_vwv0,count);
3623 /****************************************************************************
3625 ****************************************************************************/
3626 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3634 if (!CAN_SETDIR(snum))
3635 return(ERROR(ERRDOS,ERRnoaccess));
3637 pstrcpy(newdir,smb_buf(inbuf) + 1);
3640 if (strlen(newdir) == 0) {
3643 ok = dos_directory_exist(newdir,NULL);
3645 string_set(&conn->connectpath,newdir);
3650 return(ERROR(ERRDOS,ERRbadpath));
3652 outsize = set_message(outbuf,0,0,True);
3653 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3655 DEBUG(3,("setdir %s\n", newdir));
3660 /****************************************************************************
3661 reply to a lockingX request
3662 ****************************************************************************/
3663 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3665 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3666 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3668 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3670 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3671 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3672 SMB_OFF_T count = 0, offset = 0;
3673 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3676 uint32 ecode=0, dummy2;
3677 int eclass=0, dummy1;
3678 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3679 CHECK_FSP(fsp,conn);
3682 data = smb_buf(inbuf);
3684 /* Check if this is an oplock break on a file
3685 we have granted an oplock on.
3687 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3690 SMB_DEV_T dev = fsp->fd_ptr->dev;
3691 SMB_INO_T inode = fsp->fd_ptr->inode;
3693 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3696 * Make sure we have granted an oplock on this file.
3698 if(!fsp->granted_oplock)
3700 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3701 no oplock granted on this file.\n", fsp->fnum));
3702 return ERROR(ERRDOS,ERRlock);
3705 /* Remove the oplock flag from the sharemode. */
3706 lock_share_entry(fsp->conn, dev, inode, &token);
3707 if(remove_share_oplock(token, fsp)==False) {
3709 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3710 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3712 unlock_share_entry(fsp->conn, dev, inode, token);
3714 unlock_share_entry(fsp->conn, dev, inode, token);
3716 /* Clear the granted flag and return. */
3717 fsp->granted_oplock = False;
3720 /* if this is a pure oplock break request then don't send a reply */
3721 if (num_locks == 0 && num_ulocks == 0)
3723 /* Sanity check - ensure a pure oplock break is not a
3725 if(CVAL(inbuf,smb_vwv0) != 0xff)
3726 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3727 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3732 /* Data now points at the beginning of the list
3733 of smb_unlkrng structs */
3734 for(i = 0; i < (int)num_ulocks; i++) {
3735 if(!large_file_format) {
3736 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3737 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3739 #ifdef LARGE_SMB_OFF_T
3741 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3742 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3743 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3744 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3746 #endif /* LARGE_SMB_OFF_T */
3748 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3749 (double)offset, (double)count, fsp->fsp_name ));
3751 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3752 return ERROR(eclass,ecode);
3755 /* Setup the timeout in seconds. */
3756 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3758 /* Now do any requested locks */
3759 data += ((large_file_format ? 20 : 10)*num_ulocks);
3761 /* Data now points at the beginning of the list
3762 of smb_lkrng structs */
3764 for(i = 0; i < (int)num_locks; i++) {
3765 if(!large_file_format) {
3766 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3767 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3769 #ifdef LARGE_SMB_OFF_T
3771 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3772 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3773 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3774 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3776 #endif /* LARGE_SMB_OFF_T */
3778 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3779 (double)offset, (double)count, fsp->fsp_name ));
3781 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3783 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3785 * A blocking lock was requested. Package up
3786 * this smb into a queued request and push it
3787 * onto the blocking lock queue.
3789 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3796 /* If any of the above locks failed, then we must unlock
3797 all of the previous locks (X/Open spec). */
3798 if(i != num_locks && num_locks != 0) {
3799 for(; i >= 0; i--) {
3800 if(!large_file_format) {
3801 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3802 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3804 #ifdef LARGE_SMB_OFF_T
3806 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3807 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3808 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3809 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3811 #endif /* LARGE_SMB_OFF_T */
3813 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3815 return ERROR(eclass,ecode);
3818 set_message(outbuf,2,0,True);
3820 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3821 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3823 return chain_reply(inbuf,outbuf,length,bufsize);
3827 /****************************************************************************
3828 reply to a SMBreadbmpx (read block multiplex) request
3829 ****************************************************************************/
3830 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3841 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3843 /* this function doesn't seem to work - disable by default */
3845 return(ERROR(ERRSRV,ERRuseSTD));
3847 outsize = set_message(outbuf,8,0,True);
3849 CHECK_FSP(fsp,conn);
3853 startpos = IVAL(inbuf,smb_vwv1);
3854 maxcount = SVAL(inbuf,smb_vwv3);
3856 data = smb_buf(outbuf);
3857 pad = ((long)data)%4;
3858 if (pad) pad = 4 - pad;
3861 max_per_packet = bufsize-(outsize+pad);
3865 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3866 return(ERROR(ERRDOS,ERRlock));