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;
33 extern int chain_size;
35 extern int chain_fnum;
36 extern char magic_char;
37 extern connection_struct Connections[];
38 extern files_struct Files[];
39 extern BOOL case_sensitive;
40 extern pstring sesssetup_user;
43 /* this macro should always be used to extract an fnum (smb_fid) from
44 a packet to ensure chaining works correctly */
45 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
48 /****************************************************************************
49 reply to an special message
50 ****************************************************************************/
51 int reply_special(char *inbuf,char *outbuf)
54 int msg_type = CVAL(inbuf,0);
55 int msg_flags = CVAL(inbuf,1);
57 extern fstring remote_machine;
58 extern fstring local_machine;
67 case 0x81: /* session request */
68 CVAL(outbuf,0) = 0x82;
70 if (name_len(inbuf+4) > 50)
72 DEBUG(0,("Invalid name length in session request\n"));
75 name_extract(inbuf,4,name1);
76 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
77 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2));
79 strcpy(remote_machine,name2);
80 trim_string(remote_machine," "," ");
81 p = strchr(remote_machine,' ');
82 strlower(remote_machine);
85 strcpy(local_machine,name1);
86 trim_string(local_machine," "," ");
87 p = strchr(local_machine,' ');
88 strlower(local_machine);
91 add_session_user(remote_machine);
93 reload_services(True);
97 case 0x85: /* session keepalive */
102 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags));
108 /*******************************************************************
109 work out what error to give to a failed connection
110 ********************************************************************/
111 static int connection_error(char *inbuf,char *outbuf,int connection_num)
113 switch (connection_num)
116 return(ERROR(ERRSRV,ERRnoresource));
118 return(ERROR(ERRSRV,ERRbaduid));
120 return(ERROR(ERRSRV,ERRinvdevice));
122 return(ERROR(ERRSRV,ERRinvnetname));
124 return(ERROR(ERRSRV,ERRaccess));
126 return(ERROR(ERRDOS,ERRnoipc));
128 return(ERROR(ERRSRV,ERRinvnetname));
130 return(ERROR(ERRSRV,ERRbadpw));
134 /****************************************************************************
136 ****************************************************************************/
137 int reply_tcon(char *inbuf,char *outbuf)
145 int uid = SVAL(inbuf,smb_uid);
149 *service = *user = *password = *dev = 0;
151 vuid = valid_uid(uid);
153 parse_connect(inbuf,service,user,password,&pwlen,dev);
155 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
157 if (connection_num < 0)
158 return(connection_error(inbuf,outbuf,connection_num));
160 outsize = set_message(outbuf,2,0,True);
161 SSVAL(outbuf,smb_vwv0,maxxmit);
162 SSVAL(outbuf,smb_vwv1,connection_num);
163 SSVAL(outbuf,smb_tid,connection_num);
165 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
171 /****************************************************************************
172 reply to a tcon and X
173 ****************************************************************************/
174 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
182 int uid = SVAL(inbuf,smb_uid);
184 int smb_com2 = SVAL(inbuf,smb_vwv0);
185 int smb_off2 = SVAL(inbuf,smb_vwv1);
186 int passlen = SVAL(inbuf,smb_vwv3);
188 *service = *user = *password = *devicename = 0;
190 /* we might have to close an old one */
191 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
192 close_cnum(SVAL(inbuf,smb_tid),uid);
194 vuid = valid_uid(uid);
199 memcpy(password,smb_buf(inbuf),passlen);
201 path = smb_buf(inbuf) + passlen;
202 DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
203 strcpy(service,path+2);
204 p = strchr(service,'\\');
206 return(ERROR(ERRSRV,ERRinvnetname));
209 p = strchr(service,'%');
215 StrnCpy(devicename,path + strlen(path) + 1,6);
216 DEBUG(4,("Got device type %s\n",devicename));
219 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
221 if (connection_num < 0)
222 return(connection_error(inbuf,outbuf,connection_num));
224 outsize = set_message(outbuf,2,strlen(devicename)+1,True);
226 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
228 /* set the incoming and outgoing tid to the just created one */
229 SSVAL(inbuf,smb_tid,connection_num);
230 SSVAL(outbuf,smb_tid,connection_num);
232 CVAL(outbuf,smb_vwv0) = smb_com2;
233 SSVAL(outbuf,smb_vwv1,(chain_size + outsize)-4);
235 strcpy(smb_buf(outbuf),devicename);
237 if (smb_com2 != 0xFF)
238 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
239 outbuf,outbuf+outsize,
246 /****************************************************************************
247 reply to an unknown type
248 ****************************************************************************/
249 int reply_unknown(char *inbuf,char *outbuf)
253 cnum = SVAL(inbuf,smb_tid);
254 type = CVAL(inbuf,smb_com);
256 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
261 return(ERROR(ERRSRV,ERRunknownsmb));
265 /****************************************************************************
267 ****************************************************************************/
268 int reply_ioctl(char *inbuf,char *outbuf)
270 DEBUG(3,("ignoring ioctl\n"));
272 return(ERROR(ERRSRV,ERRnosupport));
276 /****************************************************************************
277 reply to a session setup command
278 ****************************************************************************/
279 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
292 int smb_ntpasslen = 0;
293 pstring smb_ntpasswd;
294 BOOL valid_nt_password = False;
300 sess_uid = SVAL(inbuf,smb_uid);
301 smb_com2 = CVAL(inbuf,smb_vwv0);
302 smb_off2 = SVAL(inbuf,smb_vwv1);
303 smb_bufsize = SVAL(inbuf,smb_vwv2);
304 smb_mpxmax = SVAL(inbuf,smb_vwv3);
305 smb_vc_num = SVAL(inbuf,smb_vwv4);
306 smb_sesskey = IVAL(inbuf,smb_vwv5);
308 if (Protocol < PROTOCOL_NT1) {
309 smb_apasslen = SVAL(inbuf,smb_vwv7);
310 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
311 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
313 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
314 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
315 BOOL doencrypt = SMBENCRYPT();
316 char *p = smb_buf(inbuf);
317 if (passlen1 > 256) passlen1 = 0;
318 if (passlen2 > 256) passlen2 = 0; /* I don't know why NT gives weird
321 /* Save the lanman2 password and the NT md4 password. */
322 smb_apasslen = passlen1;
323 memcpy(smb_apasswd,p,smb_apasslen);
324 smb_ntpasslen = passlen2;
325 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
328 if (passlen1 > passlen2) {
329 smb_apasslen = passlen1;
330 StrnCpy(smb_apasswd,p,smb_apasslen);
332 smb_apasslen = passlen2;
333 StrnCpy(smb_apasswd,p + passlen1,smb_apasslen);
338 /* apparently NT sometimes sets passlen2 to 1 when it means 0. This
339 tries to work around that problem */
343 p += passlen1 + passlen2;
344 strcpy(user,p); p = skip_string(p,1);
345 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
346 p,skip_string(p,1),skip_string(p,2)));
350 DEBUG(3,("sesssetupX:name=[%s]\n",user));
353 strcpy(user,lp_guestaccount(-1));
357 strcpy(sesssetup_user,user);
359 reload_services(True);
361 add_session_user(user);
364 if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
365 !check_hosts_equiv(user))
368 if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
371 /* now check if it's a valid username/password */
372 /* If an NT password was supplied try and validate with that
373 first. This is superior as the passwords are mixed case 128 length unicode */
374 if(smb_ntpasslen && !guest)
376 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL,True))
377 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
379 valid_nt_password = True;
381 if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL,False))
383 if (lp_security() >= SEC_USER) {
384 #if (GUEST_SESSSETUP == 0)
385 return(ERROR(ERRSRV,ERRbadpw));
387 #if (GUEST_SESSSETUP == 1)
388 if (Get_Pwnam(user,True))
389 return(ERROR(ERRSRV,ERRbadpw));
392 if (*smb_apasswd || !Get_Pwnam(user,True))
393 strcpy(user,lp_guestaccount(-1));
394 DEBUG(3,("Registered username %s for guest access\n",user));
399 if (!Get_Pwnam(user,True)) {
400 DEBUG(3,("No such user %s - using guest account\n",user));
401 strcpy(user,lp_guestaccount(-1));
405 if (!strequal(user,lp_guestaccount(-1)) &&
406 lp_servicenumber(user) < 0)
408 int homes = lp_servicenumber(HOMES_NAME);
409 char *home = get_home_dir(user);
410 if (homes >= 0 && home)
411 lp_add_home(user,homes,home);
415 /* it's ok - setup a reply */
416 if (Protocol < PROTOCOL_NT1) {
417 outsize = set_message(outbuf,3,0,True);
420 outsize = set_message(outbuf,3,3,True);
422 strcpy(p,"Unix"); p = skip_string(p,1);
423 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
424 strcpy(p,my_workgroup()); p = skip_string(p,1);
425 outsize = set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
426 /* perhaps grab OS version here?? */
429 /* Set the correct uid in the outgoing and incoming packets
430 We will use this on future requests to determine which
431 user we should become.
434 struct passwd *pw = Get_Pwnam(user,False);
436 DEBUG(1,("Username %s is invalid on this system\n",user));
437 return(ERROR(ERRSRV,ERRbadpw));
440 SSVAL(outbuf,smb_uid,(uint16)pw->pw_uid);
441 SSVAL(inbuf,smb_uid,(uint16)pw->pw_uid);
444 CVAL(outbuf,smb_vwv0) = smb_com2;
445 SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
448 SSVAL(outbuf,smb_vwv2,1);
450 /* register the name and uid as being validated, so further connections
451 to a uid can get through without a password, on the same VC */
452 register_uid(SVAL(inbuf,smb_uid),gid,user,guest);
454 maxxmit = MIN(maxxmit,smb_bufsize);
456 if (smb_com2 != 0xFF)
457 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
458 outbuf,outbuf+outsize,
465 /****************************************************************************
467 ****************************************************************************/
468 int reply_chkpth(char *inbuf,char *outbuf)
475 cnum = SVAL(inbuf,smb_tid);
477 strcpy(name,smb_buf(inbuf) + 1);
478 unix_convert(name,cnum);
480 mode = SVAL(inbuf,smb_vwv0);
482 if (check_name(name,cnum))
483 ok = directory_exist(name,NULL);
486 return(ERROR(ERRDOS,ERRbadpath));
488 outsize = set_message(outbuf,0,0,True);
490 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
496 /****************************************************************************
498 ****************************************************************************/
499 int reply_getatr(char *inbuf,char *outbuf)
510 cnum = SVAL(inbuf,smb_tid);
512 strcpy(fname,smb_buf(inbuf) + 1);
513 unix_convert(fname,cnum);
515 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
516 under WfWg - weird! */
519 mode = aHIDDEN | aDIR;
520 if (!CAN_WRITE(cnum)) mode |= aRONLY;
526 if (check_name(fname,cnum))
528 if (sys_stat(fname,&sbuf) == 0)
530 mode = dos_mode(cnum,fname,&sbuf);
532 mtime = sbuf.st_mtime;
538 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
542 return(UNIXERROR(ERRDOS,ERRbadfile));
544 outsize = set_message(outbuf,10,0,True);
546 SSVAL(outbuf,smb_vwv0,mode);
547 put_dos_date3(outbuf,smb_vwv1,mtime);
548 SIVAL(outbuf,smb_vwv3,size);
550 if (Protocol >= PROTOCOL_NT1) {
551 char *p = strrchr(fname,'/');
552 uint16 flg2 = SVAL(outbuf,smb_flg2);
555 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
558 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
564 /****************************************************************************
566 ****************************************************************************/
567 int reply_setatr(char *inbuf,char *outbuf)
576 cnum = SVAL(inbuf,smb_tid);
578 strcpy(fname,smb_buf(inbuf) + 1);
579 unix_convert(fname,cnum);
581 mode = SVAL(inbuf,smb_vwv0);
582 mtime = make_unix_date3(inbuf+smb_vwv1);
584 if (directory_exist(fname,NULL))
586 if (check_name(fname,cnum))
587 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
589 ok = set_filetime(fname,mtime);
592 return(UNIXERROR(ERRDOS,ERRnoaccess));
594 outsize = set_message(outbuf,0,0,True);
596 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
602 /****************************************************************************
604 ****************************************************************************/
605 int reply_dskattr(char *inbuf,char *outbuf)
609 int dfree,dsize,bsize;
611 cnum = SVAL(inbuf,smb_tid);
613 sys_disk_free(".",&bsize,&dfree,&dsize);
615 outsize = set_message(outbuf,5,0,True);
617 SSVAL(outbuf,smb_vwv0,dsize);
618 SSVAL(outbuf,smb_vwv1,bsize/512);
619 SSVAL(outbuf,smb_vwv2,512);
620 SSVAL(outbuf,smb_vwv3,dfree);
622 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
628 /****************************************************************************
630 Can be called from SMBsearch, SMBffirst or SMBfunique.
631 ****************************************************************************/
632 int reply_search(char *inbuf,char *outbuf)
643 BOOL finished = False;
652 BOOL check_descend = False;
653 BOOL expect_close = False;
654 BOOL can_open = True;
656 *mask = *directory = *fname = 0;
658 /* If we were called as SMBffirst then we must expect close. */
659 if(CVAL(inbuf,smb_com) == SMBffirst)
662 cnum = SVAL(inbuf,smb_tid);
664 outsize = set_message(outbuf,1,3,True);
665 maxentries = SVAL(inbuf,smb_vwv0);
666 dirtype = SVAL(inbuf,smb_vwv1);
667 path = smb_buf(inbuf) + 1;
668 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
671 /* dirtype &= ~aDIR; */
673 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
680 strcpy(directory,smb_buf(inbuf)+1);
681 strcpy(dir2,smb_buf(inbuf)+1);
682 unix_convert(directory,cnum);
685 if (!check_name(directory,cnum))
688 p = strrchr(dir2,'/');
690 {strcpy(mask,dir2);*dir2 = 0;}
692 {*p = 0;strcpy(mask,p+1);}
694 p = strrchr(directory,'/');
700 if (strlen(directory) == 0)
701 strcpy(directory,"./");
703 CVAL(status,0) = dirtype;
707 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
708 memcpy(mask,status+1,11);
710 dirtype = CVAL(status,0) & 0x1F;
711 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
712 if (!Connections[cnum].dirptr)
714 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
719 /* turn strings of spaces into a . */
721 trim_string(mask,NULL," ");
722 if ((p = strrchr(mask,' ')))
727 trim_string(mask,NULL," ");
734 for (p=mask; *p; p++)
736 if (*p != '?' && *p != '*' && !isdoschar(*p))
738 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
744 if (!strchr(mask,'.') && strlen(mask)>8)
747 strcpy(tmp,&mask[8]);
753 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
757 p = smb_buf(outbuf) + 3;
763 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
765 return(ERROR(ERRDOS,ERRnofids));
768 DEBUG(4,("dptr_num is %d\n",dptr_num));
772 if ((dirtype&0x1F) == aVOLID)
775 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
776 dptr_fill(p+12,dptr_num);
777 if (dptr_zero(p+12) && (status_len==0))
781 p += DIR_STRUCT_SIZE;
785 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
786 if (in_list(Connections[cnum].dirpath,
787 lp_dontdescend(SNUM(cnum)),True))
788 check_descend = True;
790 for (i=numentries;(i<maxentries) && !finished;i++)
793 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
797 make_dir_struct(p,mask,fname,size,mode,date);
798 dptr_fill(p+12,dptr_num);
801 p += DIR_STRUCT_SIZE;
810 if (numentries == 0 || !ok)
812 CVAL(outbuf,smb_rcls) = ERRDOS;
813 SSVAL(outbuf,smb_err,ERRnofiles);
816 /* If we were called as SMBffirst with smb_search_id == NULL
817 and no entries were found then return error and close dirptr
820 if(ok && expect_close && numentries == 0 && status_len == 0)
822 CVAL(outbuf,smb_rcls) = ERRDOS;
823 SSVAL(outbuf,smb_err,ERRnofiles);
824 /* Also close the dptr - we know it's gone */
825 dptr_close(dptr_num);
828 /* If we were called as SMBfunique, then we can close the dirptr now ! */
829 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
830 dptr_close(dptr_num);
832 SSVAL(outbuf,smb_vwv0,numentries);
833 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
834 CVAL(smb_buf(outbuf),0) = 5;
835 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
837 if (Protocol >= PROTOCOL_NT1) {
838 uint16 flg2 = SVAL(outbuf,smb_flg2);
839 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
842 outsize += DIR_STRUCT_SIZE*numentries;
843 smb_setlen(outbuf,outsize - 4);
845 if ((! *directory) && dptr_path(dptr_num))
846 sprintf(directory,"(%s)",dptr_path(dptr_num));
848 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
850 smb_fn_name(CVAL(inbuf,smb_com)),
851 mask,directory,cnum,dirtype,numentries,maxentries));
857 /****************************************************************************
858 reply to a fclose (stop directory search)
859 ****************************************************************************/
860 int reply_fclose(char *inbuf,char *outbuf)
869 cnum = SVAL(inbuf,smb_tid);
871 outsize = set_message(outbuf,1,0,True);
872 path = smb_buf(inbuf) + 1;
873 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
877 return(ERROR(ERRSRV,ERRsrverror));
879 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
881 if(dptr_fetch(status+12,&dptr_num)) {
882 /* Close the dptr - we know it's gone */
883 dptr_close(dptr_num);
886 SSVAL(outbuf,smb_vwv0,0);
888 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
894 /****************************************************************************
896 ****************************************************************************/
897 int reply_open(char *inbuf,char *outbuf)
911 cnum = SVAL(inbuf,smb_tid);
913 share_mode = SVAL(inbuf,smb_vwv0);
915 strcpy(fname,smb_buf(inbuf)+1);
916 unix_convert(fname,cnum);
918 fnum = find_free_file();
920 return(ERROR(ERRSRV,ERRnofids));
922 if (!check_name(fname,cnum))
923 return(UNIXERROR(ERRDOS,ERRnoaccess));
925 unixmode = unix_mode(cnum,aARCH);
927 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
929 if (!Files[fnum].open)
930 return(UNIXERROR(ERRDOS,ERRnoaccess));
932 if (fstat(Files[fnum].fd,&sbuf) != 0) {
934 return(ERROR(ERRDOS,ERRnoaccess));
938 fmode = dos_mode(cnum,fname,&sbuf);
939 mtime = sbuf.st_mtime;
942 DEBUG(3,("attempt to open a directory %s\n",fname));
944 return(ERROR(ERRDOS,ERRnoaccess));
947 outsize = set_message(outbuf,7,0,True);
948 SSVAL(outbuf,smb_vwv0,fnum);
949 SSVAL(outbuf,smb_vwv1,fmode);
950 put_dos_date3(outbuf,smb_vwv2,mtime);
951 SIVAL(outbuf,smb_vwv4,size);
952 SSVAL(outbuf,smb_vwv6,rmode);
958 /****************************************************************************
959 reply to an open and X
960 ****************************************************************************/
961 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
964 int cnum = SVAL(inbuf,smb_tid);
968 int smb_com2 = CVAL(inbuf,smb_vwv0);
969 int smb_off2 = SVAL(inbuf,smb_vwv1);
970 int smb_mode = SVAL(inbuf,smb_vwv3);
971 int smb_attr = SVAL(inbuf,smb_vwv5);
973 int open_flags = SVAL(inbuf,smb_vwv2);
974 int smb_sattr = SVAL(inbuf,smb_vwv4);
975 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
977 int smb_ofun = SVAL(inbuf,smb_vwv8);
979 int size=0,fmode=0,mtime=0,rmode=0;
983 /* XXXX we need to handle passed times, sattr and flags */
985 strcpy(fname,smb_buf(inbuf));
986 unix_convert(fname,cnum);
988 /* now add create and trunc bits */
991 if ((smb_ofun & 0x3) == 2)
994 fnum = find_free_file();
996 return(ERROR(ERRSRV,ERRnofids));
998 if (!check_name(fname,cnum))
999 return(UNIXERROR(ERRDOS,ERRnoaccess));
1001 unixmode = unix_mode(cnum,smb_attr | aARCH);
1003 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1004 &rmode,&smb_action);
1006 if (!Files[fnum].open)
1007 return(UNIXERROR(ERRDOS,ERRnoaccess));
1009 if (fstat(Files[fnum].fd,&sbuf) != 0) {
1011 return(ERROR(ERRDOS,ERRnoaccess));
1014 size = sbuf.st_size;
1015 fmode = dos_mode(cnum,fname,&sbuf);
1016 mtime = sbuf.st_mtime;
1019 return(ERROR(ERRDOS,ERRnoaccess));
1022 outsize = set_message(outbuf,15,0,True);
1023 CVAL(outbuf,smb_vwv0) = smb_com2;
1024 SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
1025 SSVAL(outbuf,smb_vwv2,fnum);
1026 SSVAL(outbuf,smb_vwv3,fmode);
1027 put_dos_date3(outbuf,smb_vwv4,mtime);
1028 SIVAL(outbuf,smb_vwv6,size);
1029 SSVAL(outbuf,smb_vwv8,rmode);
1030 SSVAL(outbuf,smb_vwv11,smb_action);
1034 if (smb_com2 != 0xFF)
1035 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
1036 outbuf,outbuf+outsize,
1045 /****************************************************************************
1046 reply to a SMBulogoffX
1047 ****************************************************************************/
1048 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1051 int smb_com2 = CVAL(inbuf,smb_vwv0);
1052 int smb_off2 = SVAL(inbuf,smb_vwv1);
1053 int uid = SVAL(inbuf,smb_uid);
1055 invalidate_uid(uid);
1057 outsize = set_message(outbuf,2,0,True);
1058 CVAL(outbuf,smb_vwv0) = smb_com2;
1059 SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
1061 DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid));
1063 if (smb_com2 != 0xFF)
1064 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
1065 outbuf,outbuf+outsize,
1073 /****************************************************************************
1075 ****************************************************************************/
1076 int reply_mknew(char *inbuf,char *outbuf)
1085 com = SVAL(inbuf,smb_com);
1086 cnum = SVAL(inbuf,smb_tid);
1088 createmode = SVAL(inbuf,smb_vwv0);
1089 strcpy(fname,smb_buf(inbuf)+1);
1090 unix_convert(fname,cnum);
1092 if (createmode & aVOLID)
1094 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1097 unixmode = unix_mode(cnum,createmode);
1099 if (com == SMBmknew && file_exist(fname,NULL))
1100 return(ERROR(ERRDOS,ERRfilexists));
1102 fnum = find_free_file();
1104 return(ERROR(ERRSRV,ERRnofids));
1106 if (!check_name(fname,cnum))
1107 return(UNIXERROR(ERRDOS,ERRnoaccess));
1109 open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1111 if (!Files[fnum].open)
1112 return(UNIXERROR(ERRDOS,ERRnoaccess));
1114 outsize = set_message(outbuf,1,0,True);
1115 SSVAL(outbuf,smb_vwv0,fnum);
1117 DEBUG(2,("new file %s\n",fname));
1118 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));
1124 /****************************************************************************
1125 reply to a create temporary file
1126 ****************************************************************************/
1127 int reply_ctemp(char *inbuf,char *outbuf)
1137 cnum = SVAL(inbuf,smb_tid);
1138 createmode = SVAL(inbuf,smb_vwv0);
1139 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1140 unix_convert(fname,cnum);
1142 unixmode = unix_mode(cnum,createmode);
1144 fnum = find_free_file();
1146 return(ERROR(ERRSRV,ERRnofids));
1148 if (!check_name(fname,cnum))
1149 return(UNIXERROR(ERRDOS,ERRnoaccess));
1151 strcpy(fname2,(char *)mktemp(fname));
1153 open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1155 if (!Files[fnum].open)
1156 return(UNIXERROR(ERRDOS,ERRnoaccess));
1158 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1159 SSVAL(outbuf,smb_vwv0,fnum);
1160 CVAL(smb_buf(outbuf),0) = 4;
1161 strcpy(smb_buf(outbuf) + 1,fname2);
1163 DEBUG(2,("created temp file %s\n",fname2));
1164 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));
1170 /*******************************************************************
1171 check if a user is allowed to delete a file
1172 ********************************************************************/
1173 static BOOL can_delete(char *fname,int cnum,int dirtype)
1178 if (!CAN_WRITE(cnum)) return(False);
1180 if (sys_lstat(fname,&sbuf) != 0) return(False);
1181 fmode = dos_mode(cnum,fname,&sbuf);
1182 if (fmode & aDIR) return(False);
1183 if (!lp_delete_readonly(SNUM(cnum))) {
1184 if (fmode & aRONLY) return(False);
1186 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1188 if (!check_file_sharing(cnum,fname)) return(False);
1192 /****************************************************************************
1194 ****************************************************************************/
1195 int reply_unlink(char *inbuf,char *outbuf)
1205 int error = ERRnoaccess;
1209 *directory = *mask = 0;
1211 cnum = SVAL(inbuf,smb_tid);
1212 dirtype = SVAL(inbuf,smb_vwv0);
1214 strcpy(name,smb_buf(inbuf) + 1);
1216 DEBUG(3,("reply_unlink : %s\n",name));
1218 unix_convert(name,cnum);
1220 p = strrchr(name,'/');
1222 strcpy(directory,"./");
1226 strcpy(directory,name);
1230 if (is_mangled(mask))
1231 check_mangled_stack(mask);
1233 has_wild = strchr(mask,'*') || strchr(mask,'?');
1236 strcat(directory,"/");
1237 strcat(directory,mask);
1238 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1239 if (!count) exists = file_exist(directory,NULL);
1241 void *dirptr = NULL;
1244 if (check_name(directory,cnum))
1245 dirptr = OpenDir(directory);
1251 if (strequal(mask,"????????.???"))
1254 while ((dname = ReadDirName(dirptr)))
1257 strcpy(fname,dname);
1259 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1261 error = ERRnoaccess;
1262 sprintf(fname,"%s/%s",directory,dname);
1263 if (!can_delete(fname,cnum,dirtype)) continue;
1264 if (!sys_unlink(fname)) count++;
1265 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1273 return(ERROR(ERRDOS,error));
1275 return(UNIXERROR(ERRDOS,error));
1278 outsize = set_message(outbuf,0,0,True);
1284 /****************************************************************************
1285 reply to a readbraw (core+ protocol)
1286 ****************************************************************************/
1287 int reply_readbraw(char *inbuf, char *outbuf)
1289 int cnum,maxcount,mincount,fnum;
1292 char *header = outbuf;
1297 cnum = SVAL(inbuf,smb_tid);
1298 fnum = GETFNUM(inbuf,smb_vwv0);
1300 startpos = IVAL(inbuf,smb_vwv1);
1301 maxcount = SVAL(inbuf,smb_vwv3);
1302 mincount = SVAL(inbuf,smb_vwv4);
1304 /* ensure we don't overrun the packet size */
1305 maxcount = MIN(65535,maxcount);
1306 maxcount = MAX(mincount,maxcount);
1308 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1310 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1311 _smb_setlen(header,0);
1312 transfer_file(0,Client,0,header,4,0);
1317 fd = Files[fnum].fd;
1318 fname = Files[fnum].name;
1322 if (!is_locked(fnum,cnum,maxcount,startpos))
1324 int size = Files[fnum].size;
1325 int sizeneeded = startpos + maxcount;
1327 if (size < sizeneeded) {
1329 if (fstat(Files[fnum].fd,&st) == 0)
1331 if (!Files[fnum].can_write)
1332 Files[fnum].size = size;
1335 nread = MIN(maxcount,size - startpos);
1338 if (nread < mincount)
1341 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1344 maxcount,mincount,nread));
1349 _smb_setlen(header,nread);
1351 if (!Files[fnum].can_write)
1352 predict = read_predict(fd,startpos,header+4,NULL,nread);
1354 if ((nread-predict) > 0)
1355 seek_file(fnum,startpos + predict);
1357 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1362 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1363 fname,startpos,nread,ret));
1366 ret = read_file(fnum,header+4,startpos,nread,nread,-1,False);
1367 if (ret < mincount) ret = 0;
1369 _smb_setlen(header,ret);
1370 transfer_file(0,Client,0,header,4+ret,0);
1373 DEBUG(5,("readbraw finished\n"));
1378 /****************************************************************************
1379 reply to a lockread (core+ protocol)
1380 ****************************************************************************/
1381 int reply_lockread(char *inbuf,char *outbuf)
1387 uint32 startpos, numtoread;
1391 cnum = SVAL(inbuf,smb_tid);
1392 fnum = GETFNUM(inbuf,smb_vwv0);
1394 CHECK_FNUM(fnum,cnum);
1398 numtoread = SVAL(inbuf,smb_vwv1);
1399 startpos = IVAL(inbuf,smb_vwv2);
1401 outsize = set_message(outbuf,5,3,True);
1402 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1403 data = smb_buf(outbuf) + 3;
1405 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1406 return (ERROR(eclass,ecode));
1408 nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False);
1411 return(UNIXERROR(ERRDOS,ERRnoaccess));
1414 SSVAL(outbuf,smb_vwv0,nread);
1415 SSVAL(outbuf,smb_vwv5,nread+3);
1416 SSVAL(smb_buf(outbuf),1,nread);
1418 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1424 /****************************************************************************
1426 ****************************************************************************/
1427 int reply_read(char *inbuf,char *outbuf)
1429 int cnum,numtoread,fnum;
1435 cnum = SVAL(inbuf,smb_tid);
1436 fnum = GETFNUM(inbuf,smb_vwv0);
1438 CHECK_FNUM(fnum,cnum);
1442 numtoread = SVAL(inbuf,smb_vwv1);
1443 startpos = IVAL(inbuf,smb_vwv2);
1445 outsize = set_message(outbuf,5,3,True);
1446 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1447 data = smb_buf(outbuf) + 3;
1449 if (is_locked(fnum,cnum,numtoread,startpos))
1450 return(ERROR(ERRDOS,ERRlock));
1453 nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False);
1456 return(UNIXERROR(ERRDOS,ERRnoaccess));
1459 SSVAL(outbuf,smb_vwv0,nread);
1460 SSVAL(outbuf,smb_vwv5,nread+3);
1461 CVAL(smb_buf(outbuf),0) = 1;
1462 SSVAL(smb_buf(outbuf),1,nread);
1464 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1470 /****************************************************************************
1471 reply to a read and X
1472 ****************************************************************************/
1473 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1475 int smb_com2 = CVAL(inbuf,smb_vwv0);
1476 int smb_off2 = SVAL(inbuf,smb_vwv1);
1477 int fnum = GETFNUM(inbuf,smb_vwv2);
1478 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1479 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1480 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1487 cnum = SVAL(inbuf,smb_tid);
1489 CHECK_FNUM(fnum,cnum);
1493 outsize = set_message(outbuf,12,0,True);
1494 data = smb_buf(outbuf);
1496 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1497 return(ERROR(ERRDOS,ERRlock));
1498 nread = read_file(fnum,data,smb_offs,smb_maxcnt,smb_maxcnt,-1,False);
1502 return(UNIXERROR(ERRDOS,ERRnoaccess));
1505 CVAL(outbuf,smb_vwv0) = smb_com2;
1506 SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
1507 SSVAL(outbuf,smb_vwv5,nread);
1508 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf) + chain_size);
1509 SSVAL(smb_buf(outbuf),-2,nread);
1511 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d com2=%d off2=%d\n",
1512 timestring(),fnum,cnum,
1513 smb_mincnt,smb_maxcnt,nread,smb_com2,smb_off2));
1517 if (smb_com2 != 0xFF)
1518 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
1519 outbuf,outbuf+outsize,
1528 /****************************************************************************
1529 reply to a writebraw (core+ or LANMAN1.0 protocol)
1530 ****************************************************************************/
1531 int reply_writebraw(char *inbuf,char *outbuf)
1534 int total_written=0;
1543 cnum = SVAL(inbuf,smb_tid);
1544 fnum = GETFNUM(inbuf,smb_vwv0);
1546 CHECK_FNUM(fnum,cnum);
1550 tcount = IVAL(inbuf,smb_vwv1);
1551 startpos = IVAL(inbuf,smb_vwv3);
1552 write_through = BITSETW(inbuf+smb_vwv7,0);
1554 /* We have to deal with slightly different formats depending
1555 on whether we are using the core+ or lanman1.0 protocol */
1556 if(Protocol <= PROTOCOL_COREPLUS) {
1557 numtowrite = SVAL(smb_buf(inbuf),-2);
1558 data = smb_buf(inbuf);
1560 numtowrite = SVAL(inbuf,smb_vwv10);
1561 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1564 /* force the error type */
1565 CVAL(inbuf,smb_com) = SMBwritec;
1566 CVAL(outbuf,smb_com) = SMBwritec;
1568 if (is_locked(fnum,cnum,tcount,startpos))
1569 return(ERROR(ERRDOS,ERRlock));
1571 if (seek_file(fnum,startpos) != startpos)
1572 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1575 nwritten = write_file(fnum,data,numtowrite);
1577 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1578 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1580 if (nwritten < numtowrite)
1581 return(UNIXERROR(ERRHRD,ERRdiskfull));
1583 total_written = nwritten;
1585 /* Return a message to the redirector to tell it
1586 to send more bytes */
1587 CVAL(outbuf,smb_com) = SMBwritebraw;
1588 SSVALS(outbuf,smb_vwv0,-1);
1589 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1590 send_smb(Client,outbuf);
1592 /* Now read the raw data into the buffer and write it */
1593 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1594 exit_server("secondary writebraw failed");
1597 /* Even though this is not an smb message, smb_len
1598 returns the generic length of an smb message */
1599 numtowrite = smb_len(inbuf);
1601 if (tcount > nwritten+numtowrite) {
1602 DEBUG(3,("Client overestimated the write %d %d %d\n",
1603 tcount,nwritten,numtowrite));
1606 nwritten = transfer_file(Client,Files[fnum].fd,numtowrite,NULL,0,
1608 total_written += nwritten;
1610 /* Set up outbuf to return the correct return */
1611 outsize = set_message(outbuf,1,0,True);
1612 CVAL(outbuf,smb_com) = SMBwritec;
1613 SSVAL(outbuf,smb_vwv0,total_written);
1615 if (nwritten < numtowrite) {
1616 CVAL(outbuf,smb_rcls) = ERRHRD;
1617 SSVAL(outbuf,smb_err,ERRdiskfull);
1620 if (lp_syncalways(SNUM(cnum)) || write_through)
1623 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1624 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1626 /* we won't return a status if write through is not selected - this
1627 follows what WfWg does */
1628 if (!write_through && total_written==tcount)
1635 /****************************************************************************
1636 reply to a writeunlock (core+)
1637 ****************************************************************************/
1638 int reply_writeunlock(char *inbuf,char *outbuf)
1644 uint32 numtowrite,startpos;
1648 cnum = SVAL(inbuf,smb_tid);
1649 fnum = GETFNUM(inbuf,smb_vwv0);
1651 CHECK_FNUM(fnum,cnum);
1655 numtowrite = SVAL(inbuf,smb_vwv1);
1656 startpos = IVAL(inbuf,smb_vwv2);
1657 data = smb_buf(inbuf) + 3;
1659 if (is_locked(fnum,cnum,numtowrite,startpos))
1660 return(ERROR(ERRDOS,ERRlock));
1662 seek_file(fnum,startpos);
1664 /* The special X/Open SMB protocol handling of
1665 zero length writes is *NOT* done for
1670 nwritten = write_file(fnum,data,numtowrite);
1672 if (lp_syncalways(SNUM(cnum)))
1675 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1676 return(UNIXERROR(ERRDOS,ERRnoaccess));
1678 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1679 return(ERROR(eclass,ecode));
1681 outsize = set_message(outbuf,1,0,True);
1683 SSVAL(outbuf,smb_vwv0,nwritten);
1685 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1686 timestring(),fnum,cnum,numtowrite,nwritten));
1692 /****************************************************************************
1694 ****************************************************************************/
1695 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1697 int cnum,numtowrite,fnum;
1706 cnum = SVAL(inbuf,smb_tid);
1707 fnum = GETFNUM(inbuf,smb_vwv0);
1709 CHECK_FNUM(fnum,cnum);
1713 numtowrite = SVAL(inbuf,smb_vwv1);
1714 startpos = IVAL(inbuf,smb_vwv2);
1715 data = smb_buf(inbuf) + 3;
1717 if (is_locked(fnum,cnum,numtowrite,startpos))
1718 return(ERROR(ERRDOS,ERRlock));
1720 seek_file(fnum,startpos);
1722 /* X/Open SMB protocol says that if smb_vwv1 is
1723 zero then the file size should be extended or
1724 truncated to the size given in smb_vwv[2-3] */
1726 nwritten = set_filelen(Files[fnum].fd, startpos);
1728 nwritten = write_file(fnum,data,numtowrite);
1730 if (lp_syncalways(SNUM(cnum)))
1733 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1734 return(UNIXERROR(ERRDOS,ERRnoaccess));
1736 outsize = set_message(outbuf,1,0,True);
1738 SSVAL(outbuf,smb_vwv0,nwritten);
1740 if (nwritten < numtowrite) {
1741 CVAL(outbuf,smb_rcls) = ERRHRD;
1742 SSVAL(outbuf,smb_err,ERRdiskfull);
1745 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1751 /****************************************************************************
1752 reply to a write and X
1753 ****************************************************************************/
1754 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1756 int smb_com2 = CVAL(inbuf,smb_vwv0);
1757 int smb_off2 = SVAL(inbuf,smb_vwv1);
1758 int fnum = GETFNUM(inbuf,smb_vwv2);
1759 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1760 int smb_dsize = SVAL(inbuf,smb_vwv10);
1761 int smb_doff = SVAL(inbuf,smb_vwv11);
1762 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1768 cnum = SVAL(inbuf,smb_tid);
1770 CHECK_FNUM(fnum,cnum);
1774 data = smb_base(inbuf) + smb_doff;
1776 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1777 return(ERROR(ERRDOS,ERRlock));
1779 seek_file(fnum,smb_offs);
1781 /* X/Open SMB protocol says that, unlike SMBwrite
1782 if the length is zero then NO truncation is
1783 done, just a write of zero. To truncate a file,
1788 nwritten = write_file(fnum,data,smb_dsize);
1790 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1791 return(UNIXERROR(ERRDOS,ERRnoaccess));
1793 outsize = set_message(outbuf,6,0,True);
1795 CVAL(outbuf,smb_vwv0) = smb_com2;
1796 SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
1797 SSVAL(outbuf,smb_vwv2,nwritten);
1799 if (nwritten < smb_dsize) {
1800 CVAL(outbuf,smb_rcls) = ERRHRD;
1801 SSVAL(outbuf,smb_err,ERRdiskfull);
1804 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1808 if (lp_syncalways(SNUM(cnum)) || write_through)
1811 if (smb_com2 != 0xFF)
1812 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
1813 outbuf,outbuf+outsize,
1822 /****************************************************************************
1824 ****************************************************************************/
1825 int reply_lseek(char *inbuf,char *outbuf)
1833 cnum = SVAL(inbuf,smb_tid);
1834 fnum = GETFNUM(inbuf,smb_vwv0);
1836 CHECK_FNUM(fnum,cnum);
1839 mode = SVAL(inbuf,smb_vwv1) & 3;
1840 startpos = IVAL(inbuf,smb_vwv2);
1844 case 0: umode = SEEK_SET; break;
1845 case 1: umode = SEEK_CUR; break;
1846 case 2: umode = SEEK_END; break;
1848 umode = SEEK_SET; break;
1851 res = lseek(Files[fnum].fd,startpos,umode);
1852 Files[fnum].pos = res;
1854 outsize = set_message(outbuf,2,0,True);
1855 SIVALS(outbuf,smb_vwv0,res);
1857 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1863 /****************************************************************************
1865 ****************************************************************************/
1866 int reply_flush(char *inbuf,char *outbuf)
1869 int outsize = set_message(outbuf,0,0,True);
1871 cnum = SVAL(inbuf,smb_tid);
1872 fnum = GETFNUM(inbuf,smb_vwv0);
1874 if (fnum != 0xFFFF) {
1875 CHECK_FNUM(fnum,cnum);
1882 for (i=0;i<MAX_OPEN_FILES;i++)
1889 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1894 /****************************************************************************
1896 ****************************************************************************/
1897 int reply_exit(char *inbuf,char *outbuf)
1899 int outsize = set_message(outbuf,0,0,True);
1900 DEBUG(3,("%s exit\n",timestring()));
1906 /****************************************************************************
1908 ****************************************************************************/
1909 int reply_close(char *inbuf,char *outbuf)
1914 int32 eclass = 0, err = 0;
1916 outsize = set_message(outbuf,0,0,True);
1918 cnum = SVAL(inbuf,smb_tid);
1920 fnum = GETFNUM(inbuf,smb_vwv0);
1921 CHECK_FNUM(fnum,cnum);
1923 if(HAS_CACHED_ERROR(fnum)) {
1924 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1925 err = Files[fnum].wbmpx_ptr->wr_error;
1928 mtime = make_unix_date3(inbuf+smb_vwv1);
1930 /* try and set the date */
1931 set_filetime(Files[fnum].name,mtime);
1935 /* We have a cached error */
1937 return(ERROR(eclass,err));
1939 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
1940 timestring(),Files[fnum].fd,fnum,cnum,
1941 Connections[cnum].num_files_open));
1947 /****************************************************************************
1948 reply to a writeclose (Core+ protocol)
1949 ****************************************************************************/
1950 int reply_writeclose(char *inbuf,char *outbuf)
1952 int cnum,numtowrite,fnum;
1959 cnum = SVAL(inbuf,smb_tid);
1960 fnum = GETFNUM(inbuf,smb_vwv0);
1962 CHECK_FNUM(fnum,cnum);
1966 numtowrite = SVAL(inbuf,smb_vwv1);
1967 startpos = IVAL(inbuf,smb_vwv2);
1968 mtime = make_unix_date3(inbuf+smb_vwv4);
1969 data = smb_buf(inbuf) + 1;
1971 if (is_locked(fnum,cnum,numtowrite,startpos))
1972 return(ERROR(ERRDOS,ERRlock));
1974 seek_file(fnum,startpos);
1976 nwritten = write_file(fnum,data,numtowrite);
1978 set_filetime(Files[fnum].name,mtime);
1982 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
1983 timestring(),fnum,cnum,numtowrite,nwritten,
1984 Connections[cnum].num_files_open));
1987 return(UNIXERROR(ERRDOS,ERRnoaccess));
1989 outsize = set_message(outbuf,1,0,True);
1991 SSVAL(outbuf,smb_vwv0,nwritten);
1996 /****************************************************************************
1998 ****************************************************************************/
1999 int reply_lock(char *inbuf,char *outbuf)
2002 int outsize = set_message(outbuf,0,0,True);
2003 uint32 count,offset;
2007 cnum = SVAL(inbuf,smb_tid);
2008 fnum = GETFNUM(inbuf,smb_vwv0);
2010 CHECK_FNUM(fnum,cnum);
2013 count = IVAL(inbuf,smb_vwv1);
2014 offset = IVAL(inbuf,smb_vwv3);
2016 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2018 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2019 return (ERROR(eclass,ecode));
2025 /****************************************************************************
2027 ****************************************************************************/
2028 int reply_unlock(char *inbuf,char *outbuf)
2031 int outsize = set_message(outbuf,0,0,True);
2032 uint32 count,offset;
2036 cnum = SVAL(inbuf,smb_tid);
2037 fnum = GETFNUM(inbuf,smb_vwv0);
2039 CHECK_FNUM(fnum,cnum);
2042 count = IVAL(inbuf,smb_vwv1);
2043 offset = IVAL(inbuf,smb_vwv3);
2045 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2046 return (ERROR(eclass,ecode));
2048 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2054 /****************************************************************************
2056 ****************************************************************************/
2057 int reply_tdis(char *inbuf,char *outbuf)
2060 int outsize = set_message(outbuf,0,0,True);
2062 cnum = SVAL(inbuf,smb_tid);
2063 uid = SVAL(inbuf,smb_uid);
2065 if (!OPEN_CNUM(cnum)) {
2066 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2067 return(ERROR(ERRSRV,ERRinvnid));
2070 Connections[cnum].used = False;
2072 close_cnum(cnum,uid);
2074 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2081 /****************************************************************************
2083 ****************************************************************************/
2084 int reply_echo(char *inbuf,char *outbuf)
2087 int smb_reverb = SVAL(inbuf,smb_vwv0);
2089 int data_len = smb_buflen(inbuf);
2090 int outsize = set_message(outbuf,1,data_len,True);
2092 cnum = SVAL(inbuf,smb_tid);
2094 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2096 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2097 return(ERROR(ERRSRV,ERRinvnid));
2100 /* copy any incoming data back out */
2102 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2104 if (smb_reverb > 100)
2106 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2110 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2112 SSVAL(outbuf,smb_vwv0,seq_num);
2114 smb_setlen(outbuf,outsize - 4);
2116 send_smb(Client,outbuf);
2119 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2125 /****************************************************************************
2126 reply to a printopen
2127 ****************************************************************************/
2128 int reply_printopen(char *inbuf,char *outbuf)
2136 *fname = *fname2 = 0;
2138 cnum = SVAL(inbuf,smb_tid);
2140 if (!CAN_PRINT(cnum))
2141 return(ERROR(ERRDOS,ERRnoaccess));
2146 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2150 if (!(isalnum(*p) || strchr("._-",*p)))
2155 if (strlen(s) > 10) s[10] = 0;
2157 sprintf(fname,"%s.XXXXXX",s);
2160 fnum = find_free_file();
2162 return(ERROR(ERRSRV,ERRnofids));
2164 strcpy(fname2,(char *)mktemp(fname));
2166 if (!check_name(fname2,cnum))
2167 return(ERROR(ERRDOS,ERRnoaccess));
2169 open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC,
2172 if (!Files[fnum].open)
2173 return(UNIXERROR(ERRDOS,ERRnoaccess));
2175 /* force it to be a print file */
2176 Files[fnum].print_file = True;
2178 outsize = set_message(outbuf,1,0,True);
2179 SSVAL(outbuf,smb_vwv0,fnum);
2181 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum));
2187 /****************************************************************************
2188 reply to a printclose
2189 ****************************************************************************/
2190 int reply_printclose(char *inbuf,char *outbuf)
2193 int outsize = set_message(outbuf,0,0,True);
2195 cnum = SVAL(inbuf,smb_tid);
2196 fnum = GETFNUM(inbuf,smb_vwv0);
2198 CHECK_FNUM(fnum,cnum);
2201 if (!CAN_PRINT(cnum))
2202 return(ERROR(ERRDOS,ERRnoaccess));
2206 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum));
2212 /****************************************************************************
2213 reply to a printqueue
2214 ****************************************************************************/
2215 int reply_printqueue(char *inbuf,char *outbuf)
2218 int outsize = set_message(outbuf,2,3,True);
2219 int max_count = SVAL(inbuf,smb_vwv0);
2220 int start_index = SVAL(inbuf,smb_vwv1);
2222 cnum = SVAL(inbuf,smb_tid);
2223 uid = SVAL(inbuf,smb_uid);
2225 /* allow checking the queue for anyone */
2227 if (!CAN_PRINT(cnum))
2228 return(ERROR(ERRDOS,ERRnoaccess));
2231 SSVAL(outbuf,smb_vwv0,0);
2232 SSVAL(outbuf,smb_vwv1,0);
2233 CVAL(smb_buf(outbuf),0) = 1;
2234 SSVAL(smb_buf(outbuf),1,0);
2236 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2237 timestring(),cnum,start_index,max_count));
2239 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2244 for (i=0;i<MAX_CONNECTIONS;i++)
2245 if (CAN_PRINT(i) && Connections[i].printer)
2249 for (i=0;i<MAX_CONNECTIONS;i++)
2253 if (!OPEN_CNUM(cnum))
2254 return(ERROR(ERRSRV,ERRinvnid));
2256 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2259 if (!become_user(cnum,uid))
2260 return(ERROR(ERRSRV,ERRinvnid));
2263 print_queue_struct *queue = NULL;
2264 char *p = smb_buf(outbuf) + 3;
2265 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2266 int num_to_get = ABS(max_count);
2267 int first = (max_count>0?start_index:start_index+max_count+1);
2273 num_to_get = MIN(num_to_get,count-first);
2276 for (i=first;i<first+num_to_get;i++)
2278 put_dos_date2(p,0,queue[i].time);
2279 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2280 SSVAL(p,5,queue[i].job);
2281 SIVAL(p,7,queue[i].size);
2283 StrnCpy(p+12,queue[i].user,16);
2289 outsize = set_message(outbuf,2,28*count+3,False);
2290 SSVAL(outbuf,smb_vwv0,count);
2291 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2292 CVAL(smb_buf(outbuf),0) = 1;
2293 SSVAL(smb_buf(outbuf),1,28*count);
2296 if (queue) free(queue);
2298 DEBUG(3,("%d entries returned in queue\n",count));
2305 /****************************************************************************
2306 reply to a printwrite
2307 ****************************************************************************/
2308 int reply_printwrite(char *inbuf,char *outbuf)
2310 int cnum,numtowrite,fnum;
2311 int outsize = set_message(outbuf,0,0,True);
2314 cnum = SVAL(inbuf,smb_tid);
2316 if (!CAN_PRINT(cnum))
2317 return(ERROR(ERRDOS,ERRnoaccess));
2319 fnum = GETFNUM(inbuf,smb_vwv0);
2321 CHECK_FNUM(fnum,cnum);
2325 numtowrite = SVAL(smb_buf(inbuf),1);
2326 data = smb_buf(inbuf) + 3;
2328 if (write_file(fnum,data,numtowrite) != numtowrite)
2329 return(UNIXERROR(ERRDOS,ERRnoaccess));
2331 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2337 /****************************************************************************
2339 ****************************************************************************/
2340 int reply_mkdir(char *inbuf,char *outbuf)
2344 int outsize,ret= -1;
2346 strcpy(directory,smb_buf(inbuf) + 1);
2347 cnum = SVAL(inbuf,smb_tid);
2348 unix_convert(directory,cnum);
2350 if (check_name(directory,cnum))
2351 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2354 return(UNIXERROR(ERRDOS,ERRnoaccess));
2356 outsize = set_message(outbuf,0,0,True);
2358 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2364 /****************************************************************************
2366 ****************************************************************************/
2367 int reply_rmdir(char *inbuf,char *outbuf)
2374 cnum = SVAL(inbuf,smb_tid);
2375 strcpy(directory,smb_buf(inbuf) + 1);
2376 unix_convert(directory,cnum);
2378 if (check_name(directory,cnum))
2380 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2381 ok = (sys_rmdir(directory) == 0);
2383 DEBUG(3,("couldn't remove directory %s : %s\n",
2384 directory,strerror(errno)));
2388 return(UNIXERROR(ERRDOS,ERRbadpath));
2390 outsize = set_message(outbuf,0,0,True);
2392 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2398 /*******************************************************************
2399 resolve wildcards in a filename rename
2400 ********************************************************************/
2401 static BOOL resolve_wildcards(char *name1,char *name2)
2403 fstring root1,root2;
2407 name1 = strrchr(name1,'/');
2408 name2 = strrchr(name2,'/');
2410 if (!name1 || !name2) return(False);
2412 strcpy(root1,name1);
2413 strcpy(root2,name2);
2414 p = strrchr(root1,'.');
2421 p = strrchr(root2,'.');
2453 strcpy(name2,root2);
2462 /*******************************************************************
2463 check if a user is allowed to rename a file
2464 ********************************************************************/
2465 static BOOL can_rename(char *fname,int cnum)
2469 if (!CAN_WRITE(cnum)) return(False);
2471 if (sys_lstat(fname,&sbuf) != 0) return(False);
2472 if (!check_file_sharing(cnum,fname)) return(False);
2477 /****************************************************************************
2479 ****************************************************************************/
2480 int reply_mv(char *inbuf,char *outbuf)
2486 pstring mask,newname;
2489 int error = ERRnoaccess;
2493 *directory = *mask = 0;
2495 cnum = SVAL(inbuf,smb_tid);
2497 strcpy(name,smb_buf(inbuf) + 1);
2498 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2500 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2502 unix_convert(name,cnum);
2503 unix_convert(newname,cnum);
2505 p = strrchr(name,'/');
2507 strcpy(directory,"./");
2511 strcpy(directory,name);
2515 if (is_mangled(mask))
2516 check_mangled_stack(mask);
2518 has_wild = strchr(mask,'*') || strchr(mask,'?');
2521 strcat(directory,"/");
2522 strcat(directory,mask);
2523 if (resolve_wildcards(directory,newname) &&
2524 can_rename(directory,cnum) &&
2525 !file_exist(newname,NULL) &&
2526 !sys_rename(directory,newname)) count++;
2527 if (!count) exists = file_exist(directory,NULL);
2528 if (!count && exists && file_exist(newname,NULL)) {
2533 void *dirptr = NULL;
2537 if (check_name(directory,cnum))
2538 dirptr = OpenDir(directory);
2544 if (strequal(mask,"????????.???"))
2547 while ((dname = ReadDirName(dirptr)))
2550 strcpy(fname,dname);
2552 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2554 error = ERRnoaccess;
2555 sprintf(fname,"%s/%s",directory,dname);
2556 if (!can_rename(fname,cnum)) continue;
2557 strcpy(destname,newname);
2559 if (!resolve_wildcards(fname,destname)) continue;
2561 if (file_exist(destname,NULL)) {
2565 if (!sys_rename(fname,destname)) count++;
2566 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2574 return(ERROR(ERRDOS,error));
2576 return(UNIXERROR(ERRDOS,error));
2579 outsize = set_message(outbuf,0,0,True);
2584 /*******************************************************************
2585 copy a file as part of a reply_copy
2586 ******************************************************************/
2587 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2588 int count,BOOL target_is_directory)
2597 if (target_is_directory) {
2598 char *p = strrchr(src,'/');
2607 if (!file_exist(src,&st)) return(False);
2609 fnum1 = find_free_file();
2610 if (fnum1<0) return(False);
2611 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2612 1,0,&Access,&action);
2614 if (!Files[fnum1].open) return(False);
2616 if (!target_is_directory && count)
2619 fnum2 = find_free_file();
2624 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2625 ofun,st.st_mode,&Access,&action);
2627 if (!Files[fnum2].open) {
2632 if ((ofun&3) == 1) {
2633 lseek(Files[fnum2].fd,0,SEEK_END);
2637 ret = transfer_file(Files[fnum1].fd,Files[fnum2].fd,st.st_size,NULL,0,0);
2642 return(ret == st.st_size);
2647 /****************************************************************************
2648 reply to a file copy.
2649 ****************************************************************************/
2650 int reply_copy(char *inbuf,char *outbuf)
2656 pstring mask,newname;
2659 int error = ERRnoaccess;
2662 int tid2 = SVAL(inbuf,smb_vwv0);
2663 int ofun = SVAL(inbuf,smb_vwv1);
2664 int flags = SVAL(inbuf,smb_vwv2);
2665 BOOL target_is_directory=False;
2667 *directory = *mask = 0;
2669 cnum = SVAL(inbuf,smb_tid);
2671 strcpy(name,smb_buf(inbuf));
2672 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2674 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2677 /* can't currently handle inter share copies XXXX */
2678 DEBUG(3,("Rejecting inter-share copy\n"));
2679 return(ERROR(ERRSRV,ERRinvdevice));
2682 unix_convert(name,cnum);
2683 unix_convert(newname,cnum);
2685 target_is_directory = directory_exist(newname,NULL);
2687 if ((flags&1) && target_is_directory) {
2688 return(ERROR(ERRDOS,ERRbadfile));
2691 if ((flags&2) && !target_is_directory) {
2692 return(ERROR(ERRDOS,ERRbadpath));
2695 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2696 /* wants a tree copy! XXXX */
2697 DEBUG(3,("Rejecting tree copy\n"));
2698 return(ERROR(ERRSRV,ERRerror));
2701 p = strrchr(name,'/');
2703 strcpy(directory,"./");
2707 strcpy(directory,name);
2711 if (is_mangled(mask))
2712 check_mangled_stack(mask);
2714 has_wild = strchr(mask,'*') || strchr(mask,'?');
2717 strcat(directory,"/");
2718 strcat(directory,mask);
2719 if (resolve_wildcards(directory,newname) &&
2720 copy_file(directory,newname,cnum,ofun,
2721 count,target_is_directory)) count++;
2722 if (!count) exists = file_exist(directory,NULL);
2724 void *dirptr = NULL;
2728 if (check_name(directory,cnum))
2729 dirptr = OpenDir(directory);
2735 if (strequal(mask,"????????.???"))
2738 while ((dname = ReadDirName(dirptr)))
2741 strcpy(fname,dname);
2743 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2745 error = ERRnoaccess;
2746 sprintf(fname,"%s/%s",directory,dname);
2747 strcpy(destname,newname);
2748 if (resolve_wildcards(fname,destname) &&
2749 copy_file(directory,newname,cnum,ofun,
2750 count,target_is_directory)) count++;
2751 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2759 return(ERROR(ERRDOS,error));
2761 return(UNIXERROR(ERRDOS,error));
2764 outsize = set_message(outbuf,1,0,True);
2765 SSVAL(outbuf,smb_vwv0,count);
2772 /****************************************************************************
2774 ****************************************************************************/
2775 int reply_setdir(char *inbuf,char *outbuf)
2782 cnum = SVAL(inbuf,smb_tid);
2784 snum = Connections[cnum].service;
2785 if (!CAN_SETDIR(snum))
2786 return(ERROR(ERRDOS,ERRnoaccess));
2788 strcpy(newdir,smb_buf(inbuf) + 1);
2791 if (strlen(newdir) == 0)
2795 ok = directory_exist(newdir,NULL);
2797 string_set(&Connections[cnum].connectpath,newdir);
2801 return(ERROR(ERRDOS,ERRbadpath));
2803 outsize = set_message(outbuf,0,0,True);
2804 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
2806 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
2812 /****************************************************************************
2813 reply to a lockingX request
2814 ****************************************************************************/
2815 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
2817 int smb_com2 = CVAL(inbuf,smb_vwv0);
2818 int smb_off2 = SVAL(inbuf,smb_vwv1);
2819 int fnum = GETFNUM(inbuf,smb_vwv2);
2820 uint16 locktype = SVAL(inbuf,smb_vwv3);
2821 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
2822 uint16 num_locks = SVAL(inbuf,smb_vwv7);
2823 uint32 count, offset;
2828 uint32 ecode=0, dummy2;
2829 int outsize, eclass=0, dummy1;
2831 cnum = SVAL(inbuf,smb_tid);
2833 CHECK_FNUM(fnum,cnum);
2836 data = smb_buf(inbuf);
2837 /* Data now points at the beginning of the list
2838 of smb_unlkrng structs */
2839 for(i = 0; i < (int)num_ulocks; i++) {
2840 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2841 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2842 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
2843 return ERROR(eclass,ecode);
2846 /* Now do any requested locks */
2847 data += 10*num_ulocks;
2848 /* Data now points at the beginning of the list
2849 of smb_lkrng structs */
2850 for(i = 0; i < (int)num_locks; i++) {
2851 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2852 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2853 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
2857 /* If any of the above locks failed, then we must unlock
2858 all of the previous locks (X/Open spec). */
2859 if(i != num_locks && num_locks != 0) {
2860 for(; i >= 0; i--) {
2861 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2862 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2863 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
2865 return ERROR(eclass,ecode);
2868 outsize = set_message(outbuf,2,0,True);
2870 CVAL(outbuf,smb_vwv0) = smb_com2;
2871 SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
2873 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
2874 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
2878 if (smb_com2 != 0xFF)
2879 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
2880 outbuf,outbuf+outsize,
2889 /****************************************************************************
2890 reply to a SMBreadbmpx (read block multiplex) request
2891 ****************************************************************************/
2892 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
2899 int outsize, mincount, maxcount;
2904 /* this function doesn't seem to work - disable by default */
2906 return(ERROR(ERRSRV,ERRuseSTD));
2908 outsize = set_message(outbuf,8,0,True);
2910 cnum = SVAL(inbuf,smb_tid);
2911 fnum = GETFNUM(inbuf,smb_vwv0);
2913 CHECK_FNUM(fnum,cnum);
2917 startpos = IVAL(inbuf,smb_vwv1);
2918 maxcount = SVAL(inbuf,smb_vwv3);
2919 mincount = SVAL(inbuf,smb_vwv4);
2921 data = smb_buf(outbuf);
2922 pad = ((int)data)%4;
2923 if (pad) pad = 4 - pad;
2926 max_per_packet = bufsize-(outsize+pad);
2930 if (is_locked(fnum,cnum,maxcount,startpos))
2931 return(ERROR(ERRDOS,ERRlock));
2935 int N = MIN(max_per_packet,tcount-total_read);
2937 nread = read_file(fnum,data,startpos,N,N,-1,False);
2939 if (nread <= 0) nread = 0;
2942 tcount = total_read + nread;
2944 set_message(outbuf,8,nread,False);
2945 SIVAL(outbuf,smb_vwv0,startpos);
2946 SSVAL(outbuf,smb_vwv2,tcount);
2947 SSVAL(outbuf,smb_vwv6,nread);
2948 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
2950 send_smb(Client,outbuf);
2952 total_read += nread;
2955 while (total_read < tcount);
2961 /****************************************************************************
2962 reply to a SMBwritebmpx (write block multiplex primary) request
2963 ****************************************************************************/
2964 int reply_writebmpx(char *inbuf,char *outbuf)
2966 int cnum,numtowrite,fnum;
2970 int tcount, write_through, smb_doff;
2973 cnum = SVAL(inbuf,smb_tid);
2974 fnum = GETFNUM(inbuf,smb_vwv0);
2976 CHECK_FNUM(fnum,cnum);
2980 tcount = SVAL(inbuf,smb_vwv1);
2981 startpos = IVAL(inbuf,smb_vwv3);
2982 write_through = BITSETW(inbuf+smb_vwv7,0);
2983 numtowrite = SVAL(inbuf,smb_vwv10);
2984 smb_doff = SVAL(inbuf,smb_vwv11);
2986 data = smb_base(inbuf) + smb_doff;
2988 /* If this fails we need to send an SMBwriteC response,
2989 not an SMBwritebmpx - set this up now so we don't forget */
2990 CVAL(outbuf,smb_com) = SMBwritec;
2992 if (is_locked(fnum,cnum,tcount,startpos))
2993 return(ERROR(ERRDOS,ERRlock));
2995 seek_file(fnum,startpos);
2996 nwritten = write_file(fnum,data,numtowrite);
2998 if(lp_syncalways(SNUM(cnum)) || write_through)
3001 if(nwritten < numtowrite)
3002 return(UNIXERROR(ERRHRD,ERRdiskfull));
3004 /* If the maximum to be written to this file
3005 is greater than what we just wrote then set
3006 up a secondary struct to be attached to this
3007 fd, we will use this to cache error messages etc. */
3008 if(tcount > nwritten)
3010 write_bmpx_struct *wbms;
3011 if(Files[fnum].wbmpx_ptr != NULL)
3012 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3014 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3017 DEBUG(0,("Out of memory in reply_readmpx\n"));
3018 return(ERROR(ERRSRV,ERRnoresource));
3020 wbms->wr_mode = write_through;
3021 wbms->wr_discard = False; /* No errors yet */
3022 wbms->wr_total_written = nwritten;
3023 wbms->wr_errclass = 0;
3025 Files[fnum].wbmpx_ptr = wbms;
3028 /* We are returning successfully, set the message type back to
3030 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3032 outsize = set_message(outbuf,1,0,True);
3034 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3036 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3037 timestring(),fnum,cnum,numtowrite,nwritten));
3039 if (write_through && tcount==nwritten) {
3040 /* we need to send both a primary and a secondary response */
3041 smb_setlen(outbuf,outsize - 4);
3042 send_smb(Client,outbuf);
3044 /* now the secondary */
3045 outsize = set_message(outbuf,1,0,True);
3046 CVAL(outbuf,smb_com) = SMBwritec;
3047 SSVAL(outbuf,smb_vwv0,nwritten);
3054 /****************************************************************************
3055 reply to a SMBwritebs (write block multiplex secondary) request
3056 ****************************************************************************/
3057 int reply_writebs(char *inbuf,char *outbuf)
3059 int cnum,numtowrite,fnum;
3063 int tcount, write_through, smb_doff;
3065 write_bmpx_struct *wbms;
3066 BOOL send_response = False;
3068 cnum = SVAL(inbuf,smb_tid);
3069 fnum = GETFNUM(inbuf,smb_vwv0);
3070 CHECK_FNUM(fnum,cnum);
3073 tcount = SVAL(inbuf,smb_vwv1);
3074 startpos = IVAL(inbuf,smb_vwv2);
3075 numtowrite = SVAL(inbuf,smb_vwv6);
3076 smb_doff = SVAL(inbuf,smb_vwv7);
3078 data = smb_base(inbuf) + smb_doff;
3080 /* We need to send an SMBwriteC response, not an SMBwritebs */
3081 CVAL(outbuf,smb_com) = SMBwritec;
3083 /* This fd should have an auxiliary struct attached,
3084 check that it does */
3085 wbms = Files[fnum].wbmpx_ptr;
3086 if(!wbms) return(-1);
3088 /* If write through is set we can return errors, else we must
3090 write_through = wbms->wr_mode;
3092 /* Check for an earlier error */
3093 if(wbms->wr_discard)
3094 return -1; /* Just discard the packet */
3096 seek_file(fnum,startpos);
3097 nwritten = write_file(fnum,data,numtowrite);
3099 if(lp_syncalways(SNUM(cnum)) || write_through)
3102 if (nwritten < numtowrite)
3105 /* We are returning an error - we can delete the aux struct */
3106 if (wbms) free((char *)wbms);
3107 Files[fnum].wbmpx_ptr = NULL;
3108 return(ERROR(ERRHRD,ERRdiskfull));
3110 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3113 /* Increment the total written, if this matches tcount
3114 we can discard the auxiliary struct (hurrah !) and return a writeC */
3115 wbms->wr_total_written += nwritten;
3116 if(wbms->wr_total_written >= tcount)
3118 if (write_through) {
3119 outsize = set_message(outbuf,1,0,True);
3120 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3121 send_response = True;
3125 Files[fnum].wbmpx_ptr = NULL;
3135 /****************************************************************************
3136 reply to a SMBsetattrE
3137 ****************************************************************************/
3138 int reply_setattrE(char *inbuf,char *outbuf)
3141 struct utimbuf unix_times;
3144 outsize = set_message(outbuf,0,0,True);
3146 cnum = SVAL(inbuf,smb_tid);
3147 fnum = GETFNUM(inbuf,smb_vwv0);
3149 CHECK_FNUM(fnum,cnum);
3152 /* Convert the DOS times into unix times. Ignore create
3153 time as UNIX can't set this.
3155 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3156 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3158 /* Set the date on this file */
3159 if(sys_utime(Files[fnum].name, &unix_times))
3160 return(ERROR(ERRDOS,ERRnoaccess));
3162 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3168 /****************************************************************************
3169 reply to a SMBgetattrE
3170 ****************************************************************************/
3171 int reply_getattrE(char *inbuf,char *outbuf)
3178 outsize = set_message(outbuf,11,0,True);
3180 cnum = SVAL(inbuf,smb_tid);
3181 fnum = GETFNUM(inbuf,smb_vwv0);
3183 CHECK_FNUM(fnum,cnum);
3186 /* Do an fstat on this file */
3187 if(fstat(Files[fnum].fd, &sbuf))
3188 return(UNIXERROR(ERRDOS,ERRnoaccess));
3190 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3192 /* Convert the times into dos times. Set create
3193 date to be last modify date as UNIX doesn't save
3195 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3196 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3197 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3200 SIVAL(outbuf,smb_vwv6,0);
3201 SIVAL(outbuf,smb_vwv8,0);
3205 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3206 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3208 SSVAL(outbuf,smb_vwv10, mode);
3210 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));