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));
134 /****************************************************************************
135 parse a share descriptor string
136 ****************************************************************************/
137 static void parse_connect(char *p,char *service,char *user,
138 char *password,int *pwlen,char *dev)
142 DEBUG(4,("parsing connect string %s\n",p));
144 p2 = strrchr(p,'\\');
148 strcpy(service,p2+1);
153 *pwlen = strlen(password);
160 p = strchr(service,'%');
171 /****************************************************************************
173 ****************************************************************************/
174 int reply_tcon(char *inbuf,char *outbuf)
182 int uid = SVAL(inbuf,smb_uid);
186 *service = *user = *password = *dev = 0;
188 vuid = valid_uid(uid);
190 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
192 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
194 if (connection_num < 0)
195 return(connection_error(inbuf,outbuf,connection_num));
197 outsize = set_message(outbuf,2,0,True);
198 SSVAL(outbuf,smb_vwv0,maxxmit);
199 SSVAL(outbuf,smb_vwv1,connection_num);
200 SSVAL(outbuf,smb_tid,connection_num);
202 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
208 /****************************************************************************
209 reply to a tcon and X
210 ****************************************************************************/
211 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
218 int uid = SVAL(inbuf,smb_uid);
220 int passlen = SVAL(inbuf,smb_vwv3);
221 BOOL doencrypt = SMBENCRYPT();
223 *service = *user = *password = *devicename = 0;
225 /* we might have to close an old one */
226 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
227 close_cnum(SVAL(inbuf,smb_tid),uid);
229 vuid = valid_uid(uid);
234 memcpy(password,smb_buf(inbuf),passlen);
236 path = smb_buf(inbuf) + passlen;
238 if (!doencrypt || passlen != 24) {
239 if (strequal(password," "))
241 passlen = strlen(password);
244 DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
245 strcpy(service,path+2);
246 p = strchr(service,'\\');
248 return(ERROR(ERRSRV,ERRinvnetname));
251 p = strchr(service,'%');
257 StrnCpy(devicename,path + strlen(path) + 1,6);
258 DEBUG(4,("Got device type %s\n",devicename));
261 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
263 if (connection_num < 0)
264 return(connection_error(inbuf,outbuf,connection_num));
266 set_message(outbuf,2,strlen(devicename)+1,True);
268 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
270 /* set the incoming and outgoing tid to the just created one */
271 SSVAL(inbuf,smb_tid,connection_num);
272 SSVAL(outbuf,smb_tid,connection_num);
274 strcpy(smb_buf(outbuf),devicename);
276 return chain_reply(inbuf,outbuf,length,bufsize);
280 /****************************************************************************
281 reply to an unknown type
282 ****************************************************************************/
283 int reply_unknown(char *inbuf,char *outbuf)
287 cnum = SVAL(inbuf,smb_tid);
288 type = CVAL(inbuf,smb_com);
290 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
295 return(ERROR(ERRSRV,ERRunknownsmb));
299 /****************************************************************************
301 ****************************************************************************/
302 int reply_ioctl(char *inbuf,char *outbuf)
304 DEBUG(3,("ignoring ioctl\n"));
306 /* we just say it succeeds and hope its all OK.
307 some day it would be nice to interpret them individually */
308 return set_message(outbuf,1,0,True);
310 return(ERROR(ERRSRV,ERRnosupport));
315 /****************************************************************************
316 reply to a session setup command
317 ****************************************************************************/
318 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
326 int smb_apasslen = 0;
328 int smb_ntpasslen = 0;
329 pstring smb_ntpasswd;
330 BOOL valid_nt_password = False;
333 BOOL computer_id=False;
334 static BOOL done_sesssetup = False;
335 BOOL doencrypt = SMBENCRYPT();
339 sess_uid = SVAL(inbuf,smb_uid);
340 smb_bufsize = SVAL(inbuf,smb_vwv2);
341 smb_mpxmax = SVAL(inbuf,smb_vwv3);
342 smb_vc_num = SVAL(inbuf,smb_vwv4);
343 smb_sesskey = IVAL(inbuf,smb_vwv5);
345 if (Protocol < PROTOCOL_NT1) {
346 smb_apasslen = SVAL(inbuf,smb_vwv7);
347 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
348 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
350 if (lp_security() != SEC_SERVER && !doencrypt)
351 smb_apasslen = strlen(smb_apasswd);
353 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
354 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
355 char *p = smb_buf(inbuf);
357 if (passlen1 != 24 && passlen2 != 24)
361 /* Save the lanman2 password and the NT md4 password. */
362 smb_apasslen = passlen1;
363 memcpy(smb_apasswd,p,smb_apasslen);
364 smb_ntpasslen = passlen2;
365 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
367 /* both Win95 and WinNT stuff up the password lengths for
368 non-encrypting systems. Uggh.
370 if passlen1==24 its a win95 system, and its setting the
371 password length incorrectly. Luckily it still works with the
372 default code because Win95 will null terminate the password
375 if passlen1>0 and passlen2>0 then maybe its a NT box and its
376 setting passlen2 to some random value which really stuffs
377 things up. we need to fix that one. */
378 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
382 /* we use the first password that they gave */
383 smb_apasslen = passlen1;
384 StrnCpy(smb_apasswd,p,smb_apasslen);
386 /* trim the password */
387 smb_apasslen = strlen(smb_apasswd);
389 /* wfwg sometimes uses a space instead of a null */
390 if (strequal(smb_apasswd," ")) {
396 p += passlen1 + passlen2;
397 strcpy(user,p); p = skip_string(p,1);
398 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
399 p,skip_string(p,1),skip_string(p,2)));
403 DEBUG(3,("sesssetupX:name=[%s]\n",user));
405 /* If name ends in $ then I think it's asking about whether a */
406 /* computer with that name (minus the $) has access. For now */
407 /* say yes to everything ending in $. */
408 if (user[strlen(user) - 1] == '$') {
410 user[strlen(user) - 1] = '\0';
415 strcpy(user,lp_guestaccount(-1));
419 strcpy(sesssetup_user,user);
421 reload_services(True);
423 add_session_user(user);
426 if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
427 !check_hosts_equiv(user))
430 if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
433 /* now check if it's a valid username/password */
434 /* If an NT password was supplied try and validate with that
435 first. This is superior as the passwords are mixed case 128 length unicode */
436 if(smb_ntpasslen && !guest)
438 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
439 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
441 valid_nt_password = True;
443 if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
445 if (!computer_id && lp_security() >= SEC_USER) {
446 #if (GUEST_SESSSETUP == 0)
447 return(ERROR(ERRSRV,ERRbadpw));
449 #if (GUEST_SESSSETUP == 1)
450 if (Get_Pwnam(user,True))
451 return(ERROR(ERRSRV,ERRbadpw));
454 if (*smb_apasswd || !Get_Pwnam(user,True))
455 strcpy(user,lp_guestaccount(-1));
456 DEBUG(3,("Registered username %s for guest access\n",user));
461 if (!Get_Pwnam(user,True)) {
462 DEBUG(3,("No such user %s - using guest account\n",user));
463 strcpy(user,lp_guestaccount(-1));
467 if (!strequal(user,lp_guestaccount(-1)) &&
468 lp_servicenumber(user) < 0)
470 int homes = lp_servicenumber(HOMES_NAME);
471 char *home = get_home_dir(user);
472 if (homes >= 0 && home)
473 lp_add_home(user,homes,home);
477 /* it's ok - setup a reply */
478 if (Protocol < PROTOCOL_NT1) {
479 set_message(outbuf,3,0,True);
482 set_message(outbuf,3,3,True);
484 strcpy(p,"Unix"); p = skip_string(p,1);
485 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
486 strcpy(p,lp_workgroup()); p = skip_string(p,1);
487 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
488 /* perhaps grab OS version here?? */
491 /* Set the correct uid in the outgoing and incoming packets
492 We will use this on future requests to determine which
493 user we should become.
496 struct passwd *pw = Get_Pwnam(user,False);
498 DEBUG(1,("Username %s is invalid on this system\n",user));
499 return(ERROR(ERRSRV,ERRbadpw));
502 SSVAL(outbuf,smb_uid,(uint16)pw->pw_uid);
503 SSVAL(inbuf,smb_uid,(uint16)pw->pw_uid);
506 if (guest && !computer_id)
507 SSVAL(outbuf,smb_vwv2,1);
509 /* register the name and uid as being validated, so further connections
510 to a uid can get through without a password, on the same VC */
511 register_uid(SVAL(inbuf,smb_uid),gid,user,guest);
514 maxxmit = MIN(maxxmit,smb_bufsize);
516 done_sesssetup = True;
518 return chain_reply(inbuf,outbuf,length,bufsize);
522 /****************************************************************************
524 ****************************************************************************/
525 int reply_chkpth(char *inbuf,char *outbuf)
532 cnum = SVAL(inbuf,smb_tid);
534 strcpy(name,smb_buf(inbuf) + 1);
535 unix_convert(name,cnum);
537 mode = SVAL(inbuf,smb_vwv0);
539 if (check_name(name,cnum))
540 ok = directory_exist(name,NULL);
543 return(ERROR(ERRDOS,ERRbadpath));
545 outsize = set_message(outbuf,0,0,True);
547 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
553 /****************************************************************************
555 ****************************************************************************/
556 int reply_getatr(char *inbuf,char *outbuf)
567 cnum = SVAL(inbuf,smb_tid);
569 strcpy(fname,smb_buf(inbuf) + 1);
570 unix_convert(fname,cnum);
572 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
573 under WfWg - weird! */
576 mode = aHIDDEN | aDIR;
577 if (!CAN_WRITE(cnum)) mode |= aRONLY;
583 if (check_name(fname,cnum))
585 if (sys_stat(fname,&sbuf) == 0)
587 mode = dos_mode(cnum,fname,&sbuf);
589 mtime = sbuf.st_mtime;
595 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
599 return(UNIXERROR(ERRDOS,ERRbadfile));
601 outsize = set_message(outbuf,10,0,True);
603 SSVAL(outbuf,smb_vwv0,mode);
604 put_dos_date3(outbuf,smb_vwv1,mtime);
605 SIVAL(outbuf,smb_vwv3,size);
607 if (Protocol >= PROTOCOL_NT1) {
608 char *p = strrchr(fname,'/');
609 uint16 flg2 = SVAL(outbuf,smb_flg2);
612 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
615 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
621 /****************************************************************************
623 ****************************************************************************/
624 int reply_setatr(char *inbuf,char *outbuf)
633 cnum = SVAL(inbuf,smb_tid);
635 strcpy(fname,smb_buf(inbuf) + 1);
636 unix_convert(fname,cnum);
638 mode = SVAL(inbuf,smb_vwv0);
639 mtime = make_unix_date3(inbuf+smb_vwv1);
641 if (directory_exist(fname,NULL))
643 if (check_name(fname,cnum))
644 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
646 ok = set_filetime(fname,mtime);
649 return(UNIXERROR(ERRDOS,ERRnoaccess));
651 outsize = set_message(outbuf,0,0,True);
653 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
659 /****************************************************************************
661 ****************************************************************************/
662 int reply_dskattr(char *inbuf,char *outbuf)
666 int dfree,dsize,bsize;
668 cnum = SVAL(inbuf,smb_tid);
670 sys_disk_free(".",&bsize,&dfree,&dsize);
672 outsize = set_message(outbuf,5,0,True);
674 SSVAL(outbuf,smb_vwv0,dsize);
675 SSVAL(outbuf,smb_vwv1,bsize/512);
676 SSVAL(outbuf,smb_vwv2,512);
677 SSVAL(outbuf,smb_vwv3,dfree);
679 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
685 /****************************************************************************
687 Can be called from SMBsearch, SMBffirst or SMBfunique.
688 ****************************************************************************/
689 int reply_search(char *inbuf,char *outbuf)
700 BOOL finished = False;
709 BOOL check_descend = False;
710 BOOL expect_close = False;
711 BOOL can_open = True;
713 *mask = *directory = *fname = 0;
715 /* If we were called as SMBffirst then we must expect close. */
716 if(CVAL(inbuf,smb_com) == SMBffirst)
719 cnum = SVAL(inbuf,smb_tid);
721 outsize = set_message(outbuf,1,3,True);
722 maxentries = SVAL(inbuf,smb_vwv0);
723 dirtype = SVAL(inbuf,smb_vwv1);
724 path = smb_buf(inbuf) + 1;
725 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
728 /* dirtype &= ~aDIR; */
730 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
737 strcpy(directory,smb_buf(inbuf)+1);
738 strcpy(dir2,smb_buf(inbuf)+1);
739 unix_convert(directory,cnum);
742 if (!check_name(directory,cnum))
745 p = strrchr(dir2,'/');
747 {strcpy(mask,dir2);*dir2 = 0;}
749 {*p = 0;strcpy(mask,p+1);}
751 p = strrchr(directory,'/');
757 if (strlen(directory) == 0)
758 strcpy(directory,"./");
760 CVAL(status,0) = dirtype;
764 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
765 memcpy(mask,status+1,11);
767 dirtype = CVAL(status,0) & 0x1F;
768 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
769 if (!Connections[cnum].dirptr)
771 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
776 /* turn strings of spaces into a . */
778 trim_string(mask,NULL," ");
779 if ((p = strrchr(mask,' ')))
784 trim_string(mask,NULL," ");
791 for (p=mask; *p; p++)
793 if (*p != '?' && *p != '*' && !isdoschar(*p))
795 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
801 if (!strchr(mask,'.') && strlen(mask)>8)
804 strcpy(tmp,&mask[8]);
810 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
814 p = smb_buf(outbuf) + 3;
820 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
822 return(ERROR(ERRDOS,ERRnofids));
825 DEBUG(4,("dptr_num is %d\n",dptr_num));
829 if ((dirtype&0x1F) == aVOLID)
832 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
833 dptr_fill(p+12,dptr_num);
834 if (dptr_zero(p+12) && (status_len==0))
838 p += DIR_STRUCT_SIZE;
842 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
843 if (in_list(Connections[cnum].dirpath,
844 lp_dontdescend(SNUM(cnum)),True))
845 check_descend = True;
847 for (i=numentries;(i<maxentries) && !finished;i++)
850 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
854 make_dir_struct(p,mask,fname,size,mode,date);
855 dptr_fill(p+12,dptr_num);
858 p += DIR_STRUCT_SIZE;
867 if (numentries == 0 || !ok)
869 CVAL(outbuf,smb_rcls) = ERRDOS;
870 SSVAL(outbuf,smb_err,ERRnofiles);
873 /* If we were called as SMBffirst with smb_search_id == NULL
874 and no entries were found then return error and close dirptr
877 if(ok && expect_close && numentries == 0 && status_len == 0)
879 CVAL(outbuf,smb_rcls) = ERRDOS;
880 SSVAL(outbuf,smb_err,ERRnofiles);
881 /* Also close the dptr - we know it's gone */
882 dptr_close(dptr_num);
885 /* If we were called as SMBfunique, then we can close the dirptr now ! */
886 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
887 dptr_close(dptr_num);
889 SSVAL(outbuf,smb_vwv0,numentries);
890 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
891 CVAL(smb_buf(outbuf),0) = 5;
892 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
894 if (Protocol >= PROTOCOL_NT1) {
895 uint16 flg2 = SVAL(outbuf,smb_flg2);
896 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
899 outsize += DIR_STRUCT_SIZE*numentries;
900 smb_setlen(outbuf,outsize - 4);
902 if ((! *directory) && dptr_path(dptr_num))
903 sprintf(directory,"(%s)",dptr_path(dptr_num));
905 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
907 smb_fn_name(CVAL(inbuf,smb_com)),
908 mask,directory,cnum,dirtype,numentries,maxentries));
914 /****************************************************************************
915 reply to a fclose (stop directory search)
916 ****************************************************************************/
917 int reply_fclose(char *inbuf,char *outbuf)
926 cnum = SVAL(inbuf,smb_tid);
928 outsize = set_message(outbuf,1,0,True);
929 path = smb_buf(inbuf) + 1;
930 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
934 return(ERROR(ERRSRV,ERRsrverror));
936 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
938 if(dptr_fetch(status+12,&dptr_num)) {
939 /* Close the dptr - we know it's gone */
940 dptr_close(dptr_num);
943 SSVAL(outbuf,smb_vwv0,0);
945 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
951 /****************************************************************************
953 ****************************************************************************/
954 int reply_open(char *inbuf,char *outbuf)
968 cnum = SVAL(inbuf,smb_tid);
970 share_mode = SVAL(inbuf,smb_vwv0);
972 strcpy(fname,smb_buf(inbuf)+1);
973 unix_convert(fname,cnum);
975 fnum = find_free_file();
977 return(ERROR(ERRSRV,ERRnofids));
979 if (!check_name(fname,cnum))
980 return(UNIXERROR(ERRDOS,ERRnoaccess));
982 unixmode = unix_mode(cnum,aARCH);
984 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
986 if (!Files[fnum].open)
987 return(UNIXERROR(ERRDOS,ERRnoaccess));
989 if (fstat(Files[fnum].fd,&sbuf) != 0) {
991 return(ERROR(ERRDOS,ERRnoaccess));
995 fmode = dos_mode(cnum,fname,&sbuf);
996 mtime = sbuf.st_mtime;
999 DEBUG(3,("attempt to open a directory %s\n",fname));
1001 return(ERROR(ERRDOS,ERRnoaccess));
1004 outsize = set_message(outbuf,7,0,True);
1005 SSVAL(outbuf,smb_vwv0,fnum);
1006 SSVAL(outbuf,smb_vwv1,fmode);
1007 put_dos_date3(outbuf,smb_vwv2,mtime);
1008 SIVAL(outbuf,smb_vwv4,size);
1009 SSVAL(outbuf,smb_vwv6,rmode);
1011 if (lp_fake_oplocks(SNUM(cnum))) {
1012 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1019 /****************************************************************************
1020 reply to an open and X
1021 ****************************************************************************/
1022 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1025 int cnum = SVAL(inbuf,smb_tid);
1028 int smb_mode = SVAL(inbuf,smb_vwv3);
1029 int smb_attr = SVAL(inbuf,smb_vwv5);
1030 BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
1032 int open_flags = SVAL(inbuf,smb_vwv2);
1033 int smb_sattr = SVAL(inbuf,smb_vwv4);
1034 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1036 int smb_ofun = SVAL(inbuf,smb_vwv8);
1038 int size=0,fmode=0,mtime=0,rmode=0;
1042 /* If it's an IPC, pass off the pipe handler. */
1044 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1046 /* XXXX we need to handle passed times, sattr and flags */
1048 strcpy(fname,smb_buf(inbuf));
1049 unix_convert(fname,cnum);
1051 /* now add create and trunc bits */
1052 if (smb_ofun & 0x10)
1053 openmode |= O_CREAT;
1054 if ((smb_ofun & 0x3) == 2)
1055 openmode |= O_TRUNC;
1057 fnum = find_free_file();
1059 return(ERROR(ERRSRV,ERRnofids));
1061 if (!check_name(fname,cnum))
1062 return(UNIXERROR(ERRDOS,ERRnoaccess));
1064 unixmode = unix_mode(cnum,smb_attr | aARCH);
1066 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1067 &rmode,&smb_action);
1069 if (!Files[fnum].open)
1070 return(UNIXERROR(ERRDOS,ERRnoaccess));
1072 if (fstat(Files[fnum].fd,&sbuf) != 0) {
1074 return(ERROR(ERRDOS,ERRnoaccess));
1077 size = sbuf.st_size;
1078 fmode = dos_mode(cnum,fname,&sbuf);
1079 mtime = sbuf.st_mtime;
1082 return(ERROR(ERRDOS,ERRnoaccess));
1085 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1086 smb_action |= (1<<15);
1089 set_message(outbuf,15,0,True);
1090 SSVAL(outbuf,smb_vwv2,fnum);
1091 SSVAL(outbuf,smb_vwv3,fmode);
1092 put_dos_date3(outbuf,smb_vwv4,mtime);
1093 SIVAL(outbuf,smb_vwv6,size);
1094 SSVAL(outbuf,smb_vwv8,rmode);
1095 SSVAL(outbuf,smb_vwv11,smb_action);
1099 return chain_reply(inbuf,outbuf,length,bufsize);
1103 /****************************************************************************
1104 reply to a SMBulogoffX
1105 ****************************************************************************/
1106 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1108 int uid = SVAL(inbuf,smb_uid);
1110 invalidate_uid(uid);
1112 /* in user level security we are supposed to close any files
1113 open by this user */
1114 if (lp_security() != SEC_SHARE) {
1116 for (i=0;i<MAX_OPEN_FILES;i++)
1117 if (Files[i].uid == uid && Files[i].open) {
1122 set_message(outbuf,2,0,True);
1124 DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid));
1126 return chain_reply(inbuf,outbuf,length,bufsize);
1130 /****************************************************************************
1132 ****************************************************************************/
1133 int reply_mknew(char *inbuf,char *outbuf)
1142 com = SVAL(inbuf,smb_com);
1143 cnum = SVAL(inbuf,smb_tid);
1145 createmode = SVAL(inbuf,smb_vwv0);
1146 strcpy(fname,smb_buf(inbuf)+1);
1147 unix_convert(fname,cnum);
1149 if (createmode & aVOLID)
1151 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1154 unixmode = unix_mode(cnum,createmode);
1156 if (com == SMBmknew && file_exist(fname,NULL))
1157 return(ERROR(ERRDOS,ERRfilexists));
1159 fnum = find_free_file();
1161 return(ERROR(ERRSRV,ERRnofids));
1163 if (!check_name(fname,cnum))
1164 return(UNIXERROR(ERRDOS,ERRnoaccess));
1166 open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1168 if (!Files[fnum].open)
1169 return(UNIXERROR(ERRDOS,ERRnoaccess));
1171 outsize = set_message(outbuf,1,0,True);
1172 SSVAL(outbuf,smb_vwv0,fnum);
1174 if (lp_fake_oplocks(SNUM(cnum))) {
1175 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1178 DEBUG(2,("new file %s\n",fname));
1179 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));
1185 /****************************************************************************
1186 reply to a create temporary file
1187 ****************************************************************************/
1188 int reply_ctemp(char *inbuf,char *outbuf)
1198 cnum = SVAL(inbuf,smb_tid);
1199 createmode = SVAL(inbuf,smb_vwv0);
1200 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1201 unix_convert(fname,cnum);
1203 unixmode = unix_mode(cnum,createmode);
1205 fnum = find_free_file();
1207 return(ERROR(ERRSRV,ERRnofids));
1209 if (!check_name(fname,cnum))
1210 return(UNIXERROR(ERRDOS,ERRnoaccess));
1212 strcpy(fname2,(char *)mktemp(fname));
1214 open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1216 if (!Files[fnum].open)
1217 return(UNIXERROR(ERRDOS,ERRnoaccess));
1219 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1220 SSVAL(outbuf,smb_vwv0,fnum);
1221 CVAL(smb_buf(outbuf),0) = 4;
1222 strcpy(smb_buf(outbuf) + 1,fname2);
1224 if (lp_fake_oplocks(SNUM(cnum))) {
1225 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1228 DEBUG(2,("created temp file %s\n",fname2));
1229 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));
1235 /*******************************************************************
1236 check if a user is allowed to delete a file
1237 ********************************************************************/
1238 static BOOL can_delete(char *fname,int cnum,int dirtype)
1243 if (!CAN_WRITE(cnum)) return(False);
1245 if (sys_lstat(fname,&sbuf) != 0) return(False);
1246 fmode = dos_mode(cnum,fname,&sbuf);
1247 if (fmode & aDIR) return(False);
1248 if (!lp_delete_readonly(SNUM(cnum))) {
1249 if (fmode & aRONLY) return(False);
1251 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1253 if (!check_file_sharing(cnum,fname)) return(False);
1257 /****************************************************************************
1259 ****************************************************************************/
1260 int reply_unlink(char *inbuf,char *outbuf)
1270 int error = ERRnoaccess;
1274 *directory = *mask = 0;
1276 cnum = SVAL(inbuf,smb_tid);
1277 dirtype = SVAL(inbuf,smb_vwv0);
1279 strcpy(name,smb_buf(inbuf) + 1);
1281 DEBUG(3,("reply_unlink : %s\n",name));
1283 unix_convert(name,cnum);
1285 p = strrchr(name,'/');
1287 strcpy(directory,"./");
1291 strcpy(directory,name);
1295 if (is_mangled(mask))
1296 check_mangled_stack(mask);
1298 has_wild = strchr(mask,'*') || strchr(mask,'?');
1301 strcat(directory,"/");
1302 strcat(directory,mask);
1303 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1304 if (!count) exists = file_exist(directory,NULL);
1306 void *dirptr = NULL;
1309 if (check_name(directory,cnum))
1310 dirptr = OpenDir(directory);
1312 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1313 the pattern matches against the long name, otherwise the short name
1314 We don't implement this yet XXXX
1321 if (strequal(mask,"????????.???"))
1324 while ((dname = ReadDirName(dirptr)))
1327 strcpy(fname,dname);
1329 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1331 error = ERRnoaccess;
1332 sprintf(fname,"%s/%s",directory,dname);
1333 if (!can_delete(fname,cnum,dirtype)) continue;
1334 if (!sys_unlink(fname)) count++;
1335 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1343 return(ERROR(ERRDOS,error));
1345 return(UNIXERROR(ERRDOS,error));
1348 outsize = set_message(outbuf,0,0,True);
1354 /****************************************************************************
1355 reply to a readbraw (core+ protocol)
1356 ****************************************************************************/
1357 int reply_readbraw(char *inbuf, char *outbuf)
1359 int cnum,maxcount,mincount,fnum;
1362 char *header = outbuf;
1367 cnum = SVAL(inbuf,smb_tid);
1368 fnum = GETFNUM(inbuf,smb_vwv0);
1370 startpos = IVAL(inbuf,smb_vwv1);
1371 maxcount = SVAL(inbuf,smb_vwv3);
1372 mincount = SVAL(inbuf,smb_vwv4);
1374 /* ensure we don't overrun the packet size */
1375 maxcount = MIN(65535,maxcount);
1376 maxcount = MAX(mincount,maxcount);
1378 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1380 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1381 _smb_setlen(header,0);
1382 transfer_file(0,Client,0,header,4,0);
1387 fd = Files[fnum].fd;
1388 fname = Files[fnum].name;
1392 if (!is_locked(fnum,cnum,maxcount,startpos))
1394 int size = Files[fnum].size;
1395 int sizeneeded = startpos + maxcount;
1397 if (size < sizeneeded) {
1399 if (fstat(Files[fnum].fd,&st) == 0)
1401 if (!Files[fnum].can_write)
1402 Files[fnum].size = size;
1405 nread = MIN(maxcount,size - startpos);
1408 if (nread < mincount)
1411 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1414 maxcount,mincount,nread));
1419 _smb_setlen(header,nread);
1421 if (!Files[fnum].can_write)
1422 predict = read_predict(fd,startpos,header+4,NULL,nread);
1424 if ((nread-predict) > 0)
1425 seek_file(fnum,startpos + predict);
1427 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1432 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1433 fname,startpos,nread,ret));
1436 ret = read_file(fnum,header+4,startpos,nread);
1437 if (ret < mincount) ret = 0;
1439 _smb_setlen(header,ret);
1440 transfer_file(0,Client,0,header,4+ret,0);
1443 DEBUG(5,("readbraw finished\n"));
1448 /****************************************************************************
1449 reply to a lockread (core+ protocol)
1450 ****************************************************************************/
1451 int reply_lockread(char *inbuf,char *outbuf)
1457 uint32 startpos, numtoread;
1461 cnum = SVAL(inbuf,smb_tid);
1462 fnum = GETFNUM(inbuf,smb_vwv0);
1464 CHECK_FNUM(fnum,cnum);
1468 numtoread = SVAL(inbuf,smb_vwv1);
1469 startpos = IVAL(inbuf,smb_vwv2);
1471 outsize = set_message(outbuf,5,3,True);
1472 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1473 data = smb_buf(outbuf) + 3;
1475 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1476 return (ERROR(eclass,ecode));
1478 nread = read_file(fnum,data,startpos,numtoread);
1481 return(UNIXERROR(ERRDOS,ERRnoaccess));
1484 SSVAL(outbuf,smb_vwv0,nread);
1485 SSVAL(outbuf,smb_vwv5,nread+3);
1486 SSVAL(smb_buf(outbuf),1,nread);
1488 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1494 /****************************************************************************
1496 ****************************************************************************/
1497 int reply_read(char *inbuf,char *outbuf)
1499 int cnum,numtoread,fnum;
1505 cnum = SVAL(inbuf,smb_tid);
1506 fnum = GETFNUM(inbuf,smb_vwv0);
1508 CHECK_FNUM(fnum,cnum);
1512 numtoread = SVAL(inbuf,smb_vwv1);
1513 startpos = IVAL(inbuf,smb_vwv2);
1515 outsize = set_message(outbuf,5,3,True);
1516 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1517 data = smb_buf(outbuf) + 3;
1519 if (is_locked(fnum,cnum,numtoread,startpos))
1520 return(ERROR(ERRDOS,ERRlock));
1523 nread = read_file(fnum,data,startpos,numtoread);
1526 return(UNIXERROR(ERRDOS,ERRnoaccess));
1529 SSVAL(outbuf,smb_vwv0,nread);
1530 SSVAL(outbuf,smb_vwv5,nread+3);
1531 CVAL(smb_buf(outbuf),0) = 1;
1532 SSVAL(smb_buf(outbuf),1,nread);
1534 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1540 /****************************************************************************
1541 reply to a read and X
1542 ****************************************************************************/
1543 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1545 int fnum = GETFNUM(inbuf,smb_vwv2);
1546 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1547 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1548 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1554 cnum = SVAL(inbuf,smb_tid);
1556 CHECK_FNUM(fnum,cnum);
1560 set_message(outbuf,12,0,True);
1561 data = smb_buf(outbuf);
1563 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1564 return(ERROR(ERRDOS,ERRlock));
1565 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1569 return(UNIXERROR(ERRDOS,ERRnoaccess));
1571 SSVAL(outbuf,smb_vwv5,nread);
1572 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1573 SSVAL(smb_buf(outbuf),-2,nread);
1575 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1576 timestring(),fnum,cnum,
1577 smb_mincnt,smb_maxcnt,nread));
1581 return chain_reply(inbuf,outbuf,length,bufsize);
1585 /****************************************************************************
1586 reply to a writebraw (core+ or LANMAN1.0 protocol)
1587 ****************************************************************************/
1588 int reply_writebraw(char *inbuf,char *outbuf)
1591 int total_written=0;
1600 cnum = SVAL(inbuf,smb_tid);
1601 fnum = GETFNUM(inbuf,smb_vwv0);
1603 CHECK_FNUM(fnum,cnum);
1607 tcount = IVAL(inbuf,smb_vwv1);
1608 startpos = IVAL(inbuf,smb_vwv3);
1609 write_through = BITSETW(inbuf+smb_vwv7,0);
1611 /* We have to deal with slightly different formats depending
1612 on whether we are using the core+ or lanman1.0 protocol */
1613 if(Protocol <= PROTOCOL_COREPLUS) {
1614 numtowrite = SVAL(smb_buf(inbuf),-2);
1615 data = smb_buf(inbuf);
1617 numtowrite = SVAL(inbuf,smb_vwv10);
1618 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1621 /* force the error type */
1622 CVAL(inbuf,smb_com) = SMBwritec;
1623 CVAL(outbuf,smb_com) = SMBwritec;
1625 if (is_locked(fnum,cnum,tcount,startpos))
1626 return(ERROR(ERRDOS,ERRlock));
1628 if (seek_file(fnum,startpos) != startpos)
1629 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1632 nwritten = write_file(fnum,data,numtowrite);
1634 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1635 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1637 if (nwritten < numtowrite)
1638 return(UNIXERROR(ERRHRD,ERRdiskfull));
1640 total_written = nwritten;
1642 /* Return a message to the redirector to tell it
1643 to send more bytes */
1644 CVAL(outbuf,smb_com) = SMBwritebraw;
1645 SSVALS(outbuf,smb_vwv0,-1);
1646 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1647 send_smb(Client,outbuf);
1649 /* Now read the raw data into the buffer and write it */
1650 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1651 exit_server("secondary writebraw failed");
1654 /* Even though this is not an smb message, smb_len
1655 returns the generic length of an smb message */
1656 numtowrite = smb_len(inbuf);
1658 if (tcount > nwritten+numtowrite) {
1659 DEBUG(3,("Client overestimated the write %d %d %d\n",
1660 tcount,nwritten,numtowrite));
1663 nwritten = transfer_file(Client,Files[fnum].fd,numtowrite,NULL,0,
1665 total_written += nwritten;
1667 /* Set up outbuf to return the correct return */
1668 outsize = set_message(outbuf,1,0,True);
1669 CVAL(outbuf,smb_com) = SMBwritec;
1670 SSVAL(outbuf,smb_vwv0,total_written);
1672 if (nwritten < numtowrite) {
1673 CVAL(outbuf,smb_rcls) = ERRHRD;
1674 SSVAL(outbuf,smb_err,ERRdiskfull);
1677 if (lp_syncalways(SNUM(cnum)) || write_through)
1680 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1681 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1683 /* we won't return a status if write through is not selected - this
1684 follows what WfWg does */
1685 if (!write_through && total_written==tcount)
1692 /****************************************************************************
1693 reply to a writeunlock (core+)
1694 ****************************************************************************/
1695 int reply_writeunlock(char *inbuf,char *outbuf)
1701 uint32 numtowrite,startpos;
1705 cnum = SVAL(inbuf,smb_tid);
1706 fnum = GETFNUM(inbuf,smb_vwv0);
1708 CHECK_FNUM(fnum,cnum);
1712 numtowrite = SVAL(inbuf,smb_vwv1);
1713 startpos = IVAL(inbuf,smb_vwv2);
1714 data = smb_buf(inbuf) + 3;
1716 if (is_locked(fnum,cnum,numtowrite,startpos))
1717 return(ERROR(ERRDOS,ERRlock));
1719 seek_file(fnum,startpos);
1721 /* The special X/Open SMB protocol handling of
1722 zero length writes is *NOT* done for
1727 nwritten = write_file(fnum,data,numtowrite);
1729 if (lp_syncalways(SNUM(cnum)))
1732 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1733 return(UNIXERROR(ERRDOS,ERRnoaccess));
1735 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1736 return(ERROR(eclass,ecode));
1738 outsize = set_message(outbuf,1,0,True);
1740 SSVAL(outbuf,smb_vwv0,nwritten);
1742 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1743 timestring(),fnum,cnum,numtowrite,nwritten));
1749 /****************************************************************************
1751 ****************************************************************************/
1752 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1754 int cnum,numtowrite,fnum;
1763 cnum = SVAL(inbuf,smb_tid);
1764 fnum = GETFNUM(inbuf,smb_vwv0);
1766 CHECK_FNUM(fnum,cnum);
1770 numtowrite = SVAL(inbuf,smb_vwv1);
1771 startpos = IVAL(inbuf,smb_vwv2);
1772 data = smb_buf(inbuf) + 3;
1774 if (is_locked(fnum,cnum,numtowrite,startpos))
1775 return(ERROR(ERRDOS,ERRlock));
1777 seek_file(fnum,startpos);
1779 /* X/Open SMB protocol says that if smb_vwv1 is
1780 zero then the file size should be extended or
1781 truncated to the size given in smb_vwv[2-3] */
1783 nwritten = set_filelen(Files[fnum].fd, startpos);
1785 nwritten = write_file(fnum,data,numtowrite);
1787 if (lp_syncalways(SNUM(cnum)))
1790 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1791 return(UNIXERROR(ERRDOS,ERRnoaccess));
1793 outsize = set_message(outbuf,1,0,True);
1795 SSVAL(outbuf,smb_vwv0,nwritten);
1797 if (nwritten < numtowrite) {
1798 CVAL(outbuf,smb_rcls) = ERRHRD;
1799 SSVAL(outbuf,smb_err,ERRdiskfull);
1802 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1808 /****************************************************************************
1809 reply to a write and X
1810 ****************************************************************************/
1811 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1813 int fnum = GETFNUM(inbuf,smb_vwv2);
1814 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1815 int smb_dsize = SVAL(inbuf,smb_vwv10);
1816 int smb_doff = SVAL(inbuf,smb_vwv11);
1817 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1822 cnum = SVAL(inbuf,smb_tid);
1824 CHECK_FNUM(fnum,cnum);
1828 data = smb_base(inbuf) + smb_doff;
1830 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1831 return(ERROR(ERRDOS,ERRlock));
1833 seek_file(fnum,smb_offs);
1835 /* X/Open SMB protocol says that, unlike SMBwrite
1836 if the length is zero then NO truncation is
1837 done, just a write of zero. To truncate a file,
1842 nwritten = write_file(fnum,data,smb_dsize);
1844 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1845 return(UNIXERROR(ERRDOS,ERRnoaccess));
1847 set_message(outbuf,6,0,True);
1849 SSVAL(outbuf,smb_vwv2,nwritten);
1851 if (nwritten < smb_dsize) {
1852 CVAL(outbuf,smb_rcls) = ERRHRD;
1853 SSVAL(outbuf,smb_err,ERRdiskfull);
1856 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1860 if (lp_syncalways(SNUM(cnum)) || write_through)
1863 return chain_reply(inbuf,outbuf,length,bufsize);
1867 /****************************************************************************
1869 ****************************************************************************/
1870 int reply_lseek(char *inbuf,char *outbuf)
1878 cnum = SVAL(inbuf,smb_tid);
1879 fnum = GETFNUM(inbuf,smb_vwv0);
1881 CHECK_FNUM(fnum,cnum);
1884 mode = SVAL(inbuf,smb_vwv1) & 3;
1885 startpos = IVAL(inbuf,smb_vwv2);
1889 case 0: umode = SEEK_SET; break;
1890 case 1: umode = SEEK_CUR; break;
1891 case 2: umode = SEEK_END; break;
1893 umode = SEEK_SET; break;
1896 res = lseek(Files[fnum].fd,startpos,umode);
1897 Files[fnum].pos = res;
1899 outsize = set_message(outbuf,2,0,True);
1900 SIVALS(outbuf,smb_vwv0,res);
1902 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1908 /****************************************************************************
1910 ****************************************************************************/
1911 int reply_flush(char *inbuf,char *outbuf)
1914 int outsize = set_message(outbuf,0,0,True);
1916 cnum = SVAL(inbuf,smb_tid);
1917 fnum = GETFNUM(inbuf,smb_vwv0);
1919 if (fnum != 0xFFFF) {
1920 CHECK_FNUM(fnum,cnum);
1927 for (i=0;i<MAX_OPEN_FILES;i++)
1934 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1939 /****************************************************************************
1941 ****************************************************************************/
1942 int reply_exit(char *inbuf,char *outbuf)
1944 int outsize = set_message(outbuf,0,0,True);
1945 DEBUG(3,("%s exit\n",timestring()));
1951 /****************************************************************************
1953 ****************************************************************************/
1954 int reply_close(char *inbuf,char *outbuf)
1959 int32 eclass = 0, err = 0;
1961 outsize = set_message(outbuf,0,0,True);
1963 cnum = SVAL(inbuf,smb_tid);
1965 fnum = GETFNUM(inbuf,smb_vwv0);
1966 CHECK_FNUM(fnum,cnum);
1968 if(HAS_CACHED_ERROR(fnum)) {
1969 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1970 err = Files[fnum].wbmpx_ptr->wr_error;
1973 mtime = make_unix_date3(inbuf+smb_vwv1);
1975 /* try and set the date */
1976 set_filetime(Files[fnum].name,mtime);
1980 /* We have a cached error */
1982 return(ERROR(eclass,err));
1984 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
1985 timestring(),Files[fnum].fd,fnum,cnum,
1986 Connections[cnum].num_files_open));
1992 /****************************************************************************
1993 reply to a writeclose (Core+ protocol)
1994 ****************************************************************************/
1995 int reply_writeclose(char *inbuf,char *outbuf)
1997 int cnum,numtowrite,fnum;
2004 cnum = SVAL(inbuf,smb_tid);
2005 fnum = GETFNUM(inbuf,smb_vwv0);
2007 CHECK_FNUM(fnum,cnum);
2011 numtowrite = SVAL(inbuf,smb_vwv1);
2012 startpos = IVAL(inbuf,smb_vwv2);
2013 mtime = make_unix_date3(inbuf+smb_vwv4);
2014 data = smb_buf(inbuf) + 1;
2016 if (is_locked(fnum,cnum,numtowrite,startpos))
2017 return(ERROR(ERRDOS,ERRlock));
2019 seek_file(fnum,startpos);
2021 nwritten = write_file(fnum,data,numtowrite);
2023 set_filetime(Files[fnum].name,mtime);
2027 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2028 timestring(),fnum,cnum,numtowrite,nwritten,
2029 Connections[cnum].num_files_open));
2032 return(UNIXERROR(ERRDOS,ERRnoaccess));
2034 outsize = set_message(outbuf,1,0,True);
2036 SSVAL(outbuf,smb_vwv0,nwritten);
2041 /****************************************************************************
2043 ****************************************************************************/
2044 int reply_lock(char *inbuf,char *outbuf)
2047 int outsize = set_message(outbuf,0,0,True);
2048 uint32 count,offset;
2052 cnum = SVAL(inbuf,smb_tid);
2053 fnum = GETFNUM(inbuf,smb_vwv0);
2055 CHECK_FNUM(fnum,cnum);
2058 count = IVAL(inbuf,smb_vwv1);
2059 offset = IVAL(inbuf,smb_vwv3);
2061 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2063 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2064 return (ERROR(eclass,ecode));
2070 /****************************************************************************
2072 ****************************************************************************/
2073 int reply_unlock(char *inbuf,char *outbuf)
2076 int outsize = set_message(outbuf,0,0,True);
2077 uint32 count,offset;
2081 cnum = SVAL(inbuf,smb_tid);
2082 fnum = GETFNUM(inbuf,smb_vwv0);
2084 CHECK_FNUM(fnum,cnum);
2087 count = IVAL(inbuf,smb_vwv1);
2088 offset = IVAL(inbuf,smb_vwv3);
2090 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2091 return (ERROR(eclass,ecode));
2093 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2099 /****************************************************************************
2101 ****************************************************************************/
2102 int reply_tdis(char *inbuf,char *outbuf)
2105 int outsize = set_message(outbuf,0,0,True);
2107 cnum = SVAL(inbuf,smb_tid);
2108 uid = SVAL(inbuf,smb_uid);
2110 if (!OPEN_CNUM(cnum)) {
2111 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2112 return(ERROR(ERRSRV,ERRinvnid));
2115 Connections[cnum].used = False;
2117 close_cnum(cnum,uid);
2119 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2126 /****************************************************************************
2128 ****************************************************************************/
2129 int reply_echo(char *inbuf,char *outbuf)
2132 int smb_reverb = SVAL(inbuf,smb_vwv0);
2134 int data_len = smb_buflen(inbuf);
2135 int outsize = set_message(outbuf,1,data_len,True);
2137 cnum = SVAL(inbuf,smb_tid);
2139 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2141 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2142 return(ERROR(ERRSRV,ERRinvnid));
2145 /* copy any incoming data back out */
2147 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2149 if (smb_reverb > 100)
2151 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2155 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2157 SSVAL(outbuf,smb_vwv0,seq_num);
2159 smb_setlen(outbuf,outsize - 4);
2161 send_smb(Client,outbuf);
2164 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2170 /****************************************************************************
2171 reply to a printopen
2172 ****************************************************************************/
2173 int reply_printopen(char *inbuf,char *outbuf)
2181 *fname = *fname2 = 0;
2183 cnum = SVAL(inbuf,smb_tid);
2185 if (!CAN_PRINT(cnum))
2186 return(ERROR(ERRDOS,ERRnoaccess));
2191 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2195 if (!(isalnum(*p) || strchr("._-",*p)))
2200 if (strlen(s) > 10) s[10] = 0;
2202 sprintf(fname,"%s.XXXXXX",s);
2205 fnum = find_free_file();
2207 return(ERROR(ERRSRV,ERRnofids));
2209 strcpy(fname2,(char *)mktemp(fname));
2211 if (!check_name(fname2,cnum))
2212 return(ERROR(ERRDOS,ERRnoaccess));
2214 open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC,
2217 if (!Files[fnum].open)
2218 return(UNIXERROR(ERRDOS,ERRnoaccess));
2220 /* force it to be a print file */
2221 Files[fnum].print_file = True;
2223 outsize = set_message(outbuf,1,0,True);
2224 SSVAL(outbuf,smb_vwv0,fnum);
2226 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum));
2232 /****************************************************************************
2233 reply to a printclose
2234 ****************************************************************************/
2235 int reply_printclose(char *inbuf,char *outbuf)
2238 int outsize = set_message(outbuf,0,0,True);
2240 cnum = SVAL(inbuf,smb_tid);
2241 fnum = GETFNUM(inbuf,smb_vwv0);
2243 CHECK_FNUM(fnum,cnum);
2246 if (!CAN_PRINT(cnum))
2247 return(ERROR(ERRDOS,ERRnoaccess));
2251 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum));
2257 /****************************************************************************
2258 reply to a printqueue
2259 ****************************************************************************/
2260 int reply_printqueue(char *inbuf,char *outbuf)
2263 int outsize = set_message(outbuf,2,3,True);
2264 int max_count = SVAL(inbuf,smb_vwv0);
2265 int start_index = SVAL(inbuf,smb_vwv1);
2267 cnum = SVAL(inbuf,smb_tid);
2268 uid = SVAL(inbuf,smb_uid);
2270 /* allow checking the queue for anyone */
2272 if (!CAN_PRINT(cnum))
2273 return(ERROR(ERRDOS,ERRnoaccess));
2276 SSVAL(outbuf,smb_vwv0,0);
2277 SSVAL(outbuf,smb_vwv1,0);
2278 CVAL(smb_buf(outbuf),0) = 1;
2279 SSVAL(smb_buf(outbuf),1,0);
2281 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2282 timestring(),cnum,start_index,max_count));
2284 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2289 for (i=0;i<MAX_CONNECTIONS;i++)
2290 if (CAN_PRINT(i) && Connections[i].printer)
2294 for (i=0;i<MAX_CONNECTIONS;i++)
2298 if (!OPEN_CNUM(cnum))
2299 return(ERROR(ERRSRV,ERRinvnid));
2301 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2304 if (!become_user(cnum,uid))
2305 return(ERROR(ERRSRV,ERRinvnid));
2308 print_queue_struct *queue = NULL;
2309 char *p = smb_buf(outbuf) + 3;
2310 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2311 int num_to_get = ABS(max_count);
2312 int first = (max_count>0?start_index:start_index+max_count+1);
2318 num_to_get = MIN(num_to_get,count-first);
2321 for (i=first;i<first+num_to_get;i++)
2323 put_dos_date2(p,0,queue[i].time);
2324 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2325 SSVAL(p,5,queue[i].job);
2326 SIVAL(p,7,queue[i].size);
2328 StrnCpy(p+12,queue[i].user,16);
2334 outsize = set_message(outbuf,2,28*count+3,False);
2335 SSVAL(outbuf,smb_vwv0,count);
2336 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2337 CVAL(smb_buf(outbuf),0) = 1;
2338 SSVAL(smb_buf(outbuf),1,28*count);
2341 if (queue) free(queue);
2343 DEBUG(3,("%d entries returned in queue\n",count));
2350 /****************************************************************************
2351 reply to a printwrite
2352 ****************************************************************************/
2353 int reply_printwrite(char *inbuf,char *outbuf)
2355 int cnum,numtowrite,fnum;
2356 int outsize = set_message(outbuf,0,0,True);
2359 cnum = SVAL(inbuf,smb_tid);
2361 if (!CAN_PRINT(cnum))
2362 return(ERROR(ERRDOS,ERRnoaccess));
2364 fnum = GETFNUM(inbuf,smb_vwv0);
2366 CHECK_FNUM(fnum,cnum);
2370 numtowrite = SVAL(smb_buf(inbuf),1);
2371 data = smb_buf(inbuf) + 3;
2373 if (write_file(fnum,data,numtowrite) != numtowrite)
2374 return(UNIXERROR(ERRDOS,ERRnoaccess));
2376 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2382 /****************************************************************************
2384 ****************************************************************************/
2385 int reply_mkdir(char *inbuf,char *outbuf)
2389 int outsize,ret= -1;
2391 strcpy(directory,smb_buf(inbuf) + 1);
2392 cnum = SVAL(inbuf,smb_tid);
2393 unix_convert(directory,cnum);
2395 if (check_name(directory,cnum))
2396 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2399 return(UNIXERROR(ERRDOS,ERRnoaccess));
2401 outsize = set_message(outbuf,0,0,True);
2403 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2409 /****************************************************************************
2411 ****************************************************************************/
2412 int reply_rmdir(char *inbuf,char *outbuf)
2419 cnum = SVAL(inbuf,smb_tid);
2420 strcpy(directory,smb_buf(inbuf) + 1);
2421 unix_convert(directory,cnum);
2423 if (check_name(directory,cnum))
2425 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2426 ok = (sys_rmdir(directory) == 0);
2428 DEBUG(3,("couldn't remove directory %s : %s\n",
2429 directory,strerror(errno)));
2433 return(UNIXERROR(ERRDOS,ERRbadpath));
2435 outsize = set_message(outbuf,0,0,True);
2437 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2443 /*******************************************************************
2444 resolve wildcards in a filename rename
2445 ********************************************************************/
2446 static BOOL resolve_wildcards(char *name1,char *name2)
2448 fstring root1,root2;
2452 name1 = strrchr(name1,'/');
2453 name2 = strrchr(name2,'/');
2455 if (!name1 || !name2) return(False);
2457 strcpy(root1,name1);
2458 strcpy(root2,name2);
2459 p = strrchr(root1,'.');
2466 p = strrchr(root2,'.');
2498 strcpy(name2,root2);
2507 /*******************************************************************
2508 check if a user is allowed to rename a file
2509 ********************************************************************/
2510 static BOOL can_rename(char *fname,int cnum)
2514 if (!CAN_WRITE(cnum)) return(False);
2516 if (sys_lstat(fname,&sbuf) != 0) return(False);
2517 if (!check_file_sharing(cnum,fname)) return(False);
2522 /****************************************************************************
2524 ****************************************************************************/
2525 int reply_mv(char *inbuf,char *outbuf)
2531 pstring mask,newname;
2534 int error = ERRnoaccess;
2538 *directory = *mask = 0;
2540 cnum = SVAL(inbuf,smb_tid);
2542 strcpy(name,smb_buf(inbuf) + 1);
2543 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2545 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2547 unix_convert(name,cnum);
2548 unix_convert(newname,cnum);
2550 p = strrchr(name,'/');
2552 strcpy(directory,"./");
2556 strcpy(directory,name);
2560 if (is_mangled(mask))
2561 check_mangled_stack(mask);
2563 has_wild = strchr(mask,'*') || strchr(mask,'?');
2566 strcat(directory,"/");
2567 strcat(directory,mask);
2568 if (resolve_wildcards(directory,newname) &&
2569 can_rename(directory,cnum) &&
2570 !file_exist(newname,NULL) &&
2571 !sys_rename(directory,newname)) count++;
2572 if (!count) exists = file_exist(directory,NULL);
2573 if (!count && exists && file_exist(newname,NULL)) {
2578 void *dirptr = NULL;
2582 if (check_name(directory,cnum))
2583 dirptr = OpenDir(directory);
2589 if (strequal(mask,"????????.???"))
2592 while ((dname = ReadDirName(dirptr)))
2595 strcpy(fname,dname);
2597 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2599 error = ERRnoaccess;
2600 sprintf(fname,"%s/%s",directory,dname);
2601 if (!can_rename(fname,cnum)) continue;
2602 strcpy(destname,newname);
2604 if (!resolve_wildcards(fname,destname)) continue;
2606 if (file_exist(destname,NULL)) {
2610 if (!sys_rename(fname,destname)) count++;
2611 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2619 return(ERROR(ERRDOS,error));
2621 return(UNIXERROR(ERRDOS,error));
2624 outsize = set_message(outbuf,0,0,True);
2629 /*******************************************************************
2630 copy a file as part of a reply_copy
2631 ******************************************************************/
2632 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2633 int count,BOOL target_is_directory)
2642 if (target_is_directory) {
2643 char *p = strrchr(src,'/');
2652 if (!file_exist(src,&st)) return(False);
2654 fnum1 = find_free_file();
2655 if (fnum1<0) return(False);
2656 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2657 1,0,&Access,&action);
2659 if (!Files[fnum1].open) return(False);
2661 if (!target_is_directory && count)
2664 fnum2 = find_free_file();
2669 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2670 ofun,st.st_mode,&Access,&action);
2672 if (!Files[fnum2].open) {
2677 if ((ofun&3) == 1) {
2678 lseek(Files[fnum2].fd,0,SEEK_END);
2682 ret = transfer_file(Files[fnum1].fd,Files[fnum2].fd,st.st_size,NULL,0,0);
2687 return(ret == st.st_size);
2692 /****************************************************************************
2693 reply to a file copy.
2694 ****************************************************************************/
2695 int reply_copy(char *inbuf,char *outbuf)
2701 pstring mask,newname;
2704 int error = ERRnoaccess;
2707 int tid2 = SVAL(inbuf,smb_vwv0);
2708 int ofun = SVAL(inbuf,smb_vwv1);
2709 int flags = SVAL(inbuf,smb_vwv2);
2710 BOOL target_is_directory=False;
2712 *directory = *mask = 0;
2714 cnum = SVAL(inbuf,smb_tid);
2716 strcpy(name,smb_buf(inbuf));
2717 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2719 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2722 /* can't currently handle inter share copies XXXX */
2723 DEBUG(3,("Rejecting inter-share copy\n"));
2724 return(ERROR(ERRSRV,ERRinvdevice));
2727 unix_convert(name,cnum);
2728 unix_convert(newname,cnum);
2730 target_is_directory = directory_exist(newname,NULL);
2732 if ((flags&1) && target_is_directory) {
2733 return(ERROR(ERRDOS,ERRbadfile));
2736 if ((flags&2) && !target_is_directory) {
2737 return(ERROR(ERRDOS,ERRbadpath));
2740 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2741 /* wants a tree copy! XXXX */
2742 DEBUG(3,("Rejecting tree copy\n"));
2743 return(ERROR(ERRSRV,ERRerror));
2746 p = strrchr(name,'/');
2748 strcpy(directory,"./");
2752 strcpy(directory,name);
2756 if (is_mangled(mask))
2757 check_mangled_stack(mask);
2759 has_wild = strchr(mask,'*') || strchr(mask,'?');
2762 strcat(directory,"/");
2763 strcat(directory,mask);
2764 if (resolve_wildcards(directory,newname) &&
2765 copy_file(directory,newname,cnum,ofun,
2766 count,target_is_directory)) count++;
2767 if (!count) exists = file_exist(directory,NULL);
2769 void *dirptr = NULL;
2773 if (check_name(directory,cnum))
2774 dirptr = OpenDir(directory);
2780 if (strequal(mask,"????????.???"))
2783 while ((dname = ReadDirName(dirptr)))
2786 strcpy(fname,dname);
2788 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2790 error = ERRnoaccess;
2791 sprintf(fname,"%s/%s",directory,dname);
2792 strcpy(destname,newname);
2793 if (resolve_wildcards(fname,destname) &&
2794 copy_file(directory,newname,cnum,ofun,
2795 count,target_is_directory)) count++;
2796 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2804 return(ERROR(ERRDOS,error));
2806 return(UNIXERROR(ERRDOS,error));
2809 outsize = set_message(outbuf,1,0,True);
2810 SSVAL(outbuf,smb_vwv0,count);
2817 /****************************************************************************
2819 ****************************************************************************/
2820 int reply_setdir(char *inbuf,char *outbuf)
2827 cnum = SVAL(inbuf,smb_tid);
2829 snum = Connections[cnum].service;
2830 if (!CAN_SETDIR(snum))
2831 return(ERROR(ERRDOS,ERRnoaccess));
2833 strcpy(newdir,smb_buf(inbuf) + 1);
2836 if (strlen(newdir) == 0)
2840 ok = directory_exist(newdir,NULL);
2842 string_set(&Connections[cnum].connectpath,newdir);
2846 return(ERROR(ERRDOS,ERRbadpath));
2848 outsize = set_message(outbuf,0,0,True);
2849 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
2851 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
2857 /****************************************************************************
2858 reply to a lockingX request
2859 ****************************************************************************/
2860 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
2862 int fnum = GETFNUM(inbuf,smb_vwv2);
2863 uint16 locktype = SVAL(inbuf,smb_vwv3);
2864 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
2865 uint16 num_locks = SVAL(inbuf,smb_vwv7);
2866 uint32 count, offset;
2871 uint32 ecode=0, dummy2;
2872 int eclass=0, dummy1;
2874 cnum = SVAL(inbuf,smb_tid);
2876 CHECK_FNUM(fnum,cnum);
2879 data = smb_buf(inbuf);
2880 /* Data now points at the beginning of the list
2881 of smb_unlkrng structs */
2882 for(i = 0; i < (int)num_ulocks; i++) {
2883 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2884 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2885 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
2886 return ERROR(eclass,ecode);
2889 /* Now do any requested locks */
2890 data += 10*num_ulocks;
2891 /* Data now points at the beginning of the list
2892 of smb_lkrng structs */
2893 for(i = 0; i < (int)num_locks; i++) {
2894 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2895 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2896 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
2900 /* If any of the above locks failed, then we must unlock
2901 all of the previous locks (X/Open spec). */
2902 if(i != num_locks && num_locks != 0) {
2903 for(; i >= 0; i--) {
2904 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2905 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2906 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
2908 return ERROR(eclass,ecode);
2911 set_message(outbuf,2,0,True);
2913 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
2914 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
2918 return chain_reply(inbuf,outbuf,length,bufsize);
2922 /****************************************************************************
2923 reply to a SMBreadbmpx (read block multiplex) request
2924 ****************************************************************************/
2925 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
2932 int outsize, mincount, maxcount;
2937 /* this function doesn't seem to work - disable by default */
2939 return(ERROR(ERRSRV,ERRuseSTD));
2941 outsize = set_message(outbuf,8,0,True);
2943 cnum = SVAL(inbuf,smb_tid);
2944 fnum = GETFNUM(inbuf,smb_vwv0);
2946 CHECK_FNUM(fnum,cnum);
2950 startpos = IVAL(inbuf,smb_vwv1);
2951 maxcount = SVAL(inbuf,smb_vwv3);
2952 mincount = SVAL(inbuf,smb_vwv4);
2954 data = smb_buf(outbuf);
2955 pad = ((int)data)%4;
2956 if (pad) pad = 4 - pad;
2959 max_per_packet = bufsize-(outsize+pad);
2963 if (is_locked(fnum,cnum,maxcount,startpos))
2964 return(ERROR(ERRDOS,ERRlock));
2968 int N = MIN(max_per_packet,tcount-total_read);
2970 nread = read_file(fnum,data,startpos,N);
2972 if (nread <= 0) nread = 0;
2975 tcount = total_read + nread;
2977 set_message(outbuf,8,nread,False);
2978 SIVAL(outbuf,smb_vwv0,startpos);
2979 SSVAL(outbuf,smb_vwv2,tcount);
2980 SSVAL(outbuf,smb_vwv6,nread);
2981 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
2983 send_smb(Client,outbuf);
2985 total_read += nread;
2988 while (total_read < tcount);
2994 /****************************************************************************
2995 reply to a SMBwritebmpx (write block multiplex primary) request
2996 ****************************************************************************/
2997 int reply_writebmpx(char *inbuf,char *outbuf)
2999 int cnum,numtowrite,fnum;
3003 int tcount, write_through, smb_doff;
3006 cnum = SVAL(inbuf,smb_tid);
3007 fnum = GETFNUM(inbuf,smb_vwv0);
3009 CHECK_FNUM(fnum,cnum);
3013 tcount = SVAL(inbuf,smb_vwv1);
3014 startpos = IVAL(inbuf,smb_vwv3);
3015 write_through = BITSETW(inbuf+smb_vwv7,0);
3016 numtowrite = SVAL(inbuf,smb_vwv10);
3017 smb_doff = SVAL(inbuf,smb_vwv11);
3019 data = smb_base(inbuf) + smb_doff;
3021 /* If this fails we need to send an SMBwriteC response,
3022 not an SMBwritebmpx - set this up now so we don't forget */
3023 CVAL(outbuf,smb_com) = SMBwritec;
3025 if (is_locked(fnum,cnum,tcount,startpos))
3026 return(ERROR(ERRDOS,ERRlock));
3028 seek_file(fnum,startpos);
3029 nwritten = write_file(fnum,data,numtowrite);
3031 if(lp_syncalways(SNUM(cnum)) || write_through)
3034 if(nwritten < numtowrite)
3035 return(UNIXERROR(ERRHRD,ERRdiskfull));
3037 /* If the maximum to be written to this file
3038 is greater than what we just wrote then set
3039 up a secondary struct to be attached to this
3040 fd, we will use this to cache error messages etc. */
3041 if(tcount > nwritten)
3043 write_bmpx_struct *wbms;
3044 if(Files[fnum].wbmpx_ptr != NULL)
3045 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3047 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3050 DEBUG(0,("Out of memory in reply_readmpx\n"));
3051 return(ERROR(ERRSRV,ERRnoresource));
3053 wbms->wr_mode = write_through;
3054 wbms->wr_discard = False; /* No errors yet */
3055 wbms->wr_total_written = nwritten;
3056 wbms->wr_errclass = 0;
3058 Files[fnum].wbmpx_ptr = wbms;
3061 /* We are returning successfully, set the message type back to
3063 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3065 outsize = set_message(outbuf,1,0,True);
3067 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3069 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3070 timestring(),fnum,cnum,numtowrite,nwritten));
3072 if (write_through && tcount==nwritten) {
3073 /* we need to send both a primary and a secondary response */
3074 smb_setlen(outbuf,outsize - 4);
3075 send_smb(Client,outbuf);
3077 /* now the secondary */
3078 outsize = set_message(outbuf,1,0,True);
3079 CVAL(outbuf,smb_com) = SMBwritec;
3080 SSVAL(outbuf,smb_vwv0,nwritten);
3087 /****************************************************************************
3088 reply to a SMBwritebs (write block multiplex secondary) request
3089 ****************************************************************************/
3090 int reply_writebs(char *inbuf,char *outbuf)
3092 int cnum,numtowrite,fnum;
3096 int tcount, write_through, smb_doff;
3098 write_bmpx_struct *wbms;
3099 BOOL send_response = False;
3101 cnum = SVAL(inbuf,smb_tid);
3102 fnum = GETFNUM(inbuf,smb_vwv0);
3103 CHECK_FNUM(fnum,cnum);
3106 tcount = SVAL(inbuf,smb_vwv1);
3107 startpos = IVAL(inbuf,smb_vwv2);
3108 numtowrite = SVAL(inbuf,smb_vwv6);
3109 smb_doff = SVAL(inbuf,smb_vwv7);
3111 data = smb_base(inbuf) + smb_doff;
3113 /* We need to send an SMBwriteC response, not an SMBwritebs */
3114 CVAL(outbuf,smb_com) = SMBwritec;
3116 /* This fd should have an auxiliary struct attached,
3117 check that it does */
3118 wbms = Files[fnum].wbmpx_ptr;
3119 if(!wbms) return(-1);
3121 /* If write through is set we can return errors, else we must
3123 write_through = wbms->wr_mode;
3125 /* Check for an earlier error */
3126 if(wbms->wr_discard)
3127 return -1; /* Just discard the packet */
3129 seek_file(fnum,startpos);
3130 nwritten = write_file(fnum,data,numtowrite);
3132 if(lp_syncalways(SNUM(cnum)) || write_through)
3135 if (nwritten < numtowrite)
3138 /* We are returning an error - we can delete the aux struct */
3139 if (wbms) free((char *)wbms);
3140 Files[fnum].wbmpx_ptr = NULL;
3141 return(ERROR(ERRHRD,ERRdiskfull));
3143 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3146 /* Increment the total written, if this matches tcount
3147 we can discard the auxiliary struct (hurrah !) and return a writeC */
3148 wbms->wr_total_written += nwritten;
3149 if(wbms->wr_total_written >= tcount)
3151 if (write_through) {
3152 outsize = set_message(outbuf,1,0,True);
3153 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3154 send_response = True;
3158 Files[fnum].wbmpx_ptr = NULL;
3168 /****************************************************************************
3169 reply to a SMBsetattrE
3170 ****************************************************************************/
3171 int reply_setattrE(char *inbuf,char *outbuf)
3174 struct utimbuf unix_times;
3177 outsize = set_message(outbuf,0,0,True);
3179 cnum = SVAL(inbuf,smb_tid);
3180 fnum = GETFNUM(inbuf,smb_vwv0);
3182 CHECK_FNUM(fnum,cnum);
3185 /* Convert the DOS times into unix times. Ignore create
3186 time as UNIX can't set this.
3188 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3189 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3191 /* Set the date on this file */
3192 if(sys_utime(Files[fnum].name, &unix_times))
3193 return(ERROR(ERRDOS,ERRnoaccess));
3195 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3201 /****************************************************************************
3202 reply to a SMBgetattrE
3203 ****************************************************************************/
3204 int reply_getattrE(char *inbuf,char *outbuf)
3211 outsize = set_message(outbuf,11,0,True);
3213 cnum = SVAL(inbuf,smb_tid);
3214 fnum = GETFNUM(inbuf,smb_vwv0);
3216 CHECK_FNUM(fnum,cnum);
3219 /* Do an fstat on this file */
3220 if(fstat(Files[fnum].fd, &sbuf))
3221 return(UNIXERROR(ERRDOS,ERRnoaccess));
3223 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3225 /* Convert the times into dos times. Set create
3226 date to be last modify date as UNIX doesn't save
3228 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3229 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3230 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3233 SIVAL(outbuf,smb_vwv6,0);
3234 SIVAL(outbuf,smb_vwv8,0);
3238 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3239 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3241 SSVAL(outbuf,smb_vwv10, mode);
3243 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));