2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
31 extern int DEBUGLEVEL;
34 extern char magic_char;
35 extern BOOL case_sensitive;
36 extern BOOL case_preserve;
37 extern BOOL short_case_preserve;
38 extern userdom_struct current_user_info;
39 extern pstring global_myname;
40 extern int global_oplock_break;
41 uint32 global_client_caps = 0;
42 unsigned int smb_echo_count = 0;
44 /****************************************************************************
45 report a possible attack via the password buffer overflow bug
46 ****************************************************************************/
48 static void overflow_attack(int len)
51 dbgtext( "ERROR: Invalid password length %d.\n", len );
52 dbgtext( "Your machine may be under attack by someone " );
53 dbgtext( "attempting to exploit an old bug.\n" );
54 dbgtext( "Attack was from IP = %s.\n", client_addr() );
59 /****************************************************************************
60 reply to an special message
61 ****************************************************************************/
63 int reply_special(char *inbuf,char *outbuf)
66 int msg_type = CVAL(inbuf,0);
67 int msg_flags = CVAL(inbuf,1);
69 extern fstring remote_machine;
70 extern fstring local_machine;
76 memset(outbuf,'\0',smb_size);
81 case 0x81: /* session request */
82 CVAL(outbuf,0) = 0x82;
84 if (name_len(inbuf+4) > 50 ||
85 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
86 DEBUG(0,("Invalid name length in session request\n"));
89 name_extract(inbuf,4,name1);
90 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
91 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
94 fstrcpy(remote_machine,name2);
95 remote_machine[15] = 0;
96 trim_string(remote_machine," "," ");
97 strlower(remote_machine);
98 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
100 fstrcpy(local_machine,name1);
101 len = strlen(local_machine);
103 name_type = local_machine[15];
104 local_machine[15] = 0;
106 trim_string(local_machine," "," ");
107 strlower(local_machine);
108 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
110 DEBUG(2,("netbios connect: local=%s remote=%s\n",
111 local_machine, remote_machine ));
113 if (name_type == 'R') {
114 /* We are being asked for a pathworks session ---
116 CVAL(outbuf, 0) = 0x83;
120 /* only add the client's machine name to the list
121 of possibly valid usernames if we are operating
122 in share mode security */
123 if (lp_security() == SEC_SHARE) {
124 add_session_user(remote_machine);
127 reload_services(True);
130 claim_connection(NULL,"",MAXSTATUS,True);
134 case 0x89: /* session keepalive request
135 (some old clients produce this?) */
136 CVAL(outbuf,0) = 0x85;
140 case 0x82: /* positive session response */
141 case 0x83: /* negative session response */
142 case 0x84: /* retarget session response */
143 DEBUG(0,("Unexpected session response\n"));
146 case 0x85: /* session keepalive */
151 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
152 msg_type, msg_flags));
158 /*******************************************************************
159 work out what error to give to a failed connection
160 ********************************************************************/
162 static int connection_error(char *inbuf,char *outbuf,int ecode)
164 if (ecode == ERRnoipc || ecode == ERRnosuchshare)
165 return(ERROR_DOS(ERRDOS,ecode));
167 return(ERROR_DOS(ERRSRV,ecode));
171 /****************************************************************************
173 ****************************************************************************/
175 int reply_tcon(connection_struct *conn,
176 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
183 uint16 vuid = SVAL(inbuf,smb_uid);
188 START_PROFILE(SMBtcon);
190 *service = *user = *password = *dev = 0;
192 p = smb_buf(inbuf)+1;
193 p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1;
194 p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
195 p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1;
198 p = strchr_m(service,'%');
204 p = strrchr_m(service,'\\');
206 pstrcpy(service, p+1);
210 * If the vuid is valid, we should be using that....
213 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
214 pstrcpy(user,validated_username(vuid));
218 * Pass the user through the NT -> unix user mapping
222 (void)map_username(user);
225 * Do any UNIX username case mangling.
227 (void)Get_Pwnam( user, True);
230 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
233 END_PROFILE(SMBtcon);
234 return(connection_error(inbuf,outbuf,ecode));
237 outsize = set_message(outbuf,2,0,True);
238 SSVAL(outbuf,smb_vwv0,max_recv);
239 SSVAL(outbuf,smb_vwv1,conn->cnum);
240 SSVAL(outbuf,smb_tid,conn->cnum);
242 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
243 service, user, conn->cnum));
245 END_PROFILE(SMBtcon);
249 /****************************************************************************
250 Reply to a tcon and X.
251 ****************************************************************************/
253 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
260 uint16 vuid = SVAL(inbuf,smb_uid);
261 int passlen = SVAL(inbuf,smb_vwv3);
264 START_PROFILE(SMBtconX);
266 *service = *user = *password = *devicename = 0;
268 /* we might have to close an old one */
269 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
270 close_cnum(conn,vuid);
273 if (passlen > MAX_PASS_LEN) {
274 overflow_attack(passlen);
275 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
278 memcpy(password,smb_buf(inbuf),passlen);
280 p = smb_buf(inbuf) + passlen;
281 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
284 if (strequal(password," "))
286 passlen = strlen(password);
291 * the service name can be either: \\server\share
292 * or share directly like on the DELL PowerVault 705
295 q = strchr_m(path+2,'\\');
297 END_PROFILE(SMBtconX);
298 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
300 fstrcpy(service,q+1);
303 fstrcpy(service,path);
305 q = strchr_m(service,'%');
310 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
312 DEBUG(4,("Got device type %s\n",devicename));
315 * If the vuid is valid, we should be using that....
318 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
319 pstrcpy(user,validated_username(vuid));
323 * Pass the user through the NT -> unix user mapping
327 (void)map_username(user);
330 * Do any UNIX username case mangling.
332 (void)Get_Pwnam(user, True);
336 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
339 END_PROFILE(SMBtconX);
340 return(connection_error(inbuf,outbuf,ecode));
343 if (Protocol < PROTOCOL_NT1) {
344 set_message(outbuf,2,0,True);
346 p += srvstr_push(outbuf, p, devicename, -1,
347 STR_TERMINATE|STR_ASCII);
348 set_message_end(outbuf,p);
350 /* NT sets the fstype of IPC$ to the null string */
351 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
353 set_message(outbuf,3,0,True);
356 p += srvstr_push(outbuf, p, devicename, -1,
357 STR_TERMINATE|STR_ASCII);
358 p += srvstr_push(outbuf, p, fsname, -1,
361 set_message_end(outbuf,p);
363 /* what does setting this bit do? It is set by NT4 and
364 may affect the ability to autorun mounted cdroms */
365 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
367 init_dfsroot(conn, inbuf, outbuf);
371 DEBUG(3,("tconX service=%s user=%s\n",
374 /* set the incoming and outgoing tid to the just created one */
375 SSVAL(inbuf,smb_tid,conn->cnum);
376 SSVAL(outbuf,smb_tid,conn->cnum);
378 END_PROFILE(SMBtconX);
379 return chain_reply(inbuf,outbuf,length,bufsize);
383 /****************************************************************************
384 reply to an unknown type
385 ****************************************************************************/
386 int reply_unknown(char *inbuf,char *outbuf)
389 type = CVAL(inbuf,smb_com);
391 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
392 smb_fn_name(type), type, type));
394 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
398 /****************************************************************************
400 ****************************************************************************/
401 int reply_ioctl(connection_struct *conn,
402 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
404 uint16 device = SVAL(inbuf,smb_vwv1);
405 uint16 function = SVAL(inbuf,smb_vwv2);
406 uint32 ioctl_code = (device << 16) + function;
407 int replysize, outsize;
409 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
410 START_PROFILE(SMBioctl);
412 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
416 case IOCTL_QUERY_JOB_INFO:
420 END_PROFILE(SMBioctl);
421 return(ERROR_DOS(ERRSRV,ERRnosupport));
424 outsize = set_message(outbuf,8,replysize+1,True);
425 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
426 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
427 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
428 p = smb_buf(outbuf) + 1; /* Allow for alignment */
432 case IOCTL_QUERY_JOB_INFO:
433 SSVAL(p,0,fsp->print_jobid); /* Job number */
434 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
435 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
439 END_PROFILE(SMBioctl);
443 /****************************************************************************
444 This function breaks the authentication split. It needs sorting out.
445 I can't see why we can't hadle this INSIDE the check_password, as in then
446 end all it does it spit out an nt_status code.
447 ****************************************************************************/
448 /****************************************************************************
449 always return an error: it's just a matter of which one...
450 ****************************************************************************/
451 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
452 char *smb_passwd, int smb_passlen,
453 char *smb_nt_passwd, int smb_nt_passlen)
455 /* check if trust account exists */
456 SAM_ACCOUNT *sam_trust_acct = NULL;
459 auth_usersupplied_info user_info;
460 auth_serversupplied_info server_info;
461 AUTH_STR domain, smb_username, wksta_name;
463 ZERO_STRUCT(user_info);
464 ZERO_STRUCT(server_info);
466 ZERO_STRUCT(smb_username);
467 ZERO_STRUCT(wksta_name);
469 domain.str = lp_workgroup();
470 domain.len = strlen(domain.str);
472 user_info.requested_domain = domain;
473 user_info.domain = domain;
475 smb_username.str = user;
476 smb_username.len = strlen(smb_username.str);
478 user_info.requested_username = smb_username; /* For the time-being */
479 user_info.smb_username = smb_username;
481 user_info.wksta_name = wksta_name;
483 user_info.lm_resp.buffer = (uint8 *)smb_passwd;
484 user_info.lm_resp.len = smb_passlen;
485 user_info.nt_resp.buffer = (uint8 *)smb_nt_passwd;
486 user_info.nt_resp.len = smb_nt_passlen;
488 if (!last_challenge(user_info.chal)) {
489 DEBUG(1,("smb_password_ok: no challenge done - password failed\n"));
490 return NT_STATUS_LOGON_FAILURE;
493 pdb_init_sam(&sam_trust_acct);
495 if (lp_security() == SEC_USER) {
496 ret = pdb_getsampwnam(sam_trust_acct, user);
498 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
499 pdb_free_sam(sam_trust_acct);
500 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
504 /* lkclXXXX: workstation entry doesn't exist */
505 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
506 pdb_free_sam(sam_trust_acct);
507 return(ERROR_NT(NT_STATUS_NO_SUCH_USER));
509 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
510 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
511 pdb_free_sam(sam_trust_acct);
512 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
515 if (!smb_password_ok(sam_trust_acct, &user_info, &server_info)) {
516 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
517 pdb_free_sam(sam_trust_acct);
518 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
521 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
522 pdb_free_sam(sam_trust_acct);
523 if (acct_ctrl & ACB_DOMTRUST) {
524 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
525 return(ERROR_NT(NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
528 if (acct_ctrl & ACB_SVRTRUST) {
529 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
530 return(ERROR_NT(NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
533 if (acct_ctrl & ACB_WSTRUST) {
534 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
535 return(ERROR_NT(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
539 /* don't know what to do: indicate logon failure */
540 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
544 /****************************************************************************
545 reply to a session setup command
546 ****************************************************************************/
548 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
555 int smb_apasslen = 0;
557 int smb_ntpasslen = 0;
558 pstring smb_ntpasswd;
559 BOOL valid_password = False;
564 fstring native_lanman;
566 static BOOL done_sesssetup = False;
567 BOOL doencrypt = SMBENCRYPT();
568 START_PROFILE(SMBsesssetupX);
573 smb_bufsize = SVAL(inbuf,smb_vwv2);
575 if (Protocol < PROTOCOL_NT1) {
576 smb_apasslen = SVAL(inbuf,smb_vwv7);
577 if (smb_apasslen > MAX_PASS_LEN) {
578 overflow_attack(smb_apasslen);
579 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
582 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
583 srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE);
585 if (!doencrypt && (lp_security() != SEC_SERVER)) {
586 smb_apasslen = strlen(smb_apasswd);
589 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
590 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
591 enum remote_arch_types ra_type = get_remote_arch();
592 char *p = smb_buf(inbuf);
594 if(global_client_caps == 0)
595 global_client_caps = IVAL(inbuf,smb_vwv11);
597 /* client_caps is used as final determination if client is NT or Win95.
598 This is needed to return the correct error codes in some
602 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
603 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
604 set_remote_arch( RA_WIN95);
608 if (passlen1 != 24 && passlen2 != 24)
611 if (passlen1 > MAX_PASS_LEN) {
612 overflow_attack(passlen1);
613 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
616 passlen1 = MIN(passlen1, MAX_PASS_LEN);
617 passlen2 = MIN(passlen2, MAX_PASS_LEN);
620 /* both Win95 and WinNT stuff up the password lengths for
621 non-encrypting systems. Uggh.
623 if passlen1==24 its a win95 system, and its setting the
624 password length incorrectly. Luckily it still works with the
625 default code because Win95 will null terminate the password
628 if passlen1>0 and passlen2>0 then maybe its a NT box and its
629 setting passlen2 to some random value which really stuffs
630 things up. we need to fix that one. */
632 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
636 if (lp_restrict_anonymous()) {
637 /* there seems to be no reason behind the differences in MS clients formatting
638 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
639 * in particular seems to have an extra null byte between the username and the
640 * domain, or the password length calculation is wrong, which throws off the
641 * string extraction routines below. This makes the value of domain be the
642 * empty string, which fails the restrict anonymous check further down.
643 * This compensates for that, and allows browsing to work in mixed NT and
644 * win95 environments even when restrict anonymous is true. AAB
646 dump_data(100, p, 0x70);
647 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
648 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
649 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
650 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
651 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
656 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
657 /* Save the lanman2 password and the NT md4 password. */
658 smb_apasslen = passlen1;
659 memcpy(smb_apasswd,p,smb_apasslen);
660 smb_apasswd[smb_apasslen] = 0;
661 smb_ntpasslen = passlen2;
662 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
663 smb_ntpasswd[smb_ntpasslen] = 0;
665 /* we use the first password that they gave */
666 smb_apasslen = passlen1;
667 StrnCpy(smb_apasswd,p,smb_apasslen);
669 /* trim the password */
670 smb_apasslen = strlen(smb_apasswd);
672 /* wfwg sometimes uses a space instead of a null */
673 if (strequal(smb_apasswd," ")) {
679 p += passlen1 + passlen2;
680 p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
683 * Incoming user and domain are in DOS codepage format. Convert
686 p += srvstr_pull(inbuf, domain, p, sizeof(domain),
688 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
690 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
692 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
693 domain,native_os,native_lanman));
696 /* don't allow for weird usernames or domains */
697 alpha_strcpy(user, user, ". _-$", sizeof(user));
698 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
699 if (strstr(user, "..") || strstr(domain,"..")) {
700 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
703 if (lp_security() == SEC_SHARE) {
704 /* in share level we should ignore any passwords */
711 DEBUG(3,("sesssetupX:name=[%s]\n",user));
713 /* If name ends in $ then I think it's asking about whether a */
714 /* computer with that name (minus the $) has access. For now */
715 /* say yes to everything ending in $. */
717 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
718 END_PROFILE(SMBsesssetupX);
719 return session_trust_account(conn, inbuf, outbuf, user,
720 smb_apasswd, smb_apasslen,
721 smb_ntpasswd, smb_ntpasslen);
724 if (done_sesssetup && lp_restrict_anonymous()) {
725 /* tests show that even if browsing is done over already validated connections
726 * without a username and password the domain is still provided, which it
727 * wouldn't be if it was a purely anonymous connection. So, in order to
728 * restrict anonymous, we only deny connections that have no session
729 * information. If a domain has been provided, then it's not a purely
730 * anonymous connection. AAB
732 if (!*user && !*smb_apasswd && !*domain) {
733 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
734 END_PROFILE(SMBsesssetupX);
735 return ERROR_DOS(ERRDOS,ERRnoaccess);
739 /* If no username is sent use the guest account */
741 pstrcpy(user,lp_guestaccount(-1));
745 pstrcpy(current_user_info.smb_name,user);
747 reload_services(True);
750 * Save the username before mapping. We will use
751 * the original username sent to us for security=server
752 * and security=domain checking.
755 pstrcpy( orig_user, user);
758 * Always try the "DOMAIN\user" lookup first, as this is the most
759 * specific case. If this fails then try the simple "user" lookup.
760 * But don't do this for guests, as this is always a local user.
766 /* Work out who's who */
768 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
769 domain, lp_winbind_separator(), user);
771 if (sys_getpwnam(dom_user) != NULL) {
772 pstrcpy(user, dom_user);
773 DEBUG(3,("Using unix username %s\n", dom_user));
777 * Pass the user through the NT -> unix user mapping
781 (void)map_username(user);
784 * Do any UNIX username case mangling.
786 smb_getpwnam(user, True);
789 add_session_user(user);
792 valid_password = (pass_check_smb(user, domain,
793 (unsigned char *)smb_apasswd, smb_apasslen,
794 (unsigned char *)smb_ntpasswd, smb_ntpasslen) == NT_STATUS_NOPROBLEMO);
796 /* The true branch will be executed if
797 (1) the NT password failed (or was not tried), and
798 (2) LanMan authentication failed (or was disabled)
802 if (lp_security() >= SEC_USER)
804 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
806 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
807 END_PROFILE(SMBsesssetupX);
808 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
811 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
813 if (smb_getpwnam(user,True))
815 DEBUG(1,("Rejecting user '%s': bad password\n", user));
816 END_PROFILE(SMBsesssetupX);
817 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
822 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
823 * Then always map to guest account - as done below.
827 if (*smb_apasswd || !smb_getpwnam(user,True))
828 pstrcpy(user,lp_guestaccount(-1));
829 DEBUG(3,("Registered username %s for guest access\n",user));
834 if (!smb_getpwnam(user,True)) {
835 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
836 pstrcpy(user,lp_guestaccount(-1));
840 if (!strequal(user,lp_guestaccount(-1)) &&
841 lp_servicenumber(user) < 0)
843 add_home_service(user,get_user_home_dir(user));
847 /* it's ok - setup a reply */
848 if (Protocol < PROTOCOL_NT1) {
849 set_message(outbuf,3,0,True);
852 set_message(outbuf,3,0,True);
854 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
855 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
856 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
857 set_message_end(outbuf,p);
858 /* perhaps grab OS version here?? */
861 /* Set the correct uid in the outgoing and incoming packets
862 We will use this on future requests to determine which
863 user we should become.
866 const struct passwd *pw = smb_getpwnam(user,False);
868 DEBUG(1,("Username %s is invalid on this system\n",user));
869 END_PROFILE(SMBsesssetupX);
870 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
874 full_name = pw->pw_gecos;
878 SSVAL(outbuf,smb_vwv2,1);
880 /* register the name and uid as being validated, so further connections
881 to a uid can get through without a password, on the same VC */
883 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest, full_name);
885 if (sess_vuid == -1) {
886 return ERROR_DOS(ERRDOS,ERRnoaccess);
890 SSVAL(outbuf,smb_uid,sess_vuid);
891 SSVAL(inbuf,smb_uid,sess_vuid);
894 max_send = MIN(max_send,smb_bufsize);
896 DEBUG(6,("Client requested max send size of %d\n", max_send));
898 done_sesssetup = True;
900 END_PROFILE(SMBsesssetupX);
901 return chain_reply(inbuf,outbuf,length,bufsize);
904 /****************************************************************************
906 ****************************************************************************/
907 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
913 BOOL bad_path = False;
914 SMB_STRUCT_STAT sbuf;
915 START_PROFILE(SMBchkpth);
917 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
919 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
921 unix_convert(name,conn,0,&bad_path,&sbuf);
923 mode = SVAL(inbuf,smb_vwv0);
925 if (check_name(name,conn)) {
926 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
927 ok = S_ISDIR(sbuf.st_mode);
931 /* We special case this - as when a Windows machine
932 is parsing a path is steps through the components
933 one at a time - if a component fails it expects
934 ERRbadpath, not ERRbadfile.
936 if(errno == ENOENT) {
937 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
940 return(UNIXERROR(ERRDOS,ERRbadpath));
943 outsize = set_message(outbuf,0,0,True);
945 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
947 END_PROFILE(SMBchkpth);
952 /****************************************************************************
954 ****************************************************************************/
955 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
959 SMB_STRUCT_STAT sbuf;
964 BOOL bad_path = False;
966 START_PROFILE(SMBgetatr);
968 p = smb_buf(inbuf) + 1;
969 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
971 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
973 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
974 under WfWg - weird! */
977 mode = aHIDDEN | aDIR;
978 if (!CAN_WRITE(conn)) mode |= aRONLY;
985 unix_convert(fname,conn,0,&bad_path,&sbuf);
986 if (check_name(fname,conn))
988 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
990 mode = dos_mode(conn,fname,&sbuf);
992 mtime = sbuf.st_mtime;
998 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1004 if((errno == ENOENT) && bad_path)
1006 unix_ERR_class = ERRDOS;
1007 unix_ERR_code = ERRbadpath;
1010 END_PROFILE(SMBgetatr);
1011 return(UNIXERROR(ERRDOS,ERRbadfile));
1014 outsize = set_message(outbuf,10,0,True);
1016 SSVAL(outbuf,smb_vwv0,mode);
1017 if(lp_dos_filetime_resolution(SNUM(conn)) )
1018 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1020 put_dos_date3(outbuf,smb_vwv1,mtime);
1021 SIVAL(outbuf,smb_vwv3,(uint32)size);
1023 if (Protocol >= PROTOCOL_NT1) {
1024 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1027 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1029 END_PROFILE(SMBgetatr);
1034 /****************************************************************************
1036 ****************************************************************************/
1037 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1044 SMB_STRUCT_STAT sbuf;
1045 BOOL bad_path = False;
1048 START_PROFILE(SMBsetatr);
1050 p = smb_buf(inbuf) + 1;
1051 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1052 unix_convert(fname,conn,0,&bad_path,&sbuf);
1054 mode = SVAL(inbuf,smb_vwv0);
1055 mtime = make_unix_date3(inbuf+smb_vwv1);
1057 if (VALID_STAT_OF_DIR(sbuf))
1059 if (check_name(fname,conn))
1060 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1062 ok = set_filetime(conn,fname,mtime);
1066 if((errno == ENOENT) && bad_path)
1068 unix_ERR_class = ERRDOS;
1069 unix_ERR_code = ERRbadpath;
1072 END_PROFILE(SMBsetatr);
1073 return(UNIXERROR(ERRDOS,ERRnoaccess));
1076 outsize = set_message(outbuf,0,0,True);
1078 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1080 END_PROFILE(SMBsetatr);
1085 /****************************************************************************
1087 ****************************************************************************/
1088 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1091 SMB_BIG_UINT dfree,dsize,bsize;
1092 START_PROFILE(SMBdskattr);
1094 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1096 outsize = set_message(outbuf,5,0,True);
1098 SSVAL(outbuf,smb_vwv0,dsize);
1099 SSVAL(outbuf,smb_vwv1,bsize/512);
1100 SSVAL(outbuf,smb_vwv2,512);
1101 SSVAL(outbuf,smb_vwv3,dfree);
1103 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1105 END_PROFILE(SMBdskattr);
1110 /****************************************************************************
1112 Can be called from SMBsearch, SMBffirst or SMBfunique.
1113 ****************************************************************************/
1114 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1125 BOOL finished = False;
1134 BOOL check_descend = False;
1135 BOOL expect_close = False;
1136 BOOL can_open = True;
1137 BOOL bad_path = False;
1138 START_PROFILE(SMBsearch);
1140 *mask = *directory = *fname = 0;
1142 /* If we were called as SMBffirst then we must expect close. */
1143 if(CVAL(inbuf,smb_com) == SMBffirst)
1144 expect_close = True;
1146 outsize = set_message(outbuf,1,3,True);
1147 maxentries = SVAL(inbuf,smb_vwv0);
1148 dirtype = SVAL(inbuf,smb_vwv1);
1149 p = smb_buf(inbuf) + 1;
1150 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1152 status_len = SVAL(p, 0);
1155 /* dirtype &= ~aDIR; */
1157 if (status_len == 0)
1159 SMB_STRUCT_STAT sbuf;
1162 pstrcpy(directory,path);
1164 unix_convert(directory,conn,0,&bad_path,&sbuf);
1167 if (!check_name(directory,conn))
1170 p = strrchr_m(dir2,'/');
1182 p = strrchr_m(directory,'/');
1188 if (strlen(directory) == 0)
1189 pstrcpy(directory,"./");
1190 memset((char *)status,'\0',21);
1191 CVAL(status,0) = dirtype;
1195 memcpy(status,p,21);
1196 dirtype = CVAL(status,0) & 0x1F;
1197 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1200 string_set(&conn->dirpath,dptr_path(dptr_num));
1201 fstrcpy(mask, dptr_wcard(dptr_num));
1206 p = smb_buf(outbuf) + 3;
1210 if (status_len == 0)
1212 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1217 if((errno == ENOENT) && bad_path)
1219 unix_ERR_class = ERRDOS;
1220 unix_ERR_code = ERRbadpath;
1222 END_PROFILE(SMBsearch);
1223 return (UNIXERROR(ERRDOS,ERRnofids));
1225 END_PROFILE(SMBsearch);
1226 return ERROR_DOS(ERRDOS,ERRnofids);
1228 dptr_set_wcard(dptr_num, strdup(mask));
1231 DEBUG(4,("dptr_num is %d\n",dptr_num));
1235 if ((dirtype&0x1F) == aVOLID)
1237 memcpy(p,status,21);
1238 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1239 dptr_fill(p+12,dptr_num);
1240 if (dptr_zero(p+12) && (status_len==0))
1244 p += DIR_STRUCT_SIZE;
1248 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1249 conn->dirpath,lp_dontdescend(SNUM(conn))));
1250 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1251 check_descend = True;
1253 for (i=numentries;(i<maxentries) && !finished;i++)
1256 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1259 memcpy(p,status,21);
1260 make_dir_struct(p,mask,fname,size,mode,date);
1261 dptr_fill(p+12,dptr_num);
1264 p += DIR_STRUCT_SIZE;
1273 if (numentries == 0 || !ok)
1275 CVAL(outbuf,smb_rcls) = ERRDOS;
1276 SSVAL(outbuf,smb_err,ERRnofiles);
1277 dptr_close(&dptr_num);
1280 /* If we were called as SMBffirst with smb_search_id == NULL
1281 and no entries were found then return error and close dirptr
1284 if(ok && expect_close && numentries == 0 && status_len == 0)
1286 CVAL(outbuf,smb_rcls) = ERRDOS;
1287 SSVAL(outbuf,smb_err,ERRnofiles);
1288 /* Also close the dptr - we know it's gone */
1289 dptr_close(&dptr_num);
1292 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1293 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1294 dptr_close(&dptr_num);
1296 SSVAL(outbuf,smb_vwv0,numentries);
1297 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1298 CVAL(smb_buf(outbuf),0) = 5;
1299 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1301 if (Protocol >= PROTOCOL_NT1) {
1302 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1305 outsize += DIR_STRUCT_SIZE*numentries;
1306 smb_setlen(outbuf,outsize - 4);
1308 if ((! *directory) && dptr_path(dptr_num))
1309 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1311 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1312 smb_fn_name(CVAL(inbuf,smb_com)),
1313 mask, directory, dirtype, numentries, maxentries ) );
1315 END_PROFILE(SMBsearch);
1320 /****************************************************************************
1321 reply to a fclose (stop directory search)
1322 ****************************************************************************/
1323 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1332 START_PROFILE(SMBfclose);
1334 outsize = set_message(outbuf,1,0,True);
1335 p = smb_buf(inbuf) + 1;
1336 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1338 status_len = SVAL(p,0);
1341 if (status_len == 0) {
1342 END_PROFILE(SMBfclose);
1343 return ERROR_DOS(ERRSRV,ERRsrverror);
1346 memcpy(status,p,21);
1348 if(dptr_fetch(status+12,&dptr_num)) {
1349 /* Close the dptr - we know it's gone */
1350 dptr_close(&dptr_num);
1353 SSVAL(outbuf,smb_vwv0,0);
1355 DEBUG(3,("search close\n"));
1357 END_PROFILE(SMBfclose);
1362 /****************************************************************************
1364 ****************************************************************************/
1366 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1376 SMB_STRUCT_STAT sbuf;
1377 BOOL bad_path = False;
1379 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1380 START_PROFILE(SMBopen);
1382 share_mode = SVAL(inbuf,smb_vwv0);
1384 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1386 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1388 unix_convert(fname,conn,0,&bad_path,&sbuf);
1390 unixmode = unix_mode(conn,aARCH,fname);
1392 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1393 unixmode, oplock_request,&rmode,NULL);
1397 if((errno == ENOENT) && bad_path)
1399 unix_ERR_class = ERRDOS;
1400 unix_ERR_code = ERRbadpath;
1402 END_PROFILE(SMBopen);
1403 return(UNIXERROR(ERRDOS,ERRnoaccess));
1406 size = sbuf.st_size;
1407 fmode = dos_mode(conn,fname,&sbuf);
1408 mtime = sbuf.st_mtime;
1411 DEBUG(3,("attempt to open a directory %s\n",fname));
1412 close_file(fsp,False);
1413 END_PROFILE(SMBopen);
1414 return ERROR_DOS(ERRDOS,ERRnoaccess);
1417 outsize = set_message(outbuf,7,0,True);
1418 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1419 SSVAL(outbuf,smb_vwv1,fmode);
1420 if(lp_dos_filetime_resolution(SNUM(conn)) )
1421 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1423 put_dos_date3(outbuf,smb_vwv2,mtime);
1424 SIVAL(outbuf,smb_vwv4,(uint32)size);
1425 SSVAL(outbuf,smb_vwv6,rmode);
1427 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1428 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1431 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1432 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1433 END_PROFILE(SMBopen);
1438 /****************************************************************************
1439 reply to an open and X
1440 ****************************************************************************/
1441 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1444 int smb_mode = SVAL(inbuf,smb_vwv3);
1445 int smb_attr = SVAL(inbuf,smb_vwv5);
1446 /* Breakout the oplock request bits so we can set the
1447 reply bits separately. */
1448 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1449 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1450 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1452 int open_flags = SVAL(inbuf,smb_vwv2);
1453 int smb_sattr = SVAL(inbuf,smb_vwv4);
1454 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1456 int smb_ofun = SVAL(inbuf,smb_vwv8);
1459 int fmode=0,mtime=0,rmode=0;
1460 SMB_STRUCT_STAT sbuf;
1462 BOOL bad_path = False;
1464 START_PROFILE(SMBopenX);
1466 /* If it's an IPC, pass off the pipe handler. */
1468 if (lp_nt_pipe_support()) {
1469 END_PROFILE(SMBopenX);
1470 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1472 END_PROFILE(SMBopenX);
1473 return ERROR_DOS(ERRSRV,ERRaccess);
1477 /* XXXX we need to handle passed times, sattr and flags */
1478 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1480 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1482 unix_convert(fname,conn,0,&bad_path,&sbuf);
1484 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1486 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1487 oplock_request, &rmode,&smb_action);
1491 if((errno == ENOENT) && bad_path)
1493 unix_ERR_class = ERRDOS;
1494 unix_ERR_code = ERRbadpath;
1496 END_PROFILE(SMBopenX);
1497 return(UNIXERROR(ERRDOS,ERRnoaccess));
1500 size = sbuf.st_size;
1501 fmode = dos_mode(conn,fname,&sbuf);
1502 mtime = sbuf.st_mtime;
1504 close_file(fsp,False);
1505 END_PROFILE(SMBopenX);
1506 return ERROR_DOS(ERRDOS,ERRnoaccess);
1509 /* If the caller set the extended oplock request bit
1510 and we granted one (by whatever means) - set the
1511 correct bit for extended oplock reply.
1514 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1515 smb_action |= EXTENDED_OPLOCK_GRANTED;
1518 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1519 smb_action |= EXTENDED_OPLOCK_GRANTED;
1522 /* If the caller set the core oplock request bit
1523 and we granted one (by whatever means) - set the
1524 correct bit for core oplock reply.
1527 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1528 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1531 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1532 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1535 set_message(outbuf,15,0,True);
1536 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1537 SSVAL(outbuf,smb_vwv3,fmode);
1538 if(lp_dos_filetime_resolution(SNUM(conn)) )
1539 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1541 put_dos_date3(outbuf,smb_vwv4,mtime);
1542 SIVAL(outbuf,smb_vwv6,(uint32)size);
1543 SSVAL(outbuf,smb_vwv8,rmode);
1544 SSVAL(outbuf,smb_vwv11,smb_action);
1546 END_PROFILE(SMBopenX);
1547 return chain_reply(inbuf,outbuf,length,bufsize);
1551 /****************************************************************************
1552 reply to a SMBulogoffX
1553 ****************************************************************************/
1554 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1556 uint16 vuid = SVAL(inbuf,smb_uid);
1557 user_struct *vuser = get_valid_user_struct(vuid);
1558 START_PROFILE(SMBulogoffX);
1561 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1564 /* in user level security we are supposed to close any files
1565 open by this user */
1566 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1567 file_close_user(vuid);
1570 invalidate_vuid(vuid);
1572 set_message(outbuf,2,0,True);
1574 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1576 END_PROFILE(SMBulogoffX);
1577 return chain_reply(inbuf,outbuf,length,bufsize);
1581 /****************************************************************************
1582 reply to a mknew or a create
1583 ****************************************************************************/
1584 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1592 BOOL bad_path = False;
1594 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1595 SMB_STRUCT_STAT sbuf;
1596 START_PROFILE(SMBcreate);
1598 com = SVAL(inbuf,smb_com);
1600 createmode = SVAL(inbuf,smb_vwv0);
1601 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1603 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1605 unix_convert(fname,conn,0,&bad_path,&sbuf);
1607 if (createmode & aVOLID) {
1608 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1611 unixmode = unix_mode(conn,createmode,fname);
1615 /* We should fail if file exists. */
1616 ofun = FILE_CREATE_IF_NOT_EXIST;
1620 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1621 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1624 /* Open file in dos compatibility share mode. */
1625 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1626 ofun, unixmode, oplock_request, NULL, NULL);
1630 if((errno == ENOENT) && bad_path)
1632 unix_ERR_class = ERRDOS;
1633 unix_ERR_code = ERRbadpath;
1635 END_PROFILE(SMBcreate);
1636 return(UNIXERROR(ERRDOS,ERRnoaccess));
1639 outsize = set_message(outbuf,1,0,True);
1640 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1642 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1643 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1646 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1647 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1649 DEBUG( 2, ( "new file %s\n", fname ) );
1650 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1651 fname, fsp->fd, createmode, (int)unixmode ) );
1653 END_PROFILE(SMBcreate);
1658 /****************************************************************************
1659 reply to a create temporary file
1660 ****************************************************************************/
1661 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1667 BOOL bad_path = False;
1669 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1671 SMB_STRUCT_STAT sbuf;
1674 START_PROFILE(SMBctemp);
1676 createmode = SVAL(inbuf,smb_vwv0);
1677 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1678 pstrcat(fname,"/TMXXXXXX");
1680 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1682 unix_convert(fname,conn,0,&bad_path,&sbuf);
1684 unixmode = unix_mode(conn,createmode,fname);
1686 tmpfd = smb_mkstemp(fname);
1688 END_PROFILE(SMBctemp);
1689 return(UNIXERROR(ERRDOS,ERRnoaccess));
1692 vfs_stat(conn,fname,&sbuf);
1694 /* Open file in dos compatibility share mode. */
1695 /* We should fail if file does not exist. */
1696 fsp = open_file_shared(conn,fname,&sbuf,
1697 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1698 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1699 unixmode, oplock_request, NULL, NULL);
1701 /* close fd from smb_mkstemp() */
1706 if((errno == ENOENT) && bad_path)
1708 unix_ERR_class = ERRDOS;
1709 unix_ERR_code = ERRbadpath;
1711 END_PROFILE(SMBctemp);
1712 return(UNIXERROR(ERRDOS,ERRnoaccess));
1715 outsize = set_message(outbuf,1,0,True);
1716 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1717 CVAL(smb_buf(outbuf),0) = 4;
1718 p = smb_buf(outbuf) + 1;
1719 p += srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1720 set_message_end(outbuf, p);
1722 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1723 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1726 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1727 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1729 DEBUG( 2, ( "created temp file %s\n", fname ) );
1730 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1731 fname, fsp->fd, createmode, (int)unixmode ) );
1733 END_PROFILE(SMBctemp);
1738 /*******************************************************************
1739 check if a user is allowed to delete a file
1740 ********************************************************************/
1741 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1743 SMB_STRUCT_STAT sbuf;
1746 if (!CAN_WRITE(conn)) return(False);
1748 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
1749 fmode = dos_mode(conn,fname,&sbuf);
1750 if (fmode & aDIR) return(False);
1751 if (!lp_delete_readonly(SNUM(conn))) {
1752 if (fmode & aRONLY) return(False);
1754 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1756 if (!check_file_sharing(conn,fname,False)) return(False);
1760 /****************************************************************************
1761 The guts of the unlink command, split out so it may be called by the NT SMB
1763 ****************************************************************************/
1765 int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
1766 int dirtype, char *name)
1772 int error = ERRnoaccess;
1775 BOOL bad_path = False;
1777 SMB_STRUCT_STAT sbuf;
1779 *directory = *mask = 0;
1781 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1783 p = strrchr_m(name,'/');
1785 pstrcpy(directory,"./");
1789 pstrcpy(directory,name);
1794 * We should only check the mangled cache
1795 * here if unix_convert failed. This means
1796 * that the path in 'mask' doesn't exist
1797 * on the file system and so we need to look
1798 * for a possible mangle. This patch from
1799 * Tine Smukavec <valentin.smukavec@hermes.si>.
1802 if (!rc && is_mangled(mask))
1803 check_mangled_cache( mask );
1805 has_wild = ms_has_wild(mask);
1808 pstrcat(directory,"/");
1809 pstrcat(directory,mask);
1810 if (!can_delete(directory,conn,dirtype)) {
1811 return ERROR_NT(NT_STATUS_SHARING_VIOLATION);
1813 if (vfs_unlink(conn,directory) == 0) {
1817 exists = vfs_file_exist(conn,directory,&sbuf);
1819 void *dirptr = NULL;
1822 if (check_name(directory,conn))
1823 dirptr = OpenDir(conn, directory, True);
1825 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1826 the pattern matches against the long name, otherwise the short name
1827 We don't implement this yet XXXX
1833 if (strequal(mask,"????????.???"))
1836 while ((dname = ReadDirName(dirptr))) {
1838 pstrcpy(fname,dname);
1840 if(!mask_match(fname, mask, case_sensitive)) continue;
1842 error = ERRnoaccess;
1843 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1844 if (!can_delete(fname,conn,dirtype)) continue;
1845 if (vfs_unlink(conn,fname) == 0) count++;
1846 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1854 return ERROR_DOS(ERRDOS,error);
1856 if((errno == ENOENT) && bad_path) {
1857 unix_ERR_class = ERRDOS;
1858 unix_ERR_code = ERRbadpath;
1860 return(UNIXERROR(ERRDOS,error));
1867 /****************************************************************************
1869 ****************************************************************************/
1871 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1877 START_PROFILE(SMBunlink);
1879 dirtype = SVAL(inbuf,smb_vwv0);
1881 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1883 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1885 DEBUG(3,("reply_unlink : %s\n",name));
1887 outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
1890 * Win2k needs a changenotify request response before it will
1891 * update after a rename..
1893 process_pending_change_notify_queue((time_t)0);
1895 outsize = set_message(outbuf,0,0,True);
1898 END_PROFILE(SMBunlink);
1903 /****************************************************************************
1904 reply to a readbraw (core+ protocol)
1905 ****************************************************************************/
1907 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1909 size_t maxcount,mincount;
1912 char *header = outbuf;
1915 START_PROFILE(SMBreadbraw);
1918 * Special check if an oplock break has been issued
1919 * and the readraw request croses on the wire, we must
1920 * return a zero length response here.
1923 if(global_oplock_break)
1925 _smb_setlen(header,0);
1926 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1927 DEBUG(5,("readbraw - oplock break finished\n"));
1928 END_PROFILE(SMBreadbraw);
1932 fsp = file_fsp(inbuf,smb_vwv0);
1934 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1936 * fsp could be NULL here so use the value from the packet. JRA.
1938 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1939 _smb_setlen(header,0);
1940 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1941 END_PROFILE(SMBreadbraw);
1945 CHECK_FSP(fsp,conn);
1947 flush_write_cache(fsp, READRAW_FLUSH);
1949 startpos = IVAL(inbuf,smb_vwv1);
1950 if(CVAL(inbuf,smb_wct) == 10) {
1952 * This is a large offset (64 bit) read.
1954 #ifdef LARGE_SMB_OFF_T
1956 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1958 #else /* !LARGE_SMB_OFF_T */
1961 * Ensure we haven't been sent a >32 bit offset.
1964 if(IVAL(inbuf,smb_vwv8) != 0) {
1965 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1966 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1967 _smb_setlen(header,0);
1968 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1969 END_PROFILE(SMBreadbraw);
1973 #endif /* LARGE_SMB_OFF_T */
1976 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1977 (double)startpos ));
1978 _smb_setlen(header,0);
1979 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1980 END_PROFILE(SMBreadbraw);
1984 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1985 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1987 /* ensure we don't overrun the packet size */
1988 maxcount = MIN(65535,maxcount);
1989 maxcount = MAX(mincount,maxcount);
1991 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False))
1993 SMB_OFF_T size = fsp->size;
1994 SMB_OFF_T sizeneeded = startpos + maxcount;
1996 if (size < sizeneeded)
1999 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2001 if (!fsp->can_write)
2005 nread = MIN(maxcount,(size - startpos));
2008 if (nread < mincount)
2011 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2012 fsp->fnum, (double)startpos,
2013 (int)maxcount, (int)mincount, (int)nread ) );
2017 BOOL seek_fail = False;
2019 _smb_setlen(header,nread);
2021 if ((nread-predict) > 0) {
2022 if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
2023 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2030 ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
2031 (SMB_OFF_T)(nread-predict),header,4+predict,
2036 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2037 fsp->fsp_name,startpos,nread,ret));
2039 #else /* UNSAFE_READRAW */
2040 ret = read_file(fsp,header+4,startpos,nread);
2041 if (ret < mincount) ret = 0;
2043 _smb_setlen(header,ret);
2044 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2045 #endif /* UNSAFE_READRAW */
2047 DEBUG(5,("readbraw finished\n"));
2048 END_PROFILE(SMBreadbraw);
2053 /****************************************************************************
2054 reply to a lockread (core+ protocol)
2055 ****************************************************************************/
2056 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2064 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2065 START_PROFILE(SMBlockread);
2067 CHECK_FSP(fsp,conn);
2070 release_level_2_oplocks_on_change(fsp);
2072 numtoread = SVAL(inbuf,smb_vwv1);
2073 startpos = IVAL(inbuf,smb_vwv2);
2075 outsize = set_message(outbuf,5,3,True);
2076 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2077 data = smb_buf(outbuf) + 3;
2080 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2081 * protocol request that predates the read/write lock concept.
2082 * Thus instead of asking for a read lock here we need to ask
2083 * for a write lock. JRA.
2086 status = do_lock(fsp, conn, SVAL(inbuf,smb_pid),
2087 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
2089 if (status != NT_STATUS_NOPROBLEMO) {
2090 if (lp_blocking_locks(SNUM(conn))) {
2092 * A blocking lock was requested. Package up
2093 * this smb into a queued request and push it
2094 * onto the blocking lock queue.
2096 if(push_blocking_lock_request(inbuf, length, -1, 0))
2097 END_PROFILE(SMBlockread);
2100 END_PROFILE(SMBlockread);
2101 return ERROR_NT(status);
2104 nread = read_file(fsp,data,startpos,numtoread);
2107 END_PROFILE(SMBlockread);
2108 return(UNIXERROR(ERRDOS,ERRnoaccess));
2112 SSVAL(outbuf,smb_vwv0,nread);
2113 SSVAL(outbuf,smb_vwv5,nread+3);
2114 SSVAL(smb_buf(outbuf),1,nread);
2116 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2117 fsp->fnum, (int)numtoread, (int)nread));
2119 END_PROFILE(SMBlockread);
2124 /****************************************************************************
2126 ****************************************************************************/
2128 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2135 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2136 START_PROFILE(SMBread);
2138 CHECK_FSP(fsp,conn);
2141 numtoread = SVAL(inbuf,smb_vwv1);
2142 startpos = IVAL(inbuf,smb_vwv2);
2145 outsize = set_message(outbuf,5,3,True);
2146 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2147 data = smb_buf(outbuf) + 3;
2149 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2150 END_PROFILE(SMBread);
2151 return ERROR_DOS(ERRDOS,ERRlock);
2155 nread = read_file(fsp,data,startpos,numtoread);
2158 END_PROFILE(SMBread);
2159 return(UNIXERROR(ERRDOS,ERRnoaccess));
2163 SSVAL(outbuf,smb_vwv0,nread);
2164 SSVAL(outbuf,smb_vwv5,nread+3);
2165 CVAL(smb_buf(outbuf),0) = 1;
2166 SSVAL(smb_buf(outbuf),1,nread);
2168 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2169 fsp->fnum, (int)numtoread, (int)nread ) );
2171 END_PROFILE(SMBread);
2176 /****************************************************************************
2177 reply to a read and X
2178 ****************************************************************************/
2179 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2181 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2182 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2183 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2184 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2187 START_PROFILE(SMBreadX);
2189 /* If it's an IPC, pass off the pipe handler. */
2191 END_PROFILE(SMBreadX);
2192 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2195 CHECK_FSP(fsp,conn);
2198 set_message(outbuf,12,0,True);
2199 data = smb_buf(outbuf);
2201 if(CVAL(inbuf,smb_wct) == 12) {
2202 #ifdef LARGE_SMB_OFF_T
2204 * This is a large offset (64 bit) read.
2206 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2208 #else /* !LARGE_SMB_OFF_T */
2211 * Ensure we haven't been sent a >32 bit offset.
2214 if(IVAL(inbuf,smb_vwv10) != 0) {
2215 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2216 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2217 END_PROFILE(SMBreadX);
2218 return ERROR_DOS(ERRDOS,ERRbadaccess);
2221 #endif /* LARGE_SMB_OFF_T */
2225 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2226 END_PROFILE(SMBreadX);
2227 return ERROR_DOS(ERRDOS,ERRlock);
2229 nread = read_file(fsp,data,startpos,smb_maxcnt);
2232 END_PROFILE(SMBreadX);
2233 return(UNIXERROR(ERRDOS,ERRnoaccess));
2236 SSVAL(outbuf,smb_vwv5,nread);
2237 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2238 SSVAL(smb_buf(outbuf),-2,nread);
2240 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2241 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2243 END_PROFILE(SMBreadX);
2244 return chain_reply(inbuf,outbuf,length,bufsize);
2247 /****************************************************************************
2248 reply to a writebraw (core+ or LANMAN1.0 protocol)
2249 ****************************************************************************/
2251 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2254 ssize_t total_written=0;
2255 size_t numtowrite=0;
2260 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2262 START_PROFILE(SMBwritebraw);
2264 CHECK_FSP(fsp,conn);
2267 tcount = IVAL(inbuf,smb_vwv1);
2268 startpos = IVAL(inbuf,smb_vwv3);
2269 write_through = BITSETW(inbuf+smb_vwv7,0);
2271 /* We have to deal with slightly different formats depending
2272 on whether we are using the core+ or lanman1.0 protocol */
2273 if(Protocol <= PROTOCOL_COREPLUS) {
2274 numtowrite = SVAL(smb_buf(inbuf),-2);
2275 data = smb_buf(inbuf);
2277 numtowrite = SVAL(inbuf,smb_vwv10);
2278 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2281 /* force the error type */
2282 CVAL(inbuf,smb_com) = SMBwritec;
2283 CVAL(outbuf,smb_com) = SMBwritec;
2285 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2286 END_PROFILE(SMBwritebraw);
2287 return ERROR_DOS(ERRDOS,ERRlock);
2291 nwritten = write_file(fsp,data,startpos,numtowrite);
2293 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2294 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2296 if (nwritten < numtowrite) {
2297 END_PROFILE(SMBwritebraw);
2298 return(UNIXERROR(ERRHRD,ERRdiskfull));
2301 total_written = nwritten;
2303 /* Return a message to the redirector to tell it
2304 to send more bytes */
2305 CVAL(outbuf,smb_com) = SMBwritebraw;
2306 SSVALS(outbuf,smb_vwv0,-1);
2307 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2308 if (!send_smb(smbd_server_fd(),outbuf))
2309 exit_server("reply_writebraw: send_smb failed.\n");
2311 /* Now read the raw data into the buffer and write it */
2312 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2313 exit_server("secondary writebraw failed");
2316 /* Even though this is not an smb message, smb_len
2317 returns the generic length of an smb message */
2318 numtowrite = smb_len(inbuf);
2320 if (tcount > nwritten+numtowrite) {
2321 DEBUG(3,("Client overestimated the write %d %d %d\n",
2322 (int)tcount,(int)nwritten,(int)numtowrite));
2325 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2326 (SMB_OFF_T)numtowrite,NULL,0,
2328 total_written += nwritten;
2330 /* Set up outbuf to return the correct return */
2331 outsize = set_message(outbuf,1,0,True);
2332 CVAL(outbuf,smb_com) = SMBwritec;
2333 SSVAL(outbuf,smb_vwv0,total_written);
2335 if (nwritten < (ssize_t)numtowrite) {
2336 CVAL(outbuf,smb_rcls) = ERRHRD;
2337 SSVAL(outbuf,smb_err,ERRdiskfull);
2340 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2341 lp_strict_sync(SNUM(conn)))
2342 sync_file(conn,fsp);
2344 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2345 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2347 /* we won't return a status if write through is not selected - this
2348 follows what WfWg does */
2349 END_PROFILE(SMBwritebraw);
2350 if (!write_through && total_written==tcount) {
2352 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2353 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2355 if (!send_keepalive(smbd_server_fd()))
2356 exit_server("reply_writebraw: send of keepalive failed");
2363 /****************************************************************************
2364 reply to a writeunlock (core+)
2365 ****************************************************************************/
2367 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2368 int size, int dum_buffsize)
2370 ssize_t nwritten = -1;
2375 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2377 START_PROFILE(SMBwriteunlock);
2379 CHECK_FSP(fsp,conn);
2382 numtowrite = SVAL(inbuf,smb_vwv1);
2383 startpos = IVAL(inbuf,smb_vwv2);
2384 data = smb_buf(inbuf) + 3;
2386 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2387 WRITE_LOCK,False)) {
2388 END_PROFILE(SMBwriteunlock);
2389 return ERROR_DOS(ERRDOS,ERRlock);
2392 /* The special X/Open SMB protocol handling of
2393 zero length writes is *NOT* done for
2398 nwritten = write_file(fsp,data,startpos,numtowrite);
2400 if (lp_syncalways(SNUM(conn)))
2401 sync_file(conn,fsp);
2403 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2404 END_PROFILE(SMBwriteunlock);
2405 return(UNIXERROR(ERRDOS,ERRnoaccess));
2408 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2409 (SMB_BIG_UINT)startpos);
2410 if (status != NT_STATUS_NOPROBLEMO) {
2411 END_PROFILE(SMBwriteunlock);
2412 return ERROR_NT(status);
2415 outsize = set_message(outbuf,1,0,True);
2417 SSVAL(outbuf,smb_vwv0,nwritten);
2419 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2420 fsp->fnum, (int)numtowrite, (int)nwritten));
2422 END_PROFILE(SMBwriteunlock);
2427 /****************************************************************************
2429 ****************************************************************************/
2431 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2434 ssize_t nwritten = -1;
2437 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2439 START_PROFILE(SMBwrite);
2441 /* If it's an IPC, pass off the pipe handler. */
2443 END_PROFILE(SMBwrite);
2444 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2447 CHECK_FSP(fsp,conn);
2450 numtowrite = SVAL(inbuf,smb_vwv1);
2451 startpos = IVAL(inbuf,smb_vwv2);
2452 data = smb_buf(inbuf) + 3;
2454 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2455 END_PROFILE(SMBwrite);
2456 return ERROR_DOS(ERRDOS,ERRlock);
2459 /* X/Open SMB protocol says that if smb_vwv1 is
2460 zero then the file size should be extended or
2461 truncated to the size given in smb_vwv[2-3] */
2462 if(numtowrite == 0) {
2463 /* This is actually an allocate call, not set EOF. JRA */
2464 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2466 END_PROFILE(SMBwrite);
2467 return ERROR_NT(NT_STATUS_DISK_FULL);
2470 nwritten = write_file(fsp,data,startpos,numtowrite);
2472 if (lp_syncalways(SNUM(conn)))
2473 sync_file(conn,fsp);
2475 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2476 END_PROFILE(SMBwrite);
2477 return(UNIXERROR(ERRDOS,ERRnoaccess));
2480 outsize = set_message(outbuf,1,0,True);
2482 SSVAL(outbuf,smb_vwv0,nwritten);
2484 if (nwritten < (ssize_t)numtowrite) {
2485 CVAL(outbuf,smb_rcls) = ERRHRD;
2486 SSVAL(outbuf,smb_err,ERRdiskfull);
2489 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2490 fsp->fnum, (int)numtowrite, (int)nwritten));
2492 END_PROFILE(SMBwrite);
2497 /****************************************************************************
2498 reply to a write and X
2499 ****************************************************************************/
2500 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2502 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2503 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2504 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2505 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2506 ssize_t nwritten = -1;
2507 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2508 unsigned int smblen = smb_len(inbuf);
2510 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2511 START_PROFILE(SMBwriteX);
2513 /* If it's an IPC, pass off the pipe handler. */
2515 END_PROFILE(SMBwriteX);
2516 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2519 CHECK_FSP(fsp,conn);
2522 /* Deal with possible LARGE_WRITEX */
2524 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2526 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2527 END_PROFILE(SMBwriteX);
2528 return ERROR_DOS(ERRDOS,ERRbadmem);
2531 data = smb_base(inbuf) + smb_doff;
2533 if(CVAL(inbuf,smb_wct) == 14) {
2534 #ifdef LARGE_SMB_OFF_T
2536 * This is a large offset (64 bit) write.
2538 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2540 #else /* !LARGE_SMB_OFF_T */
2543 * Ensure we haven't been sent a >32 bit offset.
2546 if(IVAL(inbuf,smb_vwv12) != 0) {
2547 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2548 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2549 END_PROFILE(SMBwriteX);
2550 return ERROR_DOS(ERRDOS,ERRbadaccess);
2553 #endif /* LARGE_SMB_OFF_T */
2556 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2557 END_PROFILE(SMBwriteX);
2558 return ERROR_DOS(ERRDOS,ERRlock);
2561 /* X/Open SMB protocol says that, unlike SMBwrite
2562 if the length is zero then NO truncation is
2563 done, just a write of zero. To truncate a file,
2568 nwritten = write_file(fsp,data,startpos,numtowrite);
2570 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2571 END_PROFILE(SMBwriteX);
2572 return(UNIXERROR(ERRDOS,ERRnoaccess));
2575 set_message(outbuf,6,0,True);
2577 SSVAL(outbuf,smb_vwv2,nwritten);
2579 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2581 if (nwritten < (ssize_t)numtowrite) {
2582 CVAL(outbuf,smb_rcls) = ERRHRD;
2583 SSVAL(outbuf,smb_err,ERRdiskfull);
2586 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2587 fsp->fnum, (int)numtowrite, (int)nwritten));
2589 if (lp_syncalways(SNUM(conn)) || write_through)
2590 sync_file(conn,fsp);
2592 END_PROFILE(SMBwriteX);
2593 return chain_reply(inbuf,outbuf,length,bufsize);
2597 /****************************************************************************
2599 ****************************************************************************/
2601 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2607 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2608 START_PROFILE(SMBlseek);
2610 CHECK_FSP(fsp,conn);
2612 flush_write_cache(fsp, SEEK_FLUSH);
2614 mode = SVAL(inbuf,smb_vwv1) & 3;
2615 startpos = IVALS(inbuf,smb_vwv2);
2618 case 0: umode = SEEK_SET; break;
2619 case 1: umode = SEEK_CUR; break;
2620 case 2: umode = SEEK_END; break;
2622 umode = SEEK_SET; break;
2625 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2627 * Check for the special case where a seek before the start
2628 * of the file sets the offset to zero. Added in the CIFS spec,
2632 if(errno == EINVAL) {
2633 SMB_OFF_T current_pos = startpos;
2635 if(umode == SEEK_CUR) {
2637 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2638 END_PROFILE(SMBlseek);
2639 return(UNIXERROR(ERRDOS,ERRnoaccess));
2642 current_pos += startpos;
2644 } else if (umode == SEEK_END) {
2646 SMB_STRUCT_STAT sbuf;
2648 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2649 END_PROFILE(SMBlseek);
2650 return(UNIXERROR(ERRDOS,ERRnoaccess));
2653 current_pos += sbuf.st_size;
2657 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2661 END_PROFILE(SMBlseek);
2662 return(UNIXERROR(ERRDOS,ERRnoaccess));
2668 outsize = set_message(outbuf,2,0,True);
2669 SIVAL(outbuf,smb_vwv0,res);
2671 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2672 fsp->fnum, (double)startpos, (double)res, mode));
2674 END_PROFILE(SMBlseek);
2678 /****************************************************************************
2680 ****************************************************************************/
2682 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2684 int outsize = set_message(outbuf,0,0,True);
2685 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2686 START_PROFILE(SMBflush);
2688 CHECK_FSP(fsp,conn);
2691 file_sync_all(conn);
2693 sync_file(conn,fsp);
2696 DEBUG(3,("flush\n"));
2697 END_PROFILE(SMBflush);
2702 /****************************************************************************
2704 ****************************************************************************/
2705 int reply_exit(connection_struct *conn,
2706 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2709 START_PROFILE(SMBexit);
2710 outsize = set_message(outbuf,0,0,True);
2712 DEBUG(3,("exit\n"));
2714 END_PROFILE(SMBexit);
2719 /****************************************************************************
2720 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2721 ****************************************************************************/
2722 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2727 int32 eclass = 0, err = 0;
2728 files_struct *fsp = NULL;
2729 START_PROFILE(SMBclose);
2731 outsize = set_message(outbuf,0,0,True);
2733 /* If it's an IPC, pass off to the pipe handler. */
2735 END_PROFILE(SMBclose);
2736 return reply_pipe_close(conn, inbuf,outbuf);
2739 fsp = file_fsp(inbuf,smb_vwv0);
2742 * We can only use CHECK_FSP if we know it's not a directory.
2745 if(!fsp || (fsp->conn != conn)) {
2746 END_PROFILE(SMBclose);
2747 return ERROR_DOS(ERRDOS,ERRbadfid);
2750 if(fsp->is_directory || fsp->stat_open) {
2752 * Special case - close NT SMB directory or stat file
2755 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2756 close_file(fsp,True);
2759 * Close ordinary file.
2764 * If there was a modify time outstanding,
2765 * try and set it here.
2767 if(fsp->pending_modtime)
2768 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2771 * Now take care of any time sent in the close.
2773 mtime = make_unix_date3(inbuf+smb_vwv1);
2775 /* try and set the date */
2776 set_filetime(conn, fsp->fsp_name,mtime);
2778 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2780 conn->num_files_open));
2783 * close_file() returns the unix errno if an error
2784 * was detected on close - normally this is due to
2785 * a disk full error. If not then it was probably an I/O error.
2788 if((close_err = close_file(fsp,True)) != 0) {
2790 END_PROFILE(SMBclose);
2791 return (UNIXERROR(ERRHRD,ERRgeneral));
2795 /* We have a cached error */
2797 END_PROFILE(SMBclose);
2798 return ERROR_DOS(eclass,err);
2801 END_PROFILE(SMBclose);
2806 /****************************************************************************
2807 reply to a writeclose (Core+ protocol)
2808 ****************************************************************************/
2810 int reply_writeclose(connection_struct *conn,
2811 char *inbuf,char *outbuf, int size, int dum_buffsize)
2814 ssize_t nwritten = -1;
2820 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2821 START_PROFILE(SMBwriteclose);
2823 CHECK_FSP(fsp,conn);
2826 numtowrite = SVAL(inbuf,smb_vwv1);
2827 startpos = IVAL(inbuf,smb_vwv2);
2828 mtime = make_unix_date3(inbuf+smb_vwv4);
2829 data = smb_buf(inbuf) + 1;
2831 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2832 END_PROFILE(SMBwriteclose);
2833 return ERROR_DOS(ERRDOS,ERRlock);
2836 nwritten = write_file(fsp,data,startpos,numtowrite);
2838 set_filetime(conn, fsp->fsp_name,mtime);
2840 close_err = close_file(fsp,True);
2842 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2843 fsp->fnum, (int)numtowrite, (int)nwritten,
2844 conn->num_files_open));
2846 if (nwritten <= 0) {
2847 END_PROFILE(SMBwriteclose);
2848 return(UNIXERROR(ERRDOS,ERRnoaccess));
2851 if(close_err != 0) {
2853 END_PROFILE(SMBwriteclose);
2854 return(UNIXERROR(ERRHRD,ERRgeneral));
2857 outsize = set_message(outbuf,1,0,True);
2859 SSVAL(outbuf,smb_vwv0,nwritten);
2860 END_PROFILE(SMBwriteclose);
2865 /****************************************************************************
2867 ****************************************************************************/
2868 int reply_lock(connection_struct *conn,
2869 char *inbuf,char *outbuf, int length, int dum_buffsize)
2871 int outsize = set_message(outbuf,0,0,True);
2872 SMB_BIG_UINT count,offset;
2874 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2875 START_PROFILE(SMBlock);
2877 CHECK_FSP(fsp,conn);
2879 release_level_2_oplocks_on_change(fsp);
2881 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2882 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2884 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2885 fsp->fd, fsp->fnum, (double)offset, (double)count));
2887 status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2888 if (status != NT_STATUS_NOPROBLEMO) {
2889 if (status != NT_STATUS_NOPROBLEMO && lp_blocking_locks(SNUM(conn))) {
2891 * A blocking lock was requested. Package up
2892 * this smb into a queued request and push it
2893 * onto the blocking lock queue.
2895 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2896 END_PROFILE(SMBlock);
2900 END_PROFILE(SMBlock);
2901 return ERROR_NT(status);
2904 END_PROFILE(SMBlock);
2909 /****************************************************************************
2911 ****************************************************************************/
2912 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2915 int outsize = set_message(outbuf,0,0,True);
2916 SMB_BIG_UINT count,offset;
2918 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2919 START_PROFILE(SMBunlock);
2921 CHECK_FSP(fsp,conn);
2923 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2924 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2926 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2927 if (status != NT_STATUS_NOPROBLEMO) {
2928 END_PROFILE(SMBunlock);
2929 return ERROR_NT(status);
2932 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2933 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2935 END_PROFILE(SMBunlock);
2940 /****************************************************************************
2942 ****************************************************************************/
2943 int reply_tdis(connection_struct *conn,
2944 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2946 int outsize = set_message(outbuf,0,0,True);
2948 START_PROFILE(SMBtdis);
2950 vuid = SVAL(inbuf,smb_uid);
2953 DEBUG(4,("Invalid connection in tdis\n"));
2954 END_PROFILE(SMBtdis);
2955 return ERROR_DOS(ERRSRV,ERRinvnid);
2960 close_cnum(conn,vuid);
2962 END_PROFILE(SMBtdis);
2968 /****************************************************************************
2970 ****************************************************************************/
2971 int reply_echo(connection_struct *conn,
2972 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2974 int smb_reverb = SVAL(inbuf,smb_vwv0);
2976 unsigned int data_len = smb_buflen(inbuf);
2977 int outsize = set_message(outbuf,1,data_len,True);
2978 START_PROFILE(SMBecho);
2980 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2982 /* copy any incoming data back out */
2984 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2986 if (smb_reverb > 100) {
2987 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2991 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2992 SSVAL(outbuf,smb_vwv0,seq_num);
2994 smb_setlen(outbuf,outsize - 4);
2996 if (!send_smb(smbd_server_fd(),outbuf))
2997 exit_server("reply_echo: send_smb failed.\n");
3000 DEBUG(3,("echo %d times\n", smb_reverb));
3004 END_PROFILE(SMBecho);
3009 /****************************************************************************
3010 reply to a printopen
3011 ****************************************************************************/
3012 int reply_printopen(connection_struct *conn,
3013 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3017 START_PROFILE(SMBsplopen);
3019 if (!CAN_PRINT(conn)) {
3020 END_PROFILE(SMBsplopen);
3021 return ERROR_DOS(ERRDOS,ERRnoaccess);
3024 /* Open for exclusive use, write only. */
3025 fsp = print_fsp_open(conn);
3028 END_PROFILE(SMBsplopen);
3029 return(UNIXERROR(ERRDOS,ERRnoaccess));
3032 outsize = set_message(outbuf,1,0,True);
3033 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3035 DEBUG(3,("openprint fd=%d fnum=%d\n",
3036 fsp->fd, fsp->fnum));
3038 END_PROFILE(SMBsplopen);
3043 /****************************************************************************
3044 reply to a printclose
3045 ****************************************************************************/
3046 int reply_printclose(connection_struct *conn,
3047 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3049 int outsize = set_message(outbuf,0,0,True);
3050 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3052 START_PROFILE(SMBsplclose);
3054 CHECK_FSP(fsp,conn);
3056 if (!CAN_PRINT(conn)) {
3057 END_PROFILE(SMBsplclose);
3058 return ERROR_DOS(ERRDOS,ERRnoaccess);
3061 DEBUG(3,("printclose fd=%d fnum=%d\n",
3062 fsp->fd,fsp->fnum));
3064 close_err = close_file(fsp,True);
3066 if(close_err != 0) {
3068 END_PROFILE(SMBsplclose);
3069 return(UNIXERROR(ERRHRD,ERRgeneral));
3072 END_PROFILE(SMBsplclose);
3077 /****************************************************************************
3078 reply to a printqueue
3079 ****************************************************************************/
3080 int reply_printqueue(connection_struct *conn,
3081 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3083 int outsize = set_message(outbuf,2,3,True);
3084 int max_count = SVAL(inbuf,smb_vwv0);
3085 int start_index = SVAL(inbuf,smb_vwv1);
3086 START_PROFILE(SMBsplretq);
3088 /* we used to allow the client to get the cnum wrong, but that
3089 is really quite gross and only worked when there was only
3090 one printer - I think we should now only accept it if they
3091 get it right (tridge) */
3092 if (!CAN_PRINT(conn)) {
3093 END_PROFILE(SMBsplretq);
3094 return ERROR_DOS(ERRDOS,ERRnoaccess);
3097 SSVAL(outbuf,smb_vwv0,0);
3098 SSVAL(outbuf,smb_vwv1,0);
3099 CVAL(smb_buf(outbuf),0) = 1;
3100 SSVAL(smb_buf(outbuf),1,0);
3102 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3103 start_index, max_count));
3106 print_queue_struct *queue = NULL;
3107 char *p = smb_buf(outbuf) + 3;
3108 int count = print_queue_status(SNUM(conn), &queue,NULL);
3109 int num_to_get = ABS(max_count);
3110 int first = (max_count>0?start_index:start_index+max_count+1);
3116 num_to_get = MIN(num_to_get,count-first);
3119 for (i=first;i<first+num_to_get;i++) {
3120 put_dos_date2(p,0,queue[i].time);
3121 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3122 SSVAL(p,5, queue[i].job);
3123 SIVAL(p,7,queue[i].size);
3125 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII);
3130 outsize = set_message(outbuf,2,28*count+3,False);
3131 SSVAL(outbuf,smb_vwv0,count);
3132 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3133 CVAL(smb_buf(outbuf),0) = 1;
3134 SSVAL(smb_buf(outbuf),1,28*count);
3137 if (queue) free(queue);
3139 DEBUG(3,("%d entries returned in queue\n",count));
3142 END_PROFILE(SMBsplretq);
3147 /****************************************************************************
3148 reply to a printwrite
3149 ****************************************************************************/
3150 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3153 int outsize = set_message(outbuf,0,0,True);
3155 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3156 START_PROFILE(SMBsplwr);
3158 if (!CAN_PRINT(conn)) {
3159 END_PROFILE(SMBsplwr);
3160 return ERROR_DOS(ERRDOS,ERRnoaccess);
3163 CHECK_FSP(fsp,conn);
3166 numtowrite = SVAL(smb_buf(inbuf),1);
3167 data = smb_buf(inbuf) + 3;
3169 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3170 END_PROFILE(SMBsplwr);
3171 return(UNIXERROR(ERRDOS,ERRnoaccess));
3174 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3176 END_PROFILE(SMBsplwr);
3181 /****************************************************************************
3182 The guts of the mkdir command, split out so it may be called by the NT SMB
3184 ****************************************************************************/
3185 int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
3187 BOOL bad_path = False;
3188 SMB_STRUCT_STAT sbuf;
3191 unix_convert(directory,conn,0,&bad_path,&sbuf);
3193 if (check_name(directory, conn))
3194 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3198 if((errno == ENOENT) && bad_path)
3200 unix_ERR_class = ERRDOS;
3201 unix_ERR_code = ERRbadpath;
3203 return(UNIXERROR(ERRDOS,ERRnoaccess));
3209 /****************************************************************************
3211 ****************************************************************************/
3212 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3216 START_PROFILE(SMBmkdir);
3218 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3220 outsize=mkdir_internal(conn, inbuf, outbuf, directory);
3222 outsize = set_message(outbuf,0,0,True);
3224 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3226 END_PROFILE(SMBmkdir);
3230 /****************************************************************************
3231 Static function used by reply_rmdir to delete an entire directory
3233 ****************************************************************************/
3235 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3239 void *dirptr = OpenDir(NULL, directory, False);
3244 while((dname = ReadDirName(dirptr)))
3249 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3252 /* Construct the full name. */
3253 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3259 pstrcpy(fullname, directory);
3260 pstrcat(fullname, "/");
3261 pstrcat(fullname, dname);
3263 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3269 if(st.st_mode & S_IFDIR)
3271 if(recursive_rmdir(conn, fullname)!=0)
3276 if(vfs_rmdir(conn,fullname) != 0)
3282 else if(vfs_unlink(conn,fullname) != 0)
3292 /****************************************************************************
3293 The internals of the rmdir code - called elsewhere.
3294 ****************************************************************************/
3296 BOOL rmdir_internals(connection_struct *conn, char *directory)
3300 ok = (vfs_rmdir(conn,directory) == 0);
3301 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3304 * Check to see if the only thing in this directory are
3305 * vetoed files/directories. If so then delete them and
3306 * retry. If we fail to delete any of them (and we *don't*
3307 * do a recursive delete) then fail the rmdir.
3309 BOOL all_veto_files = True;
3311 void *dirptr = OpenDir(conn, directory, False);
3315 int dirpos = TellDir(dirptr);
3316 while ((dname = ReadDirName(dirptr)))
3318 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3320 if(!IS_VETO_PATH(conn, dname))
3322 all_veto_files = False;
3328 SeekDir(dirptr,dirpos);
3329 while ((dname = ReadDirName(dirptr)))
3334 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3337 /* Construct the full name. */
3338 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3343 pstrcpy(fullname, directory);
3344 pstrcat(fullname, "/");
3345 pstrcat(fullname, dname);
3347 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3349 if(st.st_mode & S_IFDIR)
3351 if(lp_recursive_veto_delete(SNUM(conn)))
3353 if(recursive_rmdir(conn, fullname) != 0)
3356 if(vfs_rmdir(conn,fullname) != 0)
3359 else if(vfs_unlink(conn,fullname) != 0)
3363 /* Retry the rmdir */
3364 ok = (vfs_rmdir(conn,directory) == 0);
3374 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3375 directory,strerror(errno)));
3380 /****************************************************************************
3382 ****************************************************************************/
3384 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3389 BOOL bad_path = False;
3390 SMB_STRUCT_STAT sbuf;
3391 START_PROFILE(SMBrmdir);
3393 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3395 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3397 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3399 if (check_name(directory,conn))
3401 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3402 ok = rmdir_internals(conn, directory);
3407 if((errno == ENOENT) && bad_path)
3409 unix_ERR_class = ERRDOS;
3410 unix_ERR_code = ERRbadpath;
3412 END_PROFILE(SMBrmdir);
3413 return(UNIXERROR(ERRDOS,ERRbadpath));
3416 outsize = set_message(outbuf,0,0,True);
3418 DEBUG( 3, ( "rmdir %s\n", directory ) );
3420 END_PROFILE(SMBrmdir);
3425 /*******************************************************************
3426 resolve wildcards in a filename rename
3427 ********************************************************************/
3428 static BOOL resolve_wildcards(char *name1,char *name2)
3430 fstring root1,root2;
3434 name1 = strrchr_m(name1,'/');
3435 name2 = strrchr_m(name2,'/');
3437 if (!name1 || !name2) return(False);
3439 fstrcpy(root1,name1);
3440 fstrcpy(root2,name2);
3441 p = strrchr_m(root1,'.');
3448 p = strrchr_m(root2,'.');
3480 pstrcpy(name2,root2);
3483 pstrcat(name2,ext2);
3489 /*******************************************************************
3490 check if a user is allowed to rename a file
3491 ********************************************************************/
3492 static BOOL can_rename(char *fname,connection_struct *conn)
3494 SMB_STRUCT_STAT sbuf;
3496 if (!CAN_WRITE(conn)) return(False);
3498 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
3499 if (!check_file_sharing(conn,fname,True)) return(False);
3503 /****************************************************************************
3504 The guts of the rename command, split out so it may be called by the NT SMB
3506 ****************************************************************************/
3507 int rename_internals(connection_struct *conn,
3508 char *inbuf, char *outbuf, char *name,
3509 char *newname, BOOL replace_if_exists)
3513 pstring newname_last_component;
3516 BOOL bad_path1 = False;
3517 BOOL bad_path2 = False;
3519 int error = ERRnoaccess;
3522 SMB_STRUCT_STAT sbuf1, sbuf2;
3524 *directory = *mask = 0;
3526 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3527 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3530 * Split the old name into directory and last component
3531 * strings. Note that unix_convert may have stripped off a
3532 * leading ./ from both name and newname if the rename is
3533 * at the root of the share. We need to make sure either both
3534 * name and newname contain a / character or neither of them do
3535 * as this is checked in resolve_wildcards().
3538 p = strrchr_m(name,'/');
3540 pstrcpy(directory,".");
3544 pstrcpy(directory,name);
3546 *p = '/'; /* Replace needed for exceptional test below. */
3550 * We should only check the mangled cache
3551 * here if unix_convert failed. This means
3552 * that the path in 'mask' doesn't exist
3553 * on the file system and so we need to look
3554 * for a possible mangle. This patch from
3555 * Tine Smukavec <valentin.smukavec@hermes.si>.
3558 if (!rc && is_mangled(mask))
3559 check_mangled_cache( mask );
3561 has_wild = ms_has_wild(mask);
3565 * No wildcards - just process the one file.
3567 BOOL is_short_name = is_8_3(name, True);
3569 /* Add a terminating '/' to the directory name. */
3570 pstrcat(directory,"/");
3571 pstrcat(directory,mask);
3573 /* Ensure newname contains a '/' also */
3574 if(strrchr_m(newname,'/') == 0) {
3577 pstrcpy(tmpstr, "./");
3578 pstrcat(tmpstr, newname);
3579 pstrcpy(newname, tmpstr);
3582 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",
3583 case_sensitive, case_preserve, short_case_preserve, directory,
3584 newname, newname_last_component, is_short_name));
3587 * Check for special case with case preserving and not
3588 * case sensitive, if directory and newname are identical,
3589 * and the old last component differs from the original
3590 * last component only by case, then we should allow
3591 * the rename (user is trying to change the case of the
3594 if((case_sensitive == False) &&
3595 (((case_preserve == True) &&
3596 (is_short_name == False)) ||
3597 ((short_case_preserve == True) &&
3598 (is_short_name == True))) &&
3599 strcsequal(directory, newname)) {
3600 pstring newname_modified_last_component;
3603 * Get the last component of the modified name.
3604 * Note that we guarantee that newname contains a '/'
3607 p = strrchr_m(newname,'/');
3608 pstrcpy(newname_modified_last_component,p+1);
3610 if(strcsequal(newname_modified_last_component,
3611 newname_last_component) == False) {
3613 * Replace the modified last component with
3616 pstrcpy(p+1, newname_last_component);
3620 if(replace_if_exists) {
3622 * NT SMB specific flag - rename can overwrite
3623 * file with the same name so don't check for
3627 if(resolve_wildcards(directory,newname) &&
3628 can_rename(directory,conn) &&
3629 !conn->vfs_ops.rename(conn,directory,newname))
3632 if (resolve_wildcards(directory,newname) &&
3633 can_rename(directory,conn) &&
3634 !vfs_file_exist(conn,newname,NULL) &&
3635 !conn->vfs_ops.rename(conn,directory,newname))
3639 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3640 directory,newname));
3642 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3643 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3649 * Wildcards - process each file that matches.
3651 void *dirptr = NULL;
3655 if (check_name(directory,conn))
3656 dirptr = OpenDir(conn, directory, True);
3661 if (strequal(mask,"????????.???"))
3664 while ((dname = ReadDirName(dirptr))) {
3667 pstrcpy(fname,dname);
3669 if(!mask_match(fname, mask, case_sensitive))
3672 error = ERRnoaccess;
3673 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3674 if (!can_rename(fname,conn)) {
3675 DEBUG(6,("rename %s refused\n", fname));
3678 pstrcpy(destname,newname);
3680 if (!resolve_wildcards(fname,destname)) {
3681 DEBUG(6,("resolve_wildcards %s %s failed\n",
3686 if (!replace_if_exists &&
3687 vfs_file_exist(conn,destname, NULL)) {
3688 DEBUG(6,("file_exist %s\n", destname));
3693 if (!conn->vfs_ops.rename(conn,fname,destname))
3695 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3703 return ERROR_DOS(ERRDOS,error);
3705 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3706 unix_ERR_class = ERRDOS;
3707 unix_ERR_code = ERRbadpath;
3709 return(UNIXERROR(ERRDOS,error));
3716 /****************************************************************************
3718 ****************************************************************************/
3720 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3727 START_PROFILE(SMBmv);
3729 p = smb_buf(inbuf) + 1;
3730 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3732 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3734 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3735 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3737 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3739 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3743 * Win2k needs a changenotify request response before it will
3744 * update after a rename..
3747 process_pending_change_notify_queue((time_t)0);
3749 outsize = set_message(outbuf,0,0,True);
3756 /*******************************************************************
3757 copy a file as part of a reply_copy
3758 ******************************************************************/
3760 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3761 int count,BOOL target_is_directory, int *err_ret)
3764 SMB_STRUCT_STAT src_sbuf, sbuf2;
3766 files_struct *fsp1,*fsp2;
3771 pstrcpy(dest,dest1);
3772 if (target_is_directory) {
3773 char *p = strrchr_m(src,'/');
3782 if (!vfs_file_exist(conn,src,&src_sbuf))
3785 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3786 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3792 if (!target_is_directory && count)
3793 ofun = FILE_EXISTS_OPEN;
3795 vfs_stat(conn,dest,&sbuf2);
3796 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3797 ofun,src_sbuf.st_mode,0,&Access,&action);
3800 close_file(fsp1,False);
3804 if ((ofun&3) == 1) {
3805 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3806 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3809 * Stop the copy from occurring.
3812 src_sbuf.st_size = 0;
3816 if (src_sbuf.st_size)
3817 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
3819 close_file(fsp1,False);
3821 * As we are opening fsp1 read-only we only expect
3822 * an error on close on fsp2 if we are out of space.
3823 * Thus we don't look at the error return from the
3826 *err_ret = close_file(fsp2,False);
3828 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3833 /****************************************************************************
3834 reply to a file copy.
3835 ****************************************************************************/
3836 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3841 pstring mask,newname;
3844 int error = ERRnoaccess;
3848 int tid2 = SVAL(inbuf,smb_vwv0);
3849 int ofun = SVAL(inbuf,smb_vwv1);
3850 int flags = SVAL(inbuf,smb_vwv2);
3851 BOOL target_is_directory=False;
3852 BOOL bad_path1 = False;
3853 BOOL bad_path2 = False;
3855 SMB_STRUCT_STAT sbuf1, sbuf2;
3856 START_PROFILE(SMBcopy);
3858 *directory = *mask = 0;
3861 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3862 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3864 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3866 if (tid2 != conn->cnum) {
3867 /* can't currently handle inter share copies XXXX */
3868 DEBUG(3,("Rejecting inter-share copy\n"));
3869 END_PROFILE(SMBcopy);
3870 return ERROR_DOS(ERRSRV,ERRinvdevice);
3873 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3874 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3876 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3877 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3879 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3881 if ((flags&1) && target_is_directory) {
3882 END_PROFILE(SMBcopy);
3883 return ERROR_DOS(ERRDOS,ERRbadfile);
3886 if ((flags&2) && !target_is_directory) {
3887 END_PROFILE(SMBcopy);
3888 return ERROR_DOS(ERRDOS,ERRbadpath);
3891 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3892 /* wants a tree copy! XXXX */
3893 DEBUG(3,("Rejecting tree copy\n"));
3894 END_PROFILE(SMBcopy);
3895 return ERROR_DOS(ERRSRV,ERRerror);
3898 p = strrchr_m(name,'/');
3900 pstrcpy(directory,"./");
3904 pstrcpy(directory,name);
3909 * We should only check the mangled cache
3910 * here if unix_convert failed. This means
3911 * that the path in 'mask' doesn't exist
3912 * on the file system and so we need to look
3913 * for a possible mangle. This patch from
3914 * Tine Smukavec <valentin.smukavec@hermes.si>.
3917 if (!rc && is_mangled(mask))
3918 check_mangled_cache( mask );
3920 has_wild = ms_has_wild(mask);
3923 pstrcat(directory,"/");
3924 pstrcat(directory,mask);
3925 if (resolve_wildcards(directory,newname) &&
3926 copy_file(directory,newname,conn,ofun,
3927 count,target_is_directory,&err)) count++;
3930 END_PROFILE(SMBcopy);
3931 return(UNIXERROR(ERRHRD,ERRgeneral));
3933 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3935 void *dirptr = NULL;
3939 if (check_name(directory,conn))
3940 dirptr = OpenDir(conn, directory, True);
3945 if (strequal(mask,"????????.???"))
3948 while ((dname = ReadDirName(dirptr))) {
3950 pstrcpy(fname,dname);
3952 if(!mask_match(fname, mask, case_sensitive))
3955 error = ERRnoaccess;
3956 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3957 pstrcpy(destname,newname);
3958 if (resolve_wildcards(fname,destname) &&
3959 copy_file(fname,destname,conn,ofun,
3960 count,target_is_directory,&err)) count++;
3961 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3969 /* Error on close... */
3971 END_PROFILE(SMBcopy);
3972 return(UNIXERROR(ERRHRD,ERRgeneral));
3976 END_PROFILE(SMBcopy);
3977 return ERROR_DOS(ERRDOS,error);
3980 if((errno == ENOENT) && (bad_path1 || bad_path2))
3982 unix_ERR_class = ERRDOS;
3983 unix_ERR_code = ERRbadpath;
3985 END_PROFILE(SMBcopy);
3986 return(UNIXERROR(ERRDOS,error));
3990 outsize = set_message(outbuf,1,0,True);
3991 SSVAL(outbuf,smb_vwv0,count);
3993 END_PROFILE(SMBcopy);
3997 /****************************************************************************
3999 ****************************************************************************/
4000 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4006 START_PROFILE(pathworks_setdir);
4009 if (!CAN_SETDIR(snum)) {
4010 END_PROFILE(pathworks_setdir);
4011 return ERROR_DOS(ERRDOS,ERRnoaccess);
4014 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
4016 if (strlen(newdir) == 0) {
4019 ok = vfs_directory_exist(conn,newdir,NULL);
4021 string_set(&conn->connectpath,newdir);
4026 END_PROFILE(pathworks_setdir);
4027 return ERROR_DOS(ERRDOS,ERRbadpath);
4030 outsize = set_message(outbuf,0,0,True);
4031 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4033 DEBUG(3,("setdir %s\n", newdir));
4035 END_PROFILE(pathworks_setdir);
4039 /****************************************************************************
4040 Get a lock pid, dealing with large count requests.
4041 ****************************************************************************/
4043 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4045 if(!large_file_format)
4046 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4048 return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
4051 /****************************************************************************
4052 Get a lock count, dealing with large count requests.
4053 ****************************************************************************/
4055 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4057 SMB_BIG_UINT count = 0;
4059 if(!large_file_format) {
4060 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4063 #if defined(HAVE_LONGLONG)
4064 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4065 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4066 #else /* HAVE_LONGLONG */
4069 * NT4.x seems to be broken in that it sends large file (64 bit)
4070 * lockingX calls even if the CAP_LARGE_FILES was *not*
4071 * negotiated. For boxes without large unsigned ints truncate the
4072 * lock count by dropping the top 32 bits.
4075 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4076 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4077 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4078 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4079 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4082 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4083 #endif /* HAVE_LONGLONG */
4089 /****************************************************************************
4090 Get a lock offset, dealing with large offset requests.
4091 ****************************************************************************/
4093 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4095 SMB_BIG_UINT offset = 0;
4099 if(!large_file_format) {
4100 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4103 #if defined(HAVE_LONGLONG)
4104 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4105 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4106 #else /* HAVE_LONGLONG */
4109 * NT4.x seems to be broken in that it sends large file (64 bit)
4110 * lockingX calls even if the CAP_LARGE_FILES was *not*
4111 * negotiated. For boxes without large unsigned ints mangle the
4112 * lock offset by mapping the top 32 bits onto the lower 32.
4115 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4116 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4117 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4120 if((new_low = map_lock_offset(high, low)) == 0) {
4122 return (SMB_BIG_UINT)-1;
4125 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4126 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4127 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4128 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4131 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4132 #endif /* HAVE_LONGLONG */
4138 /****************************************************************************
4139 reply to a lockingX request
4140 ****************************************************************************/
4142 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4144 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4145 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4146 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4147 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4148 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4149 SMB_BIG_UINT count = 0, offset = 0;
4151 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4154 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4158 START_PROFILE(SMBlockingX);
4160 CHECK_FSP(fsp,conn);
4162 data = smb_buf(inbuf);
4164 /* Check if this is an oplock break on a file
4165 we have granted an oplock on.
4167 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4168 /* Client can insist on breaking to none. */
4169 BOOL break_to_none = (oplocklevel == 0);
4171 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4172 (unsigned int)oplocklevel, fsp->fnum ));
4175 * Make sure we have granted an exclusive or batch oplock on this file.
4178 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4179 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4180 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4182 /* if this is a pure oplock break request then don't send a reply */
4183 if (num_locks == 0 && num_ulocks == 0) {
4184 END_PROFILE(SMBlockingX);
4187 END_PROFILE(SMBlockingX);
4188 return ERROR_DOS(ERRDOS,ERRlock);
4192 if (remove_oplock(fsp, break_to_none) == False) {
4193 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4197 /* if this is a pure oplock break request then don't send a reply */
4198 if (num_locks == 0 && num_ulocks == 0) {
4199 /* Sanity check - ensure a pure oplock break is not a
4201 if(CVAL(inbuf,smb_vwv0) != 0xff)
4202 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4203 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4204 END_PROFILE(SMBlockingX);
4210 * We do this check *after* we have checked this is not a oplock break
4211 * response message. JRA.
4214 release_level_2_oplocks_on_change(fsp);
4216 /* Data now points at the beginning of the list
4217 of smb_unlkrng structs */
4218 for(i = 0; i < (int)num_ulocks; i++) {
4219 lock_pid = get_lock_pid( data, i, large_file_format);
4220 count = get_lock_count( data, i, large_file_format);
4221 offset = get_lock_offset( data, i, large_file_format, &err);
4224 * There is no error code marked "stupid client bug".... :-).
4227 END_PROFILE(SMBlockingX);
4228 return ERROR_DOS(ERRDOS,ERRnoaccess);
4231 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4232 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4234 status = do_unlock(fsp,conn,lock_pid,count,offset);
4235 if (status != NT_STATUS_NOPROBLEMO) {
4236 END_PROFILE(SMBlockingX);
4237 return ERROR_NT(status);
4241 /* Setup the timeout in seconds. */
4242 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4244 /* Now do any requested locks */
4245 data += ((large_file_format ? 20 : 10)*num_ulocks);
4247 /* Data now points at the beginning of the list
4248 of smb_lkrng structs */
4250 for(i = 0; i < (int)num_locks; i++) {
4251 lock_pid = get_lock_pid( data, i, large_file_format);
4252 count = get_lock_count( data, i, large_file_format);
4253 offset = get_lock_offset( data, i, large_file_format, &err);
4256 * There is no error code marked "stupid client bug".... :-).
4259 END_PROFILE(SMBlockingX);
4260 return ERROR_DOS(ERRDOS,ERRnoaccess);
4263 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
4264 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4266 status = do_lock(fsp,conn,lock_pid, count,offset,
4267 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
4268 if (status != NT_STATUS_NOPROBLEMO) {
4269 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4271 * A blocking lock was requested. Package up
4272 * this smb into a queued request and push it
4273 * onto the blocking lock queue.
4275 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4276 END_PROFILE(SMBlockingX);
4284 /* If any of the above locks failed, then we must unlock
4285 all of the previous locks (X/Open spec). */
4286 if (i != num_locks && num_locks != 0) {
4288 * Ensure we don't do a remove on the lock that just failed,
4289 * as under POSIX rules, if we have a lock already there, we
4290 * will delete it (and we shouldn't) .....
4292 for(i--; i >= 0; i--) {
4293 lock_pid = get_lock_pid( data, i, large_file_format);
4294 count = get_lock_count( data, i, large_file_format);
4295 offset = get_lock_offset( data, i, large_file_format, &err);
4298 * There is no error code marked "stupid client bug".... :-).
4301 END_PROFILE(SMBlockingX);
4302 return ERROR_DOS(ERRDOS,ERRnoaccess);
4305 do_unlock(fsp,conn,lock_pid,count,offset);
4307 END_PROFILE(SMBlockingX);
4308 return ERROR_NT(status);
4311 set_message(outbuf,2,0,True);
4313 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4314 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4316 END_PROFILE(SMBlockingX);
4317 return chain_reply(inbuf,outbuf,length,bufsize);
4321 /****************************************************************************
4322 reply to a SMBreadbmpx (read block multiplex) request
4323 ****************************************************************************/
4324 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4335 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4336 START_PROFILE(SMBreadBmpx);
4338 /* this function doesn't seem to work - disable by default */
4339 if (!lp_readbmpx()) {
4340 END_PROFILE(SMBreadBmpx);
4341 return ERROR_DOS(ERRSRV,ERRuseSTD);
4344 outsize = set_message(outbuf,8,0,True);
4346 CHECK_FSP(fsp,conn);
4349 startpos = IVAL(inbuf,smb_vwv1);
4350 maxcount = SVAL(inbuf,smb_vwv3);
4352 data = smb_buf(outbuf);
4353 pad = ((long)data)%4;
4354 if (pad) pad = 4 - pad;
4357 max_per_packet = bufsize-(outsize+pad);
4361 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4362 END_PROFILE(SMBreadBmpx);
4363 return ERROR_DOS(ERRDOS,ERRlock);
4368 size_t N = MIN(max_per_packet,tcount-total_read);
4370 nread = read_file(fsp,data,startpos,N);
4372 if (nread <= 0) nread = 0;
4374 if (nread < (ssize_t)N)
4375 tcount = total_read + nread;
4377 set_message(outbuf,8,nread,False);
4378 SIVAL(outbuf,smb_vwv0,startpos);
4379 SSVAL(outbuf,smb_vwv2,tcount);
4380 SSVAL(outbuf,smb_vwv6,nread);
4381 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4383 if (!send_smb(smbd_server_fd(),outbuf))
4384 exit_server("reply_readbmpx: send_smb failed.\n");
4386 total_read += nread;
4389 while (total_read < (ssize_t)tcount);
4391 END_PROFILE(SMBreadBmpx);
4396 /****************************************************************************
4397 reply to a SMBsetattrE
4398 ****************************************************************************/
4400 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4402 struct utimbuf unix_times;
4404 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4405 START_PROFILE(SMBsetattrE);
4407 outsize = set_message(outbuf,0,0,True);
4409 CHECK_FSP(fsp,conn);
4411 /* Convert the DOS times into unix times. Ignore create
4412 time as UNIX can't set this.
4414 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4415 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4418 * Patch from Ray Frush <frush@engr.colostate.edu>
4419 * Sometimes times are sent as zero - ignore them.
4422 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4424 /* Ignore request */
4427 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4428 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4430 END_PROFILE(SMBsetattrE);
4433 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4435 /* set modify time = to access time if modify time was 0 */
4436 unix_times.modtime = unix_times.actime;
4439 /* Set the date on this file */
4440 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4441 END_PROFILE(SMBsetattrE);
4442 return ERROR_DOS(ERRDOS,ERRnoaccess);
4445 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4446 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4448 END_PROFILE(SMBsetattrE);
4453 /****************************************************************************
4454 reply to a SMBgetattrE
4455 ****************************************************************************/
4457 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4459 SMB_STRUCT_STAT sbuf;
4462 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4463 START_PROFILE(SMBgetattrE);
4465 outsize = set_message(outbuf,11,0,True);
4467 CHECK_FSP(fsp,conn);
4469 /* Do an fstat on this file */
4470 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4471 END_PROFILE(SMBgetattrE);
4472 return(UNIXERROR(ERRDOS,ERRnoaccess));
4475 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4477 /* Convert the times into dos times. Set create
4478 date to be last modify date as UNIX doesn't save
4480 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4481 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4482 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4485 SIVAL(outbuf,smb_vwv6,0);
4486 SIVAL(outbuf,smb_vwv8,0);
4490 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4491 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4493 SSVAL(outbuf,smb_vwv10, mode);
4495 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4497 END_PROFILE(SMBgetattrE);