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 pstring global_myname;
42 extern fstring global_myworkgroup;
43 extern int global_oplock_break;
44 uint32 global_client_caps = 0;
45 unsigned int smb_echo_count = 0;
47 /****************************************************************************
48 report a possible attack via the password buffer overflow bug
49 ****************************************************************************/
51 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() );
59 exit_server("possible attack");
63 /****************************************************************************
64 reply to an special message
65 ****************************************************************************/
67 int reply_special(char *inbuf,char *outbuf)
70 int msg_type = CVAL(inbuf,0);
71 int msg_flags = CVAL(inbuf,1);
73 extern fstring remote_machine;
74 extern fstring local_machine;
80 memset(outbuf,'\0',smb_size);
85 case 0x81: /* session request */
86 CVAL(outbuf,0) = 0x82;
88 if (name_len(inbuf+4) > 50 ||
89 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
90 DEBUG(0,("Invalid name length in session request\n"));
93 name_extract(inbuf,4,name1);
94 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
95 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
98 fstrcpy(remote_machine,name2);
99 remote_machine[15] = 0;
100 trim_string(remote_machine," "," ");
101 strlower(remote_machine);
103 fstrcpy(local_machine,name1);
104 len = strlen(local_machine);
106 name_type = local_machine[15];
107 local_machine[15] = 0;
109 trim_string(local_machine," "," ");
110 strlower(local_machine);
112 if (name_type == 'R') {
113 /* We are being asked for a pathworks session ---
115 CVAL(outbuf, 0) = 0x83;
119 add_session_user(remote_machine);
121 reload_services(True);
125 claim_connection(NULL,"",MAXSTATUS,True);
130 case 0x89: /* session keepalive request
131 (some old clients produce this?) */
132 CVAL(outbuf,0) = 0x85;
136 case 0x82: /* positive session response */
137 case 0x83: /* negative session response */
138 case 0x84: /* retarget session response */
139 DEBUG(0,("Unexpected session response\n"));
142 case 0x85: /* session keepalive */
147 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
148 msg_type, msg_flags));
154 /*******************************************************************
155 work out what error to give to a failed connection
156 ********************************************************************/
158 static int connection_error(char *inbuf,char *outbuf,int ecode)
160 if (ecode == ERRnoipc)
161 return(ERROR(ERRDOS,ERRnoipc));
163 return(ERROR(ERRSRV,ecode));
168 /****************************************************************************
169 parse a share descriptor string
170 ****************************************************************************/
171 static void parse_connect(char *p,char *service,char *user,
172 char *password,int *pwlen,char *dev)
176 DEBUG(4,("parsing connect string %s\n",p));
178 p2 = strrchr(p,'\\');
182 fstrcpy(service,p2+1);
187 *pwlen = strlen(password);
194 p = strchr(service,'%');
202 /****************************************************************************
204 ****************************************************************************/
206 int reply_tcon(connection_struct *conn,
207 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
209 BOOL doencrypt = SMBENCRYPT();
215 uint16 vuid = SVAL(inbuf,smb_uid);
219 *service = *user = *password = *dev = 0;
221 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
224 * Ensure the user and password names are in UNIX codepage format.
227 dos_to_unix(user,True);
229 dos_to_unix(password,True);
232 * Pass the user through the NT -> unix user mapping
236 (void)map_username(user);
239 * Do any UNIX username case mangling.
241 (void)Get_Pwnam( user, True);
243 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
246 return(connection_error(inbuf,outbuf,ecode));
249 outsize = set_message(outbuf,2,0,True);
250 SSVAL(outbuf,smb_vwv0,max_recv);
251 SSVAL(outbuf,smb_vwv1,conn->cnum);
252 SSVAL(outbuf,smb_tid,conn->cnum);
254 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
255 service, user, conn->cnum));
260 /****************************************************************************
261 Reply to a tcon and X.
262 ****************************************************************************/
263 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
269 BOOL doencrypt = SMBENCRYPT();
271 uint16 vuid = SVAL(inbuf,smb_uid);
272 int passlen = SVAL(inbuf,smb_vwv3);
276 *service = *user = *password = *devicename = 0;
278 /* we might have to close an old one */
279 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
280 close_cnum(conn,vuid);
283 if (passlen > MAX_PASS_LEN) {
284 overflow_attack(passlen);
287 memcpy(password,smb_buf(inbuf),passlen);
289 path = smb_buf(inbuf) + passlen;
292 if (strequal(password," "))
294 passlen = strlen(password);
297 p = strchr(path+2,'\\');
299 return(ERROR(ERRSRV,ERRinvnetname));
300 fstrcpy(service,p+1);
301 p = strchr(service,'%');
306 StrnCpy(devicename,path + strlen(path) + 1,6);
307 DEBUG(4,("Got device type %s\n",devicename));
310 * Ensure the user and password names are in UNIX codepage format.
313 dos_to_unix(user,True);
315 dos_to_unix(password,True);
318 * Pass the user through the NT -> unix user mapping
322 (void)map_username(user);
325 * Do any UNIX username case mangling.
327 (void)Get_Pwnam(user, True);
329 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
332 return(connection_error(inbuf,outbuf,ecode));
334 if (Protocol < PROTOCOL_NT1) {
335 set_message(outbuf,2,strlen(devicename)+1,True);
336 pstrcpy(smb_buf(outbuf),devicename);
338 char *fsname = lp_fstype(SNUM(conn));
340 set_message(outbuf,3,3,True);
343 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
344 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
346 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
348 /* what does setting this bit do? It is set by NT4 and
349 may affect the ability to autorun mounted cdroms */
350 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
352 init_dfsroot(conn, inbuf, outbuf);
356 DEBUG(3,("tconX service=%s user=%s\n",
359 /* set the incoming and outgoing tid to the just created one */
360 SSVAL(inbuf,smb_tid,conn->cnum);
361 SSVAL(outbuf,smb_tid,conn->cnum);
363 return chain_reply(inbuf,outbuf,length,bufsize);
367 /****************************************************************************
368 reply to an unknown type
369 ****************************************************************************/
370 int reply_unknown(char *inbuf,char *outbuf)
373 type = CVAL(inbuf,smb_com);
375 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
376 smb_fn_name(type), type, type));
378 return(ERROR(ERRSRV,ERRunknownsmb));
382 /****************************************************************************
384 ****************************************************************************/
385 int reply_ioctl(connection_struct *conn,
386 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
388 uint16 device = SVAL(inbuf,smb_vwv1);
389 uint16 function = SVAL(inbuf,smb_vwv2);
390 uint32 ioctl_code = (device << 16) + function;
391 int replysize, outsize;
393 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
395 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
399 case IOCTL_QUERY_JOB_INFO:
403 return(ERROR(ERRSRV,ERRnosupport));
406 outsize = set_message(outbuf,8,replysize+1,True);
407 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
408 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
409 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
410 p = smb_buf(outbuf) + 1; /* Allow for alignment */
414 case IOCTL_QUERY_JOB_INFO:
415 SSVAL(p,0,fsp->print_jobid); /* Job number */
416 StrnCpy(p+2, global_myname, 15); /* Our NetBIOS name */
417 StrnCpy(p+18, lp_servicename(SNUM(conn)), 13); /* Service name */
424 /****************************************************************************
425 always return an error: it's just a matter of which one...
426 ****************************************************************************/
427 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
428 char *smb_passwd, int smb_passlen,
429 char *smb_nt_passwd, int smb_nt_passlen)
431 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
432 if (lp_security() == SEC_USER)
434 smb_trust_acct = getsmbpwnam(user);
438 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
439 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
440 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
443 if (smb_trust_acct == NULL)
445 /* lkclXXXX: workstation entry doesn't exist */
446 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
447 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
448 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
452 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
454 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
455 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
456 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
459 if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
461 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
462 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
463 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
466 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
468 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
469 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
470 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
473 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
475 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
476 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
477 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
480 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
482 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
483 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
484 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
488 /* don't know what to do: indicate logon failure */
489 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
490 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
493 /****************************************************************************
494 Create a UNIX user on demand.
495 ****************************************************************************/
497 static int smb_create_user(char *unix_user)
502 pstrcpy(add_script, lp_adduser_script());
503 pstring_sub(add_script, "%u", unix_user);
504 ret = smbrun(add_script,NULL,False);
505 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
509 /****************************************************************************
510 Delete a UNIX user on demand.
511 ****************************************************************************/
513 static int smb_delete_user(char *unix_user)
518 pstrcpy(del_script, lp_deluser_script());
519 pstring_sub(del_script, "%u", unix_user);
520 ret = smbrun(del_script,NULL,False);
521 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
525 /****************************************************************************
526 Check user is in correct domain if required
527 ****************************************************************************/
529 static BOOL check_domain_match(char *user, char *domain)
532 * If we aren't serving to trusted domains, we must make sure that
533 * the validation request comes from an account in the same domain
534 * as the Samba server
537 if (!lp_allow_trusted_domains() &&
538 !strequal(lp_workgroup(), domain) ) {
539 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
546 /****************************************************************************
547 Check for a valid username and password in security=server mode.
548 ****************************************************************************/
550 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
551 char *smb_apasswd, int smb_apasslen,
552 char *smb_ntpasswd, int smb_ntpasslen)
556 if(lp_security() != SEC_SERVER)
559 if (!check_domain_match(orig_user, domain))
562 ret = server_validate(orig_user, domain,
563 smb_apasswd, smb_apasslen,
564 smb_ntpasswd, smb_ntpasslen);
567 * User validated ok against Domain controller.
568 * If the admin wants us to try and create a UNIX
569 * user on the fly, do so.
570 * Note that we can never delete users when in server
571 * level security as we never know if it was a failure
572 * due to a bad password, or the user really doesn't exist.
574 if(lp_adduser_script() && !Get_Pwnam(unix_user,True)) {
575 smb_create_user(unix_user);
582 /****************************************************************************
583 Check for a valid username and password in security=domain mode.
584 ****************************************************************************/
586 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
587 char *smb_apasswd, int smb_apasslen,
588 char *smb_ntpasswd, int smb_ntpasslen)
591 BOOL user_exists = True;
593 if(lp_security() != SEC_DOMAIN)
596 if (!check_domain_match(orig_user, domain))
599 ret = domain_client_validate(orig_user, domain,
600 smb_apasswd, smb_apasslen,
601 smb_ntpasswd, smb_ntpasslen,
606 * User validated ok against Domain controller.
607 * If the admin wants us to try and create a UNIX
608 * user on the fly, do so.
610 if(user_exists && lp_adduser_script() && !Get_Pwnam(unix_user,True)) {
611 smb_create_user(unix_user);
615 * User failed to validate ok against Domain controller.
616 * If the failure was "user doesn't exist" and admin
617 * wants us to try and delete that UNIX user on the fly,
620 if(!user_exists && lp_deluser_script() && Get_Pwnam(unix_user,True)) {
621 smb_delete_user(unix_user);
628 /****************************************************************************
629 Return a bad password error configured for the correct client type.
630 ****************************************************************************/
632 static int bad_password_error(char *inbuf,char *outbuf)
634 enum remote_arch_types ra_type = get_remote_arch();
636 if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
637 (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
638 SSVAL(outbuf,smb_flg2,FLAGS2_32_BIT_ERROR_CODES);
639 return(ERROR(0,0xc0000000|NT_STATUS_LOGON_FAILURE));
642 return(ERROR(ERRSRV,ERRbadpw));
645 /****************************************************************************
646 reply to a session setup command
647 ****************************************************************************/
649 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
655 int smb_apasslen = 0;
657 int smb_ntpasslen = 0;
658 pstring smb_ntpasswd;
659 BOOL valid_nt_password = False;
663 static BOOL done_sesssetup = False;
664 BOOL doencrypt = SMBENCRYPT();
670 smb_bufsize = SVAL(inbuf,smb_vwv2);
672 if (Protocol < PROTOCOL_NT1) {
673 smb_apasslen = SVAL(inbuf,smb_vwv7);
674 if (smb_apasslen > MAX_PASS_LEN)
675 overflow_attack(smb_apasslen);
677 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
678 smb_apasswd[smb_apasslen] = 0;
679 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
681 * Incoming user is in DOS codepage format. Convert
684 dos_to_unix(user,True);
686 if (!doencrypt && (lp_security() != SEC_SERVER)) {
687 smb_apasslen = strlen(smb_apasswd);
690 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
691 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
692 enum remote_arch_types ra_type = get_remote_arch();
693 char *p = smb_buf(inbuf);
695 if(global_client_caps == 0)
696 global_client_caps = IVAL(inbuf,smb_vwv11);
698 /* client_caps is used as final determination if client is NT or Win95.
699 This is needed to return the correct error codes in some
703 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
704 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
705 set_remote_arch( RA_WIN95);
709 if (passlen1 != 24 && passlen2 != 24)
712 if (passlen1 > MAX_PASS_LEN) {
713 overflow_attack(passlen1);
716 passlen1 = MIN(passlen1, MAX_PASS_LEN);
717 passlen2 = MIN(passlen2, MAX_PASS_LEN);
720 /* both Win95 and WinNT stuff up the password lengths for
721 non-encrypting systems. Uggh.
723 if passlen1==24 its a win95 system, and its setting the
724 password length incorrectly. Luckily it still works with the
725 default code because Win95 will null terminate the password
728 if passlen1>0 and passlen2>0 then maybe its a NT box and its
729 setting passlen2 to some random value which really stuffs
730 things up. we need to fix that one. */
732 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
736 if (lp_restrict_anonymous()) {
737 /* there seems to be no reason behind the differences in MS clients formatting
738 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
739 * in particular seems to have an extra null byte between the username and the
740 * domain, or the password length calculation is wrong, which throws off the
741 * string extraction routines below. This makes the value of domain be the
742 * empty string, which fails the restrict anonymous check further down.
743 * This compensates for that, and allows browsing to work in mixed NT and
744 * win95 environments even when restrict anonymous is true. AAB
746 dump_data(100, p, 0x70);
747 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
748 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
749 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
750 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
751 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
756 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
757 /* Save the lanman2 password and the NT md4 password. */
758 smb_apasslen = passlen1;
759 memcpy(smb_apasswd,p,smb_apasslen);
760 smb_apasswd[smb_apasslen] = 0;
761 smb_ntpasslen = passlen2;
762 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
763 smb_ntpasswd[smb_ntpasslen] = 0;
766 * Ensure the plaintext passwords are in UNIX format.
769 dos_to_unix(smb_apasswd,True);
770 dos_to_unix(smb_ntpasswd,True);
774 /* we use the first password that they gave */
775 smb_apasslen = passlen1;
776 StrnCpy(smb_apasswd,p,smb_apasslen);
778 * Ensure the plaintext password is in UNIX format.
780 dos_to_unix(smb_apasswd,True);
782 /* trim the password */
783 smb_apasslen = strlen(smb_apasswd);
785 /* wfwg sometimes uses a space instead of a null */
786 if (strequal(smb_apasswd," ")) {
792 p += passlen1 + passlen2;
794 p = skip_string(p,1);
796 * Incoming user is in DOS codepage format. Convert
799 dos_to_unix(user,True);
802 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
803 domain,skip_string(p,1),skip_string(p,2)));
807 DEBUG(3,("sesssetupX:name=[%s]\n",user));
809 /* If name ends in $ then I think it's asking about whether a */
810 /* computer with that name (minus the $) has access. For now */
811 /* say yes to everything ending in $. */
813 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
814 return session_trust_account(conn, inbuf, outbuf, user,
815 smb_apasswd, smb_apasslen,
816 smb_ntpasswd, smb_ntpasslen);
819 if (done_sesssetup && lp_restrict_anonymous()) {
820 /* tests show that even if browsing is done over already validated connections
821 * without a username and password the domain is still provided, which it
822 * wouldn't be if it was a purely anonymous connection. So, in order to
823 * restrict anonymous, we only deny connections that have no session
824 * information. If a domain has been provided, then it's not a purely
825 * anonymous connection. AAB
827 if (!*user && !*smb_apasswd && !*domain) {
828 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
829 return(ERROR(ERRDOS,ERRnoaccess));
833 /* If no username is sent use the guest account */
835 pstrcpy(user,lp_guestaccount(-1));
836 /* If no user and no password then set guest flag. */
837 if( *smb_apasswd == 0)
844 * In share level security, only overwrite sesssetup_use if
845 * it's a non null-session share. Helps keep %U and %G
849 if((lp_security() != SEC_SHARE) || (*user && !guest))
850 pstrcpy(sesssetup_user,user);
852 reload_services(True);
855 * Save the username before mapping. We will use
856 * the original username sent to us for security=server
857 * and security=domain checking.
860 pstrcpy( orig_user, user);
863 * Pass the user through the NT -> unix user mapping
867 (void)map_username(user);
870 * Do any UNIX username case mangling.
872 (void)Get_Pwnam( user, True);
874 add_session_user(user);
877 * Check if the given username was the guest user with no password.
880 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
884 * Check with orig_user for security=server and
889 !check_server_security(orig_user, domain, user,
890 smb_apasswd, smb_apasslen,
891 smb_ntpasswd, smb_ntpasslen) &&
892 !check_domain_security(orig_user, domain, user,
893 smb_apasswd, smb_apasslen,
894 smb_ntpasswd, smb_ntpasslen) &&
895 !check_hosts_equiv(user)
900 * If we get here then the user wasn't guest and the remote
901 * authentication methods failed. Check the authentication
902 * methods on this local server.
904 * If an NT password was supplied try and validate with that
905 * first. This is superior as the passwords are mixed case
906 * 128 length unicode.
911 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
912 DEBUG(2,("NT Password did not match for user '%s' ! Defaulting to Lanman\n", user));
914 valid_nt_password = True;
917 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL))
919 if (lp_security() >= SEC_USER)
921 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
923 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
924 return bad_password_error(inbuf,outbuf);
927 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
929 if (Get_Pwnam(user,True))
931 DEBUG(1,("Rejecting user '%s': bad password\n", user));
932 return bad_password_error(inbuf,outbuf);
937 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
938 * Then always map to guest account - as done below.
942 if (*smb_apasswd || !Get_Pwnam(user,True))
943 pstrcpy(user,lp_guestaccount(-1));
944 DEBUG(3,("Registered username %s for guest access\n",user));
949 if (!Get_Pwnam(user,True)) {
950 DEBUG(3,("No such user %s - using guest account\n",user));
951 pstrcpy(user,lp_guestaccount(-1));
955 if (!strequal(user,lp_guestaccount(-1)) &&
956 lp_servicenumber(user) < 0)
958 int homes = lp_servicenumber(HOMES_NAME);
959 char *home = get_user_home_dir(user);
960 if (homes >= 0 && home)
961 lp_add_home(user,homes,home);
965 /* it's ok - setup a reply */
966 if (Protocol < PROTOCOL_NT1) {
967 set_message(outbuf,3,0,True);
970 set_message(outbuf,3,3,True);
972 pstrcpy(p,"Unix"); p = skip_string(p,1);
973 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
974 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
975 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
976 /* perhaps grab OS version here?? */
979 /* Set the correct uid in the outgoing and incoming packets
980 We will use this on future requests to determine which
981 user we should become.
984 const struct passwd *pw = Get_Pwnam(user,False);
986 DEBUG(1,("Username %s is invalid on this system\n",user));
987 return bad_password_error(inbuf,outbuf);
994 SSVAL(outbuf,smb_vwv2,1);
996 /* register the name and uid as being validated, so further connections
997 to a uid can get through without a password, on the same VC */
998 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
1000 SSVAL(outbuf,smb_uid,sess_vuid);
1001 SSVAL(inbuf,smb_uid,sess_vuid);
1003 if (!done_sesssetup)
1004 max_send = MIN(max_send,smb_bufsize);
1006 DEBUG(6,("Client requested max send size of %d\n", max_send));
1008 done_sesssetup = True;
1010 return chain_reply(inbuf,outbuf,length,bufsize);
1014 /****************************************************************************
1016 ****************************************************************************/
1017 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1023 BOOL bad_path = False;
1026 pstrcpy(name,smb_buf(inbuf) + 1);
1028 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1030 unix_convert(name,conn,0,&bad_path,&st);
1032 mode = SVAL(inbuf,smb_vwv0);
1034 if (check_name(name,conn)) {
1036 ok = S_ISDIR(st.st_mode);
1038 ok = vfs_directory_exist(conn,name,NULL);
1043 /* We special case this - as when a Windows machine
1044 is parsing a path is steps through the components
1045 one at a time - if a component fails it expects
1046 ERRbadpath, not ERRbadfile.
1050 unix_ERR_class = ERRDOS;
1051 unix_ERR_code = ERRbadpath;
1055 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1056 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1057 (get_remote_arch() == RA_WINNT))
1059 unix_ERR_class = ERRDOS;
1060 unix_ERR_code = ERRbaddirectory;
1064 return(UNIXERROR(ERRDOS,ERRbadpath));
1067 outsize = set_message(outbuf,0,0,True);
1069 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1075 /****************************************************************************
1077 ****************************************************************************/
1078 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1082 SMB_STRUCT_STAT sbuf;
1087 BOOL bad_path = False;
1089 pstrcpy(fname,smb_buf(inbuf) + 1);
1091 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1093 /* if((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && dfs_redirect(fname,conn)) return(dfs_path_error(inbuf,outbuf));
1095 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1096 under WfWg - weird! */
1099 mode = aHIDDEN | aDIR;
1100 if (!CAN_WRITE(conn)) mode |= aRONLY;
1107 unix_convert(fname,conn,0,&bad_path,&sbuf);
1108 if (check_name(fname,conn))
1110 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
1112 mode = dos_mode(conn,fname,&sbuf);
1113 size = sbuf.st_size;
1114 mtime = sbuf.st_mtime;
1120 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1126 if((errno == ENOENT) && bad_path)
1128 unix_ERR_class = ERRDOS;
1129 unix_ERR_code = ERRbadpath;
1132 return(UNIXERROR(ERRDOS,ERRbadfile));
1135 outsize = set_message(outbuf,10,0,True);
1137 SSVAL(outbuf,smb_vwv0,mode);
1138 if(lp_dos_filetime_resolution(SNUM(conn)) )
1139 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1141 put_dos_date3(outbuf,smb_vwv1,mtime);
1142 SIVAL(outbuf,smb_vwv3,(uint32)size);
1144 if (Protocol >= PROTOCOL_NT1) {
1145 char *p = strrchr(fname,'/');
1146 uint16 flg2 = SVAL(outbuf,smb_flg2);
1148 if (!is_8_3(fname, True))
1149 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1152 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1158 /****************************************************************************
1160 ****************************************************************************/
1161 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1169 BOOL bad_path = False;
1171 pstrcpy(fname,smb_buf(inbuf) + 1);
1172 unix_convert(fname,conn,0,&bad_path,&st);
1174 mode = SVAL(inbuf,smb_vwv0);
1175 mtime = make_unix_date3(inbuf+smb_vwv1);
1177 if (VALID_STAT_OF_DIR(st) || vfs_directory_exist(conn, fname, NULL))
1179 if (check_name(fname,conn))
1180 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1182 ok = set_filetime(conn,fname,mtime);
1186 if((errno == ENOENT) && bad_path)
1188 unix_ERR_class = ERRDOS;
1189 unix_ERR_code = ERRbadpath;
1192 return(UNIXERROR(ERRDOS,ERRnoaccess));
1195 outsize = set_message(outbuf,0,0,True);
1197 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1203 /****************************************************************************
1205 ****************************************************************************/
1206 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1209 SMB_BIG_UINT dfree,dsize,bsize;
1211 conn->vfs_ops.disk_free(".",True,&bsize,&dfree,&dsize);
1213 outsize = set_message(outbuf,5,0,True);
1215 SSVAL(outbuf,smb_vwv0,dsize);
1216 SSVAL(outbuf,smb_vwv1,bsize/512);
1217 SSVAL(outbuf,smb_vwv2,512);
1218 SSVAL(outbuf,smb_vwv3,dfree);
1220 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1226 /****************************************************************************
1228 Can be called from SMBsearch, SMBffirst or SMBfunique.
1229 ****************************************************************************/
1230 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1241 BOOL finished = False;
1250 BOOL check_descend = False;
1251 BOOL expect_close = False;
1252 BOOL can_open = True;
1253 BOOL bad_path = False;
1255 *mask = *directory = *fname = 0;
1257 /* If we were called as SMBffirst then we must expect close. */
1258 if(CVAL(inbuf,smb_com) == SMBffirst)
1259 expect_close = True;
1261 outsize = set_message(outbuf,1,3,True);
1262 maxentries = SVAL(inbuf,smb_vwv0);
1263 dirtype = SVAL(inbuf,smb_vwv1);
1264 path = smb_buf(inbuf) + 1;
1265 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1268 /* dirtype &= ~aDIR; */
1270 DEBUG(5,("reply_search: path=%s status_len=%d\n",path,status_len));
1273 if (status_len == 0)
1277 pstrcpy(directory,smb_buf(inbuf)+1);
1278 pstrcpy(dir2,smb_buf(inbuf)+1);
1279 unix_convert(directory,conn,0,&bad_path,NULL);
1282 if (!check_name(directory,conn))
1285 p = strrchr(dir2,'/');
1297 p = strrchr(directory,'/');
1303 if (strlen(directory) == 0)
1304 pstrcpy(directory,"./");
1305 memset((char *)status,'\0',21);
1306 CVAL(status,0) = dirtype;
1310 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1311 memcpy(mask,status+1,11);
1313 dirtype = CVAL(status,0) & 0x1F;
1314 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1317 string_set(&conn->dirpath,dptr_path(dptr_num));
1318 if (!case_sensitive)
1322 /* turn strings of spaces into a . */
1324 trim_string(mask,NULL," ");
1325 if ((p = strrchr(mask,' ')))
1330 trim_string(mask,NULL," ");
1336 /* Convert the formatted mask. (This code lives in trans2.c) */
1344 if((skip = get_character_len( *p )) != 0 )
1350 if (*p != '?' && *p != '*' && !isdoschar(*p))
1352 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1360 if (!strchr(mask,'.') && strlen(mask)>8)
1363 fstrcpy(tmp,&mask[8]);
1369 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1373 p = smb_buf(outbuf) + 3;
1377 if (status_len == 0)
1379 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1384 if((errno == ENOENT) && bad_path)
1386 unix_ERR_class = ERRDOS;
1387 unix_ERR_code = ERRbadpath;
1389 return (UNIXERROR(ERRDOS,ERRnofids));
1391 return(ERROR(ERRDOS,ERRnofids));
1395 DEBUG(4,("dptr_num is %d\n",dptr_num));
1399 if ((dirtype&0x1F) == aVOLID)
1401 memcpy(p,status,21);
1402 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1403 dptr_fill(p+12,dptr_num);
1404 if (dptr_zero(p+12) && (status_len==0))
1408 p += DIR_STRUCT_SIZE;
1412 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1413 conn->dirpath,lp_dontdescend(SNUM(conn))));
1414 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1415 check_descend = True;
1417 for (i=numentries;(i<maxentries) && !finished;i++)
1420 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1423 memcpy(p,status,21);
1424 make_dir_struct(p,mask,fname,size,mode,date);
1425 dptr_fill(p+12,dptr_num);
1428 p += DIR_STRUCT_SIZE;
1437 if (numentries == 0 || !ok)
1439 CVAL(outbuf,smb_rcls) = ERRDOS;
1440 SSVAL(outbuf,smb_err,ERRnofiles);
1441 dptr_close(&dptr_num);
1444 /* If we were called as SMBffirst with smb_search_id == NULL
1445 and no entries were found then return error and close dirptr
1448 if(ok && expect_close && numentries == 0 && status_len == 0)
1450 CVAL(outbuf,smb_rcls) = ERRDOS;
1451 SSVAL(outbuf,smb_err,ERRnofiles);
1452 /* Also close the dptr - we know it's gone */
1453 dptr_close(&dptr_num);
1456 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1457 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1458 dptr_close(&dptr_num);
1460 SSVAL(outbuf,smb_vwv0,numentries);
1461 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1462 CVAL(smb_buf(outbuf),0) = 5;
1463 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1465 if (Protocol >= PROTOCOL_NT1) {
1466 uint16 flg2 = SVAL(outbuf,smb_flg2);
1467 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1470 outsize += DIR_STRUCT_SIZE*numentries;
1471 smb_setlen(outbuf,outsize - 4);
1473 if ((! *directory) && dptr_path(dptr_num))
1474 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1476 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1477 smb_fn_name(CVAL(inbuf,smb_com)),
1478 mask, directory, dirtype, numentries, maxentries ) );
1484 /****************************************************************************
1485 reply to a fclose (stop directory search)
1486 ****************************************************************************/
1487 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1495 outsize = set_message(outbuf,1,0,True);
1496 path = smb_buf(inbuf) + 1;
1497 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1500 if (status_len == 0)
1501 return(ERROR(ERRSRV,ERRsrverror));
1503 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1505 if(dptr_fetch(status+12,&dptr_num)) {
1506 /* Close the dptr - we know it's gone */
1507 dptr_close(&dptr_num);
1510 SSVAL(outbuf,smb_vwv0,0);
1512 DEBUG(3,("search close\n"));
1518 /****************************************************************************
1520 ****************************************************************************/
1522 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1532 SMB_STRUCT_STAT sbuf;
1533 BOOL bad_path = False;
1535 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1537 share_mode = SVAL(inbuf,smb_vwv0);
1539 pstrcpy(fname,smb_buf(inbuf)+1);
1541 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1543 unix_convert(fname,conn,0,&bad_path,NULL);
1545 unixmode = unix_mode(conn,aARCH,fname);
1547 fsp = open_file_shared(conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1548 unixmode, oplock_request,&rmode,NULL);
1552 if((errno == ENOENT) && bad_path)
1554 unix_ERR_class = ERRDOS;
1555 unix_ERR_code = ERRbadpath;
1557 return(UNIXERROR(ERRDOS,ERRnoaccess));
1560 if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) {
1561 close_file(fsp,False);
1562 return(ERROR(ERRDOS,ERRnoaccess));
1565 size = sbuf.st_size;
1566 fmode = dos_mode(conn,fname,&sbuf);
1567 mtime = sbuf.st_mtime;
1570 DEBUG(3,("attempt to open a directory %s\n",fname));
1571 close_file(fsp,False);
1572 return(ERROR(ERRDOS,ERRnoaccess));
1575 outsize = set_message(outbuf,7,0,True);
1576 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1577 SSVAL(outbuf,smb_vwv1,fmode);
1578 if(lp_dos_filetime_resolution(SNUM(conn)) )
1579 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1581 put_dos_date3(outbuf,smb_vwv2,mtime);
1582 SIVAL(outbuf,smb_vwv4,(uint32)size);
1583 SSVAL(outbuf,smb_vwv6,rmode);
1585 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1586 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1589 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1590 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1595 /****************************************************************************
1596 reply to an open and X
1597 ****************************************************************************/
1598 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1601 int smb_mode = SVAL(inbuf,smb_vwv3);
1602 int smb_attr = SVAL(inbuf,smb_vwv5);
1603 /* Breakout the oplock request bits so we can set the
1604 reply bits separately. */
1605 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1606 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1607 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1609 int open_flags = SVAL(inbuf,smb_vwv2);
1610 int smb_sattr = SVAL(inbuf,smb_vwv4);
1611 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1613 int smb_ofun = SVAL(inbuf,smb_vwv8);
1616 int fmode=0,mtime=0,rmode=0;
1617 SMB_STRUCT_STAT sbuf;
1619 BOOL bad_path = False;
1622 /* If it's an IPC, pass off the pipe handler. */
1623 if (IS_IPC(conn) && lp_nt_pipe_support())
1624 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1626 /* XXXX we need to handle passed times, sattr and flags */
1628 pstrcpy(fname,smb_buf(inbuf));
1630 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1632 unix_convert(fname,conn,0,&bad_path,NULL);
1634 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1636 fsp = open_file_shared(conn,fname,smb_mode,smb_ofun,unixmode,
1637 oplock_request, &rmode,&smb_action);
1641 if((errno == ENOENT) && bad_path)
1643 unix_ERR_class = ERRDOS;
1644 unix_ERR_code = ERRbadpath;
1646 return(UNIXERROR(ERRDOS,ERRnoaccess));
1649 if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) {
1650 close_file(fsp,False);
1651 return(ERROR(ERRDOS,ERRnoaccess));
1654 size = sbuf.st_size;
1655 fmode = dos_mode(conn,fname,&sbuf);
1656 mtime = sbuf.st_mtime;
1658 close_file(fsp,False);
1659 return(ERROR(ERRDOS,ERRnoaccess));
1662 /* If the caller set the extended oplock request bit
1663 and we granted one (by whatever means) - set the
1664 correct bit for extended oplock reply.
1667 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1668 smb_action |= EXTENDED_OPLOCK_GRANTED;
1671 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1672 smb_action |= EXTENDED_OPLOCK_GRANTED;
1675 /* If the caller set the core oplock request bit
1676 and we granted one (by whatever means) - set the
1677 correct bit for core oplock reply.
1680 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1681 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1684 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1685 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1688 set_message(outbuf,15,0,True);
1689 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1690 SSVAL(outbuf,smb_vwv3,fmode);
1691 if(lp_dos_filetime_resolution(SNUM(conn)) )
1692 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1694 put_dos_date3(outbuf,smb_vwv4,mtime);
1695 SIVAL(outbuf,smb_vwv6,(uint32)size);
1696 SSVAL(outbuf,smb_vwv8,rmode);
1697 SSVAL(outbuf,smb_vwv11,smb_action);
1699 return chain_reply(inbuf,outbuf,length,bufsize);
1703 /****************************************************************************
1704 reply to a SMBulogoffX
1705 ****************************************************************************/
1706 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1708 uint16 vuid = SVAL(inbuf,smb_uid);
1709 user_struct *vuser = get_valid_user_struct(vuid);
1712 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1715 /* in user level security we are supposed to close any files
1716 open by this user */
1717 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1718 file_close_user(vuid);
1721 invalidate_vuid(vuid);
1723 set_message(outbuf,2,0,True);
1725 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1727 return chain_reply(inbuf,outbuf,length,bufsize);
1731 /****************************************************************************
1732 reply to a mknew or a create
1733 ****************************************************************************/
1734 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1742 BOOL bad_path = False;
1744 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1746 com = SVAL(inbuf,smb_com);
1748 createmode = SVAL(inbuf,smb_vwv0);
1749 pstrcpy(fname,smb_buf(inbuf)+1);
1751 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1753 unix_convert(fname,conn,0,&bad_path,NULL);
1755 if (createmode & aVOLID)
1757 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1760 unixmode = unix_mode(conn,createmode,fname);
1764 /* We should fail if file exists. */
1765 ofun = FILE_CREATE_IF_NOT_EXIST;
1769 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1770 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1773 /* Open file in dos compatibility share mode. */
1774 fsp = open_file_shared(conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1775 ofun, unixmode, oplock_request, NULL, NULL);
1779 if((errno == ENOENT) && bad_path)
1781 unix_ERR_class = ERRDOS;
1782 unix_ERR_code = ERRbadpath;
1784 return(UNIXERROR(ERRDOS,ERRnoaccess));
1787 outsize = set_message(outbuf,1,0,True);
1788 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1790 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1791 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1794 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1795 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1797 DEBUG( 2, ( "new file %s\n", fname ) );
1798 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1799 fname, fsp->fd, createmode, (int)unixmode ) );
1805 /****************************************************************************
1806 reply to a create temporary file
1807 ****************************************************************************/
1808 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1815 BOOL bad_path = False;
1817 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1819 createmode = SVAL(inbuf,smb_vwv0);
1820 pstrcpy(fname,smb_buf(inbuf)+1);
1821 pstrcat(fname,"/TMXXXXXX");
1823 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1825 unix_convert(fname,conn,0,&bad_path,NULL);
1827 unixmode = unix_mode(conn,createmode,fname);
1829 pstrcpy(fname2,(char *)smbd_mktemp(fname));
1831 /* Open file in dos compatibility share mode. */
1832 /* We should fail if file exists. */
1833 fsp = open_file_shared(conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1834 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1838 if((errno == ENOENT) && bad_path)
1840 unix_ERR_class = ERRDOS;
1841 unix_ERR_code = ERRbadpath;
1843 return(UNIXERROR(ERRDOS,ERRnoaccess));
1846 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1847 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1848 CVAL(smb_buf(outbuf),0) = 4;
1849 pstrcpy(smb_buf(outbuf) + 1,fname2);
1851 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1852 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1855 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1856 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1858 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1859 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1860 fname2, fsp->fd, createmode, (int)unixmode ) );
1866 /*******************************************************************
1867 check if a user is allowed to delete a file
1868 ********************************************************************/
1869 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1871 SMB_STRUCT_STAT sbuf;
1874 if (!CAN_WRITE(conn)) return(False);
1876 if (conn->vfs_ops.lstat(dos_to_unix(fname,False),&sbuf) != 0) return(False);
1877 fmode = dos_mode(conn,fname,&sbuf);
1878 if (fmode & aDIR) return(False);
1879 if (!lp_delete_readonly(SNUM(conn))) {
1880 if (fmode & aRONLY) return(False);
1882 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1884 if (!check_file_sharing(conn,fname,False)) return(False);
1888 /****************************************************************************
1890 ****************************************************************************/
1892 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1901 int error = ERRnoaccess;
1904 BOOL bad_path = False;
1907 *directory = *mask = 0;
1909 dirtype = SVAL(inbuf,smb_vwv0);
1911 pstrcpy(name,smb_buf(inbuf) + 1);
1913 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1915 DEBUG(3,("reply_unlink : %s\n",name));
1917 rc = unix_convert(name,conn,0,&bad_path,NULL);
1919 p = strrchr(name,'/');
1921 pstrcpy(directory,"./");
1925 pstrcpy(directory,name);
1930 * We should only check the mangled cache
1931 * here if unix_convert failed. This means
1932 * that the path in 'mask' doesn't exist
1933 * on the file system and so we need to look
1934 * for a possible mangle. This patch from
1935 * Tine Smukavec <valentin.smukavec@hermes.si>.
1938 if (!rc && is_mangled(mask))
1939 check_mangled_cache( mask );
1941 has_wild = strchr(mask,'*') || strchr(mask,'?');
1944 pstrcat(directory,"/");
1945 pstrcat(directory,mask);
1946 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
1949 exists = vfs_file_exist(conn,directory,NULL);
1951 void *dirptr = NULL;
1954 if (check_name(directory,conn))
1955 dirptr = OpenDir(conn, directory, True);
1957 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1958 the pattern matches against the long name, otherwise the short name
1959 We don't implement this yet XXXX
1966 if (strequal(mask,"????????.???"))
1969 while ((dname = ReadDirName(dirptr)))
1972 pstrcpy(fname,dname);
1974 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1976 error = ERRnoaccess;
1977 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1978 if (!can_delete(fname,conn,dirtype)) continue;
1979 if (!conn->vfs_ops.unlink(dos_to_unix(fname,False))) count++;
1980 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1988 return(ERROR(ERRDOS,error));
1991 if((errno == ENOENT) && bad_path)
1993 unix_ERR_class = ERRDOS;
1994 unix_ERR_code = ERRbadpath;
1996 return(UNIXERROR(ERRDOS,error));
2000 outsize = set_message(outbuf,0,0,True);
2006 /****************************************************************************
2007 reply to a readbraw (core+ protocol)
2008 ****************************************************************************/
2010 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2012 size_t maxcount,mincount;
2015 char *header = outbuf;
2020 * Special check if an oplock break has been issued
2021 * and the readraw request croses on the wire, we must
2022 * return a zero length response here.
2025 if(global_oplock_break)
2027 _smb_setlen(header,0);
2028 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2029 DEBUG(5,("readbraw - oplock break finished\n"));
2033 fsp = file_fsp(inbuf,smb_vwv0);
2035 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2037 * fsp could be NULL here so use the value from the packet. JRA.
2039 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2040 _smb_setlen(header,0);
2041 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2045 CHECK_FSP(fsp,conn);
2047 flush_write_cache(fsp, READRAW_FLUSH);
2049 startpos = IVAL(inbuf,smb_vwv1);
2050 if(CVAL(inbuf,smb_wct) == 10) {
2052 * This is a large offset (64 bit) read.
2054 #ifdef LARGE_SMB_OFF_T
2056 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2058 #else /* !LARGE_SMB_OFF_T */
2061 * Ensure we haven't been sent a >32 bit offset.
2064 if(IVAL(inbuf,smb_vwv8) != 0) {
2065 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2066 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2067 _smb_setlen(header,0);
2068 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2072 #endif /* LARGE_SMB_OFF_T */
2075 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2076 (double)startpos ));
2077 _smb_setlen(header,0);
2078 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2082 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2083 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2085 /* ensure we don't overrun the packet size */
2086 maxcount = MIN(65535,maxcount);
2087 maxcount = MAX(mincount,maxcount);
2089 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK))
2091 SMB_OFF_T size = fsp->size;
2092 SMB_OFF_T sizeneeded = startpos + maxcount;
2094 if (size < sizeneeded)
2097 if (fsp->conn->vfs_ops.fstat(fsp->fd,&st) == 0)
2099 if (!fsp->can_write)
2103 nread = MIN(maxcount,(size - startpos));
2106 if (nread < mincount)
2109 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2110 fsp->fnum, (double)startpos,
2111 (int)maxcount, (int)mincount, (int)nread ) );
2115 BOOL seek_fail = False;
2117 _smb_setlen(header,nread);
2119 #if USE_READ_PREDICTION
2120 if (!fsp->can_write)
2121 predict = read_predict(fsp, fsp->fd,startpos,header+4,NULL,nread);
2122 #endif /* USE_READ_PREDICTION */
2124 if ((nread-predict) > 0) {
2125 if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) {
2126 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2133 ret = (ssize_t)vfs_transfer_file(-1, fsp->fd, Client, NULL,
2134 (SMB_OFF_T)(nread-predict),header,4+predict,
2139 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2140 fsp->fsp_name,startpos,nread,ret));
2142 #else /* UNSAFE_READRAW */
2143 ret = read_file(fsp,header+4,startpos,nread);
2144 if (ret < mincount) ret = 0;
2146 _smb_setlen(header,ret);
2147 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2148 #endif /* UNSAFE_READRAW */
2150 DEBUG(5,("readbraw finished\n"));
2155 /****************************************************************************
2156 reply to a lockread (core+ protocol)
2157 ****************************************************************************/
2158 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2167 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2169 CHECK_FSP(fsp,conn);
2173 numtoread = SVAL(inbuf,smb_vwv1);
2174 startpos = IVAL(inbuf,smb_vwv2);
2176 outsize = set_message(outbuf,5,3,True);
2177 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2178 data = smb_buf(outbuf) + 3;
2181 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2182 * protocol request that predates the read/write lock concept.
2183 * Thus instead of asking for a read lock here we need to ask
2184 * for a write lock. JRA.
2187 if(!do_lock( fsp, conn, (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2188 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2190 * A blocking lock was requested. Package up
2191 * this smb into a queued request and push it
2192 * onto the blocking lock queue.
2194 if(push_blocking_lock_request(inbuf, length, -1, 0))
2197 return (ERROR(eclass,ecode));
2200 nread = read_file(fsp,data,startpos,numtoread);
2203 return(UNIXERROR(ERRDOS,ERRnoaccess));
2206 SSVAL(outbuf,smb_vwv0,nread);
2207 SSVAL(outbuf,smb_vwv5,nread+3);
2208 SSVAL(smb_buf(outbuf),1,nread);
2210 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2211 fsp->fnum, (int)numtoread, (int)nread ) );
2217 /****************************************************************************
2219 ****************************************************************************/
2221 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2228 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2230 CHECK_FSP(fsp,conn);
2234 numtoread = SVAL(inbuf,smb_vwv1);
2235 startpos = IVAL(inbuf,smb_vwv2);
2237 outsize = set_message(outbuf,5,3,True);
2238 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2239 data = smb_buf(outbuf) + 3;
2241 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK))
2242 return(ERROR(ERRDOS,ERRlock));
2245 nread = read_file(fsp,data,startpos,numtoread);
2248 return(UNIXERROR(ERRDOS,ERRnoaccess));
2251 SSVAL(outbuf,smb_vwv0,nread);
2252 SSVAL(outbuf,smb_vwv5,nread+3);
2253 CVAL(smb_buf(outbuf),0) = 1;
2254 SSVAL(smb_buf(outbuf),1,nread);
2256 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2257 fsp->fnum, (int)numtoread, (int)nread ) );
2263 /****************************************************************************
2264 reply to a read and X
2265 ****************************************************************************/
2266 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2268 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2269 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2270 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2271 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2275 /* If it's an IPC, pass off the pipe handler. */
2277 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2279 CHECK_FSP(fsp,conn);
2283 set_message(outbuf,12,0,True);
2284 data = smb_buf(outbuf);
2286 if(CVAL(inbuf,smb_wct) == 12) {
2287 #ifdef LARGE_SMB_OFF_T
2289 * This is a large offset (64 bit) read.
2291 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2293 #else /* !LARGE_SMB_OFF_T */
2296 * Ensure we haven't been sent a >32 bit offset.
2299 if(IVAL(inbuf,smb_vwv10) != 0) {
2300 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2301 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2302 return(ERROR(ERRDOS,ERRbadaccess));
2305 #endif /* LARGE_SMB_OFF_T */
2309 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK))
2310 return(ERROR(ERRDOS,ERRlock));
2311 nread = read_file(fsp,data,startpos,smb_maxcnt);
2314 return(UNIXERROR(ERRDOS,ERRnoaccess));
2316 SSVAL(outbuf,smb_vwv5,nread);
2317 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2318 SSVAL(smb_buf(outbuf),-2,nread);
2320 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2321 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2323 return chain_reply(inbuf,outbuf,length,bufsize);
2326 /****************************************************************************
2327 reply to a writebraw (core+ or LANMAN1.0 protocol)
2328 ****************************************************************************/
2330 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2333 ssize_t total_written=0;
2334 size_t numtowrite=0;
2339 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2342 CHECK_FSP(fsp,conn);
2346 tcount = IVAL(inbuf,smb_vwv1);
2347 startpos = IVAL(inbuf,smb_vwv3);
2348 write_through = BITSETW(inbuf+smb_vwv7,0);
2350 /* We have to deal with slightly different formats depending
2351 on whether we are using the core+ or lanman1.0 protocol */
2352 if(Protocol <= PROTOCOL_COREPLUS) {
2353 numtowrite = SVAL(smb_buf(inbuf),-2);
2354 data = smb_buf(inbuf);
2356 numtowrite = SVAL(inbuf,smb_vwv10);
2357 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2360 /* force the error type */
2361 CVAL(inbuf,smb_com) = SMBwritec;
2362 CVAL(outbuf,smb_com) = SMBwritec;
2364 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK))
2365 return(ERROR(ERRDOS,ERRlock));
2368 nwritten = write_file(fsp,data,startpos,numtowrite);
2370 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2371 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2373 if (nwritten < numtowrite)
2374 return(UNIXERROR(ERRHRD,ERRdiskfull));
2376 total_written = nwritten;
2378 /* Return a message to the redirector to tell it
2379 to send more bytes */
2380 CVAL(outbuf,smb_com) = SMBwritebraw;
2381 SSVALS(outbuf,smb_vwv0,-1);
2382 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2383 send_smb(smbd_server_fd(),outbuf);
2385 /* Now read the raw data into the buffer and write it */
2386 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2387 exit_server("secondary writebraw failed");
2390 /* Even though this is not an smb message, smb_len
2391 returns the generic length of an smb message */
2392 numtowrite = smb_len(inbuf);
2394 if (tcount > nwritten+numtowrite) {
2395 DEBUG(3,("Client overestimated the write %d %d %d\n",
2396 (int)tcount,(int)nwritten,(int)numtowrite));
2399 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2400 (SMB_OFF_T)numtowrite,NULL,0,
2402 total_written += nwritten;
2404 /* Set up outbuf to return the correct return */
2405 outsize = set_message(outbuf,1,0,True);
2406 CVAL(outbuf,smb_com) = SMBwritec;
2407 SSVAL(outbuf,smb_vwv0,total_written);
2409 if (nwritten < (ssize_t)numtowrite) {
2410 CVAL(outbuf,smb_rcls) = ERRHRD;
2411 SSVAL(outbuf,smb_err,ERRdiskfull);
2414 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2415 lp_strict_sync(SNUM(conn)))
2416 conn->vfs_ops.fsync(fsp->fd);
2418 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2419 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2421 /* we won't return a status if write through is not selected - this
2422 follows what WfWg does */
2423 if (!write_through && total_written==tcount)
2429 /****************************************************************************
2430 reply to a writeunlock (core+)
2431 ****************************************************************************/
2433 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2435 ssize_t nwritten = -1;
2441 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2444 CHECK_FSP(fsp,conn);
2448 numtowrite = SVAL(inbuf,smb_vwv1);
2449 startpos = IVAL(inbuf,smb_vwv2);
2450 data = smb_buf(inbuf) + 3;
2452 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK))
2453 return(ERROR(ERRDOS,ERRlock));
2455 /* The special X/Open SMB protocol handling of
2456 zero length writes is *NOT* done for
2461 nwritten = write_file(fsp,data,startpos,numtowrite);
2463 if (lp_syncalways(SNUM(conn)))
2464 conn->vfs_ops.fsync(fsp->fd);
2466 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2467 return(UNIXERROR(ERRDOS,ERRnoaccess));
2469 if(!do_unlock(fsp, conn, (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode))
2470 return(ERROR(eclass,ecode));
2472 outsize = set_message(outbuf,1,0,True);
2474 SSVAL(outbuf,smb_vwv0,nwritten);
2476 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2477 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2482 /****************************************************************************
2484 ****************************************************************************/
2485 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2488 ssize_t nwritten = -1;
2491 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2494 /* If it's an IPC, pass off the pipe handler. */
2496 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2498 CHECK_FSP(fsp,conn);
2502 numtowrite = SVAL(inbuf,smb_vwv1);
2503 startpos = IVAL(inbuf,smb_vwv2);
2504 data = smb_buf(inbuf) + 3;
2506 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK))
2507 return(ERROR(ERRDOS,ERRlock));
2509 /* X/Open SMB protocol says that if smb_vwv1 is
2510 zero then the file size should be extended or
2511 truncated to the size given in smb_vwv[2-3] */
2512 if(numtowrite == 0) {
2513 if((nwritten = set_filelen(fsp->fd, (SMB_OFF_T)startpos)) >= 0) /* tpot vfs */
2514 set_filelen_write_cache(fsp, startpos);
2516 nwritten = write_file(fsp,data,startpos,numtowrite);
2518 if (lp_syncalways(SNUM(conn)))
2519 conn->vfs_ops.fsync(fsp->fd);
2521 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2522 return(UNIXERROR(ERRDOS,ERRnoaccess));
2524 outsize = set_message(outbuf,1,0,True);
2526 SSVAL(outbuf,smb_vwv0,nwritten);
2528 if (nwritten < (ssize_t)numtowrite) {
2529 CVAL(outbuf,smb_rcls) = ERRHRD;
2530 SSVAL(outbuf,smb_err,ERRdiskfull);
2533 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2534 fsp->fnum, (int)numtowrite, (int)nwritten));
2540 /****************************************************************************
2541 reply to a write and X
2542 ****************************************************************************/
2543 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2545 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2546 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2547 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2548 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2549 ssize_t nwritten = -1;
2550 int smb_doff = SVAL(inbuf,smb_vwv11);
2553 /* If it's an IPC, pass off the pipe handler. */
2555 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2557 CHECK_FSP(fsp,conn);
2561 data = smb_base(inbuf) + smb_doff;
2563 if(CVAL(inbuf,smb_wct) == 14) {
2564 #ifdef LARGE_SMB_OFF_T
2566 * This is a large offset (64 bit) write.
2568 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2570 #else /* !LARGE_SMB_OFF_T */
2573 * Ensure we haven't been sent a >32 bit offset.
2576 if(IVAL(inbuf,smb_vwv12) != 0) {
2577 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2578 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2579 return(ERROR(ERRDOS,ERRbadaccess));
2582 #endif /* LARGE_SMB_OFF_T */
2585 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK))
2586 return(ERROR(ERRDOS,ERRlock));
2588 /* X/Open SMB protocol says that, unlike SMBwrite
2589 if the length is zero then NO truncation is
2590 done, just a write of zero. To truncate a file,
2595 nwritten = write_file(fsp,data,startpos,numtowrite);
2597 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2598 return(UNIXERROR(ERRDOS,ERRnoaccess));
2600 set_message(outbuf,6,0,True);
2602 SSVAL(outbuf,smb_vwv2,nwritten);
2604 if (nwritten < (ssize_t)numtowrite) {
2605 CVAL(outbuf,smb_rcls) = ERRHRD;
2606 SSVAL(outbuf,smb_err,ERRdiskfull);
2609 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2610 fsp->fnum, (int)numtowrite, (int)nwritten));
2612 if (lp_syncalways(SNUM(conn)) || write_through)
2613 conn->vfs_ops.fsync(fsp->fd);
2615 return chain_reply(inbuf,outbuf,length,bufsize);
2619 /****************************************************************************
2621 ****************************************************************************/
2623 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2629 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2631 CHECK_FSP(fsp,conn);
2634 flush_write_cache(fsp, SEEK_FLUSH);
2636 mode = SVAL(inbuf,smb_vwv1) & 3;
2637 startpos = IVALS(inbuf,smb_vwv2);
2640 case 0: umode = SEEK_SET; break;
2641 case 1: umode = SEEK_CUR; break;
2642 case 2: umode = SEEK_END; break;
2644 umode = SEEK_SET; break;
2647 if((res = conn->vfs_ops.lseek(fsp->fd,startpos,umode)) == -1) {
2649 * Check for the special case where a seek before the start
2650 * of the file sets the offset to zero. Added in the CIFS spec,
2654 if(errno == EINVAL) {
2655 SMB_OFF_T current_pos = startpos;
2657 if(umode == SEEK_CUR) {
2659 if((current_pos = conn->vfs_ops.lseek(fsp->fd,0,SEEK_CUR)) == -1)
2660 return(UNIXERROR(ERRDOS,ERRnoaccess));
2662 current_pos += startpos;
2664 } else if (umode == SEEK_END) {
2666 SMB_STRUCT_STAT sbuf;
2668 if(conn->vfs_ops.fstat(fsp->fd, &sbuf) == -1)
2669 return(UNIXERROR(ERRDOS,ERRnoaccess));
2671 current_pos += sbuf.st_size;
2675 res = conn->vfs_ops.lseek(fsp->fd,0,SEEK_SET);
2679 return(UNIXERROR(ERRDOS,ERRnoaccess));
2684 outsize = set_message(outbuf,2,0,True);
2685 SIVAL(outbuf,smb_vwv0,res);
2687 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2688 fsp->fnum, (double)startpos, (double)res, mode));
2693 /****************************************************************************
2695 ****************************************************************************/
2697 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2699 int outsize = set_message(outbuf,0,0,True);
2700 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2703 CHECK_FSP(fsp,conn);
2708 file_sync_all(conn);
2710 conn->vfs_ops.fsync(fsp->fd);
2713 DEBUG(3,("flush\n"));
2718 /****************************************************************************
2720 ****************************************************************************/
2721 int reply_exit(connection_struct *conn,
2722 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2724 int outsize = set_message(outbuf,0,0,True);
2725 DEBUG(3,("exit\n"));
2731 /****************************************************************************
2732 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2733 ****************************************************************************/
2734 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2739 int32 eclass = 0, err = 0;
2740 files_struct *fsp = NULL;
2742 outsize = set_message(outbuf,0,0,True);
2744 /* If it's an IPC, pass off to the pipe handler. */
2746 return reply_pipe_close(conn, inbuf,outbuf);
2748 fsp = file_fsp(inbuf,smb_vwv0);
2751 * We can only use CHECK_FSP if we know it's not a directory.
2754 if(!fsp || (fsp->conn != conn))
2755 return(ERROR(ERRDOS,ERRbadfid));
2757 if(HAS_CACHED_ERROR(fsp)) {
2758 eclass = fsp->wbmpx_ptr->wr_errclass;
2759 err = fsp->wbmpx_ptr->wr_error;
2762 if(fsp->is_directory || fsp->stat_open) {
2764 * Special case - close NT SMB directory or stat file
2767 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2768 close_file(fsp,True);
2771 * Close ordinary file.
2776 * If there was a modify time outstanding,
2777 * try and set it here.
2779 if(fsp->pending_modtime)
2780 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2783 * Now take care of any time sent in the close.
2785 mtime = make_unix_date3(inbuf+smb_vwv1);
2787 /* try and set the date */
2788 set_filetime(conn, fsp->fsp_name,mtime);
2790 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2792 conn->num_files_open));
2795 * close_file() returns the unix errno if an error
2796 * was detected on close - normally this is due to
2797 * a disk full error. If not then it was probably an I/O error.
2800 if((close_err = close_file(fsp,True)) != 0) {
2802 return (UNIXERROR(ERRHRD,ERRgeneral));
2806 /* We have a cached error */
2808 return(ERROR(eclass,err));
2814 /****************************************************************************
2815 reply to a writeclose (Core+ protocol)
2816 ****************************************************************************/
2818 int reply_writeclose(connection_struct *conn,
2819 char *inbuf,char *outbuf, int size, int dum_buffsize)
2822 ssize_t nwritten = -1;
2828 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2830 CHECK_FSP(fsp,conn);
2834 numtowrite = SVAL(inbuf,smb_vwv1);
2835 startpos = IVAL(inbuf,smb_vwv2);
2836 mtime = make_unix_date3(inbuf+smb_vwv4);
2837 data = smb_buf(inbuf) + 1;
2839 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK))
2840 return(ERROR(ERRDOS,ERRlock));
2842 nwritten = write_file(fsp,data,startpos,numtowrite);
2844 set_filetime(conn, fsp->fsp_name,mtime);
2846 close_err = close_file(fsp,True);
2848 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2849 fsp->fnum, (int)numtowrite, (int)nwritten,
2850 conn->num_files_open));
2853 return(UNIXERROR(ERRDOS,ERRnoaccess));
2855 if(close_err != 0) {
2857 return(UNIXERROR(ERRHRD,ERRgeneral));
2860 outsize = set_message(outbuf,1,0,True);
2862 SSVAL(outbuf,smb_vwv0,nwritten);
2867 /****************************************************************************
2869 ****************************************************************************/
2870 int reply_lock(connection_struct *conn,
2871 char *inbuf,char *outbuf, int length, int dum_buffsize)
2873 int outsize = set_message(outbuf,0,0,True);
2874 SMB_BIG_UINT count,offset;
2877 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2879 CHECK_FSP(fsp,conn);
2882 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2883 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2885 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2886 fsp->fd, fsp->fnum, (double)offset, (double)count));
2888 if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) {
2889 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2891 * A blocking lock was requested. Package up
2892 * this smb into a queued request and push it
2893 * onto the blocking lock queue.
2895 if(push_blocking_lock_request(inbuf, length, -1, 0))
2898 return (ERROR(eclass,ecode));
2905 /****************************************************************************
2907 ****************************************************************************/
2908 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2910 int outsize = set_message(outbuf,0,0,True);
2911 SMB_BIG_UINT count,offset;
2914 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2916 CHECK_FSP(fsp,conn);
2919 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2920 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2922 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2923 return (ERROR(eclass,ecode));
2925 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2926 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2932 /****************************************************************************
2934 ****************************************************************************/
2935 int reply_tdis(connection_struct *conn,
2936 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2938 int outsize = set_message(outbuf,0,0,True);
2941 vuid = SVAL(inbuf,smb_uid);
2944 DEBUG(4,("Invalid connection in tdis\n"));
2945 return(ERROR(ERRSRV,ERRinvnid));
2950 close_cnum(conn,vuid);
2957 /****************************************************************************
2959 ****************************************************************************/
2960 int reply_echo(connection_struct *conn,
2961 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2963 int smb_reverb = SVAL(inbuf,smb_vwv0);
2965 int data_len = smb_buflen(inbuf);
2966 int outsize = set_message(outbuf,1,data_len,True);
2968 /* copy any incoming data back out */
2970 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2972 if (smb_reverb > 100) {
2973 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2977 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2978 SSVAL(outbuf,smb_vwv0,seq_num);
2980 smb_setlen(outbuf,outsize - 4);
2982 send_smb(smbd_server_fd(),outbuf);
2985 DEBUG(3,("echo %d times\n", smb_reverb));
2993 /****************************************************************************
2994 reply to a printopen
2995 ****************************************************************************/
2996 int reply_printopen(connection_struct *conn,
2997 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3002 if (!CAN_PRINT(conn))
3003 return(ERROR(ERRDOS,ERRnoaccess));
3005 /* Open for exclusive use, write only. */
3006 fsp = print_fsp_open(conn,"dos.prn");
3009 return(UNIXERROR(ERRDOS,ERRnoaccess));
3012 outsize = set_message(outbuf,1,0,True);
3013 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3015 DEBUG(3,("openprint fd=%d fnum=%d\n",
3016 fsp->fd, fsp->fnum));
3022 /****************************************************************************
3023 reply to a printclose
3024 ****************************************************************************/
3025 int reply_printclose(connection_struct *conn,
3026 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3028 int outsize = set_message(outbuf,0,0,True);
3029 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3032 CHECK_FSP(fsp,conn);
3035 if (!CAN_PRINT(conn))
3036 return(ERROR(ERRDOS,ERRnoaccess));
3038 DEBUG(3,("printclose fd=%d fnum=%d\n",
3039 fsp->fd,fsp->fnum));
3041 close_err = close_file(fsp,True);
3043 if(close_err != 0) {
3045 return(UNIXERROR(ERRHRD,ERRgeneral));
3052 /****************************************************************************
3053 reply to a printqueue
3054 ****************************************************************************/
3055 int reply_printqueue(connection_struct *conn,
3056 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3058 int outsize = set_message(outbuf,2,3,True);
3059 int max_count = SVAL(inbuf,smb_vwv0);
3060 int start_index = SVAL(inbuf,smb_vwv1);
3062 /* we used to allow the client to get the cnum wrong, but that
3063 is really quite gross and only worked when there was only
3064 one printer - I think we should now only accept it if they
3065 get it right (tridge) */
3066 if (!CAN_PRINT(conn))
3067 return(ERROR(ERRDOS,ERRnoaccess));
3069 SSVAL(outbuf,smb_vwv0,0);
3070 SSVAL(outbuf,smb_vwv1,0);
3071 CVAL(smb_buf(outbuf),0) = 1;
3072 SSVAL(smb_buf(outbuf),1,0);
3074 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3075 start_index, max_count));
3078 print_queue_struct *queue = NULL;
3079 char *p = smb_buf(outbuf) + 3;
3080 int count = print_queue_status(SNUM(conn), &queue,NULL);
3081 int num_to_get = ABS(max_count);
3082 int first = (max_count>0?start_index:start_index+max_count+1);
3088 num_to_get = MIN(num_to_get,count-first);
3091 for (i=first;i<first+num_to_get;i++) {
3092 put_dos_date2(p,0,queue[i].time);
3093 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3094 SSVAL(p,5, queue[i].job);
3095 SIVAL(p,7,queue[i].size);
3097 StrnCpy(p+12,queue[i].user,16);
3102 outsize = set_message(outbuf,2,28*count+3,False);
3103 SSVAL(outbuf,smb_vwv0,count);
3104 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3105 CVAL(smb_buf(outbuf),0) = 1;
3106 SSVAL(smb_buf(outbuf),1,28*count);
3109 if (queue) free(queue);
3111 DEBUG(3,("%d entries returned in queue\n",count));
3118 /****************************************************************************
3119 reply to a printwrite
3120 ****************************************************************************/
3121 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3124 int outsize = set_message(outbuf,0,0,True);
3126 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3128 if (!CAN_PRINT(conn))
3129 return(ERROR(ERRDOS,ERRnoaccess));
3131 CHECK_FSP(fsp,conn);
3135 numtowrite = SVAL(smb_buf(inbuf),1);
3136 data = smb_buf(inbuf) + 3;
3138 if (write_file(fsp,data,-1,numtowrite) != numtowrite)
3139 return(UNIXERROR(ERRDOS,ERRnoaccess));
3141 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3147 /****************************************************************************
3149 ****************************************************************************/
3150 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3153 int outsize,ret= -1;
3154 BOOL bad_path = False;
3156 pstrcpy(directory,smb_buf(inbuf) + 1);
3157 unix_convert(directory,conn,0,&bad_path,NULL);
3159 if (check_name(directory, conn))
3160 ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
3161 unix_mode(conn,aDIR,directory));
3165 if((errno == ENOENT) && bad_path)
3167 unix_ERR_class = ERRDOS;
3168 unix_ERR_code = ERRbadpath;
3170 return(UNIXERROR(ERRDOS,ERRnoaccess));
3173 outsize = set_message(outbuf,0,0,True);
3175 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
3180 /****************************************************************************
3181 Static function used by reply_rmdir to delete an entire directory
3183 ****************************************************************************/
3185 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3189 void *dirptr = OpenDir(NULL, directory, False);
3194 while((dname = ReadDirName(dirptr)))
3199 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3202 /* Construct the full name. */
3203 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3209 pstrcpy(fullname, directory);
3210 pstrcat(fullname, "/");
3211 pstrcat(fullname, dname);
3213 if(conn->vfs_ops.lstat(dos_to_unix(fullname,False), &st) != 0)
3219 if(st.st_mode & S_IFDIR)
3221 if(recursive_rmdir(conn, fullname)!=0)
3226 if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
3232 else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
3242 /****************************************************************************
3243 The internals of the rmdir code - called elsewhere.
3244 ****************************************************************************/
3246 BOOL rmdir_internals(connection_struct *conn, char *directory)
3250 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory, False)) == 0);
3251 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3254 * Check to see if the only thing in this directory are
3255 * vetoed files/directories. If so then delete them and
3256 * retry. If we fail to delete any of them (and we *don't*
3257 * do a recursive delete) then fail the rmdir.
3259 BOOL all_veto_files = True;
3261 void *dirptr = OpenDir(conn, directory, False);
3265 int dirpos = TellDir(dirptr);
3266 while ((dname = ReadDirName(dirptr)))
3268 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3270 if(!IS_VETO_PATH(conn, dname))
3272 all_veto_files = False;
3278 SeekDir(dirptr,dirpos);
3279 while ((dname = ReadDirName(dirptr)))
3284 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3287 /* Construct the full name. */
3288 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3293 pstrcpy(fullname, directory);
3294 pstrcat(fullname, "/");
3295 pstrcat(fullname, dname);
3297 if(conn->vfs_ops.lstat(dos_to_unix(fullname, False), &st) != 0)
3299 if(st.st_mode & S_IFDIR)
3301 if(lp_recursive_veto_delete(SNUM(conn)))
3303 if(recursive_rmdir(conn, fullname) != 0)
3306 if(conn->vfs_ops.rmdir(dos_to_unix(fullname, False)) != 0)
3309 else if(conn->vfs_ops.unlink(dos_to_unix(fullname, False)) != 0)
3313 /* Retry the rmdir */
3314 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory, False)) == 0);
3324 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3325 directory,strerror(errno)));
3330 /****************************************************************************
3332 ****************************************************************************/
3334 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3339 BOOL bad_path = False;
3341 pstrcpy(directory,smb_buf(inbuf) + 1);
3343 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3345 unix_convert(directory,conn, NULL,&bad_path,NULL);
3347 if (check_name(directory,conn))
3349 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3350 ok = rmdir_internals(conn, directory);
3355 if((errno == ENOENT) && bad_path)
3357 unix_ERR_class = ERRDOS;
3358 unix_ERR_code = ERRbadpath;
3360 return(UNIXERROR(ERRDOS,ERRbadpath));
3363 outsize = set_message(outbuf,0,0,True);
3365 DEBUG( 3, ( "rmdir %s\n", directory ) );
3371 /*******************************************************************
3372 resolve wildcards in a filename rename
3373 ********************************************************************/
3374 static BOOL resolve_wildcards(char *name1,char *name2)
3376 fstring root1,root2;
3380 name1 = strrchr(name1,'/');
3381 name2 = strrchr(name2,'/');
3383 if (!name1 || !name2) return(False);
3385 fstrcpy(root1,name1);
3386 fstrcpy(root2,name2);
3387 p = strrchr(root1,'.');
3394 p = strrchr(root2,'.');
3426 pstrcpy(name2,root2);
3429 pstrcat(name2,ext2);
3435 /*******************************************************************
3436 check if a user is allowed to rename a file
3437 ********************************************************************/
3438 static BOOL can_rename(char *fname,connection_struct *conn)
3440 SMB_STRUCT_STAT sbuf;
3442 if (!CAN_WRITE(conn)) return(False);
3444 if (conn->vfs_ops.lstat(dos_to_unix(fname,False),&sbuf) != 0) return(False);
3445 if (!check_file_sharing(conn,fname,True)) return(False);
3450 /****************************************************************************
3451 The guts of the rename command, split out so it may be called by the NT SMB
3453 ****************************************************************************/
3454 int rename_internals(connection_struct *conn,
3455 char *inbuf, char *outbuf, char *name,
3456 char *newname, BOOL replace_if_exists)
3460 pstring newname_last_component;
3463 BOOL bad_path1 = False;
3464 BOOL bad_path2 = False;
3466 int error = ERRnoaccess;
3471 *directory = *mask = 0;
3473 rc = unix_convert(name,conn,0,&bad_path1,NULL);
3474 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3477 * Split the old name into directory and last component
3478 * strings. Note that unix_convert may have stripped off a
3479 * leading ./ from both name and newname if the rename is
3480 * at the root of the share. We need to make sure either both
3481 * name and newname contain a / character or neither of them do
3482 * as this is checked in resolve_wildcards().
3485 p = strrchr(name,'/');
3487 pstrcpy(directory,".");
3491 pstrcpy(directory,name);
3493 *p = '/'; /* Replace needed for exceptional test below. */
3497 * We should only check the mangled cache
3498 * here if unix_convert failed. This means
3499 * that the path in 'mask' doesn't exist
3500 * on the file system and so we need to look
3501 * for a possible mangle. This patch from
3502 * Tine Smukavec <valentin.smukavec@hermes.si>.
3505 if (!rc && is_mangled(mask))
3506 check_mangled_cache( mask );
3508 has_wild = strchr(mask,'*') || strchr(mask,'?');
3512 * No wildcards - just process the one file.
3514 BOOL is_short_name = is_8_3(name, True);
3516 /* Add a terminating '/' to the directory name. */
3517 pstrcat(directory,"/");
3518 pstrcat(directory,mask);
3520 /* Ensure newname contains a '/' also */
3521 if(strrchr(newname,'/') == 0) {
3524 pstrcpy(tmpstr, "./");
3525 pstrcat(tmpstr, newname);
3526 pstrcpy(newname, tmpstr);
3529 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",
3530 case_sensitive, case_preserve, short_case_preserve, directory,
3531 newname, newname_last_component, is_short_name));
3534 * Check for special case with case preserving and not
3535 * case sensitive, if directory and newname are identical,
3536 * and the old last component differs from the original
3537 * last component only by case, then we should allow
3538 * the rename (user is trying to change the case of the
3541 if((case_sensitive == False) &&
3542 (((case_preserve == True) &&
3543 (is_short_name == False)) ||
3544 ((short_case_preserve == True) &&
3545 (is_short_name == True))) &&
3546 strcsequal(directory, newname)) {
3547 pstring newname_modified_last_component;
3550 * Get the last component of the modified name.
3551 * Note that we guarantee that newname contains a '/'
3554 p = strrchr(newname,'/');
3555 pstrcpy(newname_modified_last_component,p+1);
3557 if(strcsequal(newname_modified_last_component,
3558 newname_last_component) == False) {
3560 * Replace the modified last component with
3563 pstrcpy(p+1, newname_last_component);
3567 pstrcpy(zdirectory, dos_to_unix(directory, False));
3568 if(replace_if_exists) {
3570 * NT SMB specific flag - rename can overwrite
3571 * file with the same name so don't check for
3574 if(resolve_wildcards(directory,newname) &&
3575 can_rename(directory,conn) &&
3576 !conn->vfs_ops.rename(zdirectory,
3577 dos_to_unix(newname,False)))
3580 if (resolve_wildcards(directory,newname) &&
3581 can_rename(directory,conn) &&
3582 !vfs_file_exist(conn,newname,NULL) &&
3583 !conn->vfs_ops.rename(zdirectory,
3584 dos_to_unix(newname,False)))
3588 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3589 directory,newname));
3591 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3592 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3598 * Wildcards - process each file that matches.
3600 void *dirptr = NULL;
3604 if (check_name(directory,conn))
3605 dirptr = OpenDir(conn, directory, True);
3610 if (strequal(mask,"????????.???"))
3613 while ((dname = ReadDirName(dirptr))) {
3616 pstrcpy(fname,dname);
3618 if(!mask_match(fname, mask, case_sensitive, False))
3621 error = ERRnoaccess;
3622 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3623 if (!can_rename(fname,conn)) {
3624 DEBUG(6,("rename %s refused\n", fname));
3627 pstrcpy(destname,newname);
3629 if (!resolve_wildcards(fname,destname)) {
3630 DEBUG(6,("resolve_wildcards %s %s failed\n",
3635 if (!replace_if_exists &&
3636 vfs_file_exist(conn,destname, NULL)) {
3637 DEBUG(6,("file_exist %s\n", destname));
3642 if (!conn->vfs_ops.rename(dos_to_unix(fname,False),
3643 dos_to_unix(destname,False)))
3645 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3653 return(ERROR(ERRDOS,error));
3655 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3656 unix_ERR_class = ERRDOS;
3657 unix_ERR_code = ERRbadpath;
3659 return(UNIXERROR(ERRDOS,error));
3666 /****************************************************************************
3668 ****************************************************************************/
3670 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3676 pstrcpy(name,smb_buf(inbuf) + 1);
3677 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3679 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3680 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3682 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3684 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3686 outsize = set_message(outbuf,0,0,True);
3691 /*******************************************************************
3692 copy a file as part of a reply_copy
3693 ******************************************************************/
3695 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3696 int count,BOOL target_is_directory, int *err_ret)
3701 files_struct *fsp1,*fsp2;
3706 pstrcpy(dest,dest1);
3707 if (target_is_directory) {
3708 char *p = strrchr(src,'/');
3717 if (!vfs_file_exist(conn,src,&st))
3720 fsp1 = open_file_shared(conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3721 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3727 if (!target_is_directory && count)
3730 fsp2 = open_file_shared(conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3731 ofun,st.st_mode,0,&Access,&action);
3734 close_file(fsp1,False);
3738 if ((ofun&3) == 1) {
3739 if(conn->vfs_ops.lseek(fsp2->fd,0,SEEK_END) == -1) {
3740 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3743 * Stop the copy from occurring.
3751 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0);
3753 close_file(fsp1,False);
3755 * As we are opening fsp1 read-only we only expect
3756 * an error on close on fsp2 if we are out of space.
3757 * Thus we don't look at the error return from the
3760 *err_ret = close_file(fsp2,False);
3762 return(ret == (SMB_OFF_T)st.st_size);
3767 /****************************************************************************
3768 reply to a file copy.
3769 ****************************************************************************/
3770 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3775 pstring mask,newname;
3778 int error = ERRnoaccess;
3782 int tid2 = SVAL(inbuf,smb_vwv0);
3783 int ofun = SVAL(inbuf,smb_vwv1);
3784 int flags = SVAL(inbuf,smb_vwv2);
3785 BOOL target_is_directory=False;
3786 BOOL bad_path1 = False;
3787 BOOL bad_path2 = False;
3790 *directory = *mask = 0;
3792 pstrcpy(name,smb_buf(inbuf));
3793 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3795 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3797 if (tid2 != conn->cnum) {
3798 /* can't currently handle inter share copies XXXX */
3799 DEBUG(3,("Rejecting inter-share copy\n"));
3800 return(ERROR(ERRSRV,ERRinvdevice));
3803 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3804 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3806 rc = unix_convert(name,conn,0,&bad_path1,NULL);
3807 unix_convert(newname,conn,0,&bad_path2,NULL);
3809 target_is_directory = vfs_directory_exist(conn,False,NULL);
3811 if ((flags&1) && target_is_directory) {
3812 return(ERROR(ERRDOS,ERRbadfile));
3815 if ((flags&2) && !target_is_directory) {
3816 return(ERROR(ERRDOS,ERRbadpath));
3819 if ((flags&(1<<5)) && vfs_directory_exist(conn,name,NULL)) {
3820 /* wants a tree copy! XXXX */
3821 DEBUG(3,("Rejecting tree copy\n"));
3822 return(ERROR(ERRSRV,ERRerror));
3825 p = strrchr(name,'/');
3827 pstrcpy(directory,"./");
3831 pstrcpy(directory,name);
3836 * We should only check the mangled cache
3837 * here if unix_convert failed. This means
3838 * that the path in 'mask' doesn't exist
3839 * on the file system and so we need to look
3840 * for a possible mangle. This patch from
3841 * Tine Smukavec <valentin.smukavec@hermes.si>.
3844 if (!rc && is_mangled(mask))
3845 check_mangled_cache( mask );
3847 has_wild = strchr(mask,'*') || strchr(mask,'?');
3850 pstrcat(directory,"/");
3851 pstrcat(directory,mask);
3852 if (resolve_wildcards(directory,newname) &&
3853 copy_file(directory,newname,conn,ofun,
3854 count,target_is_directory,&err)) count++;
3857 return(UNIXERROR(ERRHRD,ERRgeneral));
3859 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3861 void *dirptr = NULL;
3865 if (check_name(directory,conn))
3866 dirptr = OpenDir(conn, directory, True);
3871 if (strequal(mask,"????????.???"))
3874 while ((dname = ReadDirName(dirptr))) {
3876 pstrcpy(fname,dname);
3878 if(!mask_match(fname, mask, case_sensitive, False))
3881 error = ERRnoaccess;
3882 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3883 pstrcpy(destname,newname);
3884 if (resolve_wildcards(fname,destname) &&
3885 copy_file(fname,destname,conn,ofun,
3886 count,target_is_directory,&err)) count++;
3887 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3895 /* Error on close... */
3897 return(UNIXERROR(ERRHRD,ERRgeneral));
3901 return(ERROR(ERRDOS,error));
3904 if((errno == ENOENT) && (bad_path1 || bad_path2))
3906 unix_ERR_class = ERRDOS;
3907 unix_ERR_code = ERRbadpath;
3909 return(UNIXERROR(ERRDOS,error));
3913 outsize = set_message(outbuf,1,0,True);
3914 SSVAL(outbuf,smb_vwv0,count);
3919 /****************************************************************************
3921 ****************************************************************************/
3922 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3930 if (!CAN_SETDIR(snum))
3931 return(ERROR(ERRDOS,ERRnoaccess));
3933 pstrcpy(newdir,smb_buf(inbuf) + 1);
3936 if (strlen(newdir) == 0) {
3939 ok = vfs_directory_exist(conn,newdir,NULL);
3941 string_set(&conn->connectpath,newdir);
3946 return(ERROR(ERRDOS,ERRbadpath));
3948 outsize = set_message(outbuf,0,0,True);
3949 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3951 DEBUG(3,("setdir %s\n", newdir));
3956 /****************************************************************************
3957 Get a lock count, dealing with large count requests.
3958 ****************************************************************************/
3960 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3962 SMB_BIG_UINT count = 0;
3964 if(!large_file_format) {
3965 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3968 #if defined(HAVE_LONGLONG)
3969 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3970 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3971 #else /* HAVE_LONGLONG */
3974 * NT4.x seems to be broken in that it sends large file (64 bit)
3975 * lockingX calls even if the CAP_LARGE_FILES was *not*
3976 * negotiated. For boxes without large unsigned ints truncate the
3977 * lock count by dropping the top 32 bits.
3980 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3981 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3982 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3983 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3984 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3987 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3988 #endif /* HAVE_LONGLONG */
3994 /****************************************************************************
3995 Get a lock offset, dealing with large offset requests.
3996 ****************************************************************************/
3998 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4000 SMB_BIG_UINT offset = 0;
4004 if(!large_file_format) {
4005 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4008 #if defined(HAVE_LONGLONG)
4009 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4010 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4011 #else /* HAVE_LONGLONG */
4014 * NT4.x seems to be broken in that it sends large file (64 bit)
4015 * lockingX calls even if the CAP_LARGE_FILES was *not*
4016 * negotiated. For boxes without large unsigned ints mangle the
4017 * lock offset by mapping the top 32 bits onto the lower 32.
4020 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4021 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4022 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4025 if((new_low = map_lock_offset(high, low)) == 0) {
4027 return (SMB_BIG_UINT)-1;
4030 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4031 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4032 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4033 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4036 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4037 #endif /* HAVE_LONGLONG */
4043 /****************************************************************************
4044 reply to a lockingX request
4045 ****************************************************************************/
4047 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4049 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4050 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4052 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4054 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4055 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4056 SMB_BIG_UINT count = 0, offset = 0;
4057 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4060 uint32 ecode=0, dummy2;
4061 int eclass=0, dummy1;
4062 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
4065 CHECK_FSP(fsp,conn);
4068 data = smb_buf(inbuf);
4070 /* Check if this is an oplock break on a file
4071 we have granted an oplock on.
4073 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4075 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
4079 * Make sure we have granted an exclusive or batch oplock on this file.
4082 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4084 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4085 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4087 /* if this is a pure oplock break request then don't send a reply */
4088 if (num_locks == 0 && num_ulocks == 0)
4091 return ERROR(ERRDOS,ERRlock);
4094 if (remove_oplock(fsp) == False) {
4095 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4099 /* if this is a pure oplock break request then don't send a reply */
4100 if (num_locks == 0 && num_ulocks == 0)
4102 /* Sanity check - ensure a pure oplock break is not a
4104 if(CVAL(inbuf,smb_vwv0) != 0xff)
4105 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4106 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4111 /* Data now points at the beginning of the list
4112 of smb_unlkrng structs */
4113 for(i = 0; i < (int)num_ulocks; i++) {
4114 count = get_lock_count( data, i, large_file_format);
4115 offset = get_lock_offset( data, i, large_file_format, &err);
4118 * There is no error code marked "stupid client bug".... :-).
4121 return ERROR(ERRDOS,ERRnoaccess);
4123 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
4124 (double)offset, (double)count, fsp->fsp_name ));
4126 if(!do_unlock(fsp,conn,count,offset, &eclass, &ecode))
4127 return ERROR(eclass,ecode);
4130 /* Setup the timeout in seconds. */
4131 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4133 /* Now do any requested locks */
4134 data += ((large_file_format ? 20 : 10)*num_ulocks);
4136 /* Data now points at the beginning of the list
4137 of smb_lkrng structs */
4139 for(i = 0; i < (int)num_locks; i++) {
4140 count = get_lock_count( data, i, large_file_format);
4141 offset = get_lock_offset( data, i, large_file_format, &err);
4144 * There is no error code marked "stupid client bug".... :-).
4147 return ERROR(ERRDOS,ERRnoaccess);
4149 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
4150 (double)offset, (double)count, fsp->fsp_name ));
4152 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4154 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4156 * A blocking lock was requested. Package up
4157 * this smb into a queued request and push it
4158 * onto the blocking lock queue.
4160 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
4167 /* If any of the above locks failed, then we must unlock
4168 all of the previous locks (X/Open spec). */
4169 if(i != num_locks && num_locks != 0) {
4171 * Ensure we don't do a remove on the lock that just failed,
4172 * as under POSIX rules, if we have a lock already there, we
4173 * will delete it (and we shouldn't) .....
4175 for(i--; i >= 0; i--) {
4176 count = get_lock_count( data, i, large_file_format);
4177 offset = get_lock_offset( data, i, large_file_format, &err);
4180 * There is no error code marked "stupid client bug".... :-).
4183 return ERROR(ERRDOS,ERRnoaccess);
4185 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
4187 return ERROR(eclass,ecode);
4190 set_message(outbuf,2,0,True);
4192 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4193 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4195 return chain_reply(inbuf,outbuf,length,bufsize);
4199 /****************************************************************************
4200 reply to a SMBreadbmpx (read block multiplex) request
4201 ****************************************************************************/
4202 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4213 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4215 /* this function doesn't seem to work - disable by default */
4217 return(ERROR(ERRSRV,ERRuseSTD));
4219 outsize = set_message(outbuf,8,0,True);
4221 CHECK_FSP(fsp,conn);
4225 startpos = IVAL(inbuf,smb_vwv1);
4226 maxcount = SVAL(inbuf,smb_vwv3);
4228 data = smb_buf(outbuf);
4229 pad = ((long)data)%4;
4230 if (pad) pad = 4 - pad;
4233 max_per_packet = bufsize-(outsize+pad);
4237 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK))
4238 return(ERROR(ERRDOS,ERRlock));
4242 size_t N = MIN(max_per_packet,tcount-total_read);
4244 nread = read_file(fsp,data,startpos,N);
4246 if (nread <= 0) nread = 0;
4248 if (nread < (ssize_t)N)
4249 tcount = total_read + nread;
4251 set_message(outbuf,8,nread,False);
4252 SIVAL(outbuf,smb_vwv0,startpos);
4253 SSVAL(outbuf,smb_vwv2,tcount);
4254 SSVAL(outbuf,smb_vwv6,nread);
4255 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4257 send_smb(smbd_server_fd(),outbuf);
4259 total_read += nread;
4262 while (total_read < (ssize_t)tcount);
4267 /****************************************************************************
4268 reply to a SMBwritebmpx (write block multiplex primary) request
4269 ****************************************************************************/
4271 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4274 ssize_t nwritten = -1;
4281 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4283 CHECK_FSP(fsp,conn);
4287 tcount = SVAL(inbuf,smb_vwv1);
4288 startpos = IVAL(inbuf,smb_vwv3);
4289 write_through = BITSETW(inbuf+smb_vwv7,0);
4290 numtowrite = SVAL(inbuf,smb_vwv10);
4291 smb_doff = SVAL(inbuf,smb_vwv11);
4293 data = smb_base(inbuf) + smb_doff;
4295 /* If this fails we need to send an SMBwriteC response,
4296 not an SMBwritebmpx - set this up now so we don't forget */
4297 CVAL(outbuf,smb_com) = SMBwritec;
4299 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK))
4300 return(ERROR(ERRDOS,ERRlock));
4302 nwritten = write_file(fsp,data,startpos,numtowrite);
4304 if(lp_syncalways(SNUM(conn)) || write_through)
4305 conn->vfs_ops.fsync(fsp->fd);
4307 if(nwritten < (ssize_t)numtowrite)
4308 return(UNIXERROR(ERRHRD,ERRdiskfull));
4310 /* If the maximum to be written to this file
4311 is greater than what we just wrote then set
4312 up a secondary struct to be attached to this
4313 fd, we will use this to cache error messages etc. */
4314 if((ssize_t)tcount > nwritten)
4316 write_bmpx_struct *wbms;
4317 if(fsp->wbmpx_ptr != NULL)
4318 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4320 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4323 DEBUG(0,("Out of memory in reply_readmpx\n"));
4324 return(ERROR(ERRSRV,ERRnoresource));
4326 wbms->wr_mode = write_through;
4327 wbms->wr_discard = False; /* No errors yet */
4328 wbms->wr_total_written = nwritten;
4329 wbms->wr_errclass = 0;
4331 fsp->wbmpx_ptr = wbms;
4334 /* We are returning successfully, set the message type back to
4336 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4338 outsize = set_message(outbuf,1,0,True);
4340 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4342 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4343 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4345 if (write_through && tcount==nwritten) {
4346 /* we need to send both a primary and a secondary response */
4347 smb_setlen(outbuf,outsize - 4);
4348 send_smb(smbd_server_fd(),outbuf);
4350 /* now the secondary */
4351 outsize = set_message(outbuf,1,0,True);
4352 CVAL(outbuf,smb_com) = SMBwritec;
4353 SSVAL(outbuf,smb_vwv0,nwritten);
4360 /****************************************************************************
4361 reply to a SMBwritebs (write block multiplex secondary) request
4362 ****************************************************************************/
4363 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4366 ssize_t nwritten = -1;
4373 write_bmpx_struct *wbms;
4374 BOOL send_response = False;
4375 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4377 CHECK_FSP(fsp,conn);
4380 tcount = SVAL(inbuf,smb_vwv1);
4381 startpos = IVAL(inbuf,smb_vwv2);
4382 numtowrite = SVAL(inbuf,smb_vwv6);
4383 smb_doff = SVAL(inbuf,smb_vwv7);
4385 data = smb_base(inbuf) + smb_doff;
4387 /* We need to send an SMBwriteC response, not an SMBwritebs */
4388 CVAL(outbuf,smb_com) = SMBwritec;
4390 /* This fd should have an auxiliary struct attached,
4391 check that it does */
4392 wbms = fsp->wbmpx_ptr;
4393 if(!wbms) return(-1);
4395 /* If write through is set we can return errors, else we must
4397 write_through = wbms->wr_mode;
4399 /* Check for an earlier error */
4400 if(wbms->wr_discard)
4401 return -1; /* Just discard the packet */
4403 nwritten = write_file(fsp,data,startpos,numtowrite);
4405 if(lp_syncalways(SNUM(conn)) || write_through)
4406 conn->vfs_ops.fsync(fsp->fd);
4408 if (nwritten < (ssize_t)numtowrite)
4412 /* We are returning an error - we can delete the aux struct */
4413 if (wbms) free((char *)wbms);
4414 fsp->wbmpx_ptr = NULL;
4415 return(ERROR(ERRHRD,ERRdiskfull));
4417 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4420 /* Increment the total written, if this matches tcount
4421 we can discard the auxiliary struct (hurrah !) and return a writeC */
4422 wbms->wr_total_written += nwritten;
4423 if(wbms->wr_total_written >= tcount)
4427 outsize = set_message(outbuf,1,0,True);
4428 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4429 send_response = True;
4433 fsp->wbmpx_ptr = NULL;
4443 /****************************************************************************
4444 reply to a SMBsetattrE
4445 ****************************************************************************/
4447 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4449 struct utimbuf unix_times;
4451 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4453 outsize = set_message(outbuf,0,0,True);
4455 CHECK_FSP(fsp,conn);
4458 /* Convert the DOS times into unix times. Ignore create
4459 time as UNIX can't set this.
4461 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4462 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4465 * Patch from Ray Frush <frush@engr.colostate.edu>
4466 * Sometimes times are sent as zero - ignore them.
4469 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4471 /* Ignore request */
4474 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4475 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4479 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4481 /* set modify time = to access time if modify time was 0 */
4482 unix_times.modtime = unix_times.actime;
4485 /* Set the date on this file */
4486 if(file_utime(conn, fsp->fsp_name, &unix_times))
4487 return(ERROR(ERRDOS,ERRnoaccess));
4489 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4490 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4496 /****************************************************************************
4497 reply to a SMBgetattrE
4498 ****************************************************************************/
4500 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4502 SMB_STRUCT_STAT sbuf;
4505 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4507 outsize = set_message(outbuf,11,0,True);
4509 CHECK_FSP(fsp,conn);
4512 /* Do an fstat on this file */
4513 if(fsp->conn->vfs_ops.fstat(fsp->fd, &sbuf))
4514 return(UNIXERROR(ERRDOS,ERRnoaccess));
4516 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4518 /* Convert the times into dos times. Set create
4519 date to be last modify date as UNIX doesn't save
4521 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4522 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4523 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4526 SIVAL(outbuf,smb_vwv6,0);
4527 SIVAL(outbuf,smb_vwv8,0);
4531 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4532 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4534 SSVAL(outbuf,smb_vwv10, mode);
4536 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));