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);
128 DEBUG(20,("NBT message\n"));
129 dump_data(20, inbuf, smb_len(inbuf));
132 case 0x81: /* session request */
133 CVAL(outbuf,0) = 0x82;
135 if (name_len(inbuf+4) > 50 ||
136 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
137 DEBUG(0,("Invalid name length in session request\n"));
140 name_extract(inbuf,4,name1);
141 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
142 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
145 fstrcpy(remote_machine,name2);
146 remote_machine[15] = 0;
147 trim_string(remote_machine," "," ");
148 strlower(remote_machine);
150 fstrcpy(local_machine,name1);
151 len = strlen(local_machine);
153 name_type = local_machine[15];
154 local_machine[15] = 0;
156 trim_string(local_machine," "," ");
157 strlower(local_machine);
159 if (name_type == 'R') {
160 /* We are being asked for a pathworks session ---
162 CVAL(outbuf, 0) = 0x83;
166 add_session_user(remote_machine);
168 reload_services(True);
172 claim_connection(NULL,"STATUS.",MAXSTATUS,True);
177 case 0x89: /* session keepalive request
178 (some old clients produce this?) */
179 CVAL(outbuf,0) = 0x85;
183 case 0x82: /* positive session response */
184 case 0x83: /* negative session response */
185 case 0x84: /* retarget session response */
186 DEBUG(0,("Unexpected session response\n"));
189 case 0x85: /* session keepalive */
194 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
195 msg_type, msg_flags));
201 /*******************************************************************
202 work out what error to give to a failed connection
203 ********************************************************************/
204 static int connection_error(char *inbuf,char *outbuf,int ecode)
206 if (ecode == ERRnoipc) {
207 return(ERROR(ERRDOS,ERRnoipc));
210 return(ERROR(ERRSRV,ecode));
215 /****************************************************************************
216 parse a share descriptor string
217 ****************************************************************************/
218 static void parse_connect(char *p,char *service,char *user,
219 char *password,int *pwlen,char *dev)
223 DEBUG(4,("parsing connect string %s\n",p));
225 p2 = strrchr(p,'\\');
229 fstrcpy(service,p2+1);
234 *pwlen = strlen(password);
241 p = strchr(service,'%');
252 /****************************************************************************
254 ****************************************************************************/
255 int reply_tcon(connection_struct *conn,
256 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
263 uint16 vuid = SVAL(inbuf,smb_uid);
267 *service = *user = *password = *dev = 0;
269 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
271 map_nt_and_unix_username(global_myworkgroup, user);
273 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
276 return(connection_error(inbuf,outbuf,ecode));
279 outsize = set_message(outbuf,2,0,True);
280 SSVAL(outbuf,smb_vwv0,max_recv);
281 SSVAL(outbuf,smb_vwv1,conn->cnum);
282 SSVAL(outbuf,smb_tid,conn->cnum);
284 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
285 service, user, conn->cnum));
291 /****************************************************************************
292 reply to a tcon and X
293 ****************************************************************************/
294 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
301 uint16 vuid = SVAL(inbuf,smb_uid);
302 int passlen = SVAL(inbuf,smb_vwv3);
306 *service = *user = *password = *devicename = 0;
308 /* we might have to close an old one */
309 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
310 close_cnum(conn,vuid);
313 if (passlen > MAX_PASS_LEN) {
314 overflow_attack(passlen);
317 memcpy(password,smb_buf(inbuf),passlen);
319 path = smb_buf(inbuf) + passlen;
322 if (strequal(password," "))
324 passlen = strlen(password);
327 fstrcpy(service,path+2);
328 p = strchr(service,'\\');
330 return(ERROR(ERRSRV,ERRinvnetname));
332 fstrcpy(service,p+1);
333 p = strchr(service,'%');
338 StrnCpy(devicename,path + strlen(path) + 1,6);
339 DEBUG(4,("Got device type %s\n",devicename));
341 map_nt_and_unix_username(global_myworkgroup, user);
343 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
346 return(connection_error(inbuf,outbuf,ecode));
348 if (Protocol < PROTOCOL_NT1) {
349 set_message(outbuf,2,strlen(devicename)+1,True);
350 pstrcpy(smb_buf(outbuf),devicename);
352 char *fsname = lp_fstype(SNUM(conn));
354 set_message(outbuf,3,3,True);
357 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
358 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
360 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
362 /* what does setting this bit do? It is set by NT4 and
363 may affect the ability to autorun mounted cdroms */
364 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
367 DEBUG(3,("tconX service=%s user=%s\n",
370 /* set the incoming and outgoing tid to the just created one */
371 SSVAL(inbuf,smb_tid,conn->cnum);
372 SSVAL(outbuf,smb_tid,conn->cnum);
374 return chain_reply(inbuf,outbuf,length,bufsize);
378 /****************************************************************************
379 reply to an unknown type
380 ****************************************************************************/
381 int reply_unknown(char *inbuf,char *outbuf)
384 type = CVAL(inbuf,smb_com);
386 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
387 smb_fn_name(type), type, type));
389 return(ERROR(ERRSRV,ERRunknownsmb));
393 /****************************************************************************
395 ****************************************************************************/
396 int reply_ioctl(connection_struct *conn,
397 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
399 DEBUG(3,("ignoring ioctl\n"));
401 /* we just say it succeeds and hope its all OK.
402 some day it would be nice to interpret them individually */
403 return set_message(outbuf,1,0,True);
405 return(ERROR(ERRSRV,ERRnosupport));
409 /****************************************************************************
410 always return an error: it's just a matter of which one...
411 ****************************************************************************/
412 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
413 char *smb_passwd, int smb_passlen,
414 char *smb_nt_passwd, int smb_nt_passlen)
416 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
417 if (lp_security() == SEC_USER)
419 smb_trust_acct = getsmbpwnam(user);
423 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
424 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
425 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
428 if (smb_trust_acct == NULL)
430 /* lkclXXXX: workstation entry doesn't exist */
431 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
432 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
433 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
437 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
439 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
440 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
441 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
444 if (!smb_password_ok(smb_trust_acct, NULL, NULL, NULL,
445 (unsigned char *)smb_passwd, smb_passlen,
446 (unsigned char *)smb_nt_passwd, smb_nt_passlen))
448 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
449 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
450 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
453 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
455 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
456 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
457 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
460 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
462 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
463 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
464 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
467 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
469 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
470 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
471 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
475 /* don't know what to do: indicate logon failure */
476 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
477 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
480 /****************************************************************************
481 Check for a valid username and password in security=server mode.
482 ****************************************************************************/
484 static BOOL check_server_security(char *orig_user, char *domain,
485 char *smb_apasswd, int smb_apasslen,
486 char *smb_ntpasswd, int smb_ntpasslen)
488 if(lp_security() != SEC_SERVER)
491 return server_validate(orig_user, domain,
492 smb_apasswd, smb_apasslen,
493 smb_ntpasswd, smb_ntpasslen);
496 /****************************************************************************
497 Check for a valid username and password in security=domain mode.
498 ****************************************************************************/
500 static BOOL check_domain_security(char *orig_user, char *domain,
501 char *smb_apasswd, int smb_apasslen,
502 char *smb_ntpasswd, int smb_ntpasslen)
504 if(lp_security() != SEC_DOMAIN)
507 return domain_client_validate(orig_user, domain,
508 smb_apasswd, smb_apasslen,
509 smb_ntpasswd, smb_ntpasslen);
512 /****************************************************************************
513 reply to a session setup command
514 ****************************************************************************/
516 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
519 uchar user_sess_key[16];
523 int smb_apasslen = 0;
525 int smb_ntpasslen = 0;
526 pstring smb_ntpasswd;
527 BOOL valid_nt_password = False;
531 static BOOL done_sesssetup = False;
532 BOOL doencrypt = SMBENCRYPT();
538 smb_bufsize = SVAL(inbuf,smb_vwv2);
540 if (Protocol < PROTOCOL_NT1) {
541 smb_apasslen = SVAL(inbuf,smb_vwv7);
542 if (smb_apasslen > MAX_PASS_LEN)
544 overflow_attack(smb_apasslen);
547 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
548 smb_apasswd[smb_apasslen] = 0;
549 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
551 if (!doencrypt && (lp_security() != SEC_SERVER)) {
552 smb_apasslen = strlen(smb_apasswd);
555 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
556 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
557 enum remote_arch_types ra_type = get_remote_arch();
558 char *p = smb_buf(inbuf);
560 global_client_caps = IVAL(inbuf,smb_vwv11);
562 /* client_caps is used as final determination if client is NT or Win95.
563 This is needed to return the correct error codes in some
567 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
569 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
570 set_remote_arch( RA_WINNT);
572 set_remote_arch( RA_WIN95);
575 if (passlen1 != 24 && passlen2 <= 24)
578 if (passlen1 > MAX_PASS_LEN) {
579 overflow_attack(passlen1);
582 passlen1 = MIN(passlen1, MAX_PASS_LEN);
583 passlen2 = MIN(passlen2, MAX_PASS_LEN);
586 /* both Win95 and WinNT stuff up the password lengths for
587 non-encrypting systems. Uggh.
589 if passlen1==24 its a win95 system, and its setting the
590 password length incorrectly. Luckily it still works with the
591 default code because Win95 will null terminate the password
594 if passlen1>0 and passlen2>0 then maybe its a NT box and its
595 setting passlen2 to some random value which really stuffs
596 things up. we need to fix that one. */
598 if (passlen1 > 0 && passlen2 > 0 && passlen2 <= 24 && passlen2 != 1)
602 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
603 /* Save the lanman2 password and the NT md4 password. */
604 smb_apasslen = passlen1;
605 memcpy(smb_apasswd,p,smb_apasslen);
606 smb_apasswd[smb_apasslen] = 0;
607 smb_ntpasslen = passlen2;
608 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
609 smb_ntpasswd[smb_ntpasslen] = 0;
611 /* we use the first password that they gave */
612 smb_apasslen = passlen1;
613 StrnCpy(smb_apasswd,p,smb_apasslen);
615 /* trim the password */
616 smb_apasslen = strlen(smb_apasswd);
618 /* wfwg sometimes uses a space instead of a null */
619 if (strequal(smb_apasswd," ")) {
625 p += passlen1 + passlen2;
626 fstrcpy(user,p); p = skip_string(p,1);
629 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
630 domain,skip_string(p,1),skip_string(p,2)));
633 DEBUG(3,("sesssetupX:name=[%s]\n",user));
635 /* If name ends in $ then I think it's asking about whether a */
636 /* computer with that name (minus the $) has access. For now */
637 /* say yes to everything ending in $. */
638 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
640 return session_trust_account(conn, inbuf, outbuf, user,
641 smb_apasswd, smb_apasslen,
642 smb_ntpasswd, smb_ntpasslen);
645 /* If no username is sent use the guest account */
648 pstrcpy(user,lp_guestaccount(-1));
649 /* If no user and no password then set guest flag. */
650 if( *smb_apasswd == 0)
656 * In share level security, only overwrite sesssetup_use if
657 * it's a non null-session share. Helps keep %U and %G
661 if((lp_security() != SEC_SHARE) || (*user && !guest))
662 pstrcpy(sesssetup_user,user);
663 reload_services(True);
666 * Save the username before mapping. We will use
667 * the original username sent to us for security=server
668 * and security=domain checking.
671 pstrcpy( orig_user, user);
673 map_nt_and_unix_username(domain, user);
675 add_session_user(user);
678 * Check if the given username was the guest user with no password.
681 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
685 * Check with orig_user for security=server and
690 !check_server_security(orig_user, domain,
691 smb_apasswd, smb_apasslen,
692 smb_ntpasswd, smb_ntpasslen) &&
693 !check_domain_security(orig_user, domain,
694 smb_apasswd, smb_apasslen,
695 smb_ntpasswd, smb_ntpasslen) &&
696 !check_hosts_equiv(user)
701 * If we get here then the user wasn't guest and the remote
702 * authentication methods failed. Check the authentication
703 * methods on this local server.
705 * If an NT password was supplied try and validate with that
706 * first. This is superior as the passwords are mixed case
707 * 128 length unicode.
712 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key))
713 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
715 valid_nt_password = True;
718 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key))
720 if (lp_security() >= SEC_USER)
722 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
723 return(ERROR(ERRSRV,ERRbadpw));
725 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
727 if (Get_Pwnam(user,True))
728 return(ERROR(ERRSRV,ERRbadpw));
732 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
733 * Then always map to guest account - as done below.
737 if (*smb_apasswd || !Get_Pwnam(user,True))
738 pstrcpy(user,lp_guestaccount(-1));
739 DEBUG(3,("Registered username %s for guest access\n",user));
744 if (!Get_Pwnam(user,True)) {
745 DEBUG(3,("No such user %s - using guest account\n",user));
746 pstrcpy(user,lp_guestaccount(-1));
750 if (!strequal(user,lp_guestaccount(-1)) &&
751 lp_servicenumber(user) < 0)
753 int homes = lp_servicenumber(HOMES_NAME);
754 char *home = get_home_dir(user);
755 if (homes >= 0 && home)
758 fstrcpy(home_dir, home);
759 lp_add_home(user,homes,home_dir);
763 /* it's ok - setup a reply */
764 if (Protocol < PROTOCOL_NT1) {
765 set_message(outbuf,3,0,True);
768 set_message(outbuf,3,3,True);
770 pstrcpy(p,"Unix"); p = skip_string(p,1);
771 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
772 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
773 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
774 /* perhaps grab OS version here?? */
777 /* Set the correct uid in the outgoing and incoming packets
778 We will use this on future requests to determine which
779 user we should become.
782 const struct passwd *pw = Get_Pwnam(user,False);
784 DEBUG(1,("Username %s is invalid on this system\n",user));
785 return(ERROR(ERRSRV,ERRbadpw));
792 SSVAL(outbuf,smb_vwv2,1);
794 /* register the name and uid as being validated, so further connections
795 to a uid can get through without a password, on the same VC */
796 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key);
798 SSVAL(outbuf,smb_uid,sess_vuid);
799 SSVAL(inbuf,smb_uid,sess_vuid);
802 max_send = MIN(max_send,smb_bufsize);
804 DEBUG(6,("Client requested max send size of %d\n", max_send));
806 done_sesssetup = True;
808 return chain_reply(inbuf,outbuf,length,bufsize);
812 /****************************************************************************
814 ****************************************************************************/
815 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
821 BOOL bad_path = False;
824 pstrcpy(name,smb_buf(inbuf) + 1);
825 unix_convert(name,conn,0,&bad_path,&st);
827 mode = SVAL(inbuf,smb_vwv0);
829 if (check_name(name,conn)) {
831 ok = S_ISDIR(st.st_mode);
833 ok = dos_directory_exist(name,NULL);
838 /* We special case this - as when a Windows machine
839 is parsing a path is steps through the components
840 one at a time - if a component fails it expects
841 ERRbadpath, not ERRbadfile.
845 unix_ERR_class = ERRDOS;
846 unix_ERR_code = ERRbadpath;
850 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
851 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
852 (get_remote_arch() == RA_WINNT))
854 unix_ERR_class = ERRDOS;
855 unix_ERR_code = ERRbaddirectory;
859 return(UNIXERROR(ERRDOS,ERRbadpath));
862 outsize = set_message(outbuf,0,0,True);
864 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
870 /****************************************************************************
872 ****************************************************************************/
873 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
877 SMB_STRUCT_STAT sbuf;
882 BOOL bad_path = False;
884 pstrcpy(fname,smb_buf(inbuf) + 1);
886 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
887 under WfWg - weird! */
890 mode = aHIDDEN | aDIR;
891 if (!CAN_WRITE(conn)) mode |= aRONLY;
898 unix_convert(fname,conn,0,&bad_path,&sbuf);
899 if (check_name(fname,conn))
901 if (VALID_STAT(sbuf) || conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == 0)
903 mode = dos_mode(conn,fname,&sbuf);
905 mtime = sbuf.st_mtime;
911 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
917 if((errno == ENOENT) && bad_path)
919 unix_ERR_class = ERRDOS;
920 unix_ERR_code = ERRbadpath;
923 return(UNIXERROR(ERRDOS,ERRbadfile));
926 outsize = set_message(outbuf,10,0,True);
928 SSVAL(outbuf,smb_vwv0,mode);
929 if(lp_dos_filetime_resolution(SNUM(conn)) )
930 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
932 put_dos_date3(outbuf,smb_vwv1,mtime);
933 SIVAL(outbuf,smb_vwv3,(uint32)size);
935 if (Protocol >= PROTOCOL_NT1) {
936 char *p = strrchr(fname,'/');
937 uint16 flg2 = SVAL(outbuf,smb_flg2);
939 if (!is_8_3(fname, True))
940 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
943 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
949 /****************************************************************************
951 ****************************************************************************/
952 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
960 BOOL bad_path = False;
962 pstrcpy(fname,smb_buf(inbuf) + 1);
963 unix_convert(fname,conn,0,&bad_path,&st);
965 mode = SVAL(inbuf,smb_vwv0);
966 mtime = make_unix_date3(inbuf+smb_vwv1);
968 if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
970 if (check_name(fname,conn))
971 ok = (file_chmod(conn,fname,mode,NULL) == 0);
973 ok = set_filetime(conn,fname,mtime);
977 if((errno == ENOENT) && bad_path)
979 unix_ERR_class = ERRDOS;
980 unix_ERR_code = ERRbadpath;
983 return(UNIXERROR(ERRDOS,ERRnoaccess));
986 outsize = set_message(outbuf,0,0,True);
988 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
994 /****************************************************************************
996 ****************************************************************************/
997 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1000 SMB_BIG_UINT dfree,dsize,bsize;
1002 conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);
1004 outsize = set_message(outbuf,5,0,True);
1006 SSVAL(outbuf,smb_vwv0,dsize);
1007 SSVAL(outbuf,smb_vwv1,bsize/512);
1008 SSVAL(outbuf,smb_vwv2,512);
1009 SSVAL(outbuf,smb_vwv3,dfree);
1011 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1017 /****************************************************************************
1019 Can be called from SMBsearch, SMBffirst or SMBfunique.
1020 ****************************************************************************/
1021 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1032 BOOL finished = False;
1041 BOOL check_descend = False;
1042 BOOL expect_close = False;
1043 BOOL can_open = True;
1044 BOOL bad_path = False;
1046 *mask = *directory = *fname = 0;
1048 /* If we were called as SMBffirst then we must expect close. */
1049 if(CVAL(inbuf,smb_com) == SMBffirst)
1050 expect_close = True;
1052 outsize = set_message(outbuf,1,3,True);
1053 maxentries = SVAL(inbuf,smb_vwv0);
1054 dirtype = SVAL(inbuf,smb_vwv1);
1055 path = smb_buf(inbuf) + 1;
1056 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1059 /* dirtype &= ~aDIR; */
1061 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1064 if (status_len == 0)
1068 pstrcpy(directory,smb_buf(inbuf)+1);
1069 pstrcpy(dir2,smb_buf(inbuf)+1);
1070 unix_convert(directory,conn,0,&bad_path,NULL);
1073 if (!check_name(directory,conn))
1076 p = strrchr(dir2,'/');
1088 p = strrchr(directory,'/');
1094 if (strlen(directory) == 0)
1095 pstrcpy(directory,"./");
1097 CVAL(status,0) = dirtype;
1101 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1102 memcpy(mask,status+1,11);
1104 dirtype = CVAL(status,0) & 0x1F;
1105 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1108 string_set(&conn->dirpath,dptr_path(dptr_num));
1109 if (!case_sensitive)
1113 /* turn strings of spaces into a . */
1115 trim_string(mask,NULL," ");
1116 if ((p = strrchr(mask,' ')))
1121 trim_string(mask,NULL," ");
1127 /* Convert the formatted mask. (This code lives in trans2.c) */
1135 if((skip = skip_multibyte_char( *p )) != 0 )
1141 if (*p != '?' && *p != '*' && !isdoschar(*p))
1143 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1151 if (!strchr(mask,'.') && strlen(mask)>8)
1154 fstrcpy(tmp,&mask[8]);
1160 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1164 p = smb_buf(outbuf) + 3;
1168 if (status_len == 0)
1170 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1175 if((errno == ENOENT) && bad_path)
1177 unix_ERR_class = ERRDOS;
1178 unix_ERR_code = ERRbadpath;
1180 return (UNIXERROR(ERRDOS,ERRnofids));
1182 return(ERROR(ERRDOS,ERRnofids));
1186 DEBUG(4,("dptr_num is %d\n",dptr_num));
1190 if ((dirtype&0x1F) == aVOLID)
1192 memcpy(p,status,21);
1193 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1194 dptr_fill(p+12,dptr_num);
1195 if (dptr_zero(p+12) && (status_len==0))
1199 p += DIR_STRUCT_SIZE;
1203 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1204 conn->dirpath,lp_dontdescend(SNUM(conn))));
1205 if (in_list(conn->dirpath,
1206 lp_dontdescend(SNUM(conn)),True))
1207 check_descend = True;
1209 for (i=numentries;(i<maxentries) && !finished;i++)
1212 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1215 memcpy(p,status,21);
1216 make_dir_struct(p,mask,fname,size,mode,date);
1217 dptr_fill(p+12,dptr_num);
1220 p += DIR_STRUCT_SIZE;
1229 if (numentries == 0 || !ok)
1231 CVAL(outbuf,smb_rcls) = ERRDOS;
1232 SSVAL(outbuf,smb_err,ERRnofiles);
1235 /* If we were called as SMBffirst with smb_search_id == NULL
1236 and no entries were found then return error and close dirptr
1239 if(ok && expect_close && numentries == 0 && status_len == 0)
1241 CVAL(outbuf,smb_rcls) = ERRDOS;
1242 SSVAL(outbuf,smb_err,ERRnofiles);
1243 /* Also close the dptr - we know it's gone */
1244 dptr_close(dptr_num);
1247 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1248 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1249 dptr_close(dptr_num);
1251 SSVAL(outbuf,smb_vwv0,numentries);
1252 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1253 CVAL(smb_buf(outbuf),0) = 5;
1254 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1256 if (Protocol >= PROTOCOL_NT1) {
1257 uint16 flg2 = SVAL(outbuf,smb_flg2);
1258 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1261 outsize += DIR_STRUCT_SIZE*numentries;
1262 smb_setlen(outbuf,outsize - 4);
1264 if ((! *directory) && dptr_path(dptr_num))
1265 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1267 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1268 smb_fn_name(CVAL(inbuf,smb_com)),
1269 mask, directory, dirtype, numentries, maxentries ) );
1275 /****************************************************************************
1276 reply to a fclose (stop directory search)
1277 ****************************************************************************/
1278 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1286 outsize = set_message(outbuf,1,0,True);
1287 path = smb_buf(inbuf) + 1;
1288 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1291 if (status_len == 0)
1292 return(ERROR(ERRSRV,ERRsrverror));
1294 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1296 if(dptr_fetch(status+12,&dptr_num)) {
1297 /* Close the dptr - we know it's gone */
1298 dptr_close(dptr_num);
1301 SSVAL(outbuf,smb_vwv0,0);
1303 DEBUG(3,("search close\n"));
1309 /****************************************************************************
1311 ****************************************************************************/
1313 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1323 SMB_STRUCT_STAT sbuf;
1324 BOOL bad_path = False;
1326 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1328 share_mode = SVAL(inbuf,smb_vwv0);
1330 pstrcpy(fname,smb_buf(inbuf)+1);
1331 unix_convert(fname,conn,0,&bad_path,NULL);
1335 return(ERROR(ERRSRV,ERRnofids));
1337 if (!check_name(fname,conn))
1339 if((errno == ENOENT) && bad_path)
1341 unix_ERR_class = ERRDOS;
1342 unix_ERR_code = ERRbadpath;
1345 return(UNIXERROR(ERRDOS,ERRnoaccess));
1348 unixmode = unix_mode(conn,aARCH);
1350 open_file_shared(fsp, conn, fname, share_mode,
1351 (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN),
1352 unixmode, oplock_request, &rmode, NULL);
1356 if((errno == ENOENT) && bad_path)
1358 unix_ERR_class = ERRDOS;
1359 unix_ERR_code = ERRbadpath;
1362 return(UNIXERROR(ERRDOS,ERRnoaccess));
1365 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1366 close_file(fsp,False);
1367 return(ERROR(ERRDOS,ERRnoaccess));
1370 size = sbuf.st_size;
1371 fmode = dos_mode(conn,fname,&sbuf);
1372 mtime = sbuf.st_mtime;
1375 DEBUG(3,("attempt to open a directory %s\n",fname));
1376 close_file(fsp,False);
1377 return(ERROR(ERRDOS,ERRnoaccess));
1380 outsize = set_message(outbuf,7,0,True);
1381 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1382 SSVAL(outbuf,smb_vwv1,fmode);
1383 if(lp_dos_filetime_resolution(SNUM(conn)) )
1384 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1386 put_dos_date3(outbuf,smb_vwv2,mtime);
1387 SIVAL(outbuf,smb_vwv4,(uint32)size);
1388 SSVAL(outbuf,smb_vwv6,rmode);
1390 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1391 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1394 if(fsp->granted_oplock)
1395 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1400 /****************************************************************************
1401 reply to an open and X
1402 ****************************************************************************/
1403 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1406 int smb_mode = SVAL(inbuf,smb_vwv3);
1407 int smb_attr = SVAL(inbuf,smb_vwv5);
1408 /* Breakout the oplock request bits so we can set the
1409 reply bits separately. */
1410 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1411 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1412 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1414 int open_flags = SVAL(inbuf,smb_vwv2);
1415 int smb_sattr = SVAL(inbuf,smb_vwv4);
1416 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1418 int smb_ofun = SVAL(inbuf,smb_vwv8);
1421 int fmode=0,mtime=0,rmode=0;
1422 SMB_STRUCT_STAT sbuf;
1424 BOOL bad_path = False;
1427 /* If it's an IPC, pass off the pipe handler. */
1428 if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
1430 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1433 /* XXXX we need to handle passed times, sattr and flags */
1435 pstrcpy(fname,smb_buf(inbuf));
1436 unix_convert(fname,conn,0,&bad_path,NULL);
1440 return(ERROR(ERRSRV,ERRnofids));
1442 if (!check_name(fname,conn))
1444 if((errno == ENOENT) && bad_path)
1446 unix_ERR_class = ERRDOS;
1447 unix_ERR_code = ERRbadpath;
1450 return(UNIXERROR(ERRDOS,ERRnoaccess));
1453 unixmode = unix_mode(conn,smb_attr | aARCH);
1455 open_file_shared(fsp, conn, fname, smb_mode, smb_ofun, unixmode,
1456 oplock_request, &rmode, &smb_action);
1460 if((errno == ENOENT) && bad_path)
1462 unix_ERR_class = ERRDOS;
1463 unix_ERR_code = ERRbadpath;
1466 return(UNIXERROR(ERRDOS,ERRnoaccess));
1469 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1470 close_file(fsp,False);
1471 return(ERROR(ERRDOS,ERRnoaccess));
1474 size = sbuf.st_size;
1475 fmode = dos_mode(conn,fname,&sbuf);
1476 mtime = sbuf.st_mtime;
1478 close_file(fsp,False);
1479 return(ERROR(ERRDOS,ERRnoaccess));
1482 /* If the caller set the extended oplock request bit
1483 and we granted one (by whatever means) - set the
1484 correct bit for extended oplock reply.
1487 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1488 smb_action |= EXTENDED_OPLOCK_GRANTED;
1491 if(ex_oplock_request && fsp->granted_oplock) {
1492 smb_action |= EXTENDED_OPLOCK_GRANTED;
1495 /* If the caller set the core oplock request bit
1496 and we granted one (by whatever means) - set the
1497 correct bit for core oplock reply.
1500 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1501 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1504 if(core_oplock_request && fsp->granted_oplock) {
1505 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1508 set_message(outbuf,15,0,True);
1509 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1510 SSVAL(outbuf,smb_vwv3,fmode);
1511 if(lp_dos_filetime_resolution(SNUM(conn)) )
1512 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1514 put_dos_date3(outbuf,smb_vwv4,mtime);
1515 SIVAL(outbuf,smb_vwv6,(uint32)size);
1516 SSVAL(outbuf,smb_vwv8,rmode);
1517 SSVAL(outbuf,smb_vwv11,smb_action);
1519 return chain_reply(inbuf,outbuf,length,bufsize);
1523 /****************************************************************************
1524 reply to a SMBulogoffX
1525 ****************************************************************************/
1526 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1528 uint16 vuid = SVAL(inbuf,smb_uid);
1529 user_struct *vuser = get_valid_user_struct(vuid);
1532 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1535 /* in user level security we are supposed to close any files
1536 open by this user */
1537 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1538 file_close_user(vuid);
1541 invalidate_vuid(vuid);
1543 set_message(outbuf,2,0,True);
1545 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1547 return chain_reply(inbuf,outbuf,length,bufsize);
1551 /****************************************************************************
1552 reply to a mknew or a create
1553 ****************************************************************************/
1554 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1562 BOOL bad_path = False;
1564 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1566 com = SVAL(inbuf,smb_com);
1568 createmode = SVAL(inbuf,smb_vwv0);
1569 pstrcpy(fname,smb_buf(inbuf)+1);
1570 unix_convert(fname,conn,0,&bad_path,NULL);
1572 if (createmode & aVOLID)
1574 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1577 unixmode = unix_mode(conn,createmode);
1581 return(ERROR(ERRSRV,ERRnofids));
1583 if (!check_name(fname,conn))
1585 if((errno == ENOENT) && bad_path)
1587 unix_ERR_class = ERRDOS;
1588 unix_ERR_code = ERRbadpath;
1591 return(UNIXERROR(ERRDOS,ERRnoaccess));
1596 /* We should fail if file exists. */
1601 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1605 /* Open file in dos compatibility share mode. */
1606 open_file_shared(fsp, conn, fname,
1607 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1608 ofun, unixmode, oplock_request, NULL, NULL);
1612 if((errno == ENOENT) && bad_path)
1614 unix_ERR_class = ERRDOS;
1615 unix_ERR_code = ERRbadpath;
1618 return(UNIXERROR(ERRDOS,ERRnoaccess));
1621 outsize = set_message(outbuf,1,0,True);
1622 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1624 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1625 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1628 if(fsp->granted_oplock)
1629 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1631 DEBUG( 2, ( "new file %s\n", fname ) );
1632 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1633 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1639 /****************************************************************************
1640 reply to a create temporary file
1641 ****************************************************************************/
1642 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1649 BOOL bad_path = False;
1651 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1653 createmode = SVAL(inbuf,smb_vwv0);
1654 pstrcpy(fname,smb_buf(inbuf)+1);
1655 pstrcat(fname,"/TMXXXXXX");
1656 unix_convert(fname,conn,0,&bad_path,NULL);
1658 unixmode = unix_mode(conn,createmode);
1662 return(ERROR(ERRSRV,ERRnofids));
1664 if (!check_name(fname,conn))
1666 if((errno == ENOENT) && bad_path)
1668 unix_ERR_class = ERRDOS;
1669 unix_ERR_code = ERRbadpath;
1672 return(UNIXERROR(ERRDOS,ERRnoaccess));
1675 pstrcpy(fname2,(char *)mktemp(fname));
1677 /* Open file in dos compatibility share mode. */
1678 /* We should fail if file exists. */
1679 open_file_shared(fsp,conn,fname2,
1680 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1681 (FILE_CREATE_IF_NOT_EXIST | FILE_EXISTS_FAIL),
1682 unixmode, oplock_request, NULL, NULL);
1686 if((errno == ENOENT) && bad_path)
1688 unix_ERR_class = ERRDOS;
1689 unix_ERR_code = ERRbadpath;
1692 return(UNIXERROR(ERRDOS,ERRnoaccess));
1695 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1696 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1697 CVAL(smb_buf(outbuf),0) = 4;
1698 pstrcpy(smb_buf(outbuf) + 1,fname2);
1700 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1701 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1704 if(fsp->granted_oplock)
1705 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1707 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1708 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1709 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1715 /*******************************************************************
1716 check if a user is allowed to delete a file
1717 ********************************************************************/
1718 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1720 SMB_STRUCT_STAT sbuf;
1723 if (!CAN_WRITE(conn)) return(False);
1725 if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False);
1726 fmode = dos_mode(conn,fname,&sbuf);
1727 if (fmode & aDIR) return(False);
1728 if (!lp_delete_readonly(SNUM(conn))) {
1729 if (fmode & aRONLY) return(False);
1731 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1733 if (!check_file_sharing(conn,fname,False)) return(False);
1737 /****************************************************************************
1739 ****************************************************************************/
1740 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1749 int error = ERRnoaccess;
1752 BOOL bad_path = False;
1754 *directory = *mask = 0;
1756 dirtype = SVAL(inbuf,smb_vwv0);
1758 pstrcpy(name,smb_buf(inbuf) + 1);
1760 DEBUG(3,("reply_unlink : %s\n",name));
1762 unix_convert(name,conn,0,&bad_path,NULL);
1764 p = strrchr(name,'/');
1766 pstrcpy(directory,"./");
1770 pstrcpy(directory,name);
1774 if (is_mangled(mask))
1775 check_mangled_cache( mask );
1777 has_wild = strchr(mask,'*') || strchr(mask,'?');
1780 pstrcat(directory,"/");
1781 pstrcat(directory,mask);
1782 if (can_delete(directory,conn,dirtype) && !conn->vfs_ops.unlink(directory))
1785 exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
1787 void *dirptr = NULL;
1790 if (check_name(directory,conn))
1791 dirptr = OpenDir(conn, directory, True);
1793 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1794 the pattern matches against the long name, otherwise the short name
1795 We don't implement this yet XXXX
1802 if (strequal(mask,"????????.???"))
1805 while ((dname = ReadDirName(dirptr)))
1808 pstrcpy(fname,dname);
1810 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1812 error = ERRnoaccess;
1813 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1814 if (!can_delete(fname,conn,dirtype)) continue;
1815 if (!conn->vfs_ops.unlink(fname)) count++;
1816 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1824 return(ERROR(ERRDOS,error));
1827 if((errno == ENOENT) && bad_path)
1829 unix_ERR_class = ERRDOS;
1830 unix_ERR_code = ERRbadpath;
1832 return(UNIXERROR(ERRDOS,error));
1836 outsize = set_message(outbuf,0,0,True);
1842 /****************************************************************************
1843 reply to a readbraw (core+ protocol)
1844 ****************************************************************************/
1845 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1847 size_t maxcount,mincount;
1850 char *header = outbuf;
1855 * Special check if an oplock break has been issued
1856 * and the readraw request croses on the wire, we must
1857 * return a zero length response here.
1860 if(global_oplock_break)
1862 _smb_setlen(header,0);
1863 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1864 DEBUG(5,("readbraw - oplock break finished\n"));
1868 fsp = file_fsp(inbuf,smb_vwv0);
1870 startpos = IVAL(inbuf,smb_vwv1);
1871 #ifdef LARGE_SMB_OFF_T
1872 if(CVAL(inbuf,smb_wct) == 10) {
1874 * This is a large offset (64 bit) read.
1876 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1878 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1879 (double)startpos ));
1880 _smb_setlen(header,0);
1881 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1885 #endif /* LARGE_SMB_OFF_T */
1886 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1887 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1889 /* ensure we don't overrun the packet size */
1890 maxcount = MIN(65535,maxcount);
1891 maxcount = MAX(mincount,maxcount);
1893 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1894 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1895 _smb_setlen(header,0);
1896 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1900 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1902 SMB_OFF_T size = fsp->size;
1903 SMB_OFF_T sizeneeded = startpos + maxcount;
1905 if (size < sizeneeded)
1908 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0)
1910 if (!fsp->can_write)
1914 nread = MIN(maxcount,(size - startpos));
1917 if (nread < mincount)
1920 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1921 fsp->fnum, (double)startpos,
1922 maxcount, mincount, nread ) );
1926 BOOL seek_fail = False;
1928 _smb_setlen(header,nread);
1930 #if USE_READ_PREDICTION
1931 if (!fsp->can_write)
1932 predict = read_predict(fsp, fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1933 #endif /* USE_READ_PREDICTION */
1935 if ((nread-predict) > 0) {
1936 if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) {
1937 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1944 ret = (ssize_t)vfs_transfer_file(-1, fsp->fd_ptr->fd, Client, NULL,
1945 (SMB_OFF_T)(nread-predict),header,4+predict,
1950 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1951 fsp->fsp_name,startpos,nread,ret));
1953 #else /* UNSAFE_READRAW */
1954 ret = read_file(fsp,header+4,startpos,nread);
1955 if (ret < mincount) ret = 0;
1957 _smb_setlen(header,ret);
1958 transfer_file(0,Client,0,header,4+ret,0);
1959 #endif /* UNSAFE_READRAW */
1961 DEBUG(5,("readbraw finished\n"));
1966 /****************************************************************************
1967 reply to a lockread (core+ protocol)
1968 ****************************************************************************/
1969 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1978 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1980 CHECK_FSP(fsp,conn);
1984 numtoread = SVAL(inbuf,smb_vwv1);
1985 startpos = IVAL(inbuf,smb_vwv2);
1987 outsize = set_message(outbuf,5,3,True);
1988 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1989 data = smb_buf(outbuf) + 3;
1991 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1992 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1994 * A blocking lock was requested. Package up
1995 * this smb into a queued request and push it
1996 * onto the blocking lock queue.
1998 if(push_blocking_lock_request(inbuf, length, -1, 0))
2001 return (ERROR(eclass,ecode));
2004 nread = read_file(fsp,data,startpos,numtoread);
2007 return(UNIXERROR(ERRDOS,ERRnoaccess));
2010 SSVAL(outbuf,smb_vwv0,nread);
2011 SSVAL(outbuf,smb_vwv5,nread+3);
2012 SSVAL(smb_buf(outbuf),1,nread);
2014 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2015 fsp->fnum, numtoread, nread ) );
2021 /****************************************************************************
2023 ****************************************************************************/
2024 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2031 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2033 CHECK_FSP(fsp,conn);
2037 numtoread = SVAL(inbuf,smb_vwv1);
2038 startpos = IVAL(inbuf,smb_vwv2);
2040 outsize = set_message(outbuf,5,3,True);
2041 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2042 data = smb_buf(outbuf) + 3;
2044 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2045 return(ERROR(ERRDOS,ERRlock));
2047 if (numtoread > 0) {
2048 nread = read_file(fsp,data,startpos,numtoread);
2052 return(UNIXERROR(ERRDOS,ERRnoaccess));
2055 SSVAL(outbuf,smb_vwv0,nread);
2056 SSVAL(outbuf,smb_vwv5,nread+3);
2057 CVAL(smb_buf(outbuf),0) = 1;
2058 SSVAL(smb_buf(outbuf),1,nread);
2060 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2061 fsp->fnum, numtoread, nread ) );
2067 /****************************************************************************
2068 reply to a read and X
2069 ****************************************************************************/
2070 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2072 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2073 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2074 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2075 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2079 /* If it's an IPC, pass off the pipe handler. */
2081 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2083 CHECK_FSP(fsp,conn);
2087 set_message(outbuf,12,0,True);
2088 data = smb_buf(outbuf);
2090 #ifdef LARGE_SMB_OFF_T
2091 if(CVAL(inbuf,smb_wct) == 12) {
2093 * This is a large offset (64 bit) read.
2095 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2097 #endif /* LARGE_SMB_OFF_T */
2099 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2100 return(ERROR(ERRDOS,ERRlock));
2101 nread = read_file(fsp,data,startpos,smb_maxcnt);
2104 return(UNIXERROR(ERRDOS,ERRnoaccess));
2106 SSVAL(outbuf,smb_vwv5,nread);
2107 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2108 SSVAL(smb_buf(outbuf),-2,nread);
2110 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2111 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2113 return chain_reply(inbuf,outbuf,length,bufsize);
2116 /****************************************************************************
2117 reply to a writebraw (core+ or LANMAN1.0 protocol)
2118 ****************************************************************************/
2119 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2122 ssize_t total_written=0;
2123 size_t numtowrite=0;
2128 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2131 CHECK_FSP(fsp,conn);
2135 tcount = IVAL(inbuf,smb_vwv1);
2136 startpos = IVAL(inbuf,smb_vwv3);
2137 write_through = BITSETW(inbuf+smb_vwv7,0);
2139 /* We have to deal with slightly different formats depending
2140 on whether we are using the core+ or lanman1.0 protocol */
2141 if(Protocol <= PROTOCOL_COREPLUS) {
2142 numtowrite = SVAL(smb_buf(inbuf),-2);
2143 data = smb_buf(inbuf);
2145 numtowrite = SVAL(inbuf,smb_vwv10);
2146 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2149 /* force the error type */
2150 CVAL(inbuf,smb_com) = SMBwritec;
2151 CVAL(outbuf,smb_com) = SMBwritec;
2153 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2154 return(ERROR(ERRDOS,ERRlock));
2156 if (seek_file(fsp,startpos) == -1) {
2157 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2158 return(UNIXERROR(ERRDOS,ERRnoaccess));
2162 nwritten = write_file(fsp,data,numtowrite);
2164 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2165 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2167 if (nwritten < numtowrite)
2168 return(UNIXERROR(ERRHRD,ERRdiskfull));
2170 total_written = nwritten;
2172 /* Return a message to the redirector to tell it
2173 to send more bytes */
2174 CVAL(outbuf,smb_com) = SMBwritebraw;
2175 SSVALS(outbuf,smb_vwv0,-1);
2176 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2177 send_smb(Client,outbuf);
2179 /* Now read the raw data into the buffer and write it */
2180 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2181 exit_server("secondary writebraw failed");
2184 /* Even though this is not an smb message, smb_len
2185 returns the generic length of an smb message */
2186 numtowrite = smb_len(inbuf);
2188 if (tcount > nwritten+numtowrite) {
2189 DEBUG(3,("Client overestimated the write %d %d %d\n",
2190 tcount,nwritten,numtowrite));
2193 nwritten = vfs_transfer_file(Client, NULL, -1, fsp,
2194 (SMB_OFF_T)numtowrite,NULL,0,
2196 total_written += nwritten;
2198 /* Set up outbuf to return the correct return */
2199 outsize = set_message(outbuf,1,0,True);
2200 CVAL(outbuf,smb_com) = SMBwritec;
2201 SSVAL(outbuf,smb_vwv0,total_written);
2203 if (nwritten < (ssize_t)numtowrite) {
2204 CVAL(outbuf,smb_rcls) = ERRHRD;
2205 SSVAL(outbuf,smb_err,ERRdiskfull);
2208 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2209 lp_strict_sync(SNUM(conn)))
2210 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2212 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2213 fsp->fnum, (double)startpos, numtowrite, total_written));
2215 /* we won't return a status if write through is not selected - this
2216 follows what WfWg does */
2217 if (!write_through && total_written==tcount)
2223 /****************************************************************************
2224 reply to a writeunlock (core+)
2225 ****************************************************************************/
2226 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2228 ssize_t nwritten = -1;
2234 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2237 CHECK_FSP(fsp,conn);
2241 numtowrite = SVAL(inbuf,smb_vwv1);
2242 startpos = IVAL(inbuf,smb_vwv2);
2243 data = smb_buf(inbuf) + 3;
2245 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2246 return(ERROR(ERRDOS,ERRlock));
2248 if(seek_file(fsp,startpos) == -1)
2249 return(UNIXERROR(ERRDOS,ERRnoaccess));
2251 /* The special X/Open SMB protocol handling of
2252 zero length writes is *NOT* done for
2257 nwritten = write_file(fsp,data,numtowrite);
2259 if (lp_syncalways(SNUM(conn)) && lp_strict_sync(SNUM(conn)))
2260 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2262 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2263 return(UNIXERROR(ERRDOS,ERRnoaccess));
2265 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2266 return(ERROR(eclass,ecode));
2268 outsize = set_message(outbuf,1,0,True);
2270 SSVAL(outbuf,smb_vwv0,nwritten);
2272 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2273 fsp->fnum, numtowrite, nwritten ) );
2278 /****************************************************************************
2280 ****************************************************************************/
2281 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2284 ssize_t nwritten = -1;
2287 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2290 CHECK_FSP(fsp,conn);
2294 numtowrite = SVAL(inbuf,smb_vwv1);
2295 startpos = IVAL(inbuf,smb_vwv2);
2296 data = smb_buf(inbuf) + 3;
2298 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2299 return(ERROR(ERRDOS,ERRlock));
2301 if(seek_file(fsp,startpos) == -1)
2302 return(UNIXERROR(ERRDOS,ERRnoaccess));
2304 /* X/Open SMB protocol says that if smb_vwv1 is
2305 zero then the file size should be extended or
2306 truncated to the size given in smb_vwv[2-3] */
2308 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2310 nwritten = write_file(fsp,data,numtowrite);
2312 if (lp_syncalways(SNUM(conn)) && lp_strict_sync(SNUM(conn)))
2313 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2315 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2316 return(UNIXERROR(ERRDOS,ERRnoaccess));
2318 outsize = set_message(outbuf,1,0,True);
2320 SSVAL(outbuf,smb_vwv0,nwritten);
2322 if (nwritten < (ssize_t)numtowrite) {
2323 CVAL(outbuf,smb_rcls) = ERRHRD;
2324 SSVAL(outbuf,smb_err,ERRdiskfull);
2327 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2328 fsp->fnum, numtowrite, nwritten));
2334 /****************************************************************************
2335 reply to a write and X
2336 ****************************************************************************/
2337 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2339 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2340 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2341 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2342 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2343 ssize_t nwritten = -1;
2344 int smb_doff = SVAL(inbuf,smb_vwv11);
2347 /* If it's an IPC, pass off the pipe handler. */
2349 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2351 CHECK_FSP(fsp,conn);
2355 data = smb_base(inbuf) + smb_doff;
2357 #ifdef LARGE_SMB_OFF_T
2358 if(CVAL(inbuf,smb_wct) == 14) {
2360 * This is a large offset (64 bit) write.
2362 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2364 #endif /* LARGE_SMB_OFF_T */
2366 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2367 return(ERROR(ERRDOS,ERRlock));
2369 if(seek_file(fsp,startpos) == -1)
2370 return(UNIXERROR(ERRDOS,ERRnoaccess));
2372 /* X/Open SMB protocol says that, unlike SMBwrite
2373 if the length is zero then NO truncation is
2374 done, just a write of zero. To truncate a file,
2379 nwritten = write_file(fsp,data,numtowrite);
2381 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2382 return(UNIXERROR(ERRDOS,ERRnoaccess));
2384 set_message(outbuf,6,0,True);
2386 SSVAL(outbuf,smb_vwv2,nwritten);
2388 if (nwritten < (ssize_t)numtowrite) {
2389 CVAL(outbuf,smb_rcls) = ERRHRD;
2390 SSVAL(outbuf,smb_err,ERRdiskfull);
2393 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2394 fsp->fnum, numtowrite, nwritten));
2396 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2397 lp_strict_sync(SNUM(conn)))
2398 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2400 return chain_reply(inbuf,outbuf,length,bufsize);
2404 /****************************************************************************
2406 ****************************************************************************/
2407 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2413 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2415 CHECK_FSP(fsp,conn);
2418 mode = SVAL(inbuf,smb_vwv1) & 3;
2419 startpos = IVAL(inbuf,smb_vwv2);
2423 case 0: umode = SEEK_SET; break;
2424 case 1: umode = SEEK_CUR; break;
2425 case 2: umode = SEEK_END; break;
2427 umode = SEEK_SET; break;
2430 if((res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2431 return(UNIXERROR(ERRDOS,ERRnoaccess));
2435 outsize = set_message(outbuf,2,0,True);
2436 SIVALS(outbuf,smb_vwv0,res);
2438 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2439 fsp->fnum, (double)startpos, mode));
2444 /****************************************************************************
2446 ****************************************************************************/
2447 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2449 int outsize = set_message(outbuf,0,0,True);
2450 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2453 CHECK_FSP(fsp,conn);
2458 file_sync_all(conn);
2460 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2463 DEBUG(3,("flush\n"));
2468 /****************************************************************************
2470 ****************************************************************************/
2471 int reply_exit(connection_struct *conn,
2472 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2474 int outsize = set_message(outbuf,0,0,True);
2475 DEBUG(3,("exit\n"));
2481 /****************************************************************************
2482 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2483 ****************************************************************************/
2484 int reply_close(connection_struct *conn,
2485 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2489 int32 eclass = 0, err = 0;
2490 files_struct *fsp = NULL;
2492 outsize = set_message(outbuf,0,0,True);
2494 /* If it's an IPC, pass off to the pipe handler. */
2496 return reply_pipe_close(conn, inbuf,outbuf);
2499 fsp = file_fsp(inbuf,smb_vwv0);
2502 * We can only use CHECK_FSP if we know it's not a directory.
2505 if(!fsp || !fsp->open || (fsp->conn != conn))
2506 return(ERROR(ERRDOS,ERRbadfid));
2508 if(HAS_CACHED_ERROR(fsp)) {
2509 eclass = fsp->wbmpx_ptr->wr_errclass;
2510 err = fsp->wbmpx_ptr->wr_error;
2513 if(fsp->is_directory) {
2515 * Special case - close NT SMB directory
2518 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2519 close_directory(fsp);
2522 * Close ordinary file.
2526 * If there was a modify time outstanding,
2527 * try and set it here.
2529 if(fsp->pending_modtime)
2530 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2533 * Now take care of any time sent in the close.
2535 mtime = make_unix_date3(inbuf+smb_vwv1);
2537 /* try and set the date */
2538 set_filetime(conn, fsp->fsp_name,mtime);
2540 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2541 fsp->fd_ptr->fd, fsp->fnum,
2542 conn->num_files_open));
2544 close_file(fsp,True);
2547 /* We have a cached error */
2549 return(ERROR(eclass,err));
2555 /****************************************************************************
2556 reply to a writeclose (Core+ protocol)
2557 ****************************************************************************/
2558 int reply_writeclose(connection_struct *conn,
2559 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2562 ssize_t nwritten = -1;
2567 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2569 CHECK_FSP(fsp,conn);
2573 numtowrite = SVAL(inbuf,smb_vwv1);
2574 startpos = IVAL(inbuf,smb_vwv2);
2575 mtime = make_unix_date3(inbuf+smb_vwv4);
2576 data = smb_buf(inbuf) + 1;
2578 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2579 return(ERROR(ERRDOS,ERRlock));
2581 if(seek_file(fsp,startpos) == -1)
2582 return(UNIXERROR(ERRDOS,ERRnoaccess));
2584 nwritten = write_file(fsp,data,numtowrite);
2586 set_filetime(conn, fsp->fsp_name,mtime);
2588 close_file(fsp,True);
2590 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2591 fsp->fnum, numtowrite, nwritten,
2592 conn->num_files_open));
2595 return(UNIXERROR(ERRDOS,ERRnoaccess));
2597 outsize = set_message(outbuf,1,0,True);
2599 SSVAL(outbuf,smb_vwv0,nwritten);
2604 /****************************************************************************
2606 ****************************************************************************/
2607 int reply_lock(connection_struct *conn,
2608 char *inbuf,char *outbuf, int length, int dum_buffsize)
2610 int outsize = set_message(outbuf,0,0,True);
2611 SMB_OFF_T count,offset;
2614 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2616 CHECK_FSP(fsp,conn);
2619 count = IVAL(inbuf,smb_vwv1);
2620 offset = IVAL(inbuf,smb_vwv3);
2622 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2623 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2625 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2626 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2628 * A blocking lock was requested. Package up
2629 * this smb into a queued request and push it
2630 * onto the blocking lock queue.
2632 if(push_blocking_lock_request(inbuf, length, -1, 0))
2635 return (ERROR(eclass,ecode));
2642 /****************************************************************************
2644 ****************************************************************************/
2645 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2647 int outsize = set_message(outbuf,0,0,True);
2648 SMB_OFF_T count,offset;
2651 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2653 CHECK_FSP(fsp,conn);
2656 count = IVAL(inbuf,smb_vwv1);
2657 offset = IVAL(inbuf,smb_vwv3);
2659 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2660 return (ERROR(eclass,ecode));
2662 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2663 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2669 /****************************************************************************
2671 ****************************************************************************/
2672 int reply_tdis(connection_struct *conn,
2673 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2675 int outsize = set_message(outbuf,0,0,True);
2678 vuid = SVAL(inbuf,smb_uid);
2681 DEBUG(4,("Invalid connection in tdis\n"));
2682 return(ERROR(ERRSRV,ERRinvnid));
2687 close_cnum(conn,vuid);
2694 /****************************************************************************
2696 ****************************************************************************/
2697 int reply_echo(connection_struct *conn,
2698 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2700 int smb_reverb = SVAL(inbuf,smb_vwv0);
2702 int data_len = smb_buflen(inbuf);
2703 int outsize = set_message(outbuf,1,data_len,True);
2705 /* copy any incoming data back out */
2707 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2709 if (smb_reverb > 100) {
2710 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2714 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2715 SSVAL(outbuf,smb_vwv0,seq_num);
2717 smb_setlen(outbuf,outsize - 4);
2719 send_smb(Client,outbuf);
2722 DEBUG(3,("echo %d times\n", smb_reverb));
2728 /****************************************************************************
2729 reply to a printopen
2730 ****************************************************************************/
2731 int reply_printopen(connection_struct *conn,
2732 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2739 *fname = *fname2 = 0;
2741 if (!CAN_PRINT(conn))
2742 return(ERROR(ERRDOS,ERRnoaccess));
2747 pstrcpy(s,smb_buf(inbuf)+1);
2750 if (!(isalnum((int)*p) || strchr("._-",*p)))
2755 if (strlen(s) > 10) s[10] = 0;
2757 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2762 return(ERROR(ERRSRV,ERRnofids));
2764 pstrcpy(fname2,(char *)mktemp(fname));
2766 if (!check_name(fname2,conn)) {
2768 return(ERROR(ERRDOS,ERRnoaccess));
2771 /* Open for exclusive use, write only. */
2772 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2773 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2777 return(UNIXERROR(ERRDOS,ERRnoaccess));
2780 /* force it to be a print file */
2781 fsp->print_file = True;
2783 outsize = set_message(outbuf,1,0,True);
2784 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2786 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2787 fname2, fsp->fd_ptr->fd, fsp->fnum));
2793 /****************************************************************************
2794 reply to a printclose
2795 ****************************************************************************/
2796 int reply_printclose(connection_struct *conn,
2797 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2799 int outsize = set_message(outbuf,0,0,True);
2800 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2802 CHECK_FSP(fsp,conn);
2805 if (!CAN_PRINT(conn))
2806 return(ERROR(ERRDOS,ERRnoaccess));
2808 DEBUG(3,("printclose fd=%d fnum=%d\n",
2809 fsp->fd_ptr->fd,fsp->fnum));
2811 close_file(fsp,True);
2817 /****************************************************************************
2818 reply to a printqueue
2819 ****************************************************************************/
2820 int reply_printqueue(connection_struct *conn,
2821 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2823 int outsize = set_message(outbuf,2,3,True);
2824 int max_count = SVAL(inbuf,smb_vwv0);
2825 int start_index = SVAL(inbuf,smb_vwv1);
2827 /* we used to allow the client to get the cnum wrong, but that
2828 is really quite gross and only worked when there was only
2829 one printer - I think we should now only accept it if they
2830 get it right (tridge) */
2831 if (!CAN_PRINT(conn))
2832 return(ERROR(ERRDOS,ERRnoaccess));
2834 SSVAL(outbuf,smb_vwv0,0);
2835 SSVAL(outbuf,smb_vwv1,0);
2836 CVAL(smb_buf(outbuf),0) = 1;
2837 SSVAL(smb_buf(outbuf),1,0);
2839 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2840 start_index, max_count));
2843 print_queue_struct *queue = NULL;
2844 char *p = smb_buf(outbuf) + 3;
2845 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2846 int num_to_get = ABS(max_count);
2847 int first = (max_count>0?start_index:start_index+max_count+1);
2853 num_to_get = MIN(num_to_get,count-first);
2856 for (i=first;i<first+num_to_get;i++) {
2857 put_dos_date2(p,0,queue[i].time);
2858 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2859 SSVAL(p,5,printjob_encode(SNUM(conn),
2861 SIVAL(p,7,queue[i].size);
2863 StrnCpy(p+12,queue[i].user,16);
2868 outsize = set_message(outbuf,2,28*count+3,False);
2869 SSVAL(outbuf,smb_vwv0,count);
2870 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2871 CVAL(smb_buf(outbuf),0) = 1;
2872 SSVAL(smb_buf(outbuf),1,28*count);
2875 if (queue) free(queue);
2877 DEBUG(3,("%d entries returned in queue\n",count));
2884 /****************************************************************************
2885 reply to a printwrite
2886 ****************************************************************************/
2887 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2890 int outsize = set_message(outbuf,0,0,True);
2892 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2894 if (!CAN_PRINT(conn))
2895 return(ERROR(ERRDOS,ERRnoaccess));
2897 CHECK_FSP(fsp,conn);
2901 numtowrite = SVAL(smb_buf(inbuf),1);
2902 data = smb_buf(inbuf) + 3;
2904 if (write_file(fsp,data,numtowrite) != numtowrite)
2905 return(UNIXERROR(ERRDOS,ERRnoaccess));
2907 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2913 /****************************************************************************
2915 ****************************************************************************/
2916 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2919 int outsize,ret= -1;
2920 BOOL bad_path = False;
2922 pstrcpy(directory,smb_buf(inbuf) + 1);
2923 unix_convert(directory,conn,0,&bad_path,NULL);
2925 if (check_name(directory, conn))
2926 ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
2927 unix_mode(conn,aDIR));
2931 if((errno == ENOENT) && bad_path)
2933 unix_ERR_class = ERRDOS;
2934 unix_ERR_code = ERRbadpath;
2936 return(UNIXERROR(ERRDOS,ERRnoaccess));
2939 outsize = set_message(outbuf,0,0,True);
2941 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2946 /****************************************************************************
2947 Static function used by reply_rmdir to delete an entire directory
2949 ****************************************************************************/
2950 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2954 void *dirptr = OpenDir(conn, directory, False);
2959 while((dname = ReadDirName(dirptr)))
2964 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2967 /* Construct the full name. */
2968 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2974 pstrcpy(fullname, directory);
2975 pstrcat(fullname, "/");
2976 pstrcat(fullname, dname);
2978 if(conn->vfs_ops.lstat(fullname, &st) != 0)
2984 if(st.st_mode & S_IFDIR)
2986 if(recursive_rmdir(conn, fullname)!=0)
2991 if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
2997 else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
3007 /****************************************************************************
3009 ****************************************************************************/
3010 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3015 BOOL bad_path = False;
3017 pstrcpy(directory,smb_buf(inbuf) + 1);
3018 unix_convert(directory,conn, NULL,&bad_path,NULL);
3020 if (check_name(directory,conn))
3023 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3024 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0);
3025 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
3027 /* Check to see if the only thing in this directory are
3028 vetoed files/directories. If so then delete them and
3029 retry. If we fail to delete any of them (and we *don't*
3030 do a recursive delete) then fail the rmdir. */
3031 BOOL all_veto_files = True;
3033 void *dirptr = OpenDir(conn, directory, False);
3037 int dirpos = TellDir(dirptr);
3038 while ((dname = ReadDirName(dirptr)))
3040 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3042 if(!IS_VETO_PATH(conn, dname))
3044 all_veto_files = False;
3050 SeekDir(dirptr,dirpos);
3051 while ((dname = ReadDirName(dirptr)))
3056 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3059 /* Construct the full name. */
3060 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3065 pstrcpy(fullname, directory);
3066 pstrcat(fullname, "/");
3067 pstrcat(fullname, dname);
3069 if(conn->vfs_ops.lstat(fullname, &st) != 0)
3071 if(st.st_mode & S_IFDIR)
3073 if(lp_recursive_veto_delete(SNUM(conn)))
3075 DEBUG(0, ("ERROR: recursive_rmdir()\n"));
3076 if(recursive_rmdir(conn, fullname) != 0)
3079 if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
3082 else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
3086 /* Retry the rmdir */
3087 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0);
3097 DEBUG(3,("couldn't remove directory %s : %s\n",
3098 directory,strerror(errno)));
3103 if((errno == ENOENT) && bad_path)
3105 unix_ERR_class = ERRDOS;
3106 unix_ERR_code = ERRbadpath;
3108 return(UNIXERROR(ERRDOS,ERRbadpath));
3111 outsize = set_message(outbuf,0,0,True);
3113 DEBUG( 3, ( "rmdir %s\n", directory ) );
3119 /*******************************************************************
3120 resolve wildcards in a filename rename
3121 ********************************************************************/
3122 static BOOL resolve_wildcards(char *name1,char *name2)
3124 fstring root1,root2;
3128 name1 = strrchr(name1,'/');
3129 name2 = strrchr(name2,'/');
3131 if (!name1 || !name2) return(False);
3133 fstrcpy(root1,name1);
3134 fstrcpy(root2,name2);
3135 p = strrchr(root1,'.');
3142 p = strrchr(root2,'.');
3174 pstrcpy(name2,root2);
3177 pstrcat(name2,ext2);
3183 /*******************************************************************
3184 check if a user is allowed to rename a file
3185 ********************************************************************/
3186 static BOOL can_rename(char *fname,connection_struct *conn)
3188 SMB_STRUCT_STAT sbuf;
3190 if (!CAN_WRITE(conn)) return(False);
3192 if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False);
3193 if (!check_file_sharing(conn,fname,True)) return(False);
3198 /****************************************************************************
3199 The guts of the rename command, split out so it may be called by the NT SMB
3201 ****************************************************************************/
3202 int rename_internals(connection_struct *conn,
3203 char *inbuf, char *outbuf, char *name,
3204 char *newname, BOOL replace_if_exists)
3208 pstring newname_last_component;
3211 BOOL bad_path1 = False;
3212 BOOL bad_path2 = False;
3214 int error = ERRnoaccess;
3217 *directory = *mask = 0;
3219 unix_convert(name,conn,0,&bad_path1,NULL);
3220 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3223 * Split the old name into directory and last component
3224 * strings. Note that unix_convert may have stripped off a
3225 * leading ./ from both name and newname if the rename is
3226 * at the root of the share. We need to make sure either both
3227 * name and newname contain a / character or neither of them do
3228 * as this is checked in resolve_wildcards().
3231 p = strrchr(name,'/');
3233 pstrcpy(directory,".");
3237 pstrcpy(directory,name);
3239 *p = '/'; /* Replace needed for exceptional test below. */
3242 if (is_mangled(mask))
3243 check_mangled_cache( mask );
3245 has_wild = strchr(mask,'*') || strchr(mask,'?');
3249 * No wildcards - just process the one file.
3251 BOOL is_short_name = is_8_3(name, True);
3253 /* Add a terminating '/' to the directory name. */
3254 pstrcat(directory,"/");
3255 pstrcat(directory,mask);
3257 /* Ensure newname contains a '/' also */
3258 if(strrchr(newname,'/') == 0) {
3261 pstrcpy(tmpstr, "./");
3262 pstrcat(tmpstr, newname);
3263 pstrcpy(newname, tmpstr);
3266 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",
3267 case_sensitive, case_preserve, short_case_preserve, directory,
3268 newname, newname_last_component, is_short_name));
3271 * Check for special case with case preserving and not
3272 * case sensitive, if directory and newname are identical,
3273 * and the old last component differs from the original
3274 * last component only by case, then we should allow
3275 * the rename (user is trying to change the case of the
3278 if((case_sensitive == False) &&
3279 (((case_preserve == True) &&
3280 (is_short_name == False)) ||
3281 ((short_case_preserve == True) &&
3282 (is_short_name == True))) &&
3283 strcsequal(directory, newname)) {
3284 pstring newname_modified_last_component;
3287 * Get the last component of the modified name.
3288 * Note that we guarantee that newname contains a '/'
3291 p = strrchr(newname,'/');
3292 pstrcpy(newname_modified_last_component,p+1);
3294 if(strcsequal(newname_modified_last_component,
3295 newname_last_component) == False) {
3297 * Replace the modified last component with
3300 pstrcpy(p+1, newname_last_component);
3304 if(replace_if_exists) {
3306 * NT SMB specific flag - rename can overwrite
3307 * file with the same name so don't check for
3310 if(resolve_wildcards(directory,newname) &&
3311 can_rename(directory,conn) &&
3312 !conn->vfs_ops.rename(dos_to_unix(directory,False),
3316 if (resolve_wildcards(directory,newname) &&
3317 can_rename(directory,conn) &&
3318 !vfs_file_exist(conn,dos_to_unix(newname,False),NULL) &&
3319 !conn->vfs_ops.rename(dos_to_unix(directory,False),
3324 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3325 directory,newname));
3327 if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
3328 if (!count && exists && vfs_file_exist(conn,dos_to_unix(newname,False),NULL)) {
3334 * Wildcards - process each file that matches.
3336 void *dirptr = NULL;
3340 if (check_name(directory,conn))
3341 dirptr = OpenDir(conn, directory, True);
3346 if (strequal(mask,"????????.???"))
3349 while ((dname = ReadDirName(dirptr))) {
3351 pstrcpy(fname,dname);
3353 if(!mask_match(fname, mask, case_sensitive, False))
3356 error = ERRnoaccess;
3357 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3358 if (!can_rename(fname,conn)) {
3359 DEBUG(6,("rename %s refused\n", fname));
3362 pstrcpy(destname,newname);
3364 if (!resolve_wildcards(fname,destname)) {
3365 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3369 if (!replace_if_exists && vfs_file_exist(conn,dos_to_unix(destname,False),NULL)) {
3370 DEBUG(6,("file_exist %s\n", destname));
3375 if (!conn->vfs_ops.rename(dos_to_unix(fname,False),destname))
3377 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3385 return(ERROR(ERRDOS,error));
3387 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3388 unix_ERR_class = ERRDOS;
3389 unix_ERR_code = ERRbadpath;
3391 return(UNIXERROR(ERRDOS,error));
3398 /****************************************************************************
3400 ****************************************************************************/
3402 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3408 pstrcpy(name,smb_buf(inbuf) + 1);
3409 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3411 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3413 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3415 outsize = set_message(outbuf,0,0,True);
3420 /*******************************************************************
3421 copy a file as part of a reply_copy
3422 ******************************************************************/
3424 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3425 int count,BOOL target_is_directory)
3430 files_struct *fsp1,*fsp2;
3433 pstrcpy(dest,dest1);
3434 if (target_is_directory) {
3435 char *p = strrchr(src,'/');
3444 if (!vfs_file_exist(conn,dos_to_unix(src,False),&st))
3451 open_file_shared(fsp1, conn, src,
3452 SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_RDONLY),
3453 (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN), 0, 0, &Access, &action);
3460 if (!target_is_directory && count)
3465 close_file(fsp1,False);
3468 open_file_shared(fsp2, conn, dest,
3469 SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_WRONLY),
3470 ofun, st.st_mode, 0, &Access, &action);
3473 close_file(fsp1,False);
3478 if ((ofun&3) == 1) {
3479 if(conn->vfs_ops.lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3480 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3483 * Stop the copy from occurring.
3491 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0);
3493 close_file(fsp1,False);
3494 close_file(fsp2,False);
3496 return(ret == st.st_size);
3501 /****************************************************************************
3502 reply to a file copy.
3503 ****************************************************************************/
3504 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3509 pstring mask,newname;
3512 int error = ERRnoaccess;
3515 int tid2 = SVAL(inbuf,smb_vwv0);
3516 int ofun = SVAL(inbuf,smb_vwv1);
3517 int flags = SVAL(inbuf,smb_vwv2);
3518 BOOL target_is_directory=False;
3519 BOOL bad_path1 = False;
3520 BOOL bad_path2 = False;
3522 *directory = *mask = 0;
3524 pstrcpy(name,smb_buf(inbuf));
3525 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3527 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3529 if (tid2 != conn->cnum) {
3530 /* can't currently handle inter share copies XXXX */
3531 DEBUG(3,("Rejecting inter-share copy\n"));
3532 return(ERROR(ERRSRV,ERRinvdevice));
3535 unix_convert(name,conn,0,&bad_path1,NULL);
3536 unix_convert(newname,conn,0,&bad_path2,NULL);
3538 target_is_directory = dos_directory_exist(newname,NULL);
3540 if ((flags&1) && target_is_directory) {
3541 return(ERROR(ERRDOS,ERRbadfile));
3544 if ((flags&2) && !target_is_directory) {
3545 return(ERROR(ERRDOS,ERRbadpath));
3548 if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
3549 /* wants a tree copy! XXXX */
3550 DEBUG(3,("Rejecting tree copy\n"));
3551 return(ERROR(ERRSRV,ERRerror));
3554 p = strrchr(name,'/');
3556 pstrcpy(directory,"./");
3560 pstrcpy(directory,name);
3564 if (is_mangled(mask))
3565 check_mangled_cache( mask );
3567 has_wild = strchr(mask,'*') || strchr(mask,'?');
3570 pstrcat(directory,"/");
3571 pstrcat(directory,mask);
3572 if (resolve_wildcards(directory,newname) &&
3573 copy_file(directory,newname,conn,ofun,
3574 count,target_is_directory)) count++;
3575 if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
3577 void *dirptr = NULL;
3581 if (check_name(directory,conn))
3582 dirptr = OpenDir(conn, directory, True);
3588 if (strequal(mask,"????????.???"))
3591 while ((dname = ReadDirName(dirptr)))
3594 pstrcpy(fname,dname);
3596 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3598 error = ERRnoaccess;
3599 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3600 pstrcpy(destname,newname);
3601 if (resolve_wildcards(fname,destname) &&
3602 copy_file(directory,newname,conn,ofun,
3603 count,target_is_directory)) count++;
3604 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3612 return(ERROR(ERRDOS,error));
3615 if((errno == ENOENT) && (bad_path1 || bad_path2))
3617 unix_ERR_class = ERRDOS;
3618 unix_ERR_code = ERRbadpath;
3620 return(UNIXERROR(ERRDOS,error));
3624 outsize = set_message(outbuf,1,0,True);
3625 SSVAL(outbuf,smb_vwv0,count);
3630 /****************************************************************************
3632 ****************************************************************************/
3633 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3641 if (!CAN_SETDIR(snum))
3642 return(ERROR(ERRDOS,ERRnoaccess));
3644 pstrcpy(newdir,smb_buf(inbuf) + 1);
3647 if (strlen(newdir) == 0) {
3650 ok = dos_directory_exist(newdir,NULL);
3652 string_set(&conn->connectpath,newdir);
3657 return(ERROR(ERRDOS,ERRbadpath));
3659 outsize = set_message(outbuf,0,0,True);
3660 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3662 DEBUG(3,("setdir %s\n", newdir));
3667 /****************************************************************************
3668 reply to a lockingX request
3669 ****************************************************************************/
3670 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3672 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3673 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3675 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3677 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3678 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3679 SMB_OFF_T count = 0, offset = 0;
3680 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3683 uint32 ecode=0, dummy2;
3684 int eclass=0, dummy1;
3685 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3686 CHECK_FSP(fsp,conn);
3689 data = smb_buf(inbuf);
3691 /* Check if this is an oplock break on a file
3692 we have granted an oplock on.
3694 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3697 SMB_DEV_T dev = fsp->fd_ptr->dev;
3698 SMB_INO_T inode = fsp->fd_ptr->inode;
3700 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3703 * Make sure we have granted an oplock on this file.
3705 if(!fsp->granted_oplock)
3707 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3708 no oplock granted on this file.\n", fsp->fnum));
3709 return ERROR(ERRDOS,ERRlock);
3712 /* Remove the oplock flag from the sharemode. */
3713 lock_share_entry(fsp->conn, dev, inode, &token);
3714 if(remove_share_oplock(token, fsp)==False) {
3716 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3717 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3719 unlock_share_entry(fsp->conn, dev, inode, token);
3721 unlock_share_entry(fsp->conn, dev, inode, token);
3723 /* Clear the granted flag and return. */
3724 fsp->granted_oplock = False;
3727 /* if this is a pure oplock break request then don't send a reply */
3728 if (num_locks == 0 && num_ulocks == 0)
3730 /* Sanity check - ensure a pure oplock break is not a
3732 if(CVAL(inbuf,smb_vwv0) != 0xff)
3733 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3734 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3739 /* Data now points at the beginning of the list
3740 of smb_unlkrng structs */
3741 for(i = 0; i < (int)num_ulocks; i++) {
3742 if(!large_file_format) {
3743 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3744 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3746 #ifdef LARGE_SMB_OFF_T
3748 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3749 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3750 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3751 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3753 #endif /* LARGE_SMB_OFF_T */
3755 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3756 (double)offset, (double)count, fsp->fsp_name ));
3758 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3759 return ERROR(eclass,ecode);
3762 /* Setup the timeout in seconds. */
3763 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3765 /* Now do any requested locks */
3766 data += ((large_file_format ? 20 : 10)*num_ulocks);
3768 /* Data now points at the beginning of the list
3769 of smb_lkrng structs */
3771 for(i = 0; i < (int)num_locks; i++) {
3772 if(!large_file_format) {
3773 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3774 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3776 #ifdef LARGE_SMB_OFF_T
3778 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3779 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3780 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3781 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3783 #endif /* LARGE_SMB_OFF_T */
3785 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3786 (double)offset, (double)count, fsp->fsp_name ));
3788 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3790 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3792 * A blocking lock was requested. Package up
3793 * this smb into a queued request and push it
3794 * onto the blocking lock queue.
3796 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3803 /* If any of the above locks failed, then we must unlock
3804 all of the previous locks (X/Open spec). */
3805 if(i != num_locks && num_locks != 0) {
3806 for(; i >= 0; i--) {
3807 if(!large_file_format) {
3808 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3809 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3811 #ifdef LARGE_SMB_OFF_T
3813 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3814 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3815 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3816 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3818 #endif /* LARGE_SMB_OFF_T */
3820 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3822 return ERROR(eclass,ecode);
3825 set_message(outbuf,2,0,True);
3827 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3828 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3830 return chain_reply(inbuf,outbuf,length,bufsize);
3834 /****************************************************************************
3835 reply to a SMBreadbmpx (read block multiplex) request
3836 ****************************************************************************/
3837 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3848 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3850 /* this function doesn't seem to work - disable by default */
3852 return(ERROR(ERRSRV,ERRuseSTD));
3854 outsize = set_message(outbuf,8,0,True);
3856 CHECK_FSP(fsp,conn);
3860 startpos = IVAL(inbuf,smb_vwv1);
3861 maxcount = SVAL(inbuf,smb_vwv3);
3863 data = smb_buf(outbuf);
3864 pad = ((long)data)%4;
3865 if (pad) pad = 4 - pad;
3868 max_per_packet = bufsize-(outsize+pad);
3872 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3873 return(ERROR(ERRDOS,ERRlock));
3877 size_t N = MIN(max_per_packet,tcount-total_read);
3879 nread = read_file(fsp,data,startpos,N);
3881 if (nread <= 0) nread = 0;
3883 if (nread < (ssize_t)N)
3884 tcount = total_read + nread;
3886 set_message(outbuf,8,nread,False);
3887 SIVAL(outbuf,smb_vwv0,startpos);
3888 SSVAL(outbuf,smb_vwv2,tcount);
3889 SSVAL(outbuf,smb_vwv6,nread);
3890 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3892 send_smb(Client,outbuf);
3894 total_read += nread;
3897 while (total_read < (ssize_t)tcount);
3902 /****************************************************************************
3903 reply to a SMBwritebmpx (write block multiplex primary) request
3904 ****************************************************************************/
3905 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3908 ssize_t nwritten = -1;
3915 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3917 CHECK_FSP(fsp,conn);
3921 tcount = SVAL(inbuf,smb_vwv1);
3922 startpos = IVAL(inbuf,smb_vwv3);
3923 write_through = BITSETW(inbuf+smb_vwv7,0);
3924 numtowrite = SVAL(inbuf,smb_vwv10);
3925 smb_doff = SVAL(inbuf,smb_vwv11);
3927 data = smb_base(inbuf) + smb_doff;
3929 /* If this fails we need to send an SMBwriteC response,
3930 not an SMBwritebmpx - set this up now so we don't forget */
3931 CVAL(outbuf,smb_com) = SMBwritec;
3933 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3934 return(ERROR(ERRDOS,ERRlock));
3936 if(seek_file(fsp,startpos) == -1)
3937 return(UNIXERROR(ERRDOS,ERRnoaccess));
3939 nwritten = write_file(fsp,data,numtowrite);
3941 if((lp_syncalways(SNUM(conn)) || write_through) &&
3942 lp_strict_sync(SNUM(conn)))
3943 conn->vfs_ops.sync(fsp->fd_ptr->fd);
3945 if(nwritten < (ssize_t)numtowrite)
3946 return(UNIXERROR(ERRHRD,ERRdiskfull));
3948 /* If the maximum to be written to this file
3949 is greater than what we just wrote then set
3950 up a secondary struct to be attached to this
3951 fd, we will use this to cache error messages etc. */
3952 if((ssize_t)tcount > nwritten)
3954 write_bmpx_struct *wbms;
3955 if(fsp->wbmpx_ptr != NULL)
3956 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3958 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3961 DEBUG(0,("Out of memory in reply_readmpx\n"));
3962 return(ERROR(ERRSRV,ERRnoresource));
3964 wbms->wr_mode = write_through;
3965 wbms->wr_discard = False; /* No errors yet */
3966 wbms->wr_total_written = nwritten;
3967 wbms->wr_errclass = 0;
3969 fsp->wbmpx_ptr = wbms;
3972 /* We are returning successfully, set the message type back to
3974 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3976 outsize = set_message(outbuf,1,0,True);
3978 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3980 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3981 fsp->fnum, numtowrite, nwritten ) );
3983 if (write_through && tcount==nwritten) {
3984 /* we need to send both a primary and a secondary response */
3985 smb_setlen(outbuf,outsize - 4);
3986 send_smb(Client,outbuf);
3988 /* now the secondary */
3989 outsize = set_message(outbuf,1,0,True);
3990 CVAL(outbuf,smb_com) = SMBwritec;
3991 SSVAL(outbuf,smb_vwv0,nwritten);
3998 /****************************************************************************
3999 reply to a SMBwritebs (write block multiplex secondary) request
4000 ****************************************************************************/
4001 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4004 ssize_t nwritten = -1;
4011 write_bmpx_struct *wbms;
4012 BOOL send_response = False;
4013 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4015 CHECK_FSP(fsp,conn);
4018 tcount = SVAL(inbuf,smb_vwv1);
4019 startpos = IVAL(inbuf,smb_vwv2);
4020 numtowrite = SVAL(inbuf,smb_vwv6);
4021 smb_doff = SVAL(inbuf,smb_vwv7);
4023 data = smb_base(inbuf) + smb_doff;
4025 /* We need to send an SMBwriteC response, not an SMBwritebs */
4026 CVAL(outbuf,smb_com) = SMBwritec;
4028 /* This fd should have an auxiliary struct attached,
4029 check that it does */
4030 wbms = fsp->wbmpx_ptr;
4031 if(!wbms) return(-1);
4033 /* If write through is set we can return errors, else we must
4035 write_through = wbms->wr_mode;
4037 /* Check for an earlier error */
4038 if(wbms->wr_discard)
4039 return -1; /* Just discard the packet */
4041 if(seek_file(fsp,startpos) == -1)
4045 /* We are returning an error - we can delete the aux struct */
4046 if (wbms) free((char *)wbms);
4047 fsp->wbmpx_ptr = NULL;
4048 return(UNIXERROR(ERRDOS,ERRnoaccess));
4050 return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
4053 nwritten = write_file(fsp,data,numtowrite);
4055 if((lp_syncalways(SNUM(conn)) || write_through) &&
4056 lp_strict_sync(SNUM(conn)))
4057 conn->vfs_ops.sync(fsp->fd_ptr->fd);
4059 if (nwritten < (ssize_t)numtowrite)
4063 /* We are returning an error - we can delete the aux struct */
4064 if (wbms) free((char *)wbms);
4065 fsp->wbmpx_ptr = NULL;
4066 return(ERROR(ERRHRD,ERRdiskfull));
4068 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4071 /* Increment the total written, if this matches tcount
4072 we can discard the auxiliary struct (hurrah !) and return a writeC */
4073 wbms->wr_total_written += nwritten;
4074 if(wbms->wr_total_written >= tcount)
4078 outsize = set_message(outbuf,1,0,True);
4079 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4080 send_response = True;
4084 fsp->wbmpx_ptr = NULL;
4094 /****************************************************************************
4095 reply to a SMBsetattrE
4096 ****************************************************************************/
4097 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4099 struct utimbuf unix_times;
4101 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4103 outsize = set_message(outbuf,0,0,True);
4105 CHECK_FSP(fsp,conn);
4108 /* Convert the DOS times into unix times. Ignore create
4109 time as UNIX can't set this.
4111 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4112 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4115 * Patch from Ray Frush <frush@engr.colostate.edu>
4116 * Sometimes times are sent as zero - ignore them.
4119 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4121 /* Ignore request */
4124 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4125 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4129 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4131 /* set modify time = to access time if modify time was 0 */
4132 unix_times.modtime = unix_times.actime;
4135 /* Set the date on this file */
4136 if(file_utime(conn, fsp->fsp_name, &unix_times))
4137 return(ERROR(ERRDOS,ERRnoaccess));
4139 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4140 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4146 /****************************************************************************
4147 reply to a SMBgetattrE
4148 ****************************************************************************/
4149 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4151 SMB_STRUCT_STAT sbuf;
4154 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4156 outsize = set_message(outbuf,11,0,True);
4158 CHECK_FSP(fsp,conn);
4161 /* Do an fstat on this file */
4162 if(fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf))
4163 return(UNIXERROR(ERRDOS,ERRnoaccess));
4165 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4167 /* Convert the times into dos times. Set create
4168 date to be last modify date as UNIX doesn't save
4170 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4171 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4172 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4175 SIVAL(outbuf,smb_vwv6,0);
4176 SIVAL(outbuf,smb_vwv8,0);
4180 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4181 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4183 SSVAL(outbuf,smb_vwv10, mode);
4185 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));