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, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
446 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
447 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
448 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
451 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
453 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
454 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
455 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
458 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
460 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
461 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
462 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
465 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
467 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
468 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
469 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
473 /* don't know what to do: indicate logon failure */
474 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
475 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
478 /****************************************************************************
479 Check for a valid username and password in security=server mode.
480 ****************************************************************************/
482 static BOOL check_server_security(char *orig_user, char *domain,
483 char *smb_apasswd, int smb_apasslen,
484 char *smb_ntpasswd, int smb_ntpasslen)
486 if(lp_security() != SEC_SERVER)
489 return server_validate(orig_user, domain,
490 smb_apasswd, smb_apasslen,
491 smb_ntpasswd, smb_ntpasslen);
494 /****************************************************************************
495 Check for a valid username and password in security=domain mode.
496 ****************************************************************************/
498 static BOOL check_domain_security(char *orig_user, char *domain,
499 char *smb_apasswd, int smb_apasslen,
500 char *smb_ntpasswd, int smb_ntpasslen)
502 if(lp_security() != SEC_DOMAIN)
505 return domain_client_validate(orig_user, domain,
506 smb_apasswd, smb_apasslen,
507 smb_ntpasswd, smb_ntpasslen);
510 /****************************************************************************
511 reply to a session setup command
512 ****************************************************************************/
514 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
517 uchar user_sess_key[16];
521 int smb_apasslen = 0;
523 int smb_ntpasslen = 0;
524 pstring smb_ntpasswd;
525 BOOL valid_nt_password = False;
529 static BOOL done_sesssetup = False;
530 BOOL doencrypt = SMBENCRYPT();
536 smb_bufsize = SVAL(inbuf,smb_vwv2);
538 if (Protocol < PROTOCOL_NT1) {
539 smb_apasslen = SVAL(inbuf,smb_vwv7);
540 if (smb_apasslen > MAX_PASS_LEN)
542 overflow_attack(smb_apasslen);
545 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
546 smb_apasswd[smb_apasslen] = 0;
547 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
549 if (!doencrypt && (lp_security() != SEC_SERVER)) {
550 smb_apasslen = strlen(smb_apasswd);
553 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
554 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
555 enum remote_arch_types ra_type = get_remote_arch();
556 char *p = smb_buf(inbuf);
558 global_client_caps = IVAL(inbuf,smb_vwv11);
560 /* client_caps is used as final determination if client is NT or Win95.
561 This is needed to return the correct error codes in some
565 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
567 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
568 set_remote_arch( RA_WINNT);
570 set_remote_arch( RA_WIN95);
573 if (passlen1 != 24 && passlen2 != 24)
576 if (passlen1 > MAX_PASS_LEN) {
577 overflow_attack(passlen1);
580 passlen1 = MIN(passlen1, MAX_PASS_LEN);
581 passlen2 = MIN(passlen2, MAX_PASS_LEN);
584 /* both Win95 and WinNT stuff up the password lengths for
585 non-encrypting systems. Uggh.
587 if passlen1==24 its a win95 system, and its setting the
588 password length incorrectly. Luckily it still works with the
589 default code because Win95 will null terminate the password
592 if passlen1>0 and passlen2>0 then maybe its a NT box and its
593 setting passlen2 to some random value which really stuffs
594 things up. we need to fix that one. */
596 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
600 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
601 /* Save the lanman2 password and the NT md4 password. */
602 smb_apasslen = passlen1;
603 memcpy(smb_apasswd,p,smb_apasslen);
604 smb_apasswd[smb_apasslen] = 0;
605 smb_ntpasslen = passlen2;
606 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
607 smb_ntpasswd[smb_ntpasslen] = 0;
609 /* we use the first password that they gave */
610 smb_apasslen = passlen1;
611 StrnCpy(smb_apasswd,p,smb_apasslen);
613 /* trim the password */
614 smb_apasslen = strlen(smb_apasswd);
616 /* wfwg sometimes uses a space instead of a null */
617 if (strequal(smb_apasswd," ")) {
623 p += passlen1 + passlen2;
624 fstrcpy(user,p); p = skip_string(p,1);
627 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
628 domain,skip_string(p,1),skip_string(p,2)));
631 DEBUG(3,("sesssetupX:name=[%s]\n",user));
633 /* If name ends in $ then I think it's asking about whether a */
634 /* computer with that name (minus the $) has access. For now */
635 /* say yes to everything ending in $. */
636 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
638 return session_trust_account(conn, inbuf, outbuf, user,
639 smb_apasswd, smb_apasslen,
640 smb_ntpasswd, smb_ntpasslen);
643 /* If no username is sent use the guest account */
646 pstrcpy(user,lp_guestaccount(-1));
647 /* If no user and no password then set guest flag. */
648 if( *smb_apasswd == 0)
654 * In share level security, only overwrite sesssetup_use if
655 * it's a non null-session share. Helps keep %U and %G
659 if((lp_security() != SEC_SHARE) || (*user && !guest))
660 pstrcpy(sesssetup_user,user);
661 reload_services(True);
664 * Save the username before mapping. We will use
665 * the original username sent to us for security=server
666 * and security=domain checking.
669 pstrcpy( orig_user, user);
671 map_nt_and_unix_username(domain, user);
673 add_session_user(user);
676 * Check if the given username was the guest user with no password.
679 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
683 * Check with orig_user for security=server and
688 !check_server_security(orig_user, domain,
689 smb_apasswd, smb_apasslen,
690 smb_ntpasswd, smb_ntpasslen) &&
691 !check_domain_security(orig_user, domain,
692 smb_apasswd, smb_apasslen,
693 smb_ntpasswd, smb_ntpasslen) &&
694 !check_hosts_equiv(user)
699 * If we get here then the user wasn't guest and the remote
700 * authentication methods failed. Check the authentication
701 * methods on this local server.
703 * If an NT password was supplied try and validate with that
704 * first. This is superior as the passwords are mixed case
705 * 128 length unicode.
710 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key))
711 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
713 valid_nt_password = True;
716 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key))
718 if (lp_security() >= SEC_USER)
720 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
721 return(ERROR(ERRSRV,ERRbadpw));
723 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
725 if (Get_Pwnam(user,True))
726 return(ERROR(ERRSRV,ERRbadpw));
730 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
731 * Then always map to guest account - as done below.
735 if (*smb_apasswd || !Get_Pwnam(user,True))
736 pstrcpy(user,lp_guestaccount(-1));
737 DEBUG(3,("Registered username %s for guest access\n",user));
742 if (!Get_Pwnam(user,True)) {
743 DEBUG(3,("No such user %s - using guest account\n",user));
744 pstrcpy(user,lp_guestaccount(-1));
748 if (!strequal(user,lp_guestaccount(-1)) &&
749 lp_servicenumber(user) < 0)
751 int homes = lp_servicenumber(HOMES_NAME);
752 char *home = get_home_dir(user);
753 if (homes >= 0 && home)
756 fstrcpy(home_dir, home);
757 lp_add_home(user,homes,home_dir);
761 /* it's ok - setup a reply */
762 if (Protocol < PROTOCOL_NT1) {
763 set_message(outbuf,3,0,True);
766 set_message(outbuf,3,3,True);
768 pstrcpy(p,"Unix"); p = skip_string(p,1);
769 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
770 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
771 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
772 /* perhaps grab OS version here?? */
775 /* Set the correct uid in the outgoing and incoming packets
776 We will use this on future requests to determine which
777 user we should become.
780 const struct passwd *pw = Get_Pwnam(user,False);
782 DEBUG(1,("Username %s is invalid on this system\n",user));
783 return(ERROR(ERRSRV,ERRbadpw));
790 SSVAL(outbuf,smb_vwv2,1);
792 /* register the name and uid as being validated, so further connections
793 to a uid can get through without a password, on the same VC */
794 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key);
796 SSVAL(outbuf,smb_uid,sess_vuid);
797 SSVAL(inbuf,smb_uid,sess_vuid);
800 max_send = MIN(max_send,smb_bufsize);
802 DEBUG(6,("Client requested max send size of %d\n", max_send));
804 done_sesssetup = True;
806 return chain_reply(inbuf,outbuf,length,bufsize);
810 /****************************************************************************
812 ****************************************************************************/
813 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
819 BOOL bad_path = False;
822 pstrcpy(name,smb_buf(inbuf) + 1);
823 unix_convert(name,conn,0,&bad_path,&st);
825 mode = SVAL(inbuf,smb_vwv0);
827 if (check_name(name,conn)) {
829 ok = S_ISDIR(st.st_mode);
831 ok = dos_directory_exist(name,NULL);
836 /* We special case this - as when a Windows machine
837 is parsing a path is steps through the components
838 one at a time - if a component fails it expects
839 ERRbadpath, not ERRbadfile.
843 unix_ERR_class = ERRDOS;
844 unix_ERR_code = ERRbadpath;
848 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
849 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
850 (get_remote_arch() == RA_WINNT))
852 unix_ERR_class = ERRDOS;
853 unix_ERR_code = ERRbaddirectory;
857 return(UNIXERROR(ERRDOS,ERRbadpath));
860 outsize = set_message(outbuf,0,0,True);
862 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
868 /****************************************************************************
870 ****************************************************************************/
871 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
875 SMB_STRUCT_STAT sbuf;
880 BOOL bad_path = False;
882 pstrcpy(fname,smb_buf(inbuf) + 1);
884 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
885 under WfWg - weird! */
888 mode = aHIDDEN | aDIR;
889 if (!CAN_WRITE(conn)) mode |= aRONLY;
896 unix_convert(fname,conn,0,&bad_path,&sbuf);
897 if (check_name(fname,conn))
899 if (VALID_STAT(sbuf) || conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == 0)
901 mode = dos_mode(conn,fname,&sbuf);
903 mtime = sbuf.st_mtime;
909 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
915 if((errno == ENOENT) && bad_path)
917 unix_ERR_class = ERRDOS;
918 unix_ERR_code = ERRbadpath;
921 return(UNIXERROR(ERRDOS,ERRbadfile));
924 outsize = set_message(outbuf,10,0,True);
926 SSVAL(outbuf,smb_vwv0,mode);
927 if(lp_dos_filetime_resolution(SNUM(conn)) )
928 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
930 put_dos_date3(outbuf,smb_vwv1,mtime);
931 SIVAL(outbuf,smb_vwv3,(uint32)size);
933 if (Protocol >= PROTOCOL_NT1) {
934 char *p = strrchr(fname,'/');
935 uint16 flg2 = SVAL(outbuf,smb_flg2);
937 if (!is_8_3(fname, True))
938 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
941 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
947 /****************************************************************************
949 ****************************************************************************/
950 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
958 BOOL bad_path = False;
960 pstrcpy(fname,smb_buf(inbuf) + 1);
961 unix_convert(fname,conn,0,&bad_path,&st);
963 mode = SVAL(inbuf,smb_vwv0);
964 mtime = make_unix_date3(inbuf+smb_vwv1);
966 if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
968 if (check_name(fname,conn))
969 ok = (file_chmod(conn,fname,mode,NULL) == 0);
971 ok = set_filetime(conn,fname,mtime);
975 if((errno == ENOENT) && bad_path)
977 unix_ERR_class = ERRDOS;
978 unix_ERR_code = ERRbadpath;
981 return(UNIXERROR(ERRDOS,ERRnoaccess));
984 outsize = set_message(outbuf,0,0,True);
986 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
992 /****************************************************************************
994 ****************************************************************************/
995 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
998 SMB_BIG_UINT dfree,dsize,bsize;
1000 conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);
1002 outsize = set_message(outbuf,5,0,True);
1004 SSVAL(outbuf,smb_vwv0,dsize);
1005 SSVAL(outbuf,smb_vwv1,bsize/512);
1006 SSVAL(outbuf,smb_vwv2,512);
1007 SSVAL(outbuf,smb_vwv3,dfree);
1009 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1015 /****************************************************************************
1017 Can be called from SMBsearch, SMBffirst or SMBfunique.
1018 ****************************************************************************/
1019 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1030 BOOL finished = False;
1039 BOOL check_descend = False;
1040 BOOL expect_close = False;
1041 BOOL can_open = True;
1042 BOOL bad_path = False;
1044 *mask = *directory = *fname = 0;
1046 /* If we were called as SMBffirst then we must expect close. */
1047 if(CVAL(inbuf,smb_com) == SMBffirst)
1048 expect_close = True;
1050 outsize = set_message(outbuf,1,3,True);
1051 maxentries = SVAL(inbuf,smb_vwv0);
1052 dirtype = SVAL(inbuf,smb_vwv1);
1053 path = smb_buf(inbuf) + 1;
1054 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1057 /* dirtype &= ~aDIR; */
1059 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1062 if (status_len == 0)
1066 pstrcpy(directory,smb_buf(inbuf)+1);
1067 pstrcpy(dir2,smb_buf(inbuf)+1);
1068 unix_convert(directory,conn,0,&bad_path,NULL);
1071 if (!check_name(directory,conn))
1074 p = strrchr(dir2,'/');
1086 p = strrchr(directory,'/');
1092 if (strlen(directory) == 0)
1093 pstrcpy(directory,"./");
1095 CVAL(status,0) = dirtype;
1099 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1100 memcpy(mask,status+1,11);
1102 dirtype = CVAL(status,0) & 0x1F;
1103 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1106 string_set(&conn->dirpath,dptr_path(dptr_num));
1107 if (!case_sensitive)
1111 /* turn strings of spaces into a . */
1113 trim_string(mask,NULL," ");
1114 if ((p = strrchr(mask,' ')))
1119 trim_string(mask,NULL," ");
1125 /* Convert the formatted mask. (This code lives in trans2.c) */
1133 if((skip = skip_multibyte_char( *p )) != 0 )
1139 if (*p != '?' && *p != '*' && !isdoschar(*p))
1141 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1149 if (!strchr(mask,'.') && strlen(mask)>8)
1152 fstrcpy(tmp,&mask[8]);
1158 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1162 p = smb_buf(outbuf) + 3;
1166 if (status_len == 0)
1168 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1173 if((errno == ENOENT) && bad_path)
1175 unix_ERR_class = ERRDOS;
1176 unix_ERR_code = ERRbadpath;
1178 return (UNIXERROR(ERRDOS,ERRnofids));
1180 return(ERROR(ERRDOS,ERRnofids));
1184 DEBUG(4,("dptr_num is %d\n",dptr_num));
1188 if ((dirtype&0x1F) == aVOLID)
1190 memcpy(p,status,21);
1191 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1192 dptr_fill(p+12,dptr_num);
1193 if (dptr_zero(p+12) && (status_len==0))
1197 p += DIR_STRUCT_SIZE;
1201 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1202 conn->dirpath,lp_dontdescend(SNUM(conn))));
1203 if (in_list(conn->dirpath,
1204 lp_dontdescend(SNUM(conn)),True))
1205 check_descend = True;
1207 for (i=numentries;(i<maxentries) && !finished;i++)
1210 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1213 memcpy(p,status,21);
1214 make_dir_struct(p,mask,fname,size,mode,date);
1215 dptr_fill(p+12,dptr_num);
1218 p += DIR_STRUCT_SIZE;
1227 if (numentries == 0 || !ok)
1229 CVAL(outbuf,smb_rcls) = ERRDOS;
1230 SSVAL(outbuf,smb_err,ERRnofiles);
1233 /* If we were called as SMBffirst with smb_search_id == NULL
1234 and no entries were found then return error and close dirptr
1237 if(ok && expect_close && numentries == 0 && status_len == 0)
1239 CVAL(outbuf,smb_rcls) = ERRDOS;
1240 SSVAL(outbuf,smb_err,ERRnofiles);
1241 /* Also close the dptr - we know it's gone */
1242 dptr_close(dptr_num);
1245 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1246 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1247 dptr_close(dptr_num);
1249 SSVAL(outbuf,smb_vwv0,numentries);
1250 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1251 CVAL(smb_buf(outbuf),0) = 5;
1252 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1254 if (Protocol >= PROTOCOL_NT1) {
1255 uint16 flg2 = SVAL(outbuf,smb_flg2);
1256 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1259 outsize += DIR_STRUCT_SIZE*numentries;
1260 smb_setlen(outbuf,outsize - 4);
1262 if ((! *directory) && dptr_path(dptr_num))
1263 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1265 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1266 smb_fn_name(CVAL(inbuf,smb_com)),
1267 mask, directory, dirtype, numentries, maxentries ) );
1273 /****************************************************************************
1274 reply to a fclose (stop directory search)
1275 ****************************************************************************/
1276 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1284 outsize = set_message(outbuf,1,0,True);
1285 path = smb_buf(inbuf) + 1;
1286 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1289 if (status_len == 0)
1290 return(ERROR(ERRSRV,ERRsrverror));
1292 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1294 if(dptr_fetch(status+12,&dptr_num)) {
1295 /* Close the dptr - we know it's gone */
1296 dptr_close(dptr_num);
1299 SSVAL(outbuf,smb_vwv0,0);
1301 DEBUG(3,("search close\n"));
1307 /****************************************************************************
1309 ****************************************************************************/
1311 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1321 SMB_STRUCT_STAT sbuf;
1322 BOOL bad_path = False;
1324 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1326 share_mode = SVAL(inbuf,smb_vwv0);
1328 pstrcpy(fname,smb_buf(inbuf)+1);
1329 unix_convert(fname,conn,0,&bad_path,NULL);
1333 return(ERROR(ERRSRV,ERRnofids));
1335 if (!check_name(fname,conn))
1337 if((errno == ENOENT) && bad_path)
1339 unix_ERR_class = ERRDOS;
1340 unix_ERR_code = ERRbadpath;
1343 return(UNIXERROR(ERRDOS,ERRnoaccess));
1346 unixmode = unix_mode(conn,aARCH);
1348 open_file_shared(fsp, conn, fname, share_mode,
1349 (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN),
1350 unixmode, oplock_request, &rmode, NULL);
1354 if((errno == ENOENT) && bad_path)
1356 unix_ERR_class = ERRDOS;
1357 unix_ERR_code = ERRbadpath;
1360 return(UNIXERROR(ERRDOS,ERRnoaccess));
1363 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1364 close_file(fsp,False);
1365 return(ERROR(ERRDOS,ERRnoaccess));
1368 size = sbuf.st_size;
1369 fmode = dos_mode(conn,fname,&sbuf);
1370 mtime = sbuf.st_mtime;
1373 DEBUG(3,("attempt to open a directory %s\n",fname));
1374 close_file(fsp,False);
1375 return(ERROR(ERRDOS,ERRnoaccess));
1378 outsize = set_message(outbuf,7,0,True);
1379 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1380 SSVAL(outbuf,smb_vwv1,fmode);
1381 if(lp_dos_filetime_resolution(SNUM(conn)) )
1382 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1384 put_dos_date3(outbuf,smb_vwv2,mtime);
1385 SIVAL(outbuf,smb_vwv4,(uint32)size);
1386 SSVAL(outbuf,smb_vwv6,rmode);
1388 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1389 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1392 if(fsp->granted_oplock)
1393 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1398 /****************************************************************************
1399 reply to an open and X
1400 ****************************************************************************/
1401 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1404 int smb_mode = SVAL(inbuf,smb_vwv3);
1405 int smb_attr = SVAL(inbuf,smb_vwv5);
1406 /* Breakout the oplock request bits so we can set the
1407 reply bits separately. */
1408 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1409 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1410 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1412 int open_flags = SVAL(inbuf,smb_vwv2);
1413 int smb_sattr = SVAL(inbuf,smb_vwv4);
1414 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1416 int smb_ofun = SVAL(inbuf,smb_vwv8);
1419 int fmode=0,mtime=0,rmode=0;
1420 SMB_STRUCT_STAT sbuf;
1422 BOOL bad_path = False;
1425 /* If it's an IPC, pass off the pipe handler. */
1426 if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
1428 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1431 /* XXXX we need to handle passed times, sattr and flags */
1433 pstrcpy(fname,smb_buf(inbuf));
1434 unix_convert(fname,conn,0,&bad_path,NULL);
1438 return(ERROR(ERRSRV,ERRnofids));
1440 if (!check_name(fname,conn))
1442 if((errno == ENOENT) && bad_path)
1444 unix_ERR_class = ERRDOS;
1445 unix_ERR_code = ERRbadpath;
1448 return(UNIXERROR(ERRDOS,ERRnoaccess));
1451 unixmode = unix_mode(conn,smb_attr | aARCH);
1453 open_file_shared(fsp, conn, fname, smb_mode, smb_ofun, unixmode,
1454 oplock_request, &rmode, &smb_action);
1458 if((errno == ENOENT) && bad_path)
1460 unix_ERR_class = ERRDOS;
1461 unix_ERR_code = ERRbadpath;
1464 return(UNIXERROR(ERRDOS,ERRnoaccess));
1467 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1468 close_file(fsp,False);
1469 return(ERROR(ERRDOS,ERRnoaccess));
1472 size = sbuf.st_size;
1473 fmode = dos_mode(conn,fname,&sbuf);
1474 mtime = sbuf.st_mtime;
1476 close_file(fsp,False);
1477 return(ERROR(ERRDOS,ERRnoaccess));
1480 /* If the caller set the extended oplock request bit
1481 and we granted one (by whatever means) - set the
1482 correct bit for extended oplock reply.
1485 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1486 smb_action |= EXTENDED_OPLOCK_GRANTED;
1489 if(ex_oplock_request && fsp->granted_oplock) {
1490 smb_action |= EXTENDED_OPLOCK_GRANTED;
1493 /* If the caller set the core oplock request bit
1494 and we granted one (by whatever means) - set the
1495 correct bit for core oplock reply.
1498 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1499 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1502 if(core_oplock_request && fsp->granted_oplock) {
1503 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1506 set_message(outbuf,15,0,True);
1507 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1508 SSVAL(outbuf,smb_vwv3,fmode);
1509 if(lp_dos_filetime_resolution(SNUM(conn)) )
1510 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1512 put_dos_date3(outbuf,smb_vwv4,mtime);
1513 SIVAL(outbuf,smb_vwv6,(uint32)size);
1514 SSVAL(outbuf,smb_vwv8,rmode);
1515 SSVAL(outbuf,smb_vwv11,smb_action);
1517 return chain_reply(inbuf,outbuf,length,bufsize);
1521 /****************************************************************************
1522 reply to a SMBulogoffX
1523 ****************************************************************************/
1524 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1526 uint16 vuid = SVAL(inbuf,smb_uid);
1527 user_struct *vuser = get_valid_user_struct(vuid);
1530 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1533 /* in user level security we are supposed to close any files
1534 open by this user */
1535 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1536 file_close_user(vuid);
1539 invalidate_vuid(vuid);
1541 set_message(outbuf,2,0,True);
1543 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1545 return chain_reply(inbuf,outbuf,length,bufsize);
1549 /****************************************************************************
1550 reply to a mknew or a create
1551 ****************************************************************************/
1552 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1560 BOOL bad_path = False;
1562 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1564 com = SVAL(inbuf,smb_com);
1566 createmode = SVAL(inbuf,smb_vwv0);
1567 pstrcpy(fname,smb_buf(inbuf)+1);
1568 unix_convert(fname,conn,0,&bad_path,NULL);
1570 if (createmode & aVOLID)
1572 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1575 unixmode = unix_mode(conn,createmode);
1579 return(ERROR(ERRSRV,ERRnofids));
1581 if (!check_name(fname,conn))
1583 if((errno == ENOENT) && bad_path)
1585 unix_ERR_class = ERRDOS;
1586 unix_ERR_code = ERRbadpath;
1589 return(UNIXERROR(ERRDOS,ERRnoaccess));
1594 /* We should fail if file exists. */
1599 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1603 /* Open file in dos compatibility share mode. */
1604 open_file_shared(fsp, conn, fname,
1605 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1606 ofun, unixmode, oplock_request, NULL, NULL);
1610 if((errno == ENOENT) && bad_path)
1612 unix_ERR_class = ERRDOS;
1613 unix_ERR_code = ERRbadpath;
1616 return(UNIXERROR(ERRDOS,ERRnoaccess));
1619 outsize = set_message(outbuf,1,0,True);
1620 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1622 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1623 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1626 if(fsp->granted_oplock)
1627 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1629 DEBUG( 2, ( "new file %s\n", fname ) );
1630 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1631 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1637 /****************************************************************************
1638 reply to a create temporary file
1639 ****************************************************************************/
1640 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1647 BOOL bad_path = False;
1649 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1651 createmode = SVAL(inbuf,smb_vwv0);
1652 pstrcpy(fname,smb_buf(inbuf)+1);
1653 pstrcat(fname,"/TMXXXXXX");
1654 unix_convert(fname,conn,0,&bad_path,NULL);
1656 unixmode = unix_mode(conn,createmode);
1660 return(ERROR(ERRSRV,ERRnofids));
1662 if (!check_name(fname,conn))
1664 if((errno == ENOENT) && bad_path)
1666 unix_ERR_class = ERRDOS;
1667 unix_ERR_code = ERRbadpath;
1670 return(UNIXERROR(ERRDOS,ERRnoaccess));
1673 pstrcpy(fname2,(char *)mktemp(fname));
1675 /* Open file in dos compatibility share mode. */
1676 /* We should fail if file exists. */
1677 open_file_shared(fsp,conn,fname2,
1678 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1679 (FILE_CREATE_IF_NOT_EXIST | FILE_EXISTS_FAIL),
1680 unixmode, oplock_request, NULL, NULL);
1684 if((errno == ENOENT) && bad_path)
1686 unix_ERR_class = ERRDOS;
1687 unix_ERR_code = ERRbadpath;
1690 return(UNIXERROR(ERRDOS,ERRnoaccess));
1693 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1694 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1695 CVAL(smb_buf(outbuf),0) = 4;
1696 pstrcpy(smb_buf(outbuf) + 1,fname2);
1698 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1699 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1702 if(fsp->granted_oplock)
1703 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1705 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1706 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1707 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1713 /*******************************************************************
1714 check if a user is allowed to delete a file
1715 ********************************************************************/
1716 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1718 SMB_STRUCT_STAT sbuf;
1721 if (!CAN_WRITE(conn)) return(False);
1723 if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False);
1724 fmode = dos_mode(conn,fname,&sbuf);
1725 if (fmode & aDIR) return(False);
1726 if (!lp_delete_readonly(SNUM(conn))) {
1727 if (fmode & aRONLY) return(False);
1729 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1731 if (!check_file_sharing(conn,fname,False)) return(False);
1735 /****************************************************************************
1737 ****************************************************************************/
1738 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1747 int error = ERRnoaccess;
1750 BOOL bad_path = False;
1752 *directory = *mask = 0;
1754 dirtype = SVAL(inbuf,smb_vwv0);
1756 pstrcpy(name,smb_buf(inbuf) + 1);
1758 DEBUG(3,("reply_unlink : %s\n",name));
1760 unix_convert(name,conn,0,&bad_path,NULL);
1762 p = strrchr(name,'/');
1764 pstrcpy(directory,"./");
1768 pstrcpy(directory,name);
1772 if (is_mangled(mask))
1773 check_mangled_cache( mask );
1775 has_wild = strchr(mask,'*') || strchr(mask,'?');
1778 pstrcat(directory,"/");
1779 pstrcat(directory,mask);
1780 if (can_delete(directory,conn,dirtype) && !conn->vfs_ops.unlink(directory))
1783 exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
1785 void *dirptr = NULL;
1788 if (check_name(directory,conn))
1789 dirptr = OpenDir(conn, directory, True);
1791 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1792 the pattern matches against the long name, otherwise the short name
1793 We don't implement this yet XXXX
1800 if (strequal(mask,"????????.???"))
1803 while ((dname = ReadDirName(dirptr)))
1806 pstrcpy(fname,dname);
1808 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1810 error = ERRnoaccess;
1811 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1812 if (!can_delete(fname,conn,dirtype)) continue;
1813 if (!conn->vfs_ops.unlink(fname)) count++;
1814 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1822 return(ERROR(ERRDOS,error));
1825 if((errno == ENOENT) && bad_path)
1827 unix_ERR_class = ERRDOS;
1828 unix_ERR_code = ERRbadpath;
1830 return(UNIXERROR(ERRDOS,error));
1834 outsize = set_message(outbuf,0,0,True);
1840 /****************************************************************************
1841 reply to a readbraw (core+ protocol)
1842 ****************************************************************************/
1843 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1845 size_t maxcount,mincount;
1848 char *header = outbuf;
1853 * Special check if an oplock break has been issued
1854 * and the readraw request croses on the wire, we must
1855 * return a zero length response here.
1858 if(global_oplock_break)
1860 _smb_setlen(header,0);
1861 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1862 DEBUG(5,("readbraw - oplock break finished\n"));
1866 fsp = file_fsp(inbuf,smb_vwv0);
1868 startpos = IVAL(inbuf,smb_vwv1);
1869 #ifdef LARGE_SMB_OFF_T
1870 if(CVAL(inbuf,smb_wct) == 10) {
1872 * This is a large offset (64 bit) read.
1874 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1876 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1877 (double)startpos ));
1878 _smb_setlen(header,0);
1879 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1883 #endif /* LARGE_SMB_OFF_T */
1884 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1885 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1887 /* ensure we don't overrun the packet size */
1888 maxcount = MIN(65535,maxcount);
1889 maxcount = MAX(mincount,maxcount);
1891 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1892 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1893 _smb_setlen(header,0);
1894 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1898 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1900 SMB_OFF_T size = fsp->size;
1901 SMB_OFF_T sizeneeded = startpos + maxcount;
1903 if (size < sizeneeded)
1906 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0)
1908 if (!fsp->can_write)
1912 nread = MIN(maxcount,(size - startpos));
1915 if (nread < mincount)
1918 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1919 fsp->fnum, (double)startpos,
1920 maxcount, mincount, nread ) );
1924 BOOL seek_fail = False;
1926 _smb_setlen(header,nread);
1928 #if USE_READ_PREDICTION
1929 if (!fsp->can_write)
1930 predict = read_predict(fsp, fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1931 #endif /* USE_READ_PREDICTION */
1933 if ((nread-predict) > 0) {
1934 if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) {
1935 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1942 ret = (ssize_t)vfs_transfer_file(-1, fsp->fd_ptr->fd, Client, NULL,
1943 (SMB_OFF_T)(nread-predict),header,4+predict,
1948 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1949 fsp->fsp_name,startpos,nread,ret));
1951 #else /* UNSAFE_READRAW */
1952 ret = read_file(fsp,header+4,startpos,nread);
1953 if (ret < mincount) ret = 0;
1955 _smb_setlen(header,ret);
1956 transfer_file(0,Client,0,header,4+ret,0);
1957 #endif /* UNSAFE_READRAW */
1959 DEBUG(5,("readbraw finished\n"));
1964 /****************************************************************************
1965 reply to a lockread (core+ protocol)
1966 ****************************************************************************/
1967 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1976 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1978 CHECK_FSP(fsp,conn);
1982 numtoread = SVAL(inbuf,smb_vwv1);
1983 startpos = IVAL(inbuf,smb_vwv2);
1985 outsize = set_message(outbuf,5,3,True);
1986 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1987 data = smb_buf(outbuf) + 3;
1989 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1990 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1992 * A blocking lock was requested. Package up
1993 * this smb into a queued request and push it
1994 * onto the blocking lock queue.
1996 if(push_blocking_lock_request(inbuf, length, -1, 0))
1999 return (ERROR(eclass,ecode));
2002 nread = read_file(fsp,data,startpos,numtoread);
2005 return(UNIXERROR(ERRDOS,ERRnoaccess));
2008 SSVAL(outbuf,smb_vwv0,nread);
2009 SSVAL(outbuf,smb_vwv5,nread+3);
2010 SSVAL(smb_buf(outbuf),1,nread);
2012 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2013 fsp->fnum, numtoread, nread ) );
2019 /****************************************************************************
2021 ****************************************************************************/
2022 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2029 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2031 CHECK_FSP(fsp,conn);
2035 numtoread = SVAL(inbuf,smb_vwv1);
2036 startpos = IVAL(inbuf,smb_vwv2);
2038 outsize = set_message(outbuf,5,3,True);
2039 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2040 data = smb_buf(outbuf) + 3;
2042 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2043 return(ERROR(ERRDOS,ERRlock));
2045 if (numtoread > 0) {
2046 nread = read_file(fsp,data,startpos,numtoread);
2050 return(UNIXERROR(ERRDOS,ERRnoaccess));
2053 SSVAL(outbuf,smb_vwv0,nread);
2054 SSVAL(outbuf,smb_vwv5,nread+3);
2055 CVAL(smb_buf(outbuf),0) = 1;
2056 SSVAL(smb_buf(outbuf),1,nread);
2058 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2059 fsp->fnum, numtoread, nread ) );
2065 /****************************************************************************
2066 reply to a read and X
2067 ****************************************************************************/
2068 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2070 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2071 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2072 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2073 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2077 /* If it's an IPC, pass off the pipe handler. */
2079 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2081 CHECK_FSP(fsp,conn);
2085 set_message(outbuf,12,0,True);
2086 data = smb_buf(outbuf);
2088 #ifdef LARGE_SMB_OFF_T
2089 if(CVAL(inbuf,smb_wct) == 12) {
2091 * This is a large offset (64 bit) read.
2093 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2095 #endif /* LARGE_SMB_OFF_T */
2097 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2098 return(ERROR(ERRDOS,ERRlock));
2099 nread = read_file(fsp,data,startpos,smb_maxcnt);
2102 return(UNIXERROR(ERRDOS,ERRnoaccess));
2104 SSVAL(outbuf,smb_vwv5,nread);
2105 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2106 SSVAL(smb_buf(outbuf),-2,nread);
2108 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2109 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2111 return chain_reply(inbuf,outbuf,length,bufsize);
2114 /****************************************************************************
2115 reply to a writebraw (core+ or LANMAN1.0 protocol)
2116 ****************************************************************************/
2117 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2120 ssize_t total_written=0;
2121 size_t numtowrite=0;
2126 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2129 CHECK_FSP(fsp,conn);
2133 tcount = IVAL(inbuf,smb_vwv1);
2134 startpos = IVAL(inbuf,smb_vwv3);
2135 write_through = BITSETW(inbuf+smb_vwv7,0);
2137 /* We have to deal with slightly different formats depending
2138 on whether we are using the core+ or lanman1.0 protocol */
2139 if(Protocol <= PROTOCOL_COREPLUS) {
2140 numtowrite = SVAL(smb_buf(inbuf),-2);
2141 data = smb_buf(inbuf);
2143 numtowrite = SVAL(inbuf,smb_vwv10);
2144 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2147 /* force the error type */
2148 CVAL(inbuf,smb_com) = SMBwritec;
2149 CVAL(outbuf,smb_com) = SMBwritec;
2151 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2152 return(ERROR(ERRDOS,ERRlock));
2154 if (seek_file(fsp,startpos) == -1) {
2155 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2156 return(UNIXERROR(ERRDOS,ERRnoaccess));
2160 nwritten = write_file(fsp,data,numtowrite);
2162 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2163 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2165 if (nwritten < numtowrite)
2166 return(UNIXERROR(ERRHRD,ERRdiskfull));
2168 total_written = nwritten;
2170 /* Return a message to the redirector to tell it
2171 to send more bytes */
2172 CVAL(outbuf,smb_com) = SMBwritebraw;
2173 SSVALS(outbuf,smb_vwv0,-1);
2174 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2175 send_smb(Client,outbuf);
2177 /* Now read the raw data into the buffer and write it */
2178 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2179 exit_server("secondary writebraw failed");
2182 /* Even though this is not an smb message, smb_len
2183 returns the generic length of an smb message */
2184 numtowrite = smb_len(inbuf);
2186 if (tcount > nwritten+numtowrite) {
2187 DEBUG(3,("Client overestimated the write %d %d %d\n",
2188 tcount,nwritten,numtowrite));
2191 nwritten = vfs_transfer_file(Client, NULL, -1, fsp,
2192 (SMB_OFF_T)numtowrite,NULL,0,
2194 total_written += nwritten;
2196 /* Set up outbuf to return the correct return */
2197 outsize = set_message(outbuf,1,0,True);
2198 CVAL(outbuf,smb_com) = SMBwritec;
2199 SSVAL(outbuf,smb_vwv0,total_written);
2201 if (nwritten < (ssize_t)numtowrite) {
2202 CVAL(outbuf,smb_rcls) = ERRHRD;
2203 SSVAL(outbuf,smb_err,ERRdiskfull);
2206 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2207 lp_strict_sync(SNUM(conn)))
2208 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2210 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2211 fsp->fnum, (double)startpos, numtowrite, total_written));
2213 /* we won't return a status if write through is not selected - this
2214 follows what WfWg does */
2215 if (!write_through && total_written==tcount)
2221 /****************************************************************************
2222 reply to a writeunlock (core+)
2223 ****************************************************************************/
2224 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2226 ssize_t nwritten = -1;
2232 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2235 CHECK_FSP(fsp,conn);
2239 numtowrite = SVAL(inbuf,smb_vwv1);
2240 startpos = IVAL(inbuf,smb_vwv2);
2241 data = smb_buf(inbuf) + 3;
2243 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2244 return(ERROR(ERRDOS,ERRlock));
2246 if(seek_file(fsp,startpos) == -1)
2247 return(UNIXERROR(ERRDOS,ERRnoaccess));
2249 /* The special X/Open SMB protocol handling of
2250 zero length writes is *NOT* done for
2255 nwritten = write_file(fsp,data,numtowrite);
2257 if (lp_syncalways(SNUM(conn)) && lp_strict_sync(SNUM(conn)))
2258 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2260 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2261 return(UNIXERROR(ERRDOS,ERRnoaccess));
2263 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2264 return(ERROR(eclass,ecode));
2266 outsize = set_message(outbuf,1,0,True);
2268 SSVAL(outbuf,smb_vwv0,nwritten);
2270 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2271 fsp->fnum, numtowrite, nwritten ) );
2276 /****************************************************************************
2278 ****************************************************************************/
2279 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2282 ssize_t nwritten = -1;
2285 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2288 CHECK_FSP(fsp,conn);
2292 numtowrite = SVAL(inbuf,smb_vwv1);
2293 startpos = IVAL(inbuf,smb_vwv2);
2294 data = smb_buf(inbuf) + 3;
2296 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2297 return(ERROR(ERRDOS,ERRlock));
2299 if(seek_file(fsp,startpos) == -1)
2300 return(UNIXERROR(ERRDOS,ERRnoaccess));
2302 /* X/Open SMB protocol says that if smb_vwv1 is
2303 zero then the file size should be extended or
2304 truncated to the size given in smb_vwv[2-3] */
2306 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2308 nwritten = write_file(fsp,data,numtowrite);
2310 if (lp_syncalways(SNUM(conn)) && lp_strict_sync(SNUM(conn)))
2311 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2313 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2314 return(UNIXERROR(ERRDOS,ERRnoaccess));
2316 outsize = set_message(outbuf,1,0,True);
2318 SSVAL(outbuf,smb_vwv0,nwritten);
2320 if (nwritten < (ssize_t)numtowrite) {
2321 CVAL(outbuf,smb_rcls) = ERRHRD;
2322 SSVAL(outbuf,smb_err,ERRdiskfull);
2325 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2326 fsp->fnum, numtowrite, nwritten));
2332 /****************************************************************************
2333 reply to a write and X
2334 ****************************************************************************/
2335 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2337 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2338 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2339 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2340 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2341 ssize_t nwritten = -1;
2342 int smb_doff = SVAL(inbuf,smb_vwv11);
2345 /* If it's an IPC, pass off the pipe handler. */
2347 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2349 CHECK_FSP(fsp,conn);
2353 data = smb_base(inbuf) + smb_doff;
2355 #ifdef LARGE_SMB_OFF_T
2356 if(CVAL(inbuf,smb_wct) == 14) {
2358 * This is a large offset (64 bit) write.
2360 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2362 #endif /* LARGE_SMB_OFF_T */
2364 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2365 return(ERROR(ERRDOS,ERRlock));
2367 if(seek_file(fsp,startpos) == -1)
2368 return(UNIXERROR(ERRDOS,ERRnoaccess));
2370 /* X/Open SMB protocol says that, unlike SMBwrite
2371 if the length is zero then NO truncation is
2372 done, just a write of zero. To truncate a file,
2377 nwritten = write_file(fsp,data,numtowrite);
2379 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2380 return(UNIXERROR(ERRDOS,ERRnoaccess));
2382 set_message(outbuf,6,0,True);
2384 SSVAL(outbuf,smb_vwv2,nwritten);
2386 if (nwritten < (ssize_t)numtowrite) {
2387 CVAL(outbuf,smb_rcls) = ERRHRD;
2388 SSVAL(outbuf,smb_err,ERRdiskfull);
2391 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2392 fsp->fnum, numtowrite, nwritten));
2394 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2395 lp_strict_sync(SNUM(conn)))
2396 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2398 return chain_reply(inbuf,outbuf,length,bufsize);
2402 /****************************************************************************
2404 ****************************************************************************/
2405 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2411 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2413 CHECK_FSP(fsp,conn);
2416 mode = SVAL(inbuf,smb_vwv1) & 3;
2417 startpos = IVAL(inbuf,smb_vwv2);
2421 case 0: umode = SEEK_SET; break;
2422 case 1: umode = SEEK_CUR; break;
2423 case 2: umode = SEEK_END; break;
2425 umode = SEEK_SET; break;
2428 if((res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2429 return(UNIXERROR(ERRDOS,ERRnoaccess));
2433 outsize = set_message(outbuf,2,0,True);
2434 SIVALS(outbuf,smb_vwv0,res);
2436 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2437 fsp->fnum, (double)startpos, mode));
2442 /****************************************************************************
2444 ****************************************************************************/
2445 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2447 int outsize = set_message(outbuf,0,0,True);
2448 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2451 CHECK_FSP(fsp,conn);
2456 file_sync_all(conn);
2458 conn->vfs_ops.sync(fsp->fd_ptr->fd);
2461 DEBUG(3,("flush\n"));
2466 /****************************************************************************
2468 ****************************************************************************/
2469 int reply_exit(connection_struct *conn,
2470 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2472 int outsize = set_message(outbuf,0,0,True);
2473 DEBUG(3,("exit\n"));
2479 /****************************************************************************
2480 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2481 ****************************************************************************/
2482 int reply_close(connection_struct *conn,
2483 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2487 int32 eclass = 0, err = 0;
2488 files_struct *fsp = NULL;
2490 outsize = set_message(outbuf,0,0,True);
2492 /* If it's an IPC, pass off to the pipe handler. */
2494 return reply_pipe_close(conn, inbuf,outbuf);
2497 fsp = file_fsp(inbuf,smb_vwv0);
2500 * We can only use CHECK_FSP if we know it's not a directory.
2503 if(!fsp || !fsp->open || (fsp->conn != conn))
2504 return(ERROR(ERRDOS,ERRbadfid));
2506 if(HAS_CACHED_ERROR(fsp)) {
2507 eclass = fsp->wbmpx_ptr->wr_errclass;
2508 err = fsp->wbmpx_ptr->wr_error;
2511 if(fsp->is_directory) {
2513 * Special case - close NT SMB directory
2516 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2517 close_directory(fsp);
2520 * Close ordinary file.
2524 * If there was a modify time outstanding,
2525 * try and set it here.
2527 if(fsp->pending_modtime)
2528 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2531 * Now take care of any time sent in the close.
2533 mtime = make_unix_date3(inbuf+smb_vwv1);
2535 /* try and set the date */
2536 set_filetime(conn, fsp->fsp_name,mtime);
2538 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2539 fsp->fd_ptr->fd, fsp->fnum,
2540 conn->num_files_open));
2542 close_file(fsp,True);
2545 /* We have a cached error */
2547 return(ERROR(eclass,err));
2553 /****************************************************************************
2554 reply to a writeclose (Core+ protocol)
2555 ****************************************************************************/
2556 int reply_writeclose(connection_struct *conn,
2557 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2560 ssize_t nwritten = -1;
2565 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2567 CHECK_FSP(fsp,conn);
2571 numtowrite = SVAL(inbuf,smb_vwv1);
2572 startpos = IVAL(inbuf,smb_vwv2);
2573 mtime = make_unix_date3(inbuf+smb_vwv4);
2574 data = smb_buf(inbuf) + 1;
2576 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2577 return(ERROR(ERRDOS,ERRlock));
2579 if(seek_file(fsp,startpos) == -1)
2580 return(UNIXERROR(ERRDOS,ERRnoaccess));
2582 nwritten = write_file(fsp,data,numtowrite);
2584 set_filetime(conn, fsp->fsp_name,mtime);
2586 close_file(fsp,True);
2588 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2589 fsp->fnum, numtowrite, nwritten,
2590 conn->num_files_open));
2593 return(UNIXERROR(ERRDOS,ERRnoaccess));
2595 outsize = set_message(outbuf,1,0,True);
2597 SSVAL(outbuf,smb_vwv0,nwritten);
2602 /****************************************************************************
2604 ****************************************************************************/
2605 int reply_lock(connection_struct *conn,
2606 char *inbuf,char *outbuf, int length, int dum_buffsize)
2608 int outsize = set_message(outbuf,0,0,True);
2609 SMB_OFF_T count,offset;
2612 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2614 CHECK_FSP(fsp,conn);
2617 count = IVAL(inbuf,smb_vwv1);
2618 offset = IVAL(inbuf,smb_vwv3);
2620 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2621 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2623 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2624 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2626 * A blocking lock was requested. Package up
2627 * this smb into a queued request and push it
2628 * onto the blocking lock queue.
2630 if(push_blocking_lock_request(inbuf, length, -1, 0))
2633 return (ERROR(eclass,ecode));
2640 /****************************************************************************
2642 ****************************************************************************/
2643 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2645 int outsize = set_message(outbuf,0,0,True);
2646 SMB_OFF_T count,offset;
2649 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2651 CHECK_FSP(fsp,conn);
2654 count = IVAL(inbuf,smb_vwv1);
2655 offset = IVAL(inbuf,smb_vwv3);
2657 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2658 return (ERROR(eclass,ecode));
2660 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2661 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2667 /****************************************************************************
2669 ****************************************************************************/
2670 int reply_tdis(connection_struct *conn,
2671 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2673 int outsize = set_message(outbuf,0,0,True);
2676 vuid = SVAL(inbuf,smb_uid);
2679 DEBUG(4,("Invalid connection in tdis\n"));
2680 return(ERROR(ERRSRV,ERRinvnid));
2685 close_cnum(conn,vuid);
2692 /****************************************************************************
2694 ****************************************************************************/
2695 int reply_echo(connection_struct *conn,
2696 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2698 int smb_reverb = SVAL(inbuf,smb_vwv0);
2700 int data_len = smb_buflen(inbuf);
2701 int outsize = set_message(outbuf,1,data_len,True);
2703 /* copy any incoming data back out */
2705 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2707 if (smb_reverb > 100) {
2708 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2712 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2713 SSVAL(outbuf,smb_vwv0,seq_num);
2715 smb_setlen(outbuf,outsize - 4);
2717 send_smb(Client,outbuf);
2720 DEBUG(3,("echo %d times\n", smb_reverb));
2726 /****************************************************************************
2727 reply to a printopen
2728 ****************************************************************************/
2729 int reply_printopen(connection_struct *conn,
2730 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2737 *fname = *fname2 = 0;
2739 if (!CAN_PRINT(conn))
2740 return(ERROR(ERRDOS,ERRnoaccess));
2745 pstrcpy(s,smb_buf(inbuf)+1);
2748 if (!(isalnum((int)*p) || strchr("._-",*p)))
2753 if (strlen(s) > 10) s[10] = 0;
2755 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2760 return(ERROR(ERRSRV,ERRnofids));
2762 pstrcpy(fname2,(char *)mktemp(fname));
2764 if (!check_name(fname2,conn)) {
2766 return(ERROR(ERRDOS,ERRnoaccess));
2769 /* Open for exclusive use, write only. */
2770 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2771 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2775 return(UNIXERROR(ERRDOS,ERRnoaccess));
2778 /* force it to be a print file */
2779 fsp->print_file = True;
2781 outsize = set_message(outbuf,1,0,True);
2782 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2784 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2785 fname2, fsp->fd_ptr->fd, fsp->fnum));
2791 /****************************************************************************
2792 reply to a printclose
2793 ****************************************************************************/
2794 int reply_printclose(connection_struct *conn,
2795 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2797 int outsize = set_message(outbuf,0,0,True);
2798 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2800 CHECK_FSP(fsp,conn);
2803 if (!CAN_PRINT(conn))
2804 return(ERROR(ERRDOS,ERRnoaccess));
2806 DEBUG(3,("printclose fd=%d fnum=%d\n",
2807 fsp->fd_ptr->fd,fsp->fnum));
2809 close_file(fsp,True);
2815 /****************************************************************************
2816 reply to a printqueue
2817 ****************************************************************************/
2818 int reply_printqueue(connection_struct *conn,
2819 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2821 int outsize = set_message(outbuf,2,3,True);
2822 int max_count = SVAL(inbuf,smb_vwv0);
2823 int start_index = SVAL(inbuf,smb_vwv1);
2825 /* we used to allow the client to get the cnum wrong, but that
2826 is really quite gross and only worked when there was only
2827 one printer - I think we should now only accept it if they
2828 get it right (tridge) */
2829 if (!CAN_PRINT(conn))
2830 return(ERROR(ERRDOS,ERRnoaccess));
2832 SSVAL(outbuf,smb_vwv0,0);
2833 SSVAL(outbuf,smb_vwv1,0);
2834 CVAL(smb_buf(outbuf),0) = 1;
2835 SSVAL(smb_buf(outbuf),1,0);
2837 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2838 start_index, max_count));
2841 print_queue_struct *queue = NULL;
2842 char *p = smb_buf(outbuf) + 3;
2843 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2844 int num_to_get = ABS(max_count);
2845 int first = (max_count>0?start_index:start_index+max_count+1);
2851 num_to_get = MIN(num_to_get,count-first);
2854 for (i=first;i<first+num_to_get;i++) {
2855 put_dos_date2(p,0,queue[i].time);
2856 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2857 SSVAL(p,5,printjob_encode(SNUM(conn),
2859 SIVAL(p,7,queue[i].size);
2861 StrnCpy(p+12,queue[i].user,16);
2866 outsize = set_message(outbuf,2,28*count+3,False);
2867 SSVAL(outbuf,smb_vwv0,count);
2868 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2869 CVAL(smb_buf(outbuf),0) = 1;
2870 SSVAL(smb_buf(outbuf),1,28*count);
2873 if (queue) free(queue);
2875 DEBUG(3,("%d entries returned in queue\n",count));
2882 /****************************************************************************
2883 reply to a printwrite
2884 ****************************************************************************/
2885 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2888 int outsize = set_message(outbuf,0,0,True);
2890 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2892 if (!CAN_PRINT(conn))
2893 return(ERROR(ERRDOS,ERRnoaccess));
2895 CHECK_FSP(fsp,conn);
2899 numtowrite = SVAL(smb_buf(inbuf),1);
2900 data = smb_buf(inbuf) + 3;
2902 if (write_file(fsp,data,numtowrite) != numtowrite)
2903 return(UNIXERROR(ERRDOS,ERRnoaccess));
2905 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2911 /****************************************************************************
2913 ****************************************************************************/
2914 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2917 int outsize,ret= -1;
2918 BOOL bad_path = False;
2920 pstrcpy(directory,smb_buf(inbuf) + 1);
2921 unix_convert(directory,conn,0,&bad_path,NULL);
2923 if (check_name(directory, conn))
2924 ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
2925 unix_mode(conn,aDIR));
2929 if((errno == ENOENT) && bad_path)
2931 unix_ERR_class = ERRDOS;
2932 unix_ERR_code = ERRbadpath;
2934 return(UNIXERROR(ERRDOS,ERRnoaccess));
2937 outsize = set_message(outbuf,0,0,True);
2939 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2944 /****************************************************************************
2945 Static function used by reply_rmdir to delete an entire directory
2947 ****************************************************************************/
2948 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2952 void *dirptr = OpenDir(conn, directory, False);
2957 while((dname = ReadDirName(dirptr)))
2962 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2965 /* Construct the full name. */
2966 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2972 pstrcpy(fullname, directory);
2973 pstrcat(fullname, "/");
2974 pstrcat(fullname, dname);
2976 if(conn->vfs_ops.lstat(fullname, &st) != 0)
2982 if(st.st_mode & S_IFDIR)
2984 if(recursive_rmdir(conn, fullname)!=0)
2989 if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
2995 else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
3005 /****************************************************************************
3007 ****************************************************************************/
3008 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3013 BOOL bad_path = False;
3015 pstrcpy(directory,smb_buf(inbuf) + 1);
3016 unix_convert(directory,conn, NULL,&bad_path,NULL);
3018 if (check_name(directory,conn))
3021 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3022 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0);
3023 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
3025 /* Check to see if the only thing in this directory are
3026 vetoed files/directories. If so then delete them and
3027 retry. If we fail to delete any of them (and we *don't*
3028 do a recursive delete) then fail the rmdir. */
3029 BOOL all_veto_files = True;
3031 void *dirptr = OpenDir(conn, directory, False);
3035 int dirpos = TellDir(dirptr);
3036 while ((dname = ReadDirName(dirptr)))
3038 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3040 if(!IS_VETO_PATH(conn, dname))
3042 all_veto_files = False;
3048 SeekDir(dirptr,dirpos);
3049 while ((dname = ReadDirName(dirptr)))
3054 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3057 /* Construct the full name. */
3058 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3063 pstrcpy(fullname, directory);
3064 pstrcat(fullname, "/");
3065 pstrcat(fullname, dname);
3067 if(conn->vfs_ops.lstat(fullname, &st) != 0)
3069 if(st.st_mode & S_IFDIR)
3071 if(lp_recursive_veto_delete(SNUM(conn)))
3073 DEBUG(0, ("ERROR: recursive_rmdir()\n"));
3074 if(recursive_rmdir(conn, fullname) != 0)
3077 if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
3080 else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
3084 /* Retry the rmdir */
3085 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0);
3095 DEBUG(3,("couldn't remove directory %s : %s\n",
3096 directory,strerror(errno)));
3101 if((errno == ENOENT) && bad_path)
3103 unix_ERR_class = ERRDOS;
3104 unix_ERR_code = ERRbadpath;
3106 return(UNIXERROR(ERRDOS,ERRbadpath));
3109 outsize = set_message(outbuf,0,0,True);
3111 DEBUG( 3, ( "rmdir %s\n", directory ) );
3117 /*******************************************************************
3118 resolve wildcards in a filename rename
3119 ********************************************************************/
3120 static BOOL resolve_wildcards(char *name1,char *name2)
3122 fstring root1,root2;
3126 name1 = strrchr(name1,'/');
3127 name2 = strrchr(name2,'/');
3129 if (!name1 || !name2) return(False);
3131 fstrcpy(root1,name1);
3132 fstrcpy(root2,name2);
3133 p = strrchr(root1,'.');
3140 p = strrchr(root2,'.');
3172 pstrcpy(name2,root2);
3175 pstrcat(name2,ext2);
3181 /*******************************************************************
3182 check if a user is allowed to rename a file
3183 ********************************************************************/
3184 static BOOL can_rename(char *fname,connection_struct *conn)
3186 SMB_STRUCT_STAT sbuf;
3188 if (!CAN_WRITE(conn)) return(False);
3190 if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False);
3191 if (!check_file_sharing(conn,fname,True)) return(False);
3196 /****************************************************************************
3197 The guts of the rename command, split out so it may be called by the NT SMB
3199 ****************************************************************************/
3200 int rename_internals(connection_struct *conn,
3201 char *inbuf, char *outbuf, char *name,
3202 char *newname, BOOL replace_if_exists)
3206 pstring newname_last_component;
3209 BOOL bad_path1 = False;
3210 BOOL bad_path2 = False;
3212 int error = ERRnoaccess;
3215 *directory = *mask = 0;
3217 unix_convert(name,conn,0,&bad_path1,NULL);
3218 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3221 * Split the old name into directory and last component
3222 * strings. Note that unix_convert may have stripped off a
3223 * leading ./ from both name and newname if the rename is
3224 * at the root of the share. We need to make sure either both
3225 * name and newname contain a / character or neither of them do
3226 * as this is checked in resolve_wildcards().
3229 p = strrchr(name,'/');
3231 pstrcpy(directory,".");
3235 pstrcpy(directory,name);
3237 *p = '/'; /* Replace needed for exceptional test below. */
3240 if (is_mangled(mask))
3241 check_mangled_cache( mask );
3243 has_wild = strchr(mask,'*') || strchr(mask,'?');
3247 * No wildcards - just process the one file.
3249 BOOL is_short_name = is_8_3(name, True);
3251 /* Add a terminating '/' to the directory name. */
3252 pstrcat(directory,"/");
3253 pstrcat(directory,mask);
3255 /* Ensure newname contains a '/' also */
3256 if(strrchr(newname,'/') == 0) {
3259 pstrcpy(tmpstr, "./");
3260 pstrcat(tmpstr, newname);
3261 pstrcpy(newname, tmpstr);
3264 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",
3265 case_sensitive, case_preserve, short_case_preserve, directory,
3266 newname, newname_last_component, is_short_name));
3269 * Check for special case with case preserving and not
3270 * case sensitive, if directory and newname are identical,
3271 * and the old last component differs from the original
3272 * last component only by case, then we should allow
3273 * the rename (user is trying to change the case of the
3276 if((case_sensitive == False) &&
3277 (((case_preserve == True) &&
3278 (is_short_name == False)) ||
3279 ((short_case_preserve == True) &&
3280 (is_short_name == True))) &&
3281 strcsequal(directory, newname)) {
3282 pstring newname_modified_last_component;
3285 * Get the last component of the modified name.
3286 * Note that we guarantee that newname contains a '/'
3289 p = strrchr(newname,'/');
3290 pstrcpy(newname_modified_last_component,p+1);
3292 if(strcsequal(newname_modified_last_component,
3293 newname_last_component) == False) {
3295 * Replace the modified last component with
3298 pstrcpy(p+1, newname_last_component);
3302 if(replace_if_exists) {
3304 * NT SMB specific flag - rename can overwrite
3305 * file with the same name so don't check for
3308 if(resolve_wildcards(directory,newname) &&
3309 can_rename(directory,conn) &&
3310 !conn->vfs_ops.rename(dos_to_unix(directory,False),
3314 if (resolve_wildcards(directory,newname) &&
3315 can_rename(directory,conn) &&
3316 !vfs_file_exist(conn,dos_to_unix(newname,False),NULL) &&
3317 !conn->vfs_ops.rename(dos_to_unix(directory,False),
3322 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3323 directory,newname));
3325 if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
3326 if (!count && exists && vfs_file_exist(conn,dos_to_unix(newname,False),NULL)) {
3332 * Wildcards - process each file that matches.
3334 void *dirptr = NULL;
3338 if (check_name(directory,conn))
3339 dirptr = OpenDir(conn, directory, True);
3344 if (strequal(mask,"????????.???"))
3347 while ((dname = ReadDirName(dirptr))) {
3349 pstrcpy(fname,dname);
3351 if(!mask_match(fname, mask, case_sensitive, False))
3354 error = ERRnoaccess;
3355 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3356 if (!can_rename(fname,conn)) {
3357 DEBUG(6,("rename %s refused\n", fname));
3360 pstrcpy(destname,newname);
3362 if (!resolve_wildcards(fname,destname)) {
3363 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3367 if (!replace_if_exists && vfs_file_exist(conn,dos_to_unix(destname,False),NULL)) {
3368 DEBUG(6,("file_exist %s\n", destname));
3373 if (!conn->vfs_ops.rename(dos_to_unix(fname,False),destname))
3375 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3383 return(ERROR(ERRDOS,error));
3385 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3386 unix_ERR_class = ERRDOS;
3387 unix_ERR_code = ERRbadpath;
3389 return(UNIXERROR(ERRDOS,error));
3396 /****************************************************************************
3398 ****************************************************************************/
3400 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3406 pstrcpy(name,smb_buf(inbuf) + 1);
3407 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3409 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3411 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3413 outsize = set_message(outbuf,0,0,True);
3418 /*******************************************************************
3419 copy a file as part of a reply_copy
3420 ******************************************************************/
3422 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3423 int count,BOOL target_is_directory)
3428 files_struct *fsp1,*fsp2;
3431 pstrcpy(dest,dest1);
3432 if (target_is_directory) {
3433 char *p = strrchr(src,'/');
3442 if (!vfs_file_exist(conn,dos_to_unix(src,False),&st))
3449 open_file_shared(fsp1, conn, src,
3450 SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_RDONLY),
3451 (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN), 0, 0, &Access, &action);
3458 if (!target_is_directory && count)
3463 close_file(fsp1,False);
3466 open_file_shared(fsp2, conn, dest,
3467 SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_WRONLY),
3468 ofun, st.st_mode, 0, &Access, &action);
3471 close_file(fsp1,False);
3476 if ((ofun&3) == 1) {
3477 if(conn->vfs_ops.lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3478 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3481 * Stop the copy from occurring.
3489 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0);
3491 close_file(fsp1,False);
3492 close_file(fsp2,False);
3494 return(ret == st.st_size);
3499 /****************************************************************************
3500 reply to a file copy.
3501 ****************************************************************************/
3502 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3507 pstring mask,newname;
3510 int error = ERRnoaccess;
3513 int tid2 = SVAL(inbuf,smb_vwv0);
3514 int ofun = SVAL(inbuf,smb_vwv1);
3515 int flags = SVAL(inbuf,smb_vwv2);
3516 BOOL target_is_directory=False;
3517 BOOL bad_path1 = False;
3518 BOOL bad_path2 = False;
3520 *directory = *mask = 0;
3522 pstrcpy(name,smb_buf(inbuf));
3523 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3525 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3527 if (tid2 != conn->cnum) {
3528 /* can't currently handle inter share copies XXXX */
3529 DEBUG(3,("Rejecting inter-share copy\n"));
3530 return(ERROR(ERRSRV,ERRinvdevice));
3533 unix_convert(name,conn,0,&bad_path1,NULL);
3534 unix_convert(newname,conn,0,&bad_path2,NULL);
3536 target_is_directory = dos_directory_exist(newname,NULL);
3538 if ((flags&1) && target_is_directory) {
3539 return(ERROR(ERRDOS,ERRbadfile));
3542 if ((flags&2) && !target_is_directory) {
3543 return(ERROR(ERRDOS,ERRbadpath));
3546 if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
3547 /* wants a tree copy! XXXX */
3548 DEBUG(3,("Rejecting tree copy\n"));
3549 return(ERROR(ERRSRV,ERRerror));
3552 p = strrchr(name,'/');
3554 pstrcpy(directory,"./");
3558 pstrcpy(directory,name);
3562 if (is_mangled(mask))
3563 check_mangled_cache( mask );
3565 has_wild = strchr(mask,'*') || strchr(mask,'?');
3568 pstrcat(directory,"/");
3569 pstrcat(directory,mask);
3570 if (resolve_wildcards(directory,newname) &&
3571 copy_file(directory,newname,conn,ofun,
3572 count,target_is_directory)) count++;
3573 if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
3575 void *dirptr = NULL;
3579 if (check_name(directory,conn))
3580 dirptr = OpenDir(conn, directory, True);
3586 if (strequal(mask,"????????.???"))
3589 while ((dname = ReadDirName(dirptr)))
3592 pstrcpy(fname,dname);
3594 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3596 error = ERRnoaccess;
3597 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3598 pstrcpy(destname,newname);
3599 if (resolve_wildcards(fname,destname) &&
3600 copy_file(directory,newname,conn,ofun,
3601 count,target_is_directory)) count++;
3602 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3610 return(ERROR(ERRDOS,error));
3613 if((errno == ENOENT) && (bad_path1 || bad_path2))
3615 unix_ERR_class = ERRDOS;
3616 unix_ERR_code = ERRbadpath;
3618 return(UNIXERROR(ERRDOS,error));
3622 outsize = set_message(outbuf,1,0,True);
3623 SSVAL(outbuf,smb_vwv0,count);
3628 /****************************************************************************
3630 ****************************************************************************/
3631 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3639 if (!CAN_SETDIR(snum))
3640 return(ERROR(ERRDOS,ERRnoaccess));
3642 pstrcpy(newdir,smb_buf(inbuf) + 1);
3645 if (strlen(newdir) == 0) {
3648 ok = dos_directory_exist(newdir,NULL);
3650 string_set(&conn->connectpath,newdir);
3655 return(ERROR(ERRDOS,ERRbadpath));
3657 outsize = set_message(outbuf,0,0,True);
3658 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3660 DEBUG(3,("setdir %s\n", newdir));
3665 /****************************************************************************
3666 reply to a lockingX request
3667 ****************************************************************************/
3668 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3670 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3671 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3673 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3675 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3676 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3677 SMB_OFF_T count = 0, offset = 0;
3678 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3681 uint32 ecode=0, dummy2;
3682 int eclass=0, dummy1;
3683 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3684 CHECK_FSP(fsp,conn);
3687 data = smb_buf(inbuf);
3689 /* Check if this is an oplock break on a file
3690 we have granted an oplock on.
3692 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3695 SMB_DEV_T dev = fsp->fd_ptr->dev;
3696 SMB_INO_T inode = fsp->fd_ptr->inode;
3698 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3701 * Make sure we have granted an oplock on this file.
3703 if(!fsp->granted_oplock)
3705 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3706 no oplock granted on this file.\n", fsp->fnum));
3707 return ERROR(ERRDOS,ERRlock);
3710 /* Remove the oplock flag from the sharemode. */
3711 lock_share_entry(fsp->conn, dev, inode, &token);
3712 if(remove_share_oplock(token, fsp)==False) {
3714 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3715 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3717 unlock_share_entry(fsp->conn, dev, inode, token);
3719 unlock_share_entry(fsp->conn, dev, inode, token);
3721 /* Clear the granted flag and return. */
3722 fsp->granted_oplock = False;
3725 /* if this is a pure oplock break request then don't send a reply */
3726 if (num_locks == 0 && num_ulocks == 0)
3728 /* Sanity check - ensure a pure oplock break is not a
3730 if(CVAL(inbuf,smb_vwv0) != 0xff)
3731 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3732 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3737 /* Data now points at the beginning of the list
3738 of smb_unlkrng structs */
3739 for(i = 0; i < (int)num_ulocks; i++) {
3740 if(!large_file_format) {
3741 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3742 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3744 #ifdef LARGE_SMB_OFF_T
3746 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3747 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3748 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3749 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3751 #endif /* LARGE_SMB_OFF_T */
3753 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3754 (double)offset, (double)count, fsp->fsp_name ));
3756 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3757 return ERROR(eclass,ecode);
3760 /* Setup the timeout in seconds. */
3761 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3763 /* Now do any requested locks */
3764 data += ((large_file_format ? 20 : 10)*num_ulocks);
3766 /* Data now points at the beginning of the list
3767 of smb_lkrng structs */
3769 for(i = 0; i < (int)num_locks; i++) {
3770 if(!large_file_format) {
3771 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3772 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3774 #ifdef LARGE_SMB_OFF_T
3776 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3777 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3778 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3779 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3781 #endif /* LARGE_SMB_OFF_T */
3783 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3784 (double)offset, (double)count, fsp->fsp_name ));
3786 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3788 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3790 * A blocking lock was requested. Package up
3791 * this smb into a queued request and push it
3792 * onto the blocking lock queue.
3794 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3801 /* If any of the above locks failed, then we must unlock
3802 all of the previous locks (X/Open spec). */
3803 if(i != num_locks && num_locks != 0) {
3804 for(; i >= 0; i--) {
3805 if(!large_file_format) {
3806 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3807 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3809 #ifdef LARGE_SMB_OFF_T
3811 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3812 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3813 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3814 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3816 #endif /* LARGE_SMB_OFF_T */
3818 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3820 return ERROR(eclass,ecode);
3823 set_message(outbuf,2,0,True);
3825 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3826 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3828 return chain_reply(inbuf,outbuf,length,bufsize);
3832 /****************************************************************************
3833 reply to a SMBreadbmpx (read block multiplex) request
3834 ****************************************************************************/
3835 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3846 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3848 /* this function doesn't seem to work - disable by default */
3850 return(ERROR(ERRSRV,ERRuseSTD));
3852 outsize = set_message(outbuf,8,0,True);
3854 CHECK_FSP(fsp,conn);
3858 startpos = IVAL(inbuf,smb_vwv1);
3859 maxcount = SVAL(inbuf,smb_vwv3);
3861 data = smb_buf(outbuf);
3862 pad = ((long)data)%4;
3863 if (pad) pad = 4 - pad;
3866 max_per_packet = bufsize-(outsize+pad);
3870 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3871 return(ERROR(ERRDOS,ERRlock));
3875 size_t N = MIN(max_per_packet,tcount-total_read);
3877 nread = read_file(fsp,data,startpos,N);
3879 if (nread <= 0) nread = 0;
3881 if (nread < (ssize_t)N)
3882 tcount = total_read + nread;
3884 set_message(outbuf,8,nread,False);
3885 SIVAL(outbuf,smb_vwv0,startpos);
3886 SSVAL(outbuf,smb_vwv2,tcount);
3887 SSVAL(outbuf,smb_vwv6,nread);
3888 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3890 send_smb(Client,outbuf);
3892 total_read += nread;
3895 while (total_read < (ssize_t)tcount);
3900 /****************************************************************************
3901 reply to a SMBwritebmpx (write block multiplex primary) request
3902 ****************************************************************************/
3903 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3906 ssize_t nwritten = -1;
3913 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3915 CHECK_FSP(fsp,conn);
3919 tcount = SVAL(inbuf,smb_vwv1);
3920 startpos = IVAL(inbuf,smb_vwv3);
3921 write_through = BITSETW(inbuf+smb_vwv7,0);
3922 numtowrite = SVAL(inbuf,smb_vwv10);
3923 smb_doff = SVAL(inbuf,smb_vwv11);
3925 data = smb_base(inbuf) + smb_doff;
3927 /* If this fails we need to send an SMBwriteC response,
3928 not an SMBwritebmpx - set this up now so we don't forget */
3929 CVAL(outbuf,smb_com) = SMBwritec;
3931 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3932 return(ERROR(ERRDOS,ERRlock));
3934 if(seek_file(fsp,startpos) == -1)
3935 return(UNIXERROR(ERRDOS,ERRnoaccess));
3937 nwritten = write_file(fsp,data,numtowrite);
3939 if((lp_syncalways(SNUM(conn)) || write_through) &&
3940 lp_strict_sync(SNUM(conn)))
3941 conn->vfs_ops.sync(fsp->fd_ptr->fd);
3943 if(nwritten < (ssize_t)numtowrite)
3944 return(UNIXERROR(ERRHRD,ERRdiskfull));
3946 /* If the maximum to be written to this file
3947 is greater than what we just wrote then set
3948 up a secondary struct to be attached to this
3949 fd, we will use this to cache error messages etc. */
3950 if((ssize_t)tcount > nwritten)
3952 write_bmpx_struct *wbms;
3953 if(fsp->wbmpx_ptr != NULL)
3954 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3956 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3959 DEBUG(0,("Out of memory in reply_readmpx\n"));
3960 return(ERROR(ERRSRV,ERRnoresource));
3962 wbms->wr_mode = write_through;
3963 wbms->wr_discard = False; /* No errors yet */
3964 wbms->wr_total_written = nwritten;
3965 wbms->wr_errclass = 0;
3967 fsp->wbmpx_ptr = wbms;
3970 /* We are returning successfully, set the message type back to
3972 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3974 outsize = set_message(outbuf,1,0,True);
3976 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3978 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3979 fsp->fnum, numtowrite, nwritten ) );
3981 if (write_through && tcount==nwritten) {
3982 /* we need to send both a primary and a secondary response */
3983 smb_setlen(outbuf,outsize - 4);
3984 send_smb(Client,outbuf);
3986 /* now the secondary */
3987 outsize = set_message(outbuf,1,0,True);
3988 CVAL(outbuf,smb_com) = SMBwritec;
3989 SSVAL(outbuf,smb_vwv0,nwritten);
3996 /****************************************************************************
3997 reply to a SMBwritebs (write block multiplex secondary) request
3998 ****************************************************************************/
3999 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4002 ssize_t nwritten = -1;
4009 write_bmpx_struct *wbms;
4010 BOOL send_response = False;
4011 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4013 CHECK_FSP(fsp,conn);
4016 tcount = SVAL(inbuf,smb_vwv1);
4017 startpos = IVAL(inbuf,smb_vwv2);
4018 numtowrite = SVAL(inbuf,smb_vwv6);
4019 smb_doff = SVAL(inbuf,smb_vwv7);
4021 data = smb_base(inbuf) + smb_doff;
4023 /* We need to send an SMBwriteC response, not an SMBwritebs */
4024 CVAL(outbuf,smb_com) = SMBwritec;
4026 /* This fd should have an auxiliary struct attached,
4027 check that it does */
4028 wbms = fsp->wbmpx_ptr;
4029 if(!wbms) return(-1);
4031 /* If write through is set we can return errors, else we must
4033 write_through = wbms->wr_mode;
4035 /* Check for an earlier error */
4036 if(wbms->wr_discard)
4037 return -1; /* Just discard the packet */
4039 if(seek_file(fsp,startpos) == -1)
4043 /* We are returning an error - we can delete the aux struct */
4044 if (wbms) free((char *)wbms);
4045 fsp->wbmpx_ptr = NULL;
4046 return(UNIXERROR(ERRDOS,ERRnoaccess));
4048 return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
4051 nwritten = write_file(fsp,data,numtowrite);
4053 if((lp_syncalways(SNUM(conn)) || write_through) &&
4054 lp_strict_sync(SNUM(conn)))
4055 conn->vfs_ops.sync(fsp->fd_ptr->fd);
4057 if (nwritten < (ssize_t)numtowrite)
4061 /* We are returning an error - we can delete the aux struct */
4062 if (wbms) free((char *)wbms);
4063 fsp->wbmpx_ptr = NULL;
4064 return(ERROR(ERRHRD,ERRdiskfull));
4066 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4069 /* Increment the total written, if this matches tcount
4070 we can discard the auxiliary struct (hurrah !) and return a writeC */
4071 wbms->wr_total_written += nwritten;
4072 if(wbms->wr_total_written >= tcount)
4076 outsize = set_message(outbuf,1,0,True);
4077 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4078 send_response = True;
4082 fsp->wbmpx_ptr = NULL;
4092 /****************************************************************************
4093 reply to a SMBsetattrE
4094 ****************************************************************************/
4095 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4097 struct utimbuf unix_times;
4099 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4101 outsize = set_message(outbuf,0,0,True);
4103 CHECK_FSP(fsp,conn);
4106 /* Convert the DOS times into unix times. Ignore create
4107 time as UNIX can't set this.
4109 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4110 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4113 * Patch from Ray Frush <frush@engr.colostate.edu>
4114 * Sometimes times are sent as zero - ignore them.
4117 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4119 /* Ignore request */
4122 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4123 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4127 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4129 /* set modify time = to access time if modify time was 0 */
4130 unix_times.modtime = unix_times.actime;
4133 /* Set the date on this file */
4134 if(file_utime(conn, fsp->fsp_name, &unix_times))
4135 return(ERROR(ERRDOS,ERRnoaccess));
4137 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4138 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4144 /****************************************************************************
4145 reply to a SMBgetattrE
4146 ****************************************************************************/
4147 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4149 SMB_STRUCT_STAT sbuf;
4152 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4154 outsize = set_message(outbuf,11,0,True);
4156 CHECK_FSP(fsp,conn);
4159 /* Do an fstat on this file */
4160 if(fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf))
4161 return(UNIXERROR(ERRDOS,ERRnoaccess));
4163 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4165 /* Convert the times into dos times. Set create
4166 date to be last modify date as UNIX doesn't save
4168 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4169 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4170 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4173 SIVAL(outbuf,smb_vwv6,0);
4174 SIVAL(outbuf,smb_vwv8,0);
4178 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4179 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4181 SSVAL(outbuf,smb_vwv10, mode);
4183 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));