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
31 /* look in server.c for some explanation of these variables */
33 extern int DEBUGLEVEL;
36 extern char magic_char;
37 extern BOOL case_sensitive;
38 extern BOOL case_preserve;
39 extern BOOL short_case_preserve;
40 extern pstring sesssetup_user;
41 extern fstring global_myworkgroup;
43 extern int global_oplock_break;
44 uint32 global_client_caps = 0;
47 /****************************************************************************
48 report a possible attack via the password buffer overflow bug
49 ****************************************************************************/
50 static void overflow_attack(int len)
54 dbgtext( "ERROR: Invalid password length %d.\n", len );
55 dbgtext( "Your machine may be under attack by someone " );
56 dbgtext( "attempting to exploit an old bug.\n" );
57 dbgtext( "Attack was from IP = %s.\n", client_addr(Client) );
59 exit_server("possible attack");
63 /****************************************************************************
64 does _both_ nt->unix and unix->unix username remappings.
65 ****************************************************************************/
66 static BOOL map_nt_and_unix_username(const char *domain, char *user)
72 * Pass the user through the NT -> unix user mapping
76 memset(nt_username, 0, sizeof(nt_username));
79 slprintf(nt_username, sizeof(nt_username)-1, "%s\\%s",
84 fstrcpy(nt_username, user);
86 if (!lookupsmbpwntnam(nt_username, &gmep))
91 fstrcpy(user, gmep.unix_name);
94 * Pass the user through the unix -> unix user mapping
98 (void)map_username(user);
101 * Do any UNIX username case mangling.
103 return Get_Pwnam( user, True) != NULL;
106 /****************************************************************************
107 reply to an special message
108 ****************************************************************************/
109 int reply_special(char *inbuf,char *outbuf)
112 int msg_type = CVAL(inbuf,0);
113 int msg_flags = CVAL(inbuf,1);
115 extern fstring remote_machine;
116 extern fstring local_machine;
122 bzero(outbuf,smb_size);
124 smb_setlen(outbuf,0);
127 case 0x81: /* session request */
128 CVAL(outbuf,0) = 0x82;
130 if (name_len(inbuf+4) > 50 ||
131 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
132 DEBUG(0,("Invalid name length in session request\n"));
135 name_extract(inbuf,4,name1);
136 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
137 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
140 fstrcpy(remote_machine,name2);
141 remote_machine[15] = 0;
142 trim_string(remote_machine," "," ");
143 strlower(remote_machine);
145 fstrcpy(local_machine,name1);
146 len = strlen(local_machine);
148 name_type = local_machine[15];
149 local_machine[15] = 0;
151 trim_string(local_machine," "," ");
152 strlower(local_machine);
154 if (name_type == 'R') {
155 /* We are being asked for a pathworks session ---
157 CVAL(outbuf, 0) = 0x83;
161 add_session_user(remote_machine);
163 reload_services(True);
167 claim_connection(NULL,"STATUS.",MAXSTATUS,True);
172 case 0x89: /* session keepalive request
173 (some old clients produce this?) */
174 CVAL(outbuf,0) = 0x85;
178 case 0x82: /* positive session response */
179 case 0x83: /* negative session response */
180 case 0x84: /* retarget session response */
181 DEBUG(0,("Unexpected session response\n"));
184 case 0x85: /* session keepalive */
189 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
190 msg_type, msg_flags));
196 /*******************************************************************
197 work out what error to give to a failed connection
198 ********************************************************************/
199 static int connection_error(char *inbuf,char *outbuf,int ecode)
201 if (ecode == ERRnoipc) {
202 return(ERROR(ERRDOS,ERRnoipc));
205 return(ERROR(ERRSRV,ecode));
210 /****************************************************************************
211 parse a share descriptor string
212 ****************************************************************************/
213 static void parse_connect(char *p,char *service,char *user,
214 char *password,int *pwlen,char *dev)
218 DEBUG(4,("parsing connect string %s\n",p));
220 p2 = strrchr(p,'\\');
224 fstrcpy(service,p2+1);
229 *pwlen = strlen(password);
236 p = strchr(service,'%');
247 /****************************************************************************
249 ****************************************************************************/
250 int reply_tcon(connection_struct *conn,
251 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
258 uint16 vuid = SVAL(inbuf,smb_uid);
262 *service = *user = *password = *dev = 0;
264 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
266 map_nt_and_unix_username(global_myworkgroup, user);
268 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
271 return(connection_error(inbuf,outbuf,ecode));
274 outsize = set_message(outbuf,2,0,True);
275 SSVAL(outbuf,smb_vwv0,max_recv);
276 SSVAL(outbuf,smb_vwv1,conn->cnum);
277 SSVAL(outbuf,smb_tid,conn->cnum);
279 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
280 service, user, conn->cnum));
286 /****************************************************************************
287 reply to a tcon and X
288 ****************************************************************************/
289 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
296 uint16 vuid = SVAL(inbuf,smb_uid);
297 int passlen = SVAL(inbuf,smb_vwv3);
301 *service = *user = *password = *devicename = 0;
303 /* we might have to close an old one */
304 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
305 close_cnum(conn,vuid);
308 if (passlen > MAX_PASS_LEN) {
309 overflow_attack(passlen);
312 memcpy(password,smb_buf(inbuf),passlen);
314 path = smb_buf(inbuf) + passlen;
317 if (strequal(password," "))
319 passlen = strlen(password);
322 fstrcpy(service,path+2);
323 p = strchr(service,'\\');
325 return(ERROR(ERRSRV,ERRinvnetname));
327 fstrcpy(service,p+1);
328 p = strchr(service,'%');
333 StrnCpy(devicename,path + strlen(path) + 1,6);
334 DEBUG(4,("Got device type %s\n",devicename));
336 map_nt_and_unix_username(global_myworkgroup, user);
338 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
341 return(connection_error(inbuf,outbuf,ecode));
343 if (Protocol < PROTOCOL_NT1) {
344 set_message(outbuf,2,strlen(devicename)+1,True);
345 pstrcpy(smb_buf(outbuf),devicename);
347 char *fsname = lp_fstype(SNUM(conn));
349 set_message(outbuf,3,3,True);
352 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
353 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
355 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
357 /* what does setting this bit do? It is set by NT4 and
358 may affect the ability to autorun mounted cdroms */
359 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
362 DEBUG(3,("tconX service=%s user=%s\n",
365 /* set the incoming and outgoing tid to the just created one */
366 SSVAL(inbuf,smb_tid,conn->cnum);
367 SSVAL(outbuf,smb_tid,conn->cnum);
369 return chain_reply(inbuf,outbuf,length,bufsize);
373 /****************************************************************************
374 reply to an unknown type
375 ****************************************************************************/
376 int reply_unknown(char *inbuf,char *outbuf)
379 type = CVAL(inbuf,smb_com);
381 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
382 smb_fn_name(type), type, type));
384 return(ERROR(ERRSRV,ERRunknownsmb));
388 /****************************************************************************
390 ****************************************************************************/
391 int reply_ioctl(connection_struct *conn,
392 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
394 DEBUG(3,("ignoring ioctl\n"));
396 /* we just say it succeeds and hope its all OK.
397 some day it would be nice to interpret them individually */
398 return set_message(outbuf,1,0,True);
400 return(ERROR(ERRSRV,ERRnosupport));
404 /****************************************************************************
405 always return an error: it's just a matter of which one...
406 ****************************************************************************/
407 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
408 char *smb_passwd, int smb_passlen,
409 char *smb_nt_passwd, int smb_nt_passlen)
411 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
412 if (lp_security() == SEC_USER)
414 smb_trust_acct = getsmbpwnam(user);
418 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
419 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
420 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
423 if (smb_trust_acct == NULL)
425 /* lkclXXXX: workstation entry doesn't exist */
426 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
427 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
428 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
432 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
434 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
435 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
436 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
439 if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
441 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
442 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
443 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
446 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
448 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
449 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
450 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
453 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
455 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
456 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
457 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
460 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
462 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
463 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
464 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
468 /* don't know what to do: indicate logon failure */
469 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
470 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
473 /****************************************************************************
474 Check for a valid username and password in security=server mode.
475 ****************************************************************************/
477 static BOOL check_server_security(char *orig_user, char *domain,
478 char *smb_apasswd, int smb_apasslen,
479 char *smb_ntpasswd, int smb_ntpasslen)
481 if(lp_security() != SEC_SERVER)
484 return server_validate(orig_user, domain,
485 smb_apasswd, smb_apasslen,
486 smb_ntpasswd, smb_ntpasslen);
489 /****************************************************************************
490 Check for a valid username and password in security=domain mode.
491 ****************************************************************************/
493 static BOOL check_domain_security(char *orig_user, char *domain,
494 char *smb_apasswd, int smb_apasslen,
495 char *smb_ntpasswd, int smb_ntpasslen)
497 if(lp_security() != SEC_DOMAIN)
500 return domain_client_validate(orig_user, domain,
501 smb_apasswd, smb_apasslen,
502 smb_ntpasswd, smb_ntpasslen);
505 /****************************************************************************
506 reply to a session setup command
507 ****************************************************************************/
509 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
515 int smb_apasslen = 0;
517 int smb_ntpasslen = 0;
518 pstring smb_ntpasswd;
519 BOOL valid_nt_password = False;
523 static BOOL done_sesssetup = False;
524 BOOL doencrypt = SMBENCRYPT();
530 smb_bufsize = SVAL(inbuf,smb_vwv2);
532 if (Protocol < PROTOCOL_NT1) {
533 smb_apasslen = SVAL(inbuf,smb_vwv7);
534 if (smb_apasslen > MAX_PASS_LEN)
536 overflow_attack(smb_apasslen);
539 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
540 smb_apasswd[smb_apasslen] = 0;
541 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
543 if (!doencrypt && (lp_security() != SEC_SERVER)) {
544 smb_apasslen = strlen(smb_apasswd);
547 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
548 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
549 enum remote_arch_types ra_type = get_remote_arch();
550 char *p = smb_buf(inbuf);
552 global_client_caps = IVAL(inbuf,smb_vwv11);
554 /* client_caps is used as final determination if client is NT or Win95.
555 This is needed to return the correct error codes in some
559 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
561 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
562 set_remote_arch( RA_WINNT);
564 set_remote_arch( RA_WIN95);
567 if (passlen1 != 24 && passlen2 != 24)
570 if (passlen1 > MAX_PASS_LEN) {
571 overflow_attack(passlen1);
574 passlen1 = MIN(passlen1, MAX_PASS_LEN);
575 passlen2 = MIN(passlen2, MAX_PASS_LEN);
578 /* both Win95 and WinNT stuff up the password lengths for
579 non-encrypting systems. Uggh.
581 if passlen1==24 its a win95 system, and its setting the
582 password length incorrectly. Luckily it still works with the
583 default code because Win95 will null terminate the password
586 if passlen1>0 and passlen2>0 then maybe its a NT box and its
587 setting passlen2 to some random value which really stuffs
588 things up. we need to fix that one. */
590 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
594 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
595 /* Save the lanman2 password and the NT md4 password. */
596 smb_apasslen = passlen1;
597 memcpy(smb_apasswd,p,smb_apasslen);
598 smb_apasswd[smb_apasslen] = 0;
599 smb_ntpasslen = passlen2;
600 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
601 smb_ntpasswd[smb_ntpasslen] = 0;
603 /* we use the first password that they gave */
604 smb_apasslen = passlen1;
605 StrnCpy(smb_apasswd,p,smb_apasslen);
607 /* trim the password */
608 smb_apasslen = strlen(smb_apasswd);
610 /* wfwg sometimes uses a space instead of a null */
611 if (strequal(smb_apasswd," ")) {
617 p += passlen1 + passlen2;
618 fstrcpy(user,p); p = skip_string(p,1);
621 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
622 domain,skip_string(p,1),skip_string(p,2)));
626 DEBUG(3,("sesssetupX:name=[%s]\n",user));
628 /* If name ends in $ then I think it's asking about whether a */
629 /* computer with that name (minus the $) has access. For now */
630 /* say yes to everything ending in $. */
631 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
633 return session_trust_account(conn, inbuf, outbuf, user,
634 smb_apasswd, smb_apasslen,
635 smb_ntpasswd, smb_ntpasslen);
638 /* If no username is sent use the guest account */
641 pstrcpy(user,lp_guestaccount(-1));
642 /* If no user and no password then set guest flag. */
643 if( *smb_apasswd == 0)
650 * In share level security, only overwrite sesssetup_use if
651 * it's a non null-session share. Helps keep %U and %G
655 if((lp_security() != SEC_SHARE) || (*user && !guest))
656 pstrcpy(sesssetup_user,user);
658 reload_services(True);
661 * Save the username before mapping. We will use
662 * the original username sent to us for security=server
663 * and security=domain checking.
666 pstrcpy( orig_user, user);
668 if (!map_nt_and_unix_username(domain, user))
670 return(ERROR(ERRSRV,ERRbadpw));
673 add_session_user(user);
676 * Check if the given username was the guest user with no password.
679 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
683 * Check with orig_user for security=server and
688 !check_server_security(orig_user, domain,
689 smb_apasswd, smb_apasslen,
690 smb_ntpasswd, smb_ntpasslen) &&
691 !check_domain_security(orig_user, domain,
692 smb_apasswd, smb_apasslen,
693 smb_ntpasswd, smb_ntpasslen) &&
694 !check_hosts_equiv(user)
699 * If we get here then the user wasn't guest and the remote
700 * authentication methods failed. Check the authentication
701 * methods on this local server.
703 * If an NT password was supplied try and validate with that
704 * first. This is superior as the passwords are mixed case
705 * 128 length unicode.
710 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
711 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
713 valid_nt_password = True;
716 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL))
718 if (lp_security() >= SEC_USER)
720 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
721 return(ERROR(ERRSRV,ERRbadpw));
723 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
725 if (Get_Pwnam(user,True))
726 return(ERROR(ERRSRV,ERRbadpw));
730 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
731 * Then always map to guest account - as done below.
735 if (*smb_apasswd || !Get_Pwnam(user,True))
736 pstrcpy(user,lp_guestaccount(-1));
737 DEBUG(3,("Registered username %s for guest access\n",user));
742 if (!Get_Pwnam(user,True)) {
743 DEBUG(3,("No such user %s - using guest account\n",user));
744 pstrcpy(user,lp_guestaccount(-1));
748 if (!strequal(user,lp_guestaccount(-1)) &&
749 lp_servicenumber(user) < 0)
751 int homes = lp_servicenumber(HOMES_NAME);
752 char *home = get_home_dir(user);
753 if (homes >= 0 && home)
754 lp_add_home(user,homes,home);
758 /* it's ok - setup a reply */
759 if (Protocol < PROTOCOL_NT1) {
760 set_message(outbuf,3,0,True);
763 set_message(outbuf,3,3,True);
765 pstrcpy(p,"Unix"); p = skip_string(p,1);
766 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
767 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
768 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
769 /* perhaps grab OS version here?? */
772 /* Set the correct uid in the outgoing and incoming packets
773 We will use this on future requests to determine which
774 user we should become.
777 struct passwd *pw = Get_Pwnam(user,False);
779 DEBUG(1,("Username %s is invalid on this system\n",user));
780 return(ERROR(ERRSRV,ERRbadpw));
787 SSVAL(outbuf,smb_vwv2,1);
789 /* register the name and uid as being validated, so further connections
790 to a uid can get through without a password, on the same VC */
791 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
793 SSVAL(outbuf,smb_uid,sess_vuid);
794 SSVAL(inbuf,smb_uid,sess_vuid);
797 max_send = MIN(max_send,smb_bufsize);
799 DEBUG(6,("Client requested max send size of %d\n", max_send));
801 done_sesssetup = True;
803 return chain_reply(inbuf,outbuf,length,bufsize);
807 /****************************************************************************
809 ****************************************************************************/
810 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
816 BOOL bad_path = False;
819 pstrcpy(name,smb_buf(inbuf) + 1);
820 unix_convert(name,conn,0,&bad_path,&st);
822 mode = SVAL(inbuf,smb_vwv0);
824 if (check_name(name,conn)) {
826 ok = S_ISDIR(st.st_mode);
828 ok = dos_directory_exist(name,NULL);
833 /* We special case this - as when a Windows machine
834 is parsing a path is steps through the components
835 one at a time - if a component fails it expects
836 ERRbadpath, not ERRbadfile.
840 unix_ERR_class = ERRDOS;
841 unix_ERR_code = ERRbadpath;
845 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
846 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
847 (get_remote_arch() == RA_WINNT))
849 unix_ERR_class = ERRDOS;
850 unix_ERR_code = ERRbaddirectory;
854 return(UNIXERROR(ERRDOS,ERRbadpath));
857 outsize = set_message(outbuf,0,0,True);
859 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
865 /****************************************************************************
867 ****************************************************************************/
868 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
872 SMB_STRUCT_STAT sbuf;
877 BOOL bad_path = False;
879 pstrcpy(fname,smb_buf(inbuf) + 1);
881 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
882 under WfWg - weird! */
885 mode = aHIDDEN | aDIR;
886 if (!CAN_WRITE(conn)) mode |= aRONLY;
893 unix_convert(fname,conn,0,&bad_path,&sbuf);
894 if (check_name(fname,conn))
896 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
898 mode = dos_mode(conn,fname,&sbuf);
900 mtime = sbuf.st_mtime;
906 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
912 if((errno == ENOENT) && bad_path)
914 unix_ERR_class = ERRDOS;
915 unix_ERR_code = ERRbadpath;
918 return(UNIXERROR(ERRDOS,ERRbadfile));
921 outsize = set_message(outbuf,10,0,True);
923 SSVAL(outbuf,smb_vwv0,mode);
924 if(lp_dos_filetime_resolution(SNUM(conn)) )
925 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
927 put_dos_date3(outbuf,smb_vwv1,mtime);
928 SIVAL(outbuf,smb_vwv3,(uint32)size);
930 if (Protocol >= PROTOCOL_NT1) {
931 char *p = strrchr(fname,'/');
932 uint16 flg2 = SVAL(outbuf,smb_flg2);
934 if (!is_8_3(fname, True))
935 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
938 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
944 /****************************************************************************
946 ****************************************************************************/
947 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
955 BOOL bad_path = False;
957 pstrcpy(fname,smb_buf(inbuf) + 1);
958 unix_convert(fname,conn,0,&bad_path,&st);
960 mode = SVAL(inbuf,smb_vwv0);
961 mtime = make_unix_date3(inbuf+smb_vwv1);
963 if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
965 if (check_name(fname,conn))
966 ok = (file_chmod(conn,fname,mode,NULL) == 0);
968 ok = set_filetime(conn,fname,mtime);
972 if((errno == ENOENT) && bad_path)
974 unix_ERR_class = ERRDOS;
975 unix_ERR_code = ERRbadpath;
978 return(UNIXERROR(ERRDOS,ERRnoaccess));
981 outsize = set_message(outbuf,0,0,True);
983 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
989 /****************************************************************************
991 ****************************************************************************/
992 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
995 SMB_BIG_UINT dfree,dsize,bsize;
997 sys_disk_free(".",&bsize,&dfree,&dsize);
999 outsize = set_message(outbuf,5,0,True);
1001 SSVAL(outbuf,smb_vwv0,dsize);
1002 SSVAL(outbuf,smb_vwv1,bsize/512);
1003 SSVAL(outbuf,smb_vwv2,512);
1004 SSVAL(outbuf,smb_vwv3,dfree);
1006 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1012 /****************************************************************************
1014 Can be called from SMBsearch, SMBffirst or SMBfunique.
1015 ****************************************************************************/
1016 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1027 BOOL finished = False;
1036 BOOL check_descend = False;
1037 BOOL expect_close = False;
1038 BOOL can_open = True;
1039 BOOL bad_path = False;
1041 *mask = *directory = *fname = 0;
1043 /* If we were called as SMBffirst then we must expect close. */
1044 if(CVAL(inbuf,smb_com) == SMBffirst)
1045 expect_close = True;
1047 outsize = set_message(outbuf,1,3,True);
1048 maxentries = SVAL(inbuf,smb_vwv0);
1049 dirtype = SVAL(inbuf,smb_vwv1);
1050 path = smb_buf(inbuf) + 1;
1051 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1054 /* dirtype &= ~aDIR; */
1056 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1059 if (status_len == 0)
1063 pstrcpy(directory,smb_buf(inbuf)+1);
1064 pstrcpy(dir2,smb_buf(inbuf)+1);
1065 unix_convert(directory,conn,0,&bad_path,NULL);
1068 if (!check_name(directory,conn))
1071 p = strrchr(dir2,'/');
1083 p = strrchr(directory,'/');
1089 if (strlen(directory) == 0)
1090 pstrcpy(directory,"./");
1092 CVAL(status,0) = dirtype;
1096 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1097 memcpy(mask,status+1,11);
1099 dirtype = CVAL(status,0) & 0x1F;
1100 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1103 string_set(&conn->dirpath,dptr_path(dptr_num));
1104 if (!case_sensitive)
1108 /* turn strings of spaces into a . */
1110 trim_string(mask,NULL," ");
1111 if ((p = strrchr(mask,' ')))
1116 trim_string(mask,NULL," ");
1122 /* Convert the formatted mask. (This code lives in trans2.c) */
1130 if((skip = skip_multibyte_char( *p )) != 0 )
1136 if (*p != '?' && *p != '*' && !isdoschar(*p))
1138 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1146 if (!strchr(mask,'.') && strlen(mask)>8)
1149 fstrcpy(tmp,&mask[8]);
1155 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1159 p = smb_buf(outbuf) + 3;
1163 if (status_len == 0)
1165 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1170 if((errno == ENOENT) && bad_path)
1172 unix_ERR_class = ERRDOS;
1173 unix_ERR_code = ERRbadpath;
1175 return (UNIXERROR(ERRDOS,ERRnofids));
1177 return(ERROR(ERRDOS,ERRnofids));
1181 DEBUG(4,("dptr_num is %d\n",dptr_num));
1185 if ((dirtype&0x1F) == aVOLID)
1187 memcpy(p,status,21);
1188 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1189 dptr_fill(p+12,dptr_num);
1190 if (dptr_zero(p+12) && (status_len==0))
1194 p += DIR_STRUCT_SIZE;
1198 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1199 conn->dirpath,lp_dontdescend(SNUM(conn))));
1200 if (in_list(conn->dirpath,
1201 lp_dontdescend(SNUM(conn)),True))
1202 check_descend = True;
1204 for (i=numentries;(i<maxentries) && !finished;i++)
1207 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1210 memcpy(p,status,21);
1211 make_dir_struct(p,mask,fname,size,mode,date);
1212 dptr_fill(p+12,dptr_num);
1215 p += DIR_STRUCT_SIZE;
1224 if (numentries == 0 || !ok)
1226 CVAL(outbuf,smb_rcls) = ERRDOS;
1227 SSVAL(outbuf,smb_err,ERRnofiles);
1230 /* If we were called as SMBffirst with smb_search_id == NULL
1231 and no entries were found then return error and close dirptr
1234 if(ok && expect_close && numentries == 0 && status_len == 0)
1236 CVAL(outbuf,smb_rcls) = ERRDOS;
1237 SSVAL(outbuf,smb_err,ERRnofiles);
1238 /* Also close the dptr - we know it's gone */
1239 dptr_close(dptr_num);
1242 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1243 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1244 dptr_close(dptr_num);
1246 SSVAL(outbuf,smb_vwv0,numentries);
1247 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1248 CVAL(smb_buf(outbuf),0) = 5;
1249 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1251 if (Protocol >= PROTOCOL_NT1) {
1252 uint16 flg2 = SVAL(outbuf,smb_flg2);
1253 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1256 outsize += DIR_STRUCT_SIZE*numentries;
1257 smb_setlen(outbuf,outsize - 4);
1259 if ((! *directory) && dptr_path(dptr_num))
1260 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1262 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1263 smb_fn_name(CVAL(inbuf,smb_com)),
1264 mask, directory, dirtype, numentries, maxentries ) );
1270 /****************************************************************************
1271 reply to a fclose (stop directory search)
1272 ****************************************************************************/
1273 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1281 outsize = set_message(outbuf,1,0,True);
1282 path = smb_buf(inbuf) + 1;
1283 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1286 if (status_len == 0)
1287 return(ERROR(ERRSRV,ERRsrverror));
1289 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1291 if(dptr_fetch(status+12,&dptr_num)) {
1292 /* Close the dptr - we know it's gone */
1293 dptr_close(dptr_num);
1296 SSVAL(outbuf,smb_vwv0,0);
1298 DEBUG(3,("search close\n"));
1304 /****************************************************************************
1306 ****************************************************************************/
1308 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1318 SMB_STRUCT_STAT sbuf;
1319 BOOL bad_path = False;
1321 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1323 share_mode = SVAL(inbuf,smb_vwv0);
1325 pstrcpy(fname,smb_buf(inbuf)+1);
1326 unix_convert(fname,conn,0,&bad_path,NULL);
1330 return(ERROR(ERRSRV,ERRnofids));
1332 if (!check_name(fname,conn))
1334 if((errno == ENOENT) && bad_path)
1336 unix_ERR_class = ERRDOS;
1337 unix_ERR_code = ERRbadpath;
1340 return(UNIXERROR(ERRDOS,ERRnoaccess));
1343 unixmode = unix_mode(conn,aARCH);
1345 open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1346 unixmode, oplock_request,&rmode,NULL);
1350 if((errno == ENOENT) && bad_path)
1352 unix_ERR_class = ERRDOS;
1353 unix_ERR_code = ERRbadpath;
1356 return(UNIXERROR(ERRDOS,ERRnoaccess));
1359 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1360 close_file(fsp,False);
1361 return(ERROR(ERRDOS,ERRnoaccess));
1364 size = sbuf.st_size;
1365 fmode = dos_mode(conn,fname,&sbuf);
1366 mtime = sbuf.st_mtime;
1369 DEBUG(3,("attempt to open a directory %s\n",fname));
1370 close_file(fsp,False);
1371 return(ERROR(ERRDOS,ERRnoaccess));
1374 outsize = set_message(outbuf,7,0,True);
1375 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1376 SSVAL(outbuf,smb_vwv1,fmode);
1377 if(lp_dos_filetime_resolution(SNUM(conn)) )
1378 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1380 put_dos_date3(outbuf,smb_vwv2,mtime);
1381 SIVAL(outbuf,smb_vwv4,(uint32)size);
1382 SSVAL(outbuf,smb_vwv6,rmode);
1384 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1385 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1388 if(fsp->granted_oplock)
1389 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1394 /****************************************************************************
1395 reply to an open and X
1396 ****************************************************************************/
1397 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1400 int smb_mode = SVAL(inbuf,smb_vwv3);
1401 int smb_attr = SVAL(inbuf,smb_vwv5);
1402 /* Breakout the oplock request bits so we can set the
1403 reply bits separately. */
1404 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1405 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1406 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1408 int open_flags = SVAL(inbuf,smb_vwv2);
1409 int smb_sattr = SVAL(inbuf,smb_vwv4);
1410 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1412 int smb_ofun = SVAL(inbuf,smb_vwv8);
1415 int fmode=0,mtime=0,rmode=0;
1416 SMB_STRUCT_STAT sbuf;
1418 BOOL bad_path = False;
1421 /* If it's an IPC, pass off the pipe handler. */
1422 if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
1424 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1427 /* XXXX we need to handle passed times, sattr and flags */
1429 pstrcpy(fname,smb_buf(inbuf));
1430 unix_convert(fname,conn,0,&bad_path,NULL);
1434 return(ERROR(ERRSRV,ERRnofids));
1436 if (!check_name(fname,conn))
1438 if((errno == ENOENT) && bad_path)
1440 unix_ERR_class = ERRDOS;
1441 unix_ERR_code = ERRbadpath;
1444 return(UNIXERROR(ERRDOS,ERRnoaccess));
1447 unixmode = unix_mode(conn,smb_attr | aARCH);
1449 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1450 oplock_request, &rmode,&smb_action);
1454 if((errno == ENOENT) && bad_path)
1456 unix_ERR_class = ERRDOS;
1457 unix_ERR_code = ERRbadpath;
1460 return(UNIXERROR(ERRDOS,ERRnoaccess));
1463 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1464 close_file(fsp,False);
1465 return(ERROR(ERRDOS,ERRnoaccess));
1468 size = sbuf.st_size;
1469 fmode = dos_mode(conn,fname,&sbuf);
1470 mtime = sbuf.st_mtime;
1472 close_file(fsp,False);
1473 return(ERROR(ERRDOS,ERRnoaccess));
1476 /* If the caller set the extended oplock request bit
1477 and we granted one (by whatever means) - set the
1478 correct bit for extended oplock reply.
1481 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1482 smb_action |= EXTENDED_OPLOCK_GRANTED;
1485 if(ex_oplock_request && fsp->granted_oplock) {
1486 smb_action |= EXTENDED_OPLOCK_GRANTED;
1489 /* If the caller set the core oplock request bit
1490 and we granted one (by whatever means) - set the
1491 correct bit for core oplock reply.
1494 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1495 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1498 if(core_oplock_request && fsp->granted_oplock) {
1499 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1502 set_message(outbuf,15,0,True);
1503 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1504 SSVAL(outbuf,smb_vwv3,fmode);
1505 if(lp_dos_filetime_resolution(SNUM(conn)) )
1506 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1508 put_dos_date3(outbuf,smb_vwv4,mtime);
1509 SIVAL(outbuf,smb_vwv6,(uint32)size);
1510 SSVAL(outbuf,smb_vwv8,rmode);
1511 SSVAL(outbuf,smb_vwv11,smb_action);
1513 return chain_reply(inbuf,outbuf,length,bufsize);
1517 /****************************************************************************
1518 reply to a SMBulogoffX
1519 ****************************************************************************/
1520 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1522 uint16 vuid = SVAL(inbuf,smb_uid);
1523 user_struct *vuser = get_valid_user_struct(vuid);
1526 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1529 /* in user level security we are supposed to close any files
1530 open by this user */
1531 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1532 file_close_user(vuid);
1535 invalidate_vuid(vuid);
1537 set_message(outbuf,2,0,True);
1539 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1541 return chain_reply(inbuf,outbuf,length,bufsize);
1545 /****************************************************************************
1546 reply to a mknew or a create
1547 ****************************************************************************/
1548 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1556 BOOL bad_path = False;
1558 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1560 com = SVAL(inbuf,smb_com);
1562 createmode = SVAL(inbuf,smb_vwv0);
1563 pstrcpy(fname,smb_buf(inbuf)+1);
1564 unix_convert(fname,conn,0,&bad_path,NULL);
1566 if (createmode & aVOLID)
1568 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1571 unixmode = unix_mode(conn,createmode);
1575 return(ERROR(ERRSRV,ERRnofids));
1577 if (!check_name(fname,conn))
1579 if((errno == ENOENT) && bad_path)
1581 unix_ERR_class = ERRDOS;
1582 unix_ERR_code = ERRbadpath;
1585 return(UNIXERROR(ERRDOS,ERRnoaccess));
1590 /* We should fail if file exists. */
1595 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1599 /* Open file in dos compatibility share mode. */
1600 open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1601 ofun, unixmode, oplock_request, NULL, NULL);
1605 if((errno == ENOENT) && bad_path)
1607 unix_ERR_class = ERRDOS;
1608 unix_ERR_code = ERRbadpath;
1611 return(UNIXERROR(ERRDOS,ERRnoaccess));
1614 outsize = set_message(outbuf,1,0,True);
1615 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1617 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1618 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1621 if(fsp->granted_oplock)
1622 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1624 DEBUG( 2, ( "new file %s\n", fname ) );
1625 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1626 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1632 /****************************************************************************
1633 reply to a create temporary file
1634 ****************************************************************************/
1635 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1642 BOOL bad_path = False;
1644 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1646 createmode = SVAL(inbuf,smb_vwv0);
1647 pstrcpy(fname,smb_buf(inbuf)+1);
1648 pstrcat(fname,"/TMXXXXXX");
1649 unix_convert(fname,conn,0,&bad_path,NULL);
1651 unixmode = unix_mode(conn,createmode);
1655 return(ERROR(ERRSRV,ERRnofids));
1657 if (!check_name(fname,conn))
1659 if((errno == ENOENT) && bad_path)
1661 unix_ERR_class = ERRDOS;
1662 unix_ERR_code = ERRbadpath;
1665 return(UNIXERROR(ERRDOS,ERRnoaccess));
1668 pstrcpy(fname2,(char *)mktemp(fname));
1670 /* Open file in dos compatibility share mode. */
1671 /* We should fail if file exists. */
1672 open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1673 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1677 if((errno == ENOENT) && bad_path)
1679 unix_ERR_class = ERRDOS;
1680 unix_ERR_code = ERRbadpath;
1683 return(UNIXERROR(ERRDOS,ERRnoaccess));
1686 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1687 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1688 CVAL(smb_buf(outbuf),0) = 4;
1689 pstrcpy(smb_buf(outbuf) + 1,fname2);
1691 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1692 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1695 if(fsp->granted_oplock)
1696 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1698 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1699 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1700 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1706 /*******************************************************************
1707 check if a user is allowed to delete a file
1708 ********************************************************************/
1709 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1711 SMB_STRUCT_STAT sbuf;
1714 if (!CAN_WRITE(conn)) return(False);
1716 if (dos_lstat(fname,&sbuf) != 0) return(False);
1717 fmode = dos_mode(conn,fname,&sbuf);
1718 if (fmode & aDIR) return(False);
1719 if (!lp_delete_readonly(SNUM(conn))) {
1720 if (fmode & aRONLY) return(False);
1722 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1724 if (!check_file_sharing(conn,fname,False)) return(False);
1728 /****************************************************************************
1730 ****************************************************************************/
1731 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1740 int error = ERRnoaccess;
1743 BOOL bad_path = False;
1745 *directory = *mask = 0;
1747 dirtype = SVAL(inbuf,smb_vwv0);
1749 pstrcpy(name,smb_buf(inbuf) + 1);
1751 DEBUG(3,("reply_unlink : %s\n",name));
1753 unix_convert(name,conn,0,&bad_path,NULL);
1755 p = strrchr(name,'/');
1757 pstrcpy(directory,"./");
1761 pstrcpy(directory,name);
1765 if (is_mangled(mask))
1766 check_mangled_cache( mask );
1768 has_wild = strchr(mask,'*') || strchr(mask,'?');
1771 pstrcat(directory,"/");
1772 pstrcat(directory,mask);
1773 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
1776 exists = dos_file_exist(directory,NULL);
1778 void *dirptr = NULL;
1781 if (check_name(directory,conn))
1782 dirptr = OpenDir(conn, directory, True);
1784 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1785 the pattern matches against the long name, otherwise the short name
1786 We don't implement this yet XXXX
1793 if (strequal(mask,"????????.???"))
1796 while ((dname = ReadDirName(dirptr)))
1799 pstrcpy(fname,dname);
1801 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1803 error = ERRnoaccess;
1804 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1805 if (!can_delete(fname,conn,dirtype)) continue;
1806 if (!dos_unlink(fname)) count++;
1807 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1815 return(ERROR(ERRDOS,error));
1818 if((errno == ENOENT) && bad_path)
1820 unix_ERR_class = ERRDOS;
1821 unix_ERR_code = ERRbadpath;
1823 return(UNIXERROR(ERRDOS,error));
1827 outsize = set_message(outbuf,0,0,True);
1833 /****************************************************************************
1834 reply to a readbraw (core+ protocol)
1835 ****************************************************************************/
1836 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1838 size_t maxcount,mincount;
1841 char *header = outbuf;
1846 * Special check if an oplock break has been issued
1847 * and the readraw request croses on the wire, we must
1848 * return a zero length response here.
1851 if(global_oplock_break)
1853 _smb_setlen(header,0);
1854 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1855 DEBUG(5,("readbraw - oplock break finished\n"));
1859 fsp = file_fsp(inbuf,smb_vwv0);
1861 startpos = IVAL(inbuf,smb_vwv1);
1862 #ifdef LARGE_SMB_OFF_T
1863 if(CVAL(inbuf,smb_wct) == 10) {
1865 * This is a large offset (64 bit) read.
1867 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1869 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1870 (double)startpos ));
1871 _smb_setlen(header,0);
1872 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1876 #endif /* LARGE_SMB_OFF_T */
1877 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1878 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1880 /* ensure we don't overrun the packet size */
1881 maxcount = MIN(65535,maxcount);
1882 maxcount = MAX(mincount,maxcount);
1884 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1885 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1886 _smb_setlen(header,0);
1887 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1891 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1893 SMB_OFF_T size = fsp->size;
1894 SMB_OFF_T sizeneeded = startpos + maxcount;
1896 if (size < sizeneeded)
1899 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1901 if (!fsp->can_write)
1905 nread = MIN(maxcount,(size - startpos));
1908 if (nread < mincount)
1911 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1912 fsp->fnum, (double)startpos,
1913 maxcount, mincount, nread ) );
1917 BOOL seek_fail = False;
1919 _smb_setlen(header,nread);
1921 #if USE_READ_PREDICTION
1922 if (!fsp->can_write)
1923 predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1924 #endif /* USE_READ_PREDICTION */
1926 if ((nread-predict) > 0) {
1927 if(seek_file(fsp,startpos + predict) == -1) {
1928 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1935 ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,
1936 (SMB_OFF_T)(nread-predict),header,4+predict,
1941 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1942 fsp->fsp_name,startpos,nread,ret));
1944 #else /* UNSAFE_READRAW */
1945 ret = read_file(fsp,header+4,startpos,nread);
1946 if (ret < mincount) ret = 0;
1948 _smb_setlen(header,ret);
1949 transfer_file(0,Client,0,header,4+ret,0);
1950 #endif /* UNSAFE_READRAW */
1952 DEBUG(5,("readbraw finished\n"));
1957 /****************************************************************************
1958 reply to a lockread (core+ protocol)
1959 ****************************************************************************/
1960 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1969 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1971 CHECK_FSP(fsp,conn);
1975 numtoread = SVAL(inbuf,smb_vwv1);
1976 startpos = IVAL(inbuf,smb_vwv2);
1978 outsize = set_message(outbuf,5,3,True);
1979 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1980 data = smb_buf(outbuf) + 3;
1982 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1983 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1985 * A blocking lock was requested. Package up
1986 * this smb into a queued request and push it
1987 * onto the blocking lock queue.
1989 if(push_blocking_lock_request(inbuf, length, -1, 0))
1992 return (ERROR(eclass,ecode));
1995 nread = read_file(fsp,data,startpos,numtoread);
1998 return(UNIXERROR(ERRDOS,ERRnoaccess));
2001 SSVAL(outbuf,smb_vwv0,nread);
2002 SSVAL(outbuf,smb_vwv5,nread+3);
2003 SSVAL(smb_buf(outbuf),1,nread);
2005 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2006 fsp->fnum, numtoread, nread ) );
2012 /****************************************************************************
2014 ****************************************************************************/
2015 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2022 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2024 CHECK_FSP(fsp,conn);
2028 numtoread = SVAL(inbuf,smb_vwv1);
2029 startpos = IVAL(inbuf,smb_vwv2);
2031 outsize = set_message(outbuf,5,3,True);
2032 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2033 data = smb_buf(outbuf) + 3;
2035 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2036 return(ERROR(ERRDOS,ERRlock));
2039 nread = read_file(fsp,data,startpos,numtoread);
2042 return(UNIXERROR(ERRDOS,ERRnoaccess));
2045 SSVAL(outbuf,smb_vwv0,nread);
2046 SSVAL(outbuf,smb_vwv5,nread+3);
2047 CVAL(smb_buf(outbuf),0) = 1;
2048 SSVAL(smb_buf(outbuf),1,nread);
2050 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2051 fsp->fnum, numtoread, nread ) );
2057 /****************************************************************************
2058 reply to a read and X
2059 ****************************************************************************/
2060 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2062 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2063 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2064 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2065 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2069 /* If it's an IPC, pass off the pipe handler. */
2071 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2073 CHECK_FSP(fsp,conn);
2077 set_message(outbuf,12,0,True);
2078 data = smb_buf(outbuf);
2080 #ifdef LARGE_SMB_OFF_T
2081 if(CVAL(inbuf,smb_wct) == 12) {
2083 * This is a large offset (64 bit) read.
2085 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2087 #endif /* LARGE_SMB_OFF_T */
2089 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2090 return(ERROR(ERRDOS,ERRlock));
2091 nread = read_file(fsp,data,startpos,smb_maxcnt);
2094 return(UNIXERROR(ERRDOS,ERRnoaccess));
2096 SSVAL(outbuf,smb_vwv5,nread);
2097 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2098 SSVAL(smb_buf(outbuf),-2,nread);
2100 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2101 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2103 return chain_reply(inbuf,outbuf,length,bufsize);
2106 /****************************************************************************
2107 reply to a writebraw (core+ or LANMAN1.0 protocol)
2108 ****************************************************************************/
2109 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2112 ssize_t total_written=0;
2113 size_t numtowrite=0;
2118 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2121 CHECK_FSP(fsp,conn);
2125 tcount = IVAL(inbuf,smb_vwv1);
2126 startpos = IVAL(inbuf,smb_vwv3);
2127 write_through = BITSETW(inbuf+smb_vwv7,0);
2129 /* We have to deal with slightly different formats depending
2130 on whether we are using the core+ or lanman1.0 protocol */
2131 if(Protocol <= PROTOCOL_COREPLUS) {
2132 numtowrite = SVAL(smb_buf(inbuf),-2);
2133 data = smb_buf(inbuf);
2135 numtowrite = SVAL(inbuf,smb_vwv10);
2136 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2139 /* force the error type */
2140 CVAL(inbuf,smb_com) = SMBwritec;
2141 CVAL(outbuf,smb_com) = SMBwritec;
2143 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2144 return(ERROR(ERRDOS,ERRlock));
2146 if (seek_file(fsp,startpos) == -1) {
2147 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2148 return(UNIXERROR(ERRDOS,ERRnoaccess));
2152 nwritten = write_file(fsp,data,numtowrite);
2154 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2155 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2157 if (nwritten < numtowrite)
2158 return(UNIXERROR(ERRHRD,ERRdiskfull));
2160 total_written = nwritten;
2162 /* Return a message to the redirector to tell it
2163 to send more bytes */
2164 CVAL(outbuf,smb_com) = SMBwritebraw;
2165 SSVALS(outbuf,smb_vwv0,-1);
2166 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2167 send_smb(Client,outbuf);
2169 /* Now read the raw data into the buffer and write it */
2170 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2171 exit_server("secondary writebraw failed");
2174 /* Even though this is not an smb message, smb_len
2175 returns the generic length of an smb message */
2176 numtowrite = smb_len(inbuf);
2178 if (tcount > nwritten+numtowrite) {
2179 DEBUG(3,("Client overestimated the write %d %d %d\n",
2180 tcount,nwritten,numtowrite));
2183 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2185 total_written += nwritten;
2187 /* Set up outbuf to return the correct return */
2188 outsize = set_message(outbuf,1,0,True);
2189 CVAL(outbuf,smb_com) = SMBwritec;
2190 SSVAL(outbuf,smb_vwv0,total_written);
2192 if (nwritten < (ssize_t)numtowrite) {
2193 CVAL(outbuf,smb_rcls) = ERRHRD;
2194 SSVAL(outbuf,smb_err,ERRdiskfull);
2197 if (lp_syncalways(SNUM(conn)) || write_through)
2198 sync_file(conn,fsp);
2200 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2201 fsp->fnum, (double)startpos, numtowrite, total_written));
2203 /* we won't return a status if write through is not selected - this
2204 follows what WfWg does */
2205 if (!write_through && total_written==tcount)
2211 /****************************************************************************
2212 reply to a writeunlock (core+)
2213 ****************************************************************************/
2214 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2216 ssize_t nwritten = -1;
2222 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2225 CHECK_FSP(fsp,conn);
2229 numtowrite = SVAL(inbuf,smb_vwv1);
2230 startpos = IVAL(inbuf,smb_vwv2);
2231 data = smb_buf(inbuf) + 3;
2233 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2234 return(ERROR(ERRDOS,ERRlock));
2236 if(seek_file(fsp,startpos) == -1)
2237 return(UNIXERROR(ERRDOS,ERRnoaccess));
2239 /* The special X/Open SMB protocol handling of
2240 zero length writes is *NOT* done for
2245 nwritten = write_file(fsp,data,numtowrite);
2247 if (lp_syncalways(SNUM(conn)))
2248 sync_file(conn,fsp);
2250 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2251 return(UNIXERROR(ERRDOS,ERRnoaccess));
2253 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2254 return(ERROR(eclass,ecode));
2256 outsize = set_message(outbuf,1,0,True);
2258 SSVAL(outbuf,smb_vwv0,nwritten);
2260 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2261 fsp->fnum, numtowrite, nwritten ) );
2266 /****************************************************************************
2268 ****************************************************************************/
2269 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2272 ssize_t nwritten = -1;
2275 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2278 CHECK_FSP(fsp,conn);
2282 numtowrite = SVAL(inbuf,smb_vwv1);
2283 startpos = IVAL(inbuf,smb_vwv2);
2284 data = smb_buf(inbuf) + 3;
2286 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2287 return(ERROR(ERRDOS,ERRlock));
2289 if(seek_file(fsp,startpos) == -1)
2290 return(UNIXERROR(ERRDOS,ERRnoaccess));
2292 /* X/Open SMB protocol says that if smb_vwv1 is
2293 zero then the file size should be extended or
2294 truncated to the size given in smb_vwv[2-3] */
2296 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2298 nwritten = write_file(fsp,data,numtowrite);
2300 if (lp_syncalways(SNUM(conn)))
2301 sync_file(conn,fsp);
2303 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2304 return(UNIXERROR(ERRDOS,ERRnoaccess));
2306 outsize = set_message(outbuf,1,0,True);
2308 SSVAL(outbuf,smb_vwv0,nwritten);
2310 if (nwritten < (ssize_t)numtowrite) {
2311 CVAL(outbuf,smb_rcls) = ERRHRD;
2312 SSVAL(outbuf,smb_err,ERRdiskfull);
2315 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2316 fsp->fnum, numtowrite, nwritten));
2322 /****************************************************************************
2323 reply to a write and X
2324 ****************************************************************************/
2325 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2327 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2328 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2329 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2330 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2331 ssize_t nwritten = -1;
2332 int smb_doff = SVAL(inbuf,smb_vwv11);
2335 /* If it's an IPC, pass off the pipe handler. */
2337 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2339 CHECK_FSP(fsp,conn);
2343 data = smb_base(inbuf) + smb_doff;
2345 #ifdef LARGE_SMB_OFF_T
2346 if(CVAL(inbuf,smb_wct) == 14) {
2348 * This is a large offset (64 bit) write.
2350 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2352 #endif /* LARGE_SMB_OFF_T */
2354 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2355 return(ERROR(ERRDOS,ERRlock));
2357 if(seek_file(fsp,startpos) == -1)
2358 return(UNIXERROR(ERRDOS,ERRnoaccess));
2360 /* X/Open SMB protocol says that, unlike SMBwrite
2361 if the length is zero then NO truncation is
2362 done, just a write of zero. To truncate a file,
2367 nwritten = write_file(fsp,data,numtowrite);
2369 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2370 return(UNIXERROR(ERRDOS,ERRnoaccess));
2372 set_message(outbuf,6,0,True);
2374 SSVAL(outbuf,smb_vwv2,nwritten);
2376 if (nwritten < (ssize_t)numtowrite) {
2377 CVAL(outbuf,smb_rcls) = ERRHRD;
2378 SSVAL(outbuf,smb_err,ERRdiskfull);
2381 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2382 fsp->fnum, numtowrite, nwritten));
2384 if (lp_syncalways(SNUM(conn)) || write_through)
2385 sync_file(conn,fsp);
2387 return chain_reply(inbuf,outbuf,length,bufsize);
2391 /****************************************************************************
2393 ****************************************************************************/
2394 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2400 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2402 CHECK_FSP(fsp,conn);
2405 mode = SVAL(inbuf,smb_vwv1) & 3;
2406 startpos = IVAL(inbuf,smb_vwv2);
2410 case 0: umode = SEEK_SET; break;
2411 case 1: umode = SEEK_CUR; break;
2412 case 2: umode = SEEK_END; break;
2414 umode = SEEK_SET; break;
2417 if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2418 return(UNIXERROR(ERRDOS,ERRnoaccess));
2422 outsize = set_message(outbuf,2,0,True);
2423 SIVALS(outbuf,smb_vwv0,res);
2425 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2426 fsp->fnum, (double)startpos, mode));
2431 /****************************************************************************
2433 ****************************************************************************/
2434 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2436 int outsize = set_message(outbuf,0,0,True);
2437 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2440 CHECK_FSP(fsp,conn);
2445 file_sync_all(conn);
2447 sync_file(conn,fsp);
2450 DEBUG(3,("flush\n"));
2455 /****************************************************************************
2457 ****************************************************************************/
2458 int reply_exit(connection_struct *conn,
2459 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2461 int outsize = set_message(outbuf,0,0,True);
2462 DEBUG(3,("exit\n"));
2468 /****************************************************************************
2469 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2470 ****************************************************************************/
2471 int reply_close(connection_struct *conn,
2472 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2476 int32 eclass = 0, err = 0;
2477 files_struct *fsp = NULL;
2479 outsize = set_message(outbuf,0,0,True);
2481 /* If it's an IPC, pass off to the pipe handler. */
2483 return reply_pipe_close(conn, inbuf,outbuf);
2486 fsp = file_fsp(inbuf,smb_vwv0);
2489 * We can only use CHECK_FSP if we know it's not a directory.
2492 if(!fsp || !fsp->open || (fsp->conn != conn))
2493 return(ERROR(ERRDOS,ERRbadfid));
2495 if(HAS_CACHED_ERROR(fsp)) {
2496 eclass = fsp->wbmpx_ptr->wr_errclass;
2497 err = fsp->wbmpx_ptr->wr_error;
2500 if(fsp->is_directory) {
2502 * Special case - close NT SMB directory
2505 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2506 close_directory(fsp);
2509 * Close ordinary file.
2513 * If there was a modify time outstanding,
2514 * try and set it here.
2516 if(fsp->pending_modtime)
2517 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2520 * Now take care of any time sent in the close.
2522 mtime = make_unix_date3(inbuf+smb_vwv1);
2524 /* try and set the date */
2525 set_filetime(conn, fsp->fsp_name,mtime);
2527 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2528 fsp->fd_ptr->fd, fsp->fnum,
2529 conn->num_files_open));
2531 close_file(fsp,True);
2534 /* We have a cached error */
2536 return(ERROR(eclass,err));
2542 /****************************************************************************
2543 reply to a writeclose (Core+ protocol)
2544 ****************************************************************************/
2545 int reply_writeclose(connection_struct *conn,
2546 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2549 ssize_t nwritten = -1;
2554 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2556 CHECK_FSP(fsp,conn);
2560 numtowrite = SVAL(inbuf,smb_vwv1);
2561 startpos = IVAL(inbuf,smb_vwv2);
2562 mtime = make_unix_date3(inbuf+smb_vwv4);
2563 data = smb_buf(inbuf) + 1;
2565 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2566 return(ERROR(ERRDOS,ERRlock));
2568 if(seek_file(fsp,startpos) == -1)
2569 return(UNIXERROR(ERRDOS,ERRnoaccess));
2571 nwritten = write_file(fsp,data,numtowrite);
2573 set_filetime(conn, fsp->fsp_name,mtime);
2575 close_file(fsp,True);
2577 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2578 fsp->fnum, numtowrite, nwritten,
2579 conn->num_files_open));
2582 return(UNIXERROR(ERRDOS,ERRnoaccess));
2584 outsize = set_message(outbuf,1,0,True);
2586 SSVAL(outbuf,smb_vwv0,nwritten);
2591 /****************************************************************************
2593 ****************************************************************************/
2594 int reply_lock(connection_struct *conn,
2595 char *inbuf,char *outbuf, int length, int dum_buffsize)
2597 int outsize = set_message(outbuf,0,0,True);
2598 SMB_OFF_T count,offset;
2601 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2603 CHECK_FSP(fsp,conn);
2606 count = IVAL(inbuf,smb_vwv1);
2607 offset = IVAL(inbuf,smb_vwv3);
2609 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2610 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2612 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2613 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2615 * A blocking lock was requested. Package up
2616 * this smb into a queued request and push it
2617 * onto the blocking lock queue.
2619 if(push_blocking_lock_request(inbuf, length, -1, 0))
2622 return (ERROR(eclass,ecode));
2629 /****************************************************************************
2631 ****************************************************************************/
2632 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2634 int outsize = set_message(outbuf,0,0,True);
2635 SMB_OFF_T count,offset;
2638 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2640 CHECK_FSP(fsp,conn);
2643 count = IVAL(inbuf,smb_vwv1);
2644 offset = IVAL(inbuf,smb_vwv3);
2646 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2647 return (ERROR(eclass,ecode));
2649 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2650 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2656 /****************************************************************************
2658 ****************************************************************************/
2659 int reply_tdis(connection_struct *conn,
2660 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2662 int outsize = set_message(outbuf,0,0,True);
2665 vuid = SVAL(inbuf,smb_uid);
2668 DEBUG(4,("Invalid connection in tdis\n"));
2669 return(ERROR(ERRSRV,ERRinvnid));
2674 close_cnum(conn,vuid);
2681 /****************************************************************************
2683 ****************************************************************************/
2684 int reply_echo(connection_struct *conn,
2685 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2687 int smb_reverb = SVAL(inbuf,smb_vwv0);
2689 int data_len = smb_buflen(inbuf);
2690 int outsize = set_message(outbuf,1,data_len,True);
2692 /* copy any incoming data back out */
2694 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2696 if (smb_reverb > 100) {
2697 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2701 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2702 SSVAL(outbuf,smb_vwv0,seq_num);
2704 smb_setlen(outbuf,outsize - 4);
2706 send_smb(Client,outbuf);
2709 DEBUG(3,("echo %d times\n", smb_reverb));
2715 /****************************************************************************
2716 reply to a printopen
2717 ****************************************************************************/
2718 int reply_printopen(connection_struct *conn,
2719 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2726 *fname = *fname2 = 0;
2728 if (!CAN_PRINT(conn))
2729 return(ERROR(ERRDOS,ERRnoaccess));
2734 pstrcpy(s,smb_buf(inbuf)+1);
2737 if (!(isalnum((int)*p) || strchr("._-",*p)))
2742 if (strlen(s) > 10) s[10] = 0;
2744 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2749 return(ERROR(ERRSRV,ERRnofids));
2751 pstrcpy(fname2,(char *)mktemp(fname));
2753 if (!check_name(fname2,conn)) {
2755 return(ERROR(ERRDOS,ERRnoaccess));
2758 /* Open for exclusive use, write only. */
2759 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2760 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2764 return(UNIXERROR(ERRDOS,ERRnoaccess));
2767 /* force it to be a print file */
2768 fsp->print_file = True;
2770 outsize = set_message(outbuf,1,0,True);
2771 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2773 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2774 fname2, fsp->fd_ptr->fd, fsp->fnum));
2780 /****************************************************************************
2781 reply to a printclose
2782 ****************************************************************************/
2783 int reply_printclose(connection_struct *conn,
2784 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2786 int outsize = set_message(outbuf,0,0,True);
2787 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2789 CHECK_FSP(fsp,conn);
2792 if (!CAN_PRINT(conn))
2793 return(ERROR(ERRDOS,ERRnoaccess));
2795 DEBUG(3,("printclose fd=%d fnum=%d\n",
2796 fsp->fd_ptr->fd,fsp->fnum));
2798 close_file(fsp,True);
2804 /****************************************************************************
2805 reply to a printqueue
2806 ****************************************************************************/
2807 int reply_printqueue(connection_struct *conn,
2808 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2810 int outsize = set_message(outbuf,2,3,True);
2811 int max_count = SVAL(inbuf,smb_vwv0);
2812 int start_index = SVAL(inbuf,smb_vwv1);
2814 /* we used to allow the client to get the cnum wrong, but that
2815 is really quite gross and only worked when there was only
2816 one printer - I think we should now only accept it if they
2817 get it right (tridge) */
2818 if (!CAN_PRINT(conn))
2819 return(ERROR(ERRDOS,ERRnoaccess));
2821 SSVAL(outbuf,smb_vwv0,0);
2822 SSVAL(outbuf,smb_vwv1,0);
2823 CVAL(smb_buf(outbuf),0) = 1;
2824 SSVAL(smb_buf(outbuf),1,0);
2826 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2827 start_index, max_count));
2830 print_queue_struct *queue = NULL;
2831 char *p = smb_buf(outbuf) + 3;
2832 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2833 int num_to_get = ABS(max_count);
2834 int first = (max_count>0?start_index:start_index+max_count+1);
2840 num_to_get = MIN(num_to_get,count-first);
2843 for (i=first;i<first+num_to_get;i++) {
2844 put_dos_date2(p,0,queue[i].time);
2845 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2846 SSVAL(p,5,printjob_encode(SNUM(conn),
2848 SIVAL(p,7,queue[i].size);
2850 StrnCpy(p+12,queue[i].user,16);
2855 outsize = set_message(outbuf,2,28*count+3,False);
2856 SSVAL(outbuf,smb_vwv0,count);
2857 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2858 CVAL(smb_buf(outbuf),0) = 1;
2859 SSVAL(smb_buf(outbuf),1,28*count);
2862 if (queue) free(queue);
2864 DEBUG(3,("%d entries returned in queue\n",count));
2871 /****************************************************************************
2872 reply to a printwrite
2873 ****************************************************************************/
2874 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2877 int outsize = set_message(outbuf,0,0,True);
2879 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2881 if (!CAN_PRINT(conn))
2882 return(ERROR(ERRDOS,ERRnoaccess));
2884 CHECK_FSP(fsp,conn);
2888 numtowrite = SVAL(smb_buf(inbuf),1);
2889 data = smb_buf(inbuf) + 3;
2891 if (write_file(fsp,data,numtowrite) != numtowrite)
2892 return(UNIXERROR(ERRDOS,ERRnoaccess));
2894 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2900 /****************************************************************************
2902 ****************************************************************************/
2903 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2906 int outsize,ret= -1;
2907 BOOL bad_path = False;
2909 pstrcpy(directory,smb_buf(inbuf) + 1);
2910 unix_convert(directory,conn,0,&bad_path,NULL);
2912 if (check_name(directory, conn))
2913 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2917 if((errno == ENOENT) && bad_path)
2919 unix_ERR_class = ERRDOS;
2920 unix_ERR_code = ERRbadpath;
2922 return(UNIXERROR(ERRDOS,ERRnoaccess));
2925 outsize = set_message(outbuf,0,0,True);
2927 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2932 /****************************************************************************
2933 Static function used by reply_rmdir to delete an entire directory
2935 ****************************************************************************/
2936 static BOOL recursive_rmdir(char *directory)
2940 void *dirptr = OpenDir(NULL, directory, False);
2945 while((dname = ReadDirName(dirptr)))
2950 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2953 /* Construct the full name. */
2954 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2960 pstrcpy(fullname, directory);
2961 pstrcat(fullname, "/");
2962 pstrcat(fullname, dname);
2964 if(dos_lstat(fullname, &st) != 0)
2970 if(st.st_mode & S_IFDIR)
2972 if(recursive_rmdir(fullname)!=0)
2977 if(dos_rmdir(fullname) != 0)
2983 else if(dos_unlink(fullname) != 0)
2993 /****************************************************************************
2995 ****************************************************************************/
2996 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3001 BOOL bad_path = False;
3003 pstrcpy(directory,smb_buf(inbuf) + 1);
3004 unix_convert(directory,conn, NULL,&bad_path,NULL);
3006 if (check_name(directory,conn))
3009 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3010 ok = (dos_rmdir(directory) == 0);
3011 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
3013 /* Check to see if the only thing in this directory are
3014 vetoed files/directories. If so then delete them and
3015 retry. If we fail to delete any of them (and we *don't*
3016 do a recursive delete) then fail the rmdir. */
3017 BOOL all_veto_files = True;
3019 void *dirptr = OpenDir(conn, directory, False);
3023 int dirpos = TellDir(dirptr);
3024 while ((dname = ReadDirName(dirptr)))
3026 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3028 if(!IS_VETO_PATH(conn, dname))
3030 all_veto_files = False;
3036 SeekDir(dirptr,dirpos);
3037 while ((dname = ReadDirName(dirptr)))
3042 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3045 /* Construct the full name. */
3046 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3051 pstrcpy(fullname, directory);
3052 pstrcat(fullname, "/");
3053 pstrcat(fullname, dname);
3055 if(dos_lstat(fullname, &st) != 0)
3057 if(st.st_mode & S_IFDIR)
3059 if(lp_recursive_veto_delete(SNUM(conn)))
3061 if(recursive_rmdir(fullname) != 0)
3064 if(dos_rmdir(fullname) != 0)
3067 else if(dos_unlink(fullname) != 0)
3071 /* Retry the rmdir */
3072 ok = (dos_rmdir(directory) == 0);
3082 DEBUG(3,("couldn't remove directory %s : %s\n",
3083 directory,strerror(errno)));
3088 if((errno == ENOENT) && bad_path)
3090 unix_ERR_class = ERRDOS;
3091 unix_ERR_code = ERRbadpath;
3093 return(UNIXERROR(ERRDOS,ERRbadpath));
3096 outsize = set_message(outbuf,0,0,True);
3098 DEBUG( 3, ( "rmdir %s\n", directory ) );
3104 /*******************************************************************
3105 resolve wildcards in a filename rename
3106 ********************************************************************/
3107 static BOOL resolve_wildcards(char *name1,char *name2)
3109 fstring root1,root2;
3113 name1 = strrchr(name1,'/');
3114 name2 = strrchr(name2,'/');
3116 if (!name1 || !name2) return(False);
3118 fstrcpy(root1,name1);
3119 fstrcpy(root2,name2);
3120 p = strrchr(root1,'.');
3127 p = strrchr(root2,'.');
3159 pstrcpy(name2,root2);
3162 pstrcat(name2,ext2);
3168 /*******************************************************************
3169 check if a user is allowed to rename a file
3170 ********************************************************************/
3171 static BOOL can_rename(char *fname,connection_struct *conn)
3173 SMB_STRUCT_STAT sbuf;
3175 if (!CAN_WRITE(conn)) return(False);
3177 if (dos_lstat(fname,&sbuf) != 0) return(False);
3178 if (!check_file_sharing(conn,fname,True)) return(False);
3183 /****************************************************************************
3184 The guts of the rename command, split out so it may be called by the NT SMB
3186 ****************************************************************************/
3187 int rename_internals(connection_struct *conn,
3188 char *inbuf, char *outbuf, char *name,
3189 char *newname, BOOL replace_if_exists)
3193 pstring newname_last_component;
3196 BOOL bad_path1 = False;
3197 BOOL bad_path2 = False;
3199 int error = ERRnoaccess;
3202 *directory = *mask = 0;
3204 unix_convert(name,conn,0,&bad_path1,NULL);
3205 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3208 * Split the old name into directory and last component
3209 * strings. Note that unix_convert may have stripped off a
3210 * leading ./ from both name and newname if the rename is
3211 * at the root of the share. We need to make sure either both
3212 * name and newname contain a / character or neither of them do
3213 * as this is checked in resolve_wildcards().
3216 p = strrchr(name,'/');
3218 pstrcpy(directory,".");
3222 pstrcpy(directory,name);
3224 *p = '/'; /* Replace needed for exceptional test below. */
3227 if (is_mangled(mask))
3228 check_mangled_cache( mask );
3230 has_wild = strchr(mask,'*') || strchr(mask,'?');
3234 * No wildcards - just process the one file.
3236 BOOL is_short_name = is_8_3(name, True);
3238 /* Add a terminating '/' to the directory name. */
3239 pstrcat(directory,"/");
3240 pstrcat(directory,mask);
3242 /* Ensure newname contains a '/' also */
3243 if(strrchr(newname,'/') == 0) {
3246 pstrcpy(tmpstr, "./");
3247 pstrcat(tmpstr, newname);
3248 pstrcpy(newname, tmpstr);
3251 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",
3252 case_sensitive, case_preserve, short_case_preserve, directory,
3253 newname, newname_last_component, is_short_name));
3256 * Check for special case with case preserving and not
3257 * case sensitive, if directory and newname are identical,
3258 * and the old last component differs from the original
3259 * last component only by case, then we should allow
3260 * the rename (user is trying to change the case of the
3263 if((case_sensitive == False) &&
3264 (((case_preserve == True) &&
3265 (is_short_name == False)) ||
3266 ((short_case_preserve == True) &&
3267 (is_short_name == True))) &&
3268 strcsequal(directory, newname)) {
3269 pstring newname_modified_last_component;
3272 * Get the last component of the modified name.
3273 * Note that we guarantee that newname contains a '/'
3276 p = strrchr(newname,'/');
3277 pstrcpy(newname_modified_last_component,p+1);
3279 if(strcsequal(newname_modified_last_component,
3280 newname_last_component) == False) {
3282 * Replace the modified last component with
3285 pstrcpy(p+1, newname_last_component);
3289 if(replace_if_exists) {
3291 * NT SMB specific flag - rename can overwrite
3292 * file with the same name so don't check for
3295 if(resolve_wildcards(directory,newname) &&
3296 can_rename(directory,conn) &&
3297 !dos_rename(directory,newname))
3300 if (resolve_wildcards(directory,newname) &&
3301 can_rename(directory,conn) &&
3302 !dos_file_exist(newname,NULL) &&
3303 !dos_rename(directory,newname))
3307 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3308 directory,newname));
3310 if (!count) exists = dos_file_exist(directory,NULL);
3311 if (!count && exists && dos_file_exist(newname,NULL)) {
3317 * Wildcards - process each file that matches.
3319 void *dirptr = NULL;
3323 if (check_name(directory,conn))
3324 dirptr = OpenDir(conn, directory, True);
3329 if (strequal(mask,"????????.???"))
3332 while ((dname = ReadDirName(dirptr))) {
3334 pstrcpy(fname,dname);
3336 if(!mask_match(fname, mask, case_sensitive, False))
3339 error = ERRnoaccess;
3340 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3341 if (!can_rename(fname,conn)) {
3342 DEBUG(6,("rename %s refused\n", fname));
3345 pstrcpy(destname,newname);
3347 if (!resolve_wildcards(fname,destname)) {
3348 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3352 if (!replace_if_exists && dos_file_exist(destname,NULL)) {
3353 DEBUG(6,("dos_file_exist %s\n", destname));
3358 if (!dos_rename(fname,destname))
3360 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3368 return(ERROR(ERRDOS,error));
3370 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3371 unix_ERR_class = ERRDOS;
3372 unix_ERR_code = ERRbadpath;
3374 return(UNIXERROR(ERRDOS,error));
3381 /****************************************************************************
3383 ****************************************************************************/
3385 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3391 pstrcpy(name,smb_buf(inbuf) + 1);
3392 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3394 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3396 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3398 outsize = set_message(outbuf,0,0,True);
3403 /*******************************************************************
3404 copy a file as part of a reply_copy
3405 ******************************************************************/
3407 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3408 int count,BOOL target_is_directory)
3413 files_struct *fsp1,*fsp2;
3416 pstrcpy(dest,dest1);
3417 if (target_is_directory) {
3418 char *p = strrchr(src,'/');
3427 if (!dos_file_exist(src,&st))
3434 open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3435 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3442 if (!target_is_directory && count)
3447 close_file(fsp1,False);
3450 open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3451 ofun,st.st_mode,0,&Access,&action);
3454 close_file(fsp1,False);
3459 if ((ofun&3) == 1) {
3460 if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3461 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3464 * Stop the copy from occurring.
3472 ret = transfer_file(fsp1->fd_ptr->fd,
3473 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3475 close_file(fsp1,False);
3476 close_file(fsp2,False);
3478 return(ret == st.st_size);
3483 /****************************************************************************
3484 reply to a file copy.
3485 ****************************************************************************/
3486 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3491 pstring mask,newname;
3494 int error = ERRnoaccess;
3497 int tid2 = SVAL(inbuf,smb_vwv0);
3498 int ofun = SVAL(inbuf,smb_vwv1);
3499 int flags = SVAL(inbuf,smb_vwv2);
3500 BOOL target_is_directory=False;
3501 BOOL bad_path1 = False;
3502 BOOL bad_path2 = False;
3504 *directory = *mask = 0;
3506 pstrcpy(name,smb_buf(inbuf));
3507 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3509 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3511 if (tid2 != conn->cnum) {
3512 /* can't currently handle inter share copies XXXX */
3513 DEBUG(3,("Rejecting inter-share copy\n"));
3514 return(ERROR(ERRSRV,ERRinvdevice));
3517 unix_convert(name,conn,0,&bad_path1,NULL);
3518 unix_convert(newname,conn,0,&bad_path2,NULL);
3520 target_is_directory = dos_directory_exist(newname,NULL);
3522 if ((flags&1) && target_is_directory) {
3523 return(ERROR(ERRDOS,ERRbadfile));
3526 if ((flags&2) && !target_is_directory) {
3527 return(ERROR(ERRDOS,ERRbadpath));
3530 if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
3531 /* wants a tree copy! XXXX */
3532 DEBUG(3,("Rejecting tree copy\n"));
3533 return(ERROR(ERRSRV,ERRerror));
3536 p = strrchr(name,'/');
3538 pstrcpy(directory,"./");
3542 pstrcpy(directory,name);
3546 if (is_mangled(mask))
3547 check_mangled_cache( mask );
3549 has_wild = strchr(mask,'*') || strchr(mask,'?');
3552 pstrcat(directory,"/");
3553 pstrcat(directory,mask);
3554 if (resolve_wildcards(directory,newname) &&
3555 copy_file(directory,newname,conn,ofun,
3556 count,target_is_directory)) count++;
3557 if (!count) exists = dos_file_exist(directory,NULL);
3559 void *dirptr = NULL;
3563 if (check_name(directory,conn))
3564 dirptr = OpenDir(conn, directory, True);
3570 if (strequal(mask,"????????.???"))
3573 while ((dname = ReadDirName(dirptr)))
3576 pstrcpy(fname,dname);
3578 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3580 error = ERRnoaccess;
3581 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3582 pstrcpy(destname,newname);
3583 if (resolve_wildcards(fname,destname) &&
3584 copy_file(directory,newname,conn,ofun,
3585 count,target_is_directory)) count++;
3586 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3594 return(ERROR(ERRDOS,error));
3597 if((errno == ENOENT) && (bad_path1 || bad_path2))
3599 unix_ERR_class = ERRDOS;
3600 unix_ERR_code = ERRbadpath;
3602 return(UNIXERROR(ERRDOS,error));
3606 outsize = set_message(outbuf,1,0,True);
3607 SSVAL(outbuf,smb_vwv0,count);
3612 /****************************************************************************
3614 ****************************************************************************/
3615 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3623 if (!CAN_SETDIR(snum))
3624 return(ERROR(ERRDOS,ERRnoaccess));
3626 pstrcpy(newdir,smb_buf(inbuf) + 1);
3629 if (strlen(newdir) == 0) {
3632 ok = dos_directory_exist(newdir,NULL);
3634 string_set(&conn->connectpath,newdir);
3639 return(ERROR(ERRDOS,ERRbadpath));
3641 outsize = set_message(outbuf,0,0,True);
3642 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3644 DEBUG(3,("setdir %s\n", newdir));
3649 /****************************************************************************
3650 reply to a lockingX request
3651 ****************************************************************************/
3652 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3654 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3655 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3657 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3659 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3660 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3661 SMB_OFF_T count = 0, offset = 0;
3662 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3665 uint32 ecode=0, dummy2;
3666 int eclass=0, dummy1;
3667 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3668 CHECK_FSP(fsp,conn);
3671 data = smb_buf(inbuf);
3673 /* Check if this is an oplock break on a file
3674 we have granted an oplock on.
3676 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3679 SMB_DEV_T dev = fsp->fd_ptr->dev;
3680 SMB_INO_T inode = fsp->fd_ptr->inode;
3682 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3685 * Make sure we have granted an oplock on this file.
3687 if(!fsp->granted_oplock)
3689 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3690 no oplock granted on this file.\n", fsp->fnum));
3691 return ERROR(ERRDOS,ERRlock);
3694 /* Remove the oplock flag from the sharemode. */
3695 lock_share_entry(fsp->conn, dev, inode, &token);
3696 if(remove_share_oplock(token, fsp)==False) {
3698 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3699 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3701 unlock_share_entry(fsp->conn, dev, inode, token);
3703 unlock_share_entry(fsp->conn, dev, inode, token);
3705 /* Clear the granted flag and return. */
3706 fsp->granted_oplock = False;
3709 /* if this is a pure oplock break request then don't send a reply */
3710 if (num_locks == 0 && num_ulocks == 0)
3712 /* Sanity check - ensure a pure oplock break is not a
3714 if(CVAL(inbuf,smb_vwv0) != 0xff)
3715 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3716 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3721 /* Data now points at the beginning of the list
3722 of smb_unlkrng structs */
3723 for(i = 0; i < (int)num_ulocks; i++) {
3724 if(!large_file_format) {
3725 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3726 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3728 #ifdef LARGE_SMB_OFF_T
3730 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3731 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3732 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3733 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3735 #endif /* LARGE_SMB_OFF_T */
3737 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3738 (double)offset, (double)count, fsp->fsp_name ));
3740 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3741 return ERROR(eclass,ecode);
3744 /* Setup the timeout in seconds. */
3745 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3747 /* Now do any requested locks */
3748 data += ((large_file_format ? 20 : 10)*num_ulocks);
3750 /* Data now points at the beginning of the list
3751 of smb_lkrng structs */
3753 for(i = 0; i < (int)num_locks; i++) {
3754 if(!large_file_format) {
3755 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3756 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3758 #ifdef LARGE_SMB_OFF_T
3760 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3761 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3762 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3763 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3765 #endif /* LARGE_SMB_OFF_T */
3767 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3768 (double)offset, (double)count, fsp->fsp_name ));
3770 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3772 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3774 * A blocking lock was requested. Package up
3775 * this smb into a queued request and push it
3776 * onto the blocking lock queue.
3778 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3785 /* If any of the above locks failed, then we must unlock
3786 all of the previous locks (X/Open spec). */
3787 if(i != num_locks && num_locks != 0) {
3788 for(; i >= 0; i--) {
3789 if(!large_file_format) {
3790 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3791 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3793 #ifdef LARGE_SMB_OFF_T
3795 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3796 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3797 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3798 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3800 #endif /* LARGE_SMB_OFF_T */
3802 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3804 return ERROR(eclass,ecode);
3807 set_message(outbuf,2,0,True);
3809 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3810 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3812 return chain_reply(inbuf,outbuf,length,bufsize);
3816 /****************************************************************************
3817 reply to a SMBreadbmpx (read block multiplex) request
3818 ****************************************************************************/
3819 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3830 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3832 /* this function doesn't seem to work - disable by default */
3834 return(ERROR(ERRSRV,ERRuseSTD));
3836 outsize = set_message(outbuf,8,0,True);
3838 CHECK_FSP(fsp,conn);
3842 startpos = IVAL(inbuf,smb_vwv1);
3843 maxcount = SVAL(inbuf,smb_vwv3);
3845 data = smb_buf(outbuf);
3846 pad = ((long)data)%4;
3847 if (pad) pad = 4 - pad;
3850 max_per_packet = bufsize-(outsize+pad);
3854 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3855 return(ERROR(ERRDOS,ERRlock));
3859 size_t N = MIN(max_per_packet,tcount-total_read);
3861 nread = read_file(fsp,data,startpos,N);
3863 if (nread <= 0) nread = 0;
3865 if (nread < (ssize_t)N)
3866 tcount = total_read + nread;
3868 set_message(outbuf,8,nread,False);
3869 SIVAL(outbuf,smb_vwv0,startpos);
3870 SSVAL(outbuf,smb_vwv2,tcount);
3871 SSVAL(outbuf,smb_vwv6,nread);
3872 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3874 send_smb(Client,outbuf);
3876 total_read += nread;
3879 while (total_read < (ssize_t)tcount);
3884 /****************************************************************************
3885 reply to a SMBwritebmpx (write block multiplex primary) request
3886 ****************************************************************************/
3887 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3890 ssize_t nwritten = -1;
3897 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3899 CHECK_FSP(fsp,conn);
3903 tcount = SVAL(inbuf,smb_vwv1);
3904 startpos = IVAL(inbuf,smb_vwv3);
3905 write_through = BITSETW(inbuf+smb_vwv7,0);
3906 numtowrite = SVAL(inbuf,smb_vwv10);
3907 smb_doff = SVAL(inbuf,smb_vwv11);
3909 data = smb_base(inbuf) + smb_doff;
3911 /* If this fails we need to send an SMBwriteC response,
3912 not an SMBwritebmpx - set this up now so we don't forget */
3913 CVAL(outbuf,smb_com) = SMBwritec;
3915 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3916 return(ERROR(ERRDOS,ERRlock));
3918 if(seek_file(fsp,startpos) == -1)
3919 return(UNIXERROR(ERRDOS,ERRnoaccess));
3921 nwritten = write_file(fsp,data,numtowrite);
3923 if(lp_syncalways(SNUM(conn)) || write_through)
3924 sync_file(conn,fsp);
3926 if(nwritten < (ssize_t)numtowrite)
3927 return(UNIXERROR(ERRHRD,ERRdiskfull));
3929 /* If the maximum to be written to this file
3930 is greater than what we just wrote then set
3931 up a secondary struct to be attached to this
3932 fd, we will use this to cache error messages etc. */
3933 if((ssize_t)tcount > nwritten)
3935 write_bmpx_struct *wbms;
3936 if(fsp->wbmpx_ptr != NULL)
3937 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3939 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3942 DEBUG(0,("Out of memory in reply_readmpx\n"));
3943 return(ERROR(ERRSRV,ERRnoresource));
3945 wbms->wr_mode = write_through;
3946 wbms->wr_discard = False; /* No errors yet */
3947 wbms->wr_total_written = nwritten;
3948 wbms->wr_errclass = 0;
3950 fsp->wbmpx_ptr = wbms;
3953 /* We are returning successfully, set the message type back to
3955 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3957 outsize = set_message(outbuf,1,0,True);
3959 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3961 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3962 fsp->fnum, numtowrite, nwritten ) );
3964 if (write_through && tcount==nwritten) {
3965 /* we need to send both a primary and a secondary response */
3966 smb_setlen(outbuf,outsize - 4);
3967 send_smb(Client,outbuf);
3969 /* now the secondary */
3970 outsize = set_message(outbuf,1,0,True);
3971 CVAL(outbuf,smb_com) = SMBwritec;
3972 SSVAL(outbuf,smb_vwv0,nwritten);
3979 /****************************************************************************
3980 reply to a SMBwritebs (write block multiplex secondary) request
3981 ****************************************************************************/
3982 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3985 ssize_t nwritten = -1;
3992 write_bmpx_struct *wbms;
3993 BOOL send_response = False;
3994 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3996 CHECK_FSP(fsp,conn);
3999 tcount = SVAL(inbuf,smb_vwv1);
4000 startpos = IVAL(inbuf,smb_vwv2);
4001 numtowrite = SVAL(inbuf,smb_vwv6);
4002 smb_doff = SVAL(inbuf,smb_vwv7);
4004 data = smb_base(inbuf) + smb_doff;
4006 /* We need to send an SMBwriteC response, not an SMBwritebs */
4007 CVAL(outbuf,smb_com) = SMBwritec;
4009 /* This fd should have an auxiliary struct attached,
4010 check that it does */
4011 wbms = fsp->wbmpx_ptr;
4012 if(!wbms) return(-1);
4014 /* If write through is set we can return errors, else we must
4016 write_through = wbms->wr_mode;
4018 /* Check for an earlier error */
4019 if(wbms->wr_discard)
4020 return -1; /* Just discard the packet */
4022 if(seek_file(fsp,startpos) == -1)
4026 /* We are returning an error - we can delete the aux struct */
4027 if (wbms) free((char *)wbms);
4028 fsp->wbmpx_ptr = NULL;
4029 return(UNIXERROR(ERRDOS,ERRnoaccess));
4031 return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
4034 nwritten = write_file(fsp,data,numtowrite);
4036 if(lp_syncalways(SNUM(conn)) || write_through)
4037 sync_file(conn,fsp);
4039 if (nwritten < (ssize_t)numtowrite)
4043 /* We are returning an error - we can delete the aux struct */
4044 if (wbms) free((char *)wbms);
4045 fsp->wbmpx_ptr = NULL;
4046 return(ERROR(ERRHRD,ERRdiskfull));
4048 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4051 /* Increment the total written, if this matches tcount
4052 we can discard the auxiliary struct (hurrah !) and return a writeC */
4053 wbms->wr_total_written += nwritten;
4054 if(wbms->wr_total_written >= tcount)
4058 outsize = set_message(outbuf,1,0,True);
4059 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4060 send_response = True;
4064 fsp->wbmpx_ptr = NULL;
4074 /****************************************************************************
4075 reply to a SMBsetattrE
4076 ****************************************************************************/
4077 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4079 struct utimbuf unix_times;
4081 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4083 outsize = set_message(outbuf,0,0,True);
4085 CHECK_FSP(fsp,conn);
4088 /* Convert the DOS times into unix times. Ignore create
4089 time as UNIX can't set this.
4091 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4092 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4095 * Patch from Ray Frush <frush@engr.colostate.edu>
4096 * Sometimes times are sent as zero - ignore them.
4099 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4101 /* Ignore request */
4104 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4105 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4109 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4111 /* set modify time = to access time if modify time was 0 */
4112 unix_times.modtime = unix_times.actime;
4115 /* Set the date on this file */
4116 if(file_utime(conn, fsp->fsp_name, &unix_times))
4117 return(ERROR(ERRDOS,ERRnoaccess));
4119 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4120 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4126 /****************************************************************************
4127 reply to a SMBgetattrE
4128 ****************************************************************************/
4129 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4131 SMB_STRUCT_STAT sbuf;
4134 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4136 outsize = set_message(outbuf,11,0,True);
4138 CHECK_FSP(fsp,conn);
4141 /* Do an fstat on this file */
4142 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4143 return(UNIXERROR(ERRDOS,ERRnoaccess));
4145 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4147 /* Convert the times into dos times. Set create
4148 date to be last modify date as UNIX doesn't save
4150 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4151 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4152 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4155 SIVAL(outbuf,smb_vwv6,0);
4156 SIVAL(outbuf,smb_vwv8,0);
4160 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4161 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4163 SSVAL(outbuf,smb_vwv10, mode);
4165 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));