2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1995
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
30 /* look in server.c for some explanation of these variables */
32 extern int DEBUGLEVEL;
34 extern int chain_fnum;
35 extern char magic_char;
36 extern connection_struct Connections[];
37 extern files_struct Files[];
38 extern BOOL case_sensitive;
39 extern pstring sesssetup_user;
42 /* this macro should always be used to extract an fnum (smb_fid) from
43 a packet to ensure chaining works correctly */
44 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
47 /****************************************************************************
48 reply to an special message
49 ****************************************************************************/
50 int reply_special(char *inbuf,char *outbuf)
53 int msg_type = CVAL(inbuf,0);
54 int msg_flags = CVAL(inbuf,1);
56 extern fstring remote_machine;
57 extern fstring local_machine;
66 case 0x81: /* session request */
67 CVAL(outbuf,0) = 0x82;
69 if (name_len(inbuf+4) > 50)
71 DEBUG(0,("Invalid name length in session request\n"));
74 name_extract(inbuf,4,name1);
75 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
76 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2));
78 strcpy(remote_machine,name2);
79 trim_string(remote_machine," "," ");
80 p = strchr(remote_machine,' ');
81 strlower(remote_machine);
84 strcpy(local_machine,name1);
85 trim_string(local_machine," "," ");
86 p = strchr(local_machine,' ');
87 strlower(local_machine);
90 add_session_user(remote_machine);
92 reload_services(True);
96 case 0x85: /* session keepalive */
101 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags));
107 /*******************************************************************
108 work out what error to give to a failed connection
109 ********************************************************************/
110 static int connection_error(char *inbuf,char *outbuf,int connection_num)
112 switch (connection_num)
115 return(ERROR(ERRSRV,ERRnoresource));
117 return(ERROR(ERRSRV,ERRbaduid));
119 return(ERROR(ERRSRV,ERRinvdevice));
121 return(ERROR(ERRSRV,ERRinvnetname));
123 return(ERROR(ERRSRV,ERRaccess));
125 return(ERROR(ERRDOS,ERRnoipc));
127 return(ERROR(ERRSRV,ERRinvnetname));
129 return(ERROR(ERRSRV,ERRbadpw));
133 /****************************************************************************
135 ****************************************************************************/
136 int reply_tcon(char *inbuf,char *outbuf)
144 int uid = SVAL(inbuf,smb_uid);
148 *service = *user = *password = *dev = 0;
150 vuid = valid_uid(uid);
152 parse_connect(inbuf,service,user,password,&pwlen,dev);
154 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
156 if (connection_num < 0)
157 return(connection_error(inbuf,outbuf,connection_num));
159 outsize = set_message(outbuf,2,0,True);
160 SSVAL(outbuf,smb_vwv0,maxxmit);
161 SSVAL(outbuf,smb_vwv1,connection_num);
162 SSVAL(outbuf,smb_tid,connection_num);
164 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
170 /****************************************************************************
171 reply to a tcon and X
172 ****************************************************************************/
173 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
180 int uid = SVAL(inbuf,smb_uid);
182 int passlen = SVAL(inbuf,smb_vwv3);
184 *service = *user = *password = *devicename = 0;
186 /* we might have to close an old one */
187 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
188 close_cnum(SVAL(inbuf,smb_tid),uid);
190 vuid = valid_uid(uid);
195 memcpy(password,smb_buf(inbuf),passlen);
197 path = smb_buf(inbuf) + passlen;
198 DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
199 strcpy(service,path+2);
200 p = strchr(service,'\\');
202 return(ERROR(ERRSRV,ERRinvnetname));
205 p = strchr(service,'%');
211 StrnCpy(devicename,path + strlen(path) + 1,6);
212 DEBUG(4,("Got device type %s\n",devicename));
215 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
217 if (connection_num < 0)
218 return(connection_error(inbuf,outbuf,connection_num));
220 set_message(outbuf,2,strlen(devicename)+1,True);
222 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
224 /* set the incoming and outgoing tid to the just created one */
225 SSVAL(inbuf,smb_tid,connection_num);
226 SSVAL(outbuf,smb_tid,connection_num);
228 strcpy(smb_buf(outbuf),devicename);
230 return chain_reply(inbuf,outbuf,length,bufsize);
234 /****************************************************************************
235 reply to an unknown type
236 ****************************************************************************/
237 int reply_unknown(char *inbuf,char *outbuf)
241 cnum = SVAL(inbuf,smb_tid);
242 type = CVAL(inbuf,smb_com);
244 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
249 return(ERROR(ERRSRV,ERRunknownsmb));
253 /****************************************************************************
255 ****************************************************************************/
256 int reply_ioctl(char *inbuf,char *outbuf)
258 DEBUG(3,("ignoring ioctl\n"));
260 return(ERROR(ERRSRV,ERRnosupport));
264 /****************************************************************************
265 reply to a session setup command
266 ****************************************************************************/
267 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
277 int smb_ntpasslen = 0;
278 pstring smb_ntpasswd;
279 BOOL valid_nt_password = False;
282 BOOL computer_id=False;
286 sess_uid = SVAL(inbuf,smb_uid);
287 smb_bufsize = SVAL(inbuf,smb_vwv2);
288 smb_mpxmax = SVAL(inbuf,smb_vwv3);
289 smb_vc_num = SVAL(inbuf,smb_vwv4);
290 smb_sesskey = IVAL(inbuf,smb_vwv5);
292 if (Protocol < PROTOCOL_NT1) {
293 smb_apasslen = SVAL(inbuf,smb_vwv7);
294 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
295 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
297 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
298 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
299 BOOL doencrypt = SMBENCRYPT();
300 char *p = smb_buf(inbuf);
301 if (passlen1 > 256) passlen1 = 0;
302 if (passlen2 > 256) passlen2 = 0; /* I don't know why NT gives weird
305 /* Save the lanman2 password and the NT md4 password. */
306 smb_apasslen = passlen1;
307 memcpy(smb_apasswd,p,smb_apasslen);
308 smb_ntpasslen = passlen2;
309 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
312 if (passlen1 > passlen2) {
313 smb_apasslen = passlen1;
314 StrnCpy(smb_apasswd,p,smb_apasslen);
316 smb_apasslen = passlen2;
317 StrnCpy(smb_apasswd,p + passlen1,smb_apasslen);
322 /* apparently NT sometimes sets passlen2 to 1 when it means 0. This
323 tries to work around that problem */
327 p += passlen1 + passlen2;
328 strcpy(user,p); p = skip_string(p,1);
329 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
330 p,skip_string(p,1),skip_string(p,2)));
334 DEBUG(3,("sesssetupX:name=[%s]\n",user));
336 /* If name ends in $ then I think it's asking about whether a */
337 /* computer with that name (minus the $) has access. For now */
338 /* say yes to everything ending in $. */
339 if (user[strlen(user) - 1] == '$') {
341 user[strlen(user) - 1] = '\0';
346 strcpy(user,lp_guestaccount(-1));
350 strcpy(sesssetup_user,user);
352 reload_services(True);
354 add_session_user(user);
357 if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
358 !check_hosts_equiv(user))
361 if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
364 /* now check if it's a valid username/password */
365 /* If an NT password was supplied try and validate with that
366 first. This is superior as the passwords are mixed case 128 length unicode */
367 if(smb_ntpasslen && !guest)
369 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL,True))
370 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
372 valid_nt_password = True;
374 if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL,False))
376 if (!computer_id && lp_security() >= SEC_USER) {
377 #if (GUEST_SESSSETUP == 0)
378 return(ERROR(ERRSRV,ERRbadpw));
380 #if (GUEST_SESSSETUP == 1)
381 if (Get_Pwnam(user,True))
382 return(ERROR(ERRSRV,ERRbadpw));
385 if (*smb_apasswd || !Get_Pwnam(user,True))
386 strcpy(user,lp_guestaccount(-1));
387 DEBUG(3,("Registered username %s for guest access\n",user));
392 if (!Get_Pwnam(user,True)) {
393 DEBUG(3,("No such user %s - using guest account\n",user));
394 strcpy(user,lp_guestaccount(-1));
398 if (!strequal(user,lp_guestaccount(-1)) &&
399 lp_servicenumber(user) < 0)
401 int homes = lp_servicenumber(HOMES_NAME);
402 char *home = get_home_dir(user);
403 if (homes >= 0 && home)
404 lp_add_home(user,homes,home);
408 /* it's ok - setup a reply */
409 if (Protocol < PROTOCOL_NT1) {
410 set_message(outbuf,3,0,True);
413 set_message(outbuf,3,3,True);
415 strcpy(p,"Unix"); p = skip_string(p,1);
416 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
417 strcpy(p,lp_workgroup()); p = skip_string(p,1);
418 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
419 /* perhaps grab OS version here?? */
422 /* Set the correct uid in the outgoing and incoming packets
423 We will use this on future requests to determine which
424 user we should become.
427 struct passwd *pw = Get_Pwnam(user,False);
429 DEBUG(1,("Username %s is invalid on this system\n",user));
430 return(ERROR(ERRSRV,ERRbadpw));
433 SSVAL(outbuf,smb_uid,(uint16)pw->pw_uid);
434 SSVAL(inbuf,smb_uid,(uint16)pw->pw_uid);
437 if (guest && !computer_id)
438 SSVAL(outbuf,smb_vwv2,1);
440 /* register the name and uid as being validated, so further connections
441 to a uid can get through without a password, on the same VC */
442 register_uid(SVAL(inbuf,smb_uid),gid,user,guest);
444 maxxmit = MIN(maxxmit,smb_bufsize);
446 return chain_reply(inbuf,outbuf,length,bufsize);
450 /****************************************************************************
452 ****************************************************************************/
453 int reply_chkpth(char *inbuf,char *outbuf)
460 cnum = SVAL(inbuf,smb_tid);
462 strcpy(name,smb_buf(inbuf) + 1);
463 unix_convert(name,cnum);
465 mode = SVAL(inbuf,smb_vwv0);
467 if (check_name(name,cnum))
468 ok = directory_exist(name,NULL);
471 return(ERROR(ERRDOS,ERRbadpath));
473 outsize = set_message(outbuf,0,0,True);
475 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
481 /****************************************************************************
483 ****************************************************************************/
484 int reply_getatr(char *inbuf,char *outbuf)
495 cnum = SVAL(inbuf,smb_tid);
497 strcpy(fname,smb_buf(inbuf) + 1);
498 unix_convert(fname,cnum);
500 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
501 under WfWg - weird! */
504 mode = aHIDDEN | aDIR;
505 if (!CAN_WRITE(cnum)) mode |= aRONLY;
511 if (check_name(fname,cnum))
513 if (sys_stat(fname,&sbuf) == 0)
515 mode = dos_mode(cnum,fname,&sbuf);
517 mtime = sbuf.st_mtime;
523 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
527 return(UNIXERROR(ERRDOS,ERRbadfile));
529 outsize = set_message(outbuf,10,0,True);
531 SSVAL(outbuf,smb_vwv0,mode);
532 put_dos_date3(outbuf,smb_vwv1,mtime);
533 SIVAL(outbuf,smb_vwv3,size);
535 if (Protocol >= PROTOCOL_NT1) {
536 char *p = strrchr(fname,'/');
537 uint16 flg2 = SVAL(outbuf,smb_flg2);
540 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
543 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
549 /****************************************************************************
551 ****************************************************************************/
552 int reply_setatr(char *inbuf,char *outbuf)
561 cnum = SVAL(inbuf,smb_tid);
563 strcpy(fname,smb_buf(inbuf) + 1);
564 unix_convert(fname,cnum);
566 mode = SVAL(inbuf,smb_vwv0);
567 mtime = make_unix_date3(inbuf+smb_vwv1);
569 if (directory_exist(fname,NULL))
571 if (check_name(fname,cnum))
572 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
574 ok = set_filetime(fname,mtime);
577 return(UNIXERROR(ERRDOS,ERRnoaccess));
579 outsize = set_message(outbuf,0,0,True);
581 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
587 /****************************************************************************
589 ****************************************************************************/
590 int reply_dskattr(char *inbuf,char *outbuf)
594 int dfree,dsize,bsize;
596 cnum = SVAL(inbuf,smb_tid);
598 sys_disk_free(".",&bsize,&dfree,&dsize);
600 outsize = set_message(outbuf,5,0,True);
602 SSVAL(outbuf,smb_vwv0,dsize);
603 SSVAL(outbuf,smb_vwv1,bsize/512);
604 SSVAL(outbuf,smb_vwv2,512);
605 SSVAL(outbuf,smb_vwv3,dfree);
607 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
613 /****************************************************************************
615 Can be called from SMBsearch, SMBffirst or SMBfunique.
616 ****************************************************************************/
617 int reply_search(char *inbuf,char *outbuf)
628 BOOL finished = False;
637 BOOL check_descend = False;
638 BOOL expect_close = False;
639 BOOL can_open = True;
641 *mask = *directory = *fname = 0;
643 /* If we were called as SMBffirst then we must expect close. */
644 if(CVAL(inbuf,smb_com) == SMBffirst)
647 cnum = SVAL(inbuf,smb_tid);
649 outsize = set_message(outbuf,1,3,True);
650 maxentries = SVAL(inbuf,smb_vwv0);
651 dirtype = SVAL(inbuf,smb_vwv1);
652 path = smb_buf(inbuf) + 1;
653 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
656 /* dirtype &= ~aDIR; */
658 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
665 strcpy(directory,smb_buf(inbuf)+1);
666 strcpy(dir2,smb_buf(inbuf)+1);
667 unix_convert(directory,cnum);
670 if (!check_name(directory,cnum))
673 p = strrchr(dir2,'/');
675 {strcpy(mask,dir2);*dir2 = 0;}
677 {*p = 0;strcpy(mask,p+1);}
679 p = strrchr(directory,'/');
685 if (strlen(directory) == 0)
686 strcpy(directory,"./");
688 CVAL(status,0) = dirtype;
692 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
693 memcpy(mask,status+1,11);
695 dirtype = CVAL(status,0) & 0x1F;
696 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
697 if (!Connections[cnum].dirptr)
699 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
704 /* turn strings of spaces into a . */
706 trim_string(mask,NULL," ");
707 if ((p = strrchr(mask,' ')))
712 trim_string(mask,NULL," ");
719 for (p=mask; *p; p++)
721 if (*p != '?' && *p != '*' && !isdoschar(*p))
723 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
729 if (!strchr(mask,'.') && strlen(mask)>8)
732 strcpy(tmp,&mask[8]);
738 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
742 p = smb_buf(outbuf) + 3;
748 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
750 return(ERROR(ERRDOS,ERRnofids));
753 DEBUG(4,("dptr_num is %d\n",dptr_num));
757 if ((dirtype&0x1F) == aVOLID)
760 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
761 dptr_fill(p+12,dptr_num);
762 if (dptr_zero(p+12) && (status_len==0))
766 p += DIR_STRUCT_SIZE;
770 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
771 if (in_list(Connections[cnum].dirpath,
772 lp_dontdescend(SNUM(cnum)),True))
773 check_descend = True;
775 for (i=numentries;(i<maxentries) && !finished;i++)
778 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
782 make_dir_struct(p,mask,fname,size,mode,date);
783 dptr_fill(p+12,dptr_num);
786 p += DIR_STRUCT_SIZE;
795 if (numentries == 0 || !ok)
797 CVAL(outbuf,smb_rcls) = ERRDOS;
798 SSVAL(outbuf,smb_err,ERRnofiles);
801 /* If we were called as SMBffirst with smb_search_id == NULL
802 and no entries were found then return error and close dirptr
805 if(ok && expect_close && numentries == 0 && status_len == 0)
807 CVAL(outbuf,smb_rcls) = ERRDOS;
808 SSVAL(outbuf,smb_err,ERRnofiles);
809 /* Also close the dptr - we know it's gone */
810 dptr_close(dptr_num);
813 /* If we were called as SMBfunique, then we can close the dirptr now ! */
814 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
815 dptr_close(dptr_num);
817 SSVAL(outbuf,smb_vwv0,numentries);
818 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
819 CVAL(smb_buf(outbuf),0) = 5;
820 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
822 if (Protocol >= PROTOCOL_NT1) {
823 uint16 flg2 = SVAL(outbuf,smb_flg2);
824 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
827 outsize += DIR_STRUCT_SIZE*numentries;
828 smb_setlen(outbuf,outsize - 4);
830 if ((! *directory) && dptr_path(dptr_num))
831 sprintf(directory,"(%s)",dptr_path(dptr_num));
833 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
835 smb_fn_name(CVAL(inbuf,smb_com)),
836 mask,directory,cnum,dirtype,numentries,maxentries));
842 /****************************************************************************
843 reply to a fclose (stop directory search)
844 ****************************************************************************/
845 int reply_fclose(char *inbuf,char *outbuf)
854 cnum = SVAL(inbuf,smb_tid);
856 outsize = set_message(outbuf,1,0,True);
857 path = smb_buf(inbuf) + 1;
858 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
862 return(ERROR(ERRSRV,ERRsrverror));
864 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
866 if(dptr_fetch(status+12,&dptr_num)) {
867 /* Close the dptr - we know it's gone */
868 dptr_close(dptr_num);
871 SSVAL(outbuf,smb_vwv0,0);
873 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
879 /****************************************************************************
881 ****************************************************************************/
882 int reply_open(char *inbuf,char *outbuf)
896 cnum = SVAL(inbuf,smb_tid);
898 share_mode = SVAL(inbuf,smb_vwv0);
900 strcpy(fname,smb_buf(inbuf)+1);
901 unix_convert(fname,cnum);
903 fnum = find_free_file();
905 return(ERROR(ERRSRV,ERRnofids));
907 if (!check_name(fname,cnum))
908 return(UNIXERROR(ERRDOS,ERRnoaccess));
910 unixmode = unix_mode(cnum,aARCH);
912 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
914 if (!Files[fnum].open)
915 return(UNIXERROR(ERRDOS,ERRnoaccess));
917 if (fstat(Files[fnum].fd,&sbuf) != 0) {
919 return(ERROR(ERRDOS,ERRnoaccess));
923 fmode = dos_mode(cnum,fname,&sbuf);
924 mtime = sbuf.st_mtime;
927 DEBUG(3,("attempt to open a directory %s\n",fname));
929 return(ERROR(ERRDOS,ERRnoaccess));
932 outsize = set_message(outbuf,7,0,True);
933 SSVAL(outbuf,smb_vwv0,fnum);
934 SSVAL(outbuf,smb_vwv1,fmode);
935 put_dos_date3(outbuf,smb_vwv2,mtime);
936 SIVAL(outbuf,smb_vwv4,size);
937 SSVAL(outbuf,smb_vwv6,rmode);
943 /****************************************************************************
944 reply to an open and X
945 ****************************************************************************/
946 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
949 int cnum = SVAL(inbuf,smb_tid);
952 int smb_mode = SVAL(inbuf,smb_vwv3);
953 int smb_attr = SVAL(inbuf,smb_vwv5);
955 int open_flags = SVAL(inbuf,smb_vwv2);
956 int smb_sattr = SVAL(inbuf,smb_vwv4);
957 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
959 int smb_ofun = SVAL(inbuf,smb_vwv8);
961 int size=0,fmode=0,mtime=0,rmode=0;
965 /* If it's an IPC, pass off the pipe handler. */
967 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
969 /* XXXX we need to handle passed times, sattr and flags */
971 strcpy(fname,smb_buf(inbuf));
972 unix_convert(fname,cnum);
974 /* now add create and trunc bits */
977 if ((smb_ofun & 0x3) == 2)
980 fnum = find_free_file();
982 return(ERROR(ERRSRV,ERRnofids));
984 if (!check_name(fname,cnum))
985 return(UNIXERROR(ERRDOS,ERRnoaccess));
987 unixmode = unix_mode(cnum,smb_attr | aARCH);
989 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
992 if (!Files[fnum].open)
993 return(UNIXERROR(ERRDOS,ERRnoaccess));
995 if (fstat(Files[fnum].fd,&sbuf) != 0) {
997 return(ERROR(ERRDOS,ERRnoaccess));
1000 size = sbuf.st_size;
1001 fmode = dos_mode(cnum,fname,&sbuf);
1002 mtime = sbuf.st_mtime;
1005 return(ERROR(ERRDOS,ERRnoaccess));
1008 set_message(outbuf,15,0,True);
1009 SSVAL(outbuf,smb_vwv2,fnum);
1010 SSVAL(outbuf,smb_vwv3,fmode);
1011 put_dos_date3(outbuf,smb_vwv4,mtime);
1012 SIVAL(outbuf,smb_vwv6,size);
1013 SSVAL(outbuf,smb_vwv8,rmode);
1014 SSVAL(outbuf,smb_vwv11,smb_action);
1018 return chain_reply(inbuf,outbuf,length,bufsize);
1022 /****************************************************************************
1023 reply to a SMBulogoffX
1024 ****************************************************************************/
1025 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1027 int uid = SVAL(inbuf,smb_uid);
1029 invalidate_uid(uid);
1031 set_message(outbuf,2,0,True);
1033 DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid));
1035 return chain_reply(inbuf,outbuf,length,bufsize);
1039 /****************************************************************************
1041 ****************************************************************************/
1042 int reply_mknew(char *inbuf,char *outbuf)
1051 com = SVAL(inbuf,smb_com);
1052 cnum = SVAL(inbuf,smb_tid);
1054 createmode = SVAL(inbuf,smb_vwv0);
1055 strcpy(fname,smb_buf(inbuf)+1);
1056 unix_convert(fname,cnum);
1058 if (createmode & aVOLID)
1060 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1063 unixmode = unix_mode(cnum,createmode);
1065 if (com == SMBmknew && file_exist(fname,NULL))
1066 return(ERROR(ERRDOS,ERRfilexists));
1068 fnum = find_free_file();
1070 return(ERROR(ERRSRV,ERRnofids));
1072 if (!check_name(fname,cnum))
1073 return(UNIXERROR(ERRDOS,ERRnoaccess));
1075 open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1077 if (!Files[fnum].open)
1078 return(UNIXERROR(ERRDOS,ERRnoaccess));
1080 outsize = set_message(outbuf,1,0,True);
1081 SSVAL(outbuf,smb_vwv0,fnum);
1083 DEBUG(2,("new file %s\n",fname));
1084 DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd,fnum,cnum,createmode,unixmode));
1090 /****************************************************************************
1091 reply to a create temporary file
1092 ****************************************************************************/
1093 int reply_ctemp(char *inbuf,char *outbuf)
1103 cnum = SVAL(inbuf,smb_tid);
1104 createmode = SVAL(inbuf,smb_vwv0);
1105 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1106 unix_convert(fname,cnum);
1108 unixmode = unix_mode(cnum,createmode);
1110 fnum = find_free_file();
1112 return(ERROR(ERRSRV,ERRnofids));
1114 if (!check_name(fname,cnum))
1115 return(UNIXERROR(ERRDOS,ERRnoaccess));
1117 strcpy(fname2,(char *)mktemp(fname));
1119 open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1121 if (!Files[fnum].open)
1122 return(UNIXERROR(ERRDOS,ERRnoaccess));
1124 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1125 SSVAL(outbuf,smb_vwv0,fnum);
1126 CVAL(smb_buf(outbuf),0) = 4;
1127 strcpy(smb_buf(outbuf) + 1,fname2);
1129 DEBUG(2,("created temp file %s\n",fname2));
1130 DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd,fnum,cnum,createmode,unixmode));
1136 /*******************************************************************
1137 check if a user is allowed to delete a file
1138 ********************************************************************/
1139 static BOOL can_delete(char *fname,int cnum,int dirtype)
1144 if (!CAN_WRITE(cnum)) return(False);
1146 if (sys_lstat(fname,&sbuf) != 0) return(False);
1147 fmode = dos_mode(cnum,fname,&sbuf);
1148 if (fmode & aDIR) return(False);
1149 if (!lp_delete_readonly(SNUM(cnum))) {
1150 if (fmode & aRONLY) return(False);
1152 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1154 if (!check_file_sharing(cnum,fname)) return(False);
1158 /****************************************************************************
1160 ****************************************************************************/
1161 int reply_unlink(char *inbuf,char *outbuf)
1171 int error = ERRnoaccess;
1175 *directory = *mask = 0;
1177 cnum = SVAL(inbuf,smb_tid);
1178 dirtype = SVAL(inbuf,smb_vwv0);
1180 strcpy(name,smb_buf(inbuf) + 1);
1182 DEBUG(3,("reply_unlink : %s\n",name));
1184 unix_convert(name,cnum);
1186 p = strrchr(name,'/');
1188 strcpy(directory,"./");
1192 strcpy(directory,name);
1196 if (is_mangled(mask))
1197 check_mangled_stack(mask);
1199 has_wild = strchr(mask,'*') || strchr(mask,'?');
1202 strcat(directory,"/");
1203 strcat(directory,mask);
1204 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1205 if (!count) exists = file_exist(directory,NULL);
1207 void *dirptr = NULL;
1210 if (check_name(directory,cnum))
1211 dirptr = OpenDir(directory);
1217 if (strequal(mask,"????????.???"))
1220 while ((dname = ReadDirName(dirptr)))
1223 strcpy(fname,dname);
1225 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1227 error = ERRnoaccess;
1228 sprintf(fname,"%s/%s",directory,dname);
1229 if (!can_delete(fname,cnum,dirtype)) continue;
1230 if (!sys_unlink(fname)) count++;
1231 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1239 return(ERROR(ERRDOS,error));
1241 return(UNIXERROR(ERRDOS,error));
1244 outsize = set_message(outbuf,0,0,True);
1250 /****************************************************************************
1251 reply to a readbraw (core+ protocol)
1252 ****************************************************************************/
1253 int reply_readbraw(char *inbuf, char *outbuf)
1255 int cnum,maxcount,mincount,fnum;
1258 char *header = outbuf;
1263 cnum = SVAL(inbuf,smb_tid);
1264 fnum = GETFNUM(inbuf,smb_vwv0);
1266 startpos = IVAL(inbuf,smb_vwv1);
1267 maxcount = SVAL(inbuf,smb_vwv3);
1268 mincount = SVAL(inbuf,smb_vwv4);
1270 /* ensure we don't overrun the packet size */
1271 maxcount = MIN(65535,maxcount);
1272 maxcount = MAX(mincount,maxcount);
1274 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1276 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1277 _smb_setlen(header,0);
1278 transfer_file(0,Client,0,header,4,0);
1283 fd = Files[fnum].fd;
1284 fname = Files[fnum].name;
1288 if (!is_locked(fnum,cnum,maxcount,startpos))
1290 int size = Files[fnum].size;
1291 int sizeneeded = startpos + maxcount;
1293 if (size < sizeneeded) {
1295 if (fstat(Files[fnum].fd,&st) == 0)
1297 if (!Files[fnum].can_write)
1298 Files[fnum].size = size;
1301 nread = MIN(maxcount,size - startpos);
1304 if (nread < mincount)
1307 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1310 maxcount,mincount,nread));
1315 _smb_setlen(header,nread);
1317 if (!Files[fnum].can_write)
1318 predict = read_predict(fd,startpos,header+4,NULL,nread);
1320 if ((nread-predict) > 0)
1321 seek_file(fnum,startpos + predict);
1323 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1328 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1329 fname,startpos,nread,ret));
1332 ret = read_file(fnum,header+4,startpos,nread);
1333 if (ret < mincount) ret = 0;
1335 _smb_setlen(header,ret);
1336 transfer_file(0,Client,0,header,4+ret,0);
1339 DEBUG(5,("readbraw finished\n"));
1344 /****************************************************************************
1345 reply to a lockread (core+ protocol)
1346 ****************************************************************************/
1347 int reply_lockread(char *inbuf,char *outbuf)
1353 uint32 startpos, numtoread;
1357 cnum = SVAL(inbuf,smb_tid);
1358 fnum = GETFNUM(inbuf,smb_vwv0);
1360 CHECK_FNUM(fnum,cnum);
1364 numtoread = SVAL(inbuf,smb_vwv1);
1365 startpos = IVAL(inbuf,smb_vwv2);
1367 outsize = set_message(outbuf,5,3,True);
1368 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1369 data = smb_buf(outbuf) + 3;
1371 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1372 return (ERROR(eclass,ecode));
1374 nread = read_file(fnum,data,startpos,numtoread);
1377 return(UNIXERROR(ERRDOS,ERRnoaccess));
1380 SSVAL(outbuf,smb_vwv0,nread);
1381 SSVAL(outbuf,smb_vwv5,nread+3);
1382 SSVAL(smb_buf(outbuf),1,nread);
1384 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1390 /****************************************************************************
1392 ****************************************************************************/
1393 int reply_read(char *inbuf,char *outbuf)
1395 int cnum,numtoread,fnum;
1401 cnum = SVAL(inbuf,smb_tid);
1402 fnum = GETFNUM(inbuf,smb_vwv0);
1404 CHECK_FNUM(fnum,cnum);
1408 numtoread = SVAL(inbuf,smb_vwv1);
1409 startpos = IVAL(inbuf,smb_vwv2);
1411 outsize = set_message(outbuf,5,3,True);
1412 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1413 data = smb_buf(outbuf) + 3;
1415 if (is_locked(fnum,cnum,numtoread,startpos))
1416 return(ERROR(ERRDOS,ERRlock));
1419 nread = read_file(fnum,data,startpos,numtoread);
1422 return(UNIXERROR(ERRDOS,ERRnoaccess));
1425 SSVAL(outbuf,smb_vwv0,nread);
1426 SSVAL(outbuf,smb_vwv5,nread+3);
1427 CVAL(smb_buf(outbuf),0) = 1;
1428 SSVAL(smb_buf(outbuf),1,nread);
1430 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1436 /****************************************************************************
1437 reply to a read and X
1438 ****************************************************************************/
1439 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1441 int fnum = GETFNUM(inbuf,smb_vwv2);
1442 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1443 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1444 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1450 cnum = SVAL(inbuf,smb_tid);
1452 CHECK_FNUM(fnum,cnum);
1456 set_message(outbuf,12,0,True);
1457 data = smb_buf(outbuf);
1459 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1460 return(ERROR(ERRDOS,ERRlock));
1461 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1465 return(UNIXERROR(ERRDOS,ERRnoaccess));
1467 SSVAL(outbuf,smb_vwv5,nread);
1468 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1469 SSVAL(smb_buf(outbuf),-2,nread);
1471 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1472 timestring(),fnum,cnum,
1473 smb_mincnt,smb_maxcnt,nread));
1477 return chain_reply(inbuf,outbuf,length,bufsize);
1481 /****************************************************************************
1482 reply to a writebraw (core+ or LANMAN1.0 protocol)
1483 ****************************************************************************/
1484 int reply_writebraw(char *inbuf,char *outbuf)
1487 int total_written=0;
1496 cnum = SVAL(inbuf,smb_tid);
1497 fnum = GETFNUM(inbuf,smb_vwv0);
1499 CHECK_FNUM(fnum,cnum);
1503 tcount = IVAL(inbuf,smb_vwv1);
1504 startpos = IVAL(inbuf,smb_vwv3);
1505 write_through = BITSETW(inbuf+smb_vwv7,0);
1507 /* We have to deal with slightly different formats depending
1508 on whether we are using the core+ or lanman1.0 protocol */
1509 if(Protocol <= PROTOCOL_COREPLUS) {
1510 numtowrite = SVAL(smb_buf(inbuf),-2);
1511 data = smb_buf(inbuf);
1513 numtowrite = SVAL(inbuf,smb_vwv10);
1514 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1517 /* force the error type */
1518 CVAL(inbuf,smb_com) = SMBwritec;
1519 CVAL(outbuf,smb_com) = SMBwritec;
1521 if (is_locked(fnum,cnum,tcount,startpos))
1522 return(ERROR(ERRDOS,ERRlock));
1524 if (seek_file(fnum,startpos) != startpos)
1525 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1528 nwritten = write_file(fnum,data,numtowrite);
1530 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1531 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1533 if (nwritten < numtowrite)
1534 return(UNIXERROR(ERRHRD,ERRdiskfull));
1536 total_written = nwritten;
1538 /* Return a message to the redirector to tell it
1539 to send more bytes */
1540 CVAL(outbuf,smb_com) = SMBwritebraw;
1541 SSVALS(outbuf,smb_vwv0,-1);
1542 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1543 send_smb(Client,outbuf);
1545 /* Now read the raw data into the buffer and write it */
1546 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1547 exit_server("secondary writebraw failed");
1550 /* Even though this is not an smb message, smb_len
1551 returns the generic length of an smb message */
1552 numtowrite = smb_len(inbuf);
1554 if (tcount > nwritten+numtowrite) {
1555 DEBUG(3,("Client overestimated the write %d %d %d\n",
1556 tcount,nwritten,numtowrite));
1559 nwritten = transfer_file(Client,Files[fnum].fd,numtowrite,NULL,0,
1561 total_written += nwritten;
1563 /* Set up outbuf to return the correct return */
1564 outsize = set_message(outbuf,1,0,True);
1565 CVAL(outbuf,smb_com) = SMBwritec;
1566 SSVAL(outbuf,smb_vwv0,total_written);
1568 if (nwritten < numtowrite) {
1569 CVAL(outbuf,smb_rcls) = ERRHRD;
1570 SSVAL(outbuf,smb_err,ERRdiskfull);
1573 if (lp_syncalways(SNUM(cnum)) || write_through)
1576 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1577 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1579 /* we won't return a status if write through is not selected - this
1580 follows what WfWg does */
1581 if (!write_through && total_written==tcount)
1588 /****************************************************************************
1589 reply to a writeunlock (core+)
1590 ****************************************************************************/
1591 int reply_writeunlock(char *inbuf,char *outbuf)
1597 uint32 numtowrite,startpos;
1601 cnum = SVAL(inbuf,smb_tid);
1602 fnum = GETFNUM(inbuf,smb_vwv0);
1604 CHECK_FNUM(fnum,cnum);
1608 numtowrite = SVAL(inbuf,smb_vwv1);
1609 startpos = IVAL(inbuf,smb_vwv2);
1610 data = smb_buf(inbuf) + 3;
1612 if (is_locked(fnum,cnum,numtowrite,startpos))
1613 return(ERROR(ERRDOS,ERRlock));
1615 seek_file(fnum,startpos);
1617 /* The special X/Open SMB protocol handling of
1618 zero length writes is *NOT* done for
1623 nwritten = write_file(fnum,data,numtowrite);
1625 if (lp_syncalways(SNUM(cnum)))
1628 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1629 return(UNIXERROR(ERRDOS,ERRnoaccess));
1631 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1632 return(ERROR(eclass,ecode));
1634 outsize = set_message(outbuf,1,0,True);
1636 SSVAL(outbuf,smb_vwv0,nwritten);
1638 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1639 timestring(),fnum,cnum,numtowrite,nwritten));
1645 /****************************************************************************
1647 ****************************************************************************/
1648 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1650 int cnum,numtowrite,fnum;
1659 cnum = SVAL(inbuf,smb_tid);
1660 fnum = GETFNUM(inbuf,smb_vwv0);
1662 CHECK_FNUM(fnum,cnum);
1666 numtowrite = SVAL(inbuf,smb_vwv1);
1667 startpos = IVAL(inbuf,smb_vwv2);
1668 data = smb_buf(inbuf) + 3;
1670 if (is_locked(fnum,cnum,numtowrite,startpos))
1671 return(ERROR(ERRDOS,ERRlock));
1673 seek_file(fnum,startpos);
1675 /* X/Open SMB protocol says that if smb_vwv1 is
1676 zero then the file size should be extended or
1677 truncated to the size given in smb_vwv[2-3] */
1679 nwritten = set_filelen(Files[fnum].fd, startpos);
1681 nwritten = write_file(fnum,data,numtowrite);
1683 if (lp_syncalways(SNUM(cnum)))
1686 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1687 return(UNIXERROR(ERRDOS,ERRnoaccess));
1689 outsize = set_message(outbuf,1,0,True);
1691 SSVAL(outbuf,smb_vwv0,nwritten);
1693 if (nwritten < numtowrite) {
1694 CVAL(outbuf,smb_rcls) = ERRHRD;
1695 SSVAL(outbuf,smb_err,ERRdiskfull);
1698 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1704 /****************************************************************************
1705 reply to a write and X
1706 ****************************************************************************/
1707 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1709 int fnum = GETFNUM(inbuf,smb_vwv2);
1710 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1711 int smb_dsize = SVAL(inbuf,smb_vwv10);
1712 int smb_doff = SVAL(inbuf,smb_vwv11);
1713 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1718 cnum = SVAL(inbuf,smb_tid);
1720 CHECK_FNUM(fnum,cnum);
1724 data = smb_base(inbuf) + smb_doff;
1726 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1727 return(ERROR(ERRDOS,ERRlock));
1729 seek_file(fnum,smb_offs);
1731 /* X/Open SMB protocol says that, unlike SMBwrite
1732 if the length is zero then NO truncation is
1733 done, just a write of zero. To truncate a file,
1738 nwritten = write_file(fnum,data,smb_dsize);
1740 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1741 return(UNIXERROR(ERRDOS,ERRnoaccess));
1743 set_message(outbuf,6,0,True);
1745 SSVAL(outbuf,smb_vwv2,nwritten);
1747 if (nwritten < smb_dsize) {
1748 CVAL(outbuf,smb_rcls) = ERRHRD;
1749 SSVAL(outbuf,smb_err,ERRdiskfull);
1752 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1756 if (lp_syncalways(SNUM(cnum)) || write_through)
1759 return chain_reply(inbuf,outbuf,length,bufsize);
1763 /****************************************************************************
1765 ****************************************************************************/
1766 int reply_lseek(char *inbuf,char *outbuf)
1774 cnum = SVAL(inbuf,smb_tid);
1775 fnum = GETFNUM(inbuf,smb_vwv0);
1777 CHECK_FNUM(fnum,cnum);
1780 mode = SVAL(inbuf,smb_vwv1) & 3;
1781 startpos = IVAL(inbuf,smb_vwv2);
1785 case 0: umode = SEEK_SET; break;
1786 case 1: umode = SEEK_CUR; break;
1787 case 2: umode = SEEK_END; break;
1789 umode = SEEK_SET; break;
1792 res = lseek(Files[fnum].fd,startpos,umode);
1793 Files[fnum].pos = res;
1795 outsize = set_message(outbuf,2,0,True);
1796 SIVALS(outbuf,smb_vwv0,res);
1798 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1804 /****************************************************************************
1806 ****************************************************************************/
1807 int reply_flush(char *inbuf,char *outbuf)
1810 int outsize = set_message(outbuf,0,0,True);
1812 cnum = SVAL(inbuf,smb_tid);
1813 fnum = GETFNUM(inbuf,smb_vwv0);
1815 if (fnum != 0xFFFF) {
1816 CHECK_FNUM(fnum,cnum);
1823 for (i=0;i<MAX_OPEN_FILES;i++)
1830 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1835 /****************************************************************************
1837 ****************************************************************************/
1838 int reply_exit(char *inbuf,char *outbuf)
1840 int outsize = set_message(outbuf,0,0,True);
1841 DEBUG(3,("%s exit\n",timestring()));
1847 /****************************************************************************
1849 ****************************************************************************/
1850 int reply_close(char *inbuf,char *outbuf)
1855 int32 eclass = 0, err = 0;
1857 outsize = set_message(outbuf,0,0,True);
1859 cnum = SVAL(inbuf,smb_tid);
1861 fnum = GETFNUM(inbuf,smb_vwv0);
1862 CHECK_FNUM(fnum,cnum);
1864 if(HAS_CACHED_ERROR(fnum)) {
1865 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1866 err = Files[fnum].wbmpx_ptr->wr_error;
1869 mtime = make_unix_date3(inbuf+smb_vwv1);
1871 /* try and set the date */
1872 set_filetime(Files[fnum].name,mtime);
1876 /* We have a cached error */
1878 return(ERROR(eclass,err));
1880 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
1881 timestring(),Files[fnum].fd,fnum,cnum,
1882 Connections[cnum].num_files_open));
1888 /****************************************************************************
1889 reply to a writeclose (Core+ protocol)
1890 ****************************************************************************/
1891 int reply_writeclose(char *inbuf,char *outbuf)
1893 int cnum,numtowrite,fnum;
1900 cnum = SVAL(inbuf,smb_tid);
1901 fnum = GETFNUM(inbuf,smb_vwv0);
1903 CHECK_FNUM(fnum,cnum);
1907 numtowrite = SVAL(inbuf,smb_vwv1);
1908 startpos = IVAL(inbuf,smb_vwv2);
1909 mtime = make_unix_date3(inbuf+smb_vwv4);
1910 data = smb_buf(inbuf) + 1;
1912 if (is_locked(fnum,cnum,numtowrite,startpos))
1913 return(ERROR(ERRDOS,ERRlock));
1915 seek_file(fnum,startpos);
1917 nwritten = write_file(fnum,data,numtowrite);
1919 set_filetime(Files[fnum].name,mtime);
1923 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
1924 timestring(),fnum,cnum,numtowrite,nwritten,
1925 Connections[cnum].num_files_open));
1928 return(UNIXERROR(ERRDOS,ERRnoaccess));
1930 outsize = set_message(outbuf,1,0,True);
1932 SSVAL(outbuf,smb_vwv0,nwritten);
1937 /****************************************************************************
1939 ****************************************************************************/
1940 int reply_lock(char *inbuf,char *outbuf)
1943 int outsize = set_message(outbuf,0,0,True);
1944 uint32 count,offset;
1948 cnum = SVAL(inbuf,smb_tid);
1949 fnum = GETFNUM(inbuf,smb_vwv0);
1951 CHECK_FNUM(fnum,cnum);
1954 count = IVAL(inbuf,smb_vwv1);
1955 offset = IVAL(inbuf,smb_vwv3);
1957 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
1959 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
1960 return (ERROR(eclass,ecode));
1966 /****************************************************************************
1968 ****************************************************************************/
1969 int reply_unlock(char *inbuf,char *outbuf)
1972 int outsize = set_message(outbuf,0,0,True);
1973 uint32 count,offset;
1977 cnum = SVAL(inbuf,smb_tid);
1978 fnum = GETFNUM(inbuf,smb_vwv0);
1980 CHECK_FNUM(fnum,cnum);
1983 count = IVAL(inbuf,smb_vwv1);
1984 offset = IVAL(inbuf,smb_vwv3);
1986 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
1987 return (ERROR(eclass,ecode));
1989 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
1995 /****************************************************************************
1997 ****************************************************************************/
1998 int reply_tdis(char *inbuf,char *outbuf)
2001 int outsize = set_message(outbuf,0,0,True);
2003 cnum = SVAL(inbuf,smb_tid);
2004 uid = SVAL(inbuf,smb_uid);
2006 if (!OPEN_CNUM(cnum)) {
2007 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2008 return(ERROR(ERRSRV,ERRinvnid));
2011 Connections[cnum].used = False;
2013 close_cnum(cnum,uid);
2015 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2022 /****************************************************************************
2024 ****************************************************************************/
2025 int reply_echo(char *inbuf,char *outbuf)
2028 int smb_reverb = SVAL(inbuf,smb_vwv0);
2030 int data_len = smb_buflen(inbuf);
2031 int outsize = set_message(outbuf,1,data_len,True);
2033 cnum = SVAL(inbuf,smb_tid);
2035 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2037 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2038 return(ERROR(ERRSRV,ERRinvnid));
2041 /* copy any incoming data back out */
2043 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2045 if (smb_reverb > 100)
2047 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2051 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2053 SSVAL(outbuf,smb_vwv0,seq_num);
2055 smb_setlen(outbuf,outsize - 4);
2057 send_smb(Client,outbuf);
2060 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2066 /****************************************************************************
2067 reply to a printopen
2068 ****************************************************************************/
2069 int reply_printopen(char *inbuf,char *outbuf)
2077 *fname = *fname2 = 0;
2079 cnum = SVAL(inbuf,smb_tid);
2081 if (!CAN_PRINT(cnum))
2082 return(ERROR(ERRDOS,ERRnoaccess));
2087 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2091 if (!(isalnum(*p) || strchr("._-",*p)))
2096 if (strlen(s) > 10) s[10] = 0;
2098 sprintf(fname,"%s.XXXXXX",s);
2101 fnum = find_free_file();
2103 return(ERROR(ERRSRV,ERRnofids));
2105 strcpy(fname2,(char *)mktemp(fname));
2107 if (!check_name(fname2,cnum))
2108 return(ERROR(ERRDOS,ERRnoaccess));
2110 open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC,
2113 if (!Files[fnum].open)
2114 return(UNIXERROR(ERRDOS,ERRnoaccess));
2116 /* force it to be a print file */
2117 Files[fnum].print_file = True;
2119 outsize = set_message(outbuf,1,0,True);
2120 SSVAL(outbuf,smb_vwv0,fnum);
2122 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum));
2128 /****************************************************************************
2129 reply to a printclose
2130 ****************************************************************************/
2131 int reply_printclose(char *inbuf,char *outbuf)
2134 int outsize = set_message(outbuf,0,0,True);
2136 cnum = SVAL(inbuf,smb_tid);
2137 fnum = GETFNUM(inbuf,smb_vwv0);
2139 CHECK_FNUM(fnum,cnum);
2142 if (!CAN_PRINT(cnum))
2143 return(ERROR(ERRDOS,ERRnoaccess));
2147 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum));
2153 /****************************************************************************
2154 reply to a printqueue
2155 ****************************************************************************/
2156 int reply_printqueue(char *inbuf,char *outbuf)
2159 int outsize = set_message(outbuf,2,3,True);
2160 int max_count = SVAL(inbuf,smb_vwv0);
2161 int start_index = SVAL(inbuf,smb_vwv1);
2163 cnum = SVAL(inbuf,smb_tid);
2164 uid = SVAL(inbuf,smb_uid);
2166 /* allow checking the queue for anyone */
2168 if (!CAN_PRINT(cnum))
2169 return(ERROR(ERRDOS,ERRnoaccess));
2172 SSVAL(outbuf,smb_vwv0,0);
2173 SSVAL(outbuf,smb_vwv1,0);
2174 CVAL(smb_buf(outbuf),0) = 1;
2175 SSVAL(smb_buf(outbuf),1,0);
2177 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2178 timestring(),cnum,start_index,max_count));
2180 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2185 for (i=0;i<MAX_CONNECTIONS;i++)
2186 if (CAN_PRINT(i) && Connections[i].printer)
2190 for (i=0;i<MAX_CONNECTIONS;i++)
2194 if (!OPEN_CNUM(cnum))
2195 return(ERROR(ERRSRV,ERRinvnid));
2197 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2200 if (!become_user(cnum,uid))
2201 return(ERROR(ERRSRV,ERRinvnid));
2204 print_queue_struct *queue = NULL;
2205 char *p = smb_buf(outbuf) + 3;
2206 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2207 int num_to_get = ABS(max_count);
2208 int first = (max_count>0?start_index:start_index+max_count+1);
2214 num_to_get = MIN(num_to_get,count-first);
2217 for (i=first;i<first+num_to_get;i++)
2219 put_dos_date2(p,0,queue[i].time);
2220 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2221 SSVAL(p,5,queue[i].job);
2222 SIVAL(p,7,queue[i].size);
2224 StrnCpy(p+12,queue[i].user,16);
2230 outsize = set_message(outbuf,2,28*count+3,False);
2231 SSVAL(outbuf,smb_vwv0,count);
2232 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2233 CVAL(smb_buf(outbuf),0) = 1;
2234 SSVAL(smb_buf(outbuf),1,28*count);
2237 if (queue) free(queue);
2239 DEBUG(3,("%d entries returned in queue\n",count));
2246 /****************************************************************************
2247 reply to a printwrite
2248 ****************************************************************************/
2249 int reply_printwrite(char *inbuf,char *outbuf)
2251 int cnum,numtowrite,fnum;
2252 int outsize = set_message(outbuf,0,0,True);
2255 cnum = SVAL(inbuf,smb_tid);
2257 if (!CAN_PRINT(cnum))
2258 return(ERROR(ERRDOS,ERRnoaccess));
2260 fnum = GETFNUM(inbuf,smb_vwv0);
2262 CHECK_FNUM(fnum,cnum);
2266 numtowrite = SVAL(smb_buf(inbuf),1);
2267 data = smb_buf(inbuf) + 3;
2269 if (write_file(fnum,data,numtowrite) != numtowrite)
2270 return(UNIXERROR(ERRDOS,ERRnoaccess));
2272 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2278 /****************************************************************************
2280 ****************************************************************************/
2281 int reply_mkdir(char *inbuf,char *outbuf)
2285 int outsize,ret= -1;
2287 strcpy(directory,smb_buf(inbuf) + 1);
2288 cnum = SVAL(inbuf,smb_tid);
2289 unix_convert(directory,cnum);
2291 if (check_name(directory,cnum))
2292 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2295 return(UNIXERROR(ERRDOS,ERRnoaccess));
2297 outsize = set_message(outbuf,0,0,True);
2299 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2305 /****************************************************************************
2307 ****************************************************************************/
2308 int reply_rmdir(char *inbuf,char *outbuf)
2315 cnum = SVAL(inbuf,smb_tid);
2316 strcpy(directory,smb_buf(inbuf) + 1);
2317 unix_convert(directory,cnum);
2319 if (check_name(directory,cnum))
2321 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2322 ok = (sys_rmdir(directory) == 0);
2324 DEBUG(3,("couldn't remove directory %s : %s\n",
2325 directory,strerror(errno)));
2329 return(UNIXERROR(ERRDOS,ERRbadpath));
2331 outsize = set_message(outbuf,0,0,True);
2333 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2339 /*******************************************************************
2340 resolve wildcards in a filename rename
2341 ********************************************************************/
2342 static BOOL resolve_wildcards(char *name1,char *name2)
2344 fstring root1,root2;
2348 name1 = strrchr(name1,'/');
2349 name2 = strrchr(name2,'/');
2351 if (!name1 || !name2) return(False);
2353 strcpy(root1,name1);
2354 strcpy(root2,name2);
2355 p = strrchr(root1,'.');
2362 p = strrchr(root2,'.');
2394 strcpy(name2,root2);
2403 /*******************************************************************
2404 check if a user is allowed to rename a file
2405 ********************************************************************/
2406 static BOOL can_rename(char *fname,int cnum)
2410 if (!CAN_WRITE(cnum)) return(False);
2412 if (sys_lstat(fname,&sbuf) != 0) return(False);
2413 if (!check_file_sharing(cnum,fname)) return(False);
2418 /****************************************************************************
2420 ****************************************************************************/
2421 int reply_mv(char *inbuf,char *outbuf)
2427 pstring mask,newname;
2430 int error = ERRnoaccess;
2434 *directory = *mask = 0;
2436 cnum = SVAL(inbuf,smb_tid);
2438 strcpy(name,smb_buf(inbuf) + 1);
2439 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2441 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2443 unix_convert(name,cnum);
2444 unix_convert(newname,cnum);
2446 p = strrchr(name,'/');
2448 strcpy(directory,"./");
2452 strcpy(directory,name);
2456 if (is_mangled(mask))
2457 check_mangled_stack(mask);
2459 has_wild = strchr(mask,'*') || strchr(mask,'?');
2462 strcat(directory,"/");
2463 strcat(directory,mask);
2464 if (resolve_wildcards(directory,newname) &&
2465 can_rename(directory,cnum) &&
2466 !file_exist(newname,NULL) &&
2467 !sys_rename(directory,newname)) count++;
2468 if (!count) exists = file_exist(directory,NULL);
2469 if (!count && exists && file_exist(newname,NULL)) {
2474 void *dirptr = NULL;
2478 if (check_name(directory,cnum))
2479 dirptr = OpenDir(directory);
2485 if (strequal(mask,"????????.???"))
2488 while ((dname = ReadDirName(dirptr)))
2491 strcpy(fname,dname);
2493 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2495 error = ERRnoaccess;
2496 sprintf(fname,"%s/%s",directory,dname);
2497 if (!can_rename(fname,cnum)) continue;
2498 strcpy(destname,newname);
2500 if (!resolve_wildcards(fname,destname)) continue;
2502 if (file_exist(destname,NULL)) {
2506 if (!sys_rename(fname,destname)) count++;
2507 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2515 return(ERROR(ERRDOS,error));
2517 return(UNIXERROR(ERRDOS,error));
2520 outsize = set_message(outbuf,0,0,True);
2525 /*******************************************************************
2526 copy a file as part of a reply_copy
2527 ******************************************************************/
2528 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2529 int count,BOOL target_is_directory)
2538 if (target_is_directory) {
2539 char *p = strrchr(src,'/');
2548 if (!file_exist(src,&st)) return(False);
2550 fnum1 = find_free_file();
2551 if (fnum1<0) return(False);
2552 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2553 1,0,&Access,&action);
2555 if (!Files[fnum1].open) return(False);
2557 if (!target_is_directory && count)
2560 fnum2 = find_free_file();
2565 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2566 ofun,st.st_mode,&Access,&action);
2568 if (!Files[fnum2].open) {
2573 if ((ofun&3) == 1) {
2574 lseek(Files[fnum2].fd,0,SEEK_END);
2578 ret = transfer_file(Files[fnum1].fd,Files[fnum2].fd,st.st_size,NULL,0,0);
2583 return(ret == st.st_size);
2588 /****************************************************************************
2589 reply to a file copy.
2590 ****************************************************************************/
2591 int reply_copy(char *inbuf,char *outbuf)
2597 pstring mask,newname;
2600 int error = ERRnoaccess;
2603 int tid2 = SVAL(inbuf,smb_vwv0);
2604 int ofun = SVAL(inbuf,smb_vwv1);
2605 int flags = SVAL(inbuf,smb_vwv2);
2606 BOOL target_is_directory=False;
2608 *directory = *mask = 0;
2610 cnum = SVAL(inbuf,smb_tid);
2612 strcpy(name,smb_buf(inbuf));
2613 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2615 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2618 /* can't currently handle inter share copies XXXX */
2619 DEBUG(3,("Rejecting inter-share copy\n"));
2620 return(ERROR(ERRSRV,ERRinvdevice));
2623 unix_convert(name,cnum);
2624 unix_convert(newname,cnum);
2626 target_is_directory = directory_exist(newname,NULL);
2628 if ((flags&1) && target_is_directory) {
2629 return(ERROR(ERRDOS,ERRbadfile));
2632 if ((flags&2) && !target_is_directory) {
2633 return(ERROR(ERRDOS,ERRbadpath));
2636 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2637 /* wants a tree copy! XXXX */
2638 DEBUG(3,("Rejecting tree copy\n"));
2639 return(ERROR(ERRSRV,ERRerror));
2642 p = strrchr(name,'/');
2644 strcpy(directory,"./");
2648 strcpy(directory,name);
2652 if (is_mangled(mask))
2653 check_mangled_stack(mask);
2655 has_wild = strchr(mask,'*') || strchr(mask,'?');
2658 strcat(directory,"/");
2659 strcat(directory,mask);
2660 if (resolve_wildcards(directory,newname) &&
2661 copy_file(directory,newname,cnum,ofun,
2662 count,target_is_directory)) count++;
2663 if (!count) exists = file_exist(directory,NULL);
2665 void *dirptr = NULL;
2669 if (check_name(directory,cnum))
2670 dirptr = OpenDir(directory);
2676 if (strequal(mask,"????????.???"))
2679 while ((dname = ReadDirName(dirptr)))
2682 strcpy(fname,dname);
2684 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2686 error = ERRnoaccess;
2687 sprintf(fname,"%s/%s",directory,dname);
2688 strcpy(destname,newname);
2689 if (resolve_wildcards(fname,destname) &&
2690 copy_file(directory,newname,cnum,ofun,
2691 count,target_is_directory)) count++;
2692 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2700 return(ERROR(ERRDOS,error));
2702 return(UNIXERROR(ERRDOS,error));
2705 outsize = set_message(outbuf,1,0,True);
2706 SSVAL(outbuf,smb_vwv0,count);
2713 /****************************************************************************
2715 ****************************************************************************/
2716 int reply_setdir(char *inbuf,char *outbuf)
2723 cnum = SVAL(inbuf,smb_tid);
2725 snum = Connections[cnum].service;
2726 if (!CAN_SETDIR(snum))
2727 return(ERROR(ERRDOS,ERRnoaccess));
2729 strcpy(newdir,smb_buf(inbuf) + 1);
2732 if (strlen(newdir) == 0)
2736 ok = directory_exist(newdir,NULL);
2738 string_set(&Connections[cnum].connectpath,newdir);
2742 return(ERROR(ERRDOS,ERRbadpath));
2744 outsize = set_message(outbuf,0,0,True);
2745 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
2747 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
2753 /****************************************************************************
2754 reply to a lockingX request
2755 ****************************************************************************/
2756 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
2758 int fnum = GETFNUM(inbuf,smb_vwv2);
2759 uint16 locktype = SVAL(inbuf,smb_vwv3);
2760 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
2761 uint16 num_locks = SVAL(inbuf,smb_vwv7);
2762 uint32 count, offset;
2767 uint32 ecode=0, dummy2;
2768 int eclass=0, dummy1;
2770 cnum = SVAL(inbuf,smb_tid);
2772 CHECK_FNUM(fnum,cnum);
2775 data = smb_buf(inbuf);
2776 /* Data now points at the beginning of the list
2777 of smb_unlkrng structs */
2778 for(i = 0; i < (int)num_ulocks; i++) {
2779 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2780 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2781 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
2782 return ERROR(eclass,ecode);
2785 /* Now do any requested locks */
2786 data += 10*num_ulocks;
2787 /* Data now points at the beginning of the list
2788 of smb_lkrng structs */
2789 for(i = 0; i < (int)num_locks; i++) {
2790 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2791 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2792 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
2796 /* If any of the above locks failed, then we must unlock
2797 all of the previous locks (X/Open spec). */
2798 if(i != num_locks && num_locks != 0) {
2799 for(; i >= 0; i--) {
2800 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2801 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2802 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
2804 return ERROR(eclass,ecode);
2807 set_message(outbuf,2,0,True);
2809 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
2810 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
2814 return chain_reply(inbuf,outbuf,length,bufsize);
2818 /****************************************************************************
2819 reply to a SMBreadbmpx (read block multiplex) request
2820 ****************************************************************************/
2821 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
2828 int outsize, mincount, maxcount;
2833 /* this function doesn't seem to work - disable by default */
2835 return(ERROR(ERRSRV,ERRuseSTD));
2837 outsize = set_message(outbuf,8,0,True);
2839 cnum = SVAL(inbuf,smb_tid);
2840 fnum = GETFNUM(inbuf,smb_vwv0);
2842 CHECK_FNUM(fnum,cnum);
2846 startpos = IVAL(inbuf,smb_vwv1);
2847 maxcount = SVAL(inbuf,smb_vwv3);
2848 mincount = SVAL(inbuf,smb_vwv4);
2850 data = smb_buf(outbuf);
2851 pad = ((int)data)%4;
2852 if (pad) pad = 4 - pad;
2855 max_per_packet = bufsize-(outsize+pad);
2859 if (is_locked(fnum,cnum,maxcount,startpos))
2860 return(ERROR(ERRDOS,ERRlock));
2864 int N = MIN(max_per_packet,tcount-total_read);
2866 nread = read_file(fnum,data,startpos,N);
2868 if (nread <= 0) nread = 0;
2871 tcount = total_read + nread;
2873 set_message(outbuf,8,nread,False);
2874 SIVAL(outbuf,smb_vwv0,startpos);
2875 SSVAL(outbuf,smb_vwv2,tcount);
2876 SSVAL(outbuf,smb_vwv6,nread);
2877 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
2879 send_smb(Client,outbuf);
2881 total_read += nread;
2884 while (total_read < tcount);
2890 /****************************************************************************
2891 reply to a SMBwritebmpx (write block multiplex primary) request
2892 ****************************************************************************/
2893 int reply_writebmpx(char *inbuf,char *outbuf)
2895 int cnum,numtowrite,fnum;
2899 int tcount, write_through, smb_doff;
2902 cnum = SVAL(inbuf,smb_tid);
2903 fnum = GETFNUM(inbuf,smb_vwv0);
2905 CHECK_FNUM(fnum,cnum);
2909 tcount = SVAL(inbuf,smb_vwv1);
2910 startpos = IVAL(inbuf,smb_vwv3);
2911 write_through = BITSETW(inbuf+smb_vwv7,0);
2912 numtowrite = SVAL(inbuf,smb_vwv10);
2913 smb_doff = SVAL(inbuf,smb_vwv11);
2915 data = smb_base(inbuf) + smb_doff;
2917 /* If this fails we need to send an SMBwriteC response,
2918 not an SMBwritebmpx - set this up now so we don't forget */
2919 CVAL(outbuf,smb_com) = SMBwritec;
2921 if (is_locked(fnum,cnum,tcount,startpos))
2922 return(ERROR(ERRDOS,ERRlock));
2924 seek_file(fnum,startpos);
2925 nwritten = write_file(fnum,data,numtowrite);
2927 if(lp_syncalways(SNUM(cnum)) || write_through)
2930 if(nwritten < numtowrite)
2931 return(UNIXERROR(ERRHRD,ERRdiskfull));
2933 /* If the maximum to be written to this file
2934 is greater than what we just wrote then set
2935 up a secondary struct to be attached to this
2936 fd, we will use this to cache error messages etc. */
2937 if(tcount > nwritten)
2939 write_bmpx_struct *wbms;
2940 if(Files[fnum].wbmpx_ptr != NULL)
2941 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
2943 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
2946 DEBUG(0,("Out of memory in reply_readmpx\n"));
2947 return(ERROR(ERRSRV,ERRnoresource));
2949 wbms->wr_mode = write_through;
2950 wbms->wr_discard = False; /* No errors yet */
2951 wbms->wr_total_written = nwritten;
2952 wbms->wr_errclass = 0;
2954 Files[fnum].wbmpx_ptr = wbms;
2957 /* We are returning successfully, set the message type back to
2959 CVAL(outbuf,smb_com) = SMBwriteBmpx;
2961 outsize = set_message(outbuf,1,0,True);
2963 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
2965 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
2966 timestring(),fnum,cnum,numtowrite,nwritten));
2968 if (write_through && tcount==nwritten) {
2969 /* we need to send both a primary and a secondary response */
2970 smb_setlen(outbuf,outsize - 4);
2971 send_smb(Client,outbuf);
2973 /* now the secondary */
2974 outsize = set_message(outbuf,1,0,True);
2975 CVAL(outbuf,smb_com) = SMBwritec;
2976 SSVAL(outbuf,smb_vwv0,nwritten);
2983 /****************************************************************************
2984 reply to a SMBwritebs (write block multiplex secondary) request
2985 ****************************************************************************/
2986 int reply_writebs(char *inbuf,char *outbuf)
2988 int cnum,numtowrite,fnum;
2992 int tcount, write_through, smb_doff;
2994 write_bmpx_struct *wbms;
2995 BOOL send_response = False;
2997 cnum = SVAL(inbuf,smb_tid);
2998 fnum = GETFNUM(inbuf,smb_vwv0);
2999 CHECK_FNUM(fnum,cnum);
3002 tcount = SVAL(inbuf,smb_vwv1);
3003 startpos = IVAL(inbuf,smb_vwv2);
3004 numtowrite = SVAL(inbuf,smb_vwv6);
3005 smb_doff = SVAL(inbuf,smb_vwv7);
3007 data = smb_base(inbuf) + smb_doff;
3009 /* We need to send an SMBwriteC response, not an SMBwritebs */
3010 CVAL(outbuf,smb_com) = SMBwritec;
3012 /* This fd should have an auxiliary struct attached,
3013 check that it does */
3014 wbms = Files[fnum].wbmpx_ptr;
3015 if(!wbms) return(-1);
3017 /* If write through is set we can return errors, else we must
3019 write_through = wbms->wr_mode;
3021 /* Check for an earlier error */
3022 if(wbms->wr_discard)
3023 return -1; /* Just discard the packet */
3025 seek_file(fnum,startpos);
3026 nwritten = write_file(fnum,data,numtowrite);
3028 if(lp_syncalways(SNUM(cnum)) || write_through)
3031 if (nwritten < numtowrite)
3034 /* We are returning an error - we can delete the aux struct */
3035 if (wbms) free((char *)wbms);
3036 Files[fnum].wbmpx_ptr = NULL;
3037 return(ERROR(ERRHRD,ERRdiskfull));
3039 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3042 /* Increment the total written, if this matches tcount
3043 we can discard the auxiliary struct (hurrah !) and return a writeC */
3044 wbms->wr_total_written += nwritten;
3045 if(wbms->wr_total_written >= tcount)
3047 if (write_through) {
3048 outsize = set_message(outbuf,1,0,True);
3049 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3050 send_response = True;
3054 Files[fnum].wbmpx_ptr = NULL;
3064 /****************************************************************************
3065 reply to a SMBsetattrE
3066 ****************************************************************************/
3067 int reply_setattrE(char *inbuf,char *outbuf)
3070 struct utimbuf unix_times;
3073 outsize = set_message(outbuf,0,0,True);
3075 cnum = SVAL(inbuf,smb_tid);
3076 fnum = GETFNUM(inbuf,smb_vwv0);
3078 CHECK_FNUM(fnum,cnum);
3081 /* Convert the DOS times into unix times. Ignore create
3082 time as UNIX can't set this.
3084 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3085 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3087 /* Set the date on this file */
3088 if(sys_utime(Files[fnum].name, &unix_times))
3089 return(ERROR(ERRDOS,ERRnoaccess));
3091 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3097 /****************************************************************************
3098 reply to a SMBgetattrE
3099 ****************************************************************************/
3100 int reply_getattrE(char *inbuf,char *outbuf)
3107 outsize = set_message(outbuf,11,0,True);
3109 cnum = SVAL(inbuf,smb_tid);
3110 fnum = GETFNUM(inbuf,smb_vwv0);
3112 CHECK_FNUM(fnum,cnum);
3115 /* Do an fstat on this file */
3116 if(fstat(Files[fnum].fd, &sbuf))
3117 return(UNIXERROR(ERRDOS,ERRnoaccess));
3119 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3121 /* Convert the times into dos times. Set create
3122 date to be last modify date as UNIX doesn't save
3124 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3125 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3126 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3129 SIVAL(outbuf,smb_vwv6,0);
3130 SIVAL(outbuf,smb_vwv8,0);
3134 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3135 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3137 SSVAL(outbuf,smb_vwv10, mode);
3139 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));