2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1997
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 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,("ERROR: Invalid password length %d\n", 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()));
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;
85 case 0x81: /* session request */
86 CVAL(outbuf,0) = 0x82;
88 if (name_len(inbuf+4) > 50 ||
89 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
90 DEBUG(0,("Invalid name length in session request\n"));
93 name_extract(inbuf,4,name1);
94 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
95 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
98 fstrcpy(remote_machine,name2);
99 trim_string(remote_machine," "," ");
100 p = strchr(remote_machine,' ');
101 strlower(remote_machine);
104 fstrcpy(local_machine,name1);
105 trim_string(local_machine," "," ");
106 len = strlen(local_machine);
108 name_type = local_machine[15];
109 local_machine[15] = 0;
111 p = strchr(local_machine,' ');
112 strlower(local_machine);
115 if (name_type == 'R') {
116 /* We are being asked for a pathworks session ---
118 CVAL(outbuf, 0) = 0x83;
122 add_session_user(remote_machine);
124 reload_services(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)
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 = "SAMBA";
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)
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));
374 /****************************************************************************
375 reply to a session setup command
376 ****************************************************************************/
377 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
386 int smb_apasslen = 0;
388 int smb_ntpasslen = 0;
389 pstring smb_ntpasswd;
390 BOOL valid_nt_password = False;
393 BOOL computer_id=False;
394 static BOOL done_sesssetup = False;
395 BOOL doencrypt = SMBENCRYPT();
401 smb_bufsize = SVAL(inbuf,smb_vwv2);
402 smb_mpxmax = SVAL(inbuf,smb_vwv3);
403 smb_vc_num = SVAL(inbuf,smb_vwv4);
404 smb_sesskey = IVAL(inbuf,smb_vwv5);
406 if (Protocol < PROTOCOL_NT1) {
407 smb_apasslen = SVAL(inbuf,smb_vwv7);
408 if (smb_apasslen > MAX_PASS_LEN)
410 overflow_attack(smb_apasslen);
413 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
414 smb_apasswd[smb_apasslen] = 0;
415 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
417 if (!doencrypt && (lp_security() != SEC_SERVER)) {
418 smb_apasslen = strlen(smb_apasswd);
421 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
422 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
423 uint32 client_caps = IVAL(inbuf,smb_vwv11);
424 enum remote_arch_types ra_type = get_remote_arch();
426 char *p = smb_buf(inbuf);
428 /* client_caps is used as final determination if client is NT or Win95.
429 This is needed to return the correct error codes in some
433 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
435 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
436 set_remote_arch( RA_WINNT);
438 set_remote_arch( RA_WIN95);
441 if (passlen1 != 24 && passlen2 != 24)
444 if (passlen1 > MAX_PASS_LEN) {
445 overflow_attack(passlen1);
448 passlen1 = MIN(passlen1, MAX_PASS_LEN);
449 passlen2 = MIN(passlen2, MAX_PASS_LEN);
451 if(doencrypt || (lp_security() == SEC_SERVER)) {
452 /* Save the lanman2 password and the NT md4 password. */
453 smb_apasslen = passlen1;
454 memcpy(smb_apasswd,p,smb_apasslen);
455 smb_apasswd[smb_apasslen] = 0;
456 smb_ntpasslen = passlen2;
457 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
458 smb_ntpasswd[smb_ntpasslen] = 0;
460 /* both Win95 and WinNT stuff up the password lengths for
461 non-encrypting systems. Uggh.
463 if passlen1==24 its a win95 system, and its setting the
464 password length incorrectly. Luckily it still works with the
465 default code because Win95 will null terminate the password
468 if passlen1>0 and passlen2>0 then maybe its a NT box and its
469 setting passlen2 to some random value which really stuffs
470 things up. we need to fix that one. */
471 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
475 /* we use the first password that they gave */
476 smb_apasslen = passlen1;
477 StrnCpy(smb_apasswd,p,smb_apasslen);
479 /* trim the password */
480 smb_apasslen = strlen(smb_apasswd);
482 /* wfwg sometimes uses a space instead of a null */
483 if (strequal(smb_apasswd," ")) {
489 p += passlen1 + passlen2;
490 fstrcpy(user,p); p = skip_string(p,1);
493 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
494 domain,skip_string(p,1),skip_string(p,2)));
498 DEBUG(3,("sesssetupX:name=[%s]\n",user));
500 /* If name ends in $ then I think it's asking about whether a */
501 /* computer with that name (minus the $) has access. For now */
502 /* say yes to everything ending in $. */
503 if (user[strlen(user) - 1] == '$')
506 struct smb_passwd *smb_pass; /* To check if machine account exists */
508 PAXX: Ack. We don't want to do this. The workstation trust account
509 with a $ on the end should exist in the local password database
510 or be mapped to something generic, but not modified. For NT
511 domain support we must reject this used in certain circumstances
512 with a code to indicate to the client that it is an invalid use
513 of a workstation trust account. NTWKS needs this error to join
514 a domain. This may be the source of future bugs if we cannot
515 be sure whether to reject this or not.
517 /* non-null user name indicates search by username not by smb userid */
518 smb_pass = get_smbpwd_entry(user, 0);
522 /* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */
523 DEBUG(4,("Workstation trust account %s doesn't exist.",user));
524 SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
525 CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
526 return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */
530 /* PAXX: This is the NO LOGON workstation trust account stuff */
531 /* lkclXXXX: if the workstation *does* exist, indicate failure differently! */
532 DEBUG(4,("No Workstation trust account %s",user));
533 SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
534 CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
535 return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */
539 #else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */
540 user[strlen(user) - 1] = '\0';
545 /* If no username is sent use the guest account */
548 strcpy(user,lp_guestaccount(-1));
549 /* If no user and no password then set guest flag. */
550 if( *smb_apasswd == 0)
556 strcpy(sesssetup_user,user);
558 reload_services(True);
560 add_session_user(user);
562 /* Check if the given username was the guest user with no password.
563 We need to do this check after add_session_user() as that
564 call can potentially change the username (via map_user).
567 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
570 if (!guest && !(lp_security() == SEC_SERVER &&
571 server_validate(user, domain,
572 smb_apasswd, smb_apasslen,
573 smb_ntpasswd, smb_ntpasslen)) &&
574 !check_hosts_equiv(user))
577 /* now check if it's a valid username/password */
578 /* If an NT password was supplied try and validate with that
579 first. This is superior as the passwords are mixed case
580 128 length unicode */
583 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
584 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
586 valid_nt_password = True;
588 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
590 if (!computer_id && lp_security() >= SEC_USER) {
591 #if (GUEST_SESSSETUP == 0)
592 return(ERROR(ERRSRV,ERRbadpw));
594 #if (GUEST_SESSSETUP == 1)
595 if (Get_Pwnam(user,True))
596 return(ERROR(ERRSRV,ERRbadpw));
599 if (*smb_apasswd || !Get_Pwnam(user,True))
600 strcpy(user,lp_guestaccount(-1));
601 DEBUG(3,("Registered username %s for guest access\n",user));
606 if (!Get_Pwnam(user,True)) {
607 DEBUG(3,("No such user %s - using guest account\n",user));
608 strcpy(user,lp_guestaccount(-1));
612 if (!strequal(user,lp_guestaccount(-1)) &&
613 lp_servicenumber(user) < 0)
615 int homes = lp_servicenumber(HOMES_NAME);
616 char *home = get_home_dir(user);
617 if (homes >= 0 && home)
618 lp_add_home(user,homes,home);
622 /* it's ok - setup a reply */
623 if (Protocol < PROTOCOL_NT1) {
624 set_message(outbuf,3,0,True);
627 set_message(outbuf,3,3,True);
629 strcpy(p,"Unix"); p = skip_string(p,1);
630 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
631 strcpy(p,myworkgroup); p = skip_string(p,1);
632 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
633 /* perhaps grab OS version here?? */
636 /* Set the correct uid in the outgoing and incoming packets
637 We will use this on future requests to determine which
638 user we should become.
641 struct passwd *pw = Get_Pwnam(user,False);
643 DEBUG(1,("Username %s is invalid on this system\n",user));
644 return(ERROR(ERRSRV,ERRbadpw));
650 if (guest && !computer_id)
651 SSVAL(outbuf,smb_vwv2,1);
653 /* register the name and uid as being validated, so further connections
654 to a uid can get through without a password, on the same VC */
655 sess_vuid = register_vuid(uid,gid,user,guest);
657 SSVAL(outbuf,smb_uid,sess_vuid);
658 SSVAL(inbuf,smb_uid,sess_vuid);
661 max_send = MIN(max_send,smb_bufsize);
663 DEBUG(6,("Client requested max send size of %d\n", max_send));
665 done_sesssetup = True;
667 return chain_reply(inbuf,outbuf,length,bufsize);
671 /****************************************************************************
673 ****************************************************************************/
674 int reply_chkpth(char *inbuf,char *outbuf)
680 BOOL bad_path = False;
682 cnum = SVAL(inbuf,smb_tid);
684 pstrcpy(name,smb_buf(inbuf) + 1);
685 unix_convert(name,cnum,0,&bad_path);
687 mode = SVAL(inbuf,smb_vwv0);
689 if (check_name(name,cnum))
690 ok = directory_exist(name,NULL);
694 /* We special case this - as when a Windows machine
695 is parsing a path is steps through the components
696 one at a time - if a component fails it expects
697 ERRbadpath, not ERRbadfile.
701 unix_ERR_class = ERRDOS;
702 unix_ERR_code = ERRbadpath;
706 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
707 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
708 (get_remote_arch() == RA_WINNT))
710 unix_ERR_class = ERRDOS;
711 unix_ERR_code = ERRbaddirectory;
715 return(UNIXERROR(ERRDOS,ERRbadpath));
718 outsize = set_message(outbuf,0,0,True);
720 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
726 /****************************************************************************
728 ****************************************************************************/
729 int reply_getatr(char *inbuf,char *outbuf)
739 BOOL bad_path = False;
741 cnum = SVAL(inbuf,smb_tid);
743 pstrcpy(fname,smb_buf(inbuf) + 1);
744 unix_convert(fname,cnum,0,&bad_path);
746 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
747 under WfWg - weird! */
750 mode = aHIDDEN | aDIR;
751 if (!CAN_WRITE(cnum)) mode |= aRONLY;
757 if (check_name(fname,cnum))
759 if (sys_stat(fname,&sbuf) == 0)
761 mode = dos_mode(cnum,fname,&sbuf);
763 mtime = sbuf.st_mtime;
769 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
774 if((errno == ENOENT) && bad_path)
776 unix_ERR_class = ERRDOS;
777 unix_ERR_code = ERRbadpath;
780 return(UNIXERROR(ERRDOS,ERRbadfile));
783 outsize = set_message(outbuf,10,0,True);
785 SSVAL(outbuf,smb_vwv0,mode);
786 put_dos_date3(outbuf,smb_vwv1,mtime);
787 SIVAL(outbuf,smb_vwv3,size);
789 if (Protocol >= PROTOCOL_NT1) {
790 char *p = strrchr(fname,'/');
791 uint16 flg2 = SVAL(outbuf,smb_flg2);
793 if (!is_8_3(fname, True))
794 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
797 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
803 /****************************************************************************
805 ****************************************************************************/
806 int reply_setatr(char *inbuf,char *outbuf)
814 BOOL bad_path = False;
816 cnum = SVAL(inbuf,smb_tid);
818 pstrcpy(fname,smb_buf(inbuf) + 1);
819 unix_convert(fname,cnum,0,&bad_path);
821 mode = SVAL(inbuf,smb_vwv0);
822 mtime = make_unix_date3(inbuf+smb_vwv1);
824 if (directory_exist(fname,NULL))
826 if (check_name(fname,cnum))
827 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
829 ok = set_filetime(cnum,fname,mtime);
833 if((errno == ENOENT) && bad_path)
835 unix_ERR_class = ERRDOS;
836 unix_ERR_code = ERRbadpath;
839 return(UNIXERROR(ERRDOS,ERRnoaccess));
842 outsize = set_message(outbuf,0,0,True);
844 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
850 /****************************************************************************
852 ****************************************************************************/
853 int reply_dskattr(char *inbuf,char *outbuf)
857 int dfree,dsize,bsize;
859 cnum = SVAL(inbuf,smb_tid);
861 sys_disk_free(".",&bsize,&dfree,&dsize);
863 outsize = set_message(outbuf,5,0,True);
865 SSVAL(outbuf,smb_vwv0,dsize);
866 SSVAL(outbuf,smb_vwv1,bsize/512);
867 SSVAL(outbuf,smb_vwv2,512);
868 SSVAL(outbuf,smb_vwv3,dfree);
870 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
876 /****************************************************************************
878 Can be called from SMBsearch, SMBffirst or SMBfunique.
879 ****************************************************************************/
880 int reply_search(char *inbuf,char *outbuf)
891 BOOL finished = False;
900 BOOL check_descend = False;
901 BOOL expect_close = False;
902 BOOL can_open = True;
903 BOOL bad_path = False;
905 *mask = *directory = *fname = 0;
907 /* If we were called as SMBffirst then we must expect close. */
908 if(CVAL(inbuf,smb_com) == SMBffirst)
911 cnum = SVAL(inbuf,smb_tid);
913 outsize = set_message(outbuf,1,3,True);
914 maxentries = SVAL(inbuf,smb_vwv0);
915 dirtype = SVAL(inbuf,smb_vwv1);
916 path = smb_buf(inbuf) + 1;
917 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
920 /* dirtype &= ~aDIR; */
922 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
929 pstrcpy(directory,smb_buf(inbuf)+1);
930 pstrcpy(dir2,smb_buf(inbuf)+1);
931 unix_convert(directory,cnum,0,&bad_path);
934 if (!check_name(directory,cnum))
937 p = strrchr(dir2,'/');
949 p = strrchr(directory,'/');
955 if (strlen(directory) == 0)
956 strcpy(directory,"./");
958 CVAL(status,0) = dirtype;
962 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
963 memcpy(mask,status+1,11);
965 dirtype = CVAL(status,0) & 0x1F;
966 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
967 if (!Connections[cnum].dirptr)
969 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
974 /* turn strings of spaces into a . */
976 trim_string(mask,NULL," ");
977 if ((p = strrchr(mask,' ')))
982 trim_string(mask,NULL," ");
989 for (p=mask; *p; p++)
991 if (*p != '?' && *p != '*' && !isdoschar(*p))
993 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
999 if (!strchr(mask,'.') && strlen(mask)>8)
1002 fstrcpy(tmp,&mask[8]);
1008 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1012 p = smb_buf(outbuf) + 3;
1016 if (status_len == 0)
1018 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
1023 if((errno == ENOENT) && bad_path)
1025 unix_ERR_class = ERRDOS;
1026 unix_ERR_code = ERRbadpath;
1028 return (UNIXERROR(ERRDOS,ERRnofids));
1030 return(ERROR(ERRDOS,ERRnofids));
1034 DEBUG(4,("dptr_num is %d\n",dptr_num));
1038 if ((dirtype&0x1F) == aVOLID)
1040 memcpy(p,status,21);
1041 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
1042 dptr_fill(p+12,dptr_num);
1043 if (dptr_zero(p+12) && (status_len==0))
1047 p += DIR_STRUCT_SIZE;
1051 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
1052 if (in_list(Connections[cnum].dirpath,
1053 lp_dontdescend(SNUM(cnum)),True))
1054 check_descend = True;
1056 for (i=numentries;(i<maxentries) && !finished;i++)
1059 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
1062 memcpy(p,status,21);
1063 make_dir_struct(p,mask,fname,size,mode,date);
1064 dptr_fill(p+12,dptr_num);
1067 p += DIR_STRUCT_SIZE;
1076 if (numentries == 0 || !ok)
1078 CVAL(outbuf,smb_rcls) = ERRDOS;
1079 SSVAL(outbuf,smb_err,ERRnofiles);
1082 /* If we were called as SMBffirst with smb_search_id == NULL
1083 and no entries were found then return error and close dirptr
1086 if(ok && expect_close && numentries == 0 && status_len == 0)
1088 CVAL(outbuf,smb_rcls) = ERRDOS;
1089 SSVAL(outbuf,smb_err,ERRnofiles);
1090 /* Also close the dptr - we know it's gone */
1091 dptr_close(dptr_num);
1094 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1095 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1096 dptr_close(dptr_num);
1098 SSVAL(outbuf,smb_vwv0,numentries);
1099 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1100 CVAL(smb_buf(outbuf),0) = 5;
1101 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1103 if (Protocol >= PROTOCOL_NT1) {
1104 uint16 flg2 = SVAL(outbuf,smb_flg2);
1105 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1108 outsize += DIR_STRUCT_SIZE*numentries;
1109 smb_setlen(outbuf,outsize - 4);
1111 if ((! *directory) && dptr_path(dptr_num))
1112 sprintf(directory,"(%s)",dptr_path(dptr_num));
1114 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1116 smb_fn_name(CVAL(inbuf,smb_com)),
1117 mask,directory,cnum,dirtype,numentries,maxentries));
1123 /****************************************************************************
1124 reply to a fclose (stop directory search)
1125 ****************************************************************************/
1126 int reply_fclose(char *inbuf,char *outbuf)
1135 cnum = SVAL(inbuf,smb_tid);
1137 outsize = set_message(outbuf,1,0,True);
1138 path = smb_buf(inbuf) + 1;
1139 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1142 if (status_len == 0)
1143 return(ERROR(ERRSRV,ERRsrverror));
1145 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1147 if(dptr_fetch(status+12,&dptr_num)) {
1148 /* Close the dptr - we know it's gone */
1149 dptr_close(dptr_num);
1152 SSVAL(outbuf,smb_vwv0,0);
1154 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1160 /****************************************************************************
1162 ****************************************************************************/
1163 int reply_open(char *inbuf,char *outbuf)
1176 BOOL bad_path = False;
1178 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1180 cnum = SVAL(inbuf,smb_tid);
1182 share_mode = SVAL(inbuf,smb_vwv0);
1184 pstrcpy(fname,smb_buf(inbuf)+1);
1185 unix_convert(fname,cnum,0,&bad_path);
1187 fnum = find_free_file();
1189 return(ERROR(ERRSRV,ERRnofids));
1191 if (!check_name(fname,cnum))
1193 if((errno == ENOENT) && bad_path)
1195 unix_ERR_class = ERRDOS;
1196 unix_ERR_code = ERRbadpath;
1198 return(UNIXERROR(ERRDOS,ERRnoaccess));
1201 unixmode = unix_mode(cnum,aARCH);
1203 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1204 oplock_request,&rmode,NULL);
1210 if((errno == ENOENT) && bad_path)
1212 unix_ERR_class = ERRDOS;
1213 unix_ERR_code = ERRbadpath;
1215 return(UNIXERROR(ERRDOS,ERRnoaccess));
1218 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1219 close_file(fnum,False);
1220 return(ERROR(ERRDOS,ERRnoaccess));
1223 size = sbuf.st_size;
1224 fmode = dos_mode(cnum,fname,&sbuf);
1225 mtime = sbuf.st_mtime;
1228 DEBUG(3,("attempt to open a directory %s\n",fname));
1229 close_file(fnum,False);
1230 return(ERROR(ERRDOS,ERRnoaccess));
1233 outsize = set_message(outbuf,7,0,True);
1234 SSVAL(outbuf,smb_vwv0,fnum);
1235 SSVAL(outbuf,smb_vwv1,fmode);
1236 put_dos_date3(outbuf,smb_vwv2,mtime);
1237 SIVAL(outbuf,smb_vwv4,size);
1238 SSVAL(outbuf,smb_vwv6,rmode);
1240 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1241 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1244 if(fsp->granted_oplock)
1245 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1250 /****************************************************************************
1251 reply to an open and X
1252 ****************************************************************************/
1253 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1256 int cnum = SVAL(inbuf,smb_tid);
1258 int smb_mode = SVAL(inbuf,smb_vwv3);
1259 int smb_attr = SVAL(inbuf,smb_vwv5);
1260 /* Breakout the oplock request bits so we can set the
1261 reply bits separately. */
1262 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1263 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1264 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1266 int open_flags = SVAL(inbuf,smb_vwv2);
1267 int smb_sattr = SVAL(inbuf,smb_vwv4);
1268 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1270 int smb_ofun = SVAL(inbuf,smb_vwv8);
1272 int size=0,fmode=0,mtime=0,rmode=0;
1275 BOOL bad_path = False;
1278 /* If it's an IPC, pass off the pipe handler. */
1280 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1282 /* XXXX we need to handle passed times, sattr and flags */
1284 pstrcpy(fname,smb_buf(inbuf));
1285 unix_convert(fname,cnum,0,&bad_path);
1287 fnum = find_free_file();
1289 return(ERROR(ERRSRV,ERRnofids));
1291 if (!check_name(fname,cnum))
1293 if((errno == ENOENT) && bad_path)
1295 unix_ERR_class = ERRDOS;
1296 unix_ERR_code = ERRbadpath;
1298 return(UNIXERROR(ERRDOS,ERRnoaccess));
1301 unixmode = unix_mode(cnum,smb_attr | aARCH);
1303 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1304 oplock_request, &rmode,&smb_action);
1310 if((errno == ENOENT) && bad_path)
1312 unix_ERR_class = ERRDOS;
1313 unix_ERR_code = ERRbadpath;
1315 return(UNIXERROR(ERRDOS,ERRnoaccess));
1318 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1319 close_file(fnum,False);
1320 return(ERROR(ERRDOS,ERRnoaccess));
1323 size = sbuf.st_size;
1324 fmode = dos_mode(cnum,fname,&sbuf);
1325 mtime = sbuf.st_mtime;
1327 close_file(fnum,False);
1328 return(ERROR(ERRDOS,ERRnoaccess));
1331 /* If the caller set the extended oplock request bit
1332 and we granted one (by whatever means) - set the
1333 correct bit for extended oplock reply.
1336 if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1337 smb_action |= EXTENDED_OPLOCK_GRANTED;
1340 if(ex_oplock_request && fsp->granted_oplock) {
1341 smb_action |= EXTENDED_OPLOCK_GRANTED;
1344 /* If the caller set the core oplock request bit
1345 and we granted one (by whatever means) - set the
1346 correct bit for core oplock reply.
1349 if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1350 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1353 if(core_oplock_request && fsp->granted_oplock) {
1354 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1357 set_message(outbuf,15,0,True);
1358 SSVAL(outbuf,smb_vwv2,fnum);
1359 SSVAL(outbuf,smb_vwv3,fmode);
1360 put_dos_date3(outbuf,smb_vwv4,mtime);
1361 SIVAL(outbuf,smb_vwv6,size);
1362 SSVAL(outbuf,smb_vwv8,rmode);
1363 SSVAL(outbuf,smb_vwv11,smb_action);
1367 return chain_reply(inbuf,outbuf,length,bufsize);
1371 /****************************************************************************
1372 reply to a SMBulogoffX
1373 ****************************************************************************/
1374 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1376 uint16 vuid = SVAL(inbuf,smb_uid);
1377 user_struct *vuser = get_valid_user_struct(vuid);
1380 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1383 /* in user level security we are supposed to close any files
1384 open by this user */
1385 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1387 for (i=0;i<MAX_OPEN_FILES;i++)
1388 if (Files[i].uid == vuser->uid && Files[i].open) {
1389 close_file(i,False);
1393 invalidate_vuid(vuid);
1395 set_message(outbuf,2,0,True);
1397 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1399 return chain_reply(inbuf,outbuf,length,bufsize);
1403 /****************************************************************************
1404 reply to a mknew or a create
1405 ****************************************************************************/
1406 int reply_mknew(char *inbuf,char *outbuf)
1415 BOOL bad_path = False;
1417 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1419 com = SVAL(inbuf,smb_com);
1420 cnum = SVAL(inbuf,smb_tid);
1422 createmode = SVAL(inbuf,smb_vwv0);
1423 pstrcpy(fname,smb_buf(inbuf)+1);
1424 unix_convert(fname,cnum,0,&bad_path);
1426 if (createmode & aVOLID)
1428 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1431 unixmode = unix_mode(cnum,createmode);
1433 fnum = find_free_file();
1435 return(ERROR(ERRSRV,ERRnofids));
1437 if (!check_name(fname,cnum))
1439 if((errno == ENOENT) && bad_path)
1441 unix_ERR_class = ERRDOS;
1442 unix_ERR_code = ERRbadpath;
1444 return(UNIXERROR(ERRDOS,ERRnoaccess));
1449 /* We should fail if file exists. */
1454 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1458 /* Open file in dos compatibility share mode. */
1459 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1460 oplock_request, NULL, NULL);
1466 if((errno == ENOENT) && bad_path)
1468 unix_ERR_class = ERRDOS;
1469 unix_ERR_code = ERRbadpath;
1471 return(UNIXERROR(ERRDOS,ERRnoaccess));
1474 outsize = set_message(outbuf,1,0,True);
1475 SSVAL(outbuf,smb_vwv0,fnum);
1477 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1478 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1481 if(fsp->granted_oplock)
1482 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1484 DEBUG(2,("new file %s\n",fname));
1485 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));
1491 /****************************************************************************
1492 reply to a create temporary file
1493 ****************************************************************************/
1494 int reply_ctemp(char *inbuf,char *outbuf)
1503 BOOL bad_path = False;
1505 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1507 cnum = SVAL(inbuf,smb_tid);
1508 createmode = SVAL(inbuf,smb_vwv0);
1509 pstrcpy(fname,smb_buf(inbuf)+1);
1510 strcat(fname,"/TMXXXXXX");
1511 unix_convert(fname,cnum,0,&bad_path);
1513 unixmode = unix_mode(cnum,createmode);
1515 fnum = find_free_file();
1517 return(ERROR(ERRSRV,ERRnofids));
1519 if (!check_name(fname,cnum))
1521 if((errno == ENOENT) && bad_path)
1523 unix_ERR_class = ERRDOS;
1524 unix_ERR_code = ERRbadpath;
1526 return(UNIXERROR(ERRDOS,ERRnoaccess));
1529 strcpy(fname2,(char *)mktemp(fname));
1531 /* Open file in dos compatibility share mode. */
1532 /* We should fail if file exists. */
1533 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1534 oplock_request, NULL, NULL);
1540 if((errno == ENOENT) && bad_path)
1542 unix_ERR_class = ERRDOS;
1543 unix_ERR_code = ERRbadpath;
1545 return(UNIXERROR(ERRDOS,ERRnoaccess));
1548 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1549 SSVAL(outbuf,smb_vwv0,fnum);
1550 CVAL(smb_buf(outbuf),0) = 4;
1551 strcpy(smb_buf(outbuf) + 1,fname2);
1553 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1554 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1557 if(fsp->granted_oplock)
1558 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1560 DEBUG(2,("created temp file %s\n",fname2));
1561 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));
1567 /*******************************************************************
1568 check if a user is allowed to delete a file
1569 ********************************************************************/
1570 static BOOL can_delete(char *fname,int cnum,int dirtype)
1575 if (!CAN_WRITE(cnum)) return(False);
1577 if (sys_lstat(fname,&sbuf) != 0) return(False);
1578 fmode = dos_mode(cnum,fname,&sbuf);
1579 if (fmode & aDIR) return(False);
1580 if (!lp_delete_readonly(SNUM(cnum))) {
1581 if (fmode & aRONLY) return(False);
1583 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1585 if (!check_file_sharing(cnum,fname)) return(False);
1589 /****************************************************************************
1591 ****************************************************************************/
1592 int reply_unlink(char *inbuf,char *outbuf)
1602 int error = ERRnoaccess;
1605 BOOL bad_path = False;
1607 *directory = *mask = 0;
1609 cnum = SVAL(inbuf,smb_tid);
1610 dirtype = SVAL(inbuf,smb_vwv0);
1612 pstrcpy(name,smb_buf(inbuf) + 1);
1614 DEBUG(3,("reply_unlink : %s\n",name));
1616 unix_convert(name,cnum,0,&bad_path);
1618 p = strrchr(name,'/');
1620 strcpy(directory,"./");
1624 strcpy(directory,name);
1628 if (is_mangled(mask))
1629 check_mangled_stack(mask);
1631 has_wild = strchr(mask,'*') || strchr(mask,'?');
1634 strcat(directory,"/");
1635 strcat(directory,mask);
1636 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1637 if (!count) exists = file_exist(directory,NULL);
1639 void *dirptr = NULL;
1642 if (check_name(directory,cnum))
1643 dirptr = OpenDir(cnum, directory, True);
1645 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1646 the pattern matches against the long name, otherwise the short name
1647 We don't implement this yet XXXX
1654 if (strequal(mask,"????????.???"))
1657 while ((dname = ReadDirName(dirptr)))
1660 pstrcpy(fname,dname);
1662 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1664 error = ERRnoaccess;
1665 sprintf(fname,"%s/%s",directory,dname);
1666 if (!can_delete(fname,cnum,dirtype)) continue;
1667 if (!sys_unlink(fname)) count++;
1668 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1676 return(ERROR(ERRDOS,error));
1679 if((errno == ENOENT) && bad_path)
1681 unix_ERR_class = ERRDOS;
1682 unix_ERR_code = ERRbadpath;
1684 return(UNIXERROR(ERRDOS,error));
1688 outsize = set_message(outbuf,0,0,True);
1694 /****************************************************************************
1695 reply to a readbraw (core+ protocol)
1696 ****************************************************************************/
1697 int reply_readbraw(char *inbuf, char *outbuf)
1699 int cnum,maxcount,mincount,fnum;
1702 char *header = outbuf;
1708 * Special check if an oplock break has been issued
1709 * and the readraw request croses on the wire, we must
1710 * return a zero length response here.
1713 if(global_oplock_break)
1715 _smb_setlen(header,0);
1716 transfer_file(0,Client,0,header,4,0);
1717 DEBUG(5,("readbraw - oplock break finished\n"));
1721 cnum = SVAL(inbuf,smb_tid);
1722 fnum = GETFNUM(inbuf,smb_vwv0);
1724 startpos = IVAL(inbuf,smb_vwv1);
1725 maxcount = SVAL(inbuf,smb_vwv3);
1726 mincount = SVAL(inbuf,smb_vwv4);
1728 /* ensure we don't overrun the packet size */
1729 maxcount = MIN(65535,maxcount);
1730 maxcount = MAX(mincount,maxcount);
1732 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1734 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1735 _smb_setlen(header,0);
1736 transfer_file(0,Client,0,header,4,0);
1741 fd = Files[fnum].fd_ptr->fd;
1742 fname = Files[fnum].name;
1746 if (!is_locked(fnum,cnum,maxcount,startpos))
1748 int size = Files[fnum].size;
1749 int sizeneeded = startpos + maxcount;
1751 if (size < sizeneeded) {
1753 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1755 if (!Files[fnum].can_write)
1756 Files[fnum].size = size;
1759 nread = MIN(maxcount,(int)(size - startpos));
1762 if (nread < mincount)
1765 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1768 maxcount,mincount,nread));
1773 _smb_setlen(header,nread);
1775 #if USE_READ_PREDICTION
1776 if (!Files[fnum].can_write)
1777 predict = read_predict(fd,startpos,header+4,NULL,nread);
1780 if ((nread-predict) > 0)
1781 seek_file(fnum,startpos + predict);
1783 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1788 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1789 fname,startpos,nread,ret));
1792 ret = read_file(fnum,header+4,startpos,nread);
1793 if (ret < mincount) ret = 0;
1795 _smb_setlen(header,ret);
1796 transfer_file(0,Client,0,header,4+ret,0);
1799 DEBUG(5,("readbraw finished\n"));
1804 /****************************************************************************
1805 reply to a lockread (core+ protocol)
1806 ****************************************************************************/
1807 int reply_lockread(char *inbuf,char *outbuf)
1813 uint32 startpos, numtoread;
1817 cnum = SVAL(inbuf,smb_tid);
1818 fnum = GETFNUM(inbuf,smb_vwv0);
1820 CHECK_FNUM(fnum,cnum);
1824 numtoread = SVAL(inbuf,smb_vwv1);
1825 startpos = IVAL(inbuf,smb_vwv2);
1827 outsize = set_message(outbuf,5,3,True);
1828 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1829 data = smb_buf(outbuf) + 3;
1831 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1832 return (ERROR(eclass,ecode));
1834 nread = read_file(fnum,data,startpos,numtoread);
1837 return(UNIXERROR(ERRDOS,ERRnoaccess));
1840 SSVAL(outbuf,smb_vwv0,nread);
1841 SSVAL(outbuf,smb_vwv5,nread+3);
1842 SSVAL(smb_buf(outbuf),1,nread);
1844 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1850 /****************************************************************************
1852 ****************************************************************************/
1853 int reply_read(char *inbuf,char *outbuf)
1855 int cnum,numtoread,fnum;
1861 cnum = SVAL(inbuf,smb_tid);
1862 fnum = GETFNUM(inbuf,smb_vwv0);
1864 CHECK_FNUM(fnum,cnum);
1868 numtoread = SVAL(inbuf,smb_vwv1);
1869 startpos = IVAL(inbuf,smb_vwv2);
1871 outsize = set_message(outbuf,5,3,True);
1872 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1873 data = smb_buf(outbuf) + 3;
1875 if (is_locked(fnum,cnum,numtoread,startpos))
1876 return(ERROR(ERRDOS,ERRlock));
1879 nread = read_file(fnum,data,startpos,numtoread);
1882 return(UNIXERROR(ERRDOS,ERRnoaccess));
1885 SSVAL(outbuf,smb_vwv0,nread);
1886 SSVAL(outbuf,smb_vwv5,nread+3);
1887 CVAL(smb_buf(outbuf),0) = 1;
1888 SSVAL(smb_buf(outbuf),1,nread);
1890 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1896 /****************************************************************************
1897 reply to a read and X
1898 ****************************************************************************/
1899 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1901 int fnum = GETFNUM(inbuf,smb_vwv2);
1902 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1903 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1904 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1910 cnum = SVAL(inbuf,smb_tid);
1912 CHECK_FNUM(fnum,cnum);
1916 set_message(outbuf,12,0,True);
1917 data = smb_buf(outbuf);
1919 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1920 return(ERROR(ERRDOS,ERRlock));
1921 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1925 return(UNIXERROR(ERRDOS,ERRnoaccess));
1927 SSVAL(outbuf,smb_vwv5,nread);
1928 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1929 SSVAL(smb_buf(outbuf),-2,nread);
1931 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1932 timestring(),fnum,cnum,
1933 smb_mincnt,smb_maxcnt,nread));
1937 return chain_reply(inbuf,outbuf,length,bufsize);
1941 /****************************************************************************
1942 reply to a writebraw (core+ or LANMAN1.0 protocol)
1943 ****************************************************************************/
1944 int reply_writebraw(char *inbuf,char *outbuf)
1947 int total_written=0;
1956 cnum = SVAL(inbuf,smb_tid);
1957 fnum = GETFNUM(inbuf,smb_vwv0);
1959 CHECK_FNUM(fnum,cnum);
1963 tcount = IVAL(inbuf,smb_vwv1);
1964 startpos = IVAL(inbuf,smb_vwv3);
1965 write_through = BITSETW(inbuf+smb_vwv7,0);
1967 /* We have to deal with slightly different formats depending
1968 on whether we are using the core+ or lanman1.0 protocol */
1969 if(Protocol <= PROTOCOL_COREPLUS) {
1970 numtowrite = SVAL(smb_buf(inbuf),-2);
1971 data = smb_buf(inbuf);
1973 numtowrite = SVAL(inbuf,smb_vwv10);
1974 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1977 /* force the error type */
1978 CVAL(inbuf,smb_com) = SMBwritec;
1979 CVAL(outbuf,smb_com) = SMBwritec;
1981 if (is_locked(fnum,cnum,tcount,startpos))
1982 return(ERROR(ERRDOS,ERRlock));
1984 if (seek_file(fnum,startpos) != startpos)
1985 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1988 nwritten = write_file(fnum,data,numtowrite);
1990 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1991 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1993 if (nwritten < numtowrite)
1994 return(UNIXERROR(ERRHRD,ERRdiskfull));
1996 total_written = nwritten;
1998 /* Return a message to the redirector to tell it
1999 to send more bytes */
2000 CVAL(outbuf,smb_com) = SMBwritebraw;
2001 SSVALS(outbuf,smb_vwv0,-1);
2002 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2003 send_smb(Client,outbuf);
2005 /* Now read the raw data into the buffer and write it */
2006 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2007 exit_server("secondary writebraw failed");
2010 /* Even though this is not an smb message, smb_len
2011 returns the generic length of an smb message */
2012 numtowrite = smb_len(inbuf);
2014 if (tcount > nwritten+numtowrite) {
2015 DEBUG(3,("Client overestimated the write %d %d %d\n",
2016 tcount,nwritten,numtowrite));
2019 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
2021 total_written += nwritten;
2023 /* Set up outbuf to return the correct return */
2024 outsize = set_message(outbuf,1,0,True);
2025 CVAL(outbuf,smb_com) = SMBwritec;
2026 SSVAL(outbuf,smb_vwv0,total_written);
2028 if (nwritten < numtowrite) {
2029 CVAL(outbuf,smb_rcls) = ERRHRD;
2030 SSVAL(outbuf,smb_err,ERRdiskfull);
2033 if (lp_syncalways(SNUM(cnum)) || write_through)
2036 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
2037 timestring(),fnum,cnum,startpos,numtowrite,total_written));
2039 /* we won't return a status if write through is not selected - this
2040 follows what WfWg does */
2041 if (!write_through && total_written==tcount)
2048 /****************************************************************************
2049 reply to a writeunlock (core+)
2050 ****************************************************************************/
2051 int reply_writeunlock(char *inbuf,char *outbuf)
2057 uint32 numtowrite,startpos;
2061 cnum = SVAL(inbuf,smb_tid);
2062 fnum = GETFNUM(inbuf,smb_vwv0);
2064 CHECK_FNUM(fnum,cnum);
2068 numtowrite = SVAL(inbuf,smb_vwv1);
2069 startpos = IVAL(inbuf,smb_vwv2);
2070 data = smb_buf(inbuf) + 3;
2072 if (is_locked(fnum,cnum,numtowrite,startpos))
2073 return(ERROR(ERRDOS,ERRlock));
2075 seek_file(fnum,startpos);
2077 /* The special X/Open SMB protocol handling of
2078 zero length writes is *NOT* done for
2083 nwritten = write_file(fnum,data,numtowrite);
2085 if (lp_syncalways(SNUM(cnum)))
2088 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2089 return(UNIXERROR(ERRDOS,ERRnoaccess));
2091 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2092 return(ERROR(eclass,ecode));
2094 outsize = set_message(outbuf,1,0,True);
2096 SSVAL(outbuf,smb_vwv0,nwritten);
2098 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2099 timestring(),fnum,cnum,numtowrite,nwritten));
2105 /****************************************************************************
2107 ****************************************************************************/
2108 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
2110 int cnum,numtowrite,fnum;
2119 cnum = SVAL(inbuf,smb_tid);
2120 fnum = GETFNUM(inbuf,smb_vwv0);
2122 CHECK_FNUM(fnum,cnum);
2126 numtowrite = SVAL(inbuf,smb_vwv1);
2127 startpos = IVAL(inbuf,smb_vwv2);
2128 data = smb_buf(inbuf) + 3;
2130 if (is_locked(fnum,cnum,numtowrite,startpos))
2131 return(ERROR(ERRDOS,ERRlock));
2133 seek_file(fnum,startpos);
2135 /* X/Open SMB protocol says that if smb_vwv1 is
2136 zero then the file size should be extended or
2137 truncated to the size given in smb_vwv[2-3] */
2139 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2141 nwritten = write_file(fnum,data,numtowrite);
2143 if (lp_syncalways(SNUM(cnum)))
2146 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2147 return(UNIXERROR(ERRDOS,ERRnoaccess));
2149 outsize = set_message(outbuf,1,0,True);
2151 SSVAL(outbuf,smb_vwv0,nwritten);
2153 if (nwritten < numtowrite) {
2154 CVAL(outbuf,smb_rcls) = ERRHRD;
2155 SSVAL(outbuf,smb_err,ERRdiskfull);
2158 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2164 /****************************************************************************
2165 reply to a write and X
2166 ****************************************************************************/
2167 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2169 int fnum = GETFNUM(inbuf,smb_vwv2);
2170 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2171 int smb_dsize = SVAL(inbuf,smb_vwv10);
2172 int smb_doff = SVAL(inbuf,smb_vwv11);
2173 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2178 cnum = SVAL(inbuf,smb_tid);
2180 CHECK_FNUM(fnum,cnum);
2184 data = smb_base(inbuf) + smb_doff;
2186 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2187 return(ERROR(ERRDOS,ERRlock));
2189 seek_file(fnum,smb_offs);
2191 /* X/Open SMB protocol says that, unlike SMBwrite
2192 if the length is zero then NO truncation is
2193 done, just a write of zero. To truncate a file,
2198 nwritten = write_file(fnum,data,smb_dsize);
2200 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2201 return(UNIXERROR(ERRDOS,ERRnoaccess));
2203 set_message(outbuf,6,0,True);
2205 SSVAL(outbuf,smb_vwv2,nwritten);
2207 if (nwritten < smb_dsize) {
2208 CVAL(outbuf,smb_rcls) = ERRHRD;
2209 SSVAL(outbuf,smb_err,ERRdiskfull);
2212 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2216 if (lp_syncalways(SNUM(cnum)) || write_through)
2219 return chain_reply(inbuf,outbuf,length,bufsize);
2223 /****************************************************************************
2225 ****************************************************************************/
2226 int reply_lseek(char *inbuf,char *outbuf)
2234 cnum = SVAL(inbuf,smb_tid);
2235 fnum = GETFNUM(inbuf,smb_vwv0);
2237 CHECK_FNUM(fnum,cnum);
2240 mode = SVAL(inbuf,smb_vwv1) & 3;
2241 startpos = IVAL(inbuf,smb_vwv2);
2245 case 0: umode = SEEK_SET; break;
2246 case 1: umode = SEEK_CUR; break;
2247 case 2: umode = SEEK_END; break;
2249 umode = SEEK_SET; break;
2252 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2253 Files[fnum].pos = res;
2255 outsize = set_message(outbuf,2,0,True);
2256 SIVALS(outbuf,smb_vwv0,res);
2258 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2264 /****************************************************************************
2266 ****************************************************************************/
2267 int reply_flush(char *inbuf,char *outbuf)
2270 int outsize = set_message(outbuf,0,0,True);
2272 cnum = SVAL(inbuf,smb_tid);
2273 fnum = GETFNUM(inbuf,smb_vwv0);
2275 if (fnum != 0xFFFF) {
2276 CHECK_FNUM(fnum,cnum);
2283 for (i=0;i<MAX_OPEN_FILES;i++)
2290 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2295 /****************************************************************************
2297 ****************************************************************************/
2298 int reply_exit(char *inbuf,char *outbuf)
2300 int outsize = set_message(outbuf,0,0,True);
2301 DEBUG(3,("%s exit\n",timestring()));
2307 /****************************************************************************
2309 ****************************************************************************/
2310 int reply_close(char *inbuf,char *outbuf)
2315 int32 eclass = 0, err = 0;
2317 outsize = set_message(outbuf,0,0,True);
2319 cnum = SVAL(inbuf,smb_tid);
2321 /* If it's an IPC, pass off to the pipe handler. */
2323 return reply_pipe_close(inbuf,outbuf);
2325 fnum = GETFNUM(inbuf,smb_vwv0);
2327 CHECK_FNUM(fnum,cnum);
2329 if(HAS_CACHED_ERROR(fnum)) {
2330 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2331 err = Files[fnum].wbmpx_ptr->wr_error;
2334 mtime = make_unix_date3(inbuf+smb_vwv1);
2336 /* try and set the date */
2337 set_filetime(cnum, Files[fnum].name,mtime);
2339 close_file(fnum,True);
2341 /* We have a cached error */
2343 return(ERROR(eclass,err));
2345 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2346 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2347 Connections[cnum].num_files_open));
2353 /****************************************************************************
2354 reply to a writeclose (Core+ protocol)
2355 ****************************************************************************/
2356 int reply_writeclose(char *inbuf,char *outbuf)
2358 int cnum,numtowrite,fnum;
2365 cnum = SVAL(inbuf,smb_tid);
2366 fnum = GETFNUM(inbuf,smb_vwv0);
2368 CHECK_FNUM(fnum,cnum);
2372 numtowrite = SVAL(inbuf,smb_vwv1);
2373 startpos = IVAL(inbuf,smb_vwv2);
2374 mtime = make_unix_date3(inbuf+smb_vwv4);
2375 data = smb_buf(inbuf) + 1;
2377 if (is_locked(fnum,cnum,numtowrite,startpos))
2378 return(ERROR(ERRDOS,ERRlock));
2380 seek_file(fnum,startpos);
2382 nwritten = write_file(fnum,data,numtowrite);
2384 set_filetime(cnum, Files[fnum].name,mtime);
2386 close_file(fnum,True);
2388 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2389 timestring(),fnum,cnum,numtowrite,nwritten,
2390 Connections[cnum].num_files_open));
2393 return(UNIXERROR(ERRDOS,ERRnoaccess));
2395 outsize = set_message(outbuf,1,0,True);
2397 SSVAL(outbuf,smb_vwv0,nwritten);
2402 /****************************************************************************
2404 ****************************************************************************/
2405 int reply_lock(char *inbuf,char *outbuf)
2408 int outsize = set_message(outbuf,0,0,True);
2409 uint32 count,offset;
2413 cnum = SVAL(inbuf,smb_tid);
2414 fnum = GETFNUM(inbuf,smb_vwv0);
2416 CHECK_FNUM(fnum,cnum);
2419 count = IVAL(inbuf,smb_vwv1);
2420 offset = IVAL(inbuf,smb_vwv3);
2422 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));
2424 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2425 return (ERROR(eclass,ecode));
2431 /****************************************************************************
2433 ****************************************************************************/
2434 int reply_unlock(char *inbuf,char *outbuf)
2437 int outsize = set_message(outbuf,0,0,True);
2438 uint32 count,offset;
2442 cnum = SVAL(inbuf,smb_tid);
2443 fnum = GETFNUM(inbuf,smb_vwv0);
2445 CHECK_FNUM(fnum,cnum);
2448 count = IVAL(inbuf,smb_vwv1);
2449 offset = IVAL(inbuf,smb_vwv3);
2451 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2452 return (ERROR(eclass,ecode));
2454 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));
2460 /****************************************************************************
2462 ****************************************************************************/
2463 int reply_tdis(char *inbuf,char *outbuf)
2466 int outsize = set_message(outbuf,0,0,True);
2469 cnum = SVAL(inbuf,smb_tid);
2470 vuid = SVAL(inbuf,smb_uid);
2472 if (!OPEN_CNUM(cnum)) {
2473 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2474 return(ERROR(ERRSRV,ERRinvnid));
2477 Connections[cnum].used = False;
2479 close_cnum(cnum,vuid);
2481 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2488 /****************************************************************************
2490 ****************************************************************************/
2491 int reply_echo(char *inbuf,char *outbuf)
2494 int smb_reverb = SVAL(inbuf,smb_vwv0);
2496 int data_len = smb_buflen(inbuf);
2497 int outsize = set_message(outbuf,1,data_len,True);
2499 cnum = SVAL(inbuf,smb_tid);
2501 /* According to the latest CIFS spec we shouldn't
2502 care what the TID is.
2506 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2508 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2509 return(ERROR(ERRSRV,ERRinvnid));
2513 /* copy any incoming data back out */
2515 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2517 if (smb_reverb > 100)
2519 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2523 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2525 SSVAL(outbuf,smb_vwv0,seq_num);
2527 smb_setlen(outbuf,outsize - 4);
2529 send_smb(Client,outbuf);
2532 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2538 /****************************************************************************
2539 reply to a printopen
2540 ****************************************************************************/
2541 int reply_printopen(char *inbuf,char *outbuf)
2549 *fname = *fname2 = 0;
2551 cnum = SVAL(inbuf,smb_tid);
2553 if (!CAN_PRINT(cnum))
2554 return(ERROR(ERRDOS,ERRnoaccess));
2559 pstrcpy(s,smb_buf(inbuf)+1);
2563 if (!(isalnum(*p) || strchr("._-",*p)))
2568 if (strlen(s) > 10) s[10] = 0;
2570 sprintf(fname,"%s.XXXXXX",s);
2573 fnum = find_free_file();
2575 return(ERROR(ERRSRV,ERRnofids));
2577 strcpy(fname2,(char *)mktemp(fname));
2579 if (!check_name(fname2,cnum))
2580 return(ERROR(ERRDOS,ERRnoaccess));
2582 /* Open for exclusive use, write only. */
2583 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2586 if (!Files[fnum].open)
2587 return(UNIXERROR(ERRDOS,ERRnoaccess));
2589 /* force it to be a print file */
2590 Files[fnum].print_file = True;
2592 outsize = set_message(outbuf,1,0,True);
2593 SSVAL(outbuf,smb_vwv0,fnum);
2595 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2601 /****************************************************************************
2602 reply to a printclose
2603 ****************************************************************************/
2604 int reply_printclose(char *inbuf,char *outbuf)
2607 int outsize = set_message(outbuf,0,0,True);
2609 cnum = SVAL(inbuf,smb_tid);
2610 fnum = GETFNUM(inbuf,smb_vwv0);
2612 CHECK_FNUM(fnum,cnum);
2615 if (!CAN_PRINT(cnum))
2616 return(ERROR(ERRDOS,ERRnoaccess));
2618 close_file(fnum,True);
2620 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2626 /****************************************************************************
2627 reply to a printqueue
2628 ****************************************************************************/
2629 int reply_printqueue(char *inbuf,char *outbuf)
2632 int outsize = set_message(outbuf,2,3,True);
2633 int max_count = SVAL(inbuf,smb_vwv0);
2634 int start_index = SVAL(inbuf,smb_vwv1);
2637 cnum = SVAL(inbuf,smb_tid);
2638 vuid = SVAL(inbuf,smb_uid);
2640 /* allow checking the queue for anyone */
2642 if (!CAN_PRINT(cnum))
2643 return(ERROR(ERRDOS,ERRnoaccess));
2646 SSVAL(outbuf,smb_vwv0,0);
2647 SSVAL(outbuf,smb_vwv1,0);
2648 CVAL(smb_buf(outbuf),0) = 1;
2649 SSVAL(smb_buf(outbuf),1,0);
2651 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2652 timestring(),cnum,start_index,max_count));
2654 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2659 for (i=0;i<MAX_CONNECTIONS;i++)
2660 if (CAN_PRINT(i) && Connections[i].printer)
2664 for (i=0;i<MAX_CONNECTIONS;i++)
2668 if (!OPEN_CNUM(cnum))
2669 return(ERROR(ERRSRV,ERRinvnid));
2671 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2674 if (!become_user(&Connections[cnum], cnum, vuid))
2675 return(ERROR(ERRSRV,ERRinvnid));
2678 print_queue_struct *queue = NULL;
2679 char *p = smb_buf(outbuf) + 3;
2680 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2681 int num_to_get = ABS(max_count);
2682 int first = (max_count>0?start_index:start_index+max_count+1);
2688 num_to_get = MIN(num_to_get,count-first);
2691 for (i=first;i<first+num_to_get;i++)
2693 put_dos_date2(p,0,queue[i].time);
2694 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2695 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2696 SIVAL(p,7,queue[i].size);
2698 StrnCpy(p+12,queue[i].user,16);
2704 outsize = set_message(outbuf,2,28*count+3,False);
2705 SSVAL(outbuf,smb_vwv0,count);
2706 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2707 CVAL(smb_buf(outbuf),0) = 1;
2708 SSVAL(smb_buf(outbuf),1,28*count);
2711 if (queue) free(queue);
2713 DEBUG(3,("%d entries returned in queue\n",count));
2720 /****************************************************************************
2721 reply to a printwrite
2722 ****************************************************************************/
2723 int reply_printwrite(char *inbuf,char *outbuf)
2725 int cnum,numtowrite,fnum;
2726 int outsize = set_message(outbuf,0,0,True);
2729 cnum = SVAL(inbuf,smb_tid);
2731 if (!CAN_PRINT(cnum))
2732 return(ERROR(ERRDOS,ERRnoaccess));
2734 fnum = GETFNUM(inbuf,smb_vwv0);
2736 CHECK_FNUM(fnum,cnum);
2740 numtowrite = SVAL(smb_buf(inbuf),1);
2741 data = smb_buf(inbuf) + 3;
2743 if (write_file(fnum,data,numtowrite) != numtowrite)
2744 return(UNIXERROR(ERRDOS,ERRnoaccess));
2746 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2752 /****************************************************************************
2754 ****************************************************************************/
2755 int reply_mkdir(char *inbuf,char *outbuf)
2759 int outsize,ret= -1;
2760 BOOL bad_path = False;
2762 pstrcpy(directory,smb_buf(inbuf) + 1);
2763 cnum = SVAL(inbuf,smb_tid);
2764 unix_convert(directory,cnum,0,&bad_path);
2766 if (check_name(directory,cnum))
2767 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2771 if((errno == ENOENT) && bad_path)
2773 unix_ERR_class = ERRDOS;
2774 unix_ERR_code = ERRbadpath;
2776 return(UNIXERROR(ERRDOS,ERRnoaccess));
2779 outsize = set_message(outbuf,0,0,True);
2781 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2786 /****************************************************************************
2787 Static function used by reply_rmdir to delete an entire directory
2789 ****************************************************************************/
2790 static BOOL recursive_rmdir(char *directory)
2794 void *dirptr = OpenDir(-1, directory, False);
2799 while((dname = ReadDirName(dirptr)))
2804 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2807 /* Construct the full name. */
2808 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2814 strcpy(fullname, directory);
2815 strcat(fullname, "/");
2816 strcat(fullname, dname);
2818 if(sys_lstat(fullname, &st) != 0)
2824 if(st.st_mode & S_IFDIR)
2826 if(recursive_rmdir(fullname)!=0)
2831 if(sys_rmdir(fullname) != 0)
2837 else if(sys_unlink(fullname) != 0)
2847 /****************************************************************************
2849 ****************************************************************************/
2850 int reply_rmdir(char *inbuf,char *outbuf)
2856 BOOL bad_path = False;
2858 cnum = SVAL(inbuf,smb_tid);
2859 pstrcpy(directory,smb_buf(inbuf) + 1);
2860 unix_convert(directory,cnum,0,&bad_path);
2862 if (check_name(directory,cnum))
2865 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2866 ok = (sys_rmdir(directory) == 0);
2867 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2869 /* Check to see if the only thing in this directory are
2870 vetoed files/directories. If so then delete them and
2871 retry. If we fail to delete any of them (and we *don't*
2872 do a recursive delete) then fail the rmdir. */
2873 BOOL all_veto_files = True;
2875 void *dirptr = OpenDir(cnum, directory, False);
2879 int dirpos = TellDir(dirptr);
2880 while ((dname = ReadDirName(dirptr)))
2882 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2884 if(!IS_VETO_PATH(cnum, dname))
2886 all_veto_files = False;
2892 SeekDir(dirptr,dirpos);
2893 while ((dname = ReadDirName(dirptr)))
2898 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2901 /* Construct the full name. */
2902 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2907 pstrcpy(fullname, directory);
2908 strcat(fullname, "/");
2909 strcat(fullname, dname);
2911 if(sys_lstat(fullname, &st) != 0)
2913 if(st.st_mode & S_IFDIR)
2915 if(lp_recursive_veto_delete(SNUM(cnum)))
2917 if(recursive_rmdir(fullname) != 0)
2920 if(sys_rmdir(fullname) != 0)
2923 else if(sys_unlink(fullname) != 0)
2927 /* Retry the rmdir */
2928 ok = (sys_rmdir(directory) == 0);
2938 DEBUG(3,("couldn't remove directory %s : %s\n",
2939 directory,strerror(errno)));
2944 if((errno == ENOENT) && bad_path)
2946 unix_ERR_class = ERRDOS;
2947 unix_ERR_code = ERRbadpath;
2949 return(UNIXERROR(ERRDOS,ERRbadpath));
2952 outsize = set_message(outbuf,0,0,True);
2954 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2960 /*******************************************************************
2961 resolve wildcards in a filename rename
2962 ********************************************************************/
2963 static BOOL resolve_wildcards(char *name1,char *name2)
2965 fstring root1,root2;
2969 name1 = strrchr(name1,'/');
2970 name2 = strrchr(name2,'/');
2972 if (!name1 || !name2) return(False);
2974 fstrcpy(root1,name1);
2975 fstrcpy(root2,name2);
2976 p = strrchr(root1,'.');
2983 p = strrchr(root2,'.');
3015 strcpy(name2,root2);
3024 /*******************************************************************
3025 check if a user is allowed to rename a file
3026 ********************************************************************/
3027 static BOOL can_rename(char *fname,int cnum)
3031 if (!CAN_WRITE(cnum)) return(False);
3033 if (sys_lstat(fname,&sbuf) != 0) return(False);
3034 if (!check_file_sharing(cnum,fname)) return(False);
3039 /****************************************************************************
3041 ****************************************************************************/
3042 int reply_mv(char *inbuf,char *outbuf)
3048 pstring mask,newname;
3049 pstring newname_last_component;
3052 int error = ERRnoaccess;
3055 BOOL bad_path1 = False;
3056 BOOL bad_path2 = False;
3058 *directory = *mask = 0;
3060 cnum = SVAL(inbuf,smb_tid);
3062 pstrcpy(name,smb_buf(inbuf) + 1);
3063 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3065 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3067 unix_convert(name,cnum,0,&bad_path1);
3068 unix_convert(newname,cnum,newname_last_component,&bad_path2);
3071 * Split the old name into directory and last component
3072 * strings. Note that unix_convert may have stripped off a
3073 * leading ./ from both name and newname if the rename is
3074 * at the root of the share. We need to make sure either both
3075 * name and newname contain a / character or neither of them do
3076 * as this is checked in resolve_wildcards().
3079 p = strrchr(name,'/');
3081 strcpy(directory,".");
3085 strcpy(directory,name);
3087 *p = '/'; /* Replace needed for exceptional test below. */
3090 if (is_mangled(mask))
3091 check_mangled_stack(mask);
3093 has_wild = strchr(mask,'*') || strchr(mask,'?');
3096 BOOL is_short_name = is_8_3(name, True);
3098 /* Add a terminating '/' to the directory name. */
3099 strcat(directory,"/");
3100 strcat(directory,mask);
3102 /* Ensure newname contains a '/' also */
3103 if(strrchr(newname,'/') == 0) {
3106 strcpy(tmpstr, "./");
3107 strcat(tmpstr, newname);
3108 strcpy(newname, tmpstr);
3111 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",
3112 case_sensitive, case_preserve, short_case_preserve, directory,
3113 newname, newname_last_component, is_short_name));
3116 * Check for special case with case preserving and not
3117 * case sensitive, if directory and newname are identical,
3118 * and the old last component differs from the original
3119 * last component only by case, then we should allow
3120 * the rename (user is trying to change the case of the
3123 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3124 ((short_case_preserve == True) && (is_short_name == True))) &&
3125 strcsequal(directory, newname)) {
3126 pstring newname_modified_last_component;
3129 * Get the last component of the modified name.
3130 * Note that we guarantee that newname contains a '/'
3133 p = strrchr(newname,'/');
3134 strcpy(newname_modified_last_component,p+1);
3136 if(strcsequal(newname_modified_last_component,
3137 newname_last_component) == False) {
3139 * Replace the modified last component with
3142 strcpy(p+1, newname_last_component);
3146 if (resolve_wildcards(directory,newname) &&
3147 can_rename(directory,cnum) &&
3148 !file_exist(newname,NULL) &&
3149 !sys_rename(directory,newname)) count++;
3151 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3152 directory,newname));
3154 if (!count) exists = file_exist(directory,NULL);
3155 if (!count && exists && file_exist(newname,NULL)) {
3160 void *dirptr = NULL;
3164 if (check_name(directory,cnum))
3165 dirptr = OpenDir(cnum, directory, True);
3171 if (strequal(mask,"????????.???"))
3174 while ((dname = ReadDirName(dirptr)))
3177 pstrcpy(fname,dname);
3179 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3181 error = ERRnoaccess;
3182 sprintf(fname,"%s/%s",directory,dname);
3183 if (!can_rename(fname,cnum)) {
3184 DEBUG(6,("rename %s refused\n", fname));
3187 pstrcpy(destname,newname);
3189 if (!resolve_wildcards(fname,destname)) {
3190 DEBUG(6,("resolve_wildcards %s %s failed\n",
3195 if (file_exist(destname,NULL)) {
3196 DEBUG(6,("file_exist %s\n",
3201 if (!sys_rename(fname,destname)) count++;
3202 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3210 return(ERROR(ERRDOS,error));
3213 if((errno == ENOENT) && (bad_path1 || bad_path2))
3215 unix_ERR_class = ERRDOS;
3216 unix_ERR_code = ERRbadpath;
3218 return(UNIXERROR(ERRDOS,error));
3222 outsize = set_message(outbuf,0,0,True);
3227 /*******************************************************************
3228 copy a file as part of a reply_copy
3229 ******************************************************************/
3230 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3231 int count,BOOL target_is_directory)
3239 pstrcpy(dest,dest1);
3240 if (target_is_directory) {
3241 char *p = strrchr(src,'/');
3250 if (!file_exist(src,&st)) return(False);
3252 fnum1 = find_free_file();
3253 if (fnum1<0) return(False);
3254 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3255 1,0,0,&Access,&action);
3257 if (!Files[fnum1].open) return(False);
3259 if (!target_is_directory && count)
3262 fnum2 = find_free_file();
3264 close_file(fnum1,False);
3267 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3268 ofun,st.st_mode,0,&Access,&action);
3270 if (!Files[fnum2].open) {
3271 close_file(fnum1,False);
3275 if ((ofun&3) == 1) {
3276 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3280 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3282 close_file(fnum1,False);
3283 close_file(fnum2,False);
3285 return(ret == st.st_size);
3290 /****************************************************************************
3291 reply to a file copy.
3292 ****************************************************************************/
3293 int reply_copy(char *inbuf,char *outbuf)
3299 pstring mask,newname;
3302 int error = ERRnoaccess;
3305 int tid2 = SVAL(inbuf,smb_vwv0);
3306 int ofun = SVAL(inbuf,smb_vwv1);
3307 int flags = SVAL(inbuf,smb_vwv2);
3308 BOOL target_is_directory=False;
3309 BOOL bad_path1 = False;
3310 BOOL bad_path2 = False;
3312 *directory = *mask = 0;
3314 cnum = SVAL(inbuf,smb_tid);
3316 pstrcpy(name,smb_buf(inbuf));
3317 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3319 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3322 /* can't currently handle inter share copies XXXX */
3323 DEBUG(3,("Rejecting inter-share copy\n"));
3324 return(ERROR(ERRSRV,ERRinvdevice));
3327 unix_convert(name,cnum,0,&bad_path1);
3328 unix_convert(newname,cnum,0,&bad_path2);
3330 target_is_directory = directory_exist(newname,NULL);
3332 if ((flags&1) && target_is_directory) {
3333 return(ERROR(ERRDOS,ERRbadfile));
3336 if ((flags&2) && !target_is_directory) {
3337 return(ERROR(ERRDOS,ERRbadpath));
3340 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3341 /* wants a tree copy! XXXX */
3342 DEBUG(3,("Rejecting tree copy\n"));
3343 return(ERROR(ERRSRV,ERRerror));
3346 p = strrchr(name,'/');
3348 strcpy(directory,"./");
3352 strcpy(directory,name);
3356 if (is_mangled(mask))
3357 check_mangled_stack(mask);
3359 has_wild = strchr(mask,'*') || strchr(mask,'?');
3362 strcat(directory,"/");
3363 strcat(directory,mask);
3364 if (resolve_wildcards(directory,newname) &&
3365 copy_file(directory,newname,cnum,ofun,
3366 count,target_is_directory)) count++;
3367 if (!count) exists = file_exist(directory,NULL);
3369 void *dirptr = NULL;
3373 if (check_name(directory,cnum))
3374 dirptr = OpenDir(cnum, directory, True);
3380 if (strequal(mask,"????????.???"))
3383 while ((dname = ReadDirName(dirptr)))
3386 pstrcpy(fname,dname);
3388 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3390 error = ERRnoaccess;
3391 sprintf(fname,"%s/%s",directory,dname);
3392 strcpy(destname,newname);
3393 if (resolve_wildcards(fname,destname) &&
3394 copy_file(directory,newname,cnum,ofun,
3395 count,target_is_directory)) count++;
3396 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3404 return(ERROR(ERRDOS,error));
3407 if((errno == ENOENT) && (bad_path1 || bad_path2))
3409 unix_ERR_class = ERRDOS;
3410 unix_ERR_code = ERRbadpath;
3412 return(UNIXERROR(ERRDOS,error));
3416 outsize = set_message(outbuf,1,0,True);
3417 SSVAL(outbuf,smb_vwv0,count);
3424 /****************************************************************************
3426 ****************************************************************************/
3427 int reply_setdir(char *inbuf,char *outbuf)
3434 cnum = SVAL(inbuf,smb_tid);
3436 snum = Connections[cnum].service;
3437 if (!CAN_SETDIR(snum))
3438 return(ERROR(ERRDOS,ERRnoaccess));
3440 pstrcpy(newdir,smb_buf(inbuf) + 1);
3443 if (strlen(newdir) == 0)
3447 ok = directory_exist(newdir,NULL);
3449 string_set(&Connections[cnum].connectpath,newdir);
3453 return(ERROR(ERRDOS,ERRbadpath));
3455 outsize = set_message(outbuf,0,0,True);
3456 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3458 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3464 /****************************************************************************
3465 reply to a lockingX request
3466 ****************************************************************************/
3467 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3469 int fnum = GETFNUM(inbuf,smb_vwv2);
3470 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3472 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3474 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3475 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3476 uint32 count, offset;
3481 uint32 ecode=0, dummy2;
3482 int eclass=0, dummy1;
3484 cnum = SVAL(inbuf,smb_tid);
3486 CHECK_FNUM(fnum,cnum);
3489 data = smb_buf(inbuf);
3491 /* Check if this is an oplock break on a file
3492 we have granted an oplock on.
3494 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3497 files_struct *fsp = &Files[fnum];
3498 uint32 dev = fsp->fd_ptr->dev;
3499 uint32 inode = fsp->fd_ptr->inode;
3501 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3504 * Make sure we have granted an oplock on this file.
3506 if(!fsp->granted_oplock)
3508 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3509 no oplock granted on this file.\n", fnum));
3510 return ERROR(ERRDOS,ERRlock);
3513 /* Remove the oplock flag from the sharemode. */
3514 lock_share_entry(fsp->cnum, dev, inode, &token);
3515 if(remove_share_oplock( fnum, token)==False) {
3516 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3517 dev = %x, inode = %x\n",
3519 unlock_share_entry(fsp->cnum, dev, inode, token);
3521 unlock_share_entry(fsp->cnum, dev, inode, token);
3523 /* Clear the granted flag and return. */
3524 fsp->granted_oplock = False;
3527 /* if this is a pure oplock break request then don't send a reply */
3528 if (num_locks == 0 && num_ulocks == 0)
3530 /* Sanity check - ensure a pure oplock break is not a
3532 if(CVAL(inbuf,smb_vwv0) != 0xff)
3533 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3534 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3539 /* Data now points at the beginning of the list
3540 of smb_unlkrng structs */
3541 for(i = 0; i < (int)num_ulocks; i++) {
3542 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3543 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3544 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3545 return ERROR(eclass,ecode);
3548 /* Now do any requested locks */
3549 data += 10*num_ulocks;
3550 /* Data now points at the beginning of the list
3551 of smb_lkrng structs */
3552 for(i = 0; i < (int)num_locks; i++) {
3553 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3554 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3555 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3559 /* If any of the above locks failed, then we must unlock
3560 all of the previous locks (X/Open spec). */
3561 if(i != num_locks && num_locks != 0) {
3562 for(; i >= 0; i--) {
3563 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3564 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3565 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3567 return ERROR(eclass,ecode);
3570 set_message(outbuf,2,0,True);
3572 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3573 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3577 return chain_reply(inbuf,outbuf,length,bufsize);
3581 /****************************************************************************
3582 reply to a SMBreadbmpx (read block multiplex) request
3583 ****************************************************************************/
3584 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3591 int outsize, mincount, maxcount;
3596 /* this function doesn't seem to work - disable by default */
3598 return(ERROR(ERRSRV,ERRuseSTD));
3600 outsize = set_message(outbuf,8,0,True);
3602 cnum = SVAL(inbuf,smb_tid);
3603 fnum = GETFNUM(inbuf,smb_vwv0);
3605 CHECK_FNUM(fnum,cnum);
3609 startpos = IVAL(inbuf,smb_vwv1);
3610 maxcount = SVAL(inbuf,smb_vwv3);
3611 mincount = SVAL(inbuf,smb_vwv4);
3613 data = smb_buf(outbuf);
3614 pad = ((long)data)%4;
3615 if (pad) pad = 4 - pad;
3618 max_per_packet = bufsize-(outsize+pad);
3622 if (is_locked(fnum,cnum,maxcount,startpos))
3623 return(ERROR(ERRDOS,ERRlock));
3627 int N = MIN(max_per_packet,tcount-total_read);
3629 nread = read_file(fnum,data,startpos,N);
3631 if (nread <= 0) nread = 0;
3634 tcount = total_read + nread;
3636 set_message(outbuf,8,nread,False);
3637 SIVAL(outbuf,smb_vwv0,startpos);
3638 SSVAL(outbuf,smb_vwv2,tcount);
3639 SSVAL(outbuf,smb_vwv6,nread);
3640 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3642 send_smb(Client,outbuf);
3644 total_read += nread;
3647 while (total_read < tcount);
3653 /****************************************************************************
3654 reply to a SMBwritebmpx (write block multiplex primary) request
3655 ****************************************************************************/
3656 int reply_writebmpx(char *inbuf,char *outbuf)
3658 int cnum,numtowrite,fnum;
3662 int tcount, write_through, smb_doff;
3665 cnum = SVAL(inbuf,smb_tid);
3666 fnum = GETFNUM(inbuf,smb_vwv0);
3668 CHECK_FNUM(fnum,cnum);
3672 tcount = SVAL(inbuf,smb_vwv1);
3673 startpos = IVAL(inbuf,smb_vwv3);
3674 write_through = BITSETW(inbuf+smb_vwv7,0);
3675 numtowrite = SVAL(inbuf,smb_vwv10);
3676 smb_doff = SVAL(inbuf,smb_vwv11);
3678 data = smb_base(inbuf) + smb_doff;
3680 /* If this fails we need to send an SMBwriteC response,
3681 not an SMBwritebmpx - set this up now so we don't forget */
3682 CVAL(outbuf,smb_com) = SMBwritec;
3684 if (is_locked(fnum,cnum,tcount,startpos))
3685 return(ERROR(ERRDOS,ERRlock));
3687 seek_file(fnum,startpos);
3688 nwritten = write_file(fnum,data,numtowrite);
3690 if(lp_syncalways(SNUM(cnum)) || write_through)
3693 if(nwritten < numtowrite)
3694 return(UNIXERROR(ERRHRD,ERRdiskfull));
3696 /* If the maximum to be written to this file
3697 is greater than what we just wrote then set
3698 up a secondary struct to be attached to this
3699 fd, we will use this to cache error messages etc. */
3700 if(tcount > nwritten)
3702 write_bmpx_struct *wbms;
3703 if(Files[fnum].wbmpx_ptr != NULL)
3704 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3706 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3709 DEBUG(0,("Out of memory in reply_readmpx\n"));
3710 return(ERROR(ERRSRV,ERRnoresource));
3712 wbms->wr_mode = write_through;
3713 wbms->wr_discard = False; /* No errors yet */
3714 wbms->wr_total_written = nwritten;
3715 wbms->wr_errclass = 0;
3717 Files[fnum].wbmpx_ptr = wbms;
3720 /* We are returning successfully, set the message type back to
3722 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3724 outsize = set_message(outbuf,1,0,True);
3726 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3728 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3729 timestring(),fnum,cnum,numtowrite,nwritten));
3731 if (write_through && tcount==nwritten) {
3732 /* we need to send both a primary and a secondary response */
3733 smb_setlen(outbuf,outsize - 4);
3734 send_smb(Client,outbuf);
3736 /* now the secondary */
3737 outsize = set_message(outbuf,1,0,True);
3738 CVAL(outbuf,smb_com) = SMBwritec;
3739 SSVAL(outbuf,smb_vwv0,nwritten);
3746 /****************************************************************************
3747 reply to a SMBwritebs (write block multiplex secondary) request
3748 ****************************************************************************/
3749 int reply_writebs(char *inbuf,char *outbuf)
3751 int cnum,numtowrite,fnum;
3755 int tcount, write_through, smb_doff;
3757 write_bmpx_struct *wbms;
3758 BOOL send_response = False;
3760 cnum = SVAL(inbuf,smb_tid);
3761 fnum = GETFNUM(inbuf,smb_vwv0);
3762 CHECK_FNUM(fnum,cnum);
3765 tcount = SVAL(inbuf,smb_vwv1);
3766 startpos = IVAL(inbuf,smb_vwv2);
3767 numtowrite = SVAL(inbuf,smb_vwv6);
3768 smb_doff = SVAL(inbuf,smb_vwv7);
3770 data = smb_base(inbuf) + smb_doff;
3772 /* We need to send an SMBwriteC response, not an SMBwritebs */
3773 CVAL(outbuf,smb_com) = SMBwritec;
3775 /* This fd should have an auxiliary struct attached,
3776 check that it does */
3777 wbms = Files[fnum].wbmpx_ptr;
3778 if(!wbms) return(-1);
3780 /* If write through is set we can return errors, else we must
3782 write_through = wbms->wr_mode;
3784 /* Check for an earlier error */
3785 if(wbms->wr_discard)
3786 return -1; /* Just discard the packet */
3788 seek_file(fnum,startpos);
3789 nwritten = write_file(fnum,data,numtowrite);
3791 if(lp_syncalways(SNUM(cnum)) || write_through)
3794 if (nwritten < numtowrite)
3797 /* We are returning an error - we can delete the aux struct */
3798 if (wbms) free((char *)wbms);
3799 Files[fnum].wbmpx_ptr = NULL;
3800 return(ERROR(ERRHRD,ERRdiskfull));
3802 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3805 /* Increment the total written, if this matches tcount
3806 we can discard the auxiliary struct (hurrah !) and return a writeC */
3807 wbms->wr_total_written += nwritten;
3808 if(wbms->wr_total_written >= tcount)
3810 if (write_through) {
3811 outsize = set_message(outbuf,1,0,True);
3812 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3813 send_response = True;
3817 Files[fnum].wbmpx_ptr = NULL;
3827 /****************************************************************************
3828 reply to a SMBsetattrE
3829 ****************************************************************************/
3830 int reply_setattrE(char *inbuf,char *outbuf)
3833 struct utimbuf unix_times;
3836 outsize = set_message(outbuf,0,0,True);
3838 cnum = SVAL(inbuf,smb_tid);
3839 fnum = GETFNUM(inbuf,smb_vwv0);
3841 CHECK_FNUM(fnum,cnum);
3844 /* Convert the DOS times into unix times. Ignore create
3845 time as UNIX can't set this.
3847 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3848 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3851 * Patch from Ray Frush <frush@engr.colostate.edu>
3852 * Sometimes times are sent as zero - ignore them.
3855 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3857 /* Ignore request */
3858 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3859 not setting timestamps of 0\n",
3860 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3863 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3865 /* set modify time = to access time if modify time was 0 */
3866 unix_times.modtime = unix_times.actime;
3869 /* Set the date on this file */
3870 if(file_utime(cnum, Files[fnum].name, &unix_times))
3871 return(ERROR(ERRDOS,ERRnoaccess));
3873 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3874 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3880 /****************************************************************************
3881 reply to a SMBgetattrE
3882 ****************************************************************************/
3883 int reply_getattrE(char *inbuf,char *outbuf)
3890 outsize = set_message(outbuf,11,0,True);
3892 cnum = SVAL(inbuf,smb_tid);
3893 fnum = GETFNUM(inbuf,smb_vwv0);
3895 CHECK_FNUM(fnum,cnum);
3898 /* Do an fstat on this file */
3899 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3900 return(UNIXERROR(ERRDOS,ERRnoaccess));
3902 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3904 /* Convert the times into dos times. Set create
3905 date to be last modify date as UNIX doesn't save
3907 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3908 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3909 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3912 SIVAL(outbuf,smb_vwv6,0);
3913 SIVAL(outbuf,smb_vwv8,0);
3917 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3918 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3920 SSVAL(outbuf,smb_vwv10, mode);
3922 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));