2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
31 extern int DEBUGLEVEL;
34 extern char magic_char;
35 extern BOOL case_sensitive;
36 extern BOOL case_preserve;
37 extern BOOL short_case_preserve;
38 extern userdom_struct current_user_info;
39 extern pstring global_myname;
40 extern fstring global_myworkgroup;
41 extern int global_oplock_break;
42 uint32 global_client_caps = 0;
43 unsigned int smb_echo_count = 0;
45 /****************************************************************************
46 report a possible attack via the password buffer overflow bug
47 ****************************************************************************/
49 static void overflow_attack(int len)
52 dbgtext( "ERROR: Invalid password length %d.\n", len );
53 dbgtext( "Your machine may be under attack by someone " );
54 dbgtext( "attempting to exploit an old bug.\n" );
55 dbgtext( "Attack was from IP = %s.\n", client_addr() );
60 /****************************************************************************
61 reply to an special message
62 ****************************************************************************/
64 int reply_special(char *inbuf,char *outbuf)
67 int msg_type = CVAL(inbuf,0);
68 int msg_flags = CVAL(inbuf,1);
70 extern fstring remote_machine;
71 extern fstring local_machine;
77 memset(outbuf,'\0',smb_size);
82 case 0x81: /* session request */
83 CVAL(outbuf,0) = 0x82;
85 if (name_len(inbuf+4) > 50 ||
86 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
87 DEBUG(0,("Invalid name length in session request\n"));
90 name_extract(inbuf,4,name1);
91 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
92 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
95 fstrcpy(remote_machine,name2);
96 remote_machine[15] = 0;
97 trim_string(remote_machine," "," ");
98 strlower(remote_machine);
99 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
101 fstrcpy(local_machine,name1);
102 len = strlen(local_machine);
104 name_type = local_machine[15];
105 local_machine[15] = 0;
107 trim_string(local_machine," "," ");
108 strlower(local_machine);
109 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
111 DEBUG(2,("netbios connect: local=%s remote=%s\n",
112 local_machine, remote_machine ));
114 if (name_type == 'R') {
115 /* We are being asked for a pathworks session ---
117 CVAL(outbuf, 0) = 0x83;
121 /* only add the client's machine name to the list
122 of possibly valid usernames if we are operating
123 in share mode security */
124 if (lp_security() == SEC_SHARE) {
125 add_session_user(remote_machine);
128 reload_services(True);
132 claim_connection(NULL,"",MAXSTATUS,True);
137 case 0x89: /* session keepalive request
138 (some old clients produce this?) */
139 CVAL(outbuf,0) = 0x85;
143 case 0x82: /* positive session response */
144 case 0x83: /* negative session response */
145 case 0x84: /* retarget session response */
146 DEBUG(0,("Unexpected session response\n"));
149 case 0x85: /* session keepalive */
154 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
155 msg_type, msg_flags));
161 /*******************************************************************
162 work out what error to give to a failed connection
163 ********************************************************************/
165 static int connection_error(char *inbuf,char *outbuf,int ecode)
167 if (ecode == ERRnoipc || ecode == ERRnosuchshare)
168 return(ERROR(ERRDOS,ecode));
170 return(ERROR(ERRSRV,ecode));
174 /****************************************************************************
176 ****************************************************************************/
178 int reply_tcon(connection_struct *conn,
179 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
181 BOOL doencrypt = SMBENCRYPT();
187 uint16 vuid = SVAL(inbuf,smb_uid);
192 START_PROFILE(SMBtcon);
194 *service = *user = *password = *dev = 0;
196 p = smb_buf(inbuf)+1;
197 p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE|STR_CONVERT) + 1;
198 p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE|STR_CONVERT) + 1;
199 p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE|STR_CONVERT) + 1;
202 p = strchr(service,'%');
208 p = strrchr(service,'\\');
210 pstrcpy(service, p+1);
214 * If the vuid is valid, we should be using that....
217 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
218 pstrcpy(user,validated_username(vuid));
222 * Ensure the user and password names are in UNIX codepage format.
225 pstrcpy(user,dos_to_unix(user,False));
227 pstrcpy(password,dos_to_unix(password,False));
230 * Pass the user through the NT -> unix user mapping
234 (void)map_username(user);
237 * Do any UNIX username case mangling.
239 (void)Get_Pwnam( user, True);
241 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
244 END_PROFILE(SMBtcon);
245 return(connection_error(inbuf,outbuf,ecode));
248 outsize = set_message(outbuf,2,0,True);
249 SSVAL(outbuf,smb_vwv0,max_recv);
250 SSVAL(outbuf,smb_vwv1,conn->cnum);
251 SSVAL(outbuf,smb_tid,conn->cnum);
253 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
254 service, user, conn->cnum));
256 END_PROFILE(SMBtcon);
260 /****************************************************************************
261 Reply to a tcon and X.
262 ****************************************************************************/
264 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
271 uint16 vuid = SVAL(inbuf,smb_uid);
272 int passlen = SVAL(inbuf,smb_vwv3);
275 START_PROFILE(SMBtconX);
277 *service = *user = *password = *devicename = 0;
279 /* we might have to close an old one */
280 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
281 close_cnum(conn,vuid);
284 if (passlen > MAX_PASS_LEN) {
285 overflow_attack(passlen);
286 return(ERROR(ERRDOS,ERRbuftoosmall));
289 memcpy(password,smb_buf(inbuf),passlen);
291 p = smb_buf(inbuf) + passlen;
292 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE|STR_CONVERT);
295 if (strequal(password," "))
297 passlen = strlen(password);
300 q = strchr(path+2,'\\');
302 END_PROFILE(SMBtconX);
303 return(ERROR(ERRDOS,ERRnosuchshare));
305 fstrcpy(service,q+1);
306 q = strchr(service,'%');
311 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_CONVERT|STR_ASCII);
313 DEBUG(4,("Got device type %s\n",devicename));
316 * If the vuid is valid, we should be using that....
319 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
320 pstrcpy(user,validated_username(vuid));
324 * Pass the user through the NT -> unix user mapping
328 (void)map_username(user);
331 * Do any UNIX username case mangling.
333 (void)Get_Pwnam(user, True);
335 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
338 END_PROFILE(SMBtconX);
339 return(connection_error(inbuf,outbuf,ecode));
342 if (Protocol < PROTOCOL_NT1) {
343 set_message(outbuf,2,0,True);
345 p += srvstr_push(outbuf, p, devicename, -1,
346 STR_CONVERT|STR_TERMINATE|STR_ASCII);
347 set_message_end(outbuf,p);
349 /* NT sets the fstype of IPC$ to the null string */
350 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
352 set_message(outbuf,3,0,True);
355 p += srvstr_push(outbuf, p, devicename, -1,
356 STR_CONVERT|STR_TERMINATE|STR_ASCII);
357 p += srvstr_push(outbuf, p, fsname, -1,
358 STR_CONVERT|STR_TERMINATE);
360 set_message_end(outbuf,p);
362 /* what does setting this bit do? It is set by NT4 and
363 may affect the ability to autorun mounted cdroms */
364 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
366 init_dfsroot(conn, inbuf, outbuf);
370 DEBUG(3,("tconX service=%s user=%s\n",
373 /* set the incoming and outgoing tid to the just created one */
374 SSVAL(inbuf,smb_tid,conn->cnum);
375 SSVAL(outbuf,smb_tid,conn->cnum);
377 END_PROFILE(SMBtconX);
378 return chain_reply(inbuf,outbuf,length,bufsize);
382 /****************************************************************************
383 reply to an unknown type
384 ****************************************************************************/
385 int reply_unknown(char *inbuf,char *outbuf)
388 type = CVAL(inbuf,smb_com);
390 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
391 smb_fn_name(type), type, type));
393 return(ERROR(ERRSRV,ERRunknownsmb));
397 /****************************************************************************
399 ****************************************************************************/
400 int reply_ioctl(connection_struct *conn,
401 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
403 uint16 device = SVAL(inbuf,smb_vwv1);
404 uint16 function = SVAL(inbuf,smb_vwv2);
405 uint32 ioctl_code = (device << 16) + function;
406 int replysize, outsize;
408 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
409 START_PROFILE(SMBioctl);
411 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
415 case IOCTL_QUERY_JOB_INFO:
419 END_PROFILE(SMBioctl);
420 return(ERROR(ERRSRV,ERRnosupport));
423 outsize = set_message(outbuf,8,replysize+1,True);
424 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
425 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
426 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
427 p = smb_buf(outbuf) + 1; /* Allow for alignment */
431 case IOCTL_QUERY_JOB_INFO:
432 SSVAL(p,0,fsp->print_jobid); /* Job number */
433 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_CONVERT|STR_ASCII);
434 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_CONVERT|STR_ASCII);
438 END_PROFILE(SMBioctl);
442 /****************************************************************************
443 always return an error: it's just a matter of which one...
444 ****************************************************************************/
445 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
446 char *smb_passwd, int smb_passlen,
447 char *smb_nt_passwd, int smb_nt_passlen)
449 /* check if trust account exists */
450 SAM_ACCOUNT *sam_trust_acct = NULL;
454 pdb_init_sam(&sam_trust_acct);
456 if (lp_security() == SEC_USER) {
457 ret = pdb_getsampwnam(sam_trust_acct, user);
459 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
460 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
461 pdb_free_sam(sam_trust_acct);
462 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
466 /* lkclXXXX: workstation entry doesn't exist */
467 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
468 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
469 pdb_free_sam(sam_trust_acct);
470 return(ERROR(0, NT_STATUS_NO_SUCH_USER));
472 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
473 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
474 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
475 pdb_free_sam(sam_trust_acct);
476 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
479 if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) {
480 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
481 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
482 pdb_free_sam(sam_trust_acct);
483 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
486 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
487 pdb_free_sam(sam_trust_acct);
488 if (acct_ctrl & ACB_DOMTRUST) {
489 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
490 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
491 return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
494 if (acct_ctrl & ACB_SVRTRUST) {
495 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
496 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
497 return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
500 if (acct_ctrl & ACB_WSTRUST) {
501 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
502 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
503 return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
507 /* don't know what to do: indicate logon failure */
508 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
509 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
512 /****************************************************************************
513 Create a UNIX user on demand.
514 ****************************************************************************/
516 int smb_create_user(char *unix_user, char *homedir)
521 pstrcpy(add_script, lp_adduser_script());
522 if (! *add_script) return -1;
523 all_string_sub(add_script, "%u", unix_user, sizeof(pstring));
525 all_string_sub(add_script, "%H", homedir, sizeof(pstring));
526 ret = smbrun(add_script,NULL);
527 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
531 /****************************************************************************
532 Delete a UNIX user on demand.
533 ****************************************************************************/
535 static int smb_delete_user(char *unix_user)
540 pstrcpy(del_script, lp_deluser_script());
541 if (! *del_script) return -1;
542 all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
543 ret = smbrun(del_script,NULL);
544 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
548 /****************************************************************************
549 Check user is in correct domain if required
550 ****************************************************************************/
552 static BOOL check_domain_match(char *user, char *domain)
555 * If we aren't serving to trusted domains, we must make sure that
556 * the validation request comes from an account in the same domain
557 * as the Samba server
560 if (!lp_allow_trusted_domains() &&
561 !strequal(lp_workgroup(), domain) ) {
562 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
569 /****************************************************************************
570 Check for a valid username and password in security=server mode.
571 ****************************************************************************/
573 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
574 char *smb_apasswd, int smb_apasslen,
575 char *smb_ntpasswd, int smb_ntpasslen)
579 if(lp_security() != SEC_SERVER)
582 if (!check_domain_match(orig_user, domain))
585 ret = server_validate(orig_user, domain,
586 smb_apasswd, smb_apasslen,
587 smb_ntpasswd, smb_ntpasslen);
589 struct passwd *pwd=NULL;
592 * User validated ok against Domain controller.
593 * If the admin wants us to try and create a UNIX
594 * user on the fly, do so.
595 * Note that we can never delete users when in server
596 * level security as we never know if it was a failure
597 * due to a bad password, or the user really doesn't exist.
599 if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
600 smb_create_user(unix_user, NULL);
603 if(lp_adduser_script() && pwd) {
607 * Also call smb_create_user if the users home directory
608 * doesn't exist. Used with winbindd to allow the script to
609 * create the home directory for a user mapped with winbindd.
612 if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
613 smb_create_user(unix_user, pwd->pw_dir);
620 /****************************************************************************
621 Check for a valid username and password in security=domain mode.
622 ****************************************************************************/
624 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
625 char *smb_apasswd, int smb_apasslen,
626 char *smb_ntpasswd, int smb_ntpasslen)
629 BOOL user_exists = True;
630 struct passwd *pwd=NULL;
632 if(lp_security() != SEC_DOMAIN)
635 if (!check_domain_match(orig_user, domain))
638 ret = domain_client_validate(orig_user, domain,
639 smb_apasswd, smb_apasslen,
640 smb_ntpasswd, smb_ntpasslen,
645 * User validated ok against Domain controller.
646 * If the admin wants us to try and create a UNIX
647 * user on the fly, do so.
649 if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True)))
650 smb_create_user(unix_user, NULL);
652 if(lp_adduser_script() && pwd) {
656 * Also call smb_create_user if the users home directory
657 * doesn't exist. Used with winbindd to allow the script to
658 * create the home directory for a user mapped with winbindd.
661 if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
662 smb_create_user(unix_user, pwd->pw_dir);
667 * User failed to validate ok against Domain controller.
668 * If the failure was "user doesn't exist" and admin
669 * wants us to try and delete that UNIX user on the fly,
672 if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True))
673 smb_delete_user(unix_user);
679 /****************************************************************************
680 Return a bad password error configured for the correct client type.
681 ****************************************************************************/
683 static int bad_password_error(char *inbuf,char *outbuf)
685 enum remote_arch_types ra_type = get_remote_arch();
687 if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
688 (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
689 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
690 return(ERROR(0,NT_STATUS_LOGON_FAILURE));
693 return(ERROR(ERRSRV,ERRbadpw));
696 /****************************************************************************
697 reply to a session setup command
698 ****************************************************************************/
700 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
706 int smb_apasslen = 0;
708 int smb_ntpasslen = 0;
709 pstring smb_ntpasswd;
710 BOOL valid_nt_password = False;
711 BOOL valid_lm_password = False;
716 fstring native_lanman;
718 static BOOL done_sesssetup = False;
719 BOOL doencrypt = SMBENCRYPT();
720 START_PROFILE(SMBsesssetupX);
725 smb_bufsize = SVAL(inbuf,smb_vwv2);
727 if (Protocol < PROTOCOL_NT1) {
728 smb_apasslen = SVAL(inbuf,smb_vwv7);
729 if (smb_apasslen > MAX_PASS_LEN) {
730 overflow_attack(smb_apasslen);
731 return(ERROR(ERRDOS,ERRbuftoosmall));
734 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
735 smb_apasswd[smb_apasslen] = 0;
736 srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE|STR_CONVERT);
738 if (!doencrypt && (lp_security() != SEC_SERVER)) {
739 smb_apasslen = strlen(smb_apasswd);
742 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
743 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
744 enum remote_arch_types ra_type = get_remote_arch();
745 char *p = smb_buf(inbuf);
747 if(global_client_caps == 0)
748 global_client_caps = IVAL(inbuf,smb_vwv11);
750 /* client_caps is used as final determination if client is NT or Win95.
751 This is needed to return the correct error codes in some
755 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
756 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
757 set_remote_arch( RA_WIN95);
761 if (passlen1 != 24 && passlen2 != 24)
764 if (passlen1 > MAX_PASS_LEN) {
765 overflow_attack(passlen1);
766 return(ERROR(ERRDOS,ERRbuftoosmall));
769 passlen1 = MIN(passlen1, MAX_PASS_LEN);
770 passlen2 = MIN(passlen2, MAX_PASS_LEN);
773 /* both Win95 and WinNT stuff up the password lengths for
774 non-encrypting systems. Uggh.
776 if passlen1==24 its a win95 system, and its setting the
777 password length incorrectly. Luckily it still works with the
778 default code because Win95 will null terminate the password
781 if passlen1>0 and passlen2>0 then maybe its a NT box and its
782 setting passlen2 to some random value which really stuffs
783 things up. we need to fix that one. */
785 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
789 if (lp_restrict_anonymous()) {
790 /* there seems to be no reason behind the differences in MS clients formatting
791 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
792 * in particular seems to have an extra null byte between the username and the
793 * domain, or the password length calculation is wrong, which throws off the
794 * string extraction routines below. This makes the value of domain be the
795 * empty string, which fails the restrict anonymous check further down.
796 * This compensates for that, and allows browsing to work in mixed NT and
797 * win95 environments even when restrict anonymous is true. AAB
799 dump_data(100, p, 0x70);
800 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
801 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
802 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
803 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
804 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
809 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
810 /* Save the lanman2 password and the NT md4 password. */
811 smb_apasslen = passlen1;
812 memcpy(smb_apasswd,p,smb_apasslen);
813 smb_apasswd[smb_apasslen] = 0;
814 smb_ntpasslen = passlen2;
815 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
816 smb_ntpasswd[smb_ntpasslen] = 0;
819 * Ensure the plaintext passwords are in UNIX format.
822 pstrcpy(smb_apasswd,dos_to_unix(smb_apasswd,False));
823 pstrcpy(smb_ntpasswd,dos_to_unix(smb_ntpasswd,False));
827 /* we use the first password that they gave */
828 smb_apasslen = passlen1;
829 StrnCpy(smb_apasswd,p,smb_apasslen);
831 * Ensure the plaintext password is in UNIX format.
833 pstrcpy(smb_apasswd,dos_to_unix(smb_apasswd,False));
835 /* trim the password */
836 smb_apasslen = strlen(smb_apasswd);
838 /* wfwg sometimes uses a space instead of a null */
839 if (strequal(smb_apasswd," ")) {
845 p += passlen1 + passlen2;
846 p += srvstr_pull(inbuf, user, p, sizeof(user), -1, STR_CONVERT|STR_TERMINATE);
848 * Incoming user and domain are in DOS codepage format. Convert
851 p += srvstr_pull(inbuf, domain, p, sizeof(domain),
852 -1, STR_CONVERT|STR_TERMINATE);
853 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
854 -1, STR_CONVERT|STR_TERMINATE);
855 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
856 -1, STR_CONVERT|STR_TERMINATE);
857 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
858 domain,native_os,native_lanman));
861 DEBUG(3,("sesssetupX:name=[%s]\n",user));
863 /* If name ends in $ then I think it's asking about whether a */
864 /* computer with that name (minus the $) has access. For now */
865 /* say yes to everything ending in $. */
867 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
868 END_PROFILE(SMBsesssetupX);
869 return session_trust_account(conn, inbuf, outbuf, user,
870 smb_apasswd, smb_apasslen,
871 smb_ntpasswd, smb_ntpasslen);
874 if (done_sesssetup && lp_restrict_anonymous()) {
875 /* tests show that even if browsing is done over already validated connections
876 * without a username and password the domain is still provided, which it
877 * wouldn't be if it was a purely anonymous connection. So, in order to
878 * restrict anonymous, we only deny connections that have no session
879 * information. If a domain has been provided, then it's not a purely
880 * anonymous connection. AAB
882 if (!*user && !*smb_apasswd && !*domain) {
883 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
884 END_PROFILE(SMBsesssetupX);
885 return(ERROR(ERRDOS,ERRnoaccess));
889 /* If no username is sent use the guest account */
891 pstrcpy(user,lp_guestaccount(-1));
892 /* If no user and no password then set guest flag. */
893 if( *smb_apasswd == 0)
897 pstrcpy(current_user_info.smb_name,user);
899 reload_services(True);
902 * Save the username before mapping. We will use
903 * the original username sent to us for security=server
904 * and security=domain checking.
907 pstrcpy( orig_user, user);
910 * Always try the "DOMAIN\user" lookup first, as this is the most
911 * specific case. If this fails then try the simple "user" lookup.
917 /* Work out who's who */
919 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
920 dos_to_unix(domain, False), lp_winbind_separator(), user);
922 if (sys_getpwnam(dom_user) != NULL) {
923 pstrcpy(user, dom_user);
924 DEBUG(3,("Using unix username %s\n", dom_user));
929 * Pass the user through the NT -> unix user mapping
933 (void)map_username(user);
936 * Do any UNIX username case mangling.
938 smb_getpwnam(user, True);
940 add_session_user(user);
943 * Check if the given username was the guest user with no password.
946 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
950 * Check with orig_user for security=server and
954 if (!guest && !check_server_security(orig_user, domain, user,
955 smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
956 !check_domain_security(orig_user, domain, user, smb_apasswd,
957 smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
958 !check_hosts_equiv(user))
962 * If we get here then the user wasn't guest and the remote
963 * authentication methods failed. Check the authentication
964 * methods on this local server.
966 * If an NT password was supplied try and validate with that
967 * first. This is superior as the passwords are mixed case
968 * 128 length unicode.
973 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
974 DEBUG(2,("NT Password did not match for user '%s'!\n", user));
976 valid_nt_password = True;
980 /* check the LanMan password only if necessary and if allowed
981 by lp_lanman_auth() */
982 if (!valid_nt_password && lp_lanman_auth())
984 DEBUG(2,("Defaulting to Lanman password for %s\n", user));
985 valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen,NULL);
989 /* The true branch will be executed if
990 (1) the NT password failed (or was not tried), and
991 (2) LanMan authentication failed (or was disabled)
993 if (!valid_nt_password && !valid_lm_password)
995 if (lp_security() >= SEC_USER)
997 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
999 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
1000 END_PROFILE(SMBsesssetupX);
1001 return bad_password_error(inbuf,outbuf);
1004 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
1006 if (smb_getpwnam(user,True))
1008 DEBUG(1,("Rejecting user '%s': bad password\n", user));
1009 END_PROFILE(SMBsesssetupX);
1010 return bad_password_error(inbuf,outbuf);
1015 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
1016 * Then always map to guest account - as done below.
1020 if (*smb_apasswd || !smb_getpwnam(user,True))
1021 pstrcpy(user,lp_guestaccount(-1));
1022 DEBUG(3,("Registered username %s for guest access\n",user));
1027 if (!smb_getpwnam(user,True)) {
1028 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
1029 pstrcpy(user,lp_guestaccount(-1));
1033 if (!strequal(user,lp_guestaccount(-1)) &&
1034 lp_servicenumber(user) < 0)
1036 add_home_service(user,get_user_home_dir(user));
1040 /* it's ok - setup a reply */
1041 if (Protocol < PROTOCOL_NT1) {
1042 set_message(outbuf,3,0,True);
1045 set_message(outbuf,3,0,True);
1046 p = smb_buf(outbuf);
1047 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE|STR_CONVERT);
1048 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE|STR_CONVERT);
1049 p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE|STR_CONVERT);
1050 set_message_end(outbuf,p);
1051 /* perhaps grab OS version here?? */
1054 /* Set the correct uid in the outgoing and incoming packets
1055 We will use this on future requests to determine which
1056 user we should become.
1059 const struct passwd *pw = smb_getpwnam(user,False);
1061 DEBUG(1,("Username %s is invalid on this system\n",user));
1062 END_PROFILE(SMBsesssetupX);
1063 return bad_password_error(inbuf,outbuf);
1070 SSVAL(outbuf,smb_vwv2,1);
1072 /* register the name and uid as being validated, so further connections
1073 to a uid can get through without a password, on the same VC */
1075 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest);
1077 if (sess_vuid == -1) {
1078 return(ERROR(ERRDOS,ERRnoaccess));
1082 SSVAL(outbuf,smb_uid,sess_vuid);
1083 SSVAL(inbuf,smb_uid,sess_vuid);
1085 if (!done_sesssetup)
1086 max_send = MIN(max_send,smb_bufsize);
1088 DEBUG(6,("Client requested max send size of %d\n", max_send));
1090 done_sesssetup = True;
1092 END_PROFILE(SMBsesssetupX);
1093 return chain_reply(inbuf,outbuf,length,bufsize);
1096 /****************************************************************************
1098 ****************************************************************************/
1099 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1105 BOOL bad_path = False;
1106 SMB_STRUCT_STAT sbuf;
1107 START_PROFILE(SMBchkpth);
1109 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1111 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1113 unix_convert(name,conn,0,&bad_path,&sbuf);
1115 mode = SVAL(inbuf,smb_vwv0);
1117 if (check_name(name,conn)) {
1118 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
1119 ok = S_ISDIR(sbuf.st_mode);
1124 /* We special case this - as when a Windows machine
1125 is parsing a path is steps through the components
1126 one at a time - if a component fails it expects
1127 ERRbadpath, not ERRbadfile.
1131 unix_ERR_class = ERRDOS;
1132 unix_ERR_code = ERRbadpath;
1136 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1137 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1138 (get_remote_arch() == RA_WINNT))
1140 unix_ERR_class = ERRDOS;
1141 unix_ERR_code = ERRbaddirectory;
1145 return(UNIXERROR(ERRDOS,ERRbadpath));
1148 outsize = set_message(outbuf,0,0,True);
1150 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1152 END_PROFILE(SMBchkpth);
1157 /****************************************************************************
1159 ****************************************************************************/
1160 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1164 SMB_STRUCT_STAT sbuf;
1169 BOOL bad_path = False;
1171 START_PROFILE(SMBgetatr);
1173 p = smb_buf(inbuf) + 1;
1174 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1176 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1178 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1179 under WfWg - weird! */
1182 mode = aHIDDEN | aDIR;
1183 if (!CAN_WRITE(conn)) mode |= aRONLY;
1190 unix_convert(fname,conn,0,&bad_path,&sbuf);
1191 if (check_name(fname,conn))
1193 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1195 mode = dos_mode(conn,fname,&sbuf);
1196 size = sbuf.st_size;
1197 mtime = sbuf.st_mtime;
1203 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1209 if((errno == ENOENT) && bad_path)
1211 unix_ERR_class = ERRDOS;
1212 unix_ERR_code = ERRbadpath;
1215 END_PROFILE(SMBgetatr);
1216 return(UNIXERROR(ERRDOS,ERRbadfile));
1219 outsize = set_message(outbuf,10,0,True);
1221 SSVAL(outbuf,smb_vwv0,mode);
1222 if(lp_dos_filetime_resolution(SNUM(conn)) )
1223 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1225 put_dos_date3(outbuf,smb_vwv1,mtime);
1226 SIVAL(outbuf,smb_vwv3,(uint32)size);
1228 if (Protocol >= PROTOCOL_NT1) {
1229 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1232 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1234 END_PROFILE(SMBgetatr);
1239 /****************************************************************************
1241 ****************************************************************************/
1242 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1249 SMB_STRUCT_STAT sbuf;
1250 BOOL bad_path = False;
1253 START_PROFILE(SMBsetatr);
1255 p = smb_buf(inbuf) + 1;
1256 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1257 unix_convert(fname,conn,0,&bad_path,&sbuf);
1259 mode = SVAL(inbuf,smb_vwv0);
1260 mtime = make_unix_date3(inbuf+smb_vwv1);
1262 if (VALID_STAT_OF_DIR(sbuf))
1264 if (check_name(fname,conn))
1265 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1267 ok = set_filetime(conn,fname,mtime);
1271 if((errno == ENOENT) && bad_path)
1273 unix_ERR_class = ERRDOS;
1274 unix_ERR_code = ERRbadpath;
1277 END_PROFILE(SMBsetatr);
1278 return(UNIXERROR(ERRDOS,ERRnoaccess));
1281 outsize = set_message(outbuf,0,0,True);
1283 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1285 END_PROFILE(SMBsetatr);
1290 /****************************************************************************
1292 ****************************************************************************/
1293 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1296 SMB_BIG_UINT dfree,dsize,bsize;
1297 START_PROFILE(SMBdskattr);
1299 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1301 outsize = set_message(outbuf,5,0,True);
1303 SSVAL(outbuf,smb_vwv0,dsize);
1304 SSVAL(outbuf,smb_vwv1,bsize/512);
1305 SSVAL(outbuf,smb_vwv2,512);
1306 SSVAL(outbuf,smb_vwv3,dfree);
1308 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1310 END_PROFILE(SMBdskattr);
1315 /****************************************************************************
1317 Can be called from SMBsearch, SMBffirst or SMBfunique.
1318 ****************************************************************************/
1319 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1330 BOOL finished = False;
1339 BOOL check_descend = False;
1340 BOOL expect_close = False;
1341 BOOL can_open = True;
1342 BOOL bad_path = False;
1343 START_PROFILE(SMBsearch);
1345 *mask = *directory = *fname = 0;
1347 /* If we were called as SMBffirst then we must expect close. */
1348 if(CVAL(inbuf,smb_com) == SMBffirst)
1349 expect_close = True;
1351 outsize = set_message(outbuf,1,3,True);
1352 maxentries = SVAL(inbuf,smb_vwv0);
1353 dirtype = SVAL(inbuf,smb_vwv1);
1354 p = smb_buf(inbuf) + 1;
1355 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1357 status_len = SVAL(p, 0);
1360 /* dirtype &= ~aDIR; */
1362 if (status_len == 0)
1364 SMB_STRUCT_STAT sbuf;
1367 pstrcpy(directory,path);
1369 unix_convert(directory,conn,0,&bad_path,&sbuf);
1372 if (!check_name(directory,conn))
1375 p = strrchr(dir2,'/');
1387 p = strrchr(directory,'/');
1393 if (strlen(directory) == 0)
1394 pstrcpy(directory,"./");
1395 memset((char *)status,'\0',21);
1396 CVAL(status,0) = dirtype;
1400 memcpy(status,p,21);
1401 dirtype = CVAL(status,0) & 0x1F;
1402 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1405 string_set(&conn->dirpath,dptr_path(dptr_num));
1406 fstrcpy(mask, dptr_wcard(dptr_num));
1411 p = smb_buf(outbuf) + 3;
1415 if (status_len == 0)
1417 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1422 if((errno == ENOENT) && bad_path)
1424 unix_ERR_class = ERRDOS;
1425 unix_ERR_code = ERRbadpath;
1427 END_PROFILE(SMBsearch);
1428 return (UNIXERROR(ERRDOS,ERRnofids));
1430 END_PROFILE(SMBsearch);
1431 return(ERROR(ERRDOS,ERRnofids));
1433 dptr_set_wcard(dptr_num, strdup(mask));
1436 DEBUG(4,("dptr_num is %d\n",dptr_num));
1440 if ((dirtype&0x1F) == aVOLID)
1442 memcpy(p,status,21);
1443 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1444 dptr_fill(p+12,dptr_num);
1445 if (dptr_zero(p+12) && (status_len==0))
1449 p += DIR_STRUCT_SIZE;
1453 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1454 conn->dirpath,lp_dontdescend(SNUM(conn))));
1455 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1456 check_descend = True;
1458 for (i=numentries;(i<maxentries) && !finished;i++)
1461 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1464 memcpy(p,status,21);
1465 make_dir_struct(p,mask,fname,size,mode,date);
1466 dptr_fill(p+12,dptr_num);
1469 p += DIR_STRUCT_SIZE;
1478 if (numentries == 0 || !ok)
1480 CVAL(outbuf,smb_rcls) = ERRDOS;
1481 SSVAL(outbuf,smb_err,ERRnofiles);
1482 dptr_close(&dptr_num);
1485 /* If we were called as SMBffirst with smb_search_id == NULL
1486 and no entries were found then return error and close dirptr
1489 if(ok && expect_close && numentries == 0 && status_len == 0)
1491 CVAL(outbuf,smb_rcls) = ERRDOS;
1492 SSVAL(outbuf,smb_err,ERRnofiles);
1493 /* Also close the dptr - we know it's gone */
1494 dptr_close(&dptr_num);
1497 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1498 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1499 dptr_close(&dptr_num);
1501 SSVAL(outbuf,smb_vwv0,numentries);
1502 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1503 CVAL(smb_buf(outbuf),0) = 5;
1504 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1506 if (Protocol >= PROTOCOL_NT1) {
1507 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1510 outsize += DIR_STRUCT_SIZE*numentries;
1511 smb_setlen(outbuf,outsize - 4);
1513 if ((! *directory) && dptr_path(dptr_num))
1514 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1516 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1517 smb_fn_name(CVAL(inbuf,smb_com)),
1518 mask, directory, dirtype, numentries, maxentries ) );
1520 END_PROFILE(SMBsearch);
1525 /****************************************************************************
1526 reply to a fclose (stop directory search)
1527 ****************************************************************************/
1528 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1537 START_PROFILE(SMBfclose);
1539 outsize = set_message(outbuf,1,0,True);
1540 p = smb_buf(inbuf) + 1;
1541 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE|STR_CONVERT);
1543 status_len = SVAL(p,0);
1546 if (status_len == 0) {
1547 END_PROFILE(SMBfclose);
1548 return(ERROR(ERRSRV,ERRsrverror));
1551 memcpy(status,p,21);
1553 if(dptr_fetch(status+12,&dptr_num)) {
1554 /* Close the dptr - we know it's gone */
1555 dptr_close(&dptr_num);
1558 SSVAL(outbuf,smb_vwv0,0);
1560 DEBUG(3,("search close\n"));
1562 END_PROFILE(SMBfclose);
1567 /****************************************************************************
1569 ****************************************************************************/
1571 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1581 SMB_STRUCT_STAT sbuf;
1582 BOOL bad_path = False;
1584 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1585 START_PROFILE(SMBopen);
1587 share_mode = SVAL(inbuf,smb_vwv0);
1589 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1591 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1593 unix_convert(fname,conn,0,&bad_path,&sbuf);
1595 unixmode = unix_mode(conn,aARCH,fname);
1597 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1598 unixmode, oplock_request,&rmode,NULL);
1602 if((errno == ENOENT) && bad_path)
1604 unix_ERR_class = ERRDOS;
1605 unix_ERR_code = ERRbadpath;
1607 END_PROFILE(SMBopen);
1608 return(UNIXERROR(ERRDOS,ERRnoaccess));
1611 size = sbuf.st_size;
1612 fmode = dos_mode(conn,fname,&sbuf);
1613 mtime = sbuf.st_mtime;
1616 DEBUG(3,("attempt to open a directory %s\n",fname));
1617 close_file(fsp,False);
1618 END_PROFILE(SMBopen);
1619 return(ERROR(ERRDOS,ERRnoaccess));
1622 outsize = set_message(outbuf,7,0,True);
1623 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1624 SSVAL(outbuf,smb_vwv1,fmode);
1625 if(lp_dos_filetime_resolution(SNUM(conn)) )
1626 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1628 put_dos_date3(outbuf,smb_vwv2,mtime);
1629 SIVAL(outbuf,smb_vwv4,(uint32)size);
1630 SSVAL(outbuf,smb_vwv6,rmode);
1632 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1633 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1636 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1637 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1638 END_PROFILE(SMBopen);
1643 /****************************************************************************
1644 reply to an open and X
1645 ****************************************************************************/
1646 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1649 int smb_mode = SVAL(inbuf,smb_vwv3);
1650 int smb_attr = SVAL(inbuf,smb_vwv5);
1651 /* Breakout the oplock request bits so we can set the
1652 reply bits separately. */
1653 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1654 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1655 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1657 int open_flags = SVAL(inbuf,smb_vwv2);
1658 int smb_sattr = SVAL(inbuf,smb_vwv4);
1659 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1661 int smb_ofun = SVAL(inbuf,smb_vwv8);
1664 int fmode=0,mtime=0,rmode=0;
1665 SMB_STRUCT_STAT sbuf;
1667 BOOL bad_path = False;
1669 START_PROFILE(SMBopenX);
1671 /* If it's an IPC, pass off the pipe handler. */
1673 if (lp_nt_pipe_support()) {
1674 END_PROFILE(SMBopenX);
1675 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1677 END_PROFILE(SMBopenX);
1678 return (ERROR(ERRSRV,ERRaccess));
1682 /* XXXX we need to handle passed times, sattr and flags */
1683 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1685 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1687 unix_convert(fname,conn,0,&bad_path,&sbuf);
1689 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1691 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1692 oplock_request, &rmode,&smb_action);
1696 if((errno == ENOENT) && bad_path)
1698 unix_ERR_class = ERRDOS;
1699 unix_ERR_code = ERRbadpath;
1701 END_PROFILE(SMBopenX);
1702 return(UNIXERROR(ERRDOS,ERRnoaccess));
1705 size = sbuf.st_size;
1706 fmode = dos_mode(conn,fname,&sbuf);
1707 mtime = sbuf.st_mtime;
1709 close_file(fsp,False);
1710 END_PROFILE(SMBopenX);
1711 return(ERROR(ERRDOS,ERRnoaccess));
1714 /* If the caller set the extended oplock request bit
1715 and we granted one (by whatever means) - set the
1716 correct bit for extended oplock reply.
1719 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1720 smb_action |= EXTENDED_OPLOCK_GRANTED;
1723 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1724 smb_action |= EXTENDED_OPLOCK_GRANTED;
1727 /* If the caller set the core oplock request bit
1728 and we granted one (by whatever means) - set the
1729 correct bit for core oplock reply.
1732 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1733 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1736 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1737 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1740 set_message(outbuf,15,0,True);
1741 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1742 SSVAL(outbuf,smb_vwv3,fmode);
1743 if(lp_dos_filetime_resolution(SNUM(conn)) )
1744 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1746 put_dos_date3(outbuf,smb_vwv4,mtime);
1747 SIVAL(outbuf,smb_vwv6,(uint32)size);
1748 SSVAL(outbuf,smb_vwv8,rmode);
1749 SSVAL(outbuf,smb_vwv11,smb_action);
1751 END_PROFILE(SMBopenX);
1752 return chain_reply(inbuf,outbuf,length,bufsize);
1756 /****************************************************************************
1757 reply to a SMBulogoffX
1758 ****************************************************************************/
1759 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1761 uint16 vuid = SVAL(inbuf,smb_uid);
1762 user_struct *vuser = get_valid_user_struct(vuid);
1763 START_PROFILE(SMBulogoffX);
1766 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1769 /* in user level security we are supposed to close any files
1770 open by this user */
1771 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1772 file_close_user(vuid);
1775 invalidate_vuid(vuid);
1777 set_message(outbuf,2,0,True);
1779 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1781 END_PROFILE(SMBulogoffX);
1782 return chain_reply(inbuf,outbuf,length,bufsize);
1786 /****************************************************************************
1787 reply to a mknew or a create
1788 ****************************************************************************/
1789 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1797 BOOL bad_path = False;
1799 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1800 SMB_STRUCT_STAT sbuf;
1801 START_PROFILE(SMBcreate);
1803 com = SVAL(inbuf,smb_com);
1805 createmode = SVAL(inbuf,smb_vwv0);
1806 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1808 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1810 unix_convert(fname,conn,0,&bad_path,&sbuf);
1812 if (createmode & aVOLID) {
1813 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1816 unixmode = unix_mode(conn,createmode,fname);
1820 /* We should fail if file exists. */
1821 ofun = FILE_CREATE_IF_NOT_EXIST;
1825 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1826 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1829 /* Open file in dos compatibility share mode. */
1830 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1831 ofun, unixmode, oplock_request, NULL, NULL);
1835 if((errno == ENOENT) && bad_path)
1837 unix_ERR_class = ERRDOS;
1838 unix_ERR_code = ERRbadpath;
1840 END_PROFILE(SMBcreate);
1841 return(UNIXERROR(ERRDOS,ERRnoaccess));
1844 outsize = set_message(outbuf,1,0,True);
1845 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1847 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1848 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1851 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1852 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1854 DEBUG( 2, ( "new file %s\n", fname ) );
1855 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1856 fname, fsp->fd, createmode, (int)unixmode ) );
1858 END_PROFILE(SMBcreate);
1863 /****************************************************************************
1864 reply to a create temporary file
1865 ****************************************************************************/
1866 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1873 BOOL bad_path = False;
1875 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1877 SMB_STRUCT_STAT sbuf;
1880 START_PROFILE(SMBctemp);
1882 createmode = SVAL(inbuf,smb_vwv0);
1883 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT);
1884 pstrcat(fname,"/TMXXXXXX");
1886 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1888 unix_convert(fname,conn,0,&bad_path,&sbuf);
1890 unixmode = unix_mode(conn,createmode,fname);
1892 tmpfd = smb_mkstemp(fname);
1894 END_PROFILE(SMBctemp);
1895 return(UNIXERROR(ERRDOS,ERRnoaccess));
1898 vfs_stat(conn,fname2,&sbuf);
1900 /* Open file in dos compatibility share mode. */
1901 /* We should fail if file does not exist. */
1902 fsp = open_file_shared(conn,fname,&sbuf,
1903 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1904 FILE_FAIL_IF_NOT_EXIST,
1905 unixmode, oplock_request, NULL, NULL);
1907 /* close fd from smb_mkstemp() */
1912 if((errno == ENOENT) && bad_path)
1914 unix_ERR_class = ERRDOS;
1915 unix_ERR_code = ERRbadpath;
1917 END_PROFILE(SMBctemp);
1918 return(UNIXERROR(ERRDOS,ERRnoaccess));
1921 outsize = set_message(outbuf,1,0,True);
1922 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1923 CVAL(smb_buf(outbuf),0) = 4;
1924 p = smb_buf(outbuf) + 1;
1925 p += srvstr_push(outbuf, p, fname2, -1, STR_TERMINATE|STR_CONVERT);
1926 set_message_end(outbuf, p);
1928 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1929 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1932 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1933 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1935 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1936 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1937 fname2, fsp->fd, createmode, (int)unixmode ) );
1939 END_PROFILE(SMBctemp);
1944 /*******************************************************************
1945 check if a user is allowed to delete a file
1946 ********************************************************************/
1947 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1949 SMB_STRUCT_STAT sbuf;
1952 if (!CAN_WRITE(conn)) return(False);
1954 if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False);
1955 fmode = dos_mode(conn,fname,&sbuf);
1956 if (fmode & aDIR) return(False);
1957 if (!lp_delete_readonly(SNUM(conn))) {
1958 if (fmode & aRONLY) return(False);
1960 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1962 if (!check_file_sharing(conn,fname,False)) return(False);
1966 /****************************************************************************
1967 The guts of the unlink command, split out so it may be called by the NT SMB
1969 ****************************************************************************/
1971 int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
1972 int dirtype, char *name)
1978 int error = ERRnoaccess;
1981 BOOL bad_path = False;
1983 SMB_STRUCT_STAT sbuf;
1985 *directory = *mask = 0;
1987 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1989 p = strrchr(name,'/');
1991 pstrcpy(directory,"./");
1995 pstrcpy(directory,name);
2000 * We should only check the mangled cache
2001 * here if unix_convert failed. This means
2002 * that the path in 'mask' doesn't exist
2003 * on the file system and so we need to look
2004 * for a possible mangle. This patch from
2005 * Tine Smukavec <valentin.smukavec@hermes.si>.
2008 if (!rc && is_mangled(mask))
2009 check_mangled_cache( mask );
2011 has_wild = ms_has_wild(mask);
2014 pstrcat(directory,"/");
2015 pstrcat(directory,mask);
2016 if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory))
2019 exists = vfs_file_exist(conn,directory,&sbuf);
2021 void *dirptr = NULL;
2024 if (check_name(directory,conn))
2025 dirptr = OpenDir(conn, directory, True);
2027 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2028 the pattern matches against the long name, otherwise the short name
2029 We don't implement this yet XXXX
2036 if (strequal(mask,"????????.???"))
2039 while ((dname = ReadDirName(dirptr)))
2042 pstrcpy(fname,dname);
2044 if(!mask_match(fname, mask, case_sensitive)) continue;
2046 error = ERRnoaccess;
2047 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2048 if (!can_delete(fname,conn,dirtype)) continue;
2049 if (!vfs_unlink(conn,fname)) count++;
2050 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2058 return(ERROR(ERRDOS,error));
2060 if((errno == ENOENT) && bad_path) {
2061 unix_ERR_class = ERRDOS;
2062 unix_ERR_code = ERRbadpath;
2064 return(UNIXERROR(ERRDOS,error));
2071 /****************************************************************************
2073 ****************************************************************************/
2075 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2080 START_PROFILE(SMBunlink);
2082 dirtype = SVAL(inbuf,smb_vwv0);
2084 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
2086 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
2088 DEBUG(3,("reply_unlink : %s\n",name));
2090 outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
2094 * Win2k needs a changenotify request response before it will
2095 * update after a rename..
2098 process_pending_change_notify_queue((time_t)0);
2100 outsize = set_message(outbuf,0,0,True);
2103 END_PROFILE(SMBunlink);
2108 /****************************************************************************
2109 reply to a readbraw (core+ protocol)
2110 ****************************************************************************/
2112 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2114 size_t maxcount,mincount;
2117 char *header = outbuf;
2120 START_PROFILE(SMBreadbraw);
2123 * Special check if an oplock break has been issued
2124 * and the readraw request croses on the wire, we must
2125 * return a zero length response here.
2128 if(global_oplock_break)
2130 _smb_setlen(header,0);
2131 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2132 DEBUG(5,("readbraw - oplock break finished\n"));
2133 END_PROFILE(SMBreadbraw);
2137 fsp = file_fsp(inbuf,smb_vwv0);
2139 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2141 * fsp could be NULL here so use the value from the packet. JRA.
2143 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2144 _smb_setlen(header,0);
2145 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2146 END_PROFILE(SMBreadbraw);
2150 CHECK_FSP(fsp,conn);
2152 flush_write_cache(fsp, READRAW_FLUSH);
2154 startpos = IVAL(inbuf,smb_vwv1);
2155 if(CVAL(inbuf,smb_wct) == 10) {
2157 * This is a large offset (64 bit) read.
2159 #ifdef LARGE_SMB_OFF_T
2161 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2163 #else /* !LARGE_SMB_OFF_T */
2166 * Ensure we haven't been sent a >32 bit offset.
2169 if(IVAL(inbuf,smb_vwv8) != 0) {
2170 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2171 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2172 _smb_setlen(header,0);
2173 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2174 END_PROFILE(SMBreadbraw);
2178 #endif /* LARGE_SMB_OFF_T */
2181 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2182 (double)startpos ));
2183 _smb_setlen(header,0);
2184 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2185 END_PROFILE(SMBreadbraw);
2189 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2190 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2192 /* ensure we don't overrun the packet size */
2193 maxcount = MIN(65535,maxcount);
2194 maxcount = MAX(mincount,maxcount);
2196 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False))
2198 SMB_OFF_T size = fsp->size;
2199 SMB_OFF_T sizeneeded = startpos + maxcount;
2201 if (size < sizeneeded)
2204 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2206 if (!fsp->can_write)
2210 nread = MIN(maxcount,(size - startpos));
2213 if (nread < mincount)
2216 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2217 fsp->fnum, (double)startpos,
2218 (int)maxcount, (int)mincount, (int)nread ) );
2222 BOOL seek_fail = False;
2224 _smb_setlen(header,nread);
2226 if ((nread-predict) > 0) {
2227 if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
2228 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2235 ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
2236 (SMB_OFF_T)(nread-predict),header,4+predict,
2241 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2242 fsp->fsp_name,startpos,nread,ret));
2244 #else /* UNSAFE_READRAW */
2245 ret = read_file(fsp,header+4,startpos,nread);
2246 if (ret < mincount) ret = 0;
2248 _smb_setlen(header,ret);
2249 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2250 #endif /* UNSAFE_READRAW */
2252 DEBUG(5,("readbraw finished\n"));
2253 END_PROFILE(SMBreadbraw);
2258 /****************************************************************************
2259 reply to a lockread (core+ protocol)
2260 ****************************************************************************/
2261 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2270 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2271 START_PROFILE(SMBlockread);
2273 CHECK_FSP(fsp,conn);
2277 release_level_2_oplocks_on_change(fsp);
2279 numtoread = SVAL(inbuf,smb_vwv1);
2280 startpos = IVAL(inbuf,smb_vwv2);
2282 outsize = set_message(outbuf,5,3,True);
2283 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2284 data = smb_buf(outbuf) + 3;
2287 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2288 * protocol request that predates the read/write lock concept.
2289 * Thus instead of asking for a read lock here we need to ask
2290 * for a write lock. JRA.
2293 if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2294 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2296 * A blocking lock was requested. Package up
2297 * this smb into a queued request and push it
2298 * onto the blocking lock queue.
2300 if(push_blocking_lock_request(inbuf, length, -1, 0))
2301 END_PROFILE(SMBlockread);
2304 END_PROFILE(SMBlockread);
2305 return (ERROR(eclass,ecode));
2308 nread = read_file(fsp,data,startpos,numtoread);
2311 END_PROFILE(SMBlockread);
2312 return(UNIXERROR(ERRDOS,ERRnoaccess));
2316 SSVAL(outbuf,smb_vwv0,nread);
2317 SSVAL(outbuf,smb_vwv5,nread+3);
2318 SSVAL(smb_buf(outbuf),1,nread);
2320 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2321 fsp->fnum, (int)numtoread, (int)nread ) );
2323 END_PROFILE(SMBlockread);
2328 /****************************************************************************
2330 ****************************************************************************/
2332 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2339 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2340 START_PROFILE(SMBread);
2342 CHECK_FSP(fsp,conn);
2346 numtoread = SVAL(inbuf,smb_vwv1);
2347 startpos = IVAL(inbuf,smb_vwv2);
2349 outsize = set_message(outbuf,5,3,True);
2350 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2351 data = smb_buf(outbuf) + 3;
2353 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2354 END_PROFILE(SMBread);
2355 return(ERROR(ERRDOS,ERRlock));
2359 nread = read_file(fsp,data,startpos,numtoread);
2362 END_PROFILE(SMBread);
2363 return(UNIXERROR(ERRDOS,ERRnoaccess));
2367 SSVAL(outbuf,smb_vwv0,nread);
2368 SSVAL(outbuf,smb_vwv5,nread+3);
2369 CVAL(smb_buf(outbuf),0) = 1;
2370 SSVAL(smb_buf(outbuf),1,nread);
2372 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2373 fsp->fnum, (int)numtoread, (int)nread ) );
2375 END_PROFILE(SMBread);
2380 /****************************************************************************
2381 reply to a read and X
2382 ****************************************************************************/
2383 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2385 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2386 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2387 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2388 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2391 START_PROFILE(SMBreadX);
2393 /* If it's an IPC, pass off the pipe handler. */
2395 END_PROFILE(SMBreadX);
2396 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2399 CHECK_FSP(fsp,conn);
2403 set_message(outbuf,12,0,True);
2404 data = smb_buf(outbuf);
2406 if(CVAL(inbuf,smb_wct) == 12) {
2407 #ifdef LARGE_SMB_OFF_T
2409 * This is a large offset (64 bit) read.
2411 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2413 #else /* !LARGE_SMB_OFF_T */
2416 * Ensure we haven't been sent a >32 bit offset.
2419 if(IVAL(inbuf,smb_vwv10) != 0) {
2420 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2421 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2422 END_PROFILE(SMBreadX);
2423 return(ERROR(ERRDOS,ERRbadaccess));
2426 #endif /* LARGE_SMB_OFF_T */
2430 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2431 END_PROFILE(SMBreadX);
2432 return(ERROR(ERRDOS,ERRlock));
2434 nread = read_file(fsp,data,startpos,smb_maxcnt);
2437 END_PROFILE(SMBreadX);
2438 return(UNIXERROR(ERRDOS,ERRnoaccess));
2441 SSVAL(outbuf,smb_vwv5,nread);
2442 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2443 SSVAL(smb_buf(outbuf),-2,nread);
2445 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2446 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2448 END_PROFILE(SMBreadX);
2449 return chain_reply(inbuf,outbuf,length,bufsize);
2452 /****************************************************************************
2453 reply to a writebraw (core+ or LANMAN1.0 protocol)
2454 ****************************************************************************/
2456 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2459 ssize_t total_written=0;
2460 size_t numtowrite=0;
2465 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2467 START_PROFILE(SMBwritebraw);
2469 CHECK_FSP(fsp,conn);
2473 tcount = IVAL(inbuf,smb_vwv1);
2474 startpos = IVAL(inbuf,smb_vwv3);
2475 write_through = BITSETW(inbuf+smb_vwv7,0);
2477 /* We have to deal with slightly different formats depending
2478 on whether we are using the core+ or lanman1.0 protocol */
2479 if(Protocol <= PROTOCOL_COREPLUS) {
2480 numtowrite = SVAL(smb_buf(inbuf),-2);
2481 data = smb_buf(inbuf);
2483 numtowrite = SVAL(inbuf,smb_vwv10);
2484 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2487 /* force the error type */
2488 CVAL(inbuf,smb_com) = SMBwritec;
2489 CVAL(outbuf,smb_com) = SMBwritec;
2491 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2492 END_PROFILE(SMBwritebraw);
2493 return(ERROR(ERRDOS,ERRlock));
2497 nwritten = write_file(fsp,data,startpos,numtowrite);
2499 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2500 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2502 if (nwritten < numtowrite) {
2503 END_PROFILE(SMBwritebraw);
2504 return(UNIXERROR(ERRHRD,ERRdiskfull));
2507 total_written = nwritten;
2509 /* Return a message to the redirector to tell it
2510 to send more bytes */
2511 CVAL(outbuf,smb_com) = SMBwritebraw;
2512 SSVALS(outbuf,smb_vwv0,-1);
2513 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2514 if (!send_smb(smbd_server_fd(),outbuf))
2515 exit_server("reply_writebraw: send_smb failed.\n");
2517 /* Now read the raw data into the buffer and write it */
2518 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2519 exit_server("secondary writebraw failed");
2522 /* Even though this is not an smb message, smb_len
2523 returns the generic length of an smb message */
2524 numtowrite = smb_len(inbuf);
2526 if (tcount > nwritten+numtowrite) {
2527 DEBUG(3,("Client overestimated the write %d %d %d\n",
2528 (int)tcount,(int)nwritten,(int)numtowrite));
2531 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2532 (SMB_OFF_T)numtowrite,NULL,0,
2534 total_written += nwritten;
2536 /* Set up outbuf to return the correct return */
2537 outsize = set_message(outbuf,1,0,True);
2538 CVAL(outbuf,smb_com) = SMBwritec;
2539 SSVAL(outbuf,smb_vwv0,total_written);
2541 if (nwritten < (ssize_t)numtowrite) {
2542 CVAL(outbuf,smb_rcls) = ERRHRD;
2543 SSVAL(outbuf,smb_err,ERRdiskfull);
2546 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2547 lp_strict_sync(SNUM(conn)))
2548 sync_file(conn,fsp);
2550 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2551 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2553 /* we won't return a status if write through is not selected - this
2554 follows what WfWg does */
2555 END_PROFILE(SMBwritebraw);
2556 if (!write_through && total_written==tcount) {
2563 /****************************************************************************
2564 reply to a writeunlock (core+)
2565 ****************************************************************************/
2567 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2569 ssize_t nwritten = -1;
2575 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2577 START_PROFILE(SMBwriteunlock);
2579 CHECK_FSP(fsp,conn);
2583 numtowrite = SVAL(inbuf,smb_vwv1);
2584 startpos = IVAL(inbuf,smb_vwv2);
2585 data = smb_buf(inbuf) + 3;
2587 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2588 END_PROFILE(SMBwriteunlock);
2589 return(ERROR(ERRDOS,ERRlock));
2592 /* The special X/Open SMB protocol handling of
2593 zero length writes is *NOT* done for
2598 nwritten = write_file(fsp,data,startpos,numtowrite);
2600 if (lp_syncalways(SNUM(conn)))
2601 sync_file(conn,fsp);
2603 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2604 END_PROFILE(SMBwriteunlock);
2605 return(UNIXERROR(ERRDOS,ERRnoaccess));
2608 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) {
2609 END_PROFILE(SMBwriteunlock);
2610 return(ERROR(eclass,ecode));
2613 outsize = set_message(outbuf,1,0,True);
2615 SSVAL(outbuf,smb_vwv0,nwritten);
2617 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2618 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2620 END_PROFILE(SMBwriteunlock);
2624 /****************************************************************************
2626 ****************************************************************************/
2627 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2630 ssize_t nwritten = -1;
2633 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2635 START_PROFILE(SMBwrite);
2637 /* If it's an IPC, pass off the pipe handler. */
2639 END_PROFILE(SMBwrite);
2640 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2643 CHECK_FSP(fsp,conn);
2647 numtowrite = SVAL(inbuf,smb_vwv1);
2648 startpos = IVAL(inbuf,smb_vwv2);
2649 data = smb_buf(inbuf) + 3;
2651 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2652 END_PROFILE(SMBwrite);
2653 return(ERROR(ERRDOS,ERRlock));
2656 /* X/Open SMB protocol says that if smb_vwv1 is
2657 zero then the file size should be extended or
2658 truncated to the size given in smb_vwv[2-3] */
2659 if(numtowrite == 0) {
2660 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2662 nwritten = write_file(fsp,data,startpos,numtowrite);
2664 if (lp_syncalways(SNUM(conn)))
2665 sync_file(conn,fsp);
2667 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2668 END_PROFILE(SMBwrite);
2669 return(UNIXERROR(ERRDOS,ERRnoaccess));
2672 outsize = set_message(outbuf,1,0,True);
2674 SSVAL(outbuf,smb_vwv0,nwritten);
2676 if (nwritten < (ssize_t)numtowrite) {
2677 CVAL(outbuf,smb_rcls) = ERRHRD;
2678 SSVAL(outbuf,smb_err,ERRdiskfull);
2681 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2682 fsp->fnum, (int)numtowrite, (int)nwritten));
2684 END_PROFILE(SMBwrite);
2689 /****************************************************************************
2690 reply to a write and X
2691 ****************************************************************************/
2692 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2694 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2695 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2696 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2697 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2698 ssize_t nwritten = -1;
2699 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2700 unsigned int smblen = smb_len(inbuf);
2702 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2703 START_PROFILE(SMBwriteX);
2705 /* If it's an IPC, pass off the pipe handler. */
2707 END_PROFILE(SMBwriteX);
2708 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2711 CHECK_FSP(fsp,conn);
2715 /* Deal with possible LARGE_WRITEX */
2717 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2719 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2720 END_PROFILE(SMBwriteX);
2721 return(ERROR(ERRDOS,ERRbadmem));
2724 data = smb_base(inbuf) + smb_doff;
2726 if(CVAL(inbuf,smb_wct) == 14) {
2727 #ifdef LARGE_SMB_OFF_T
2729 * This is a large offset (64 bit) write.
2731 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2733 #else /* !LARGE_SMB_OFF_T */
2736 * Ensure we haven't been sent a >32 bit offset.
2739 if(IVAL(inbuf,smb_vwv12) != 0) {
2740 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2741 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2742 END_PROFILE(SMBwriteX);
2743 return(ERROR(ERRDOS,ERRbadaccess));
2746 #endif /* LARGE_SMB_OFF_T */
2749 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2750 END_PROFILE(SMBwriteX);
2751 return(ERROR(ERRDOS,ERRlock));
2754 /* X/Open SMB protocol says that, unlike SMBwrite
2755 if the length is zero then NO truncation is
2756 done, just a write of zero. To truncate a file,
2761 nwritten = write_file(fsp,data,startpos,numtowrite);
2763 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2764 END_PROFILE(SMBwriteX);
2765 return(UNIXERROR(ERRDOS,ERRnoaccess));
2768 set_message(outbuf,6,0,True);
2770 SSVAL(outbuf,smb_vwv2,nwritten);
2772 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2774 if (nwritten < (ssize_t)numtowrite) {
2775 CVAL(outbuf,smb_rcls) = ERRHRD;
2776 SSVAL(outbuf,smb_err,ERRdiskfull);
2779 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2780 fsp->fnum, (int)numtowrite, (int)nwritten));
2782 if (lp_syncalways(SNUM(conn)) || write_through)
2783 sync_file(conn,fsp);
2785 END_PROFILE(SMBwriteX);
2786 return chain_reply(inbuf,outbuf,length,bufsize);
2790 /****************************************************************************
2792 ****************************************************************************/
2794 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2800 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2801 START_PROFILE(SMBlseek);
2803 CHECK_FSP(fsp,conn);
2806 flush_write_cache(fsp, SEEK_FLUSH);
2808 mode = SVAL(inbuf,smb_vwv1) & 3;
2809 startpos = IVALS(inbuf,smb_vwv2);
2812 case 0: umode = SEEK_SET; break;
2813 case 1: umode = SEEK_CUR; break;
2814 case 2: umode = SEEK_END; break;
2816 umode = SEEK_SET; break;
2819 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2821 * Check for the special case where a seek before the start
2822 * of the file sets the offset to zero. Added in the CIFS spec,
2826 if(errno == EINVAL) {
2827 SMB_OFF_T current_pos = startpos;
2829 if(umode == SEEK_CUR) {
2831 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2832 END_PROFILE(SMBlseek);
2833 return(UNIXERROR(ERRDOS,ERRnoaccess));
2836 current_pos += startpos;
2838 } else if (umode == SEEK_END) {
2840 SMB_STRUCT_STAT sbuf;
2842 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2843 END_PROFILE(SMBlseek);
2844 return(UNIXERROR(ERRDOS,ERRnoaccess));
2847 current_pos += sbuf.st_size;
2851 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2855 END_PROFILE(SMBlseek);
2856 return(UNIXERROR(ERRDOS,ERRnoaccess));
2862 outsize = set_message(outbuf,2,0,True);
2863 SIVAL(outbuf,smb_vwv0,res);
2865 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2866 fsp->fnum, (double)startpos, (double)res, mode));
2868 END_PROFILE(SMBlseek);
2872 /****************************************************************************
2874 ****************************************************************************/
2876 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2878 int outsize = set_message(outbuf,0,0,True);
2879 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2880 START_PROFILE(SMBflush);
2883 CHECK_FSP(fsp,conn);
2888 file_sync_all(conn);
2890 sync_file(conn,fsp);
2893 DEBUG(3,("flush\n"));
2894 END_PROFILE(SMBflush);
2899 /****************************************************************************
2901 ****************************************************************************/
2902 int reply_exit(connection_struct *conn,
2903 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2906 START_PROFILE(SMBexit);
2907 outsize = set_message(outbuf,0,0,True);
2909 DEBUG(3,("exit\n"));
2911 END_PROFILE(SMBexit);
2916 /****************************************************************************
2917 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2918 ****************************************************************************/
2919 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2924 int32 eclass = 0, err = 0;
2925 files_struct *fsp = NULL;
2926 START_PROFILE(SMBclose);
2928 outsize = set_message(outbuf,0,0,True);
2930 /* If it's an IPC, pass off to the pipe handler. */
2932 END_PROFILE(SMBclose);
2933 return reply_pipe_close(conn, inbuf,outbuf);
2936 fsp = file_fsp(inbuf,smb_vwv0);
2939 * We can only use CHECK_FSP if we know it's not a directory.
2942 if(!fsp || (fsp->conn != conn)) {
2943 END_PROFILE(SMBclose);
2944 return(ERROR(ERRDOS,ERRbadfid));
2947 if(HAS_CACHED_ERROR(fsp)) {
2948 eclass = fsp->wbmpx_ptr->wr_errclass;
2949 err = fsp->wbmpx_ptr->wr_error;
2952 if(fsp->is_directory || fsp->stat_open) {
2954 * Special case - close NT SMB directory or stat file
2957 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2958 close_file(fsp,True);
2961 * Close ordinary file.
2966 * If there was a modify time outstanding,
2967 * try and set it here.
2969 if(fsp->pending_modtime)
2970 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2973 * Now take care of any time sent in the close.
2975 mtime = make_unix_date3(inbuf+smb_vwv1);
2977 /* try and set the date */
2978 set_filetime(conn, fsp->fsp_name,mtime);
2980 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2982 conn->num_files_open));
2985 * close_file() returns the unix errno if an error
2986 * was detected on close - normally this is due to
2987 * a disk full error. If not then it was probably an I/O error.
2990 if((close_err = close_file(fsp,True)) != 0) {
2992 END_PROFILE(SMBclose);
2993 return (UNIXERROR(ERRHRD,ERRgeneral));
2997 /* We have a cached error */
2999 END_PROFILE(SMBclose);
3000 return(ERROR(eclass,err));
3003 END_PROFILE(SMBclose);
3008 /****************************************************************************
3009 reply to a writeclose (Core+ protocol)
3010 ****************************************************************************/
3012 int reply_writeclose(connection_struct *conn,
3013 char *inbuf,char *outbuf, int size, int dum_buffsize)
3016 ssize_t nwritten = -1;
3022 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3023 START_PROFILE(SMBwriteclose);
3025 CHECK_FSP(fsp,conn);
3029 numtowrite = SVAL(inbuf,smb_vwv1);
3030 startpos = IVAL(inbuf,smb_vwv2);
3031 mtime = make_unix_date3(inbuf+smb_vwv4);
3032 data = smb_buf(inbuf) + 1;
3034 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
3035 END_PROFILE(SMBwriteclose);
3036 return(ERROR(ERRDOS,ERRlock));
3039 nwritten = write_file(fsp,data,startpos,numtowrite);
3041 set_filetime(conn, fsp->fsp_name,mtime);
3043 close_err = close_file(fsp,True);
3045 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3046 fsp->fnum, (int)numtowrite, (int)nwritten,
3047 conn->num_files_open));
3049 if (nwritten <= 0) {
3050 END_PROFILE(SMBwriteclose);
3051 return(UNIXERROR(ERRDOS,ERRnoaccess));
3054 if(close_err != 0) {
3056 END_PROFILE(SMBwriteclose);
3057 return(UNIXERROR(ERRHRD,ERRgeneral));
3060 outsize = set_message(outbuf,1,0,True);
3062 SSVAL(outbuf,smb_vwv0,nwritten);
3063 END_PROFILE(SMBwriteclose);
3068 /****************************************************************************
3070 ****************************************************************************/
3071 int reply_lock(connection_struct *conn,
3072 char *inbuf,char *outbuf, int length, int dum_buffsize)
3074 int outsize = set_message(outbuf,0,0,True);
3075 SMB_BIG_UINT count,offset;
3078 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3079 START_PROFILE(SMBlock);
3081 CHECK_FSP(fsp,conn);
3084 release_level_2_oplocks_on_change(fsp);
3086 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3087 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3089 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3090 fsp->fd, fsp->fnum, (double)offset, (double)count));
3092 if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &eclass, &ecode)) {
3093 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
3095 * A blocking lock was requested. Package up
3096 * this smb into a queued request and push it
3097 * onto the blocking lock queue.
3099 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
3100 END_PROFILE(SMBlock);
3104 END_PROFILE(SMBlock);
3105 return (ERROR(eclass,ecode));
3108 END_PROFILE(SMBlock);
3113 /****************************************************************************
3115 ****************************************************************************/
3116 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3118 int outsize = set_message(outbuf,0,0,True);
3119 SMB_BIG_UINT count,offset;
3122 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3123 START_PROFILE(SMBunlock);
3125 CHECK_FSP(fsp,conn);
3128 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3129 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3131 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, &eclass, &ecode)) {
3132 END_PROFILE(SMBunlock);
3133 return (ERROR(eclass,ecode));
3136 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3137 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3139 END_PROFILE(SMBunlock);
3144 /****************************************************************************
3146 ****************************************************************************/
3147 int reply_tdis(connection_struct *conn,
3148 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3150 int outsize = set_message(outbuf,0,0,True);
3152 START_PROFILE(SMBtdis);
3154 vuid = SVAL(inbuf,smb_uid);
3157 DEBUG(4,("Invalid connection in tdis\n"));
3158 END_PROFILE(SMBtdis);
3159 return(ERROR(ERRSRV,ERRinvnid));
3164 close_cnum(conn,vuid);
3166 END_PROFILE(SMBtdis);
3172 /****************************************************************************
3174 ****************************************************************************/
3175 int reply_echo(connection_struct *conn,
3176 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3178 int smb_reverb = SVAL(inbuf,smb_vwv0);
3180 unsigned int data_len = smb_buflen(inbuf);
3181 int outsize = set_message(outbuf,1,data_len,True);
3182 START_PROFILE(SMBecho);
3184 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3186 /* copy any incoming data back out */
3188 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3190 if (smb_reverb > 100) {
3191 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3195 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3196 SSVAL(outbuf,smb_vwv0,seq_num);
3198 smb_setlen(outbuf,outsize - 4);
3200 if (!send_smb(smbd_server_fd(),outbuf))
3201 exit_server("reply_echo: send_smb failed.\n");
3204 DEBUG(3,("echo %d times\n", smb_reverb));
3208 END_PROFILE(SMBecho);
3213 /****************************************************************************
3214 reply to a printopen
3215 ****************************************************************************/
3216 int reply_printopen(connection_struct *conn,
3217 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3221 START_PROFILE(SMBsplopen);
3223 if (!CAN_PRINT(conn)) {
3224 END_PROFILE(SMBsplopen);
3225 return(ERROR(ERRDOS,ERRnoaccess));
3228 /* Open for exclusive use, write only. */
3229 fsp = print_fsp_open(conn);
3232 END_PROFILE(SMBsplopen);
3233 return(UNIXERROR(ERRDOS,ERRnoaccess));
3236 outsize = set_message(outbuf,1,0,True);
3237 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3239 DEBUG(3,("openprint fd=%d fnum=%d\n",
3240 fsp->fd, fsp->fnum));
3242 END_PROFILE(SMBsplopen);
3247 /****************************************************************************
3248 reply to a printclose
3249 ****************************************************************************/
3250 int reply_printclose(connection_struct *conn,
3251 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3253 int outsize = set_message(outbuf,0,0,True);
3254 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3256 START_PROFILE(SMBsplclose);
3258 CHECK_FSP(fsp,conn);
3261 if (!CAN_PRINT(conn)) {
3262 END_PROFILE(SMBsplclose);
3263 return(ERROR(ERRDOS,ERRnoaccess));
3266 DEBUG(3,("printclose fd=%d fnum=%d\n",
3267 fsp->fd,fsp->fnum));
3269 close_err = close_file(fsp,True);
3271 if(close_err != 0) {
3273 END_PROFILE(SMBsplclose);
3274 return(UNIXERROR(ERRHRD,ERRgeneral));
3277 END_PROFILE(SMBsplclose);
3282 /****************************************************************************
3283 reply to a printqueue
3284 ****************************************************************************/
3285 int reply_printqueue(connection_struct *conn,
3286 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3288 int outsize = set_message(outbuf,2,3,True);
3289 int max_count = SVAL(inbuf,smb_vwv0);
3290 int start_index = SVAL(inbuf,smb_vwv1);
3291 START_PROFILE(SMBsplretq);
3293 /* we used to allow the client to get the cnum wrong, but that
3294 is really quite gross and only worked when there was only
3295 one printer - I think we should now only accept it if they
3296 get it right (tridge) */
3297 if (!CAN_PRINT(conn)) {
3298 END_PROFILE(SMBsplretq);
3299 return(ERROR(ERRDOS,ERRnoaccess));
3302 SSVAL(outbuf,smb_vwv0,0);
3303 SSVAL(outbuf,smb_vwv1,0);
3304 CVAL(smb_buf(outbuf),0) = 1;
3305 SSVAL(smb_buf(outbuf),1,0);
3307 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3308 start_index, max_count));
3311 print_queue_struct *queue = NULL;
3312 char *p = smb_buf(outbuf) + 3;
3313 int count = print_queue_status(SNUM(conn), &queue,NULL);
3314 int num_to_get = ABS(max_count);
3315 int first = (max_count>0?start_index:start_index+max_count+1);
3321 num_to_get = MIN(num_to_get,count-first);
3324 for (i=first;i<first+num_to_get;i++) {
3325 put_dos_date2(p,0,queue[i].time);
3326 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3327 SSVAL(p,5, queue[i].job);
3328 SIVAL(p,7,queue[i].size);
3330 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_CONVERT|STR_ASCII);
3335 outsize = set_message(outbuf,2,28*count+3,False);
3336 SSVAL(outbuf,smb_vwv0,count);
3337 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3338 CVAL(smb_buf(outbuf),0) = 1;
3339 SSVAL(smb_buf(outbuf),1,28*count);
3342 if (queue) free(queue);
3344 DEBUG(3,("%d entries returned in queue\n",count));
3347 END_PROFILE(SMBsplretq);
3352 /****************************************************************************
3353 reply to a printwrite
3354 ****************************************************************************/
3355 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3358 int outsize = set_message(outbuf,0,0,True);
3360 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3361 START_PROFILE(SMBsplwr);
3363 if (!CAN_PRINT(conn)) {
3364 END_PROFILE(SMBsplwr);
3365 return(ERROR(ERRDOS,ERRnoaccess));
3368 CHECK_FSP(fsp,conn);
3372 numtowrite = SVAL(smb_buf(inbuf),1);
3373 data = smb_buf(inbuf) + 3;
3375 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3376 END_PROFILE(SMBsplwr);
3377 return(UNIXERROR(ERRDOS,ERRnoaccess));
3380 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3382 END_PROFILE(SMBsplwr);
3387 /****************************************************************************
3388 The guts of the mkdir command, split out so it may be called by the NT SMB
3390 ****************************************************************************/
3391 int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
3393 BOOL bad_path = False;
3394 SMB_STRUCT_STAT sbuf;
3397 unix_convert(directory,conn,0,&bad_path,&sbuf);
3399 if (check_name(directory, conn))
3400 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3404 if((errno == ENOENT) && bad_path)
3406 unix_ERR_class = ERRDOS;
3407 unix_ERR_code = ERRbadpath;
3409 return(UNIXERROR(ERRDOS,ERRnoaccess));
3415 /****************************************************************************
3417 ****************************************************************************/
3418 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3422 START_PROFILE(SMBmkdir);
3424 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3426 outsize=mkdir_internal(conn, inbuf, outbuf, directory);
3428 outsize = set_message(outbuf,0,0,True);
3430 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3432 END_PROFILE(SMBmkdir);
3436 /****************************************************************************
3437 Static function used by reply_rmdir to delete an entire directory
3439 ****************************************************************************/
3441 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3445 void *dirptr = OpenDir(NULL, directory, False);
3450 while((dname = ReadDirName(dirptr)))
3455 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3458 /* Construct the full name. */
3459 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3465 pstrcpy(fullname, directory);
3466 pstrcat(fullname, "/");
3467 pstrcat(fullname, dname);
3469 if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname,False), &st) != 0)
3475 if(st.st_mode & S_IFDIR)
3477 if(recursive_rmdir(conn, fullname)!=0)
3482 if(vfs_rmdir(conn,fullname) != 0)
3488 else if(vfs_unlink(conn,fullname) != 0)
3498 /****************************************************************************
3499 The internals of the rmdir code - called elsewhere.
3500 ****************************************************************************/
3502 BOOL rmdir_internals(connection_struct *conn, char *directory)
3506 ok = (vfs_rmdir(conn,directory) == 0);
3507 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3510 * Check to see if the only thing in this directory are
3511 * vetoed files/directories. If so then delete them and
3512 * retry. If we fail to delete any of them (and we *don't*
3513 * do a recursive delete) then fail the rmdir.
3515 BOOL all_veto_files = True;
3517 void *dirptr = OpenDir(conn, directory, False);
3521 int dirpos = TellDir(dirptr);
3522 while ((dname = ReadDirName(dirptr)))
3524 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3526 if(!IS_VETO_PATH(conn, dname))
3528 all_veto_files = False;
3534 SeekDir(dirptr,dirpos);
3535 while ((dname = ReadDirName(dirptr)))
3540 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3543 /* Construct the full name. */
3544 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3549 pstrcpy(fullname, directory);
3550 pstrcat(fullname, "/");
3551 pstrcat(fullname, dname);
3553 if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname, False), &st) != 0)
3555 if(st.st_mode & S_IFDIR)
3557 if(lp_recursive_veto_delete(SNUM(conn)))
3559 if(recursive_rmdir(conn, fullname) != 0)
3562 if(vfs_rmdir(conn,fullname) != 0)
3565 else if(vfs_unlink(conn,fullname) != 0)
3569 /* Retry the rmdir */
3570 ok = (vfs_rmdir(conn,directory) == 0);
3580 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3581 directory,strerror(errno)));
3586 /****************************************************************************
3588 ****************************************************************************/
3590 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3595 BOOL bad_path = False;
3596 SMB_STRUCT_STAT sbuf;
3597 START_PROFILE(SMBrmdir);
3599 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3601 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3603 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3605 if (check_name(directory,conn))
3607 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3608 ok = rmdir_internals(conn, directory);
3613 if((errno == ENOENT) && bad_path)
3615 unix_ERR_class = ERRDOS;
3616 unix_ERR_code = ERRbadpath;
3618 END_PROFILE(SMBrmdir);
3619 return(UNIXERROR(ERRDOS,ERRbadpath));
3622 outsize = set_message(outbuf,0,0,True);
3624 DEBUG( 3, ( "rmdir %s\n", directory ) );
3626 END_PROFILE(SMBrmdir);
3631 /*******************************************************************
3632 resolve wildcards in a filename rename
3633 ********************************************************************/
3634 static BOOL resolve_wildcards(char *name1,char *name2)
3636 fstring root1,root2;
3640 name1 = strrchr(name1,'/');
3641 name2 = strrchr(name2,'/');
3643 if (!name1 || !name2) return(False);
3645 fstrcpy(root1,name1);
3646 fstrcpy(root2,name2);
3647 p = strrchr(root1,'.');
3654 p = strrchr(root2,'.');
3686 pstrcpy(name2,root2);
3689 pstrcat(name2,ext2);
3695 /*******************************************************************
3696 check if a user is allowed to rename a file
3697 ********************************************************************/
3698 static BOOL can_rename(char *fname,connection_struct *conn)
3700 SMB_STRUCT_STAT sbuf;
3702 if (!CAN_WRITE(conn)) return(False);
3704 if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False);
3705 if (!check_file_sharing(conn,fname,True)) return(False);
3709 /****************************************************************************
3710 The guts of the rename command, split out so it may be called by the NT SMB
3712 ****************************************************************************/
3713 int rename_internals(connection_struct *conn,
3714 char *inbuf, char *outbuf, char *name,
3715 char *newname, BOOL replace_if_exists)
3719 pstring newname_last_component;
3722 BOOL bad_path1 = False;
3723 BOOL bad_path2 = False;
3725 int error = ERRnoaccess;
3728 SMB_STRUCT_STAT sbuf1, sbuf2;
3731 *directory = *mask = 0;
3733 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3734 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3737 * Split the old name into directory and last component
3738 * strings. Note that unix_convert may have stripped off a
3739 * leading ./ from both name and newname if the rename is
3740 * at the root of the share. We need to make sure either both
3741 * name and newname contain a / character or neither of them do
3742 * as this is checked in resolve_wildcards().
3745 p = strrchr(name,'/');
3747 pstrcpy(directory,".");
3751 pstrcpy(directory,name);
3753 *p = '/'; /* Replace needed for exceptional test below. */
3757 * We should only check the mangled cache
3758 * here if unix_convert failed. This means
3759 * that the path in 'mask' doesn't exist
3760 * on the file system and so we need to look
3761 * for a possible mangle. This patch from
3762 * Tine Smukavec <valentin.smukavec@hermes.si>.
3765 if (!rc && is_mangled(mask))
3766 check_mangled_cache( mask );
3768 has_wild = ms_has_wild(mask);
3772 * No wildcards - just process the one file.
3774 BOOL is_short_name = is_8_3(name, True);
3776 /* Add a terminating '/' to the directory name. */
3777 pstrcat(directory,"/");
3778 pstrcat(directory,mask);
3780 /* Ensure newname contains a '/' also */
3781 if(strrchr(newname,'/') == 0) {
3784 pstrcpy(tmpstr, "./");
3785 pstrcat(tmpstr, newname);
3786 pstrcpy(newname, tmpstr);
3789 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3790 case_sensitive, case_preserve, short_case_preserve, directory,
3791 newname, newname_last_component, is_short_name));
3794 * Check for special case with case preserving and not
3795 * case sensitive, if directory and newname are identical,
3796 * and the old last component differs from the original
3797 * last component only by case, then we should allow
3798 * the rename (user is trying to change the case of the
3801 if((case_sensitive == False) &&
3802 (((case_preserve == True) &&
3803 (is_short_name == False)) ||
3804 ((short_case_preserve == True) &&
3805 (is_short_name == True))) &&
3806 strcsequal(directory, newname)) {
3807 pstring newname_modified_last_component;
3810 * Get the last component of the modified name.
3811 * Note that we guarantee that newname contains a '/'
3814 p = strrchr(newname,'/');
3815 pstrcpy(newname_modified_last_component,p+1);
3817 if(strcsequal(newname_modified_last_component,
3818 newname_last_component) == False) {
3820 * Replace the modified last component with
3823 pstrcpy(p+1, newname_last_component);
3827 pstrcpy(zdirectory, dos_to_unix(directory, False));
3828 if(replace_if_exists) {
3830 * NT SMB specific flag - rename can overwrite
3831 * file with the same name so don't check for
3835 if(resolve_wildcards(directory,newname) &&
3836 can_rename(directory,conn) &&
3837 !conn->vfs_ops.rename(conn,zdirectory,
3838 dos_to_unix(newname,False)))
3841 if (resolve_wildcards(directory,newname) &&
3842 can_rename(directory,conn) &&
3843 !vfs_file_exist(conn,newname,NULL) &&
3844 !conn->vfs_ops.rename(conn,zdirectory,
3845 dos_to_unix(newname,False)))
3849 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3850 directory,newname));
3852 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3853 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3859 * Wildcards - process each file that matches.
3861 void *dirptr = NULL;
3865 if (check_name(directory,conn))
3866 dirptr = OpenDir(conn, directory, True);
3871 if (strequal(mask,"????????.???"))
3874 while ((dname = ReadDirName(dirptr))) {
3877 pstrcpy(fname,dname);
3879 if(!mask_match(fname, mask, case_sensitive))
3882 error = ERRnoaccess;
3883 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3884 if (!can_rename(fname,conn)) {
3885 DEBUG(6,("rename %s refused\n", fname));
3888 pstrcpy(destname,newname);
3890 if (!resolve_wildcards(fname,destname)) {
3891 DEBUG(6,("resolve_wildcards %s %s failed\n",
3896 if (!replace_if_exists &&
3897 vfs_file_exist(conn,destname, NULL)) {
3898 DEBUG(6,("file_exist %s\n", destname));
3903 if (!conn->vfs_ops.rename(conn,dos_to_unix(fname,False),
3904 dos_to_unix(destname,False)))
3906 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3914 return(ERROR(ERRDOS,error));
3916 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3917 unix_ERR_class = ERRDOS;
3918 unix_ERR_code = ERRbadpath;
3920 return(UNIXERROR(ERRDOS,error));
3927 /****************************************************************************
3929 ****************************************************************************/
3931 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3938 START_PROFILE(SMBmv);
3940 p = smb_buf(inbuf) + 1;
3941 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3943 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3945 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3946 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3948 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3950 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3954 * Win2k needs a changenotify request response before it will
3955 * update after a rename..
3958 process_pending_change_notify_queue((time_t)0);
3960 outsize = set_message(outbuf,0,0,True);
3967 /*******************************************************************
3968 copy a file as part of a reply_copy
3969 ******************************************************************/
3971 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3972 int count,BOOL target_is_directory, int *err_ret)
3975 SMB_STRUCT_STAT src_sbuf, sbuf2;
3977 files_struct *fsp1,*fsp2;
3982 pstrcpy(dest,dest1);
3983 if (target_is_directory) {
3984 char *p = strrchr(src,'/');
3993 if (!vfs_file_exist(conn,src,&src_sbuf))
3996 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3997 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
4003 if (!target_is_directory && count)
4004 ofun = FILE_EXISTS_OPEN;
4006 vfs_stat(conn,dest,&sbuf2);
4007 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4008 ofun,src_sbuf.st_mode,0,&Access,&action);
4011 close_file(fsp1,False);
4015 if ((ofun&3) == 1) {
4016 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4017 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
4020 * Stop the copy from occurring.
4023 src_sbuf.st_size = 0;
4027 if (src_sbuf.st_size)
4028 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
4030 close_file(fsp1,False);
4032 * As we are opening fsp1 read-only we only expect
4033 * an error on close on fsp2 if we are out of space.
4034 * Thus we don't look at the error return from the
4037 *err_ret = close_file(fsp2,False);
4039 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4044 /****************************************************************************
4045 reply to a file copy.
4046 ****************************************************************************/
4047 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4052 pstring mask,newname;
4055 int error = ERRnoaccess;
4059 int tid2 = SVAL(inbuf,smb_vwv0);
4060 int ofun = SVAL(inbuf,smb_vwv1);
4061 int flags = SVAL(inbuf,smb_vwv2);
4062 BOOL target_is_directory=False;
4063 BOOL bad_path1 = False;
4064 BOOL bad_path2 = False;
4066 SMB_STRUCT_STAT sbuf1, sbuf2;
4067 START_PROFILE(SMBcopy);
4069 *directory = *mask = 0;
4072 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
4073 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
4075 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4077 if (tid2 != conn->cnum) {
4078 /* can't currently handle inter share copies XXXX */
4079 DEBUG(3,("Rejecting inter-share copy\n"));
4080 END_PROFILE(SMBcopy);
4081 return(ERROR(ERRSRV,ERRinvdevice));
4084 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4085 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4087 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4088 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4090 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4092 if ((flags&1) && target_is_directory) {
4093 END_PROFILE(SMBcopy);
4094 return(ERROR(ERRDOS,ERRbadfile));
4097 if ((flags&2) && !target_is_directory) {
4098 END_PROFILE(SMBcopy);
4099 return(ERROR(ERRDOS,ERRbadpath));
4102 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4103 /* wants a tree copy! XXXX */
4104 DEBUG(3,("Rejecting tree copy\n"));
4105 END_PROFILE(SMBcopy);
4106 return(ERROR(ERRSRV,ERRerror));
4109 p = strrchr(name,'/');
4111 pstrcpy(directory,"./");
4115 pstrcpy(directory,name);
4120 * We should only check the mangled cache
4121 * here if unix_convert failed. This means
4122 * that the path in 'mask' doesn't exist
4123 * on the file system and so we need to look
4124 * for a possible mangle. This patch from
4125 * Tine Smukavec <valentin.smukavec@hermes.si>.
4128 if (!rc && is_mangled(mask))
4129 check_mangled_cache( mask );
4131 has_wild = ms_has_wild(mask);
4134 pstrcat(directory,"/");
4135 pstrcat(directory,mask);
4136 if (resolve_wildcards(directory,newname) &&
4137 copy_file(directory,newname,conn,ofun,
4138 count,target_is_directory,&err)) count++;
4141 END_PROFILE(SMBcopy);
4142 return(UNIXERROR(ERRHRD,ERRgeneral));
4144 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4146 void *dirptr = NULL;
4150 if (check_name(directory,conn))
4151 dirptr = OpenDir(conn, directory, True);
4156 if (strequal(mask,"????????.???"))
4159 while ((dname = ReadDirName(dirptr))) {
4161 pstrcpy(fname,dname);
4163 if(!mask_match(fname, mask, case_sensitive))
4166 error = ERRnoaccess;
4167 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4168 pstrcpy(destname,newname);
4169 if (resolve_wildcards(fname,destname) &&
4170 copy_file(fname,destname,conn,ofun,
4171 count,target_is_directory,&err)) count++;
4172 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4180 /* Error on close... */
4182 END_PROFILE(SMBcopy);
4183 return(UNIXERROR(ERRHRD,ERRgeneral));
4187 END_PROFILE(SMBcopy);
4188 return(ERROR(ERRDOS,error));
4191 if((errno == ENOENT) && (bad_path1 || bad_path2))
4193 unix_ERR_class = ERRDOS;
4194 unix_ERR_code = ERRbadpath;
4196 END_PROFILE(SMBcopy);
4197 return(UNIXERROR(ERRDOS,error));
4201 outsize = set_message(outbuf,1,0,True);
4202 SSVAL(outbuf,smb_vwv0,count);
4204 END_PROFILE(SMBcopy);
4208 /****************************************************************************
4210 ****************************************************************************/
4211 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4217 START_PROFILE(pathworks_setdir);
4220 if (!CAN_SETDIR(snum)) {
4221 END_PROFILE(pathworks_setdir);
4222 return(ERROR(ERRDOS,ERRnoaccess));
4225 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE|STR_CONVERT);
4227 if (strlen(newdir) == 0) {
4230 ok = vfs_directory_exist(conn,newdir,NULL);
4232 string_set(&conn->connectpath,newdir);
4237 END_PROFILE(pathworks_setdir);
4238 return(ERROR(ERRDOS,ERRbadpath));
4241 outsize = set_message(outbuf,0,0,True);
4242 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4244 DEBUG(3,("setdir %s\n", newdir));
4246 END_PROFILE(pathworks_setdir);
4250 /****************************************************************************
4251 Get a lock pid, dealing with large count requests.
4252 ****************************************************************************/
4254 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4256 if(!large_file_format)
4257 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4259 return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
4262 /****************************************************************************
4263 Get a lock count, dealing with large count requests.
4264 ****************************************************************************/
4266 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4268 SMB_BIG_UINT count = 0;
4270 if(!large_file_format) {
4271 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4274 #if defined(HAVE_LONGLONG)
4275 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4276 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4277 #else /* HAVE_LONGLONG */
4280 * NT4.x seems to be broken in that it sends large file (64 bit)
4281 * lockingX calls even if the CAP_LARGE_FILES was *not*
4282 * negotiated. For boxes without large unsigned ints truncate the
4283 * lock count by dropping the top 32 bits.
4286 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4287 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4288 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4289 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4290 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4293 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4294 #endif /* HAVE_LONGLONG */
4300 /****************************************************************************
4301 Get a lock offset, dealing with large offset requests.
4302 ****************************************************************************/
4304 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4306 SMB_BIG_UINT offset = 0;
4310 if(!large_file_format) {
4311 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4314 #if defined(HAVE_LONGLONG)
4315 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4316 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4317 #else /* HAVE_LONGLONG */
4320 * NT4.x seems to be broken in that it sends large file (64 bit)
4321 * lockingX calls even if the CAP_LARGE_FILES was *not*
4322 * negotiated. For boxes without large unsigned ints mangle the
4323 * lock offset by mapping the top 32 bits onto the lower 32.
4326 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4327 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4328 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4331 if((new_low = map_lock_offset(high, low)) == 0) {
4333 return (SMB_BIG_UINT)-1;
4336 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4337 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4338 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4339 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4342 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4343 #endif /* HAVE_LONGLONG */
4349 /****************************************************************************
4350 reply to a lockingX request
4351 ****************************************************************************/
4353 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4355 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4356 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4357 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4358 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4359 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4360 SMB_BIG_UINT count = 0, offset = 0;
4362 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4365 uint32 ecode=0, dummy2;
4366 int eclass=0, dummy1;
4367 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4369 START_PROFILE(SMBlockingX);
4371 CHECK_FSP(fsp,conn);
4374 data = smb_buf(inbuf);
4376 /* Check if this is an oplock break on a file
4377 we have granted an oplock on.
4379 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4381 /* Client can insist on breaking to none. */
4382 BOOL break_to_none = (oplocklevel == 0);
4384 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4385 (unsigned int)oplocklevel, fsp->fnum ));
4388 * Make sure we have granted an exclusive or batch oplock on this file.
4391 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4393 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4394 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4396 /* if this is a pure oplock break request then don't send a reply */
4397 if (num_locks == 0 && num_ulocks == 0) {
4398 END_PROFILE(SMBlockingX);
4401 END_PROFILE(SMBlockingX);
4402 return ERROR(ERRDOS,ERRlock);
4406 if (remove_oplock(fsp, break_to_none) == False) {
4407 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4411 /* if this is a pure oplock break request then don't send a reply */
4412 if (num_locks == 0 && num_ulocks == 0)
4414 /* Sanity check - ensure a pure oplock break is not a
4416 if(CVAL(inbuf,smb_vwv0) != 0xff)
4417 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4418 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4419 END_PROFILE(SMBlockingX);
4425 * We do this check *after* we have checked this is not a oplock break
4426 * response message. JRA.
4429 release_level_2_oplocks_on_change(fsp);
4431 /* Data now points at the beginning of the list
4432 of smb_unlkrng structs */
4433 for(i = 0; i < (int)num_ulocks; i++) {
4434 lock_pid = get_lock_pid( data, i, large_file_format);
4435 count = get_lock_count( data, i, large_file_format);
4436 offset = get_lock_offset( data, i, large_file_format, &err);
4439 * There is no error code marked "stupid client bug".... :-).
4442 END_PROFILE(SMBlockingX);
4443 return ERROR(ERRDOS,ERRnoaccess);
4446 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4447 (unsigned int)lock_pid, (double)offset, (double)count, fsp->fsp_name ));
4449 if(!do_unlock(fsp,conn,lock_pid,count,offset, &eclass, &ecode)) {
4450 END_PROFILE(SMBlockingX);
4451 return ERROR(eclass,ecode);
4455 /* Setup the timeout in seconds. */
4456 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4458 /* Now do any requested locks */
4459 data += ((large_file_format ? 20 : 10)*num_ulocks);
4461 /* Data now points at the beginning of the list
4462 of smb_lkrng structs */
4464 for(i = 0; i < (int)num_locks; i++) {
4465 lock_pid = get_lock_pid( data, i, large_file_format);
4466 count = get_lock_count( data, i, large_file_format);
4467 offset = get_lock_offset( data, i, large_file_format, &err);
4470 * There is no error code marked "stupid client bug".... :-).
4473 END_PROFILE(SMBlockingX);
4474 return ERROR(ERRDOS,ERRnoaccess);
4477 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
4478 (unsigned int)lock_pid, (double)offset, (double)count, fsp->fsp_name ));
4480 if(!do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4482 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4484 * A blocking lock was requested. Package up
4485 * this smb into a queued request and push it
4486 * onto the blocking lock queue.
4488 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4489 END_PROFILE(SMBlockingX);
4497 /* If any of the above locks failed, then we must unlock
4498 all of the previous locks (X/Open spec). */
4499 if(i != num_locks && num_locks != 0) {
4501 * Ensure we don't do a remove on the lock that just failed,
4502 * as under POSIX rules, if we have a lock already there, we
4503 * will delete it (and we shouldn't) .....
4505 for(i--; i >= 0; i--) {
4506 lock_pid = get_lock_pid( data, i, large_file_format);
4507 count = get_lock_count( data, i, large_file_format);
4508 offset = get_lock_offset( data, i, large_file_format, &err);
4511 * There is no error code marked "stupid client bug".... :-).
4514 END_PROFILE(SMBlockingX);
4515 return ERROR(ERRDOS,ERRnoaccess);
4518 do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2);
4520 END_PROFILE(SMBlockingX);
4521 return ERROR(eclass,ecode);
4524 set_message(outbuf,2,0,True);
4526 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4527 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4529 END_PROFILE(SMBlockingX);
4530 return chain_reply(inbuf,outbuf,length,bufsize);
4534 /****************************************************************************
4535 reply to a SMBreadbmpx (read block multiplex) request
4536 ****************************************************************************/
4537 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4548 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4549 START_PROFILE(SMBreadBmpx);
4551 /* this function doesn't seem to work - disable by default */
4552 if (!lp_readbmpx()) {
4553 END_PROFILE(SMBreadBmpx);
4554 return(ERROR(ERRSRV,ERRuseSTD));
4557 outsize = set_message(outbuf,8,0,True);
4559 CHECK_FSP(fsp,conn);
4563 startpos = IVAL(inbuf,smb_vwv1);
4564 maxcount = SVAL(inbuf,smb_vwv3);
4566 data = smb_buf(outbuf);
4567 pad = ((long)data)%4;
4568 if (pad) pad = 4 - pad;
4571 max_per_packet = bufsize-(outsize+pad);
4575 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4576 END_PROFILE(SMBreadBmpx);
4577 return(ERROR(ERRDOS,ERRlock));
4582 size_t N = MIN(max_per_packet,tcount-total_read);
4584 nread = read_file(fsp,data,startpos,N);
4586 if (nread <= 0) nread = 0;
4588 if (nread < (ssize_t)N)
4589 tcount = total_read + nread;
4591 set_message(outbuf,8,nread,False);
4592 SIVAL(outbuf,smb_vwv0,startpos);
4593 SSVAL(outbuf,smb_vwv2,tcount);
4594 SSVAL(outbuf,smb_vwv6,nread);
4595 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4597 if (!send_smb(smbd_server_fd(),outbuf))
4598 exit_server("reply_readbmpx: send_smb failed.\n");
4600 total_read += nread;
4603 while (total_read < (ssize_t)tcount);
4605 END_PROFILE(SMBreadBmpx);
4609 /****************************************************************************
4610 reply to a SMBwritebmpx (write block multiplex primary) request
4611 ****************************************************************************/
4613 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4616 ssize_t nwritten = -1;
4623 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4624 START_PROFILE(SMBwriteBmpx);
4626 CHECK_FSP(fsp,conn);
4630 tcount = SVAL(inbuf,smb_vwv1);
4631 startpos = IVAL(inbuf,smb_vwv3);
4632 write_through = BITSETW(inbuf+smb_vwv7,0);
4633 numtowrite = SVAL(inbuf,smb_vwv10);
4634 smb_doff = SVAL(inbuf,smb_vwv11);
4636 data = smb_base(inbuf) + smb_doff;
4638 /* If this fails we need to send an SMBwriteC response,
4639 not an SMBwritebmpx - set this up now so we don't forget */
4640 CVAL(outbuf,smb_com) = SMBwritec;
4642 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4643 END_PROFILE(SMBwriteBmpx);
4644 return(ERROR(ERRDOS,ERRlock));
4647 nwritten = write_file(fsp,data,startpos,numtowrite);
4649 if(lp_syncalways(SNUM(conn)) || write_through)
4650 sync_file(conn,fsp);
4652 if(nwritten < (ssize_t)numtowrite) {
4653 END_PROFILE(SMBwriteBmpx);
4654 return(UNIXERROR(ERRHRD,ERRdiskfull));
4657 /* If the maximum to be written to this file
4658 is greater than what we just wrote then set
4659 up a secondary struct to be attached to this
4660 fd, we will use this to cache error messages etc. */
4661 if((ssize_t)tcount > nwritten)
4663 write_bmpx_struct *wbms;
4664 if(fsp->wbmpx_ptr != NULL)
4665 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4667 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4670 DEBUG(0,("Out of memory in reply_readmpx\n"));
4671 END_PROFILE(SMBwriteBmpx);
4672 return(ERROR(ERRSRV,ERRnoresource));
4674 wbms->wr_mode = write_through;
4675 wbms->wr_discard = False; /* No errors yet */
4676 wbms->wr_total_written = nwritten;
4677 wbms->wr_errclass = 0;
4679 fsp->wbmpx_ptr = wbms;
4682 /* We are returning successfully, set the message type back to
4684 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4686 outsize = set_message(outbuf,1,0,True);
4688 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4690 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4691 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4693 if (write_through && tcount==nwritten) {
4694 /* we need to send both a primary and a secondary response */
4695 smb_setlen(outbuf,outsize - 4);
4696 if (!send_smb(smbd_server_fd(),outbuf))
4697 exit_server("reply_writebmpx: send_smb failed.\n");
4699 /* now the secondary */
4700 outsize = set_message(outbuf,1,0,True);
4701 CVAL(outbuf,smb_com) = SMBwritec;
4702 SSVAL(outbuf,smb_vwv0,nwritten);
4705 END_PROFILE(SMBwriteBmpx);
4710 /****************************************************************************
4711 reply to a SMBwritebs (write block multiplex secondary) request
4712 ****************************************************************************/
4713 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4716 ssize_t nwritten = -1;
4723 write_bmpx_struct *wbms;
4724 BOOL send_response = False;
4725 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4726 START_PROFILE(SMBwriteBs);
4728 CHECK_FSP(fsp,conn);
4731 tcount = SVAL(inbuf,smb_vwv1);
4732 startpos = IVAL(inbuf,smb_vwv2);
4733 numtowrite = SVAL(inbuf,smb_vwv6);
4734 smb_doff = SVAL(inbuf,smb_vwv7);
4736 data = smb_base(inbuf) + smb_doff;
4738 /* We need to send an SMBwriteC response, not an SMBwritebs */
4739 CVAL(outbuf,smb_com) = SMBwritec;
4741 /* This fd should have an auxiliary struct attached,
4742 check that it does */
4743 wbms = fsp->wbmpx_ptr;
4745 END_PROFILE(SMBwriteBs);
4749 /* If write through is set we can return errors, else we must
4751 write_through = wbms->wr_mode;
4753 /* Check for an earlier error */
4754 if(wbms->wr_discard) {
4755 END_PROFILE(SMBwriteBs);
4756 return -1; /* Just discard the packet */
4759 nwritten = write_file(fsp,data,startpos,numtowrite);
4761 if(lp_syncalways(SNUM(conn)) || write_through)
4762 sync_file(conn,fsp);
4764 if (nwritten < (ssize_t)numtowrite)
4768 /* We are returning an error - we can delete the aux struct */
4769 if (wbms) free((char *)wbms);
4770 fsp->wbmpx_ptr = NULL;
4771 END_PROFILE(SMBwriteBs);
4772 return(ERROR(ERRHRD,ERRdiskfull));
4774 END_PROFILE(SMBwriteBs);
4775 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4778 /* Increment the total written, if this matches tcount
4779 we can discard the auxiliary struct (hurrah !) and return a writeC */
4780 wbms->wr_total_written += nwritten;
4781 if(wbms->wr_total_written >= tcount)
4785 outsize = set_message(outbuf,1,0,True);
4786 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4787 send_response = True;
4791 fsp->wbmpx_ptr = NULL;
4795 END_PROFILE(SMBwriteBs);
4799 END_PROFILE(SMBwriteBs);
4804 /****************************************************************************
4805 reply to a SMBsetattrE
4806 ****************************************************************************/
4808 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4810 struct utimbuf unix_times;
4812 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4813 START_PROFILE(SMBsetattrE);
4815 outsize = set_message(outbuf,0,0,True);
4817 CHECK_FSP(fsp,conn);
4820 /* Convert the DOS times into unix times. Ignore create
4821 time as UNIX can't set this.
4823 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4824 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4827 * Patch from Ray Frush <frush@engr.colostate.edu>
4828 * Sometimes times are sent as zero - ignore them.
4831 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4833 /* Ignore request */
4836 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4837 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4839 END_PROFILE(SMBsetattrE);
4842 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4844 /* set modify time = to access time if modify time was 0 */
4845 unix_times.modtime = unix_times.actime;
4848 /* Set the date on this file */
4849 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4850 END_PROFILE(SMBsetattrE);
4851 return(ERROR(ERRDOS,ERRnoaccess));
4854 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4855 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4857 END_PROFILE(SMBsetattrE);
4862 /****************************************************************************
4863 reply to a SMBgetattrE
4864 ****************************************************************************/
4866 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4868 SMB_STRUCT_STAT sbuf;
4871 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4872 START_PROFILE(SMBgetattrE);
4874 outsize = set_message(outbuf,11,0,True);
4876 CHECK_FSP(fsp,conn);
4879 /* Do an fstat on this file */
4880 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4881 END_PROFILE(SMBgetattrE);
4882 return(UNIXERROR(ERRDOS,ERRnoaccess));
4885 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4887 /* Convert the times into dos times. Set create
4888 date to be last modify date as UNIX doesn't save
4890 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4891 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4892 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4895 SIVAL(outbuf,smb_vwv6,0);
4896 SIVAL(outbuf,smb_vwv8,0);
4900 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4901 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4903 SSVAL(outbuf,smb_vwv10, mode);
4905 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4907 END_PROFILE(SMBgetattrE);