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,0) == -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 Connections[cnum].used = False;
2067 close_cnum(cnum,uid);
2069 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2076 /****************************************************************************
2078 ****************************************************************************/
2079 int reply_echo(char *inbuf,char *outbuf)
2082 int smb_reverb = SVAL(inbuf,smb_vwv0);
2084 int data_len = smb_buflen(inbuf);
2085 int outsize = set_message(outbuf,1,data_len,True);
2087 cnum = SVAL(inbuf,smb_tid);
2089 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2091 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2092 return(ERROR(ERRSRV,ERRinvnid));
2095 /* copy any incoming data back out */
2097 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2099 if (smb_reverb > 100)
2101 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2105 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2107 SSVAL(outbuf,smb_vwv0,seq_num);
2109 smb_setlen(outbuf,outsize - 4);
2111 send_smb(Client,outbuf);
2114 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2120 /****************************************************************************
2121 reply to a printopen
2122 ****************************************************************************/
2123 int reply_printopen(char *inbuf,char *outbuf)
2131 *fname = *fname2 = 0;
2133 cnum = SVAL(inbuf,smb_tid);
2135 if (!CAN_PRINT(cnum))
2136 return(ERROR(ERRDOS,ERRnoaccess));
2141 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2145 if (!(isalnum(*p) || strchr("._-",*p)))
2150 if (strlen(s) > 10) s[10] = 0;
2152 sprintf(fname,"%s.XXXXXX",s);
2155 fnum = find_free_file();
2157 return(ERROR(ERRSRV,ERRnofids));
2159 strcpy(fname2,(char *)mktemp(fname));
2161 if (!check_name(fname2,cnum))
2162 return(ERROR(ERRDOS,ERRnoaccess));
2164 open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC,
2167 if (!Files[fnum].open)
2168 return(UNIXERROR(ERRDOS,ERRnoaccess));
2170 /* force it to be a print file */
2171 Files[fnum].print_file = True;
2173 outsize = set_message(outbuf,1,0,True);
2174 SSVAL(outbuf,smb_vwv0,fnum);
2176 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum));
2182 /****************************************************************************
2183 reply to a printclose
2184 ****************************************************************************/
2185 int reply_printclose(char *inbuf,char *outbuf)
2188 int outsize = set_message(outbuf,0,0,True);
2190 cnum = SVAL(inbuf,smb_tid);
2191 fnum = GETFNUM(inbuf,smb_vwv0);
2193 CHECK_FNUM(fnum,cnum);
2196 if (!CAN_PRINT(cnum))
2197 return(ERROR(ERRDOS,ERRnoaccess));
2201 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum));
2207 /****************************************************************************
2208 reply to a printqueue
2209 ****************************************************************************/
2210 int reply_printqueue(char *inbuf,char *outbuf)
2213 int outsize = set_message(outbuf,2,3,True);
2214 int max_count = SVAL(inbuf,smb_vwv0);
2215 int start_index = SVAL(inbuf,smb_vwv1);
2217 cnum = SVAL(inbuf,smb_tid);
2218 uid = SVAL(inbuf,smb_uid);
2220 /* allow checking the queue for anyone */
2222 if (!CAN_PRINT(cnum))
2223 return(ERROR(ERRDOS,ERRnoaccess));
2226 SSVAL(outbuf,smb_vwv0,0);
2227 SSVAL(outbuf,smb_vwv1,0);
2228 CVAL(smb_buf(outbuf),0) = 1;
2229 SSVAL(smb_buf(outbuf),1,0);
2231 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2232 timestring(),cnum,start_index,max_count));
2234 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2239 for (i=0;i<MAX_CONNECTIONS;i++)
2240 if (CAN_PRINT(i) && Connections[i].printer)
2244 for (i=0;i<MAX_CONNECTIONS;i++)
2248 if (!OPEN_CNUM(cnum))
2249 return(ERROR(ERRSRV,ERRinvnid));
2251 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2254 if (!become_user(cnum,uid))
2255 return(ERROR(ERRSRV,ERRinvnid));
2258 print_queue_struct *queue = NULL;
2259 char *p = smb_buf(outbuf) + 3;
2260 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2261 int num_to_get = ABS(max_count);
2262 int first = (max_count>0?start_index:start_index+max_count+1);
2268 num_to_get = MIN(num_to_get,count-first);
2271 for (i=first;i<first+num_to_get;i++)
2273 put_dos_date2(p,0,queue[i].time);
2274 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2275 SSVAL(p,5,queue[i].job);
2276 SIVAL(p,7,queue[i].size);
2278 StrnCpy(p+12,queue[i].user,16);
2284 outsize = set_message(outbuf,2,28*count+3,False);
2285 SSVAL(outbuf,smb_vwv0,count);
2286 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2287 CVAL(smb_buf(outbuf),0) = 1;
2288 SSVAL(smb_buf(outbuf),1,28*count);
2291 if (queue) free(queue);
2293 DEBUG(3,("%d entries returned in queue\n",count));
2300 /****************************************************************************
2301 reply to a printwrite
2302 ****************************************************************************/
2303 int reply_printwrite(char *inbuf,char *outbuf)
2305 int cnum,numtowrite,fnum;
2306 int outsize = set_message(outbuf,0,0,True);
2309 cnum = SVAL(inbuf,smb_tid);
2311 if (!CAN_PRINT(cnum))
2312 return(ERROR(ERRDOS,ERRnoaccess));
2314 fnum = GETFNUM(inbuf,smb_vwv0);
2316 CHECK_FNUM(fnum,cnum);
2320 numtowrite = SVAL(smb_buf(inbuf),1);
2321 data = smb_buf(inbuf) + 3;
2323 if (write_file(fnum,data,numtowrite) != numtowrite)
2324 return(UNIXERROR(ERRDOS,ERRnoaccess));
2326 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2332 /****************************************************************************
2334 ****************************************************************************/
2335 int reply_mkdir(char *inbuf,char *outbuf)
2339 int outsize,ret= -1;
2341 strcpy(directory,smb_buf(inbuf) + 1);
2342 cnum = SVAL(inbuf,smb_tid);
2343 unix_convert(directory,cnum);
2345 if (check_name(directory,cnum))
2346 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2349 return(UNIXERROR(ERRDOS,ERRnoaccess));
2351 outsize = set_message(outbuf,0,0,True);
2353 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2359 /****************************************************************************
2361 ****************************************************************************/
2362 int reply_rmdir(char *inbuf,char *outbuf)
2369 cnum = SVAL(inbuf,smb_tid);
2370 strcpy(directory,smb_buf(inbuf) + 1);
2371 unix_convert(directory,cnum);
2373 if (check_name(directory,cnum))
2375 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2376 ok = (sys_rmdir(directory) == 0);
2378 DEBUG(3,("couldn't remove directory %s : %s\n",
2379 directory,strerror(errno)));
2383 return(UNIXERROR(ERRDOS,ERRbadpath));
2385 outsize = set_message(outbuf,0,0,True);
2387 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2393 /*******************************************************************
2394 resolve wildcards in a filename rename
2395 ********************************************************************/
2396 static BOOL resolve_wildcards(char *name1,char *name2)
2398 fstring root1,root2;
2402 name1 = strrchr(name1,'/');
2403 name2 = strrchr(name2,'/');
2405 if (!name1 || !name2) return(False);
2407 strcpy(root1,name1);
2408 strcpy(root2,name2);
2409 p = strrchr(root1,'.');
2416 p = strrchr(root2,'.');
2448 strcpy(name2,root2);
2457 /*******************************************************************
2458 check if a user is allowed to rename a file
2459 ********************************************************************/
2460 static BOOL can_rename(char *fname,int cnum)
2464 if (!CAN_WRITE(cnum)) return(False);
2466 if (sys_lstat(fname,&sbuf) != 0) return(False);
2467 if (!check_file_sharing(cnum,fname)) return(False);
2472 /****************************************************************************
2474 ****************************************************************************/
2475 int reply_mv(char *inbuf,char *outbuf)
2481 pstring mask,newname;
2484 int error = ERRnoaccess;
2488 *directory = *mask = 0;
2490 cnum = SVAL(inbuf,smb_tid);
2492 strcpy(name,smb_buf(inbuf) + 1);
2493 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2495 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2497 unix_convert(name,cnum);
2498 unix_convert(newname,cnum);
2500 p = strrchr(name,'/');
2502 strcpy(directory,"./");
2506 strcpy(directory,name);
2510 if (is_mangled(mask))
2511 check_mangled_stack(mask);
2513 has_wild = strchr(mask,'*') || strchr(mask,'?');
2516 strcat(directory,"/");
2517 strcat(directory,mask);
2518 if (resolve_wildcards(directory,newname) &&
2519 can_rename(directory,cnum) &&
2520 !file_exist(newname,NULL) &&
2521 !sys_rename(directory,newname)) count++;
2522 if (!count) exists = file_exist(directory,NULL);
2523 if (!count && exists && file_exist(newname,NULL)) {
2528 void *dirptr = NULL;
2532 if (check_name(directory,cnum))
2533 dirptr = OpenDir(directory);
2539 if (strequal(mask,"????????.???"))
2542 while ((dname = ReadDirName(dirptr)))
2545 strcpy(fname,dname);
2547 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2549 error = ERRnoaccess;
2550 sprintf(fname,"%s/%s",directory,dname);
2551 if (!can_rename(fname,cnum)) continue;
2552 strcpy(destname,newname);
2554 if (!resolve_wildcards(fname,destname)) continue;
2556 if (file_exist(destname,NULL)) {
2560 if (!sys_rename(fname,destname)) count++;
2561 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2569 return(ERROR(ERRDOS,error));
2571 return(UNIXERROR(ERRDOS,error));
2574 outsize = set_message(outbuf,0,0,True);
2579 /*******************************************************************
2580 copy a file as part of a reply_copy
2581 ******************************************************************/
2582 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2583 int count,BOOL target_is_directory)
2592 if (target_is_directory) {
2593 char *p = strrchr(src,'/');
2602 if (!file_exist(src,&st)) return(False);
2604 fnum1 = find_free_file();
2605 if (fnum1<0) return(False);
2606 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2607 1,0,&Access,&action);
2609 if (!Files[fnum1].open) return(False);
2611 if (!target_is_directory && count)
2614 fnum2 = find_free_file();
2619 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2620 ofun,st.st_mode,&Access,&action);
2622 if (!Files[fnum2].open) {
2627 if ((ofun&3) == 1) {
2628 lseek(Files[fnum2].fd,0,SEEK_END);
2632 ret = transfer_file(Files[fnum1].fd,Files[fnum2].fd,st.st_size,NULL,0,0);
2637 return(ret == st.st_size);
2642 /****************************************************************************
2643 reply to a file copy.
2644 ****************************************************************************/
2645 int reply_copy(char *inbuf,char *outbuf)
2651 pstring mask,newname;
2654 int error = ERRnoaccess;
2657 int tid2 = SVAL(inbuf,smb_vwv0);
2658 int ofun = SVAL(inbuf,smb_vwv1);
2659 int flags = SVAL(inbuf,smb_vwv2);
2660 BOOL target_is_directory=False;
2662 *directory = *mask = 0;
2664 cnum = SVAL(inbuf,smb_tid);
2666 strcpy(name,smb_buf(inbuf));
2667 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2669 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2672 /* can't currently handle inter share copies XXXX */
2673 DEBUG(3,("Rejecting inter-share copy\n"));
2674 return(ERROR(ERRSRV,ERRinvdevice));
2677 unix_convert(name,cnum);
2678 unix_convert(newname,cnum);
2680 target_is_directory = directory_exist(newname,NULL);
2682 if ((flags&1) && target_is_directory) {
2683 return(ERROR(ERRDOS,ERRbadfile));
2686 if ((flags&2) && !target_is_directory) {
2687 return(ERROR(ERRDOS,ERRbadpath));
2690 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2691 /* wants a tree copy! XXXX */
2692 DEBUG(3,("Rejecting tree copy\n"));
2693 return(ERROR(ERRSRV,ERRerror));
2696 p = strrchr(name,'/');
2698 strcpy(directory,"./");
2702 strcpy(directory,name);
2706 if (is_mangled(mask))
2707 check_mangled_stack(mask);
2709 has_wild = strchr(mask,'*') || strchr(mask,'?');
2712 strcat(directory,"/");
2713 strcat(directory,mask);
2714 if (resolve_wildcards(directory,newname) &&
2715 copy_file(directory,newname,cnum,ofun,
2716 count,target_is_directory)) count++;
2717 if (!count) exists = file_exist(directory,NULL);
2719 void *dirptr = NULL;
2723 if (check_name(directory,cnum))
2724 dirptr = OpenDir(directory);
2730 if (strequal(mask,"????????.???"))
2733 while ((dname = ReadDirName(dirptr)))
2736 strcpy(fname,dname);
2738 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2740 error = ERRnoaccess;
2741 sprintf(fname,"%s/%s",directory,dname);
2742 strcpy(destname,newname);
2743 if (resolve_wildcards(fname,destname) &&
2744 copy_file(directory,newname,cnum,ofun,
2745 count,target_is_directory)) count++;
2746 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2754 return(ERROR(ERRDOS,error));
2756 return(UNIXERROR(ERRDOS,error));
2759 outsize = set_message(outbuf,1,0,True);
2760 SSVAL(outbuf,smb_vwv0,count);
2767 /****************************************************************************
2769 ****************************************************************************/
2770 int reply_setdir(char *inbuf,char *outbuf)
2777 cnum = SVAL(inbuf,smb_tid);
2779 snum = Connections[cnum].service;
2780 if (!CAN_SETDIR(snum))
2781 return(ERROR(ERRDOS,ERRnoaccess));
2783 strcpy(newdir,smb_buf(inbuf) + 1);
2786 if (strlen(newdir) == 0)
2790 ok = directory_exist(newdir,NULL);
2792 string_set(&Connections[cnum].connectpath,newdir);
2796 return(ERROR(ERRDOS,ERRbadpath));
2798 outsize = set_message(outbuf,0,0,True);
2799 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
2801 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
2807 /****************************************************************************
2808 reply to a lockingX request
2809 ****************************************************************************/
2810 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
2812 int smb_com2 = CVAL(inbuf,smb_vwv0);
2813 int smb_off2 = SVAL(inbuf,smb_vwv1);
2814 int fnum = GETFNUM(inbuf,smb_vwv2);
2815 uint16 locktype = SVAL(inbuf,smb_vwv3);
2816 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
2817 uint16 num_locks = SVAL(inbuf,smb_vwv7);
2818 uint32 count, offset;
2823 uint32 ecode=0, dummy2;
2824 int outsize, eclass=0, dummy1;
2826 cnum = SVAL(inbuf,smb_tid);
2828 CHECK_FNUM(fnum,cnum);
2831 data = smb_buf(inbuf);
2832 /* Data now points at the beginning of the list
2833 of smb_unlkrng structs */
2834 for(i = 0; i < (int)num_ulocks; i++) {
2835 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2836 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2837 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
2838 return ERROR(eclass,ecode);
2841 /* Now do any requested locks */
2842 data += 10*num_ulocks;
2843 /* Data now points at the beginning of the list
2844 of smb_lkrng structs */
2845 for(i = 0; i < (int)num_locks; i++) {
2846 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2847 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2848 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
2852 /* If any of the above locks failed, then we must unlock
2853 all of the previous locks (X/Open spec). */
2854 if(i != num_locks && num_locks != 0) {
2855 for(; i >= 0; i--) {
2856 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2857 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2858 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
2860 return ERROR(eclass,ecode);
2863 outsize = set_message(outbuf,2,0,True);
2865 CVAL(outbuf,smb_vwv0) = smb_com2;
2866 SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
2868 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
2869 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
2873 if (smb_com2 != 0xFF)
2874 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
2875 outbuf,outbuf+outsize,
2884 /****************************************************************************
2885 reply to a SMBreadbmpx (read block multiplex) request
2886 ****************************************************************************/
2887 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
2894 int outsize, mincount, maxcount;
2899 /* this function doesn't seem to work - disable by default */
2901 return(ERROR(ERRSRV,ERRuseSTD));
2903 outsize = set_message(outbuf,8,0,True);
2905 cnum = SVAL(inbuf,smb_tid);
2906 fnum = GETFNUM(inbuf,smb_vwv0);
2908 CHECK_FNUM(fnum,cnum);
2912 startpos = IVAL(inbuf,smb_vwv1);
2913 maxcount = SVAL(inbuf,smb_vwv3);
2914 mincount = SVAL(inbuf,smb_vwv4);
2916 data = smb_buf(outbuf);
2917 pad = ((int)data)%4;
2918 if (pad) pad = 4 - pad;
2921 max_per_packet = bufsize-(outsize+pad);
2925 if (is_locked(fnum,cnum,maxcount,startpos))
2926 return(ERROR(ERRDOS,ERRlock));
2930 int N = MIN(max_per_packet,tcount-total_read);
2932 nread = read_file(fnum,data,startpos,N,N,-1,False);
2934 if (nread <= 0) nread = 0;
2937 tcount = total_read + nread;
2939 set_message(outbuf,8,nread,False);
2940 SIVAL(outbuf,smb_vwv0,startpos);
2941 SSVAL(outbuf,smb_vwv2,tcount);
2942 SSVAL(outbuf,smb_vwv6,nread);
2943 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
2945 send_smb(Client,outbuf);
2947 total_read += nread;
2950 while (total_read < tcount);
2956 /****************************************************************************
2957 reply to a SMBwritebmpx (write block multiplex primary) request
2958 ****************************************************************************/
2959 int reply_writebmpx(char *inbuf,char *outbuf)
2961 int cnum,numtowrite,fnum;
2965 int tcount, write_through, smb_doff;
2968 cnum = SVAL(inbuf,smb_tid);
2969 fnum = GETFNUM(inbuf,smb_vwv0);
2971 CHECK_FNUM(fnum,cnum);
2975 tcount = SVAL(inbuf,smb_vwv1);
2976 startpos = IVAL(inbuf,smb_vwv3);
2977 write_through = BITSETW(inbuf+smb_vwv7,0);
2978 numtowrite = SVAL(inbuf,smb_vwv10);
2979 smb_doff = SVAL(inbuf,smb_vwv11);
2981 data = smb_base(inbuf) + smb_doff;
2983 /* If this fails we need to send an SMBwriteC response,
2984 not an SMBwritebmpx - set this up now so we don't forget */
2985 CVAL(outbuf,smb_com) = SMBwritec;
2987 if (is_locked(fnum,cnum,tcount,startpos))
2988 return(ERROR(ERRDOS,ERRlock));
2990 seek_file(fnum,startpos);
2991 nwritten = write_file(fnum,data,numtowrite);
2993 if(lp_syncalways(SNUM(cnum)) || write_through)
2996 if(nwritten < numtowrite)
2997 return(UNIXERROR(ERRHRD,ERRdiskfull));
2999 /* If the maximum to be written to this file
3000 is greater than what we just wrote then set
3001 up a secondary struct to be attached to this
3002 fd, we will use this to cache error messages etc. */
3003 if(tcount > nwritten)
3005 write_bmpx_struct *wbms;
3006 if(Files[fnum].wbmpx_ptr != NULL)
3007 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3009 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3012 DEBUG(0,("Out of memory in reply_readmpx\n"));
3013 return(ERROR(ERRSRV,ERRnoresource));
3015 wbms->wr_mode = write_through;
3016 wbms->wr_discard = False; /* No errors yet */
3017 wbms->wr_total_written = nwritten;
3018 wbms->wr_errclass = 0;
3020 Files[fnum].wbmpx_ptr = wbms;
3023 /* We are returning successfully, set the message type back to
3025 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3027 outsize = set_message(outbuf,1,0,True);
3029 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3031 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3032 timestring(),fnum,cnum,numtowrite,nwritten));
3034 if (write_through && tcount==nwritten) {
3035 /* we need to send both a primary and a secondary response */
3036 smb_setlen(outbuf,outsize - 4);
3037 send_smb(Client,outbuf);
3039 /* now the secondary */
3040 outsize = set_message(outbuf,1,0,True);
3041 CVAL(outbuf,smb_com) = SMBwritec;
3042 SSVAL(outbuf,smb_vwv0,nwritten);
3049 /****************************************************************************
3050 reply to a SMBwritebs (write block multiplex secondary) request
3051 ****************************************************************************/
3052 int reply_writebs(char *inbuf,char *outbuf)
3054 int cnum,numtowrite,fnum;
3058 int tcount, write_through, smb_doff;
3060 write_bmpx_struct *wbms;
3061 BOOL send_response = False;
3063 cnum = SVAL(inbuf,smb_tid);
3064 fnum = GETFNUM(inbuf,smb_vwv0);
3065 CHECK_FNUM(fnum,cnum);
3068 tcount = SVAL(inbuf,smb_vwv1);
3069 startpos = IVAL(inbuf,smb_vwv2);
3070 numtowrite = SVAL(inbuf,smb_vwv6);
3071 smb_doff = SVAL(inbuf,smb_vwv7);
3073 data = smb_base(inbuf) + smb_doff;
3075 /* We need to send an SMBwriteC response, not an SMBwritebs */
3076 CVAL(outbuf,smb_com) = SMBwritec;
3078 /* This fd should have an auxiliary struct attached,
3079 check that it does */
3080 wbms = Files[fnum].wbmpx_ptr;
3081 if(!wbms) return(-1);
3083 /* If write through is set we can return errors, else we must
3085 write_through = wbms->wr_mode;
3087 /* Check for an earlier error */
3088 if(wbms->wr_discard)
3089 return -1; /* Just discard the packet */
3091 seek_file(fnum,startpos);
3092 nwritten = write_file(fnum,data,numtowrite);
3094 if(lp_syncalways(SNUM(cnum)) || write_through)
3097 if (nwritten < numtowrite)
3100 /* We are returning an error - we can delete the aux struct */
3101 if (wbms) free((char *)wbms);
3102 Files[fnum].wbmpx_ptr = NULL;
3103 return(ERROR(ERRHRD,ERRdiskfull));
3105 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3108 /* Increment the total written, if this matches tcount
3109 we can discard the auxiliary struct (hurrah !) and return a writeC */
3110 wbms->wr_total_written += nwritten;
3111 if(wbms->wr_total_written >= tcount)
3113 if (write_through) {
3114 outsize = set_message(outbuf,1,0,True);
3115 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3116 send_response = True;
3120 Files[fnum].wbmpx_ptr = NULL;
3130 /****************************************************************************
3131 reply to a SMBsetattrE
3132 ****************************************************************************/
3133 int reply_setattrE(char *inbuf,char *outbuf)
3136 struct utimbuf unix_times;
3139 outsize = set_message(outbuf,0,0,True);
3141 cnum = SVAL(inbuf,smb_tid);
3142 fnum = GETFNUM(inbuf,smb_vwv0);
3144 CHECK_FNUM(fnum,cnum);
3147 /* Convert the DOS times into unix times. Ignore create
3148 time as UNIX can't set this.
3150 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3151 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3153 /* Set the date on this file */
3154 if(sys_utime(Files[fnum].name, &unix_times))
3155 return(ERROR(ERRDOS,ERRnoaccess));
3157 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3163 /****************************************************************************
3164 reply to a SMBgetattrE
3165 ****************************************************************************/
3166 int reply_getattrE(char *inbuf,char *outbuf)
3173 outsize = set_message(outbuf,11,0,True);
3175 cnum = SVAL(inbuf,smb_tid);
3176 fnum = GETFNUM(inbuf,smb_vwv0);
3178 CHECK_FNUM(fnum,cnum);
3181 /* Do an fstat on this file */
3182 if(fstat(Files[fnum].fd, &sbuf))
3183 return(UNIXERROR(ERRDOS,ERRnoaccess));
3185 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3187 /* Convert the times into dos times. Set create
3188 date to be last modify date as UNIX doesn't save
3190 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3191 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3192 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3195 SIVAL(outbuf,smb_vwv6,0);
3196 SIVAL(outbuf,smb_vwv8,0);
3200 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3201 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3203 SSVAL(outbuf,smb_vwv10, mode);
3205 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));