3 Unix SMB/Netbios implementation.
5 Main SMB reply routines
6 Copyright (C) Andrew Tridgell 1992-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
30 /* look in server.c for some explanation of these variables */
32 extern int DEBUGLEVEL;
35 extern char magic_char;
36 extern BOOL case_sensitive;
37 extern BOOL case_preserve;
38 extern BOOL short_case_preserve;
39 extern pstring sesssetup_user;
40 extern pstring global_myname;
41 extern fstring global_myworkgroup;
42 extern int global_oplock_break;
43 uint32 global_client_caps = 0;
44 unsigned int smb_echo_count = 0;
46 /****************************************************************************
47 report a possible attack via the password buffer overflow bug
48 ****************************************************************************/
50 static void overflow_attack(int len)
53 dbgtext( "ERROR: Invalid password length %d.\n", len );
54 dbgtext( "Your machine may be under attack by someone " );
55 dbgtext( "attempting to exploit an old bug.\n" );
56 dbgtext( "Attack was from IP = %s.\n", client_addr() );
58 exit_server("possible attack");
62 /****************************************************************************
63 reply to an special message
64 ****************************************************************************/
66 int reply_special(char *inbuf,char *outbuf)
69 int msg_type = CVAL(inbuf,0);
70 int msg_flags = CVAL(inbuf,1);
72 extern fstring remote_machine;
73 extern fstring local_machine;
79 memset(outbuf,'\0',smb_size);
84 case 0x81: /* session request */
85 CVAL(outbuf,0) = 0x82;
87 if (name_len(inbuf+4) > 50 ||
88 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
89 DEBUG(0,("Invalid name length in session request\n"));
92 name_extract(inbuf,4,name1);
93 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
94 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
97 fstrcpy(remote_machine,name2);
98 remote_machine[15] = 0;
99 trim_string(remote_machine," "," ");
100 strlower(remote_machine);
102 fstrcpy(local_machine,name1);
103 len = strlen(local_machine);
105 name_type = local_machine[15];
106 local_machine[15] = 0;
108 trim_string(local_machine," "," ");
109 strlower(local_machine);
111 if (name_type == 'R') {
112 /* We are being asked for a pathworks session ---
114 CVAL(outbuf, 0) = 0x83;
118 add_session_user(remote_machine);
120 reload_services(True);
124 claim_connection(NULL,"",MAXSTATUS,True);
129 case 0x89: /* session keepalive request
130 (some old clients produce this?) */
131 CVAL(outbuf,0) = 0x85;
135 case 0x82: /* positive session response */
136 case 0x83: /* negative session response */
137 case 0x84: /* retarget session response */
138 DEBUG(0,("Unexpected session response\n"));
141 case 0x85: /* session keepalive */
146 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
147 msg_type, msg_flags));
153 /*******************************************************************
154 work out what error to give to a failed connection
155 ********************************************************************/
157 static int connection_error(char *inbuf,char *outbuf,int ecode)
159 if (ecode == ERRnoipc)
160 return(ERROR(ERRDOS,ERRnoipc));
162 return(ERROR(ERRSRV,ecode));
167 /****************************************************************************
168 parse a share descriptor string
169 ****************************************************************************/
170 static void parse_connect(char *p,char *service,char *user,
171 char *password,int *pwlen,char *dev)
175 DEBUG(4,("parsing connect string %s\n",p));
177 p2 = strrchr(p,'\\');
181 fstrcpy(service,p2+1);
186 *pwlen = strlen(password);
193 p = strchr(service,'%');
201 /****************************************************************************
203 ****************************************************************************/
205 int reply_tcon(connection_struct *conn,
206 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
208 BOOL doencrypt = SMBENCRYPT();
214 uint16 vuid = SVAL(inbuf,smb_uid);
218 *service = *user = *password = *dev = 0;
220 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
223 * Ensure the user and password names are in UNIX codepage format.
226 dos_to_unix(user,True);
228 dos_to_unix(password,True);
231 * Pass the user through the NT -> unix user mapping
235 (void)map_username(user);
238 * Do any UNIX username case mangling.
240 (void)Get_Pwnam( user, True);
242 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
245 return(connection_error(inbuf,outbuf,ecode));
248 outsize = set_message(outbuf,2,0,True);
249 SSVAL(outbuf,smb_vwv0,max_recv);
250 SSVAL(outbuf,smb_vwv1,conn->cnum);
251 SSVAL(outbuf,smb_tid,conn->cnum);
253 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
254 service, user, conn->cnum));
259 /****************************************************************************
260 Reply to a tcon and X.
261 ****************************************************************************/
262 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
268 BOOL doencrypt = SMBENCRYPT();
270 uint16 vuid = SVAL(inbuf,smb_uid);
271 int passlen = SVAL(inbuf,smb_vwv3);
275 *service = *user = *password = *devicename = 0;
277 /* we might have to close an old one */
278 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
279 close_cnum(conn,vuid);
282 if (passlen > MAX_PASS_LEN) {
283 overflow_attack(passlen);
286 memcpy(password,smb_buf(inbuf),passlen);
288 path = smb_buf(inbuf) + passlen;
291 if (strequal(password," "))
293 passlen = strlen(password);
296 p = strchr(path+2,'\\');
298 return(ERROR(ERRSRV,ERRinvnetname));
299 fstrcpy(service,p+1);
300 p = strchr(service,'%');
305 StrnCpy(devicename,path + strlen(path) + 1,6);
306 DEBUG(4,("Got device type %s\n",devicename));
309 * Ensure the user and password names are in UNIX codepage format.
312 dos_to_unix(user,True);
314 dos_to_unix(password,True);
317 * Pass the user through the NT -> unix user mapping
321 (void)map_username(user);
324 * Do any UNIX username case mangling.
326 (void)Get_Pwnam(user, True);
328 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
331 return(connection_error(inbuf,outbuf,ecode));
333 if (Protocol < PROTOCOL_NT1) {
334 set_message(outbuf,2,strlen(devicename)+1,True);
335 pstrcpy(smb_buf(outbuf),devicename);
337 char *fsname = lp_fstype(SNUM(conn));
339 set_message(outbuf,3,3,True);
342 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
343 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
345 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
347 /* what does setting this bit do? It is set by NT4 and
348 may affect the ability to autorun mounted cdroms */
349 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
351 init_dfsroot(conn, inbuf, outbuf);
355 DEBUG(3,("tconX service=%s user=%s\n",
358 /* set the incoming and outgoing tid to the just created one */
359 SSVAL(inbuf,smb_tid,conn->cnum);
360 SSVAL(outbuf,smb_tid,conn->cnum);
362 return chain_reply(inbuf,outbuf,length,bufsize);
366 /****************************************************************************
367 reply to an unknown type
368 ****************************************************************************/
369 int reply_unknown(char *inbuf,char *outbuf)
372 type = CVAL(inbuf,smb_com);
374 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
375 smb_fn_name(type), type, type));
377 return(ERROR(ERRSRV,ERRunknownsmb));
381 /****************************************************************************
383 ****************************************************************************/
384 int reply_ioctl(connection_struct *conn,
385 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
387 uint16 device = SVAL(inbuf,smb_vwv1);
388 uint16 function = SVAL(inbuf,smb_vwv2);
389 uint32 ioctl_code = (device << 16) + function;
390 int replysize, outsize;
392 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
394 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
398 case IOCTL_QUERY_JOB_INFO:
402 return(ERROR(ERRSRV,ERRnosupport));
405 outsize = set_message(outbuf,8,replysize+1,True);
406 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
407 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
408 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
409 p = smb_buf(outbuf) + 1; /* Allow for alignment */
413 case IOCTL_QUERY_JOB_INFO:
414 SSVAL(p,0,fsp->print_jobid); /* Job number */
415 StrnCpy(p+2, global_myname, 15); /* Our NetBIOS name */
416 StrnCpy(p+18, lp_servicename(SNUM(conn)), 13); /* Service name */
423 /****************************************************************************
424 always return an error: it's just a matter of which one...
425 ****************************************************************************/
426 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
427 char *smb_passwd, int smb_passlen,
428 char *smb_nt_passwd, int smb_nt_passlen)
430 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
431 if (lp_security() == SEC_USER)
433 smb_trust_acct = getsmbpwnam(user);
437 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
438 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
439 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
442 if (smb_trust_acct == NULL)
444 /* lkclXXXX: workstation entry doesn't exist */
445 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
446 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
447 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
451 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
453 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
454 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
455 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
458 if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
460 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
461 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
462 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
465 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
467 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
468 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
469 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
472 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
474 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
475 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
476 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
479 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
481 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
482 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
483 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
487 /* don't know what to do: indicate logon failure */
488 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
489 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
492 /****************************************************************************
493 Create a UNIX user on demand.
494 ****************************************************************************/
496 static int smb_create_user(char *unix_user)
501 pstrcpy(add_script, lp_adduser_script());
502 if (! *add_script) return -1;
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 if (! *del_script) return -1;
520 pstring_sub(del_script, "%u", unix_user);
521 ret = smbrun(del_script,NULL,False);
522 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
526 /****************************************************************************
527 Check user is in correct domain if required
528 ****************************************************************************/
530 static BOOL check_domain_match(char *user, char *domain)
533 * If we aren't serving to trusted domains, we must make sure that
534 * the validation request comes from an account in the same domain
535 * as the Samba server
538 if (!lp_allow_trusted_domains() &&
539 !strequal(lp_workgroup(), domain) ) {
540 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
547 /****************************************************************************
548 Check for a valid username and password in security=server mode.
549 ****************************************************************************/
551 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
552 char *smb_apasswd, int smb_apasslen,
553 char *smb_ntpasswd, int smb_ntpasslen)
557 if(lp_security() != SEC_SERVER)
560 if (!check_domain_match(orig_user, domain))
563 ret = server_validate(orig_user, domain,
564 smb_apasswd, smb_apasslen,
565 smb_ntpasswd, smb_ntpasslen);
568 * User validated ok against Domain controller.
569 * If the admin wants us to try and create a UNIX
570 * user on the fly, do so.
571 * Note that we can never delete users when in server
572 * level security as we never know if it was a failure
573 * due to a bad password, or the user really doesn't exist.
575 if(lp_adduser_script() && !smb_getpwnam(unix_user,True)) {
576 smb_create_user(unix_user);
583 /****************************************************************************
584 Check for a valid username and password in security=domain mode.
585 ****************************************************************************/
587 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
588 char *smb_apasswd, int smb_apasslen,
589 char *smb_ntpasswd, int smb_ntpasslen)
592 BOOL user_exists = True;
594 if(lp_security() != SEC_DOMAIN)
597 if (!check_domain_match(orig_user, domain))
600 ret = domain_client_validate(orig_user, domain,
601 smb_apasswd, smb_apasslen,
602 smb_ntpasswd, smb_ntpasslen,
607 * User validated ok against Domain controller.
608 * If the admin wants us to try and create a UNIX
609 * user on the fly, do so.
611 if(user_exists && lp_adduser_script() && !smb_getpwnam(unix_user,True)) {
612 smb_create_user(unix_user);
616 * User failed to validate ok against Domain controller.
617 * If the failure was "user doesn't exist" and admin
618 * wants us to try and delete that UNIX user on the fly,
621 if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) {
622 smb_delete_user(unix_user);
629 /****************************************************************************
630 Return a bad password error configured for the correct client type.
631 ****************************************************************************/
633 static int bad_password_error(char *inbuf,char *outbuf)
635 enum remote_arch_types ra_type = get_remote_arch();
637 if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
638 (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
639 SSVAL(outbuf,smb_flg2,FLAGS2_32_BIT_ERROR_CODES);
640 return(ERROR(0,0xc0000000|NT_STATUS_LOGON_FAILURE));
643 return(ERROR(ERRSRV,ERRbadpw));
646 /****************************************************************************
647 reply to a session setup command
648 ****************************************************************************/
650 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
656 int smb_apasslen = 0;
658 int smb_ntpasslen = 0;
659 pstring smb_ntpasswd;
660 BOOL valid_nt_password = False;
664 static BOOL done_sesssetup = False;
665 BOOL doencrypt = SMBENCRYPT();
671 smb_bufsize = SVAL(inbuf,smb_vwv2);
673 if (Protocol < PROTOCOL_NT1) {
674 smb_apasslen = SVAL(inbuf,smb_vwv7);
675 if (smb_apasslen > MAX_PASS_LEN)
676 overflow_attack(smb_apasslen);
678 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
679 smb_apasswd[smb_apasslen] = 0;
680 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
682 * Incoming user is in DOS codepage format. Convert
685 dos_to_unix(user,True);
687 if (!doencrypt && (lp_security() != SEC_SERVER)) {
688 smb_apasslen = strlen(smb_apasswd);
691 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
692 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
693 enum remote_arch_types ra_type = get_remote_arch();
694 char *p = smb_buf(inbuf);
696 if(global_client_caps == 0)
697 global_client_caps = IVAL(inbuf,smb_vwv11);
699 /* client_caps is used as final determination if client is NT or Win95.
700 This is needed to return the correct error codes in some
704 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
705 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
706 set_remote_arch( RA_WIN95);
710 if (passlen1 != 24 && passlen2 != 24)
713 if (passlen1 > MAX_PASS_LEN) {
714 overflow_attack(passlen1);
717 passlen1 = MIN(passlen1, MAX_PASS_LEN);
718 passlen2 = MIN(passlen2, MAX_PASS_LEN);
721 /* both Win95 and WinNT stuff up the password lengths for
722 non-encrypting systems. Uggh.
724 if passlen1==24 its a win95 system, and its setting the
725 password length incorrectly. Luckily it still works with the
726 default code because Win95 will null terminate the password
729 if passlen1>0 and passlen2>0 then maybe its a NT box and its
730 setting passlen2 to some random value which really stuffs
731 things up. we need to fix that one. */
733 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
737 if (lp_restrict_anonymous()) {
738 /* there seems to be no reason behind the differences in MS clients formatting
739 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
740 * in particular seems to have an extra null byte between the username and the
741 * domain, or the password length calculation is wrong, which throws off the
742 * string extraction routines below. This makes the value of domain be the
743 * empty string, which fails the restrict anonymous check further down.
744 * This compensates for that, and allows browsing to work in mixed NT and
745 * win95 environments even when restrict anonymous is true. AAB
747 dump_data(100, p, 0x70);
748 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
749 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
750 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
751 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
752 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
757 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
758 /* Save the lanman2 password and the NT md4 password. */
759 smb_apasslen = passlen1;
760 memcpy(smb_apasswd,p,smb_apasslen);
761 smb_apasswd[smb_apasslen] = 0;
762 smb_ntpasslen = passlen2;
763 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
764 smb_ntpasswd[smb_ntpasslen] = 0;
767 * Ensure the plaintext passwords are in UNIX format.
770 dos_to_unix(smb_apasswd,True);
771 dos_to_unix(smb_ntpasswd,True);
775 /* we use the first password that they gave */
776 smb_apasslen = passlen1;
777 StrnCpy(smb_apasswd,p,smb_apasslen);
779 * Ensure the plaintext password is in UNIX format.
781 dos_to_unix(smb_apasswd,True);
783 /* trim the password */
784 smb_apasslen = strlen(smb_apasswd);
786 /* wfwg sometimes uses a space instead of a null */
787 if (strequal(smb_apasswd," ")) {
793 p += passlen1 + passlen2;
795 p = skip_string(p,1);
797 * Incoming user is in DOS codepage format. Convert
800 dos_to_unix(user,True);
803 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
804 domain,skip_string(p,1),skip_string(p,2)));
808 DEBUG(3,("sesssetupX:name=[%s]\n",user));
810 /* If name ends in $ then I think it's asking about whether a */
811 /* computer with that name (minus the $) has access. For now */
812 /* say yes to everything ending in $. */
814 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
815 return session_trust_account(conn, inbuf, outbuf, user,
816 smb_apasswd, smb_apasslen,
817 smb_ntpasswd, smb_ntpasslen);
820 if (done_sesssetup && lp_restrict_anonymous()) {
821 /* tests show that even if browsing is done over already validated connections
822 * without a username and password the domain is still provided, which it
823 * wouldn't be if it was a purely anonymous connection. So, in order to
824 * restrict anonymous, we only deny connections that have no session
825 * information. If a domain has been provided, then it's not a purely
826 * anonymous connection. AAB
828 if (!*user && !*smb_apasswd && !*domain) {
829 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
830 return(ERROR(ERRDOS,ERRnoaccess));
834 /* If no username is sent use the guest account */
836 pstrcpy(user,lp_guestaccount(-1));
837 /* If no user and no password then set guest flag. */
838 if( *smb_apasswd == 0)
844 pstrcpy(sesssetup_user,user);
846 reload_services(True);
849 * Save the username before mapping. We will use
850 * the original username sent to us for security=server
851 * and security=domain checking.
854 pstrcpy( orig_user, user);
856 /* if the username exists as a domain/username pair on the unix system then use
858 if (!Get_Pwnam(user, False)) {
860 slprintf(user2,sizeof(user2),"%s/%s", domain, user);
861 if (Get_Pwnam(user2, True)) {
862 DEBUG(3,("Using unix username %s\n", user2));
863 pstrcpy(user, user2);
868 * Pass the user through the NT -> unix user mapping
872 (void)map_username(user);
875 * Do any UNIX username case mangling.
877 smb_getpwnam(user, True);
879 add_session_user(user);
882 * Check if the given username was the guest user with no password.
885 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
889 * Check with orig_user for security=server and
894 !check_server_security(orig_user, domain, user,
895 smb_apasswd, smb_apasslen,
896 smb_ntpasswd, smb_ntpasslen) &&
897 !check_domain_security(orig_user, domain, user,
898 smb_apasswd, smb_apasslen,
899 smb_ntpasswd, smb_ntpasslen) &&
900 !check_hosts_equiv(user)
905 * If we get here then the user wasn't guest and the remote
906 * authentication methods failed. Check the authentication
907 * methods on this local server.
909 * If an NT password was supplied try and validate with that
910 * first. This is superior as the passwords are mixed case
911 * 128 length unicode.
916 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
917 DEBUG(2,("NT Password did not match for user '%s' ! Defaulting to Lanman\n", user));
919 valid_nt_password = True;
922 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL))
924 if (lp_security() >= SEC_USER)
926 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
928 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
929 return bad_password_error(inbuf,outbuf);
932 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
934 if (smb_getpwnam(user,True))
936 DEBUG(1,("Rejecting user '%s': bad password\n", user));
937 return bad_password_error(inbuf,outbuf);
942 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
943 * Then always map to guest account - as done below.
947 if (*smb_apasswd || !smb_getpwnam(user,True))
948 pstrcpy(user,lp_guestaccount(-1));
949 DEBUG(3,("Registered username %s for guest access\n",user));
954 if (!smb_getpwnam(user,True)) {
955 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
956 pstrcpy(user,lp_guestaccount(-1));
960 if (!strequal(user,lp_guestaccount(-1)) &&
961 lp_servicenumber(user) < 0)
963 int homes = lp_servicenumber(HOMES_NAME);
964 char *home = get_user_home_dir(user);
965 if (homes >= 0 && home)
966 lp_add_home(user,homes,home);
970 /* it's ok - setup a reply */
971 if (Protocol < PROTOCOL_NT1) {
972 set_message(outbuf,3,0,True);
975 set_message(outbuf,3,3,True);
977 pstrcpy(p,"Unix"); p = skip_string(p,1);
978 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
979 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
980 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
981 /* perhaps grab OS version here?? */
984 /* Set the correct uid in the outgoing and incoming packets
985 We will use this on future requests to determine which
986 user we should become.
989 const struct passwd *pw = smb_getpwnam(user,False);
991 DEBUG(1,("Username %s is invalid on this system\n",user));
992 return bad_password_error(inbuf,outbuf);
999 SSVAL(outbuf,smb_vwv2,1);
1001 /* register the name and uid as being validated, so further connections
1002 to a uid can get through without a password, on the same VC */
1003 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,domain,guest);
1005 SSVAL(outbuf,smb_uid,sess_vuid);
1006 SSVAL(inbuf,smb_uid,sess_vuid);
1008 if (!done_sesssetup)
1009 max_send = MIN(max_send,smb_bufsize);
1011 DEBUG(6,("Client requested max send size of %d\n", max_send));
1013 done_sesssetup = True;
1015 return chain_reply(inbuf,outbuf,length,bufsize);
1019 /****************************************************************************
1021 ****************************************************************************/
1022 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1028 BOOL bad_path = False;
1031 pstrcpy(name,smb_buf(inbuf) + 1);
1033 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1035 unix_convert(name,conn,0,&bad_path,&st);
1037 mode = SVAL(inbuf,smb_vwv0);
1039 if (check_name(name,conn)) {
1041 ok = S_ISDIR(st.st_mode);
1043 ok = vfs_directory_exist(conn,name,NULL);
1048 /* We special case this - as when a Windows machine
1049 is parsing a path is steps through the components
1050 one at a time - if a component fails it expects
1051 ERRbadpath, not ERRbadfile.
1055 unix_ERR_class = ERRDOS;
1056 unix_ERR_code = ERRbadpath;
1060 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1061 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1062 (get_remote_arch() == RA_WINNT))
1064 unix_ERR_class = ERRDOS;
1065 unix_ERR_code = ERRbaddirectory;
1069 return(UNIXERROR(ERRDOS,ERRbadpath));
1072 outsize = set_message(outbuf,0,0,True);
1074 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1080 /****************************************************************************
1082 ****************************************************************************/
1083 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1087 SMB_STRUCT_STAT sbuf;
1092 BOOL bad_path = False;
1094 pstrcpy(fname,smb_buf(inbuf) + 1);
1096 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1098 /* if((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && dfs_redirect(fname,conn)) return(dfs_path_error(inbuf,outbuf));
1100 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1101 under WfWg - weird! */
1104 mode = aHIDDEN | aDIR;
1105 if (!CAN_WRITE(conn)) mode |= aRONLY;
1112 unix_convert(fname,conn,0,&bad_path,&sbuf);
1113 if (check_name(fname,conn))
1115 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
1117 mode = dos_mode(conn,fname,&sbuf);
1118 size = sbuf.st_size;
1119 mtime = sbuf.st_mtime;
1125 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1131 if((errno == ENOENT) && bad_path)
1133 unix_ERR_class = ERRDOS;
1134 unix_ERR_code = ERRbadpath;
1137 return(UNIXERROR(ERRDOS,ERRbadfile));
1140 outsize = set_message(outbuf,10,0,True);
1142 SSVAL(outbuf,smb_vwv0,mode);
1143 if(lp_dos_filetime_resolution(SNUM(conn)) )
1144 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1146 put_dos_date3(outbuf,smb_vwv1,mtime);
1147 SIVAL(outbuf,smb_vwv3,(uint32)size);
1149 if (Protocol >= PROTOCOL_NT1) {
1150 char *p = strrchr(fname,'/');
1151 uint16 flg2 = SVAL(outbuf,smb_flg2);
1153 if (!is_8_3(fname, True))
1154 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1157 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1163 /****************************************************************************
1165 ****************************************************************************/
1166 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1174 BOOL bad_path = False;
1176 pstrcpy(fname,smb_buf(inbuf) + 1);
1177 unix_convert(fname,conn,0,&bad_path,&st);
1179 mode = SVAL(inbuf,smb_vwv0);
1180 mtime = make_unix_date3(inbuf+smb_vwv1);
1182 if (VALID_STAT_OF_DIR(st) || vfs_directory_exist(conn, fname, NULL))
1184 if (check_name(fname,conn))
1185 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1187 ok = set_filetime(conn,fname,mtime);
1191 if((errno == ENOENT) && bad_path)
1193 unix_ERR_class = ERRDOS;
1194 unix_ERR_code = ERRbadpath;
1197 return(UNIXERROR(ERRDOS,ERRnoaccess));
1200 outsize = set_message(outbuf,0,0,True);
1202 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1208 /****************************************************************************
1210 ****************************************************************************/
1211 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1214 SMB_BIG_UINT dfree,dsize,bsize;
1216 conn->vfs_ops.disk_free(".",True,&bsize,&dfree,&dsize);
1218 outsize = set_message(outbuf,5,0,True);
1220 SSVAL(outbuf,smb_vwv0,dsize);
1221 SSVAL(outbuf,smb_vwv1,bsize/512);
1222 SSVAL(outbuf,smb_vwv2,512);
1223 SSVAL(outbuf,smb_vwv3,dfree);
1225 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1231 /****************************************************************************
1233 Can be called from SMBsearch, SMBffirst or SMBfunique.
1234 ****************************************************************************/
1235 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1246 BOOL finished = False;
1255 BOOL check_descend = False;
1256 BOOL expect_close = False;
1257 BOOL can_open = True;
1258 BOOL bad_path = False;
1260 *mask = *directory = *fname = 0;
1262 /* If we were called as SMBffirst then we must expect close. */
1263 if(CVAL(inbuf,smb_com) == SMBffirst)
1264 expect_close = True;
1266 outsize = set_message(outbuf,1,3,True);
1267 maxentries = SVAL(inbuf,smb_vwv0);
1268 dirtype = SVAL(inbuf,smb_vwv1);
1269 path = smb_buf(inbuf) + 1;
1270 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1273 /* dirtype &= ~aDIR; */
1275 if (status_len == 0)
1279 pstrcpy(directory,smb_buf(inbuf)+1);
1280 pstrcpy(dir2,smb_buf(inbuf)+1);
1281 unix_convert(directory,conn,0,&bad_path,NULL);
1284 if (!check_name(directory,conn))
1287 p = strrchr(dir2,'/');
1299 p = strrchr(directory,'/');
1305 if (strlen(directory) == 0)
1306 pstrcpy(directory,"./");
1307 memset((char *)status,'\0',21);
1308 CVAL(status,0) = dirtype;
1312 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
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 fstrcpy(mask, dptr_wcard(dptr_num));
1323 p = smb_buf(outbuf) + 3;
1327 if (status_len == 0)
1329 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1334 if((errno == ENOENT) && bad_path)
1336 unix_ERR_class = ERRDOS;
1337 unix_ERR_code = ERRbadpath;
1339 return (UNIXERROR(ERRDOS,ERRnofids));
1341 return(ERROR(ERRDOS,ERRnofids));
1343 dptr_set_wcard(dptr_num, strdup(mask));
1346 DEBUG(4,("dptr_num is %d\n",dptr_num));
1350 if ((dirtype&0x1F) == aVOLID)
1352 memcpy(p,status,21);
1353 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1354 dptr_fill(p+12,dptr_num);
1355 if (dptr_zero(p+12) && (status_len==0))
1359 p += DIR_STRUCT_SIZE;
1363 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1364 conn->dirpath,lp_dontdescend(SNUM(conn))));
1365 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1366 check_descend = True;
1368 for (i=numentries;(i<maxentries) && !finished;i++)
1371 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1374 memcpy(p,status,21);
1375 make_dir_struct(p,mask,fname,size,mode,date);
1376 dptr_fill(p+12,dptr_num);
1379 p += DIR_STRUCT_SIZE;
1388 if (numentries == 0 || !ok)
1390 CVAL(outbuf,smb_rcls) = ERRDOS;
1391 SSVAL(outbuf,smb_err,ERRnofiles);
1392 dptr_close(&dptr_num);
1395 /* If we were called as SMBffirst with smb_search_id == NULL
1396 and no entries were found then return error and close dirptr
1399 if(ok && expect_close && numentries == 0 && status_len == 0)
1401 CVAL(outbuf,smb_rcls) = ERRDOS;
1402 SSVAL(outbuf,smb_err,ERRnofiles);
1403 /* Also close the dptr - we know it's gone */
1404 dptr_close(&dptr_num);
1407 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1408 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1409 dptr_close(&dptr_num);
1411 SSVAL(outbuf,smb_vwv0,numentries);
1412 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1413 CVAL(smb_buf(outbuf),0) = 5;
1414 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1416 if (Protocol >= PROTOCOL_NT1) {
1417 uint16 flg2 = SVAL(outbuf,smb_flg2);
1418 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1421 outsize += DIR_STRUCT_SIZE*numentries;
1422 smb_setlen(outbuf,outsize - 4);
1424 if ((! *directory) && dptr_path(dptr_num))
1425 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1427 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1428 smb_fn_name(CVAL(inbuf,smb_com)),
1429 mask, directory, dirtype, numentries, maxentries ) );
1435 /****************************************************************************
1436 reply to a fclose (stop directory search)
1437 ****************************************************************************/
1438 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1446 outsize = set_message(outbuf,1,0,True);
1447 path = smb_buf(inbuf) + 1;
1448 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1451 if (status_len == 0)
1452 return(ERROR(ERRSRV,ERRsrverror));
1454 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1456 if(dptr_fetch(status+12,&dptr_num)) {
1457 /* Close the dptr - we know it's gone */
1458 dptr_close(&dptr_num);
1461 SSVAL(outbuf,smb_vwv0,0);
1463 DEBUG(3,("search close\n"));
1469 /****************************************************************************
1471 ****************************************************************************/
1473 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1483 SMB_STRUCT_STAT sbuf;
1484 BOOL bad_path = False;
1486 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1488 share_mode = SVAL(inbuf,smb_vwv0);
1490 pstrcpy(fname,smb_buf(inbuf)+1);
1492 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1494 unix_convert(fname,conn,0,&bad_path,NULL);
1496 unixmode = unix_mode(conn,aARCH,fname);
1498 fsp = open_file_shared(conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1499 unixmode, oplock_request,&rmode,NULL);
1503 if((errno == ENOENT) && bad_path)
1505 unix_ERR_class = ERRDOS;
1506 unix_ERR_code = ERRbadpath;
1508 return(UNIXERROR(ERRDOS,ERRnoaccess));
1511 if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) {
1512 close_file(fsp,False);
1513 return(ERROR(ERRDOS,ERRnoaccess));
1516 size = sbuf.st_size;
1517 fmode = dos_mode(conn,fname,&sbuf);
1518 mtime = sbuf.st_mtime;
1521 DEBUG(3,("attempt to open a directory %s\n",fname));
1522 close_file(fsp,False);
1523 return(ERROR(ERRDOS,ERRnoaccess));
1526 outsize = set_message(outbuf,7,0,True);
1527 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1528 SSVAL(outbuf,smb_vwv1,fmode);
1529 if(lp_dos_filetime_resolution(SNUM(conn)) )
1530 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1532 put_dos_date3(outbuf,smb_vwv2,mtime);
1533 SIVAL(outbuf,smb_vwv4,(uint32)size);
1534 SSVAL(outbuf,smb_vwv6,rmode);
1536 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1537 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1540 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1541 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1546 /****************************************************************************
1547 reply to an open and X
1548 ****************************************************************************/
1549 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1552 int smb_mode = SVAL(inbuf,smb_vwv3);
1553 int smb_attr = SVAL(inbuf,smb_vwv5);
1554 /* Breakout the oplock request bits so we can set the
1555 reply bits separately. */
1556 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1557 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1558 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1560 int open_flags = SVAL(inbuf,smb_vwv2);
1561 int smb_sattr = SVAL(inbuf,smb_vwv4);
1562 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1564 int smb_ofun = SVAL(inbuf,smb_vwv8);
1567 int fmode=0,mtime=0,rmode=0;
1568 SMB_STRUCT_STAT sbuf;
1570 BOOL bad_path = False;
1573 /* If it's an IPC, pass off the pipe handler. */
1574 if (IS_IPC(conn) && lp_nt_pipe_support())
1575 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1577 /* XXXX we need to handle passed times, sattr and flags */
1579 pstrcpy(fname,smb_buf(inbuf));
1581 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1583 unix_convert(fname,conn,0,&bad_path,NULL);
1585 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1587 fsp = open_file_shared(conn,fname,smb_mode,smb_ofun,unixmode,
1588 oplock_request, &rmode,&smb_action);
1592 if((errno == ENOENT) && bad_path)
1594 unix_ERR_class = ERRDOS;
1595 unix_ERR_code = ERRbadpath;
1597 return(UNIXERROR(ERRDOS,ERRnoaccess));
1600 if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) {
1601 close_file(fsp,False);
1602 return(ERROR(ERRDOS,ERRnoaccess));
1605 size = sbuf.st_size;
1606 fmode = dos_mode(conn,fname,&sbuf);
1607 mtime = sbuf.st_mtime;
1609 close_file(fsp,False);
1610 return(ERROR(ERRDOS,ERRnoaccess));
1613 /* If the caller set the extended oplock request bit
1614 and we granted one (by whatever means) - set the
1615 correct bit for extended oplock reply.
1618 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1619 smb_action |= EXTENDED_OPLOCK_GRANTED;
1622 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1623 smb_action |= EXTENDED_OPLOCK_GRANTED;
1626 /* If the caller set the core oplock request bit
1627 and we granted one (by whatever means) - set the
1628 correct bit for core oplock reply.
1631 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1632 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1635 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1636 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1639 set_message(outbuf,15,0,True);
1640 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1641 SSVAL(outbuf,smb_vwv3,fmode);
1642 if(lp_dos_filetime_resolution(SNUM(conn)) )
1643 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1645 put_dos_date3(outbuf,smb_vwv4,mtime);
1646 SIVAL(outbuf,smb_vwv6,(uint32)size);
1647 SSVAL(outbuf,smb_vwv8,rmode);
1648 SSVAL(outbuf,smb_vwv11,smb_action);
1650 return chain_reply(inbuf,outbuf,length,bufsize);
1654 /****************************************************************************
1655 reply to a SMBulogoffX
1656 ****************************************************************************/
1657 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1659 uint16 vuid = SVAL(inbuf,smb_uid);
1660 user_struct *vuser = get_valid_user_struct(vuid);
1663 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1666 /* in user level security we are supposed to close any files
1667 open by this user */
1668 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1669 file_close_user(vuid);
1672 invalidate_vuid(vuid);
1674 set_message(outbuf,2,0,True);
1676 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1678 return chain_reply(inbuf,outbuf,length,bufsize);
1682 /****************************************************************************
1683 reply to a mknew or a create
1684 ****************************************************************************/
1685 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1693 BOOL bad_path = False;
1695 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1697 com = SVAL(inbuf,smb_com);
1699 createmode = SVAL(inbuf,smb_vwv0);
1700 pstrcpy(fname,smb_buf(inbuf)+1);
1702 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1704 unix_convert(fname,conn,0,&bad_path,NULL);
1706 if (createmode & aVOLID)
1708 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1711 unixmode = unix_mode(conn,createmode,fname);
1715 /* We should fail if file exists. */
1716 ofun = FILE_CREATE_IF_NOT_EXIST;
1720 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1721 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1724 /* Open file in dos compatibility share mode. */
1725 fsp = open_file_shared(conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1726 ofun, unixmode, oplock_request, NULL, NULL);
1730 if((errno == ENOENT) && bad_path)
1732 unix_ERR_class = ERRDOS;
1733 unix_ERR_code = ERRbadpath;
1735 return(UNIXERROR(ERRDOS,ERRnoaccess));
1738 outsize = set_message(outbuf,1,0,True);
1739 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1741 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1742 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1745 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1746 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1748 DEBUG( 2, ( "new file %s\n", fname ) );
1749 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1750 fname, fsp->fd, createmode, (int)unixmode ) );
1756 /****************************************************************************
1757 reply to a create temporary file
1758 ****************************************************************************/
1759 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1766 BOOL bad_path = False;
1768 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1770 createmode = SVAL(inbuf,smb_vwv0);
1771 pstrcpy(fname,smb_buf(inbuf)+1);
1772 pstrcat(fname,"/TMXXXXXX");
1774 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1776 unix_convert(fname,conn,0,&bad_path,NULL);
1778 unixmode = unix_mode(conn,createmode,fname);
1780 pstrcpy(fname2,(char *)smbd_mktemp(fname));
1782 /* Open file in dos compatibility share mode. */
1783 /* We should fail if file exists. */
1784 fsp = open_file_shared(conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1785 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1789 if((errno == ENOENT) && bad_path)
1791 unix_ERR_class = ERRDOS;
1792 unix_ERR_code = ERRbadpath;
1794 return(UNIXERROR(ERRDOS,ERRnoaccess));
1797 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1798 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1799 CVAL(smb_buf(outbuf),0) = 4;
1800 pstrcpy(smb_buf(outbuf) + 1,fname2);
1802 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1803 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1806 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1807 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1809 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1810 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1811 fname2, fsp->fd, createmode, (int)unixmode ) );
1817 /*******************************************************************
1818 check if a user is allowed to delete a file
1819 ********************************************************************/
1820 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1822 SMB_STRUCT_STAT sbuf;
1825 if (!CAN_WRITE(conn)) return(False);
1827 if (conn->vfs_ops.lstat(dos_to_unix(fname,False),&sbuf) != 0) return(False);
1828 fmode = dos_mode(conn,fname,&sbuf);
1829 if (fmode & aDIR) return(False);
1830 if (!lp_delete_readonly(SNUM(conn))) {
1831 if (fmode & aRONLY) return(False);
1833 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1835 if (!check_file_sharing(conn,fname,False)) return(False);
1839 /****************************************************************************
1841 ****************************************************************************/
1843 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1852 int error = ERRnoaccess;
1855 BOOL bad_path = False;
1858 *directory = *mask = 0;
1860 dirtype = SVAL(inbuf,smb_vwv0);
1862 pstrcpy(name,smb_buf(inbuf) + 1);
1864 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1866 DEBUG(3,("reply_unlink : %s\n",name));
1868 rc = unix_convert(name,conn,0,&bad_path,NULL);
1870 p = strrchr(name,'/');
1872 pstrcpy(directory,"./");
1876 pstrcpy(directory,name);
1881 * We should only check the mangled cache
1882 * here if unix_convert failed. This means
1883 * that the path in 'mask' doesn't exist
1884 * on the file system and so we need to look
1885 * for a possible mangle. This patch from
1886 * Tine Smukavec <valentin.smukavec@hermes.si>.
1889 if (!rc && is_mangled(mask))
1890 check_mangled_cache( mask );
1892 has_wild = ms_has_wild(mask);
1895 pstrcat(directory,"/");
1896 pstrcat(directory,mask);
1897 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
1900 exists = vfs_file_exist(conn,directory,NULL);
1902 void *dirptr = NULL;
1905 if (check_name(directory,conn))
1906 dirptr = OpenDir(conn, directory, True);
1908 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1909 the pattern matches against the long name, otherwise the short name
1910 We don't implement this yet XXXX
1917 if (strequal(mask,"????????.???"))
1920 while ((dname = ReadDirName(dirptr)))
1923 pstrcpy(fname,dname);
1925 if(!mask_match(fname, mask, case_sensitive)) continue;
1927 error = ERRnoaccess;
1928 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1929 if (!can_delete(fname,conn,dirtype)) continue;
1930 if (!conn->vfs_ops.unlink(dos_to_unix(fname,False))) count++;
1931 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1939 return(ERROR(ERRDOS,error));
1942 if((errno == ENOENT) && bad_path)
1944 unix_ERR_class = ERRDOS;
1945 unix_ERR_code = ERRbadpath;
1947 return(UNIXERROR(ERRDOS,error));
1951 outsize = set_message(outbuf,0,0,True);
1957 /****************************************************************************
1958 reply to a readbraw (core+ protocol)
1959 ****************************************************************************/
1961 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1963 size_t maxcount,mincount;
1966 char *header = outbuf;
1971 * Special check if an oplock break has been issued
1972 * and the readraw request croses on the wire, we must
1973 * return a zero length response here.
1976 if(global_oplock_break)
1978 _smb_setlen(header,0);
1979 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1980 DEBUG(5,("readbraw - oplock break finished\n"));
1984 fsp = file_fsp(inbuf,smb_vwv0);
1986 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1988 * fsp could be NULL here so use the value from the packet. JRA.
1990 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1991 _smb_setlen(header,0);
1992 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1996 CHECK_FSP(fsp,conn);
1998 flush_write_cache(fsp, READRAW_FLUSH);
2000 startpos = IVAL(inbuf,smb_vwv1);
2001 if(CVAL(inbuf,smb_wct) == 10) {
2003 * This is a large offset (64 bit) read.
2005 #ifdef LARGE_SMB_OFF_T
2007 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2009 #else /* !LARGE_SMB_OFF_T */
2012 * Ensure we haven't been sent a >32 bit offset.
2015 if(IVAL(inbuf,smb_vwv8) != 0) {
2016 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2017 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2018 _smb_setlen(header,0);
2019 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2023 #endif /* LARGE_SMB_OFF_T */
2026 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2027 (double)startpos ));
2028 _smb_setlen(header,0);
2029 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2033 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2034 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2036 /* ensure we don't overrun the packet size */
2037 maxcount = MIN(65535,maxcount);
2038 maxcount = MAX(mincount,maxcount);
2040 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK))
2042 SMB_OFF_T size = fsp->size;
2043 SMB_OFF_T sizeneeded = startpos + maxcount;
2045 if (size < sizeneeded)
2048 if (fsp->conn->vfs_ops.fstat(fsp->fd,&st) == 0)
2050 if (!fsp->can_write)
2054 nread = MIN(maxcount,(size - startpos));
2057 if (nread < mincount)
2060 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2061 fsp->fnum, (double)startpos,
2062 (int)maxcount, (int)mincount, (int)nread ) );
2066 BOOL seek_fail = False;
2068 _smb_setlen(header,nread);
2070 #if USE_READ_PREDICTION
2071 if (!fsp->can_write)
2072 predict = read_predict(fsp, fsp->fd,startpos,header+4,NULL,nread);
2073 #endif /* USE_READ_PREDICTION */
2075 if ((nread-predict) > 0) {
2076 if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) {
2077 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2084 ret = (ssize_t)vfs_transfer_file(-1, fsp->fd, Client, NULL,
2085 (SMB_OFF_T)(nread-predict),header,4+predict,
2090 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2091 fsp->fsp_name,startpos,nread,ret));
2093 #else /* UNSAFE_READRAW */
2094 ret = read_file(fsp,header+4,startpos,nread);
2095 if (ret < mincount) ret = 0;
2097 _smb_setlen(header,ret);
2098 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2099 #endif /* UNSAFE_READRAW */
2101 DEBUG(5,("readbraw finished\n"));
2106 /****************************************************************************
2107 reply to a lockread (core+ protocol)
2108 ****************************************************************************/
2109 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2118 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2120 CHECK_FSP(fsp,conn);
2124 numtoread = SVAL(inbuf,smb_vwv1);
2125 startpos = IVAL(inbuf,smb_vwv2);
2127 outsize = set_message(outbuf,5,3,True);
2128 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2129 data = smb_buf(outbuf) + 3;
2132 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2133 * protocol request that predates the read/write lock concept.
2134 * Thus instead of asking for a read lock here we need to ask
2135 * for a write lock. JRA.
2138 if(!do_lock( fsp, conn, (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2139 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2141 * A blocking lock was requested. Package up
2142 * this smb into a queued request and push it
2143 * onto the blocking lock queue.
2145 if(push_blocking_lock_request(inbuf, length, -1, 0))
2148 return (ERROR(eclass,ecode));
2151 nread = read_file(fsp,data,startpos,numtoread);
2154 return(UNIXERROR(ERRDOS,ERRnoaccess));
2157 SSVAL(outbuf,smb_vwv0,nread);
2158 SSVAL(outbuf,smb_vwv5,nread+3);
2159 SSVAL(smb_buf(outbuf),1,nread);
2161 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2162 fsp->fnum, (int)numtoread, (int)nread ) );
2168 /****************************************************************************
2170 ****************************************************************************/
2172 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2179 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2181 CHECK_FSP(fsp,conn);
2185 numtoread = SVAL(inbuf,smb_vwv1);
2186 startpos = IVAL(inbuf,smb_vwv2);
2188 outsize = set_message(outbuf,5,3,True);
2189 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2190 data = smb_buf(outbuf) + 3;
2192 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK))
2193 return(ERROR(ERRDOS,ERRlock));
2196 nread = read_file(fsp,data,startpos,numtoread);
2199 return(UNIXERROR(ERRDOS,ERRnoaccess));
2202 SSVAL(outbuf,smb_vwv0,nread);
2203 SSVAL(outbuf,smb_vwv5,nread+3);
2204 CVAL(smb_buf(outbuf),0) = 1;
2205 SSVAL(smb_buf(outbuf),1,nread);
2207 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2208 fsp->fnum, (int)numtoread, (int)nread ) );
2214 /****************************************************************************
2215 reply to a read and X
2216 ****************************************************************************/
2217 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2219 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2220 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2221 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2222 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2226 /* If it's an IPC, pass off the pipe handler. */
2228 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2230 CHECK_FSP(fsp,conn);
2234 set_message(outbuf,12,0,True);
2235 data = smb_buf(outbuf);
2237 if(CVAL(inbuf,smb_wct) == 12) {
2238 #ifdef LARGE_SMB_OFF_T
2240 * This is a large offset (64 bit) read.
2242 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2244 #else /* !LARGE_SMB_OFF_T */
2247 * Ensure we haven't been sent a >32 bit offset.
2250 if(IVAL(inbuf,smb_vwv10) != 0) {
2251 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2252 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2253 return(ERROR(ERRDOS,ERRbadaccess));
2256 #endif /* LARGE_SMB_OFF_T */
2260 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK))
2261 return(ERROR(ERRDOS,ERRlock));
2262 nread = read_file(fsp,data,startpos,smb_maxcnt);
2265 return(UNIXERROR(ERRDOS,ERRnoaccess));
2267 SSVAL(outbuf,smb_vwv5,nread);
2268 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2269 SSVAL(smb_buf(outbuf),-2,nread);
2271 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2272 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2274 return chain_reply(inbuf,outbuf,length,bufsize);
2277 /****************************************************************************
2278 reply to a writebraw (core+ or LANMAN1.0 protocol)
2279 ****************************************************************************/
2281 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2284 ssize_t total_written=0;
2285 size_t numtowrite=0;
2290 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2293 CHECK_FSP(fsp,conn);
2297 tcount = IVAL(inbuf,smb_vwv1);
2298 startpos = IVAL(inbuf,smb_vwv3);
2299 write_through = BITSETW(inbuf+smb_vwv7,0);
2301 /* We have to deal with slightly different formats depending
2302 on whether we are using the core+ or lanman1.0 protocol */
2303 if(Protocol <= PROTOCOL_COREPLUS) {
2304 numtowrite = SVAL(smb_buf(inbuf),-2);
2305 data = smb_buf(inbuf);
2307 numtowrite = SVAL(inbuf,smb_vwv10);
2308 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2311 /* force the error type */
2312 CVAL(inbuf,smb_com) = SMBwritec;
2313 CVAL(outbuf,smb_com) = SMBwritec;
2315 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK))
2316 return(ERROR(ERRDOS,ERRlock));
2319 nwritten = write_file(fsp,data,startpos,numtowrite);
2321 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2322 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2324 if (nwritten < numtowrite)
2325 return(UNIXERROR(ERRHRD,ERRdiskfull));
2327 total_written = nwritten;
2329 /* Return a message to the redirector to tell it
2330 to send more bytes */
2331 CVAL(outbuf,smb_com) = SMBwritebraw;
2332 SSVALS(outbuf,smb_vwv0,-1);
2333 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2334 send_smb(smbd_server_fd(),outbuf);
2336 /* Now read the raw data into the buffer and write it */
2337 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2338 exit_server("secondary writebraw failed");
2341 /* Even though this is not an smb message, smb_len
2342 returns the generic length of an smb message */
2343 numtowrite = smb_len(inbuf);
2345 if (tcount > nwritten+numtowrite) {
2346 DEBUG(3,("Client overestimated the write %d %d %d\n",
2347 (int)tcount,(int)nwritten,(int)numtowrite));
2350 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2351 (SMB_OFF_T)numtowrite,NULL,0,
2353 total_written += nwritten;
2355 /* Set up outbuf to return the correct return */
2356 outsize = set_message(outbuf,1,0,True);
2357 CVAL(outbuf,smb_com) = SMBwritec;
2358 SSVAL(outbuf,smb_vwv0,total_written);
2360 if (nwritten < (ssize_t)numtowrite) {
2361 CVAL(outbuf,smb_rcls) = ERRHRD;
2362 SSVAL(outbuf,smb_err,ERRdiskfull);
2365 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2366 lp_strict_sync(SNUM(conn)))
2367 sync_file(conn,fsp);
2369 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2370 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2372 /* we won't return a status if write through is not selected - this
2373 follows what WfWg does */
2374 if (!write_through && total_written==tcount)
2380 /****************************************************************************
2381 reply to a writeunlock (core+)
2382 ****************************************************************************/
2384 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2386 ssize_t nwritten = -1;
2392 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2395 CHECK_FSP(fsp,conn);
2399 numtowrite = SVAL(inbuf,smb_vwv1);
2400 startpos = IVAL(inbuf,smb_vwv2);
2401 data = smb_buf(inbuf) + 3;
2403 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK))
2404 return(ERROR(ERRDOS,ERRlock));
2406 /* The special X/Open SMB protocol handling of
2407 zero length writes is *NOT* done for
2412 nwritten = write_file(fsp,data,startpos,numtowrite);
2414 if (lp_syncalways(SNUM(conn)))
2415 sync_file(conn,fsp);
2417 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2418 return(UNIXERROR(ERRDOS,ERRnoaccess));
2420 if(!do_unlock(fsp, conn, (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode))
2421 return(ERROR(eclass,ecode));
2423 outsize = set_message(outbuf,1,0,True);
2425 SSVAL(outbuf,smb_vwv0,nwritten);
2427 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2428 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2433 /****************************************************************************
2435 ****************************************************************************/
2436 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2439 ssize_t nwritten = -1;
2442 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2445 /* If it's an IPC, pass off the pipe handler. */
2447 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2449 CHECK_FSP(fsp,conn);
2453 numtowrite = SVAL(inbuf,smb_vwv1);
2454 startpos = IVAL(inbuf,smb_vwv2);
2455 data = smb_buf(inbuf) + 3;
2457 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK))
2458 return(ERROR(ERRDOS,ERRlock));
2460 /* X/Open SMB protocol says that if smb_vwv1 is
2461 zero then the file size should be extended or
2462 truncated to the size given in smb_vwv[2-3] */
2463 if(numtowrite == 0) {
2464 if((nwritten = set_filelen(fsp->fd, (SMB_OFF_T)startpos)) >= 0) /* tpot vfs */
2465 set_filelen_write_cache(fsp, startpos);
2467 nwritten = write_file(fsp,data,startpos,numtowrite);
2469 if (lp_syncalways(SNUM(conn)))
2470 sync_file(conn,fsp);
2472 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2473 return(UNIXERROR(ERRDOS,ERRnoaccess));
2475 outsize = set_message(outbuf,1,0,True);
2477 SSVAL(outbuf,smb_vwv0,nwritten);
2479 if (nwritten < (ssize_t)numtowrite) {
2480 CVAL(outbuf,smb_rcls) = ERRHRD;
2481 SSVAL(outbuf,smb_err,ERRdiskfull);
2484 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2485 fsp->fnum, (int)numtowrite, (int)nwritten));
2491 /****************************************************************************
2492 reply to a write and X
2493 ****************************************************************************/
2494 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2496 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2497 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2498 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2499 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2500 ssize_t nwritten = -1;
2501 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2504 /* If it's an IPC, pass off the pipe handler. */
2506 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2508 CHECK_FSP(fsp,conn);
2512 if(smb_doff > smb_len(inbuf))
2513 return(ERROR(ERRDOS,ERRbadmem));
2515 data = smb_base(inbuf) + smb_doff;
2517 if(CVAL(inbuf,smb_wct) == 14) {
2518 #ifdef LARGE_SMB_OFF_T
2520 * This is a large offset (64 bit) write.
2522 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2524 #else /* !LARGE_SMB_OFF_T */
2527 * Ensure we haven't been sent a >32 bit offset.
2530 if(IVAL(inbuf,smb_vwv12) != 0) {
2531 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2532 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2533 return(ERROR(ERRDOS,ERRbadaccess));
2536 #endif /* LARGE_SMB_OFF_T */
2539 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK))
2540 return(ERROR(ERRDOS,ERRlock));
2542 /* X/Open SMB protocol says that, unlike SMBwrite
2543 if the length is zero then NO truncation is
2544 done, just a write of zero. To truncate a file,
2549 nwritten = write_file(fsp,data,startpos,numtowrite);
2551 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2552 return(UNIXERROR(ERRDOS,ERRnoaccess));
2554 set_message(outbuf,6,0,True);
2556 SSVAL(outbuf,smb_vwv2,nwritten);
2558 if (nwritten < (ssize_t)numtowrite) {
2559 CVAL(outbuf,smb_rcls) = ERRHRD;
2560 SSVAL(outbuf,smb_err,ERRdiskfull);
2563 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2564 fsp->fnum, (int)numtowrite, (int)nwritten));
2566 if (lp_syncalways(SNUM(conn)) || write_through)
2567 sync_file(conn,fsp);
2569 return chain_reply(inbuf,outbuf,length,bufsize);
2573 /****************************************************************************
2575 ****************************************************************************/
2577 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2583 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2585 CHECK_FSP(fsp,conn);
2588 flush_write_cache(fsp, SEEK_FLUSH);
2590 mode = SVAL(inbuf,smb_vwv1) & 3;
2591 startpos = IVALS(inbuf,smb_vwv2);
2594 case 0: umode = SEEK_SET; break;
2595 case 1: umode = SEEK_CUR; break;
2596 case 2: umode = SEEK_END; break;
2598 umode = SEEK_SET; break;
2601 if((res = conn->vfs_ops.lseek(fsp->fd,startpos,umode)) == -1) {
2603 * Check for the special case where a seek before the start
2604 * of the file sets the offset to zero. Added in the CIFS spec,
2608 if(errno == EINVAL) {
2609 SMB_OFF_T current_pos = startpos;
2611 if(umode == SEEK_CUR) {
2613 if((current_pos = conn->vfs_ops.lseek(fsp->fd,0,SEEK_CUR)) == -1)
2614 return(UNIXERROR(ERRDOS,ERRnoaccess));
2616 current_pos += startpos;
2618 } else if (umode == SEEK_END) {
2620 SMB_STRUCT_STAT sbuf;
2622 if(conn->vfs_ops.fstat(fsp->fd, &sbuf) == -1)
2623 return(UNIXERROR(ERRDOS,ERRnoaccess));
2625 current_pos += sbuf.st_size;
2629 res = conn->vfs_ops.lseek(fsp->fd,0,SEEK_SET);
2633 return(UNIXERROR(ERRDOS,ERRnoaccess));
2638 outsize = set_message(outbuf,2,0,True);
2639 SIVAL(outbuf,smb_vwv0,res);
2641 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2642 fsp->fnum, (double)startpos, (double)res, mode));
2647 /****************************************************************************
2649 ****************************************************************************/
2651 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2653 int outsize = set_message(outbuf,0,0,True);
2654 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2657 CHECK_FSP(fsp,conn);
2662 file_sync_all(conn);
2664 sync_file(conn,fsp);
2667 DEBUG(3,("flush\n"));
2672 /****************************************************************************
2674 ****************************************************************************/
2675 int reply_exit(connection_struct *conn,
2676 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2678 int outsize = set_message(outbuf,0,0,True);
2679 DEBUG(3,("exit\n"));
2685 /****************************************************************************
2686 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2687 ****************************************************************************/
2688 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2693 int32 eclass = 0, err = 0;
2694 files_struct *fsp = NULL;
2696 outsize = set_message(outbuf,0,0,True);
2698 /* If it's an IPC, pass off to the pipe handler. */
2700 return reply_pipe_close(conn, inbuf,outbuf);
2702 fsp = file_fsp(inbuf,smb_vwv0);
2705 * We can only use CHECK_FSP if we know it's not a directory.
2708 if(!fsp || (fsp->conn != conn))
2709 return(ERROR(ERRDOS,ERRbadfid));
2711 if(HAS_CACHED_ERROR(fsp)) {
2712 eclass = fsp->wbmpx_ptr->wr_errclass;
2713 err = fsp->wbmpx_ptr->wr_error;
2716 if(fsp->is_directory || fsp->stat_open) {
2718 * Special case - close NT SMB directory or stat file
2721 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2722 close_file(fsp,True);
2725 * Close ordinary file.
2730 * If there was a modify time outstanding,
2731 * try and set it here.
2733 if(fsp->pending_modtime)
2734 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2737 * Now take care of any time sent in the close.
2739 mtime = make_unix_date3(inbuf+smb_vwv1);
2741 /* try and set the date */
2742 set_filetime(conn, fsp->fsp_name,mtime);
2744 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2746 conn->num_files_open));
2749 * close_file() returns the unix errno if an error
2750 * was detected on close - normally this is due to
2751 * a disk full error. If not then it was probably an I/O error.
2754 if((close_err = close_file(fsp,True)) != 0) {
2756 return (UNIXERROR(ERRHRD,ERRgeneral));
2760 /* We have a cached error */
2762 return(ERROR(eclass,err));
2768 /****************************************************************************
2769 reply to a writeclose (Core+ protocol)
2770 ****************************************************************************/
2772 int reply_writeclose(connection_struct *conn,
2773 char *inbuf,char *outbuf, int size, int dum_buffsize)
2776 ssize_t nwritten = -1;
2782 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2784 CHECK_FSP(fsp,conn);
2788 numtowrite = SVAL(inbuf,smb_vwv1);
2789 startpos = IVAL(inbuf,smb_vwv2);
2790 mtime = make_unix_date3(inbuf+smb_vwv4);
2791 data = smb_buf(inbuf) + 1;
2793 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK))
2794 return(ERROR(ERRDOS,ERRlock));
2796 nwritten = write_file(fsp,data,startpos,numtowrite);
2798 set_filetime(conn, fsp->fsp_name,mtime);
2800 close_err = close_file(fsp,True);
2802 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2803 fsp->fnum, (int)numtowrite, (int)nwritten,
2804 conn->num_files_open));
2807 return(UNIXERROR(ERRDOS,ERRnoaccess));
2809 if(close_err != 0) {
2811 return(UNIXERROR(ERRHRD,ERRgeneral));
2814 outsize = set_message(outbuf,1,0,True);
2816 SSVAL(outbuf,smb_vwv0,nwritten);
2821 /****************************************************************************
2823 ****************************************************************************/
2824 int reply_lock(connection_struct *conn,
2825 char *inbuf,char *outbuf, int length, int dum_buffsize)
2827 int outsize = set_message(outbuf,0,0,True);
2828 SMB_BIG_UINT count,offset;
2831 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2833 CHECK_FSP(fsp,conn);
2836 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2837 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2839 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2840 fsp->fd, fsp->fnum, (double)offset, (double)count));
2842 if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) {
2843 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2845 * A blocking lock was requested. Package up
2846 * this smb into a queued request and push it
2847 * onto the blocking lock queue.
2849 if(push_blocking_lock_request(inbuf, length, -1, 0))
2852 return (ERROR(eclass,ecode));
2859 /****************************************************************************
2861 ****************************************************************************/
2862 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2864 int outsize = set_message(outbuf,0,0,True);
2865 SMB_BIG_UINT count,offset;
2868 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2870 CHECK_FSP(fsp,conn);
2873 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2874 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2876 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2877 return (ERROR(eclass,ecode));
2879 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2880 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2886 /****************************************************************************
2888 ****************************************************************************/
2889 int reply_tdis(connection_struct *conn,
2890 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2892 int outsize = set_message(outbuf,0,0,True);
2895 vuid = SVAL(inbuf,smb_uid);
2898 DEBUG(4,("Invalid connection in tdis\n"));
2899 return(ERROR(ERRSRV,ERRinvnid));
2904 close_cnum(conn,vuid);
2911 /****************************************************************************
2913 ****************************************************************************/
2914 int reply_echo(connection_struct *conn,
2915 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2917 int smb_reverb = SVAL(inbuf,smb_vwv0);
2919 unsigned int data_len = smb_buflen(inbuf);
2920 int outsize = set_message(outbuf,1,data_len,True);
2922 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2924 /* copy any incoming data back out */
2926 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2928 if (smb_reverb > 100) {
2929 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2933 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2934 SSVAL(outbuf,smb_vwv0,seq_num);
2936 smb_setlen(outbuf,outsize - 4);
2938 send_smb(smbd_server_fd(),outbuf);
2941 DEBUG(3,("echo %d times\n", smb_reverb));
2949 /****************************************************************************
2950 reply to a printopen
2951 ****************************************************************************/
2952 int reply_printopen(connection_struct *conn,
2953 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2958 if (!CAN_PRINT(conn))
2959 return(ERROR(ERRDOS,ERRnoaccess));
2961 /* Open for exclusive use, write only. */
2962 fsp = print_fsp_open(conn,"dos.prn");
2965 return(UNIXERROR(ERRDOS,ERRnoaccess));
2968 outsize = set_message(outbuf,1,0,True);
2969 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2971 DEBUG(3,("openprint fd=%d fnum=%d\n",
2972 fsp->fd, fsp->fnum));
2978 /****************************************************************************
2979 reply to a printclose
2980 ****************************************************************************/
2981 int reply_printclose(connection_struct *conn,
2982 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2984 int outsize = set_message(outbuf,0,0,True);
2985 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2988 CHECK_FSP(fsp,conn);
2991 if (!CAN_PRINT(conn))
2992 return(ERROR(ERRDOS,ERRnoaccess));
2994 DEBUG(3,("printclose fd=%d fnum=%d\n",
2995 fsp->fd,fsp->fnum));
2997 close_err = close_file(fsp,True);
2999 if(close_err != 0) {
3001 return(UNIXERROR(ERRHRD,ERRgeneral));
3008 /****************************************************************************
3009 reply to a printqueue
3010 ****************************************************************************/
3011 int reply_printqueue(connection_struct *conn,
3012 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3014 int outsize = set_message(outbuf,2,3,True);
3015 int max_count = SVAL(inbuf,smb_vwv0);
3016 int start_index = SVAL(inbuf,smb_vwv1);
3018 /* we used to allow the client to get the cnum wrong, but that
3019 is really quite gross and only worked when there was only
3020 one printer - I think we should now only accept it if they
3021 get it right (tridge) */
3022 if (!CAN_PRINT(conn))
3023 return(ERROR(ERRDOS,ERRnoaccess));
3025 SSVAL(outbuf,smb_vwv0,0);
3026 SSVAL(outbuf,smb_vwv1,0);
3027 CVAL(smb_buf(outbuf),0) = 1;
3028 SSVAL(smb_buf(outbuf),1,0);
3030 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3031 start_index, max_count));
3034 print_queue_struct *queue = NULL;
3035 char *p = smb_buf(outbuf) + 3;
3036 int count = print_queue_status(SNUM(conn), &queue,NULL);
3037 int num_to_get = ABS(max_count);
3038 int first = (max_count>0?start_index:start_index+max_count+1);
3044 num_to_get = MIN(num_to_get,count-first);
3047 for (i=first;i<first+num_to_get;i++) {
3048 put_dos_date2(p,0,queue[i].time);
3049 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3050 SSVAL(p,5, queue[i].job);
3051 SIVAL(p,7,queue[i].size);
3053 StrnCpy(p+12,queue[i].user,16);
3058 outsize = set_message(outbuf,2,28*count+3,False);
3059 SSVAL(outbuf,smb_vwv0,count);
3060 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3061 CVAL(smb_buf(outbuf),0) = 1;
3062 SSVAL(smb_buf(outbuf),1,28*count);
3065 if (queue) free(queue);
3067 DEBUG(3,("%d entries returned in queue\n",count));
3074 /****************************************************************************
3075 reply to a printwrite
3076 ****************************************************************************/
3077 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3080 int outsize = set_message(outbuf,0,0,True);
3082 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3084 if (!CAN_PRINT(conn))
3085 return(ERROR(ERRDOS,ERRnoaccess));
3087 CHECK_FSP(fsp,conn);
3091 numtowrite = SVAL(smb_buf(inbuf),1);
3092 data = smb_buf(inbuf) + 3;
3094 if (write_file(fsp,data,-1,numtowrite) != numtowrite)
3095 return(UNIXERROR(ERRDOS,ERRnoaccess));
3097 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3103 /****************************************************************************
3105 ****************************************************************************/
3106 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3109 int outsize,ret= -1;
3110 BOOL bad_path = False;
3112 pstrcpy(directory,smb_buf(inbuf) + 1);
3113 unix_convert(directory,conn,0,&bad_path,NULL);
3115 if (check_name(directory, conn))
3116 ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
3117 unix_mode(conn,aDIR,directory));
3121 if((errno == ENOENT) && bad_path)
3123 unix_ERR_class = ERRDOS;
3124 unix_ERR_code = ERRbadpath;
3126 return(UNIXERROR(ERRDOS,ERRnoaccess));
3129 outsize = set_message(outbuf,0,0,True);
3131 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
3136 /****************************************************************************
3137 Static function used by reply_rmdir to delete an entire directory
3139 ****************************************************************************/
3141 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3145 void *dirptr = OpenDir(NULL, directory, False);
3150 while((dname = ReadDirName(dirptr)))
3155 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3158 /* Construct the full name. */
3159 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3165 pstrcpy(fullname, directory);
3166 pstrcat(fullname, "/");
3167 pstrcat(fullname, dname);
3169 if(conn->vfs_ops.lstat(dos_to_unix(fullname,False), &st) != 0)
3175 if(st.st_mode & S_IFDIR)
3177 if(recursive_rmdir(conn, fullname)!=0)
3182 if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
3188 else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
3198 /****************************************************************************
3199 The internals of the rmdir code - called elsewhere.
3200 ****************************************************************************/
3202 BOOL rmdir_internals(connection_struct *conn, char *directory)
3206 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory, False)) == 0);
3207 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3210 * Check to see if the only thing in this directory are
3211 * vetoed files/directories. If so then delete them and
3212 * retry. If we fail to delete any of them (and we *don't*
3213 * do a recursive delete) then fail the rmdir.
3215 BOOL all_veto_files = True;
3217 void *dirptr = OpenDir(conn, directory, False);
3221 int dirpos = TellDir(dirptr);
3222 while ((dname = ReadDirName(dirptr)))
3224 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3226 if(!IS_VETO_PATH(conn, dname))
3228 all_veto_files = False;
3234 SeekDir(dirptr,dirpos);
3235 while ((dname = ReadDirName(dirptr)))
3240 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3243 /* Construct the full name. */
3244 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3249 pstrcpy(fullname, directory);
3250 pstrcat(fullname, "/");
3251 pstrcat(fullname, dname);
3253 if(conn->vfs_ops.lstat(dos_to_unix(fullname, False), &st) != 0)
3255 if(st.st_mode & S_IFDIR)
3257 if(lp_recursive_veto_delete(SNUM(conn)))
3259 if(recursive_rmdir(conn, fullname) != 0)
3262 if(conn->vfs_ops.rmdir(dos_to_unix(fullname, False)) != 0)
3265 else if(conn->vfs_ops.unlink(dos_to_unix(fullname, False)) != 0)
3269 /* Retry the rmdir */
3270 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory, False)) == 0);
3280 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3281 directory,strerror(errno)));
3286 /****************************************************************************
3288 ****************************************************************************/
3290 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3295 BOOL bad_path = False;
3297 pstrcpy(directory,smb_buf(inbuf) + 1);
3299 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3301 unix_convert(directory,conn, NULL,&bad_path,NULL);
3303 if (check_name(directory,conn))
3305 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3306 ok = rmdir_internals(conn, directory);
3311 if((errno == ENOENT) && bad_path)
3313 unix_ERR_class = ERRDOS;
3314 unix_ERR_code = ERRbadpath;
3316 return(UNIXERROR(ERRDOS,ERRbadpath));
3319 outsize = set_message(outbuf,0,0,True);
3321 DEBUG( 3, ( "rmdir %s\n", directory ) );
3327 /*******************************************************************
3328 resolve wildcards in a filename rename
3329 ********************************************************************/
3330 static BOOL resolve_wildcards(char *name1,char *name2)
3332 fstring root1,root2;
3336 name1 = strrchr(name1,'/');
3337 name2 = strrchr(name2,'/');
3339 if (!name1 || !name2) return(False);
3341 fstrcpy(root1,name1);
3342 fstrcpy(root2,name2);
3343 p = strrchr(root1,'.');
3350 p = strrchr(root2,'.');
3382 pstrcpy(name2,root2);
3385 pstrcat(name2,ext2);
3391 /*******************************************************************
3392 check if a user is allowed to rename a file
3393 ********************************************************************/
3394 static BOOL can_rename(char *fname,connection_struct *conn)
3396 SMB_STRUCT_STAT sbuf;
3398 if (!CAN_WRITE(conn)) return(False);
3400 if (conn->vfs_ops.lstat(dos_to_unix(fname,False),&sbuf) != 0) return(False);
3401 if (!check_file_sharing(conn,fname,True)) return(False);
3406 /****************************************************************************
3407 The guts of the rename command, split out so it may be called by the NT SMB
3409 ****************************************************************************/
3410 int rename_internals(connection_struct *conn,
3411 char *inbuf, char *outbuf, char *name,
3412 char *newname, BOOL replace_if_exists)
3416 pstring newname_last_component;
3419 BOOL bad_path1 = False;
3420 BOOL bad_path2 = False;
3422 int error = ERRnoaccess;
3427 *directory = *mask = 0;
3429 rc = unix_convert(name,conn,0,&bad_path1,NULL);
3430 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3433 * Split the old name into directory and last component
3434 * strings. Note that unix_convert may have stripped off a
3435 * leading ./ from both name and newname if the rename is
3436 * at the root of the share. We need to make sure either both
3437 * name and newname contain a / character or neither of them do
3438 * as this is checked in resolve_wildcards().
3441 p = strrchr(name,'/');
3443 pstrcpy(directory,".");
3447 pstrcpy(directory,name);
3449 *p = '/'; /* Replace needed for exceptional test below. */
3453 * We should only check the mangled cache
3454 * here if unix_convert failed. This means
3455 * that the path in 'mask' doesn't exist
3456 * on the file system and so we need to look
3457 * for a possible mangle. This patch from
3458 * Tine Smukavec <valentin.smukavec@hermes.si>.
3461 if (!rc && is_mangled(mask))
3462 check_mangled_cache( mask );
3464 has_wild = ms_has_wild(mask);
3468 * No wildcards - just process the one file.
3470 BOOL is_short_name = is_8_3(name, True);
3472 /* Add a terminating '/' to the directory name. */
3473 pstrcat(directory,"/");
3474 pstrcat(directory,mask);
3476 /* Ensure newname contains a '/' also */
3477 if(strrchr(newname,'/') == 0) {
3480 pstrcpy(tmpstr, "./");
3481 pstrcat(tmpstr, newname);
3482 pstrcpy(newname, tmpstr);
3485 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",
3486 case_sensitive, case_preserve, short_case_preserve, directory,
3487 newname, newname_last_component, is_short_name));
3490 * Check for special case with case preserving and not
3491 * case sensitive, if directory and newname are identical,
3492 * and the old last component differs from the original
3493 * last component only by case, then we should allow
3494 * the rename (user is trying to change the case of the
3497 if((case_sensitive == False) &&
3498 (((case_preserve == True) &&
3499 (is_short_name == False)) ||
3500 ((short_case_preserve == True) &&
3501 (is_short_name == True))) &&
3502 strcsequal(directory, newname)) {
3503 pstring newname_modified_last_component;
3506 * Get the last component of the modified name.
3507 * Note that we guarantee that newname contains a '/'
3510 p = strrchr(newname,'/');
3511 pstrcpy(newname_modified_last_component,p+1);
3513 if(strcsequal(newname_modified_last_component,
3514 newname_last_component) == False) {
3516 * Replace the modified last component with
3519 pstrcpy(p+1, newname_last_component);
3523 pstrcpy(zdirectory, dos_to_unix(directory, False));
3524 if(replace_if_exists) {
3526 * NT SMB specific flag - rename can overwrite
3527 * file with the same name so don't check for
3530 if(resolve_wildcards(directory,newname) &&
3531 can_rename(directory,conn) &&
3532 !conn->vfs_ops.rename(zdirectory,
3533 dos_to_unix(newname,False)))
3536 if (resolve_wildcards(directory,newname) &&
3537 can_rename(directory,conn) &&
3538 !vfs_file_exist(conn,newname,NULL) &&
3539 !conn->vfs_ops.rename(zdirectory,
3540 dos_to_unix(newname,False)))
3544 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3545 directory,newname));
3547 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3548 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3554 * Wildcards - process each file that matches.
3556 void *dirptr = NULL;
3560 if (check_name(directory,conn))
3561 dirptr = OpenDir(conn, directory, True);
3566 if (strequal(mask,"????????.???"))
3569 while ((dname = ReadDirName(dirptr))) {
3572 pstrcpy(fname,dname);
3574 if(!mask_match(fname, mask, case_sensitive))
3577 error = ERRnoaccess;
3578 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3579 if (!can_rename(fname,conn)) {
3580 DEBUG(6,("rename %s refused\n", fname));
3583 pstrcpy(destname,newname);
3585 if (!resolve_wildcards(fname,destname)) {
3586 DEBUG(6,("resolve_wildcards %s %s failed\n",
3591 if (!replace_if_exists &&
3592 vfs_file_exist(conn,destname, NULL)) {
3593 DEBUG(6,("file_exist %s\n", destname));
3598 if (!conn->vfs_ops.rename(dos_to_unix(fname,False),
3599 dos_to_unix(destname,False)))
3601 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3609 return(ERROR(ERRDOS,error));
3611 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3612 unix_ERR_class = ERRDOS;
3613 unix_ERR_code = ERRbadpath;
3615 return(UNIXERROR(ERRDOS,error));
3622 /****************************************************************************
3624 ****************************************************************************/
3626 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3632 pstrcpy(name,smb_buf(inbuf) + 1);
3633 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3635 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3636 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3638 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3640 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3642 outsize = set_message(outbuf,0,0,True);
3647 /*******************************************************************
3648 copy a file as part of a reply_copy
3649 ******************************************************************/
3651 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3652 int count,BOOL target_is_directory, int *err_ret)
3657 files_struct *fsp1,*fsp2;
3662 pstrcpy(dest,dest1);
3663 if (target_is_directory) {
3664 char *p = strrchr(src,'/');
3673 if (!vfs_file_exist(conn,src,&st))
3676 fsp1 = open_file_shared(conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3677 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3683 if (!target_is_directory && count)
3686 fsp2 = open_file_shared(conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3687 ofun,st.st_mode,0,&Access,&action);
3690 close_file(fsp1,False);
3694 if ((ofun&3) == 1) {
3695 if(conn->vfs_ops.lseek(fsp2->fd,0,SEEK_END) == -1) {
3696 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3699 * Stop the copy from occurring.
3707 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0);
3709 close_file(fsp1,False);
3711 * As we are opening fsp1 read-only we only expect
3712 * an error on close on fsp2 if we are out of space.
3713 * Thus we don't look at the error return from the
3716 *err_ret = close_file(fsp2,False);
3718 return(ret == (SMB_OFF_T)st.st_size);
3723 /****************************************************************************
3724 reply to a file copy.
3725 ****************************************************************************/
3726 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3731 pstring mask,newname;
3734 int error = ERRnoaccess;
3738 int tid2 = SVAL(inbuf,smb_vwv0);
3739 int ofun = SVAL(inbuf,smb_vwv1);
3740 int flags = SVAL(inbuf,smb_vwv2);
3741 BOOL target_is_directory=False;
3742 BOOL bad_path1 = False;
3743 BOOL bad_path2 = False;
3746 *directory = *mask = 0;
3748 pstrcpy(name,smb_buf(inbuf));
3749 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3751 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3753 if (tid2 != conn->cnum) {
3754 /* can't currently handle inter share copies XXXX */
3755 DEBUG(3,("Rejecting inter-share copy\n"));
3756 return(ERROR(ERRSRV,ERRinvdevice));
3759 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3760 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3762 rc = unix_convert(name,conn,0,&bad_path1,NULL);
3763 unix_convert(newname,conn,0,&bad_path2,NULL);
3765 target_is_directory = vfs_directory_exist(conn,False,NULL);
3767 if ((flags&1) && target_is_directory) {
3768 return(ERROR(ERRDOS,ERRbadfile));
3771 if ((flags&2) && !target_is_directory) {
3772 return(ERROR(ERRDOS,ERRbadpath));
3775 if ((flags&(1<<5)) && vfs_directory_exist(conn,name,NULL)) {
3776 /* wants a tree copy! XXXX */
3777 DEBUG(3,("Rejecting tree copy\n"));
3778 return(ERROR(ERRSRV,ERRerror));
3781 p = strrchr(name,'/');
3783 pstrcpy(directory,"./");
3787 pstrcpy(directory,name);
3792 * We should only check the mangled cache
3793 * here if unix_convert failed. This means
3794 * that the path in 'mask' doesn't exist
3795 * on the file system and so we need to look
3796 * for a possible mangle. This patch from
3797 * Tine Smukavec <valentin.smukavec@hermes.si>.
3800 if (!rc && is_mangled(mask))
3801 check_mangled_cache( mask );
3803 has_wild = ms_has_wild(mask);
3806 pstrcat(directory,"/");
3807 pstrcat(directory,mask);
3808 if (resolve_wildcards(directory,newname) &&
3809 copy_file(directory,newname,conn,ofun,
3810 count,target_is_directory,&err)) count++;
3813 return(UNIXERROR(ERRHRD,ERRgeneral));
3815 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3817 void *dirptr = NULL;
3821 if (check_name(directory,conn))
3822 dirptr = OpenDir(conn, directory, True);
3827 if (strequal(mask,"????????.???"))
3830 while ((dname = ReadDirName(dirptr))) {
3832 pstrcpy(fname,dname);
3834 if(!mask_match(fname, mask, case_sensitive))
3837 error = ERRnoaccess;
3838 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3839 pstrcpy(destname,newname);
3840 if (resolve_wildcards(fname,destname) &&
3841 copy_file(fname,destname,conn,ofun,
3842 count,target_is_directory,&err)) count++;
3843 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3851 /* Error on close... */
3853 return(UNIXERROR(ERRHRD,ERRgeneral));
3857 return(ERROR(ERRDOS,error));
3860 if((errno == ENOENT) && (bad_path1 || bad_path2))
3862 unix_ERR_class = ERRDOS;
3863 unix_ERR_code = ERRbadpath;
3865 return(UNIXERROR(ERRDOS,error));
3869 outsize = set_message(outbuf,1,0,True);
3870 SSVAL(outbuf,smb_vwv0,count);
3875 /****************************************************************************
3877 ****************************************************************************/
3878 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3886 if (!CAN_SETDIR(snum))
3887 return(ERROR(ERRDOS,ERRnoaccess));
3889 pstrcpy(newdir,smb_buf(inbuf) + 1);
3892 if (strlen(newdir) == 0) {
3895 ok = vfs_directory_exist(conn,newdir,NULL);
3897 string_set(&conn->connectpath,newdir);
3902 return(ERROR(ERRDOS,ERRbadpath));
3904 outsize = set_message(outbuf,0,0,True);
3905 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3907 DEBUG(3,("setdir %s\n", newdir));
3912 /****************************************************************************
3913 Get a lock count, dealing with large count requests.
3914 ****************************************************************************/
3916 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3918 SMB_BIG_UINT count = 0;
3920 if(!large_file_format) {
3921 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3924 #if defined(HAVE_LONGLONG)
3925 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3926 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3927 #else /* HAVE_LONGLONG */
3930 * NT4.x seems to be broken in that it sends large file (64 bit)
3931 * lockingX calls even if the CAP_LARGE_FILES was *not*
3932 * negotiated. For boxes without large unsigned ints truncate the
3933 * lock count by dropping the top 32 bits.
3936 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3937 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3938 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3939 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3940 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3943 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3944 #endif /* HAVE_LONGLONG */
3950 /****************************************************************************
3951 Get a lock offset, dealing with large offset requests.
3952 ****************************************************************************/
3954 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3956 SMB_BIG_UINT offset = 0;
3960 if(!large_file_format) {
3961 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3964 #if defined(HAVE_LONGLONG)
3965 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3966 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3967 #else /* HAVE_LONGLONG */
3970 * NT4.x seems to be broken in that it sends large file (64 bit)
3971 * lockingX calls even if the CAP_LARGE_FILES was *not*
3972 * negotiated. For boxes without large unsigned ints mangle the
3973 * lock offset by mapping the top 32 bits onto the lower 32.
3976 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3977 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3978 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3981 if((new_low = map_lock_offset(high, low)) == 0) {
3983 return (SMB_BIG_UINT)-1;
3986 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3987 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3988 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3989 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3992 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3993 #endif /* HAVE_LONGLONG */
3999 /****************************************************************************
4000 reply to a lockingX request
4001 ****************************************************************************/
4003 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4005 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4006 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4008 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4010 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4011 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4012 SMB_BIG_UINT count = 0, offset = 0;
4013 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4016 uint32 ecode=0, dummy2;
4017 int eclass=0, dummy1;
4018 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
4021 CHECK_FSP(fsp,conn);
4024 data = smb_buf(inbuf);
4026 /* Check if this is an oplock break on a file
4027 we have granted an oplock on.
4029 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4031 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
4035 * Make sure we have granted an exclusive or batch oplock on this file.
4038 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4040 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4041 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4043 /* if this is a pure oplock break request then don't send a reply */
4044 if (num_locks == 0 && num_ulocks == 0)
4047 return ERROR(ERRDOS,ERRlock);
4050 if (remove_oplock(fsp) == False) {
4051 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4055 /* if this is a pure oplock break request then don't send a reply */
4056 if (num_locks == 0 && num_ulocks == 0)
4058 /* Sanity check - ensure a pure oplock break is not a
4060 if(CVAL(inbuf,smb_vwv0) != 0xff)
4061 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4062 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4067 /* Data now points at the beginning of the list
4068 of smb_unlkrng structs */
4069 for(i = 0; i < (int)num_ulocks; i++) {
4070 count = get_lock_count( data, i, large_file_format);
4071 offset = get_lock_offset( data, i, large_file_format, &err);
4074 * There is no error code marked "stupid client bug".... :-).
4077 return ERROR(ERRDOS,ERRnoaccess);
4079 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
4080 (double)offset, (double)count, fsp->fsp_name ));
4082 if(!do_unlock(fsp,conn,count,offset, &eclass, &ecode))
4083 return ERROR(eclass,ecode);
4086 /* Setup the timeout in seconds. */
4087 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4089 /* Now do any requested locks */
4090 data += ((large_file_format ? 20 : 10)*num_ulocks);
4092 /* Data now points at the beginning of the list
4093 of smb_lkrng structs */
4095 for(i = 0; i < (int)num_locks; i++) {
4096 count = get_lock_count( data, i, large_file_format);
4097 offset = get_lock_offset( data, i, large_file_format, &err);
4100 * There is no error code marked "stupid client bug".... :-).
4103 return ERROR(ERRDOS,ERRnoaccess);
4105 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
4106 (double)offset, (double)count, fsp->fsp_name ));
4108 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4110 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4112 * A blocking lock was requested. Package up
4113 * this smb into a queued request and push it
4114 * onto the blocking lock queue.
4116 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
4123 /* If any of the above locks failed, then we must unlock
4124 all of the previous locks (X/Open spec). */
4125 if(i != num_locks && num_locks != 0) {
4127 * Ensure we don't do a remove on the lock that just failed,
4128 * as under POSIX rules, if we have a lock already there, we
4129 * will delete it (and we shouldn't) .....
4131 for(i--; i >= 0; i--) {
4132 count = get_lock_count( data, i, large_file_format);
4133 offset = get_lock_offset( data, i, large_file_format, &err);
4136 * There is no error code marked "stupid client bug".... :-).
4139 return ERROR(ERRDOS,ERRnoaccess);
4141 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
4143 return ERROR(eclass,ecode);
4146 set_message(outbuf,2,0,True);
4148 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4149 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4151 return chain_reply(inbuf,outbuf,length,bufsize);
4155 /****************************************************************************
4156 reply to a SMBreadbmpx (read block multiplex) request
4157 ****************************************************************************/
4158 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4169 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4171 /* this function doesn't seem to work - disable by default */
4173 return(ERROR(ERRSRV,ERRuseSTD));
4175 outsize = set_message(outbuf,8,0,True);
4177 CHECK_FSP(fsp,conn);
4181 startpos = IVAL(inbuf,smb_vwv1);
4182 maxcount = SVAL(inbuf,smb_vwv3);
4184 data = smb_buf(outbuf);
4185 pad = ((long)data)%4;
4186 if (pad) pad = 4 - pad;
4189 max_per_packet = bufsize-(outsize+pad);
4193 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK))
4194 return(ERROR(ERRDOS,ERRlock));
4198 size_t N = MIN(max_per_packet,tcount-total_read);
4200 nread = read_file(fsp,data,startpos,N);
4202 if (nread <= 0) nread = 0;
4204 if (nread < (ssize_t)N)
4205 tcount = total_read + nread;
4207 set_message(outbuf,8,nread,False);
4208 SIVAL(outbuf,smb_vwv0,startpos);
4209 SSVAL(outbuf,smb_vwv2,tcount);
4210 SSVAL(outbuf,smb_vwv6,nread);
4211 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4213 send_smb(smbd_server_fd(),outbuf);
4215 total_read += nread;
4218 while (total_read < (ssize_t)tcount);
4223 /****************************************************************************
4224 reply to a SMBwritebmpx (write block multiplex primary) request
4225 ****************************************************************************/
4227 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4230 ssize_t nwritten = -1;
4237 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4239 CHECK_FSP(fsp,conn);
4243 tcount = SVAL(inbuf,smb_vwv1);
4244 startpos = IVAL(inbuf,smb_vwv3);
4245 write_through = BITSETW(inbuf+smb_vwv7,0);
4246 numtowrite = SVAL(inbuf,smb_vwv10);
4247 smb_doff = SVAL(inbuf,smb_vwv11);
4249 data = smb_base(inbuf) + smb_doff;
4251 /* If this fails we need to send an SMBwriteC response,
4252 not an SMBwritebmpx - set this up now so we don't forget */
4253 CVAL(outbuf,smb_com) = SMBwritec;
4255 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK))
4256 return(ERROR(ERRDOS,ERRlock));
4258 nwritten = write_file(fsp,data,startpos,numtowrite);
4260 if(lp_syncalways(SNUM(conn)) || write_through)
4261 sync_file(conn,fsp);
4263 if(nwritten < (ssize_t)numtowrite)
4264 return(UNIXERROR(ERRHRD,ERRdiskfull));
4266 /* If the maximum to be written to this file
4267 is greater than what we just wrote then set
4268 up a secondary struct to be attached to this
4269 fd, we will use this to cache error messages etc. */
4270 if((ssize_t)tcount > nwritten)
4272 write_bmpx_struct *wbms;
4273 if(fsp->wbmpx_ptr != NULL)
4274 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4276 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4279 DEBUG(0,("Out of memory in reply_readmpx\n"));
4280 return(ERROR(ERRSRV,ERRnoresource));
4282 wbms->wr_mode = write_through;
4283 wbms->wr_discard = False; /* No errors yet */
4284 wbms->wr_total_written = nwritten;
4285 wbms->wr_errclass = 0;
4287 fsp->wbmpx_ptr = wbms;
4290 /* We are returning successfully, set the message type back to
4292 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4294 outsize = set_message(outbuf,1,0,True);
4296 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4298 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4299 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4301 if (write_through && tcount==nwritten) {
4302 /* we need to send both a primary and a secondary response */
4303 smb_setlen(outbuf,outsize - 4);
4304 send_smb(smbd_server_fd(),outbuf);
4306 /* now the secondary */
4307 outsize = set_message(outbuf,1,0,True);
4308 CVAL(outbuf,smb_com) = SMBwritec;
4309 SSVAL(outbuf,smb_vwv0,nwritten);
4316 /****************************************************************************
4317 reply to a SMBwritebs (write block multiplex secondary) request
4318 ****************************************************************************/
4319 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4322 ssize_t nwritten = -1;
4329 write_bmpx_struct *wbms;
4330 BOOL send_response = False;
4331 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4333 CHECK_FSP(fsp,conn);
4336 tcount = SVAL(inbuf,smb_vwv1);
4337 startpos = IVAL(inbuf,smb_vwv2);
4338 numtowrite = SVAL(inbuf,smb_vwv6);
4339 smb_doff = SVAL(inbuf,smb_vwv7);
4341 data = smb_base(inbuf) + smb_doff;
4343 /* We need to send an SMBwriteC response, not an SMBwritebs */
4344 CVAL(outbuf,smb_com) = SMBwritec;
4346 /* This fd should have an auxiliary struct attached,
4347 check that it does */
4348 wbms = fsp->wbmpx_ptr;
4349 if(!wbms) return(-1);
4351 /* If write through is set we can return errors, else we must
4353 write_through = wbms->wr_mode;
4355 /* Check for an earlier error */
4356 if(wbms->wr_discard)
4357 return -1; /* Just discard the packet */
4359 nwritten = write_file(fsp,data,startpos,numtowrite);
4361 if(lp_syncalways(SNUM(conn)) || write_through)
4362 sync_file(conn,fsp);
4364 if (nwritten < (ssize_t)numtowrite)
4368 /* We are returning an error - we can delete the aux struct */
4369 if (wbms) free((char *)wbms);
4370 fsp->wbmpx_ptr = NULL;
4371 return(ERROR(ERRHRD,ERRdiskfull));
4373 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4376 /* Increment the total written, if this matches tcount
4377 we can discard the auxiliary struct (hurrah !) and return a writeC */
4378 wbms->wr_total_written += nwritten;
4379 if(wbms->wr_total_written >= tcount)
4383 outsize = set_message(outbuf,1,0,True);
4384 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4385 send_response = True;
4389 fsp->wbmpx_ptr = NULL;
4399 /****************************************************************************
4400 reply to a SMBsetattrE
4401 ****************************************************************************/
4403 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4405 struct utimbuf unix_times;
4407 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4409 outsize = set_message(outbuf,0,0,True);
4411 CHECK_FSP(fsp,conn);
4414 /* Convert the DOS times into unix times. Ignore create
4415 time as UNIX can't set this.
4417 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4418 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4421 * Patch from Ray Frush <frush@engr.colostate.edu>
4422 * Sometimes times are sent as zero - ignore them.
4425 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4427 /* Ignore request */
4430 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4431 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4435 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4437 /* set modify time = to access time if modify time was 0 */
4438 unix_times.modtime = unix_times.actime;
4441 /* Set the date on this file */
4442 if(file_utime(conn, fsp->fsp_name, &unix_times))
4443 return(ERROR(ERRDOS,ERRnoaccess));
4445 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4446 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4452 /****************************************************************************
4453 reply to a SMBgetattrE
4454 ****************************************************************************/
4456 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4458 SMB_STRUCT_STAT sbuf;
4461 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4463 outsize = set_message(outbuf,11,0,True);
4465 CHECK_FSP(fsp,conn);
4468 /* Do an fstat on this file */
4469 if(fsp->conn->vfs_ops.fstat(fsp->fd, &sbuf))
4470 return(UNIXERROR(ERRDOS,ERRnoaccess));
4472 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4474 /* Convert the times into dos times. Set create
4475 date to be last modify date as UNIX doesn't save
4477 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4478 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4479 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4482 SIVAL(outbuf,smb_vwv6,0);
4483 SIVAL(outbuf,smb_vwv8,0);
4487 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4488 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4490 SSVAL(outbuf,smb_vwv10, mode);
4492 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));