3 Unix SMB/Netbios implementation.
5 Main SMB reply routines
6 Copyright (C) Andrew Tridgell 1992-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
30 /* look in server.c for some explanation of these variables */
32 extern int DEBUGLEVEL
;
35 extern char magic_char
;
36 extern BOOL case_sensitive
;
37 extern BOOL case_preserve
;
38 extern BOOL short_case_preserve
;
39 extern userdom_struct current_user_info
;
40 extern pstring global_myname
;
41 extern fstring global_myworkgroup
;
42 extern int global_oplock_break
;
43 uint32 global_client_caps
= 0;
44 unsigned int smb_echo_count
= 0;
46 /****************************************************************************
47 report a possible attack via the password buffer overflow bug
48 ****************************************************************************/
50 static void overflow_attack(int len
)
53 dbgtext( "ERROR: Invalid password length %d.\n", len
);
54 dbgtext( "Your machine may be under attack by someone " );
55 dbgtext( "attempting to exploit an old bug.\n" );
56 dbgtext( "Attack was from IP = %s.\n", client_addr() );
58 exit_server("possible attack");
62 /****************************************************************************
63 reply to an special message
64 ****************************************************************************/
66 int reply_special(char *inbuf
,char *outbuf
)
69 int msg_type
= CVAL(inbuf
,0);
70 int msg_flags
= CVAL(inbuf
,1);
72 extern fstring remote_machine
;
73 extern fstring local_machine
;
79 memset(outbuf
,'\0',smb_size
);
84 case 0x81: /* session request */
85 CVAL(outbuf
,0) = 0x82;
87 if (name_len(inbuf
+4) > 50 ||
88 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
89 DEBUG(0,("Invalid name length in session request\n"));
92 name_extract(inbuf
,4,name1
);
93 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
94 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
97 fstrcpy(remote_machine
,name2
);
98 remote_machine
[15] = 0;
99 trim_string(remote_machine
," "," ");
100 strlower(remote_machine
);
102 fstrcpy(local_machine
,name1
);
103 len
= strlen(local_machine
);
105 name_type
= local_machine
[15];
106 local_machine
[15] = 0;
108 trim_string(local_machine
," "," ");
109 strlower(local_machine
);
111 if (name_type
== 'R') {
112 /* We are being asked for a pathworks session ---
114 CVAL(outbuf
, 0) = 0x83;
118 /* add it as a possible user name if we
119 are in share mode security */
120 if (lp_security() == SEC_SHARE
) {
121 add_session_user(remote_machine
);
124 reload_services(True
);
128 claim_connection(NULL
,"",MAXSTATUS
,True
);
133 case 0x89: /* session keepalive request
134 (some old clients produce this?) */
135 CVAL(outbuf
,0) = 0x85;
139 case 0x82: /* positive session response */
140 case 0x83: /* negative session response */
141 case 0x84: /* retarget session response */
142 DEBUG(0,("Unexpected session response\n"));
145 case 0x85: /* session keepalive */
150 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
151 msg_type
, msg_flags
));
157 /*******************************************************************
158 work out what error to give to a failed connection
159 ********************************************************************/
161 static int connection_error(char *inbuf
,char *outbuf
,int ecode
)
163 if (ecode
== ERRnoipc
|| ecode
== ERRnosuchshare
)
164 return(ERROR(ERRDOS
,ecode
));
166 return(ERROR(ERRSRV
,ecode
));
171 /****************************************************************************
172 parse a share descriptor string
173 ****************************************************************************/
174 static void parse_connect(char *p
,char *service
,char *user
,
175 char *password
,int *pwlen
,char *dev
)
179 DEBUG(4,("parsing connect string %s\n",p
));
181 p2
= strrchr(p
,'\\');
185 fstrcpy(service
,p2
+1);
190 *pwlen
= strlen(password
);
197 p
= strchr(service
,'%');
205 /****************************************************************************
207 ****************************************************************************/
209 int reply_tcon(connection_struct
*conn
,
210 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
212 BOOL doencrypt
= SMBENCRYPT();
218 uint16 vuid
= SVAL(inbuf
,smb_uid
);
221 START_PROFILE(SMBtcon
);
223 *service
= *user
= *password
= *dev
= 0;
225 parse_connect(smb_buf(inbuf
)+1,service
,user
,password
,&pwlen
,dev
);
228 * Ensure the user and password names are in UNIX codepage format.
231 dos_to_unix(user
,True
);
233 dos_to_unix(password
,True
);
236 * Pass the user through the NT -> unix user mapping
240 (void)map_username(user
);
243 * Do any UNIX username case mangling.
245 (void)Get_Pwnam( user
, True
);
247 conn
= make_connection(service
,user
,password
,pwlen
,dev
,vuid
,&ecode
);
250 END_PROFILE(SMBtcon
);
251 return(connection_error(inbuf
,outbuf
,ecode
));
254 outsize
= set_message(outbuf
,2,0,True
);
255 SSVAL(outbuf
,smb_vwv0
,max_recv
);
256 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
257 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
259 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
260 service
, user
, conn
->cnum
));
262 END_PROFILE(SMBtcon
);
266 /****************************************************************************
267 Reply to a tcon and X.
268 ****************************************************************************/
269 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
275 BOOL doencrypt
= SMBENCRYPT();
277 uint16 vuid
= SVAL(inbuf
,smb_uid
);
278 int passlen
= SVAL(inbuf
,smb_vwv3
);
281 START_PROFILE(SMBtconX
);
283 *service
= *user
= *password
= *devicename
= 0;
285 /* we might have to close an old one */
286 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
287 close_cnum(conn
,vuid
);
290 if (passlen
> MAX_PASS_LEN
) {
291 overflow_attack(passlen
);
294 memcpy(password
,smb_buf(inbuf
),passlen
);
296 path
= smb_buf(inbuf
) + passlen
;
299 if (strequal(password
," "))
301 passlen
= strlen(password
);
304 p
= strchr(path
+2,'\\');
306 END_PROFILE(SMBtconX
);
307 return(ERROR(ERRDOS
,ERRnosuchshare
));
309 fstrcpy(service
,p
+1);
310 p
= strchr(service
,'%');
315 StrnCpy(devicename
,path
+ strlen(path
) + 1,6);
316 DEBUG(4,("Got device type %s\n",devicename
));
319 * Ensure the user and password names are in UNIX codepage format.
322 dos_to_unix(user
,True
);
324 dos_to_unix(password
,True
);
327 * Pass the user through the NT -> unix user mapping
331 (void)map_username(user
);
334 * Do any UNIX username case mangling.
336 (void)Get_Pwnam(user
, True
);
338 conn
= make_connection(service
,user
,password
,passlen
,devicename
,vuid
,&ecode
);
341 END_PROFILE(SMBtconX
);
342 return(connection_error(inbuf
,outbuf
,ecode
));
345 if (Protocol
< PROTOCOL_NT1
) {
346 set_message(outbuf
,2,strlen(devicename
)+1,True
);
347 pstrcpy(smb_buf(outbuf
),devicename
);
349 char *fsname
= lp_fstype(SNUM(conn
));
351 set_message(outbuf
,3,3,True
);
354 pstrcpy(p
,devicename
); p
= skip_string(p
,1); /* device name */
355 pstrcpy(p
,fsname
); p
= skip_string(p
,1); /* filesystem type e.g NTFS */
357 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
359 /* what does setting this bit do? It is set by NT4 and
360 may affect the ability to autorun mounted cdroms */
361 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
);
363 init_dfsroot(conn
, inbuf
, outbuf
);
367 DEBUG(3,("tconX service=%s user=%s\n",
370 /* set the incoming and outgoing tid to the just created one */
371 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
372 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
374 END_PROFILE(SMBtconX
);
375 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
379 /****************************************************************************
380 reply to an unknown type
381 ****************************************************************************/
382 int reply_unknown(char *inbuf
,char *outbuf
)
385 type
= CVAL(inbuf
,smb_com
);
387 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
388 smb_fn_name(type
), type
, type
));
390 return(ERROR(ERRSRV
,ERRunknownsmb
));
394 /****************************************************************************
396 ****************************************************************************/
397 int reply_ioctl(connection_struct
*conn
,
398 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
400 uint16 device
= SVAL(inbuf
,smb_vwv1
);
401 uint16 function
= SVAL(inbuf
,smb_vwv2
);
402 uint32 ioctl_code
= (device
<< 16) + function
;
403 int replysize
, outsize
;
405 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
406 START_PROFILE(SMBioctl
);
408 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
412 case IOCTL_QUERY_JOB_INFO
:
416 END_PROFILE(SMBioctl
);
417 return(ERROR(ERRSRV
,ERRnosupport
));
420 outsize
= set_message(outbuf
,8,replysize
+1,True
);
421 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
422 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
423 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
424 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
428 case IOCTL_QUERY_JOB_INFO
:
429 SSVAL(p
,0,fsp
->print_jobid
); /* Job number */
430 StrnCpy(p
+2, global_myname
, 15); /* Our NetBIOS name */
431 StrnCpy(p
+18, lp_servicename(SNUM(conn
)), 13); /* Service name */
435 END_PROFILE(SMBioctl
);
439 /****************************************************************************
440 always return an error: it's just a matter of which one...
441 ****************************************************************************/
442 static int session_trust_account(connection_struct
*conn
, char *inbuf
, char *outbuf
, char *user
,
443 char *smb_passwd
, int smb_passlen
,
444 char *smb_nt_passwd
, int smb_nt_passlen
)
446 struct smb_passwd
*smb_trust_acct
= NULL
; /* check if trust account exists */
447 if (lp_security() == SEC_USER
) {
448 smb_trust_acct
= getsmbpwnam(user
);
450 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user
));
451 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
452 return(ERROR(0, NT_STATUS_LOGON_FAILURE
));
455 if (smb_trust_acct
== NULL
) {
456 /* lkclXXXX: workstation entry doesn't exist */
457 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user
));
458 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
459 return(ERROR(0, NT_STATUS_NO_SUCH_USER
));
461 if ((smb_passlen
!= 24) || (smb_nt_passlen
!= 24)) {
462 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user
));
463 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
464 return(ERROR(0, NT_STATUS_LOGON_FAILURE
));
467 if (!smb_password_ok(smb_trust_acct
, NULL
, (unsigned char *)smb_passwd
, (unsigned char *)smb_nt_passwd
)) {
468 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user
));
469 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
470 return(ERROR(0, NT_STATUS_LOGON_FAILURE
));
473 if (smb_trust_acct
->acct_ctrl
& ACB_DOMTRUST
) {
474 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user
));
475 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
476 return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT
));
479 if (smb_trust_acct
->acct_ctrl
& ACB_SVRTRUST
) {
480 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user
));
481 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
482 return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT
));
485 if (smb_trust_acct
->acct_ctrl
& ACB_WSTRUST
) {
486 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user
));
487 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
488 return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
));
492 /* don't know what to do: indicate logon failure */
493 SSVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
494 return(ERROR(0, NT_STATUS_LOGON_FAILURE
));
497 /****************************************************************************
498 Create a UNIX user on demand.
499 ****************************************************************************/
501 int smb_create_user(char *unix_user
, char *homedir
)
506 pstrcpy(add_script
, lp_adduser_script());
507 if (! *add_script
) return -1;
508 all_string_sub(add_script
, "%u", unix_user
, sizeof(pstring
));
510 all_string_sub(add_script
, "%H", homedir
, sizeof(pstring
));
511 ret
= smbrun(add_script
,NULL
,False
);
512 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script
,ret
));
516 /****************************************************************************
517 Delete a UNIX user on demand.
518 ****************************************************************************/
520 static int smb_delete_user(char *unix_user
)
525 pstrcpy(del_script
, lp_deluser_script());
526 if (! *del_script
) return -1;
527 all_string_sub(del_script
, "%u", unix_user
, sizeof(pstring
));
528 ret
= smbrun(del_script
,NULL
,False
);
529 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script
,ret
));
533 /****************************************************************************
534 Check user is in correct domain if required
535 ****************************************************************************/
537 static BOOL
check_domain_match(char *user
, char *domain
)
540 * If we aren't serving to trusted domains, we must make sure that
541 * the validation request comes from an account in the same domain
542 * as the Samba server
545 if (!lp_allow_trusted_domains() &&
546 !strequal(lp_workgroup(), domain
) ) {
547 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user
, domain
));
554 /****************************************************************************
555 Check for a valid username and password in security=server mode.
556 ****************************************************************************/
558 static BOOL
check_server_security(char *orig_user
, char *domain
, char *unix_user
,
559 char *smb_apasswd
, int smb_apasslen
,
560 char *smb_ntpasswd
, int smb_ntpasslen
)
564 if(lp_security() != SEC_SERVER
)
567 if (!check_domain_match(orig_user
, domain
))
570 ret
= server_validate(orig_user
, domain
,
571 smb_apasswd
, smb_apasslen
,
572 smb_ntpasswd
, smb_ntpasslen
);
577 * User validated ok against Domain controller.
578 * If the admin wants us to try and create a UNIX
579 * user on the fly, do so.
580 * Note that we can never delete users when in server
581 * level security as we never know if it was a failure
582 * due to a bad password, or the user really doesn't exist.
584 if(lp_adduser_script() && !(pwd
= smb_getpwnam(unix_user
,True
))) {
585 smb_create_user(unix_user
, NULL
);
588 if(lp_adduser_script() && pwd
) {
592 * Also call smb_create_user if the users home directory
593 * doesn't exist. Used with winbindd to allow the script to
594 * create the home directory for a user mapped with winbindd.
597 if (pwd
->pw_shell
&& (sys_stat(pwd
->pw_dir
, &st
) == -1) && (errno
== ENOENT
))
598 smb_create_user(unix_user
, pwd
->pw_dir
);
605 /****************************************************************************
606 Check for a valid username and password in security=domain mode.
607 ****************************************************************************/
609 static BOOL
check_domain_security(char *orig_user
, char *domain
, char *unix_user
,
610 char *smb_apasswd
, int smb_apasslen
,
611 char *smb_ntpasswd
, int smb_ntpasslen
)
614 BOOL user_exists
= True
;
617 if(lp_security() != SEC_DOMAIN
)
620 if (!check_domain_match(orig_user
, domain
))
623 ret
= domain_client_validate(orig_user
, domain
,
624 smb_apasswd
, smb_apasslen
,
625 smb_ntpasswd
, smb_ntpasslen
,
630 * User validated ok against Domain controller.
631 * If the admin wants us to try and create a UNIX
632 * user on the fly, do so.
634 if(user_exists
&& lp_adduser_script() && !(pwd
= smb_getpwnam(unix_user
,True
))) {
635 smb_create_user(unix_user
, NULL
);
638 if(lp_adduser_script() && pwd
) {
642 * Also call smb_create_user if the users home directory
643 * doesn't exist. Used with winbindd to allow the script to
644 * create the home directory for a user mapped with winbindd.
647 if (pwd
->pw_shell
&& (sys_stat(pwd
->pw_dir
, &st
) == -1) && (errno
== ENOENT
))
648 smb_create_user(unix_user
, pwd
->pw_dir
);
653 * User failed to validate ok against Domain controller.
654 * If the failure was "user doesn't exist" and admin
655 * wants us to try and delete that UNIX user on the fly,
658 if(!user_exists
&& lp_deluser_script() && smb_getpwnam(unix_user
,True
)) {
659 smb_delete_user(unix_user
);
666 /****************************************************************************
667 Return a bad password error configured for the correct client type.
668 ****************************************************************************/
670 static int bad_password_error(char *inbuf
,char *outbuf
)
672 enum remote_arch_types ra_type
= get_remote_arch();
674 if(((ra_type
== RA_WINNT
) || (ra_type
== RA_WIN2K
)) &&
675 (global_client_caps
& (CAP_NT_SMBS
| CAP_STATUS32
))) {
676 SSVAL(outbuf
,smb_flg2
,FLAGS2_32_BIT_ERROR_CODES
);
677 return(ERROR(0,NT_STATUS_LOGON_FAILURE
));
680 return(ERROR(ERRSRV
,ERRbadpw
));
683 /****************************************************************************
684 reply to a session setup command
685 ****************************************************************************/
687 int reply_sesssetup_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
693 int smb_apasslen
= 0;
695 int smb_ntpasslen
= 0;
696 pstring smb_ntpasswd
;
697 BOOL valid_nt_password
= False
;
701 static BOOL done_sesssetup
= False
;
702 BOOL doencrypt
= SMBENCRYPT();
704 START_PROFILE(SMBsesssetupX
);
709 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
711 if (Protocol
< PROTOCOL_NT1
) {
712 smb_apasslen
= SVAL(inbuf
,smb_vwv7
);
713 if (smb_apasslen
> MAX_PASS_LEN
)
714 overflow_attack(smb_apasslen
);
716 memcpy(smb_apasswd
,smb_buf(inbuf
),smb_apasslen
);
717 smb_apasswd
[smb_apasslen
] = 0;
718 pstrcpy(user
,smb_buf(inbuf
)+smb_apasslen
);
720 * Incoming user is in DOS codepage format. Convert
723 dos_to_unix(user
,True
);
725 if (!doencrypt
&& (lp_security() != SEC_SERVER
)) {
726 smb_apasslen
= strlen(smb_apasswd
);
729 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
730 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
731 enum remote_arch_types ra_type
= get_remote_arch();
732 char *p
= smb_buf(inbuf
);
734 if(global_client_caps
== 0)
735 global_client_caps
= IVAL(inbuf
,smb_vwv11
);
737 /* client_caps is used as final determination if client is NT or Win95.
738 This is needed to return the correct error codes in some
742 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
|| ra_type
== RA_WIN95
) {
743 if(!(global_client_caps
& (CAP_NT_SMBS
| CAP_STATUS32
))) {
744 set_remote_arch( RA_WIN95
);
748 if (passlen1
!= 24 && passlen2
!= 24)
751 if (passlen1
> MAX_PASS_LEN
) {
752 overflow_attack(passlen1
);
755 passlen1
= MIN(passlen1
, MAX_PASS_LEN
);
756 passlen2
= MIN(passlen2
, MAX_PASS_LEN
);
759 /* both Win95 and WinNT stuff up the password lengths for
760 non-encrypting systems. Uggh.
762 if passlen1==24 its a win95 system, and its setting the
763 password length incorrectly. Luckily it still works with the
764 default code because Win95 will null terminate the password
767 if passlen1>0 and passlen2>0 then maybe its a NT box and its
768 setting passlen2 to some random value which really stuffs
769 things up. we need to fix that one. */
771 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 && passlen2
!= 1)
775 if (lp_restrict_anonymous()) {
776 /* there seems to be no reason behind the differences in MS clients formatting
777 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
778 * in particular seems to have an extra null byte between the username and the
779 * domain, or the password length calculation is wrong, which throws off the
780 * string extraction routines below. This makes the value of domain be the
781 * empty string, which fails the restrict anonymous check further down.
782 * This compensates for that, and allows browsing to work in mixed NT and
783 * win95 environments even when restrict anonymous is true. AAB
785 dump_data(100, p
, 0x70);
786 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1
, passlen2
));
787 if (ra_type
== RA_WIN95
&& !passlen1
&& !passlen2
&& p
[0] == 0 && p
[1] == 0) {
788 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
789 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
790 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
795 if(doencrypt
|| ((lp_security() == SEC_SERVER
) || (lp_security() == SEC_DOMAIN
))) {
796 /* Save the lanman2 password and the NT md4 password. */
797 smb_apasslen
= passlen1
;
798 memcpy(smb_apasswd
,p
,smb_apasslen
);
799 smb_apasswd
[smb_apasslen
] = 0;
800 smb_ntpasslen
= passlen2
;
801 memcpy(smb_ntpasswd
,p
+passlen1
,smb_ntpasslen
);
802 smb_ntpasswd
[smb_ntpasslen
] = 0;
805 * Ensure the plaintext passwords are in UNIX format.
808 dos_to_unix(smb_apasswd
,True
);
809 dos_to_unix(smb_ntpasswd
,True
);
813 /* we use the first password that they gave */
814 smb_apasslen
= passlen1
;
815 StrnCpy(smb_apasswd
,p
,smb_apasslen
);
817 * Ensure the plaintext password is in UNIX format.
819 dos_to_unix(smb_apasswd
,True
);
821 /* trim the password */
822 smb_apasslen
= strlen(smb_apasswd
);
824 /* wfwg sometimes uses a space instead of a null */
825 if (strequal(smb_apasswd
," ")) {
831 p
+= passlen1
+ passlen2
;
833 p
= skip_string(p
,1);
835 * Incoming user is in DOS codepage format. Convert
838 dos_to_unix(user
,True
);
841 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
842 domain
,skip_string(p
,1),skip_string(p
,2)));
846 DEBUG(3,("sesssetupX:name=[%s]\n",user
));
848 /* If name ends in $ then I think it's asking about whether a */
849 /* computer with that name (minus the $) has access. For now */
850 /* say yes to everything ending in $. */
852 if (*user
&& (user
[strlen(user
) - 1] == '$') && (smb_apasslen
== 24) && (smb_ntpasslen
== 24)) {
853 END_PROFILE(SMBsesssetupX
);
854 return session_trust_account(conn
, inbuf
, outbuf
, user
,
855 smb_apasswd
, smb_apasslen
,
856 smb_ntpasswd
, smb_ntpasslen
);
859 if (done_sesssetup
&& lp_restrict_anonymous()) {
860 /* tests show that even if browsing is done over already validated connections
861 * without a username and password the domain is still provided, which it
862 * wouldn't be if it was a purely anonymous connection. So, in order to
863 * restrict anonymous, we only deny connections that have no session
864 * information. If a domain has been provided, then it's not a purely
865 * anonymous connection. AAB
867 if (!*user
&& !*smb_apasswd
&& !*domain
) {
868 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
869 END_PROFILE(SMBsesssetupX
);
870 return(ERROR(ERRDOS
,ERRnoaccess
));
874 /* If no username is sent use the guest account */
876 pstrcpy(user
,lp_guestaccount(-1));
877 /* If no user and no password then set guest flag. */
878 if( *smb_apasswd
== 0)
882 pstrcpy(current_user_info
.smb_name
,user
);
884 reload_services(True
);
887 * Save the username before mapping. We will use
888 * the original username sent to us for security=server
889 * and security=domain checking.
892 pstrcpy( orig_user
, user
);
894 /* if the username exists as a domain/username pair on the unix system then use
896 if (!getpwnam(user
)) {
898 slprintf(user2
,sizeof(user2
),"%s%s%s", dos_to_unix(domain
,False
), lp_winbind_separator(), user
);
899 if (getpwnam(user2
)) {
900 DEBUG(3,("Using unix username %s\n", user2
));
901 pstrcpy(user
, user2
);
906 * Pass the user through the NT -> unix user mapping
910 (void)map_username(user
);
913 * Do any UNIX username case mangling.
915 smb_getpwnam(user
, True
);
917 add_session_user(user
);
920 * Check if the given username was the guest user with no password.
923 if(!guest
&& strequal(user
,lp_guestaccount(-1)) && (*smb_apasswd
== 0))
927 * Check with orig_user for security=server and
932 !check_server_security(orig_user
, domain
, user
,
933 smb_apasswd
, smb_apasslen
,
934 smb_ntpasswd
, smb_ntpasslen
) &&
935 !check_domain_security(orig_user
, domain
, user
,
936 smb_apasswd
, smb_apasslen
,
937 smb_ntpasswd
, smb_ntpasslen
) &&
938 !check_hosts_equiv(user
)
943 * If we get here then the user wasn't guest and the remote
944 * authentication methods failed. Check the authentication
945 * methods on this local server.
947 * If an NT password was supplied try and validate with that
948 * first. This is superior as the passwords are mixed case
949 * 128 length unicode.
954 if(!password_ok(user
, smb_ntpasswd
,smb_ntpasslen
,NULL
))
955 DEBUG(2,("NT Password did not match for user '%s' ! Defaulting to Lanman\n", user
));
957 valid_nt_password
= True
;
960 if (!valid_nt_password
&& !password_ok(user
, smb_apasswd
,smb_apasslen
,NULL
))
962 if (lp_security() >= SEC_USER
)
964 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST
)
966 DEBUG(1,("Rejecting user '%s': authentication failed\n", user
));
967 END_PROFILE(SMBsesssetupX
);
968 return bad_password_error(inbuf
,outbuf
);
971 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER
)
973 if (smb_getpwnam(user
,True
))
975 DEBUG(1,("Rejecting user '%s': bad password\n", user
));
976 END_PROFILE(SMBsesssetupX
);
977 return bad_password_error(inbuf
,outbuf
);
982 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
983 * Then always map to guest account - as done below.
987 if (*smb_apasswd
|| !smb_getpwnam(user
,True
))
988 pstrcpy(user
,lp_guestaccount(-1));
989 DEBUG(3,("Registered username %s for guest access\n",user
));
994 if (!smb_getpwnam(user
,True
)) {
995 DEBUG(3,("No such user %s [%s] - using guest account\n",user
, domain
));
996 pstrcpy(user
,lp_guestaccount(-1));
1000 if (!strequal(user
,lp_guestaccount(-1)) &&
1001 lp_servicenumber(user
) < 0)
1003 add_home_service(user
,get_user_home_dir(user
));
1007 /* it's ok - setup a reply */
1008 if (Protocol
< PROTOCOL_NT1
) {
1009 set_message(outbuf
,3,0,True
);
1012 set_message(outbuf
,3,3,True
);
1013 p
= smb_buf(outbuf
);
1014 pstrcpy(p
,"Unix"); p
= skip_string(p
,1);
1015 pstrcpy(p
,"Samba "); pstrcat(p
,VERSION
); p
= skip_string(p
,1);
1016 pstrcpy(p
,global_myworkgroup
); p
= skip_string(p
,1);
1017 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
1018 /* perhaps grab OS version here?? */
1021 /* Set the correct uid in the outgoing and incoming packets
1022 We will use this on future requests to determine which
1023 user we should become.
1026 const struct passwd
*pw
= smb_getpwnam(user
,False
);
1028 DEBUG(1,("Username %s is invalid on this system\n",user
));
1029 END_PROFILE(SMBsesssetupX
);
1030 return bad_password_error(inbuf
,outbuf
);
1037 SSVAL(outbuf
,smb_vwv2
,1);
1039 /* register the name and uid as being validated, so further connections
1040 to a uid can get through without a password, on the same VC */
1042 sess_vuid
= register_vuid(uid
,gid
,user
,current_user_info
.smb_name
,domain
,guest
);
1044 SSVAL(outbuf
,smb_uid
,sess_vuid
);
1045 SSVAL(inbuf
,smb_uid
,sess_vuid
);
1047 if (!done_sesssetup
)
1048 max_send
= MIN(max_send
,smb_bufsize
);
1050 DEBUG(6,("Client requested max send size of %d\n", max_send
));
1052 done_sesssetup
= True
;
1054 END_PROFILE(SMBsesssetupX
);
1055 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1059 /****************************************************************************
1061 ****************************************************************************/
1062 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1068 BOOL bad_path
= False
;
1069 SMB_STRUCT_STAT sbuf
;
1070 START_PROFILE(SMBchkpth
);
1072 pstrcpy(name
,smb_buf(inbuf
) + 1);
1074 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
1076 unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1078 mode
= SVAL(inbuf
,smb_vwv0
);
1080 if (check_name(name
,conn
)) {
1081 if (VALID_STAT(sbuf
) || vfs_stat(conn
,name
,&sbuf
) == 0)
1082 ok
= S_ISDIR(sbuf
.st_mode
);
1087 /* We special case this - as when a Windows machine
1088 is parsing a path is steps through the components
1089 one at a time - if a component fails it expects
1090 ERRbadpath, not ERRbadfile.
1094 unix_ERR_class
= ERRDOS
;
1095 unix_ERR_code
= ERRbadpath
;
1099 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1100 if((errno
== ENOTDIR
) && (Protocol
>= PROTOCOL_NT1
) &&
1101 (get_remote_arch() == RA_WINNT
))
1103 unix_ERR_class
= ERRDOS
;
1104 unix_ERR_code
= ERRbaddirectory
;
1108 return(UNIXERROR(ERRDOS
,ERRbadpath
));
1111 outsize
= set_message(outbuf
,0,0,True
);
1113 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
1115 END_PROFILE(SMBchkpth
);
1120 /****************************************************************************
1122 ****************************************************************************/
1123 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1127 SMB_STRUCT_STAT sbuf
;
1132 BOOL bad_path
= False
;
1133 START_PROFILE(SMBgetatr
);
1135 pstrcpy(fname
,smb_buf(inbuf
) + 1);
1137 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1139 /* if((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && dfs_redirect(fname,conn)) return(dfs_path_error(inbuf,outbuf));
1141 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1142 under WfWg - weird! */
1145 mode
= aHIDDEN
| aDIR
;
1146 if (!CAN_WRITE(conn
)) mode
|= aRONLY
;
1153 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1154 if (check_name(fname
,conn
))
1156 if (VALID_STAT(sbuf
) || vfs_stat(conn
,fname
,&sbuf
) == 0)
1158 mode
= dos_mode(conn
,fname
,&sbuf
);
1159 size
= sbuf
.st_size
;
1160 mtime
= sbuf
.st_mtime
;
1166 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
1172 if((errno
== ENOENT
) && bad_path
)
1174 unix_ERR_class
= ERRDOS
;
1175 unix_ERR_code
= ERRbadpath
;
1178 END_PROFILE(SMBgetatr
);
1179 return(UNIXERROR(ERRDOS
,ERRbadfile
));
1182 outsize
= set_message(outbuf
,10,0,True
);
1184 SSVAL(outbuf
,smb_vwv0
,mode
);
1185 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1186 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
1188 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
1189 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
1191 if (Protocol
>= PROTOCOL_NT1
) {
1192 char *p
= strrchr(fname
,'/');
1193 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
1195 if (!is_8_3(fname
, True
))
1196 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
1199 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
1201 END_PROFILE(SMBgetatr
);
1206 /****************************************************************************
1208 ****************************************************************************/
1209 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1216 SMB_STRUCT_STAT sbuf
;
1217 BOOL bad_path
= False
;
1218 START_PROFILE(SMBsetatr
);
1220 pstrcpy(fname
,smb_buf(inbuf
) + 1);
1221 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1223 mode
= SVAL(inbuf
,smb_vwv0
);
1224 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
1226 if (VALID_STAT_OF_DIR(sbuf
))
1228 if (check_name(fname
,conn
))
1229 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
1231 ok
= set_filetime(conn
,fname
,mtime
);
1235 if((errno
== ENOENT
) && bad_path
)
1237 unix_ERR_class
= ERRDOS
;
1238 unix_ERR_code
= ERRbadpath
;
1241 END_PROFILE(SMBsetatr
);
1242 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1245 outsize
= set_message(outbuf
,0,0,True
);
1247 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
1249 END_PROFILE(SMBsetatr
);
1254 /****************************************************************************
1256 ****************************************************************************/
1257 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1260 SMB_BIG_UINT dfree
,dsize
,bsize
;
1261 START_PROFILE(SMBdskattr
);
1263 conn
->vfs_ops
.disk_free(conn
,".",True
,&bsize
,&dfree
,&dsize
);
1265 outsize
= set_message(outbuf
,5,0,True
);
1267 SSVAL(outbuf
,smb_vwv0
,dsize
);
1268 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
1269 SSVAL(outbuf
,smb_vwv2
,512);
1270 SSVAL(outbuf
,smb_vwv3
,dfree
);
1272 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1274 END_PROFILE(SMBdskattr
);
1279 /****************************************************************************
1281 Can be called from SMBsearch, SMBffirst or SMBfunique.
1282 ****************************************************************************/
1283 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1294 BOOL finished
= False
;
1303 BOOL check_descend
= False
;
1304 BOOL expect_close
= False
;
1305 BOOL can_open
= True
;
1306 BOOL bad_path
= False
;
1307 START_PROFILE(SMBsearch
);
1309 *mask
= *directory
= *fname
= 0;
1311 /* If we were called as SMBffirst then we must expect close. */
1312 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
1313 expect_close
= True
;
1315 outsize
= set_message(outbuf
,1,3,True
);
1316 maxentries
= SVAL(inbuf
,smb_vwv0
);
1317 dirtype
= SVAL(inbuf
,smb_vwv1
);
1318 path
= smb_buf(inbuf
) + 1;
1319 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
1322 /* dirtype &= ~aDIR; */
1324 if (status_len
== 0)
1326 SMB_STRUCT_STAT sbuf
;
1329 pstrcpy(directory
,smb_buf(inbuf
)+1);
1330 pstrcpy(dir2
,smb_buf(inbuf
)+1);
1331 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
1334 if (!check_name(directory
,conn
))
1337 p
= strrchr(dir2
,'/');
1349 p
= strrchr(directory
,'/');
1355 if (strlen(directory
) == 0)
1356 pstrcpy(directory
,"./");
1357 memset((char *)status
,'\0',21);
1358 CVAL(status
,0) = dirtype
;
1362 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1363 dirtype
= CVAL(status
,0) & 0x1F;
1364 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1367 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1368 fstrcpy(mask
, dptr_wcard(dptr_num
));
1373 p
= smb_buf(outbuf
) + 3;
1377 if (status_len
== 0)
1379 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
1384 if((errno
== ENOENT
) && bad_path
)
1386 unix_ERR_class
= ERRDOS
;
1387 unix_ERR_code
= ERRbadpath
;
1389 END_PROFILE(SMBsearch
);
1390 return (UNIXERROR(ERRDOS
,ERRnofids
));
1392 END_PROFILE(SMBsearch
);
1393 return(ERROR(ERRDOS
,ERRnofids
));
1395 dptr_set_wcard(dptr_num
, strdup(mask
));
1398 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1402 if ((dirtype
&0x1F) == aVOLID
)
1404 memcpy(p
,status
,21);
1405 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
1406 dptr_fill(p
+12,dptr_num
);
1407 if (dptr_zero(p
+12) && (status_len
==0))
1411 p
+= DIR_STRUCT_SIZE
;
1415 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1416 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1417 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
1418 check_descend
= True
;
1420 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
1423 !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
1426 memcpy(p
,status
,21);
1427 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
1428 dptr_fill(p
+12,dptr_num
);
1431 p
+= DIR_STRUCT_SIZE
;
1440 if (numentries
== 0 || !ok
)
1442 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1443 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1444 dptr_close(&dptr_num
);
1447 /* If we were called as SMBffirst with smb_search_id == NULL
1448 and no entries were found then return error and close dirptr
1451 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
1453 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1454 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1455 /* Also close the dptr - we know it's gone */
1456 dptr_close(&dptr_num
);
1459 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1460 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
1461 dptr_close(&dptr_num
);
1463 SSVAL(outbuf
,smb_vwv0
,numentries
);
1464 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1465 CVAL(smb_buf(outbuf
),0) = 5;
1466 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1468 if (Protocol
>= PROTOCOL_NT1
) {
1469 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
1470 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
1473 outsize
+= DIR_STRUCT_SIZE
*numentries
;
1474 smb_setlen(outbuf
,outsize
- 4);
1476 if ((! *directory
) && dptr_path(dptr_num
))
1477 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1479 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1480 smb_fn_name(CVAL(inbuf
,smb_com
)),
1481 mask
, directory
, dirtype
, numentries
, maxentries
) );
1483 END_PROFILE(SMBsearch
);
1488 /****************************************************************************
1489 reply to a fclose (stop directory search)
1490 ****************************************************************************/
1491 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1498 START_PROFILE(SMBfclose
);
1500 outsize
= set_message(outbuf
,1,0,True
);
1501 path
= smb_buf(inbuf
) + 1;
1502 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
1505 if (status_len
== 0) {
1506 END_PROFILE(SMBfclose
);
1507 return(ERROR(ERRSRV
,ERRsrverror
));
1510 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1512 if(dptr_fetch(status
+12,&dptr_num
)) {
1513 /* Close the dptr - we know it's gone */
1514 dptr_close(&dptr_num
);
1517 SSVAL(outbuf
,smb_vwv0
,0);
1519 DEBUG(3,("search close\n"));
1521 END_PROFILE(SMBfclose
);
1526 /****************************************************************************
1528 ****************************************************************************/
1530 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1540 SMB_STRUCT_STAT sbuf
;
1541 BOOL bad_path
= False
;
1543 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1544 START_PROFILE(SMBopen
);
1546 share_mode
= SVAL(inbuf
,smb_vwv0
);
1548 pstrcpy(fname
,smb_buf(inbuf
)+1);
1550 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1552 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1554 unixmode
= unix_mode(conn
,aARCH
,fname
);
1556 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1557 unixmode
, oplock_request
,&rmode
,NULL
);
1561 if((errno
== ENOENT
) && bad_path
)
1563 unix_ERR_class
= ERRDOS
;
1564 unix_ERR_code
= ERRbadpath
;
1566 END_PROFILE(SMBopen
);
1567 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1570 size
= sbuf
.st_size
;
1571 fmode
= dos_mode(conn
,fname
,&sbuf
);
1572 mtime
= sbuf
.st_mtime
;
1575 DEBUG(3,("attempt to open a directory %s\n",fname
));
1576 close_file(fsp
,False
);
1577 END_PROFILE(SMBopen
);
1578 return(ERROR(ERRDOS
,ERRnoaccess
));
1581 outsize
= set_message(outbuf
,7,0,True
);
1582 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1583 SSVAL(outbuf
,smb_vwv1
,fmode
);
1584 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1585 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1587 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1588 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1589 SSVAL(outbuf
,smb_vwv6
,rmode
);
1591 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1592 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1595 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1596 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1597 END_PROFILE(SMBopen
);
1602 /****************************************************************************
1603 reply to an open and X
1604 ****************************************************************************/
1605 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1608 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1609 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1610 /* Breakout the oplock request bits so we can set the
1611 reply bits separately. */
1612 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1613 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1614 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1616 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1617 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1618 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1620 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1623 int fmode
=0,mtime
=0,rmode
=0;
1624 SMB_STRUCT_STAT sbuf
;
1626 BOOL bad_path
= False
;
1628 START_PROFILE(SMBopenX
);
1630 /* If it's an IPC, pass off the pipe handler. */
1632 if (lp_nt_pipe_support()) {
1633 END_PROFILE(SMBopenX
);
1634 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1636 END_PROFILE(SMBopenX
);
1637 return (ERROR(ERRSRV
,ERRaccess
));
1641 /* XXXX we need to handle passed times, sattr and flags */
1643 pstrcpy(fname
,smb_buf(inbuf
));
1645 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1647 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1649 unixmode
= unix_mode(conn
,smb_attr
| aARCH
, fname
);
1651 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,unixmode
,
1652 oplock_request
, &rmode
,&smb_action
);
1656 if((errno
== ENOENT
) && bad_path
)
1658 unix_ERR_class
= ERRDOS
;
1659 unix_ERR_code
= ERRbadpath
;
1661 END_PROFILE(SMBopenX
);
1662 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1665 size
= sbuf
.st_size
;
1666 fmode
= dos_mode(conn
,fname
,&sbuf
);
1667 mtime
= sbuf
.st_mtime
;
1669 close_file(fsp
,False
);
1670 END_PROFILE(SMBopenX
);
1671 return(ERROR(ERRDOS
,ERRnoaccess
));
1674 /* If the caller set the extended oplock request bit
1675 and we granted one (by whatever means) - set the
1676 correct bit for extended oplock reply.
1679 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1680 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1683 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1684 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1687 /* If the caller set the core oplock request bit
1688 and we granted one (by whatever means) - set the
1689 correct bit for core oplock reply.
1692 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1693 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1696 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1697 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1700 set_message(outbuf
,15,0,True
);
1701 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1702 SSVAL(outbuf
,smb_vwv3
,fmode
);
1703 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1704 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1706 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1707 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1708 SSVAL(outbuf
,smb_vwv8
,rmode
);
1709 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1711 END_PROFILE(SMBopenX
);
1712 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1716 /****************************************************************************
1717 reply to a SMBulogoffX
1718 ****************************************************************************/
1719 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1721 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1722 user_struct
*vuser
= get_valid_user_struct(vuid
);
1723 START_PROFILE(SMBulogoffX
);
1726 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1729 /* in user level security we are supposed to close any files
1730 open by this user */
1731 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1732 file_close_user(vuid
);
1735 invalidate_vuid(vuid
);
1737 set_message(outbuf
,2,0,True
);
1739 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1741 END_PROFILE(SMBulogoffX
);
1742 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1746 /****************************************************************************
1747 reply to a mknew or a create
1748 ****************************************************************************/
1749 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1757 BOOL bad_path
= False
;
1759 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1760 SMB_STRUCT_STAT sbuf
;
1761 START_PROFILE(SMBcreate
);
1763 com
= SVAL(inbuf
,smb_com
);
1765 createmode
= SVAL(inbuf
,smb_vwv0
);
1766 pstrcpy(fname
,smb_buf(inbuf
)+1);
1768 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1770 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1772 if (createmode
& aVOLID
) {
1773 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1776 unixmode
= unix_mode(conn
,createmode
,fname
);
1780 /* We should fail if file exists. */
1781 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1785 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1786 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1789 /* Open file in dos compatibility share mode. */
1790 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1791 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1795 if((errno
== ENOENT
) && bad_path
)
1797 unix_ERR_class
= ERRDOS
;
1798 unix_ERR_code
= ERRbadpath
;
1800 END_PROFILE(SMBcreate
);
1801 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1804 outsize
= set_message(outbuf
,1,0,True
);
1805 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1807 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1808 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1811 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1812 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1814 DEBUG( 2, ( "new file %s\n", fname
) );
1815 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1816 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1818 END_PROFILE(SMBcreate
);
1823 /****************************************************************************
1824 reply to a create temporary file
1825 ****************************************************************************/
1826 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1833 BOOL bad_path
= False
;
1835 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1836 SMB_STRUCT_STAT sbuf
;
1837 START_PROFILE(SMBctemp
);
1839 createmode
= SVAL(inbuf
,smb_vwv0
);
1840 pstrcpy(fname
,smb_buf(inbuf
)+1);
1841 pstrcat(fname
,"/TMXXXXXX");
1843 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1845 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1847 unixmode
= unix_mode(conn
,createmode
,fname
);
1849 pstrcpy(fname2
,(char *)smbd_mktemp(fname
));
1850 /* This file should not exist. */
1852 vfs_stat(conn
,fname2
,&sbuf
);
1854 /* Open file in dos compatibility share mode. */
1855 /* We should fail if file exists. */
1856 fsp
= open_file_shared(conn
,fname2
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1857 (FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_FAIL
), unixmode
, oplock_request
, NULL
, NULL
);
1861 if((errno
== ENOENT
) && bad_path
)
1863 unix_ERR_class
= ERRDOS
;
1864 unix_ERR_code
= ERRbadpath
;
1866 END_PROFILE(SMBctemp
);
1867 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1870 outsize
= set_message(outbuf
,1,2 + strlen(fname2
),True
);
1871 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1872 CVAL(smb_buf(outbuf
),0) = 4;
1873 pstrcpy(smb_buf(outbuf
) + 1,fname2
);
1875 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1876 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1879 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1880 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1882 DEBUG( 2, ( "created temp file %s\n", fname2
) );
1883 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1884 fname2
, fsp
->fd
, createmode
, (int)unixmode
) );
1886 END_PROFILE(SMBctemp
);
1891 /*******************************************************************
1892 check if a user is allowed to delete a file
1893 ********************************************************************/
1894 static BOOL
can_delete(char *fname
,connection_struct
*conn
, int dirtype
)
1896 SMB_STRUCT_STAT sbuf
;
1899 if (!CAN_WRITE(conn
)) return(False
);
1901 if (conn
->vfs_ops
.lstat(conn
,dos_to_unix(fname
,False
),&sbuf
) != 0) return(False
);
1902 fmode
= dos_mode(conn
,fname
,&sbuf
);
1903 if (fmode
& aDIR
) return(False
);
1904 if (!lp_delete_readonly(SNUM(conn
))) {
1905 if (fmode
& aRONLY
) return(False
);
1907 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1909 if (!check_file_sharing(conn
,fname
,False
)) return(False
);
1913 /****************************************************************************
1914 The guts of the unlink command, split out so it may be called by the NT SMB
1916 ****************************************************************************/
1918 int unlink_internals(connection_struct
*conn
, char *inbuf
,char *outbuf
,
1919 int dirtype
, char *name
)
1925 int error
= ERRnoaccess
;
1928 BOOL bad_path
= False
;
1930 SMB_STRUCT_STAT sbuf
;
1932 *directory
= *mask
= 0;
1934 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1936 p
= strrchr(name
,'/');
1938 pstrcpy(directory
,"./");
1942 pstrcpy(directory
,name
);
1947 * We should only check the mangled cache
1948 * here if unix_convert failed. This means
1949 * that the path in 'mask' doesn't exist
1950 * on the file system and so we need to look
1951 * for a possible mangle. This patch from
1952 * Tine Smukavec <valentin.smukavec@hermes.si>.
1955 if (!rc
&& is_mangled(mask
))
1956 check_mangled_cache( mask
);
1958 has_wild
= ms_has_wild(mask
);
1961 pstrcat(directory
,"/");
1962 pstrcat(directory
,mask
);
1963 if (can_delete(directory
,conn
,dirtype
) && !vfs_unlink(conn
,directory
))
1966 exists
= vfs_file_exist(conn
,directory
,&sbuf
);
1968 void *dirptr
= NULL
;
1971 if (check_name(directory
,conn
))
1972 dirptr
= OpenDir(conn
, directory
, True
);
1974 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1975 the pattern matches against the long name, otherwise the short name
1976 We don't implement this yet XXXX
1983 if (strequal(mask
,"????????.???"))
1986 while ((dname
= ReadDirName(dirptr
)))
1989 pstrcpy(fname
,dname
);
1991 if(!mask_match(fname
, mask
, case_sensitive
)) continue;
1993 error
= ERRnoaccess
;
1994 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1995 if (!can_delete(fname
,conn
,dirtype
)) continue;
1996 if (!vfs_unlink(conn
,fname
)) count
++;
1997 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
2005 return(ERROR(ERRDOS
,error
));
2007 if((errno
== ENOENT
) && bad_path
) {
2008 unix_ERR_class
= ERRDOS
;
2009 unix_ERR_code
= ERRbadpath
;
2011 return(UNIXERROR(ERRDOS
,error
));
2018 /****************************************************************************
2020 ****************************************************************************/
2022 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2027 START_PROFILE(SMBunlink
);
2029 dirtype
= SVAL(inbuf
,smb_vwv0
);
2031 pstrcpy(name
,smb_buf(inbuf
) + 1);
2033 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
2035 DEBUG(3,("reply_unlink : %s\n",name
));
2037 outsize
= unlink_internals(conn
, inbuf
, outbuf
, dirtype
, name
);
2041 * Win2k needs a changenotify request response before it will
2042 * update after a rename..
2045 process_pending_change_notify_queue((time_t)0);
2047 outsize
= set_message(outbuf
,0,0,True
);
2050 END_PROFILE(SMBunlink
);
2055 /****************************************************************************
2056 reply to a readbraw (core+ protocol)
2057 ****************************************************************************/
2059 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
2061 size_t maxcount
,mincount
;
2064 char *header
= outbuf
;
2067 START_PROFILE(SMBreadbraw
);
2070 * Special check if an oplock break has been issued
2071 * and the readraw request croses on the wire, we must
2072 * return a zero length response here.
2075 if(global_oplock_break
)
2077 _smb_setlen(header
,0);
2078 transfer_file(0,smbd_server_fd(),(SMB_OFF_T
)0,header
,4,0);
2079 DEBUG(5,("readbraw - oplock break finished\n"));
2080 END_PROFILE(SMBreadbraw
);
2084 fsp
= file_fsp(inbuf
,smb_vwv0
);
2086 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
2088 * fsp could be NULL here so use the value from the packet. JRA.
2090 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
2091 _smb_setlen(header
,0);
2092 transfer_file(0,smbd_server_fd(),(SMB_OFF_T
)0,header
,4,0);
2093 END_PROFILE(SMBreadbraw
);
2097 CHECK_FSP(fsp
,conn
);
2099 flush_write_cache(fsp
, READRAW_FLUSH
);
2101 startpos
= IVAL(inbuf
,smb_vwv1
);
2102 if(CVAL(inbuf
,smb_wct
) == 10) {
2104 * This is a large offset (64 bit) read.
2106 #ifdef LARGE_SMB_OFF_T
2108 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
2110 #else /* !LARGE_SMB_OFF_T */
2113 * Ensure we haven't been sent a >32 bit offset.
2116 if(IVAL(inbuf
,smb_vwv8
) != 0) {
2117 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2118 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
2119 _smb_setlen(header
,0);
2120 transfer_file(0,smbd_server_fd(),(SMB_OFF_T
)0,header
,4,0);
2121 END_PROFILE(SMBreadbraw
);
2125 #endif /* LARGE_SMB_OFF_T */
2128 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2129 (double)startpos
));
2130 _smb_setlen(header
,0);
2131 transfer_file(0,smbd_server_fd(),(SMB_OFF_T
)0,header
,4,0);
2132 END_PROFILE(SMBreadbraw
);
2136 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
2137 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
2139 /* ensure we don't overrun the packet size */
2140 maxcount
= MIN(65535,maxcount
);
2141 maxcount
= MAX(mincount
,maxcount
);
2143 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
))
2145 SMB_OFF_T size
= fsp
->size
;
2146 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
2148 if (size
< sizeneeded
)
2151 if (vfs_fstat(fsp
,fsp
->fd
,&st
) == 0)
2153 if (!fsp
->can_write
)
2157 nread
= MIN(maxcount
,(size
- startpos
));
2160 if (nread
< mincount
)
2163 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2164 fsp
->fnum
, (double)startpos
,
2165 (int)maxcount
, (int)mincount
, (int)nread
) );
2169 BOOL seek_fail
= False
;
2171 _smb_setlen(header
,nread
);
2173 if ((nread
-predict
) > 0) {
2174 if(conn
->vfs_ops
.seek(fsp
,fsp
->fd
,startpos
+ predict
) == -1) {
2175 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2182 ret
= (ssize_t
)vfs_transfer_file(-1, fsp
, fsp
->fd
, Client
, NULL
,
2183 (SMB_OFF_T
)(nread
-predict
),header
,4+predict
,
2188 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2189 fsp
->fsp_name
,startpos
,nread
,ret
));
2191 #else /* UNSAFE_READRAW */
2192 ret
= read_file(fsp
,header
+4,startpos
,nread
);
2193 if (ret
< mincount
) ret
= 0;
2195 _smb_setlen(header
,ret
);
2196 transfer_file(0,smbd_server_fd(),0,header
,4+ret
,0);
2197 #endif /* UNSAFE_READRAW */
2199 DEBUG(5,("readbraw finished\n"));
2200 END_PROFILE(SMBreadbraw
);
2205 /****************************************************************************
2206 reply to a lockread (core+ protocol)
2207 ****************************************************************************/
2208 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
2217 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2218 START_PROFILE(SMBlockread
);
2220 CHECK_FSP(fsp
,conn
);
2224 release_level_2_oplocks_on_change(fsp
);
2226 numtoread
= SVAL(inbuf
,smb_vwv1
);
2227 startpos
= IVAL(inbuf
,smb_vwv2
);
2229 outsize
= set_message(outbuf
,5,3,True
);
2230 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2231 data
= smb_buf(outbuf
) + 3;
2234 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2235 * protocol request that predates the read/write lock concept.
2236 * Thus instead of asking for a read lock here we need to ask
2237 * for a write lock. JRA.
2240 if(!do_lock( fsp
, conn
, (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
, &eclass
, &ecode
)) {
2241 if((ecode
== ERRlock
) && lp_blocking_locks(SNUM(conn
))) {
2243 * A blocking lock was requested. Package up
2244 * this smb into a queued request and push it
2245 * onto the blocking lock queue.
2247 if(push_blocking_lock_request(inbuf
, length
, -1, 0))
2248 END_PROFILE(SMBlockread
);
2251 END_PROFILE(SMBlockread
);
2252 return (ERROR(eclass
,ecode
));
2255 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2258 END_PROFILE(SMBlockread
);
2259 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2263 SSVAL(outbuf
,smb_vwv0
,nread
);
2264 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2265 SSVAL(smb_buf(outbuf
),1,nread
);
2267 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2268 fsp
->fnum
, (int)numtoread
, (int)nread
) );
2270 END_PROFILE(SMBlockread
);
2275 /****************************************************************************
2277 ****************************************************************************/
2279 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2286 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2287 START_PROFILE(SMBread
);
2289 CHECK_FSP(fsp
,conn
);
2293 numtoread
= SVAL(inbuf
,smb_vwv1
);
2294 startpos
= IVAL(inbuf
,smb_vwv2
);
2296 outsize
= set_message(outbuf
,5,3,True
);
2297 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2298 data
= smb_buf(outbuf
) + 3;
2300 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
2301 END_PROFILE(SMBread
);
2302 return(ERROR(ERRDOS
,ERRlock
));
2306 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2309 END_PROFILE(SMBread
);
2310 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2314 SSVAL(outbuf
,smb_vwv0
,nread
);
2315 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2316 CVAL(smb_buf(outbuf
),0) = 1;
2317 SSVAL(smb_buf(outbuf
),1,nread
);
2319 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2320 fsp
->fnum
, (int)numtoread
, (int)nread
) );
2322 END_PROFILE(SMBread
);
2327 /****************************************************************************
2328 reply to a read and X
2329 ****************************************************************************/
2330 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2332 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2333 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2334 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2335 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2338 START_PROFILE(SMBreadX
);
2340 /* If it's an IPC, pass off the pipe handler. */
2342 END_PROFILE(SMBreadX
);
2343 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2346 CHECK_FSP(fsp
,conn
);
2350 set_message(outbuf
,12,0,True
);
2351 data
= smb_buf(outbuf
);
2353 if(CVAL(inbuf
,smb_wct
) == 12) {
2354 #ifdef LARGE_SMB_OFF_T
2356 * This is a large offset (64 bit) read.
2358 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2360 #else /* !LARGE_SMB_OFF_T */
2363 * Ensure we haven't been sent a >32 bit offset.
2366 if(IVAL(inbuf
,smb_vwv10
) != 0) {
2367 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2368 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
2369 END_PROFILE(SMBreadX
);
2370 return(ERROR(ERRDOS
,ERRbadaccess
));
2373 #endif /* LARGE_SMB_OFF_T */
2377 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
2378 END_PROFILE(SMBreadX
);
2379 return(ERROR(ERRDOS
,ERRlock
));
2381 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2384 END_PROFILE(SMBreadX
);
2385 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2388 SSVAL(outbuf
,smb_vwv5
,nread
);
2389 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2390 SSVAL(smb_buf(outbuf
),-2,nread
);
2392 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2393 fsp
->fnum
, (int)smb_mincnt
, (int)smb_maxcnt
, (int)nread
) );
2395 END_PROFILE(SMBreadX
);
2396 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2399 /****************************************************************************
2400 reply to a writebraw (core+ or LANMAN1.0 protocol)
2401 ****************************************************************************/
2403 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2406 ssize_t total_written
=0;
2407 size_t numtowrite
=0;
2412 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2414 START_PROFILE(SMBwritebraw
);
2416 CHECK_FSP(fsp
,conn
);
2420 tcount
= IVAL(inbuf
,smb_vwv1
);
2421 startpos
= IVAL(inbuf
,smb_vwv3
);
2422 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2424 /* We have to deal with slightly different formats depending
2425 on whether we are using the core+ or lanman1.0 protocol */
2426 if(Protocol
<= PROTOCOL_COREPLUS
) {
2427 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2428 data
= smb_buf(inbuf
);
2430 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2431 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2434 /* force the error type */
2435 CVAL(inbuf
,smb_com
) = SMBwritec
;
2436 CVAL(outbuf
,smb_com
) = SMBwritec
;
2438 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
2439 END_PROFILE(SMBwritebraw
);
2440 return(ERROR(ERRDOS
,ERRlock
));
2444 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2446 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2447 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2449 if (nwritten
< numtowrite
) {
2450 END_PROFILE(SMBwritebraw
);
2451 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2454 total_written
= nwritten
;
2456 /* Return a message to the redirector to tell it
2457 to send more bytes */
2458 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
2459 SSVALS(outbuf
,smb_vwv0
,-1);
2460 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2461 send_smb(smbd_server_fd(),outbuf
);
2463 /* Now read the raw data into the buffer and write it */
2464 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2465 exit_server("secondary writebraw failed");
2468 /* Even though this is not an smb message, smb_len
2469 returns the generic length of an smb message */
2470 numtowrite
= smb_len(inbuf
);
2472 if (tcount
> nwritten
+numtowrite
) {
2473 DEBUG(3,("Client overestimated the write %d %d %d\n",
2474 (int)tcount
,(int)nwritten
,(int)numtowrite
));
2477 nwritten
= vfs_transfer_file(smbd_server_fd(), NULL
, -1, fsp
,
2478 (SMB_OFF_T
)numtowrite
,NULL
,0,
2480 total_written
+= nwritten
;
2482 /* Set up outbuf to return the correct return */
2483 outsize
= set_message(outbuf
,1,0,True
);
2484 CVAL(outbuf
,smb_com
) = SMBwritec
;
2485 SSVAL(outbuf
,smb_vwv0
,total_written
);
2487 if (nwritten
< (ssize_t
)numtowrite
) {
2488 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2489 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2492 if ((lp_syncalways(SNUM(conn
)) || write_through
) &&
2493 lp_strict_sync(SNUM(conn
)))
2494 sync_file(conn
,fsp
);
2496 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2497 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
2499 /* we won't return a status if write through is not selected - this
2500 follows what WfWg does */
2501 END_PROFILE(SMBwritebraw
);
2502 if (!write_through
&& total_written
==tcount
) {
2509 /****************************************************************************
2510 reply to a writeunlock (core+)
2511 ****************************************************************************/
2513 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2515 ssize_t nwritten
= -1;
2521 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2523 START_PROFILE(SMBwriteunlock
);
2525 CHECK_FSP(fsp
,conn
);
2529 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2530 startpos
= IVAL(inbuf
,smb_vwv2
);
2531 data
= smb_buf(inbuf
) + 3;
2533 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
2534 END_PROFILE(SMBwriteunlock
);
2535 return(ERROR(ERRDOS
,ERRlock
));
2538 /* The special X/Open SMB protocol handling of
2539 zero length writes is *NOT* done for
2544 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2546 if (lp_syncalways(SNUM(conn
)))
2547 sync_file(conn
,fsp
);
2549 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2550 END_PROFILE(SMBwriteunlock
);
2551 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2554 if(!do_unlock(fsp
, conn
, (SMB_BIG_UINT
)numtowrite
, (SMB_BIG_UINT
)startpos
, &eclass
, &ecode
)) {
2555 END_PROFILE(SMBwriteunlock
);
2556 return(ERROR(eclass
,ecode
));
2559 outsize
= set_message(outbuf
,1,0,True
);
2561 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2563 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2564 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
2566 END_PROFILE(SMBwriteunlock
);
2570 /****************************************************************************
2572 ****************************************************************************/
2573 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2576 ssize_t nwritten
= -1;
2579 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2581 START_PROFILE(SMBwrite
);
2583 /* If it's an IPC, pass off the pipe handler. */
2585 END_PROFILE(SMBwrite
);
2586 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2589 CHECK_FSP(fsp
,conn
);
2593 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2594 startpos
= IVAL(inbuf
,smb_vwv2
);
2595 data
= smb_buf(inbuf
) + 3;
2597 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
2598 END_PROFILE(SMBwrite
);
2599 return(ERROR(ERRDOS
,ERRlock
));
2602 /* X/Open SMB protocol says that if smb_vwv1 is
2603 zero then the file size should be extended or
2604 truncated to the size given in smb_vwv[2-3] */
2605 if(numtowrite
== 0) {
2606 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2608 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2610 if (lp_syncalways(SNUM(conn
)))
2611 sync_file(conn
,fsp
);
2613 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2614 END_PROFILE(SMBwrite
);
2615 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2618 outsize
= set_message(outbuf
,1,0,True
);
2620 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2622 if (nwritten
< (ssize_t
)numtowrite
) {
2623 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2624 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2627 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2628 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2630 END_PROFILE(SMBwrite
);
2635 /****************************************************************************
2636 reply to a write and X
2637 ****************************************************************************/
2638 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2640 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2641 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2642 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2643 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2644 ssize_t nwritten
= -1;
2645 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2647 START_PROFILE(SMBwriteX
);
2649 /* If it's an IPC, pass off the pipe handler. */
2651 END_PROFILE(SMBwriteX
);
2652 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2655 CHECK_FSP(fsp
,conn
);
2659 if(smb_doff
> smb_len(inbuf
)) {
2660 END_PROFILE(SMBwriteX
);
2661 return(ERROR(ERRDOS
,ERRbadmem
));
2664 data
= smb_base(inbuf
) + smb_doff
;
2666 if(CVAL(inbuf
,smb_wct
) == 14) {
2667 #ifdef LARGE_SMB_OFF_T
2669 * This is a large offset (64 bit) write.
2671 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2673 #else /* !LARGE_SMB_OFF_T */
2676 * Ensure we haven't been sent a >32 bit offset.
2679 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2680 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2681 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2682 END_PROFILE(SMBwriteX
);
2683 return(ERROR(ERRDOS
,ERRbadaccess
));
2686 #endif /* LARGE_SMB_OFF_T */
2689 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
2690 END_PROFILE(SMBwriteX
);
2691 return(ERROR(ERRDOS
,ERRlock
));
2694 /* X/Open SMB protocol says that, unlike SMBwrite
2695 if the length is zero then NO truncation is
2696 done, just a write of zero. To truncate a file,
2701 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2703 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2704 END_PROFILE(SMBwriteX
);
2705 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2708 set_message(outbuf
,6,0,True
);
2710 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2712 if (nwritten
< (ssize_t
)numtowrite
) {
2713 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2714 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2717 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2718 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2720 if (lp_syncalways(SNUM(conn
)) || write_through
)
2721 sync_file(conn
,fsp
);
2723 END_PROFILE(SMBwriteX
);
2724 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2728 /****************************************************************************
2730 ****************************************************************************/
2732 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2738 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2739 START_PROFILE(SMBlseek
);
2741 CHECK_FSP(fsp
,conn
);
2744 flush_write_cache(fsp
, SEEK_FLUSH
);
2746 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2747 startpos
= IVALS(inbuf
,smb_vwv2
);
2750 case 0: umode
= SEEK_SET
; break;
2751 case 1: umode
= SEEK_CUR
; break;
2752 case 2: umode
= SEEK_END
; break;
2754 umode
= SEEK_SET
; break;
2757 if((res
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
2759 * Check for the special case where a seek before the start
2760 * of the file sets the offset to zero. Added in the CIFS spec,
2764 if(errno
== EINVAL
) {
2765 SMB_OFF_T current_pos
= startpos
;
2767 if(umode
== SEEK_CUR
) {
2769 if((current_pos
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,0,SEEK_CUR
)) == -1) {
2770 END_PROFILE(SMBlseek
);
2771 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2774 current_pos
+= startpos
;
2776 } else if (umode
== SEEK_END
) {
2778 SMB_STRUCT_STAT sbuf
;
2780 if(vfs_fstat(fsp
,fsp
->fd
, &sbuf
) == -1) {
2781 END_PROFILE(SMBlseek
);
2782 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2785 current_pos
+= sbuf
.st_size
;
2789 res
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,0,SEEK_SET
);
2793 END_PROFILE(SMBlseek
);
2794 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2800 outsize
= set_message(outbuf
,2,0,True
);
2801 SIVAL(outbuf
,smb_vwv0
,res
);
2803 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2804 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
2806 END_PROFILE(SMBlseek
);
2810 /****************************************************************************
2812 ****************************************************************************/
2814 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2816 int outsize
= set_message(outbuf
,0,0,True
);
2817 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2818 START_PROFILE(SMBflush
);
2821 CHECK_FSP(fsp
,conn
);
2826 file_sync_all(conn
);
2828 sync_file(conn
,fsp
);
2831 DEBUG(3,("flush\n"));
2832 END_PROFILE(SMBflush
);
2837 /****************************************************************************
2839 ****************************************************************************/
2840 int reply_exit(connection_struct
*conn
,
2841 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2844 START_PROFILE(SMBexit
);
2845 outsize
= set_message(outbuf
,0,0,True
);
2847 DEBUG(3,("exit\n"));
2849 END_PROFILE(SMBexit
);
2854 /****************************************************************************
2855 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2856 ****************************************************************************/
2857 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2862 int32 eclass
= 0, err
= 0;
2863 files_struct
*fsp
= NULL
;
2864 START_PROFILE(SMBclose
);
2866 outsize
= set_message(outbuf
,0,0,True
);
2868 /* If it's an IPC, pass off to the pipe handler. */
2870 END_PROFILE(SMBclose
);
2871 return reply_pipe_close(conn
, inbuf
,outbuf
);
2874 fsp
= file_fsp(inbuf
,smb_vwv0
);
2877 * We can only use CHECK_FSP if we know it's not a directory.
2880 if(!fsp
|| (fsp
->conn
!= conn
)) {
2881 END_PROFILE(SMBclose
);
2882 return(ERROR(ERRDOS
,ERRbadfid
));
2885 if(HAS_CACHED_ERROR(fsp
)) {
2886 eclass
= fsp
->wbmpx_ptr
->wr_errclass
;
2887 err
= fsp
->wbmpx_ptr
->wr_error
;
2890 if(fsp
->is_directory
|| fsp
->stat_open
) {
2892 * Special case - close NT SMB directory or stat file
2895 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
2896 close_file(fsp
,True
);
2899 * Close ordinary file.
2904 * If there was a modify time outstanding,
2905 * try and set it here.
2907 if(fsp
->pending_modtime
)
2908 set_filetime(conn
, fsp
->fsp_name
, fsp
->pending_modtime
);
2911 * Now take care of any time sent in the close.
2913 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2915 /* try and set the date */
2916 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2918 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2920 conn
->num_files_open
));
2923 * close_file() returns the unix errno if an error
2924 * was detected on close - normally this is due to
2925 * a disk full error. If not then it was probably an I/O error.
2928 if((close_err
= close_file(fsp
,True
)) != 0) {
2930 END_PROFILE(SMBclose
);
2931 return (UNIXERROR(ERRHRD
,ERRgeneral
));
2935 /* We have a cached error */
2937 END_PROFILE(SMBclose
);
2938 return(ERROR(eclass
,err
));
2941 END_PROFILE(SMBclose
);
2946 /****************************************************************************
2947 reply to a writeclose (Core+ protocol)
2948 ****************************************************************************/
2950 int reply_writeclose(connection_struct
*conn
,
2951 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2954 ssize_t nwritten
= -1;
2960 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2961 START_PROFILE(SMBwriteclose
);
2963 CHECK_FSP(fsp
,conn
);
2967 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2968 startpos
= IVAL(inbuf
,smb_vwv2
);
2969 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2970 data
= smb_buf(inbuf
) + 1;
2972 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
)) {
2973 END_PROFILE(SMBwriteclose
);
2974 return(ERROR(ERRDOS
,ERRlock
));
2977 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2979 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2981 close_err
= close_file(fsp
,True
);
2983 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2984 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
2985 conn
->num_files_open
));
2987 if (nwritten
<= 0) {
2988 END_PROFILE(SMBwriteclose
);
2989 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2992 if(close_err
!= 0) {
2994 END_PROFILE(SMBwriteclose
);
2995 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2998 outsize
= set_message(outbuf
,1,0,True
);
3000 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3001 END_PROFILE(SMBwriteclose
);
3006 /****************************************************************************
3008 ****************************************************************************/
3009 int reply_lock(connection_struct
*conn
,
3010 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
3012 int outsize
= set_message(outbuf
,0,0,True
);
3013 SMB_BIG_UINT count
,offset
;
3016 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3017 START_PROFILE(SMBlock
);
3019 CHECK_FSP(fsp
,conn
);
3022 release_level_2_oplocks_on_change(fsp
);
3024 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
3025 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
3027 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3028 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
3030 if (!do_lock(fsp
, conn
, count
, offset
, WRITE_LOCK
, &eclass
, &ecode
)) {
3031 if((ecode
== ERRlock
) && lp_blocking_locks(SNUM(conn
))) {
3033 * A blocking lock was requested. Package up
3034 * this smb into a queued request and push it
3035 * onto the blocking lock queue.
3037 if(push_blocking_lock_request(inbuf
, length
, -1, 0)) {
3038 END_PROFILE(SMBlock
);
3042 END_PROFILE(SMBlock
);
3043 return (ERROR(eclass
,ecode
));
3046 END_PROFILE(SMBlock
);
3051 /****************************************************************************
3053 ****************************************************************************/
3054 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
3056 int outsize
= set_message(outbuf
,0,0,True
);
3057 SMB_BIG_UINT count
,offset
;
3060 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3061 START_PROFILE(SMBunlock
);
3063 CHECK_FSP(fsp
,conn
);
3066 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
3067 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
3069 if(!do_unlock(fsp
, conn
, count
, offset
, &eclass
, &ecode
)) {
3070 END_PROFILE(SMBunlock
);
3071 return (ERROR(eclass
,ecode
));
3074 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3075 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
3077 END_PROFILE(SMBunlock
);
3082 /****************************************************************************
3084 ****************************************************************************/
3085 int reply_tdis(connection_struct
*conn
,
3086 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3088 int outsize
= set_message(outbuf
,0,0,True
);
3090 START_PROFILE(SMBtdis
);
3092 vuid
= SVAL(inbuf
,smb_uid
);
3095 DEBUG(4,("Invalid connection in tdis\n"));
3096 END_PROFILE(SMBtdis
);
3097 return(ERROR(ERRSRV
,ERRinvnid
));
3102 close_cnum(conn
,vuid
);
3104 END_PROFILE(SMBtdis
);
3110 /****************************************************************************
3112 ****************************************************************************/
3113 int reply_echo(connection_struct
*conn
,
3114 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3116 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
3118 unsigned int data_len
= smb_buflen(inbuf
);
3119 int outsize
= set_message(outbuf
,1,data_len
,True
);
3120 START_PROFILE(SMBecho
);
3122 data_len
= MIN(data_len
, (sizeof(inbuf
)-(smb_buf(inbuf
)-inbuf
)));
3124 /* copy any incoming data back out */
3126 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
3128 if (smb_reverb
> 100) {
3129 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
3133 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
3134 SSVAL(outbuf
,smb_vwv0
,seq_num
);
3136 smb_setlen(outbuf
,outsize
- 4);
3138 send_smb(smbd_server_fd(),outbuf
);
3141 DEBUG(3,("echo %d times\n", smb_reverb
));
3145 END_PROFILE(SMBecho
);
3150 /****************************************************************************
3151 reply to a printopen
3152 ****************************************************************************/
3153 int reply_printopen(connection_struct
*conn
,
3154 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3158 START_PROFILE(SMBsplopen
);
3160 if (!CAN_PRINT(conn
)) {
3161 END_PROFILE(SMBsplopen
);
3162 return(ERROR(ERRDOS
,ERRnoaccess
));
3165 /* Open for exclusive use, write only. */
3166 fsp
= print_fsp_open(conn
,"dos.prn");
3169 END_PROFILE(SMBsplopen
);
3170 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3173 outsize
= set_message(outbuf
,1,0,True
);
3174 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
3176 DEBUG(3,("openprint fd=%d fnum=%d\n",
3177 fsp
->fd
, fsp
->fnum
));
3179 END_PROFILE(SMBsplopen
);
3184 /****************************************************************************
3185 reply to a printclose
3186 ****************************************************************************/
3187 int reply_printclose(connection_struct
*conn
,
3188 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3190 int outsize
= set_message(outbuf
,0,0,True
);
3191 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3193 START_PROFILE(SMBsplclose
);
3195 CHECK_FSP(fsp
,conn
);
3198 if (!CAN_PRINT(conn
)) {
3199 END_PROFILE(SMBsplclose
);
3200 return(ERROR(ERRDOS
,ERRnoaccess
));
3203 DEBUG(3,("printclose fd=%d fnum=%d\n",
3204 fsp
->fd
,fsp
->fnum
));
3206 close_err
= close_file(fsp
,True
);
3208 if(close_err
!= 0) {
3210 END_PROFILE(SMBsplclose
);
3211 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3214 END_PROFILE(SMBsplclose
);
3219 /****************************************************************************
3220 reply to a printqueue
3221 ****************************************************************************/
3222 int reply_printqueue(connection_struct
*conn
,
3223 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3225 int outsize
= set_message(outbuf
,2,3,True
);
3226 int max_count
= SVAL(inbuf
,smb_vwv0
);
3227 int start_index
= SVAL(inbuf
,smb_vwv1
);
3228 START_PROFILE(SMBsplretq
);
3230 /* we used to allow the client to get the cnum wrong, but that
3231 is really quite gross and only worked when there was only
3232 one printer - I think we should now only accept it if they
3233 get it right (tridge) */
3234 if (!CAN_PRINT(conn
)) {
3235 END_PROFILE(SMBsplretq
);
3236 return(ERROR(ERRDOS
,ERRnoaccess
));
3239 SSVAL(outbuf
,smb_vwv0
,0);
3240 SSVAL(outbuf
,smb_vwv1
,0);
3241 CVAL(smb_buf(outbuf
),0) = 1;
3242 SSVAL(smb_buf(outbuf
),1,0);
3244 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3245 start_index
, max_count
));
3248 print_queue_struct
*queue
= NULL
;
3249 char *p
= smb_buf(outbuf
) + 3;
3250 int count
= print_queue_status(SNUM(conn
), &queue
,NULL
);
3251 int num_to_get
= ABS(max_count
);
3252 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
3258 num_to_get
= MIN(num_to_get
,count
-first
);
3261 for (i
=first
;i
<first
+num_to_get
;i
++) {
3262 put_dos_date2(p
,0,queue
[i
].time
);
3263 CVAL(p
,4) = (queue
[i
].status
==LPQ_PRINTING
?2:3);
3264 SSVAL(p
,5, queue
[i
].job
);
3265 SIVAL(p
,7,queue
[i
].size
);
3267 StrnCpy(p
+12,queue
[i
].user
,16);
3272 outsize
= set_message(outbuf
,2,28*count
+3,False
);
3273 SSVAL(outbuf
,smb_vwv0
,count
);
3274 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
3275 CVAL(smb_buf(outbuf
),0) = 1;
3276 SSVAL(smb_buf(outbuf
),1,28*count
);
3279 if (queue
) free(queue
);
3281 DEBUG(3,("%d entries returned in queue\n",count
));
3284 END_PROFILE(SMBsplretq
);
3289 /****************************************************************************
3290 reply to a printwrite
3291 ****************************************************************************/
3292 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3295 int outsize
= set_message(outbuf
,0,0,True
);
3297 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3298 START_PROFILE(SMBsplwr
);
3300 if (!CAN_PRINT(conn
)) {
3301 END_PROFILE(SMBsplwr
);
3302 return(ERROR(ERRDOS
,ERRnoaccess
));
3305 CHECK_FSP(fsp
,conn
);
3309 numtowrite
= SVAL(smb_buf(inbuf
),1);
3310 data
= smb_buf(inbuf
) + 3;
3312 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
3313 END_PROFILE(SMBsplwr
);
3314 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3317 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
3319 END_PROFILE(SMBsplwr
);
3324 /****************************************************************************
3325 The guts of the mkdir command, split out so it may be called by the NT SMB
3327 ****************************************************************************/
3328 int mkdir_internal(connection_struct
*conn
, char *inbuf
, char *outbuf
, pstring directory
)
3330 BOOL bad_path
= False
;
3331 SMB_STRUCT_STAT sbuf
;
3334 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3336 if (check_name(directory
, conn
))
3337 ret
= vfs_mkdir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3341 if((errno
== ENOENT
) && bad_path
)
3343 unix_ERR_class
= ERRDOS
;
3344 unix_ERR_code
= ERRbadpath
;
3346 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3352 /****************************************************************************
3354 ****************************************************************************/
3355 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3359 START_PROFILE(SMBmkdir
);
3361 pstrcpy(directory
,smb_buf(inbuf
) + 1);
3363 outsize
=mkdir_internal(conn
, inbuf
, outbuf
, directory
);
3365 outsize
= set_message(outbuf
,0,0,True
);
3367 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
3369 END_PROFILE(SMBmkdir
);
3373 /****************************************************************************
3374 Static function used by reply_rmdir to delete an entire directory
3376 ****************************************************************************/
3378 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
3382 void *dirptr
= OpenDir(NULL
, directory
, False
);
3387 while((dname
= ReadDirName(dirptr
)))
3392 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3395 /* Construct the full name. */
3396 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
3402 pstrcpy(fullname
, directory
);
3403 pstrcat(fullname
, "/");
3404 pstrcat(fullname
, dname
);
3406 if(conn
->vfs_ops
.lstat(conn
,dos_to_unix(fullname
,False
), &st
) != 0)
3412 if(st
.st_mode
& S_IFDIR
)
3414 if(recursive_rmdir(conn
, fullname
)!=0)
3419 if(vfs_rmdir(conn
,fullname
) != 0)
3425 else if(vfs_unlink(conn
,fullname
) != 0)
3435 /****************************************************************************
3436 The internals of the rmdir code - called elsewhere.
3437 ****************************************************************************/
3439 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
3443 ok
= (vfs_rmdir(conn
,directory
) == 0);
3444 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
)))
3447 * Check to see if the only thing in this directory are
3448 * vetoed files/directories. If so then delete them and
3449 * retry. If we fail to delete any of them (and we *don't*
3450 * do a recursive delete) then fail the rmdir.
3452 BOOL all_veto_files
= True
;
3454 void *dirptr
= OpenDir(conn
, directory
, False
);
3458 int dirpos
= TellDir(dirptr
);
3459 while ((dname
= ReadDirName(dirptr
)))
3461 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3463 if(!IS_VETO_PATH(conn
, dname
))
3465 all_veto_files
= False
;
3471 SeekDir(dirptr
,dirpos
);
3472 while ((dname
= ReadDirName(dirptr
)))
3477 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3480 /* Construct the full name. */
3481 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
3486 pstrcpy(fullname
, directory
);
3487 pstrcat(fullname
, "/");
3488 pstrcat(fullname
, dname
);
3490 if(conn
->vfs_ops
.lstat(conn
,dos_to_unix(fullname
, False
), &st
) != 0)
3492 if(st
.st_mode
& S_IFDIR
)
3494 if(lp_recursive_veto_delete(SNUM(conn
)))
3496 if(recursive_rmdir(conn
, fullname
) != 0)
3499 if(vfs_rmdir(conn
,fullname
) != 0)
3502 else if(vfs_unlink(conn
,fullname
) != 0)
3506 /* Retry the rmdir */
3507 ok
= (vfs_rmdir(conn
,directory
) == 0);
3517 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3518 directory
,strerror(errno
)));
3523 /****************************************************************************
3525 ****************************************************************************/
3527 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3532 BOOL bad_path
= False
;
3533 SMB_STRUCT_STAT sbuf
;
3534 START_PROFILE(SMBrmdir
);
3536 pstrcpy(directory
,smb_buf(inbuf
) + 1);
3538 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3540 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3542 if (check_name(directory
,conn
))
3544 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3545 ok
= rmdir_internals(conn
, directory
);
3550 if((errno
== ENOENT
) && bad_path
)
3552 unix_ERR_class
= ERRDOS
;
3553 unix_ERR_code
= ERRbadpath
;
3555 END_PROFILE(SMBrmdir
);
3556 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3559 outsize
= set_message(outbuf
,0,0,True
);
3561 DEBUG( 3, ( "rmdir %s\n", directory
) );
3563 END_PROFILE(SMBrmdir
);
3568 /*******************************************************************
3569 resolve wildcards in a filename rename
3570 ********************************************************************/
3571 static BOOL
resolve_wildcards(char *name1
,char *name2
)
3573 fstring root1
,root2
;
3577 name1
= strrchr(name1
,'/');
3578 name2
= strrchr(name2
,'/');
3580 if (!name1
|| !name2
) return(False
);
3582 fstrcpy(root1
,name1
);
3583 fstrcpy(root2
,name2
);
3584 p
= strrchr(root1
,'.');
3591 p
= strrchr(root2
,'.');
3623 pstrcpy(name2
,root2
);
3626 pstrcat(name2
,ext2
);
3632 /*******************************************************************
3633 check if a user is allowed to rename a file
3634 ********************************************************************/
3635 static BOOL
can_rename(char *fname
,connection_struct
*conn
)
3637 SMB_STRUCT_STAT sbuf
;
3639 if (!CAN_WRITE(conn
)) return(False
);
3641 if (conn
->vfs_ops
.lstat(conn
,dos_to_unix(fname
,False
),&sbuf
) != 0) return(False
);
3642 if (!check_file_sharing(conn
,fname
,True
)) return(False
);
3646 /****************************************************************************
3647 The guts of the rename command, split out so it may be called by the NT SMB
3649 ****************************************************************************/
3650 int rename_internals(connection_struct
*conn
,
3651 char *inbuf
, char *outbuf
, char *name
,
3652 char *newname
, BOOL replace_if_exists
)
3656 pstring newname_last_component
;
3659 BOOL bad_path1
= False
;
3660 BOOL bad_path2
= False
;
3662 int error
= ERRnoaccess
;
3665 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3668 *directory
= *mask
= 0;
3670 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
3671 unix_convert(newname
,conn
,newname_last_component
,&bad_path2
,&sbuf2
);
3674 * Split the old name into directory and last component
3675 * strings. Note that unix_convert may have stripped off a
3676 * leading ./ from both name and newname if the rename is
3677 * at the root of the share. We need to make sure either both
3678 * name and newname contain a / character or neither of them do
3679 * as this is checked in resolve_wildcards().
3682 p
= strrchr(name
,'/');
3684 pstrcpy(directory
,".");
3688 pstrcpy(directory
,name
);
3690 *p
= '/'; /* Replace needed for exceptional test below. */
3694 * We should only check the mangled cache
3695 * here if unix_convert failed. This means
3696 * that the path in 'mask' doesn't exist
3697 * on the file system and so we need to look
3698 * for a possible mangle. This patch from
3699 * Tine Smukavec <valentin.smukavec@hermes.si>.
3702 if (!rc
&& is_mangled(mask
))
3703 check_mangled_cache( mask
);
3705 has_wild
= ms_has_wild(mask
);
3709 * No wildcards - just process the one file.
3711 BOOL is_short_name
= is_8_3(name
, True
);
3713 /* Add a terminating '/' to the directory name. */
3714 pstrcat(directory
,"/");
3715 pstrcat(directory
,mask
);
3717 /* Ensure newname contains a '/' also */
3718 if(strrchr(newname
,'/') == 0) {
3721 pstrcpy(tmpstr
, "./");
3722 pstrcat(tmpstr
, newname
);
3723 pstrcpy(newname
, tmpstr
);
3726 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",
3727 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3728 newname
, newname_last_component
, is_short_name
));
3731 * Check for special case with case preserving and not
3732 * case sensitive, if directory and newname are identical,
3733 * and the old last component differs from the original
3734 * last component only by case, then we should allow
3735 * the rename (user is trying to change the case of the
3738 if((case_sensitive
== False
) &&
3739 (((case_preserve
== True
) &&
3740 (is_short_name
== False
)) ||
3741 ((short_case_preserve
== True
) &&
3742 (is_short_name
== True
))) &&
3743 strcsequal(directory
, newname
)) {
3744 pstring newname_modified_last_component
;
3747 * Get the last component of the modified name.
3748 * Note that we guarantee that newname contains a '/'
3751 p
= strrchr(newname
,'/');
3752 pstrcpy(newname_modified_last_component
,p
+1);
3754 if(strcsequal(newname_modified_last_component
,
3755 newname_last_component
) == False
) {
3757 * Replace the modified last component with
3760 pstrcpy(p
+1, newname_last_component
);
3764 pstrcpy(zdirectory
, dos_to_unix(directory
, False
));
3765 if(replace_if_exists
) {
3767 * NT SMB specific flag - rename can overwrite
3768 * file with the same name so don't check for
3772 if(resolve_wildcards(directory
,newname
) &&
3773 can_rename(directory
,conn
) &&
3774 !conn
->vfs_ops
.rename(conn
,zdirectory
,
3775 dos_to_unix(newname
,False
)))
3778 if (resolve_wildcards(directory
,newname
) &&
3779 can_rename(directory
,conn
) &&
3780 !vfs_file_exist(conn
,newname
,NULL
) &&
3781 !conn
->vfs_ops
.rename(conn
,zdirectory
,
3782 dos_to_unix(newname
,False
)))
3786 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count
!= 0) ? "succeeded" : "failed",
3787 directory
,newname
));
3789 if (!count
) exists
= vfs_file_exist(conn
,directory
,NULL
);
3790 if (!count
&& exists
&& vfs_file_exist(conn
,newname
,NULL
)) {
3796 * Wildcards - process each file that matches.
3798 void *dirptr
= NULL
;
3802 if (check_name(directory
,conn
))
3803 dirptr
= OpenDir(conn
, directory
, True
);
3808 if (strequal(mask
,"????????.???"))
3811 while ((dname
= ReadDirName(dirptr
))) {
3814 pstrcpy(fname
,dname
);
3816 if(!mask_match(fname
, mask
, case_sensitive
))
3819 error
= ERRnoaccess
;
3820 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3821 if (!can_rename(fname
,conn
)) {
3822 DEBUG(6,("rename %s refused\n", fname
));
3825 pstrcpy(destname
,newname
);
3827 if (!resolve_wildcards(fname
,destname
)) {
3828 DEBUG(6,("resolve_wildcards %s %s failed\n",
3833 if (!replace_if_exists
&&
3834 vfs_file_exist(conn
,destname
, NULL
)) {
3835 DEBUG(6,("file_exist %s\n", destname
));
3840 if (!conn
->vfs_ops
.rename(conn
,dos_to_unix(fname
,False
),
3841 dos_to_unix(destname
,False
)))
3843 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3851 return(ERROR(ERRDOS
,error
));
3853 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
)) {
3854 unix_ERR_class
= ERRDOS
;
3855 unix_ERR_code
= ERRbadpath
;
3857 return(UNIXERROR(ERRDOS
,error
));
3864 /****************************************************************************
3866 ****************************************************************************/
3868 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3873 START_PROFILE(SMBmv
);
3875 pstrcpy(name
,smb_buf(inbuf
) + 1);
3876 pstrcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
3878 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3879 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3881 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3883 outsize
= rename_internals(conn
, inbuf
, outbuf
, name
, newname
, False
);
3887 * Win2k needs a changenotify request response before it will
3888 * update after a rename..
3891 process_pending_change_notify_queue((time_t)0);
3893 outsize
= set_message(outbuf
,0,0,True
);
3900 /*******************************************************************
3901 copy a file as part of a reply_copy
3902 ******************************************************************/
3904 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3905 int count
,BOOL target_is_directory
, int *err_ret
)
3908 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
3910 files_struct
*fsp1
,*fsp2
;
3915 pstrcpy(dest
,dest1
);
3916 if (target_is_directory
) {
3917 char *p
= strrchr(src
,'/');
3926 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
3929 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3930 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
3936 if (!target_is_directory
&& count
)
3937 ofun
= FILE_EXISTS_OPEN
;
3939 vfs_stat(conn
,dest
,&sbuf2
);
3940 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3941 ofun
,src_sbuf
.st_mode
,0,&Access
,&action
);
3944 close_file(fsp1
,False
);
3948 if ((ofun
&3) == 1) {
3949 if(conn
->vfs_ops
.lseek(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
3950 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3953 * Stop the copy from occurring.
3956 src_sbuf
.st_size
= 0;
3960 if (src_sbuf
.st_size
)
3961 ret
= vfs_transfer_file(-1, fsp1
, -1, fsp2
, src_sbuf
.st_size
, NULL
, 0, 0);
3963 close_file(fsp1
,False
);
3965 * As we are opening fsp1 read-only we only expect
3966 * an error on close on fsp2 if we are out of space.
3967 * Thus we don't look at the error return from the
3970 *err_ret
= close_file(fsp2
,False
);
3972 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
3977 /****************************************************************************
3978 reply to a file copy.
3979 ****************************************************************************/
3980 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3985 pstring mask
,newname
;
3988 int error
= ERRnoaccess
;
3992 int tid2
= SVAL(inbuf
,smb_vwv0
);
3993 int ofun
= SVAL(inbuf
,smb_vwv1
);
3994 int flags
= SVAL(inbuf
,smb_vwv2
);
3995 BOOL target_is_directory
=False
;
3996 BOOL bad_path1
= False
;
3997 BOOL bad_path2
= False
;
3999 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4000 START_PROFILE(SMBcopy
);
4002 *directory
= *mask
= 0;
4004 pstrcpy(name
,smb_buf(inbuf
));
4005 pstrcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
4007 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
4009 if (tid2
!= conn
->cnum
) {
4010 /* can't currently handle inter share copies XXXX */
4011 DEBUG(3,("Rejecting inter-share copy\n"));
4012 END_PROFILE(SMBcopy
);
4013 return(ERROR(ERRSRV
,ERRinvdevice
));
4016 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
4017 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
4019 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
4020 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
4022 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
4024 if ((flags
&1) && target_is_directory
) {
4025 END_PROFILE(SMBcopy
);
4026 return(ERROR(ERRDOS
,ERRbadfile
));
4029 if ((flags
&2) && !target_is_directory
) {
4030 END_PROFILE(SMBcopy
);
4031 return(ERROR(ERRDOS
,ERRbadpath
));
4034 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
4035 /* wants a tree copy! XXXX */
4036 DEBUG(3,("Rejecting tree copy\n"));
4037 END_PROFILE(SMBcopy
);
4038 return(ERROR(ERRSRV
,ERRerror
));
4041 p
= strrchr(name
,'/');
4043 pstrcpy(directory
,"./");
4047 pstrcpy(directory
,name
);
4052 * We should only check the mangled cache
4053 * here if unix_convert failed. This means
4054 * that the path in 'mask' doesn't exist
4055 * on the file system and so we need to look
4056 * for a possible mangle. This patch from
4057 * Tine Smukavec <valentin.smukavec@hermes.si>.
4060 if (!rc
&& is_mangled(mask
))
4061 check_mangled_cache( mask
);
4063 has_wild
= ms_has_wild(mask
);
4066 pstrcat(directory
,"/");
4067 pstrcat(directory
,mask
);
4068 if (resolve_wildcards(directory
,newname
) &&
4069 copy_file(directory
,newname
,conn
,ofun
,
4070 count
,target_is_directory
,&err
)) count
++;
4073 END_PROFILE(SMBcopy
);
4074 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4076 if (!count
) exists
= vfs_file_exist(conn
,directory
,NULL
);
4078 void *dirptr
= NULL
;
4082 if (check_name(directory
,conn
))
4083 dirptr
= OpenDir(conn
, directory
, True
);
4088 if (strequal(mask
,"????????.???"))
4091 while ((dname
= ReadDirName(dirptr
))) {
4093 pstrcpy(fname
,dname
);
4095 if(!mask_match(fname
, mask
, case_sensitive
))
4098 error
= ERRnoaccess
;
4099 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
4100 pstrcpy(destname
,newname
);
4101 if (resolve_wildcards(fname
,destname
) &&
4102 copy_file(fname
,destname
,conn
,ofun
,
4103 count
,target_is_directory
,&err
)) count
++;
4104 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
4112 /* Error on close... */
4114 END_PROFILE(SMBcopy
);
4115 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4119 END_PROFILE(SMBcopy
);
4120 return(ERROR(ERRDOS
,error
));
4123 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
4125 unix_ERR_class
= ERRDOS
;
4126 unix_ERR_code
= ERRbadpath
;
4128 END_PROFILE(SMBcopy
);
4129 return(UNIXERROR(ERRDOS
,error
));
4133 outsize
= set_message(outbuf
,1,0,True
);
4134 SSVAL(outbuf
,smb_vwv0
,count
);
4136 END_PROFILE(SMBcopy
);
4140 /****************************************************************************
4142 ****************************************************************************/
4143 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4149 START_PROFILE(pathworks_setdir
);
4152 if (!CAN_SETDIR(snum
)) {
4153 END_PROFILE(pathworks_setdir
);
4154 return(ERROR(ERRDOS
,ERRnoaccess
));
4157 pstrcpy(newdir
,smb_buf(inbuf
) + 1);
4160 if (strlen(newdir
) == 0) {
4163 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
4165 string_set(&conn
->connectpath
,newdir
);
4170 END_PROFILE(pathworks_setdir
);
4171 return(ERROR(ERRDOS
,ERRbadpath
));
4174 outsize
= set_message(outbuf
,0,0,True
);
4175 CVAL(outbuf
,smb_reh
) = CVAL(inbuf
,smb_reh
);
4177 DEBUG(3,("setdir %s\n", newdir
));
4179 END_PROFILE(pathworks_setdir
);
4183 /****************************************************************************
4184 Get a lock count, dealing with large count requests.
4185 ****************************************************************************/
4187 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
4189 SMB_BIG_UINT count
= 0;
4191 if(!large_file_format
) {
4192 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
4195 #if defined(HAVE_LONGLONG)
4196 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
4197 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
4198 #else /* HAVE_LONGLONG */
4201 * NT4.x seems to be broken in that it sends large file (64 bit)
4202 * lockingX calls even if the CAP_LARGE_FILES was *not*
4203 * negotiated. For boxes without large unsigned ints truncate the
4204 * lock count by dropping the top 32 bits.
4207 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
4208 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4209 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
4210 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
4211 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
4214 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
4215 #endif /* HAVE_LONGLONG */
4221 /****************************************************************************
4222 Get a lock offset, dealing with large offset requests.
4223 ****************************************************************************/
4225 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
4227 SMB_BIG_UINT offset
= 0;
4231 if(!large_file_format
) {
4232 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
4235 #if defined(HAVE_LONGLONG)
4236 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
4237 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
4238 #else /* HAVE_LONGLONG */
4241 * NT4.x seems to be broken in that it sends large file (64 bit)
4242 * lockingX calls even if the CAP_LARGE_FILES was *not*
4243 * negotiated. For boxes without large unsigned ints mangle the
4244 * lock offset by mapping the top 32 bits onto the lower 32.
4247 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
4248 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4249 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
4252 if((new_low
= map_lock_offset(high
, low
)) == 0) {
4254 return (SMB_BIG_UINT
)-1;
4257 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4258 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
4259 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
4260 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
4263 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4264 #endif /* HAVE_LONGLONG */
4270 /****************************************************************************
4271 reply to a lockingX request
4272 ****************************************************************************/
4274 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4276 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
4277 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
4278 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
4279 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
4280 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
4281 SMB_BIG_UINT count
= 0, offset
= 0;
4282 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
4285 uint32 ecode
=0, dummy2
;
4286 int eclass
=0, dummy1
;
4287 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
4289 START_PROFILE(SMBlockingX
);
4291 CHECK_FSP(fsp
,conn
);
4294 data
= smb_buf(inbuf
);
4296 /* Check if this is an oplock break on a file
4297 we have granted an oplock on.
4299 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
))
4301 /* Client can insist on breaking to none. */
4302 BOOL break_to_none
= (oplocklevel
== 0);
4304 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4305 fsp
->fnum
, (unsigned int)oplocklevel
));
4308 * Make sure we have granted an exclusive or batch oplock on this file.
4311 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
4313 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4314 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
4316 /* if this is a pure oplock break request then don't send a reply */
4317 if (num_locks
== 0 && num_ulocks
== 0) {
4318 END_PROFILE(SMBlockingX
);
4321 END_PROFILE(SMBlockingX
);
4322 return ERROR(ERRDOS
,ERRlock
);
4326 if (remove_oplock(fsp
, break_to_none
) == False
) {
4327 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4331 /* if this is a pure oplock break request then don't send a reply */
4332 if (num_locks
== 0 && num_ulocks
== 0)
4334 /* Sanity check - ensure a pure oplock break is not a
4336 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
4337 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4338 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
4339 END_PROFILE(SMBlockingX
);
4345 * We do this check *after* we have checked this is not a oplock break
4346 * response message. JRA.
4349 release_level_2_oplocks_on_change(fsp
);
4351 /* Data now points at the beginning of the list
4352 of smb_unlkrng structs */
4353 for(i
= 0; i
< (int)num_ulocks
; i
++) {
4354 count
= get_lock_count( data
, i
, large_file_format
);
4355 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4358 * There is no error code marked "stupid client bug".... :-).
4361 END_PROFILE(SMBlockingX
);
4362 return ERROR(ERRDOS
,ERRnoaccess
);
4365 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
4366 (double)offset
, (double)count
, fsp
->fsp_name
));
4368 if(!do_unlock(fsp
,conn
,count
,offset
, &eclass
, &ecode
)) {
4369 END_PROFILE(SMBlockingX
);
4370 return ERROR(eclass
,ecode
);
4374 /* Setup the timeout in seconds. */
4375 lock_timeout
= ((lock_timeout
== -1) ? -1 : lock_timeout
/1000);
4377 /* Now do any requested locks */
4378 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
4380 /* Data now points at the beginning of the list
4381 of smb_lkrng structs */
4383 for(i
= 0; i
< (int)num_locks
; i
++) {
4384 count
= get_lock_count( data
, i
, large_file_format
);
4385 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4388 * There is no error code marked "stupid client bug".... :-).
4391 END_PROFILE(SMBlockingX
);
4392 return ERROR(ERRDOS
,ERRnoaccess
);
4395 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
4396 (double)offset
, (double)count
, fsp
->fsp_name
));
4398 if(!do_lock(fsp
,conn
,count
,offset
, ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
),
4400 if((ecode
== ERRlock
) && (lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
))) {
4402 * A blocking lock was requested. Package up
4403 * this smb into a queued request and push it
4404 * onto the blocking lock queue.
4406 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
)) {
4407 END_PROFILE(SMBlockingX
);
4415 /* If any of the above locks failed, then we must unlock
4416 all of the previous locks (X/Open spec). */
4417 if(i
!= num_locks
&& num_locks
!= 0) {
4419 * Ensure we don't do a remove on the lock that just failed,
4420 * as under POSIX rules, if we have a lock already there, we
4421 * will delete it (and we shouldn't) .....
4423 for(i
--; i
>= 0; i
--) {
4424 count
= get_lock_count( data
, i
, large_file_format
);
4425 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4428 * There is no error code marked "stupid client bug".... :-).
4431 END_PROFILE(SMBlockingX
);
4432 return ERROR(ERRDOS
,ERRnoaccess
);
4435 do_unlock(fsp
,conn
,count
,offset
,&dummy1
,&dummy2
);
4437 END_PROFILE(SMBlockingX
);
4438 return ERROR(eclass
,ecode
);
4441 set_message(outbuf
,2,0,True
);
4443 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4444 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4446 END_PROFILE(SMBlockingX
);
4447 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4451 /****************************************************************************
4452 reply to a SMBreadbmpx (read block multiplex) request
4453 ****************************************************************************/
4454 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4465 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4466 START_PROFILE(SMBreadBmpx
);
4468 /* this function doesn't seem to work - disable by default */
4469 if (!lp_readbmpx()) {
4470 END_PROFILE(SMBreadBmpx
);
4471 return(ERROR(ERRSRV
,ERRuseSTD
));
4474 outsize
= set_message(outbuf
,8,0,True
);
4476 CHECK_FSP(fsp
,conn
);
4480 startpos
= IVAL(inbuf
,smb_vwv1
);
4481 maxcount
= SVAL(inbuf
,smb_vwv3
);
4483 data
= smb_buf(outbuf
);
4484 pad
= ((long)data
)%4;
4485 if (pad
) pad
= 4 - pad
;
4488 max_per_packet
= bufsize
-(outsize
+pad
);
4492 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
)) {
4493 END_PROFILE(SMBreadBmpx
);
4494 return(ERROR(ERRDOS
,ERRlock
));
4499 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4501 nread
= read_file(fsp
,data
,startpos
,N
);
4503 if (nread
<= 0) nread
= 0;
4505 if (nread
< (ssize_t
)N
)
4506 tcount
= total_read
+ nread
;
4508 set_message(outbuf
,8,nread
,False
);
4509 SIVAL(outbuf
,smb_vwv0
,startpos
);
4510 SSVAL(outbuf
,smb_vwv2
,tcount
);
4511 SSVAL(outbuf
,smb_vwv6
,nread
);
4512 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4514 send_smb(smbd_server_fd(),outbuf
);
4516 total_read
+= nread
;
4519 while (total_read
< (ssize_t
)tcount
);
4521 END_PROFILE(SMBreadBmpx
);
4525 /****************************************************************************
4526 reply to a SMBwritebmpx (write block multiplex primary) request
4527 ****************************************************************************/
4529 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4532 ssize_t nwritten
= -1;
4539 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4540 START_PROFILE(SMBwriteBmpx
);
4542 CHECK_FSP(fsp
,conn
);
4546 tcount
= SVAL(inbuf
,smb_vwv1
);
4547 startpos
= IVAL(inbuf
,smb_vwv3
);
4548 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
4549 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4550 smb_doff
= SVAL(inbuf
,smb_vwv11
);
4552 data
= smb_base(inbuf
) + smb_doff
;
4554 /* If this fails we need to send an SMBwriteC response,
4555 not an SMBwritebmpx - set this up now so we don't forget */
4556 CVAL(outbuf
,smb_com
) = SMBwritec
;
4558 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
)) {
4559 END_PROFILE(SMBwriteBmpx
);
4560 return(ERROR(ERRDOS
,ERRlock
));
4563 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4565 if(lp_syncalways(SNUM(conn
)) || write_through
)
4566 sync_file(conn
,fsp
);
4568 if(nwritten
< (ssize_t
)numtowrite
) {
4569 END_PROFILE(SMBwriteBmpx
);
4570 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
4573 /* If the maximum to be written to this file
4574 is greater than what we just wrote then set
4575 up a secondary struct to be attached to this
4576 fd, we will use this to cache error messages etc. */
4577 if((ssize_t
)tcount
> nwritten
)
4579 write_bmpx_struct
*wbms
;
4580 if(fsp
->wbmpx_ptr
!= NULL
)
4581 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
4583 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
4586 DEBUG(0,("Out of memory in reply_readmpx\n"));
4587 END_PROFILE(SMBwriteBmpx
);
4588 return(ERROR(ERRSRV
,ERRnoresource
));
4590 wbms
->wr_mode
= write_through
;
4591 wbms
->wr_discard
= False
; /* No errors yet */
4592 wbms
->wr_total_written
= nwritten
;
4593 wbms
->wr_errclass
= 0;
4595 fsp
->wbmpx_ptr
= wbms
;
4598 /* We are returning successfully, set the message type back to
4600 CVAL(outbuf
,smb_com
) = SMBwriteBmpx
;
4602 outsize
= set_message(outbuf
,1,0,True
);
4604 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
4606 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4607 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
4609 if (write_through
&& tcount
==nwritten
) {
4610 /* we need to send both a primary and a secondary response */
4611 smb_setlen(outbuf
,outsize
- 4);
4612 send_smb(smbd_server_fd(),outbuf
);
4614 /* now the secondary */
4615 outsize
= set_message(outbuf
,1,0,True
);
4616 CVAL(outbuf
,smb_com
) = SMBwritec
;
4617 SSVAL(outbuf
,smb_vwv0
,nwritten
);
4620 END_PROFILE(SMBwriteBmpx
);
4625 /****************************************************************************
4626 reply to a SMBwritebs (write block multiplex secondary) request
4627 ****************************************************************************/
4628 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4631 ssize_t nwritten
= -1;
4638 write_bmpx_struct
*wbms
;
4639 BOOL send_response
= False
;
4640 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4641 START_PROFILE(SMBwriteBs
);
4643 CHECK_FSP(fsp
,conn
);
4646 tcount
= SVAL(inbuf
,smb_vwv1
);
4647 startpos
= IVAL(inbuf
,smb_vwv2
);
4648 numtowrite
= SVAL(inbuf
,smb_vwv6
);
4649 smb_doff
= SVAL(inbuf
,smb_vwv7
);
4651 data
= smb_base(inbuf
) + smb_doff
;
4653 /* We need to send an SMBwriteC response, not an SMBwritebs */
4654 CVAL(outbuf
,smb_com
) = SMBwritec
;
4656 /* This fd should have an auxiliary struct attached,
4657 check that it does */
4658 wbms
= fsp
->wbmpx_ptr
;
4660 END_PROFILE(SMBwriteBs
);
4664 /* If write through is set we can return errors, else we must
4666 write_through
= wbms
->wr_mode
;
4668 /* Check for an earlier error */
4669 if(wbms
->wr_discard
) {
4670 END_PROFILE(SMBwriteBs
);
4671 return -1; /* Just discard the packet */
4674 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4676 if(lp_syncalways(SNUM(conn
)) || write_through
)
4677 sync_file(conn
,fsp
);
4679 if (nwritten
< (ssize_t
)numtowrite
)
4683 /* We are returning an error - we can delete the aux struct */
4684 if (wbms
) free((char *)wbms
);
4685 fsp
->wbmpx_ptr
= NULL
;
4686 END_PROFILE(SMBwriteBs
);
4687 return(ERROR(ERRHRD
,ERRdiskfull
));
4689 END_PROFILE(SMBwriteBs
);
4690 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4693 /* Increment the total written, if this matches tcount
4694 we can discard the auxiliary struct (hurrah !) and return a writeC */
4695 wbms
->wr_total_written
+= nwritten
;
4696 if(wbms
->wr_total_written
>= tcount
)
4700 outsize
= set_message(outbuf
,1,0,True
);
4701 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4702 send_response
= True
;
4706 fsp
->wbmpx_ptr
= NULL
;
4710 END_PROFILE(SMBwriteBs
);
4714 END_PROFILE(SMBwriteBs
);
4719 /****************************************************************************
4720 reply to a SMBsetattrE
4721 ****************************************************************************/
4723 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4725 struct utimbuf unix_times
;
4727 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4728 START_PROFILE(SMBsetattrE
);
4730 outsize
= set_message(outbuf
,0,0,True
);
4732 CHECK_FSP(fsp
,conn
);
4735 /* Convert the DOS times into unix times. Ignore create
4736 time as UNIX can't set this.
4738 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4739 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4742 * Patch from Ray Frush <frush@engr.colostate.edu>
4743 * Sometimes times are sent as zero - ignore them.
4746 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0))
4748 /* Ignore request */
4751 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4752 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4754 END_PROFILE(SMBsetattrE
);
4757 else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0))
4759 /* set modify time = to access time if modify time was 0 */
4760 unix_times
.modtime
= unix_times
.actime
;
4763 /* Set the date on this file */
4764 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4765 END_PROFILE(SMBsetattrE
);
4766 return(ERROR(ERRDOS
,ERRnoaccess
));
4769 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4770 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4772 END_PROFILE(SMBsetattrE
);
4777 /****************************************************************************
4778 reply to a SMBgetattrE
4779 ****************************************************************************/
4781 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4783 SMB_STRUCT_STAT sbuf
;
4786 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4787 START_PROFILE(SMBgetattrE
);
4789 outsize
= set_message(outbuf
,11,0,True
);
4791 CHECK_FSP(fsp
,conn
);
4794 /* Do an fstat on this file */
4795 if(vfs_fstat(fsp
,fsp
->fd
, &sbuf
)) {
4796 END_PROFILE(SMBgetattrE
);
4797 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4800 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4802 /* Convert the times into dos times. Set create
4803 date to be last modify date as UNIX doesn't save
4805 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4806 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4807 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4810 SIVAL(outbuf
,smb_vwv6
,0);
4811 SIVAL(outbuf
,smb_vwv8
,0);
4815 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4816 SIVAL(outbuf
,smb_vwv8
,SMB_ROUNDUP(sbuf
.st_size
,1024));
4818 SSVAL(outbuf
,smb_vwv10
, mode
);
4820 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
4822 END_PROFILE(SMBgetattrE
);