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;
338 sess_uid = SVAL(inbuf,smb_uid);
339 smb_bufsize = SVAL(inbuf,smb_vwv2);
340 smb_mpxmax = SVAL(inbuf,smb_vwv3);
341 smb_vc_num = SVAL(inbuf,smb_vwv4);
342 smb_sesskey = IVAL(inbuf,smb_vwv5);
344 if (Protocol < PROTOCOL_NT1) {
345 smb_apasslen = SVAL(inbuf,smb_vwv7);
346 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
347 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
349 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
350 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
351 BOOL doencrypt = SMBENCRYPT();
352 char *p = smb_buf(inbuf);
354 if (passlen1 != 24 && passlen2 != 24)
358 /* Save the lanman2 password and the NT md4 password. */
359 smb_apasslen = passlen1;
360 memcpy(smb_apasswd,p,smb_apasslen);
361 smb_ntpasslen = passlen2;
362 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
364 /* both Win95 and WinNT stuff up the password lengths for
365 non-encrypting systems. Uggh.
367 if passlen1==24 its a win95 system, and its setting the
368 password length incorrectly. Luckily it still works with the
369 default code because Win95 will null terminate the password
372 if passlen1>0 and passlen2>0 then its a NT box and its
373 setting passlen2 to some random value which really stuffs
374 things up. we need to fix that one. */
375 if (passlen1 > 0 && passlen2 > 0) {
378 /* we use the first password that they gave */
379 smb_apasslen = passlen1;
380 StrnCpy(smb_apasswd,p,smb_apasslen);
382 /* trim the password */
383 smb_apasslen = strlen(smb_apasswd);
385 /* wfwg sometimes uses a space instead of a null */
386 if (strequal(smb_apasswd," ")) {
392 p += passlen1 + passlen2;
393 strcpy(user,p); p = skip_string(p,1);
394 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
395 p,skip_string(p,1),skip_string(p,2)));
399 DEBUG(3,("sesssetupX:name=[%s]\n",user));
401 /* If name ends in $ then I think it's asking about whether a */
402 /* computer with that name (minus the $) has access. For now */
403 /* say yes to everything ending in $. */
404 if (user[strlen(user) - 1] == '$') {
406 user[strlen(user) - 1] = '\0';
411 strcpy(user,lp_guestaccount(-1));
415 strcpy(sesssetup_user,user);
417 reload_services(True);
419 add_session_user(user);
422 if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
423 !check_hosts_equiv(user))
426 if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
429 /* now check if it's a valid username/password */
430 /* If an NT password was supplied try and validate with that
431 first. This is superior as the passwords are mixed case 128 length unicode */
432 if(smb_ntpasslen && !guest)
434 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
435 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
437 valid_nt_password = True;
439 if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
441 if (!computer_id && lp_security() >= SEC_USER) {
442 #if (GUEST_SESSSETUP == 0)
443 return(ERROR(ERRSRV,ERRbadpw));
445 #if (GUEST_SESSSETUP == 1)
446 if (Get_Pwnam(user,True))
447 return(ERROR(ERRSRV,ERRbadpw));
450 if (*smb_apasswd || !Get_Pwnam(user,True))
451 strcpy(user,lp_guestaccount(-1));
452 DEBUG(3,("Registered username %s for guest access\n",user));
457 if (!Get_Pwnam(user,True)) {
458 DEBUG(3,("No such user %s - using guest account\n",user));
459 strcpy(user,lp_guestaccount(-1));
463 if (!strequal(user,lp_guestaccount(-1)) &&
464 lp_servicenumber(user) < 0)
466 int homes = lp_servicenumber(HOMES_NAME);
467 char *home = get_home_dir(user);
468 if (homes >= 0 && home)
469 lp_add_home(user,homes,home);
473 /* it's ok - setup a reply */
474 if (Protocol < PROTOCOL_NT1) {
475 set_message(outbuf,3,0,True);
478 set_message(outbuf,3,3,True);
480 strcpy(p,"Unix"); p = skip_string(p,1);
481 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
482 strcpy(p,lp_workgroup()); p = skip_string(p,1);
483 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
484 /* perhaps grab OS version here?? */
487 /* Set the correct uid in the outgoing and incoming packets
488 We will use this on future requests to determine which
489 user we should become.
492 struct passwd *pw = Get_Pwnam(user,False);
494 DEBUG(1,("Username %s is invalid on this system\n",user));
495 return(ERROR(ERRSRV,ERRbadpw));
498 SSVAL(outbuf,smb_uid,(uint16)pw->pw_uid);
499 SSVAL(inbuf,smb_uid,(uint16)pw->pw_uid);
502 if (guest && !computer_id)
503 SSVAL(outbuf,smb_vwv2,1);
505 /* register the name and uid as being validated, so further connections
506 to a uid can get through without a password, on the same VC */
507 register_uid(SVAL(inbuf,smb_uid),gid,user,guest);
510 maxxmit = MIN(maxxmit,smb_bufsize);
512 done_sesssetup = True;
514 return chain_reply(inbuf,outbuf,length,bufsize);
518 /****************************************************************************
520 ****************************************************************************/
521 int reply_chkpth(char *inbuf,char *outbuf)
528 cnum = SVAL(inbuf,smb_tid);
530 strcpy(name,smb_buf(inbuf) + 1);
531 unix_convert(name,cnum);
533 mode = SVAL(inbuf,smb_vwv0);
535 if (check_name(name,cnum))
536 ok = directory_exist(name,NULL);
539 return(ERROR(ERRDOS,ERRbadpath));
541 outsize = set_message(outbuf,0,0,True);
543 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
549 /****************************************************************************
551 ****************************************************************************/
552 int reply_getatr(char *inbuf,char *outbuf)
563 cnum = SVAL(inbuf,smb_tid);
565 strcpy(fname,smb_buf(inbuf) + 1);
566 unix_convert(fname,cnum);
568 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
569 under WfWg - weird! */
572 mode = aHIDDEN | aDIR;
573 if (!CAN_WRITE(cnum)) mode |= aRONLY;
579 if (check_name(fname,cnum))
581 if (sys_stat(fname,&sbuf) == 0)
583 mode = dos_mode(cnum,fname,&sbuf);
585 mtime = sbuf.st_mtime;
591 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
595 return(UNIXERROR(ERRDOS,ERRbadfile));
597 outsize = set_message(outbuf,10,0,True);
599 SSVAL(outbuf,smb_vwv0,mode);
600 put_dos_date3(outbuf,smb_vwv1,mtime);
601 SIVAL(outbuf,smb_vwv3,size);
603 if (Protocol >= PROTOCOL_NT1) {
604 char *p = strrchr(fname,'/');
605 uint16 flg2 = SVAL(outbuf,smb_flg2);
608 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
611 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
617 /****************************************************************************
619 ****************************************************************************/
620 int reply_setatr(char *inbuf,char *outbuf)
629 cnum = SVAL(inbuf,smb_tid);
631 strcpy(fname,smb_buf(inbuf) + 1);
632 unix_convert(fname,cnum);
634 mode = SVAL(inbuf,smb_vwv0);
635 mtime = make_unix_date3(inbuf+smb_vwv1);
637 if (directory_exist(fname,NULL))
639 if (check_name(fname,cnum))
640 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
642 ok = set_filetime(fname,mtime);
645 return(UNIXERROR(ERRDOS,ERRnoaccess));
647 outsize = set_message(outbuf,0,0,True);
649 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
655 /****************************************************************************
657 ****************************************************************************/
658 int reply_dskattr(char *inbuf,char *outbuf)
662 int dfree,dsize,bsize;
664 cnum = SVAL(inbuf,smb_tid);
666 sys_disk_free(".",&bsize,&dfree,&dsize);
668 outsize = set_message(outbuf,5,0,True);
670 SSVAL(outbuf,smb_vwv0,dsize);
671 SSVAL(outbuf,smb_vwv1,bsize/512);
672 SSVAL(outbuf,smb_vwv2,512);
673 SSVAL(outbuf,smb_vwv3,dfree);
675 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
681 /****************************************************************************
683 Can be called from SMBsearch, SMBffirst or SMBfunique.
684 ****************************************************************************/
685 int reply_search(char *inbuf,char *outbuf)
696 BOOL finished = False;
705 BOOL check_descend = False;
706 BOOL expect_close = False;
707 BOOL can_open = True;
709 *mask = *directory = *fname = 0;
711 /* If we were called as SMBffirst then we must expect close. */
712 if(CVAL(inbuf,smb_com) == SMBffirst)
715 cnum = SVAL(inbuf,smb_tid);
717 outsize = set_message(outbuf,1,3,True);
718 maxentries = SVAL(inbuf,smb_vwv0);
719 dirtype = SVAL(inbuf,smb_vwv1);
720 path = smb_buf(inbuf) + 1;
721 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
724 /* dirtype &= ~aDIR; */
726 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
733 strcpy(directory,smb_buf(inbuf)+1);
734 strcpy(dir2,smb_buf(inbuf)+1);
735 unix_convert(directory,cnum);
738 if (!check_name(directory,cnum))
741 p = strrchr(dir2,'/');
743 {strcpy(mask,dir2);*dir2 = 0;}
745 {*p = 0;strcpy(mask,p+1);}
747 p = strrchr(directory,'/');
753 if (strlen(directory) == 0)
754 strcpy(directory,"./");
756 CVAL(status,0) = dirtype;
760 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
761 memcpy(mask,status+1,11);
763 dirtype = CVAL(status,0) & 0x1F;
764 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
765 if (!Connections[cnum].dirptr)
767 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
772 /* turn strings of spaces into a . */
774 trim_string(mask,NULL," ");
775 if ((p = strrchr(mask,' ')))
780 trim_string(mask,NULL," ");
787 for (p=mask; *p; p++)
789 if (*p != '?' && *p != '*' && !isdoschar(*p))
791 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
797 if (!strchr(mask,'.') && strlen(mask)>8)
800 strcpy(tmp,&mask[8]);
806 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
810 p = smb_buf(outbuf) + 3;
816 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
818 return(ERROR(ERRDOS,ERRnofids));
821 DEBUG(4,("dptr_num is %d\n",dptr_num));
825 if ((dirtype&0x1F) == aVOLID)
828 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
829 dptr_fill(p+12,dptr_num);
830 if (dptr_zero(p+12) && (status_len==0))
834 p += DIR_STRUCT_SIZE;
838 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
839 if (in_list(Connections[cnum].dirpath,
840 lp_dontdescend(SNUM(cnum)),True))
841 check_descend = True;
843 for (i=numentries;(i<maxentries) && !finished;i++)
846 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
850 make_dir_struct(p,mask,fname,size,mode,date);
851 dptr_fill(p+12,dptr_num);
854 p += DIR_STRUCT_SIZE;
863 if (numentries == 0 || !ok)
865 CVAL(outbuf,smb_rcls) = ERRDOS;
866 SSVAL(outbuf,smb_err,ERRnofiles);
869 /* If we were called as SMBffirst with smb_search_id == NULL
870 and no entries were found then return error and close dirptr
873 if(ok && expect_close && numentries == 0 && status_len == 0)
875 CVAL(outbuf,smb_rcls) = ERRDOS;
876 SSVAL(outbuf,smb_err,ERRnofiles);
877 /* Also close the dptr - we know it's gone */
878 dptr_close(dptr_num);
881 /* If we were called as SMBfunique, then we can close the dirptr now ! */
882 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
883 dptr_close(dptr_num);
885 SSVAL(outbuf,smb_vwv0,numentries);
886 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
887 CVAL(smb_buf(outbuf),0) = 5;
888 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
890 if (Protocol >= PROTOCOL_NT1) {
891 uint16 flg2 = SVAL(outbuf,smb_flg2);
892 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
895 outsize += DIR_STRUCT_SIZE*numentries;
896 smb_setlen(outbuf,outsize - 4);
898 if ((! *directory) && dptr_path(dptr_num))
899 sprintf(directory,"(%s)",dptr_path(dptr_num));
901 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
903 smb_fn_name(CVAL(inbuf,smb_com)),
904 mask,directory,cnum,dirtype,numentries,maxentries));
910 /****************************************************************************
911 reply to a fclose (stop directory search)
912 ****************************************************************************/
913 int reply_fclose(char *inbuf,char *outbuf)
922 cnum = SVAL(inbuf,smb_tid);
924 outsize = set_message(outbuf,1,0,True);
925 path = smb_buf(inbuf) + 1;
926 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
930 return(ERROR(ERRSRV,ERRsrverror));
932 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
934 if(dptr_fetch(status+12,&dptr_num)) {
935 /* Close the dptr - we know it's gone */
936 dptr_close(dptr_num);
939 SSVAL(outbuf,smb_vwv0,0);
941 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
947 /****************************************************************************
949 ****************************************************************************/
950 int reply_open(char *inbuf,char *outbuf)
964 cnum = SVAL(inbuf,smb_tid);
966 share_mode = SVAL(inbuf,smb_vwv0);
968 strcpy(fname,smb_buf(inbuf)+1);
969 unix_convert(fname,cnum);
971 fnum = find_free_file();
973 return(ERROR(ERRSRV,ERRnofids));
975 if (!check_name(fname,cnum))
976 return(UNIXERROR(ERRDOS,ERRnoaccess));
978 unixmode = unix_mode(cnum,aARCH);
980 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
982 if (!Files[fnum].open)
983 return(UNIXERROR(ERRDOS,ERRnoaccess));
985 if (fstat(Files[fnum].fd,&sbuf) != 0) {
987 return(ERROR(ERRDOS,ERRnoaccess));
991 fmode = dos_mode(cnum,fname,&sbuf);
992 mtime = sbuf.st_mtime;
995 DEBUG(3,("attempt to open a directory %s\n",fname));
997 return(ERROR(ERRDOS,ERRnoaccess));
1000 outsize = set_message(outbuf,7,0,True);
1001 SSVAL(outbuf,smb_vwv0,fnum);
1002 SSVAL(outbuf,smb_vwv1,fmode);
1003 put_dos_date3(outbuf,smb_vwv2,mtime);
1004 SIVAL(outbuf,smb_vwv4,size);
1005 SSVAL(outbuf,smb_vwv6,rmode);
1007 if (lp_fake_oplocks(SNUM(cnum))) {
1008 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1015 /****************************************************************************
1016 reply to an open and X
1017 ****************************************************************************/
1018 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1021 int cnum = SVAL(inbuf,smb_tid);
1024 int smb_mode = SVAL(inbuf,smb_vwv3);
1025 int smb_attr = SVAL(inbuf,smb_vwv5);
1026 BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
1028 int open_flags = SVAL(inbuf,smb_vwv2);
1029 int smb_sattr = SVAL(inbuf,smb_vwv4);
1030 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1032 int smb_ofun = SVAL(inbuf,smb_vwv8);
1034 int size=0,fmode=0,mtime=0,rmode=0;
1038 /* If it's an IPC, pass off the pipe handler. */
1040 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1042 /* XXXX we need to handle passed times, sattr and flags */
1044 strcpy(fname,smb_buf(inbuf));
1045 unix_convert(fname,cnum);
1047 /* now add create and trunc bits */
1048 if (smb_ofun & 0x10)
1049 openmode |= O_CREAT;
1050 if ((smb_ofun & 0x3) == 2)
1051 openmode |= O_TRUNC;
1053 fnum = find_free_file();
1055 return(ERROR(ERRSRV,ERRnofids));
1057 if (!check_name(fname,cnum))
1058 return(UNIXERROR(ERRDOS,ERRnoaccess));
1060 unixmode = unix_mode(cnum,smb_attr | aARCH);
1062 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1063 &rmode,&smb_action);
1065 if (!Files[fnum].open)
1066 return(UNIXERROR(ERRDOS,ERRnoaccess));
1068 if (fstat(Files[fnum].fd,&sbuf) != 0) {
1070 return(ERROR(ERRDOS,ERRnoaccess));
1073 size = sbuf.st_size;
1074 fmode = dos_mode(cnum,fname,&sbuf);
1075 mtime = sbuf.st_mtime;
1078 return(ERROR(ERRDOS,ERRnoaccess));
1081 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1082 smb_action |= (1<<15);
1085 set_message(outbuf,15,0,True);
1086 SSVAL(outbuf,smb_vwv2,fnum);
1087 SSVAL(outbuf,smb_vwv3,fmode);
1088 put_dos_date3(outbuf,smb_vwv4,mtime);
1089 SIVAL(outbuf,smb_vwv6,size);
1090 SSVAL(outbuf,smb_vwv8,rmode);
1091 SSVAL(outbuf,smb_vwv11,smb_action);
1095 return chain_reply(inbuf,outbuf,length,bufsize);
1099 /****************************************************************************
1100 reply to a SMBulogoffX
1101 ****************************************************************************/
1102 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1104 int uid = SVAL(inbuf,smb_uid);
1106 invalidate_uid(uid);
1108 /* in user level security we are supposed to close any files
1109 open by this user */
1110 if (lp_security() != SEC_SHARE) {
1112 for (i=0;i<MAX_OPEN_FILES;i++)
1113 if (Files[i].uid == uid && Files[i].open) {
1118 set_message(outbuf,2,0,True);
1120 DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid));
1122 return chain_reply(inbuf,outbuf,length,bufsize);
1126 /****************************************************************************
1128 ****************************************************************************/
1129 int reply_mknew(char *inbuf,char *outbuf)
1138 com = SVAL(inbuf,smb_com);
1139 cnum = SVAL(inbuf,smb_tid);
1141 createmode = SVAL(inbuf,smb_vwv0);
1142 strcpy(fname,smb_buf(inbuf)+1);
1143 unix_convert(fname,cnum);
1145 if (createmode & aVOLID)
1147 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1150 unixmode = unix_mode(cnum,createmode);
1152 if (com == SMBmknew && file_exist(fname,NULL))
1153 return(ERROR(ERRDOS,ERRfilexists));
1155 fnum = find_free_file();
1157 return(ERROR(ERRSRV,ERRnofids));
1159 if (!check_name(fname,cnum))
1160 return(UNIXERROR(ERRDOS,ERRnoaccess));
1162 open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1164 if (!Files[fnum].open)
1165 return(UNIXERROR(ERRDOS,ERRnoaccess));
1167 outsize = set_message(outbuf,1,0,True);
1168 SSVAL(outbuf,smb_vwv0,fnum);
1170 if (lp_fake_oplocks(SNUM(cnum))) {
1171 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1174 DEBUG(2,("new file %s\n",fname));
1175 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));
1181 /****************************************************************************
1182 reply to a create temporary file
1183 ****************************************************************************/
1184 int reply_ctemp(char *inbuf,char *outbuf)
1194 cnum = SVAL(inbuf,smb_tid);
1195 createmode = SVAL(inbuf,smb_vwv0);
1196 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1197 unix_convert(fname,cnum);
1199 unixmode = unix_mode(cnum,createmode);
1201 fnum = find_free_file();
1203 return(ERROR(ERRSRV,ERRnofids));
1205 if (!check_name(fname,cnum))
1206 return(UNIXERROR(ERRDOS,ERRnoaccess));
1208 strcpy(fname2,(char *)mktemp(fname));
1210 open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1212 if (!Files[fnum].open)
1213 return(UNIXERROR(ERRDOS,ERRnoaccess));
1215 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1216 SSVAL(outbuf,smb_vwv0,fnum);
1217 CVAL(smb_buf(outbuf),0) = 4;
1218 strcpy(smb_buf(outbuf) + 1,fname2);
1220 if (lp_fake_oplocks(SNUM(cnum))) {
1221 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1224 DEBUG(2,("created temp file %s\n",fname2));
1225 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));
1231 /*******************************************************************
1232 check if a user is allowed to delete a file
1233 ********************************************************************/
1234 static BOOL can_delete(char *fname,int cnum,int dirtype)
1239 if (!CAN_WRITE(cnum)) return(False);
1241 if (sys_lstat(fname,&sbuf) != 0) return(False);
1242 fmode = dos_mode(cnum,fname,&sbuf);
1243 if (fmode & aDIR) return(False);
1244 if (!lp_delete_readonly(SNUM(cnum))) {
1245 if (fmode & aRONLY) return(False);
1247 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1249 if (!check_file_sharing(cnum,fname)) return(False);
1253 /****************************************************************************
1255 ****************************************************************************/
1256 int reply_unlink(char *inbuf,char *outbuf)
1266 int error = ERRnoaccess;
1270 *directory = *mask = 0;
1272 cnum = SVAL(inbuf,smb_tid);
1273 dirtype = SVAL(inbuf,smb_vwv0);
1275 strcpy(name,smb_buf(inbuf) + 1);
1277 DEBUG(3,("reply_unlink : %s\n",name));
1279 unix_convert(name,cnum);
1281 p = strrchr(name,'/');
1283 strcpy(directory,"./");
1287 strcpy(directory,name);
1291 if (is_mangled(mask))
1292 check_mangled_stack(mask);
1294 has_wild = strchr(mask,'*') || strchr(mask,'?');
1297 strcat(directory,"/");
1298 strcat(directory,mask);
1299 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1300 if (!count) exists = file_exist(directory,NULL);
1302 void *dirptr = NULL;
1305 if (check_name(directory,cnum))
1306 dirptr = OpenDir(directory);
1308 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1309 the pattern matches against the long name, otherwise the short name
1310 We don't implement this yet XXXX
1317 if (strequal(mask,"????????.???"))
1320 while ((dname = ReadDirName(dirptr)))
1323 strcpy(fname,dname);
1325 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1327 error = ERRnoaccess;
1328 sprintf(fname,"%s/%s",directory,dname);
1329 if (!can_delete(fname,cnum,dirtype)) continue;
1330 if (!sys_unlink(fname)) count++;
1331 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1339 return(ERROR(ERRDOS,error));
1341 return(UNIXERROR(ERRDOS,error));
1344 outsize = set_message(outbuf,0,0,True);
1350 /****************************************************************************
1351 reply to a readbraw (core+ protocol)
1352 ****************************************************************************/
1353 int reply_readbraw(char *inbuf, char *outbuf)
1355 int cnum,maxcount,mincount,fnum;
1358 char *header = outbuf;
1363 cnum = SVAL(inbuf,smb_tid);
1364 fnum = GETFNUM(inbuf,smb_vwv0);
1366 startpos = IVAL(inbuf,smb_vwv1);
1367 maxcount = SVAL(inbuf,smb_vwv3);
1368 mincount = SVAL(inbuf,smb_vwv4);
1370 /* ensure we don't overrun the packet size */
1371 maxcount = MIN(65535,maxcount);
1372 maxcount = MAX(mincount,maxcount);
1374 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1376 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1377 _smb_setlen(header,0);
1378 transfer_file(0,Client,0,header,4,0);
1383 fd = Files[fnum].fd;
1384 fname = Files[fnum].name;
1388 if (!is_locked(fnum,cnum,maxcount,startpos))
1390 int size = Files[fnum].size;
1391 int sizeneeded = startpos + maxcount;
1393 if (size < sizeneeded) {
1395 if (fstat(Files[fnum].fd,&st) == 0)
1397 if (!Files[fnum].can_write)
1398 Files[fnum].size = size;
1401 nread = MIN(maxcount,size - startpos);
1404 if (nread < mincount)
1407 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1410 maxcount,mincount,nread));
1415 _smb_setlen(header,nread);
1417 if (!Files[fnum].can_write)
1418 predict = read_predict(fd,startpos,header+4,NULL,nread);
1420 if ((nread-predict) > 0)
1421 seek_file(fnum,startpos + predict);
1423 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1428 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1429 fname,startpos,nread,ret));
1432 ret = read_file(fnum,header+4,startpos,nread);
1433 if (ret < mincount) ret = 0;
1435 _smb_setlen(header,ret);
1436 transfer_file(0,Client,0,header,4+ret,0);
1439 DEBUG(5,("readbraw finished\n"));
1444 /****************************************************************************
1445 reply to a lockread (core+ protocol)
1446 ****************************************************************************/
1447 int reply_lockread(char *inbuf,char *outbuf)
1453 uint32 startpos, numtoread;
1457 cnum = SVAL(inbuf,smb_tid);
1458 fnum = GETFNUM(inbuf,smb_vwv0);
1460 CHECK_FNUM(fnum,cnum);
1464 numtoread = SVAL(inbuf,smb_vwv1);
1465 startpos = IVAL(inbuf,smb_vwv2);
1467 outsize = set_message(outbuf,5,3,True);
1468 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1469 data = smb_buf(outbuf) + 3;
1471 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1472 return (ERROR(eclass,ecode));
1474 nread = read_file(fnum,data,startpos,numtoread);
1477 return(UNIXERROR(ERRDOS,ERRnoaccess));
1480 SSVAL(outbuf,smb_vwv0,nread);
1481 SSVAL(outbuf,smb_vwv5,nread+3);
1482 SSVAL(smb_buf(outbuf),1,nread);
1484 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1490 /****************************************************************************
1492 ****************************************************************************/
1493 int reply_read(char *inbuf,char *outbuf)
1495 int cnum,numtoread,fnum;
1501 cnum = SVAL(inbuf,smb_tid);
1502 fnum = GETFNUM(inbuf,smb_vwv0);
1504 CHECK_FNUM(fnum,cnum);
1508 numtoread = SVAL(inbuf,smb_vwv1);
1509 startpos = IVAL(inbuf,smb_vwv2);
1511 outsize = set_message(outbuf,5,3,True);
1512 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1513 data = smb_buf(outbuf) + 3;
1515 if (is_locked(fnum,cnum,numtoread,startpos))
1516 return(ERROR(ERRDOS,ERRlock));
1519 nread = read_file(fnum,data,startpos,numtoread);
1522 return(UNIXERROR(ERRDOS,ERRnoaccess));
1525 SSVAL(outbuf,smb_vwv0,nread);
1526 SSVAL(outbuf,smb_vwv5,nread+3);
1527 CVAL(smb_buf(outbuf),0) = 1;
1528 SSVAL(smb_buf(outbuf),1,nread);
1530 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1536 /****************************************************************************
1537 reply to a read and X
1538 ****************************************************************************/
1539 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1541 int fnum = GETFNUM(inbuf,smb_vwv2);
1542 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1543 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1544 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1550 cnum = SVAL(inbuf,smb_tid);
1552 CHECK_FNUM(fnum,cnum);
1556 set_message(outbuf,12,0,True);
1557 data = smb_buf(outbuf);
1559 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1560 return(ERROR(ERRDOS,ERRlock));
1561 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1565 return(UNIXERROR(ERRDOS,ERRnoaccess));
1567 SSVAL(outbuf,smb_vwv5,nread);
1568 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1569 SSVAL(smb_buf(outbuf),-2,nread);
1571 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1572 timestring(),fnum,cnum,
1573 smb_mincnt,smb_maxcnt,nread));
1577 return chain_reply(inbuf,outbuf,length,bufsize);
1581 /****************************************************************************
1582 reply to a writebraw (core+ or LANMAN1.0 protocol)
1583 ****************************************************************************/
1584 int reply_writebraw(char *inbuf,char *outbuf)
1587 int total_written=0;
1596 cnum = SVAL(inbuf,smb_tid);
1597 fnum = GETFNUM(inbuf,smb_vwv0);
1599 CHECK_FNUM(fnum,cnum);
1603 tcount = IVAL(inbuf,smb_vwv1);
1604 startpos = IVAL(inbuf,smb_vwv3);
1605 write_through = BITSETW(inbuf+smb_vwv7,0);
1607 /* We have to deal with slightly different formats depending
1608 on whether we are using the core+ or lanman1.0 protocol */
1609 if(Protocol <= PROTOCOL_COREPLUS) {
1610 numtowrite = SVAL(smb_buf(inbuf),-2);
1611 data = smb_buf(inbuf);
1613 numtowrite = SVAL(inbuf,smb_vwv10);
1614 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1617 /* force the error type */
1618 CVAL(inbuf,smb_com) = SMBwritec;
1619 CVAL(outbuf,smb_com) = SMBwritec;
1621 if (is_locked(fnum,cnum,tcount,startpos))
1622 return(ERROR(ERRDOS,ERRlock));
1624 if (seek_file(fnum,startpos) != startpos)
1625 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1628 nwritten = write_file(fnum,data,numtowrite);
1630 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1631 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1633 if (nwritten < numtowrite)
1634 return(UNIXERROR(ERRHRD,ERRdiskfull));
1636 total_written = nwritten;
1638 /* Return a message to the redirector to tell it
1639 to send more bytes */
1640 CVAL(outbuf,smb_com) = SMBwritebraw;
1641 SSVALS(outbuf,smb_vwv0,-1);
1642 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1643 send_smb(Client,outbuf);
1645 /* Now read the raw data into the buffer and write it */
1646 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1647 exit_server("secondary writebraw failed");
1650 /* Even though this is not an smb message, smb_len
1651 returns the generic length of an smb message */
1652 numtowrite = smb_len(inbuf);
1654 if (tcount > nwritten+numtowrite) {
1655 DEBUG(3,("Client overestimated the write %d %d %d\n",
1656 tcount,nwritten,numtowrite));
1659 nwritten = transfer_file(Client,Files[fnum].fd,numtowrite,NULL,0,
1661 total_written += nwritten;
1663 /* Set up outbuf to return the correct return */
1664 outsize = set_message(outbuf,1,0,True);
1665 CVAL(outbuf,smb_com) = SMBwritec;
1666 SSVAL(outbuf,smb_vwv0,total_written);
1668 if (nwritten < numtowrite) {
1669 CVAL(outbuf,smb_rcls) = ERRHRD;
1670 SSVAL(outbuf,smb_err,ERRdiskfull);
1673 if (lp_syncalways(SNUM(cnum)) || write_through)
1676 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1677 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1679 /* we won't return a status if write through is not selected - this
1680 follows what WfWg does */
1681 if (!write_through && total_written==tcount)
1688 /****************************************************************************
1689 reply to a writeunlock (core+)
1690 ****************************************************************************/
1691 int reply_writeunlock(char *inbuf,char *outbuf)
1697 uint32 numtowrite,startpos;
1701 cnum = SVAL(inbuf,smb_tid);
1702 fnum = GETFNUM(inbuf,smb_vwv0);
1704 CHECK_FNUM(fnum,cnum);
1708 numtowrite = SVAL(inbuf,smb_vwv1);
1709 startpos = IVAL(inbuf,smb_vwv2);
1710 data = smb_buf(inbuf) + 3;
1712 if (is_locked(fnum,cnum,numtowrite,startpos))
1713 return(ERROR(ERRDOS,ERRlock));
1715 seek_file(fnum,startpos);
1717 /* The special X/Open SMB protocol handling of
1718 zero length writes is *NOT* done for
1723 nwritten = write_file(fnum,data,numtowrite);
1725 if (lp_syncalways(SNUM(cnum)))
1728 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1729 return(UNIXERROR(ERRDOS,ERRnoaccess));
1731 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1732 return(ERROR(eclass,ecode));
1734 outsize = set_message(outbuf,1,0,True);
1736 SSVAL(outbuf,smb_vwv0,nwritten);
1738 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1739 timestring(),fnum,cnum,numtowrite,nwritten));
1745 /****************************************************************************
1747 ****************************************************************************/
1748 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1750 int cnum,numtowrite,fnum;
1759 cnum = SVAL(inbuf,smb_tid);
1760 fnum = GETFNUM(inbuf,smb_vwv0);
1762 CHECK_FNUM(fnum,cnum);
1766 numtowrite = SVAL(inbuf,smb_vwv1);
1767 startpos = IVAL(inbuf,smb_vwv2);
1768 data = smb_buf(inbuf) + 3;
1770 if (is_locked(fnum,cnum,numtowrite,startpos))
1771 return(ERROR(ERRDOS,ERRlock));
1773 seek_file(fnum,startpos);
1775 /* X/Open SMB protocol says that if smb_vwv1 is
1776 zero then the file size should be extended or
1777 truncated to the size given in smb_vwv[2-3] */
1779 nwritten = set_filelen(Files[fnum].fd, startpos);
1781 nwritten = write_file(fnum,data,numtowrite);
1783 if (lp_syncalways(SNUM(cnum)))
1786 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1787 return(UNIXERROR(ERRDOS,ERRnoaccess));
1789 outsize = set_message(outbuf,1,0,True);
1791 SSVAL(outbuf,smb_vwv0,nwritten);
1793 if (nwritten < numtowrite) {
1794 CVAL(outbuf,smb_rcls) = ERRHRD;
1795 SSVAL(outbuf,smb_err,ERRdiskfull);
1798 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1804 /****************************************************************************
1805 reply to a write and X
1806 ****************************************************************************/
1807 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1809 int fnum = GETFNUM(inbuf,smb_vwv2);
1810 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1811 int smb_dsize = SVAL(inbuf,smb_vwv10);
1812 int smb_doff = SVAL(inbuf,smb_vwv11);
1813 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1818 cnum = SVAL(inbuf,smb_tid);
1820 CHECK_FNUM(fnum,cnum);
1824 data = smb_base(inbuf) + smb_doff;
1826 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1827 return(ERROR(ERRDOS,ERRlock));
1829 seek_file(fnum,smb_offs);
1831 /* X/Open SMB protocol says that, unlike SMBwrite
1832 if the length is zero then NO truncation is
1833 done, just a write of zero. To truncate a file,
1838 nwritten = write_file(fnum,data,smb_dsize);
1840 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1841 return(UNIXERROR(ERRDOS,ERRnoaccess));
1843 set_message(outbuf,6,0,True);
1845 SSVAL(outbuf,smb_vwv2,nwritten);
1847 if (nwritten < smb_dsize) {
1848 CVAL(outbuf,smb_rcls) = ERRHRD;
1849 SSVAL(outbuf,smb_err,ERRdiskfull);
1852 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1856 if (lp_syncalways(SNUM(cnum)) || write_through)
1859 return chain_reply(inbuf,outbuf,length,bufsize);
1863 /****************************************************************************
1865 ****************************************************************************/
1866 int reply_lseek(char *inbuf,char *outbuf)
1874 cnum = SVAL(inbuf,smb_tid);
1875 fnum = GETFNUM(inbuf,smb_vwv0);
1877 CHECK_FNUM(fnum,cnum);
1880 mode = SVAL(inbuf,smb_vwv1) & 3;
1881 startpos = IVAL(inbuf,smb_vwv2);
1885 case 0: umode = SEEK_SET; break;
1886 case 1: umode = SEEK_CUR; break;
1887 case 2: umode = SEEK_END; break;
1889 umode = SEEK_SET; break;
1892 res = lseek(Files[fnum].fd,startpos,umode);
1893 Files[fnum].pos = res;
1895 outsize = set_message(outbuf,2,0,True);
1896 SIVALS(outbuf,smb_vwv0,res);
1898 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1904 /****************************************************************************
1906 ****************************************************************************/
1907 int reply_flush(char *inbuf,char *outbuf)
1910 int outsize = set_message(outbuf,0,0,True);
1912 cnum = SVAL(inbuf,smb_tid);
1913 fnum = GETFNUM(inbuf,smb_vwv0);
1915 if (fnum != 0xFFFF) {
1916 CHECK_FNUM(fnum,cnum);
1923 for (i=0;i<MAX_OPEN_FILES;i++)
1930 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1935 /****************************************************************************
1937 ****************************************************************************/
1938 int reply_exit(char *inbuf,char *outbuf)
1940 int outsize = set_message(outbuf,0,0,True);
1941 DEBUG(3,("%s exit\n",timestring()));
1947 /****************************************************************************
1949 ****************************************************************************/
1950 int reply_close(char *inbuf,char *outbuf)
1955 int32 eclass = 0, err = 0;
1957 outsize = set_message(outbuf,0,0,True);
1959 cnum = SVAL(inbuf,smb_tid);
1961 fnum = GETFNUM(inbuf,smb_vwv0);
1962 CHECK_FNUM(fnum,cnum);
1964 if(HAS_CACHED_ERROR(fnum)) {
1965 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1966 err = Files[fnum].wbmpx_ptr->wr_error;
1969 mtime = make_unix_date3(inbuf+smb_vwv1);
1971 /* try and set the date */
1972 set_filetime(Files[fnum].name,mtime);
1976 /* We have a cached error */
1978 return(ERROR(eclass,err));
1980 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
1981 timestring(),Files[fnum].fd,fnum,cnum,
1982 Connections[cnum].num_files_open));
1988 /****************************************************************************
1989 reply to a writeclose (Core+ protocol)
1990 ****************************************************************************/
1991 int reply_writeclose(char *inbuf,char *outbuf)
1993 int cnum,numtowrite,fnum;
2000 cnum = SVAL(inbuf,smb_tid);
2001 fnum = GETFNUM(inbuf,smb_vwv0);
2003 CHECK_FNUM(fnum,cnum);
2007 numtowrite = SVAL(inbuf,smb_vwv1);
2008 startpos = IVAL(inbuf,smb_vwv2);
2009 mtime = make_unix_date3(inbuf+smb_vwv4);
2010 data = smb_buf(inbuf) + 1;
2012 if (is_locked(fnum,cnum,numtowrite,startpos))
2013 return(ERROR(ERRDOS,ERRlock));
2015 seek_file(fnum,startpos);
2017 nwritten = write_file(fnum,data,numtowrite);
2019 set_filetime(Files[fnum].name,mtime);
2023 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2024 timestring(),fnum,cnum,numtowrite,nwritten,
2025 Connections[cnum].num_files_open));
2028 return(UNIXERROR(ERRDOS,ERRnoaccess));
2030 outsize = set_message(outbuf,1,0,True);
2032 SSVAL(outbuf,smb_vwv0,nwritten);
2037 /****************************************************************************
2039 ****************************************************************************/
2040 int reply_lock(char *inbuf,char *outbuf)
2043 int outsize = set_message(outbuf,0,0,True);
2044 uint32 count,offset;
2048 cnum = SVAL(inbuf,smb_tid);
2049 fnum = GETFNUM(inbuf,smb_vwv0);
2051 CHECK_FNUM(fnum,cnum);
2054 count = IVAL(inbuf,smb_vwv1);
2055 offset = IVAL(inbuf,smb_vwv3);
2057 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2059 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2060 return (ERROR(eclass,ecode));
2066 /****************************************************************************
2068 ****************************************************************************/
2069 int reply_unlock(char *inbuf,char *outbuf)
2072 int outsize = set_message(outbuf,0,0,True);
2073 uint32 count,offset;
2077 cnum = SVAL(inbuf,smb_tid);
2078 fnum = GETFNUM(inbuf,smb_vwv0);
2080 CHECK_FNUM(fnum,cnum);
2083 count = IVAL(inbuf,smb_vwv1);
2084 offset = IVAL(inbuf,smb_vwv3);
2086 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2087 return (ERROR(eclass,ecode));
2089 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2095 /****************************************************************************
2097 ****************************************************************************/
2098 int reply_tdis(char *inbuf,char *outbuf)
2101 int outsize = set_message(outbuf,0,0,True);
2103 cnum = SVAL(inbuf,smb_tid);
2104 uid = SVAL(inbuf,smb_uid);
2106 if (!OPEN_CNUM(cnum)) {
2107 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2108 return(ERROR(ERRSRV,ERRinvnid));
2111 Connections[cnum].used = False;
2113 close_cnum(cnum,uid);
2115 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2122 /****************************************************************************
2124 ****************************************************************************/
2125 int reply_echo(char *inbuf,char *outbuf)
2128 int smb_reverb = SVAL(inbuf,smb_vwv0);
2130 int data_len = smb_buflen(inbuf);
2131 int outsize = set_message(outbuf,1,data_len,True);
2133 cnum = SVAL(inbuf,smb_tid);
2135 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2137 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2138 return(ERROR(ERRSRV,ERRinvnid));
2141 /* copy any incoming data back out */
2143 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2145 if (smb_reverb > 100)
2147 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2151 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2153 SSVAL(outbuf,smb_vwv0,seq_num);
2155 smb_setlen(outbuf,outsize - 4);
2157 send_smb(Client,outbuf);
2160 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2166 /****************************************************************************
2167 reply to a printopen
2168 ****************************************************************************/
2169 int reply_printopen(char *inbuf,char *outbuf)
2177 *fname = *fname2 = 0;
2179 cnum = SVAL(inbuf,smb_tid);
2181 if (!CAN_PRINT(cnum))
2182 return(ERROR(ERRDOS,ERRnoaccess));
2187 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2191 if (!(isalnum(*p) || strchr("._-",*p)))
2196 if (strlen(s) > 10) s[10] = 0;
2198 sprintf(fname,"%s.XXXXXX",s);
2201 fnum = find_free_file();
2203 return(ERROR(ERRSRV,ERRnofids));
2205 strcpy(fname2,(char *)mktemp(fname));
2207 if (!check_name(fname2,cnum))
2208 return(ERROR(ERRDOS,ERRnoaccess));
2210 open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC,
2213 if (!Files[fnum].open)
2214 return(UNIXERROR(ERRDOS,ERRnoaccess));
2216 /* force it to be a print file */
2217 Files[fnum].print_file = True;
2219 outsize = set_message(outbuf,1,0,True);
2220 SSVAL(outbuf,smb_vwv0,fnum);
2222 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum));
2228 /****************************************************************************
2229 reply to a printclose
2230 ****************************************************************************/
2231 int reply_printclose(char *inbuf,char *outbuf)
2234 int outsize = set_message(outbuf,0,0,True);
2236 cnum = SVAL(inbuf,smb_tid);
2237 fnum = GETFNUM(inbuf,smb_vwv0);
2239 CHECK_FNUM(fnum,cnum);
2242 if (!CAN_PRINT(cnum))
2243 return(ERROR(ERRDOS,ERRnoaccess));
2247 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum));
2253 /****************************************************************************
2254 reply to a printqueue
2255 ****************************************************************************/
2256 int reply_printqueue(char *inbuf,char *outbuf)
2259 int outsize = set_message(outbuf,2,3,True);
2260 int max_count = SVAL(inbuf,smb_vwv0);
2261 int start_index = SVAL(inbuf,smb_vwv1);
2263 cnum = SVAL(inbuf,smb_tid);
2264 uid = SVAL(inbuf,smb_uid);
2266 /* allow checking the queue for anyone */
2268 if (!CAN_PRINT(cnum))
2269 return(ERROR(ERRDOS,ERRnoaccess));
2272 SSVAL(outbuf,smb_vwv0,0);
2273 SSVAL(outbuf,smb_vwv1,0);
2274 CVAL(smb_buf(outbuf),0) = 1;
2275 SSVAL(smb_buf(outbuf),1,0);
2277 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2278 timestring(),cnum,start_index,max_count));
2280 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2285 for (i=0;i<MAX_CONNECTIONS;i++)
2286 if (CAN_PRINT(i) && Connections[i].printer)
2290 for (i=0;i<MAX_CONNECTIONS;i++)
2294 if (!OPEN_CNUM(cnum))
2295 return(ERROR(ERRSRV,ERRinvnid));
2297 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2300 if (!become_user(cnum,uid))
2301 return(ERROR(ERRSRV,ERRinvnid));
2304 print_queue_struct *queue = NULL;
2305 char *p = smb_buf(outbuf) + 3;
2306 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2307 int num_to_get = ABS(max_count);
2308 int first = (max_count>0?start_index:start_index+max_count+1);
2314 num_to_get = MIN(num_to_get,count-first);
2317 for (i=first;i<first+num_to_get;i++)
2319 put_dos_date2(p,0,queue[i].time);
2320 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2321 SSVAL(p,5,queue[i].job);
2322 SIVAL(p,7,queue[i].size);
2324 StrnCpy(p+12,queue[i].user,16);
2330 outsize = set_message(outbuf,2,28*count+3,False);
2331 SSVAL(outbuf,smb_vwv0,count);
2332 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2333 CVAL(smb_buf(outbuf),0) = 1;
2334 SSVAL(smb_buf(outbuf),1,28*count);
2337 if (queue) free(queue);
2339 DEBUG(3,("%d entries returned in queue\n",count));
2346 /****************************************************************************
2347 reply to a printwrite
2348 ****************************************************************************/
2349 int reply_printwrite(char *inbuf,char *outbuf)
2351 int cnum,numtowrite,fnum;
2352 int outsize = set_message(outbuf,0,0,True);
2355 cnum = SVAL(inbuf,smb_tid);
2357 if (!CAN_PRINT(cnum))
2358 return(ERROR(ERRDOS,ERRnoaccess));
2360 fnum = GETFNUM(inbuf,smb_vwv0);
2362 CHECK_FNUM(fnum,cnum);
2366 numtowrite = SVAL(smb_buf(inbuf),1);
2367 data = smb_buf(inbuf) + 3;
2369 if (write_file(fnum,data,numtowrite) != numtowrite)
2370 return(UNIXERROR(ERRDOS,ERRnoaccess));
2372 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2378 /****************************************************************************
2380 ****************************************************************************/
2381 int reply_mkdir(char *inbuf,char *outbuf)
2385 int outsize,ret= -1;
2387 strcpy(directory,smb_buf(inbuf) + 1);
2388 cnum = SVAL(inbuf,smb_tid);
2389 unix_convert(directory,cnum);
2391 if (check_name(directory,cnum))
2392 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2395 return(UNIXERROR(ERRDOS,ERRnoaccess));
2397 outsize = set_message(outbuf,0,0,True);
2399 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2405 /****************************************************************************
2407 ****************************************************************************/
2408 int reply_rmdir(char *inbuf,char *outbuf)
2415 cnum = SVAL(inbuf,smb_tid);
2416 strcpy(directory,smb_buf(inbuf) + 1);
2417 unix_convert(directory,cnum);
2419 if (check_name(directory,cnum))
2421 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2422 ok = (sys_rmdir(directory) == 0);
2424 DEBUG(3,("couldn't remove directory %s : %s\n",
2425 directory,strerror(errno)));
2429 return(UNIXERROR(ERRDOS,ERRbadpath));
2431 outsize = set_message(outbuf,0,0,True);
2433 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2439 /*******************************************************************
2440 resolve wildcards in a filename rename
2441 ********************************************************************/
2442 static BOOL resolve_wildcards(char *name1,char *name2)
2444 fstring root1,root2;
2448 name1 = strrchr(name1,'/');
2449 name2 = strrchr(name2,'/');
2451 if (!name1 || !name2) return(False);
2453 strcpy(root1,name1);
2454 strcpy(root2,name2);
2455 p = strrchr(root1,'.');
2462 p = strrchr(root2,'.');
2494 strcpy(name2,root2);
2503 /*******************************************************************
2504 check if a user is allowed to rename a file
2505 ********************************************************************/
2506 static BOOL can_rename(char *fname,int cnum)
2510 if (!CAN_WRITE(cnum)) return(False);
2512 if (sys_lstat(fname,&sbuf) != 0) return(False);
2513 if (!check_file_sharing(cnum,fname)) return(False);
2518 /****************************************************************************
2520 ****************************************************************************/
2521 int reply_mv(char *inbuf,char *outbuf)
2527 pstring mask,newname;
2530 int error = ERRnoaccess;
2534 *directory = *mask = 0;
2536 cnum = SVAL(inbuf,smb_tid);
2538 strcpy(name,smb_buf(inbuf) + 1);
2539 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2541 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2543 unix_convert(name,cnum);
2544 unix_convert(newname,cnum);
2546 p = strrchr(name,'/');
2548 strcpy(directory,"./");
2552 strcpy(directory,name);
2556 if (is_mangled(mask))
2557 check_mangled_stack(mask);
2559 has_wild = strchr(mask,'*') || strchr(mask,'?');
2562 strcat(directory,"/");
2563 strcat(directory,mask);
2564 if (resolve_wildcards(directory,newname) &&
2565 can_rename(directory,cnum) &&
2566 !file_exist(newname,NULL) &&
2567 !sys_rename(directory,newname)) count++;
2568 if (!count) exists = file_exist(directory,NULL);
2569 if (!count && exists && file_exist(newname,NULL)) {
2574 void *dirptr = NULL;
2578 if (check_name(directory,cnum))
2579 dirptr = OpenDir(directory);
2585 if (strequal(mask,"????????.???"))
2588 while ((dname = ReadDirName(dirptr)))
2591 strcpy(fname,dname);
2593 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2595 error = ERRnoaccess;
2596 sprintf(fname,"%s/%s",directory,dname);
2597 if (!can_rename(fname,cnum)) continue;
2598 strcpy(destname,newname);
2600 if (!resolve_wildcards(fname,destname)) continue;
2602 if (file_exist(destname,NULL)) {
2606 if (!sys_rename(fname,destname)) count++;
2607 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2615 return(ERROR(ERRDOS,error));
2617 return(UNIXERROR(ERRDOS,error));
2620 outsize = set_message(outbuf,0,0,True);
2625 /*******************************************************************
2626 copy a file as part of a reply_copy
2627 ******************************************************************/
2628 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2629 int count,BOOL target_is_directory)
2638 if (target_is_directory) {
2639 char *p = strrchr(src,'/');
2648 if (!file_exist(src,&st)) return(False);
2650 fnum1 = find_free_file();
2651 if (fnum1<0) return(False);
2652 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2653 1,0,&Access,&action);
2655 if (!Files[fnum1].open) return(False);
2657 if (!target_is_directory && count)
2660 fnum2 = find_free_file();
2665 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2666 ofun,st.st_mode,&Access,&action);
2668 if (!Files[fnum2].open) {
2673 if ((ofun&3) == 1) {
2674 lseek(Files[fnum2].fd,0,SEEK_END);
2678 ret = transfer_file(Files[fnum1].fd,Files[fnum2].fd,st.st_size,NULL,0,0);
2683 return(ret == st.st_size);
2688 /****************************************************************************
2689 reply to a file copy.
2690 ****************************************************************************/
2691 int reply_copy(char *inbuf,char *outbuf)
2697 pstring mask,newname;
2700 int error = ERRnoaccess;
2703 int tid2 = SVAL(inbuf,smb_vwv0);
2704 int ofun = SVAL(inbuf,smb_vwv1);
2705 int flags = SVAL(inbuf,smb_vwv2);
2706 BOOL target_is_directory=False;
2708 *directory = *mask = 0;
2710 cnum = SVAL(inbuf,smb_tid);
2712 strcpy(name,smb_buf(inbuf));
2713 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2715 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2718 /* can't currently handle inter share copies XXXX */
2719 DEBUG(3,("Rejecting inter-share copy\n"));
2720 return(ERROR(ERRSRV,ERRinvdevice));
2723 unix_convert(name,cnum);
2724 unix_convert(newname,cnum);
2726 target_is_directory = directory_exist(newname,NULL);
2728 if ((flags&1) && target_is_directory) {
2729 return(ERROR(ERRDOS,ERRbadfile));
2732 if ((flags&2) && !target_is_directory) {
2733 return(ERROR(ERRDOS,ERRbadpath));
2736 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2737 /* wants a tree copy! XXXX */
2738 DEBUG(3,("Rejecting tree copy\n"));
2739 return(ERROR(ERRSRV,ERRerror));
2742 p = strrchr(name,'/');
2744 strcpy(directory,"./");
2748 strcpy(directory,name);
2752 if (is_mangled(mask))
2753 check_mangled_stack(mask);
2755 has_wild = strchr(mask,'*') || strchr(mask,'?');
2758 strcat(directory,"/");
2759 strcat(directory,mask);
2760 if (resolve_wildcards(directory,newname) &&
2761 copy_file(directory,newname,cnum,ofun,
2762 count,target_is_directory)) count++;
2763 if (!count) exists = file_exist(directory,NULL);
2765 void *dirptr = NULL;
2769 if (check_name(directory,cnum))
2770 dirptr = OpenDir(directory);
2776 if (strequal(mask,"????????.???"))
2779 while ((dname = ReadDirName(dirptr)))
2782 strcpy(fname,dname);
2784 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2786 error = ERRnoaccess;
2787 sprintf(fname,"%s/%s",directory,dname);
2788 strcpy(destname,newname);
2789 if (resolve_wildcards(fname,destname) &&
2790 copy_file(directory,newname,cnum,ofun,
2791 count,target_is_directory)) count++;
2792 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2800 return(ERROR(ERRDOS,error));
2802 return(UNIXERROR(ERRDOS,error));
2805 outsize = set_message(outbuf,1,0,True);
2806 SSVAL(outbuf,smb_vwv0,count);
2813 /****************************************************************************
2815 ****************************************************************************/
2816 int reply_setdir(char *inbuf,char *outbuf)
2823 cnum = SVAL(inbuf,smb_tid);
2825 snum = Connections[cnum].service;
2826 if (!CAN_SETDIR(snum))
2827 return(ERROR(ERRDOS,ERRnoaccess));
2829 strcpy(newdir,smb_buf(inbuf) + 1);
2832 if (strlen(newdir) == 0)
2836 ok = directory_exist(newdir,NULL);
2838 string_set(&Connections[cnum].connectpath,newdir);
2842 return(ERROR(ERRDOS,ERRbadpath));
2844 outsize = set_message(outbuf,0,0,True);
2845 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
2847 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
2853 /****************************************************************************
2854 reply to a lockingX request
2855 ****************************************************************************/
2856 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
2858 int fnum = GETFNUM(inbuf,smb_vwv2);
2859 uint16 locktype = SVAL(inbuf,smb_vwv3);
2860 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
2861 uint16 num_locks = SVAL(inbuf,smb_vwv7);
2862 uint32 count, offset;
2867 uint32 ecode=0, dummy2;
2868 int eclass=0, dummy1;
2870 cnum = SVAL(inbuf,smb_tid);
2872 CHECK_FNUM(fnum,cnum);
2875 data = smb_buf(inbuf);
2876 /* Data now points at the beginning of the list
2877 of smb_unlkrng structs */
2878 for(i = 0; i < (int)num_ulocks; i++) {
2879 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2880 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2881 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
2882 return ERROR(eclass,ecode);
2885 /* Now do any requested locks */
2886 data += 10*num_ulocks;
2887 /* Data now points at the beginning of the list
2888 of smb_lkrng structs */
2889 for(i = 0; i < (int)num_locks; i++) {
2890 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2891 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2892 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
2896 /* If any of the above locks failed, then we must unlock
2897 all of the previous locks (X/Open spec). */
2898 if(i != num_locks && num_locks != 0) {
2899 for(; i >= 0; i--) {
2900 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2901 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2902 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
2904 return ERROR(eclass,ecode);
2907 set_message(outbuf,2,0,True);
2909 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
2910 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
2914 return chain_reply(inbuf,outbuf,length,bufsize);
2918 /****************************************************************************
2919 reply to a SMBreadbmpx (read block multiplex) request
2920 ****************************************************************************/
2921 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
2928 int outsize, mincount, maxcount;
2933 /* this function doesn't seem to work - disable by default */
2935 return(ERROR(ERRSRV,ERRuseSTD));
2937 outsize = set_message(outbuf,8,0,True);
2939 cnum = SVAL(inbuf,smb_tid);
2940 fnum = GETFNUM(inbuf,smb_vwv0);
2942 CHECK_FNUM(fnum,cnum);
2946 startpos = IVAL(inbuf,smb_vwv1);
2947 maxcount = SVAL(inbuf,smb_vwv3);
2948 mincount = SVAL(inbuf,smb_vwv4);
2950 data = smb_buf(outbuf);
2951 pad = ((int)data)%4;
2952 if (pad) pad = 4 - pad;
2955 max_per_packet = bufsize-(outsize+pad);
2959 if (is_locked(fnum,cnum,maxcount,startpos))
2960 return(ERROR(ERRDOS,ERRlock));
2964 int N = MIN(max_per_packet,tcount-total_read);
2966 nread = read_file(fnum,data,startpos,N);
2968 if (nread <= 0) nread = 0;
2971 tcount = total_read + nread;
2973 set_message(outbuf,8,nread,False);
2974 SIVAL(outbuf,smb_vwv0,startpos);
2975 SSVAL(outbuf,smb_vwv2,tcount);
2976 SSVAL(outbuf,smb_vwv6,nread);
2977 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
2979 send_smb(Client,outbuf);
2981 total_read += nread;
2984 while (total_read < tcount);
2990 /****************************************************************************
2991 reply to a SMBwritebmpx (write block multiplex primary) request
2992 ****************************************************************************/
2993 int reply_writebmpx(char *inbuf,char *outbuf)
2995 int cnum,numtowrite,fnum;
2999 int tcount, write_through, smb_doff;
3002 cnum = SVAL(inbuf,smb_tid);
3003 fnum = GETFNUM(inbuf,smb_vwv0);
3005 CHECK_FNUM(fnum,cnum);
3009 tcount = SVAL(inbuf,smb_vwv1);
3010 startpos = IVAL(inbuf,smb_vwv3);
3011 write_through = BITSETW(inbuf+smb_vwv7,0);
3012 numtowrite = SVAL(inbuf,smb_vwv10);
3013 smb_doff = SVAL(inbuf,smb_vwv11);
3015 data = smb_base(inbuf) + smb_doff;
3017 /* If this fails we need to send an SMBwriteC response,
3018 not an SMBwritebmpx - set this up now so we don't forget */
3019 CVAL(outbuf,smb_com) = SMBwritec;
3021 if (is_locked(fnum,cnum,tcount,startpos))
3022 return(ERROR(ERRDOS,ERRlock));
3024 seek_file(fnum,startpos);
3025 nwritten = write_file(fnum,data,numtowrite);
3027 if(lp_syncalways(SNUM(cnum)) || write_through)
3030 if(nwritten < numtowrite)
3031 return(UNIXERROR(ERRHRD,ERRdiskfull));
3033 /* If the maximum to be written to this file
3034 is greater than what we just wrote then set
3035 up a secondary struct to be attached to this
3036 fd, we will use this to cache error messages etc. */
3037 if(tcount > nwritten)
3039 write_bmpx_struct *wbms;
3040 if(Files[fnum].wbmpx_ptr != NULL)
3041 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3043 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3046 DEBUG(0,("Out of memory in reply_readmpx\n"));
3047 return(ERROR(ERRSRV,ERRnoresource));
3049 wbms->wr_mode = write_through;
3050 wbms->wr_discard = False; /* No errors yet */
3051 wbms->wr_total_written = nwritten;
3052 wbms->wr_errclass = 0;
3054 Files[fnum].wbmpx_ptr = wbms;
3057 /* We are returning successfully, set the message type back to
3059 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3061 outsize = set_message(outbuf,1,0,True);
3063 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3065 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3066 timestring(),fnum,cnum,numtowrite,nwritten));
3068 if (write_through && tcount==nwritten) {
3069 /* we need to send both a primary and a secondary response */
3070 smb_setlen(outbuf,outsize - 4);
3071 send_smb(Client,outbuf);
3073 /* now the secondary */
3074 outsize = set_message(outbuf,1,0,True);
3075 CVAL(outbuf,smb_com) = SMBwritec;
3076 SSVAL(outbuf,smb_vwv0,nwritten);
3083 /****************************************************************************
3084 reply to a SMBwritebs (write block multiplex secondary) request
3085 ****************************************************************************/
3086 int reply_writebs(char *inbuf,char *outbuf)
3088 int cnum,numtowrite,fnum;
3092 int tcount, write_through, smb_doff;
3094 write_bmpx_struct *wbms;
3095 BOOL send_response = False;
3097 cnum = SVAL(inbuf,smb_tid);
3098 fnum = GETFNUM(inbuf,smb_vwv0);
3099 CHECK_FNUM(fnum,cnum);
3102 tcount = SVAL(inbuf,smb_vwv1);
3103 startpos = IVAL(inbuf,smb_vwv2);
3104 numtowrite = SVAL(inbuf,smb_vwv6);
3105 smb_doff = SVAL(inbuf,smb_vwv7);
3107 data = smb_base(inbuf) + smb_doff;
3109 /* We need to send an SMBwriteC response, not an SMBwritebs */
3110 CVAL(outbuf,smb_com) = SMBwritec;
3112 /* This fd should have an auxiliary struct attached,
3113 check that it does */
3114 wbms = Files[fnum].wbmpx_ptr;
3115 if(!wbms) return(-1);
3117 /* If write through is set we can return errors, else we must
3119 write_through = wbms->wr_mode;
3121 /* Check for an earlier error */
3122 if(wbms->wr_discard)
3123 return -1; /* Just discard the packet */
3125 seek_file(fnum,startpos);
3126 nwritten = write_file(fnum,data,numtowrite);
3128 if(lp_syncalways(SNUM(cnum)) || write_through)
3131 if (nwritten < numtowrite)
3134 /* We are returning an error - we can delete the aux struct */
3135 if (wbms) free((char *)wbms);
3136 Files[fnum].wbmpx_ptr = NULL;
3137 return(ERROR(ERRHRD,ERRdiskfull));
3139 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3142 /* Increment the total written, if this matches tcount
3143 we can discard the auxiliary struct (hurrah !) and return a writeC */
3144 wbms->wr_total_written += nwritten;
3145 if(wbms->wr_total_written >= tcount)
3147 if (write_through) {
3148 outsize = set_message(outbuf,1,0,True);
3149 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3150 send_response = True;
3154 Files[fnum].wbmpx_ptr = NULL;
3164 /****************************************************************************
3165 reply to a SMBsetattrE
3166 ****************************************************************************/
3167 int reply_setattrE(char *inbuf,char *outbuf)
3170 struct utimbuf unix_times;
3173 outsize = set_message(outbuf,0,0,True);
3175 cnum = SVAL(inbuf,smb_tid);
3176 fnum = GETFNUM(inbuf,smb_vwv0);
3178 CHECK_FNUM(fnum,cnum);
3181 /* Convert the DOS times into unix times. Ignore create
3182 time as UNIX can't set this.
3184 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3185 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3187 /* Set the date on this file */
3188 if(sys_utime(Files[fnum].name, &unix_times))
3189 return(ERROR(ERRDOS,ERRnoaccess));
3191 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3197 /****************************************************************************
3198 reply to a SMBgetattrE
3199 ****************************************************************************/
3200 int reply_getattrE(char *inbuf,char *outbuf)
3207 outsize = set_message(outbuf,11,0,True);
3209 cnum = SVAL(inbuf,smb_tid);
3210 fnum = GETFNUM(inbuf,smb_vwv0);
3212 CHECK_FNUM(fnum,cnum);
3215 /* Do an fstat on this file */
3216 if(fstat(Files[fnum].fd, &sbuf))
3217 return(UNIXERROR(ERRDOS,ERRnoaccess));
3219 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3221 /* Convert the times into dos times. Set create
3222 date to be last modify date as UNIX doesn't save
3224 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3225 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3226 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3229 SIVAL(outbuf,smb_vwv6,0);
3230 SIVAL(outbuf,smb_vwv8,0);
3234 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3235 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3237 SSVAL(outbuf,smb_vwv10, mode);
3239 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));