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 /* don't allow for weird usernames */
862 alpha_strcpy(user, user, ". _-", sizeof(user));
863 if (strstr(user, "..")) {
864 return bad_password_error(inbuf, outbuf);
867 DEBUG(3,("sesssetupX:name=[%s]\n",user));
869 /* If name ends in $ then I think it's asking about whether a */
870 /* computer with that name (minus the $) has access. For now */
871 /* say yes to everything ending in $. */
873 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
874 END_PROFILE(SMBsesssetupX);
875 return session_trust_account(conn, inbuf, outbuf, user,
876 smb_apasswd, smb_apasslen,
877 smb_ntpasswd, smb_ntpasslen);
880 if (done_sesssetup && lp_restrict_anonymous()) {
881 /* tests show that even if browsing is done over already validated connections
882 * without a username and password the domain is still provided, which it
883 * wouldn't be if it was a purely anonymous connection. So, in order to
884 * restrict anonymous, we only deny connections that have no session
885 * information. If a domain has been provided, then it's not a purely
886 * anonymous connection. AAB
888 if (!*user && !*smb_apasswd && !*domain) {
889 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
890 END_PROFILE(SMBsesssetupX);
891 return(ERROR(ERRDOS,ERRnoaccess));
895 /* If no username is sent use the guest account */
897 pstrcpy(user,lp_guestaccount(-1));
898 /* If no user and no password then set guest flag. */
899 if( *smb_apasswd == 0)
903 pstrcpy(current_user_info.smb_name,user);
905 reload_services(True);
908 * Save the username before mapping. We will use
909 * the original username sent to us for security=server
910 * and security=domain checking.
913 pstrcpy( orig_user, user);
916 * Always try the "DOMAIN\user" lookup first, as this is the most
917 * specific case. If this fails then try the simple "user" lookup.
923 /* Work out who's who */
925 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
926 dos_to_unix(domain, False), lp_winbind_separator(), user);
928 if (sys_getpwnam(dom_user) != NULL) {
929 pstrcpy(user, dom_user);
930 DEBUG(3,("Using unix username %s\n", dom_user));
935 * Pass the user through the NT -> unix user mapping
939 (void)map_username(user);
942 * Do any UNIX username case mangling.
944 smb_getpwnam(user, True);
946 add_session_user(user);
949 * Check if the given username was the guest user with no password.
952 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
956 * Check with orig_user for security=server and
960 if (!guest && !check_server_security(orig_user, domain, user,
961 smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
962 !check_domain_security(orig_user, domain, user, smb_apasswd,
963 smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
964 !check_hosts_equiv(user))
968 * If we get here then the user wasn't guest and the remote
969 * authentication methods failed. Check the authentication
970 * methods on this local server.
972 * If an NT password was supplied try and validate with that
973 * first. This is superior as the passwords are mixed case
974 * 128 length unicode.
979 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
980 DEBUG(2,("NT Password did not match for user '%s'!\n", user));
982 valid_nt_password = True;
986 /* check the LanMan password only if necessary and if allowed
987 by lp_lanman_auth() */
988 if (!valid_nt_password && lp_lanman_auth())
990 DEBUG(2,("Defaulting to Lanman password for %s\n", user));
991 valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen,NULL);
995 /* The true branch will be executed if
996 (1) the NT password failed (or was not tried), and
997 (2) LanMan authentication failed (or was disabled)
999 if (!valid_nt_password && !valid_lm_password)
1001 if (lp_security() >= SEC_USER)
1003 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
1005 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
1006 END_PROFILE(SMBsesssetupX);
1007 return bad_password_error(inbuf,outbuf);
1010 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
1012 if (smb_getpwnam(user,True))
1014 DEBUG(1,("Rejecting user '%s': bad password\n", user));
1015 END_PROFILE(SMBsesssetupX);
1016 return bad_password_error(inbuf,outbuf);
1021 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
1022 * Then always map to guest account - as done below.
1026 if (*smb_apasswd || !smb_getpwnam(user,True))
1027 pstrcpy(user,lp_guestaccount(-1));
1028 DEBUG(3,("Registered username %s for guest access\n",user));
1033 if (!smb_getpwnam(user,True)) {
1034 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
1035 pstrcpy(user,lp_guestaccount(-1));
1039 if (!strequal(user,lp_guestaccount(-1)) &&
1040 lp_servicenumber(user) < 0)
1042 add_home_service(user,get_user_home_dir(user));
1046 /* it's ok - setup a reply */
1047 if (Protocol < PROTOCOL_NT1) {
1048 set_message(outbuf,3,0,True);
1051 set_message(outbuf,3,0,True);
1052 p = smb_buf(outbuf);
1053 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE|STR_CONVERT);
1054 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE|STR_CONVERT);
1055 p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE|STR_CONVERT);
1056 set_message_end(outbuf,p);
1057 /* perhaps grab OS version here?? */
1060 /* Set the correct uid in the outgoing and incoming packets
1061 We will use this on future requests to determine which
1062 user we should become.
1065 const struct passwd *pw = smb_getpwnam(user,False);
1067 DEBUG(1,("Username %s is invalid on this system\n",user));
1068 END_PROFILE(SMBsesssetupX);
1069 return bad_password_error(inbuf,outbuf);
1076 SSVAL(outbuf,smb_vwv2,1);
1078 /* register the name and uid as being validated, so further connections
1079 to a uid can get through without a password, on the same VC */
1081 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest);
1083 if (sess_vuid == -1) {
1084 return(ERROR(ERRDOS,ERRnoaccess));
1088 SSVAL(outbuf,smb_uid,sess_vuid);
1089 SSVAL(inbuf,smb_uid,sess_vuid);
1091 if (!done_sesssetup)
1092 max_send = MIN(max_send,smb_bufsize);
1094 DEBUG(6,("Client requested max send size of %d\n", max_send));
1096 done_sesssetup = True;
1098 END_PROFILE(SMBsesssetupX);
1099 return chain_reply(inbuf,outbuf,length,bufsize);
1102 /****************************************************************************
1104 ****************************************************************************/
1105 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1111 BOOL bad_path = False;
1112 SMB_STRUCT_STAT sbuf;
1113 START_PROFILE(SMBchkpth);
1115 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1117 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1119 unix_convert(name,conn,0,&bad_path,&sbuf);
1121 mode = SVAL(inbuf,smb_vwv0);
1123 if (check_name(name,conn)) {
1124 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
1125 ok = S_ISDIR(sbuf.st_mode);
1130 /* We special case this - as when a Windows machine
1131 is parsing a path is steps through the components
1132 one at a time - if a component fails it expects
1133 ERRbadpath, not ERRbadfile.
1137 unix_ERR_class = ERRDOS;
1138 unix_ERR_code = ERRbadpath;
1142 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1143 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1144 (get_remote_arch() == RA_WINNT))
1146 unix_ERR_class = ERRDOS;
1147 unix_ERR_code = ERRbaddirectory;
1151 return(UNIXERROR(ERRDOS,ERRbadpath));
1154 outsize = set_message(outbuf,0,0,True);
1156 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1158 END_PROFILE(SMBchkpth);
1163 /****************************************************************************
1165 ****************************************************************************/
1166 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1170 SMB_STRUCT_STAT sbuf;
1175 BOOL bad_path = False;
1177 START_PROFILE(SMBgetatr);
1179 p = smb_buf(inbuf) + 1;
1180 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1182 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1184 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1185 under WfWg - weird! */
1188 mode = aHIDDEN | aDIR;
1189 if (!CAN_WRITE(conn)) mode |= aRONLY;
1196 unix_convert(fname,conn,0,&bad_path,&sbuf);
1197 if (check_name(fname,conn))
1199 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1201 mode = dos_mode(conn,fname,&sbuf);
1202 size = sbuf.st_size;
1203 mtime = sbuf.st_mtime;
1209 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1215 if((errno == ENOENT) && bad_path)
1217 unix_ERR_class = ERRDOS;
1218 unix_ERR_code = ERRbadpath;
1221 END_PROFILE(SMBgetatr);
1222 return(UNIXERROR(ERRDOS,ERRbadfile));
1225 outsize = set_message(outbuf,10,0,True);
1227 SSVAL(outbuf,smb_vwv0,mode);
1228 if(lp_dos_filetime_resolution(SNUM(conn)) )
1229 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1231 put_dos_date3(outbuf,smb_vwv1,mtime);
1232 SIVAL(outbuf,smb_vwv3,(uint32)size);
1234 if (Protocol >= PROTOCOL_NT1) {
1235 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1238 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1240 END_PROFILE(SMBgetatr);
1245 /****************************************************************************
1247 ****************************************************************************/
1248 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1255 SMB_STRUCT_STAT sbuf;
1256 BOOL bad_path = False;
1259 START_PROFILE(SMBsetatr);
1261 p = smb_buf(inbuf) + 1;
1262 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1263 unix_convert(fname,conn,0,&bad_path,&sbuf);
1265 mode = SVAL(inbuf,smb_vwv0);
1266 mtime = make_unix_date3(inbuf+smb_vwv1);
1268 if (VALID_STAT_OF_DIR(sbuf))
1270 if (check_name(fname,conn))
1271 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1273 ok = set_filetime(conn,fname,mtime);
1277 if((errno == ENOENT) && bad_path)
1279 unix_ERR_class = ERRDOS;
1280 unix_ERR_code = ERRbadpath;
1283 END_PROFILE(SMBsetatr);
1284 return(UNIXERROR(ERRDOS,ERRnoaccess));
1287 outsize = set_message(outbuf,0,0,True);
1289 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1291 END_PROFILE(SMBsetatr);
1296 /****************************************************************************
1298 ****************************************************************************/
1299 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1302 SMB_BIG_UINT dfree,dsize,bsize;
1303 START_PROFILE(SMBdskattr);
1305 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1307 outsize = set_message(outbuf,5,0,True);
1309 SSVAL(outbuf,smb_vwv0,dsize);
1310 SSVAL(outbuf,smb_vwv1,bsize/512);
1311 SSVAL(outbuf,smb_vwv2,512);
1312 SSVAL(outbuf,smb_vwv3,dfree);
1314 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1316 END_PROFILE(SMBdskattr);
1321 /****************************************************************************
1323 Can be called from SMBsearch, SMBffirst or SMBfunique.
1324 ****************************************************************************/
1325 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1336 BOOL finished = False;
1345 BOOL check_descend = False;
1346 BOOL expect_close = False;
1347 BOOL can_open = True;
1348 BOOL bad_path = False;
1349 START_PROFILE(SMBsearch);
1351 *mask = *directory = *fname = 0;
1353 /* If we were called as SMBffirst then we must expect close. */
1354 if(CVAL(inbuf,smb_com) == SMBffirst)
1355 expect_close = True;
1357 outsize = set_message(outbuf,1,3,True);
1358 maxentries = SVAL(inbuf,smb_vwv0);
1359 dirtype = SVAL(inbuf,smb_vwv1);
1360 p = smb_buf(inbuf) + 1;
1361 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1363 status_len = SVAL(p, 0);
1366 /* dirtype &= ~aDIR; */
1368 if (status_len == 0)
1370 SMB_STRUCT_STAT sbuf;
1373 pstrcpy(directory,path);
1375 unix_convert(directory,conn,0,&bad_path,&sbuf);
1378 if (!check_name(directory,conn))
1381 p = strrchr(dir2,'/');
1393 p = strrchr(directory,'/');
1399 if (strlen(directory) == 0)
1400 pstrcpy(directory,"./");
1401 memset((char *)status,'\0',21);
1402 CVAL(status,0) = dirtype;
1406 memcpy(status,p,21);
1407 dirtype = CVAL(status,0) & 0x1F;
1408 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1411 string_set(&conn->dirpath,dptr_path(dptr_num));
1412 fstrcpy(mask, dptr_wcard(dptr_num));
1417 p = smb_buf(outbuf) + 3;
1421 if (status_len == 0)
1423 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1428 if((errno == ENOENT) && bad_path)
1430 unix_ERR_class = ERRDOS;
1431 unix_ERR_code = ERRbadpath;
1433 END_PROFILE(SMBsearch);
1434 return (UNIXERROR(ERRDOS,ERRnofids));
1436 END_PROFILE(SMBsearch);
1437 return(ERROR(ERRDOS,ERRnofids));
1439 dptr_set_wcard(dptr_num, strdup(mask));
1442 DEBUG(4,("dptr_num is %d\n",dptr_num));
1446 if ((dirtype&0x1F) == aVOLID)
1448 memcpy(p,status,21);
1449 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1450 dptr_fill(p+12,dptr_num);
1451 if (dptr_zero(p+12) && (status_len==0))
1455 p += DIR_STRUCT_SIZE;
1459 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1460 conn->dirpath,lp_dontdescend(SNUM(conn))));
1461 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1462 check_descend = True;
1464 for (i=numentries;(i<maxentries) && !finished;i++)
1467 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1470 memcpy(p,status,21);
1471 make_dir_struct(p,mask,fname,size,mode,date);
1472 dptr_fill(p+12,dptr_num);
1475 p += DIR_STRUCT_SIZE;
1484 if (numentries == 0 || !ok)
1486 CVAL(outbuf,smb_rcls) = ERRDOS;
1487 SSVAL(outbuf,smb_err,ERRnofiles);
1488 dptr_close(&dptr_num);
1491 /* If we were called as SMBffirst with smb_search_id == NULL
1492 and no entries were found then return error and close dirptr
1495 if(ok && expect_close && numentries == 0 && status_len == 0)
1497 CVAL(outbuf,smb_rcls) = ERRDOS;
1498 SSVAL(outbuf,smb_err,ERRnofiles);
1499 /* Also close the dptr - we know it's gone */
1500 dptr_close(&dptr_num);
1503 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1504 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1505 dptr_close(&dptr_num);
1507 SSVAL(outbuf,smb_vwv0,numentries);
1508 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1509 CVAL(smb_buf(outbuf),0) = 5;
1510 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1512 if (Protocol >= PROTOCOL_NT1) {
1513 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1516 outsize += DIR_STRUCT_SIZE*numentries;
1517 smb_setlen(outbuf,outsize - 4);
1519 if ((! *directory) && dptr_path(dptr_num))
1520 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1522 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1523 smb_fn_name(CVAL(inbuf,smb_com)),
1524 mask, directory, dirtype, numentries, maxentries ) );
1526 END_PROFILE(SMBsearch);
1531 /****************************************************************************
1532 reply to a fclose (stop directory search)
1533 ****************************************************************************/
1534 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1543 START_PROFILE(SMBfclose);
1545 outsize = set_message(outbuf,1,0,True);
1546 p = smb_buf(inbuf) + 1;
1547 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE|STR_CONVERT);
1549 status_len = SVAL(p,0);
1552 if (status_len == 0) {
1553 END_PROFILE(SMBfclose);
1554 return(ERROR(ERRSRV,ERRsrverror));
1557 memcpy(status,p,21);
1559 if(dptr_fetch(status+12,&dptr_num)) {
1560 /* Close the dptr - we know it's gone */
1561 dptr_close(&dptr_num);
1564 SSVAL(outbuf,smb_vwv0,0);
1566 DEBUG(3,("search close\n"));
1568 END_PROFILE(SMBfclose);
1573 /****************************************************************************
1575 ****************************************************************************/
1577 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1587 SMB_STRUCT_STAT sbuf;
1588 BOOL bad_path = False;
1590 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1591 START_PROFILE(SMBopen);
1593 share_mode = SVAL(inbuf,smb_vwv0);
1595 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1597 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1599 unix_convert(fname,conn,0,&bad_path,&sbuf);
1601 unixmode = unix_mode(conn,aARCH,fname);
1603 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1604 unixmode, oplock_request,&rmode,NULL);
1608 if((errno == ENOENT) && bad_path)
1610 unix_ERR_class = ERRDOS;
1611 unix_ERR_code = ERRbadpath;
1613 END_PROFILE(SMBopen);
1614 return(UNIXERROR(ERRDOS,ERRnoaccess));
1617 size = sbuf.st_size;
1618 fmode = dos_mode(conn,fname,&sbuf);
1619 mtime = sbuf.st_mtime;
1622 DEBUG(3,("attempt to open a directory %s\n",fname));
1623 close_file(fsp,False);
1624 END_PROFILE(SMBopen);
1625 return(ERROR(ERRDOS,ERRnoaccess));
1628 outsize = set_message(outbuf,7,0,True);
1629 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1630 SSVAL(outbuf,smb_vwv1,fmode);
1631 if(lp_dos_filetime_resolution(SNUM(conn)) )
1632 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1634 put_dos_date3(outbuf,smb_vwv2,mtime);
1635 SIVAL(outbuf,smb_vwv4,(uint32)size);
1636 SSVAL(outbuf,smb_vwv6,rmode);
1638 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1639 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1642 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1643 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1644 END_PROFILE(SMBopen);
1649 /****************************************************************************
1650 reply to an open and X
1651 ****************************************************************************/
1652 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1655 int smb_mode = SVAL(inbuf,smb_vwv3);
1656 int smb_attr = SVAL(inbuf,smb_vwv5);
1657 /* Breakout the oplock request bits so we can set the
1658 reply bits separately. */
1659 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1660 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1661 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1663 int open_flags = SVAL(inbuf,smb_vwv2);
1664 int smb_sattr = SVAL(inbuf,smb_vwv4);
1665 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1667 int smb_ofun = SVAL(inbuf,smb_vwv8);
1670 int fmode=0,mtime=0,rmode=0;
1671 SMB_STRUCT_STAT sbuf;
1673 BOOL bad_path = False;
1675 START_PROFILE(SMBopenX);
1677 /* If it's an IPC, pass off the pipe handler. */
1679 if (lp_nt_pipe_support()) {
1680 END_PROFILE(SMBopenX);
1681 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1683 END_PROFILE(SMBopenX);
1684 return (ERROR(ERRSRV,ERRaccess));
1688 /* XXXX we need to handle passed times, sattr and flags */
1689 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1691 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1693 unix_convert(fname,conn,0,&bad_path,&sbuf);
1695 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1697 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1698 oplock_request, &rmode,&smb_action);
1702 if((errno == ENOENT) && bad_path)
1704 unix_ERR_class = ERRDOS;
1705 unix_ERR_code = ERRbadpath;
1707 END_PROFILE(SMBopenX);
1708 return(UNIXERROR(ERRDOS,ERRnoaccess));
1711 size = sbuf.st_size;
1712 fmode = dos_mode(conn,fname,&sbuf);
1713 mtime = sbuf.st_mtime;
1715 close_file(fsp,False);
1716 END_PROFILE(SMBopenX);
1717 return(ERROR(ERRDOS,ERRnoaccess));
1720 /* If the caller set the extended oplock request bit
1721 and we granted one (by whatever means) - set the
1722 correct bit for extended oplock reply.
1725 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1726 smb_action |= EXTENDED_OPLOCK_GRANTED;
1729 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1730 smb_action |= EXTENDED_OPLOCK_GRANTED;
1733 /* If the caller set the core oplock request bit
1734 and we granted one (by whatever means) - set the
1735 correct bit for core oplock reply.
1738 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1739 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1742 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1743 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1746 set_message(outbuf,15,0,True);
1747 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1748 SSVAL(outbuf,smb_vwv3,fmode);
1749 if(lp_dos_filetime_resolution(SNUM(conn)) )
1750 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1752 put_dos_date3(outbuf,smb_vwv4,mtime);
1753 SIVAL(outbuf,smb_vwv6,(uint32)size);
1754 SSVAL(outbuf,smb_vwv8,rmode);
1755 SSVAL(outbuf,smb_vwv11,smb_action);
1757 END_PROFILE(SMBopenX);
1758 return chain_reply(inbuf,outbuf,length,bufsize);
1762 /****************************************************************************
1763 reply to a SMBulogoffX
1764 ****************************************************************************/
1765 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1767 uint16 vuid = SVAL(inbuf,smb_uid);
1768 user_struct *vuser = get_valid_user_struct(vuid);
1769 START_PROFILE(SMBulogoffX);
1772 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1775 /* in user level security we are supposed to close any files
1776 open by this user */
1777 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1778 file_close_user(vuid);
1781 invalidate_vuid(vuid);
1783 set_message(outbuf,2,0,True);
1785 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1787 END_PROFILE(SMBulogoffX);
1788 return chain_reply(inbuf,outbuf,length,bufsize);
1792 /****************************************************************************
1793 reply to a mknew or a create
1794 ****************************************************************************/
1795 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1803 BOOL bad_path = False;
1805 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1806 SMB_STRUCT_STAT sbuf;
1807 START_PROFILE(SMBcreate);
1809 com = SVAL(inbuf,smb_com);
1811 createmode = SVAL(inbuf,smb_vwv0);
1812 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1814 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1816 unix_convert(fname,conn,0,&bad_path,&sbuf);
1818 if (createmode & aVOLID) {
1819 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1822 unixmode = unix_mode(conn,createmode,fname);
1826 /* We should fail if file exists. */
1827 ofun = FILE_CREATE_IF_NOT_EXIST;
1831 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1832 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1835 /* Open file in dos compatibility share mode. */
1836 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1837 ofun, unixmode, oplock_request, NULL, NULL);
1841 if((errno == ENOENT) && bad_path)
1843 unix_ERR_class = ERRDOS;
1844 unix_ERR_code = ERRbadpath;
1846 END_PROFILE(SMBcreate);
1847 return(UNIXERROR(ERRDOS,ERRnoaccess));
1850 outsize = set_message(outbuf,1,0,True);
1851 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1853 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1854 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1857 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1858 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1860 DEBUG( 2, ( "new file %s\n", fname ) );
1861 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1862 fname, fsp->fd, createmode, (int)unixmode ) );
1864 END_PROFILE(SMBcreate);
1869 /****************************************************************************
1870 reply to a create temporary file
1871 ****************************************************************************/
1872 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1879 BOOL bad_path = False;
1881 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1883 SMB_STRUCT_STAT sbuf;
1886 START_PROFILE(SMBctemp);
1888 createmode = SVAL(inbuf,smb_vwv0);
1889 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT);
1890 pstrcat(fname,"/TMXXXXXX");
1892 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1894 unix_convert(fname,conn,0,&bad_path,&sbuf);
1896 unixmode = unix_mode(conn,createmode,fname);
1898 tmpfd = smb_mkstemp(fname);
1900 END_PROFILE(SMBctemp);
1901 return(UNIXERROR(ERRDOS,ERRnoaccess));
1904 vfs_stat(conn,fname2,&sbuf);
1906 /* Open file in dos compatibility share mode. */
1907 /* We should fail if file does not exist. */
1908 fsp = open_file_shared(conn,fname,&sbuf,
1909 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1910 FILE_FAIL_IF_NOT_EXIST,
1911 unixmode, oplock_request, NULL, NULL);
1913 /* close fd from smb_mkstemp() */
1918 if((errno == ENOENT) && bad_path)
1920 unix_ERR_class = ERRDOS;
1921 unix_ERR_code = ERRbadpath;
1923 END_PROFILE(SMBctemp);
1924 return(UNIXERROR(ERRDOS,ERRnoaccess));
1927 outsize = set_message(outbuf,1,0,True);
1928 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1929 CVAL(smb_buf(outbuf),0) = 4;
1930 p = smb_buf(outbuf) + 1;
1931 p += srvstr_push(outbuf, p, fname2, -1, STR_TERMINATE|STR_CONVERT);
1932 set_message_end(outbuf, p);
1934 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1935 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1938 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1939 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1941 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1942 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1943 fname2, fsp->fd, createmode, (int)unixmode ) );
1945 END_PROFILE(SMBctemp);
1950 /*******************************************************************
1951 check if a user is allowed to delete a file
1952 ********************************************************************/
1953 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1955 SMB_STRUCT_STAT sbuf;
1958 if (!CAN_WRITE(conn)) return(False);
1960 if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False);
1961 fmode = dos_mode(conn,fname,&sbuf);
1962 if (fmode & aDIR) return(False);
1963 if (!lp_delete_readonly(SNUM(conn))) {
1964 if (fmode & aRONLY) return(False);
1966 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1968 if (!check_file_sharing(conn,fname,False)) return(False);
1972 /****************************************************************************
1973 The guts of the unlink command, split out so it may be called by the NT SMB
1975 ****************************************************************************/
1977 int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
1978 int dirtype, char *name)
1984 int error = ERRnoaccess;
1987 BOOL bad_path = False;
1989 SMB_STRUCT_STAT sbuf;
1991 *directory = *mask = 0;
1993 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1995 p = strrchr(name,'/');
1997 pstrcpy(directory,"./");
2001 pstrcpy(directory,name);
2006 * We should only check the mangled cache
2007 * here if unix_convert failed. This means
2008 * that the path in 'mask' doesn't exist
2009 * on the file system and so we need to look
2010 * for a possible mangle. This patch from
2011 * Tine Smukavec <valentin.smukavec@hermes.si>.
2014 if (!rc && is_mangled(mask))
2015 check_mangled_cache( mask );
2017 has_wild = ms_has_wild(mask);
2020 pstrcat(directory,"/");
2021 pstrcat(directory,mask);
2022 if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory))
2025 exists = vfs_file_exist(conn,directory,&sbuf);
2027 void *dirptr = NULL;
2030 if (check_name(directory,conn))
2031 dirptr = OpenDir(conn, directory, True);
2033 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2034 the pattern matches against the long name, otherwise the short name
2035 We don't implement this yet XXXX
2042 if (strequal(mask,"????????.???"))
2045 while ((dname = ReadDirName(dirptr)))
2048 pstrcpy(fname,dname);
2050 if(!mask_match(fname, mask, case_sensitive)) continue;
2052 error = ERRnoaccess;
2053 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2054 if (!can_delete(fname,conn,dirtype)) continue;
2055 if (!vfs_unlink(conn,fname)) count++;
2056 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2064 return(ERROR(ERRDOS,error));
2066 if((errno == ENOENT) && bad_path) {
2067 unix_ERR_class = ERRDOS;
2068 unix_ERR_code = ERRbadpath;
2070 return(UNIXERROR(ERRDOS,error));
2077 /****************************************************************************
2079 ****************************************************************************/
2081 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2086 START_PROFILE(SMBunlink);
2088 dirtype = SVAL(inbuf,smb_vwv0);
2090 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
2092 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
2094 DEBUG(3,("reply_unlink : %s\n",name));
2096 outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
2100 * Win2k needs a changenotify request response before it will
2101 * update after a rename..
2104 process_pending_change_notify_queue((time_t)0);
2106 outsize = set_message(outbuf,0,0,True);
2109 END_PROFILE(SMBunlink);
2114 /****************************************************************************
2115 reply to a readbraw (core+ protocol)
2116 ****************************************************************************/
2118 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2120 size_t maxcount,mincount;
2123 char *header = outbuf;
2126 START_PROFILE(SMBreadbraw);
2129 * Special check if an oplock break has been issued
2130 * and the readraw request croses on the wire, we must
2131 * return a zero length response here.
2134 if(global_oplock_break)
2136 _smb_setlen(header,0);
2137 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2138 DEBUG(5,("readbraw - oplock break finished\n"));
2139 END_PROFILE(SMBreadbraw);
2143 fsp = file_fsp(inbuf,smb_vwv0);
2145 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2147 * fsp could be NULL here so use the value from the packet. JRA.
2149 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2150 _smb_setlen(header,0);
2151 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2152 END_PROFILE(SMBreadbraw);
2156 CHECK_FSP(fsp,conn);
2158 flush_write_cache(fsp, READRAW_FLUSH);
2160 startpos = IVAL(inbuf,smb_vwv1);
2161 if(CVAL(inbuf,smb_wct) == 10) {
2163 * This is a large offset (64 bit) read.
2165 #ifdef LARGE_SMB_OFF_T
2167 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2169 #else /* !LARGE_SMB_OFF_T */
2172 * Ensure we haven't been sent a >32 bit offset.
2175 if(IVAL(inbuf,smb_vwv8) != 0) {
2176 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2177 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2178 _smb_setlen(header,0);
2179 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2180 END_PROFILE(SMBreadbraw);
2184 #endif /* LARGE_SMB_OFF_T */
2187 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2188 (double)startpos ));
2189 _smb_setlen(header,0);
2190 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2191 END_PROFILE(SMBreadbraw);
2195 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2196 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2198 /* ensure we don't overrun the packet size */
2199 maxcount = MIN(65535,maxcount);
2200 maxcount = MAX(mincount,maxcount);
2202 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False))
2204 SMB_OFF_T size = fsp->size;
2205 SMB_OFF_T sizeneeded = startpos + maxcount;
2207 if (size < sizeneeded)
2210 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2212 if (!fsp->can_write)
2216 nread = MIN(maxcount,(size - startpos));
2219 if (nread < mincount)
2222 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2223 fsp->fnum, (double)startpos,
2224 (int)maxcount, (int)mincount, (int)nread ) );
2228 BOOL seek_fail = False;
2230 _smb_setlen(header,nread);
2232 if ((nread-predict) > 0) {
2233 if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
2234 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2241 ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
2242 (SMB_OFF_T)(nread-predict),header,4+predict,
2247 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2248 fsp->fsp_name,startpos,nread,ret));
2250 #else /* UNSAFE_READRAW */
2251 ret = read_file(fsp,header+4,startpos,nread);
2252 if (ret < mincount) ret = 0;
2254 _smb_setlen(header,ret);
2255 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2256 #endif /* UNSAFE_READRAW */
2258 DEBUG(5,("readbraw finished\n"));
2259 END_PROFILE(SMBreadbraw);
2264 /****************************************************************************
2265 reply to a lockread (core+ protocol)
2266 ****************************************************************************/
2267 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2276 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2277 START_PROFILE(SMBlockread);
2279 CHECK_FSP(fsp,conn);
2283 release_level_2_oplocks_on_change(fsp);
2285 numtoread = SVAL(inbuf,smb_vwv1);
2286 startpos = IVAL(inbuf,smb_vwv2);
2288 outsize = set_message(outbuf,5,3,True);
2289 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2290 data = smb_buf(outbuf) + 3;
2293 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2294 * protocol request that predates the read/write lock concept.
2295 * Thus instead of asking for a read lock here we need to ask
2296 * for a write lock. JRA.
2299 if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2300 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2302 * A blocking lock was requested. Package up
2303 * this smb into a queued request and push it
2304 * onto the blocking lock queue.
2306 if(push_blocking_lock_request(inbuf, length, -1, 0))
2307 END_PROFILE(SMBlockread);
2310 END_PROFILE(SMBlockread);
2311 return (ERROR(eclass,ecode));
2314 nread = read_file(fsp,data,startpos,numtoread);
2317 END_PROFILE(SMBlockread);
2318 return(UNIXERROR(ERRDOS,ERRnoaccess));
2322 SSVAL(outbuf,smb_vwv0,nread);
2323 SSVAL(outbuf,smb_vwv5,nread+3);
2324 SSVAL(smb_buf(outbuf),1,nread);
2326 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2327 fsp->fnum, (int)numtoread, (int)nread ) );
2329 END_PROFILE(SMBlockread);
2334 /****************************************************************************
2336 ****************************************************************************/
2338 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2345 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2346 START_PROFILE(SMBread);
2348 CHECK_FSP(fsp,conn);
2352 numtoread = SVAL(inbuf,smb_vwv1);
2353 startpos = IVAL(inbuf,smb_vwv2);
2355 outsize = set_message(outbuf,5,3,True);
2356 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2357 data = smb_buf(outbuf) + 3;
2359 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2360 END_PROFILE(SMBread);
2361 return(ERROR(ERRDOS,ERRlock));
2365 nread = read_file(fsp,data,startpos,numtoread);
2368 END_PROFILE(SMBread);
2369 return(UNIXERROR(ERRDOS,ERRnoaccess));
2373 SSVAL(outbuf,smb_vwv0,nread);
2374 SSVAL(outbuf,smb_vwv5,nread+3);
2375 CVAL(smb_buf(outbuf),0) = 1;
2376 SSVAL(smb_buf(outbuf),1,nread);
2378 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2379 fsp->fnum, (int)numtoread, (int)nread ) );
2381 END_PROFILE(SMBread);
2386 /****************************************************************************
2387 reply to a read and X
2388 ****************************************************************************/
2389 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2391 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2392 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2393 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2394 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2397 START_PROFILE(SMBreadX);
2399 /* If it's an IPC, pass off the pipe handler. */
2401 END_PROFILE(SMBreadX);
2402 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2405 CHECK_FSP(fsp,conn);
2409 set_message(outbuf,12,0,True);
2410 data = smb_buf(outbuf);
2412 if(CVAL(inbuf,smb_wct) == 12) {
2413 #ifdef LARGE_SMB_OFF_T
2415 * This is a large offset (64 bit) read.
2417 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2419 #else /* !LARGE_SMB_OFF_T */
2422 * Ensure we haven't been sent a >32 bit offset.
2425 if(IVAL(inbuf,smb_vwv10) != 0) {
2426 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2427 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2428 END_PROFILE(SMBreadX);
2429 return(ERROR(ERRDOS,ERRbadaccess));
2432 #endif /* LARGE_SMB_OFF_T */
2436 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2437 END_PROFILE(SMBreadX);
2438 return(ERROR(ERRDOS,ERRlock));
2440 nread = read_file(fsp,data,startpos,smb_maxcnt);
2443 END_PROFILE(SMBreadX);
2444 return(UNIXERROR(ERRDOS,ERRnoaccess));
2447 SSVAL(outbuf,smb_vwv5,nread);
2448 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2449 SSVAL(smb_buf(outbuf),-2,nread);
2451 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2452 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2454 END_PROFILE(SMBreadX);
2455 return chain_reply(inbuf,outbuf,length,bufsize);
2458 /****************************************************************************
2459 reply to a writebraw (core+ or LANMAN1.0 protocol)
2460 ****************************************************************************/
2462 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2465 ssize_t total_written=0;
2466 size_t numtowrite=0;
2471 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2473 START_PROFILE(SMBwritebraw);
2475 CHECK_FSP(fsp,conn);
2479 tcount = IVAL(inbuf,smb_vwv1);
2480 startpos = IVAL(inbuf,smb_vwv3);
2481 write_through = BITSETW(inbuf+smb_vwv7,0);
2483 /* We have to deal with slightly different formats depending
2484 on whether we are using the core+ or lanman1.0 protocol */
2485 if(Protocol <= PROTOCOL_COREPLUS) {
2486 numtowrite = SVAL(smb_buf(inbuf),-2);
2487 data = smb_buf(inbuf);
2489 numtowrite = SVAL(inbuf,smb_vwv10);
2490 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2493 /* force the error type */
2494 CVAL(inbuf,smb_com) = SMBwritec;
2495 CVAL(outbuf,smb_com) = SMBwritec;
2497 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2498 END_PROFILE(SMBwritebraw);
2499 return(ERROR(ERRDOS,ERRlock));
2503 nwritten = write_file(fsp,data,startpos,numtowrite);
2505 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2506 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2508 if (nwritten < numtowrite) {
2509 END_PROFILE(SMBwritebraw);
2510 return(UNIXERROR(ERRHRD,ERRdiskfull));
2513 total_written = nwritten;
2515 /* Return a message to the redirector to tell it
2516 to send more bytes */
2517 CVAL(outbuf,smb_com) = SMBwritebraw;
2518 SSVALS(outbuf,smb_vwv0,-1);
2519 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2520 if (!send_smb(smbd_server_fd(),outbuf))
2521 exit_server("reply_writebraw: send_smb failed.\n");
2523 /* Now read the raw data into the buffer and write it */
2524 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2525 exit_server("secondary writebraw failed");
2528 /* Even though this is not an smb message, smb_len
2529 returns the generic length of an smb message */
2530 numtowrite = smb_len(inbuf);
2532 if (tcount > nwritten+numtowrite) {
2533 DEBUG(3,("Client overestimated the write %d %d %d\n",
2534 (int)tcount,(int)nwritten,(int)numtowrite));
2537 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2538 (SMB_OFF_T)numtowrite,NULL,0,
2540 total_written += nwritten;
2542 /* Set up outbuf to return the correct return */
2543 outsize = set_message(outbuf,1,0,True);
2544 CVAL(outbuf,smb_com) = SMBwritec;
2545 SSVAL(outbuf,smb_vwv0,total_written);
2547 if (nwritten < (ssize_t)numtowrite) {
2548 CVAL(outbuf,smb_rcls) = ERRHRD;
2549 SSVAL(outbuf,smb_err,ERRdiskfull);
2552 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2553 lp_strict_sync(SNUM(conn)))
2554 sync_file(conn,fsp);
2556 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2557 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2559 /* we won't return a status if write through is not selected - this
2560 follows what WfWg does */
2561 END_PROFILE(SMBwritebraw);
2562 if (!write_through && total_written==tcount) {
2569 /****************************************************************************
2570 reply to a writeunlock (core+)
2571 ****************************************************************************/
2573 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2575 ssize_t nwritten = -1;
2581 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2583 START_PROFILE(SMBwriteunlock);
2585 CHECK_FSP(fsp,conn);
2589 numtowrite = SVAL(inbuf,smb_vwv1);
2590 startpos = IVAL(inbuf,smb_vwv2);
2591 data = smb_buf(inbuf) + 3;
2593 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2594 END_PROFILE(SMBwriteunlock);
2595 return(ERROR(ERRDOS,ERRlock));
2598 /* The special X/Open SMB protocol handling of
2599 zero length writes is *NOT* done for
2604 nwritten = write_file(fsp,data,startpos,numtowrite);
2606 if (lp_syncalways(SNUM(conn)))
2607 sync_file(conn,fsp);
2609 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2610 END_PROFILE(SMBwriteunlock);
2611 return(UNIXERROR(ERRDOS,ERRnoaccess));
2614 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) {
2615 END_PROFILE(SMBwriteunlock);
2616 return(ERROR(eclass,ecode));
2619 outsize = set_message(outbuf,1,0,True);
2621 SSVAL(outbuf,smb_vwv0,nwritten);
2623 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2624 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2626 END_PROFILE(SMBwriteunlock);
2630 /****************************************************************************
2632 ****************************************************************************/
2633 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2636 ssize_t nwritten = -1;
2639 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2641 START_PROFILE(SMBwrite);
2643 /* If it's an IPC, pass off the pipe handler. */
2645 END_PROFILE(SMBwrite);
2646 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2649 CHECK_FSP(fsp,conn);
2653 numtowrite = SVAL(inbuf,smb_vwv1);
2654 startpos = IVAL(inbuf,smb_vwv2);
2655 data = smb_buf(inbuf) + 3;
2657 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2658 END_PROFILE(SMBwrite);
2659 return(ERROR(ERRDOS,ERRlock));
2662 /* X/Open SMB protocol says that if smb_vwv1 is
2663 zero then the file size should be extended or
2664 truncated to the size given in smb_vwv[2-3] */
2665 if(numtowrite == 0) {
2666 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2668 nwritten = write_file(fsp,data,startpos,numtowrite);
2670 if (lp_syncalways(SNUM(conn)))
2671 sync_file(conn,fsp);
2673 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2674 END_PROFILE(SMBwrite);
2675 return(UNIXERROR(ERRDOS,ERRnoaccess));
2678 outsize = set_message(outbuf,1,0,True);
2680 SSVAL(outbuf,smb_vwv0,nwritten);
2682 if (nwritten < (ssize_t)numtowrite) {
2683 CVAL(outbuf,smb_rcls) = ERRHRD;
2684 SSVAL(outbuf,smb_err,ERRdiskfull);
2687 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2688 fsp->fnum, (int)numtowrite, (int)nwritten));
2690 END_PROFILE(SMBwrite);
2695 /****************************************************************************
2696 reply to a write and X
2697 ****************************************************************************/
2698 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2700 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2701 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2702 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2703 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2704 ssize_t nwritten = -1;
2705 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2706 unsigned int smblen = smb_len(inbuf);
2708 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2709 START_PROFILE(SMBwriteX);
2711 /* If it's an IPC, pass off the pipe handler. */
2713 END_PROFILE(SMBwriteX);
2714 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2717 CHECK_FSP(fsp,conn);
2721 /* Deal with possible LARGE_WRITEX */
2723 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2725 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2726 END_PROFILE(SMBwriteX);
2727 return(ERROR(ERRDOS,ERRbadmem));
2730 data = smb_base(inbuf) + smb_doff;
2732 if(CVAL(inbuf,smb_wct) == 14) {
2733 #ifdef LARGE_SMB_OFF_T
2735 * This is a large offset (64 bit) write.
2737 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2739 #else /* !LARGE_SMB_OFF_T */
2742 * Ensure we haven't been sent a >32 bit offset.
2745 if(IVAL(inbuf,smb_vwv12) != 0) {
2746 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2747 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2748 END_PROFILE(SMBwriteX);
2749 return(ERROR(ERRDOS,ERRbadaccess));
2752 #endif /* LARGE_SMB_OFF_T */
2755 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2756 END_PROFILE(SMBwriteX);
2757 return(ERROR(ERRDOS,ERRlock));
2760 /* X/Open SMB protocol says that, unlike SMBwrite
2761 if the length is zero then NO truncation is
2762 done, just a write of zero. To truncate a file,
2767 nwritten = write_file(fsp,data,startpos,numtowrite);
2769 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2770 END_PROFILE(SMBwriteX);
2771 return(UNIXERROR(ERRDOS,ERRnoaccess));
2774 set_message(outbuf,6,0,True);
2776 SSVAL(outbuf,smb_vwv2,nwritten);
2778 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2780 if (nwritten < (ssize_t)numtowrite) {
2781 CVAL(outbuf,smb_rcls) = ERRHRD;
2782 SSVAL(outbuf,smb_err,ERRdiskfull);
2785 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2786 fsp->fnum, (int)numtowrite, (int)nwritten));
2788 if (lp_syncalways(SNUM(conn)) || write_through)
2789 sync_file(conn,fsp);
2791 END_PROFILE(SMBwriteX);
2792 return chain_reply(inbuf,outbuf,length,bufsize);
2796 /****************************************************************************
2798 ****************************************************************************/
2800 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2806 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2807 START_PROFILE(SMBlseek);
2809 CHECK_FSP(fsp,conn);
2812 flush_write_cache(fsp, SEEK_FLUSH);
2814 mode = SVAL(inbuf,smb_vwv1) & 3;
2815 startpos = IVALS(inbuf,smb_vwv2);
2818 case 0: umode = SEEK_SET; break;
2819 case 1: umode = SEEK_CUR; break;
2820 case 2: umode = SEEK_END; break;
2822 umode = SEEK_SET; break;
2825 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2827 * Check for the special case where a seek before the start
2828 * of the file sets the offset to zero. Added in the CIFS spec,
2832 if(errno == EINVAL) {
2833 SMB_OFF_T current_pos = startpos;
2835 if(umode == SEEK_CUR) {
2837 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2838 END_PROFILE(SMBlseek);
2839 return(UNIXERROR(ERRDOS,ERRnoaccess));
2842 current_pos += startpos;
2844 } else if (umode == SEEK_END) {
2846 SMB_STRUCT_STAT sbuf;
2848 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2849 END_PROFILE(SMBlseek);
2850 return(UNIXERROR(ERRDOS,ERRnoaccess));
2853 current_pos += sbuf.st_size;
2857 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2861 END_PROFILE(SMBlseek);
2862 return(UNIXERROR(ERRDOS,ERRnoaccess));
2868 outsize = set_message(outbuf,2,0,True);
2869 SIVAL(outbuf,smb_vwv0,res);
2871 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2872 fsp->fnum, (double)startpos, (double)res, mode));
2874 END_PROFILE(SMBlseek);
2878 /****************************************************************************
2880 ****************************************************************************/
2882 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2884 int outsize = set_message(outbuf,0,0,True);
2885 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2886 START_PROFILE(SMBflush);
2889 CHECK_FSP(fsp,conn);
2894 file_sync_all(conn);
2896 sync_file(conn,fsp);
2899 DEBUG(3,("flush\n"));
2900 END_PROFILE(SMBflush);
2905 /****************************************************************************
2907 ****************************************************************************/
2908 int reply_exit(connection_struct *conn,
2909 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2912 START_PROFILE(SMBexit);
2913 outsize = set_message(outbuf,0,0,True);
2915 DEBUG(3,("exit\n"));
2917 END_PROFILE(SMBexit);
2922 /****************************************************************************
2923 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2924 ****************************************************************************/
2925 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2930 int32 eclass = 0, err = 0;
2931 files_struct *fsp = NULL;
2932 START_PROFILE(SMBclose);
2934 outsize = set_message(outbuf,0,0,True);
2936 /* If it's an IPC, pass off to the pipe handler. */
2938 END_PROFILE(SMBclose);
2939 return reply_pipe_close(conn, inbuf,outbuf);
2942 fsp = file_fsp(inbuf,smb_vwv0);
2945 * We can only use CHECK_FSP if we know it's not a directory.
2948 if(!fsp || (fsp->conn != conn)) {
2949 END_PROFILE(SMBclose);
2950 return(ERROR(ERRDOS,ERRbadfid));
2953 if(HAS_CACHED_ERROR(fsp)) {
2954 eclass = fsp->wbmpx_ptr->wr_errclass;
2955 err = fsp->wbmpx_ptr->wr_error;
2958 if(fsp->is_directory || fsp->stat_open) {
2960 * Special case - close NT SMB directory or stat file
2963 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2964 close_file(fsp,True);
2967 * Close ordinary file.
2972 * If there was a modify time outstanding,
2973 * try and set it here.
2975 if(fsp->pending_modtime)
2976 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2979 * Now take care of any time sent in the close.
2981 mtime = make_unix_date3(inbuf+smb_vwv1);
2983 /* try and set the date */
2984 set_filetime(conn, fsp->fsp_name,mtime);
2986 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2988 conn->num_files_open));
2991 * close_file() returns the unix errno if an error
2992 * was detected on close - normally this is due to
2993 * a disk full error. If not then it was probably an I/O error.
2996 if((close_err = close_file(fsp,True)) != 0) {
2998 END_PROFILE(SMBclose);
2999 return (UNIXERROR(ERRHRD,ERRgeneral));
3003 /* We have a cached error */
3005 END_PROFILE(SMBclose);
3006 return(ERROR(eclass,err));
3009 END_PROFILE(SMBclose);
3014 /****************************************************************************
3015 reply to a writeclose (Core+ protocol)
3016 ****************************************************************************/
3018 int reply_writeclose(connection_struct *conn,
3019 char *inbuf,char *outbuf, int size, int dum_buffsize)
3022 ssize_t nwritten = -1;
3028 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3029 START_PROFILE(SMBwriteclose);
3031 CHECK_FSP(fsp,conn);
3035 numtowrite = SVAL(inbuf,smb_vwv1);
3036 startpos = IVAL(inbuf,smb_vwv2);
3037 mtime = make_unix_date3(inbuf+smb_vwv4);
3038 data = smb_buf(inbuf) + 1;
3040 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
3041 END_PROFILE(SMBwriteclose);
3042 return(ERROR(ERRDOS,ERRlock));
3045 nwritten = write_file(fsp,data,startpos,numtowrite);
3047 set_filetime(conn, fsp->fsp_name,mtime);
3049 close_err = close_file(fsp,True);
3051 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3052 fsp->fnum, (int)numtowrite, (int)nwritten,
3053 conn->num_files_open));
3055 if (nwritten <= 0) {
3056 END_PROFILE(SMBwriteclose);
3057 return(UNIXERROR(ERRDOS,ERRnoaccess));
3060 if(close_err != 0) {
3062 END_PROFILE(SMBwriteclose);
3063 return(UNIXERROR(ERRHRD,ERRgeneral));
3066 outsize = set_message(outbuf,1,0,True);
3068 SSVAL(outbuf,smb_vwv0,nwritten);
3069 END_PROFILE(SMBwriteclose);
3074 /****************************************************************************
3076 ****************************************************************************/
3077 int reply_lock(connection_struct *conn,
3078 char *inbuf,char *outbuf, int length, int dum_buffsize)
3080 int outsize = set_message(outbuf,0,0,True);
3081 SMB_BIG_UINT count,offset;
3084 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3085 START_PROFILE(SMBlock);
3087 CHECK_FSP(fsp,conn);
3090 release_level_2_oplocks_on_change(fsp);
3092 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3093 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3095 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3096 fsp->fd, fsp->fnum, (double)offset, (double)count));
3098 if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &eclass, &ecode)) {
3099 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
3101 * A blocking lock was requested. Package up
3102 * this smb into a queued request and push it
3103 * onto the blocking lock queue.
3105 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
3106 END_PROFILE(SMBlock);
3110 END_PROFILE(SMBlock);
3111 return (ERROR(eclass,ecode));
3114 END_PROFILE(SMBlock);
3119 /****************************************************************************
3121 ****************************************************************************/
3122 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3124 int outsize = set_message(outbuf,0,0,True);
3125 SMB_BIG_UINT count,offset;
3128 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3129 START_PROFILE(SMBunlock);
3131 CHECK_FSP(fsp,conn);
3134 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3135 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3137 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, &eclass, &ecode)) {
3138 END_PROFILE(SMBunlock);
3139 return (ERROR(eclass,ecode));
3142 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3143 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3145 END_PROFILE(SMBunlock);
3150 /****************************************************************************
3152 ****************************************************************************/
3153 int reply_tdis(connection_struct *conn,
3154 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3156 int outsize = set_message(outbuf,0,0,True);
3158 START_PROFILE(SMBtdis);
3160 vuid = SVAL(inbuf,smb_uid);
3163 DEBUG(4,("Invalid connection in tdis\n"));
3164 END_PROFILE(SMBtdis);
3165 return(ERROR(ERRSRV,ERRinvnid));
3170 close_cnum(conn,vuid);
3172 END_PROFILE(SMBtdis);
3178 /****************************************************************************
3180 ****************************************************************************/
3181 int reply_echo(connection_struct *conn,
3182 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3184 int smb_reverb = SVAL(inbuf,smb_vwv0);
3186 unsigned int data_len = smb_buflen(inbuf);
3187 int outsize = set_message(outbuf,1,data_len,True);
3188 START_PROFILE(SMBecho);
3190 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3192 /* copy any incoming data back out */
3194 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3196 if (smb_reverb > 100) {
3197 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3201 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3202 SSVAL(outbuf,smb_vwv0,seq_num);
3204 smb_setlen(outbuf,outsize - 4);
3206 if (!send_smb(smbd_server_fd(),outbuf))
3207 exit_server("reply_echo: send_smb failed.\n");
3210 DEBUG(3,("echo %d times\n", smb_reverb));
3214 END_PROFILE(SMBecho);
3219 /****************************************************************************
3220 reply to a printopen
3221 ****************************************************************************/
3222 int reply_printopen(connection_struct *conn,
3223 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3227 START_PROFILE(SMBsplopen);
3229 if (!CAN_PRINT(conn)) {
3230 END_PROFILE(SMBsplopen);
3231 return(ERROR(ERRDOS,ERRnoaccess));
3234 /* Open for exclusive use, write only. */
3235 fsp = print_fsp_open(conn);
3238 END_PROFILE(SMBsplopen);
3239 return(UNIXERROR(ERRDOS,ERRnoaccess));
3242 outsize = set_message(outbuf,1,0,True);
3243 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3245 DEBUG(3,("openprint fd=%d fnum=%d\n",
3246 fsp->fd, fsp->fnum));
3248 END_PROFILE(SMBsplopen);
3253 /****************************************************************************
3254 reply to a printclose
3255 ****************************************************************************/
3256 int reply_printclose(connection_struct *conn,
3257 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3259 int outsize = set_message(outbuf,0,0,True);
3260 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3262 START_PROFILE(SMBsplclose);
3264 CHECK_FSP(fsp,conn);
3267 if (!CAN_PRINT(conn)) {
3268 END_PROFILE(SMBsplclose);
3269 return(ERROR(ERRDOS,ERRnoaccess));
3272 DEBUG(3,("printclose fd=%d fnum=%d\n",
3273 fsp->fd,fsp->fnum));
3275 close_err = close_file(fsp,True);
3277 if(close_err != 0) {
3279 END_PROFILE(SMBsplclose);
3280 return(UNIXERROR(ERRHRD,ERRgeneral));
3283 END_PROFILE(SMBsplclose);
3288 /****************************************************************************
3289 reply to a printqueue
3290 ****************************************************************************/
3291 int reply_printqueue(connection_struct *conn,
3292 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3294 int outsize = set_message(outbuf,2,3,True);
3295 int max_count = SVAL(inbuf,smb_vwv0);
3296 int start_index = SVAL(inbuf,smb_vwv1);
3297 START_PROFILE(SMBsplretq);
3299 /* we used to allow the client to get the cnum wrong, but that
3300 is really quite gross and only worked when there was only
3301 one printer - I think we should now only accept it if they
3302 get it right (tridge) */
3303 if (!CAN_PRINT(conn)) {
3304 END_PROFILE(SMBsplretq);
3305 return(ERROR(ERRDOS,ERRnoaccess));
3308 SSVAL(outbuf,smb_vwv0,0);
3309 SSVAL(outbuf,smb_vwv1,0);
3310 CVAL(smb_buf(outbuf),0) = 1;
3311 SSVAL(smb_buf(outbuf),1,0);
3313 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3314 start_index, max_count));
3317 print_queue_struct *queue = NULL;
3318 char *p = smb_buf(outbuf) + 3;
3319 int count = print_queue_status(SNUM(conn), &queue,NULL);
3320 int num_to_get = ABS(max_count);
3321 int first = (max_count>0?start_index:start_index+max_count+1);
3327 num_to_get = MIN(num_to_get,count-first);
3330 for (i=first;i<first+num_to_get;i++) {
3331 put_dos_date2(p,0,queue[i].time);
3332 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3333 SSVAL(p,5, queue[i].job);
3334 SIVAL(p,7,queue[i].size);
3336 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_CONVERT|STR_ASCII);
3341 outsize = set_message(outbuf,2,28*count+3,False);
3342 SSVAL(outbuf,smb_vwv0,count);
3343 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3344 CVAL(smb_buf(outbuf),0) = 1;
3345 SSVAL(smb_buf(outbuf),1,28*count);
3348 if (queue) free(queue);
3350 DEBUG(3,("%d entries returned in queue\n",count));
3353 END_PROFILE(SMBsplretq);
3358 /****************************************************************************
3359 reply to a printwrite
3360 ****************************************************************************/
3361 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3364 int outsize = set_message(outbuf,0,0,True);
3366 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3367 START_PROFILE(SMBsplwr);
3369 if (!CAN_PRINT(conn)) {
3370 END_PROFILE(SMBsplwr);
3371 return(ERROR(ERRDOS,ERRnoaccess));
3374 CHECK_FSP(fsp,conn);
3378 numtowrite = SVAL(smb_buf(inbuf),1);
3379 data = smb_buf(inbuf) + 3;
3381 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3382 END_PROFILE(SMBsplwr);
3383 return(UNIXERROR(ERRDOS,ERRnoaccess));
3386 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3388 END_PROFILE(SMBsplwr);
3393 /****************************************************************************
3394 The guts of the mkdir command, split out so it may be called by the NT SMB
3396 ****************************************************************************/
3397 int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
3399 BOOL bad_path = False;
3400 SMB_STRUCT_STAT sbuf;
3403 unix_convert(directory,conn,0,&bad_path,&sbuf);
3405 if (check_name(directory, conn))
3406 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3410 if((errno == ENOENT) && bad_path)
3412 unix_ERR_class = ERRDOS;
3413 unix_ERR_code = ERRbadpath;
3415 return(UNIXERROR(ERRDOS,ERRnoaccess));
3421 /****************************************************************************
3423 ****************************************************************************/
3424 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3428 START_PROFILE(SMBmkdir);
3430 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3432 outsize=mkdir_internal(conn, inbuf, outbuf, directory);
3434 outsize = set_message(outbuf,0,0,True);
3436 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3438 END_PROFILE(SMBmkdir);
3442 /****************************************************************************
3443 Static function used by reply_rmdir to delete an entire directory
3445 ****************************************************************************/
3447 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3451 void *dirptr = OpenDir(NULL, directory, False);
3456 while((dname = ReadDirName(dirptr)))
3461 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3464 /* Construct the full name. */
3465 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3471 pstrcpy(fullname, directory);
3472 pstrcat(fullname, "/");
3473 pstrcat(fullname, dname);
3475 if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname,False), &st) != 0)
3481 if(st.st_mode & S_IFDIR)
3483 if(recursive_rmdir(conn, fullname)!=0)
3488 if(vfs_rmdir(conn,fullname) != 0)
3494 else if(vfs_unlink(conn,fullname) != 0)
3504 /****************************************************************************
3505 The internals of the rmdir code - called elsewhere.
3506 ****************************************************************************/
3508 BOOL rmdir_internals(connection_struct *conn, char *directory)
3512 ok = (vfs_rmdir(conn,directory) == 0);
3513 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3516 * Check to see if the only thing in this directory are
3517 * vetoed files/directories. If so then delete them and
3518 * retry. If we fail to delete any of them (and we *don't*
3519 * do a recursive delete) then fail the rmdir.
3521 BOOL all_veto_files = True;
3523 void *dirptr = OpenDir(conn, directory, False);
3527 int dirpos = TellDir(dirptr);
3528 while ((dname = ReadDirName(dirptr)))
3530 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3532 if(!IS_VETO_PATH(conn, dname))
3534 all_veto_files = False;
3540 SeekDir(dirptr,dirpos);
3541 while ((dname = ReadDirName(dirptr)))
3546 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3549 /* Construct the full name. */
3550 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3555 pstrcpy(fullname, directory);
3556 pstrcat(fullname, "/");
3557 pstrcat(fullname, dname);
3559 if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname, False), &st) != 0)
3561 if(st.st_mode & S_IFDIR)
3563 if(lp_recursive_veto_delete(SNUM(conn)))
3565 if(recursive_rmdir(conn, fullname) != 0)
3568 if(vfs_rmdir(conn,fullname) != 0)
3571 else if(vfs_unlink(conn,fullname) != 0)
3575 /* Retry the rmdir */
3576 ok = (vfs_rmdir(conn,directory) == 0);
3586 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3587 directory,strerror(errno)));
3592 /****************************************************************************
3594 ****************************************************************************/
3596 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3601 BOOL bad_path = False;
3602 SMB_STRUCT_STAT sbuf;
3603 START_PROFILE(SMBrmdir);
3605 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3607 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3609 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3611 if (check_name(directory,conn))
3613 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3614 ok = rmdir_internals(conn, directory);
3619 if((errno == ENOENT) && bad_path)
3621 unix_ERR_class = ERRDOS;
3622 unix_ERR_code = ERRbadpath;
3624 END_PROFILE(SMBrmdir);
3625 return(UNIXERROR(ERRDOS,ERRbadpath));
3628 outsize = set_message(outbuf,0,0,True);
3630 DEBUG( 3, ( "rmdir %s\n", directory ) );
3632 END_PROFILE(SMBrmdir);
3637 /*******************************************************************
3638 resolve wildcards in a filename rename
3639 ********************************************************************/
3640 static BOOL resolve_wildcards(char *name1,char *name2)
3642 fstring root1,root2;
3646 name1 = strrchr(name1,'/');
3647 name2 = strrchr(name2,'/');
3649 if (!name1 || !name2) return(False);
3651 fstrcpy(root1,name1);
3652 fstrcpy(root2,name2);
3653 p = strrchr(root1,'.');
3660 p = strrchr(root2,'.');
3692 pstrcpy(name2,root2);
3695 pstrcat(name2,ext2);
3701 /*******************************************************************
3702 check if a user is allowed to rename a file
3703 ********************************************************************/
3704 static BOOL can_rename(char *fname,connection_struct *conn)
3706 SMB_STRUCT_STAT sbuf;
3708 if (!CAN_WRITE(conn)) return(False);
3710 if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False);
3711 if (!check_file_sharing(conn,fname,True)) return(False);
3715 /****************************************************************************
3716 The guts of the rename command, split out so it may be called by the NT SMB
3718 ****************************************************************************/
3719 int rename_internals(connection_struct *conn,
3720 char *inbuf, char *outbuf, char *name,
3721 char *newname, BOOL replace_if_exists)
3725 pstring newname_last_component;
3728 BOOL bad_path1 = False;
3729 BOOL bad_path2 = False;
3731 int error = ERRnoaccess;
3734 SMB_STRUCT_STAT sbuf1, sbuf2;
3737 *directory = *mask = 0;
3739 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3740 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3743 * Split the old name into directory and last component
3744 * strings. Note that unix_convert may have stripped off a
3745 * leading ./ from both name and newname if the rename is
3746 * at the root of the share. We need to make sure either both
3747 * name and newname contain a / character or neither of them do
3748 * as this is checked in resolve_wildcards().
3751 p = strrchr(name,'/');
3753 pstrcpy(directory,".");
3757 pstrcpy(directory,name);
3759 *p = '/'; /* Replace needed for exceptional test below. */
3763 * We should only check the mangled cache
3764 * here if unix_convert failed. This means
3765 * that the path in 'mask' doesn't exist
3766 * on the file system and so we need to look
3767 * for a possible mangle. This patch from
3768 * Tine Smukavec <valentin.smukavec@hermes.si>.
3771 if (!rc && is_mangled(mask))
3772 check_mangled_cache( mask );
3774 has_wild = ms_has_wild(mask);
3778 * No wildcards - just process the one file.
3780 BOOL is_short_name = is_8_3(name, True);
3782 /* Add a terminating '/' to the directory name. */
3783 pstrcat(directory,"/");
3784 pstrcat(directory,mask);
3786 /* Ensure newname contains a '/' also */
3787 if(strrchr(newname,'/') == 0) {
3790 pstrcpy(tmpstr, "./");
3791 pstrcat(tmpstr, newname);
3792 pstrcpy(newname, tmpstr);
3795 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",
3796 case_sensitive, case_preserve, short_case_preserve, directory,
3797 newname, newname_last_component, is_short_name));
3800 * Check for special case with case preserving and not
3801 * case sensitive, if directory and newname are identical,
3802 * and the old last component differs from the original
3803 * last component only by case, then we should allow
3804 * the rename (user is trying to change the case of the
3807 if((case_sensitive == False) &&
3808 (((case_preserve == True) &&
3809 (is_short_name == False)) ||
3810 ((short_case_preserve == True) &&
3811 (is_short_name == True))) &&
3812 strcsequal(directory, newname)) {
3813 pstring newname_modified_last_component;
3816 * Get the last component of the modified name.
3817 * Note that we guarantee that newname contains a '/'
3820 p = strrchr(newname,'/');
3821 pstrcpy(newname_modified_last_component,p+1);
3823 if(strcsequal(newname_modified_last_component,
3824 newname_last_component) == False) {
3826 * Replace the modified last component with
3829 pstrcpy(p+1, newname_last_component);
3833 pstrcpy(zdirectory, dos_to_unix(directory, False));
3834 if(replace_if_exists) {
3836 * NT SMB specific flag - rename can overwrite
3837 * file with the same name so don't check for
3841 if(resolve_wildcards(directory,newname) &&
3842 can_rename(directory,conn) &&
3843 !conn->vfs_ops.rename(conn,zdirectory,
3844 dos_to_unix(newname,False)))
3847 if (resolve_wildcards(directory,newname) &&
3848 can_rename(directory,conn) &&
3849 !vfs_file_exist(conn,newname,NULL) &&
3850 !conn->vfs_ops.rename(conn,zdirectory,
3851 dos_to_unix(newname,False)))
3855 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3856 directory,newname));
3858 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3859 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3865 * Wildcards - process each file that matches.
3867 void *dirptr = NULL;
3871 if (check_name(directory,conn))
3872 dirptr = OpenDir(conn, directory, True);
3877 if (strequal(mask,"????????.???"))
3880 while ((dname = ReadDirName(dirptr))) {
3883 pstrcpy(fname,dname);
3885 if(!mask_match(fname, mask, case_sensitive))
3888 error = ERRnoaccess;
3889 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3890 if (!can_rename(fname,conn)) {
3891 DEBUG(6,("rename %s refused\n", fname));
3894 pstrcpy(destname,newname);
3896 if (!resolve_wildcards(fname,destname)) {
3897 DEBUG(6,("resolve_wildcards %s %s failed\n",
3902 if (!replace_if_exists &&
3903 vfs_file_exist(conn,destname, NULL)) {
3904 DEBUG(6,("file_exist %s\n", destname));
3909 if (!conn->vfs_ops.rename(conn,dos_to_unix(fname,False),
3910 dos_to_unix(destname,False)))
3912 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3920 return(ERROR(ERRDOS,error));
3922 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3923 unix_ERR_class = ERRDOS;
3924 unix_ERR_code = ERRbadpath;
3926 return(UNIXERROR(ERRDOS,error));
3933 /****************************************************************************
3935 ****************************************************************************/
3937 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3944 START_PROFILE(SMBmv);
3946 p = smb_buf(inbuf) + 1;
3947 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3949 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3951 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3952 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3954 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3956 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3960 * Win2k needs a changenotify request response before it will
3961 * update after a rename..
3964 process_pending_change_notify_queue((time_t)0);
3966 outsize = set_message(outbuf,0,0,True);
3973 /*******************************************************************
3974 copy a file as part of a reply_copy
3975 ******************************************************************/
3977 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3978 int count,BOOL target_is_directory, int *err_ret)
3981 SMB_STRUCT_STAT src_sbuf, sbuf2;
3983 files_struct *fsp1,*fsp2;
3988 pstrcpy(dest,dest1);
3989 if (target_is_directory) {
3990 char *p = strrchr(src,'/');
3999 if (!vfs_file_exist(conn,src,&src_sbuf))
4002 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4003 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
4009 if (!target_is_directory && count)
4010 ofun = FILE_EXISTS_OPEN;
4012 vfs_stat(conn,dest,&sbuf2);
4013 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4014 ofun,src_sbuf.st_mode,0,&Access,&action);
4017 close_file(fsp1,False);
4021 if ((ofun&3) == 1) {
4022 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4023 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
4026 * Stop the copy from occurring.
4029 src_sbuf.st_size = 0;
4033 if (src_sbuf.st_size)
4034 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
4036 close_file(fsp1,False);
4038 * As we are opening fsp1 read-only we only expect
4039 * an error on close on fsp2 if we are out of space.
4040 * Thus we don't look at the error return from the
4043 *err_ret = close_file(fsp2,False);
4045 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4050 /****************************************************************************
4051 reply to a file copy.
4052 ****************************************************************************/
4053 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4058 pstring mask,newname;
4061 int error = ERRnoaccess;
4065 int tid2 = SVAL(inbuf,smb_vwv0);
4066 int ofun = SVAL(inbuf,smb_vwv1);
4067 int flags = SVAL(inbuf,smb_vwv2);
4068 BOOL target_is_directory=False;
4069 BOOL bad_path1 = False;
4070 BOOL bad_path2 = False;
4072 SMB_STRUCT_STAT sbuf1, sbuf2;
4073 START_PROFILE(SMBcopy);
4075 *directory = *mask = 0;
4078 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
4079 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
4081 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4083 if (tid2 != conn->cnum) {
4084 /* can't currently handle inter share copies XXXX */
4085 DEBUG(3,("Rejecting inter-share copy\n"));
4086 END_PROFILE(SMBcopy);
4087 return(ERROR(ERRSRV,ERRinvdevice));
4090 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4091 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4093 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4094 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4096 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4098 if ((flags&1) && target_is_directory) {
4099 END_PROFILE(SMBcopy);
4100 return(ERROR(ERRDOS,ERRbadfile));
4103 if ((flags&2) && !target_is_directory) {
4104 END_PROFILE(SMBcopy);
4105 return(ERROR(ERRDOS,ERRbadpath));
4108 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4109 /* wants a tree copy! XXXX */
4110 DEBUG(3,("Rejecting tree copy\n"));
4111 END_PROFILE(SMBcopy);
4112 return(ERROR(ERRSRV,ERRerror));
4115 p = strrchr(name,'/');
4117 pstrcpy(directory,"./");
4121 pstrcpy(directory,name);
4126 * We should only check the mangled cache
4127 * here if unix_convert failed. This means
4128 * that the path in 'mask' doesn't exist
4129 * on the file system and so we need to look
4130 * for a possible mangle. This patch from
4131 * Tine Smukavec <valentin.smukavec@hermes.si>.
4134 if (!rc && is_mangled(mask))
4135 check_mangled_cache( mask );
4137 has_wild = ms_has_wild(mask);
4140 pstrcat(directory,"/");
4141 pstrcat(directory,mask);
4142 if (resolve_wildcards(directory,newname) &&
4143 copy_file(directory,newname,conn,ofun,
4144 count,target_is_directory,&err)) count++;
4147 END_PROFILE(SMBcopy);
4148 return(UNIXERROR(ERRHRD,ERRgeneral));
4150 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4152 void *dirptr = NULL;
4156 if (check_name(directory,conn))
4157 dirptr = OpenDir(conn, directory, True);
4162 if (strequal(mask,"????????.???"))
4165 while ((dname = ReadDirName(dirptr))) {
4167 pstrcpy(fname,dname);
4169 if(!mask_match(fname, mask, case_sensitive))
4172 error = ERRnoaccess;
4173 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4174 pstrcpy(destname,newname);
4175 if (resolve_wildcards(fname,destname) &&
4176 copy_file(fname,destname,conn,ofun,
4177 count,target_is_directory,&err)) count++;
4178 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4186 /* Error on close... */
4188 END_PROFILE(SMBcopy);
4189 return(UNIXERROR(ERRHRD,ERRgeneral));
4193 END_PROFILE(SMBcopy);
4194 return(ERROR(ERRDOS,error));
4197 if((errno == ENOENT) && (bad_path1 || bad_path2))
4199 unix_ERR_class = ERRDOS;
4200 unix_ERR_code = ERRbadpath;
4202 END_PROFILE(SMBcopy);
4203 return(UNIXERROR(ERRDOS,error));
4207 outsize = set_message(outbuf,1,0,True);
4208 SSVAL(outbuf,smb_vwv0,count);
4210 END_PROFILE(SMBcopy);
4214 /****************************************************************************
4216 ****************************************************************************/
4217 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4223 START_PROFILE(pathworks_setdir);
4226 if (!CAN_SETDIR(snum)) {
4227 END_PROFILE(pathworks_setdir);
4228 return(ERROR(ERRDOS,ERRnoaccess));
4231 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE|STR_CONVERT);
4233 if (strlen(newdir) == 0) {
4236 ok = vfs_directory_exist(conn,newdir,NULL);
4238 string_set(&conn->connectpath,newdir);
4243 END_PROFILE(pathworks_setdir);
4244 return(ERROR(ERRDOS,ERRbadpath));
4247 outsize = set_message(outbuf,0,0,True);
4248 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4250 DEBUG(3,("setdir %s\n", newdir));
4252 END_PROFILE(pathworks_setdir);
4256 /****************************************************************************
4257 Get a lock pid, dealing with large count requests.
4258 ****************************************************************************/
4260 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4262 if(!large_file_format)
4263 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4265 return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
4268 /****************************************************************************
4269 Get a lock count, dealing with large count requests.
4270 ****************************************************************************/
4272 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4274 SMB_BIG_UINT count = 0;
4276 if(!large_file_format) {
4277 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4280 #if defined(HAVE_LONGLONG)
4281 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4282 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4283 #else /* HAVE_LONGLONG */
4286 * NT4.x seems to be broken in that it sends large file (64 bit)
4287 * lockingX calls even if the CAP_LARGE_FILES was *not*
4288 * negotiated. For boxes without large unsigned ints truncate the
4289 * lock count by dropping the top 32 bits.
4292 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4293 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4294 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4295 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4296 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4299 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4300 #endif /* HAVE_LONGLONG */
4306 /****************************************************************************
4307 Get a lock offset, dealing with large offset requests.
4308 ****************************************************************************/
4310 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4312 SMB_BIG_UINT offset = 0;
4316 if(!large_file_format) {
4317 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4320 #if defined(HAVE_LONGLONG)
4321 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4322 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4323 #else /* HAVE_LONGLONG */
4326 * NT4.x seems to be broken in that it sends large file (64 bit)
4327 * lockingX calls even if the CAP_LARGE_FILES was *not*
4328 * negotiated. For boxes without large unsigned ints mangle the
4329 * lock offset by mapping the top 32 bits onto the lower 32.
4332 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4333 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4334 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4337 if((new_low = map_lock_offset(high, low)) == 0) {
4339 return (SMB_BIG_UINT)-1;
4342 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4343 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4344 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4345 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4348 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4349 #endif /* HAVE_LONGLONG */
4355 /****************************************************************************
4356 reply to a lockingX request
4357 ****************************************************************************/
4359 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4361 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4362 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4363 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4364 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4365 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4366 SMB_BIG_UINT count = 0, offset = 0;
4368 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4371 uint32 ecode=0, dummy2;
4372 int eclass=0, dummy1;
4373 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4375 START_PROFILE(SMBlockingX);
4377 CHECK_FSP(fsp,conn);
4380 data = smb_buf(inbuf);
4382 /* Check if this is an oplock break on a file
4383 we have granted an oplock on.
4385 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4387 /* Client can insist on breaking to none. */
4388 BOOL break_to_none = (oplocklevel == 0);
4390 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4391 (unsigned int)oplocklevel, fsp->fnum ));
4394 * Make sure we have granted an exclusive or batch oplock on this file.
4397 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4399 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4400 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4402 /* if this is a pure oplock break request then don't send a reply */
4403 if (num_locks == 0 && num_ulocks == 0) {
4404 END_PROFILE(SMBlockingX);
4407 END_PROFILE(SMBlockingX);
4408 return ERROR(ERRDOS,ERRlock);
4412 if (remove_oplock(fsp, break_to_none) == False) {
4413 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4417 /* if this is a pure oplock break request then don't send a reply */
4418 if (num_locks == 0 && num_ulocks == 0)
4420 /* Sanity check - ensure a pure oplock break is not a
4422 if(CVAL(inbuf,smb_vwv0) != 0xff)
4423 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4424 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4425 END_PROFILE(SMBlockingX);
4431 * We do this check *after* we have checked this is not a oplock break
4432 * response message. JRA.
4435 release_level_2_oplocks_on_change(fsp);
4437 /* Data now points at the beginning of the list
4438 of smb_unlkrng structs */
4439 for(i = 0; i < (int)num_ulocks; i++) {
4440 lock_pid = get_lock_pid( data, i, large_file_format);
4441 count = get_lock_count( data, i, large_file_format);
4442 offset = get_lock_offset( data, i, large_file_format, &err);
4445 * There is no error code marked "stupid client bug".... :-).
4448 END_PROFILE(SMBlockingX);
4449 return ERROR(ERRDOS,ERRnoaccess);
4452 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4453 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4455 if(!do_unlock(fsp,conn,lock_pid,count,offset, &eclass, &ecode)) {
4456 END_PROFILE(SMBlockingX);
4457 return ERROR(eclass,ecode);
4461 /* Setup the timeout in seconds. */
4462 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4464 /* Now do any requested locks */
4465 data += ((large_file_format ? 20 : 10)*num_ulocks);
4467 /* Data now points at the beginning of the list
4468 of smb_lkrng structs */
4470 for(i = 0; i < (int)num_locks; i++) {
4471 lock_pid = get_lock_pid( data, i, large_file_format);
4472 count = get_lock_count( data, i, large_file_format);
4473 offset = get_lock_offset( data, i, large_file_format, &err);
4476 * There is no error code marked "stupid client bug".... :-).
4479 END_PROFILE(SMBlockingX);
4480 return ERROR(ERRDOS,ERRnoaccess);
4483 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
4484 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4486 if(!do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4488 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4490 * A blocking lock was requested. Package up
4491 * this smb into a queued request and push it
4492 * onto the blocking lock queue.
4494 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4495 END_PROFILE(SMBlockingX);
4503 /* If any of the above locks failed, then we must unlock
4504 all of the previous locks (X/Open spec). */
4505 if(i != num_locks && num_locks != 0) {
4507 * Ensure we don't do a remove on the lock that just failed,
4508 * as under POSIX rules, if we have a lock already there, we
4509 * will delete it (and we shouldn't) .....
4511 for(i--; i >= 0; i--) {
4512 lock_pid = get_lock_pid( data, i, large_file_format);
4513 count = get_lock_count( data, i, large_file_format);
4514 offset = get_lock_offset( data, i, large_file_format, &err);
4517 * There is no error code marked "stupid client bug".... :-).
4520 END_PROFILE(SMBlockingX);
4521 return ERROR(ERRDOS,ERRnoaccess);
4524 do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2);
4526 END_PROFILE(SMBlockingX);
4527 return ERROR(eclass,ecode);
4530 set_message(outbuf,2,0,True);
4532 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4533 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4535 END_PROFILE(SMBlockingX);
4536 return chain_reply(inbuf,outbuf,length,bufsize);
4540 /****************************************************************************
4541 reply to a SMBreadbmpx (read block multiplex) request
4542 ****************************************************************************/
4543 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4554 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4555 START_PROFILE(SMBreadBmpx);
4557 /* this function doesn't seem to work - disable by default */
4558 if (!lp_readbmpx()) {
4559 END_PROFILE(SMBreadBmpx);
4560 return(ERROR(ERRSRV,ERRuseSTD));
4563 outsize = set_message(outbuf,8,0,True);
4565 CHECK_FSP(fsp,conn);
4569 startpos = IVAL(inbuf,smb_vwv1);
4570 maxcount = SVAL(inbuf,smb_vwv3);
4572 data = smb_buf(outbuf);
4573 pad = ((long)data)%4;
4574 if (pad) pad = 4 - pad;
4577 max_per_packet = bufsize-(outsize+pad);
4581 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4582 END_PROFILE(SMBreadBmpx);
4583 return(ERROR(ERRDOS,ERRlock));
4588 size_t N = MIN(max_per_packet,tcount-total_read);
4590 nread = read_file(fsp,data,startpos,N);
4592 if (nread <= 0) nread = 0;
4594 if (nread < (ssize_t)N)
4595 tcount = total_read + nread;
4597 set_message(outbuf,8,nread,False);
4598 SIVAL(outbuf,smb_vwv0,startpos);
4599 SSVAL(outbuf,smb_vwv2,tcount);
4600 SSVAL(outbuf,smb_vwv6,nread);
4601 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4603 if (!send_smb(smbd_server_fd(),outbuf))
4604 exit_server("reply_readbmpx: send_smb failed.\n");
4606 total_read += nread;
4609 while (total_read < (ssize_t)tcount);
4611 END_PROFILE(SMBreadBmpx);
4615 /****************************************************************************
4616 reply to a SMBwritebmpx (write block multiplex primary) request
4617 ****************************************************************************/
4619 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4622 ssize_t nwritten = -1;
4629 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4630 START_PROFILE(SMBwriteBmpx);
4632 CHECK_FSP(fsp,conn);
4636 tcount = SVAL(inbuf,smb_vwv1);
4637 startpos = IVAL(inbuf,smb_vwv3);
4638 write_through = BITSETW(inbuf+smb_vwv7,0);
4639 numtowrite = SVAL(inbuf,smb_vwv10);
4640 smb_doff = SVAL(inbuf,smb_vwv11);
4642 data = smb_base(inbuf) + smb_doff;
4644 /* If this fails we need to send an SMBwriteC response,
4645 not an SMBwritebmpx - set this up now so we don't forget */
4646 CVAL(outbuf,smb_com) = SMBwritec;
4648 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4649 END_PROFILE(SMBwriteBmpx);
4650 return(ERROR(ERRDOS,ERRlock));
4653 nwritten = write_file(fsp,data,startpos,numtowrite);
4655 if(lp_syncalways(SNUM(conn)) || write_through)
4656 sync_file(conn,fsp);
4658 if(nwritten < (ssize_t)numtowrite) {
4659 END_PROFILE(SMBwriteBmpx);
4660 return(UNIXERROR(ERRHRD,ERRdiskfull));
4663 /* If the maximum to be written to this file
4664 is greater than what we just wrote then set
4665 up a secondary struct to be attached to this
4666 fd, we will use this to cache error messages etc. */
4667 if((ssize_t)tcount > nwritten)
4669 write_bmpx_struct *wbms;
4670 if(fsp->wbmpx_ptr != NULL)
4671 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4673 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4676 DEBUG(0,("Out of memory in reply_readmpx\n"));
4677 END_PROFILE(SMBwriteBmpx);
4678 return(ERROR(ERRSRV,ERRnoresource));
4680 wbms->wr_mode = write_through;
4681 wbms->wr_discard = False; /* No errors yet */
4682 wbms->wr_total_written = nwritten;
4683 wbms->wr_errclass = 0;
4685 fsp->wbmpx_ptr = wbms;
4688 /* We are returning successfully, set the message type back to
4690 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4692 outsize = set_message(outbuf,1,0,True);
4694 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4696 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4697 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4699 if (write_through && tcount==nwritten) {
4700 /* we need to send both a primary and a secondary response */
4701 smb_setlen(outbuf,outsize - 4);
4702 if (!send_smb(smbd_server_fd(),outbuf))
4703 exit_server("reply_writebmpx: send_smb failed.\n");
4705 /* now the secondary */
4706 outsize = set_message(outbuf,1,0,True);
4707 CVAL(outbuf,smb_com) = SMBwritec;
4708 SSVAL(outbuf,smb_vwv0,nwritten);
4711 END_PROFILE(SMBwriteBmpx);
4716 /****************************************************************************
4717 reply to a SMBwritebs (write block multiplex secondary) request
4718 ****************************************************************************/
4719 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4722 ssize_t nwritten = -1;
4729 write_bmpx_struct *wbms;
4730 BOOL send_response = False;
4731 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4732 START_PROFILE(SMBwriteBs);
4734 CHECK_FSP(fsp,conn);
4737 tcount = SVAL(inbuf,smb_vwv1);
4738 startpos = IVAL(inbuf,smb_vwv2);
4739 numtowrite = SVAL(inbuf,smb_vwv6);
4740 smb_doff = SVAL(inbuf,smb_vwv7);
4742 data = smb_base(inbuf) + smb_doff;
4744 /* We need to send an SMBwriteC response, not an SMBwritebs */
4745 CVAL(outbuf,smb_com) = SMBwritec;
4747 /* This fd should have an auxiliary struct attached,
4748 check that it does */
4749 wbms = fsp->wbmpx_ptr;
4751 END_PROFILE(SMBwriteBs);
4755 /* If write through is set we can return errors, else we must
4757 write_through = wbms->wr_mode;
4759 /* Check for an earlier error */
4760 if(wbms->wr_discard) {
4761 END_PROFILE(SMBwriteBs);
4762 return -1; /* Just discard the packet */
4765 nwritten = write_file(fsp,data,startpos,numtowrite);
4767 if(lp_syncalways(SNUM(conn)) || write_through)
4768 sync_file(conn,fsp);
4770 if (nwritten < (ssize_t)numtowrite)
4774 /* We are returning an error - we can delete the aux struct */
4775 if (wbms) free((char *)wbms);
4776 fsp->wbmpx_ptr = NULL;
4777 END_PROFILE(SMBwriteBs);
4778 return(ERROR(ERRHRD,ERRdiskfull));
4780 END_PROFILE(SMBwriteBs);
4781 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4784 /* Increment the total written, if this matches tcount
4785 we can discard the auxiliary struct (hurrah !) and return a writeC */
4786 wbms->wr_total_written += nwritten;
4787 if(wbms->wr_total_written >= tcount)
4791 outsize = set_message(outbuf,1,0,True);
4792 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4793 send_response = True;
4797 fsp->wbmpx_ptr = NULL;
4801 END_PROFILE(SMBwriteBs);
4805 END_PROFILE(SMBwriteBs);
4810 /****************************************************************************
4811 reply to a SMBsetattrE
4812 ****************************************************************************/
4814 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4816 struct utimbuf unix_times;
4818 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4819 START_PROFILE(SMBsetattrE);
4821 outsize = set_message(outbuf,0,0,True);
4823 CHECK_FSP(fsp,conn);
4826 /* Convert the DOS times into unix times. Ignore create
4827 time as UNIX can't set this.
4829 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4830 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4833 * Patch from Ray Frush <frush@engr.colostate.edu>
4834 * Sometimes times are sent as zero - ignore them.
4837 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4839 /* Ignore request */
4842 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4843 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4845 END_PROFILE(SMBsetattrE);
4848 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4850 /* set modify time = to access time if modify time was 0 */
4851 unix_times.modtime = unix_times.actime;
4854 /* Set the date on this file */
4855 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4856 END_PROFILE(SMBsetattrE);
4857 return(ERROR(ERRDOS,ERRnoaccess));
4860 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4861 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4863 END_PROFILE(SMBsetattrE);
4868 /****************************************************************************
4869 reply to a SMBgetattrE
4870 ****************************************************************************/
4872 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4874 SMB_STRUCT_STAT sbuf;
4877 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4878 START_PROFILE(SMBgetattrE);
4880 outsize = set_message(outbuf,11,0,True);
4882 CHECK_FSP(fsp,conn);
4885 /* Do an fstat on this file */
4886 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4887 END_PROFILE(SMBgetattrE);
4888 return(UNIXERROR(ERRDOS,ERRnoaccess));
4891 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4893 /* Convert the times into dos times. Set create
4894 date to be last modify date as UNIX doesn't save
4896 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4897 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4898 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4901 SIVAL(outbuf,smb_vwv6,0);
4902 SIVAL(outbuf,smb_vwv8,0);
4906 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4907 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4909 SSVAL(outbuf,smb_vwv10, mode);
4911 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4913 END_PROFILE(SMBgetattrE);