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);
235 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
237 if (connection_num < 0)
238 return(connection_error(inbuf,outbuf,connection_num));
240 outsize = set_message(outbuf,2,0,True);
241 SSVAL(outbuf,smb_vwv0,max_recv);
242 SSVAL(outbuf,smb_vwv1,connection_num);
243 SSVAL(outbuf,smb_tid,connection_num);
245 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
251 /****************************************************************************
252 reply to a tcon and X
253 ****************************************************************************/
254 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
261 uint16 vuid = SVAL(inbuf,smb_uid);
262 int passlen = SVAL(inbuf,smb_vwv3);
264 *service = *user = *password = *devicename = 0;
266 /* we might have to close an old one */
267 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
268 close_cnum(SVAL(inbuf,smb_tid),vuid);
270 if (passlen > MAX_PASS_LEN) {
271 overflow_attack(passlen);
277 memcpy(password,smb_buf(inbuf),passlen);
279 path = smb_buf(inbuf) + passlen;
282 if (strequal(password," "))
284 passlen = strlen(password);
287 fstrcpy(service,path+2);
288 p = strchr(service,'\\');
290 return(ERROR(ERRSRV,ERRinvnetname));
292 fstrcpy(service,p+1);
293 p = strchr(service,'%');
299 StrnCpy(devicename,path + strlen(path) + 1,6);
300 DEBUG(4,("Got device type %s\n",devicename));
303 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
305 if (connection_num < 0)
306 return(connection_error(inbuf,outbuf,connection_num));
308 if (Protocol < PROTOCOL_NT1)
310 set_message(outbuf,2,strlen(devicename)+1,True);
311 strcpy(smb_buf(outbuf),devicename);
315 char *fsname = FSTYPE_STRING;
318 set_message(outbuf,3,3,True);
321 strcpy(p,devicename); p = skip_string(p,1); /* device name */
322 strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
324 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
326 SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
329 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
331 /* set the incoming and outgoing tid to the just created one */
332 SSVAL(inbuf,smb_tid,connection_num);
333 SSVAL(outbuf,smb_tid,connection_num);
335 return chain_reply(inbuf,outbuf,length,bufsize);
339 /****************************************************************************
340 reply to an unknown type
341 ****************************************************************************/
342 int reply_unknown(char *inbuf,char *outbuf)
346 cnum = SVAL(inbuf,smb_tid);
347 type = CVAL(inbuf,smb_com);
349 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
354 return(ERROR(ERRSRV,ERRunknownsmb));
358 /****************************************************************************
360 ****************************************************************************/
361 int reply_ioctl(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
363 DEBUG(3,("ignoring ioctl\n"));
365 /* we just say it succeeds and hope its all OK.
366 some day it would be nice to interpret them individually */
367 return set_message(outbuf,1,0,True);
369 return(ERROR(ERRSRV,ERRnosupport));
373 /****************************************************************************
374 always return an error: it's just a matter of which one...
375 ****************************************************************************/
376 static int session_trust_account(char *inbuf, char *outbuf, char *user,
377 char *smb_passwd, int smb_passlen,
378 char *smb_nt_passwd, int smb_nt_passlen)
380 struct smb_passwd *sam_trust_acct = NULL; /* check if trust account exists */
381 if (lp_security() == SEC_USER)
383 sam_trust_acct = getsampwnam(user);
387 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
388 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
389 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
392 if (sam_trust_acct == NULL)
394 /* lkclXXXX: workstation entry doesn't exist */
395 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
396 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
397 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
401 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
403 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
404 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
405 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
408 if (!smb_password_ok(sam_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
410 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
411 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
412 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
415 if (IS_BITS_SET_ALL(sam_trust_acct->acct_ctrl, ACB_DOMTRUST))
417 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
418 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
419 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
422 if (IS_BITS_SET_ALL(sam_trust_acct->acct_ctrl, ACB_SVRTRUST))
424 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
425 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
426 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
429 if (IS_BITS_SET_ALL(sam_trust_acct->acct_ctrl, ACB_WSTRUST))
431 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
432 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
433 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
437 /* don't know what to do: indicate logon failure */
438 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
439 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
443 /****************************************************************************
444 reply to a session setup command
445 ****************************************************************************/
446 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
455 int smb_apasslen = 0;
457 int smb_ntpasslen = 0;
458 pstring smb_ntpasswd;
459 BOOL valid_nt_password = False;
462 static BOOL done_sesssetup = False;
463 BOOL doencrypt = SMBENCRYPT();
469 smb_bufsize = SVAL(inbuf,smb_vwv2);
470 smb_mpxmax = SVAL(inbuf,smb_vwv3);
471 smb_vc_num = SVAL(inbuf,smb_vwv4);
472 smb_sesskey = IVAL(inbuf,smb_vwv5);
474 if (Protocol < PROTOCOL_NT1) {
475 smb_apasslen = SVAL(inbuf,smb_vwv7);
476 if (smb_apasslen > MAX_PASS_LEN)
478 overflow_attack(smb_apasslen);
481 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
482 smb_apasswd[smb_apasslen] = 0;
483 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
485 if (!doencrypt && (lp_security() != SEC_SERVER)) {
486 smb_apasslen = strlen(smb_apasswd);
489 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
490 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
491 uint32 client_caps = IVAL(inbuf,smb_vwv11);
492 enum remote_arch_types ra_type = get_remote_arch();
494 char *p = smb_buf(inbuf);
496 /* client_caps is used as final determination if client is NT or Win95.
497 This is needed to return the correct error codes in some
501 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
503 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
504 set_remote_arch( RA_WINNT);
506 set_remote_arch( RA_WIN95);
509 if (passlen1 != 24 && passlen2 != 24)
512 if (passlen1 > MAX_PASS_LEN) {
513 overflow_attack(passlen1);
516 passlen1 = MIN(passlen1, MAX_PASS_LEN);
517 passlen2 = MIN(passlen2, MAX_PASS_LEN);
519 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
520 /* Save the lanman2 password and the NT md4 password. */
521 smb_apasslen = passlen1;
522 memcpy(smb_apasswd,p,smb_apasslen);
523 smb_apasswd[smb_apasslen] = 0;
524 smb_ntpasslen = passlen2;
525 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
526 smb_ntpasswd[smb_ntpasslen] = 0;
528 /* both Win95 and WinNT stuff up the password lengths for
529 non-encrypting systems. Uggh.
531 if passlen1==24 its a win95 system, and its setting the
532 password length incorrectly. Luckily it still works with the
533 default code because Win95 will null terminate the password
536 if passlen1>0 and passlen2>0 then maybe its a NT box and its
537 setting passlen2 to some random value which really stuffs
538 things up. we need to fix that one. */
539 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
543 /* we use the first password that they gave */
544 smb_apasslen = passlen1;
545 StrnCpy(smb_apasswd,p,smb_apasslen);
547 /* trim the password */
548 smb_apasslen = strlen(smb_apasswd);
550 /* wfwg sometimes uses a space instead of a null */
551 if (strequal(smb_apasswd," ")) {
557 p += passlen1 + passlen2;
558 fstrcpy(user,p); p = skip_string(p,1);
561 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
562 domain,skip_string(p,1),skip_string(p,2)));
566 DEBUG(3,("sesssetupX:name=[%s]\n",user));
568 /* If name ends in $ then I think it's asking about whether a */
569 /* computer with that name (minus the $) has access. For now */
570 /* say yes to everything ending in $. */
571 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
573 return session_trust_account(inbuf, outbuf, user,
574 smb_apasswd, smb_apasslen,
575 smb_ntpasswd, smb_ntpasslen);
578 /* If no username is sent use the guest account */
581 strcpy(user,lp_guestaccount(-1));
582 /* If no user and no password then set guest flag. */
583 if( *smb_apasswd == 0)
590 * In share level security, only overwrite sesssetup_use if
591 * it's a non null-session share. Helps keep %U and %G
595 if((lp_security() != SEC_SHARE) || *user)
596 strcpy(sesssetup_user,user);
598 reload_services(True);
600 add_session_user(user);
602 /* Check if the given username was the guest user with no password.
603 We need to do this check after add_session_user() as that
604 call can potentially change the username (via map_user).
607 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
610 if (!guest && !(lp_security() == SEC_SERVER &&
611 server_validate(user, domain,
612 smb_apasswd, smb_apasslen,
613 smb_ntpasswd, smb_ntpasslen)) &&
614 !(lp_security() == SEC_DOMAIN &&
615 domain_client_validate(user, domain,
616 smb_apasswd, smb_apasslen,
617 smb_ntpasswd, smb_ntpasslen)) &&
618 !check_hosts_equiv(user))
621 /* now check if it's a valid username/password */
622 /* If an NT password was supplied try and validate with that
623 first. This is superior as the passwords are mixed case
624 128 length unicode */
627 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
628 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
630 valid_nt_password = True;
632 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
634 if (lp_security() >= SEC_USER) {
635 #if (GUEST_SESSSETUP == 0)
636 return(ERROR(ERRSRV,ERRbadpw));
638 #if (GUEST_SESSSETUP == 1)
639 if (Get_Pwnam(user,True))
640 return(ERROR(ERRSRV,ERRbadpw));
643 if (*smb_apasswd || !Get_Pwnam(user,True))
644 strcpy(user,lp_guestaccount(-1));
645 DEBUG(3,("Registered username %s for guest access\n",user));
650 if (!Get_Pwnam(user,True)) {
651 DEBUG(3,("No such user %s - using guest account\n",user));
652 strcpy(user,lp_guestaccount(-1));
656 if (!strequal(user,lp_guestaccount(-1)) &&
657 lp_servicenumber(user) < 0)
659 int homes = lp_servicenumber(HOMES_NAME);
660 char *home = get_home_dir(user);
661 if (homes >= 0 && home)
662 lp_add_home(user,homes,home);
666 /* it's ok - setup a reply */
667 if (Protocol < PROTOCOL_NT1) {
668 set_message(outbuf,3,0,True);
671 set_message(outbuf,3,3,True);
673 strcpy(p,"Unix"); p = skip_string(p,1);
674 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
675 strcpy(p,global_myworkgroup); p = skip_string(p,1);
676 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
677 /* perhaps grab OS version here?? */
680 /* Set the correct uid in the outgoing and incoming packets
681 We will use this on future requests to determine which
682 user we should become.
685 struct passwd *pw = Get_Pwnam(user,False);
687 DEBUG(1,("Username %s is invalid on this system\n",user));
688 return(ERROR(ERRSRV,ERRbadpw));
695 SSVAL(outbuf,smb_vwv2,1);
697 /* register the name and uid as being validated, so further connections
698 to a uid can get through without a password, on the same VC */
699 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
701 SSVAL(outbuf,smb_uid,sess_vuid);
702 SSVAL(inbuf,smb_uid,sess_vuid);
705 max_send = MIN(max_send,smb_bufsize);
707 DEBUG(6,("Client requested max send size of %d\n", max_send));
709 done_sesssetup = True;
711 return chain_reply(inbuf,outbuf,length,bufsize);
715 /****************************************************************************
717 ****************************************************************************/
718 int reply_chkpth(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
724 BOOL bad_path = False;
726 cnum = SVAL(inbuf,smb_tid);
728 pstrcpy(name,smb_buf(inbuf) + 1);
729 unix_convert(name,cnum,0,&bad_path);
731 mode = SVAL(inbuf,smb_vwv0);
733 if (check_name(name,cnum))
734 ok = directory_exist(name,NULL);
738 /* We special case this - as when a Windows machine
739 is parsing a path is steps through the components
740 one at a time - if a component fails it expects
741 ERRbadpath, not ERRbadfile.
745 unix_ERR_class = ERRDOS;
746 unix_ERR_code = ERRbadpath;
750 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
751 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
752 (get_remote_arch() == RA_WINNT))
754 unix_ERR_class = ERRDOS;
755 unix_ERR_code = ERRbaddirectory;
759 return(UNIXERROR(ERRDOS,ERRbadpath));
762 outsize = set_message(outbuf,0,0,True);
764 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
770 /****************************************************************************
772 ****************************************************************************/
773 int reply_getatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
783 BOOL bad_path = False;
785 cnum = SVAL(inbuf,smb_tid);
787 pstrcpy(fname,smb_buf(inbuf) + 1);
788 unix_convert(fname,cnum,0,&bad_path);
790 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
791 under WfWg - weird! */
794 mode = aHIDDEN | aDIR;
795 if (!CAN_WRITE(cnum)) mode |= aRONLY;
801 if (check_name(fname,cnum))
803 if (sys_stat(fname,&sbuf) == 0)
805 mode = dos_mode(cnum,fname,&sbuf);
807 mtime = sbuf.st_mtime;
813 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
818 if((errno == ENOENT) && bad_path)
820 unix_ERR_class = ERRDOS;
821 unix_ERR_code = ERRbadpath;
824 return(UNIXERROR(ERRDOS,ERRbadfile));
827 outsize = set_message(outbuf,10,0,True);
829 SSVAL(outbuf,smb_vwv0,mode);
830 if(lp_dos_filetime_resolution(SNUM(cnum)) )
831 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
833 put_dos_date3(outbuf,smb_vwv1,mtime);
834 SIVAL(outbuf,smb_vwv3,size);
836 if (Protocol >= PROTOCOL_NT1) {
837 char *p = strrchr(fname,'/');
838 uint16 flg2 = SVAL(outbuf,smb_flg2);
840 if (!is_8_3(fname, True))
841 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
844 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
850 /****************************************************************************
852 ****************************************************************************/
853 int reply_setatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
861 BOOL bad_path = False;
863 cnum = SVAL(inbuf,smb_tid);
865 pstrcpy(fname,smb_buf(inbuf) + 1);
866 unix_convert(fname,cnum,0,&bad_path);
868 mode = SVAL(inbuf,smb_vwv0);
869 mtime = make_unix_date3(inbuf+smb_vwv1);
871 if (directory_exist(fname,NULL))
873 if (check_name(fname,cnum))
874 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
876 ok = set_filetime(cnum,fname,mtime);
880 if((errno == ENOENT) && bad_path)
882 unix_ERR_class = ERRDOS;
883 unix_ERR_code = ERRbadpath;
886 return(UNIXERROR(ERRDOS,ERRnoaccess));
889 outsize = set_message(outbuf,0,0,True);
891 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
897 /****************************************************************************
899 ****************************************************************************/
900 int reply_dskattr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
904 int dfree,dsize,bsize;
906 cnum = SVAL(inbuf,smb_tid);
908 sys_disk_free(".",&bsize,&dfree,&dsize);
910 outsize = set_message(outbuf,5,0,True);
912 SSVAL(outbuf,smb_vwv0,dsize);
913 SSVAL(outbuf,smb_vwv1,bsize/512);
914 SSVAL(outbuf,smb_vwv2,512);
915 SSVAL(outbuf,smb_vwv3,dfree);
917 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
923 /****************************************************************************
925 Can be called from SMBsearch, SMBffirst or SMBfunique.
926 ****************************************************************************/
927 int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
938 BOOL finished = False;
947 BOOL check_descend = False;
948 BOOL expect_close = False;
949 BOOL can_open = True;
950 BOOL bad_path = False;
952 *mask = *directory = *fname = 0;
954 /* If we were called as SMBffirst then we must expect close. */
955 if(CVAL(inbuf,smb_com) == SMBffirst)
958 cnum = SVAL(inbuf,smb_tid);
960 outsize = set_message(outbuf,1,3,True);
961 maxentries = SVAL(inbuf,smb_vwv0);
962 dirtype = SVAL(inbuf,smb_vwv1);
963 path = smb_buf(inbuf) + 1;
964 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
967 /* dirtype &= ~aDIR; */
969 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
976 pstrcpy(directory,smb_buf(inbuf)+1);
977 pstrcpy(dir2,smb_buf(inbuf)+1);
978 unix_convert(directory,cnum,0,&bad_path);
981 if (!check_name(directory,cnum))
984 p = strrchr(dir2,'/');
996 p = strrchr(directory,'/');
1002 if (strlen(directory) == 0)
1003 strcpy(directory,"./");
1005 CVAL(status,0) = dirtype;
1009 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1010 memcpy(mask,status+1,11);
1012 dirtype = CVAL(status,0) & 0x1F;
1013 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
1014 if (!Connections[cnum].dirptr)
1016 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
1017 if (!case_sensitive)
1021 /* turn strings of spaces into a . */
1023 trim_string(mask,NULL," ");
1024 if ((p = strrchr(mask,' ')))
1029 trim_string(mask,NULL," ");
1036 for (p=mask; *p; p++)
1038 if (*p != '?' && *p != '*' && !isdoschar(*p))
1040 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1046 if (!strchr(mask,'.') && strlen(mask)>8)
1049 fstrcpy(tmp,&mask[8]);
1055 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1059 p = smb_buf(outbuf) + 3;
1063 if (status_len == 0)
1065 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
1070 if((errno == ENOENT) && bad_path)
1072 unix_ERR_class = ERRDOS;
1073 unix_ERR_code = ERRbadpath;
1075 return (UNIXERROR(ERRDOS,ERRnofids));
1077 return(ERROR(ERRDOS,ERRnofids));
1081 DEBUG(4,("dptr_num is %d\n",dptr_num));
1085 if ((dirtype&0x1F) == aVOLID)
1087 memcpy(p,status,21);
1088 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
1089 dptr_fill(p+12,dptr_num);
1090 if (dptr_zero(p+12) && (status_len==0))
1094 p += DIR_STRUCT_SIZE;
1098 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
1099 if (in_list(Connections[cnum].dirpath,
1100 lp_dontdescend(SNUM(cnum)),True))
1101 check_descend = True;
1103 for (i=numentries;(i<maxentries) && !finished;i++)
1106 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
1109 memcpy(p,status,21);
1110 make_dir_struct(p,mask,fname,size,mode,date);
1111 dptr_fill(p+12,dptr_num);
1114 p += DIR_STRUCT_SIZE;
1123 if (numentries == 0 || !ok)
1125 CVAL(outbuf,smb_rcls) = ERRDOS;
1126 SSVAL(outbuf,smb_err,ERRnofiles);
1129 /* If we were called as SMBffirst with smb_search_id == NULL
1130 and no entries were found then return error and close dirptr
1133 if(ok && expect_close && numentries == 0 && status_len == 0)
1135 CVAL(outbuf,smb_rcls) = ERRDOS;
1136 SSVAL(outbuf,smb_err,ERRnofiles);
1137 /* Also close the dptr - we know it's gone */
1138 dptr_close(dptr_num);
1141 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1142 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1143 dptr_close(dptr_num);
1145 SSVAL(outbuf,smb_vwv0,numentries);
1146 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1147 CVAL(smb_buf(outbuf),0) = 5;
1148 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1150 if (Protocol >= PROTOCOL_NT1) {
1151 uint16 flg2 = SVAL(outbuf,smb_flg2);
1152 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1155 outsize += DIR_STRUCT_SIZE*numentries;
1156 smb_setlen(outbuf,outsize - 4);
1158 if ((! *directory) && dptr_path(dptr_num))
1159 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1161 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1163 smb_fn_name(CVAL(inbuf,smb_com)),
1164 mask,directory,cnum,dirtype,numentries,maxentries));
1170 /****************************************************************************
1171 reply to a fclose (stop directory search)
1172 ****************************************************************************/
1173 int reply_fclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1182 cnum = SVAL(inbuf,smb_tid);
1184 outsize = set_message(outbuf,1,0,True);
1185 path = smb_buf(inbuf) + 1;
1186 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1189 if (status_len == 0)
1190 return(ERROR(ERRSRV,ERRsrverror));
1192 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1194 if(dptr_fetch(status+12,&dptr_num)) {
1195 /* Close the dptr - we know it's gone */
1196 dptr_close(dptr_num);
1199 SSVAL(outbuf,smb_vwv0,0);
1201 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1207 /****************************************************************************
1209 ****************************************************************************/
1210 int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1223 BOOL bad_path = False;
1225 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1227 cnum = SVAL(inbuf,smb_tid);
1229 share_mode = SVAL(inbuf,smb_vwv0);
1231 pstrcpy(fname,smb_buf(inbuf)+1);
1232 unix_convert(fname,cnum,0,&bad_path);
1234 fnum = find_free_file();
1236 return(ERROR(ERRSRV,ERRnofids));
1238 if (!check_name(fname,cnum))
1240 if((errno == ENOENT) && bad_path)
1242 unix_ERR_class = ERRDOS;
1243 unix_ERR_code = ERRbadpath;
1245 Files[fnum].reserved = False;
1246 return(UNIXERROR(ERRDOS,ERRnoaccess));
1249 unixmode = unix_mode(cnum,aARCH);
1251 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1252 oplock_request,&rmode,NULL);
1258 if((errno == ENOENT) && bad_path)
1260 unix_ERR_class = ERRDOS;
1261 unix_ERR_code = ERRbadpath;
1263 Files[fnum].reserved = False;
1264 return(UNIXERROR(ERRDOS,ERRnoaccess));
1267 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1268 close_file(fnum,False);
1269 return(ERROR(ERRDOS,ERRnoaccess));
1272 size = sbuf.st_size;
1273 fmode = dos_mode(cnum,fname,&sbuf);
1274 mtime = sbuf.st_mtime;
1277 DEBUG(3,("attempt to open a directory %s\n",fname));
1278 close_file(fnum,False);
1279 return(ERROR(ERRDOS,ERRnoaccess));
1282 outsize = set_message(outbuf,7,0,True);
1283 SSVAL(outbuf,smb_vwv0,fnum);
1284 SSVAL(outbuf,smb_vwv1,fmode);
1285 if(lp_dos_filetime_resolution(SNUM(cnum)) )
1286 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1288 put_dos_date3(outbuf,smb_vwv2,mtime);
1289 SIVAL(outbuf,smb_vwv4,size);
1290 SSVAL(outbuf,smb_vwv6,rmode);
1292 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1293 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1296 if(fsp->granted_oplock)
1297 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1302 /****************************************************************************
1303 reply to an open and X
1304 ****************************************************************************/
1305 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1308 int cnum = SVAL(inbuf,smb_tid);
1310 int smb_mode = SVAL(inbuf,smb_vwv3);
1311 int smb_attr = SVAL(inbuf,smb_vwv5);
1312 /* Breakout the oplock request bits so we can set the
1313 reply bits separately. */
1314 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1315 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1316 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1318 int open_flags = SVAL(inbuf,smb_vwv2);
1319 int smb_sattr = SVAL(inbuf,smb_vwv4);
1320 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1322 int smb_ofun = SVAL(inbuf,smb_vwv8);
1324 int size=0,fmode=0,mtime=0,rmode=0;
1327 BOOL bad_path = False;
1330 /* If it's an IPC, pass off the pipe handler. */
1332 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1334 /* XXXX we need to handle passed times, sattr and flags */
1336 pstrcpy(fname,smb_buf(inbuf));
1337 unix_convert(fname,cnum,0,&bad_path);
1339 fnum = find_free_file();
1341 return(ERROR(ERRSRV,ERRnofids));
1343 if (!check_name(fname,cnum))
1345 if((errno == ENOENT) && bad_path)
1347 unix_ERR_class = ERRDOS;
1348 unix_ERR_code = ERRbadpath;
1350 Files[fnum].reserved = False;
1351 return(UNIXERROR(ERRDOS,ERRnoaccess));
1354 unixmode = unix_mode(cnum,smb_attr | aARCH);
1356 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1357 oplock_request, &rmode,&smb_action);
1363 if((errno == ENOENT) && bad_path)
1365 unix_ERR_class = ERRDOS;
1366 unix_ERR_code = ERRbadpath;
1368 Files[fnum].reserved = False;
1369 return(UNIXERROR(ERRDOS,ERRnoaccess));
1372 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1373 close_file(fnum,False);
1374 return(ERROR(ERRDOS,ERRnoaccess));
1377 size = sbuf.st_size;
1378 fmode = dos_mode(cnum,fname,&sbuf);
1379 mtime = sbuf.st_mtime;
1381 close_file(fnum,False);
1382 return(ERROR(ERRDOS,ERRnoaccess));
1385 /* If the caller set the extended oplock request bit
1386 and we granted one (by whatever means) - set the
1387 correct bit for extended oplock reply.
1390 if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1391 smb_action |= EXTENDED_OPLOCK_GRANTED;
1394 if(ex_oplock_request && fsp->granted_oplock) {
1395 smb_action |= EXTENDED_OPLOCK_GRANTED;
1398 /* If the caller set the core oplock request bit
1399 and we granted one (by whatever means) - set the
1400 correct bit for core oplock reply.
1403 if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1404 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1407 if(core_oplock_request && fsp->granted_oplock) {
1408 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1411 set_message(outbuf,15,0,True);
1412 SSVAL(outbuf,smb_vwv2,fnum);
1413 SSVAL(outbuf,smb_vwv3,fmode);
1414 if(lp_dos_filetime_resolution(SNUM(cnum)) )
1415 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1417 put_dos_date3(outbuf,smb_vwv4,mtime);
1418 SIVAL(outbuf,smb_vwv6,size);
1419 SSVAL(outbuf,smb_vwv8,rmode);
1420 SSVAL(outbuf,smb_vwv11,smb_action);
1424 return chain_reply(inbuf,outbuf,length,bufsize);
1428 /****************************************************************************
1429 reply to a SMBulogoffX
1430 ****************************************************************************/
1431 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1433 uint16 vuid = SVAL(inbuf,smb_uid);
1434 user_struct *vuser = get_valid_user_struct(vuid);
1437 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1440 /* in user level security we are supposed to close any files
1441 open by this user */
1442 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1444 for (i=0;i<MAX_OPEN_FILES;i++)
1445 if ((Files[i].vuid == vuid) && Files[i].open) {
1446 close_file(i,False);
1450 invalidate_vuid(vuid);
1452 set_message(outbuf,2,0,True);
1454 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1456 return chain_reply(inbuf,outbuf,length,bufsize);
1460 /****************************************************************************
1461 reply to a mknew or a create
1462 ****************************************************************************/
1463 int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1472 BOOL bad_path = False;
1474 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1476 com = SVAL(inbuf,smb_com);
1477 cnum = SVAL(inbuf,smb_tid);
1479 createmode = SVAL(inbuf,smb_vwv0);
1480 pstrcpy(fname,smb_buf(inbuf)+1);
1481 unix_convert(fname,cnum,0,&bad_path);
1483 if (createmode & aVOLID)
1485 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1488 unixmode = unix_mode(cnum,createmode);
1490 fnum = find_free_file();
1492 return(ERROR(ERRSRV,ERRnofids));
1494 if (!check_name(fname,cnum))
1496 if((errno == ENOENT) && bad_path)
1498 unix_ERR_class = ERRDOS;
1499 unix_ERR_code = ERRbadpath;
1501 Files[fnum].reserved = False;
1502 return(UNIXERROR(ERRDOS,ERRnoaccess));
1507 /* We should fail if file exists. */
1512 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1516 /* Open file in dos compatibility share mode. */
1517 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1518 oplock_request, NULL, NULL);
1524 if((errno == ENOENT) && bad_path)
1526 unix_ERR_class = ERRDOS;
1527 unix_ERR_code = ERRbadpath;
1529 Files[fnum].reserved = False;
1530 return(UNIXERROR(ERRDOS,ERRnoaccess));
1533 outsize = set_message(outbuf,1,0,True);
1534 SSVAL(outbuf,smb_vwv0,fnum);
1536 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1537 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1540 if(fsp->granted_oplock)
1541 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1543 DEBUG(2,("new file %s\n",fname));
1544 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));
1550 /****************************************************************************
1551 reply to a create temporary file
1552 ****************************************************************************/
1553 int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1562 BOOL bad_path = False;
1564 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1566 cnum = SVAL(inbuf,smb_tid);
1567 createmode = SVAL(inbuf,smb_vwv0);
1568 pstrcpy(fname,smb_buf(inbuf)+1);
1569 strcat(fname,"/TMXXXXXX");
1570 unix_convert(fname,cnum,0,&bad_path);
1572 unixmode = unix_mode(cnum,createmode);
1574 fnum = find_free_file();
1576 return(ERROR(ERRSRV,ERRnofids));
1578 if (!check_name(fname,cnum))
1580 if((errno == ENOENT) && bad_path)
1582 unix_ERR_class = ERRDOS;
1583 unix_ERR_code = ERRbadpath;
1585 Files[fnum].reserved = False;
1586 return(UNIXERROR(ERRDOS,ERRnoaccess));
1589 strcpy(fname2,(char *)mktemp(fname));
1591 /* Open file in dos compatibility share mode. */
1592 /* We should fail if file exists. */
1593 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1594 oplock_request, NULL, NULL);
1600 if((errno == ENOENT) && bad_path)
1602 unix_ERR_class = ERRDOS;
1603 unix_ERR_code = ERRbadpath;
1605 Files[fnum].reserved = False;
1606 return(UNIXERROR(ERRDOS,ERRnoaccess));
1609 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1610 SSVAL(outbuf,smb_vwv0,fnum);
1611 CVAL(smb_buf(outbuf),0) = 4;
1612 strcpy(smb_buf(outbuf) + 1,fname2);
1614 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1615 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1618 if(fsp->granted_oplock)
1619 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1621 DEBUG(2,("created temp file %s\n",fname2));
1622 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));
1628 /*******************************************************************
1629 check if a user is allowed to delete a file
1630 ********************************************************************/
1631 static BOOL can_delete(char *fname,int cnum,int dirtype)
1636 if (!CAN_WRITE(cnum)) return(False);
1638 if (sys_lstat(fname,&sbuf) != 0) return(False);
1639 fmode = dos_mode(cnum,fname,&sbuf);
1640 if (fmode & aDIR) return(False);
1641 if (!lp_delete_readonly(SNUM(cnum))) {
1642 if (fmode & aRONLY) return(False);
1644 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1646 if (!check_file_sharing(cnum,fname,False)) return(False);
1650 /****************************************************************************
1652 ****************************************************************************/
1653 int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1663 int error = ERRnoaccess;
1666 BOOL bad_path = False;
1668 *directory = *mask = 0;
1670 cnum = SVAL(inbuf,smb_tid);
1671 dirtype = SVAL(inbuf,smb_vwv0);
1673 pstrcpy(name,smb_buf(inbuf) + 1);
1675 DEBUG(3,("reply_unlink : %s\n",name));
1677 unix_convert(name,cnum,0,&bad_path);
1679 p = strrchr(name,'/');
1681 strcpy(directory,"./");
1685 strcpy(directory,name);
1689 if (is_mangled(mask))
1690 check_mangled_cache( mask );
1692 has_wild = strchr(mask,'*') || strchr(mask,'?');
1695 strcat(directory,"/");
1696 strcat(directory,mask);
1697 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1698 if (!count) exists = file_exist(directory,NULL);
1700 void *dirptr = NULL;
1703 if (check_name(directory,cnum))
1704 dirptr = OpenDir(cnum, directory, True);
1706 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1707 the pattern matches against the long name, otherwise the short name
1708 We don't implement this yet XXXX
1715 if (strequal(mask,"????????.???"))
1718 while ((dname = ReadDirName(dirptr)))
1721 pstrcpy(fname,dname);
1723 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1725 error = ERRnoaccess;
1726 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1727 if (!can_delete(fname,cnum,dirtype)) continue;
1728 if (!sys_unlink(fname)) count++;
1729 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1737 return(ERROR(ERRDOS,error));
1740 if((errno == ENOENT) && bad_path)
1742 unix_ERR_class = ERRDOS;
1743 unix_ERR_code = ERRbadpath;
1745 return(UNIXERROR(ERRDOS,error));
1749 outsize = set_message(outbuf,0,0,True);
1755 /****************************************************************************
1756 reply to a readbraw (core+ protocol)
1757 ****************************************************************************/
1758 int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1760 int cnum,maxcount,mincount,fnum;
1763 char *header = outbuf;
1769 * Special check if an oplock break has been issued
1770 * and the readraw request croses on the wire, we must
1771 * return a zero length response here.
1774 if(global_oplock_break)
1776 _smb_setlen(header,0);
1777 transfer_file(0,Client,0,header,4,0);
1778 DEBUG(5,("readbraw - oplock break finished\n"));
1782 cnum = SVAL(inbuf,smb_tid);
1783 fnum = GETFNUM(inbuf,smb_vwv0);
1785 startpos = IVAL(inbuf,smb_vwv1);
1786 maxcount = SVAL(inbuf,smb_vwv3);
1787 mincount = SVAL(inbuf,smb_vwv4);
1789 /* ensure we don't overrun the packet size */
1790 maxcount = MIN(65535,maxcount);
1791 maxcount = MAX(mincount,maxcount);
1793 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1795 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1796 _smb_setlen(header,0);
1797 transfer_file(0,Client,0,header,4,0);
1802 fd = Files[fnum].fd_ptr->fd;
1803 fname = Files[fnum].name;
1807 if (!is_locked(fnum,cnum,maxcount,startpos))
1809 int size = Files[fnum].size;
1810 int sizeneeded = startpos + maxcount;
1812 if (size < sizeneeded) {
1814 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1816 if (!Files[fnum].can_write)
1817 Files[fnum].size = size;
1820 nread = MIN(maxcount,(int)(size - startpos));
1823 if (nread < mincount)
1826 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1829 maxcount,mincount,nread));
1834 _smb_setlen(header,nread);
1836 #if USE_READ_PREDICTION
1837 if (!Files[fnum].can_write)
1838 predict = read_predict(fd,startpos,header+4,NULL,nread);
1841 if ((nread-predict) > 0)
1842 seek_file(fnum,startpos + predict);
1844 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1849 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1850 fname,startpos,nread,ret));
1853 ret = read_file(fnum,header+4,startpos,nread);
1854 if (ret < mincount) ret = 0;
1856 _smb_setlen(header,ret);
1857 transfer_file(0,Client,0,header,4+ret,0);
1860 DEBUG(5,("readbraw finished\n"));
1865 /****************************************************************************
1866 reply to a lockread (core+ protocol)
1867 ****************************************************************************/
1868 int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz)
1874 uint32 startpos, numtoread;
1878 cnum = SVAL(inbuf,smb_tid);
1879 fnum = GETFNUM(inbuf,smb_vwv0);
1881 CHECK_FNUM(fnum,cnum);
1885 numtoread = SVAL(inbuf,smb_vwv1);
1886 startpos = IVAL(inbuf,smb_vwv2);
1888 outsize = set_message(outbuf,5,3,True);
1889 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1890 data = smb_buf(outbuf) + 3;
1892 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1893 return (ERROR(eclass,ecode));
1895 nread = read_file(fnum,data,startpos,numtoread);
1898 return(UNIXERROR(ERRDOS,ERRnoaccess));
1901 SSVAL(outbuf,smb_vwv0,nread);
1902 SSVAL(outbuf,smb_vwv5,nread+3);
1903 SSVAL(smb_buf(outbuf),1,nread);
1905 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1911 /****************************************************************************
1913 ****************************************************************************/
1914 int reply_read(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1916 int cnum,numtoread,fnum;
1922 cnum = SVAL(inbuf,smb_tid);
1923 fnum = GETFNUM(inbuf,smb_vwv0);
1925 CHECK_FNUM(fnum,cnum);
1929 numtoread = SVAL(inbuf,smb_vwv1);
1930 startpos = IVAL(inbuf,smb_vwv2);
1932 outsize = set_message(outbuf,5,3,True);
1933 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1934 data = smb_buf(outbuf) + 3;
1936 if (is_locked(fnum,cnum,numtoread,startpos))
1937 return(ERROR(ERRDOS,ERRlock));
1940 nread = read_file(fnum,data,startpos,numtoread);
1943 return(UNIXERROR(ERRDOS,ERRnoaccess));
1946 SSVAL(outbuf,smb_vwv0,nread);
1947 SSVAL(outbuf,smb_vwv5,nread+3);
1948 CVAL(smb_buf(outbuf),0) = 1;
1949 SSVAL(smb_buf(outbuf),1,nread);
1951 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1957 /****************************************************************************
1958 reply to a read and X
1959 ****************************************************************************/
1960 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1962 int fnum = GETFNUM(inbuf,smb_vwv2);
1963 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1964 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1965 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1971 cnum = SVAL(inbuf,smb_tid);
1973 /* If it's an IPC, pass off the pipe handler. */
1975 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1977 CHECK_FNUM(fnum,cnum);
1981 set_message(outbuf,12,0,True);
1982 data = smb_buf(outbuf);
1984 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1985 return(ERROR(ERRDOS,ERRlock));
1986 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1990 return(UNIXERROR(ERRDOS,ERRnoaccess));
1992 SSVAL(outbuf,smb_vwv5,nread);
1993 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1994 SSVAL(smb_buf(outbuf),-2,nread);
1996 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1997 timestring(),fnum,cnum,
1998 smb_mincnt,smb_maxcnt,nread));
2002 return chain_reply(inbuf,outbuf,length,bufsize);
2006 /****************************************************************************
2007 reply to a writebraw (core+ or LANMAN1.0 protocol)
2008 ****************************************************************************/
2009 int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2012 int total_written=0;
2021 cnum = SVAL(inbuf,smb_tid);
2022 fnum = GETFNUM(inbuf,smb_vwv0);
2024 CHECK_FNUM(fnum,cnum);
2028 tcount = IVAL(inbuf,smb_vwv1);
2029 startpos = IVAL(inbuf,smb_vwv3);
2030 write_through = BITSETW(inbuf+smb_vwv7,0);
2032 /* We have to deal with slightly different formats depending
2033 on whether we are using the core+ or lanman1.0 protocol */
2034 if(Protocol <= PROTOCOL_COREPLUS) {
2035 numtowrite = SVAL(smb_buf(inbuf),-2);
2036 data = smb_buf(inbuf);
2038 numtowrite = SVAL(inbuf,smb_vwv10);
2039 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2042 /* force the error type */
2043 CVAL(inbuf,smb_com) = SMBwritec;
2044 CVAL(outbuf,smb_com) = SMBwritec;
2046 if (is_locked(fnum,cnum,tcount,startpos))
2047 return(ERROR(ERRDOS,ERRlock));
2049 if (seek_file(fnum,startpos) != startpos)
2050 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
2053 nwritten = write_file(fnum,data,numtowrite);
2055 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
2056 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
2058 if (nwritten < numtowrite)
2059 return(UNIXERROR(ERRHRD,ERRdiskfull));
2061 total_written = nwritten;
2063 /* Return a message to the redirector to tell it
2064 to send more bytes */
2065 CVAL(outbuf,smb_com) = SMBwritebraw;
2066 SSVALS(outbuf,smb_vwv0,-1);
2067 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2068 send_smb(Client,outbuf);
2070 /* Now read the raw data into the buffer and write it */
2071 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2072 exit_server("secondary writebraw failed");
2075 /* Even though this is not an smb message, smb_len
2076 returns the generic length of an smb message */
2077 numtowrite = smb_len(inbuf);
2079 if (tcount > nwritten+numtowrite) {
2080 DEBUG(3,("Client overestimated the write %d %d %d\n",
2081 tcount,nwritten,numtowrite));
2084 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
2086 total_written += nwritten;
2088 /* Set up outbuf to return the correct return */
2089 outsize = set_message(outbuf,1,0,True);
2090 CVAL(outbuf,smb_com) = SMBwritec;
2091 SSVAL(outbuf,smb_vwv0,total_written);
2093 if (nwritten < numtowrite) {
2094 CVAL(outbuf,smb_rcls) = ERRHRD;
2095 SSVAL(outbuf,smb_err,ERRdiskfull);
2098 if (lp_syncalways(SNUM(cnum)) || write_through)
2101 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
2102 timestring(),fnum,cnum,startpos,numtowrite,total_written));
2104 /* we won't return a status if write through is not selected - this
2105 follows what WfWg does */
2106 if (!write_through && total_written==tcount)
2113 /****************************************************************************
2114 reply to a writeunlock (core+)
2115 ****************************************************************************/
2116 int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2122 uint32 numtowrite,startpos;
2126 cnum = SVAL(inbuf,smb_tid);
2127 fnum = GETFNUM(inbuf,smb_vwv0);
2129 CHECK_FNUM(fnum,cnum);
2133 numtowrite = SVAL(inbuf,smb_vwv1);
2134 startpos = IVAL(inbuf,smb_vwv2);
2135 data = smb_buf(inbuf) + 3;
2137 if (is_locked(fnum,cnum,numtowrite,startpos))
2138 return(ERROR(ERRDOS,ERRlock));
2140 seek_file(fnum,startpos);
2142 /* The special X/Open SMB protocol handling of
2143 zero length writes is *NOT* done for
2148 nwritten = write_file(fnum,data,numtowrite);
2150 if (lp_syncalways(SNUM(cnum)))
2153 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2154 return(UNIXERROR(ERRDOS,ERRnoaccess));
2156 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2157 return(ERROR(eclass,ecode));
2159 outsize = set_message(outbuf,1,0,True);
2161 SSVAL(outbuf,smb_vwv0,nwritten);
2163 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2164 timestring(),fnum,cnum,numtowrite,nwritten));
2170 /****************************************************************************
2172 ****************************************************************************/
2173 int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2175 int cnum,numtowrite,fnum;
2181 cnum = SVAL(inbuf,smb_tid);
2182 fnum = GETFNUM(inbuf,smb_vwv0);
2184 CHECK_FNUM(fnum,cnum);
2188 numtowrite = SVAL(inbuf,smb_vwv1);
2189 startpos = IVAL(inbuf,smb_vwv2);
2190 data = smb_buf(inbuf) + 3;
2192 if (is_locked(fnum,cnum,numtowrite,startpos))
2193 return(ERROR(ERRDOS,ERRlock));
2195 seek_file(fnum,startpos);
2197 /* X/Open SMB protocol says that if smb_vwv1 is
2198 zero then the file size should be extended or
2199 truncated to the size given in smb_vwv[2-3] */
2201 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2203 nwritten = write_file(fnum,data,numtowrite);
2205 if (lp_syncalways(SNUM(cnum)))
2208 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2209 return(UNIXERROR(ERRDOS,ERRnoaccess));
2211 outsize = set_message(outbuf,1,0,True);
2213 SSVAL(outbuf,smb_vwv0,nwritten);
2215 if (nwritten < numtowrite) {
2216 CVAL(outbuf,smb_rcls) = ERRHRD;
2217 SSVAL(outbuf,smb_err,ERRdiskfull);
2220 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2226 /****************************************************************************
2227 reply to a write and X
2228 ****************************************************************************/
2229 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2231 int fnum = GETFNUM(inbuf,smb_vwv2);
2232 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2233 int smb_dsize = SVAL(inbuf,smb_vwv10);
2234 int smb_doff = SVAL(inbuf,smb_vwv11);
2235 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2240 cnum = SVAL(inbuf,smb_tid);
2242 CHECK_FNUM(fnum,cnum);
2246 data = smb_base(inbuf) + smb_doff;
2248 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2249 return(ERROR(ERRDOS,ERRlock));
2251 seek_file(fnum,smb_offs);
2253 /* X/Open SMB protocol says that, unlike SMBwrite
2254 if the length is zero then NO truncation is
2255 done, just a write of zero. To truncate a file,
2260 nwritten = write_file(fnum,data,smb_dsize);
2262 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2263 return(UNIXERROR(ERRDOS,ERRnoaccess));
2265 set_message(outbuf,6,0,True);
2267 SSVAL(outbuf,smb_vwv2,nwritten);
2269 if (nwritten < smb_dsize) {
2270 CVAL(outbuf,smb_rcls) = ERRHRD;
2271 SSVAL(outbuf,smb_err,ERRdiskfull);
2274 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2278 if (lp_syncalways(SNUM(cnum)) || write_through)
2281 return chain_reply(inbuf,outbuf,length,bufsize);
2285 /****************************************************************************
2287 ****************************************************************************/
2288 int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2296 cnum = SVAL(inbuf,smb_tid);
2297 fnum = GETFNUM(inbuf,smb_vwv0);
2299 CHECK_FNUM(fnum,cnum);
2302 mode = SVAL(inbuf,smb_vwv1) & 3;
2303 startpos = IVAL(inbuf,smb_vwv2);
2307 case 0: umode = SEEK_SET; break;
2308 case 1: umode = SEEK_CUR; break;
2309 case 2: umode = SEEK_END; break;
2311 umode = SEEK_SET; break;
2314 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2315 Files[fnum].pos = res;
2317 outsize = set_message(outbuf,2,0,True);
2318 SIVALS(outbuf,smb_vwv0,res);
2320 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2326 /****************************************************************************
2328 ****************************************************************************/
2329 int reply_flush(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2332 int outsize = set_message(outbuf,0,0,True);
2334 cnum = SVAL(inbuf,smb_tid);
2335 fnum = GETFNUM(inbuf,smb_vwv0);
2337 if (fnum != 0xFFFF) {
2338 CHECK_FNUM(fnum,cnum);
2345 for (i=0;i<MAX_OPEN_FILES;i++)
2352 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2357 /****************************************************************************
2359 ****************************************************************************/
2360 int reply_exit(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2362 int outsize = set_message(outbuf,0,0,True);
2363 DEBUG(3,("%s exit\n",timestring()));
2369 /****************************************************************************
2371 ****************************************************************************/
2372 int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2377 int32 eclass = 0, err = 0;
2379 outsize = set_message(outbuf,0,0,True);
2381 cnum = SVAL(inbuf,smb_tid);
2383 /* If it's an IPC, pass off to the pipe handler. */
2385 return reply_pipe_close(inbuf,outbuf);
2387 fnum = GETFNUM(inbuf,smb_vwv0);
2389 CHECK_FNUM(fnum,cnum);
2391 if(HAS_CACHED_ERROR(fnum)) {
2392 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2393 err = Files[fnum].wbmpx_ptr->wr_error;
2396 mtime = make_unix_date3(inbuf+smb_vwv1);
2398 /* try and set the date */
2399 set_filetime(cnum, Files[fnum].name,mtime);
2401 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2402 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2403 Connections[cnum].num_files_open));
2405 close_file(fnum,True);
2407 /* We have a cached error */
2409 return(ERROR(eclass,err));
2415 /****************************************************************************
2416 reply to a writeclose (Core+ protocol)
2417 ****************************************************************************/
2418 int reply_writeclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2420 int cnum,numtowrite,fnum;
2427 cnum = SVAL(inbuf,smb_tid);
2428 fnum = GETFNUM(inbuf,smb_vwv0);
2430 CHECK_FNUM(fnum,cnum);
2434 numtowrite = SVAL(inbuf,smb_vwv1);
2435 startpos = IVAL(inbuf,smb_vwv2);
2436 mtime = make_unix_date3(inbuf+smb_vwv4);
2437 data = smb_buf(inbuf) + 1;
2439 if (is_locked(fnum,cnum,numtowrite,startpos))
2440 return(ERROR(ERRDOS,ERRlock));
2442 seek_file(fnum,startpos);
2444 nwritten = write_file(fnum,data,numtowrite);
2446 set_filetime(cnum, Files[fnum].name,mtime);
2448 close_file(fnum,True);
2450 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2451 timestring(),fnum,cnum,numtowrite,nwritten,
2452 Connections[cnum].num_files_open));
2455 return(UNIXERROR(ERRDOS,ERRnoaccess));
2457 outsize = set_message(outbuf,1,0,True);
2459 SSVAL(outbuf,smb_vwv0,nwritten);
2464 /****************************************************************************
2466 ****************************************************************************/
2467 int reply_lock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2470 int outsize = set_message(outbuf,0,0,True);
2471 uint32 count,offset;
2475 cnum = SVAL(inbuf,smb_tid);
2476 fnum = GETFNUM(inbuf,smb_vwv0);
2478 CHECK_FNUM(fnum,cnum);
2481 count = IVAL(inbuf,smb_vwv1);
2482 offset = IVAL(inbuf,smb_vwv3);
2484 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));
2486 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2487 return (ERROR(eclass,ecode));
2493 /****************************************************************************
2495 ****************************************************************************/
2496 int reply_unlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2499 int outsize = set_message(outbuf,0,0,True);
2500 uint32 count,offset;
2504 cnum = SVAL(inbuf,smb_tid);
2505 fnum = GETFNUM(inbuf,smb_vwv0);
2507 CHECK_FNUM(fnum,cnum);
2510 count = IVAL(inbuf,smb_vwv1);
2511 offset = IVAL(inbuf,smb_vwv3);
2513 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2514 return (ERROR(eclass,ecode));
2516 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));
2522 /****************************************************************************
2524 ****************************************************************************/
2525 int reply_tdis(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2528 int outsize = set_message(outbuf,0,0,True);
2531 cnum = SVAL(inbuf,smb_tid);
2532 vuid = SVAL(inbuf,smb_uid);
2534 if (!OPEN_CNUM(cnum)) {
2535 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2536 return(ERROR(ERRSRV,ERRinvnid));
2539 Connections[cnum].used = False;
2541 close_cnum(cnum,vuid);
2543 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2550 /****************************************************************************
2552 ****************************************************************************/
2553 int reply_echo(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2556 int smb_reverb = SVAL(inbuf,smb_vwv0);
2558 int data_len = smb_buflen(inbuf);
2559 int outsize = set_message(outbuf,1,data_len,True);
2561 cnum = SVAL(inbuf,smb_tid);
2563 /* According to the latest CIFS spec we shouldn't
2564 care what the TID is.
2568 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2570 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2571 return(ERROR(ERRSRV,ERRinvnid));
2575 /* copy any incoming data back out */
2577 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2579 if (smb_reverb > 100)
2581 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2585 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2587 SSVAL(outbuf,smb_vwv0,seq_num);
2589 smb_setlen(outbuf,outsize - 4);
2591 send_smb(Client,outbuf);
2594 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2600 /****************************************************************************
2601 reply to a printopen
2602 ****************************************************************************/
2603 int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2611 *fname = *fname2 = 0;
2613 cnum = SVAL(inbuf,smb_tid);
2615 if (!CAN_PRINT(cnum))
2616 return(ERROR(ERRDOS,ERRnoaccess));
2621 pstrcpy(s,smb_buf(inbuf)+1);
2625 if (!(isalnum(*p) || strchr("._-",*p)))
2630 if (strlen(s) > 10) s[10] = 0;
2632 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2635 fnum = find_free_file();
2637 return(ERROR(ERRSRV,ERRnofids));
2639 strcpy(fname2,(char *)mktemp(fname));
2641 if (!check_name(fname2,cnum)) {
2642 Files[fnum].reserved = False;
2643 return(ERROR(ERRDOS,ERRnoaccess));
2646 /* Open for exclusive use, write only. */
2647 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2650 if (!Files[fnum].open) {
2651 Files[fnum].reserved = False;
2652 return(UNIXERROR(ERRDOS,ERRnoaccess));
2655 /* force it to be a print file */
2656 Files[fnum].print_file = True;
2658 outsize = set_message(outbuf,1,0,True);
2659 SSVAL(outbuf,smb_vwv0,fnum);
2661 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2667 /****************************************************************************
2668 reply to a printclose
2669 ****************************************************************************/
2670 int reply_printclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2673 int outsize = set_message(outbuf,0,0,True);
2675 cnum = SVAL(inbuf,smb_tid);
2676 fnum = GETFNUM(inbuf,smb_vwv0);
2678 CHECK_FNUM(fnum,cnum);
2681 if (!CAN_PRINT(cnum))
2682 return(ERROR(ERRDOS,ERRnoaccess));
2684 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2686 close_file(fnum,True);
2692 /****************************************************************************
2693 reply to a printqueue
2694 ****************************************************************************/
2695 int reply_printqueue(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2698 int outsize = set_message(outbuf,2,3,True);
2699 int max_count = SVAL(inbuf,smb_vwv0);
2700 int start_index = SVAL(inbuf,smb_vwv1);
2703 cnum = SVAL(inbuf,smb_tid);
2704 vuid = SVAL(inbuf,smb_uid);
2706 /* allow checking the queue for anyone */
2708 if (!CAN_PRINT(cnum))
2709 return(ERROR(ERRDOS,ERRnoaccess));
2712 SSVAL(outbuf,smb_vwv0,0);
2713 SSVAL(outbuf,smb_vwv1,0);
2714 CVAL(smb_buf(outbuf),0) = 1;
2715 SSVAL(smb_buf(outbuf),1,0);
2717 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2718 timestring(),cnum,start_index,max_count));
2720 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2725 for (i=0;i<MAX_CONNECTIONS;i++)
2726 if (CAN_PRINT(i) && Connections[i].printer)
2730 for (i=0;i<MAX_CONNECTIONS;i++)
2734 if (!OPEN_CNUM(cnum))
2735 return(ERROR(ERRSRV,ERRinvnid));
2737 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2740 if (!become_user(&Connections[cnum], cnum, vuid))
2741 return(ERROR(ERRSRV,ERRinvnid));
2744 print_queue_struct *queue = NULL;
2745 char *p = smb_buf(outbuf) + 3;
2746 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2747 int num_to_get = ABS(max_count);
2748 int first = (max_count>0?start_index:start_index+max_count+1);
2754 num_to_get = MIN(num_to_get,count-first);
2757 for (i=first;i<first+num_to_get;i++)
2759 put_dos_date2(p,0,queue[i].time);
2760 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2761 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2762 SIVAL(p,7,queue[i].size);
2764 StrnCpy(p+12,queue[i].user,16);
2770 outsize = set_message(outbuf,2,28*count+3,False);
2771 SSVAL(outbuf,smb_vwv0,count);
2772 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2773 CVAL(smb_buf(outbuf),0) = 1;
2774 SSVAL(smb_buf(outbuf),1,28*count);
2777 if (queue) free(queue);
2779 DEBUG(3,("%d entries returned in queue\n",count));
2786 /****************************************************************************
2787 reply to a printwrite
2788 ****************************************************************************/
2789 int reply_printwrite(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2791 int cnum,numtowrite,fnum;
2792 int outsize = set_message(outbuf,0,0,True);
2795 cnum = SVAL(inbuf,smb_tid);
2797 if (!CAN_PRINT(cnum))
2798 return(ERROR(ERRDOS,ERRnoaccess));
2800 fnum = GETFNUM(inbuf,smb_vwv0);
2802 CHECK_FNUM(fnum,cnum);
2806 numtowrite = SVAL(smb_buf(inbuf),1);
2807 data = smb_buf(inbuf) + 3;
2809 if (write_file(fnum,data,numtowrite) != numtowrite)
2810 return(UNIXERROR(ERRDOS,ERRnoaccess));
2812 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2818 /****************************************************************************
2820 ****************************************************************************/
2821 int reply_mkdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2825 int outsize,ret= -1;
2826 BOOL bad_path = False;
2828 pstrcpy(directory,smb_buf(inbuf) + 1);
2829 cnum = SVAL(inbuf,smb_tid);
2830 unix_convert(directory,cnum,0,&bad_path);
2832 if (check_name(directory,cnum))
2833 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2837 if((errno == ENOENT) && bad_path)
2839 unix_ERR_class = ERRDOS;
2840 unix_ERR_code = ERRbadpath;
2842 return(UNIXERROR(ERRDOS,ERRnoaccess));
2845 outsize = set_message(outbuf,0,0,True);
2847 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2852 /****************************************************************************
2853 Static function used by reply_rmdir to delete an entire directory
2855 ****************************************************************************/
2856 static BOOL recursive_rmdir(char *directory)
2860 void *dirptr = OpenDir(-1, directory, False);
2865 while((dname = ReadDirName(dirptr)))
2870 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2873 /* Construct the full name. */
2874 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2880 strcpy(fullname, directory);
2881 strcat(fullname, "/");
2882 strcat(fullname, dname);
2884 if(sys_lstat(fullname, &st) != 0)
2890 if(st.st_mode & S_IFDIR)
2892 if(recursive_rmdir(fullname)!=0)
2897 if(sys_rmdir(fullname) != 0)
2903 else if(sys_unlink(fullname) != 0)
2913 /****************************************************************************
2915 ****************************************************************************/
2916 int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2922 BOOL bad_path = False;
2924 cnum = SVAL(inbuf,smb_tid);
2925 pstrcpy(directory,smb_buf(inbuf) + 1);
2926 unix_convert(directory,cnum,0,&bad_path);
2928 if (check_name(directory,cnum))
2931 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2932 ok = (sys_rmdir(directory) == 0);
2933 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2935 /* Check to see if the only thing in this directory are
2936 vetoed files/directories. If so then delete them and
2937 retry. If we fail to delete any of them (and we *don't*
2938 do a recursive delete) then fail the rmdir. */
2939 BOOL all_veto_files = True;
2941 void *dirptr = OpenDir(cnum, directory, False);
2945 int dirpos = TellDir(dirptr);
2946 while ((dname = ReadDirName(dirptr)))
2948 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2950 if(!IS_VETO_PATH(cnum, dname))
2952 all_veto_files = False;
2958 SeekDir(dirptr,dirpos);
2959 while ((dname = ReadDirName(dirptr)))
2964 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2967 /* Construct the full name. */
2968 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2973 pstrcpy(fullname, directory);
2974 strcat(fullname, "/");
2975 strcat(fullname, dname);
2977 if(sys_lstat(fullname, &st) != 0)
2979 if(st.st_mode & S_IFDIR)
2981 if(lp_recursive_veto_delete(SNUM(cnum)))
2983 if(recursive_rmdir(fullname) != 0)
2986 if(sys_rmdir(fullname) != 0)
2989 else if(sys_unlink(fullname) != 0)
2993 /* Retry the rmdir */
2994 ok = (sys_rmdir(directory) == 0);
3004 DEBUG(3,("couldn't remove directory %s : %s\n",
3005 directory,strerror(errno)));
3010 if((errno == ENOENT) && bad_path)
3012 unix_ERR_class = ERRDOS;
3013 unix_ERR_code = ERRbadpath;
3015 return(UNIXERROR(ERRDOS,ERRbadpath));
3018 outsize = set_message(outbuf,0,0,True);
3020 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
3026 /*******************************************************************
3027 resolve wildcards in a filename rename
3028 ********************************************************************/
3029 static BOOL resolve_wildcards(char *name1,char *name2)
3031 fstring root1,root2;
3035 name1 = strrchr(name1,'/');
3036 name2 = strrchr(name2,'/');
3038 if (!name1 || !name2) return(False);
3040 fstrcpy(root1,name1);
3041 fstrcpy(root2,name2);
3042 p = strrchr(root1,'.');
3049 p = strrchr(root2,'.');
3081 strcpy(name2,root2);
3090 /*******************************************************************
3091 check if a user is allowed to rename a file
3092 ********************************************************************/
3093 static BOOL can_rename(char *fname,int cnum)
3097 if (!CAN_WRITE(cnum)) return(False);
3099 if (sys_lstat(fname,&sbuf) != 0) return(False);
3100 if (!check_file_sharing(cnum,fname,True)) return(False);
3105 /****************************************************************************
3107 ****************************************************************************/
3108 int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3114 pstring mask,newname;
3115 pstring newname_last_component;
3118 int error = ERRnoaccess;
3121 BOOL bad_path1 = False;
3122 BOOL bad_path2 = False;
3124 *directory = *mask = 0;
3126 cnum = SVAL(inbuf,smb_tid);
3128 pstrcpy(name,smb_buf(inbuf) + 1);
3129 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3131 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3133 unix_convert(name,cnum,0,&bad_path1);
3134 unix_convert(newname,cnum,newname_last_component,&bad_path2);
3137 * Split the old name into directory and last component
3138 * strings. Note that unix_convert may have stripped off a
3139 * leading ./ from both name and newname if the rename is
3140 * at the root of the share. We need to make sure either both
3141 * name and newname contain a / character or neither of them do
3142 * as this is checked in resolve_wildcards().
3145 p = strrchr(name,'/');
3147 strcpy(directory,".");
3151 strcpy(directory,name);
3153 *p = '/'; /* Replace needed for exceptional test below. */
3156 if (is_mangled(mask))
3157 check_mangled_cache( mask );
3159 has_wild = strchr(mask,'*') || strchr(mask,'?');
3162 BOOL is_short_name = is_8_3(name, True);
3164 /* Add a terminating '/' to the directory name. */
3165 strcat(directory,"/");
3166 strcat(directory,mask);
3168 /* Ensure newname contains a '/' also */
3169 if(strrchr(newname,'/') == 0) {
3172 strcpy(tmpstr, "./");
3173 strcat(tmpstr, newname);
3174 strcpy(newname, tmpstr);
3177 DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3178 case_sensitive, case_preserve, short_case_preserve, directory,
3179 newname, newname_last_component, is_short_name));
3182 * Check for special case with case preserving and not
3183 * case sensitive, if directory and newname are identical,
3184 * and the old last component differs from the original
3185 * last component only by case, then we should allow
3186 * the rename (user is trying to change the case of the
3189 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3190 ((short_case_preserve == True) && (is_short_name == True))) &&
3191 strcsequal(directory, newname)) {
3192 pstring newname_modified_last_component;
3195 * Get the last component of the modified name.
3196 * Note that we guarantee that newname contains a '/'
3199 p = strrchr(newname,'/');
3200 strcpy(newname_modified_last_component,p+1);
3202 if(strcsequal(newname_modified_last_component,
3203 newname_last_component) == False) {
3205 * Replace the modified last component with
3208 strcpy(p+1, newname_last_component);
3212 if (resolve_wildcards(directory,newname) &&
3213 can_rename(directory,cnum) &&
3214 !file_exist(newname,NULL) &&
3215 !sys_rename(directory,newname)) count++;
3217 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3218 directory,newname));
3220 if (!count) exists = file_exist(directory,NULL);
3221 if (!count && exists && file_exist(newname,NULL)) {
3226 void *dirptr = NULL;
3230 if (check_name(directory,cnum))
3231 dirptr = OpenDir(cnum, directory, True);
3237 if (strequal(mask,"????????.???"))
3240 while ((dname = ReadDirName(dirptr)))
3243 pstrcpy(fname,dname);
3245 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3247 error = ERRnoaccess;
3248 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3249 if (!can_rename(fname,cnum)) {
3250 DEBUG(6,("rename %s refused\n", fname));
3253 pstrcpy(destname,newname);
3255 if (!resolve_wildcards(fname,destname)) {
3256 DEBUG(6,("resolve_wildcards %s %s failed\n",
3261 if (file_exist(destname,NULL)) {
3262 DEBUG(6,("file_exist %s\n",
3267 if (!sys_rename(fname,destname)) count++;
3268 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3276 return(ERROR(ERRDOS,error));
3279 if((errno == ENOENT) && (bad_path1 || bad_path2))
3281 unix_ERR_class = ERRDOS;
3282 unix_ERR_code = ERRbadpath;
3284 return(UNIXERROR(ERRDOS,error));
3288 outsize = set_message(outbuf,0,0,True);
3293 /*******************************************************************
3294 copy a file as part of a reply_copy
3295 ******************************************************************/
3296 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3297 int count,BOOL target_is_directory)
3305 pstrcpy(dest,dest1);
3306 if (target_is_directory) {
3307 char *p = strrchr(src,'/');
3316 if (!file_exist(src,&st)) return(False);
3318 fnum1 = find_free_file();
3319 if (fnum1<0) return(False);
3320 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3321 1,0,0,&Access,&action);
3323 if (!Files[fnum1].open) {
3324 Files[fnum1].reserved = False;
3328 if (!target_is_directory && count)
3331 fnum2 = find_free_file();
3333 close_file(fnum1,False);
3336 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3337 ofun,st.st_mode,0,&Access,&action);
3339 if (!Files[fnum2].open) {
3340 close_file(fnum1,False);
3341 Files[fnum2].reserved = False;
3345 if ((ofun&3) == 1) {
3346 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3350 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3352 close_file(fnum1,False);
3353 close_file(fnum2,False);
3355 return(ret == st.st_size);
3360 /****************************************************************************
3361 reply to a file copy.
3362 ****************************************************************************/
3363 int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3369 pstring mask,newname;
3372 int error = ERRnoaccess;
3375 int tid2 = SVAL(inbuf,smb_vwv0);
3376 int ofun = SVAL(inbuf,smb_vwv1);
3377 int flags = SVAL(inbuf,smb_vwv2);
3378 BOOL target_is_directory=False;
3379 BOOL bad_path1 = False;
3380 BOOL bad_path2 = False;
3382 *directory = *mask = 0;
3384 cnum = SVAL(inbuf,smb_tid);
3386 pstrcpy(name,smb_buf(inbuf));
3387 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3389 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3392 /* can't currently handle inter share copies XXXX */
3393 DEBUG(3,("Rejecting inter-share copy\n"));
3394 return(ERROR(ERRSRV,ERRinvdevice));
3397 unix_convert(name,cnum,0,&bad_path1);
3398 unix_convert(newname,cnum,0,&bad_path2);
3400 target_is_directory = directory_exist(newname,NULL);
3402 if ((flags&1) && target_is_directory) {
3403 return(ERROR(ERRDOS,ERRbadfile));
3406 if ((flags&2) && !target_is_directory) {
3407 return(ERROR(ERRDOS,ERRbadpath));
3410 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3411 /* wants a tree copy! XXXX */
3412 DEBUG(3,("Rejecting tree copy\n"));
3413 return(ERROR(ERRSRV,ERRerror));
3416 p = strrchr(name,'/');
3418 strcpy(directory,"./");
3422 strcpy(directory,name);
3426 if (is_mangled(mask))
3427 check_mangled_cache( mask );
3429 has_wild = strchr(mask,'*') || strchr(mask,'?');
3432 strcat(directory,"/");
3433 strcat(directory,mask);
3434 if (resolve_wildcards(directory,newname) &&
3435 copy_file(directory,newname,cnum,ofun,
3436 count,target_is_directory)) count++;
3437 if (!count) exists = file_exist(directory,NULL);
3439 void *dirptr = NULL;
3443 if (check_name(directory,cnum))
3444 dirptr = OpenDir(cnum, directory, True);
3450 if (strequal(mask,"????????.???"))
3453 while ((dname = ReadDirName(dirptr)))
3456 pstrcpy(fname,dname);
3458 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3460 error = ERRnoaccess;
3461 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3462 strcpy(destname,newname);
3463 if (resolve_wildcards(fname,destname) &&
3464 copy_file(directory,newname,cnum,ofun,
3465 count,target_is_directory)) count++;
3466 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3474 return(ERROR(ERRDOS,error));
3477 if((errno == ENOENT) && (bad_path1 || bad_path2))
3479 unix_ERR_class = ERRDOS;
3480 unix_ERR_code = ERRbadpath;
3482 return(UNIXERROR(ERRDOS,error));
3486 outsize = set_message(outbuf,1,0,True);
3487 SSVAL(outbuf,smb_vwv0,count);
3494 /****************************************************************************
3496 ****************************************************************************/
3497 int reply_setdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3504 cnum = SVAL(inbuf,smb_tid);
3506 snum = Connections[cnum].service;
3507 if (!CAN_SETDIR(snum))
3508 return(ERROR(ERRDOS,ERRnoaccess));
3510 pstrcpy(newdir,smb_buf(inbuf) + 1);
3513 if (strlen(newdir) == 0)
3517 ok = directory_exist(newdir,NULL);
3519 string_set(&Connections[cnum].connectpath,newdir);
3523 return(ERROR(ERRDOS,ERRbadpath));
3525 outsize = set_message(outbuf,0,0,True);
3526 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3528 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3534 /****************************************************************************
3535 reply to a lockingX request
3536 ****************************************************************************/
3537 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3539 int fnum = GETFNUM(inbuf,smb_vwv2);
3540 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3542 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3544 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3545 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3546 uint32 count, offset;
3551 uint32 ecode=0, dummy2;
3552 int eclass=0, dummy1;
3554 cnum = SVAL(inbuf,smb_tid);
3556 CHECK_FNUM(fnum,cnum);
3559 data = smb_buf(inbuf);
3561 /* Check if this is an oplock break on a file
3562 we have granted an oplock on.
3564 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3567 files_struct *fsp = &Files[fnum];
3568 uint32 dev = fsp->fd_ptr->dev;
3569 uint32 inode = fsp->fd_ptr->inode;
3571 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3574 * Make sure we have granted an oplock on this file.
3576 if(!fsp->granted_oplock)
3578 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3579 no oplock granted on this file.\n", fnum));
3580 return ERROR(ERRDOS,ERRlock);
3583 /* Remove the oplock flag from the sharemode. */
3584 lock_share_entry(fsp->cnum, dev, inode, &token);
3585 if(remove_share_oplock( fnum, token)==False) {
3586 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3587 dev = %x, inode = %x\n",
3589 unlock_share_entry(fsp->cnum, dev, inode, token);
3591 unlock_share_entry(fsp->cnum, dev, inode, token);
3593 /* Clear the granted flag and return. */
3594 fsp->granted_oplock = False;
3597 /* if this is a pure oplock break request then don't send a reply */
3598 if (num_locks == 0 && num_ulocks == 0)
3600 /* Sanity check - ensure a pure oplock break is not a
3602 if(CVAL(inbuf,smb_vwv0) != 0xff)
3603 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3604 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3609 /* Data now points at the beginning of the list
3610 of smb_unlkrng structs */
3611 for(i = 0; i < (int)num_ulocks; i++) {
3612 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3613 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3614 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3615 return ERROR(eclass,ecode);
3618 /* Now do any requested locks */
3619 data += 10*num_ulocks;
3620 /* Data now points at the beginning of the list
3621 of smb_lkrng structs */
3622 for(i = 0; i < (int)num_locks; i++) {
3623 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3624 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3625 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3629 /* If any of the above locks failed, then we must unlock
3630 all of the previous locks (X/Open spec). */
3631 if(i != num_locks && num_locks != 0) {
3632 for(; i >= 0; i--) {
3633 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3634 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3635 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3637 return ERROR(eclass,ecode);
3640 set_message(outbuf,2,0,True);
3642 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3643 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3647 return chain_reply(inbuf,outbuf,length,bufsize);
3651 /****************************************************************************
3652 reply to a SMBreadbmpx (read block multiplex) request
3653 ****************************************************************************/
3654 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3661 int outsize, mincount, maxcount;
3666 /* this function doesn't seem to work - disable by default */
3668 return(ERROR(ERRSRV,ERRuseSTD));
3670 outsize = set_message(outbuf,8,0,True);
3672 cnum = SVAL(inbuf,smb_tid);
3673 fnum = GETFNUM(inbuf,smb_vwv0);
3675 CHECK_FNUM(fnum,cnum);
3679 startpos = IVAL(inbuf,smb_vwv1);
3680 maxcount = SVAL(inbuf,smb_vwv3);
3681 mincount = SVAL(inbuf,smb_vwv4);
3683 data = smb_buf(outbuf);
3684 pad = ((long)data)%4;
3685 if (pad) pad = 4 - pad;
3688 max_per_packet = bufsize-(outsize+pad);
3692 if (is_locked(fnum,cnum,maxcount,startpos))
3693 return(ERROR(ERRDOS,ERRlock));
3697 int N = MIN(max_per_packet,tcount-total_read);
3699 nread = read_file(fnum,data,startpos,N);
3701 if (nread <= 0) nread = 0;
3704 tcount = total_read + nread;
3706 set_message(outbuf,8,nread,False);
3707 SIVAL(outbuf,smb_vwv0,startpos);
3708 SSVAL(outbuf,smb_vwv2,tcount);
3709 SSVAL(outbuf,smb_vwv6,nread);
3710 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3712 send_smb(Client,outbuf);
3714 total_read += nread;
3717 while (total_read < tcount);
3723 /****************************************************************************
3724 reply to a SMBwritebmpx (write block multiplex primary) request
3725 ****************************************************************************/
3726 int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3728 int cnum,numtowrite,fnum;
3732 int tcount, write_through, smb_doff;
3735 cnum = SVAL(inbuf,smb_tid);
3736 fnum = GETFNUM(inbuf,smb_vwv0);
3738 CHECK_FNUM(fnum,cnum);
3742 tcount = SVAL(inbuf,smb_vwv1);
3743 startpos = IVAL(inbuf,smb_vwv3);
3744 write_through = BITSETW(inbuf+smb_vwv7,0);
3745 numtowrite = SVAL(inbuf,smb_vwv10);
3746 smb_doff = SVAL(inbuf,smb_vwv11);
3748 data = smb_base(inbuf) + smb_doff;
3750 /* If this fails we need to send an SMBwriteC response,
3751 not an SMBwritebmpx - set this up now so we don't forget */
3752 CVAL(outbuf,smb_com) = SMBwritec;
3754 if (is_locked(fnum,cnum,tcount,startpos))
3755 return(ERROR(ERRDOS,ERRlock));
3757 seek_file(fnum,startpos);
3758 nwritten = write_file(fnum,data,numtowrite);
3760 if(lp_syncalways(SNUM(cnum)) || write_through)
3763 if(nwritten < numtowrite)
3764 return(UNIXERROR(ERRHRD,ERRdiskfull));
3766 /* If the maximum to be written to this file
3767 is greater than what we just wrote then set
3768 up a secondary struct to be attached to this
3769 fd, we will use this to cache error messages etc. */
3770 if(tcount > nwritten)
3772 write_bmpx_struct *wbms;
3773 if(Files[fnum].wbmpx_ptr != NULL)
3774 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3776 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3779 DEBUG(0,("Out of memory in reply_readmpx\n"));
3780 return(ERROR(ERRSRV,ERRnoresource));
3782 wbms->wr_mode = write_through;
3783 wbms->wr_discard = False; /* No errors yet */
3784 wbms->wr_total_written = nwritten;
3785 wbms->wr_errclass = 0;
3787 Files[fnum].wbmpx_ptr = wbms;
3790 /* We are returning successfully, set the message type back to
3792 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3794 outsize = set_message(outbuf,1,0,True);
3796 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3798 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3799 timestring(),fnum,cnum,numtowrite,nwritten));
3801 if (write_through && tcount==nwritten) {
3802 /* we need to send both a primary and a secondary response */
3803 smb_setlen(outbuf,outsize - 4);
3804 send_smb(Client,outbuf);
3806 /* now the secondary */
3807 outsize = set_message(outbuf,1,0,True);
3808 CVAL(outbuf,smb_com) = SMBwritec;
3809 SSVAL(outbuf,smb_vwv0,nwritten);
3816 /****************************************************************************
3817 reply to a SMBwritebs (write block multiplex secondary) request
3818 ****************************************************************************/
3819 int reply_writebs(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3821 int cnum,numtowrite,fnum;
3825 int tcount, write_through, smb_doff;
3827 write_bmpx_struct *wbms;
3828 BOOL send_response = False;
3830 cnum = SVAL(inbuf,smb_tid);
3831 fnum = GETFNUM(inbuf,smb_vwv0);
3832 CHECK_FNUM(fnum,cnum);
3835 tcount = SVAL(inbuf,smb_vwv1);
3836 startpos = IVAL(inbuf,smb_vwv2);
3837 numtowrite = SVAL(inbuf,smb_vwv6);
3838 smb_doff = SVAL(inbuf,smb_vwv7);
3840 data = smb_base(inbuf) + smb_doff;
3842 /* We need to send an SMBwriteC response, not an SMBwritebs */
3843 CVAL(outbuf,smb_com) = SMBwritec;
3845 /* This fd should have an auxiliary struct attached,
3846 check that it does */
3847 wbms = Files[fnum].wbmpx_ptr;
3848 if(!wbms) return(-1);
3850 /* If write through is set we can return errors, else we must
3852 write_through = wbms->wr_mode;
3854 /* Check for an earlier error */
3855 if(wbms->wr_discard)
3856 return -1; /* Just discard the packet */
3858 seek_file(fnum,startpos);
3859 nwritten = write_file(fnum,data,numtowrite);
3861 if(lp_syncalways(SNUM(cnum)) || write_through)
3864 if (nwritten < numtowrite)
3867 /* We are returning an error - we can delete the aux struct */
3868 if (wbms) free((char *)wbms);
3869 Files[fnum].wbmpx_ptr = NULL;
3870 return(ERROR(ERRHRD,ERRdiskfull));
3872 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3875 /* Increment the total written, if this matches tcount
3876 we can discard the auxiliary struct (hurrah !) and return a writeC */
3877 wbms->wr_total_written += nwritten;
3878 if(wbms->wr_total_written >= tcount)
3880 if (write_through) {
3881 outsize = set_message(outbuf,1,0,True);
3882 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3883 send_response = True;
3887 Files[fnum].wbmpx_ptr = NULL;
3897 /****************************************************************************
3898 reply to a SMBsetattrE
3899 ****************************************************************************/
3900 int reply_setattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3903 struct utimbuf unix_times;
3906 outsize = set_message(outbuf,0,0,True);
3908 cnum = SVAL(inbuf,smb_tid);
3909 fnum = GETFNUM(inbuf,smb_vwv0);
3911 CHECK_FNUM(fnum,cnum);
3914 /* Convert the DOS times into unix times. Ignore create
3915 time as UNIX can't set this.
3917 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3918 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3921 * Patch from Ray Frush <frush@engr.colostate.edu>
3922 * Sometimes times are sent as zero - ignore them.
3925 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3927 /* Ignore request */
3928 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3929 not setting timestamps of 0\n",
3930 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3933 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3935 /* set modify time = to access time if modify time was 0 */
3936 unix_times.modtime = unix_times.actime;
3939 /* Set the date on this file */
3940 if(file_utime(cnum, Files[fnum].name, &unix_times))
3941 return(ERROR(ERRDOS,ERRnoaccess));
3943 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3944 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3950 /****************************************************************************
3951 reply to a SMBgetattrE
3952 ****************************************************************************/
3953 int reply_getattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3960 outsize = set_message(outbuf,11,0,True);
3962 cnum = SVAL(inbuf,smb_tid);
3963 fnum = GETFNUM(inbuf,smb_vwv0);
3965 CHECK_FNUM(fnum,cnum);
3968 /* Do an fstat on this file */
3969 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3970 return(UNIXERROR(ERRDOS,ERRnoaccess));
3972 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3974 /* Convert the times into dos times. Set create
3975 date to be last modify date as UNIX doesn't save
3977 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
3978 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3979 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3982 SIVAL(outbuf,smb_vwv6,0);
3983 SIVAL(outbuf,smb_vwv8,0);
3987 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3988 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3990 SSVAL(outbuf,smb_vwv10, mode);
3992 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));