syncing with release branch (includes trans2 fixes)
[Samba.git] / source / smbd / reply.c
blob12995722c7881e8709ad7ecf35721a54afa91fac
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
27 #include "includes.h"
29 /* look in server.c for some explanation of these variables */
30 extern int Protocol;
31 extern int max_send;
32 extern int max_recv;
33 extern char magic_char;
34 extern BOOL case_sensitive;
35 extern BOOL case_preserve;
36 extern BOOL short_case_preserve;
37 extern userdom_struct current_user_info;
38 extern pstring global_myname;
39 extern fstring global_myworkgroup;
40 extern int global_oplock_break;
41 uint32 global_client_caps = 0;
42 unsigned int smb_echo_count = 0;
44 /****************************************************************************
45 Report a possible attack via the password buffer overflow bug.
46 ****************************************************************************/
48 static void overflow_attack(int len)
50 if( DEBUGLVL( 0 ) ) {
51 dbgtext( "ERROR: Invalid password length %d.\n", len );
52 dbgtext( "Your machine may be under attack by someone " );
53 dbgtext( "attempting to exploit an old bug.\n" );
54 dbgtext( "Attack was from IP = %s.\n", client_addr() );
59 /****************************************************************************
60 Reply to an special message.
61 ****************************************************************************/
63 int reply_special(char *inbuf,char *outbuf)
65 int outsize = 4;
66 int msg_type = CVAL(inbuf,0);
67 int msg_flags = CVAL(inbuf,1);
68 pstring name1,name2;
69 extern fstring remote_machine;
70 extern fstring local_machine;
71 int len;
72 char name_type = 0;
74 *name1 = *name2 = 0;
76 memset(outbuf,'\0',smb_size);
78 smb_setlen(outbuf,0);
80 switch (msg_type) {
81 case 0x81: /* session request */
82 SCVAL(outbuf,0,0x82);
83 SCVAL(outbuf,3,0);
84 if (name_len(inbuf+4) > 50 ||
85 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
86 DEBUG(0,("Invalid name length in session request\n"));
87 return(0);
89 name_extract(inbuf,4,name1);
90 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
91 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
92 name1,name2));
94 fstrcpy(remote_machine,name2);
95 remote_machine[15] = 0;
96 trim_string(remote_machine," "," ");
97 strlower(remote_machine);
98 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
100 fstrcpy(local_machine,name1);
101 len = strlen(local_machine);
102 if (len == 16) {
103 name_type = local_machine[15];
104 local_machine[15] = 0;
106 trim_string(local_machine," "," ");
107 strlower(local_machine);
108 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
110 DEBUG(2,("netbios connect: local=%s remote=%s\n",
111 local_machine, remote_machine ));
113 if (name_type == 'R') {
114 /* We are being asked for a pathworks session ---
115 no thanks! */
116 SCVAL(outbuf, 0, 0x83);
117 break;
120 /* add it as a possible user name if we
121 are in share mode security */
122 if (lp_security() == SEC_SHARE) {
123 add_session_user(remote_machine);
126 reload_services(True);
127 reopen_logs();
129 if (lp_status(-1))
130 claim_connection(NULL,"",0,True);
132 break;
134 case 0x89: /* session keepalive request
135 (some old clients produce this?) */
136 SCVAL(outbuf,0,0x85);
137 SCVAL(outbuf,3,0);
138 break;
140 case 0x82: /* positive session response */
141 case 0x83: /* negative session response */
142 case 0x84: /* retarget session response */
143 DEBUG(0,("Unexpected session response\n"));
144 break;
146 case 0x85: /* session keepalive */
147 default:
148 return(0);
151 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
152 msg_type, msg_flags));
154 return(outsize);
157 /*******************************************************************
158 Work out what error to give to a failed connection.
159 ********************************************************************/
161 static int connection_error(char *outbuf, int ecode)
163 if (ecode == ERRnoipc || ecode == ERRnosuchshare)
164 return(ERROR_DOS(ERRDOS,ecode));
166 return(ERROR_DOS(ERRSRV,ecode));
169 /****************************************************************************
170 Parse a share descriptor string.
171 ****************************************************************************/
173 static void parse_connect(char *p,char *service,char *user,
174 char *password,int *pwlen,char *dev)
176 char *p2;
178 DEBUG(4,("parsing connect string %s\n",p));
180 p2 = strrchr(p,'\\');
181 if (p2 == NULL)
182 fstrcpy(service,p);
183 else
184 fstrcpy(service,p2+1);
186 p += strlen(p) + 2;
188 fstrcpy(password,p);
189 *pwlen = strlen(password);
191 p += strlen(p) + 2;
193 fstrcpy(dev,p);
195 *user = 0;
196 p = strchr(service,'%');
197 if (p != NULL)
199 *p = 0;
200 fstrcpy(user,p+1);
204 /****************************************************************************
205 Reply to a tcon.
206 ****************************************************************************/
208 int reply_tcon(connection_struct *conn,
209 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
211 BOOL doencrypt = SMBENCRYPT();
212 pstring service;
213 pstring user;
214 pstring password;
215 pstring dev;
216 int outsize = 0;
217 uint16 vuid = SVAL(inbuf,smb_uid);
218 int pwlen=0;
219 int ecode = -1;
220 START_PROFILE(SMBtcon);
222 *service = *user = *password = *dev = 0;
224 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
227 * If the vuid is valid, we should be using that....
230 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
231 pstrcpy(user,validated_username(vuid));
235 * Ensure the user and password names are in UNIX codepage format.
238 pstrcpy(user,dos_to_unix_static(user));
239 if (!doencrypt)
240 pstrcpy(password,dos_to_unix_static(password));
243 * Pass the user through the NT -> unix user mapping
244 * function.
247 (void)map_username(user);
250 * Do any UNIX username case mangling.
252 (void)Get_Pwnam( user, True);
254 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
256 if (!conn) {
257 END_PROFILE(SMBtcon);
258 return(connection_error(outbuf,ecode));
261 outsize = set_message(outbuf,2,0,True);
262 SSVAL(outbuf,smb_vwv0,max_recv);
263 SSVAL(outbuf,smb_vwv1,conn->cnum);
264 SSVAL(outbuf,smb_tid,conn->cnum);
266 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
267 service, user, conn->cnum));
269 END_PROFILE(SMBtcon);
270 return(outsize);
273 /****************************************************************************
274 Reply to a tcon and X.
275 ****************************************************************************/
277 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
279 fstring service;
280 pstring user;
281 pstring password;
282 pstring devicename;
283 BOOL doencrypt = SMBENCRYPT();
284 int ecode = -1;
285 uint16 vuid = SVAL(inbuf,smb_uid);
286 int passlen = SVAL(inbuf,smb_vwv3);
287 char *path;
288 char *p;
289 START_PROFILE(SMBtconX);
291 *service = *user = *password = *devicename = 0;
293 /* we might have to close an old one */
294 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
295 close_cnum(conn,vuid);
298 if (passlen > MAX_PASS_LEN) {
299 overflow_attack(passlen);
300 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
303 memcpy(password,smb_buf(inbuf),passlen);
304 password[passlen]=0;
305 path = smb_buf(inbuf) + passlen;
307 if (passlen != 24) {
308 if (strequal(password," "))
309 *password = 0;
310 passlen = strlen(password);
314 * the service name can be either: \\server\share
315 * or share directly like on the DELL PowerVault 705
317 if (*path=='\\') {
318 p = strchr(path+2,'\\');
319 if (!p) {
320 END_PROFILE(SMBtconX);
321 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
323 fstrcpy(service,p+1);
325 else
326 fstrcpy(service,path);
328 p = strchr(service,'%');
329 if (p) {
330 *p++ = 0;
331 fstrcpy(user,p);
333 StrnCpy(devicename,path + strlen(path) + 1,6);
334 DEBUG(4,("Got device type %s\n",devicename));
337 * If the vuid is valid, we should be using that....
340 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
341 pstrcpy(user,validated_username(vuid));
345 * Ensure the user and password names are in UNIX codepage format.
348 pstrcpy(user,dos_to_unix_static(user));
349 if (!doencrypt)
350 pstrcpy(password,dos_to_unix_static(password));
353 * Pass the user through the NT -> unix user mapping
354 * function.
357 (void)map_username(user);
360 * Do any UNIX username case mangling.
362 (void)Get_Pwnam(user, True);
364 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
366 if (!conn) {
367 END_PROFILE(SMBtconX);
368 return(connection_error(outbuf,ecode));
371 if (Protocol < PROTOCOL_NT1) {
372 set_message(outbuf,2,strlen(devicename)+1,True);
373 pstrcpy(smb_buf(outbuf),devicename);
374 } else {
375 char *fsname = lp_fstype(SNUM(conn));
377 set_message(outbuf,3,3,True);
379 p = smb_buf(outbuf);
380 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
381 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
383 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
385 /* what does setting this bit do? It is set by NT4 and
386 may affect the ability to autorun mounted cdroms */
387 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
388 (lp_csc_policy(SNUM(conn)) << 2));
390 init_dfsroot(conn, inbuf, outbuf);
394 DEBUG(3,("tconX service=%s user=%s\n",
395 service, user));
397 /* set the incoming and outgoing tid to the just created one */
398 SSVAL(inbuf,smb_tid,conn->cnum);
399 SSVAL(outbuf,smb_tid,conn->cnum);
401 END_PROFILE(SMBtconX);
402 return chain_reply(inbuf,outbuf,length,bufsize);
405 /****************************************************************************
406 Reply to an unknown type.
407 ****************************************************************************/
409 int reply_unknown(char *inbuf,char *outbuf)
411 int type;
412 type = CVAL(inbuf,smb_com);
414 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
415 smb_fn_name(type), type, type));
417 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
420 /****************************************************************************
421 Reply to an ioctl.
422 ****************************************************************************/
424 int reply_ioctl(connection_struct *conn,
425 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
427 uint16 device = SVAL(inbuf,smb_vwv1);
428 uint16 function = SVAL(inbuf,smb_vwv2);
429 uint32 ioctl_code = (device << 16) + function;
430 int replysize, outsize;
431 char *p;
432 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
433 START_PROFILE(SMBioctl);
435 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
437 switch (ioctl_code)
439 case IOCTL_QUERY_JOB_INFO:
440 replysize = 32;
441 break;
442 default:
443 END_PROFILE(SMBioctl);
444 return(ERROR_DOS(ERRSRV,ERRnosupport));
447 outsize = set_message(outbuf,8,replysize+1,True);
448 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
449 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
450 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
451 p = smb_buf(outbuf) + 1; /* Allow for alignment */
453 switch (ioctl_code)
455 case IOCTL_QUERY_JOB_INFO:
456 SSVAL(p,0,fsp->print_jobid); /* Job number */
457 StrnCpy(p+2, global_myname, 15); /* Our NetBIOS name */
458 StrnCpy(p+18, lp_servicename(SNUM(conn)), 13); /* Service name */
459 break;
462 END_PROFILE(SMBioctl);
463 return outsize;
466 /****************************************************************************
467 Always return an error: it's just a matter of which one...
468 ****************************************************************************/
470 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
471 char *smb_passwd, int smb_passlen,
472 char *smb_nt_passwd, int smb_nt_passlen)
474 SAM_ACCOUNT *sam_trust_acct = NULL; /* check if trust account exists */
475 uint16 acct_ctrl;
477 if (lp_security() == SEC_USER) {
478 pdb_init_sam(&sam_trust_acct);
479 pdb_getsampwnam(sam_trust_acct, user);
480 } else {
481 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
482 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw));
485 if (sam_trust_acct == NULL) {
486 /* lkclXXXX: workstation entry doesn't exist */
487 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
488 return(ERROR_BOTH(NT_STATUS_NO_SUCH_USER,ERRDOS,1317));
489 } else {
490 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
491 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
492 pdb_free_sam(sam_trust_acct);
493 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw));
496 if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) {
497 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
498 pdb_free_sam(sam_trust_acct);
499 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw));
502 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
503 if (acct_ctrl & ACB_DOMTRUST) {
504 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
505 pdb_free_sam(sam_trust_acct);
506 return(ERROR_BOTH(NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT,ERRDOS,1807));
509 if (acct_ctrl & ACB_SVRTRUST) {
510 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
511 pdb_free_sam(sam_trust_acct);
512 return(ERROR_BOTH(NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT,ERRDOS,1809));
515 if (acct_ctrl & ACB_WSTRUST) {
516 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
517 pdb_free_sam(sam_trust_acct);
518 return(ERROR_BOTH(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT,ERRDOS,1808));
522 /* don't know what to do: indicate logon failure */
523 pdb_free_sam(sam_trust_acct);
524 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRDOS,1326));
527 /****************************************************************************
528 Create a UNIX user on demand.
529 ****************************************************************************/
531 int smb_create_user(char *unix_user, char *homedir)
533 pstring add_script;
534 int ret;
536 pstrcpy(add_script, lp_adduser_script());
537 if (! *add_script)
538 return -1;
539 all_string_sub(add_script, "%u", unix_user, sizeof(pstring));
540 if (homedir)
541 all_string_sub(add_script, "%H", homedir, sizeof(pstring));
542 ret = smbrun(add_script,NULL);
543 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
544 return ret;
547 /****************************************************************************
548 Delete a UNIX user on demand.
549 ****************************************************************************/
551 static int smb_delete_user(char *unix_user)
553 pstring del_script;
554 int ret;
557 * Sanity check -- do not delete 'root' account
560 if (StrCaseCmp("root", unix_user) == 0) {
561 DEBUG(0,("smb_delete_user: Will not delete the [%s] user account!\n", unix_user));
562 return -1;
565 pstrcpy(del_script, lp_deluser_script());
566 if (! *del_script)
567 return -1;
568 all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
569 ret = smbrun(del_script,NULL);
570 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
571 return ret;
574 /****************************************************************************
575 Check user is in correct domain if required
576 ****************************************************************************/
578 static BOOL check_domain_match(char *user, char *domain)
581 * If we aren't serving to trusted domains, we must make sure that
582 * the validation request comes from an account in the same domain
583 * as the Samba server
586 if (!lp_allow_trusted_domains() &&
587 !strequal(lp_workgroup(), domain) ) {
588 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
589 return False;
590 } else {
591 return True;
595 /****************************************************************************
596 Check for a valid username and password in security=server mode.
597 ****************************************************************************/
599 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
600 char *smb_apasswd, int smb_apasslen,
601 char *smb_ntpasswd, int smb_ntpasslen)
603 BOOL ret = False;
605 if(lp_security() != SEC_SERVER)
606 return False;
608 if (!check_domain_match(orig_user, domain))
609 return False;
611 ret = server_validate(orig_user, domain,
612 smb_apasswd, smb_apasslen,
613 smb_ntpasswd, smb_ntpasslen);
615 if(ret) {
617 * User validated ok against Domain controller.
618 * If the admin wants us to try and create a UNIX
619 * user on the fly, do so.
620 * Note that we can never delete users when in server
621 * level security as we never know if it was a failure
622 * due to a bad password, or the user really doesn't exist.
625 if(lp_adduser_script() && !smb_getpwnam(unix_user,True))
626 smb_create_user(unix_user, NULL);
629 return ret;
632 /****************************************************************************
633 Check for a valid username and password in security=domain mode.
634 ****************************************************************************/
636 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
637 char *smb_apasswd, int smb_apasslen,
638 char *smb_ntpasswd, int smb_ntpasslen, NT_USER_TOKEN **pptoken)
640 BOOL ret = False;
641 BOOL user_exists = True;
642 struct passwd *pwd = NULL;
644 if(lp_security() != SEC_DOMAIN)
645 return False;
647 if (!check_domain_match(orig_user, domain))
648 return False;
650 ret = domain_client_validate(orig_user, domain,
651 smb_apasswd, smb_apasslen,
652 smb_ntpasswd, smb_ntpasslen,
653 &user_exists, pptoken);
655 if(ret) {
657 * User validated ok against Domain controller.
658 * If the admin wants us to try and create a UNIX
659 * user on the fly, do so.
661 if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
662 smb_create_user(unix_user, NULL);
665 if(lp_adduser_script() && pwd) {
666 SMB_STRUCT_STAT st;
669 * Also call smb_create_user if the users home directory
670 * doesn't exist. Used with winbindd to allow the script to
671 * create the home directory for a user mapped with winbindd.
674 if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
675 smb_create_user(unix_user, pwd->pw_dir);
678 } else {
680 * User failed to validate ok against Domain controller.
681 * If the failure was "user doesn't exist" and admin
682 * wants us to try and delete that UNIX user on the fly,
683 * do so.
685 if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) {
686 smb_delete_user(unix_user);
690 return ret;
693 /****************************************************************************
694 Reply to a session setup command.
695 ****************************************************************************/
697 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
699 int sess_vuid;
700 gid_t gid;
701 uid_t uid;
702 int smb_bufsize;
703 int smb_apasslen = 0;
704 pstring smb_apasswd;
705 int smb_ntpasslen = 0;
706 pstring smb_ntpasswd;
707 BOOL valid_nt_password = False;
708 BOOL valid_lm_password = False;
709 fstring user;
710 fstring orig_user;
711 BOOL guest=False;
712 static BOOL done_sesssetup = False;
713 BOOL doencrypt = SMBENCRYPT();
714 fstring domain;
715 NT_USER_TOKEN *ptok = NULL;
717 START_PROFILE(SMBsesssetupX);
719 *smb_apasswd = 0;
720 *smb_ntpasswd = 0;
721 *domain = 0;
723 smb_bufsize = SVAL(inbuf,smb_vwv2);
725 if (Protocol < PROTOCOL_NT1) {
726 smb_apasslen = SVAL(inbuf,smb_vwv7);
727 if (smb_apasslen > MAX_PASS_LEN) {
728 overflow_attack(smb_apasslen);
729 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
732 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
733 smb_apasswd[smb_apasslen] = 0;
734 fstrcpy(user,smb_buf(inbuf)+smb_apasslen);
736 * Incoming user is in DOS codepage format. Convert
737 * to UNIX.
739 fstrcpy(user,dos_to_unix_static(user));
741 if (!doencrypt && (lp_security() != SEC_SERVER)) {
742 smb_apasslen = strlen(smb_apasswd);
744 } else {
745 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
746 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
747 enum remote_arch_types ra_type = get_remote_arch();
748 char *p = smb_buf(inbuf);
749 char *username_str;
750 fstring native_lanman;
753 if(global_client_caps == 0)
754 global_client_caps = IVAL(inbuf,smb_vwv11);
756 /* client_caps is used as final determination if client is NT or Win95.
757 This is needed to return the correct error codes in some
758 circumstances.
761 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
762 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
763 set_remote_arch( RA_WIN95);
767 username_str = smb_buf(inbuf)+smb_apasslen;
768 fstrcpy( native_lanman, skip_string(username_str, 3));
771 * we distinguish between 2K and XP by the "Native Lan Manager"
772 * string.
773 * .NET RC2 => "Windows .NET 5.2"
774 * WinXP => "Windows 2002 5.1"
775 * Win2k => "Windows 2000 5.0"
776 * NT4 => (off by one bug) "Windows NT 4.0"
777 * Win9x => "Windows 4.0"
779 if ( ra_type == RA_WIN2K ) {
780 if ( 0 == strcmp( native_lanman, "Windows 2002 5.1" ) )
781 set_remote_arch( RA_WINXP );
782 else if ( 0 == strcmp( native_lanman, "Windows .NET 5.2" ) )
783 set_remote_arch( RA_WIN2K3 );
786 if (passlen1 != 24 && passlen2 != 24)
787 doencrypt = False;
789 if (passlen1 > MAX_PASS_LEN) {
790 overflow_attack(passlen1);
791 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
794 passlen1 = MIN(passlen1, MAX_PASS_LEN);
795 passlen2 = MIN(passlen2, MAX_PASS_LEN);
797 if(!doencrypt) {
798 /* both Win95 and WinNT stuff up the password lengths for
799 non-encrypting systems. Uggh.
801 if passlen1==24 its a win95 system, and its setting the
802 password length incorrectly. Luckily it still works with the
803 default code because Win95 will null terminate the password
804 anyway
806 if passlen1>0 and passlen2>0 then maybe its a NT box and its
807 setting passlen2 to some random value which really stuffs
808 things up. we need to fix that one. */
810 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
811 passlen2 = 0;
814 if (lp_restrict_anonymous()) {
815 /* there seems to be no reason behind the differences in MS clients formatting
816 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
817 * in particular seems to have an extra null byte between the username and the
818 * domain, or the password length calculation is wrong, which throws off the
819 * string extraction routines below. This makes the value of domain be the
820 * empty string, which fails the restrict anonymous check further down.
821 * This compensates for that, and allows browsing to work in mixed NT and
822 * win95 environments even when restrict anonymous is true. AAB
824 dump_data(100, p, 0x70);
825 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
826 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
827 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
828 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
829 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
830 passlen1 = 1;
834 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
835 /* Save the lanman2 password and the NT md4 password. */
836 smb_apasslen = passlen1;
837 memcpy(smb_apasswd,p,smb_apasslen);
838 smb_apasswd[smb_apasslen] = 0;
839 smb_ntpasslen = passlen2;
840 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
841 smb_ntpasswd[smb_ntpasslen] = 0;
844 * Ensure the plaintext passwords are in UNIX format.
846 if(!doencrypt) {
847 pstrcpy(smb_apasswd,dos_to_unix_static(smb_apasswd));
848 pstrcpy(smb_ntpasswd,dos_to_unix_static(smb_ntpasswd));
851 } else {
852 /* we use the first password that they gave */
853 smb_apasslen = passlen1;
854 StrnCpy(smb_apasswd,p,smb_apasslen);
856 * Ensure the plaintext password is in UNIX format.
858 pstrcpy(smb_apasswd,dos_to_unix_static(smb_apasswd));
860 /* trim the password */
861 smb_apasslen = strlen(smb_apasswd);
863 /* wfwg sometimes uses a space instead of a null */
864 if (strequal(smb_apasswd," ")) {
865 smb_apasslen = 0;
866 *smb_apasswd = 0;
870 p += passlen1 + passlen2;
871 fstrcpy(user,p);
872 p = skip_string(p,1);
874 * Incoming user and domain are in DOS codepage format. Convert
875 * to UNIX.
877 fstrcpy(user,dos_to_unix_static(user));
878 fstrcpy(domain, dos_to_unix_static(p));
879 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
880 domain,skip_string(p,1),skip_string(p,2)));
883 /* don't allow strange characters in usernames or domains */
884 alpha_strcpy(user, user, ". _-$", sizeof(user));
885 alpha_strcpy(domain, domain, ". _-@", sizeof(domain));
886 if (strstr(user, "..") || strstr(domain,"..")) {
887 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
890 DEBUG(3,("sesssetupX:name=[%s]\n",user));
892 /* If name ends in $ then I think it's asking about whether a */
893 /* computer with that name (minus the $) has access. For now */
894 /* say yes to everything ending in $. */
896 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
897 END_PROFILE(SMBsesssetupX);
898 return session_trust_account(conn, inbuf, outbuf, user,
899 smb_apasswd, smb_apasslen,
900 smb_ntpasswd, smb_ntpasslen);
903 if (done_sesssetup && lp_restrict_anonymous()) {
904 /* tests show that even if browsing is done over already validated connections
905 * without a username and password the domain is still provided, which it
906 * wouldn't be if it was a purely anonymous connection. So, in order to
907 * restrict anonymous, we only deny connections that have no session
908 * information. If a domain has been provided, then it's not a purely
909 * anonymous connection. AAB
911 if (!*user && !*smb_apasswd && !*domain) {
912 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
913 END_PROFILE(SMBsesssetupX);
914 return(ERROR_DOS(ERRDOS,ERRnoaccess));
918 /* setup %U substitution */
919 sub_set_smb_name(user);
921 /* If no username is sent use the guest account */
922 if (!*user) {
923 fstrcpy(user,lp_guestaccount(-1));
924 guest = True;
927 fstrcpy(current_user_info.smb_name,user);
929 reload_services(True);
932 * Save the username before mapping. We will use
933 * the original username sent to us for security=server
934 * and security=domain checking.
937 fstrcpy( orig_user, user);
940 * Always try the "DOMAIN\user" lookup first, as this is the most
941 * specific case. If this fails then try the simple "user" lookup.
945 fstring dom_user;
947 /* Work out who's who */
949 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
950 domain, lp_winbind_separator(), user);
952 if (sys_getpwnam(dom_user) != NULL) {
953 fstrcpy(user, dom_user);
954 DEBUG(3,("Using unix username %s\n", dom_user));
959 * Pass the user through the NT -> unix user mapping
960 * function.
963 (void)map_username(user);
966 * Do any UNIX username case mangling.
968 smb_getpwnam(user, True);
970 add_session_user(user);
973 * Check with orig_user for security=server and
974 * security=domain.
977 if (!guest && !check_server_security(orig_user, domain, user,
978 smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
979 !check_domain_security(orig_user, domain, user, smb_apasswd,
980 smb_apasslen, smb_ntpasswd, smb_ntpasslen, &ptok) &&
981 !check_hosts_equiv(user))
985 * If we get here then the user wasn't guest and the remote
986 * authentication methods failed. Check the authentication
987 * methods on this local server.
989 * If an NT password was supplied try and validate with that
990 * first. This is superior as the passwords are mixed case
991 * 128 length unicode.
994 if(smb_ntpasslen)
996 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
997 DEBUG(2,("NT Password did not match for user '%s'!\n", user));
998 else
999 valid_nt_password = True;
1003 /* check the LanMan password only if necessary and if allowed
1004 by lp_lanman_auth() */
1005 if (!valid_nt_password && lp_lanman_auth())
1007 DEBUG(2,("Defaulting to Lanman password for %s\n", user));
1008 valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen,NULL);
1012 /* The true branch will be executed if
1013 (1) the NT password failed (or was not tried), and
1014 (2) LanMan authentication failed (or was disabled)
1016 if (!valid_nt_password && !valid_lm_password)
1018 if (lp_security() >= SEC_USER)
1020 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
1022 delete_nt_token(&ptok);
1023 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
1024 END_PROFILE(SMBsesssetupX);
1025 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
1028 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
1030 SAM_ACCOUNT *sampass = NULL;
1032 pdb_init_sam(&sampass);
1035 * This is really bad form. We know that password_ok() failed,
1036 * but the return value can't distinguish between a non-existent user
1037 * and a bad password. So we try to look the user up again here
1038 * to see if he or she exists. We must look up the user in the
1039 * "smb passwd file" and not /etc/passwd so that we don't
1040 * get confused when the two don't have a one-to-one correspondence.
1041 * e.g. a standard UNIX account such as "operator" --jerry
1044 if (pdb_getsampwnam(sampass, user))
1046 delete_nt_token(&ptok);
1047 DEBUG(1,("Rejecting user '%s': bad password\n", user));
1048 END_PROFILE(SMBsesssetupX);
1049 pdb_free_sam(sampass);
1050 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
1053 pdb_free_sam(sampass);
1057 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
1058 * Then always map to guest account - as done below.
1062 if (*smb_apasswd || !smb_getpwnam(user,True))
1063 fstrcpy(user,lp_guestaccount(-1));
1064 DEBUG(3,("Registered username %s for guest access\n",user));
1065 guest = True;
1069 if (!smb_getpwnam(user,True)) {
1070 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
1071 fstrcpy(user,lp_guestaccount(-1));
1072 guest = True;
1075 if (!strequal(user,lp_guestaccount(-1)) &&
1076 lp_servicenumber(user) < 0)
1078 add_home_service(user,get_user_service_home_dir(user));
1082 /* it's ok - setup a reply */
1083 if (Protocol < PROTOCOL_NT1) {
1084 set_message(outbuf,3,0,True);
1085 } else {
1086 char *p;
1087 set_message(outbuf,3,3,True);
1088 p = smb_buf(outbuf);
1089 pstrcpy(p,"Unix"); p = skip_string(p,1);
1090 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
1091 pstrcpy(p,global_myworkgroup); unix_to_dos(p); p = skip_string(p,1);
1092 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
1093 /* perhaps grab OS version here?? */
1096 /* Set the correct uid in the outgoing and incoming packets
1097 We will use this on future requests to determine which
1098 user we should become.
1101 const struct passwd *pw = smb_getpwnam(user,False);
1102 if (!pw) {
1103 delete_nt_token(&ptok);
1104 DEBUG(1,("Username %s is invalid on this system\n",user));
1105 END_PROFILE(SMBsesssetupX);
1106 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
1108 gid = pw->pw_gid;
1109 uid = pw->pw_uid;
1112 if (guest)
1113 SSVAL(outbuf,smb_vwv2,1);
1115 /* register the name and uid as being validated, so further connections
1116 to a uid can get through without a password, on the same VC */
1118 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest,&ptok);
1120 delete_nt_token(&ptok);
1122 if (sess_vuid == -1) {
1123 END_PROFILE(SMBsesssetupX);
1124 return(ERROR_DOS(ERRDOS,ERRnoaccess));
1127 SSVAL(outbuf,smb_uid,sess_vuid);
1128 SSVAL(inbuf,smb_uid,sess_vuid);
1130 if (!done_sesssetup)
1131 max_send = MIN(max_send,smb_bufsize);
1133 DEBUG(6,("Client requested max send size of %d\n", max_send));
1135 done_sesssetup = True;
1137 END_PROFILE(SMBsesssetupX);
1138 return chain_reply(inbuf,outbuf,length,bufsize);
1141 /****************************************************************************
1142 Reply to a chkpth.
1143 ****************************************************************************/
1145 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1147 int outsize = 0;
1148 int mode;
1149 pstring name;
1150 BOOL ok = False;
1151 BOOL bad_path = False;
1152 SMB_STRUCT_STAT sbuf;
1153 START_PROFILE(SMBchkpth);
1155 pstrcpy(name,smb_buf(inbuf) + 1);
1157 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1159 unix_convert(name,conn,0,&bad_path,&sbuf);
1161 mode = SVAL(inbuf,smb_vwv0);
1163 if (check_name(name,conn)) {
1164 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
1165 if (!(ok = S_ISDIR(sbuf.st_mode)))
1166 errno = ENOTDIR;
1170 if (!ok) {
1171 /* We special case this - as when a Windows machine
1172 is parsing a path is steps through the components
1173 one at a time - if a component fails it expects
1174 ERRbadpath, not ERRbadfile.
1176 if(errno == ENOENT) {
1177 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1180 return(UNIXERROR(ERRDOS,ERRbadpath));
1183 outsize = set_message(outbuf,0,0,True);
1185 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1187 END_PROFILE(SMBchkpth);
1188 return(outsize);
1191 /****************************************************************************
1192 Reply to a getatr.
1193 ****************************************************************************/
1195 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1197 pstring fname;
1198 int outsize = 0;
1199 SMB_STRUCT_STAT sbuf;
1200 BOOL ok = False;
1201 int mode=0;
1202 SMB_OFF_T size=0;
1203 time_t mtime=0;
1204 BOOL bad_path = False;
1205 START_PROFILE(SMBgetatr);
1207 pstrcpy(fname,smb_buf(inbuf) + 1);
1209 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1211 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1212 under WfWg - weird! */
1213 if (! (*fname))
1215 mode = aHIDDEN | aDIR;
1216 if (!CAN_WRITE(conn)) mode |= aRONLY;
1217 size = 0;
1218 mtime = 0;
1219 ok = True;
1221 else
1223 unix_convert(fname,conn,0,&bad_path,&sbuf);
1224 if (check_name(fname,conn))
1226 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1228 mode = dos_mode(conn,fname,&sbuf);
1229 size = sbuf.st_size;
1230 mtime = sbuf.st_mtime;
1231 if (mode & aDIR)
1232 size = 0;
1233 ok = True;
1235 else
1236 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1240 if (!ok)
1242 set_bad_path_error(errno, bad_path);
1243 END_PROFILE(SMBgetatr);
1244 return(UNIXERROR(ERRDOS,ERRbadfile));
1247 outsize = set_message(outbuf,10,0,True);
1249 SSVAL(outbuf,smb_vwv0,mode);
1250 if(lp_dos_filetime_resolution(SNUM(conn)) )
1251 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1252 else
1253 put_dos_date3(outbuf,smb_vwv1,mtime);
1254 SIVAL(outbuf,smb_vwv3,(uint32)size);
1256 if (Protocol >= PROTOCOL_NT1)
1257 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1259 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1261 END_PROFILE(SMBgetatr);
1262 return(outsize);
1265 /****************************************************************************
1266 Reply to a setatr.
1267 ****************************************************************************/
1269 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1271 pstring fname;
1272 int outsize = 0;
1273 BOOL ok=False;
1274 int mode;
1275 time_t mtime;
1276 SMB_STRUCT_STAT sbuf;
1277 BOOL bad_path = False;
1278 START_PROFILE(SMBsetatr);
1280 pstrcpy(fname,smb_buf(inbuf) + 1);
1281 unix_convert(fname,conn,0,&bad_path,&sbuf);
1283 mode = SVAL(inbuf,smb_vwv0);
1284 mtime = make_unix_date3(inbuf+smb_vwv1);
1286 if (VALID_STAT_OF_DIR(sbuf))
1287 mode |= aDIR;
1288 else
1289 mode &= ~aDIR;
1291 if (check_name(fname,conn))
1292 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1293 if (ok)
1294 ok = set_filetime(conn,fname,mtime);
1296 if (!ok)
1298 set_bad_path_error(errno, bad_path);
1299 END_PROFILE(SMBsetatr);
1300 return(UNIXERROR(ERRDOS,ERRnoaccess));
1303 outsize = set_message(outbuf,0,0,True);
1305 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1307 END_PROFILE(SMBsetatr);
1308 return(outsize);
1311 /****************************************************************************
1312 Reply to a dskattr.
1313 ****************************************************************************/
1315 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1317 int outsize = 0;
1318 SMB_BIG_UINT dfree,dsize,bsize;
1319 START_PROFILE(SMBdskattr);
1321 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1323 outsize = set_message(outbuf,5,0,True);
1325 if (Protocol <= PROTOCOL_LANMAN2) {
1326 double total_space, free_space;
1327 /* we need to scale this to a number that DOS6 can handle. We
1328 use floating point so we can handle large drives on systems
1329 that don't have 64 bit integers
1331 we end up displaying a maximum of 2G to DOS systems
1333 total_space = dsize * (double)bsize;
1334 free_space = dfree * (double)bsize;
1336 dsize = (total_space+63*512) / (64*512);
1337 dfree = (free_space+63*512) / (64*512);
1339 if (dsize > 0xFFFF) dsize = 0xFFFF;
1340 if (dfree > 0xFFFF) dfree = 0xFFFF;
1342 SSVAL(outbuf,smb_vwv0,dsize);
1343 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1344 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
1345 SSVAL(outbuf,smb_vwv3,dfree);
1346 } else {
1347 SSVAL(outbuf,smb_vwv0,dsize);
1348 SSVAL(outbuf,smb_vwv1,bsize/512);
1349 SSVAL(outbuf,smb_vwv2,512);
1350 SSVAL(outbuf,smb_vwv3,dfree);
1353 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1355 END_PROFILE(SMBdskattr);
1356 return(outsize);
1359 /****************************************************************************
1360 Reply to a search.
1361 Can be called from SMBsearch, SMBffirst or SMBfunique.
1362 ****************************************************************************/
1364 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1366 pstring mask;
1367 pstring directory;
1368 pstring fname;
1369 SMB_OFF_T size;
1370 int mode;
1371 time_t date;
1372 int dirtype;
1373 int outsize = 0;
1374 int numentries = 0;
1375 BOOL finished = False;
1376 int maxentries;
1377 int i;
1378 char *p;
1379 BOOL ok = False;
1380 int status_len;
1381 char *path;
1382 char status[21];
1383 int dptr_num= -1;
1384 BOOL check_descend = False;
1385 BOOL expect_close = False;
1386 BOOL can_open = True;
1387 BOOL bad_path = False;
1388 START_PROFILE(SMBsearch);
1390 *mask = *directory = *fname = 0;
1392 /* If we were called as SMBffirst then we must expect close. */
1393 if(CVAL(inbuf,smb_com) == SMBffirst)
1394 expect_close = True;
1396 outsize = set_message(outbuf,1,3,True);
1397 maxentries = SVAL(inbuf,smb_vwv0);
1398 dirtype = SVAL(inbuf,smb_vwv1);
1399 path = smb_buf(inbuf) + 1;
1400 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1402 RESOLVE_DFSPATH(path, conn, inbuf, outbuf);
1403 /* dirtype &= ~aDIR; */
1405 if (status_len == 0)
1407 SMB_STRUCT_STAT sbuf;
1408 pstring dir2;
1410 pstrcpy(directory,smb_buf(inbuf)+1);
1411 pstrcpy(dir2,smb_buf(inbuf)+1);
1412 unix_convert(directory,conn,0,&bad_path,&sbuf);
1413 unix_format(dir2);
1415 if (!check_name(directory,conn))
1416 can_open = False;
1418 p = strrchr(dir2,'/');
1419 if (p == NULL)
1421 pstrcpy(mask,dir2);
1422 *dir2 = 0;
1424 else
1426 *p = 0;
1427 pstrcpy(mask,p+1);
1430 p = strrchr(directory,'/');
1431 if (!p)
1432 *directory = 0;
1433 else
1434 *p = 0;
1436 if (strlen(directory) == 0)
1437 pstrcpy(directory,"./");
1438 memset((char *)status,'\0',21);
1439 SCVAL(status,0,(dirtype & 0x1F));
1441 else
1443 int status_dirtype;
1444 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1445 status_dirtype = CVAL(status,0) & 0x1F;
1446 if (status_dirtype != (dirtype & 0x1F))
1447 dirtype = status_dirtype;
1448 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1449 if (!conn->dirptr)
1450 goto SearchEmpty;
1451 string_set(&conn->dirpath,dptr_path(dptr_num));
1452 fstrcpy(mask, dptr_wcard(dptr_num));
1455 if (can_open)
1457 p = smb_buf(outbuf) + 3;
1459 ok = True;
1461 if (status_len == 0)
1463 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1464 if (dptr_num < 0)
1466 if(dptr_num == -2)
1468 set_bad_path_error(errno, bad_path);
1469 END_PROFILE(SMBsearch);
1470 return (UNIXERROR(ERRDOS,ERRnofids));
1472 END_PROFILE(SMBsearch);
1473 return ERROR_DOS(ERRDOS,ERRnofids);
1475 dptr_set_wcard(dptr_num, strdup(mask));
1476 dptr_set_attr(dptr_num, dirtype);
1477 } else {
1478 dirtype = dptr_attr(dptr_num);
1481 DEBUG(4,("dptr_num is %d\n",dptr_num));
1483 if (ok)
1485 if ((dirtype&0x1F) == aVOLID)
1487 memcpy(p,status,21);
1488 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1489 dptr_fill(p+12,dptr_num);
1490 if (dptr_zero(p+12) && (status_len==0))
1491 numentries = 1;
1492 else
1493 numentries = 0;
1494 p += DIR_STRUCT_SIZE;
1496 else
1498 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1499 conn->dirpath,lp_dontdescend(SNUM(conn))));
1500 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1501 check_descend = True;
1503 for (i=numentries;(i<maxentries) && !finished;i++)
1505 /* check to make sure we have room in the buffer */
1506 if ( ((PTR_DIFF(p, outbuf))+DIR_STRUCT_SIZE) > BUFFER_SIZE )
1507 break;
1508 finished =
1509 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1510 if (!finished)
1512 memcpy(p,status,21);
1513 make_dir_struct(p,mask,fname,size,mode,date);
1514 dptr_fill(p+12,dptr_num);
1515 numentries++;
1517 p += DIR_STRUCT_SIZE;
1520 } /* if (ok ) */
1524 SearchEmpty:
1526 if ( (numentries == 0) || !ok)
1528 SCVAL(outbuf,smb_rcls,ERRDOS);
1529 SSVAL(outbuf,smb_err,ERRnofiles);
1530 dptr_close(&dptr_num);
1533 /* If we were called as SMBffirst with smb_search_id == NULL
1534 and no entries were found then return error and close dirptr
1535 (X/Open spec) */
1537 if(ok && expect_close && numentries == 0 && status_len == 0)
1539 SCVAL(outbuf,smb_rcls,ERRDOS);
1540 SSVAL(outbuf,smb_err,ERRnofiles);
1541 /* Also close the dptr - we know it's gone */
1542 dptr_close(&dptr_num);
1545 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1546 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1547 dptr_close(&dptr_num);
1549 SSVAL(outbuf,smb_vwv0,numentries);
1550 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1551 SCVAL(smb_buf(outbuf),0,5);
1552 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1554 if (Protocol >= PROTOCOL_NT1)
1555 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1557 outsize += DIR_STRUCT_SIZE*numentries;
1558 smb_setlen(outbuf,outsize - 4);
1560 if ((! *directory) && dptr_path(dptr_num))
1561 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1563 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1564 smb_fn_name(CVAL(inbuf,smb_com)),
1565 mask, directory, dirtype, numentries, maxentries ) );
1567 END_PROFILE(SMBsearch);
1568 return(outsize);
1571 /****************************************************************************
1572 Reply to a fclose (stop directory search).
1573 ****************************************************************************/
1575 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1577 int outsize = 0;
1578 int status_len;
1579 char *path;
1580 char status[21];
1581 int dptr_num= -2;
1582 START_PROFILE(SMBfclose);
1584 outsize = set_message(outbuf,1,0,True);
1585 path = smb_buf(inbuf) + 1;
1586 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1589 if (status_len == 0) {
1590 END_PROFILE(SMBfclose);
1591 return ERROR_DOS(ERRSRV,ERRsrverror);
1594 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1596 if(dptr_fetch(status+12,&dptr_num)) {
1597 /* Close the dptr - we know it's gone */
1598 dptr_close(&dptr_num);
1601 SSVAL(outbuf,smb_vwv0,0);
1603 DEBUG(3,("search close\n"));
1605 END_PROFILE(SMBfclose);
1606 return(outsize);
1609 /****************************************************************************
1610 Reply to an open.
1611 ****************************************************************************/
1613 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1615 pstring fname;
1616 int outsize = 0;
1617 int fmode=0;
1618 int share_mode;
1619 SMB_OFF_T size = 0;
1620 time_t mtime=0;
1621 mode_t unixmode;
1622 int rmode=0;
1623 SMB_STRUCT_STAT sbuf;
1624 BOOL bad_path = False;
1625 files_struct *fsp;
1626 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1627 START_PROFILE(SMBopen);
1629 share_mode = SVAL(inbuf,smb_vwv0);
1631 pstrcpy(fname,smb_buf(inbuf)+1);
1633 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1635 unix_convert(fname,conn,0,&bad_path,&sbuf);
1637 unixmode = unix_mode(conn,aARCH,fname);
1639 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1640 unixmode, oplock_request,&rmode,NULL);
1642 if (!fsp)
1644 set_bad_path_error(errno, bad_path);
1645 END_PROFILE(SMBopen);
1646 return(UNIXERROR(ERRDOS,ERRnoaccess));
1649 size = sbuf.st_size;
1650 fmode = dos_mode(conn,fname,&sbuf);
1651 mtime = sbuf.st_mtime;
1653 if (fmode & aDIR) {
1654 DEBUG(3,("attempt to open a directory %s\n",fname));
1655 close_file(fsp,False);
1656 END_PROFILE(SMBopen);
1657 return ERROR_DOS(ERRDOS,ERRnoaccess);
1660 outsize = set_message(outbuf,7,0,True);
1661 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1662 SSVAL(outbuf,smb_vwv1,fmode);
1663 if(lp_dos_filetime_resolution(SNUM(conn)) )
1664 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1665 else
1666 put_dos_date3(outbuf,smb_vwv2,mtime);
1667 SIVAL(outbuf,smb_vwv4,(uint32)size);
1668 SSVAL(outbuf,smb_vwv6,rmode);
1670 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1671 SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1674 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1675 SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1676 END_PROFILE(SMBopen);
1677 return(outsize);
1680 /****************************************************************************
1681 Reply to an open and X.
1682 ****************************************************************************/
1684 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1686 pstring fname;
1687 int smb_mode = SVAL(inbuf,smb_vwv3);
1688 int smb_attr = SVAL(inbuf,smb_vwv5);
1689 /* Breakout the oplock request bits so we can set the
1690 reply bits separately. */
1691 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1692 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1693 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1694 #if 0
1695 int open_flags = SVAL(inbuf,smb_vwv2);
1696 int smb_sattr = SVAL(inbuf,smb_vwv4);
1697 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1698 #endif
1699 int smb_ofun = SVAL(inbuf,smb_vwv8);
1700 mode_t unixmode;
1701 SMB_OFF_T size=0;
1702 int fmode=0,mtime=0,rmode=0;
1703 SMB_STRUCT_STAT sbuf;
1704 int smb_action = 0;
1705 BOOL bad_path = False;
1706 files_struct *fsp;
1707 START_PROFILE(SMBopenX);
1709 /* If it's an IPC, pass off the pipe handler. */
1710 if (IS_IPC(conn)) {
1711 if (lp_nt_pipe_support()) {
1712 END_PROFILE(SMBopenX);
1713 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1714 } else {
1715 END_PROFILE(SMBopenX);
1716 return ERROR_DOS(ERRSRV,ERRaccess);
1720 /* XXXX we need to handle passed times, sattr and flags */
1722 pstrcpy(fname,smb_buf(inbuf));
1724 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1726 unix_convert(fname,conn,0,&bad_path,&sbuf);
1728 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1730 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1731 oplock_request, &rmode,&smb_action);
1733 if (!fsp)
1735 set_bad_path_error(errno, bad_path);
1736 END_PROFILE(SMBopenX);
1737 return(UNIXERROR(ERRDOS,ERRnoaccess));
1740 size = sbuf.st_size;
1741 fmode = dos_mode(conn,fname,&sbuf);
1742 mtime = sbuf.st_mtime;
1743 if (fmode & aDIR) {
1744 close_file(fsp,False);
1745 END_PROFILE(SMBopenX);
1746 return ERROR_DOS(ERRDOS,ERRnoaccess);
1749 /* If the caller set the extended oplock request bit
1750 and we granted one (by whatever means) - set the
1751 correct bit for extended oplock reply.
1754 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1755 smb_action |= EXTENDED_OPLOCK_GRANTED;
1758 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1759 smb_action |= EXTENDED_OPLOCK_GRANTED;
1762 /* If the caller set the core oplock request bit
1763 and we granted one (by whatever means) - set the
1764 correct bit for core oplock reply.
1767 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1768 SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1771 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1772 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1775 set_message(outbuf,15,0,True);
1776 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1777 SSVAL(outbuf,smb_vwv3,fmode);
1778 if(lp_dos_filetime_resolution(SNUM(conn)) )
1779 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1780 else
1781 put_dos_date3(outbuf,smb_vwv4,mtime);
1782 SIVAL(outbuf,smb_vwv6,(uint32)size);
1783 SSVAL(outbuf,smb_vwv8,rmode);
1784 SSVAL(outbuf,smb_vwv11,smb_action);
1786 END_PROFILE(SMBopenX);
1787 return chain_reply(inbuf,outbuf,length,bufsize);
1790 /****************************************************************************
1791 Reply to a SMBulogoffX.
1792 ****************************************************************************/
1794 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1796 uint16 vuid = SVAL(inbuf,smb_uid);
1797 user_struct *vuser = get_valid_user_struct(vuid);
1798 START_PROFILE(SMBulogoffX);
1800 if(vuser == 0) {
1801 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1804 /* in user level security we are supposed to close any files
1805 open by this user */
1806 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1807 file_close_user(vuid);
1810 invalidate_vuid(vuid);
1812 set_message(outbuf,2,0,True);
1814 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1816 END_PROFILE(SMBulogoffX);
1817 return chain_reply(inbuf,outbuf,length,bufsize);
1820 /****************************************************************************
1821 Reply to a mknew or a create.
1822 ****************************************************************************/
1824 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1826 pstring fname;
1827 int com;
1828 int outsize = 0;
1829 int createmode;
1830 mode_t unixmode;
1831 int ofun = 0;
1832 BOOL bad_path = False;
1833 files_struct *fsp;
1834 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1835 SMB_STRUCT_STAT sbuf;
1836 START_PROFILE(SMBcreate);
1838 com = SVAL(inbuf,smb_com);
1840 createmode = SVAL(inbuf,smb_vwv0);
1841 pstrcpy(fname,smb_buf(inbuf)+1);
1843 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1845 unix_convert(fname,conn,0,&bad_path,&sbuf);
1847 if (createmode & aVOLID) {
1848 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1851 unixmode = unix_mode(conn,createmode,fname);
1853 if(com == SMBmknew)
1855 /* We should fail if file exists. */
1856 ofun = FILE_CREATE_IF_NOT_EXIST;
1858 else
1860 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1861 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1864 /* Open file in dos compatibility share mode. */
1865 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1866 ofun, unixmode, oplock_request, NULL, NULL);
1868 if (!fsp)
1870 set_bad_path_error(errno, bad_path);
1871 END_PROFILE(SMBcreate);
1872 return(UNIXERROR(ERRDOS,ERRnoaccess));
1875 outsize = set_message(outbuf,1,0,True);
1876 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1878 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1879 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1882 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1883 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1885 DEBUG( 2, ( "new file %s\n", fname ) );
1886 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1887 fname, fsp->fd, createmode, (int)unixmode ) );
1889 END_PROFILE(SMBcreate);
1890 return(outsize);
1893 /****************************************************************************
1894 Reply to a create temporary file.
1895 ****************************************************************************/
1897 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1899 pstring fname;
1900 int outsize = 0;
1901 int createmode;
1902 mode_t unixmode;
1903 BOOL bad_path = False;
1904 files_struct *fsp;
1905 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1906 int tmpfd;
1907 SMB_STRUCT_STAT sbuf;
1908 char *p, *s;
1910 START_PROFILE(SMBctemp);
1912 createmode = SVAL(inbuf,smb_vwv0);
1913 pstrcpy(fname,smb_buf(inbuf)+1);
1914 pstrcat(fname,"\\TMXXXXXX");
1916 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1918 unix_convert(fname,conn,0,&bad_path,&sbuf);
1920 unixmode = unix_mode(conn,createmode,fname);
1922 tmpfd = smb_mkstemp(fname);
1923 if (tmpfd == -1) {
1924 END_PROFILE(SMBctemp);
1925 return(UNIXERROR(ERRDOS,ERRnoaccess));
1928 vfs_stat(conn,fname,&sbuf);
1930 /* Open file in dos compatibility share mode. */
1931 /* We should fail if file does not exist. */
1932 fsp = open_file_shared(conn,fname,&sbuf,
1933 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1934 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1935 unixmode, oplock_request, NULL, NULL);
1936 /* close fd from smb_mkstemp() */
1937 close(tmpfd);
1939 if (!fsp) {
1940 set_bad_path_error(errno, bad_path);
1941 END_PROFILE(SMBctemp);
1942 return(UNIXERROR(ERRDOS,ERRnoaccess));
1945 /* the returned filename is relative to the directory */
1946 s = strrchr(fname, '/');
1947 if (!s)
1948 s = fname;
1949 else
1950 s++;
1952 outsize = set_message(outbuf,1,4+ strlen(fname),True);
1953 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1955 p = smb_buf(outbuf);
1956 SSVALS(p, 0, -1); /* what is this? not in spec */
1957 SSVAL(p, 2, strlen(s));
1958 p += 4;
1959 pstrcpy(p,s);
1961 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1962 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1965 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1966 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1968 DEBUG( 2, ( "created temp file %s\n", fname ) );
1969 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1970 fname, fsp->fd, createmode, (int)unixmode ) );
1972 END_PROFILE(SMBctemp);
1973 return(outsize);
1976 /*******************************************************************
1977 Check if a user is allowed to rename a file.
1978 ********************************************************************/
1980 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1982 int smb_action;
1983 int access_mode;
1984 files_struct *fsp;
1986 if (!CAN_WRITE(conn))
1987 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1989 if (S_ISDIR(pst->st_mode))
1990 return NT_STATUS_OK;
1992 /* We need a better way to return NT status codes from open... */
1993 unix_ERR_class = 0;
1994 unix_ERR_code = 0;
1996 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1997 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1999 if (!fsp) {
2000 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
2001 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
2002 ret = unix_ERR_ntstatus;
2003 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
2004 ret = NT_STATUS_SHARING_VIOLATION;
2005 unix_ERR_class = 0;
2006 unix_ERR_code = 0;
2007 unix_ERR_ntstatus = NT_STATUS_OK;
2008 return ret;
2010 close_file(fsp,False);
2011 return NT_STATUS_OK;
2014 /*******************************************************************
2015 Check if a user is allowed to delete a file.
2016 ********************************************************************/
2018 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
2020 SMB_STRUCT_STAT sbuf;
2021 int fmode;
2022 int smb_action;
2023 int access_mode;
2024 files_struct *fsp;
2026 if (!CAN_WRITE(conn))
2027 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2029 if (conn->vfs_ops.lstat(conn,dos_to_unix_static(fname),&sbuf) != 0)
2030 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2032 fmode = dos_mode(conn,fname,&sbuf);
2033 if (fmode & aDIR)
2034 return NT_STATUS_FILE_IS_A_DIRECTORY;
2035 if (!lp_delete_readonly(SNUM(conn))) {
2036 if (fmode & aRONLY)
2037 return NT_STATUS_CANNOT_DELETE;
2040 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
2041 return NT_STATUS_CANNOT_DELETE;
2043 /* We need a better way to return NT status codes from open... */
2044 unix_ERR_class = 0;
2045 unix_ERR_code = 0;
2047 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
2048 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
2050 if (!fsp) {
2051 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
2052 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
2053 ret = NT_STATUS_SHARING_VIOLATION;
2054 unix_ERR_class = 0;
2055 unix_ERR_code = 0;
2056 return ret;
2058 close_file(fsp,False);
2059 return NT_STATUS_OK;
2062 /****************************************************************************
2063 The guts of the unlink command, split out so it may be called by the NT SMB
2064 code.
2065 ****************************************************************************/
2067 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
2069 pstring directory;
2070 pstring mask;
2071 char *p;
2072 int count=0;
2073 NTSTATUS error = NT_STATUS_OK;
2074 BOOL has_wild;
2075 BOOL bad_path = False;
2076 BOOL rc = True;
2077 SMB_STRUCT_STAT sbuf;
2079 *directory = *mask = 0;
2081 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
2083 p = strrchr(name,'/');
2084 if (!p) {
2085 pstrcpy(directory,".");
2086 pstrcpy(mask,name);
2087 } else {
2088 *p = 0;
2089 pstrcpy(directory,name);
2090 pstrcpy(mask,p+1);
2094 * We should only check the mangled cache
2095 * here if unix_convert failed. This means
2096 * that the path in 'mask' doesn't exist
2097 * on the file system and so we need to look
2098 * for a possible mangle. This patch from
2099 * Tine Smukavec <valentin.smukavec@hermes.si>.
2102 if (!rc && mangle_is_mangled(mask))
2103 mangle_check_cache( mask );
2105 has_wild = ms_has_wild(mask);
2107 if (!has_wild) {
2108 pstrcat(directory,"/");
2109 pstrcat(directory,mask);
2110 error = can_delete(directory,conn,dirtype);
2111 if (!NT_STATUS_IS_OK(error))
2112 return error;
2114 if (vfs_unlink(conn,directory) == 0)
2115 count++;
2116 } else {
2117 void *dirptr = NULL;
2118 char *dname;
2119 if (check_name(directory,conn))
2120 dirptr = OpenDir(conn, directory, True);
2122 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2123 the pattern matches against the long name, otherwise the short name
2124 We don't implement this yet XXXX
2127 if (dirptr) {
2128 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2130 if (strequal(mask,"????????.???"))
2131 pstrcpy(mask,"*");
2133 while ((dname = ReadDirName(dirptr))) {
2134 pstring fname;
2135 pstrcpy(fname,dname);
2137 if(!mask_match(fname, mask, case_sensitive))
2138 continue;
2140 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2141 error = can_delete(fname,conn,dirtype);
2142 if (!NT_STATUS_IS_OK(error))
2143 continue;
2144 if (vfs_unlink(conn,fname) == 0)
2145 count++;
2146 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2148 CloseDir(dirptr);
2152 if (count == 0 && NT_STATUS_IS_OK(error))
2153 error = map_nt_error_from_unix(errno);
2155 return error;
2158 /****************************************************************************
2159 Reply to a unlink
2160 ****************************************************************************/
2162 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2164 int outsize = 0;
2165 pstring name;
2166 int dirtype;
2167 NTSTATUS status;
2169 START_PROFILE(SMBunlink);
2171 dirtype = SVAL(inbuf,smb_vwv0);
2173 pstrcpy(name,smb_buf(inbuf) + 1);
2175 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
2177 DEBUG(3,("reply_unlink : %s\n",name));
2179 status = unlink_internals(conn, dirtype, name);
2180 if (!NT_STATUS_IS_OK(status))
2181 return ERROR_NT(status);
2184 * Win2k needs a changenotify request response before it will
2185 * update after a rename..
2188 process_pending_change_notify_queue((time_t)0);
2190 outsize = set_message(outbuf,0,0,True);
2192 END_PROFILE(SMBunlink);
2193 return outsize;
2196 /****************************************************************************
2197 Fail for readbraw.
2198 ****************************************************************************/
2200 void fail_readraw(void)
2202 pstring errstr;
2203 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2204 strerror(errno) );
2205 exit_server(errstr);
2208 /****************************************************************************
2209 Use sendfile in readbraw.
2210 ****************************************************************************/
2212 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2213 ssize_t mincount, char *outbuf)
2215 ssize_t ret=0;
2217 #if defined(WITH_SENDFILE)
2219 * We can only use sendfile on a non-chained packet and on a file
2220 * that is exclusively oplocked. reply_readbraw has already checked the length.
2223 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
2224 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
2225 DATA_BLOB header;
2227 _smb_setlen(outbuf,nread);
2228 header.data = outbuf;
2229 header.length = 4;
2230 header.free = NULL;
2232 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
2234 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2235 * return ENOSYS then pretend we just got a normal read.
2237 if (errno == ENOSYS)
2238 goto normal_read;
2240 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2241 fsp->fsp_name, strerror(errno) ));
2242 exit_server("send_file_readbraw sendfile failed");
2247 normal_read:
2248 #endif
2250 if (nread > 0) {
2251 ret = read_file(fsp,outbuf+4,startpos,nread);
2252 if (ret < mincount)
2253 ret = 0;
2256 _smb_setlen(outbuf,ret);
2257 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2258 fail_readraw();
2261 /****************************************************************************
2262 Reply to a readbraw (core+ protocol).
2263 ****************************************************************************/
2265 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2267 ssize_t maxcount,mincount;
2268 size_t nread = 0;
2269 SMB_OFF_T startpos;
2270 char *header = outbuf;
2271 files_struct *fsp;
2272 START_PROFILE(SMBreadbraw);
2275 * Special check if an oplock break has been issued
2276 * and the readraw request croses on the wire, we must
2277 * return a zero length response here.
2280 if(global_oplock_break) {
2281 _smb_setlen(header,0);
2282 if (write_data(smbd_server_fd(),header,4) != 4)
2283 fail_readraw();
2284 DEBUG(5,("readbraw - oplock break finished\n"));
2285 END_PROFILE(SMBreadbraw);
2286 return -1;
2289 fsp = file_fsp(inbuf,smb_vwv0);
2291 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2293 * fsp could be NULL here so use the value from the packet. JRA.
2295 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2296 _smb_setlen(header,0);
2297 if (write_data(smbd_server_fd(),header,4) != 4)
2298 fail_readraw();
2299 END_PROFILE(SMBreadbraw);
2300 return(-1);
2303 CHECK_FSP(fsp,conn);
2305 flush_write_cache(fsp, READRAW_FLUSH);
2307 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2308 if(CVAL(inbuf,smb_wct) == 10) {
2310 * This is a large offset (64 bit) read.
2312 #ifdef LARGE_SMB_OFF_T
2314 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2316 #else /* !LARGE_SMB_OFF_T */
2319 * Ensure we haven't been sent a >32 bit offset.
2322 if(IVAL(inbuf,smb_vwv8) != 0) {
2323 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2324 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2325 _smb_setlen(header,0);
2326 if (write_data(smbd_server_fd(),header,4) != 4)
2327 fail_readraw();
2328 END_PROFILE(SMBreadbraw);
2329 return(-1);
2332 #endif /* LARGE_SMB_OFF_T */
2334 if(startpos < 0) {
2335 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2336 _smb_setlen(header,0);
2337 if (write_data(smbd_server_fd(),header,4) != 4)
2338 fail_readraw();
2339 END_PROFILE(SMBreadbraw);
2340 return(-1);
2343 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2344 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2346 /* ensure we don't overrun the packet size */
2347 maxcount = MIN(65535,maxcount);
2348 maxcount = MAX(mincount,maxcount);
2350 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2351 SMB_OFF_T size = fsp->size;
2352 SMB_OFF_T sizeneeded = startpos + maxcount;
2354 if (size < sizeneeded) {
2355 SMB_STRUCT_STAT st;
2356 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2357 fsp->size = size = st.st_size;
2360 if (startpos >= size)
2361 nread = 0;
2362 else
2363 nread = MIN(maxcount,(size - startpos));
2366 if (nread < mincount)
2367 nread = 0;
2369 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2370 (int)maxcount, (int)mincount, (int)nread ) );
2372 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
2374 DEBUG(5,("readbraw finished\n"));
2375 END_PROFILE(SMBreadbraw);
2376 return -1;
2379 /****************************************************************************
2380 Reply to a lockread (core+ protocol).
2381 ****************************************************************************/
2383 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2385 ssize_t nread = -1;
2386 char *data;
2387 int outsize = 0;
2388 SMB_OFF_T startpos;
2389 size_t numtoread;
2390 NTSTATUS status;
2391 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2392 START_PROFILE(SMBlockread);
2394 CHECK_FSP(fsp,conn);
2395 CHECK_READ(fsp);
2397 release_level_2_oplocks_on_change(fsp);
2399 numtoread = SVAL(inbuf,smb_vwv1);
2400 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2402 outsize = set_message(outbuf,5,3,True);
2403 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2404 data = smb_buf(outbuf) + 3;
2407 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2408 * protocol request that predates the read/write lock concept.
2409 * Thus instead of asking for a read lock here we need to ask
2410 * for a write lock. JRA.
2413 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2414 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
2416 if (NT_STATUS_V(status)) {
2417 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2419 * A blocking lock was requested. Package up
2420 * this smb into a queued request and push it
2421 * onto the blocking lock queue.
2423 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2424 (SMB_BIG_UINT)numtoread)) {
2425 END_PROFILE(SMBlockread);
2426 return -1;
2429 END_PROFILE(SMBlockread);
2430 return ERROR_NT(status);
2433 nread = read_file(fsp,data,startpos,numtoread);
2435 if (nread < 0) {
2436 END_PROFILE(SMBlockread);
2437 return(UNIXERROR(ERRDOS,ERRnoaccess));
2440 outsize += nread;
2441 SSVAL(outbuf,smb_vwv0,nread);
2442 SSVAL(outbuf,smb_vwv5,nread+3);
2443 SSVAL(smb_buf(outbuf),1,nread);
2445 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2446 fsp->fnum, (int)numtoread, (int)nread ) );
2448 END_PROFILE(SMBlockread);
2449 return(outsize);
2452 /****************************************************************************
2453 Reply to a read.
2454 ****************************************************************************/
2456 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2458 size_t numtoread;
2459 ssize_t nread = 0;
2460 char *data;
2461 SMB_OFF_T startpos;
2462 int outsize = 0;
2463 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2464 START_PROFILE(SMBread);
2466 CHECK_FSP(fsp,conn);
2467 CHECK_READ(fsp);
2469 numtoread = SVAL(inbuf,smb_vwv1);
2470 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2472 outsize = set_message(outbuf,5,3,True);
2473 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2474 data = smb_buf(outbuf) + 3;
2476 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2477 END_PROFILE(SMBread);
2478 return ERROR_DOS(ERRDOS,ERRlock);
2481 if (numtoread > 0)
2482 nread = read_file(fsp,data,startpos,numtoread);
2484 if (nread < 0) {
2485 END_PROFILE(SMBread);
2486 return(UNIXERROR(ERRDOS,ERRnoaccess));
2489 outsize += nread;
2490 SSVAL(outbuf,smb_vwv0,nread);
2491 SSVAL(outbuf,smb_vwv5,nread+3);
2492 SCVAL(smb_buf(outbuf),0,1);
2493 SSVAL(smb_buf(outbuf),1,nread);
2495 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2496 fsp->fnum, (int)numtoread, (int)nread ) );
2498 END_PROFILE(SMBread);
2499 return(outsize);
2502 /****************************************************************************
2503 Reply to a read and X - possibly using sendfile.
2504 ****************************************************************************/
2506 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
2507 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2509 ssize_t nread = -1;
2510 char *data = smb_buf(outbuf);
2512 #if defined(WITH_SENDFILE)
2514 * We can only use sendfile on a non-chained packet and on a file
2515 * that is exclusively oplocked.
2518 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
2519 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2520 SMB_STRUCT_STAT sbuf;
2521 DATA_BLOB header;
2523 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1)
2524 return(UNIXERROR(ERRDOS,ERRnoaccess));
2526 if (startpos > sbuf.st_size)
2527 goto normal_read;
2529 if (smb_maxcnt > (sbuf.st_size - startpos))
2530 smb_maxcnt = (sbuf.st_size - startpos);
2532 if (smb_maxcnt == 0)
2533 goto normal_read;
2536 * Set up the packet header before send. We
2537 * assume here the sendfile will work (get the
2538 * correct amount of data).
2541 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2542 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2543 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2544 SCVAL(outbuf,smb_vwv0,0xFF);
2545 set_message(outbuf,12,smb_maxcnt,False);
2546 header.data = outbuf;
2547 header.length = data - outbuf;
2548 header.free = NULL;
2550 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2552 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2553 * return ENOSYS then pretend we just got a normal read.
2555 if (errno == ENOSYS)
2556 goto normal_read;
2558 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2559 fsp->fsp_name, strerror(errno) ));
2560 exit_server("send_file_readX sendfile failed");
2563 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2564 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2565 return -1;
2568 normal_read:
2570 #endif
2572 nread = read_file(fsp,data,startpos,smb_maxcnt);
2574 if (nread < 0) {
2575 END_PROFILE(SMBreadX);
2576 return(UNIXERROR(ERRDOS,ERRnoaccess));
2579 SSVAL(outbuf,smb_vwv5,nread);
2580 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2581 SSVAL(smb_buf(outbuf),-2,nread);
2583 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2584 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2586 return nread;
2589 /****************************************************************************
2590 Reply to a read and X.
2591 ****************************************************************************/
2593 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2595 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2596 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2597 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2598 #if 0
2599 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2600 #endif
2601 ssize_t nread = -1;
2602 char *data;
2603 START_PROFILE(SMBreadX);
2605 /* If it's an IPC, pass off the pipe handler. */
2606 if (IS_IPC(conn)) {
2607 END_PROFILE(SMBreadX);
2608 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2611 CHECK_FSP(fsp,conn);
2612 CHECK_READ(fsp);
2614 set_message(outbuf,12,0,True);
2615 data = smb_buf(outbuf);
2617 if(CVAL(inbuf,smb_wct) == 12) {
2618 #ifdef LARGE_SMB_OFF_T
2620 * This is a large offset (64 bit) read.
2622 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2624 #else /* !LARGE_SMB_OFF_T */
2627 * Ensure we haven't been sent a >32 bit offset.
2630 if(IVAL(inbuf,smb_vwv10) != 0) {
2631 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2632 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2633 END_PROFILE(SMBreadX);
2634 return ERROR_DOS(ERRDOS,ERRbadaccess);
2637 #endif /* LARGE_SMB_OFF_T */
2641 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2642 END_PROFILE(SMBreadX);
2643 return ERROR_DOS(ERRDOS,ERRlock);
2645 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2646 if (nread != -1)
2647 nread = chain_reply(inbuf,outbuf,length,bufsize);
2649 END_PROFILE(SMBreadX);
2650 return nread;
2653 /****************************************************************************
2654 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2655 ****************************************************************************/
2657 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2659 ssize_t nwritten=0;
2660 ssize_t total_written=0;
2661 size_t numtowrite=0;
2662 size_t tcount;
2663 SMB_OFF_T startpos;
2664 char *data=NULL;
2665 BOOL write_through;
2666 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2667 int outsize = 0;
2668 START_PROFILE(SMBwritebraw);
2670 CHECK_FSP(fsp,conn);
2671 CHECK_WRITE(fsp);
2673 tcount = IVAL(inbuf,smb_vwv1);
2674 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2675 write_through = BITSETW(inbuf+smb_vwv7,0);
2677 /* We have to deal with slightly different formats depending
2678 on whether we are using the core+ or lanman1.0 protocol */
2680 if(Protocol <= PROTOCOL_COREPLUS) {
2681 numtowrite = SVAL(smb_buf(inbuf),-2);
2682 data = smb_buf(inbuf);
2683 } else {
2684 numtowrite = SVAL(inbuf,smb_vwv10);
2685 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2688 /* force the error type */
2689 SCVAL(inbuf,smb_com,SMBwritec);
2690 SCVAL(outbuf,smb_com,SMBwritec);
2692 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2693 END_PROFILE(SMBwritebraw);
2694 return(ERROR_DOS(ERRDOS,ERRlock));
2697 if (numtowrite>0)
2698 nwritten = write_file(fsp,data,startpos,numtowrite);
2700 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2701 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2703 if (nwritten < (ssize_t)numtowrite) {
2704 END_PROFILE(SMBwritebraw);
2705 return(UNIXERROR(ERRHRD,ERRdiskfull));
2708 total_written = nwritten;
2710 /* Return a message to the redirector to tell it to send more bytes */
2711 SCVAL(outbuf,smb_com,SMBwritebraw);
2712 SSVALS(outbuf,smb_vwv0,-1);
2713 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2714 if (!send_smb(smbd_server_fd(),outbuf))
2715 exit_server("reply_writebraw: send_smb failed.");
2717 /* Now read the raw data into the buffer and write it */
2718 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2719 exit_server("secondary writebraw failed");
2722 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2723 numtowrite = smb_len(inbuf);
2725 /* Set up outbuf to return the correct return */
2726 outsize = set_message(outbuf,1,0,True);
2727 SCVAL(outbuf,smb_com,SMBwritec);
2728 SSVAL(outbuf,smb_vwv0,total_written);
2730 if (numtowrite != 0) {
2732 if (numtowrite > BUFFER_SIZE) {
2733 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2734 (unsigned int)numtowrite ));
2735 exit_server("secondary writebraw failed");
2738 if (tcount > nwritten+numtowrite) {
2739 DEBUG(3,("Client overestimated the write %d %d %d\n",
2740 (int)tcount,(int)nwritten,(int)numtowrite));
2743 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2744 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2745 strerror(errno) ));
2746 exit_server("secondary writebraw failed");
2749 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2751 if (nwritten < (ssize_t)numtowrite) {
2752 SCVAL(outbuf,smb_rcls,ERRHRD);
2753 SSVAL(outbuf,smb_err,ERRdiskfull);
2756 if (nwritten > 0)
2757 total_written += nwritten;
2760 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2761 sync_file(conn,fsp);
2763 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2764 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2766 /* we won't return a status if write through is not selected - this follows what WfWg does */
2767 END_PROFILE(SMBwritebraw);
2768 if (!write_through && total_written==tcount) {
2770 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2771 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2773 if (!send_keepalive(smbd_server_fd()))
2774 exit_server("reply_writebraw: send of keepalive failed");
2775 return(-1);
2778 return(outsize);
2781 /****************************************************************************
2782 Reply to a writeunlock (core+).
2783 ****************************************************************************/
2785 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2787 ssize_t nwritten = -1;
2788 size_t numtowrite;
2789 SMB_OFF_T startpos;
2790 char *data;
2791 NTSTATUS status;
2792 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2793 int outsize = 0;
2794 START_PROFILE(SMBwriteunlock);
2796 CHECK_FSP(fsp,conn);
2797 CHECK_WRITE(fsp);
2799 numtowrite = SVAL(inbuf,smb_vwv1);
2800 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2801 data = smb_buf(inbuf) + 3;
2803 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2804 WRITE_LOCK,False)) {
2805 END_PROFILE(SMBwriteunlock);
2806 return ERROR_DOS(ERRDOS,ERRlock);
2809 /* The special X/Open SMB protocol handling of
2810 zero length writes is *NOT* done for
2811 this call */
2812 if(numtowrite == 0)
2813 nwritten = 0;
2814 else
2815 nwritten = write_file(fsp,data,startpos,numtowrite);
2817 if (lp_syncalways(SNUM(conn)))
2818 sync_file(conn,fsp);
2820 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2821 END_PROFILE(SMBwriteunlock);
2822 return(UNIXERROR(ERRHRD,ERRdiskfull));
2825 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2826 (SMB_BIG_UINT)startpos);
2827 if (NT_STATUS_V(status)) {
2828 END_PROFILE(SMBwriteunlock);
2829 return ERROR_NT(status);
2832 outsize = set_message(outbuf,1,0,True);
2834 SSVAL(outbuf,smb_vwv0,nwritten);
2836 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2837 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2839 END_PROFILE(SMBwriteunlock);
2840 return(outsize);
2843 /****************************************************************************
2844 Reply to a write.
2845 ****************************************************************************/
2847 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2849 size_t numtowrite;
2850 ssize_t nwritten = -1;
2851 SMB_OFF_T startpos;
2852 char *data;
2853 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2854 int outsize = 0;
2855 START_PROFILE(SMBwrite);
2857 /* If it's an IPC, pass off the pipe handler. */
2858 if (IS_IPC(conn)) {
2859 END_PROFILE(SMBwrite);
2860 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2863 CHECK_FSP(fsp,conn);
2864 CHECK_WRITE(fsp);
2866 numtowrite = SVAL(inbuf,smb_vwv1);
2867 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2868 data = smb_buf(inbuf) + 3;
2870 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2871 END_PROFILE(SMBwrite);
2872 return ERROR_DOS(ERRDOS,ERRlock);
2876 * X/Open SMB protocol says that if smb_vwv1 is
2877 * zero then the file size should be extended or
2878 * truncated to the size given in smb_vwv[2-3].
2881 if(numtowrite == 0) {
2883 * This is actually an allocate call, and set EOF. JRA.
2885 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2886 if (nwritten < 0) {
2887 END_PROFILE(SMBwrite);
2888 return ERROR_NT(NT_STATUS_DISK_FULL);
2890 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2891 if (nwritten < 0) {
2892 END_PROFILE(SMBwrite);
2893 return ERROR_NT(NT_STATUS_DISK_FULL);
2895 } else
2896 nwritten = write_file(fsp,data,startpos,numtowrite);
2898 if (lp_syncalways(SNUM(conn)))
2899 sync_file(conn,fsp);
2901 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2902 END_PROFILE(SMBwrite);
2903 return(UNIXERROR(ERRHRD,ERRdiskfull));
2906 outsize = set_message(outbuf,1,0,True);
2908 SSVAL(outbuf,smb_vwv0,nwritten);
2910 if (nwritten < (ssize_t)numtowrite) {
2911 SCVAL(outbuf,smb_rcls,ERRHRD);
2912 SSVAL(outbuf,smb_err,ERRdiskfull);
2915 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2917 END_PROFILE(SMBwrite);
2918 return(outsize);
2921 /****************************************************************************
2922 Reply to a write and X.
2923 ****************************************************************************/
2925 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2927 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2928 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2929 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2930 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2931 ssize_t nwritten = -1;
2932 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2933 unsigned int smblen = smb_len(inbuf);
2934 char *data;
2935 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2936 START_PROFILE(SMBwriteX);
2938 /* If it's an IPC, pass off the pipe handler. */
2939 if (IS_IPC(conn)) {
2940 END_PROFILE(SMBwriteX);
2941 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2944 CHECK_FSP(fsp,conn);
2945 CHECK_WRITE(fsp);
2947 /* Deal with possible LARGE_WRITEX */
2948 if (large_writeX)
2949 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2951 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2952 END_PROFILE(SMBwriteX);
2953 return ERROR_DOS(ERRDOS,ERRbadmem);
2956 data = smb_base(inbuf) + smb_doff;
2958 if(CVAL(inbuf,smb_wct) == 14) {
2959 #ifdef LARGE_SMB_OFF_T
2961 * This is a large offset (64 bit) write.
2963 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2965 #else /* !LARGE_SMB_OFF_T */
2968 * Ensure we haven't been sent a >32 bit offset.
2971 if(IVAL(inbuf,smb_vwv12) != 0) {
2972 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2973 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2974 END_PROFILE(SMBwriteX);
2975 return ERROR_DOS(ERRDOS,ERRbadaccess);
2978 #endif /* LARGE_SMB_OFF_T */
2981 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2982 END_PROFILE(SMBwriteX);
2983 return ERROR_DOS(ERRDOS,ERRlock);
2986 /* X/Open SMB protocol says that, unlike SMBwrite
2987 if the length is zero then NO truncation is
2988 done, just a write of zero. To truncate a file,
2989 use SMBwrite. */
2990 if(numtowrite == 0)
2991 nwritten = 0;
2992 else
2993 nwritten = write_file(fsp,data,startpos,numtowrite);
2995 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2996 END_PROFILE(SMBwriteX);
2997 return(UNIXERROR(ERRHRD,ERRdiskfull));
3000 set_message(outbuf,6,0,True);
3002 SSVAL(outbuf,smb_vwv2,nwritten);
3003 if (large_writeX)
3004 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3006 if (nwritten < (ssize_t)numtowrite) {
3007 SCVAL(outbuf,smb_rcls,ERRHRD);
3008 SSVAL(outbuf,smb_err,ERRdiskfull);
3011 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3012 fsp->fnum, (int)numtowrite, (int)nwritten));
3014 if (lp_syncalways(SNUM(conn)) || write_through)
3015 sync_file(conn,fsp);
3017 END_PROFILE(SMBwriteX);
3018 return chain_reply(inbuf,outbuf,length,bufsize);
3022 /****************************************************************************
3023 Reply to a lseek.
3024 ****************************************************************************/
3026 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3028 SMB_OFF_T startpos;
3029 SMB_OFF_T res= -1;
3030 int mode,umode;
3031 int outsize = 0;
3032 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3033 START_PROFILE(SMBlseek);
3035 CHECK_FSP(fsp,conn);
3037 flush_write_cache(fsp, SEEK_FLUSH);
3039 mode = SVAL(inbuf,smb_vwv1) & 3;
3040 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3041 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3043 switch (mode) {
3044 case 0: umode = SEEK_SET; break;
3045 case 1: umode = SEEK_CUR; break;
3046 case 2: umode = SEEK_END; break;
3047 default:
3048 umode = SEEK_SET; break;
3051 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
3053 * Check for the special case where a seek before the start
3054 * of the file sets the offset to zero. Added in the CIFS spec,
3055 * section 4.2.7.
3058 if(errno == EINVAL) {
3059 SMB_OFF_T current_pos = startpos;
3061 if(umode == SEEK_CUR) {
3063 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
3064 END_PROFILE(SMBlseek);
3065 return(UNIXERROR(ERRDOS,ERRnoaccess));
3068 current_pos += startpos;
3070 } else if (umode == SEEK_END) {
3072 SMB_STRUCT_STAT sbuf;
3074 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
3075 END_PROFILE(SMBlseek);
3076 return(UNIXERROR(ERRDOS,ERRnoaccess));
3079 current_pos += sbuf.st_size;
3082 if(current_pos < 0)
3083 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
3086 if(res == -1) {
3087 END_PROFILE(SMBlseek);
3088 return(UNIXERROR(ERRDOS,ERRnoaccess));
3092 fsp->pos = res;
3094 outsize = set_message(outbuf,2,0,True);
3095 SIVAL(outbuf,smb_vwv0,res);
3097 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3098 fsp->fnum, (double)startpos, (double)res, mode));
3100 END_PROFILE(SMBlseek);
3101 return(outsize);
3104 /****************************************************************************
3105 Reply to a flush.
3106 ****************************************************************************/
3108 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3110 int outsize = set_message(outbuf,0,0,True);
3111 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3112 START_PROFILE(SMBflush);
3114 CHECK_FSP(fsp,conn);
3116 if (!fsp) {
3117 file_sync_all(conn);
3118 } else {
3119 sync_file(conn,fsp);
3122 DEBUG(3,("flush\n"));
3123 END_PROFILE(SMBflush);
3124 return(outsize);
3127 /****************************************************************************
3128 Reply to a exit.
3129 ****************************************************************************/
3131 int reply_exit(connection_struct *conn,
3132 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3134 int outsize;
3135 START_PROFILE(SMBexit);
3136 outsize = set_message(outbuf,0,0,True);
3138 DEBUG(3,("exit\n"));
3140 END_PROFILE(SMBexit);
3141 return(outsize);
3145 /****************************************************************************
3146 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3147 ****************************************************************************/
3149 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3150 int dum_buffsize)
3152 int outsize = 0;
3153 time_t mtime;
3154 files_struct *fsp = NULL;
3155 START_PROFILE(SMBclose);
3157 outsize = set_message(outbuf,0,0,True);
3159 /* If it's an IPC, pass off to the pipe handler. */
3160 if (IS_IPC(conn)) {
3161 END_PROFILE(SMBclose);
3162 return reply_pipe_close(conn, inbuf,outbuf);
3165 fsp = file_fsp(inbuf,smb_vwv0);
3168 * We can only use CHECK_FSP if we know it's not a directory.
3171 if(!fsp || (fsp->conn != conn)) {
3172 END_PROFILE(SMBclose);
3173 return ERROR_DOS(ERRDOS,ERRbadfid);
3176 if(fsp->is_directory) {
3178 * Special case - close NT SMB directory handle.
3180 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3181 close_file(fsp,True);
3182 } else {
3184 * Close ordinary file.
3186 int close_err;
3187 pstring file_name;
3189 /* Save the name for time set in close. */
3190 pstrcpy( file_name, fsp->fsp_name);
3192 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3193 fsp->fd, fsp->fnum,
3194 conn->num_files_open));
3197 * close_file() returns the unix errno if an error
3198 * was detected on close - normally this is due to
3199 * a disk full error. If not then it was probably an I/O error.
3202 if((close_err = close_file(fsp,True)) != 0) {
3203 errno = close_err;
3204 END_PROFILE(SMBclose);
3205 return (UNIXERROR(ERRHRD,ERRgeneral));
3209 * Now take care of any time sent in the close.
3212 mtime = make_unix_date3(inbuf+smb_vwv1);
3214 /* try and set the date */
3215 set_filetime(conn, file_name, mtime);
3219 END_PROFILE(SMBclose);
3220 return(outsize);
3223 /****************************************************************************
3224 Reply to a writeclose (Core+ protocol)
3225 ****************************************************************************/
3227 int reply_writeclose(connection_struct *conn,
3228 char *inbuf,char *outbuf, int size, int dum_buffsize)
3230 size_t numtowrite;
3231 ssize_t nwritten = -1;
3232 int outsize = 0;
3233 int close_err = 0;
3234 SMB_OFF_T startpos;
3235 char *data;
3236 time_t mtime;
3237 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3238 START_PROFILE(SMBwriteclose);
3240 CHECK_FSP(fsp,conn);
3241 CHECK_WRITE(fsp);
3243 numtowrite = SVAL(inbuf,smb_vwv1);
3244 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3245 mtime = make_unix_date3(inbuf+smb_vwv4);
3246 data = smb_buf(inbuf) + 1;
3248 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
3249 END_PROFILE(SMBwriteclose);
3250 return ERROR_DOS(ERRDOS,ERRlock);
3253 nwritten = write_file(fsp,data,startpos,numtowrite);
3255 set_filetime(conn, fsp->fsp_name,mtime);
3257 close_err = close_file(fsp,True);
3259 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3260 fsp->fnum, (int)numtowrite, (int)nwritten,
3261 conn->num_files_open));
3263 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3264 END_PROFILE(SMBwriteclose);
3265 return(UNIXERROR(ERRHRD,ERRdiskfull));
3268 if(close_err != 0) {
3269 errno = close_err;
3270 END_PROFILE(SMBwriteclose);
3271 return(UNIXERROR(ERRHRD,ERRgeneral));
3274 outsize = set_message(outbuf,1,0,True);
3276 SSVAL(outbuf,smb_vwv0,nwritten);
3277 END_PROFILE(SMBwriteclose);
3278 return(outsize);
3281 /****************************************************************************
3282 Reply to a lock.
3283 ****************************************************************************/
3285 int reply_lock(connection_struct *conn,
3286 char *inbuf,char *outbuf, int length, int dum_buffsize)
3288 int outsize = set_message(outbuf,0,0,True);
3289 SMB_BIG_UINT count,offset;
3290 NTSTATUS status;
3291 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3292 START_PROFILE(SMBlock);
3294 CHECK_FSP(fsp,conn);
3296 release_level_2_oplocks_on_change(fsp);
3298 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3299 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3301 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3302 fsp->fd, fsp->fnum, (double)offset, (double)count));
3304 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
3305 if (NT_STATUS_V(status)) {
3306 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3308 * A blocking lock was requested. Package up
3309 * this smb into a queued request and push it
3310 * onto the blocking lock queue.
3312 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3313 END_PROFILE(SMBlock);
3314 return -1;
3317 END_PROFILE(SMBlock);
3318 return ERROR_NT(status);
3321 END_PROFILE(SMBlock);
3322 return(outsize);
3325 /****************************************************************************
3326 Reply to a unlock.
3327 ****************************************************************************/
3329 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3331 int outsize = set_message(outbuf,0,0,True);
3332 SMB_BIG_UINT count,offset;
3333 NTSTATUS status;
3334 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3335 START_PROFILE(SMBunlock);
3337 CHECK_FSP(fsp,conn);
3339 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3340 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3342 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3343 if (NT_STATUS_V(status)) {
3344 END_PROFILE(SMBunlock);
3345 return ERROR_NT(status);
3348 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3349 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3351 END_PROFILE(SMBunlock);
3352 return(outsize);
3355 /****************************************************************************
3356 Reply to a tdis.
3357 ****************************************************************************/
3359 int reply_tdis(connection_struct *conn,
3360 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3362 int outsize = set_message(outbuf,0,0,True);
3363 uint16 vuid;
3364 START_PROFILE(SMBtdis);
3366 vuid = SVAL(inbuf,smb_uid);
3368 if (!conn) {
3369 DEBUG(4,("Invalid connection in tdis\n"));
3370 END_PROFILE(SMBtdis);
3371 return ERROR_DOS(ERRSRV,ERRinvnid);
3374 conn->used = False;
3376 close_cnum(conn,vuid);
3378 END_PROFILE(SMBtdis);
3379 return outsize;
3382 /****************************************************************************
3383 Reply to a echo.
3384 ****************************************************************************/
3386 int reply_echo(connection_struct *conn,
3387 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3389 int smb_reverb = SVAL(inbuf,smb_vwv0);
3390 int seq_num;
3391 unsigned int data_len = smb_buflen(inbuf);
3392 int outsize = set_message(outbuf,1,data_len,True);
3393 START_PROFILE(SMBecho);
3395 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3397 /* copy any incoming data back out */
3398 if (data_len > 0)
3399 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3401 if (smb_reverb > 100) {
3402 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3403 smb_reverb = 100;
3406 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3407 SSVAL(outbuf,smb_vwv0,seq_num);
3409 smb_setlen(outbuf,outsize - 4);
3411 if (!send_smb(smbd_server_fd(),outbuf))
3412 exit_server("reply_echo: send_smb failed.");
3415 DEBUG(3,("echo %d times\n", smb_reverb));
3417 smb_echo_count++;
3419 END_PROFILE(SMBecho);
3420 return -1;
3423 /****************************************************************************
3424 Reply to a printopen.
3425 ****************************************************************************/
3427 int reply_printopen(connection_struct *conn,
3428 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3430 int outsize = 0;
3431 files_struct *fsp;
3432 START_PROFILE(SMBsplopen);
3434 if (!CAN_PRINT(conn)) {
3435 END_PROFILE(SMBsplopen);
3436 return ERROR_DOS(ERRDOS,ERRnoaccess);
3439 /* Open for exclusive use, write only. */
3440 fsp = print_fsp_open(conn, NULL);
3442 if (!fsp) {
3443 END_PROFILE(SMBsplopen);
3444 return(UNIXERROR(ERRDOS,ERRnoaccess));
3447 outsize = set_message(outbuf,1,0,True);
3448 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3450 DEBUG(3,("openprint fd=%d fnum=%d\n",
3451 fsp->fd, fsp->fnum));
3453 END_PROFILE(SMBsplopen);
3454 return(outsize);
3457 /****************************************************************************
3458 Reply to a printclose.
3459 ****************************************************************************/
3461 int reply_printclose(connection_struct *conn,
3462 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3464 int outsize = set_message(outbuf,0,0,True);
3465 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3466 int close_err = 0;
3467 START_PROFILE(SMBsplclose);
3469 CHECK_FSP(fsp,conn);
3471 if (!CAN_PRINT(conn)) {
3472 END_PROFILE(SMBsplclose);
3473 return ERROR_DOS(ERRDOS,ERRnoaccess);
3476 DEBUG(3,("printclose fd=%d fnum=%d\n",
3477 fsp->fd,fsp->fnum));
3479 close_err = close_file(fsp,True);
3481 if(close_err != 0) {
3482 errno = close_err;
3483 END_PROFILE(SMBsplclose);
3484 return(UNIXERROR(ERRHRD,ERRgeneral));
3487 END_PROFILE(SMBsplclose);
3488 return(outsize);
3491 /****************************************************************************
3492 Reply to a printqueue.
3493 ****************************************************************************/
3495 int reply_printqueue(connection_struct *conn,
3496 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3498 int outsize = set_message(outbuf,2,3,True);
3499 int max_count = SVAL(inbuf,smb_vwv0);
3500 int start_index = SVAL(inbuf,smb_vwv1);
3501 START_PROFILE(SMBsplretq);
3503 /* we used to allow the client to get the cnum wrong, but that
3504 is really quite gross and only worked when there was only
3505 one printer - I think we should now only accept it if they
3506 get it right (tridge) */
3507 if (!CAN_PRINT(conn)) {
3508 END_PROFILE(SMBsplretq);
3509 return ERROR_DOS(ERRDOS,ERRnoaccess);
3512 SSVAL(outbuf,smb_vwv0,0);
3513 SSVAL(outbuf,smb_vwv1,0);
3514 SCVAL(smb_buf(outbuf),0,1);
3515 SSVAL(smb_buf(outbuf),1,0);
3517 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3518 start_index, max_count));
3521 print_queue_struct *queue = NULL;
3522 print_status_struct status;
3523 char *p = smb_buf(outbuf) + 3;
3524 int count = print_queue_status(SNUM(conn), &queue, &status);
3525 int num_to_get = ABS(max_count);
3526 int first = (max_count>0?start_index:start_index+max_count+1);
3527 int i;
3529 if (first >= count)
3530 num_to_get = 0;
3531 else
3532 num_to_get = MIN(num_to_get,count-first);
3535 for (i=first;i<first+num_to_get;i++) {
3536 /* check to make sure we have room in the buffer */
3537 if ( (PTR_DIFF(p, outbuf)+28) > BUFFER_SIZE )
3538 break;
3539 put_dos_date2(p,0,queue[i].time);
3540 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3541 SSVAL(p,5, queue[i].job);
3542 SIVAL(p,7,queue[i].size);
3543 SCVAL(p,11,0);
3544 StrnCpy(p+12,queue[i].fs_user,16);
3545 p += 28;
3548 if (count > 0) {
3549 outsize = set_message(outbuf,2,28*count+3,False);
3550 SSVAL(outbuf,smb_vwv0,count);
3551 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3552 SCVAL(smb_buf(outbuf),0,1);
3553 SSVAL(smb_buf(outbuf),1,28*count);
3556 SAFE_FREE(queue);
3558 DEBUG(3,("%d entries returned in queue\n",count));
3561 END_PROFILE(SMBsplretq);
3562 return(outsize);
3565 /****************************************************************************
3566 Reply to a printwrite.
3567 ****************************************************************************/
3569 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3571 int numtowrite;
3572 int outsize = set_message(outbuf,0,0,True);
3573 char *data;
3574 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3575 START_PROFILE(SMBsplwr);
3577 if (!CAN_PRINT(conn)) {
3578 END_PROFILE(SMBsplwr);
3579 return ERROR_DOS(ERRDOS,ERRnoaccess);
3582 CHECK_FSP(fsp,conn);
3583 CHECK_WRITE(fsp);
3585 numtowrite = SVAL(smb_buf(inbuf),1);
3586 data = smb_buf(inbuf) + 3;
3588 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3589 END_PROFILE(SMBsplwr);
3590 return(UNIXERROR(ERRHRD,ERRdiskfull));
3593 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3595 END_PROFILE(SMBsplwr);
3596 return(outsize);
3599 /****************************************************************************
3600 The guts of the mkdir command, split out so it may be called by the NT SMB
3601 code.
3602 ****************************************************************************/
3604 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3606 BOOL bad_path = False;
3607 SMB_STRUCT_STAT sbuf;
3608 int ret= -1;
3610 unix_convert(directory,conn,0,&bad_path,&sbuf);
3612 if (check_name(directory, conn))
3613 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3615 if (ret == -1) {
3616 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
3617 if (!NT_STATUS_IS_OK(nterr))
3618 return nterr;
3619 return map_nt_error_from_unix(errno);
3622 return NT_STATUS_OK;
3625 /****************************************************************************
3626 Reply to a mkdir.
3627 ****************************************************************************/
3629 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3631 pstring directory;
3632 int outsize;
3633 NTSTATUS status;
3634 START_PROFILE(SMBmkdir);
3636 pstrcpy(directory,smb_buf(inbuf) + 1);
3638 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3640 status = mkdir_internal(conn, directory);
3641 if (!NT_STATUS_IS_OK(status))
3642 return ERROR_NT(status);
3644 outsize = set_message(outbuf,0,0,True);
3646 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3648 END_PROFILE(SMBmkdir);
3649 return(outsize);
3652 /****************************************************************************
3653 Static function used by reply_rmdir to delete an entire directory
3654 tree recursively. Return False on ok, True on fail.
3655 ****************************************************************************/
3657 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3659 char *dname = NULL;
3660 BOOL ret = False;
3661 void *dirptr = OpenDir(conn, directory, False);
3663 if(dirptr == NULL)
3664 return True;
3666 while((dname = ReadDirName(dirptr))) {
3667 pstring fullname;
3668 SMB_STRUCT_STAT st;
3670 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3671 continue;
3673 /* Construct the full name. */
3674 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3675 errno = ENOMEM;
3676 ret = True;
3677 break;
3680 pstrcpy(fullname, directory);
3681 pstrcat(fullname, "/");
3682 pstrcat(fullname, dname);
3684 if(conn->vfs_ops.lstat(conn,dos_to_unix_static(fullname), &st) != 0) {
3685 ret = True;
3686 break;
3689 if(st.st_mode & S_IFDIR) {
3690 if(recursive_rmdir(conn, fullname)!=0) {
3691 ret = True;
3692 break;
3694 if(vfs_rmdir(conn,fullname) != 0) {
3695 ret = True;
3696 break;
3698 } else if(vfs_unlink(conn,fullname) != 0) {
3699 ret = True;
3700 break;
3704 CloseDir(dirptr);
3705 return ret;
3708 /****************************************************************************
3709 The internals of the rmdir code - called elsewhere.
3710 ****************************************************************************/
3712 BOOL rmdir_internals(connection_struct *conn, char *directory)
3714 BOOL ok;
3716 ok = (vfs_rmdir(conn,directory) == 0);
3717 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3719 * Check to see if the only thing in this directory are
3720 * vetoed files/directories. If so then delete them and
3721 * retry. If we fail to delete any of them (and we *don't*
3722 * do a recursive delete) then fail the rmdir.
3724 BOOL all_veto_files = True;
3725 char *dname;
3726 void *dirptr = OpenDir(conn, directory, False);
3728 if(dirptr != NULL) {
3729 int dirpos = TellDir(dirptr);
3730 while ((dname = ReadDirName(dirptr))) {
3731 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3732 continue;
3733 if(!IS_VETO_PATH(conn, dname)) {
3734 all_veto_files = False;
3735 break;
3738 if(all_veto_files) {
3739 SeekDir(dirptr,dirpos);
3740 while ((dname = ReadDirName(dirptr))) {
3741 pstring fullname;
3742 SMB_STRUCT_STAT st;
3744 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3745 continue;
3747 /* Construct the full name. */
3748 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3749 errno = ENOMEM;
3750 break;
3752 pstrcpy(fullname, directory);
3753 pstrcat(fullname, "/");
3754 pstrcat(fullname, dname);
3756 if(conn->vfs_ops.lstat(conn,dos_to_unix_static(fullname), &st) != 0)
3757 break;
3758 if(st.st_mode & S_IFDIR) {
3759 if(lp_recursive_veto_delete(SNUM(conn))) {
3760 if(recursive_rmdir(conn, fullname) != 0)
3761 break;
3763 if(vfs_rmdir(conn,fullname) != 0)
3764 break;
3765 } else if(vfs_unlink(conn,fullname) != 0)
3766 break;
3768 CloseDir(dirptr);
3769 /* Retry the rmdir */
3770 ok = (vfs_rmdir(conn,directory) == 0);
3771 } else {
3772 CloseDir(dirptr);
3774 } else {
3775 errno = ENOTEMPTY;
3779 if (!ok)
3780 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3782 return ok;
3785 /****************************************************************************
3786 Reply to a rmdir.
3787 ****************************************************************************/
3789 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3791 pstring directory;
3792 int outsize = 0;
3793 BOOL ok = False;
3794 BOOL bad_path = False;
3795 SMB_STRUCT_STAT sbuf;
3796 START_PROFILE(SMBrmdir);
3798 pstrcpy(directory,smb_buf(inbuf) + 1);
3800 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3802 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3804 if (check_name(directory,conn))
3806 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3807 ok = rmdir_internals(conn, directory);
3810 if (!ok)
3812 set_bad_path_error(errno, bad_path);
3813 END_PROFILE(SMBrmdir);
3814 return(UNIXERROR(ERRDOS,ERRbadpath));
3817 outsize = set_message(outbuf,0,0,True);
3819 DEBUG( 3, ( "rmdir %s\n", directory ) );
3821 END_PROFILE(SMBrmdir);
3822 return(outsize);
3825 /*******************************************************************
3826 Resolve wildcards in a filename rename.
3827 ********************************************************************/
3829 static BOOL resolve_wildcards(char *name1,char *name2)
3831 fstring root1,root2;
3832 fstring ext1,ext2;
3833 char *p,*p2;
3835 name1 = strrchr(name1,'/');
3836 name2 = strrchr(name2,'/');
3838 if (!name1 || !name2) return(False);
3840 fstrcpy(root1,name1);
3841 fstrcpy(root2,name2);
3842 p = strrchr(root1,'.');
3843 if (p) {
3844 *p = 0;
3845 fstrcpy(ext1,p+1);
3846 } else {
3847 fstrcpy(ext1,"");
3849 p = strrchr(root2,'.');
3850 if (p) {
3851 *p = 0;
3852 fstrcpy(ext2,p+1);
3853 } else {
3854 fstrcpy(ext2,"");
3857 p = root1;
3858 p2 = root2;
3859 while (*p2) {
3860 if (*p2 == '?') {
3861 *p2 = *p;
3862 p2++;
3863 } else {
3864 p2++;
3866 if (*p) p++;
3869 p = ext1;
3870 p2 = ext2;
3871 while (*p2) {
3872 if (*p2 == '?') {
3873 *p2 = *p;
3874 p2++;
3875 } else {
3876 p2++;
3878 if (*p) p++;
3881 pstrcpy(name2,root2);
3882 if (ext2[0]) {
3883 pstrcat(name2,".");
3884 pstrcat(name2,ext2);
3887 return(True);
3890 /****************************************************************************
3891 The guts of the rename command, split out so it may be called by the NT SMB
3892 code.
3893 ****************************************************************************/
3895 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3897 pstring directory;
3898 pstring mask;
3899 pstring newname_last_component;
3900 char *p;
3901 BOOL has_wild;
3902 BOOL bad_path1 = False;
3903 BOOL bad_path2 = False;
3904 int count=0;
3905 NTSTATUS error = NT_STATUS_OK;
3906 BOOL rc = True;
3907 SMB_STRUCT_STAT sbuf1, sbuf2;
3909 *directory = *mask = 0;
3911 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3912 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3915 * Split the old name into directory and last component
3916 * strings. Note that unix_convert may have stripped off a
3917 * leading ./ from both name and newname if the rename is
3918 * at the root of the share. We need to make sure either both
3919 * name and newname contain a / character or neither of them do
3920 * as this is checked in resolve_wildcards().
3923 p = strrchr(name,'/');
3924 if (!p) {
3925 pstrcpy(directory,".");
3926 pstrcpy(mask,name);
3927 } else {
3928 *p = 0;
3929 pstrcpy(directory,name);
3930 pstrcpy(mask,p+1);
3931 *p = '/'; /* Replace needed for exceptional test below. */
3935 * We should only check the mangled cache
3936 * here if unix_convert failed. This means
3937 * that the path in 'mask' doesn't exist
3938 * on the file system and so we need to look
3939 * for a possible mangle. This patch from
3940 * Tine Smukavec <valentin.smukavec@hermes.si>.
3943 if (!rc && mangle_is_mangled(mask))
3944 mangle_check_cache( mask );
3946 has_wild = ms_has_wild(mask);
3948 if (!has_wild) {
3949 pstring zdirectory;
3950 pstring znewname;
3953 * No wildcards - just process the one file.
3955 BOOL is_short_name = mangle_is_8_3(name, True);
3957 /* Add a terminating '/' to the directory name. */
3958 pstrcat(directory,"/");
3959 pstrcat(directory,mask);
3961 /* Ensure newname contains a '/' also */
3962 if(strrchr(newname,'/') == 0) {
3963 pstring tmpstr;
3965 pstrcpy(tmpstr, "./");
3966 pstrcat(tmpstr, newname);
3967 pstrcpy(newname, tmpstr);
3970 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3971 directory = %s, newname = %s, newname_last_component = %s, mangle_is_8_3 = %d\n",
3972 case_sensitive, case_preserve, short_case_preserve, directory,
3973 newname, newname_last_component, is_short_name));
3976 * Check for special case with case preserving and not
3977 * case sensitive, if directory and newname are identical,
3978 * and the old last component differs from the original
3979 * last component only by case, then we should allow
3980 * the rename (user is trying to change the case of the
3981 * filename).
3983 if((case_sensitive == False) &&
3984 (((case_preserve == True) &&
3985 (is_short_name == False)) ||
3986 ((short_case_preserve == True) &&
3987 (is_short_name == True))) &&
3988 strcsequal(directory, newname)) {
3989 pstring newname_modified_last_component;
3992 * Get the last component of the modified name.
3993 * Note that we guarantee that newname contains a '/'
3994 * character above.
3996 p = strrchr(newname,'/');
3997 pstrcpy(newname_modified_last_component,p+1);
3999 if(strcsequal(newname_modified_last_component,
4000 newname_last_component) == False) {
4002 * Replace the modified last component with
4003 * the original.
4005 pstrcpy(p+1, newname_last_component);
4010 resolve_wildcards(directory,newname);
4013 * The source object must exist.
4016 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4017 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4018 directory,newname));
4020 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4022 * Must return different errors depending on whether the parent
4023 * directory existed or not.
4026 p = strrchr(directory, '/');
4027 if (!p)
4028 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4029 *p = '\0';
4030 if (vfs_object_exist(conn, directory, NULL))
4031 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4032 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4034 error = map_nt_error_from_unix(errno);
4035 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4036 get_nt_error_msg(error), directory,newname));
4038 return error;
4041 error = can_rename(directory,conn,&sbuf1);
4043 if (!NT_STATUS_IS_OK(error)) {
4044 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4045 get_nt_error_msg(error), directory,newname));
4046 return error;
4049 pstrcpy(zdirectory, dos_to_unix_static(directory));
4050 pstrcpy(znewname, dos_to_unix_static(newname));
4053 * If the src and dest names are identical - including case,
4054 * don't do the rename, just return success.
4057 if (strcsequal(zdirectory, znewname)) {
4058 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4059 return NT_STATUS_OK;
4062 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4063 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4064 directory,newname));
4065 return NT_STATUS_OBJECT_NAME_COLLISION;
4068 if(conn->vfs_ops.rename(conn,zdirectory, znewname) == 0) {
4069 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4070 directory,newname));
4071 return NT_STATUS_OK;
4074 if (errno == ENOTDIR || errno == EISDIR)
4075 error = NT_STATUS_OBJECT_NAME_COLLISION;
4076 else
4077 error = map_nt_error_from_unix(errno);
4079 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4080 get_nt_error_msg(error), directory,newname));
4082 return error;
4083 } else {
4086 * Wildcards - process each file that matches.
4088 void *dirptr = NULL;
4089 char *dname;
4090 pstring destname;
4092 if (check_name(directory,conn))
4093 dirptr = OpenDir(conn, directory, True);
4095 if (dirptr) {
4096 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4098 if (strequal(mask,"????????.???"))
4099 pstrcpy(mask,"*");
4101 while ((dname = ReadDirName(dirptr))) {
4102 pstring fname;
4104 pstrcpy(fname,dname);
4106 if(!mask_match(fname, mask, case_sensitive))
4107 continue;
4109 error = NT_STATUS_ACCESS_DENIED;
4110 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4111 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4112 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4113 DEBUG(6,("rename %s failed. Error %s\n", fname, get_nt_error_msg(error)));
4114 continue;
4116 error = can_rename(fname,conn,&sbuf1);
4117 if (!NT_STATUS_IS_OK(error)) {
4118 DEBUG(6,("rename %s failed. Error %s\n", fname, get_nt_error_msg(error)));
4119 continue;
4121 pstrcpy(destname,newname);
4123 if (!resolve_wildcards(fname,destname)) {
4124 DEBUG(6,("resolve_wildcards %s %s failed\n",
4125 fname, destname));
4126 continue;
4129 if (!replace_if_exists &&
4130 vfs_object_exist(conn,destname, NULL)) {
4131 DEBUG(6,("file_exist %s\n", destname));
4132 error = NT_STATUS_OBJECT_NAME_COLLISION;
4133 continue;
4136 if (!conn->vfs_ops.rename(conn,dos_to_unix_static(fname),
4137 dos_to_unix_static(destname)))
4138 count++;
4139 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4141 CloseDir(dirptr);
4145 if (count == 0 && NT_STATUS_IS_OK(error)) {
4146 error = map_nt_error_from_unix(errno);
4149 return error;
4152 /****************************************************************************
4153 Reply to a mv.
4154 ****************************************************************************/
4156 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4158 int outsize = 0;
4159 pstring name;
4160 pstring newname;
4161 NTSTATUS status;
4162 START_PROFILE(SMBmv);
4164 pstrcpy(name,smb_buf(inbuf) + 1);
4165 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
4167 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4168 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4170 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4172 status = rename_internals(conn, name, newname, False);
4173 if (!NT_STATUS_IS_OK(status)) {
4174 return ERROR_NT(status);
4178 * Win2k needs a changenotify request response before it will
4179 * update after a rename..
4181 process_pending_change_notify_queue((time_t)0);
4182 outsize = set_message(outbuf,0,0,True);
4184 END_PROFILE(SMBmv);
4185 return(outsize);
4188 /*******************************************************************
4189 Copy a file as part of a reply_copy.
4190 ******************************************************************/
4192 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4193 int count,BOOL target_is_directory, int *err_ret)
4195 int Access,action;
4196 SMB_STRUCT_STAT src_sbuf, sbuf2;
4197 SMB_OFF_T ret=-1;
4198 files_struct *fsp1,*fsp2;
4199 pstring dest;
4201 *err_ret = 0;
4203 pstrcpy(dest,dest1);
4204 if (target_is_directory) {
4205 char *p = strrchr(src,'/');
4206 if (p)
4207 p++;
4208 else
4209 p = src;
4210 pstrcat(dest,"/");
4211 pstrcat(dest,p);
4214 if (!vfs_file_exist(conn,src,&src_sbuf))
4215 return(False);
4217 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4218 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
4220 if (!fsp1)
4221 return(False);
4223 if (!target_is_directory && count)
4224 ofun = FILE_EXISTS_OPEN;
4226 if (vfs_stat(conn,dest,&sbuf2) == -1)
4227 ZERO_STRUCTP(&sbuf2);
4229 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4230 ofun,src_sbuf.st_mode,0,&Access,&action);
4232 if (!fsp2) {
4233 close_file(fsp1,False);
4234 return(False);
4237 if ((ofun&3) == 1) {
4238 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4239 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4241 * Stop the copy from occurring.
4243 ret = -1;
4244 src_sbuf.st_size = 0;
4248 if (src_sbuf.st_size)
4249 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4251 close_file(fsp1,False);
4253 /* Ensure the modtime is set correctly on the destination file. */
4254 fsp2->pending_modtime = src_sbuf.st_mtime;
4257 * As we are opening fsp1 read-only we only expect
4258 * an error on close on fsp2 if we are out of space.
4259 * Thus we don't look at the error return from the
4260 * close of fsp1.
4262 *err_ret = close_file(fsp2,False);
4264 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4267 /****************************************************************************
4268 Reply to a file copy.
4269 ****************************************************************************/
4271 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4273 int outsize = 0;
4274 pstring name;
4275 pstring directory;
4276 pstring mask,newname;
4277 char *p;
4278 int count=0;
4279 int error = ERRnoaccess;
4280 int err = 0;
4281 BOOL has_wild;
4282 BOOL exists=False;
4283 int tid2 = SVAL(inbuf,smb_vwv0);
4284 int ofun = SVAL(inbuf,smb_vwv1);
4285 int flags = SVAL(inbuf,smb_vwv2);
4286 BOOL target_is_directory=False;
4287 BOOL bad_path1 = False;
4288 BOOL bad_path2 = False;
4289 BOOL rc = True;
4290 SMB_STRUCT_STAT sbuf1, sbuf2;
4291 START_PROFILE(SMBcopy);
4293 *directory = *mask = 0;
4295 pstrcpy(name,smb_buf(inbuf));
4296 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
4298 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4300 if (tid2 != conn->cnum) {
4301 /* can't currently handle inter share copies XXXX */
4302 DEBUG(3,("Rejecting inter-share copy\n"));
4303 END_PROFILE(SMBcopy);
4304 return ERROR_DOS(ERRSRV,ERRinvdevice);
4307 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4308 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4310 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4311 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4313 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4315 if ((flags&1) && target_is_directory) {
4316 END_PROFILE(SMBcopy);
4317 return ERROR_DOS(ERRDOS,ERRbadfile);
4320 if ((flags&2) && !target_is_directory) {
4321 END_PROFILE(SMBcopy);
4322 return ERROR_DOS(ERRDOS,ERRbadpath);
4325 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4326 /* wants a tree copy! XXXX */
4327 DEBUG(3,("Rejecting tree copy\n"));
4328 END_PROFILE(SMBcopy);
4329 return ERROR_DOS(ERRSRV,ERRerror);
4332 p = strrchr(name,'/');
4333 if (!p) {
4334 pstrcpy(directory,"./");
4335 pstrcpy(mask,name);
4336 } else {
4337 *p = 0;
4338 pstrcpy(directory,name);
4339 pstrcpy(mask,p+1);
4343 * We should only check the mangled cache
4344 * here if unix_convert failed. This means
4345 * that the path in 'mask' doesn't exist
4346 * on the file system and so we need to look
4347 * for a possible mangle. This patch from
4348 * Tine Smukavec <valentin.smukavec@hermes.si>.
4351 if (!rc && mangle_is_mangled(mask))
4352 mangle_check_cache( mask );
4354 has_wild = ms_has_wild(mask);
4356 if (!has_wild) {
4357 pstrcat(directory,"/");
4358 pstrcat(directory,mask);
4359 if (resolve_wildcards(directory,newname) &&
4360 copy_file(directory,newname,conn,ofun,
4361 count,target_is_directory,&err)) count++;
4362 if(!count && err) {
4363 errno = err;
4364 END_PROFILE(SMBcopy);
4365 return(UNIXERROR(ERRHRD,ERRgeneral));
4367 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4368 } else {
4369 void *dirptr = NULL;
4370 char *dname;
4371 pstring destname;
4373 if (check_name(directory,conn))
4374 dirptr = OpenDir(conn, directory, True);
4376 if (dirptr) {
4377 error = ERRbadfile;
4379 if (strequal(mask,"????????.???"))
4380 pstrcpy(mask,"*");
4382 while ((dname = ReadDirName(dirptr))) {
4383 pstring fname;
4384 pstrcpy(fname,dname);
4386 if(!mask_match(fname, mask, case_sensitive))
4387 continue;
4389 error = ERRnoaccess;
4390 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4391 pstrcpy(destname,newname);
4392 if (resolve_wildcards(fname,destname) &&
4393 copy_file(fname,destname,conn,ofun,
4394 count,target_is_directory,&err)) count++;
4395 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4397 CloseDir(dirptr);
4401 if (count == 0) {
4402 if(err) {
4403 /* Error on close... */
4404 errno = err;
4405 END_PROFILE(SMBcopy);
4406 return(UNIXERROR(ERRHRD,ERRgeneral));
4409 if (exists) {
4410 END_PROFILE(SMBcopy);
4411 return ERROR_DOS(ERRDOS,error);
4412 } else
4414 if((errno == ENOENT) && (bad_path1 || bad_path2))
4416 unix_ERR_class = ERRDOS;
4417 unix_ERR_code = ERRbadpath;
4419 END_PROFILE(SMBcopy);
4420 return(UNIXERROR(ERRDOS,error));
4424 outsize = set_message(outbuf,1,0,True);
4425 SSVAL(outbuf,smb_vwv0,count);
4427 END_PROFILE(SMBcopy);
4428 return(outsize);
4431 /****************************************************************************
4432 Reply to a setdir.
4433 ****************************************************************************/
4435 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4437 int snum;
4438 int outsize = 0;
4439 BOOL ok = False;
4440 pstring newdir;
4441 START_PROFILE(pathworks_setdir);
4443 snum = SNUM(conn);
4444 if (!CAN_SETDIR(snum)) {
4445 END_PROFILE(pathworks_setdir);
4446 return ERROR_DOS(ERRDOS,ERRnoaccess);
4449 pstrcpy(newdir,smb_buf(inbuf) + 1);
4450 strlower(newdir);
4452 if (strlen(newdir) == 0) {
4453 ok = True;
4454 } else {
4455 ok = vfs_directory_exist(conn,newdir,NULL);
4456 if (ok) {
4457 string_set(&conn->connectpath,newdir);
4461 if (!ok) {
4462 END_PROFILE(pathworks_setdir);
4463 return ERROR_DOS(ERRDOS,ERRbadpath);
4466 outsize = set_message(outbuf,0,0,True);
4467 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4469 DEBUG(3,("setdir %s\n", newdir));
4471 END_PROFILE(pathworks_setdir);
4472 return(outsize);
4475 /****************************************************************************
4476 Get a lock pid, dealing with large count requests.
4477 ****************************************************************************/
4479 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4481 if(!large_file_format)
4482 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4483 else
4484 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4487 /****************************************************************************
4488 Get a lock count, dealing with large count requests.
4489 ****************************************************************************/
4491 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4493 SMB_BIG_UINT count = 0;
4495 if(!large_file_format) {
4496 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4497 } else {
4499 #if defined(HAVE_LONGLONG)
4500 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4501 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4502 #else /* HAVE_LONGLONG */
4505 * NT4.x seems to be broken in that it sends large file (64 bit)
4506 * lockingX calls even if the CAP_LARGE_FILES was *not*
4507 * negotiated. For boxes without large unsigned ints truncate the
4508 * lock count by dropping the top 32 bits.
4511 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4512 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4513 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4514 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4515 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4518 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4519 #endif /* HAVE_LONGLONG */
4522 return count;
4525 #if !defined(HAVE_LONGLONG)
4526 /****************************************************************************
4527 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4528 ****************************************************************************/
4530 static uint32 map_lock_offset(uint32 high, uint32 low)
4532 unsigned int i;
4533 uint32 mask = 0;
4534 uint32 highcopy = high;
4537 * Try and find out how many significant bits there are in high.
4540 for(i = 0; highcopy; i++)
4541 highcopy >>= 1;
4544 * We use 31 bits not 32 here as POSIX
4545 * lock offsets may not be negative.
4548 mask = (~0) << (31 - i);
4550 if(low & mask)
4551 return 0; /* Fail. */
4553 high <<= (31 - i);
4555 return (high|low);
4557 #endif /* !defined(HAVE_LONGLONG) */
4559 /****************************************************************************
4560 Get a lock offset, dealing with large offset requests.
4561 ****************************************************************************/
4563 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4565 SMB_BIG_UINT offset = 0;
4567 *err = False;
4569 if(!large_file_format) {
4570 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4571 } else {
4573 #if defined(HAVE_LONGLONG)
4574 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4575 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4576 #else /* HAVE_LONGLONG */
4579 * NT4.x seems to be broken in that it sends large file (64 bit)
4580 * lockingX calls even if the CAP_LARGE_FILES was *not*
4581 * negotiated. For boxes without large unsigned ints mangle the
4582 * lock offset by mapping the top 32 bits onto the lower 32.
4585 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4586 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4587 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4588 uint32 new_low = 0;
4590 if((new_low = map_lock_offset(high, low)) == 0) {
4591 *err = True;
4592 return (SMB_BIG_UINT)-1;
4595 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4596 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4597 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4598 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4601 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4602 #endif /* HAVE_LONGLONG */
4605 return offset;
4608 /****************************************************************************
4609 Reply to a lockingX request.
4610 ****************************************************************************/
4612 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4614 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4615 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4616 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4617 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4618 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4619 SMB_BIG_UINT count = 0, offset = 0;
4620 uint16 lock_pid;
4621 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4622 int i;
4623 char *data;
4624 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4625 BOOL err;
4626 NTSTATUS status;
4628 START_PROFILE(SMBlockingX);
4630 CHECK_FSP(fsp,conn);
4632 data = smb_buf(inbuf);
4634 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4635 /* we don't support these - and CANCEL_LOCK makes w2k
4636 and XP reboot so I don't really want to be
4637 compatible! (tridge) */
4638 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4641 /* Check if this is an oplock break on a file
4642 we have granted an oplock on.
4644 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4645 /* Client can insist on breaking to none. */
4646 BOOL break_to_none = (oplocklevel == 0);
4648 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4649 (unsigned int)oplocklevel, fsp->fnum ));
4652 * Make sure we have granted an exclusive or batch oplock on this file.
4655 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4656 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4657 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4659 /* if this is a pure oplock break request then don't send a reply */
4660 if (num_locks == 0 && num_ulocks == 0) {
4661 END_PROFILE(SMBlockingX);
4662 return -1;
4663 } else {
4664 END_PROFILE(SMBlockingX);
4665 return ERROR_DOS(ERRDOS,ERRlock);
4669 if (remove_oplock(fsp, break_to_none) == False) {
4670 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4671 fsp->fsp_name ));
4674 /* if this is a pure oplock break request then don't send a reply */
4675 if (num_locks == 0 && num_ulocks == 0) {
4676 /* Sanity check - ensure a pure oplock break is not a
4677 chained request. */
4678 if(CVAL(inbuf,smb_vwv0) != 0xff)
4679 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4680 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4681 END_PROFILE(SMBlockingX);
4682 return -1;
4687 * We do this check *after* we have checked this is not a oplock break
4688 * response message. JRA.
4691 release_level_2_oplocks_on_change(fsp);
4693 /* Data now points at the beginning of the list
4694 of smb_unlkrng structs */
4695 for(i = 0; i < (int)num_ulocks; i++) {
4696 lock_pid = get_lock_pid( data, i, large_file_format);
4697 count = get_lock_count( data, i, large_file_format);
4698 offset = get_lock_offset( data, i, large_file_format, &err);
4701 * There is no error code marked "stupid client bug".... :-).
4703 if(err) {
4704 END_PROFILE(SMBlockingX);
4705 return ERROR_DOS(ERRDOS,ERRnoaccess);
4708 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4709 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4711 status = do_unlock(fsp,conn,lock_pid,count,offset);
4712 if (NT_STATUS_V(status)) {
4713 END_PROFILE(SMBlockingX);
4714 return ERROR_NT(status);
4718 /* Setup the timeout in seconds. */
4720 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4722 /* Now do any requested locks */
4723 data += ((large_file_format ? 20 : 10)*num_ulocks);
4725 /* Data now points at the beginning of the list
4726 of smb_lkrng structs */
4728 for(i = 0; i < (int)num_locks; i++) {
4729 lock_pid = get_lock_pid( data, i, large_file_format);
4730 count = get_lock_count( data, i, large_file_format);
4731 offset = get_lock_offset( data, i, large_file_format, &err);
4734 * There is no error code marked "stupid client bug".... :-).
4736 if(err) {
4737 END_PROFILE(SMBlockingX);
4738 return ERROR_DOS(ERRDOS,ERRnoaccess);
4741 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4742 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name,
4743 (int)lock_timeout ));
4745 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4746 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
4748 if (NT_STATUS_V(status)) {
4749 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4751 * A blocking lock was requested. Package up
4752 * this smb into a queued request and push it
4753 * onto the blocking lock queue.
4755 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4756 END_PROFILE(SMBlockingX);
4757 return -1;
4760 break;
4764 /* If any of the above locks failed, then we must unlock
4765 all of the previous locks (X/Open spec). */
4766 if(i != num_locks && num_locks != 0) {
4768 * Ensure we don't do a remove on the lock that just failed,
4769 * as under POSIX rules, if we have a lock already there, we
4770 * will delete it (and we shouldn't) .....
4772 for(i--; i >= 0; i--) {
4773 lock_pid = get_lock_pid( data, i, large_file_format);
4774 count = get_lock_count( data, i, large_file_format);
4775 offset = get_lock_offset( data, i, large_file_format, &err);
4778 * There is no error code marked "stupid client bug".... :-).
4780 if(err) {
4781 END_PROFILE(SMBlockingX);
4782 return ERROR_DOS(ERRDOS,ERRnoaccess);
4785 do_unlock(fsp,conn,lock_pid,count,offset);
4787 END_PROFILE(SMBlockingX);
4788 return ERROR_NT(status);
4791 set_message(outbuf,2,0,True);
4793 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4794 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4796 END_PROFILE(SMBlockingX);
4797 return chain_reply(inbuf,outbuf,length,bufsize);
4800 /* Back from the dead for OS/2..... JRA. */
4802 /****************************************************************************
4803 Reply to a SMBreadbmpx (read block multiplex) request
4804 ****************************************************************************/
4806 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4808 ssize_t nread = -1;
4809 ssize_t total_read;
4810 char *data;
4811 SMB_OFF_T startpos;
4812 int outsize;
4813 size_t maxcount;
4814 int max_per_packet;
4815 size_t tcount;
4816 int pad;
4817 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4818 START_PROFILE(SMBreadBmpx);
4820 /* this function doesn't seem to work - disable by default */
4821 if (!lp_readbmpx()) {
4822 END_PROFILE(SMBreadBmpx);
4823 return ERROR_DOS(ERRSRV,ERRuseSTD);
4826 outsize = set_message(outbuf,8,0,True);
4828 CHECK_FSP(fsp,conn);
4829 CHECK_READ(fsp);
4830 CHECK_ERROR(fsp);
4832 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4833 maxcount = SVAL(inbuf,smb_vwv3);
4835 data = smb_buf(outbuf);
4836 pad = ((long)data)%4;
4837 if (pad)
4838 pad = 4 - pad;
4839 data += pad;
4841 max_per_packet = bufsize-(outsize+pad);
4842 tcount = maxcount;
4843 total_read = 0;
4845 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK, False)) {
4846 END_PROFILE(SMBreadBmpx);
4847 return ERROR_DOS(ERRDOS,ERRlock);
4850 do {
4851 size_t N = MIN(max_per_packet,tcount-total_read);
4853 nread = read_file(fsp,data,startpos,N);
4855 if (nread <= 0)
4856 nread = 0;
4858 if (nread < (ssize_t)N)
4859 tcount = total_read + nread;
4861 set_message(outbuf,8,nread,False);
4862 SIVAL(outbuf,smb_vwv0,startpos);
4863 SSVAL(outbuf,smb_vwv2,tcount);
4864 SSVAL(outbuf,smb_vwv6,nread);
4865 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4867 if (!send_smb(smbd_server_fd(),outbuf))
4868 exit_server("reply_readbmpx: send_smb failed.");
4870 total_read += nread;
4871 startpos += nread;
4872 } while (total_read < (ssize_t)tcount);
4874 END_PROFILE(SMBreadBmpx);
4875 return(-1);
4878 /****************************************************************************
4879 Reply to a SMBsetattrE.
4880 ****************************************************************************/
4882 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4884 struct utimbuf unix_times;
4885 int outsize = 0;
4886 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4887 START_PROFILE(SMBsetattrE);
4889 outsize = set_message(outbuf,0,0,True);
4891 if(!fsp || (fsp->conn != conn)) {
4892 END_PROFILE(SMBsetattrE);
4893 return ERROR_DOS(ERRDOS,ERRbadfid);
4897 * Convert the DOS times into unix times. Ignore create
4898 * time as UNIX can't set this.
4900 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4901 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4904 * Patch from Ray Frush <frush@engr.colostate.edu>
4905 * Sometimes times are sent as zero - ignore them.
4908 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4909 /* Ignore request */
4910 if( DEBUGLVL( 3 ) ) {
4911 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4912 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4914 END_PROFILE(SMBsetattrE);
4915 return(outsize);
4916 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4917 /* set modify time = to access time if modify time was 0 */
4918 unix_times.modtime = unix_times.actime;
4921 /* Set the date on this file */
4922 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4923 END_PROFILE(SMBsetattrE);
4924 return ERROR_DOS(ERRDOS,ERRnoaccess);
4927 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4928 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4930 END_PROFILE(SMBsetattrE);
4931 return(outsize);
4935 /* Back from the dead for OS/2..... JRA. */
4937 /****************************************************************************
4938 Reply to a SMBwritebmpx (write block multiplex primary) request.
4939 ****************************************************************************/
4941 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4943 size_t numtowrite;
4944 ssize_t nwritten = -1;
4945 int outsize = 0;
4946 SMB_OFF_T startpos;
4947 size_t tcount;
4948 BOOL write_through;
4949 int smb_doff;
4950 char *data;
4951 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4952 START_PROFILE(SMBwriteBmpx);
4954 CHECK_FSP(fsp,conn);
4955 CHECK_WRITE(fsp);
4956 CHECK_ERROR(fsp);
4958 tcount = SVAL(inbuf,smb_vwv1);
4959 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4960 write_through = BITSETW(inbuf+smb_vwv7,0);
4961 numtowrite = SVAL(inbuf,smb_vwv10);
4962 smb_doff = SVAL(inbuf,smb_vwv11);
4964 data = smb_base(inbuf) + smb_doff;
4966 /* If this fails we need to send an SMBwriteC response,
4967 not an SMBwritebmpx - set this up now so we don't forget */
4968 SCVAL(outbuf,smb_com,SMBwritec);
4970 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4971 END_PROFILE(SMBwriteBmpx);
4972 return(ERROR_DOS(ERRDOS,ERRlock));
4975 nwritten = write_file(fsp,data,startpos,numtowrite);
4977 if(lp_syncalways(SNUM(conn)) || write_through)
4978 sync_file(conn,fsp);
4980 if(nwritten < (ssize_t)numtowrite) {
4981 END_PROFILE(SMBwriteBmpx);
4982 return(UNIXERROR(ERRHRD,ERRdiskfull));
4985 /* If the maximum to be written to this file
4986 is greater than what we just wrote then set
4987 up a secondary struct to be attached to this
4988 fd, we will use this to cache error messages etc. */
4990 if((ssize_t)tcount > nwritten) {
4991 write_bmpx_struct *wbms;
4992 if(fsp->wbmpx_ptr != NULL)
4993 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4994 else
4995 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4997 if(!wbms) {
4998 DEBUG(0,("Out of memory in reply_readmpx\n"));
4999 END_PROFILE(SMBwriteBmpx);
5000 return(ERROR_DOS(ERRSRV,ERRnoresource));
5002 wbms->wr_mode = write_through;
5003 wbms->wr_discard = False; /* No errors yet */
5004 wbms->wr_total_written = nwritten;
5005 wbms->wr_errclass = 0;
5006 wbms->wr_error = 0;
5007 fsp->wbmpx_ptr = wbms;
5010 /* We are returning successfully, set the message type back to
5011 SMBwritebmpx */
5012 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5014 outsize = set_message(outbuf,1,0,True);
5016 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5018 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5019 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5021 if (write_through && tcount==nwritten) {
5022 /* We need to send both a primary and a secondary response */
5023 smb_setlen(outbuf,outsize - 4);
5024 if (!send_smb(smbd_server_fd(),outbuf))
5025 exit_server("reply_writebmpx: send_smb failed.");
5027 /* Now the secondary */
5028 outsize = set_message(outbuf,1,0,True);
5029 SCVAL(outbuf,smb_com,SMBwritec);
5030 SSVAL(outbuf,smb_vwv0,nwritten);
5033 END_PROFILE(SMBwriteBmpx);
5034 return(outsize);
5037 /****************************************************************************
5038 Reply to a SMBwritebs (write block multiplex secondary) request.
5039 ****************************************************************************/
5041 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5043 size_t numtowrite;
5044 ssize_t nwritten = -1;
5045 int outsize = 0;
5046 SMB_OFF_T startpos;
5047 size_t tcount;
5048 BOOL write_through;
5049 int smb_doff;
5050 char *data;
5051 write_bmpx_struct *wbms;
5052 BOOL send_response = False;
5053 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5054 START_PROFILE(SMBwriteBs);
5056 CHECK_FSP(fsp,conn);
5057 CHECK_WRITE(fsp);
5059 tcount = SVAL(inbuf,smb_vwv1);
5060 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5061 numtowrite = SVAL(inbuf,smb_vwv6);
5062 smb_doff = SVAL(inbuf,smb_vwv7);
5064 data = smb_base(inbuf) + smb_doff;
5066 /* We need to send an SMBwriteC response, not an SMBwritebs */
5067 SCVAL(outbuf,smb_com,SMBwritec);
5069 /* This fd should have an auxiliary struct attached,
5070 check that it does */
5071 wbms = fsp->wbmpx_ptr;
5072 if(!wbms) {
5073 END_PROFILE(SMBwriteBs);
5074 return(-1);
5077 /* If write through is set we can return errors, else we must cache them */
5078 write_through = wbms->wr_mode;
5080 /* Check for an earlier error */
5081 if(wbms->wr_discard) {
5082 END_PROFILE(SMBwriteBs);
5083 return -1; /* Just discard the packet */
5086 nwritten = write_file(fsp,data,startpos,numtowrite);
5088 if(lp_syncalways(SNUM(conn)) || write_through)
5089 sync_file(conn,fsp);
5091 if (nwritten < (ssize_t)numtowrite) {
5092 if(write_through) {
5093 /* We are returning an error - we can delete the aux struct */
5094 SAFE_FREE(wbms);
5095 fsp->wbmpx_ptr = NULL;
5096 END_PROFILE(SMBwriteBs);
5097 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5099 END_PROFILE(SMBwriteBs);
5100 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
5103 /* Increment the total written, if this matches tcount
5104 we can discard the auxiliary struct (hurrah !) and return a writeC */
5105 wbms->wr_total_written += nwritten;
5106 if(wbms->wr_total_written >= tcount) {
5107 if (write_through) {
5108 outsize = set_message(outbuf,1,0,True);
5109 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5110 send_response = True;
5113 SAFE_FREE(wbms);
5114 fsp->wbmpx_ptr = NULL;
5117 if(send_response) {
5118 END_PROFILE(SMBwriteBs);
5119 return(outsize);
5122 END_PROFILE(SMBwriteBs);
5123 return(-1);
5126 /****************************************************************************
5127 Reply to a SMBgetattrE.
5128 ****************************************************************************/
5130 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5132 SMB_STRUCT_STAT sbuf;
5133 int outsize = 0;
5134 int mode;
5135 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5136 START_PROFILE(SMBgetattrE);
5138 outsize = set_message(outbuf,11,0,True);
5140 if(!fsp || (fsp->conn != conn)) {
5141 END_PROFILE(SMBgetattrE);
5142 return ERROR_DOS(ERRDOS,ERRbadfid);
5145 /* Do an stat on this file */
5147 if(fsp_stat(fsp, &sbuf)) {
5148 END_PROFILE(SMBgetattrE);
5149 return(UNIXERROR(ERRDOS,ERRnoaccess));
5152 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5154 /* Convert the times into dos times. Set create
5155 * date to be last modify date as UNIX doesn't save
5156 * this.
5159 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5160 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5161 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5162 if (mode & aDIR) {
5163 SIVAL(outbuf,smb_vwv6,0);
5164 SIVAL(outbuf,smb_vwv8,0);
5165 } else {
5166 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5167 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
5169 SSVAL(outbuf,smb_vwv10, mode);
5171 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5173 END_PROFILE(SMBgetattrE);
5174 return(outsize);