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 int chain_fnum;
37 extern char magic_char;
38 extern connection_struct Connections[];
39 extern files_struct Files[];
40 extern BOOL case_sensitive;
41 extern BOOL case_preserve;
42 extern BOOL short_case_preserve;
43 extern pstring sesssetup_user;
44 extern fstring global_myworkgroup;
46 extern int global_oplock_break;
48 /* this macro should always be used to extract an fnum (smb_fid) from
49 a packet to ensure chaining works correctly */
50 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
53 /****************************************************************************
54 report a possible attack via the password buffer overflow bug
55 ****************************************************************************/
56 static void overflow_attack(int len)
58 DEBUG(0,("%s: ERROR: Invalid password length %d\n", timestring(), len));
59 DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n"));
60 DEBUG(0,("Attack was from IP=%s\n", client_addr(Client)));
61 exit_server("possible attack");
65 /****************************************************************************
66 reply to an special message
67 ****************************************************************************/
68 int reply_special(char *inbuf,char *outbuf)
71 int msg_type = CVAL(inbuf,0);
72 int msg_flags = CVAL(inbuf,1);
74 extern fstring remote_machine;
75 extern fstring local_machine;
84 case 0x81: /* session request */
85 CVAL(outbuf,0) = 0x82;
87 if (name_len(inbuf+4) > 50 ||
88 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
89 DEBUG(0,("Invalid name length in session request\n"));
92 name_extract(inbuf,4,name1);
93 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
94 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
97 fstrcpy(remote_machine,name2);
98 remote_machine[15] = 0;
99 trim_string(remote_machine," "," ");
100 strlower(remote_machine);
102 fstrcpy(local_machine,name1);
103 len = strlen(local_machine);
105 name_type = local_machine[15];
106 local_machine[15] = 0;
108 trim_string(local_machine," "," ");
109 strlower(local_machine);
111 if (name_type == 'R') {
112 /* We are being asked for a pathworks session ---
114 CVAL(outbuf, 0) = 0x83;
118 add_session_user(remote_machine);
120 reload_services(True);
124 claim_connection(-1,"STATUS.",MAXSTATUS,True);
129 case 0x89: /* session keepalive request
130 (some old clients produce this?) */
131 CVAL(outbuf,0) = 0x85;
135 case 0x82: /* positive session response */
136 case 0x83: /* negative session response */
137 case 0x84: /* retarget session response */
138 DEBUG(0,("Unexpected session response\n"));
141 case 0x85: /* session keepalive */
146 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",
147 timestring(),msg_type,msg_flags));
153 /*******************************************************************
154 work out what error to give to a failed connection
155 ********************************************************************/
156 static int connection_error(char *inbuf,char *outbuf,int connection_num)
158 switch (connection_num)
161 return(ERROR(ERRSRV,ERRnoresource));
163 return(ERROR(ERRSRV,ERRbaduid));
165 return(ERROR(ERRSRV,ERRinvdevice));
167 return(ERROR(ERRSRV,ERRinvnetname));
169 return(ERROR(ERRSRV,ERRaccess));
171 return(ERROR(ERRDOS,ERRnoipc));
173 return(ERROR(ERRSRV,ERRinvnetname));
175 return(ERROR(ERRSRV,ERRbadpw));
180 /****************************************************************************
181 parse a share descriptor string
182 ****************************************************************************/
183 static void parse_connect(char *p,char *service,char *user,
184 char *password,int *pwlen,char *dev)
188 DEBUG(4,("parsing connect string %s\n",p));
190 p2 = strrchr(p,'\\');
194 fstrcpy(service,p2+1);
199 *pwlen = strlen(password);
206 p = strchr(service,'%');
217 /****************************************************************************
219 ****************************************************************************/
220 int reply_tcon(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
228 uint16 vuid = SVAL(inbuf,smb_uid);
231 *service = *user = *password = *dev = 0;
233 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
236 * Pass the user through the NT -> unix user mapping
240 (void)map_username(user);
243 * Do any UNIX username case mangling.
245 (void)Get_Pwnam( user, True);
247 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
249 if (connection_num < 0)
250 return(connection_error(inbuf,outbuf,connection_num));
252 outsize = set_message(outbuf,2,0,True);
253 SSVAL(outbuf,smb_vwv0,max_recv);
254 SSVAL(outbuf,smb_vwv1,connection_num);
255 SSVAL(outbuf,smb_tid,connection_num);
257 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
263 /****************************************************************************
264 reply to a tcon and X
265 ****************************************************************************/
266 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
273 uint16 vuid = SVAL(inbuf,smb_uid);
274 int passlen = SVAL(inbuf,smb_vwv3);
276 *service = *user = *password = *devicename = 0;
278 /* we might have to close an old one */
279 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
280 close_cnum(SVAL(inbuf,smb_tid),vuid);
282 if (passlen > MAX_PASS_LEN) {
283 overflow_attack(passlen);
289 memcpy(password,smb_buf(inbuf),passlen);
291 path = smb_buf(inbuf) + passlen;
294 if (strequal(password," "))
296 passlen = strlen(password);
299 fstrcpy(service,path+2);
300 p = strchr(service,'\\');
302 return(ERROR(ERRSRV,ERRinvnetname));
304 fstrcpy(service,p+1);
305 p = strchr(service,'%');
311 StrnCpy(devicename,path + strlen(path) + 1,6);
312 DEBUG(4,("Got device type %s\n",devicename));
316 * Pass the user through the NT -> unix user mapping
320 (void)map_username(user);
323 * Do any UNIX username case mangling.
325 (void)Get_Pwnam( user, True);
327 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
329 if (connection_num < 0)
330 return(connection_error(inbuf,outbuf,connection_num));
332 if (Protocol < PROTOCOL_NT1)
334 set_message(outbuf,2,strlen(devicename)+1,True);
335 pstrcpy(smb_buf(outbuf),devicename);
339 char *fsname = FSTYPE_STRING;
342 set_message(outbuf,3,3,True);
345 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
346 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
348 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
350 SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
353 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
355 /* set the incoming and outgoing tid to the just created one */
356 SSVAL(inbuf,smb_tid,connection_num);
357 SSVAL(outbuf,smb_tid,connection_num);
359 return chain_reply(inbuf,outbuf,length,bufsize);
363 /****************************************************************************
364 reply to an unknown type
365 ****************************************************************************/
366 int reply_unknown(char *inbuf,char *outbuf)
370 cnum = SVAL(inbuf,smb_tid);
371 type = CVAL(inbuf,smb_com);
373 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
378 return(ERROR(ERRSRV,ERRunknownsmb));
382 /****************************************************************************
384 ****************************************************************************/
385 int reply_ioctl(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
387 DEBUG(3,("ignoring ioctl\n"));
389 /* we just say it succeeds and hope its all OK.
390 some day it would be nice to interpret them individually */
391 return set_message(outbuf,1,0,True);
393 return(ERROR(ERRSRV,ERRnosupport));
397 /****************************************************************************
398 always return an error: it's just a matter of which one...
399 ****************************************************************************/
400 static int session_trust_account(char *inbuf, char *outbuf, char *user,
401 char *smb_passwd, int smb_passlen,
402 char *smb_nt_passwd, int smb_nt_passlen)
404 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
405 if (lp_security() == SEC_USER)
407 smb_trust_acct = getsmbpwnam(user);
411 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
412 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
413 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
416 if (smb_trust_acct == NULL)
418 /* lkclXXXX: workstation entry doesn't exist */
419 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
420 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
421 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
425 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
427 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
428 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
429 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
432 if (!smb_password_ok(smb_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
434 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
435 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
436 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
439 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
441 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
442 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
443 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
446 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
448 DEBUG(0,("session_trust_account: Server 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_SERVER_TRUST_ACCOUNT));
453 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
455 DEBUG(4,("session_trust_account: Wksta 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_WORKSTATION_TRUST_ACCOUNT));
461 /* don't know what to do: indicate logon failure */
462 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
463 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
467 /****************************************************************************
468 reply to a session setup command
469 ****************************************************************************/
470 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
479 int smb_apasslen = 0;
481 int smb_ntpasslen = 0;
482 pstring smb_ntpasswd;
483 BOOL valid_nt_password = False;
487 static BOOL done_sesssetup = False;
488 BOOL doencrypt = SMBENCRYPT();
494 smb_bufsize = SVAL(inbuf,smb_vwv2);
495 smb_mpxmax = SVAL(inbuf,smb_vwv3);
496 smb_vc_num = SVAL(inbuf,smb_vwv4);
497 smb_sesskey = IVAL(inbuf,smb_vwv5);
499 if (Protocol < PROTOCOL_NT1) {
500 smb_apasslen = SVAL(inbuf,smb_vwv7);
501 if (smb_apasslen > MAX_PASS_LEN)
503 overflow_attack(smb_apasslen);
506 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
507 smb_apasswd[smb_apasslen] = 0;
508 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
510 if (!doencrypt && (lp_security() != SEC_SERVER)) {
511 smb_apasslen = strlen(smb_apasswd);
514 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
515 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
516 uint32 client_caps = IVAL(inbuf,smb_vwv11);
517 enum remote_arch_types ra_type = get_remote_arch();
519 char *p = smb_buf(inbuf);
521 /* client_caps is used as final determination if client is NT or Win95.
522 This is needed to return the correct error codes in some
526 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
528 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
529 set_remote_arch( RA_WINNT);
531 set_remote_arch( RA_WIN95);
534 if (passlen1 != 24 && passlen2 != 24)
537 if (passlen1 > MAX_PASS_LEN) {
538 overflow_attack(passlen1);
541 passlen1 = MIN(passlen1, MAX_PASS_LEN);
542 passlen2 = MIN(passlen2, MAX_PASS_LEN);
545 /* both Win95 and WinNT stuff up the password lengths for
546 non-encrypting systems. Uggh.
548 if passlen1==24 its a win95 system, and its setting the
549 password length incorrectly. Luckily it still works with the
550 default code because Win95 will null terminate the password
553 if passlen1>0 and passlen2>0 then maybe its a NT box and its
554 setting passlen2 to some random value which really stuffs
555 things up. we need to fix that one. */
557 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
561 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
562 /* Save the lanman2 password and the NT md4 password. */
563 smb_apasslen = passlen1;
564 memcpy(smb_apasswd,p,smb_apasslen);
565 smb_apasswd[smb_apasslen] = 0;
566 smb_ntpasslen = passlen2;
567 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
568 smb_ntpasswd[smb_ntpasslen] = 0;
570 /* we use the first password that they gave */
571 smb_apasslen = passlen1;
572 StrnCpy(smb_apasswd,p,smb_apasslen);
574 /* trim the password */
575 smb_apasslen = strlen(smb_apasswd);
577 /* wfwg sometimes uses a space instead of a null */
578 if (strequal(smb_apasswd," ")) {
584 p += passlen1 + passlen2;
585 fstrcpy(user,p); p = skip_string(p,1);
588 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
589 domain,skip_string(p,1),skip_string(p,2)));
593 DEBUG(3,("sesssetupX:name=[%s]\n",user));
595 /* If name ends in $ then I think it's asking about whether a */
596 /* computer with that name (minus the $) has access. For now */
597 /* say yes to everything ending in $. */
598 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
600 return session_trust_account(inbuf, outbuf, user,
601 smb_apasswd, smb_apasslen,
602 smb_ntpasswd, smb_ntpasslen);
605 /* If no username is sent use the guest account */
608 pstrcpy(user,lp_guestaccount(-1));
609 /* If no user and no password then set guest flag. */
610 if( *smb_apasswd == 0)
617 * In share level security, only overwrite sesssetup_use if
618 * it's a non null-session share. Helps keep %U and %G
622 if((lp_security() != SEC_SHARE) || *user)
623 pstrcpy(sesssetup_user,user);
625 reload_services(True);
628 * Save the username before mapping. We will use
629 * the original username sent to us for security=server
630 * and security=domain checking.
633 pstrcpy( orig_user, user);
636 * Pass the user through the NT -> unix user mapping
640 (void)map_username(user);
643 * Do any UNIX username case mangling.
645 (void)Get_Pwnam( user, True);
647 add_session_user(user);
650 * Check if the given username was the guest user with no password.
653 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
656 if (!guest && !(lp_security() == SEC_SERVER &&
657 /* Check with orig_user for security=server and
659 server_validate(orig_user, domain,
660 smb_apasswd, smb_apasslen,
661 smb_ntpasswd, smb_ntpasslen)) &&
662 !(lp_security() == SEC_DOMAIN &&
663 domain_client_validate(orig_user, domain,
664 smb_apasswd, smb_apasslen,
665 smb_ntpasswd, smb_ntpasslen)) &&
666 !check_hosts_equiv(user)
670 /* now check if it's a valid username/password */
671 /* If an NT password was supplied try and validate with that
672 first. This is superior as the passwords are mixed case
673 128 length unicode */
676 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
677 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
679 valid_nt_password = True;
681 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
683 if (lp_security() >= SEC_USER) {
684 #if (GUEST_SESSSETUP == 0)
685 return(ERROR(ERRSRV,ERRbadpw));
687 #if (GUEST_SESSSETUP == 1)
688 if (Get_Pwnam(user,True))
689 return(ERROR(ERRSRV,ERRbadpw));
692 if (*smb_apasswd || !Get_Pwnam(user,True))
693 pstrcpy(user,lp_guestaccount(-1));
694 DEBUG(3,("Registered username %s for guest access\n",user));
699 if (!Get_Pwnam(user,True)) {
700 DEBUG(3,("No such user %s - using guest account\n",user));
701 pstrcpy(user,lp_guestaccount(-1));
705 if (!strequal(user,lp_guestaccount(-1)) &&
706 lp_servicenumber(user) < 0)
708 int homes = lp_servicenumber(HOMES_NAME);
709 char *home = get_home_dir(user);
710 if (homes >= 0 && home)
711 lp_add_home(user,homes,home);
715 /* it's ok - setup a reply */
716 if (Protocol < PROTOCOL_NT1) {
717 set_message(outbuf,3,0,True);
720 set_message(outbuf,3,3,True);
722 pstrcpy(p,"Unix"); p = skip_string(p,1);
723 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
724 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
725 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
726 /* perhaps grab OS version here?? */
729 /* Set the correct uid in the outgoing and incoming packets
730 We will use this on future requests to determine which
731 user we should become.
734 struct passwd *pw = Get_Pwnam(user,False);
736 DEBUG(1,("Username %s is invalid on this system\n",user));
737 return(ERROR(ERRSRV,ERRbadpw));
744 SSVAL(outbuf,smb_vwv2,1);
746 /* register the name and uid as being validated, so further connections
747 to a uid can get through without a password, on the same VC */
748 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
750 SSVAL(outbuf,smb_uid,sess_vuid);
751 SSVAL(inbuf,smb_uid,sess_vuid);
754 max_send = MIN(max_send,smb_bufsize);
756 DEBUG(6,("Client requested max send size of %d\n", max_send));
758 done_sesssetup = True;
760 return chain_reply(inbuf,outbuf,length,bufsize);
764 /****************************************************************************
766 ****************************************************************************/
767 int reply_chkpth(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
773 BOOL bad_path = False;
775 cnum = SVAL(inbuf,smb_tid);
777 pstrcpy(name,smb_buf(inbuf) + 1);
778 unix_convert(name,cnum,0,&bad_path);
780 mode = SVAL(inbuf,smb_vwv0);
782 if (check_name(name,cnum))
783 ok = directory_exist(name,NULL);
787 /* We special case this - as when a Windows machine
788 is parsing a path is steps through the components
789 one at a time - if a component fails it expects
790 ERRbadpath, not ERRbadfile.
794 unix_ERR_class = ERRDOS;
795 unix_ERR_code = ERRbadpath;
799 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
800 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
801 (get_remote_arch() == RA_WINNT))
803 unix_ERR_class = ERRDOS;
804 unix_ERR_code = ERRbaddirectory;
808 return(UNIXERROR(ERRDOS,ERRbadpath));
811 outsize = set_message(outbuf,0,0,True);
813 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
819 /****************************************************************************
821 ****************************************************************************/
822 int reply_getatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
832 BOOL bad_path = False;
834 cnum = SVAL(inbuf,smb_tid);
836 pstrcpy(fname,smb_buf(inbuf) + 1);
837 unix_convert(fname,cnum,0,&bad_path);
839 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
840 under WfWg - weird! */
843 mode = aHIDDEN | aDIR;
844 if (!CAN_WRITE(cnum)) mode |= aRONLY;
850 if (check_name(fname,cnum))
852 if (sys_stat(fname,&sbuf) == 0)
854 mode = dos_mode(cnum,fname,&sbuf);
856 mtime = sbuf.st_mtime;
862 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
867 if((errno == ENOENT) && bad_path)
869 unix_ERR_class = ERRDOS;
870 unix_ERR_code = ERRbadpath;
873 return(UNIXERROR(ERRDOS,ERRbadfile));
876 outsize = set_message(outbuf,10,0,True);
878 SSVAL(outbuf,smb_vwv0,mode);
879 if(lp_dos_filetime_resolution(SNUM(cnum)) )
880 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
882 put_dos_date3(outbuf,smb_vwv1,mtime);
883 SIVAL(outbuf,smb_vwv3,size);
885 if (Protocol >= PROTOCOL_NT1) {
886 char *p = strrchr(fname,'/');
887 uint16 flg2 = SVAL(outbuf,smb_flg2);
889 if (!is_8_3(fname, True))
890 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
893 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
899 /****************************************************************************
901 ****************************************************************************/
902 int reply_setatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
910 BOOL bad_path = False;
912 cnum = SVAL(inbuf,smb_tid);
914 pstrcpy(fname,smb_buf(inbuf) + 1);
915 unix_convert(fname,cnum,0,&bad_path);
917 mode = SVAL(inbuf,smb_vwv0);
918 mtime = make_unix_date3(inbuf+smb_vwv1);
920 if (directory_exist(fname,NULL))
922 if (check_name(fname,cnum))
923 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
925 ok = set_filetime(cnum,fname,mtime);
929 if((errno == ENOENT) && bad_path)
931 unix_ERR_class = ERRDOS;
932 unix_ERR_code = ERRbadpath;
935 return(UNIXERROR(ERRDOS,ERRnoaccess));
938 outsize = set_message(outbuf,0,0,True);
940 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
946 /****************************************************************************
948 ****************************************************************************/
949 int reply_dskattr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
953 int dfree,dsize,bsize;
955 cnum = SVAL(inbuf,smb_tid);
957 sys_disk_free(".",&bsize,&dfree,&dsize);
959 outsize = set_message(outbuf,5,0,True);
961 SSVAL(outbuf,smb_vwv0,dsize);
962 SSVAL(outbuf,smb_vwv1,bsize/512);
963 SSVAL(outbuf,smb_vwv2,512);
964 SSVAL(outbuf,smb_vwv3,dfree);
966 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
972 /****************************************************************************
974 Can be called from SMBsearch, SMBffirst or SMBfunique.
975 ****************************************************************************/
976 int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
987 BOOL finished = False;
996 BOOL check_descend = False;
997 BOOL expect_close = False;
998 BOOL can_open = True;
999 BOOL bad_path = False;
1001 *mask = *directory = *fname = 0;
1003 /* If we were called as SMBffirst then we must expect close. */
1004 if(CVAL(inbuf,smb_com) == SMBffirst)
1005 expect_close = True;
1007 cnum = SVAL(inbuf,smb_tid);
1009 outsize = set_message(outbuf,1,3,True);
1010 maxentries = SVAL(inbuf,smb_vwv0);
1011 dirtype = SVAL(inbuf,smb_vwv1);
1012 path = smb_buf(inbuf) + 1;
1013 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1016 /* dirtype &= ~aDIR; */
1018 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1021 if (status_len == 0)
1025 pstrcpy(directory,smb_buf(inbuf)+1);
1026 pstrcpy(dir2,smb_buf(inbuf)+1);
1027 unix_convert(directory,cnum,0,&bad_path);
1030 if (!check_name(directory,cnum))
1033 p = strrchr(dir2,'/');
1045 p = strrchr(directory,'/');
1051 if (strlen(directory) == 0)
1052 pstrcpy(directory,"./");
1054 CVAL(status,0) = dirtype;
1058 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1059 memcpy(mask,status+1,11);
1061 dirtype = CVAL(status,0) & 0x1F;
1062 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
1063 if (!Connections[cnum].dirptr)
1065 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
1066 if (!case_sensitive)
1070 /* turn strings of spaces into a . */
1072 trim_string(mask,NULL," ");
1073 if ((p = strrchr(mask,' ')))
1078 trim_string(mask,NULL," ");
1085 for (p=mask; *p; p++)
1087 if (*p != '?' && *p != '*' && !isdoschar(*p))
1089 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1095 if (!strchr(mask,'.') && strlen(mask)>8)
1098 fstrcpy(tmp,&mask[8]);
1104 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1108 p = smb_buf(outbuf) + 3;
1112 if (status_len == 0)
1114 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
1119 if((errno == ENOENT) && bad_path)
1121 unix_ERR_class = ERRDOS;
1122 unix_ERR_code = ERRbadpath;
1124 return (UNIXERROR(ERRDOS,ERRnofids));
1126 return(ERROR(ERRDOS,ERRnofids));
1130 DEBUG(4,("dptr_num is %d\n",dptr_num));
1134 if ((dirtype&0x1F) == aVOLID)
1136 memcpy(p,status,21);
1137 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
1138 dptr_fill(p+12,dptr_num);
1139 if (dptr_zero(p+12) && (status_len==0))
1143 p += DIR_STRUCT_SIZE;
1147 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
1148 if (in_list(Connections[cnum].dirpath,
1149 lp_dontdescend(SNUM(cnum)),True))
1150 check_descend = True;
1152 for (i=numentries;(i<maxentries) && !finished;i++)
1155 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
1158 memcpy(p,status,21);
1159 make_dir_struct(p,mask,fname,size,mode,date);
1160 dptr_fill(p+12,dptr_num);
1163 p += DIR_STRUCT_SIZE;
1172 if (numentries == 0 || !ok)
1174 CVAL(outbuf,smb_rcls) = ERRDOS;
1175 SSVAL(outbuf,smb_err,ERRnofiles);
1178 /* If we were called as SMBffirst with smb_search_id == NULL
1179 and no entries were found then return error and close dirptr
1182 if(ok && expect_close && numentries == 0 && status_len == 0)
1184 CVAL(outbuf,smb_rcls) = ERRDOS;
1185 SSVAL(outbuf,smb_err,ERRnofiles);
1186 /* Also close the dptr - we know it's gone */
1187 dptr_close(dptr_num);
1190 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1191 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1192 dptr_close(dptr_num);
1194 SSVAL(outbuf,smb_vwv0,numentries);
1195 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1196 CVAL(smb_buf(outbuf),0) = 5;
1197 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1199 if (Protocol >= PROTOCOL_NT1) {
1200 uint16 flg2 = SVAL(outbuf,smb_flg2);
1201 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1204 outsize += DIR_STRUCT_SIZE*numentries;
1205 smb_setlen(outbuf,outsize - 4);
1207 if ((! *directory) && dptr_path(dptr_num))
1208 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1210 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1212 smb_fn_name(CVAL(inbuf,smb_com)),
1213 mask,directory,cnum,dirtype,numentries,maxentries));
1219 /****************************************************************************
1220 reply to a fclose (stop directory search)
1221 ****************************************************************************/
1222 int reply_fclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1231 cnum = SVAL(inbuf,smb_tid);
1233 outsize = set_message(outbuf,1,0,True);
1234 path = smb_buf(inbuf) + 1;
1235 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1238 if (status_len == 0)
1239 return(ERROR(ERRSRV,ERRsrverror));
1241 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1243 if(dptr_fetch(status+12,&dptr_num)) {
1244 /* Close the dptr - we know it's gone */
1245 dptr_close(dptr_num);
1248 SSVAL(outbuf,smb_vwv0,0);
1250 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1256 /****************************************************************************
1258 ****************************************************************************/
1259 int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1272 BOOL bad_path = False;
1274 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1276 cnum = SVAL(inbuf,smb_tid);
1278 share_mode = SVAL(inbuf,smb_vwv0);
1280 pstrcpy(fname,smb_buf(inbuf)+1);
1281 unix_convert(fname,cnum,0,&bad_path);
1283 fnum = find_free_file();
1285 return(ERROR(ERRSRV,ERRnofids));
1287 if (!check_name(fname,cnum))
1289 if((errno == ENOENT) && bad_path)
1291 unix_ERR_class = ERRDOS;
1292 unix_ERR_code = ERRbadpath;
1294 Files[fnum].reserved = False;
1295 return(UNIXERROR(ERRDOS,ERRnoaccess));
1298 unixmode = unix_mode(cnum,aARCH);
1300 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1301 oplock_request,&rmode,NULL);
1307 if((errno == ENOENT) && bad_path)
1309 unix_ERR_class = ERRDOS;
1310 unix_ERR_code = ERRbadpath;
1312 Files[fnum].reserved = False;
1313 return(UNIXERROR(ERRDOS,ERRnoaccess));
1316 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1317 close_file(fnum,False);
1318 return(ERROR(ERRDOS,ERRnoaccess));
1321 size = sbuf.st_size;
1322 fmode = dos_mode(cnum,fname,&sbuf);
1323 mtime = sbuf.st_mtime;
1326 DEBUG(3,("attempt to open a directory %s\n",fname));
1327 close_file(fnum,False);
1328 return(ERROR(ERRDOS,ERRnoaccess));
1331 outsize = set_message(outbuf,7,0,True);
1332 SSVAL(outbuf,smb_vwv0,fnum);
1333 SSVAL(outbuf,smb_vwv1,fmode);
1334 if(lp_dos_filetime_resolution(SNUM(cnum)) )
1335 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1337 put_dos_date3(outbuf,smb_vwv2,mtime);
1338 SIVAL(outbuf,smb_vwv4,size);
1339 SSVAL(outbuf,smb_vwv6,rmode);
1341 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1342 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1345 if(fsp->granted_oplock)
1346 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1351 /****************************************************************************
1352 reply to an open and X
1353 ****************************************************************************/
1354 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1357 int cnum = SVAL(inbuf,smb_tid);
1359 int smb_mode = SVAL(inbuf,smb_vwv3);
1360 int smb_attr = SVAL(inbuf,smb_vwv5);
1361 /* Breakout the oplock request bits so we can set the
1362 reply bits separately. */
1363 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1364 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1365 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1367 int open_flags = SVAL(inbuf,smb_vwv2);
1368 int smb_sattr = SVAL(inbuf,smb_vwv4);
1369 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1371 int smb_ofun = SVAL(inbuf,smb_vwv8);
1373 int size=0,fmode=0,mtime=0,rmode=0;
1376 BOOL bad_path = False;
1379 /* If it's an IPC, pass off the pipe handler. */
1381 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1383 /* XXXX we need to handle passed times, sattr and flags */
1385 pstrcpy(fname,smb_buf(inbuf));
1386 unix_convert(fname,cnum,0,&bad_path);
1388 fnum = find_free_file();
1390 return(ERROR(ERRSRV,ERRnofids));
1392 if (!check_name(fname,cnum))
1394 if((errno == ENOENT) && bad_path)
1396 unix_ERR_class = ERRDOS;
1397 unix_ERR_code = ERRbadpath;
1399 Files[fnum].reserved = False;
1400 return(UNIXERROR(ERRDOS,ERRnoaccess));
1403 unixmode = unix_mode(cnum,smb_attr | aARCH);
1405 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1406 oplock_request, &rmode,&smb_action);
1412 if((errno == ENOENT) && bad_path)
1414 unix_ERR_class = ERRDOS;
1415 unix_ERR_code = ERRbadpath;
1417 Files[fnum].reserved = False;
1418 return(UNIXERROR(ERRDOS,ERRnoaccess));
1421 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1422 close_file(fnum,False);
1423 return(ERROR(ERRDOS,ERRnoaccess));
1426 size = sbuf.st_size;
1427 fmode = dos_mode(cnum,fname,&sbuf);
1428 mtime = sbuf.st_mtime;
1430 close_file(fnum,False);
1431 return(ERROR(ERRDOS,ERRnoaccess));
1434 /* If the caller set the extended oplock request bit
1435 and we granted one (by whatever means) - set the
1436 correct bit for extended oplock reply.
1439 if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1440 smb_action |= EXTENDED_OPLOCK_GRANTED;
1443 if(ex_oplock_request && fsp->granted_oplock) {
1444 smb_action |= EXTENDED_OPLOCK_GRANTED;
1447 /* If the caller set the core oplock request bit
1448 and we granted one (by whatever means) - set the
1449 correct bit for core oplock reply.
1452 if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1453 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1456 if(core_oplock_request && fsp->granted_oplock) {
1457 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1460 set_message(outbuf,15,0,True);
1461 SSVAL(outbuf,smb_vwv2,fnum);
1462 SSVAL(outbuf,smb_vwv3,fmode);
1463 if(lp_dos_filetime_resolution(SNUM(cnum)) )
1464 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1466 put_dos_date3(outbuf,smb_vwv4,mtime);
1467 SIVAL(outbuf,smb_vwv6,size);
1468 SSVAL(outbuf,smb_vwv8,rmode);
1469 SSVAL(outbuf,smb_vwv11,smb_action);
1473 return chain_reply(inbuf,outbuf,length,bufsize);
1477 /****************************************************************************
1478 reply to a SMBulogoffX
1479 ****************************************************************************/
1480 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1482 uint16 vuid = SVAL(inbuf,smb_uid);
1483 user_struct *vuser = get_valid_user_struct(vuid);
1486 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1489 /* in user level security we are supposed to close any files
1490 open by this user */
1491 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1493 for (i=0;i<MAX_FNUMS;i++) {
1494 files_struct *fsp = &Files[i];
1495 if ((fsp->vuid == vuid) && fsp->open) {
1496 if(!fsp->is_directory)
1497 close_file(i,False);
1504 invalidate_vuid(vuid);
1506 set_message(outbuf,2,0,True);
1508 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1510 return chain_reply(inbuf,outbuf,length,bufsize);
1514 /****************************************************************************
1515 reply to a mknew or a create
1516 ****************************************************************************/
1517 int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1526 BOOL bad_path = False;
1528 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1530 com = SVAL(inbuf,smb_com);
1531 cnum = SVAL(inbuf,smb_tid);
1533 createmode = SVAL(inbuf,smb_vwv0);
1534 pstrcpy(fname,smb_buf(inbuf)+1);
1535 unix_convert(fname,cnum,0,&bad_path);
1537 if (createmode & aVOLID)
1539 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1542 unixmode = unix_mode(cnum,createmode);
1544 fnum = find_free_file();
1546 return(ERROR(ERRSRV,ERRnofids));
1548 if (!check_name(fname,cnum))
1550 if((errno == ENOENT) && bad_path)
1552 unix_ERR_class = ERRDOS;
1553 unix_ERR_code = ERRbadpath;
1555 Files[fnum].reserved = False;
1556 return(UNIXERROR(ERRDOS,ERRnoaccess));
1561 /* We should fail if file exists. */
1566 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1570 /* Open file in dos compatibility share mode. */
1571 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1572 oplock_request, NULL, NULL);
1578 if((errno == ENOENT) && bad_path)
1580 unix_ERR_class = ERRDOS;
1581 unix_ERR_code = ERRbadpath;
1583 Files[fnum].reserved = False;
1584 return(UNIXERROR(ERRDOS,ERRnoaccess));
1587 outsize = set_message(outbuf,1,0,True);
1588 SSVAL(outbuf,smb_vwv0,fnum);
1590 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1591 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1594 if(fsp->granted_oplock)
1595 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1597 DEBUG(2,("new file %s\n",fname));
1598 DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
1604 /****************************************************************************
1605 reply to a create temporary file
1606 ****************************************************************************/
1607 int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1616 BOOL bad_path = False;
1618 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1620 cnum = SVAL(inbuf,smb_tid);
1621 createmode = SVAL(inbuf,smb_vwv0);
1622 pstrcpy(fname,smb_buf(inbuf)+1);
1623 pstrcat(fname,"/TMXXXXXX");
1624 unix_convert(fname,cnum,0,&bad_path);
1626 unixmode = unix_mode(cnum,createmode);
1628 fnum = find_free_file();
1630 return(ERROR(ERRSRV,ERRnofids));
1632 if (!check_name(fname,cnum))
1634 if((errno == ENOENT) && bad_path)
1636 unix_ERR_class = ERRDOS;
1637 unix_ERR_code = ERRbadpath;
1639 Files[fnum].reserved = False;
1640 return(UNIXERROR(ERRDOS,ERRnoaccess));
1643 pstrcpy(fname2,(char *)mktemp(fname));
1645 /* Open file in dos compatibility share mode. */
1646 /* We should fail if file exists. */
1647 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1648 oplock_request, NULL, NULL);
1654 if((errno == ENOENT) && bad_path)
1656 unix_ERR_class = ERRDOS;
1657 unix_ERR_code = ERRbadpath;
1659 Files[fnum].reserved = False;
1660 return(UNIXERROR(ERRDOS,ERRnoaccess));
1663 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1664 SSVAL(outbuf,smb_vwv0,fnum);
1665 CVAL(smb_buf(outbuf),0) = 4;
1666 pstrcpy(smb_buf(outbuf) + 1,fname2);
1668 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1669 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1672 if(fsp->granted_oplock)
1673 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1675 DEBUG(2,("created temp file %s\n",fname2));
1676 DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
1682 /*******************************************************************
1683 check if a user is allowed to delete a file
1684 ********************************************************************/
1685 static BOOL can_delete(char *fname,int cnum,int dirtype)
1690 if (!CAN_WRITE(cnum)) return(False);
1692 if (sys_lstat(fname,&sbuf) != 0) return(False);
1693 fmode = dos_mode(cnum,fname,&sbuf);
1694 if (fmode & aDIR) return(False);
1695 if (!lp_delete_readonly(SNUM(cnum))) {
1696 if (fmode & aRONLY) return(False);
1698 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1700 if (!check_file_sharing(cnum,fname,False)) return(False);
1704 /****************************************************************************
1706 ****************************************************************************/
1707 int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1717 int error = ERRnoaccess;
1720 BOOL bad_path = False;
1722 *directory = *mask = 0;
1724 cnum = SVAL(inbuf,smb_tid);
1725 dirtype = SVAL(inbuf,smb_vwv0);
1727 pstrcpy(name,smb_buf(inbuf) + 1);
1729 DEBUG(3,("reply_unlink : %s\n",name));
1731 unix_convert(name,cnum,0,&bad_path);
1733 p = strrchr(name,'/');
1735 pstrcpy(directory,"./");
1739 pstrcpy(directory,name);
1743 if (is_mangled(mask))
1744 check_mangled_cache( mask );
1746 has_wild = strchr(mask,'*') || strchr(mask,'?');
1749 pstrcat(directory,"/");
1750 pstrcat(directory,mask);
1751 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1752 if (!count) exists = file_exist(directory,NULL);
1754 void *dirptr = NULL;
1757 if (check_name(directory,cnum))
1758 dirptr = OpenDir(cnum, directory, True);
1760 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1761 the pattern matches against the long name, otherwise the short name
1762 We don't implement this yet XXXX
1769 if (strequal(mask,"????????.???"))
1772 while ((dname = ReadDirName(dirptr)))
1775 pstrcpy(fname,dname);
1777 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1779 error = ERRnoaccess;
1780 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1781 if (!can_delete(fname,cnum,dirtype)) continue;
1782 if (!sys_unlink(fname)) count++;
1783 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1791 return(ERROR(ERRDOS,error));
1794 if((errno == ENOENT) && bad_path)
1796 unix_ERR_class = ERRDOS;
1797 unix_ERR_code = ERRbadpath;
1799 return(UNIXERROR(ERRDOS,error));
1803 outsize = set_message(outbuf,0,0,True);
1809 /****************************************************************************
1810 reply to a readbraw (core+ protocol)
1811 ****************************************************************************/
1812 int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1814 int cnum,maxcount,mincount,fnum;
1817 char *header = outbuf;
1823 * Special check if an oplock break has been issued
1824 * and the readraw request croses on the wire, we must
1825 * return a zero length response here.
1828 if(global_oplock_break)
1830 _smb_setlen(header,0);
1831 transfer_file(0,Client,0,header,4,0);
1832 DEBUG(5,("readbraw - oplock break finished\n"));
1836 cnum = SVAL(inbuf,smb_tid);
1837 fnum = GETFNUM(inbuf,smb_vwv0);
1839 startpos = IVAL(inbuf,smb_vwv1);
1840 maxcount = SVAL(inbuf,smb_vwv3);
1841 mincount = SVAL(inbuf,smb_vwv4);
1843 /* ensure we don't overrun the packet size */
1844 maxcount = MIN(65535,maxcount);
1845 maxcount = MAX(mincount,maxcount);
1847 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1849 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1850 _smb_setlen(header,0);
1851 transfer_file(0,Client,0,header,4,0);
1856 fd = Files[fnum].fd_ptr->fd;
1857 fname = Files[fnum].name;
1861 if (!is_locked(fnum,cnum,maxcount,startpos, F_RDLCK))
1863 int size = Files[fnum].size;
1864 int sizeneeded = startpos + maxcount;
1866 if (size < sizeneeded) {
1868 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1870 if (!Files[fnum].can_write)
1871 Files[fnum].size = size;
1874 nread = MIN(maxcount,(int)(size - startpos));
1877 if (nread < mincount)
1880 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1883 maxcount,mincount,nread));
1888 _smb_setlen(header,nread);
1890 #if USE_READ_PREDICTION
1891 if (!Files[fnum].can_write)
1892 predict = read_predict(fd,startpos,header+4,NULL,nread);
1895 if ((nread-predict) > 0)
1896 seek_file(fnum,startpos + predict);
1898 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1903 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1904 fname,startpos,nread,ret));
1907 ret = read_file(fnum,header+4,startpos,nread);
1908 if (ret < mincount) ret = 0;
1910 _smb_setlen(header,ret);
1911 transfer_file(0,Client,0,header,4+ret,0);
1914 DEBUG(5,("readbraw finished\n"));
1919 /****************************************************************************
1920 reply to a lockread (core+ protocol)
1921 ****************************************************************************/
1922 int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz)
1928 uint32 startpos, numtoread;
1932 cnum = SVAL(inbuf,smb_tid);
1933 fnum = GETFNUM(inbuf,smb_vwv0);
1935 CHECK_FNUM(fnum,cnum);
1939 numtoread = SVAL(inbuf,smb_vwv1);
1940 startpos = IVAL(inbuf,smb_vwv2);
1942 outsize = set_message(outbuf,5,3,True);
1943 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1944 data = smb_buf(outbuf) + 3;
1946 if(!do_lock( fnum, cnum, numtoread, startpos, F_RDLCK, &eclass, &ecode))
1947 return (ERROR(eclass,ecode));
1949 nread = read_file(fnum,data,startpos,numtoread);
1952 return(UNIXERROR(ERRDOS,ERRnoaccess));
1955 SSVAL(outbuf,smb_vwv0,nread);
1956 SSVAL(outbuf,smb_vwv5,nread+3);
1957 SSVAL(smb_buf(outbuf),1,nread);
1959 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1965 /****************************************************************************
1967 ****************************************************************************/
1968 int reply_read(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1970 int cnum,numtoread,fnum;
1976 cnum = SVAL(inbuf,smb_tid);
1977 fnum = GETFNUM(inbuf,smb_vwv0);
1979 CHECK_FNUM(fnum,cnum);
1983 numtoread = SVAL(inbuf,smb_vwv1);
1984 startpos = IVAL(inbuf,smb_vwv2);
1986 outsize = set_message(outbuf,5,3,True);
1987 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1988 data = smb_buf(outbuf) + 3;
1990 if (is_locked(fnum,cnum,numtoread,startpos, F_RDLCK))
1991 return(ERROR(ERRDOS,ERRlock));
1994 nread = read_file(fnum,data,startpos,numtoread);
1997 return(UNIXERROR(ERRDOS,ERRnoaccess));
2000 SSVAL(outbuf,smb_vwv0,nread);
2001 SSVAL(outbuf,smb_vwv5,nread+3);
2002 CVAL(smb_buf(outbuf),0) = 1;
2003 SSVAL(smb_buf(outbuf),1,nread);
2005 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
2011 /****************************************************************************
2012 reply to a read and X
2013 ****************************************************************************/
2014 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2016 int fnum = GETFNUM(inbuf,smb_vwv2);
2017 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2018 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
2019 int smb_mincnt = SVAL(inbuf,smb_vwv6);
2025 cnum = SVAL(inbuf,smb_tid);
2027 /* If it's an IPC, pass off the pipe handler. */
2029 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2031 CHECK_FNUM(fnum,cnum);
2035 set_message(outbuf,12,0,True);
2036 data = smb_buf(outbuf);
2038 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs, F_RDLCK))
2039 return(ERROR(ERRDOS,ERRlock));
2040 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
2044 return(UNIXERROR(ERRDOS,ERRnoaccess));
2046 SSVAL(outbuf,smb_vwv5,nread);
2047 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2048 SSVAL(smb_buf(outbuf),-2,nread);
2050 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
2051 timestring(),fnum,cnum,
2052 smb_mincnt,smb_maxcnt,nread));
2056 return chain_reply(inbuf,outbuf,length,bufsize);
2060 /****************************************************************************
2061 reply to a writebraw (core+ or LANMAN1.0 protocol)
2062 ****************************************************************************/
2063 int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2066 int total_written=0;
2075 cnum = SVAL(inbuf,smb_tid);
2076 fnum = GETFNUM(inbuf,smb_vwv0);
2078 CHECK_FNUM(fnum,cnum);
2082 tcount = IVAL(inbuf,smb_vwv1);
2083 startpos = IVAL(inbuf,smb_vwv3);
2084 write_through = BITSETW(inbuf+smb_vwv7,0);
2086 /* We have to deal with slightly different formats depending
2087 on whether we are using the core+ or lanman1.0 protocol */
2088 if(Protocol <= PROTOCOL_COREPLUS) {
2089 numtowrite = SVAL(smb_buf(inbuf),-2);
2090 data = smb_buf(inbuf);
2092 numtowrite = SVAL(inbuf,smb_vwv10);
2093 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2096 /* force the error type */
2097 CVAL(inbuf,smb_com) = SMBwritec;
2098 CVAL(outbuf,smb_com) = SMBwritec;
2100 if (is_locked(fnum,cnum,tcount,startpos, F_WRLCK))
2101 return(ERROR(ERRDOS,ERRlock));
2103 if (seek_file(fnum,startpos) != startpos)
2104 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
2107 nwritten = write_file(fnum,data,numtowrite);
2109 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
2110 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
2112 if (nwritten < numtowrite)
2113 return(UNIXERROR(ERRHRD,ERRdiskfull));
2115 total_written = nwritten;
2117 /* Return a message to the redirector to tell it
2118 to send more bytes */
2119 CVAL(outbuf,smb_com) = SMBwritebraw;
2120 SSVALS(outbuf,smb_vwv0,-1);
2121 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2122 send_smb(Client,outbuf);
2124 /* Now read the raw data into the buffer and write it */
2125 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2126 exit_server("secondary writebraw failed");
2129 /* Even though this is not an smb message, smb_len
2130 returns the generic length of an smb message */
2131 numtowrite = smb_len(inbuf);
2133 if (tcount > nwritten+numtowrite) {
2134 DEBUG(3,("Client overestimated the write %d %d %d\n",
2135 tcount,nwritten,numtowrite));
2138 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
2140 total_written += nwritten;
2142 /* Set up outbuf to return the correct return */
2143 outsize = set_message(outbuf,1,0,True);
2144 CVAL(outbuf,smb_com) = SMBwritec;
2145 SSVAL(outbuf,smb_vwv0,total_written);
2147 if (nwritten < numtowrite) {
2148 CVAL(outbuf,smb_rcls) = ERRHRD;
2149 SSVAL(outbuf,smb_err,ERRdiskfull);
2152 if (lp_syncalways(SNUM(cnum)) || write_through)
2153 sync_file(cnum,fnum);
2155 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
2156 timestring(),fnum,cnum,startpos,numtowrite,total_written));
2158 /* we won't return a status if write through is not selected - this
2159 follows what WfWg does */
2160 if (!write_through && total_written==tcount)
2167 /****************************************************************************
2168 reply to a writeunlock (core+)
2169 ****************************************************************************/
2170 int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2176 uint32 numtowrite,startpos;
2180 cnum = SVAL(inbuf,smb_tid);
2181 fnum = GETFNUM(inbuf,smb_vwv0);
2183 CHECK_FNUM(fnum,cnum);
2187 numtowrite = SVAL(inbuf,smb_vwv1);
2188 startpos = IVAL(inbuf,smb_vwv2);
2189 data = smb_buf(inbuf) + 3;
2191 if (is_locked(fnum,cnum,numtowrite,startpos, F_WRLCK))
2192 return(ERROR(ERRDOS,ERRlock));
2194 seek_file(fnum,startpos);
2196 /* The special X/Open SMB protocol handling of
2197 zero length writes is *NOT* done for
2202 nwritten = write_file(fnum,data,numtowrite);
2204 if (lp_syncalways(SNUM(cnum)))
2205 sync_file(cnum,fnum);
2207 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2208 return(UNIXERROR(ERRDOS,ERRnoaccess));
2210 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2211 return(ERROR(eclass,ecode));
2213 outsize = set_message(outbuf,1,0,True);
2215 SSVAL(outbuf,smb_vwv0,nwritten);
2217 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2218 timestring(),fnum,cnum,numtowrite,nwritten));
2224 /****************************************************************************
2226 ****************************************************************************/
2227 int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2229 int cnum,numtowrite,fnum;
2235 cnum = SVAL(inbuf,smb_tid);
2236 fnum = GETFNUM(inbuf,smb_vwv0);
2238 CHECK_FNUM(fnum,cnum);
2242 numtowrite = SVAL(inbuf,smb_vwv1);
2243 startpos = IVAL(inbuf,smb_vwv2);
2244 data = smb_buf(inbuf) + 3;
2246 if (is_locked(fnum,cnum,numtowrite,startpos, F_WRLCK))
2247 return(ERROR(ERRDOS,ERRlock));
2249 seek_file(fnum,startpos);
2251 /* X/Open SMB protocol says that if smb_vwv1 is
2252 zero then the file size should be extended or
2253 truncated to the size given in smb_vwv[2-3] */
2255 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2257 nwritten = write_file(fnum,data,numtowrite);
2259 if (lp_syncalways(SNUM(cnum)))
2260 sync_file(cnum,fnum);
2262 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2263 return(UNIXERROR(ERRDOS,ERRnoaccess));
2265 outsize = set_message(outbuf,1,0,True);
2267 SSVAL(outbuf,smb_vwv0,nwritten);
2269 if (nwritten < numtowrite) {
2270 CVAL(outbuf,smb_rcls) = ERRHRD;
2271 SSVAL(outbuf,smb_err,ERRdiskfull);
2274 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2280 /****************************************************************************
2281 reply to a write and X
2282 ****************************************************************************/
2283 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2285 int fnum = GETFNUM(inbuf,smb_vwv2);
2286 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2287 int smb_dsize = SVAL(inbuf,smb_vwv10);
2288 int smb_doff = SVAL(inbuf,smb_vwv11);
2289 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2294 cnum = SVAL(inbuf,smb_tid);
2296 CHECK_FNUM(fnum,cnum);
2300 data = smb_base(inbuf) + smb_doff;
2302 if (is_locked(fnum,cnum,smb_dsize,smb_offs, F_WRLCK))
2303 return(ERROR(ERRDOS,ERRlock));
2305 seek_file(fnum,smb_offs);
2307 /* X/Open SMB protocol says that, unlike SMBwrite
2308 if the length is zero then NO truncation is
2309 done, just a write of zero. To truncate a file,
2314 nwritten = write_file(fnum,data,smb_dsize);
2316 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2317 return(UNIXERROR(ERRDOS,ERRnoaccess));
2319 set_message(outbuf,6,0,True);
2321 SSVAL(outbuf,smb_vwv2,nwritten);
2323 if (nwritten < smb_dsize) {
2324 CVAL(outbuf,smb_rcls) = ERRHRD;
2325 SSVAL(outbuf,smb_err,ERRdiskfull);
2328 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2332 if (lp_syncalways(SNUM(cnum)) || write_through)
2333 sync_file(cnum,fnum);
2335 return chain_reply(inbuf,outbuf,length,bufsize);
2339 /****************************************************************************
2341 ****************************************************************************/
2342 int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2350 cnum = SVAL(inbuf,smb_tid);
2351 fnum = GETFNUM(inbuf,smb_vwv0);
2353 CHECK_FNUM(fnum,cnum);
2356 mode = SVAL(inbuf,smb_vwv1) & 3;
2357 startpos = IVAL(inbuf,smb_vwv2);
2361 case 0: umode = SEEK_SET; break;
2362 case 1: umode = SEEK_CUR; break;
2363 case 2: umode = SEEK_END; break;
2365 umode = SEEK_SET; break;
2368 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2369 Files[fnum].pos = res;
2371 outsize = set_message(outbuf,2,0,True);
2372 SIVALS(outbuf,smb_vwv0,res);
2374 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2380 /****************************************************************************
2382 ****************************************************************************/
2383 int reply_flush(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2386 int outsize = set_message(outbuf,0,0,True);
2388 cnum = SVAL(inbuf,smb_tid);
2389 fnum = GETFNUM(inbuf,smb_vwv0);
2391 if (fnum != 0xFFFF) {
2392 CHECK_FNUM(fnum,cnum);
2399 for (i=0;i<MAX_FNUMS;i++)
2404 sync_file(cnum,fnum);
2406 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2411 /****************************************************************************
2413 ****************************************************************************/
2414 int reply_exit(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2416 int outsize = set_message(outbuf,0,0,True);
2417 DEBUG(3,("%s exit\n",timestring()));
2423 /****************************************************************************
2424 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2425 ****************************************************************************/
2427 int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2432 int32 eclass = 0, err = 0;
2433 files_struct *fsp = NULL;
2435 outsize = set_message(outbuf,0,0,True);
2437 cnum = SVAL(inbuf,smb_tid);
2439 /* If it's an IPC, pass off to the pipe handler. */
2441 return reply_pipe_close(inbuf,outbuf);
2443 fnum = GETFNUM(inbuf,smb_vwv0);
2446 * We can only use CHECK_FNUM if we know it's not a directory.
2449 if(!(VALID_FNUM(fnum) && Files[fnum].open && Files[fnum].is_directory))
2450 CHECK_FNUM(fnum,cnum);
2454 if(HAS_CACHED_ERROR(fnum)) {
2455 eclass = fsp->wbmpx_ptr->wr_errclass;
2456 err = fsp->wbmpx_ptr->wr_error;
2459 if(fsp->is_directory) {
2461 * Special case - close NT SMB directory
2464 DEBUG(3,("%s close directory fnum=%d cnum=%d\n",
2465 timestring(), fnum, cnum ));
2466 close_directory(fnum);
2469 * Close ordinary file.
2471 mtime = make_unix_date3(inbuf+smb_vwv1);
2473 /* try and set the date */
2474 set_filetime(cnum, fsp->name,mtime);
2476 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2477 timestring(),fsp->fd_ptr->fd,fnum,cnum,
2478 Connections[cnum].num_files_open));
2480 close_file(fnum,True);
2483 /* We have a cached error */
2485 return(ERROR(eclass,err));
2491 /****************************************************************************
2492 reply to a writeclose (Core+ protocol)
2493 ****************************************************************************/
2494 int reply_writeclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2496 int cnum,numtowrite,fnum;
2503 cnum = SVAL(inbuf,smb_tid);
2504 fnum = GETFNUM(inbuf,smb_vwv0);
2506 CHECK_FNUM(fnum,cnum);
2510 numtowrite = SVAL(inbuf,smb_vwv1);
2511 startpos = IVAL(inbuf,smb_vwv2);
2512 mtime = make_unix_date3(inbuf+smb_vwv4);
2513 data = smb_buf(inbuf) + 1;
2515 if (is_locked(fnum,cnum,numtowrite,startpos, F_WRLCK))
2516 return(ERROR(ERRDOS,ERRlock));
2518 seek_file(fnum,startpos);
2520 nwritten = write_file(fnum,data,numtowrite);
2522 set_filetime(cnum, Files[fnum].name,mtime);
2524 close_file(fnum,True);
2526 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2527 timestring(),fnum,cnum,numtowrite,nwritten,
2528 Connections[cnum].num_files_open));
2531 return(UNIXERROR(ERRDOS,ERRnoaccess));
2533 outsize = set_message(outbuf,1,0,True);
2535 SSVAL(outbuf,smb_vwv0,nwritten);
2540 /****************************************************************************
2542 ****************************************************************************/
2543 int reply_lock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2546 int outsize = set_message(outbuf,0,0,True);
2547 uint32 count,offset;
2551 cnum = SVAL(inbuf,smb_tid);
2552 fnum = GETFNUM(inbuf,smb_vwv0);
2554 CHECK_FNUM(fnum,cnum);
2557 count = IVAL(inbuf,smb_vwv1);
2558 offset = IVAL(inbuf,smb_vwv3);
2560 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count));
2562 if(!do_lock( fnum, cnum, count, offset, F_WRLCK, &eclass, &ecode))
2563 return (ERROR(eclass,ecode));
2569 /****************************************************************************
2571 ****************************************************************************/
2572 int reply_unlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2575 int outsize = set_message(outbuf,0,0,True);
2576 uint32 count,offset;
2580 cnum = SVAL(inbuf,smb_tid);
2581 fnum = GETFNUM(inbuf,smb_vwv0);
2583 CHECK_FNUM(fnum,cnum);
2586 count = IVAL(inbuf,smb_vwv1);
2587 offset = IVAL(inbuf,smb_vwv3);
2589 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2590 return (ERROR(eclass,ecode));
2592 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count));
2598 /****************************************************************************
2600 ****************************************************************************/
2601 int reply_tdis(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2604 int outsize = set_message(outbuf,0,0,True);
2607 cnum = SVAL(inbuf,smb_tid);
2608 vuid = SVAL(inbuf,smb_uid);
2610 if (!OPEN_CNUM(cnum)) {
2611 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2612 return(ERROR(ERRSRV,ERRinvnid));
2615 Connections[cnum].used = False;
2617 close_cnum(cnum,vuid);
2619 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2626 /****************************************************************************
2628 ****************************************************************************/
2629 int reply_echo(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2632 int smb_reverb = SVAL(inbuf,smb_vwv0);
2634 int data_len = smb_buflen(inbuf);
2635 int outsize = set_message(outbuf,1,data_len,True);
2637 cnum = SVAL(inbuf,smb_tid);
2639 /* According to the latest CIFS spec we shouldn't
2640 care what the TID is.
2644 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2646 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2647 return(ERROR(ERRSRV,ERRinvnid));
2651 /* copy any incoming data back out */
2653 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2655 if (smb_reverb > 100)
2657 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2661 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2663 SSVAL(outbuf,smb_vwv0,seq_num);
2665 smb_setlen(outbuf,outsize - 4);
2667 send_smb(Client,outbuf);
2670 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2676 /****************************************************************************
2677 reply to a printopen
2678 ****************************************************************************/
2679 int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2687 *fname = *fname2 = 0;
2689 cnum = SVAL(inbuf,smb_tid);
2691 if (!CAN_PRINT(cnum))
2692 return(ERROR(ERRDOS,ERRnoaccess));
2697 pstrcpy(s,smb_buf(inbuf)+1);
2701 if (!(isalnum(*p) || strchr("._-",*p)))
2706 if (strlen(s) > 10) s[10] = 0;
2708 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2711 fnum = find_free_file();
2713 return(ERROR(ERRSRV,ERRnofids));
2715 pstrcpy(fname2,(char *)mktemp(fname));
2717 if (!check_name(fname2,cnum)) {
2718 Files[fnum].reserved = False;
2719 return(ERROR(ERRDOS,ERRnoaccess));
2722 /* Open for exclusive use, write only. */
2723 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2726 if (!Files[fnum].open) {
2727 Files[fnum].reserved = False;
2728 return(UNIXERROR(ERRDOS,ERRnoaccess));
2731 /* force it to be a print file */
2732 Files[fnum].print_file = True;
2734 outsize = set_message(outbuf,1,0,True);
2735 SSVAL(outbuf,smb_vwv0,fnum);
2737 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2743 /****************************************************************************
2744 reply to a printclose
2745 ****************************************************************************/
2746 int reply_printclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2749 int outsize = set_message(outbuf,0,0,True);
2751 cnum = SVAL(inbuf,smb_tid);
2752 fnum = GETFNUM(inbuf,smb_vwv0);
2754 CHECK_FNUM(fnum,cnum);
2757 if (!CAN_PRINT(cnum))
2758 return(ERROR(ERRDOS,ERRnoaccess));
2760 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2762 close_file(fnum,True);
2768 /****************************************************************************
2769 reply to a printqueue
2770 ****************************************************************************/
2771 int reply_printqueue(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2774 int outsize = set_message(outbuf,2,3,True);
2775 int max_count = SVAL(inbuf,smb_vwv0);
2776 int start_index = SVAL(inbuf,smb_vwv1);
2779 cnum = SVAL(inbuf,smb_tid);
2780 vuid = SVAL(inbuf,smb_uid);
2782 /* allow checking the queue for anyone */
2784 if (!CAN_PRINT(cnum))
2785 return(ERROR(ERRDOS,ERRnoaccess));
2788 SSVAL(outbuf,smb_vwv0,0);
2789 SSVAL(outbuf,smb_vwv1,0);
2790 CVAL(smb_buf(outbuf),0) = 1;
2791 SSVAL(smb_buf(outbuf),1,0);
2793 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2794 timestring(),cnum,start_index,max_count));
2796 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2801 for (i=0;i<MAX_CONNECTIONS;i++)
2802 if (CAN_PRINT(i) && Connections[i].printer)
2806 for (i=0;i<MAX_CONNECTIONS;i++)
2810 if (!OPEN_CNUM(cnum))
2811 return(ERROR(ERRSRV,ERRinvnid));
2813 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2816 if (!become_user(&Connections[cnum], cnum, vuid))
2817 return(ERROR(ERRSRV,ERRinvnid));
2820 print_queue_struct *queue = NULL;
2821 char *p = smb_buf(outbuf) + 3;
2822 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2823 int num_to_get = ABS(max_count);
2824 int first = (max_count>0?start_index:start_index+max_count+1);
2830 num_to_get = MIN(num_to_get,count-first);
2833 for (i=first;i<first+num_to_get;i++)
2835 put_dos_date2(p,0,queue[i].time);
2836 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2837 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2838 SIVAL(p,7,queue[i].size);
2840 StrnCpy(p+12,queue[i].user,16);
2846 outsize = set_message(outbuf,2,28*count+3,False);
2847 SSVAL(outbuf,smb_vwv0,count);
2848 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2849 CVAL(smb_buf(outbuf),0) = 1;
2850 SSVAL(smb_buf(outbuf),1,28*count);
2853 if (queue) free(queue);
2855 DEBUG(3,("%d entries returned in queue\n",count));
2862 /****************************************************************************
2863 reply to a printwrite
2864 ****************************************************************************/
2865 int reply_printwrite(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2867 int cnum,numtowrite,fnum;
2868 int outsize = set_message(outbuf,0,0,True);
2871 cnum = SVAL(inbuf,smb_tid);
2873 if (!CAN_PRINT(cnum))
2874 return(ERROR(ERRDOS,ERRnoaccess));
2876 fnum = GETFNUM(inbuf,smb_vwv0);
2878 CHECK_FNUM(fnum,cnum);
2882 numtowrite = SVAL(smb_buf(inbuf),1);
2883 data = smb_buf(inbuf) + 3;
2885 if (write_file(fnum,data,numtowrite) != numtowrite)
2886 return(UNIXERROR(ERRDOS,ERRnoaccess));
2888 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2894 /****************************************************************************
2896 ****************************************************************************/
2897 int reply_mkdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2901 int outsize,ret= -1;
2902 BOOL bad_path = False;
2904 pstrcpy(directory,smb_buf(inbuf) + 1);
2905 cnum = SVAL(inbuf,smb_tid);
2906 unix_convert(directory,cnum,0,&bad_path);
2908 if (check_name(directory,cnum))
2909 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2913 if((errno == ENOENT) && bad_path)
2915 unix_ERR_class = ERRDOS;
2916 unix_ERR_code = ERRbadpath;
2918 return(UNIXERROR(ERRDOS,ERRnoaccess));
2921 outsize = set_message(outbuf,0,0,True);
2923 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2928 /****************************************************************************
2929 Static function used by reply_rmdir to delete an entire directory
2931 ****************************************************************************/
2932 static BOOL recursive_rmdir(char *directory)
2936 void *dirptr = OpenDir(-1, directory, False);
2941 while((dname = ReadDirName(dirptr)))
2946 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2949 /* Construct the full name. */
2950 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2956 pstrcpy(fullname, directory);
2957 pstrcat(fullname, "/");
2958 pstrcat(fullname, dname);
2960 if(sys_lstat(fullname, &st) != 0)
2966 if(st.st_mode & S_IFDIR)
2968 if(recursive_rmdir(fullname)!=0)
2973 if(sys_rmdir(fullname) != 0)
2979 else if(sys_unlink(fullname) != 0)
2989 /****************************************************************************
2991 ****************************************************************************/
2992 int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2998 BOOL bad_path = False;
3000 cnum = SVAL(inbuf,smb_tid);
3001 pstrcpy(directory,smb_buf(inbuf) + 1);
3002 unix_convert(directory,cnum,0,&bad_path);
3004 if (check_name(directory,cnum))
3007 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3008 ok = (sys_rmdir(directory) == 0);
3009 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
3011 /* Check to see if the only thing in this directory are
3012 vetoed files/directories. If so then delete them and
3013 retry. If we fail to delete any of them (and we *don't*
3014 do a recursive delete) then fail the rmdir. */
3015 BOOL all_veto_files = True;
3017 void *dirptr = OpenDir(cnum, directory, False);
3021 int dirpos = TellDir(dirptr);
3022 while ((dname = ReadDirName(dirptr)))
3024 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3026 if(!IS_VETO_PATH(cnum, dname))
3028 all_veto_files = False;
3034 SeekDir(dirptr,dirpos);
3035 while ((dname = ReadDirName(dirptr)))
3040 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3043 /* Construct the full name. */
3044 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3049 pstrcpy(fullname, directory);
3050 pstrcat(fullname, "/");
3051 pstrcat(fullname, dname);
3053 if(sys_lstat(fullname, &st) != 0)
3055 if(st.st_mode & S_IFDIR)
3057 if(lp_recursive_veto_delete(SNUM(cnum)))
3059 if(recursive_rmdir(fullname) != 0)
3062 if(sys_rmdir(fullname) != 0)
3065 else if(sys_unlink(fullname) != 0)
3069 /* Retry the rmdir */
3070 ok = (sys_rmdir(directory) == 0);
3080 DEBUG(3,("couldn't remove directory %s : %s\n",
3081 directory,strerror(errno)));
3086 if((errno == ENOENT) && bad_path)
3088 unix_ERR_class = ERRDOS;
3089 unix_ERR_code = ERRbadpath;
3091 return(UNIXERROR(ERRDOS,ERRbadpath));
3094 outsize = set_message(outbuf,0,0,True);
3096 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
3102 /*******************************************************************
3103 resolve wildcards in a filename rename
3104 ********************************************************************/
3105 static BOOL resolve_wildcards(char *name1,char *name2)
3107 fstring root1,root2;
3111 name1 = strrchr(name1,'/');
3112 name2 = strrchr(name2,'/');
3114 if (!name1 || !name2) return(False);
3116 fstrcpy(root1,name1);
3117 fstrcpy(root2,name2);
3118 p = strrchr(root1,'.');
3125 p = strrchr(root2,'.');
3157 pstrcpy(name2,root2);
3160 pstrcat(name2,ext2);
3166 /*******************************************************************
3167 check if a user is allowed to rename a file
3168 ********************************************************************/
3169 static BOOL can_rename(char *fname,int cnum)
3173 if (!CAN_WRITE(cnum)) return(False);
3175 if (sys_lstat(fname,&sbuf) != 0) return(False);
3176 if (!check_file_sharing(cnum,fname,True)) return(False);
3181 /****************************************************************************
3182 The guts of the rename command, split out so it may be called by the NT SMB
3184 ****************************************************************************/
3186 int rename_internals(char *inbuf, char *outbuf, char *name, char *newname, BOOL replace_if_exists)
3191 pstring newname_last_component;
3194 BOOL bad_path1 = False;
3195 BOOL bad_path2 = False;
3197 int error = ERRnoaccess;
3200 cnum = SVAL(inbuf,smb_tid);
3202 *directory = *mask = 0;
3204 unix_convert(name,cnum,0,&bad_path1);
3205 unix_convert(newname,cnum,newname_last_component,&bad_path2);
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) && ( ((case_preserve == True) && (is_short_name == False)) ||
3264 ((short_case_preserve == True) && (is_short_name == True))) &&
3265 strcsequal(directory, newname)) {
3266 pstring newname_modified_last_component;
3269 * Get the last component of the modified name.
3270 * Note that we guarantee that newname contains a '/'
3273 p = strrchr(newname,'/');
3274 pstrcpy(newname_modified_last_component,p+1);
3276 if(strcsequal(newname_modified_last_component,
3277 newname_last_component) == False) {
3279 * Replace the modified last component with
3282 pstrcpy(p+1, newname_last_component);
3286 if(replace_if_exists) {
3288 * NT SMB specific flag - rename can overwrite
3289 * file with the same name so don't check for
3292 if(resolve_wildcards(directory,newname) &&
3293 can_rename(directory,cnum) &&
3294 !sys_rename(directory,newname))
3297 if (resolve_wildcards(directory,newname) &&
3298 can_rename(directory,cnum) &&
3299 !file_exist(newname,NULL) &&
3300 !sys_rename(directory,newname))
3304 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3305 directory,newname));
3307 if (!count) exists = file_exist(directory,NULL);
3308 if (!count && exists && file_exist(newname,NULL)) {
3314 * Wildcards - process each file that matches.
3316 void *dirptr = NULL;
3320 if (check_name(directory,cnum))
3321 dirptr = OpenDir(cnum, directory, True);
3326 if (strequal(mask,"????????.???"))
3329 while ((dname = ReadDirName(dirptr))) {
3331 pstrcpy(fname,dname);
3333 if(!mask_match(fname, mask, case_sensitive, False))
3336 error = ERRnoaccess;
3337 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3338 if (!can_rename(fname,cnum)) {
3339 DEBUG(6,("rename %s refused\n", fname));
3342 pstrcpy(destname,newname);
3344 if (!resolve_wildcards(fname,destname)) {
3345 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3349 if (!replace_if_exists && file_exist(destname,NULL)) {
3350 DEBUG(6,("file_exist %s\n", destname));
3355 if (!sys_rename(fname,destname))
3357 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3365 return(ERROR(ERRDOS,error));
3367 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3368 unix_ERR_class = ERRDOS;
3369 unix_ERR_code = ERRbadpath;
3371 return(UNIXERROR(ERRDOS,error));
3378 /****************************************************************************
3380 ****************************************************************************/
3382 int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3388 pstrcpy(name,smb_buf(inbuf) + 1);
3389 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3391 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3393 outsize = rename_internals(inbuf, outbuf, name, newname, False);
3395 outsize = set_message(outbuf,0,0,True);
3400 /*******************************************************************
3401 copy a file as part of a reply_copy
3402 ******************************************************************/
3403 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3404 int count,BOOL target_is_directory)
3412 pstrcpy(dest,dest1);
3413 if (target_is_directory) {
3414 char *p = strrchr(src,'/');
3423 if (!file_exist(src,&st)) return(False);
3425 fnum1 = find_free_file();
3426 if (fnum1<0) return(False);
3427 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3428 1,0,0,&Access,&action);
3430 if (!Files[fnum1].open) {
3431 Files[fnum1].reserved = False;
3435 if (!target_is_directory && count)
3438 fnum2 = find_free_file();
3440 close_file(fnum1,False);
3443 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3444 ofun,st.st_mode,0,&Access,&action);
3446 if (!Files[fnum2].open) {
3447 close_file(fnum1,False);
3448 Files[fnum2].reserved = False;
3452 if ((ofun&3) == 1) {
3453 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3457 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3459 close_file(fnum1,False);
3460 close_file(fnum2,False);
3462 return(ret == st.st_size);
3467 /****************************************************************************
3468 reply to a file copy.
3469 ****************************************************************************/
3470 int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3476 pstring mask,newname;
3479 int error = ERRnoaccess;
3482 int tid2 = SVAL(inbuf,smb_vwv0);
3483 int ofun = SVAL(inbuf,smb_vwv1);
3484 int flags = SVAL(inbuf,smb_vwv2);
3485 BOOL target_is_directory=False;
3486 BOOL bad_path1 = False;
3487 BOOL bad_path2 = False;
3489 *directory = *mask = 0;
3491 cnum = SVAL(inbuf,smb_tid);
3493 pstrcpy(name,smb_buf(inbuf));
3494 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3496 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3499 /* can't currently handle inter share copies XXXX */
3500 DEBUG(3,("Rejecting inter-share copy\n"));
3501 return(ERROR(ERRSRV,ERRinvdevice));
3504 unix_convert(name,cnum,0,&bad_path1);
3505 unix_convert(newname,cnum,0,&bad_path2);
3507 target_is_directory = directory_exist(newname,NULL);
3509 if ((flags&1) && target_is_directory) {
3510 return(ERROR(ERRDOS,ERRbadfile));
3513 if ((flags&2) && !target_is_directory) {
3514 return(ERROR(ERRDOS,ERRbadpath));
3517 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3518 /* wants a tree copy! XXXX */
3519 DEBUG(3,("Rejecting tree copy\n"));
3520 return(ERROR(ERRSRV,ERRerror));
3523 p = strrchr(name,'/');
3525 pstrcpy(directory,"./");
3529 pstrcpy(directory,name);
3533 if (is_mangled(mask))
3534 check_mangled_cache( mask );
3536 has_wild = strchr(mask,'*') || strchr(mask,'?');
3539 pstrcat(directory,"/");
3540 pstrcat(directory,mask);
3541 if (resolve_wildcards(directory,newname) &&
3542 copy_file(directory,newname,cnum,ofun,
3543 count,target_is_directory)) count++;
3544 if (!count) exists = file_exist(directory,NULL);
3546 void *dirptr = NULL;
3550 if (check_name(directory,cnum))
3551 dirptr = OpenDir(cnum, directory, True);
3557 if (strequal(mask,"????????.???"))
3560 while ((dname = ReadDirName(dirptr)))
3563 pstrcpy(fname,dname);
3565 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3567 error = ERRnoaccess;
3568 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3569 pstrcpy(destname,newname);
3570 if (resolve_wildcards(fname,destname) &&
3571 copy_file(directory,newname,cnum,ofun,
3572 count,target_is_directory)) count++;
3573 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3581 return(ERROR(ERRDOS,error));
3584 if((errno == ENOENT) && (bad_path1 || bad_path2))
3586 unix_ERR_class = ERRDOS;
3587 unix_ERR_code = ERRbadpath;
3589 return(UNIXERROR(ERRDOS,error));
3593 outsize = set_message(outbuf,1,0,True);
3594 SSVAL(outbuf,smb_vwv0,count);
3601 /****************************************************************************
3603 ****************************************************************************/
3604 int reply_setdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3611 cnum = SVAL(inbuf,smb_tid);
3613 snum = Connections[cnum].service;
3614 if (!CAN_SETDIR(snum))
3615 return(ERROR(ERRDOS,ERRnoaccess));
3617 pstrcpy(newdir,smb_buf(inbuf) + 1);
3620 if (strlen(newdir) == 0)
3624 ok = directory_exist(newdir,NULL);
3626 string_set(&Connections[cnum].connectpath,newdir);
3630 return(ERROR(ERRDOS,ERRbadpath));
3632 outsize = set_message(outbuf,0,0,True);
3633 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3635 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3641 /****************************************************************************
3642 reply to a lockingX request
3643 ****************************************************************************/
3644 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3646 int fnum = GETFNUM(inbuf,smb_vwv2);
3647 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3649 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3651 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3652 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3653 uint32 count, offset;
3658 uint32 ecode=0, dummy2;
3659 int eclass=0, dummy1;
3661 cnum = SVAL(inbuf,smb_tid);
3663 CHECK_FNUM(fnum,cnum);
3666 data = smb_buf(inbuf);
3668 /* Check if this is an oplock break on a file
3669 we have granted an oplock on.
3671 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3674 files_struct *fsp = &Files[fnum];
3675 uint32 dev = fsp->fd_ptr->dev;
3676 uint32 inode = fsp->fd_ptr->inode;
3678 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3681 * Make sure we have granted an oplock on this file.
3683 if(!fsp->granted_oplock)
3685 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3686 no oplock granted on this file.\n", fnum));
3687 return ERROR(ERRDOS,ERRlock);
3690 /* Remove the oplock flag from the sharemode. */
3691 lock_share_entry(fsp->cnum, dev, inode, &token);
3692 if(remove_share_oplock( fnum, token)==False) {
3693 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3694 dev = %x, inode = %x\n",
3696 unlock_share_entry(fsp->cnum, dev, inode, token);
3698 unlock_share_entry(fsp->cnum, dev, inode, token);
3700 /* Clear the granted flag and return. */
3701 fsp->granted_oplock = False;
3704 /* if this is a pure oplock break request then don't send a reply */
3705 if (num_locks == 0 && num_ulocks == 0)
3707 /* Sanity check - ensure a pure oplock break is not a
3709 if(CVAL(inbuf,smb_vwv0) != 0xff)
3710 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3711 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3716 /* Data now points at the beginning of the list
3717 of smb_unlkrng structs */
3718 for(i = 0; i < (int)num_ulocks; i++) {
3719 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3720 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3721 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3722 return ERROR(eclass,ecode);
3725 /* Now do any requested locks */
3726 data += 10*num_ulocks;
3727 /* Data now points at the beginning of the list
3728 of smb_lkrng structs */
3729 for(i = 0; i < (int)num_locks; i++) {
3730 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3731 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3732 if(!do_lock(fnum,cnum,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3737 /* If any of the above locks failed, then we must unlock
3738 all of the previous locks (X/Open spec). */
3739 if(i != num_locks && num_locks != 0) {
3740 for(; i >= 0; i--) {
3741 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3742 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3743 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3745 return ERROR(eclass,ecode);
3748 set_message(outbuf,2,0,True);
3750 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3751 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3755 return chain_reply(inbuf,outbuf,length,bufsize);
3759 /****************************************************************************
3760 reply to a SMBreadbmpx (read block multiplex) request
3761 ****************************************************************************/
3762 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3769 int outsize, mincount, maxcount;
3774 /* this function doesn't seem to work - disable by default */
3776 return(ERROR(ERRSRV,ERRuseSTD));
3778 outsize = set_message(outbuf,8,0,True);
3780 cnum = SVAL(inbuf,smb_tid);
3781 fnum = GETFNUM(inbuf,smb_vwv0);
3783 CHECK_FNUM(fnum,cnum);
3787 startpos = IVAL(inbuf,smb_vwv1);
3788 maxcount = SVAL(inbuf,smb_vwv3);
3789 mincount = SVAL(inbuf,smb_vwv4);
3791 data = smb_buf(outbuf);
3792 pad = ((long)data)%4;
3793 if (pad) pad = 4 - pad;
3796 max_per_packet = bufsize-(outsize+pad);
3800 if (is_locked(fnum,cnum,maxcount,startpos, F_RDLCK))
3801 return(ERROR(ERRDOS,ERRlock));
3805 int N = MIN(max_per_packet,tcount-total_read);
3807 nread = read_file(fnum,data,startpos,N);
3809 if (nread <= 0) nread = 0;
3812 tcount = total_read + nread;
3814 set_message(outbuf,8,nread,False);
3815 SIVAL(outbuf,smb_vwv0,startpos);
3816 SSVAL(outbuf,smb_vwv2,tcount);
3817 SSVAL(outbuf,smb_vwv6,nread);
3818 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3820 send_smb(Client,outbuf);
3822 total_read += nread;
3825 while (total_read < tcount);
3831 /****************************************************************************
3832 reply to a SMBwritebmpx (write block multiplex primary) request
3833 ****************************************************************************/
3834 int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3836 int cnum,numtowrite,fnum;
3840 int tcount, write_through, smb_doff;
3843 cnum = SVAL(inbuf,smb_tid);
3844 fnum = GETFNUM(inbuf,smb_vwv0);
3846 CHECK_FNUM(fnum,cnum);
3850 tcount = SVAL(inbuf,smb_vwv1);
3851 startpos = IVAL(inbuf,smb_vwv3);
3852 write_through = BITSETW(inbuf+smb_vwv7,0);
3853 numtowrite = SVAL(inbuf,smb_vwv10);
3854 smb_doff = SVAL(inbuf,smb_vwv11);
3856 data = smb_base(inbuf) + smb_doff;
3858 /* If this fails we need to send an SMBwriteC response,
3859 not an SMBwritebmpx - set this up now so we don't forget */
3860 CVAL(outbuf,smb_com) = SMBwritec;
3862 if (is_locked(fnum,cnum,tcount,startpos,F_WRLCK))
3863 return(ERROR(ERRDOS,ERRlock));
3865 seek_file(fnum,startpos);
3866 nwritten = write_file(fnum,data,numtowrite);
3868 if(lp_syncalways(SNUM(cnum)) || write_through)
3869 sync_file(cnum,fnum);
3871 if(nwritten < numtowrite)
3872 return(UNIXERROR(ERRHRD,ERRdiskfull));
3874 /* If the maximum to be written to this file
3875 is greater than what we just wrote then set
3876 up a secondary struct to be attached to this
3877 fd, we will use this to cache error messages etc. */
3878 if(tcount > nwritten)
3880 write_bmpx_struct *wbms;
3881 if(Files[fnum].wbmpx_ptr != NULL)
3882 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3884 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3887 DEBUG(0,("Out of memory in reply_readmpx\n"));
3888 return(ERROR(ERRSRV,ERRnoresource));
3890 wbms->wr_mode = write_through;
3891 wbms->wr_discard = False; /* No errors yet */
3892 wbms->wr_total_written = nwritten;
3893 wbms->wr_errclass = 0;
3895 Files[fnum].wbmpx_ptr = wbms;
3898 /* We are returning successfully, set the message type back to
3900 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3902 outsize = set_message(outbuf,1,0,True);
3904 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3906 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3907 timestring(),fnum,cnum,numtowrite,nwritten));
3909 if (write_through && tcount==nwritten) {
3910 /* we need to send both a primary and a secondary response */
3911 smb_setlen(outbuf,outsize - 4);
3912 send_smb(Client,outbuf);
3914 /* now the secondary */
3915 outsize = set_message(outbuf,1,0,True);
3916 CVAL(outbuf,smb_com) = SMBwritec;
3917 SSVAL(outbuf,smb_vwv0,nwritten);
3924 /****************************************************************************
3925 reply to a SMBwritebs (write block multiplex secondary) request
3926 ****************************************************************************/
3927 int reply_writebs(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3929 int cnum,numtowrite,fnum;
3933 int tcount, write_through, smb_doff;
3935 write_bmpx_struct *wbms;
3936 BOOL send_response = False;
3938 cnum = SVAL(inbuf,smb_tid);
3939 fnum = GETFNUM(inbuf,smb_vwv0);
3940 CHECK_FNUM(fnum,cnum);
3943 tcount = SVAL(inbuf,smb_vwv1);
3944 startpos = IVAL(inbuf,smb_vwv2);
3945 numtowrite = SVAL(inbuf,smb_vwv6);
3946 smb_doff = SVAL(inbuf,smb_vwv7);
3948 data = smb_base(inbuf) + smb_doff;
3950 /* We need to send an SMBwriteC response, not an SMBwritebs */
3951 CVAL(outbuf,smb_com) = SMBwritec;
3953 /* This fd should have an auxiliary struct attached,
3954 check that it does */
3955 wbms = Files[fnum].wbmpx_ptr;
3956 if(!wbms) return(-1);
3958 /* If write through is set we can return errors, else we must
3960 write_through = wbms->wr_mode;
3962 /* Check for an earlier error */
3963 if(wbms->wr_discard)
3964 return -1; /* Just discard the packet */
3966 seek_file(fnum,startpos);
3967 nwritten = write_file(fnum,data,numtowrite);
3969 if(lp_syncalways(SNUM(cnum)) || write_through)
3970 sync_file(cnum,fnum);
3972 if (nwritten < numtowrite)
3975 /* We are returning an error - we can delete the aux struct */
3976 if (wbms) free((char *)wbms);
3977 Files[fnum].wbmpx_ptr = NULL;
3978 return(ERROR(ERRHRD,ERRdiskfull));
3980 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3983 /* Increment the total written, if this matches tcount
3984 we can discard the auxiliary struct (hurrah !) and return a writeC */
3985 wbms->wr_total_written += nwritten;
3986 if(wbms->wr_total_written >= tcount)
3988 if (write_through) {
3989 outsize = set_message(outbuf,1,0,True);
3990 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3991 send_response = True;
3995 Files[fnum].wbmpx_ptr = NULL;
4005 /****************************************************************************
4006 reply to a SMBsetattrE
4007 ****************************************************************************/
4008 int reply_setattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4011 struct utimbuf unix_times;
4014 outsize = set_message(outbuf,0,0,True);
4016 cnum = SVAL(inbuf,smb_tid);
4017 fnum = GETFNUM(inbuf,smb_vwv0);
4019 CHECK_FNUM(fnum,cnum);
4022 /* Convert the DOS times into unix times. Ignore create
4023 time as UNIX can't set this.
4025 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4026 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4029 * Patch from Ray Frush <frush@engr.colostate.edu>
4030 * Sometimes times are sent as zero - ignore them.
4033 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4035 /* Ignore request */
4036 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
4037 not setting timestamps of 0\n",
4038 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
4041 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4043 /* set modify time = to access time if modify time was 0 */
4044 unix_times.modtime = unix_times.actime;
4047 /* Set the date on this file */
4048 if(file_utime(cnum, Files[fnum].name, &unix_times))
4049 return(ERROR(ERRDOS,ERRnoaccess));
4051 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
4052 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
4058 /****************************************************************************
4059 reply to a SMBgetattrE
4060 ****************************************************************************/
4061 int reply_getattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4068 outsize = set_message(outbuf,11,0,True);
4070 cnum = SVAL(inbuf,smb_tid);
4071 fnum = GETFNUM(inbuf,smb_vwv0);
4073 CHECK_FNUM(fnum,cnum);
4076 /* Do an fstat on this file */
4077 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
4078 return(UNIXERROR(ERRDOS,ERRnoaccess));
4080 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
4082 /* Convert the times into dos times. Set create
4083 date to be last modify date as UNIX doesn't save
4085 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
4086 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4087 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4090 SIVAL(outbuf,smb_vwv6,0);
4091 SIVAL(outbuf,smb_vwv8,0);
4095 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
4096 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
4098 SSVAL(outbuf,smb_vwv10, mode);
4100 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));