add WITH_SENDFILE profiling data (from Pierre Belanger)
[Samba.git] / source / smbd / reply.c
blob775eb5dfe14daba75ab94e4d05f2a4cae90d8d71
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 pstring user;
710 pstring 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 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
736 * Incoming user is in DOS codepage format. Convert
737 * to UNIX.
739 pstrcpy(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);
750 if(global_client_caps == 0)
751 global_client_caps = IVAL(inbuf,smb_vwv11);
753 /* client_caps is used as final determination if client is NT or Win95.
754 This is needed to return the correct error codes in some
755 circumstances.
758 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
759 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
760 set_remote_arch( RA_WIN95);
764 if (passlen1 != 24 && passlen2 != 24)
765 doencrypt = False;
767 if (passlen1 > MAX_PASS_LEN) {
768 overflow_attack(passlen1);
769 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
772 passlen1 = MIN(passlen1, MAX_PASS_LEN);
773 passlen2 = MIN(passlen2, MAX_PASS_LEN);
775 if(!doencrypt) {
776 /* both Win95 and WinNT stuff up the password lengths for
777 non-encrypting systems. Uggh.
779 if passlen1==24 its a win95 system, and its setting the
780 password length incorrectly. Luckily it still works with the
781 default code because Win95 will null terminate the password
782 anyway
784 if passlen1>0 and passlen2>0 then maybe its a NT box and its
785 setting passlen2 to some random value which really stuffs
786 things up. we need to fix that one. */
788 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
789 passlen2 = 0;
792 if (lp_restrict_anonymous()) {
793 /* there seems to be no reason behind the differences in MS clients formatting
794 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
795 * in particular seems to have an extra null byte between the username and the
796 * domain, or the password length calculation is wrong, which throws off the
797 * string extraction routines below. This makes the value of domain be the
798 * empty string, which fails the restrict anonymous check further down.
799 * This compensates for that, and allows browsing to work in mixed NT and
800 * win95 environments even when restrict anonymous is true. AAB
802 dump_data(100, p, 0x70);
803 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
804 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
805 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
806 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
807 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
808 passlen1 = 1;
812 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
813 /* Save the lanman2 password and the NT md4 password. */
814 smb_apasslen = passlen1;
815 memcpy(smb_apasswd,p,smb_apasslen);
816 smb_apasswd[smb_apasslen] = 0;
817 smb_ntpasslen = passlen2;
818 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
819 smb_ntpasswd[smb_ntpasslen] = 0;
822 * Ensure the plaintext passwords are in UNIX format.
824 if(!doencrypt) {
825 pstrcpy(smb_apasswd,dos_to_unix_static(smb_apasswd));
826 pstrcpy(smb_ntpasswd,dos_to_unix_static(smb_ntpasswd));
829 } else {
830 /* we use the first password that they gave */
831 smb_apasslen = passlen1;
832 StrnCpy(smb_apasswd,p,smb_apasslen);
834 * Ensure the plaintext password is in UNIX format.
836 pstrcpy(smb_apasswd,dos_to_unix_static(smb_apasswd));
838 /* trim the password */
839 smb_apasslen = strlen(smb_apasswd);
841 /* wfwg sometimes uses a space instead of a null */
842 if (strequal(smb_apasswd," ")) {
843 smb_apasslen = 0;
844 *smb_apasswd = 0;
848 p += passlen1 + passlen2;
849 fstrcpy(user,p);
850 p = skip_string(p,1);
852 * Incoming user and domain are in DOS codepage format. Convert
853 * to UNIX.
855 pstrcpy(user,dos_to_unix_static(user));
856 fstrcpy(domain, dos_to_unix_static(p));
857 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
858 domain,skip_string(p,1),skip_string(p,2)));
861 /* don't allow strange characters in usernames or domains */
862 alpha_strcpy(user, user, ". _-$", sizeof(user));
863 alpha_strcpy(domain, domain, ". _-@", sizeof(domain));
864 if (strstr(user, "..") || strstr(domain,"..")) {
865 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
868 DEBUG(3,("sesssetupX:name=[%s]\n",user));
870 /* If name ends in $ then I think it's asking about whether a */
871 /* computer with that name (minus the $) has access. For now */
872 /* say yes to everything ending in $. */
874 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
875 END_PROFILE(SMBsesssetupX);
876 return session_trust_account(conn, inbuf, outbuf, user,
877 smb_apasswd, smb_apasslen,
878 smb_ntpasswd, smb_ntpasslen);
881 if (done_sesssetup && lp_restrict_anonymous()) {
882 /* tests show that even if browsing is done over already validated connections
883 * without a username and password the domain is still provided, which it
884 * wouldn't be if it was a purely anonymous connection. So, in order to
885 * restrict anonymous, we only deny connections that have no session
886 * information. If a domain has been provided, then it's not a purely
887 * anonymous connection. AAB
889 if (!*user && !*smb_apasswd && !*domain) {
890 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
891 END_PROFILE(SMBsesssetupX);
892 return(ERROR_DOS(ERRDOS,ERRnoaccess));
896 /* If no username is sent use the guest account */
897 if (!*user) {
898 pstrcpy(user,lp_guestaccount(-1));
899 guest = True;
902 pstrcpy(current_user_info.smb_name,user);
904 reload_services(True);
907 * Save the username before mapping. We will use
908 * the original username sent to us for security=server
909 * and security=domain checking.
912 pstrcpy( orig_user, user);
915 * Always try the "DOMAIN\user" lookup first, as this is the most
916 * specific case. If this fails then try the simple "user" lookup.
920 pstring dom_user;
922 /* Work out who's who */
924 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
925 domain, lp_winbind_separator(), user);
927 if (sys_getpwnam(dom_user) != NULL) {
928 pstrcpy(user, dom_user);
929 DEBUG(3,("Using unix username %s\n", dom_user));
934 * Pass the user through the NT -> unix user mapping
935 * function.
938 (void)map_username(user);
941 * Do any UNIX username case mangling.
943 smb_getpwnam(user, True);
945 add_session_user(user);
948 * Check with orig_user for security=server and
949 * security=domain.
952 if (!guest && !check_server_security(orig_user, domain, user,
953 smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
954 !check_domain_security(orig_user, domain, user, smb_apasswd,
955 smb_apasslen, smb_ntpasswd, smb_ntpasslen, &ptok) &&
956 !check_hosts_equiv(user))
960 * If we get here then the user wasn't guest and the remote
961 * authentication methods failed. Check the authentication
962 * methods on this local server.
964 * If an NT password was supplied try and validate with that
965 * first. This is superior as the passwords are mixed case
966 * 128 length unicode.
969 if(smb_ntpasslen)
971 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
972 DEBUG(2,("NT Password did not match for user '%s'!\n", user));
973 else
974 valid_nt_password = True;
978 /* check the LanMan password only if necessary and if allowed
979 by lp_lanman_auth() */
980 if (!valid_nt_password && lp_lanman_auth())
982 DEBUG(2,("Defaulting to Lanman password for %s\n", user));
983 valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen,NULL);
987 /* The true branch will be executed if
988 (1) the NT password failed (or was not tried), and
989 (2) LanMan authentication failed (or was disabled)
991 if (!valid_nt_password && !valid_lm_password)
993 if (lp_security() >= SEC_USER)
995 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
997 delete_nt_token(&ptok);
998 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
999 END_PROFILE(SMBsesssetupX);
1000 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
1003 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
1005 SAM_ACCOUNT *sampass = NULL;
1007 pdb_init_sam(&sampass);
1010 * This is really bad form. We know that password_ok() failed,
1011 * but the return value can't distinguish between a non-existent user
1012 * and a bad password. So we try to look the user up again here
1013 * to see if he or she exists. We must look up the user in the
1014 * "smb passwd file" and not /etc/passwd so that we don't
1015 * get confused when the two don't have a one-to-one correspondence.
1016 * e.g. a standard UNIX account such as "operator" --jerry
1019 if (pdb_getsampwnam(sampass, user))
1021 delete_nt_token(&ptok);
1022 DEBUG(1,("Rejecting user '%s': bad password\n", user));
1023 END_PROFILE(SMBsesssetupX);
1024 pdb_free_sam(sampass);
1025 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
1028 pdb_free_sam(sampass);
1032 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
1033 * Then always map to guest account - as done below.
1037 if (*smb_apasswd || !smb_getpwnam(user,True))
1038 pstrcpy(user,lp_guestaccount(-1));
1039 DEBUG(3,("Registered username %s for guest access\n",user));
1040 guest = True;
1044 if (!smb_getpwnam(user,True)) {
1045 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
1046 pstrcpy(user,lp_guestaccount(-1));
1047 guest = True;
1050 if (!strequal(user,lp_guestaccount(-1)) &&
1051 lp_servicenumber(user) < 0)
1053 add_home_service(user,get_user_service_home_dir(user));
1057 /* it's ok - setup a reply */
1058 if (Protocol < PROTOCOL_NT1) {
1059 set_message(outbuf,3,0,True);
1060 } else {
1061 char *p;
1062 set_message(outbuf,3,3,True);
1063 p = smb_buf(outbuf);
1064 pstrcpy(p,"Unix"); p = skip_string(p,1);
1065 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
1066 pstrcpy(p,global_myworkgroup); unix_to_dos(p); p = skip_string(p,1);
1067 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
1068 /* perhaps grab OS version here?? */
1071 /* Set the correct uid in the outgoing and incoming packets
1072 We will use this on future requests to determine which
1073 user we should become.
1076 const struct passwd *pw = smb_getpwnam(user,False);
1077 if (!pw) {
1078 delete_nt_token(&ptok);
1079 DEBUG(1,("Username %s is invalid on this system\n",user));
1080 END_PROFILE(SMBsesssetupX);
1081 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
1083 gid = pw->pw_gid;
1084 uid = pw->pw_uid;
1087 if (guest)
1088 SSVAL(outbuf,smb_vwv2,1);
1090 /* register the name and uid as being validated, so further connections
1091 to a uid can get through without a password, on the same VC */
1093 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest,&ptok);
1095 delete_nt_token(&ptok);
1097 if (sess_vuid == -1) {
1098 END_PROFILE(SMBsesssetupX);
1099 return(ERROR_DOS(ERRDOS,ERRnoaccess));
1102 SSVAL(outbuf,smb_uid,sess_vuid);
1103 SSVAL(inbuf,smb_uid,sess_vuid);
1105 if (!done_sesssetup)
1106 max_send = MIN(max_send,smb_bufsize);
1108 DEBUG(6,("Client requested max send size of %d\n", max_send));
1110 done_sesssetup = True;
1112 END_PROFILE(SMBsesssetupX);
1113 return chain_reply(inbuf,outbuf,length,bufsize);
1116 /****************************************************************************
1117 Reply to a chkpth.
1118 ****************************************************************************/
1120 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1122 int outsize = 0;
1123 int mode;
1124 pstring name;
1125 BOOL ok = False;
1126 BOOL bad_path = False;
1127 SMB_STRUCT_STAT sbuf;
1128 START_PROFILE(SMBchkpth);
1130 pstrcpy(name,smb_buf(inbuf) + 1);
1132 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1134 unix_convert(name,conn,0,&bad_path,&sbuf);
1136 mode = SVAL(inbuf,smb_vwv0);
1138 if (check_name(name,conn)) {
1139 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
1140 ok = S_ISDIR(sbuf.st_mode);
1143 if (!ok) {
1144 /* We special case this - as when a Windows machine
1145 is parsing a path is steps through the components
1146 one at a time - if a component fails it expects
1147 ERRbadpath, not ERRbadfile.
1149 if(errno == ENOENT) {
1150 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1153 return(UNIXERROR(ERRDOS,ERRbadpath));
1156 outsize = set_message(outbuf,0,0,True);
1158 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1160 END_PROFILE(SMBchkpth);
1161 return(outsize);
1164 /****************************************************************************
1165 Reply to a getatr.
1166 ****************************************************************************/
1168 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1170 pstring fname;
1171 int outsize = 0;
1172 SMB_STRUCT_STAT sbuf;
1173 BOOL ok = False;
1174 int mode=0;
1175 SMB_OFF_T size=0;
1176 time_t mtime=0;
1177 BOOL bad_path = False;
1178 START_PROFILE(SMBgetatr);
1180 pstrcpy(fname,smb_buf(inbuf) + 1);
1182 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1184 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1185 under WfWg - weird! */
1186 if (! (*fname))
1188 mode = aHIDDEN | aDIR;
1189 if (!CAN_WRITE(conn)) mode |= aRONLY;
1190 size = 0;
1191 mtime = 0;
1192 ok = True;
1194 else
1196 unix_convert(fname,conn,0,&bad_path,&sbuf);
1197 if (check_name(fname,conn))
1199 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1201 mode = dos_mode(conn,fname,&sbuf);
1202 size = sbuf.st_size;
1203 mtime = sbuf.st_mtime;
1204 if (mode & aDIR)
1205 size = 0;
1206 ok = True;
1208 else
1209 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1213 if (!ok)
1215 set_bad_path_error(errno, bad_path);
1216 END_PROFILE(SMBgetatr);
1217 return(UNIXERROR(ERRDOS,ERRbadfile));
1220 outsize = set_message(outbuf,10,0,True);
1222 SSVAL(outbuf,smb_vwv0,mode);
1223 if(lp_dos_filetime_resolution(SNUM(conn)) )
1224 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1225 else
1226 put_dos_date3(outbuf,smb_vwv1,mtime);
1227 SIVAL(outbuf,smb_vwv3,(uint32)size);
1229 if (Protocol >= PROTOCOL_NT1)
1230 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1232 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1234 END_PROFILE(SMBgetatr);
1235 return(outsize);
1238 /****************************************************************************
1239 Reply to a setatr.
1240 ****************************************************************************/
1242 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1244 pstring fname;
1245 int outsize = 0;
1246 BOOL ok=False;
1247 int mode;
1248 time_t mtime;
1249 SMB_STRUCT_STAT sbuf;
1250 BOOL bad_path = False;
1251 START_PROFILE(SMBsetatr);
1253 pstrcpy(fname,smb_buf(inbuf) + 1);
1254 unix_convert(fname,conn,0,&bad_path,&sbuf);
1256 mode = SVAL(inbuf,smb_vwv0);
1257 mtime = make_unix_date3(inbuf+smb_vwv1);
1259 if (VALID_STAT_OF_DIR(sbuf))
1260 mode |= aDIR;
1261 else
1262 mode &= ~aDIR;
1264 if (check_name(fname,conn))
1265 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1266 if (ok)
1267 ok = set_filetime(conn,fname,mtime);
1269 if (!ok)
1271 set_bad_path_error(errno, bad_path);
1272 END_PROFILE(SMBsetatr);
1273 return(UNIXERROR(ERRDOS,ERRnoaccess));
1276 outsize = set_message(outbuf,0,0,True);
1278 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1280 END_PROFILE(SMBsetatr);
1281 return(outsize);
1284 /****************************************************************************
1285 Reply to a dskattr.
1286 ****************************************************************************/
1288 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1290 int outsize = 0;
1291 SMB_BIG_UINT dfree,dsize,bsize;
1292 START_PROFILE(SMBdskattr);
1294 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1296 outsize = set_message(outbuf,5,0,True);
1298 if (Protocol <= PROTOCOL_LANMAN2) {
1299 double total_space, free_space;
1300 /* we need to scale this to a number that DOS6 can handle. We
1301 use floating point so we can handle large drives on systems
1302 that don't have 64 bit integers
1304 we end up displaying a maximum of 2G to DOS systems
1306 total_space = dsize * (double)bsize;
1307 free_space = dfree * (double)bsize;
1309 dsize = (total_space+63*512) / (64*512);
1310 dfree = (free_space+63*512) / (64*512);
1312 if (dsize > 0xFFFF) dsize = 0xFFFF;
1313 if (dfree > 0xFFFF) dfree = 0xFFFF;
1315 SSVAL(outbuf,smb_vwv0,dsize);
1316 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1317 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
1318 SSVAL(outbuf,smb_vwv3,dfree);
1319 } else {
1320 SSVAL(outbuf,smb_vwv0,dsize);
1321 SSVAL(outbuf,smb_vwv1,bsize/512);
1322 SSVAL(outbuf,smb_vwv2,512);
1323 SSVAL(outbuf,smb_vwv3,dfree);
1326 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1328 END_PROFILE(SMBdskattr);
1329 return(outsize);
1332 /****************************************************************************
1333 Reply to a search.
1334 Can be called from SMBsearch, SMBffirst or SMBfunique.
1335 ****************************************************************************/
1337 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1339 pstring mask;
1340 pstring directory;
1341 pstring fname;
1342 SMB_OFF_T size;
1343 int mode;
1344 time_t date;
1345 int dirtype;
1346 int outsize = 0;
1347 int numentries = 0;
1348 BOOL finished = False;
1349 int maxentries;
1350 int i;
1351 char *p;
1352 BOOL ok = False;
1353 int status_len;
1354 char *path;
1355 char status[21];
1356 int dptr_num= -1;
1357 BOOL check_descend = False;
1358 BOOL expect_close = False;
1359 BOOL can_open = True;
1360 BOOL bad_path = False;
1361 START_PROFILE(SMBsearch);
1363 *mask = *directory = *fname = 0;
1365 /* If we were called as SMBffirst then we must expect close. */
1366 if(CVAL(inbuf,smb_com) == SMBffirst)
1367 expect_close = True;
1369 outsize = set_message(outbuf,1,3,True);
1370 maxentries = SVAL(inbuf,smb_vwv0);
1371 dirtype = SVAL(inbuf,smb_vwv1);
1372 path = smb_buf(inbuf) + 1;
1373 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1375 RESOLVE_DFSPATH(path, conn, inbuf, outbuf);
1376 /* dirtype &= ~aDIR; */
1378 if (status_len == 0)
1380 SMB_STRUCT_STAT sbuf;
1381 pstring dir2;
1383 pstrcpy(directory,smb_buf(inbuf)+1);
1384 pstrcpy(dir2,smb_buf(inbuf)+1);
1385 unix_convert(directory,conn,0,&bad_path,&sbuf);
1386 unix_format(dir2);
1388 if (!check_name(directory,conn))
1389 can_open = False;
1391 p = strrchr(dir2,'/');
1392 if (p == NULL)
1394 pstrcpy(mask,dir2);
1395 *dir2 = 0;
1397 else
1399 *p = 0;
1400 pstrcpy(mask,p+1);
1403 p = strrchr(directory,'/');
1404 if (!p)
1405 *directory = 0;
1406 else
1407 *p = 0;
1409 if (strlen(directory) == 0)
1410 pstrcpy(directory,"./");
1411 memset((char *)status,'\0',21);
1412 SCVAL(status,0,(dirtype & 0x1F));
1414 else
1416 int status_dirtype;
1417 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1418 status_dirtype = CVAL(status,0) & 0x1F;
1419 if (status_dirtype != (dirtype & 0x1F))
1420 dirtype = status_dirtype;
1421 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1422 if (!conn->dirptr)
1423 goto SearchEmpty;
1424 string_set(&conn->dirpath,dptr_path(dptr_num));
1425 fstrcpy(mask, dptr_wcard(dptr_num));
1428 if (can_open)
1430 p = smb_buf(outbuf) + 3;
1432 ok = True;
1434 if (status_len == 0)
1436 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1437 if (dptr_num < 0)
1439 if(dptr_num == -2)
1441 set_bad_path_error(errno, bad_path);
1442 END_PROFILE(SMBsearch);
1443 return (UNIXERROR(ERRDOS,ERRnofids));
1445 END_PROFILE(SMBsearch);
1446 return ERROR_DOS(ERRDOS,ERRnofids);
1448 dptr_set_wcard(dptr_num, strdup(mask));
1451 DEBUG(4,("dptr_num is %d\n",dptr_num));
1453 if (ok)
1455 if ((dirtype&0x1F) == aVOLID)
1457 memcpy(p,status,21);
1458 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1459 dptr_fill(p+12,dptr_num);
1460 if (dptr_zero(p+12) && (status_len==0))
1461 numentries = 1;
1462 else
1463 numentries = 0;
1464 p += DIR_STRUCT_SIZE;
1466 else
1468 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1469 conn->dirpath,lp_dontdescend(SNUM(conn))));
1470 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1471 check_descend = True;
1473 for (i=numentries;(i<maxentries) && !finished;i++)
1475 finished =
1476 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1477 if (!finished)
1479 memcpy(p,status,21);
1480 make_dir_struct(p,mask,fname,size,mode,date);
1481 dptr_fill(p+12,dptr_num);
1482 numentries++;
1484 p += DIR_STRUCT_SIZE;
1487 } /* if (ok ) */
1491 SearchEmpty:
1493 if ( (numentries == 0) || !ok)
1495 SCVAL(outbuf,smb_rcls,ERRDOS);
1496 SSVAL(outbuf,smb_err,ERRnofiles);
1497 dptr_close(&dptr_num);
1500 /* If we were called as SMBffirst with smb_search_id == NULL
1501 and no entries were found then return error and close dirptr
1502 (X/Open spec) */
1504 if(ok && expect_close && numentries == 0 && status_len == 0)
1506 SCVAL(outbuf,smb_rcls,ERRDOS);
1507 SSVAL(outbuf,smb_err,ERRnofiles);
1508 /* Also close the dptr - we know it's gone */
1509 dptr_close(&dptr_num);
1512 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1513 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1514 dptr_close(&dptr_num);
1516 SSVAL(outbuf,smb_vwv0,numentries);
1517 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1518 SCVAL(smb_buf(outbuf),0,5);
1519 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1521 if (Protocol >= PROTOCOL_NT1)
1522 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1524 outsize += DIR_STRUCT_SIZE*numentries;
1525 smb_setlen(outbuf,outsize - 4);
1527 if ((! *directory) && dptr_path(dptr_num))
1528 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1530 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1531 smb_fn_name(CVAL(inbuf,smb_com)),
1532 mask, directory, dirtype, numentries, maxentries ) );
1534 END_PROFILE(SMBsearch);
1535 return(outsize);
1538 /****************************************************************************
1539 Reply to a fclose (stop directory search).
1540 ****************************************************************************/
1542 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1544 int outsize = 0;
1545 int status_len;
1546 char *path;
1547 char status[21];
1548 int dptr_num= -2;
1549 START_PROFILE(SMBfclose);
1551 outsize = set_message(outbuf,1,0,True);
1552 path = smb_buf(inbuf) + 1;
1553 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1556 if (status_len == 0) {
1557 END_PROFILE(SMBfclose);
1558 return ERROR_DOS(ERRSRV,ERRsrverror);
1561 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1563 if(dptr_fetch(status+12,&dptr_num)) {
1564 /* Close the dptr - we know it's gone */
1565 dptr_close(&dptr_num);
1568 SSVAL(outbuf,smb_vwv0,0);
1570 DEBUG(3,("search close\n"));
1572 END_PROFILE(SMBfclose);
1573 return(outsize);
1576 /****************************************************************************
1577 Reply to an open.
1578 ****************************************************************************/
1580 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1582 pstring fname;
1583 int outsize = 0;
1584 int fmode=0;
1585 int share_mode;
1586 SMB_OFF_T size = 0;
1587 time_t mtime=0;
1588 mode_t unixmode;
1589 int rmode=0;
1590 SMB_STRUCT_STAT sbuf;
1591 BOOL bad_path = False;
1592 files_struct *fsp;
1593 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1594 START_PROFILE(SMBopen);
1596 share_mode = SVAL(inbuf,smb_vwv0);
1598 pstrcpy(fname,smb_buf(inbuf)+1);
1600 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1602 unix_convert(fname,conn,0,&bad_path,&sbuf);
1604 unixmode = unix_mode(conn,aARCH,fname);
1606 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1607 unixmode, oplock_request,&rmode,NULL);
1609 if (!fsp)
1611 set_bad_path_error(errno, bad_path);
1612 END_PROFILE(SMBopen);
1613 return(UNIXERROR(ERRDOS,ERRnoaccess));
1616 size = sbuf.st_size;
1617 fmode = dos_mode(conn,fname,&sbuf);
1618 mtime = sbuf.st_mtime;
1620 if (fmode & aDIR) {
1621 DEBUG(3,("attempt to open a directory %s\n",fname));
1622 close_file(fsp,False);
1623 END_PROFILE(SMBopen);
1624 return ERROR_DOS(ERRDOS,ERRnoaccess);
1627 outsize = set_message(outbuf,7,0,True);
1628 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1629 SSVAL(outbuf,smb_vwv1,fmode);
1630 if(lp_dos_filetime_resolution(SNUM(conn)) )
1631 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1632 else
1633 put_dos_date3(outbuf,smb_vwv2,mtime);
1634 SIVAL(outbuf,smb_vwv4,(uint32)size);
1635 SSVAL(outbuf,smb_vwv6,rmode);
1637 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1638 SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1641 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1642 SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1643 END_PROFILE(SMBopen);
1644 return(outsize);
1647 /****************************************************************************
1648 Reply to an open and X.
1649 ****************************************************************************/
1651 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1653 pstring fname;
1654 int smb_mode = SVAL(inbuf,smb_vwv3);
1655 int smb_attr = SVAL(inbuf,smb_vwv5);
1656 /* Breakout the oplock request bits so we can set the
1657 reply bits separately. */
1658 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1659 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1660 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1661 #if 0
1662 int open_flags = SVAL(inbuf,smb_vwv2);
1663 int smb_sattr = SVAL(inbuf,smb_vwv4);
1664 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1665 #endif
1666 int smb_ofun = SVAL(inbuf,smb_vwv8);
1667 mode_t unixmode;
1668 SMB_OFF_T size=0;
1669 int fmode=0,mtime=0,rmode=0;
1670 SMB_STRUCT_STAT sbuf;
1671 int smb_action = 0;
1672 BOOL bad_path = False;
1673 files_struct *fsp;
1674 START_PROFILE(SMBopenX);
1676 /* If it's an IPC, pass off the pipe handler. */
1677 if (IS_IPC(conn)) {
1678 if (lp_nt_pipe_support()) {
1679 END_PROFILE(SMBopenX);
1680 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1681 } else {
1682 END_PROFILE(SMBopenX);
1683 return ERROR_DOS(ERRSRV,ERRaccess);
1687 /* XXXX we need to handle passed times, sattr and flags */
1689 pstrcpy(fname,smb_buf(inbuf));
1691 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1693 unix_convert(fname,conn,0,&bad_path,&sbuf);
1695 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1697 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1698 oplock_request, &rmode,&smb_action);
1700 if (!fsp)
1702 set_bad_path_error(errno, bad_path);
1703 END_PROFILE(SMBopenX);
1704 return(UNIXERROR(ERRDOS,ERRnoaccess));
1707 size = sbuf.st_size;
1708 fmode = dos_mode(conn,fname,&sbuf);
1709 mtime = sbuf.st_mtime;
1710 if (fmode & aDIR) {
1711 close_file(fsp,False);
1712 END_PROFILE(SMBopenX);
1713 return ERROR_DOS(ERRDOS,ERRnoaccess);
1716 /* If the caller set the extended oplock request bit
1717 and we granted one (by whatever means) - set the
1718 correct bit for extended oplock reply.
1721 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1722 smb_action |= EXTENDED_OPLOCK_GRANTED;
1725 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1726 smb_action |= EXTENDED_OPLOCK_GRANTED;
1729 /* If the caller set the core oplock request bit
1730 and we granted one (by whatever means) - set the
1731 correct bit for core oplock reply.
1734 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1735 SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1738 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1739 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1742 set_message(outbuf,15,0,True);
1743 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1744 SSVAL(outbuf,smb_vwv3,fmode);
1745 if(lp_dos_filetime_resolution(SNUM(conn)) )
1746 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1747 else
1748 put_dos_date3(outbuf,smb_vwv4,mtime);
1749 SIVAL(outbuf,smb_vwv6,(uint32)size);
1750 SSVAL(outbuf,smb_vwv8,rmode);
1751 SSVAL(outbuf,smb_vwv11,smb_action);
1753 END_PROFILE(SMBopenX);
1754 return chain_reply(inbuf,outbuf,length,bufsize);
1757 /****************************************************************************
1758 Reply to a SMBulogoffX.
1759 ****************************************************************************/
1761 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1763 uint16 vuid = SVAL(inbuf,smb_uid);
1764 user_struct *vuser = get_valid_user_struct(vuid);
1765 START_PROFILE(SMBulogoffX);
1767 if(vuser == 0) {
1768 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1771 /* in user level security we are supposed to close any files
1772 open by this user */
1773 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1774 file_close_user(vuid);
1777 invalidate_vuid(vuid);
1779 set_message(outbuf,2,0,True);
1781 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1783 END_PROFILE(SMBulogoffX);
1784 return chain_reply(inbuf,outbuf,length,bufsize);
1787 /****************************************************************************
1788 Reply to a mknew or a create.
1789 ****************************************************************************/
1791 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1793 pstring fname;
1794 int com;
1795 int outsize = 0;
1796 int createmode;
1797 mode_t unixmode;
1798 int ofun = 0;
1799 BOOL bad_path = False;
1800 files_struct *fsp;
1801 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1802 SMB_STRUCT_STAT sbuf;
1803 START_PROFILE(SMBcreate);
1805 com = SVAL(inbuf,smb_com);
1807 createmode = SVAL(inbuf,smb_vwv0);
1808 pstrcpy(fname,smb_buf(inbuf)+1);
1810 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1812 unix_convert(fname,conn,0,&bad_path,&sbuf);
1814 if (createmode & aVOLID) {
1815 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1818 unixmode = unix_mode(conn,createmode,fname);
1820 if(com == SMBmknew)
1822 /* We should fail if file exists. */
1823 ofun = FILE_CREATE_IF_NOT_EXIST;
1825 else
1827 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1828 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1831 /* Open file in dos compatibility share mode. */
1832 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1833 ofun, unixmode, oplock_request, NULL, NULL);
1835 if (!fsp)
1837 set_bad_path_error(errno, bad_path);
1838 END_PROFILE(SMBcreate);
1839 return(UNIXERROR(ERRDOS,ERRnoaccess));
1842 outsize = set_message(outbuf,1,0,True);
1843 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1845 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1846 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1849 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1850 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1852 DEBUG( 2, ( "new file %s\n", fname ) );
1853 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1854 fname, fsp->fd, createmode, (int)unixmode ) );
1856 END_PROFILE(SMBcreate);
1857 return(outsize);
1860 /****************************************************************************
1861 Reply to a create temporary file.
1862 ****************************************************************************/
1864 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1866 pstring fname;
1867 int outsize = 0;
1868 int createmode;
1869 mode_t unixmode;
1870 BOOL bad_path = False;
1871 files_struct *fsp;
1872 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1873 int tmpfd;
1874 SMB_STRUCT_STAT sbuf;
1875 char *p, *s;
1877 START_PROFILE(SMBctemp);
1879 createmode = SVAL(inbuf,smb_vwv0);
1880 pstrcpy(fname,smb_buf(inbuf)+1);
1881 pstrcat(fname,"\\TMXXXXXX");
1883 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1885 unix_convert(fname,conn,0,&bad_path,&sbuf);
1887 unixmode = unix_mode(conn,createmode,fname);
1889 tmpfd = smb_mkstemp(fname);
1890 if (tmpfd == -1) {
1891 END_PROFILE(SMBctemp);
1892 return(UNIXERROR(ERRDOS,ERRnoaccess));
1895 vfs_stat(conn,fname,&sbuf);
1897 /* Open file in dos compatibility share mode. */
1898 /* We should fail if file does not exist. */
1899 fsp = open_file_shared(conn,fname,&sbuf,
1900 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1901 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1902 unixmode, oplock_request, NULL, NULL);
1903 /* close fd from smb_mkstemp() */
1904 close(tmpfd);
1906 if (!fsp) {
1907 set_bad_path_error(errno, bad_path);
1908 END_PROFILE(SMBctemp);
1909 return(UNIXERROR(ERRDOS,ERRnoaccess));
1912 /* the returned filename is relative to the directory */
1913 s = strrchr(fname, '/');
1914 if (!s)
1915 s = fname;
1916 else
1917 s++;
1919 outsize = set_message(outbuf,1,4+ strlen(fname),True);
1920 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1922 p = smb_buf(outbuf);
1923 SSVALS(p, 0, -1); /* what is this? not in spec */
1924 SSVAL(p, 2, strlen(s));
1925 p += 4;
1926 pstrcpy(p,s);
1928 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1929 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1932 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1933 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1935 DEBUG( 2, ( "created temp file %s\n", fname ) );
1936 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1937 fname, fsp->fd, createmode, (int)unixmode ) );
1939 END_PROFILE(SMBctemp);
1940 return(outsize);
1943 /*******************************************************************
1944 Check if a user is allowed to rename a file.
1945 ********************************************************************/
1947 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1949 int smb_action;
1950 int access_mode;
1951 files_struct *fsp;
1953 if (!CAN_WRITE(conn))
1954 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1956 if (S_ISDIR(pst->st_mode))
1957 return NT_STATUS_OK;
1959 /* We need a better way to return NT status codes from open... */
1960 unix_ERR_class = 0;
1961 unix_ERR_code = 0;
1963 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1964 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1966 if (!fsp) {
1967 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1968 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1969 ret = NT_STATUS_SHARING_VIOLATION;
1970 unix_ERR_class = 0;
1971 unix_ERR_code = 0;
1972 return ret;
1974 close_file(fsp,False);
1975 return NT_STATUS_OK;
1978 /*******************************************************************
1979 Check if a user is allowed to delete a file.
1980 ********************************************************************/
1982 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1984 SMB_STRUCT_STAT sbuf;
1985 int fmode;
1986 int smb_action;
1987 int access_mode;
1988 files_struct *fsp;
1990 if (!CAN_WRITE(conn))
1991 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1993 if (conn->vfs_ops.lstat(conn,dos_to_unix_static(fname),&sbuf) != 0)
1994 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1996 fmode = dos_mode(conn,fname,&sbuf);
1997 if (fmode & aDIR)
1998 return NT_STATUS_FILE_IS_A_DIRECTORY;
1999 if (!lp_delete_readonly(SNUM(conn))) {
2000 if (fmode & aRONLY)
2001 return NT_STATUS_CANNOT_DELETE;
2004 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
2005 return NT_STATUS_CANNOT_DELETE;
2007 /* We need a better way to return NT status codes from open... */
2008 unix_ERR_class = 0;
2009 unix_ERR_code = 0;
2011 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
2012 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
2014 if (!fsp) {
2015 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
2016 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
2017 ret = NT_STATUS_SHARING_VIOLATION;
2018 unix_ERR_class = 0;
2019 unix_ERR_code = 0;
2020 return ret;
2022 close_file(fsp,False);
2023 return NT_STATUS_OK;
2026 /****************************************************************************
2027 The guts of the unlink command, split out so it may be called by the NT SMB
2028 code.
2029 ****************************************************************************/
2031 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
2033 pstring directory;
2034 pstring mask;
2035 char *p;
2036 int count=0;
2037 NTSTATUS error = NT_STATUS_OK;
2038 BOOL has_wild;
2039 BOOL bad_path = False;
2040 BOOL rc = True;
2041 SMB_STRUCT_STAT sbuf;
2043 *directory = *mask = 0;
2045 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
2047 p = strrchr(name,'/');
2048 if (!p) {
2049 pstrcpy(directory,".");
2050 pstrcpy(mask,name);
2051 } else {
2052 *p = 0;
2053 pstrcpy(directory,name);
2054 pstrcpy(mask,p+1);
2058 * We should only check the mangled cache
2059 * here if unix_convert failed. This means
2060 * that the path in 'mask' doesn't exist
2061 * on the file system and so we need to look
2062 * for a possible mangle. This patch from
2063 * Tine Smukavec <valentin.smukavec@hermes.si>.
2066 if (!rc && mangle_is_mangled(mask))
2067 mangle_check_cache( mask );
2069 has_wild = ms_has_wild(mask);
2071 if (!has_wild) {
2072 pstrcat(directory,"/");
2073 pstrcat(directory,mask);
2074 error = can_delete(directory,conn,dirtype);
2075 if (!NT_STATUS_IS_OK(error))
2076 return error;
2078 if (vfs_unlink(conn,directory) == 0)
2079 count++;
2080 } else {
2081 void *dirptr = NULL;
2082 char *dname;
2083 if (check_name(directory,conn))
2084 dirptr = OpenDir(conn, directory, True);
2086 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2087 the pattern matches against the long name, otherwise the short name
2088 We don't implement this yet XXXX
2091 if (dirptr) {
2092 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2094 if (strequal(mask,"????????.???"))
2095 pstrcpy(mask,"*");
2097 while ((dname = ReadDirName(dirptr))) {
2098 pstring fname;
2099 pstrcpy(fname,dname);
2101 if(!mask_match(fname, mask, case_sensitive))
2102 continue;
2104 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2105 error = can_delete(fname,conn,dirtype);
2106 if (!NT_STATUS_IS_OK(error))
2107 continue;
2108 if (vfs_unlink(conn,fname) == 0)
2109 count++;
2110 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2112 CloseDir(dirptr);
2116 if (count == 0 && NT_STATUS_IS_OK(error))
2117 error = map_nt_error_from_unix(errno);
2119 return error;
2122 /****************************************************************************
2123 Reply to a unlink
2124 ****************************************************************************/
2126 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2128 int outsize = 0;
2129 pstring name;
2130 int dirtype;
2131 NTSTATUS status;
2133 START_PROFILE(SMBunlink);
2135 dirtype = SVAL(inbuf,smb_vwv0);
2137 pstrcpy(name,smb_buf(inbuf) + 1);
2139 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
2141 DEBUG(3,("reply_unlink : %s\n",name));
2143 status = unlink_internals(conn, dirtype, name);
2144 if (!NT_STATUS_IS_OK(status))
2145 return ERROR_NT(status);
2148 * Win2k needs a changenotify request response before it will
2149 * update after a rename..
2152 process_pending_change_notify_queue((time_t)0);
2154 outsize = set_message(outbuf,0,0,True);
2156 END_PROFILE(SMBunlink);
2157 return outsize;
2160 /****************************************************************************
2161 Fail for readbraw.
2162 ****************************************************************************/
2164 void fail_readraw(void)
2166 pstring errstr;
2167 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2168 strerror(errno) );
2169 exit_server(errstr);
2172 /****************************************************************************
2173 Use sendfile in readbraw.
2174 ****************************************************************************/
2176 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2177 ssize_t mincount, char *outbuf)
2179 ssize_t ret=0;
2181 #if defined(WITH_SENDFILE)
2183 * We can only use sendfile on a non-chained packet and on a file
2184 * that is exclusively oplocked. reply_readbraw has already checked the length.
2187 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
2188 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
2189 DATA_BLOB header;
2191 _smb_setlen(outbuf,nread);
2192 header.data = outbuf;
2193 header.length = 4;
2194 header.free = NULL;
2196 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
2198 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2199 * return ENOSYS then pretend we just got a normal read.
2201 if (errno == ENOSYS)
2202 goto normal_read;
2204 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2205 fsp->fsp_name, strerror(errno) ));
2206 exit_server("send_file_readbraw sendfile failed");
2211 normal_read:
2212 #endif
2214 if (nread > 0) {
2215 ret = read_file(fsp,outbuf+4,startpos,nread);
2216 if (ret < mincount)
2217 ret = 0;
2220 _smb_setlen(outbuf,ret);
2221 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2222 fail_readraw();
2225 /****************************************************************************
2226 Reply to a readbraw (core+ protocol).
2227 ****************************************************************************/
2229 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2231 ssize_t maxcount,mincount;
2232 size_t nread = 0;
2233 SMB_OFF_T startpos;
2234 char *header = outbuf;
2235 files_struct *fsp;
2236 START_PROFILE(SMBreadbraw);
2239 * Special check if an oplock break has been issued
2240 * and the readraw request croses on the wire, we must
2241 * return a zero length response here.
2244 if(global_oplock_break) {
2245 _smb_setlen(header,0);
2246 if (write_data(smbd_server_fd(),header,4) != 4)
2247 fail_readraw();
2248 DEBUG(5,("readbraw - oplock break finished\n"));
2249 END_PROFILE(SMBreadbraw);
2250 return -1;
2253 fsp = file_fsp(inbuf,smb_vwv0);
2255 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2257 * fsp could be NULL here so use the value from the packet. JRA.
2259 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2260 _smb_setlen(header,0);
2261 if (write_data(smbd_server_fd(),header,4) != 4)
2262 fail_readraw();
2263 END_PROFILE(SMBreadbraw);
2264 return(-1);
2267 CHECK_FSP(fsp,conn);
2269 flush_write_cache(fsp, READRAW_FLUSH);
2271 startpos = IVAL(inbuf,smb_vwv1);
2272 if(CVAL(inbuf,smb_wct) == 10) {
2274 * This is a large offset (64 bit) read.
2276 #ifdef LARGE_SMB_OFF_T
2278 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2280 #else /* !LARGE_SMB_OFF_T */
2283 * Ensure we haven't been sent a >32 bit offset.
2286 if(IVAL(inbuf,smb_vwv8) != 0) {
2287 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2288 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2289 _smb_setlen(header,0);
2290 if (write_data(smbd_server_fd(),header,4) != 4)
2291 fail_readraw();
2292 END_PROFILE(SMBreadbraw);
2293 return(-1);
2296 #endif /* LARGE_SMB_OFF_T */
2298 if(startpos < 0) {
2299 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2300 _smb_setlen(header,0);
2301 if (write_data(smbd_server_fd(),header,4) != 4)
2302 fail_readraw();
2303 END_PROFILE(SMBreadbraw);
2304 return(-1);
2307 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2308 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2310 /* ensure we don't overrun the packet size */
2311 maxcount = MIN(65535,maxcount);
2312 maxcount = MAX(mincount,maxcount);
2314 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2315 SMB_OFF_T size = fsp->size;
2316 SMB_OFF_T sizeneeded = startpos + maxcount;
2318 if (size < sizeneeded) {
2319 SMB_STRUCT_STAT st;
2320 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2321 fsp->size = size = st.st_size;
2324 if (startpos >= size)
2325 nread = 0;
2326 else
2327 nread = MIN(maxcount,(size - startpos));
2330 if (nread < mincount)
2331 nread = 0;
2333 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2334 (int)maxcount, (int)mincount, (int)nread ) );
2336 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
2338 DEBUG(5,("readbraw finished\n"));
2339 END_PROFILE(SMBreadbraw);
2340 return -1;
2343 /****************************************************************************
2344 Reply to a lockread (core+ protocol).
2345 ****************************************************************************/
2347 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2349 ssize_t nread = -1;
2350 char *data;
2351 int outsize = 0;
2352 SMB_OFF_T startpos;
2353 size_t numtoread;
2354 NTSTATUS status;
2355 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2356 START_PROFILE(SMBlockread);
2358 CHECK_FSP(fsp,conn);
2359 CHECK_READ(fsp);
2361 release_level_2_oplocks_on_change(fsp);
2363 numtoread = SVAL(inbuf,smb_vwv1);
2364 startpos = IVAL(inbuf,smb_vwv2);
2366 outsize = set_message(outbuf,5,3,True);
2367 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2368 data = smb_buf(outbuf) + 3;
2371 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2372 * protocol request that predates the read/write lock concept.
2373 * Thus instead of asking for a read lock here we need to ask
2374 * for a write lock. JRA.
2377 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2378 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
2380 if (NT_STATUS_V(status)) {
2381 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2383 * A blocking lock was requested. Package up
2384 * this smb into a queued request and push it
2385 * onto the blocking lock queue.
2387 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2388 END_PROFILE(SMBlockread);
2389 return -1;
2392 END_PROFILE(SMBlockread);
2393 return ERROR_NT(status);
2396 nread = read_file(fsp,data,startpos,numtoread);
2398 if (nread < 0) {
2399 END_PROFILE(SMBlockread);
2400 return(UNIXERROR(ERRDOS,ERRnoaccess));
2403 outsize += nread;
2404 SSVAL(outbuf,smb_vwv0,nread);
2405 SSVAL(outbuf,smb_vwv5,nread+3);
2406 SSVAL(smb_buf(outbuf),1,nread);
2408 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2409 fsp->fnum, (int)numtoread, (int)nread ) );
2411 END_PROFILE(SMBlockread);
2412 return(outsize);
2415 /****************************************************************************
2416 Reply to a read.
2417 ****************************************************************************/
2419 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2421 size_t numtoread;
2422 ssize_t nread = 0;
2423 char *data;
2424 SMB_OFF_T startpos;
2425 int outsize = 0;
2426 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2427 START_PROFILE(SMBread);
2429 CHECK_FSP(fsp,conn);
2430 CHECK_READ(fsp);
2432 numtoread = SVAL(inbuf,smb_vwv1);
2433 startpos = IVAL(inbuf,smb_vwv2);
2435 outsize = set_message(outbuf,5,3,True);
2436 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2437 data = smb_buf(outbuf) + 3;
2439 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2440 END_PROFILE(SMBread);
2441 return ERROR_DOS(ERRDOS,ERRlock);
2444 if (numtoread > 0)
2445 nread = read_file(fsp,data,startpos,numtoread);
2447 if (nread < 0) {
2448 END_PROFILE(SMBread);
2449 return(UNIXERROR(ERRDOS,ERRnoaccess));
2452 outsize += nread;
2453 SSVAL(outbuf,smb_vwv0,nread);
2454 SSVAL(outbuf,smb_vwv5,nread+3);
2455 SCVAL(smb_buf(outbuf),0,1);
2456 SSVAL(smb_buf(outbuf),1,nread);
2458 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2459 fsp->fnum, (int)numtoread, (int)nread ) );
2461 END_PROFILE(SMBread);
2462 return(outsize);
2465 /****************************************************************************
2466 Reply to a read and X - possibly using sendfile.
2467 ****************************************************************************/
2469 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
2470 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2472 ssize_t nread = -1;
2473 char *data = smb_buf(outbuf);
2475 #if defined(WITH_SENDFILE)
2477 * We can only use sendfile on a non-chained packet and on a file
2478 * that is exclusively oplocked.
2481 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
2482 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
2483 SMB_STRUCT_STAT sbuf;
2484 DATA_BLOB header;
2486 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1)
2487 return(UNIXERROR(ERRDOS,ERRnoaccess));
2489 if (startpos > sbuf.st_size)
2490 goto normal_read;
2492 if (smb_maxcnt > (sbuf.st_size - startpos))
2493 smb_maxcnt = (sbuf.st_size - startpos);
2495 if (smb_maxcnt == 0)
2496 goto normal_read;
2499 * Set up the packet header before send. We
2500 * assume here the sendfile will work (get the
2501 * correct amount of data).
2504 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2505 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2506 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2507 SCVAL(outbuf,smb_vwv0,0xFF);
2508 set_message(outbuf,12,smb_maxcnt,False);
2509 header.data = outbuf;
2510 header.length = data - outbuf;
2511 header.free = NULL;
2513 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2515 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2516 * return ENOSYS then pretend we just got a normal read.
2518 if (errno == ENOSYS)
2519 goto normal_read;
2521 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2522 fsp->fsp_name, strerror(errno) ));
2523 exit_server("send_file_readX sendfile failed");
2526 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2527 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2528 return -1;
2531 normal_read:
2533 #endif
2535 nread = read_file(fsp,data,startpos,smb_maxcnt);
2537 if (nread < 0) {
2538 END_PROFILE(SMBreadX);
2539 return(UNIXERROR(ERRDOS,ERRnoaccess));
2542 SSVAL(outbuf,smb_vwv5,nread);
2543 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2544 SSVAL(smb_buf(outbuf),-2,nread);
2546 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2547 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2549 return nread;
2552 /****************************************************************************
2553 Reply to a read and X.
2554 ****************************************************************************/
2556 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2558 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2559 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2560 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2561 #if 0
2562 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2563 #endif
2564 ssize_t nread = -1;
2565 char *data;
2566 START_PROFILE(SMBreadX);
2568 /* If it's an IPC, pass off the pipe handler. */
2569 if (IS_IPC(conn)) {
2570 END_PROFILE(SMBreadX);
2571 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2574 CHECK_FSP(fsp,conn);
2575 CHECK_READ(fsp);
2577 set_message(outbuf,12,0,True);
2578 data = smb_buf(outbuf);
2580 if(CVAL(inbuf,smb_wct) == 12) {
2581 #ifdef LARGE_SMB_OFF_T
2583 * This is a large offset (64 bit) read.
2585 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2587 #else /* !LARGE_SMB_OFF_T */
2590 * Ensure we haven't been sent a >32 bit offset.
2593 if(IVAL(inbuf,smb_vwv10) != 0) {
2594 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2595 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2596 END_PROFILE(SMBreadX);
2597 return ERROR_DOS(ERRDOS,ERRbadaccess);
2600 #endif /* LARGE_SMB_OFF_T */
2604 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2605 END_PROFILE(SMBreadX);
2606 return ERROR_DOS(ERRDOS,ERRlock);
2608 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2609 if (nread != -1)
2610 nread = chain_reply(inbuf,outbuf,length,bufsize);
2612 END_PROFILE(SMBreadX);
2613 return nread;
2616 /****************************************************************************
2617 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2618 ****************************************************************************/
2620 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2622 ssize_t nwritten=0;
2623 ssize_t total_written=0;
2624 size_t numtowrite=0;
2625 size_t tcount;
2626 SMB_OFF_T startpos;
2627 char *data=NULL;
2628 BOOL write_through;
2629 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2630 int outsize = 0;
2631 START_PROFILE(SMBwritebraw);
2633 CHECK_FSP(fsp,conn);
2634 CHECK_WRITE(fsp);
2636 tcount = IVAL(inbuf,smb_vwv1);
2637 startpos = IVAL(inbuf,smb_vwv3);
2638 write_through = BITSETW(inbuf+smb_vwv7,0);
2640 /* We have to deal with slightly different formats depending
2641 on whether we are using the core+ or lanman1.0 protocol */
2643 if(Protocol <= PROTOCOL_COREPLUS) {
2644 numtowrite = SVAL(smb_buf(inbuf),-2);
2645 data = smb_buf(inbuf);
2646 } else {
2647 numtowrite = SVAL(inbuf,smb_vwv10);
2648 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2651 /* force the error type */
2652 SCVAL(inbuf,smb_com,SMBwritec);
2653 SCVAL(outbuf,smb_com,SMBwritec);
2655 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2656 END_PROFILE(SMBwritebraw);
2657 return(ERROR_DOS(ERRDOS,ERRlock));
2660 if (numtowrite>0)
2661 nwritten = write_file(fsp,data,startpos,numtowrite);
2663 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2664 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2666 if (nwritten < numtowrite) {
2667 END_PROFILE(SMBwritebraw);
2668 return(UNIXERROR(ERRHRD,ERRdiskfull));
2671 total_written = nwritten;
2673 /* Return a message to the redirector to tell it to send more bytes */
2674 SCVAL(outbuf,smb_com,SMBwritebraw);
2675 SSVALS(outbuf,smb_vwv0,-1);
2676 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2677 if (!send_smb(smbd_server_fd(),outbuf))
2678 exit_server("reply_writebraw: send_smb failed.");
2680 /* Now read the raw data into the buffer and write it */
2681 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2682 exit_server("secondary writebraw failed");
2685 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2686 numtowrite = smb_len(inbuf);
2688 /* Set up outbuf to return the correct return */
2689 outsize = set_message(outbuf,1,0,True);
2690 SCVAL(outbuf,smb_com,SMBwritec);
2691 SSVAL(outbuf,smb_vwv0,total_written);
2693 if (numtowrite != 0) {
2695 if (numtowrite > BUFFER_SIZE) {
2696 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2697 (unsigned int)numtowrite ));
2698 exit_server("secondary writebraw failed");
2701 if (tcount > nwritten+numtowrite) {
2702 DEBUG(3,("Client overestimated the write %d %d %d\n",
2703 (int)tcount,(int)nwritten,(int)numtowrite));
2706 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2707 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2708 strerror(errno) ));
2709 exit_server("secondary writebraw failed");
2712 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2714 if (nwritten < (ssize_t)numtowrite) {
2715 SCVAL(outbuf,smb_rcls,ERRHRD);
2716 SSVAL(outbuf,smb_err,ERRdiskfull);
2719 if (nwritten > 0)
2720 total_written += nwritten;
2723 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2724 sync_file(conn,fsp);
2726 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2727 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2729 /* we won't return a status if write through is not selected - this follows what WfWg does */
2730 END_PROFILE(SMBwritebraw);
2731 if (!write_through && total_written==tcount) {
2733 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2734 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2736 if (!send_keepalive(smbd_server_fd()))
2737 exit_server("reply_writebraw: send of keepalive failed");
2738 return(-1);
2741 return(outsize);
2744 /****************************************************************************
2745 Reply to a writeunlock (core+).
2746 ****************************************************************************/
2748 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2750 ssize_t nwritten = -1;
2751 size_t numtowrite;
2752 SMB_OFF_T startpos;
2753 char *data;
2754 NTSTATUS status;
2755 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2756 int outsize = 0;
2757 START_PROFILE(SMBwriteunlock);
2759 CHECK_FSP(fsp,conn);
2760 CHECK_WRITE(fsp);
2762 numtowrite = SVAL(inbuf,smb_vwv1);
2763 startpos = IVAL(inbuf,smb_vwv2);
2764 data = smb_buf(inbuf) + 3;
2766 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2767 WRITE_LOCK,False)) {
2768 END_PROFILE(SMBwriteunlock);
2769 return ERROR_DOS(ERRDOS,ERRlock);
2772 /* The special X/Open SMB protocol handling of
2773 zero length writes is *NOT* done for
2774 this call */
2775 if(numtowrite == 0)
2776 nwritten = 0;
2777 else
2778 nwritten = write_file(fsp,data,startpos,numtowrite);
2780 if (lp_syncalways(SNUM(conn)))
2781 sync_file(conn,fsp);
2783 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2784 END_PROFILE(SMBwriteunlock);
2785 return(UNIXERROR(ERRDOS,ERRnoaccess));
2788 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2789 (SMB_BIG_UINT)startpos);
2790 if (NT_STATUS_V(status)) {
2791 END_PROFILE(SMBwriteunlock);
2792 return ERROR_NT(status);
2795 outsize = set_message(outbuf,1,0,True);
2797 SSVAL(outbuf,smb_vwv0,nwritten);
2799 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2800 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2802 END_PROFILE(SMBwriteunlock);
2803 return(outsize);
2806 /****************************************************************************
2807 Reply to a write.
2808 ****************************************************************************/
2810 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2812 size_t numtowrite;
2813 ssize_t nwritten = -1;
2814 SMB_OFF_T startpos;
2815 char *data;
2816 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2817 int outsize = 0;
2818 START_PROFILE(SMBwrite);
2820 /* If it's an IPC, pass off the pipe handler. */
2821 if (IS_IPC(conn)) {
2822 END_PROFILE(SMBwrite);
2823 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2826 CHECK_FSP(fsp,conn);
2827 CHECK_WRITE(fsp);
2829 numtowrite = SVAL(inbuf,smb_vwv1);
2830 startpos = IVAL(inbuf,smb_vwv2);
2831 data = smb_buf(inbuf) + 3;
2833 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2834 END_PROFILE(SMBwrite);
2835 return ERROR_DOS(ERRDOS,ERRlock);
2839 * X/Open SMB protocol says that if smb_vwv1 is
2840 * zero then the file size should be extended or
2841 * truncated to the size given in smb_vwv[2-3].
2844 if(numtowrite == 0) {
2846 * This is actually an allocate call, and set EOF. JRA.
2848 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2849 if (nwritten < 0) {
2850 END_PROFILE(SMBwrite);
2851 return ERROR_NT(NT_STATUS_DISK_FULL);
2853 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2854 if (nwritten < 0) {
2855 END_PROFILE(SMBwrite);
2856 return ERROR_NT(NT_STATUS_DISK_FULL);
2858 } else
2859 nwritten = write_file(fsp,data,startpos,numtowrite);
2861 if (lp_syncalways(SNUM(conn)))
2862 sync_file(conn,fsp);
2864 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2865 END_PROFILE(SMBwrite);
2866 return(UNIXERROR(ERRDOS,ERRnoaccess));
2869 outsize = set_message(outbuf,1,0,True);
2871 SSVAL(outbuf,smb_vwv0,nwritten);
2873 if (nwritten < (ssize_t)numtowrite) {
2874 SCVAL(outbuf,smb_rcls,ERRHRD);
2875 SSVAL(outbuf,smb_err,ERRdiskfull);
2878 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2880 END_PROFILE(SMBwrite);
2881 return(outsize);
2884 /****************************************************************************
2885 Reply to a write and X.
2886 ****************************************************************************/
2888 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2890 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2891 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2892 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2893 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2894 ssize_t nwritten = -1;
2895 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2896 unsigned int smblen = smb_len(inbuf);
2897 char *data;
2898 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2899 START_PROFILE(SMBwriteX);
2901 /* If it's an IPC, pass off the pipe handler. */
2902 if (IS_IPC(conn)) {
2903 END_PROFILE(SMBwriteX);
2904 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2907 CHECK_FSP(fsp,conn);
2908 CHECK_WRITE(fsp);
2910 /* Deal with possible LARGE_WRITEX */
2911 if (large_writeX)
2912 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2914 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2915 END_PROFILE(SMBwriteX);
2916 return ERROR_DOS(ERRDOS,ERRbadmem);
2919 data = smb_base(inbuf) + smb_doff;
2921 if(CVAL(inbuf,smb_wct) == 14) {
2922 #ifdef LARGE_SMB_OFF_T
2924 * This is a large offset (64 bit) write.
2926 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2928 #else /* !LARGE_SMB_OFF_T */
2931 * Ensure we haven't been sent a >32 bit offset.
2934 if(IVAL(inbuf,smb_vwv12) != 0) {
2935 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2936 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2937 END_PROFILE(SMBwriteX);
2938 return ERROR_DOS(ERRDOS,ERRbadaccess);
2941 #endif /* LARGE_SMB_OFF_T */
2944 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2945 END_PROFILE(SMBwriteX);
2946 return ERROR_DOS(ERRDOS,ERRlock);
2949 /* X/Open SMB protocol says that, unlike SMBwrite
2950 if the length is zero then NO truncation is
2951 done, just a write of zero. To truncate a file,
2952 use SMBwrite. */
2953 if(numtowrite == 0)
2954 nwritten = 0;
2955 else
2956 nwritten = write_file(fsp,data,startpos,numtowrite);
2958 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2959 END_PROFILE(SMBwriteX);
2960 return(UNIXERROR(ERRDOS,ERRnoaccess));
2963 set_message(outbuf,6,0,True);
2965 SSVAL(outbuf,smb_vwv2,nwritten);
2966 if (large_writeX)
2967 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2969 if (nwritten < (ssize_t)numtowrite) {
2970 SCVAL(outbuf,smb_rcls,ERRHRD);
2971 SSVAL(outbuf,smb_err,ERRdiskfull);
2974 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2975 fsp->fnum, (int)numtowrite, (int)nwritten));
2977 if (lp_syncalways(SNUM(conn)) || write_through)
2978 sync_file(conn,fsp);
2980 END_PROFILE(SMBwriteX);
2981 return chain_reply(inbuf,outbuf,length,bufsize);
2985 /****************************************************************************
2986 Reply to a lseek.
2987 ****************************************************************************/
2989 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2991 SMB_OFF_T startpos;
2992 SMB_OFF_T res= -1;
2993 int mode,umode;
2994 int outsize = 0;
2995 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2996 START_PROFILE(SMBlseek);
2998 CHECK_FSP(fsp,conn);
3000 flush_write_cache(fsp, SEEK_FLUSH);
3002 mode = SVAL(inbuf,smb_vwv1) & 3;
3003 startpos = IVALS(inbuf,smb_vwv2);
3005 switch (mode) {
3006 case 0: umode = SEEK_SET; break;
3007 case 1: umode = SEEK_CUR; break;
3008 case 2: umode = SEEK_END; break;
3009 default:
3010 umode = SEEK_SET; break;
3013 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
3015 * Check for the special case where a seek before the start
3016 * of the file sets the offset to zero. Added in the CIFS spec,
3017 * section 4.2.7.
3020 if(errno == EINVAL) {
3021 SMB_OFF_T current_pos = startpos;
3023 if(umode == SEEK_CUR) {
3025 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
3026 END_PROFILE(SMBlseek);
3027 return(UNIXERROR(ERRDOS,ERRnoaccess));
3030 current_pos += startpos;
3032 } else if (umode == SEEK_END) {
3034 SMB_STRUCT_STAT sbuf;
3036 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
3037 END_PROFILE(SMBlseek);
3038 return(UNIXERROR(ERRDOS,ERRnoaccess));
3041 current_pos += sbuf.st_size;
3044 if(current_pos < 0)
3045 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
3048 if(res == -1) {
3049 END_PROFILE(SMBlseek);
3050 return(UNIXERROR(ERRDOS,ERRnoaccess));
3054 fsp->pos = res;
3056 outsize = set_message(outbuf,2,0,True);
3057 SIVAL(outbuf,smb_vwv0,res);
3059 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3060 fsp->fnum, (double)startpos, (double)res, mode));
3062 END_PROFILE(SMBlseek);
3063 return(outsize);
3066 /****************************************************************************
3067 Reply to a flush.
3068 ****************************************************************************/
3070 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3072 int outsize = set_message(outbuf,0,0,True);
3073 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3074 START_PROFILE(SMBflush);
3076 CHECK_FSP(fsp,conn);
3078 if (!fsp) {
3079 file_sync_all(conn);
3080 } else {
3081 sync_file(conn,fsp);
3084 DEBUG(3,("flush\n"));
3085 END_PROFILE(SMBflush);
3086 return(outsize);
3089 /****************************************************************************
3090 Reply to a exit.
3091 ****************************************************************************/
3093 int reply_exit(connection_struct *conn,
3094 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3096 int outsize;
3097 START_PROFILE(SMBexit);
3098 outsize = set_message(outbuf,0,0,True);
3100 DEBUG(3,("exit\n"));
3102 END_PROFILE(SMBexit);
3103 return(outsize);
3107 /****************************************************************************
3108 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3109 ****************************************************************************/
3111 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3112 int dum_buffsize)
3114 int outsize = 0;
3115 time_t mtime;
3116 files_struct *fsp = NULL;
3117 START_PROFILE(SMBclose);
3119 outsize = set_message(outbuf,0,0,True);
3121 /* If it's an IPC, pass off to the pipe handler. */
3122 if (IS_IPC(conn)) {
3123 END_PROFILE(SMBclose);
3124 return reply_pipe_close(conn, inbuf,outbuf);
3127 fsp = file_fsp(inbuf,smb_vwv0);
3130 * We can only use CHECK_FSP if we know it's not a directory.
3133 if(!fsp || (fsp->conn != conn)) {
3134 END_PROFILE(SMBclose);
3135 return ERROR_DOS(ERRDOS,ERRbadfid);
3138 if(fsp->is_directory) {
3140 * Special case - close NT SMB directory handle.
3142 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3143 close_file(fsp,True);
3144 } else {
3146 * Close ordinary file.
3148 int close_err;
3149 pstring file_name;
3151 /* Save the name for time set in close. */
3152 pstrcpy( file_name, fsp->fsp_name);
3154 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3155 fsp->fd, fsp->fnum,
3156 conn->num_files_open));
3159 * close_file() returns the unix errno if an error
3160 * was detected on close - normally this is due to
3161 * a disk full error. If not then it was probably an I/O error.
3164 if((close_err = close_file(fsp,True)) != 0) {
3165 errno = close_err;
3166 END_PROFILE(SMBclose);
3167 return (UNIXERROR(ERRHRD,ERRgeneral));
3171 * Now take care of any time sent in the close.
3174 mtime = make_unix_date3(inbuf+smb_vwv1);
3176 /* try and set the date */
3177 set_filetime(conn, file_name, mtime);
3181 END_PROFILE(SMBclose);
3182 return(outsize);
3185 /****************************************************************************
3186 Reply to a writeclose (Core+ protocol)
3187 ****************************************************************************/
3189 int reply_writeclose(connection_struct *conn,
3190 char *inbuf,char *outbuf, int size, int dum_buffsize)
3192 size_t numtowrite;
3193 ssize_t nwritten = -1;
3194 int outsize = 0;
3195 int close_err = 0;
3196 SMB_OFF_T startpos;
3197 char *data;
3198 time_t mtime;
3199 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3200 START_PROFILE(SMBwriteclose);
3202 CHECK_FSP(fsp,conn);
3203 CHECK_WRITE(fsp);
3205 numtowrite = SVAL(inbuf,smb_vwv1);
3206 startpos = IVAL(inbuf,smb_vwv2);
3207 mtime = make_unix_date3(inbuf+smb_vwv4);
3208 data = smb_buf(inbuf) + 1;
3210 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
3211 END_PROFILE(SMBwriteclose);
3212 return ERROR_DOS(ERRDOS,ERRlock);
3215 nwritten = write_file(fsp,data,startpos,numtowrite);
3217 set_filetime(conn, fsp->fsp_name,mtime);
3219 close_err = close_file(fsp,True);
3221 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3222 fsp->fnum, (int)numtowrite, (int)nwritten,
3223 conn->num_files_open));
3225 if (nwritten <= 0) {
3226 END_PROFILE(SMBwriteclose);
3227 return(UNIXERROR(ERRDOS,ERRnoaccess));
3230 if(close_err != 0) {
3231 errno = close_err;
3232 END_PROFILE(SMBwriteclose);
3233 return(UNIXERROR(ERRHRD,ERRgeneral));
3236 outsize = set_message(outbuf,1,0,True);
3238 SSVAL(outbuf,smb_vwv0,nwritten);
3239 END_PROFILE(SMBwriteclose);
3240 return(outsize);
3243 /****************************************************************************
3244 Reply to a lock.
3245 ****************************************************************************/
3247 int reply_lock(connection_struct *conn,
3248 char *inbuf,char *outbuf, int length, int dum_buffsize)
3250 int outsize = set_message(outbuf,0,0,True);
3251 SMB_BIG_UINT count,offset;
3252 NTSTATUS status;
3253 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3254 START_PROFILE(SMBlock);
3256 CHECK_FSP(fsp,conn);
3258 release_level_2_oplocks_on_change(fsp);
3260 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3261 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3263 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3264 fsp->fd, fsp->fnum, (double)offset, (double)count));
3266 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
3267 if (NT_STATUS_V(status)) {
3268 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3270 * A blocking lock was requested. Package up
3271 * this smb into a queued request and push it
3272 * onto the blocking lock queue.
3274 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
3275 END_PROFILE(SMBlock);
3276 return -1;
3279 END_PROFILE(SMBlock);
3280 return ERROR_NT(status);
3283 END_PROFILE(SMBlock);
3284 return(outsize);
3287 /****************************************************************************
3288 Reply to a unlock.
3289 ****************************************************************************/
3291 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3293 int outsize = set_message(outbuf,0,0,True);
3294 SMB_BIG_UINT count,offset;
3295 NTSTATUS status;
3296 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3297 START_PROFILE(SMBunlock);
3299 CHECK_FSP(fsp,conn);
3301 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3302 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3304 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3305 if (NT_STATUS_V(status)) {
3306 END_PROFILE(SMBunlock);
3307 return ERROR_NT(status);
3310 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3311 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3313 END_PROFILE(SMBunlock);
3314 return(outsize);
3317 /****************************************************************************
3318 Reply to a tdis.
3319 ****************************************************************************/
3321 int reply_tdis(connection_struct *conn,
3322 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3324 int outsize = set_message(outbuf,0,0,True);
3325 uint16 vuid;
3326 START_PROFILE(SMBtdis);
3328 vuid = SVAL(inbuf,smb_uid);
3330 if (!conn) {
3331 DEBUG(4,("Invalid connection in tdis\n"));
3332 END_PROFILE(SMBtdis);
3333 return ERROR_DOS(ERRSRV,ERRinvnid);
3336 conn->used = False;
3338 close_cnum(conn,vuid);
3340 END_PROFILE(SMBtdis);
3341 return outsize;
3344 /****************************************************************************
3345 Reply to a echo.
3346 ****************************************************************************/
3348 int reply_echo(connection_struct *conn,
3349 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3351 int smb_reverb = SVAL(inbuf,smb_vwv0);
3352 int seq_num;
3353 unsigned int data_len = smb_buflen(inbuf);
3354 int outsize = set_message(outbuf,1,data_len,True);
3355 START_PROFILE(SMBecho);
3357 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3359 /* copy any incoming data back out */
3360 if (data_len > 0)
3361 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3363 if (smb_reverb > 100) {
3364 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3365 smb_reverb = 100;
3368 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3369 SSVAL(outbuf,smb_vwv0,seq_num);
3371 smb_setlen(outbuf,outsize - 4);
3373 if (!send_smb(smbd_server_fd(),outbuf))
3374 exit_server("reply_echo: send_smb failed.");
3377 DEBUG(3,("echo %d times\n", smb_reverb));
3379 smb_echo_count++;
3381 END_PROFILE(SMBecho);
3382 return -1;
3385 /****************************************************************************
3386 Reply to a printopen.
3387 ****************************************************************************/
3389 int reply_printopen(connection_struct *conn,
3390 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3392 int outsize = 0;
3393 files_struct *fsp;
3394 START_PROFILE(SMBsplopen);
3396 if (!CAN_PRINT(conn)) {
3397 END_PROFILE(SMBsplopen);
3398 return ERROR_DOS(ERRDOS,ERRnoaccess);
3401 /* Open for exclusive use, write only. */
3402 fsp = print_fsp_open(conn, NULL);
3404 if (!fsp) {
3405 END_PROFILE(SMBsplopen);
3406 return(UNIXERROR(ERRDOS,ERRnoaccess));
3409 outsize = set_message(outbuf,1,0,True);
3410 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3412 DEBUG(3,("openprint fd=%d fnum=%d\n",
3413 fsp->fd, fsp->fnum));
3415 END_PROFILE(SMBsplopen);
3416 return(outsize);
3419 /****************************************************************************
3420 Reply to a printclose.
3421 ****************************************************************************/
3423 int reply_printclose(connection_struct *conn,
3424 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3426 int outsize = set_message(outbuf,0,0,True);
3427 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3428 int close_err = 0;
3429 START_PROFILE(SMBsplclose);
3431 CHECK_FSP(fsp,conn);
3433 if (!CAN_PRINT(conn)) {
3434 END_PROFILE(SMBsplclose);
3435 return ERROR_DOS(ERRDOS,ERRnoaccess);
3438 DEBUG(3,("printclose fd=%d fnum=%d\n",
3439 fsp->fd,fsp->fnum));
3441 close_err = close_file(fsp,True);
3443 if(close_err != 0) {
3444 errno = close_err;
3445 END_PROFILE(SMBsplclose);
3446 return(UNIXERROR(ERRHRD,ERRgeneral));
3449 END_PROFILE(SMBsplclose);
3450 return(outsize);
3453 /****************************************************************************
3454 Reply to a printqueue.
3455 ****************************************************************************/
3457 int reply_printqueue(connection_struct *conn,
3458 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3460 int outsize = set_message(outbuf,2,3,True);
3461 int max_count = SVAL(inbuf,smb_vwv0);
3462 int start_index = SVAL(inbuf,smb_vwv1);
3463 START_PROFILE(SMBsplretq);
3465 /* we used to allow the client to get the cnum wrong, but that
3466 is really quite gross and only worked when there was only
3467 one printer - I think we should now only accept it if they
3468 get it right (tridge) */
3469 if (!CAN_PRINT(conn)) {
3470 END_PROFILE(SMBsplretq);
3471 return ERROR_DOS(ERRDOS,ERRnoaccess);
3474 SSVAL(outbuf,smb_vwv0,0);
3475 SSVAL(outbuf,smb_vwv1,0);
3476 SCVAL(smb_buf(outbuf),0,1);
3477 SSVAL(smb_buf(outbuf),1,0);
3479 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3480 start_index, max_count));
3483 print_queue_struct *queue = NULL;
3484 print_status_struct status;
3485 char *p = smb_buf(outbuf) + 3;
3486 int count = print_queue_status(SNUM(conn), &queue, &status);
3487 int num_to_get = ABS(max_count);
3488 int first = (max_count>0?start_index:start_index+max_count+1);
3489 int i;
3491 if (first >= count)
3492 num_to_get = 0;
3493 else
3494 num_to_get = MIN(num_to_get,count-first);
3497 for (i=first;i<first+num_to_get;i++) {
3498 put_dos_date2(p,0,queue[i].time);
3499 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3500 SSVAL(p,5, queue[i].job);
3501 SIVAL(p,7,queue[i].size);
3502 SCVAL(p,11,0);
3503 StrnCpy(p+12,queue[i].fs_user,16);
3504 p += 28;
3507 if (count > 0) {
3508 outsize = set_message(outbuf,2,28*count+3,False);
3509 SSVAL(outbuf,smb_vwv0,count);
3510 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3511 SCVAL(smb_buf(outbuf),0,1);
3512 SSVAL(smb_buf(outbuf),1,28*count);
3515 SAFE_FREE(queue);
3517 DEBUG(3,("%d entries returned in queue\n",count));
3520 END_PROFILE(SMBsplretq);
3521 return(outsize);
3524 /****************************************************************************
3525 Reply to a printwrite.
3526 ****************************************************************************/
3528 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3530 int numtowrite;
3531 int outsize = set_message(outbuf,0,0,True);
3532 char *data;
3533 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3534 START_PROFILE(SMBsplwr);
3536 if (!CAN_PRINT(conn)) {
3537 END_PROFILE(SMBsplwr);
3538 return ERROR_DOS(ERRDOS,ERRnoaccess);
3541 CHECK_FSP(fsp,conn);
3542 CHECK_WRITE(fsp);
3544 numtowrite = SVAL(smb_buf(inbuf),1);
3545 data = smb_buf(inbuf) + 3;
3547 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3548 END_PROFILE(SMBsplwr);
3549 return(UNIXERROR(ERRDOS,ERRnoaccess));
3552 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3554 END_PROFILE(SMBsplwr);
3555 return(outsize);
3558 /****************************************************************************
3559 The guts of the mkdir command, split out so it may be called by the NT SMB
3560 code.
3561 ****************************************************************************/
3563 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3565 BOOL bad_path = False;
3566 SMB_STRUCT_STAT sbuf;
3567 int ret= -1;
3569 unix_convert(directory,conn,0,&bad_path,&sbuf);
3571 if (check_name(directory, conn))
3572 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3574 if (ret == -1) {
3575 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
3576 if (!NT_STATUS_IS_OK(nterr))
3577 return nterr;
3578 return map_nt_error_from_unix(errno);
3581 return NT_STATUS_OK;
3584 /****************************************************************************
3585 Reply to a mkdir.
3586 ****************************************************************************/
3588 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3590 pstring directory;
3591 int outsize;
3592 NTSTATUS status;
3593 START_PROFILE(SMBmkdir);
3595 pstrcpy(directory,smb_buf(inbuf) + 1);
3597 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3599 status = mkdir_internal(conn, directory);
3600 if (!NT_STATUS_IS_OK(status))
3601 return ERROR_NT(status);
3603 outsize = set_message(outbuf,0,0,True);
3605 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3607 END_PROFILE(SMBmkdir);
3608 return(outsize);
3611 /****************************************************************************
3612 Static function used by reply_rmdir to delete an entire directory
3613 tree recursively. Return False on ok, True on fail.
3614 ****************************************************************************/
3616 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3618 char *dname = NULL;
3619 BOOL ret = False;
3620 void *dirptr = OpenDir(conn, directory, False);
3622 if(dirptr == NULL)
3623 return True;
3625 while((dname = ReadDirName(dirptr))) {
3626 pstring fullname;
3627 SMB_STRUCT_STAT st;
3629 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3630 continue;
3632 /* Construct the full name. */
3633 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3634 errno = ENOMEM;
3635 ret = True;
3636 break;
3639 pstrcpy(fullname, directory);
3640 pstrcat(fullname, "/");
3641 pstrcat(fullname, dname);
3643 if(conn->vfs_ops.lstat(conn,dos_to_unix_static(fullname), &st) != 0) {
3644 ret = True;
3645 break;
3648 if(st.st_mode & S_IFDIR) {
3649 if(recursive_rmdir(conn, fullname)!=0) {
3650 ret = True;
3651 break;
3653 if(vfs_rmdir(conn,fullname) != 0) {
3654 ret = True;
3655 break;
3657 } else if(vfs_unlink(conn,fullname) != 0) {
3658 ret = True;
3659 break;
3663 CloseDir(dirptr);
3664 return ret;
3667 /****************************************************************************
3668 The internals of the rmdir code - called elsewhere.
3669 ****************************************************************************/
3671 BOOL rmdir_internals(connection_struct *conn, char *directory)
3673 BOOL ok;
3675 ok = (vfs_rmdir(conn,directory) == 0);
3676 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3678 * Check to see if the only thing in this directory are
3679 * vetoed files/directories. If so then delete them and
3680 * retry. If we fail to delete any of them (and we *don't*
3681 * do a recursive delete) then fail the rmdir.
3683 BOOL all_veto_files = True;
3684 char *dname;
3685 void *dirptr = OpenDir(conn, directory, False);
3687 if(dirptr != NULL) {
3688 int dirpos = TellDir(dirptr);
3689 while ((dname = ReadDirName(dirptr))) {
3690 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3691 continue;
3692 if(!IS_VETO_PATH(conn, dname)) {
3693 all_veto_files = False;
3694 break;
3697 if(all_veto_files) {
3698 SeekDir(dirptr,dirpos);
3699 while ((dname = ReadDirName(dirptr))) {
3700 pstring fullname;
3701 SMB_STRUCT_STAT st;
3703 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3704 continue;
3706 /* Construct the full name. */
3707 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3708 errno = ENOMEM;
3709 break;
3711 pstrcpy(fullname, directory);
3712 pstrcat(fullname, "/");
3713 pstrcat(fullname, dname);
3715 if(conn->vfs_ops.lstat(conn,dos_to_unix_static(fullname), &st) != 0)
3716 break;
3717 if(st.st_mode & S_IFDIR) {
3718 if(lp_recursive_veto_delete(SNUM(conn))) {
3719 if(recursive_rmdir(conn, fullname) != 0)
3720 break;
3722 if(vfs_rmdir(conn,fullname) != 0)
3723 break;
3724 } else if(vfs_unlink(conn,fullname) != 0)
3725 break;
3727 CloseDir(dirptr);
3728 /* Retry the rmdir */
3729 ok = (vfs_rmdir(conn,directory) == 0);
3730 } else {
3731 CloseDir(dirptr);
3733 } else {
3734 errno = ENOTEMPTY;
3738 if (!ok)
3739 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3741 return ok;
3744 /****************************************************************************
3745 Reply to a rmdir.
3746 ****************************************************************************/
3748 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3750 pstring directory;
3751 int outsize = 0;
3752 BOOL ok = False;
3753 BOOL bad_path = False;
3754 SMB_STRUCT_STAT sbuf;
3755 START_PROFILE(SMBrmdir);
3757 pstrcpy(directory,smb_buf(inbuf) + 1);
3759 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3761 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3763 if (check_name(directory,conn))
3765 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3766 ok = rmdir_internals(conn, directory);
3769 if (!ok)
3771 set_bad_path_error(errno, bad_path);
3772 END_PROFILE(SMBrmdir);
3773 return(UNIXERROR(ERRDOS,ERRbadpath));
3776 outsize = set_message(outbuf,0,0,True);
3778 DEBUG( 3, ( "rmdir %s\n", directory ) );
3780 END_PROFILE(SMBrmdir);
3781 return(outsize);
3784 /*******************************************************************
3785 Resolve wildcards in a filename rename.
3786 ********************************************************************/
3788 static BOOL resolve_wildcards(char *name1,char *name2)
3790 fstring root1,root2;
3791 fstring ext1,ext2;
3792 char *p,*p2;
3794 name1 = strrchr(name1,'/');
3795 name2 = strrchr(name2,'/');
3797 if (!name1 || !name2) return(False);
3799 fstrcpy(root1,name1);
3800 fstrcpy(root2,name2);
3801 p = strrchr(root1,'.');
3802 if (p) {
3803 *p = 0;
3804 fstrcpy(ext1,p+1);
3805 } else {
3806 fstrcpy(ext1,"");
3808 p = strrchr(root2,'.');
3809 if (p) {
3810 *p = 0;
3811 fstrcpy(ext2,p+1);
3812 } else {
3813 fstrcpy(ext2,"");
3816 p = root1;
3817 p2 = root2;
3818 while (*p2) {
3819 if (*p2 == '?') {
3820 *p2 = *p;
3821 p2++;
3822 } else {
3823 p2++;
3825 if (*p) p++;
3828 p = ext1;
3829 p2 = ext2;
3830 while (*p2) {
3831 if (*p2 == '?') {
3832 *p2 = *p;
3833 p2++;
3834 } else {
3835 p2++;
3837 if (*p) p++;
3840 pstrcpy(name2,root2);
3841 if (ext2[0]) {
3842 pstrcat(name2,".");
3843 pstrcat(name2,ext2);
3846 return(True);
3849 /****************************************************************************
3850 The guts of the rename command, split out so it may be called by the NT SMB
3851 code.
3852 ****************************************************************************/
3854 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3856 pstring directory;
3857 pstring mask;
3858 pstring newname_last_component;
3859 char *p;
3860 BOOL has_wild;
3861 BOOL bad_path1 = False;
3862 BOOL bad_path2 = False;
3863 int count=0;
3864 NTSTATUS error = NT_STATUS_OK;
3865 BOOL rc = True;
3866 SMB_STRUCT_STAT sbuf1, sbuf2;
3868 *directory = *mask = 0;
3870 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3871 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3874 * Split the old name into directory and last component
3875 * strings. Note that unix_convert may have stripped off a
3876 * leading ./ from both name and newname if the rename is
3877 * at the root of the share. We need to make sure either both
3878 * name and newname contain a / character or neither of them do
3879 * as this is checked in resolve_wildcards().
3882 p = strrchr(name,'/');
3883 if (!p) {
3884 pstrcpy(directory,".");
3885 pstrcpy(mask,name);
3886 } else {
3887 *p = 0;
3888 pstrcpy(directory,name);
3889 pstrcpy(mask,p+1);
3890 *p = '/'; /* Replace needed for exceptional test below. */
3894 * We should only check the mangled cache
3895 * here if unix_convert failed. This means
3896 * that the path in 'mask' doesn't exist
3897 * on the file system and so we need to look
3898 * for a possible mangle. This patch from
3899 * Tine Smukavec <valentin.smukavec@hermes.si>.
3902 if (!rc && mangle_is_mangled(mask))
3903 mangle_check_cache( mask );
3905 has_wild = ms_has_wild(mask);
3907 if (!has_wild) {
3908 pstring zdirectory;
3909 pstring znewname;
3912 * No wildcards - just process the one file.
3914 BOOL is_short_name = mangle_is_8_3(name, True);
3916 /* Add a terminating '/' to the directory name. */
3917 pstrcat(directory,"/");
3918 pstrcat(directory,mask);
3920 /* Ensure newname contains a '/' also */
3921 if(strrchr(newname,'/') == 0) {
3922 pstring tmpstr;
3924 pstrcpy(tmpstr, "./");
3925 pstrcat(tmpstr, newname);
3926 pstrcpy(newname, tmpstr);
3929 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3930 directory = %s, newname = %s, newname_last_component = %s, mangle_is_8_3 = %d\n",
3931 case_sensitive, case_preserve, short_case_preserve, directory,
3932 newname, newname_last_component, is_short_name));
3935 * Check for special case with case preserving and not
3936 * case sensitive, if directory and newname are identical,
3937 * and the old last component differs from the original
3938 * last component only by case, then we should allow
3939 * the rename (user is trying to change the case of the
3940 * filename).
3942 if((case_sensitive == False) &&
3943 (((case_preserve == True) &&
3944 (is_short_name == False)) ||
3945 ((short_case_preserve == True) &&
3946 (is_short_name == True))) &&
3947 strcsequal(directory, newname)) {
3948 pstring newname_modified_last_component;
3951 * Get the last component of the modified name.
3952 * Note that we guarantee that newname contains a '/'
3953 * character above.
3955 p = strrchr(newname,'/');
3956 pstrcpy(newname_modified_last_component,p+1);
3958 if(strcsequal(newname_modified_last_component,
3959 newname_last_component) == False) {
3961 * Replace the modified last component with
3962 * the original.
3964 pstrcpy(p+1, newname_last_component);
3969 resolve_wildcards(directory,newname);
3972 * The source object must exist.
3975 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3976 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3977 directory,newname));
3979 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3981 * Must return different errors depending on whether the parent
3982 * directory existed or not.
3985 p = strrchr(directory, '/');
3986 if (!p)
3987 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3988 *p = '\0';
3989 if (vfs_object_exist(conn, directory, NULL))
3990 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3991 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3993 error = map_nt_error_from_unix(errno);
3994 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3995 get_nt_error_msg(error), directory,newname));
3997 return error;
4000 error = can_rename(directory,conn,&sbuf1);
4002 if (!NT_STATUS_IS_OK(error)) {
4003 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4004 get_nt_error_msg(error), directory,newname));
4005 return error;
4008 pstrcpy(zdirectory, dos_to_unix_static(directory));
4009 pstrcpy(znewname, dos_to_unix_static(newname));
4012 * If the src and dest names are identical - including case,
4013 * don't do the rename, just return success.
4016 if (strcsequal(zdirectory, znewname)) {
4017 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4018 return NT_STATUS_OK;
4021 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4022 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4023 directory,newname));
4024 return NT_STATUS_OBJECT_NAME_COLLISION;
4027 if(conn->vfs_ops.rename(conn,zdirectory, znewname) == 0) {
4028 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4029 directory,newname));
4030 return NT_STATUS_OK;
4033 if (errno == ENOTDIR || errno == EISDIR)
4034 error = NT_STATUS_OBJECT_NAME_COLLISION;
4035 else
4036 error = map_nt_error_from_unix(errno);
4038 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4039 get_nt_error_msg(error), directory,newname));
4041 return error;
4042 } else {
4045 * Wildcards - process each file that matches.
4047 void *dirptr = NULL;
4048 char *dname;
4049 pstring destname;
4051 if (check_name(directory,conn))
4052 dirptr = OpenDir(conn, directory, True);
4054 if (dirptr) {
4055 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4057 if (strequal(mask,"????????.???"))
4058 pstrcpy(mask,"*");
4060 while ((dname = ReadDirName(dirptr))) {
4061 pstring fname;
4063 pstrcpy(fname,dname);
4065 if(!mask_match(fname, mask, case_sensitive))
4066 continue;
4068 error = NT_STATUS_ACCESS_DENIED;
4069 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4070 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4071 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4072 DEBUG(6,("rename %s failed. Error %s\n", fname, get_nt_error_msg(error)));
4073 continue;
4075 error = can_rename(fname,conn,&sbuf1);
4076 if (!NT_STATUS_IS_OK(error)) {
4077 DEBUG(6,("rename %s failed. Error %s\n", fname, get_nt_error_msg(error)));
4078 continue;
4080 pstrcpy(destname,newname);
4082 if (!resolve_wildcards(fname,destname)) {
4083 DEBUG(6,("resolve_wildcards %s %s failed\n",
4084 fname, destname));
4085 continue;
4088 if (!replace_if_exists &&
4089 vfs_object_exist(conn,destname, NULL)) {
4090 DEBUG(6,("file_exist %s\n", destname));
4091 error = NT_STATUS_OBJECT_NAME_COLLISION;
4092 continue;
4095 if (!conn->vfs_ops.rename(conn,dos_to_unix_static(fname),
4096 dos_to_unix_static(destname)))
4097 count++;
4098 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4100 CloseDir(dirptr);
4104 if (count == 0 && NT_STATUS_IS_OK(error)) {
4105 error = map_nt_error_from_unix(errno);
4108 return error;
4111 /****************************************************************************
4112 Reply to a mv.
4113 ****************************************************************************/
4115 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4117 int outsize = 0;
4118 pstring name;
4119 pstring newname;
4120 NTSTATUS status;
4121 START_PROFILE(SMBmv);
4123 pstrcpy(name,smb_buf(inbuf) + 1);
4124 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
4126 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4127 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4129 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4131 status = rename_internals(conn, name, newname, False);
4132 if (!NT_STATUS_IS_OK(status)) {
4133 return ERROR_NT(status);
4137 * Win2k needs a changenotify request response before it will
4138 * update after a rename..
4140 process_pending_change_notify_queue((time_t)0);
4141 outsize = set_message(outbuf,0,0,True);
4143 END_PROFILE(SMBmv);
4144 return(outsize);
4147 /*******************************************************************
4148 Copy a file as part of a reply_copy.
4149 ******************************************************************/
4151 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4152 int count,BOOL target_is_directory, int *err_ret)
4154 int Access,action;
4155 SMB_STRUCT_STAT src_sbuf, sbuf2;
4156 SMB_OFF_T ret=-1;
4157 files_struct *fsp1,*fsp2;
4158 pstring dest;
4160 *err_ret = 0;
4162 pstrcpy(dest,dest1);
4163 if (target_is_directory) {
4164 char *p = strrchr(src,'/');
4165 if (p)
4166 p++;
4167 else
4168 p = src;
4169 pstrcat(dest,"/");
4170 pstrcat(dest,p);
4173 if (!vfs_file_exist(conn,src,&src_sbuf))
4174 return(False);
4176 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4177 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
4179 if (!fsp1)
4180 return(False);
4182 if (!target_is_directory && count)
4183 ofun = FILE_EXISTS_OPEN;
4185 if (vfs_stat(conn,dest,&sbuf2) == -1)
4186 ZERO_STRUCTP(&sbuf2);
4188 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4189 ofun,src_sbuf.st_mode,0,&Access,&action);
4191 if (!fsp2) {
4192 close_file(fsp1,False);
4193 return(False);
4196 if ((ofun&3) == 1) {
4197 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4198 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4200 * Stop the copy from occurring.
4202 ret = -1;
4203 src_sbuf.st_size = 0;
4207 if (src_sbuf.st_size)
4208 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4210 close_file(fsp1,False);
4212 /* Ensure the modtime is set correctly on the destination file. */
4213 fsp2->pending_modtime = src_sbuf.st_mtime;
4216 * As we are opening fsp1 read-only we only expect
4217 * an error on close on fsp2 if we are out of space.
4218 * Thus we don't look at the error return from the
4219 * close of fsp1.
4221 *err_ret = close_file(fsp2,False);
4223 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4226 /****************************************************************************
4227 Reply to a file copy.
4228 ****************************************************************************/
4230 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4232 int outsize = 0;
4233 pstring name;
4234 pstring directory;
4235 pstring mask,newname;
4236 char *p;
4237 int count=0;
4238 int error = ERRnoaccess;
4239 int err = 0;
4240 BOOL has_wild;
4241 BOOL exists=False;
4242 int tid2 = SVAL(inbuf,smb_vwv0);
4243 int ofun = SVAL(inbuf,smb_vwv1);
4244 int flags = SVAL(inbuf,smb_vwv2);
4245 BOOL target_is_directory=False;
4246 BOOL bad_path1 = False;
4247 BOOL bad_path2 = False;
4248 BOOL rc = True;
4249 SMB_STRUCT_STAT sbuf1, sbuf2;
4250 START_PROFILE(SMBcopy);
4252 *directory = *mask = 0;
4254 pstrcpy(name,smb_buf(inbuf));
4255 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
4257 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4259 if (tid2 != conn->cnum) {
4260 /* can't currently handle inter share copies XXXX */
4261 DEBUG(3,("Rejecting inter-share copy\n"));
4262 END_PROFILE(SMBcopy);
4263 return ERROR_DOS(ERRSRV,ERRinvdevice);
4266 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4267 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4269 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4270 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4272 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4274 if ((flags&1) && target_is_directory) {
4275 END_PROFILE(SMBcopy);
4276 return ERROR_DOS(ERRDOS,ERRbadfile);
4279 if ((flags&2) && !target_is_directory) {
4280 END_PROFILE(SMBcopy);
4281 return ERROR_DOS(ERRDOS,ERRbadpath);
4284 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4285 /* wants a tree copy! XXXX */
4286 DEBUG(3,("Rejecting tree copy\n"));
4287 END_PROFILE(SMBcopy);
4288 return ERROR_DOS(ERRSRV,ERRerror);
4291 p = strrchr(name,'/');
4292 if (!p) {
4293 pstrcpy(directory,"./");
4294 pstrcpy(mask,name);
4295 } else {
4296 *p = 0;
4297 pstrcpy(directory,name);
4298 pstrcpy(mask,p+1);
4302 * We should only check the mangled cache
4303 * here if unix_convert failed. This means
4304 * that the path in 'mask' doesn't exist
4305 * on the file system and so we need to look
4306 * for a possible mangle. This patch from
4307 * Tine Smukavec <valentin.smukavec@hermes.si>.
4310 if (!rc && mangle_is_mangled(mask))
4311 mangle_check_cache( mask );
4313 has_wild = ms_has_wild(mask);
4315 if (!has_wild) {
4316 pstrcat(directory,"/");
4317 pstrcat(directory,mask);
4318 if (resolve_wildcards(directory,newname) &&
4319 copy_file(directory,newname,conn,ofun,
4320 count,target_is_directory,&err)) count++;
4321 if(!count && err) {
4322 errno = err;
4323 END_PROFILE(SMBcopy);
4324 return(UNIXERROR(ERRHRD,ERRgeneral));
4326 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4327 } else {
4328 void *dirptr = NULL;
4329 char *dname;
4330 pstring destname;
4332 if (check_name(directory,conn))
4333 dirptr = OpenDir(conn, directory, True);
4335 if (dirptr) {
4336 error = ERRbadfile;
4338 if (strequal(mask,"????????.???"))
4339 pstrcpy(mask,"*");
4341 while ((dname = ReadDirName(dirptr))) {
4342 pstring fname;
4343 pstrcpy(fname,dname);
4345 if(!mask_match(fname, mask, case_sensitive))
4346 continue;
4348 error = ERRnoaccess;
4349 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4350 pstrcpy(destname,newname);
4351 if (resolve_wildcards(fname,destname) &&
4352 copy_file(fname,destname,conn,ofun,
4353 count,target_is_directory,&err)) count++;
4354 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4356 CloseDir(dirptr);
4360 if (count == 0) {
4361 if(err) {
4362 /* Error on close... */
4363 errno = err;
4364 END_PROFILE(SMBcopy);
4365 return(UNIXERROR(ERRHRD,ERRgeneral));
4368 if (exists) {
4369 END_PROFILE(SMBcopy);
4370 return ERROR_DOS(ERRDOS,error);
4371 } else
4373 if((errno == ENOENT) && (bad_path1 || bad_path2))
4375 unix_ERR_class = ERRDOS;
4376 unix_ERR_code = ERRbadpath;
4378 END_PROFILE(SMBcopy);
4379 return(UNIXERROR(ERRDOS,error));
4383 outsize = set_message(outbuf,1,0,True);
4384 SSVAL(outbuf,smb_vwv0,count);
4386 END_PROFILE(SMBcopy);
4387 return(outsize);
4390 /****************************************************************************
4391 Reply to a setdir.
4392 ****************************************************************************/
4394 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4396 int snum;
4397 int outsize = 0;
4398 BOOL ok = False;
4399 pstring newdir;
4400 START_PROFILE(pathworks_setdir);
4402 snum = SNUM(conn);
4403 if (!CAN_SETDIR(snum)) {
4404 END_PROFILE(pathworks_setdir);
4405 return ERROR_DOS(ERRDOS,ERRnoaccess);
4408 pstrcpy(newdir,smb_buf(inbuf) + 1);
4409 strlower(newdir);
4411 if (strlen(newdir) == 0) {
4412 ok = True;
4413 } else {
4414 ok = vfs_directory_exist(conn,newdir,NULL);
4415 if (ok) {
4416 string_set(&conn->connectpath,newdir);
4420 if (!ok) {
4421 END_PROFILE(pathworks_setdir);
4422 return ERROR_DOS(ERRDOS,ERRbadpath);
4425 outsize = set_message(outbuf,0,0,True);
4426 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4428 DEBUG(3,("setdir %s\n", newdir));
4430 END_PROFILE(pathworks_setdir);
4431 return(outsize);
4434 /****************************************************************************
4435 Get a lock pid, dealing with large count requests.
4436 ****************************************************************************/
4438 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4440 if(!large_file_format)
4441 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4442 else
4443 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4446 /****************************************************************************
4447 Get a lock count, dealing with large count requests.
4448 ****************************************************************************/
4450 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4452 SMB_BIG_UINT count = 0;
4454 if(!large_file_format) {
4455 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4456 } else {
4458 #if defined(HAVE_LONGLONG)
4459 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4460 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4461 #else /* HAVE_LONGLONG */
4464 * NT4.x seems to be broken in that it sends large file (64 bit)
4465 * lockingX calls even if the CAP_LARGE_FILES was *not*
4466 * negotiated. For boxes without large unsigned ints truncate the
4467 * lock count by dropping the top 32 bits.
4470 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4471 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4472 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4473 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4474 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4477 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4478 #endif /* HAVE_LONGLONG */
4481 return count;
4484 #if !defined(HAVE_LONGLONG)
4485 /****************************************************************************
4486 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4487 ****************************************************************************/
4489 static uint32 map_lock_offset(uint32 high, uint32 low)
4491 unsigned int i;
4492 uint32 mask = 0;
4493 uint32 highcopy = high;
4496 * Try and find out how many significant bits there are in high.
4499 for(i = 0; highcopy; i++)
4500 highcopy >>= 1;
4503 * We use 31 bits not 32 here as POSIX
4504 * lock offsets may not be negative.
4507 mask = (~0) << (31 - i);
4509 if(low & mask)
4510 return 0; /* Fail. */
4512 high <<= (31 - i);
4514 return (high|low);
4516 #endif /* !defined(HAVE_LONGLONG) */
4518 /****************************************************************************
4519 Get a lock offset, dealing with large offset requests.
4520 ****************************************************************************/
4522 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4524 SMB_BIG_UINT offset = 0;
4526 *err = False;
4528 if(!large_file_format) {
4529 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4530 } else {
4532 #if defined(HAVE_LONGLONG)
4533 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4534 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4535 #else /* HAVE_LONGLONG */
4538 * NT4.x seems to be broken in that it sends large file (64 bit)
4539 * lockingX calls even if the CAP_LARGE_FILES was *not*
4540 * negotiated. For boxes without large unsigned ints mangle the
4541 * lock offset by mapping the top 32 bits onto the lower 32.
4544 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4545 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4546 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4547 uint32 new_low = 0;
4549 if((new_low = map_lock_offset(high, low)) == 0) {
4550 *err = True;
4551 return (SMB_BIG_UINT)-1;
4554 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4555 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4556 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4557 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4560 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4561 #endif /* HAVE_LONGLONG */
4564 return offset;
4567 /****************************************************************************
4568 Reply to a lockingX request.
4569 ****************************************************************************/
4571 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4573 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4574 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4575 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4576 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4577 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4578 SMB_BIG_UINT count = 0, offset = 0;
4579 uint16 lock_pid;
4580 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4581 int i;
4582 char *data;
4583 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4584 BOOL err;
4585 NTSTATUS status;
4587 START_PROFILE(SMBlockingX);
4589 CHECK_FSP(fsp,conn);
4591 data = smb_buf(inbuf);
4593 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4594 /* we don't support these - and CANCEL_LOCK makes w2k
4595 and XP reboot so I don't really want to be
4596 compatible! (tridge) */
4597 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4600 /* Check if this is an oplock break on a file
4601 we have granted an oplock on.
4603 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4604 /* Client can insist on breaking to none. */
4605 BOOL break_to_none = (oplocklevel == 0);
4607 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4608 (unsigned int)oplocklevel, fsp->fnum ));
4611 * Make sure we have granted an exclusive or batch oplock on this file.
4614 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4615 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4616 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4618 /* if this is a pure oplock break request then don't send a reply */
4619 if (num_locks == 0 && num_ulocks == 0) {
4620 END_PROFILE(SMBlockingX);
4621 return -1;
4622 } else {
4623 END_PROFILE(SMBlockingX);
4624 return ERROR_DOS(ERRDOS,ERRlock);
4628 if (remove_oplock(fsp, break_to_none) == False) {
4629 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4630 fsp->fsp_name ));
4633 /* if this is a pure oplock break request then don't send a reply */
4634 if (num_locks == 0 && num_ulocks == 0) {
4635 /* Sanity check - ensure a pure oplock break is not a
4636 chained request. */
4637 if(CVAL(inbuf,smb_vwv0) != 0xff)
4638 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4639 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4640 END_PROFILE(SMBlockingX);
4641 return -1;
4646 * We do this check *after* we have checked this is not a oplock break
4647 * response message. JRA.
4650 release_level_2_oplocks_on_change(fsp);
4652 /* Data now points at the beginning of the list
4653 of smb_unlkrng structs */
4654 for(i = 0; i < (int)num_ulocks; i++) {
4655 lock_pid = get_lock_pid( data, i, large_file_format);
4656 count = get_lock_count( data, i, large_file_format);
4657 offset = get_lock_offset( data, i, large_file_format, &err);
4660 * There is no error code marked "stupid client bug".... :-).
4662 if(err) {
4663 END_PROFILE(SMBlockingX);
4664 return ERROR_DOS(ERRDOS,ERRnoaccess);
4667 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4668 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4670 status = do_unlock(fsp,conn,lock_pid,count,offset);
4671 if (NT_STATUS_V(status)) {
4672 END_PROFILE(SMBlockingX);
4673 return ERROR_NT(status);
4677 /* Setup the timeout in seconds. */
4679 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4681 /* Now do any requested locks */
4682 data += ((large_file_format ? 20 : 10)*num_ulocks);
4684 /* Data now points at the beginning of the list
4685 of smb_lkrng structs */
4687 for(i = 0; i < (int)num_locks; i++) {
4688 lock_pid = get_lock_pid( data, i, large_file_format);
4689 count = get_lock_count( data, i, large_file_format);
4690 offset = get_lock_offset( data, i, large_file_format, &err);
4693 * There is no error code marked "stupid client bug".... :-).
4695 if(err) {
4696 END_PROFILE(SMBlockingX);
4697 return ERROR_DOS(ERRDOS,ERRnoaccess);
4700 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4701 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name,
4702 (int)lock_timeout ));
4704 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4705 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
4707 if (NT_STATUS_V(status)) {
4708 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4710 * A blocking lock was requested. Package up
4711 * this smb into a queued request and push it
4712 * onto the blocking lock queue.
4714 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4715 END_PROFILE(SMBlockingX);
4716 return -1;
4719 break;
4723 /* If any of the above locks failed, then we must unlock
4724 all of the previous locks (X/Open spec). */
4725 if(i != num_locks && num_locks != 0) {
4727 * Ensure we don't do a remove on the lock that just failed,
4728 * as under POSIX rules, if we have a lock already there, we
4729 * will delete it (and we shouldn't) .....
4731 for(i--; i >= 0; i--) {
4732 lock_pid = get_lock_pid( data, i, large_file_format);
4733 count = get_lock_count( data, i, large_file_format);
4734 offset = get_lock_offset( data, i, large_file_format, &err);
4737 * There is no error code marked "stupid client bug".... :-).
4739 if(err) {
4740 END_PROFILE(SMBlockingX);
4741 return ERROR_DOS(ERRDOS,ERRnoaccess);
4744 do_unlock(fsp,conn,lock_pid,count,offset);
4746 END_PROFILE(SMBlockingX);
4747 return ERROR_NT(status);
4750 set_message(outbuf,2,0,True);
4752 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4753 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4755 END_PROFILE(SMBlockingX);
4756 return chain_reply(inbuf,outbuf,length,bufsize);
4759 /* Back from the dead for OS/2..... JRA. */
4761 /****************************************************************************
4762 Reply to a SMBreadbmpx (read block multiplex) request
4763 ****************************************************************************/
4765 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4767 ssize_t nread = -1;
4768 ssize_t total_read;
4769 char *data;
4770 SMB_OFF_T startpos;
4771 int outsize;
4772 size_t maxcount;
4773 int max_per_packet;
4774 size_t tcount;
4775 int pad;
4776 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4777 START_PROFILE(SMBreadBmpx);
4779 /* this function doesn't seem to work - disable by default */
4780 if (!lp_readbmpx()) {
4781 END_PROFILE(SMBreadBmpx);
4782 return ERROR_DOS(ERRSRV,ERRuseSTD);
4785 outsize = set_message(outbuf,8,0,True);
4787 CHECK_FSP(fsp,conn);
4788 CHECK_READ(fsp);
4789 CHECK_ERROR(fsp);
4791 startpos = IVAL(inbuf,smb_vwv1);
4792 maxcount = SVAL(inbuf,smb_vwv3);
4794 data = smb_buf(outbuf);
4795 pad = ((long)data)%4;
4796 if (pad)
4797 pad = 4 - pad;
4798 data += pad;
4800 max_per_packet = bufsize-(outsize+pad);
4801 tcount = maxcount;
4802 total_read = 0;
4804 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK, False)) {
4805 END_PROFILE(SMBreadBmpx);
4806 return ERROR_DOS(ERRDOS,ERRlock);
4809 do {
4810 size_t N = MIN(max_per_packet,tcount-total_read);
4812 nread = read_file(fsp,data,startpos,N);
4814 if (nread <= 0)
4815 nread = 0;
4817 if (nread < (ssize_t)N)
4818 tcount = total_read + nread;
4820 set_message(outbuf,8,nread,False);
4821 SIVAL(outbuf,smb_vwv0,startpos);
4822 SSVAL(outbuf,smb_vwv2,tcount);
4823 SSVAL(outbuf,smb_vwv6,nread);
4824 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4826 if (!send_smb(smbd_server_fd(),outbuf))
4827 exit_server("reply_readbmpx: send_smb failed.");
4829 total_read += nread;
4830 startpos += nread;
4831 } while (total_read < (ssize_t)tcount);
4833 END_PROFILE(SMBreadBmpx);
4834 return(-1);
4837 /****************************************************************************
4838 Reply to a SMBsetattrE.
4839 ****************************************************************************/
4841 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4843 struct utimbuf unix_times;
4844 int outsize = 0;
4845 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4846 START_PROFILE(SMBsetattrE);
4848 outsize = set_message(outbuf,0,0,True);
4850 if(!fsp || (fsp->conn != conn)) {
4851 END_PROFILE(SMBgetattrE);
4852 return ERROR_DOS(ERRDOS,ERRbadfid);
4856 * Convert the DOS times into unix times. Ignore create
4857 * time as UNIX can't set this.
4859 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4860 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4863 * Patch from Ray Frush <frush@engr.colostate.edu>
4864 * Sometimes times are sent as zero - ignore them.
4867 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4868 /* Ignore request */
4869 if( DEBUGLVL( 3 ) ) {
4870 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4871 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4873 END_PROFILE(SMBsetattrE);
4874 return(outsize);
4875 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4876 /* set modify time = to access time if modify time was 0 */
4877 unix_times.modtime = unix_times.actime;
4880 /* Set the date on this file */
4881 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4882 END_PROFILE(SMBsetattrE);
4883 return ERROR_DOS(ERRDOS,ERRnoaccess);
4886 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4887 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4889 END_PROFILE(SMBsetattrE);
4890 return(outsize);
4894 /* Back from the dead for OS/2..... JRA. */
4896 /****************************************************************************
4897 Reply to a SMBwritebmpx (write block multiplex primary) request.
4898 ****************************************************************************/
4900 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4902 size_t numtowrite;
4903 ssize_t nwritten = -1;
4904 int outsize = 0;
4905 SMB_OFF_T startpos;
4906 size_t tcount;
4907 BOOL write_through;
4908 int smb_doff;
4909 char *data;
4910 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4911 START_PROFILE(SMBwriteBmpx);
4913 CHECK_FSP(fsp,conn);
4914 CHECK_WRITE(fsp);
4915 CHECK_ERROR(fsp);
4917 tcount = SVAL(inbuf,smb_vwv1);
4918 startpos = IVAL(inbuf,smb_vwv3);
4919 write_through = BITSETW(inbuf+smb_vwv7,0);
4920 numtowrite = SVAL(inbuf,smb_vwv10);
4921 smb_doff = SVAL(inbuf,smb_vwv11);
4923 data = smb_base(inbuf) + smb_doff;
4925 /* If this fails we need to send an SMBwriteC response,
4926 not an SMBwritebmpx - set this up now so we don't forget */
4927 SCVAL(outbuf,smb_com,SMBwritec);
4929 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4930 END_PROFILE(SMBwriteBmpx);
4931 return(ERROR_DOS(ERRDOS,ERRlock));
4934 nwritten = write_file(fsp,data,startpos,numtowrite);
4936 if(lp_syncalways(SNUM(conn)) || write_through)
4937 sync_file(conn,fsp);
4939 if(nwritten < (ssize_t)numtowrite) {
4940 END_PROFILE(SMBwriteBmpx);
4941 return(UNIXERROR(ERRHRD,ERRdiskfull));
4944 /* If the maximum to be written to this file
4945 is greater than what we just wrote then set
4946 up a secondary struct to be attached to this
4947 fd, we will use this to cache error messages etc. */
4949 if((ssize_t)tcount > nwritten) {
4950 write_bmpx_struct *wbms;
4951 if(fsp->wbmpx_ptr != NULL)
4952 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4953 else
4954 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4956 if(!wbms) {
4957 DEBUG(0,("Out of memory in reply_readmpx\n"));
4958 END_PROFILE(SMBwriteBmpx);
4959 return(ERROR_DOS(ERRSRV,ERRnoresource));
4961 wbms->wr_mode = write_through;
4962 wbms->wr_discard = False; /* No errors yet */
4963 wbms->wr_total_written = nwritten;
4964 wbms->wr_errclass = 0;
4965 wbms->wr_error = 0;
4966 fsp->wbmpx_ptr = wbms;
4969 /* We are returning successfully, set the message type back to
4970 SMBwritebmpx */
4971 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4973 outsize = set_message(outbuf,1,0,True);
4975 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4977 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4978 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4980 if (write_through && tcount==nwritten) {
4981 /* We need to send both a primary and a secondary response */
4982 smb_setlen(outbuf,outsize - 4);
4983 if (!send_smb(smbd_server_fd(),outbuf))
4984 exit_server("reply_writebmpx: send_smb failed.");
4986 /* Now the secondary */
4987 outsize = set_message(outbuf,1,0,True);
4988 SCVAL(outbuf,smb_com,SMBwritec);
4989 SSVAL(outbuf,smb_vwv0,nwritten);
4992 END_PROFILE(SMBwriteBmpx);
4993 return(outsize);
4996 /****************************************************************************
4997 Reply to a SMBwritebs (write block multiplex secondary) request.
4998 ****************************************************************************/
5000 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5002 size_t numtowrite;
5003 ssize_t nwritten = -1;
5004 int outsize = 0;
5005 SMB_OFF_T startpos;
5006 size_t tcount;
5007 BOOL write_through;
5008 int smb_doff;
5009 char *data;
5010 write_bmpx_struct *wbms;
5011 BOOL send_response = False;
5012 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5013 START_PROFILE(SMBwriteBs);
5015 CHECK_FSP(fsp,conn);
5016 CHECK_WRITE(fsp);
5018 tcount = SVAL(inbuf,smb_vwv1);
5019 startpos = IVAL(inbuf,smb_vwv2);
5020 numtowrite = SVAL(inbuf,smb_vwv6);
5021 smb_doff = SVAL(inbuf,smb_vwv7);
5023 data = smb_base(inbuf) + smb_doff;
5025 /* We need to send an SMBwriteC response, not an SMBwritebs */
5026 SCVAL(outbuf,smb_com,SMBwritec);
5028 /* This fd should have an auxiliary struct attached,
5029 check that it does */
5030 wbms = fsp->wbmpx_ptr;
5031 if(!wbms) {
5032 END_PROFILE(SMBwriteBs);
5033 return(-1);
5036 /* If write through is set we can return errors, else we must cache them */
5037 write_through = wbms->wr_mode;
5039 /* Check for an earlier error */
5040 if(wbms->wr_discard) {
5041 END_PROFILE(SMBwriteBs);
5042 return -1; /* Just discard the packet */
5045 nwritten = write_file(fsp,data,startpos,numtowrite);
5047 if(lp_syncalways(SNUM(conn)) || write_through)
5048 sync_file(conn,fsp);
5050 if (nwritten < (ssize_t)numtowrite) {
5051 if(write_through) {
5052 /* We are returning an error - we can delete the aux struct */
5053 SAFE_FREE(wbms);
5054 fsp->wbmpx_ptr = NULL;
5055 END_PROFILE(SMBwriteBs);
5056 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5058 END_PROFILE(SMBwriteBs);
5059 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
5062 /* Increment the total written, if this matches tcount
5063 we can discard the auxiliary struct (hurrah !) and return a writeC */
5064 wbms->wr_total_written += nwritten;
5065 if(wbms->wr_total_written >= tcount) {
5066 if (write_through) {
5067 outsize = set_message(outbuf,1,0,True);
5068 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5069 send_response = True;
5072 SAFE_FREE(wbms);
5073 fsp->wbmpx_ptr = NULL;
5076 if(send_response) {
5077 END_PROFILE(SMBwriteBs);
5078 return(outsize);
5081 END_PROFILE(SMBwriteBs);
5082 return(-1);
5085 /****************************************************************************
5086 Reply to a SMBgetattrE.
5087 ****************************************************************************/
5089 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5091 SMB_STRUCT_STAT sbuf;
5092 int outsize = 0;
5093 int mode;
5094 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5095 START_PROFILE(SMBgetattrE);
5097 outsize = set_message(outbuf,11,0,True);
5099 if(!fsp || (fsp->conn != conn)) {
5100 END_PROFILE(SMBgetattrE);
5101 return ERROR_DOS(ERRDOS,ERRbadfid);
5104 /* Do an stat on this file */
5106 if(fsp_stat(fsp, &sbuf)) {
5107 END_PROFILE(SMBgetattrE);
5108 return(UNIXERROR(ERRDOS,ERRnoaccess));
5111 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5113 /* Convert the times into dos times. Set create
5114 * date to be last modify date as UNIX doesn't save
5115 * this.
5118 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5119 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5120 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5121 if (mode & aDIR) {
5122 SIVAL(outbuf,smb_vwv6,0);
5123 SIVAL(outbuf,smb_vwv8,0);
5124 } else {
5125 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5126 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
5128 SSVAL(outbuf,smb_vwv10, mode);
5130 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5132 END_PROFILE(SMBgetattrE);
5133 return(outsize);